Skip to content

Conversation

@jagarnica
Copy link
Contributor

@jagarnica jagarnica commented Jun 13, 2025

Resolve DOCS-5174

This PR fetches code samples for the code samples API to be used by the TryItNow editor in docs.

Screenshot 2025-06-13 at 12 56 54 PM

@linear
Copy link

linear bot commented Jun 13, 2025

DOCS-5174 Docs: Example Generation for TryItNow

Generate code samples for use in the try it now editor.

Requirements:

  • Code samples should be generally able to be run (there can be a few broken ones for now)
  • The snippets will be included during the docs generation step

Not required for now:

  • Intellisense for the types of the SDK (this will be added later)
  • Perfect sync between the sdk from the docs generation build SHA and the one published on npm
  • on-prem capabilities are deferred for now


export const settingsSchema = z.strictObject({
spec: z.string(),
specFilename: z.string(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't add this here. This type specifically states what information should go in speakeasy.config.js, and I don't think we should require users to fill this in given that they already supplied this information on the line above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oooh thanks for the heads up. This was a mistake on my part. I don't want the user to supply this since its from the path to the spec. I mistakenly thought this was just a global state type.

export async function getDocsData(
specContents: string
specContents: string,
specFilename: string
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of passing it in here, we can instead replace the logic with:

const { spec } = getSettings();
const specFilename = basename(spec);

const go = new Go();
const result = await WebAssembly.instantiate(wasmBuffer, go.importObject);
void go.run(result.instance);
const serializedDocsData = await SerializeDocsData(specContents);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh actually hang on, I just noticed we're now calling SerializeDocsData twice in this function. We shouldn't do that either, since again this function is expensive.

Instead, let's create a new top-level group of operations at src/generator/codeSnippets, and move all logic in there. Then, we call the top-level function (which takes in docs data) and returns code snippets, that we add between the getDocsData and generateContent functions in packages/docs-md/src/generator/generatePages.ts.

])
);
this.#lines.push(`<TryItNow {...${JSON.stringify(escapedProps)}} />`);
this.#lines.push(`<TryItNow {...${JSON.stringify(escapedProps)}} externalDependencies={${JSON.stringify(props.externalDependencies)}} defaultValue={\`${props.defaultValue}\`} />`);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that if we escape these values, things don't render correctly and the dependencies can't be read for the TryItNow component. I think there is a fix somewhere else that would address this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, escaping needs some love. I have some code in a branch somewhere that creates a much more robust escaping mechanism, but it's not quite ready yet.

...sandpackSetupOptions,
}}
theme="auto"
theme="dark"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting the default to dark for now due to an issue with the text color not changing when going from "light" mode to "dark" mode.

"-p": "--page-out-dir",
"-o": "--component-out-dir",
"-f": "--framework",
"-n": "--npm-package-name",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sets the name of the npm package downloaded later in TryItNow

@jagarnica jagarnica marked this pull request as ready for review June 13, 2025 20:02
"-p": "--page-out-dir",
"-o": "--component-out-dir",
"-f": "--framework",
"-n": "--npm-package-name",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"-n": "--npm-package-name",

Let's leave this flag out. Only about half of the settings are exposed by the CLI anyways, and I've been thinking about removing all but -c and -s anyways.

Comment on lines 8 to 16
const codeSnippets = new Map<string, CodeSnippet>();

export function setCodeSnippet(snippet: CodeSnippet) {
codeSnippets.set(snippet.operationId, snippet);
}

export function getCodeSnippet(operationId: string) {
return codeSnippets.get(operationId);
}
Copy link
Collaborator

@nebrius nebrius Jun 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const codeSnippets = new Map<string, CodeSnippet>();
export function setCodeSnippet(snippet: CodeSnippet) {
codeSnippets.set(snippet.operationId, snippet);
}
export function getCodeSnippet(operationId: string) {
return codeSnippets.get(operationId);
}

Let's not do this style of storing for code snippets. I only did it for settings caused they're used everywhere, and even then I was on the fence and am kinda worried it's going to come back to bite me in the ass 😅 . We don't use this approach for docs data though, and I think we should be consistent how we access information about a spec throughout the codebase.

return (json as CodeSamplesResponse).snippets;
}

export const fetchAndStoreDocsCodeSnippets = async (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To follow up from the above, let's merge this in with fetchCodeSnippets so that fetchCodeSnippets takes in just two parameters: docsData and specContents (the other two can be fetched from getSettings())

@jagarnica jagarnica force-pushed the feat/add-usage-snippets branch from 5abe295 to 67ef515 Compare June 13, 2025 22:52
Copy link
Collaborator

@nebrius nebrius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

We'll follow up later with the issue of some methods having the wrong name.

@jagarnica jagarnica added this pull request to the merge queue Jun 13, 2025
Merged via the queue into main with commit 00107f8 Jun 13, 2025
1 check passed
pschutz93 pushed a commit that referenced this pull request Oct 25, 2025
* add basic piping for try it now

* add npmPackageName as a string

* remove type from global

* clean up types, use separate state for usageSnippets

* add optimization regarding chunks

* move snippet logic to top-level function

* set default theme to dark

* formatting changes

* move logic for CodeSnippets closer to rendering of data

* remove flag for npm package

* Fleshed out settings so that try-it-now is optional

* Reverted SnippetAI formatting changes

---------

Co-authored-by: nebrius <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants