From 262064fe96305e68abb76e7474fdaf37daa973b6 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Wed, 7 May 2025 14:56:54 +0300 Subject: [PATCH] docs: show events emitted in an API route in the API reference (#12392) * docs: show events emitted in an API route in the API reference * fix build error * support version tag * add missing property --- .../DescriptionSection/Events/index.tsx | 135 ++++++++++++++++++ .../Operation/DescriptionSection/index.tsx | 11 ++ .../Parameters/Types/Object/index.tsx | 4 + .../Tags/Operation/Parameters/index.tsx | 3 + www/packages/types/src/openapi.ts | 10 ++ .../docs-generator/src/classes/kinds/oas.ts | 1 + .../docs-generator/src/types/index.d.ts | 1 + www/utils/packages/types/lib/index.d.ts | 1 + 8 files changed, 166 insertions(+) create mode 100644 www/apps/api-reference/components/Tags/Operation/DescriptionSection/Events/index.tsx diff --git a/www/apps/api-reference/components/Tags/Operation/DescriptionSection/Events/index.tsx b/www/apps/api-reference/components/Tags/Operation/DescriptionSection/Events/index.tsx new file mode 100644 index 0000000000..ba8b2afafd --- /dev/null +++ b/www/apps/api-reference/components/Tags/Operation/DescriptionSection/Events/index.tsx @@ -0,0 +1,135 @@ +"use client" + +import { + Badge, + DetailsSummary, + Link, + MarkdownContent, + Tabs, + TabsContent, + TabsContentWrapper, + TabsList, + TabsTrigger, + Tooltip, +} from "docs-ui" +import { useMemo } from "react" +import type { OpenAPI } from "types" +import TagOperationParameters from "../../Parameters" + +export type TagsOperationDescriptionSectionEventsProps = { + events: OpenAPI.OasEvents[] +} + +const TagsOperationDescriptionSectionEvents = ({ + events, +}: TagsOperationDescriptionSectionEventsProps) => { + return ( + <> + + The following events are emitted by the workflow used in this API + route. You can listen to and handle these events using a{" "} + + Subscriber + + + } + expandable={false} + className="border-t-0" + titleClassName="text-h3 mt-1.5" + /> + + + {events.map((event) => ( + + {event.name} + + ))} + + + {events.map((event) => ( + + ))} + + + + ) +} + +export default TagsOperationDescriptionSectionEvents + +const TagsOperationDescriptionSectionEvent = ({ + event, +}: { + event: OpenAPI.OasEvents +}) => { + const parsedPayload: OpenAPI.SchemaObject = useMemo(() => { + const payloadParams = event.payload.matchAll( + /([\w_]+),? \/\/ (\(\w*\) )*(.*)/g + ) + const payload = Array.from(payloadParams).map((match) => { + return { + name: match[1], + type: match[2]?.replace(/\(|\)/g, "") || "string", + description: match[3], + } + }) + return { + type: "object", + required: ["payload"], + properties: { + payload: { + type: "object", + description: "The payload emitted with the event", + required: [...payload.map((param) => param.name)], + properties: payload.reduce( + (acc, curr) => { + acc[curr.name] = { + type: curr.type as OpenAPI.OpenAPIV3.NonArraySchemaObjectType, + description: curr.description, + properties: {}, + } + return acc + }, + {} as Record + ), + }, + }, + } + }, [event.payload]) + return ( + +
+ + {`\`${event.name}\`: ${event.description}`} + + {event.deprecated && + (event.deprecated_message ? ( + + Deprecated + + ) : ( + Deprecated + ))} + {event.version && ( + + v{event.version} + + )} +
+ +
+ ) +} diff --git a/www/apps/api-reference/components/Tags/Operation/DescriptionSection/index.tsx b/www/apps/api-reference/components/Tags/Operation/DescriptionSection/index.tsx index ad186040a6..4193fa8154 100644 --- a/www/apps/api-reference/components/Tags/Operation/DescriptionSection/index.tsx +++ b/www/apps/api-reference/components/Tags/Operation/DescriptionSection/index.tsx @@ -11,6 +11,7 @@ import { useArea } from "../../../../providers/area" import { Feedback, Badge, Link, FeatureFlagNotice, H2 } from "docs-ui" import { usePathname } from "next/navigation" import { TagsOperationDescriptionSectionWorkflowBadgeProps } from "./WorkflowBadge" +import { TagsOperationDescriptionSectionEventsProps } from "./Events" const TagsOperationDescriptionSectionSecurity = dynamic( @@ -32,6 +33,11 @@ const TagsOperationDescriptionSectionWorkflowBadge = async () => import("./WorkflowBadge") ) as React.FC +const TagsOperationDescriptionSectionEvents = + dynamic( + async () => import("./Events") + ) as React.FC + type TagsOperationDescriptionSectionProps = { operation: OpenAPI.Operation } @@ -103,6 +109,11 @@ const TagsOperationDescriptionSection = ({ + {(operation["x-events"]?.length || 0) > 0 && ( + + )} ) } diff --git a/www/apps/api-reference/components/Tags/Operation/Parameters/Types/Object/index.tsx b/www/apps/api-reference/components/Tags/Operation/Parameters/Types/Object/index.tsx index 82b28f3b68..8391f194bf 100644 --- a/www/apps/api-reference/components/Tags/Operation/Parameters/Types/Object/index.tsx +++ b/www/apps/api-reference/components/Tags/Operation/Parameters/Types/Object/index.tsx @@ -36,6 +36,7 @@ export type TagOperationParametersObjectProps = { schema: OpenAPI.SchemaObject isRequired?: boolean topLevel?: boolean + isExpanded?: boolean } const TagOperationParametersObject = ({ @@ -43,6 +44,7 @@ const TagOperationParametersObject = ({ schema, isRequired, topLevel = false, + isExpanded = false, }: TagOperationParametersObjectProps) => { const isPropertiesEmpty = useMemo( () => !schema.properties || !Object.values(schema.properties).length, @@ -112,6 +114,7 @@ const TagOperationParametersObject = ({ properties[property].isRequired || checkRequired(schema, property) } + isExpanded={isExpanded} /> ))} @@ -141,6 +144,7 @@ const TagOperationParametersObject = ({
{getPropertyParameterElms(true)}
diff --git a/www/apps/api-reference/components/Tags/Operation/Parameters/index.tsx b/www/apps/api-reference/components/Tags/Operation/Parameters/index.tsx index a850f9a5b8..33dac38847 100644 --- a/www/apps/api-reference/components/Tags/Operation/Parameters/index.tsx +++ b/www/apps/api-reference/components/Tags/Operation/Parameters/index.tsx @@ -45,6 +45,7 @@ export type TagOperationParametersProps = { topLevel?: boolean className?: string isRequired?: boolean + isExpanded?: boolean } const TagOperationParameters = ({ @@ -52,6 +53,7 @@ const TagOperationParameters = ({ className, topLevel = false, isRequired: originalIsRequired = false, + isExpanded = false, }: TagOperationParametersProps) => { const isRequired = originalIsRequired || checkRequired(schemaObject, schemaObject.title) @@ -95,6 +97,7 @@ const TagOperationParameters = ({ schema={schemaObject} topLevel={topLevel} isRequired={isRequired} + isExpanded={isExpanded} /> ) } diff --git a/www/packages/types/src/openapi.ts b/www/packages/types/src/openapi.ts index 21ff1079d3..6aeb41a3ec 100644 --- a/www/packages/types/src/openapi.ts +++ b/www/packages/types/src/openapi.ts @@ -22,6 +22,7 @@ export type Operation = OpenAPIV3.OperationObject<{ "x-featureFlag"?: string "x-workflow"?: string "x-sidebar-summary"?: string + "x-events"?: OasEvents[] }> export type RequestObject = OpenAPIV3.RequestBodyObject & { @@ -134,3 +135,12 @@ export type TagObject = OpenAPIV3.TagObject & { export type ParsedPathItemObject = OpenAPIV3.PathItemObject & { operationPath?: string } + +export type OasEvents = { + name: string + payload: string + description?: string + deprecated?: boolean + deprecated_message?: string + version?: string +} diff --git a/www/utils/packages/docs-generator/src/classes/kinds/oas.ts b/www/utils/packages/docs-generator/src/classes/kinds/oas.ts index 9ef698e210..ab625e9f68 100644 --- a/www/utils/packages/docs-generator/src/classes/kinds/oas.ts +++ b/www/utils/packages/docs-generator/src/classes/kinds/oas.ts @@ -2690,6 +2690,7 @@ class OasKindGenerator extends FunctionKindGenerator { description: event.description, deprecated: event.deprecated, deprecated_message: event.deprecated_message, + version: event.version, })) ) } diff --git a/www/utils/packages/docs-generator/src/types/index.d.ts b/www/utils/packages/docs-generator/src/types/index.d.ts index ed63270787..ef2c7cd5ad 100644 --- a/www/utils/packages/docs-generator/src/types/index.d.ts +++ b/www/utils/packages/docs-generator/src/types/index.d.ts @@ -46,4 +46,5 @@ export declare type OasEvent = { description?: string deprecated?: boolean deprecated_message?: string + version?: string } diff --git a/www/utils/packages/types/lib/index.d.ts b/www/utils/packages/types/lib/index.d.ts index 49c7bb71d9..4803318c45 100644 --- a/www/utils/packages/types/lib/index.d.ts +++ b/www/utils/packages/types/lib/index.d.ts @@ -345,4 +345,5 @@ export declare type MedusaEvent = { version?: string deprecated?: boolean deprecated_message?: string + version?: string }