Skip to content

Commit

Permalink
docs-util: generate examples for workflows and steps
Browse files Browse the repository at this point in the history
  • Loading branch information
shahednasser committed Jan 10, 2025
1 parent feb9810 commit a311b0d
Show file tree
Hide file tree
Showing 14 changed files with 531 additions and 136 deletions.
4 changes: 4 additions & 0 deletions www/apps/resources/components/MDXComponents/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
TypeList,
WorkflowDiagram,
SourceCodeLink,
CodeTabs,
CodeTab,
} from "docs-ui"
import { CommerceModuleSections } from "../CommerceModuleSections"

Expand All @@ -15,6 +17,8 @@ const MDXComponents: MDXComponentsType = {
WorkflowDiagram,
CommerceModuleSections,
SourceCodeLink,
CodeTabs,
CodeTab,
}

export default MDXComponents
1 change: 0 additions & 1 deletion www/utils/packages/docs-generator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"openai": "^4.29.1",
"openapi-types": "^12.1.3",
"pluralize": "^8.0.0",
"prettier": "^3.2.4",
"ts-node": "^10.9.1",
"typescript": "^5.6.2",
"utils": "*",
Expand Down
28 changes: 2 additions & 26 deletions www/utils/packages/docs-generator/src/classes/helpers/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import path from "path"
import dirname from "../../utils/dirname.js"
import { minimatch } from "minimatch"
import { existsSync } from "fs"
import * as prettier from "prettier"
import getRelativePaths from "../../utils/get-relative-paths.js"
import { formatWithPrettier } from "utils"

/**
* A class used to apply formatting to files using ESLint and other formatting options.
Expand Down Expand Up @@ -174,10 +174,7 @@ class Formatter {
content: string,
fileName: string
): Promise<string> {
const prettifiedContent = await this.formatStrWithPrettier(
content,
fileName
)
const prettifiedContent = await formatWithPrettier(content, fileName)
const relevantConfig = await this.getESLintOverridesConfigForFile(fileName)

const eslint = new ESLint({
Expand All @@ -203,27 +200,6 @@ class Formatter {
return newContent
}

/**
* Format a file's content with prettier.
*
* @param content - The content to format.
* @param fileName - The name of the file the content belongs to.
* @returns The formatted content
*/
async formatStrWithPrettier(
content: string,
fileName: string
): Promise<string> {
// load config of the file
const prettierConfig = (await prettier.resolveConfig(fileName)) || undefined

if (prettierConfig && !prettierConfig.parser) {
prettierConfig.parser = "babel-ts"
}

return await prettier.format(content, prettierConfig)
}

/**
* Applies all formatting types to a string.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"typedoc": "0.27.x"
},
"devDependencies": {
"@types/js-beautify": "^1.14.3",
"@types/node": "^20.12.10",
"copyfiles": "^2.4.1",
"typedoc": "^0.27.5",
Expand All @@ -36,6 +37,7 @@
],
"dependencies": {
"handlebars": "^4.7.8",
"js-beautify": "^1.15.1",
"utils": "*"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ import ifMemberShowTitleHelper from "./resources/helpers/if-member-show-title.js
import signatureCommentHelper from "./resources/helpers/signature-comment.js"
import versionHelper from "./resources/helpers/version.js"
import sourceCodeLinkHelper from "./resources/helpers/source-code-link.js"
import workflowExamplesHelper from "./resources/helpers/workflow-examples.js"
import stepExamplesHelper from "./resources/helpers/step-examples.js"
import { MarkdownTheme } from "./theme.js"
import { getDirname } from "utils"

Expand Down Expand Up @@ -187,4 +189,6 @@ export function registerHelpers(theme: MarkdownTheme) {
signatureCommentHelper()
versionHelper()
sourceCodeLinkHelper()
workflowExamplesHelper()
stepExamplesHelper()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Handlebars from "handlebars"
import { DeclarationReflection, SignatureReflection } from "typedoc"
import { getReflectionTypeFakeValueStr, getStepInputType } from "utils"
import pkg from "js-beautify"

const { js_beautify } = pkg

export default function () {
Handlebars.registerHelper(
"stepExamples",
function (this: SignatureReflection): string {
const stepReflection = this.parent

const exampleTags = stepReflection.comment?.blockTags.filter(
(tag) => tag.tag === "@example"
)

if (exampleTags?.length) {
return Handlebars.helpers.example(stepReflection)
}

return generateStepExample(stepReflection)
}
)
}

function generateStepExample(stepReflection: DeclarationReflection): string {
if (!stepReflection.signatures?.length) {
return ""
}
const inputType = getStepInputType(stepReflection.signatures[0])
const inputStr = inputType
? `${getReflectionTypeFakeValueStr({
reflectionType: inputType,
name: "",
})}`
: ""

// generate example
return `
\`\`\`ts title="src/workflows/my-workflow.ts"
${js_beautify(
`import { createWorkflow } from "@medusajs/framework/workflows-sdk"
import { ${stepReflection.name} } from "@medusajs/medusa/core-flows"
const myWorkflow = createWorkflow(
"my-workflow",
() => {
const data = ${stepReflection.name}(${inputStr})
}
)`,
{
indent_size: 2,
brace_style: "preserve-inline",
wrap_line_length: 80,
}
)}
\`\`\`
`
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { SignatureReflection } from "typedoc"
import Handlebars from "handlebars"
import pkg from "js-beautify"
import { DeclarationReflection, SignatureReflection } from "typedoc"
import { getReflectionTypeFakeValueStr, getWorkflowInputType } from "utils"

const { js_beautify } = pkg

export default function () {
Handlebars.registerHelper(
Expand All @@ -12,24 +17,29 @@ export default function () {
)

if (!exampleTags?.length) {
return ""
}

exampleTags.forEach((exampleTag) => {
exampleTag.content.forEach((part) => {
if (part.kind !== "code") {
exampleStr.push(part.text)
return
}

exampleStr.push(
getExecutionCodeTabs({
exampleCode: part.text,
workflowName: workflowReflection.name,
})
)
exampleStr.push(
getExecutionCodeTabs({
exampleCode: generateWorkflowExample(workflowReflection),
workflowName: workflowReflection.name,
})
)
} else {
exampleTags.forEach((exampleTag) => {
exampleTag.content.forEach((part) => {
if (part.kind !== "code") {
exampleStr.push(part.text)
return
}

exampleStr.push(
getExecutionCodeTabs({
exampleCode: part.text,
workflowName: workflowReflection.name,
})
)
})
})
})
}

return exampleStr.join("\n")
}
Expand All @@ -43,28 +53,40 @@ function getExecutionCodeTabs({
exampleCode: string
workflowName: string
}): string {
exampleCode = exampleCode.replace("```ts\n", "").replace("\n```", "")
const beautifyOptions: pkg.JSBeautifyOptions = {
indent_size: 2,
brace_style: "preserve-inline",
wrap_line_length: 80,
}

return `<CodeTabs group="workflow-exection">
<CodeTab label="Another Workflow" value="another-workflow">
\`\`\`ts
import { createWorkflow } from "@medusajs/framework/workflows-sdk"
\`\`\`ts title="src/workflows/my-workflow.ts"
${js_beautify(
`import { createWorkflow } from "@medusajs/framework/workflows-sdk"
import { ${workflowName} } from "@medusajs/medusa/core-flows"
const myWorkflow = createWorkflow(
"my-workflow",
() => {
${exampleCode
.replace(`{ result }`, "result")
.replace(`await `, "")
.replace(`(container)\n\t.run(`, ".runAsStep(")}
}
)
)`,
beautifyOptions
)}
\`\`\`
</CodeTab>
<CodeTab label="API Route" value="api-route">
\`\`\`ts
import type {
\`\`\`ts title="src/api/workflow/route.ts"
${js_beautify(
`import type {
MedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
Expand All @@ -74,18 +96,21 @@ export async function POST(
req: MedusaRequest,
res: MedusaResponse
) {
${exampleCode.replace("container", "req.scope")}
${exampleCode.replace("container", "req.scope")}
res.send(result)
}
)
res.send(result)
}
`,
beautifyOptions
)}
\`\`\`
</CodeTab>
<CodeTab label="Subscriber" value="subscriber">
\`\`\`ts
import {
\`\`\`ts title="src/subscribers/order-placed.ts"
${js_beautify(
`import {
type SubscriberConfig,
type SubscriberArgs,
} from "@medusajs/framework"
Expand All @@ -102,30 +127,53 @@ export default async function handleOrderPlaced({
export const config: SubscriberConfig = {
event: "order.placed",
}
}`,
beautifyOptions
)}
\`\`\`
</CodeTab>
<CodeTab label="Scheduled Job" value="scheduled-job">
\`\`\`ts
import { MedusaContainer } from "@medusajs/framework/types"
\`\`\`ts title="src/jobs/message-daily.ts"
${js_beautify(
`import { MedusaContainer } from "@medusajs/framework/types"
import { ${workflowName} } from "@medusajs/medusa/core-flows"
export default async function myCustomJob(
container: MedusaContainer
) {
${exampleCode}
console.log(result.message)
console.log(result)
}
export const config = {
name: "run-once-a-day",
schedule: "0 0 * * *",
};
}`,
beautifyOptions
)}
\`\`\`
</CodeTab>
</CodeTabs>`
}

function generateWorkflowExample(
workflowReflection: DeclarationReflection
): string {
if (!workflowReflection.signatures?.length) {
return ""
}
const inputType = getWorkflowInputType(workflowReflection.signatures[0])
const inputStr = inputType
? `{\n\t\tinput: ${getReflectionTypeFakeValueStr({
reflectionType: inputType,
name: "",
})}\n\t}`
: ""

// generate example
return `const { result } = await ${workflowReflection.name}(container)\n\t.run(${inputStr})`
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

{{#if (sectionEnabled "member_signature_example")}}

{{{example this}}}
{{{stepExamples this}}}

{{/if}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

{{#if (sectionEnabled "member_signature_example")}}

{{{example this}}}
{{{workflowExamples this}}}

{{/if}}

Expand Down
14 changes: 0 additions & 14 deletions www/utils/packages/typedoc-plugin-workflows/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,20 +232,6 @@ class WorkflowsPlugin {
])

this.updateWorkflowsTagsMap(workflowId, uniqueResources)

// try to generate example
const generatedExample =
this.examplesHelper.generateWorkflowExample(parentReflection)
if (generatedExample) {
parentReflection.comment?.blockTags.push(
new CommentTag(`@example`, [
{
kind: "code",
text: generatedExample,
},
])
)
}
}

/**
Expand Down
Loading

0 comments on commit a311b0d

Please sign in to comment.