fumadocs-openapi 10.5.0 → 10.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/generated/shared.css +26 -21
- package/dist/generate-file.d.ts +10 -2
- package/dist/generate-file.d.ts.map +1 -1
- package/dist/generate-file.js +15 -3
- package/dist/generate-file.js.map +1 -1
- package/dist/playground/client.d.ts +27 -7
- package/dist/playground/client.d.ts.map +1 -1
- package/dist/playground/client.js +51 -44
- package/dist/playground/client.js.map +1 -1
- package/dist/playground/components/inputs.js +1 -1
- package/dist/playground/components/inputs.js.map +1 -1
- package/dist/playground/components/server-select.js +3 -4
- package/dist/playground/components/server-select.js.map +1 -1
- package/dist/playground/index.d.ts +1 -1
- package/dist/playground/index.d.ts.map +1 -1
- package/dist/playground/index.js +2 -2
- package/dist/playground/index.js.map +1 -1
- package/dist/playground/schema.d.ts.map +1 -1
- package/dist/playground/schema.js +10 -12
- package/dist/playground/schema.js.map +1 -1
- package/dist/requests/generators/python.d.ts +2 -1
- package/dist/requests/generators/python.d.ts.map +1 -1
- package/dist/requests/generators/python.js +13 -2
- package/dist/requests/generators/python.js.map +1 -1
- package/dist/scalar/index.d.ts +2 -1
- package/dist/scalar/index.d.ts.map +1 -1
- package/dist/server/create.d.ts +2 -0
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/create.js +11 -8
- package/dist/server/create.js.map +1 -1
- package/dist/server/source-api.d.ts +2 -0
- package/dist/server/source-api.d.ts.map +1 -1
- package/dist/server/source-api.js +10 -1
- package/dist/server/source-api.js.map +1 -1
- package/dist/types.d.ts +2 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/api-page.d.ts +1 -2
- package/dist/ui/api-page.d.ts.map +1 -1
- package/dist/ui/api-page.js +4 -6
- package/dist/ui/api-page.js.map +1 -1
- package/dist/ui/base.d.ts +20 -16
- package/dist/ui/base.d.ts.map +1 -1
- package/dist/ui/base.js +18 -9
- package/dist/ui/base.js.map +1 -1
- package/dist/ui/{full.client.js → client/full.js} +3 -3
- package/dist/ui/client/full.js.map +1 -0
- package/dist/ui/client/index.d.ts +1 -1
- package/dist/ui/client/index.js.map +1 -1
- package/dist/ui/client/storage-key.js.map +1 -1
- package/dist/ui/components/server-tab.js +43 -0
- package/dist/ui/components/server-tab.js.map +1 -0
- package/dist/ui/contexts/api.js +18 -35
- package/dist/ui/contexts/api.js.map +1 -1
- package/dist/ui/create-client.d.ts +26 -0
- package/dist/ui/create-client.d.ts.map +1 -0
- package/dist/ui/create-client.js +132 -0
- package/dist/ui/create-client.js.map +1 -0
- package/dist/ui/index.d.ts +10 -2
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +21 -1
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/operation/client.js +44 -36
- package/dist/ui/operation/client.js.map +1 -1
- package/dist/ui/operation/{request-tabs.d.ts → get-example-requests.d.ts} +2 -4
- package/dist/ui/operation/get-example-requests.d.ts.map +1 -0
- package/dist/ui/operation/get-example-requests.js +83 -0
- package/dist/ui/operation/get-example-requests.js.map +1 -0
- package/dist/ui/operation/index.js +101 -63
- package/dist/ui/operation/index.js.map +1 -1
- package/dist/ui/operation/request-tabs.js +3 -81
- package/dist/ui/operation/request-tabs.js.map +1 -1
- package/dist/ui/operation/response-tabs.d.ts +1 -1
- package/dist/ui/operation/response-tabs.js +57 -54
- package/dist/ui/operation/response-tabs.js.map +1 -1
- package/dist/ui/operation/usage-tabs/client.js +7 -48
- package/dist/ui/operation/usage-tabs/client.js.map +1 -1
- package/dist/ui/operation/usage-tabs/index.js +14 -10
- package/dist/ui/operation/usage-tabs/index.js.map +1 -1
- package/dist/ui/operation/usage-tabs/lazy.js +1 -2
- package/dist/ui/operation/usage-tabs/lazy.js.map +1 -1
- package/dist/ui/schema/index.d.ts +1 -1
- package/dist/ui/schema/index.js +4 -2
- package/dist/ui/schema/index.js.map +1 -1
- package/dist/utils/pages/builder.d.ts +1 -1
- package/dist/utils/pages/builder.js +1 -1
- package/dist/utils/process-document.d.ts +1 -1
- package/dist/utils/process-document.js +1 -32
- package/dist/utils/process-document.js.map +1 -1
- package/dist/utils/schema/dereference.js +37 -0
- package/dist/utils/schema/dereference.js.map +1 -0
- package/dist/utils/{schema.d.ts → schema/index.d.ts} +3 -3
- package/dist/utils/schema/index.d.ts.map +1 -0
- package/dist/utils/{schema.js → schema/index.js} +3 -3
- package/dist/utils/schema/index.js.map +1 -0
- package/dist/utils/schema/resolve-ref.js +21 -0
- package/dist/utils/schema/resolve-ref.js.map +1 -0
- package/dist/utils/{schema-to-string.js → schema/to-string.js} +2 -2
- package/dist/utils/schema/to-string.js.map +1 -0
- package/package.json +5 -4
- package/dist/requests/to-python-object.js +0 -17
- package/dist/requests/to-python-object.js.map +0 -1
- package/dist/ui/full.client.js.map +0 -1
- package/dist/ui/full.d.ts +0 -11
- package/dist/ui/full.d.ts.map +0 -1
- package/dist/ui/full.js +0 -36
- package/dist/ui/full.js.map +0 -1
- package/dist/ui/operation/request-tabs.d.ts.map +0 -1
- package/dist/utils/schema-to-string.js.map +0 -1
- package/dist/utils/schema.d.ts.map +0 -1
- package/dist/utils/schema.js.map +0 -1
- /package/dist/utils/{schema-to-string.d.ts → schema/to-string.d.ts} +0 -0
package/dist/ui/base.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","names":[],"sources":["../../src/ui/base.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"base.d.ts","names":[],"sources":["../../src/ui/base.tsx"],"mappings":";;;;;;;;;;;;;;;;;;UA4BiB,oCAAA,SAA6C,aAAA;EAC5D,SAAA,EAAW,WAAA,CAAY,iBAAA;EACvB,QAAA;EACA,SAAA;EAHe;EAKf,gBAAA;IACE,UAAA;IACA,WAAA;EAAA;AAAA;AAAA,UAIa,oBAAA;EAX0D;;;;;;;;;EAqBzE,wBAAA,KAEM,MAAA,EAAQ,WAAA,CAAY,iBAAA,GACpB,UAAA,UACA,WAAA,UACA,GAAA,EAAK,aAAA,KACF,SAAA;EApBI;;AAIf;;;EAwBE,6BAAA,KAEM,MAAA,EAAQ,UAAA,EACR,GAAA,EAAK,oCAAA,KACF,SAAA;EAhBK;;;EAsBd,UAAA,GAAa,0BAAA;EAPF;;;EAYX,mBAAA,IAAuB,MAAA,EAAQ,iBAAA,KAAsB,wBAAA;EAErD,KAAA,EAAO,YAAA;EACP,cAAA,IAAkB,EAAA,aAAe,SAAA;EACjC,YAAA,EAAc,IAAA,CAAK,uBAAA,YAAmC,iBAAA,CAAkB,YAAA;EAArD;;;;;EAOnB,kBAAA;EAW8B;;;EAN9B,aAAA,GAAgB,MAAA,SAAe,YAAA;EAUtB;;;EALT,OAAA;IACE,kBAAA,IAAsB,IAAA,EAAM,WAAA,IAAe,GAAA,EAAK,aAAA,KAAkB,SAAA;IAElE,iBAAA,IACE,KAAA,EAAO,kBAAA,IACP,GAAA,EAAK,aAAA;MACH,KAAA;MACA,SAAA,EAAW,WAAA,CAAY,iBAAA;IAAA,MAEtB,SAAA;IAEL,sBAAA,IACE,KAAA;MACE,QAAA,EAAU,SAAA;MACV,SAAA,EAAW,SAAA;MACX,YAAA,EAAc,SAAA;IAAA,GAEhB,GAAA,EAAK,aAAA,KACF,SAAA;IAoBO;;;IAfZ,yBAAA,IACE,UAAA,EAAY,0BAAA,EACZ,GAAA,EAAK,aAAA,KACF,SAAA;IAqBO;;;IAhBZ,gBAAA,IACE,KAAA;MACE,UAAA;QACE,IAAA,EAAM,aAAA;QACN,QAAA,EAAU,SAAA;MAAA;MAEZ,QAAA;QACE,IAAA,EAAM,WAAA;QACN,QAAA,EAAU,SAAA;MAAA;IAAA,GAGd,GAAA,EAAK,aAAA,KACF,SAAA;IAEL,qBAAA,IACE,KAAA;MACE,MAAA,EAAQ,SAAA;MACR,WAAA,EAAa,SAAA;MACb,UAAA,EAAY,SAAA;MACZ,aAAA,EAAe,SAAA;MAEf,WAAA,EAAa,SAAA;MACb,UAAA,EAAY,SAAA;MACZ,IAAA,EAAM,SAAA;MACN,SAAA,EAAW,SAAA;MACX,SAAA,EAAW,SAAA;IAAA,GAEb,GAAA,EAAK,aAAA,EACL,MAAA,EAAQ,WAAA,CAAY,iBAAA,MACjB,SAAA;IAEL,mBAAA,IAAuB,KAAA;MACrB,MAAA,EAAQ,SAAA;MACR,WAAA,EAAa,SAAA;MACb,WAAA,EAAa,SAAA;MACb,UAAA,EAAY,SAAA;MACZ,IAAA,EAAM,SAAA;MACN,QAAA,EAAU,SAAA;MACV,SAAA,EAAW,SAAA;MACX,SAAA,EAAW,SAAA;IAAA,MACP,SAAA;EAAA;EAsCqB;;;EAhC7B,QAAA;IACE,MAAA,IAAU,OAAA,EAAS,eAAA,EAAiB,GAAA,EAAK,aAAA,KAAkB,SAAA;IA7HvD;;;;;IAoIJ,WAAA;EAAA;EAvHI;;;EA6HN,UAAA;IArHA;;;IAyHE,OAAA;IApHqB;;;IAwHrB,MAAA,IAAU,KAAA;MACR,IAAA;MACA,MAAA,EAAQ,iBAAA;MACR,GAAA,EAAK,aAAA;IAAA,MACD,SAAA,CAAU,SAAA;EAAA;EAGlB,aAAA,IAAiB,KAAA,EAAO,cAAA,CAAe,kBAAA,GAAqB,KAAA,aAAkB,SAAA;EAC9E,eAAA,IAAmB,KAAA;IAAS,IAAA;IAAc,IAAA;EAAA,MAAmB,SAAA;EAE7D,MAAA,GAAS,oBAAA;AAAA;AAAA,UAGM,kBAAA,SAA2B,IAAA,CAAK,YAAA;EAC/C,QAAA,WAAmB,iBAAA;AAAA;AAAA,iBAGL,aAAA,CACd,MAAA,EAAQ,aAAA,EACR,OAAA,EAAS,oBAAA,GACR,EAAA,CAAG,kBAAA"}
|
package/dist/ui/base.js
CHANGED
|
@@ -13,6 +13,7 @@ import remarkRehype from "remark-rehype";
|
|
|
13
13
|
import { toJsxRuntime } from "hast-util-to-jsx-runtime";
|
|
14
14
|
import { CodeBlock, Pre } from "fumadocs-ui/components/codeblock";
|
|
15
15
|
import { highlightHast } from "fumadocs-core/highlight/shiki";
|
|
16
|
+
import { compile } from "@fumari/json-schema-ts";
|
|
16
17
|
//#region src/ui/base.tsx
|
|
17
18
|
function createAPIPage(server, options) {
|
|
18
19
|
let processor;
|
|
@@ -37,7 +38,7 @@ function createAPIPage(server, options) {
|
|
|
37
38
|
return async function APIPageWrapper({ document, ...props }) {
|
|
38
39
|
let processed;
|
|
39
40
|
if (typeof document === "string") processed = await server.getSchema(document);
|
|
40
|
-
else processed =
|
|
41
|
+
else processed = document;
|
|
41
42
|
const slugger = new Slugger();
|
|
42
43
|
const ctx = {
|
|
43
44
|
schema: processed,
|
|
@@ -47,8 +48,7 @@ function createAPIPage(server, options) {
|
|
|
47
48
|
...defaultAdapters,
|
|
48
49
|
...options.mediaAdapters
|
|
49
50
|
},
|
|
50
|
-
|
|
51
|
-
async renderHeading(depth, text, props) {
|
|
51
|
+
renderHeading(depth, text, props) {
|
|
52
52
|
const id = typeof text === "string" ? slugger.slug(text) : props?.id;
|
|
53
53
|
if (!id) throw new Error("missing 'id' for non-string children");
|
|
54
54
|
if (options.renderHeading) return options.renderHeading({
|
|
@@ -63,14 +63,23 @@ function createAPIPage(server, options) {
|
|
|
63
63
|
children: text
|
|
64
64
|
}, id);
|
|
65
65
|
},
|
|
66
|
-
generateTypeScriptDefinitions(schema, ctx) {
|
|
67
|
-
|
|
68
|
-
if (generateTypeScriptSchema && ctx._internal_legacy) {
|
|
66
|
+
generateTypeScriptDefinitions: options.generateTypeScriptDefinitions ?? ((schema, ctx) => {
|
|
67
|
+
if (options.generateTypeScriptSchema && ctx._internal_legacy) {
|
|
69
68
|
const { statusCode, contentType } = ctx._internal_legacy;
|
|
70
|
-
return generateTypeScriptSchema(ctx.operation, statusCode, contentType, ctx);
|
|
69
|
+
return options.generateTypeScriptSchema(ctx.operation, statusCode, contentType, ctx);
|
|
71
70
|
}
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
if (typeof schema !== "object") return;
|
|
72
|
+
try {
|
|
73
|
+
return compile(schema, {
|
|
74
|
+
name: "Response",
|
|
75
|
+
readOnly: ctx.readOnly,
|
|
76
|
+
writeOnly: ctx.writeOnly,
|
|
77
|
+
getSchemaId: ctx.schema.getRawRef
|
|
78
|
+
});
|
|
79
|
+
} catch (e) {
|
|
80
|
+
console.warn("Failed to generate typescript schema:", e);
|
|
81
|
+
}
|
|
82
|
+
}),
|
|
74
83
|
async renderMarkdown(text) {
|
|
75
84
|
if (options.renderMarkdown) return options.renderMarkdown(text);
|
|
76
85
|
processor ??= createMarkdownProcessor();
|
package/dist/ui/base.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","names":[],"sources":["../../src/ui/base.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any -- rehype-react without types */\nimport Slugger from 'github-slugger';\nimport type { Awaitable, MethodInformation, RenderContext } from '@/types';\nimport type { NoReference } from '@/utils/schema';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport { defaultAdapters, MediaAdapter } from '@/requests/media/adapter';\nimport type { FC, HTMLAttributes, ReactNode } from 'react';\nimport type { OpenAPIServer } from '@/server';\nimport type { APIPageClientOptions } from './client';\nimport { Heading } from 'fumadocs-ui/components/heading';\nimport { createRehypeCode } from 'fumadocs-core/mdx-plugins/rehype-code.core';\nimport { remarkGfm } from 'fumadocs-core/mdx-plugins/remark-gfm';\nimport defaultMdxComponents from 'fumadocs-ui/mdx';\nimport { remark } from 'remark';\nimport remarkRehype from 'remark-rehype';\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime';\nimport * as JsxRuntime from 'react/jsx-runtime';\nimport { CodeBlock, Pre } from 'fumadocs-ui/components/codeblock';\nimport type { SchemaUIOptions } from './schema';\nimport type { ResponseTab } from './operation/response-tabs';\nimport type { ExampleRequestItem } from './operation/request-tabs';\nimport { APIPage, type ApiPageProps, type OperationItem, type WebhookItem } from './api-page';\nimport type { CodeUsageGeneratorRegistry, InlineCodeUsageGenerator } from '@/requests/generators';\nimport type { JSONSchema } from 'json-schema-typed';\nimport type { BundledTheme, CodeOptionsThemes, CodeToHastOptionsCommon } from 'shiki';\nimport { highlightHast, type ShikiFactory } from 'fumadocs-core/highlight/shiki';\n\nexport interface GenerateTypeScriptDefinitionsContext extends RenderContext {\n operation: NoReference<MethodInformation>;\n readOnly: boolean;\n writeOnly: boolean;\n /** @deprecated */\n _internal_legacy?: {\n statusCode: string;\n contentType: string;\n };\n}\n\nexport interface CreateAPIPageOptions {\n /**\n * Generate TypeScript definitions from response schema.\n *\n * Pass `false` to disable it.\n *\n * @param method - the operation object\n * @param statusCode - status code\n * @deprecated use `generateTypeScriptDefinitions` instead.\n */\n generateTypeScriptSchema?:\n | ((\n method: NoReference<MethodInformation>,\n statusCode: string,\n contentType: string,\n ctx: RenderContext,\n ) => Awaitable<string | undefined>)\n | false;\n\n /**\n * Generate TypeScript definitions from JSON schema.\n *\n * Pass `false` to disable it.\n */\n generateTypeScriptDefinitions?: (\n schema: JSONSchema,\n ctx: GenerateTypeScriptDefinitionsContext,\n ) => Awaitable<string | undefined>;\n\n /**\n * Generate example code usage for all endpoints.\n */\n codeUsages?: CodeUsageGeneratorRegistry;\n\n /**\n * Generate example code usage for each endpoint.\n */\n generateCodeSamples?: (method: MethodInformation) => Awaitable<InlineCodeUsageGenerator[]>;\n\n shiki: ShikiFactory;\n renderMarkdown?: (md: string) => ReactNode;\n shikiOptions: Omit<CodeToHastOptionsCommon, 'lang'> & CodeOptionsThemes<BundledTheme>;\n\n /**\n * Show full response schema instead of only example response & Typescript definitions.\n *\n * @default true\n */\n showResponseSchema?: boolean;\n\n /**\n * Support other media types (for server-side generation).\n */\n mediaAdapters?: Record<string, MediaAdapter>;\n\n /**\n * Customise page content\n */\n content?: {\n renderResponseTabs?: (tabs: ResponseTab[], ctx: RenderContext) => Awaitable<ReactNode>;\n\n renderRequestTabs?: (\n items: ExampleRequestItem[],\n ctx: RenderContext & {\n route: string;\n operation: NoReference<MethodInformation>;\n },\n ) => Awaitable<ReactNode>;\n\n renderAPIExampleLayout?: (\n slots: {\n selector: ReactNode;\n usageTabs: ReactNode;\n responseTabs: ReactNode;\n },\n ctx: RenderContext,\n ) => Awaitable<ReactNode>;\n\n /**\n * @param generators - codegens for API example usages\n */\n renderAPIExampleUsageTabs?: (\n generators: CodeUsageGeneratorRegistry,\n ctx: RenderContext,\n ) => Awaitable<ReactNode>;\n\n /**\n * renderer of the entire page's layout (containing all operations & webhooks UI)\n */\n renderPageLayout?: (\n slots: {\n operations?: {\n item: OperationItem;\n children: ReactNode;\n }[];\n webhooks?: {\n item: WebhookItem;\n children: ReactNode;\n }[];\n },\n ctx: RenderContext,\n ) => Awaitable<ReactNode>;\n\n renderOperationLayout?: (\n slots: {\n header: ReactNode;\n description: ReactNode;\n apiExample: ReactNode;\n apiPlayground: ReactNode;\n\n authSchemes: ReactNode;\n parameters: ReactNode;\n body: ReactNode;\n responses: ReactNode;\n callbacks: ReactNode;\n },\n ctx: RenderContext,\n method: NoReference<MethodInformation>,\n ) => Awaitable<ReactNode>;\n\n renderWebhookLayout?: (slots: {\n header: ReactNode;\n description: ReactNode;\n authSchemes: ReactNode;\n parameters: ReactNode;\n body: ReactNode;\n requests: ReactNode;\n responses: ReactNode;\n callbacks: ReactNode;\n }) => Awaitable<ReactNode>;\n };\n\n /**\n * Info UI for JSON schemas\n */\n schemaUI?: {\n render?: (options: SchemaUIOptions, ctx: RenderContext) => Awaitable<ReactNode>;\n\n /**\n * Show examples under the generated content of JSON schemas.\n *\n * @defaultValue false\n */\n showExample?: boolean;\n };\n\n /**\n * Customise API playground\n */\n playground?: {\n /**\n * @defaultValue true\n */\n enabled?: boolean;\n /**\n * replace the server-side renderer\n */\n render?: (props: {\n path: string;\n method: MethodInformation;\n ctx: RenderContext;\n }) => Awaitable<ReactNode>;\n };\n\n renderHeading?: (\n props: HTMLAttributes<HTMLHeadingElement>,\n depth: number,\n ) => Awaitable<ReactNode>;\n renderCodeBlock?: (props: { lang: string; code: string }) => Awaitable<ReactNode>;\n\n client?: APIPageClientOptions;\n}\n\nexport function createAPIPage(\n server: OpenAPIServer,\n options: CreateAPIPageOptions,\n): FC<ApiPageProps> {\n let processor: ReturnType<typeof createMarkdownProcessor>;\n\n function createMarkdownProcessor() {\n function rehypeReact(this: any) {\n this.compiler = (tree: any, file: any) => {\n return toJsxRuntime(tree, {\n development: false,\n filePath: file.path,\n ...JsxRuntime,\n components: defaultMdxComponents,\n });\n };\n }\n\n return remark()\n .use(remarkGfm)\n .use(remarkRehype)\n .use(createRehypeCode(options.shiki), {\n langs: [],\n lazy: true,\n defaultColor: false,\n ...options.shikiOptions,\n })\n .use(rehypeReact);\n }\n\n return async function APIPageWrapper({ document, ...props }) {\n let processed: ProcessedDocument;\n if (typeof document === 'string') {\n processed = await server.getSchema(document);\n } else {\n processed = await document;\n }\n\n const slugger = new Slugger();\n\n const ctx: RenderContext = {\n schema: processed,\n proxyUrl: server.options.proxyUrl,\n ...options,\n mediaAdapters: {\n ...defaultAdapters,\n ...options.mediaAdapters,\n },\n slugger,\n async renderHeading(depth, text, props) {\n const id = typeof text === 'string' ? slugger.slug(text) : props?.id;\n if (!id) throw new Error(\"missing 'id' for non-string children\");\n\n if (options.renderHeading) {\n return options.renderHeading({ id, children: text, ...props }, depth);\n }\n\n return (\n <Heading id={id} key={id} as={`h${depth}` as `h1`} {...props}>\n {text}\n </Heading>\n );\n },\n generateTypeScriptDefinitions(schema, ctx) {\n const { generateTypeScriptSchema, generateTypeScriptDefinitions } = options;\n if (generateTypeScriptSchema && ctx._internal_legacy) {\n const { statusCode, contentType } = ctx._internal_legacy;\n return generateTypeScriptSchema(ctx.operation, statusCode, contentType, ctx);\n }\n\n return generateTypeScriptDefinitions?.(schema, ctx);\n },\n async renderMarkdown(text) {\n if (options.renderMarkdown) return options.renderMarkdown(text);\n processor ??= createMarkdownProcessor();\n\n const out = await processor.process({\n value: text,\n });\n\n return out.result as ReactNode;\n },\n async renderCodeBlock(lang, code) {\n if (options.renderCodeBlock) {\n return options.renderCodeBlock({ lang, code });\n }\n\n const hast = await highlightHast(await options.shiki.getOrInit(), code, {\n lang,\n defaultColor: false,\n ...options.shikiOptions,\n });\n const rendered = toJsxRuntime(hast, {\n ...JsxRuntime,\n components: {\n pre: Pre,\n },\n });\n\n return <CodeBlock className=\"my-0\">{rendered}</CodeBlock>;\n },\n };\n\n return <APIPage {...props} ctx={ctx} />;\n };\n}\n\nexport { ClientCodeBlockProvider } from './components/codeblock';\n"],"mappings":";;;;;;;;;;;;;;;;AAmNA,SAAgB,cACd,QACA,SACkB;CAClB,IAAI;CAEJ,SAAS,0BAA0B;EACjC,SAAS,cAAuB;AAC9B,QAAK,YAAY,MAAW,SAAc;AACxC,WAAO,aAAa,MAAM;KACxB,aAAa;KACb,UAAU,KAAK;KACf,GAAG;KACH,YAAY;KACb,CAAC;;;AAIN,SAAO,QAAQ,CACZ,IAAI,UAAU,CACd,IAAI,aAAa,CACjB,IAAI,iBAAiB,QAAQ,MAAM,EAAE;GACpC,OAAO,EAAE;GACT,MAAM;GACN,cAAc;GACd,GAAG,QAAQ;GACZ,CAAC,CACD,IAAI,YAAY;;AAGrB,QAAO,eAAe,eAAe,EAAE,UAAU,GAAG,SAAS;EAC3D,IAAI;AACJ,MAAI,OAAO,aAAa,SACtB,aAAY,MAAM,OAAO,UAAU,SAAS;MAE5C,aAAY,MAAM;EAGpB,MAAM,UAAU,IAAI,SAAS;EAE7B,MAAM,MAAqB;GACzB,QAAQ;GACR,UAAU,OAAO,QAAQ;GACzB,GAAG;GACH,eAAe;IACb,GAAG;IACH,GAAG,QAAQ;IACZ;GACD;GACA,MAAM,cAAc,OAAO,MAAM,OAAO;IACtC,MAAM,KAAK,OAAO,SAAS,WAAW,QAAQ,KAAK,KAAK,GAAG,OAAO;AAClE,QAAI,CAAC,GAAI,OAAM,IAAI,MAAM,uCAAuC;AAEhE,QAAI,QAAQ,cACV,QAAO,QAAQ,cAAc;KAAE;KAAI,UAAU;KAAM,GAAG;KAAO,EAAE,MAAM;AAGvE,WACE,oBAAC,SAAD;KAAa;KAAa,IAAI,IAAI;KAAiB,GAAI;eACpD;KACO,EAFY,GAEZ;;GAGd,8BAA8B,QAAQ,KAAK;IACzC,MAAM,EAAE,0BAA0B,kCAAkC;AACpE,QAAI,4BAA4B,IAAI,kBAAkB;KACpD,MAAM,EAAE,YAAY,gBAAgB,IAAI;AACxC,YAAO,yBAAyB,IAAI,WAAW,YAAY,aAAa,IAAI;;AAG9E,WAAO,gCAAgC,QAAQ,IAAI;;GAErD,MAAM,eAAe,MAAM;AACzB,QAAI,QAAQ,eAAgB,QAAO,QAAQ,eAAe,KAAK;AAC/D,kBAAc,yBAAyB;AAMvC,YAJY,MAAM,UAAU,QAAQ,EAClC,OAAO,MACR,CAAC,EAES;;GAEb,MAAM,gBAAgB,MAAM,MAAM;AAChC,QAAI,QAAQ,gBACV,QAAO,QAAQ,gBAAgB;KAAE;KAAM;KAAM,CAAC;AAehD,WAAO,oBAAC,WAAD;KAAW,WAAU;eAPX,aALJ,MAAM,cAAc,MAAM,QAAQ,MAAM,WAAW,EAAE,MAAM;MACtE;MACA,cAAc;MACd,GAAG,QAAQ;MACZ,CAAC,EACkC;MAClC,GAAG;MACH,YAAY,EACV,KAAK,KACN;MACF,CAAC;KAEuD,CAAA;;GAE5D;AAED,SAAO,oBAAC,SAAD;GAAS,GAAI;GAAY;GAAO,CAAA"}
|
|
1
|
+
{"version":3,"file":"base.js","names":[],"sources":["../../src/ui/base.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any -- rehype-react without types */\nimport Slugger from 'github-slugger';\nimport type { Awaitable, MethodInformation, RenderContext } from '@/types';\nimport type { NoReference } from '@/utils/schema';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport { defaultAdapters, MediaAdapter } from '@/requests/media/adapter';\nimport type { FC, HTMLAttributes, ReactNode } from 'react';\nimport type { OpenAPIServer } from '@/server';\nimport type { APIPageClientOptions } from './client';\nimport { Heading } from 'fumadocs-ui/components/heading';\nimport { createRehypeCode } from 'fumadocs-core/mdx-plugins/rehype-code.core';\nimport { remarkGfm } from 'fumadocs-core/mdx-plugins/remark-gfm';\nimport defaultMdxComponents from 'fumadocs-ui/mdx';\nimport { remark } from 'remark';\nimport remarkRehype from 'remark-rehype';\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime';\nimport * as JsxRuntime from 'react/jsx-runtime';\nimport { CodeBlock, Pre } from 'fumadocs-ui/components/codeblock';\nimport type { SchemaUIOptions } from './schema';\nimport type { ResponseTab } from './operation/response-tabs';\nimport { APIPage, type ApiPageProps, type OperationItem, type WebhookItem } from './api-page';\nimport type { CodeUsageGeneratorRegistry, InlineCodeUsageGenerator } from '@/requests/generators';\nimport type { JSONSchema } from 'json-schema-typed';\nimport type { BundledTheme, CodeOptionsThemes, CodeToHastOptionsCommon } from 'shiki';\nimport { highlightHast, type ShikiFactory } from 'fumadocs-core/highlight/shiki';\nimport type { ExampleRequestItem } from './operation/get-example-requests';\nimport { compile } from '@fumari/json-schema-ts';\n\nexport interface GenerateTypeScriptDefinitionsContext extends RenderContext {\n operation: NoReference<MethodInformation>;\n readOnly: boolean;\n writeOnly: boolean;\n /** @deprecated */\n _internal_legacy?: {\n statusCode: string;\n contentType: string;\n };\n}\n\nexport interface CreateAPIPageOptions {\n /**\n * Generate TypeScript definitions from response schema.\n *\n * Pass `false` to disable it.\n *\n * @param method - the operation object\n * @param statusCode - status code\n * @deprecated use `generateTypeScriptDefinitions` instead.\n */\n generateTypeScriptSchema?:\n | ((\n method: NoReference<MethodInformation>,\n statusCode: string,\n contentType: string,\n ctx: RenderContext,\n ) => Awaitable<string | undefined>)\n | false;\n\n /**\n * Generate TypeScript definitions from JSON schema.\n *\n * Pass `false` to disable it.\n */\n generateTypeScriptDefinitions?:\n | ((\n schema: JSONSchema,\n ctx: GenerateTypeScriptDefinitionsContext,\n ) => Awaitable<string | undefined>)\n | false;\n\n /**\n * Generate example code usage for all endpoints.\n */\n codeUsages?: CodeUsageGeneratorRegistry;\n\n /**\n * Generate example code usage for each endpoint.\n */\n generateCodeSamples?: (method: MethodInformation) => InlineCodeUsageGenerator[];\n\n shiki: ShikiFactory;\n renderMarkdown?: (md: string) => ReactNode;\n shikiOptions: Omit<CodeToHastOptionsCommon, 'lang'> & CodeOptionsThemes<BundledTheme>;\n\n /**\n * Show full response schema instead of only example response & Typescript definitions.\n *\n * @default true\n */\n showResponseSchema?: boolean;\n\n /**\n * Support other media types (for server-side generation).\n */\n mediaAdapters?: Record<string, MediaAdapter>;\n\n /**\n * Customise page content\n */\n content?: {\n renderResponseTabs?: (tabs: ResponseTab[], ctx: RenderContext) => ReactNode;\n\n renderRequestTabs?: (\n items: ExampleRequestItem[],\n ctx: RenderContext & {\n route: string;\n operation: NoReference<MethodInformation>;\n },\n ) => ReactNode;\n\n renderAPIExampleLayout?: (\n slots: {\n selector: ReactNode;\n usageTabs: ReactNode;\n responseTabs: ReactNode;\n },\n ctx: RenderContext,\n ) => ReactNode;\n\n /**\n * @param generators - codegens for API example usages\n */\n renderAPIExampleUsageTabs?: (\n generators: CodeUsageGeneratorRegistry,\n ctx: RenderContext,\n ) => ReactNode;\n\n /**\n * renderer of the entire page's layout (containing all operations & webhooks UI)\n */\n renderPageLayout?: (\n slots: {\n operations?: {\n item: OperationItem;\n children: ReactNode;\n }[];\n webhooks?: {\n item: WebhookItem;\n children: ReactNode;\n }[];\n },\n ctx: RenderContext,\n ) => ReactNode;\n\n renderOperationLayout?: (\n slots: {\n header: ReactNode;\n description: ReactNode;\n apiExample: ReactNode;\n apiPlayground: ReactNode;\n\n authSchemes: ReactNode;\n parameters: ReactNode;\n body: ReactNode;\n responses: ReactNode;\n callbacks: ReactNode;\n },\n ctx: RenderContext,\n method: NoReference<MethodInformation>,\n ) => ReactNode;\n\n renderWebhookLayout?: (slots: {\n header: ReactNode;\n description: ReactNode;\n authSchemes: ReactNode;\n parameters: ReactNode;\n body: ReactNode;\n requests: ReactNode;\n responses: ReactNode;\n callbacks: ReactNode;\n }) => ReactNode;\n };\n\n /**\n * Info UI for JSON schemas\n */\n schemaUI?: {\n render?: (options: SchemaUIOptions, ctx: RenderContext) => ReactNode;\n\n /**\n * Show examples under the generated content of JSON schemas.\n *\n * @defaultValue false\n */\n showExample?: boolean;\n };\n\n /**\n * Customise API playground\n */\n playground?: {\n /**\n * @defaultValue true\n */\n enabled?: boolean;\n /**\n * replace the server-side renderer\n */\n render?: (props: {\n path: string;\n method: MethodInformation;\n ctx: RenderContext;\n }) => Awaitable<ReactNode>;\n };\n\n renderHeading?: (props: HTMLAttributes<HTMLHeadingElement>, depth: number) => ReactNode;\n renderCodeBlock?: (props: { lang: string; code: string }) => ReactNode;\n\n client?: APIPageClientOptions;\n}\n\nexport interface ServerApiPageProps extends Omit<ApiPageProps, 'document'> {\n document: string | ProcessedDocument;\n}\n\nexport function createAPIPage(\n server: OpenAPIServer,\n options: CreateAPIPageOptions,\n): FC<ServerApiPageProps> {\n let processor: ReturnType<typeof createMarkdownProcessor>;\n\n function createMarkdownProcessor() {\n function rehypeReact(this: any) {\n this.compiler = (tree: any, file: any) => {\n return toJsxRuntime(tree, {\n development: false,\n filePath: file.path,\n ...JsxRuntime,\n components: defaultMdxComponents,\n });\n };\n }\n\n return remark()\n .use(remarkGfm)\n .use(remarkRehype)\n .use(createRehypeCode(options.shiki), {\n langs: [],\n lazy: true,\n defaultColor: false,\n ...options.shikiOptions,\n })\n .use(rehypeReact);\n }\n\n return async function APIPageWrapper({ document, ...props }) {\n let processed: ProcessedDocument;\n if (typeof document === 'string') {\n processed = await server.getSchema(document);\n } else {\n processed = document;\n }\n\n const slugger = new Slugger();\n\n const ctx: RenderContext = {\n schema: processed,\n proxyUrl: server.options.proxyUrl,\n ...options,\n mediaAdapters: {\n ...defaultAdapters,\n ...options.mediaAdapters,\n },\n renderHeading(depth, text, props) {\n const id = typeof text === 'string' ? slugger.slug(text) : props?.id;\n if (!id) throw new Error(\"missing 'id' for non-string children\");\n\n if (options.renderHeading) {\n return options.renderHeading({ id, children: text, ...props }, depth);\n }\n\n return (\n <Heading id={id} key={id} as={`h${depth}` as `h1`} {...props}>\n {text}\n </Heading>\n );\n },\n generateTypeScriptDefinitions:\n options.generateTypeScriptDefinitions ??\n ((schema, ctx) => {\n if (options.generateTypeScriptSchema && ctx._internal_legacy) {\n const { statusCode, contentType } = ctx._internal_legacy;\n return options.generateTypeScriptSchema(ctx.operation, statusCode, contentType, ctx);\n }\n\n if (typeof schema !== 'object') return;\n try {\n return compile(schema, {\n name: 'Response',\n readOnly: ctx.readOnly,\n writeOnly: ctx.writeOnly,\n getSchemaId: ctx.schema.getRawRef,\n });\n } catch (e) {\n console.warn('Failed to generate typescript schema:', e);\n }\n }),\n async renderMarkdown(text) {\n if (options.renderMarkdown) return options.renderMarkdown(text);\n processor ??= createMarkdownProcessor();\n\n const out = await processor.process({\n value: text,\n });\n\n return out.result as ReactNode;\n },\n async renderCodeBlock(lang, code) {\n if (options.renderCodeBlock) {\n return options.renderCodeBlock({ lang, code });\n }\n\n const hast = await highlightHast(await options.shiki.getOrInit(), code, {\n lang,\n defaultColor: false,\n ...options.shikiOptions,\n });\n const rendered = toJsxRuntime(hast, {\n ...JsxRuntime,\n components: {\n pre: Pre,\n },\n });\n\n return <CodeBlock className=\"my-0\">{rendered}</CodeBlock>;\n },\n };\n\n return <APIPage {...props} ctx={ctx} />;\n };\n}\n\nexport { ClientCodeBlockProvider } from './components/codeblock';\n"],"mappings":";;;;;;;;;;;;;;;;;AAuNA,SAAgB,cACd,QACA,SACwB;CACxB,IAAI;CAEJ,SAAS,0BAA0B;EACjC,SAAS,cAAuB;AAC9B,QAAK,YAAY,MAAW,SAAc;AACxC,WAAO,aAAa,MAAM;KACxB,aAAa;KACb,UAAU,KAAK;KACf,GAAG;KACH,YAAY;KACb,CAAC;;;AAIN,SAAO,QAAQ,CACZ,IAAI,UAAU,CACd,IAAI,aAAa,CACjB,IAAI,iBAAiB,QAAQ,MAAM,EAAE;GACpC,OAAO,EAAE;GACT,MAAM;GACN,cAAc;GACd,GAAG,QAAQ;GACZ,CAAC,CACD,IAAI,YAAY;;AAGrB,QAAO,eAAe,eAAe,EAAE,UAAU,GAAG,SAAS;EAC3D,IAAI;AACJ,MAAI,OAAO,aAAa,SACtB,aAAY,MAAM,OAAO,UAAU,SAAS;MAE5C,aAAY;EAGd,MAAM,UAAU,IAAI,SAAS;EAE7B,MAAM,MAAqB;GACzB,QAAQ;GACR,UAAU,OAAO,QAAQ;GACzB,GAAG;GACH,eAAe;IACb,GAAG;IACH,GAAG,QAAQ;IACZ;GACD,cAAc,OAAO,MAAM,OAAO;IAChC,MAAM,KAAK,OAAO,SAAS,WAAW,QAAQ,KAAK,KAAK,GAAG,OAAO;AAClE,QAAI,CAAC,GAAI,OAAM,IAAI,MAAM,uCAAuC;AAEhE,QAAI,QAAQ,cACV,QAAO,QAAQ,cAAc;KAAE;KAAI,UAAU;KAAM,GAAG;KAAO,EAAE,MAAM;AAGvE,WACE,oBAAC,SAAD;KAAa;KAAa,IAAI,IAAI;KAAiB,GAAI;eACpD;KACO,EAFY,GAEZ;;GAGd,+BACE,QAAQ,mCACN,QAAQ,QAAQ;AAChB,QAAI,QAAQ,4BAA4B,IAAI,kBAAkB;KAC5D,MAAM,EAAE,YAAY,gBAAgB,IAAI;AACxC,YAAO,QAAQ,yBAAyB,IAAI,WAAW,YAAY,aAAa,IAAI;;AAGtF,QAAI,OAAO,WAAW,SAAU;AAChC,QAAI;AACF,YAAO,QAAQ,QAAQ;MACrB,MAAM;MACN,UAAU,IAAI;MACd,WAAW,IAAI;MACf,aAAa,IAAI,OAAO;MACzB,CAAC;aACK,GAAG;AACV,aAAQ,KAAK,yCAAyC,EAAE;;;GAG9D,MAAM,eAAe,MAAM;AACzB,QAAI,QAAQ,eAAgB,QAAO,QAAQ,eAAe,KAAK;AAC/D,kBAAc,yBAAyB;AAMvC,YAJY,MAAM,UAAU,QAAQ,EAClC,OAAO,MACR,CAAC,EAES;;GAEb,MAAM,gBAAgB,MAAM,MAAM;AAChC,QAAI,QAAQ,gBACV,QAAO,QAAQ,gBAAgB;KAAE;KAAM;KAAM,CAAC;AAehD,WAAO,oBAAC,WAAD;KAAW,WAAU;eAPX,aALJ,MAAM,cAAc,MAAM,QAAQ,MAAM,WAAW,EAAE,MAAM;MACtE;MACA,cAAc;MACd,GAAG,QAAQ;MACZ,CAAC,EACkC;MAClC,GAAG;MACH,YAAY,EACV,KAAK,KACN;MACF,CAAC;KAEuD,CAAA;;GAE5D;AAED,SAAO,oBAAC,SAAD;GAAS,GAAI;GAAY;GAAO,CAAA"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { ClientCodeBlockProvider } from "
|
|
2
|
+
import { ClientCodeBlockProvider } from "../components/codeblock.js";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
import { defaultShikiFactory } from "fumadocs-core/highlight/shiki/full";
|
|
5
|
-
//#region src/ui/full.
|
|
5
|
+
//#region src/ui/client/full.tsx
|
|
6
6
|
function FullProvider({ children }) {
|
|
7
7
|
return /* @__PURE__ */ jsx(ClientCodeBlockProvider, {
|
|
8
8
|
factory: defaultShikiFactory,
|
|
@@ -12,4 +12,4 @@ function FullProvider({ children }) {
|
|
|
12
12
|
//#endregion
|
|
13
13
|
export { FullProvider };
|
|
14
14
|
|
|
15
|
-
//# sourceMappingURL=full.
|
|
15
|
+
//# sourceMappingURL=full.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"full.js","names":[],"sources":["../../../src/ui/client/full.tsx"],"sourcesContent":["'use client';\nimport type { ReactNode } from 'react';\nimport { ClientCodeBlockProvider } from '../components/codeblock';\nimport { defaultShikiFactory } from 'fumadocs-core/highlight/shiki/full';\n\nexport function FullProvider({ children }: { children: ReactNode }) {\n return (\n <ClientCodeBlockProvider factory={defaultShikiFactory}>{children}</ClientCodeBlockProvider>\n );\n}\n"],"mappings":";;;;;AAKA,SAAgB,aAAa,EAAE,YAAqC;AAClE,QACE,oBAAC,yBAAD;EAAyB,SAAS;EAAsB;EAAmC,CAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MediaAdapter } from "../../requests/media/adapter.js";
|
|
2
2
|
import { CodeUsageGeneratorRegistry } from "../../requests/generators/index.js";
|
|
3
3
|
import { PlaygroundClientOptions } from "../../playground/client.js";
|
|
4
|
-
import { ExampleRequestItem } from "../operation/
|
|
4
|
+
import { ExampleRequestItem } from "../operation/get-example-requests.js";
|
|
5
5
|
import { FC } from "react";
|
|
6
6
|
|
|
7
7
|
//#region src/ui/client/index.d.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/ui/client/index.tsx"],"sourcesContent":["'use client';\nimport type { PlaygroundClientOptions } from '@/playground/client';\nimport type { MediaAdapter } from '@/requests/media/adapter';\nimport type { FC } from 'react';\nimport type {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/ui/client/index.tsx"],"sourcesContent":["'use client';\nimport type { PlaygroundClientOptions } from '@/playground/client';\nimport type { MediaAdapter } from '@/requests/media/adapter';\nimport type { FC } from 'react';\nimport type { CodeUsageGeneratorRegistry } from '@/requests/generators';\nimport type { ExampleRequestItem } from '../operation/get-example-requests';\n\nexport interface APIPageClientOptions {\n playground?: PlaygroundClientOptions;\n operation?: OperationClientOptions;\n\n /**\n * Set a prefix for `localStorage` keys.\n *\n * Useful when using multiple OpenAPI instances to prevent state conflicts.\n *\n * @defaultValue `fumadocs-openapi-`\n */\n storageKeyPrefix?: string;\n\n /**\n * Support other media types (for client-side serialization)\n */\n mediaAdapters?: Record<string, MediaAdapter>;\n\n /**\n * generate code usage examples\n */\n codeUsages?: CodeUsageGeneratorRegistry;\n}\n\nexport interface OperationClientOptions {\n APIExampleSelector?: FC<{\n items: ExampleRequestItem[];\n\n value: string | undefined;\n onValueChange: (id: string) => void;\n }>;\n}\n\nexport function defineClientConfig(options: APIPageClientOptions = {}): APIPageClientOptions {\n return options;\n}\n"],"mappings":";;AAwCA,SAAgB,mBAAmB,UAAgC,EAAE,EAAwB;AAC3F,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-key.js","names":[],"sources":["../../../src/ui/client/storage-key.ts"],"sourcesContent":["import type { AuthField } from '@/playground/client';\nimport { useApiContext } from '../contexts/api';\nimport { useMemo } from 'react';\n\ntype KeyName = 'server-url' | `auth-${string}`;\n\nexport function useStorageKey() {\n const { storageKeyPrefix } = useApiContext().client;\n\n return useMemo(\n () => ({\n of: (name: KeyName) => getStorageKey(storageKeyPrefix, name),\n AuthField: (field: AuthField) =>\n getStorageKey(storageKeyPrefix, `auth-${field.original?.id ?? field.fieldName}`),\n }),\n [storageKeyPrefix],\n );\n}\n\
|
|
1
|
+
{"version":3,"file":"storage-key.js","names":[],"sources":["../../../src/ui/client/storage-key.ts"],"sourcesContent":["import type { AuthField } from '@/playground/client';\nimport { useApiContext } from '../contexts/api';\nimport { useMemo } from 'react';\n\ntype KeyName = 'server-url' | `auth-${string}`;\n\nexport function useStorageKey() {\n const { storageKeyPrefix } = useApiContext().client;\n\n return useMemo(\n () => ({\n of: (name: KeyName) => getStorageKey(storageKeyPrefix, name),\n AuthField: (field: AuthField) =>\n getStorageKey(storageKeyPrefix, `auth-${field.original?.id ?? field.fieldName}`),\n }),\n [storageKeyPrefix],\n );\n}\n\nfunction getStorageKey(prefix = 'fumadocs-openapi-', name: KeyName) {\n return prefix + name;\n}\n"],"mappings":";;;AAMA,SAAgB,gBAAgB;CAC9B,MAAM,EAAE,qBAAqB,eAAe,CAAC;AAE7C,QAAO,eACE;EACL,KAAK,SAAkB,cAAc,kBAAkB,KAAK;EAC5D,YAAY,UACV,cAAc,kBAAkB,QAAQ,MAAM,UAAU,MAAM,MAAM,YAAY;EACnF,GACD,CAAC,iBAAiB,CACnB;;AAGH,SAAS,cAAc,SAAS,qBAAqB,MAAe;AAClE,QAAO,SAAS"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select.js";
|
|
4
|
+
import { createContext, use, useMemo, useState } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/ui/components/server-tab.tsx
|
|
7
|
+
const Context = createContext(null);
|
|
8
|
+
function SelectTabs({ defaultValue, children }) {
|
|
9
|
+
const [type, setType] = useState(defaultValue ?? null);
|
|
10
|
+
return /* @__PURE__ */ jsx(Context, {
|
|
11
|
+
value: useMemo(() => ({
|
|
12
|
+
type,
|
|
13
|
+
setType
|
|
14
|
+
}), [type]),
|
|
15
|
+
children
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function SelectTab({ value, ...props }) {
|
|
19
|
+
if (value !== use(Context)?.type) return;
|
|
20
|
+
return /* @__PURE__ */ jsx("div", {
|
|
21
|
+
...props,
|
|
22
|
+
children: props.children
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function SelectTabTrigger({ items, className, ...props }) {
|
|
26
|
+
const { type, setType } = use(Context);
|
|
27
|
+
return /* @__PURE__ */ jsxs(Select, {
|
|
28
|
+
value: type ?? "",
|
|
29
|
+
onValueChange: setType,
|
|
30
|
+
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
31
|
+
className: cn("not-prose w-fit min-w-0 *:min-w-0", className),
|
|
32
|
+
...props,
|
|
33
|
+
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
34
|
+
}), /* @__PURE__ */ jsx(SelectContent, { children: items.map(({ label, value }) => /* @__PURE__ */ jsx(SelectItem, {
|
|
35
|
+
value,
|
|
36
|
+
children: label
|
|
37
|
+
}, value)) })]
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { SelectTab, SelectTabTrigger, SelectTabs };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=server-tab.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-tab.js","names":[],"sources":["../../../src/ui/components/server-tab.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@/utils/cn';\nimport { SelectTrigger, Select, SelectValue, SelectContent, SelectItem } from './select';\nimport { type ReactNode, useState, useMemo, type ComponentProps, createContext, use } from 'react';\n\nconst Context = createContext<{\n type: string | null;\n setType: (type: string) => void;\n} | null>(null);\n\nexport function SelectTabs({\n defaultValue,\n children,\n}: {\n defaultValue?: string;\n children: ReactNode;\n}) {\n const [type, setType] = useState<string | null>(defaultValue ?? null);\n\n return <Context value={useMemo(() => ({ type, setType }), [type])}>{children}</Context>;\n}\n\nexport function SelectTab({\n value,\n ...props\n}: ComponentProps<'div'> & {\n value: string;\n}) {\n const ctx = use(Context);\n if (value !== ctx?.type) return;\n\n return <div {...props}>{props.children}</div>;\n}\n\nexport function SelectTabTrigger({\n items,\n className,\n ...props\n}: ComponentProps<typeof SelectTrigger> & {\n items: {\n label: ReactNode;\n value: string;\n }[];\n}) {\n const { type, setType } = use(Context)!;\n\n return (\n <Select value={type ?? ''} onValueChange={setType}>\n <SelectTrigger className={cn('not-prose w-fit min-w-0 *:min-w-0', className)} {...props}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {items.map(({ label, value }) => (\n <SelectItem key={value} value={value}>\n {label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n}\n"],"mappings":";;;;;;AAMA,MAAM,UAAU,cAGN,KAAK;AAEf,SAAgB,WAAW,EACzB,cACA,YAIC;CACD,MAAM,CAAC,MAAM,WAAW,SAAwB,gBAAgB,KAAK;AAErE,QAAO,oBAAC,SAAD;EAAS,OAAO,eAAe;GAAE;GAAM;GAAS,GAAG,CAAC,KAAK,CAAC;EAAG;EAAmB,CAAA;;AAGzF,SAAgB,UAAU,EACxB,OACA,GAAG,SAGF;AAED,KAAI,UADQ,IAAI,QAAQ,EACL,KAAM;AAEzB,QAAO,oBAAC,OAAD;EAAK,GAAI;YAAQ,MAAM;EAAe,CAAA;;AAG/C,SAAgB,iBAAiB,EAC/B,OACA,WACA,GAAG,SAMF;CACD,MAAM,EAAE,MAAM,YAAY,IAAI,QAAQ;AAEtC,QACE,qBAAC,QAAD;EAAQ,OAAO,QAAQ;EAAI,eAAe;YAA1C,CACE,oBAAC,eAAD;GAAe,WAAW,GAAG,qCAAqC,UAAU;GAAE,GAAI;aAChF,oBAAC,aAAD,EAAe,CAAA;GACD,CAAA,EAChB,oBAAC,eAAD,EAAA,UACG,MAAM,KAAK,EAAE,OAAO,YACnB,oBAAC,YAAD;GAA+B;aAC5B;GACU,EAFI,MAEJ,CACb,EACY,CAAA,CACT"}
|
package/dist/ui/contexts/api.js
CHANGED
|
@@ -3,22 +3,18 @@ import { defaultAdapters } from "../../requests/media/adapter.js";
|
|
|
3
3
|
import { useStorageKey } from "../client/storage-key.js";
|
|
4
4
|
import { createCodeUsageGeneratorRegistry } from "../../requests/generators/index.js";
|
|
5
5
|
import { registerDefault } from "../../requests/generators/all.js";
|
|
6
|
-
import { createContext, use, useEffect, useMemo,
|
|
6
|
+
import { createContext, use, useEffect, useMemo, useState } from "react";
|
|
7
7
|
import { jsx } from "react/jsx-runtime";
|
|
8
8
|
//#region src/ui/contexts/api.tsx
|
|
9
|
-
const ServerContext = createContext(null);
|
|
10
9
|
const ApiContext = createContext(null);
|
|
11
|
-
const
|
|
10
|
+
const ServerContext = createContext(null);
|
|
12
11
|
function useApiContext() {
|
|
13
12
|
const ctx = use(ApiContext);
|
|
14
13
|
if (!ctx) throw new Error("Component must be used under <ApiProvider />");
|
|
15
14
|
return ctx;
|
|
16
15
|
}
|
|
17
16
|
function useServerContext() {
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
function useServerSelectContext() {
|
|
21
|
-
const ctx = use(ServerSelectContext);
|
|
17
|
+
const ctx = use(ServerContext);
|
|
22
18
|
if (!ctx) throw new Error("Component must be used under <ApiProvider />");
|
|
23
19
|
return ctx;
|
|
24
20
|
}
|
|
@@ -44,41 +40,28 @@ function ApiProvider({ children, shikiOptions, client }) {
|
|
|
44
40
|
children
|
|
45
41
|
});
|
|
46
42
|
}
|
|
47
|
-
function ServerProvider({ servers,
|
|
48
|
-
const
|
|
49
|
-
return /* @__PURE__ */ jsx(ServerContext, {
|
|
50
|
-
value: useMemo(() => ({
|
|
51
|
-
servers,
|
|
52
|
-
serverRef
|
|
53
|
-
}), [servers]),
|
|
54
|
-
children: /* @__PURE__ */ jsx(ServerSelectProvider, {
|
|
55
|
-
defaultBaseUrl,
|
|
56
|
-
children
|
|
57
|
-
})
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
function ServerSelectProvider({ defaultBaseUrl, children }) {
|
|
61
|
-
const { servers, serverRef } = use(ServerContext);
|
|
62
|
-
const storageKeys = useStorageKey();
|
|
43
|
+
function ServerProvider({ servers, children }) {
|
|
44
|
+
const storageKey = useStorageKey().of("server-url");
|
|
63
45
|
const [server, setServer] = useState(() => {
|
|
64
|
-
|
|
65
|
-
|
|
46
|
+
if (!servers || servers.length === 0) return null;
|
|
47
|
+
const defaultItem = servers[0];
|
|
48
|
+
return {
|
|
66
49
|
name: defaultItem.name,
|
|
67
50
|
url: defaultItem.url,
|
|
68
51
|
variables: getDefaultValues(defaultItem)
|
|
69
|
-
}
|
|
52
|
+
};
|
|
70
53
|
});
|
|
71
|
-
serverRef.current = server;
|
|
72
54
|
useEffect(() => {
|
|
73
|
-
const cached = localStorage.getItem(
|
|
55
|
+
const cached = localStorage.getItem(storageKey);
|
|
74
56
|
if (!cached) return;
|
|
75
57
|
try {
|
|
76
58
|
const obj = JSON.parse(cached);
|
|
77
59
|
if (typeof obj === "object" && obj !== null && "url" in obj && typeof obj.url === "string" && "variables" in obj && typeof obj.variables === "object" && obj.variables !== null) setServer(obj);
|
|
78
60
|
} catch {}
|
|
79
|
-
}, [
|
|
80
|
-
return /* @__PURE__ */ jsx(
|
|
61
|
+
}, [storageKey]);
|
|
62
|
+
return /* @__PURE__ */ jsx(ServerContext, {
|
|
81
63
|
value: useMemo(() => ({
|
|
64
|
+
servers,
|
|
82
65
|
server,
|
|
83
66
|
setServerVariables(variables) {
|
|
84
67
|
setServer((prev) => {
|
|
@@ -87,25 +70,25 @@ function ServerSelectProvider({ defaultBaseUrl, children }) {
|
|
|
87
70
|
...prev,
|
|
88
71
|
variables
|
|
89
72
|
};
|
|
90
|
-
localStorage.setItem(
|
|
73
|
+
localStorage.setItem(storageKey, JSON.stringify(updated));
|
|
91
74
|
return updated;
|
|
92
75
|
});
|
|
93
76
|
},
|
|
94
77
|
setServer(value) {
|
|
95
|
-
const obj = servers
|
|
78
|
+
const obj = servers?.find((item) => item.url === value);
|
|
96
79
|
if (!obj) return;
|
|
97
80
|
const result = {
|
|
98
81
|
name: obj.name,
|
|
99
82
|
url: value,
|
|
100
83
|
variables: getDefaultValues(obj)
|
|
101
84
|
};
|
|
102
|
-
localStorage.setItem(
|
|
85
|
+
localStorage.setItem(storageKey, JSON.stringify(result));
|
|
103
86
|
setServer(result);
|
|
104
87
|
}
|
|
105
88
|
}), [
|
|
106
89
|
server,
|
|
107
90
|
servers,
|
|
108
|
-
|
|
91
|
+
storageKey
|
|
109
92
|
]),
|
|
110
93
|
children
|
|
111
94
|
});
|
|
@@ -117,6 +100,6 @@ function getDefaultValues(server) {
|
|
|
117
100
|
return out;
|
|
118
101
|
}
|
|
119
102
|
//#endregion
|
|
120
|
-
export { ApiProvider, ServerProvider, useApiContext, useServerContext
|
|
103
|
+
export { ApiProvider, ServerProvider, useApiContext, useServerContext };
|
|
121
104
|
|
|
122
105
|
//# sourceMappingURL=api.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","names":[],"sources":["../../../src/ui/contexts/api.tsx"],"sourcesContent":["'use client';\nimport {
|
|
1
|
+
{"version":3,"file":"api.js","names":[],"sources":["../../../src/ui/contexts/api.tsx"],"sourcesContent":["'use client';\nimport { createContext, type ReactNode, use, useEffect, useMemo, useState } from 'react';\nimport type { RenderContext, ServerObject } from '@/types';\nimport { defaultAdapters, type MediaAdapter } from '@/requests/media/adapter';\nimport { useStorageKey } from '../client/storage-key';\nimport type { APIPageClientOptions } from '../client';\nimport {\n type CodeUsageGeneratorRegistry,\n createCodeUsageGeneratorRegistry,\n} from '@/requests/generators';\nimport { registerDefault } from '@/requests/generators/all';\n\ninterface InheritFromContext extends Pick<RenderContext, 'shikiOptions'> {\n client: APIPageClientOptions;\n}\n\ninterface ServerContextType {\n servers?: ServerObject[];\n server: SelectedServer | null;\n setServer: (value: string) => void;\n setServerVariables: (value: Record<string, string>) => void;\n}\n\nexport type ApiProviderProps = InheritFromContext;\n\nexport interface SelectedServer {\n url: string;\n name?: string;\n variables: Record<string, string>;\n}\n\ninterface ApiContextType extends InheritFromContext {\n mediaAdapters: Record<string, MediaAdapter>;\n codeUsages: CodeUsageGeneratorRegistry;\n}\n\nconst ApiContext = createContext<ApiContextType | null>(null);\nconst ServerContext = createContext<ServerContextType | null>(null);\n\nexport function useApiContext(): ApiContextType {\n const ctx = use(ApiContext);\n if (!ctx) throw new Error('Component must be used under <ApiProvider />');\n\n return ctx;\n}\n\nexport function useServerContext() {\n const ctx = use(ServerContext);\n if (!ctx) throw new Error('Component must be used under <ApiProvider />');\n\n return ctx;\n}\n\nexport function ApiProvider({\n children,\n shikiOptions,\n client,\n}: ApiProviderProps & { children: ReactNode }) {\n return (\n <ApiContext\n value={useMemo(() => {\n let codeUsages: CodeUsageGeneratorRegistry;\n if (client.codeUsages) {\n codeUsages = createCodeUsageGeneratorRegistry(client.codeUsages);\n } else {\n codeUsages = createCodeUsageGeneratorRegistry();\n registerDefault(codeUsages);\n }\n\n return {\n shikiOptions,\n client,\n codeUsages,\n mediaAdapters: {\n ...defaultAdapters,\n ...client.mediaAdapters,\n },\n };\n }, [client, shikiOptions])}\n >\n {children}\n </ApiContext>\n );\n}\n\nexport function ServerProvider({\n servers,\n children,\n}: {\n servers?: ServerObject[];\n children: ReactNode;\n}) {\n const storageKey = useStorageKey().of('server-url');\n const [server, setServer] = useState<SelectedServer | null>(() => {\n if (!servers || servers.length === 0) return null;\n const defaultItem = servers[0];\n\n return {\n name: defaultItem.name,\n url: defaultItem.url!,\n variables: getDefaultValues(defaultItem),\n };\n });\n\n useEffect(() => {\n const cached = localStorage.getItem(storageKey);\n if (!cached) return;\n\n try {\n const obj: unknown = JSON.parse(cached);\n if (\n typeof obj === 'object' &&\n obj !== null &&\n 'url' in obj &&\n typeof obj.url === 'string' &&\n 'variables' in obj &&\n typeof obj.variables === 'object' &&\n obj.variables !== null\n ) {\n setServer(obj as SelectedServer);\n }\n } catch {\n // ignore\n }\n }, [storageKey]);\n\n return (\n <ServerContext\n value={useMemo(\n () => ({\n servers,\n server,\n setServerVariables(variables) {\n setServer((prev) => {\n if (!prev) return null;\n\n const updated = { ...prev, variables };\n localStorage.setItem(storageKey, JSON.stringify(updated));\n return updated;\n });\n },\n setServer(value) {\n const obj = servers?.find((item) => item.url === value);\n if (!obj) return;\n\n const result: SelectedServer = {\n name: obj.name,\n url: value,\n variables: getDefaultValues(obj),\n };\n\n localStorage.setItem(storageKey, JSON.stringify(result));\n setServer(result);\n },\n }),\n [server, servers, storageKey],\n )}\n >\n {children}\n </ServerContext>\n );\n}\n\nfunction getDefaultValues(server: ServerObject): Record<string, string> {\n const out: Record<string, string> = {};\n if (!server.variables) return out;\n\n for (const [k, v] of Object.entries(server.variables)) {\n if (v.default !== undefined) out[k] = String(v.default);\n }\n\n return out;\n}\n"],"mappings":";;;;;;;;AAoCA,MAAM,aAAa,cAAqC,KAAK;AAC7D,MAAM,gBAAgB,cAAwC,KAAK;AAEnE,SAAgB,gBAAgC;CAC9C,MAAM,MAAM,IAAI,WAAW;AAC3B,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,+CAA+C;AAEzE,QAAO;;AAGT,SAAgB,mBAAmB;CACjC,MAAM,MAAM,IAAI,cAAc;AAC9B,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,+CAA+C;AAEzE,QAAO;;AAGT,SAAgB,YAAY,EAC1B,UACA,cACA,UAC6C;AAC7C,QACE,oBAAC,YAAD;EACE,OAAO,cAAc;GACnB,IAAI;AACJ,OAAI,OAAO,WACT,cAAa,iCAAiC,OAAO,WAAW;QAC3D;AACL,iBAAa,kCAAkC;AAC/C,oBAAgB,WAAW;;AAG7B,UAAO;IACL;IACA;IACA;IACA,eAAe;KACb,GAAG;KACH,GAAG,OAAO;KACX;IACF;KACA,CAAC,QAAQ,aAAa,CAAC;EAEzB;EACU,CAAA;;AAIjB,SAAgB,eAAe,EAC7B,SACA,YAIC;CACD,MAAM,aAAa,eAAe,CAAC,GAAG,aAAa;CACnD,MAAM,CAAC,QAAQ,aAAa,eAAsC;AAChE,MAAI,CAAC,WAAW,QAAQ,WAAW,EAAG,QAAO;EAC7C,MAAM,cAAc,QAAQ;AAE5B,SAAO;GACL,MAAM,YAAY;GAClB,KAAK,YAAY;GACjB,WAAW,iBAAiB,YAAY;GACzC;GACD;AAEF,iBAAgB;EACd,MAAM,SAAS,aAAa,QAAQ,WAAW;AAC/C,MAAI,CAAC,OAAQ;AAEb,MAAI;GACF,MAAM,MAAe,KAAK,MAAM,OAAO;AACvC,OACE,OAAO,QAAQ,YACf,QAAQ,QACR,SAAS,OACT,OAAO,IAAI,QAAQ,YACnB,eAAe,OACf,OAAO,IAAI,cAAc,YACzB,IAAI,cAAc,KAElB,WAAU,IAAsB;UAE5B;IAGP,CAAC,WAAW,CAAC;AAEhB,QACE,oBAAC,eAAD;EACE,OAAO,eACE;GACL;GACA;GACA,mBAAmB,WAAW;AAC5B,eAAW,SAAS;AAClB,SAAI,CAAC,KAAM,QAAO;KAElB,MAAM,UAAU;MAAE,GAAG;MAAM;MAAW;AACtC,kBAAa,QAAQ,YAAY,KAAK,UAAU,QAAQ,CAAC;AACzD,YAAO;MACP;;GAEJ,UAAU,OAAO;IACf,MAAM,MAAM,SAAS,MAAM,SAAS,KAAK,QAAQ,MAAM;AACvD,QAAI,CAAC,IAAK;IAEV,MAAM,SAAyB;KAC7B,MAAM,IAAI;KACV,KAAK;KACL,WAAW,iBAAiB,IAAI;KACjC;AAED,iBAAa,QAAQ,YAAY,KAAK,UAAU,OAAO,CAAC;AACxD,cAAU,OAAO;;GAEpB,GACD;GAAC;GAAQ;GAAS;GAAW,CAC9B;EAEA;EACa,CAAA;;AAIpB,SAAS,iBAAiB,QAA8C;CACtE,MAAM,MAA8B,EAAE;AACtC,KAAI,CAAC,OAAO,UAAW,QAAO;AAE9B,MAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,OAAO,UAAU,CACnD,KAAI,EAAE,YAAY,KAAA,EAAW,KAAI,KAAK,OAAO,EAAE,QAAQ;AAGzD,QAAO"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ApiPageProps } from "./api-page.js";
|
|
2
|
+
import { CreateAPIPageOptions } from "./base.js";
|
|
3
|
+
import { Document } from "../types.js";
|
|
4
|
+
import { FC } from "react";
|
|
5
|
+
|
|
6
|
+
//#region src/ui/create-client.d.ts
|
|
7
|
+
interface ClientApiPageProps extends Omit<ApiPageProps, 'document'> {
|
|
8
|
+
payload: ClientApiPagePayload;
|
|
9
|
+
}
|
|
10
|
+
interface ClientApiPagePayload {
|
|
11
|
+
bundled: Document;
|
|
12
|
+
proxyUrl?: string;
|
|
13
|
+
}
|
|
14
|
+
type CreateClientAPIPageOptions = Omit<Partial<CreateAPIPageOptions>, 'generateTypeScriptSchema'>;
|
|
15
|
+
/**
|
|
16
|
+
* Create `<APIPage />` for non-RSC environment, note that this may be unstable, and doesn't support the full set of features.
|
|
17
|
+
*/
|
|
18
|
+
declare function createClientAPIPage({
|
|
19
|
+
shiki,
|
|
20
|
+
shikiOptions,
|
|
21
|
+
generateTypeScriptDefinitions,
|
|
22
|
+
...options
|
|
23
|
+
}?: CreateClientAPIPageOptions): FC<ClientApiPageProps>;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { ClientApiPagePayload, ClientApiPageProps, CreateClientAPIPageOptions, createClientAPIPage };
|
|
26
|
+
//# sourceMappingURL=create-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-client.d.ts","names":[],"sources":["../../src/ui/create-client.tsx"],"mappings":";;;;;;UA6BiB,kBAAA,SAA2B,IAAA,CAAK,YAAA;EAC/C,OAAA,EAAS,oBAAA;AAAA;AAAA,UAGM,oBAAA;EACf,OAAA,EAAS,QAAA;EACT,QAAA;AAAA;AAAA,KAGU,0BAAA,GAA6B,IAAA,CACvC,OAAA,CAAQ,oBAAA;;;;iBAOM,mBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,6BAAA;EAAA,GAcG;AAAA,IACF,0BAAA,GAAkC,EAAA,CAAG,kBAAA"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { defaultAdapters } from "../requests/media/adapter.js";
|
|
2
|
+
import { ClientCodeBlock, ClientCodeBlockProvider } from "./components/codeblock.js";
|
|
3
|
+
import { dereferenceSync } from "../utils/schema/dereference.js";
|
|
4
|
+
import { APIPage } from "./api-page.js";
|
|
5
|
+
import { slug } from "github-slugger";
|
|
6
|
+
import { Children, useMemo } from "react";
|
|
7
|
+
import * as JsxRuntime from "react/jsx-runtime";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
import { Heading } from "fumadocs-ui/components/heading";
|
|
10
|
+
import { remarkGfm } from "fumadocs-core/mdx-plugins/remark-gfm";
|
|
11
|
+
import defaultMdxComponents from "fumadocs-ui/mdx";
|
|
12
|
+
import { remark } from "remark";
|
|
13
|
+
import remarkRehype from "remark-rehype";
|
|
14
|
+
import { toJsxRuntime } from "hast-util-to-jsx-runtime";
|
|
15
|
+
import { compile } from "@fumari/json-schema-ts";
|
|
16
|
+
import { defaultShikiFactory } from "fumadocs-core/highlight/shiki/full";
|
|
17
|
+
//#region src/ui/create-client.tsx
|
|
18
|
+
/**
|
|
19
|
+
* Create `<APIPage />` for non-RSC environment, note that this may be unstable, and doesn't support the full set of features.
|
|
20
|
+
*/
|
|
21
|
+
function createClientAPIPage({ shiki = defaultShikiFactory, shikiOptions = { themes: {
|
|
22
|
+
light: "github-light",
|
|
23
|
+
dark: "github-dark"
|
|
24
|
+
} }, generateTypeScriptDefinitions = (schema, ctx) => {
|
|
25
|
+
if (typeof schema !== "object") return;
|
|
26
|
+
try {
|
|
27
|
+
return compile(schema, {
|
|
28
|
+
name: "Response",
|
|
29
|
+
readOnly: ctx.readOnly,
|
|
30
|
+
writeOnly: ctx.writeOnly,
|
|
31
|
+
getSchemaId: ctx.schema.getRawRef
|
|
32
|
+
});
|
|
33
|
+
} catch (e) {
|
|
34
|
+
console.warn("Failed to generate typescript schema:", e);
|
|
35
|
+
}
|
|
36
|
+
}, ...options } = {}) {
|
|
37
|
+
let processor;
|
|
38
|
+
const mdxComponents = {
|
|
39
|
+
...defaultMdxComponents,
|
|
40
|
+
img: void 0,
|
|
41
|
+
pre: MarkdownPre
|
|
42
|
+
};
|
|
43
|
+
function createMarkdownProcessor() {
|
|
44
|
+
function rehypeReact() {
|
|
45
|
+
this.compiler = (tree, file) => {
|
|
46
|
+
return toJsxRuntime(tree, {
|
|
47
|
+
development: false,
|
|
48
|
+
filePath: file.path,
|
|
49
|
+
...JsxRuntime,
|
|
50
|
+
components: mdxComponents
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return remark().use(remarkGfm).use(remarkRehype).use(rehypeReact);
|
|
55
|
+
}
|
|
56
|
+
return function ClientAPIPage({ payload, ...props }) {
|
|
57
|
+
const processed = useMemo(() => {
|
|
58
|
+
const dereferenceMap = /* @__PURE__ */ new Map();
|
|
59
|
+
return {
|
|
60
|
+
bundled: payload.bundled,
|
|
61
|
+
dereferenced: dereferenceSync(payload.bundled, (schema, ref) => {
|
|
62
|
+
dereferenceMap.set(schema, ref);
|
|
63
|
+
}),
|
|
64
|
+
getRawRef(obj) {
|
|
65
|
+
return dereferenceMap.get(obj);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}, [payload.bundled]);
|
|
69
|
+
const ctx = useMemo(() => ({
|
|
70
|
+
schema: processed,
|
|
71
|
+
proxyUrl: payload.proxyUrl,
|
|
72
|
+
shiki,
|
|
73
|
+
shikiOptions,
|
|
74
|
+
generateTypeScriptDefinitions,
|
|
75
|
+
...options,
|
|
76
|
+
mediaAdapters: {
|
|
77
|
+
...defaultAdapters,
|
|
78
|
+
...options.mediaAdapters
|
|
79
|
+
},
|
|
80
|
+
renderHeading(depth, text, props) {
|
|
81
|
+
const id = typeof text === "string" ? slug(text) : props?.id;
|
|
82
|
+
if (!id) throw new Error("missing 'id' for non-string children");
|
|
83
|
+
if (options.renderHeading) return options.renderHeading({
|
|
84
|
+
id,
|
|
85
|
+
children: text,
|
|
86
|
+
...props
|
|
87
|
+
}, depth);
|
|
88
|
+
return /* @__PURE__ */ jsx(Heading, {
|
|
89
|
+
id,
|
|
90
|
+
as: `h${depth}`,
|
|
91
|
+
...props,
|
|
92
|
+
children: text
|
|
93
|
+
}, id);
|
|
94
|
+
},
|
|
95
|
+
renderMarkdown(text) {
|
|
96
|
+
if (options.renderMarkdown) return options.renderMarkdown(text);
|
|
97
|
+
processor ??= createMarkdownProcessor();
|
|
98
|
+
return processor.processSync({ value: text }).result;
|
|
99
|
+
},
|
|
100
|
+
renderCodeBlock(lang, code) {
|
|
101
|
+
if (options.renderCodeBlock) return options.renderCodeBlock({
|
|
102
|
+
lang,
|
|
103
|
+
code
|
|
104
|
+
});
|
|
105
|
+
return /* @__PURE__ */ jsx(ClientCodeBlock, {
|
|
106
|
+
lang,
|
|
107
|
+
code
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}), [payload.proxyUrl, processed]);
|
|
111
|
+
return /* @__PURE__ */ jsx(ClientCodeBlockProvider, {
|
|
112
|
+
factory: shiki,
|
|
113
|
+
children: /* @__PURE__ */ jsx(APIPage, {
|
|
114
|
+
...props,
|
|
115
|
+
ctx
|
|
116
|
+
})
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function MarkdownPre(props) {
|
|
121
|
+
const codeProps = Children.only(props.children).props;
|
|
122
|
+
const content = codeProps.children;
|
|
123
|
+
if (typeof content !== "string") return null;
|
|
124
|
+
return /* @__PURE__ */ jsx(ClientCodeBlock, {
|
|
125
|
+
lang: codeProps.className?.split(" ").find((v) => v.startsWith("language-"))?.slice(9) ?? "text",
|
|
126
|
+
code: content.trimEnd()
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
export { createClientAPIPage };
|
|
131
|
+
|
|
132
|
+
//# sourceMappingURL=create-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-client.js","names":[],"sources":["../../src/ui/create-client.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any -- rehype-react without types */\nimport type { Document, RenderContext } from '@/types';\nimport type { NoReference } from '@/utils/schema';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport { defaultAdapters } from '@/requests/media/adapter';\nimport {\n Children,\n type ComponentProps,\n type ReactElement,\n useMemo,\n type FC,\n type ReactNode,\n} from 'react';\nimport { Heading } from 'fumadocs-ui/components/heading';\nimport { remarkGfm } from 'fumadocs-core/mdx-plugins/remark-gfm';\nimport defaultMdxComponents from 'fumadocs-ui/mdx';\nimport { remark } from 'remark';\nimport remarkRehype from 'remark-rehype';\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime';\nimport * as JsxRuntime from 'react/jsx-runtime';\nimport { APIPage, type ApiPageProps } from './api-page';\nimport type { CreateAPIPageOptions } from './base';\nimport { defaultShikiFactory } from 'fumadocs-core/highlight/shiki/full';\nimport { compile } from '@fumari/json-schema-ts';\nimport { ClientCodeBlock, ClientCodeBlockProvider } from './components/codeblock';\nimport { dereferenceSync } from '@/utils/schema/dereference';\nimport type { JSONSchema } from 'json-schema-typed/draft-2020-12';\nimport { slug } from 'github-slugger';\n\nexport interface ClientApiPageProps extends Omit<ApiPageProps, 'document'> {\n payload: ClientApiPagePayload;\n}\n\nexport interface ClientApiPagePayload {\n bundled: Document;\n proxyUrl?: string;\n}\n\nexport type CreateClientAPIPageOptions = Omit<\n Partial<CreateAPIPageOptions>,\n 'generateTypeScriptSchema'\n>;\n\n/**\n * Create `<APIPage />` for non-RSC environment, note that this may be unstable, and doesn't support the full set of features.\n */\nexport function createClientAPIPage({\n shiki = defaultShikiFactory,\n shikiOptions = { themes: { light: 'github-light', dark: 'github-dark' } },\n generateTypeScriptDefinitions = (schema, ctx) => {\n if (typeof schema !== 'object') return;\n\n try {\n return compile(schema, {\n name: 'Response',\n readOnly: ctx.readOnly,\n writeOnly: ctx.writeOnly,\n getSchemaId: ctx.schema.getRawRef,\n });\n } catch (e) {\n console.warn('Failed to generate typescript schema:', e);\n }\n },\n ...options\n}: CreateClientAPIPageOptions = {}): FC<ClientApiPageProps> {\n let processor: ReturnType<typeof createMarkdownProcessor>;\n const mdxComponents = {\n ...defaultMdxComponents,\n img: undefined,\n pre: MarkdownPre,\n };\n\n function createMarkdownProcessor() {\n function rehypeReact(this: any) {\n this.compiler = (tree: any, file: any) => {\n return toJsxRuntime(tree, {\n development: false,\n filePath: file.path,\n ...JsxRuntime,\n components: mdxComponents,\n });\n };\n }\n\n return remark().use(remarkGfm).use(remarkRehype).use(rehypeReact);\n }\n\n return function ClientAPIPage({ payload, ...props }) {\n const processed = useMemo<ProcessedDocument>(() => {\n const dereferenceMap = new Map<object, string>();\n\n return {\n bundled: payload.bundled,\n dereferenced: dereferenceSync(payload.bundled as JSONSchema, (schema, ref) => {\n dereferenceMap.set(schema as object, ref);\n }) as NoReference<Document>,\n getRawRef(obj) {\n return dereferenceMap.get(obj);\n },\n };\n }, [payload.bundled]);\n\n const ctx: RenderContext = useMemo(\n () => ({\n schema: processed,\n proxyUrl: payload.proxyUrl,\n shiki,\n shikiOptions,\n generateTypeScriptDefinitions,\n ...options,\n mediaAdapters: {\n ...defaultAdapters,\n ...options.mediaAdapters,\n },\n renderHeading(depth, text, props) {\n const id = typeof text === 'string' ? slug(text) : props?.id;\n if (!id) throw new Error(\"missing 'id' for non-string children\");\n\n if (options.renderHeading) {\n return options.renderHeading({ id, children: text, ...props }, depth);\n }\n\n return (\n <Heading id={id} key={id} as={`h${depth}` as `h1`} {...props}>\n {text}\n </Heading>\n );\n },\n renderMarkdown(text) {\n if (options.renderMarkdown) return options.renderMarkdown(text);\n processor ??= createMarkdownProcessor();\n\n return processor.processSync({\n value: text,\n }).result as ReactNode;\n },\n renderCodeBlock(lang, code) {\n if (options.renderCodeBlock) {\n return options.renderCodeBlock({ lang, code });\n }\n\n return <ClientCodeBlock lang={lang} code={code} />;\n },\n }),\n [payload.proxyUrl, processed],\n );\n\n return (\n <ClientCodeBlockProvider factory={shiki}>\n <APIPage {...props} ctx={ctx} />\n </ClientCodeBlockProvider>\n );\n };\n}\n\nfunction MarkdownPre(props: ComponentProps<'pre'>) {\n const code = Children.only(props.children) as ReactElement;\n const codeProps = code.props as ComponentProps<'code'>;\n const content = codeProps.children;\n if (typeof content !== 'string') return null;\n\n const lang =\n codeProps.className\n ?.split(' ')\n .find((v) => v.startsWith('language-'))\n ?.slice('language-'.length) ?? 'text';\n\n return <ClientCodeBlock lang={lang} code={content.trimEnd()} />;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA8CA,SAAgB,oBAAoB,EAClC,QAAQ,qBACR,eAAe,EAAE,QAAQ;CAAE,OAAO;CAAgB,MAAM;CAAe,EAAE,EACzE,iCAAiC,QAAQ,QAAQ;AAC/C,KAAI,OAAO,WAAW,SAAU;AAEhC,KAAI;AACF,SAAO,QAAQ,QAAQ;GACrB,MAAM;GACN,UAAU,IAAI;GACd,WAAW,IAAI;GACf,aAAa,IAAI,OAAO;GACzB,CAAC;UACK,GAAG;AACV,UAAQ,KAAK,yCAAyC,EAAE;;GAG5D,GAAG,YAC2B,EAAE,EAA0B;CAC1D,IAAI;CACJ,MAAM,gBAAgB;EACpB,GAAG;EACH,KAAK,KAAA;EACL,KAAK;EACN;CAED,SAAS,0BAA0B;EACjC,SAAS,cAAuB;AAC9B,QAAK,YAAY,MAAW,SAAc;AACxC,WAAO,aAAa,MAAM;KACxB,aAAa;KACb,UAAU,KAAK;KACf,GAAG;KACH,YAAY;KACb,CAAC;;;AAIN,SAAO,QAAQ,CAAC,IAAI,UAAU,CAAC,IAAI,aAAa,CAAC,IAAI,YAAY;;AAGnE,QAAO,SAAS,cAAc,EAAE,SAAS,GAAG,SAAS;EACnD,MAAM,YAAY,cAAiC;GACjD,MAAM,iCAAiB,IAAI,KAAqB;AAEhD,UAAO;IACL,SAAS,QAAQ;IACjB,cAAc,gBAAgB,QAAQ,UAAwB,QAAQ,QAAQ;AAC5E,oBAAe,IAAI,QAAkB,IAAI;MACzC;IACF,UAAU,KAAK;AACb,YAAO,eAAe,IAAI,IAAI;;IAEjC;KACA,CAAC,QAAQ,QAAQ,CAAC;EAErB,MAAM,MAAqB,eAClB;GACL,QAAQ;GACR,UAAU,QAAQ;GAClB;GACA;GACA;GACA,GAAG;GACH,eAAe;IACb,GAAG;IACH,GAAG,QAAQ;IACZ;GACD,cAAc,OAAO,MAAM,OAAO;IAChC,MAAM,KAAK,OAAO,SAAS,WAAW,KAAK,KAAK,GAAG,OAAO;AAC1D,QAAI,CAAC,GAAI,OAAM,IAAI,MAAM,uCAAuC;AAEhE,QAAI,QAAQ,cACV,QAAO,QAAQ,cAAc;KAAE;KAAI,UAAU;KAAM,GAAG;KAAO,EAAE,MAAM;AAGvE,WACE,oBAAC,SAAD;KAAa;KAAa,IAAI,IAAI;KAAiB,GAAI;eACpD;KACO,EAFY,GAEZ;;GAGd,eAAe,MAAM;AACnB,QAAI,QAAQ,eAAgB,QAAO,QAAQ,eAAe,KAAK;AAC/D,kBAAc,yBAAyB;AAEvC,WAAO,UAAU,YAAY,EAC3B,OAAO,MACR,CAAC,CAAC;;GAEL,gBAAgB,MAAM,MAAM;AAC1B,QAAI,QAAQ,gBACV,QAAO,QAAQ,gBAAgB;KAAE;KAAM;KAAM,CAAC;AAGhD,WAAO,oBAAC,iBAAD;KAAuB;KAAY;KAAQ,CAAA;;GAErD,GACD,CAAC,QAAQ,UAAU,UAAU,CAC9B;AAED,SACE,oBAAC,yBAAD;GAAyB,SAAS;aAChC,oBAAC,SAAD;IAAS,GAAI;IAAY;IAAO,CAAA;GACR,CAAA;;;AAKhC,SAAS,YAAY,OAA8B;CAEjD,MAAM,YADO,SAAS,KAAK,MAAM,SAAS,CACnB;CACvB,MAAM,UAAU,UAAU;AAC1B,KAAI,OAAO,YAAY,SAAU,QAAO;AAQxC,QAAO,oBAAC,iBAAD;EAAiB,MALtB,UAAU,WACN,MAAM,IAAI,CACX,MAAM,MAAM,EAAE,WAAW,YAAY,CAAC,EACrC,MAAM,EAAmB,IAAI;EAEC,MAAM,QAAQ,SAAS;EAAI,CAAA"}
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import { OpenAPIServer } from "../server/create.js";
|
|
1
2
|
import { ApiPageProps, OperationItem, WebhookItem } from "./api-page.js";
|
|
2
|
-
import { CreateAPIPageOptions,
|
|
3
|
-
|
|
3
|
+
import { CreateAPIPageOptions as CreateAPIPageOptions$1, ServerApiPageProps } from "./base.js";
|
|
4
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/ui/index.d.ts
|
|
7
|
+
type CreateAPIPageOptions = Partial<CreateAPIPageOptions$1>;
|
|
8
|
+
declare function createAPIPage(server: OpenAPIServer, options?: CreateAPIPageOptions): (props: ServerApiPageProps) => react_jsx_runtime0.JSX.Element;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { type ApiPageProps, CreateAPIPageOptions, type OperationItem, type WebhookItem, createAPIPage };
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/ui/index.tsx"],"mappings":";;;;;;KAKY,oBAAA,GAAuB,OAAA,CAAQ,sBAAA;AAAA,iBAE3B,aAAA,CAAc,MAAA,EAAQ,aAAA,EAAe,OAAA,GAAS,oBAAA,IAOhC,KAAA,EAAO,kBAAA,KAAuB,kBAAA,CAAA,GAAA,CAAA,OAAA"}
|
package/dist/ui/index.js
CHANGED
|
@@ -1,2 +1,22 @@
|
|
|
1
|
-
import { createAPIPage } from "./
|
|
1
|
+
import { createAPIPage as createAPIPage$1 } from "./base.js";
|
|
2
|
+
import { FullProvider } from "./client/full.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { defaultShikiFactory } from "fumadocs-core/highlight/shiki/full";
|
|
5
|
+
//#region src/ui/index.tsx
|
|
6
|
+
function createAPIPage(server, options = {}) {
|
|
7
|
+
const APIPage = createAPIPage$1(server, {
|
|
8
|
+
shiki: defaultShikiFactory,
|
|
9
|
+
shikiOptions: { themes: {
|
|
10
|
+
light: "github-light",
|
|
11
|
+
dark: "github-dark"
|
|
12
|
+
} },
|
|
13
|
+
...options
|
|
14
|
+
});
|
|
15
|
+
return function APIPageFull(props) {
|
|
16
|
+
return /* @__PURE__ */ jsx(FullProvider, { children: /* @__PURE__ */ jsx(APIPage, { ...props }) });
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
2
20
|
export { createAPIPage };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["base.createAPIPage"],"sources":["../../src/ui/index.tsx"],"sourcesContent":["import type { OpenAPIServer } from '@/server';\nimport * as base from './base';\nimport { defaultShikiFactory } from 'fumadocs-core/highlight/shiki/full';\nimport { FullProvider } from './client/full';\n\nexport type CreateAPIPageOptions = Partial<base.CreateAPIPageOptions>;\n\nexport function createAPIPage(server: OpenAPIServer, options: CreateAPIPageOptions = {}) {\n const APIPage = base.createAPIPage(server, {\n shiki: defaultShikiFactory,\n shikiOptions: { themes: { light: 'github-light', dark: 'github-dark' } },\n ...options,\n });\n\n return function APIPageFull(props: base.ServerApiPageProps) {\n return (\n <FullProvider>\n <APIPage {...props} />\n </FullProvider>\n );\n };\n}\n\nexport type { ApiPageProps, OperationItem, WebhookItem } from './api-page';\n"],"mappings":";;;;;AAOA,SAAgB,cAAc,QAAuB,UAAgC,EAAE,EAAE;CACvF,MAAM,UAAUA,gBAAmB,QAAQ;EACzC,OAAO;EACP,cAAc,EAAE,QAAQ;GAAE,OAAO;GAAgB,MAAM;GAAe,EAAE;EACxE,GAAG;EACJ,CAAC;AAEF,QAAO,SAAS,YAAY,OAAgC;AAC1D,SACE,oBAAC,cAAD,EAAA,UACE,oBAAC,SAAD,EAAS,GAAI,OAAS,CAAA,EACT,CAAA"}
|