docs-utils: support routes that include global variables (#11976)

* docs-util: support urls that have variable names

* re-generate examples

* disable removing js sdk examples and replace with warning
This commit is contained in:
Shahed Nasser
2025-03-25 15:36:00 +02:00
committed by GitHub
parent 768ea91e1b
commit 83e063229b
3 changed files with 361 additions and 13 deletions

View File

@@ -721,8 +721,12 @@ class OasKindGenerator extends FunctionKindGenerator {
}
}
} else if (oldJsSdkExampleIndex !== -1) {
// remove the JS SDK example if it doesn't exist
oas["x-codeSamples"]!.splice(oldJsSdkExampleIndex, 1)
// output a warning that maybe the JS SDK should be updated
console.warn(
chalk.yellow(
`[WARNING] The JS SDK example of ${methodName} ${oasPath} is missing from generated route examples. Consider updating it.`
)
)
}
// push new tags to the tags property

View File

@@ -99,16 +99,29 @@ class RouteExamplesKindGenerator extends DefaultKindGenerator<ts.MethodDeclarati
method: "",
}
if (
node.kind === ts.SyntaxKind.StringLiteral ||
node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral ||
node.kind === ts.SyntaxKind.TemplateExpression
) {
let str = node
.getText()
.replace(/^["'`]|["'`]$/g, "")
.replace(/\$\{(.+?)\}/g, `{$1}`)
.toLowerCase()
/**
* Internal function to maybe set the route result for a string
*/
const maybeSetRouteResult = (str: string) => {
str = str.replace(/^["'`]|["'`]$/g, "")
// check if any of the template variables are local variables
const localVariables = this.getLocalVariables(node)
const templateVariables = str.match(/{(.+?)}/g) || []
for (const variable of templateVariables) {
const variableName = variable.slice(1, -1)
const localVariable = localVariables.get(variableName)
if (localVariable && localVariable.valueDeclaration) {
str = str.replace(
`$${variable}`,
this.getValueFromDeclaration(localVariable.valueDeclaration)
)
}
}
// replace the remaining template variables with correct OAS syntax
str = str.toLowerCase().replace(/\$\{(.+?)\}/g, `{$1}`)
// remove possible query params in string
const queryIndex = str.indexOf("?")
if (queryIndex > -1) {
@@ -128,6 +141,26 @@ class RouteExamplesKindGenerator extends DefaultKindGenerator<ts.MethodDeclarati
) {
result.method = str.toUpperCase()
}
}
if (
node.kind === ts.SyntaxKind.StringLiteral ||
node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral ||
node.kind === ts.SyntaxKind.TemplateExpression
) {
maybeSetRouteResult(node.getText())
} else if (
ts.isIdentifier(node) &&
ts.isCallExpression(node.parent) &&
node.parent.expression.getText().endsWith(".fetch")
) {
const localVariables = this.getLocalVariables(node)
const variableSymbol = localVariables.get(node.getText())
if (variableSymbol?.valueDeclaration) {
maybeSetRouteResult(
this.getValueFromDeclaration(variableSymbol.valueDeclaration)
)
}
} else {
node.forEachChild((child) => {
if (result.route.length > 0 && result.method.length > 0) {
@@ -188,6 +221,26 @@ class RouteExamplesKindGenerator extends DefaultKindGenerator<ts.MethodDeclarati
// Check for private class member
return (node.flags & ts.ModifierFlags.Private) !== 0
}
getLocalVariables(node: ts.Node): Map<string, ts.Symbol> {
const sourceFile = node.getSourceFile()
return "locals" in sourceFile
? (sourceFile.locals as Map<string, ts.Symbol>)
: new Map<string, ts.Symbol>()
}
getValueFromDeclaration(declaration: ts.Declaration) {
if (!ts.isVariableDeclaration(declaration)) {
return ""
}
const initializer = declaration.initializer
if (!initializer || !ts.isStringLiteral(initializer)) {
return ""
}
return initializer.getText().replace(/^["'`]|["'`]$/g, "")
}
}
export default RouteExamplesKindGenerator