docs: generate events reference (#12341)
* docs: generate events reference * change link in navbar * fix redirect
This commit is contained in:
1 parent
332e46d1db
commit
70a99a2434
94 files changed
+31164
-18109
No files matched your search
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -3,6 +3,7 @@ import DefaultKindGenerator, { GetDocBlockOptions } from "./default.js"
|
||||
import { glob } from "glob"
|
||||
import getMonorepoRoot from "../../utils/get-monorepo-root.js"
|
||||
import { readFile } from "fs/promises"
|
||||
import { MedusaEvent } from "types"
|
||||
|
||||
class EventsKindGenerator extends DefaultKindGenerator<ts.VariableDeclaration> {
|
||||
protected allowedKinds: ts.SyntaxKind[] = [ts.SyntaxKind.VariableDeclaration]
|
||||
@@ -33,17 +34,7 @@ class EventsKindGenerator extends DefaultKindGenerator<ts.VariableDeclaration> {
|
||||
const properties = (node.initializer as ts.ObjectLiteralExpression)
|
||||
.properties
|
||||
|
||||
const events: {
|
||||
name: string
|
||||
parentName: string
|
||||
propertyName: string
|
||||
payload: string
|
||||
description?: string
|
||||
workflows: string[]
|
||||
version?: string
|
||||
deprecated?: boolean
|
||||
deprecated_message?: string
|
||||
}[] = properties
|
||||
const events: MedusaEvent[] = properties
|
||||
.filter((property) => ts.isPropertyAssignment(property))
|
||||
.map((property) => {
|
||||
const propertyAssignment = property as ts.PropertyAssignment
|
||||
|
||||
@@ -57,6 +57,18 @@
|
||||
{
|
||||
"tagName": "@tags",
|
||||
"syntaxKind": "block"
|
||||
},
|
||||
{
|
||||
"tagName": "@eventName",
|
||||
"syntaxKind": "block"
|
||||
},
|
||||
{
|
||||
"tagName": "@workflows",
|
||||
"syntaxKind": "block"
|
||||
},
|
||||
{
|
||||
"tagName": "@eventPayload",
|
||||
"syntaxKind": "block"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -47,6 +47,19 @@ const customOptions: Record<string, Partial<TypeDocOptions>> = {
|
||||
tsConfigName: "types.json",
|
||||
name: "event",
|
||||
}),
|
||||
events: getOptions({
|
||||
entryPointPath: "packages/core/utils/src/core-flows/events.ts",
|
||||
tsConfigName: "utils.json",
|
||||
name: "events",
|
||||
enableEventsResolver: true,
|
||||
}),
|
||||
"module-events": getOptions({
|
||||
entryPointPath: "packages/core/utils/src/core-flows/events.ts",
|
||||
tsConfigName: "utils.json",
|
||||
name: "module-events",
|
||||
enableEventsResolver: true,
|
||||
generateCustomNamespaces: true,
|
||||
}),
|
||||
file: getOptions({
|
||||
entryPointPath: "packages/core/utils/src/file/abstract-file-provider.ts",
|
||||
tsConfigName: "utils.json",
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import { FormattingOptionsType } from "types"
|
||||
|
||||
const eventsOptions: FormattingOptionsType = {
|
||||
"^modules/events/": {
|
||||
reflectionDescription: `This documentation page includes the list of all events emitted by [Medusa's workflows](https://docs.medusajs.com/resources/medusa-workflows-reference).`,
|
||||
frontmatterData: {
|
||||
slug: "/references/events",
|
||||
sidebar_label: "Events Reference",
|
||||
},
|
||||
isEventsReference: true,
|
||||
reflectionTitle: {
|
||||
fullReplacement: "Events Reference",
|
||||
},
|
||||
},
|
||||
"^module_events": {
|
||||
expandMembers: true,
|
||||
isEventsReference: true,
|
||||
reflectionDescription: `This reference shows all the events emitted by the Medusa application related to the {{alias}} Module. If you use the module outside the Medusa application, these events aren't emitted.`,
|
||||
reflectionTitle: {
|
||||
suffix: "Module Events Reference",
|
||||
},
|
||||
frontmatterData: {
|
||||
slug: "/references/{{alias-slug}}/events",
|
||||
sidebar_label: "Events Reference",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default eventsOptions
|
||||
+2
@@ -18,6 +18,7 @@ import cacheOptions from "./cache.js"
|
||||
import eventOptions from "./event.js"
|
||||
import fileServiceOptions from "./file-service.js"
|
||||
import notificationServiceOptions from "./notification-service.js"
|
||||
import eventsOptions from "./events.js"
|
||||
|
||||
const mergerCustomOptions: FormattingOptionsType = {
|
||||
...authProviderOptions,
|
||||
@@ -25,6 +26,7 @@ const mergerCustomOptions: FormattingOptionsType = {
|
||||
...coreFlowsOptions,
|
||||
...dmlOptions,
|
||||
...eventOptions,
|
||||
...eventsOptions,
|
||||
...fileServiceOptions,
|
||||
...fileOptions,
|
||||
...fulfillmentProviderOptions,
|
||||
|
||||
@@ -30,6 +30,9 @@ const allowedProjectDocuments: AllowedProjectDocumentsOption = {
|
||||
[ReflectionKind.Method]: true,
|
||||
[ReflectionKind.Property]: true,
|
||||
},
|
||||
"module-events": {
|
||||
[ReflectionKind.Namespace]: true,
|
||||
},
|
||||
}
|
||||
|
||||
modules.forEach((module) => {
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
import { readFileSync } from "fs"
|
||||
import path from "path"
|
||||
import {
|
||||
Application,
|
||||
Comment,
|
||||
CommentTag,
|
||||
Context,
|
||||
Converter,
|
||||
DeclarationReflection,
|
||||
ParameterType,
|
||||
ReflectionKind,
|
||||
} from "typedoc"
|
||||
import { MedusaEvent } from "types"
|
||||
import { getDirname } from "utils"
|
||||
|
||||
export class EventsResolver {
|
||||
private app: Application
|
||||
private events: MedusaEvent[] = []
|
||||
|
||||
constructor(app: Application) {
|
||||
this.app = app
|
||||
|
||||
this.app.options.addDeclaration({
|
||||
name: "enableEventsResolver",
|
||||
help: "Whether to resolve events.",
|
||||
type: ParameterType.Boolean,
|
||||
defaultValue: false,
|
||||
})
|
||||
|
||||
this.app.converter.on(
|
||||
Converter.EVENT_RESOLVE_BEGIN,
|
||||
this.resolveEvents.bind(this)
|
||||
)
|
||||
}
|
||||
|
||||
resolveEvents(context: Context) {
|
||||
if (!this.app.options.getValue("enableEventsResolver")) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.events.length) {
|
||||
const __dirname = getDirname(import.meta.url)
|
||||
|
||||
const jsonFilePath = path.resolve(
|
||||
__dirname,
|
||||
path.join("..", "..", "..", "generated", "events-output.json")
|
||||
)
|
||||
// read events file
|
||||
const eventsJSON = readFileSync(jsonFilePath, "utf-8")
|
||||
this.events = JSON.parse(eventsJSON)
|
||||
}
|
||||
|
||||
for (const reflection of context.project.getReflectionsByKind(
|
||||
ReflectionKind.Variable
|
||||
)) {
|
||||
if (
|
||||
!(reflection instanceof DeclarationReflection) ||
|
||||
reflection.type?.type !== "reflection" ||
|
||||
!reflection.type.declaration.children
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
const relatedEvents = this.events.filter(
|
||||
(event) => event.parentName === reflection.name
|
||||
)
|
||||
|
||||
if (!relatedEvents.length) {
|
||||
continue
|
||||
}
|
||||
|
||||
// loop over variable properties
|
||||
for (const property of reflection.type.declaration.children) {
|
||||
const propertyEvent = relatedEvents.find(
|
||||
(event) => event.propertyName === property.name
|
||||
)
|
||||
|
||||
if (!propertyEvent) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (!property.comment) {
|
||||
property.comment = new Comment()
|
||||
}
|
||||
|
||||
property.comment.blockTags.push(
|
||||
new CommentTag("@eventName", [
|
||||
{
|
||||
kind: "code",
|
||||
text: propertyEvent.name,
|
||||
},
|
||||
])
|
||||
)
|
||||
|
||||
property.comment.blockTags.push(
|
||||
new CommentTag("@workflows", [
|
||||
{
|
||||
kind: "text",
|
||||
text: propertyEvent.workflows.join(", "),
|
||||
},
|
||||
])
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import { load as dmlTypesNormalizer } from "./dml-types-normalizer.js"
|
||||
import { MermaidDiagramDMLGenerator } from "./mermaid-diagram-dml-generator.js"
|
||||
import { load as dmlJsonParser } from "./dml-json-parser.js"
|
||||
import { GenerateCustomNamespacePlugin } from "./generate-custom-namespaces.js"
|
||||
import { EventsResolver } from "./events-resolver.js"
|
||||
|
||||
export function load(app: Application) {
|
||||
resolveReferencesPluginLoad(app)
|
||||
@@ -30,4 +31,5 @@ export function load(app: Application) {
|
||||
new DmlRelationsResolver(app)
|
||||
new MermaidDiagramDMLGenerator(app)
|
||||
new GenerateCustomNamespacePlugin(app)
|
||||
new EventsResolver(app)
|
||||
}
|
||||
@@ -38,6 +38,7 @@
|
||||
"dependencies": {
|
||||
"handlebars": "^4.7.8",
|
||||
"js-beautify": "^1.15.1",
|
||||
"slugify": "^1.6.6",
|
||||
"utils": "*"
|
||||
}
|
||||
}
|
||||
@@ -80,6 +80,8 @@ 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 ifEventsReferenceHelper from "./resources/helpers/if-events-reference.js"
|
||||
import eventsListingHelper from "./resources/helpers/events-listing.js"
|
||||
import { MarkdownTheme } from "./theme.js"
|
||||
import { getDirname } from "utils"
|
||||
|
||||
@@ -191,4 +193,6 @@ export function registerHelpers(theme: MarkdownTheme) {
|
||||
sourceCodeLinkHelper()
|
||||
workflowExamplesHelper()
|
||||
stepExamplesHelper()
|
||||
ifEventsReferenceHelper(theme)
|
||||
eventsListingHelper()
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
import Handlebars from "handlebars"
|
||||
import pkg from "slugify"
|
||||
import { DeclarationReflection } from "typedoc"
|
||||
import { pascalToWords } from "utils"
|
||||
|
||||
const slugify = pkg.default
|
||||
|
||||
export default function () {
|
||||
Handlebars.registerHelper(
|
||||
"eventsListing",
|
||||
function (this: DeclarationReflection) {
|
||||
const content: string[] = []
|
||||
|
||||
const subtitleLevel = (this.children?.length ?? 0) > 1 ? 3 : 2
|
||||
const showHeader = (this.children?.length ?? 0) > 1
|
||||
|
||||
this.children?.forEach((child, index) => {
|
||||
content.push(
|
||||
formatEventsType(child as DeclarationReflection, {
|
||||
subtitleLevel,
|
||||
showHeader,
|
||||
})
|
||||
)
|
||||
if (index < this.children!.length - 1) {
|
||||
content.push("")
|
||||
content.push("---")
|
||||
content.push("")
|
||||
}
|
||||
})
|
||||
|
||||
return content.join("\n")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function formatEventsType(
|
||||
eventVariable: DeclarationReflection,
|
||||
{
|
||||
subtitleLevel = 3,
|
||||
showHeader = true,
|
||||
}: {
|
||||
subtitleLevel?: number
|
||||
showHeader?: boolean
|
||||
}
|
||||
) {
|
||||
if (eventVariable.type?.type !== "reflection") {
|
||||
return ""
|
||||
}
|
||||
const content: string[] = []
|
||||
const subHeaderPrefix = "#".repeat(subtitleLevel)
|
||||
const header = pascalToWords(
|
||||
eventVariable.name.replaceAll("WorkflowEvents", "")
|
||||
)
|
||||
if (showHeader) {
|
||||
content.push(`## ${header} Events`)
|
||||
}
|
||||
content.push("")
|
||||
|
||||
const eventProperties = eventVariable.type.declaration.children || []
|
||||
|
||||
content.push(`${subHeaderPrefix} Summary`)
|
||||
content.push("")
|
||||
// table start
|
||||
content.push(`<Table>`)
|
||||
// table header start
|
||||
content.push(` <Table.Header>`)
|
||||
content.push(` <Table.Row>`)
|
||||
content.push(` <Table.HeaderCell>\nEvent\n</Table.HeaderCell>`)
|
||||
content.push(` <Table.HeaderCell>\nDescription\n</Table.HeaderCell>`)
|
||||
// table header end
|
||||
content.push(` </Table.Row>`)
|
||||
content.push(` </Table.Header>`)
|
||||
// table body start
|
||||
content.push(` <Table.Body>`)
|
||||
eventProperties.forEach((event) => {
|
||||
const eventName =
|
||||
event.comment?.blockTags
|
||||
.find((tag) => tag.tag === "@eventName")
|
||||
?.content.map((content) => content.text)
|
||||
.join("") || ""
|
||||
const eventDescription = event.comment?.summary
|
||||
.map((content) => content.text)
|
||||
.join("")
|
||||
|
||||
content.push(` <Table.Row>`)
|
||||
content.push(
|
||||
` <Table.Cell>\n[${eventName}](#${slugify(
|
||||
eventName.replace(".", ""),
|
||||
{
|
||||
lower: true,
|
||||
}
|
||||
)})\n</Table.Cell>`
|
||||
)
|
||||
content.push(` <Table.Cell>\n${eventDescription}\n</Table.Cell>`)
|
||||
content.push(` </Table.Row>`)
|
||||
})
|
||||
// table body end
|
||||
content.push(` </Table.Body>`)
|
||||
// table end
|
||||
content.push(`</Table>`)
|
||||
content.push("")
|
||||
|
||||
eventProperties.forEach((event, index) => {
|
||||
const eventName = event.comment?.blockTags
|
||||
.find((tag) => tag.tag === "@eventName")
|
||||
?.content.map((content) => content.text)
|
||||
.join("")
|
||||
const eventDescription = event.comment?.summary
|
||||
.map((content) => content.text)
|
||||
.join("")
|
||||
const eventPayload = event.comment?.blockTags
|
||||
.find((tag) => tag.tag === "@eventPayload")
|
||||
?.content.map((content) => content.text)
|
||||
.join("")
|
||||
const workflows = event.comment?.blockTags
|
||||
.find((tag) => tag.tag === "@workflows")
|
||||
?.content.map((content) => content.text)
|
||||
.join("")
|
||||
.split(", ")
|
||||
|
||||
content.push(`${subHeaderPrefix} \`${eventName}\``)
|
||||
content.push("")
|
||||
content.push(eventDescription || "")
|
||||
content.push("")
|
||||
content.push(`${subHeaderPrefix}# Payload`)
|
||||
content.push("")
|
||||
content.push(eventPayload || "")
|
||||
content.push("")
|
||||
content.push(`${subHeaderPrefix}# Workflows Emitting this Event`)
|
||||
content.push("")
|
||||
workflows?.forEach((workflow) => {
|
||||
content.push(`- [${workflow}](/references/medusa-workflows/${workflow})`)
|
||||
})
|
||||
content.push("")
|
||||
if (index < eventProperties.length - 1) {
|
||||
content.push("---")
|
||||
content.push("")
|
||||
}
|
||||
})
|
||||
|
||||
return content.join("\n")
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import Handlebars from "handlebars"
|
||||
import { Reflection } from "typedoc"
|
||||
import { MarkdownTheme } from "../../theme.js"
|
||||
|
||||
export default function (theme: MarkdownTheme) {
|
||||
Handlebars.registerHelper(
|
||||
"ifEventsReference",
|
||||
function (this: Reflection, options: Handlebars.HelperOptions) {
|
||||
const { isEventsReference = false } =
|
||||
theme.getFormattingOptionsForLocation()
|
||||
|
||||
return isEventsReference ? options.fn(this) : options.inverse(this)
|
||||
}
|
||||
)
|
||||
}
|
||||
+12
@@ -6,6 +6,16 @@
|
||||
|
||||
{{{ startSections }}}
|
||||
|
||||
{{#ifEventsReference}}
|
||||
|
||||
{{#with model}}
|
||||
|
||||
{{{ eventsListing }}}
|
||||
|
||||
{{/with}}
|
||||
|
||||
{{else}}
|
||||
|
||||
{{#with model}}
|
||||
|
||||
{{#if (sectionEnabled "reflection_comment")}}
|
||||
@@ -148,4 +158,6 @@
|
||||
|
||||
{{/with}}
|
||||
|
||||
{{/ifEventsReference}}
|
||||
|
||||
{{{ endSections }}}
|
||||
+9
@@ -1,4 +1,7 @@
|
||||
import { Reflection, ReflectionKind } from "typedoc"
|
||||
import pkg from "slugify"
|
||||
|
||||
const slugify = pkg.default
|
||||
|
||||
export function replaceTemplateVariables(
|
||||
reflection: Reflection,
|
||||
@@ -11,6 +14,12 @@ export function replaceTemplateVariables(
|
||||
return text
|
||||
.replaceAll("{{alias}}", reflection.name)
|
||||
.replaceAll("{{alias-lower}}", reflection.name.toLowerCase())
|
||||
.replaceAll(
|
||||
"{{alias-slug}}",
|
||||
slugify(reflection.name, {
|
||||
lower: true,
|
||||
})
|
||||
)
|
||||
.replaceAll("{{parent.alias}}", reflection.parent?.name || "")
|
||||
.replaceAll(
|
||||
"{{parent.alias-lower}}",
|
||||
|
||||
+18
@@ -100,6 +100,7 @@ export type FormattingOptionType = {
|
||||
shouldIncrementAfterStartSections?: boolean
|
||||
hideTocHeaders?: boolean
|
||||
workflowDiagramComponent?: string
|
||||
isEventsReference?: boolean
|
||||
}
|
||||
|
||||
export type AllowedProjectDocumentsOption = {
|
||||
@@ -289,6 +290,11 @@ export declare module "typedoc" {
|
||||
* Optionally specify a name prefix for all custom namespaces.
|
||||
*/
|
||||
customNamespaceNamePrefix: string
|
||||
/**
|
||||
* Whether to resolve events.
|
||||
* @defaultValue false
|
||||
*/
|
||||
enableEventsResolver: boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,3 +334,15 @@ export declare type NamespaceGenerateDetails = {
|
||||
*/
|
||||
children?: NamespaceGenerateDetails[]
|
||||
}
|
||||
|
||||
export declare type MedusaEvent = {
|
||||
name: string
|
||||
parentName: string
|
||||
propertyName: string
|
||||
payload: string
|
||||
description?: string
|
||||
workflows: string[]
|
||||
version?: string
|
||||
deprecated?: boolean
|
||||
deprecated_message?: string
|
||||
}
|
||||
@@ -5556,6 +5556,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"slugify@npm:^1.6.6":
|
||||
version: 1.6.6
|
||||
resolution: "slugify@npm:1.6.6"
|
||||
checksum: e7e63f08f389a371d6228bc19d64ec84360bf0a538333446cc49dbbf3971751a6d180d2f31551188dd007a65ca771e69f574e0283290a7825a818e90b75ef44d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"source-map@npm:^0.6.1":
|
||||
version: 0.6.1
|
||||
resolution: "source-map@npm:0.6.1"
|
||||
@@ -6035,6 +6042,7 @@ __metadata:
|
||||
copyfiles: ^2.4.1
|
||||
handlebars: ^4.7.8
|
||||
js-beautify: ^1.15.1
|
||||
slugify: ^1.6.6
|
||||
typedoc: ^0.27.5
|
||||
types: "*"
|
||||
typescript: ^5.6.2
|
||||
|
||||
Reference in new issue
Block a user