From b07dd33a57f2bb4e7e0bea3755b8385a5d460da3 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 17 Oct 2024 19:32:21 +0300 Subject: [PATCH] docs-util: add configuration to generate js-sdk reference (#9630) --- www/utils/packages/typedoc-config/js-sdk.json | 11 ++ .../src/constants/base-options.ts | 2 +- .../src/constants/custom-options.ts | 22 ++- .../constants/merger-custom-options/index.ts | 2 + .../constants/merger-custom-options/js-sdk.ts | 88 ++++++++++ .../src/constants/merger-options.ts | 1 + .../src/constants/references.ts | 1 + .../src/index.ts | 7 + .../resources/partials/member.declaration.hbs | 38 +++-- .../src/theme.ts | 29 +++- .../typedoc-plugin-workflows/src/plugin.ts | 4 +- .../src/utils/helper.ts | 154 +++++++++++++++++- www/utils/packages/types/lib/index.d.ts | 4 + .../packages/utils/src/get-type-children.ts | 7 +- 14 files changed, 339 insertions(+), 31 deletions(-) create mode 100644 www/utils/packages/typedoc-config/js-sdk.json create mode 100644 www/utils/packages/typedoc-generate-references/src/constants/merger-custom-options/js-sdk.ts diff --git a/www/utils/packages/typedoc-config/js-sdk.json b/www/utils/packages/typedoc-config/js-sdk.json new file mode 100644 index 0000000000..af9c4b0bdf --- /dev/null +++ b/www/utils/packages/typedoc-config/js-sdk.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json.schemastore.org/tsconfig", + "extends": [ + "../../../../packages/core/js-sdk/tsconfig.json" + ], + "include": ["../../../../packages/core/js-sdk/src"], + "exclude": [ + "../../../../packages/core/js-sdk/dist", + "../../../../packages/core/js-sdk/node_modules" + ] +} \ No newline at end of file diff --git a/www/utils/packages/typedoc-generate-references/src/constants/base-options.ts b/www/utils/packages/typedoc-generate-references/src/constants/base-options.ts index bb79579128..2f5e83f214 100644 --- a/www/utils/packages/typedoc-generate-references/src/constants/base-options.ts +++ b/www/utils/packages/typedoc-generate-references/src/constants/base-options.ts @@ -12,7 +12,7 @@ export const baseOptions: Partial = { "www/packages/eslint-config-docs/content.js" ), pluginsResolvePath: path.join(rootPathPrefix, "www"), - exclude: [path.join(rootPathPrefix, "node_modules/**")], + exclude: ["**/node_modules/**"], excludeInternal: true, excludeExternals: true, excludeReferences: true, diff --git a/www/utils/packages/typedoc-generate-references/src/constants/custom-options.ts b/www/utils/packages/typedoc-generate-references/src/constants/custom-options.ts index 3b2c955d1d..40a0c28352 100644 --- a/www/utils/packages/typedoc-generate-references/src/constants/custom-options.ts +++ b/www/utils/packages/typedoc-generate-references/src/constants/custom-options.ts @@ -49,6 +49,16 @@ const customOptions: Record> = { name: "fulfillment-provider", parentIgnore: true, }), + "js-sdk": getOptions({ + entryPointPath: [ + "packages/core/js-sdk/src/admin/index.ts", + "packages/core/js-sdk/src/auth/index.ts", + "packages/core/js-sdk/src/store/index.ts", + ], + tsConfigName: "js-sdk.json", + name: "js-sdk", + enableInternalResolve: true, + }), "helper-steps": getOptions({ entryPointPath: "packages/core/core-flows/src/common/index.ts", tsConfigName: "core-flows.json", @@ -62,12 +72,13 @@ const customOptions: Record> = { ], }), "medusa-config": getOptions({ - entryPointPath: "packages/framework/src/config/types.ts", + entryPointPath: "packages/core/framework/src/config/types.ts", tsConfigName: "framework.json", name: "medusa-config", + exclude: [...(baseOptions.exclude || []), "**/dist/**"], }), medusa: getOptions({ - entryPointPath: "packages/medusa/src/index.js", + entryPointPath: "packages/medusa/src/index.ts", tsConfigName: "medusa.json", name: "medusa", jsonFileName: "0-medusa", @@ -140,10 +151,13 @@ const customOptions: Record> = { enableInternalResolve: true, exclude: [ ...(baseOptions.exclude || []), + "**/dist/**", "**/api-key/**", + "**/auth/**", + "**/bundles/**", "**/common/**", "**/dal/**/**", - "**/decorators/**", + "**/dml/**", "**/defaults/**", "**/**provider.ts", "**/event-bus/**", @@ -151,10 +165,10 @@ const customOptions: Record> = { "**/feature-flags/**", "**/modules-sdk/**", "**/orchestration/**", + "**/pg/**", "**/pricing/builders.ts", "**/search/**", "**/totals/**", - "**/dml/**", ], }), workflows: getOptions({ diff --git a/www/utils/packages/typedoc-generate-references/src/constants/merger-custom-options/index.ts b/www/utils/packages/typedoc-generate-references/src/constants/merger-custom-options/index.ts index c618ac7f45..27b7f675ea 100644 --- a/www/utils/packages/typedoc-generate-references/src/constants/merger-custom-options/index.ts +++ b/www/utils/packages/typedoc-generate-references/src/constants/merger-custom-options/index.ts @@ -12,6 +12,7 @@ import taxProviderOptions from "./tax-provider.js" import workflowsOptions from "./workflows.js" import dmlOptions from "./dml.js" import coreFlowsOptions from "./core-flows.js" +import jsSdkOptions from "./js-sdk.js" const mergerCustomOptions: FormattingOptionsType = { ...authProviderOptions, @@ -20,6 +21,7 @@ const mergerCustomOptions: FormattingOptionsType = { ...fileOptions, ...fulfillmentProviderOptions, ...helperStepsOptions, + ...jsSdkOptions, ...medusaConfigOptions, ...medusaOptions, ...notificationOptions, diff --git a/www/utils/packages/typedoc-generate-references/src/constants/merger-custom-options/js-sdk.ts b/www/utils/packages/typedoc-generate-references/src/constants/merger-custom-options/js-sdk.ts new file mode 100644 index 0000000000..186631f41e --- /dev/null +++ b/www/utils/packages/typedoc-generate-references/src/constants/merger-custom-options/js-sdk.ts @@ -0,0 +1,88 @@ +import { FormattingOptionsType } from "types" +import baseSectionsOptions from "../base-section-options.js" + +const jsSdkOptions: FormattingOptionsType = { + "^js_sdk": { + expandMembers: true, + expandProperties: true, + reflectionGroups: { + Constructors: false, + }, + sections: { + ...baseSectionsOptions, + member_declaration_title: false, + member_declaration_children: true, + }, + }, + "^js_sdk/store/classes/.*Store": { + frontmatterData: { + slug: "/references/js-sdk/store", + }, + reflectionDescription: + "The `sdk.store` class provides methods to send requests to Medusa's Store API routes.", + reflectionTitle: { + fullReplacement: "JS SDK Store Reference", + }, + }, + "^js_sdk/store/Store/properties/": { + frontmatterData: { + slug: "/references/js-sdk/admin/{{alias}}", + sidebar_label: "{{alias}}", + }, + reflectionTitle: { + kind: false, + typeParameters: false, + suffix: "- JS SDK Store Reference", + }, + reflectionDescription: + "This documentation provides a reference to the `sdk.store.{{alias}}` set of methods used to send requests to Medusa's Store API routes.", + }, + "^js_sdk/store/classes/.*Admin": { + frontmatterData: { + slug: "/references/js-sdk/admin", + }, + reflectionDescription: + "The `sdk.admin` class provides methods to send requests to Medusa's Admin API routes.", + reflectionTitle: { + fullReplacement: "JS SDK Admin Reference", + }, + }, + "^js_sdk/admin/Admin/properties/": { + frontmatterData: { + slug: "/references/js-sdk/admin/{{alias}}", + sidebar_label: "{{alias}}", + }, + reflectionTitle: { + kind: false, + typeParameters: false, + suffix: "- JS SDK Admin Reference", + }, + reflectionDescription: + "This documentation provides a reference to the `sdk.admin.{{alias}}` set of methods used to send requests to Medusa's Admin API routes.", + }, + "^js_sdk/store/classes/.*Auth": { + frontmatterData: { + slug: "/references/js-sdk/auth", + }, + reflectionDescription: + "The `sdk.auth` class provides methods to send requests to manage a user or customer's authentication", + reflectionTitle: { + fullReplacement: "JS SDK Auth Reference", + }, + }, + "^js_sdk/auth/Auth/methods/": { + frontmatterData: { + slug: "/references/js-sdk/auth/{{alias}}", + sidebar_label: "{{alias}}", + }, + reflectionTitle: { + kind: false, + typeParameters: false, + suffix: "- JS SDK Auth Reference", + }, + reflectionDescription: + "This documentation provides a reference to the `sdk.auth.{{alias}}` method used to send requests to Medusa's Authentication API routes. It can be used for admin users, customers, or custom actor types.", + }, +} + +export default jsSdkOptions diff --git a/www/utils/packages/typedoc-generate-references/src/constants/merger-options.ts b/www/utils/packages/typedoc-generate-references/src/constants/merger-options.ts index 0a98b50718..3d9e1411b4 100644 --- a/www/utils/packages/typedoc-generate-references/src/constants/merger-options.ts +++ b/www/utils/packages/typedoc-generate-references/src/constants/merger-options.ts @@ -40,6 +40,7 @@ const mergerOptions: Partial = { "helper-steps", "workflows", ], + allPropertyReflectionsHaveOwnDocument: ["js-sdk"], allReflectionsHaveOwnDocumentInNamespace: [ ...getNamespaceNames(getCoreFlowNamespaces()), ], diff --git a/www/utils/packages/typedoc-generate-references/src/constants/references.ts b/www/utils/packages/typedoc-generate-references/src/constants/references.ts index fff98c9977..2260ebd22a 100644 --- a/www/utils/packages/typedoc-generate-references/src/constants/references.ts +++ b/www/utils/packages/typedoc-generate-references/src/constants/references.ts @@ -27,6 +27,7 @@ const allReferences = [ "file", "fulfillment-provider", "helper-steps", + "js-sdk", "medusa-config", "medusa", "modules-sdk", diff --git a/www/utils/packages/typedoc-plugin-markdown-medusa/src/index.ts b/www/utils/packages/typedoc-plugin-markdown-medusa/src/index.ts index 98727f588b..14415938ce 100644 --- a/www/utils/packages/typedoc-plugin-markdown-medusa/src/index.ts +++ b/www/utils/packages/typedoc-plugin-markdown-medusa/src/index.ts @@ -40,6 +40,13 @@ export function load(app: Application) { defaultValue: [], }) + app.options.addDeclaration({ + help: "[Markdown Plugin] Specify module names where property reflections are outputted into seperate files.", + name: "allPropertyReflectionsHaveOwnDocument", + type: ParameterType.Array, + defaultValue: [], + }) + app.options.addDeclaration({ help: "[Markdown Plugin] Specify namespace names where all reflections are outputted into seperate files.", name: "allReflectionsHaveOwnDocumentInNamespace", diff --git a/www/utils/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.declaration.hbs b/www/utils/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.declaration.hbs index 9a853f8526..0cb27bc799 100755 --- a/www/utils/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.declaration.hbs +++ b/www/utils/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.declaration.hbs @@ -56,24 +56,10 @@ {{#if type.declaration.signatures}} -{{#if type.declaration.children}} - -{{{titleLevel}}} Call signature - -{{else}} - -{{{titleLevel}}} Type declaration - -{{/if}} - {{#each type.declaration.signatures}} -{{incrementCurrentTitleLevel}} - {{> member.signature-wrapper showSources=false parent=../type.declaration }} -{{decrementCurrentTitleLevel}} - {{/each}} {{/if}} @@ -84,11 +70,23 @@ {{#if type.declaration.children}} -{{#with type.declaration}} +{{#unless (getFormattingOption "expandMembers")}} {{{titleLevel}}} Properties -{{/with}} +{{incrementCurrentTitleLevel}} + +{{/unless}} + +{{#if (shouldExpandProperties "Properties")}} + +{{#each type.declaration.children}} + +{{> member }} + +{{/each}} + +{{else}} {{#with type.declaration.children}} @@ -98,6 +96,14 @@ {{/if}} +{{#unless (getFormattingOption "expandMembers")}} + +{{decrementCurrentTitleLevel}} + +{{/unless}} + +{{/if}} + {{/if}} {{/if}} diff --git a/www/utils/packages/typedoc-plugin-markdown-medusa/src/theme.ts b/www/utils/packages/typedoc-plugin-markdown-medusa/src/theme.ts index 8f01ef8d51..73fd753265 100644 --- a/www/utils/packages/typedoc-plugin-markdown-medusa/src/theme.ts +++ b/www/utils/packages/typedoc-plugin-markdown-medusa/src/theme.ts @@ -30,6 +30,7 @@ import { Mapping } from "./types" export class MarkdownTheme extends Theme { allReflectionsHaveOwnDocument!: string[] + allPropertyReflectionsHaveOwnDocument!: string[] allReflectionsHaveOwnDocumentInNamespace: string[] entryDocument: string entryPoints!: string[] @@ -65,6 +66,9 @@ export class MarkdownTheme extends Theme { // prettier-ignore this.allReflectionsHaveOwnDocument = this.getOption("allReflectionsHaveOwnDocument") as string[] + this.allPropertyReflectionsHaveOwnDocument = this.getOption( + "allPropertyReflectionsHaveOwnDocument" + ) as string[] this.allReflectionsHaveOwnDocumentInNamespace = this.getOption( "allReflectionsHaveOwnDocumentInNamespace" ) as string[] @@ -334,7 +338,10 @@ export class MarkdownTheme extends Theme { return parents } - getAllReflectionsHaveOwnDocument(reflection: DeclarationReflection): boolean { + getAllReflectionsHaveOwnDocument( + reflection: DeclarationReflection, + checkProperties?: boolean + ): boolean { const moduleParents = this.getParentsOfKind( reflection, ReflectionKind.Module @@ -344,6 +351,12 @@ export class MarkdownTheme extends Theme { ReflectionKind.Namespace ) + if (checkProperties) { + return moduleParents.some((parent) => + this.allPropertyReflectionsHaveOwnDocument.includes(parent.name) + ) + } + return ( moduleParents.some((parent) => this.allReflectionsHaveOwnDocument.includes(parent.name) @@ -458,6 +471,20 @@ export class MarkdownTheme extends Theme { }, ] : []), + ...(this.getAllReflectionsHaveOwnDocument(reflection, true) + ? [ + { + kind: [ReflectionKind.Property], + modifiers: { + has: [], + not: [], + }, + isLeaf: true, + directory: path.join(directoryPrefix || "", "properties"), + template: this.getReflectionMemberTemplate(), + }, + ] + : []), ] } diff --git a/www/utils/packages/typedoc-plugin-workflows/src/plugin.ts b/www/utils/packages/typedoc-plugin-workflows/src/plugin.ts index 97d9ffa2e7..2aa17c1d18 100644 --- a/www/utils/packages/typedoc-plugin-workflows/src/plugin.ts +++ b/www/utils/packages/typedoc-plugin-workflows/src/plugin.ts @@ -92,7 +92,8 @@ class WorkflowsPlugin { const workflowId = this.helper.getStepOrWorkflowId( initializer, - context.project + context.project, + "workflow" ) if (!workflowId) { @@ -270,6 +271,7 @@ class WorkflowsPlugin { stepId = this.helper.getStepOrWorkflowId( originalInitializer, context.project, + "step", true ) stepType = this.helper.getStepType(originalInitializer) diff --git a/www/utils/packages/typedoc-plugin-workflows/src/utils/helper.ts b/www/utils/packages/typedoc-plugin-workflows/src/utils/helper.ts index 9419d1ea1a..b3c4da0426 100644 --- a/www/utils/packages/typedoc-plugin-workflows/src/utils/helper.ts +++ b/www/utils/packages/typedoc-plugin-workflows/src/utils/helper.ts @@ -3,8 +3,9 @@ import { ParameterReflection, ProjectReflection, } from "typedoc" -import ts, { isStringLiteral } from "typescript" +import ts from "typescript" import { StepModifier, StepType } from "../types" +import { capitalize } from "utils" /** * A class of helper methods. @@ -84,13 +85,22 @@ export default class Helper { * @returns The ID of the step or workflow. */ getStepOrWorkflowId( - initializer: ts.CallExpression, + initializer: ts.CallExpression | ts.ArrowFunction, project: ProjectReflection, + type: "workflow" | "step", checkWorkflowStep = false ): string | undefined { - const idArg = initializer.arguments[0] + const callInitializer = ts.isCallExpression(initializer) + ? initializer + : this.getCallExpressionFromBody(initializer.body) + if (!callInitializer) { + throw new Error( + `Couldn't find initializer of a step or workflow: ${initializer.getText()}` + ) + } + const idArg = callInitializer.arguments[0] const isWorkflowStep = - checkWorkflowStep && this.getStepType(initializer) === "workflowStep" + checkWorkflowStep && this.getStepType(callInitializer) === "workflowStep" const idArgValue = this.normalizeName(idArg.getText()) let stepId: string | undefined @@ -106,15 +116,58 @@ export default class Helper { ? nameValue : this.getValueFromReflection(nameValue, project) } - } else if (!isStringLiteral(idArg)) { + } else if (!ts.isStringLiteral(idArg)) { stepId = this.getValueFromReflection(idArgValue, project) } else { stepId = idArgValue } + if (!stepId && ts.isArrowFunction(initializer)) { + stepId = this._getStepOrWorkflowIdFromArrowFunction(initializer, type) + } + return isWorkflowStep ? `${stepId}-as-step` : stepId } + private _getStepOrWorkflowIdFromArrowFunction( + initializer: ts.ArrowFunction, + type: "workflow" | "step" + ) { + // for arrow functions, the inner workflow / step isn't exported + // so we have to rely on a hacky way of retrieving the ID from the source file + const sourceFile = initializer.getSourceFile() + const localMap: Map = + "locals" in sourceFile + ? (sourceFile.locals as Map) + : new Map() + + if (!localMap.size) { + throw new Error(`Couldn't find ID of ${type}: ${initializer.getText()}`) + } + + let id = "" + const capitalizedType = capitalize(type) + + localMap.forEach((value, key) => { + if ( + !key.endsWith(`${capitalizedType}Id`) || + id.length || + !value.declarations?.length || + !ts.isVariableDeclaration(value.declarations[0]) + ) { + return + } + + id = value.declarations[0].initializer?.getText() || "" + }) + + if (!id.length) { + throw new Error(`Couldn't find ID of ${type}: ${initializer.getText()}`) + } + + return this.normalizeName(id) + } + private getValueFromReflection( refName: string, project: ProjectReflection @@ -139,8 +192,9 @@ export default class Helper { * @param initializer - The initializer of the step. * @returns The step's type. */ - getStepType(initializer: ts.CallExpression): StepType { - switch (initializer.expression.getText()) { + getStepType(initializer: ts.CallExpression | ts.ArrowFunction): StepType { + const stepText = this._getStepText(initializer) + switch (stepText) { case "createWorkflow": return "workflowStep" case "createHook": @@ -152,6 +206,57 @@ export default class Helper { } } + private _getStepText( + initializer: ts.CallExpression | ts.ArrowFunction + ): string { + if (ts.isCallExpression(initializer)) { + return initializer.expression.getText() + } + + const callExpression = this.getCallExpressionFromBody(initializer.body) + + if ( + callExpression && + (!("symbol" in callExpression) || !callExpression.symbol) + ) { + // for arrow functions, the inner workflow / step isn't exported + // so we have to rely on a hacky way of retrieving the text from the source file + + const sourceFile = initializer.getSourceFile() + const localMap: Map = + "locals" in sourceFile + ? (sourceFile.locals as Map) + : new Map() + + let text = "" + const fnName = callExpression.expression.getText() + localMap.forEach((value, key) => { + if (text.length) { + return + } + + if ( + key === fnName && + value.declarations?.length && + "initializer" in value.declarations[0] && + ts.isCallExpression(value.declarations[0].initializer as ts.Node) + ) { + text = this._getStepText( + value.declarations[0].initializer as ts.CallExpression + ) + } + }) + + return text + } else if (callExpression?.symbol) { + return ( + (callExpression.symbol as ts.Symbol).declarations?.[0].getText() || "" + ) + } + + return "" + } + /** * Get the modifier to use based on the step's type. * @@ -193,4 +298,39 @@ export default class Helper { return str } + + getCallExpressionFromBody( + body: ts.ConciseBody + ): ts.CallExpression | undefined { + let callExpression: ts.CallExpression | undefined + + const checkChildren = (child: ts.Node) => { + if (callExpression) { + return + } else if (ts.isCallExpression(child)) { + callExpression = child + return + } + + if ("expression" in child) { + checkChildren(child.expression as ts.Node) + } + } + + body.forEachChild(checkChildren) + + return callExpression + } + + getIdentifierExpression(node: ts.Node): ts.Identifier | undefined { + if (ts.isIdentifier(node)) { + return node + } + + if ("expression" in node) { + return this.getIdentifierExpression(node.expression as ts.Node) + } + + return + } } diff --git a/www/utils/packages/types/lib/index.d.ts b/www/utils/packages/types/lib/index.d.ts index 920eb18762..f804f8d5e6 100644 --- a/www/utils/packages/types/lib/index.d.ts +++ b/www/utils/packages/types/lib/index.d.ts @@ -140,6 +140,10 @@ export declare module "typedoc" { * [Markdown Plugin] Specify module names where all reflections are outputted into seperate files. */ allReflectionsHaveOwnDocument: string[] + /** + * [Markdown Plugin] Specify module names where property reflections are outputted into seperate files. + */ + allPropertyReflectionsHaveOwnDocument: string[] /** * [Markdown Plugin] Separator used to format filenames. * @defaultValue "." diff --git a/www/utils/packages/utils/src/get-type-children.ts b/www/utils/packages/utils/src/get-type-children.ts index 0284fd2879..babd52b771 100644 --- a/www/utils/packages/utils/src/get-type-children.ts +++ b/www/utils/packages/utils/src/get-type-children.ts @@ -170,7 +170,12 @@ const REJECTED_CHILDREN_NAMES = ["__type"] function filterChildren(children: DeclarationReflection[]) { return children.filter( - (child) => !REJECTED_CHILDREN_NAMES.includes(child.name) + (child) => + !REJECTED_CHILDREN_NAMES.includes(child.name) && + !child.comment?.modifierTags.has("@ignore") && + !child.signatures?.some( + (signature) => signature.comment?.modifierTags.has("@ignore") + ) ) }