fumadocs-openapi 9.7.3 → 10.0.1
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/dist/generate-file.d.ts +3 -4
- package/dist/generate-file.d.ts.map +1 -1
- package/dist/generate-file.js +4 -34
- package/dist/playground/client.d.ts +43 -22
- package/dist/playground/client.d.ts.map +1 -1
- package/dist/playground/client.js +68 -63
- package/dist/playground/{inputs.d.ts → components/inputs.d.ts} +1 -1
- package/dist/playground/components/inputs.d.ts.map +1 -0
- package/dist/playground/{inputs.js → components/inputs.js} +7 -7
- package/dist/playground/components/oauth-dialog.d.ts.map +1 -0
- package/dist/playground/components/server-select.d.ts.map +1 -0
- package/dist/{ui → playground/components}/server-select.js +6 -7
- package/dist/playground/index.d.ts +1 -4
- package/dist/playground/index.d.ts.map +1 -1
- package/dist/playground/index.js +5 -3
- package/dist/playground/lazy.d.ts +2 -0
- package/dist/playground/lazy.d.ts.map +1 -0
- package/dist/playground/lazy.js +3 -0
- package/dist/requests/generators/index.d.ts +2 -2
- package/dist/requests/generators/index.d.ts.map +1 -1
- package/dist/requests/generators/index.js +6 -0
- package/dist/requests/media/adapter.d.ts +0 -6
- package/dist/requests/media/adapter.d.ts.map +1 -1
- package/dist/scalar/client.d.ts +1 -0
- package/dist/scalar/client.d.ts.map +1 -1
- package/dist/scalar/client.js +2 -3
- package/dist/scalar/index.d.ts +7 -6
- package/dist/scalar/index.d.ts.map +1 -1
- package/dist/scalar/index.js +17 -1
- package/dist/server/create.d.ts +11 -59
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/create.js +5 -14
- package/dist/server/source-api.d.ts +1 -1
- package/dist/server/source-api.d.ts.map +1 -1
- package/dist/server/source-api.js +1 -1
- package/dist/types.d.ts +12 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/api-page.d.ts +145 -0
- package/dist/ui/api-page.d.ts.map +1 -0
- package/dist/ui/api-page.js +120 -0
- package/dist/ui/client/index.d.ts +29 -0
- package/dist/ui/client/index.d.ts.map +1 -0
- package/dist/ui/client/index.js +4 -0
- package/dist/ui/client/storage-key.d.ts +9 -0
- package/dist/ui/client/storage-key.d.ts.map +1 -0
- package/dist/ui/client/storage-key.js +12 -0
- package/dist/ui/components/method-label.d.ts +1 -1
- package/dist/ui/contexts/api.d.ts +12 -10
- package/dist/ui/contexts/api.d.ts.map +1 -1
- package/dist/ui/contexts/api.js +53 -37
- package/dist/ui/contexts/api.lazy.d.ts +2 -0
- package/dist/ui/contexts/api.lazy.d.ts.map +1 -0
- package/dist/ui/contexts/api.lazy.js +3 -0
- package/dist/ui/contexts/operation.d.ts +20 -0
- package/dist/ui/contexts/operation.d.ts.map +1 -0
- package/dist/ui/contexts/operation.js +48 -0
- package/dist/ui/contexts/operation.lazy.d.ts +2 -0
- package/dist/ui/contexts/operation.lazy.d.ts.map +1 -0
- package/dist/ui/contexts/operation.lazy.js +3 -0
- package/dist/ui/index.d.ts +1 -8
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +1 -26
- package/dist/ui/{select-tabs.d.ts → operation/client.d.ts} +5 -2
- package/dist/ui/operation/client.d.ts.map +1 -0
- package/dist/ui/{client.js → operation/client.js} +18 -1
- package/dist/ui/operation/example-panel/client.d.ts +4 -0
- package/dist/ui/operation/example-panel/client.d.ts.map +1 -0
- package/dist/ui/operation/example-panel/client.js +50 -0
- package/dist/ui/operation/example-panel/index.d.ts +58 -0
- package/dist/ui/operation/example-panel/index.d.ts.map +1 -0
- package/dist/ui/operation/example-panel/index.js +140 -0
- package/dist/ui/operation/example-panel/lazy.d.ts +3 -0
- package/dist/ui/operation/example-panel/lazy.d.ts.map +1 -0
- package/dist/ui/operation/example-panel/lazy.js +4 -0
- package/dist/ui/operation/get-request-data.d.ts.map +1 -0
- package/dist/ui/operation/index.d.ts +11 -0
- package/dist/ui/operation/index.d.ts.map +1 -0
- package/dist/{render → ui}/operation/index.js +50 -24
- package/dist/ui/schema/client.d.ts +11 -0
- package/dist/ui/schema/client.d.ts.map +1 -0
- package/dist/{render → ui}/schema/client.js +22 -12
- package/dist/{render/schema/server.d.ts → ui/schema/index.d.ts} +5 -4
- package/dist/ui/schema/index.d.ts.map +1 -0
- package/dist/{render/schema/server.js → ui/schema/index.js} +11 -5
- package/dist/ui/schema/lazy.d.ts +2 -0
- package/dist/ui/schema/lazy.d.ts.map +1 -0
- package/dist/ui/schema/lazy.js +3 -0
- package/dist/utils/get-typescript-schema.d.ts +3 -2
- package/dist/utils/get-typescript-schema.d.ts.map +1 -1
- package/dist/utils/get-typescript-schema.js +12 -7
- package/dist/utils/lazy.d.ts +5 -0
- package/dist/utils/lazy.d.ts.map +1 -0
- package/dist/utils/lazy.js +12 -0
- package/dist/utils/pages/builder.d.ts +1 -1
- package/dist/utils/pages/builder.d.ts.map +1 -1
- package/dist/utils/pages/to-body.d.ts +2 -3
- package/dist/utils/pages/to-body.d.ts.map +1 -1
- package/dist/utils/pages/to-body.js +7 -7
- package/dist/utils/pages/to-text.d.ts.map +1 -1
- package/dist/utils/process-document.d.ts +1 -0
- package/dist/utils/process-document.d.ts.map +1 -1
- package/dist/utils/process-document.js +7 -2
- package/package.json +20 -16
- package/dist/playground/auth/oauth-dialog.d.ts.map +0 -1
- package/dist/playground/inputs.d.ts.map +0 -1
- package/dist/render/api-page.d.ts +0 -33
- package/dist/render/api-page.d.ts.map +0 -1
- package/dist/render/api-page.js +0 -59
- package/dist/render/codeblock.d.ts +0 -9
- package/dist/render/codeblock.d.ts.map +0 -1
- package/dist/render/codeblock.js +0 -14
- package/dist/render/heading.d.ts +0 -4
- package/dist/render/heading.d.ts.map +0 -1
- package/dist/render/heading.js +0 -6
- package/dist/render/markdown.d.ts +0 -5
- package/dist/render/markdown.d.ts.map +0 -1
- package/dist/render/markdown.js +0 -31
- package/dist/render/operation/api-example.d.ts +0 -30
- package/dist/render/operation/api-example.d.ts.map +0 -1
- package/dist/render/operation/api-example.js +0 -103
- package/dist/render/operation/get-request-data.d.ts.map +0 -1
- package/dist/render/operation/index.d.ts +0 -27
- package/dist/render/operation/index.d.ts.map +0 -1
- package/dist/render/renderer.d.ts +0 -79
- package/dist/render/renderer.d.ts.map +0 -1
- package/dist/render/renderer.js +0 -25
- package/dist/render/schema/client.d.ts +0 -18
- package/dist/render/schema/client.d.ts.map +0 -1
- package/dist/render/schema/index.d.ts +0 -7
- package/dist/render/schema/index.d.ts.map +0 -1
- package/dist/render/schema/index.js +0 -11
- package/dist/render/schema/server.d.ts.map +0 -1
- package/dist/render/schema/ui.d.ts +0 -16
- package/dist/render/schema/ui.d.ts.map +0 -1
- package/dist/render/schema/ui.js +0 -14
- package/dist/ui/client.d.ts +0 -4
- package/dist/ui/client.d.ts.map +0 -1
- package/dist/ui/contexts/code-example.d.ts +0 -24
- package/dist/ui/contexts/code-example.d.ts.map +0 -1
- package/dist/ui/contexts/code-example.js +0 -97
- package/dist/ui/lazy.d.ts +0 -16
- package/dist/ui/lazy.d.ts.map +0 -1
- package/dist/ui/lazy.js +0 -22
- package/dist/ui/select-tabs.d.ts.map +0 -1
- package/dist/ui/select-tabs.js +0 -20
- package/dist/ui/server-select.d.ts.map +0 -1
- /package/dist/playground/{auth → components}/oauth-dialog.d.ts +0 -0
- /package/dist/playground/{auth → components}/oauth-dialog.js +0 -0
- /package/dist/{ui → playground/components}/server-select.d.ts +0 -0
- /package/dist/{render → ui}/operation/get-request-data.d.ts +0 -0
- /package/dist/{render → ui}/operation/get-request-data.js +0 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { getPreferredType } from '../../../utils/schema.js';
|
|
3
|
+
import { getRequestData } from '../../../ui/operation/get-request-data.js';
|
|
4
|
+
import { sample } from 'openapi-sampler';
|
|
5
|
+
import { defaultSamples } from '../../../requests/generators/index.js';
|
|
6
|
+
import { encodeRequestData } from '../../../requests/media/encode.js';
|
|
7
|
+
import { AccordionContent, AccordionHeader, AccordionItem, Accordions, AccordionTrigger, } from '../../../ui/components/accordion.js';
|
|
8
|
+
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
|
9
|
+
import { CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, } from 'fumadocs-ui/components/codeblock';
|
|
10
|
+
import { APIExampleSelectorLazy, APIExampleUsageTabLazy } from './lazy.js';
|
|
11
|
+
export function getAPIExamples(path, method, ctx) {
|
|
12
|
+
const media = method.requestBody
|
|
13
|
+
? getPreferredType(method.requestBody.content)
|
|
14
|
+
: null;
|
|
15
|
+
const bodyOfType = media ? method.requestBody?.content[media] : null;
|
|
16
|
+
if (bodyOfType?.examples) {
|
|
17
|
+
const result = [];
|
|
18
|
+
for (const [key, value] of Object.entries(bodyOfType.examples)) {
|
|
19
|
+
const data = getRequestData(path, method, key, ctx);
|
|
20
|
+
result.push({
|
|
21
|
+
id: key,
|
|
22
|
+
name: value.summary ?? key,
|
|
23
|
+
description: value.description,
|
|
24
|
+
data,
|
|
25
|
+
encoded: encodeRequestData(data, ctx.mediaAdapters, method.parameters ?? []),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
if (result.length > 0)
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
const data = getRequestData(path, method, null, ctx);
|
|
32
|
+
return [
|
|
33
|
+
{
|
|
34
|
+
id: '_default',
|
|
35
|
+
name: 'Default',
|
|
36
|
+
description: bodyOfType?.schema?.description,
|
|
37
|
+
data,
|
|
38
|
+
encoded: encodeRequestData(data, ctx.mediaAdapters, method.parameters ?? []),
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
export async function APIExample({ method, ctx, }) {
|
|
43
|
+
let { renderAPIExampleUsageTabs, renderAPIExampleLayout } = ctx.content ?? {};
|
|
44
|
+
renderAPIExampleLayout ?? (renderAPIExampleLayout = (slots) => {
|
|
45
|
+
return (_jsxs("div", { className: "prose-no-margin md:sticky md:top-(--fd-api-info-top) xl:w-[400px]", children: [slots.selector, slots.usageTabs, slots.responseTabs] }));
|
|
46
|
+
});
|
|
47
|
+
renderAPIExampleUsageTabs ?? (renderAPIExampleUsageTabs = (generators) => {
|
|
48
|
+
if (generators.length === 0)
|
|
49
|
+
return null;
|
|
50
|
+
return (_jsxs(CodeBlockTabs, { groupId: "fumadocs_openapi_requests", defaultValue: generators[0].id, children: [_jsx(CodeBlockTabsList, { children: generators.map((item) => (_jsx(CodeBlockTabsTrigger, { value: item.id, children: item.label ?? item.lang }, item.id))) }), generators.map((item) => (_jsx(CodeBlockTab, { value: item.id, children: _jsx(APIExampleUsageTabLazy, { ...item }) }, item.id)))] }));
|
|
51
|
+
});
|
|
52
|
+
let generators = [...defaultSamples];
|
|
53
|
+
if (ctx.generateCodeSamples) {
|
|
54
|
+
generators.push(...(await ctx.generateCodeSamples(method)));
|
|
55
|
+
}
|
|
56
|
+
if (method['x-codeSamples']) {
|
|
57
|
+
for (const sample of method['x-codeSamples']) {
|
|
58
|
+
generators.push('id' in sample && typeof sample.id === 'string'
|
|
59
|
+
? sample
|
|
60
|
+
: {
|
|
61
|
+
id: sample.lang,
|
|
62
|
+
...sample,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
generators = dedupe(generators);
|
|
67
|
+
return renderAPIExampleLayout({
|
|
68
|
+
selector: method['x-exclusiveCodeSample'] ? null : (_jsx(APIExampleSelectorLazy, {})),
|
|
69
|
+
usageTabs: await renderAPIExampleUsageTabs(generators, ctx),
|
|
70
|
+
responseTabs: _jsx(ResponseTabs, { operation: method, ctx: ctx }),
|
|
71
|
+
}, ctx);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Remove duplicated ids
|
|
75
|
+
*/
|
|
76
|
+
function dedupe(samples) {
|
|
77
|
+
const set = new Set();
|
|
78
|
+
const out = [];
|
|
79
|
+
for (let i = samples.length - 1; i >= 0; i--) {
|
|
80
|
+
const item = samples[i];
|
|
81
|
+
if (set.has(item.id))
|
|
82
|
+
continue;
|
|
83
|
+
set.add(item.id);
|
|
84
|
+
if (item.source !== false)
|
|
85
|
+
out.unshift(item);
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
function ResponseTabs({ operation, ctx, }) {
|
|
90
|
+
if (!operation.responses)
|
|
91
|
+
return null;
|
|
92
|
+
const tabs = [];
|
|
93
|
+
for (const [code, response] of Object.entries(operation.responses)) {
|
|
94
|
+
const media = response.content ? getPreferredType(response.content) : null;
|
|
95
|
+
const responseOfType = media ? response.content?.[media] : null;
|
|
96
|
+
const tab = {
|
|
97
|
+
code,
|
|
98
|
+
response,
|
|
99
|
+
mediaType: media,
|
|
100
|
+
};
|
|
101
|
+
if (responseOfType?.examples) {
|
|
102
|
+
tab.examples ?? (tab.examples = []);
|
|
103
|
+
for (const [key, sample] of Object.entries(responseOfType.examples)) {
|
|
104
|
+
const title = sample?.summary ?? `Example ${key}`;
|
|
105
|
+
tab.examples.push({
|
|
106
|
+
label: title,
|
|
107
|
+
sample: sample.value,
|
|
108
|
+
description: sample?.description,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else if (responseOfType?.example || responseOfType?.schema) {
|
|
113
|
+
tab.examples ?? (tab.examples = []);
|
|
114
|
+
tab.examples.push({
|
|
115
|
+
label: 'Example',
|
|
116
|
+
sample: responseOfType.example ?? sample(responseOfType.schema),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
tabs.push(tab);
|
|
120
|
+
}
|
|
121
|
+
const { renderResponseTabs = renderResponseTabsDefault } = ctx.content ?? {};
|
|
122
|
+
return renderResponseTabs(tabs, ctx);
|
|
123
|
+
}
|
|
124
|
+
function renderResponseTabsDefault(tabs, ctx) {
|
|
125
|
+
async function renderResponse(tab) {
|
|
126
|
+
const { examples = [] } = tab;
|
|
127
|
+
let slot = 'Empty';
|
|
128
|
+
if (examples.length > 1) {
|
|
129
|
+
slot = (_jsx(Accordions, { type: "single", className: "pt-2", defaultValue: examples[0].label, children: examples.map((example, i) => (_jsxs(AccordionItem, { value: example.label, children: [_jsx(AccordionHeader, { children: _jsx(AccordionTrigger, { children: example.label }) }), _jsxs(AccordionContent, { className: "prose-no-margin", children: [example.description && ctx.renderMarkdown(example.description), ctx.renderCodeBlock('json', JSON.stringify(example.sample, null, 2))] })] }, i))) }));
|
|
130
|
+
}
|
|
131
|
+
else if (examples.length === 1) {
|
|
132
|
+
const example = examples[0];
|
|
133
|
+
slot = (_jsxs(_Fragment, { children: [example.description && ctx.renderMarkdown(example.description), ctx.renderCodeBlock('json', JSON.stringify(example.sample, null, 2))] }));
|
|
134
|
+
}
|
|
135
|
+
return _jsx(Tab, { value: tab.code, children: slot });
|
|
136
|
+
}
|
|
137
|
+
if (tabs.length === 0)
|
|
138
|
+
return null;
|
|
139
|
+
return (_jsx(Tabs, { groupId: "fumadocs_openapi_responses", items: tabs.map((tab) => tab.code), children: tabs.map(renderResponse) }));
|
|
140
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../../../../src/ui/operation/example-panel/lazy.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,8CAElC,CAAC;AAEF,eAAO,MAAM,sBAAsB,8CAElC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { wrapLazy } from '../../../utils/lazy.js';
|
|
3
|
+
export const APIExampleSelectorLazy = wrapLazy(() => import('./client.js').then((mod) => ({ default: mod.APIExampleSelector })));
|
|
4
|
+
export const APIExampleUsageTabLazy = wrapLazy(() => import('./client.js').then((mod) => ({ default: mod.APIExampleUsageTab })));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-request-data.d.ts","sourceRoot":"","sources":["../../../src/ui/operation/get-request-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAIhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,iBAAiB,EACzB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,IAAI,EAAE,aAAa,GAClB,cAAc,CAwEhB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { MethodInformation, RenderContext } from '../../types.js';
|
|
3
|
+
export declare function Operation({ type, path, method, ctx, hasHead, headingLevel, }: {
|
|
4
|
+
type?: 'webhook' | 'operation';
|
|
5
|
+
path: string;
|
|
6
|
+
method: MethodInformation;
|
|
7
|
+
ctx: RenderContext;
|
|
8
|
+
hasHead?: boolean;
|
|
9
|
+
headingLevel?: number;
|
|
10
|
+
}): Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined>;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/operation/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACtE,OAAO,KAAK,EAEV,iBAAiB,EACjB,aAAa,EAEd,MAAM,SAAS,CAAC;AAqCjB,wBAAsB,SAAS,CAAC,EAC9B,IAAkB,EAClB,IAAI,EACJ,MAAM,EACN,GAAG,EACH,OAAO,EACP,YAAgB,GACjB,EAAE;IACD,IAAI,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,GAAG,EAAE,aAAa,CAAC;IAEnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,kIAgQA"}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Fragment } from 'react';
|
|
3
3
|
import { createMethod, methodKeys, } from '../../utils/schema.js';
|
|
4
4
|
import { idToTitle } from '../../utils/id-to-title.js';
|
|
5
|
-
import { Markdown } from '../markdown.js';
|
|
6
|
-
import { heading } from '../heading.js';
|
|
7
5
|
import { Schema } from '../schema/index.js';
|
|
8
|
-
import { APIExample,
|
|
6
|
+
import { APIExample, getAPIExamples } from '../../ui/operation/example-panel/index.js';
|
|
9
7
|
import { MethodLabel } from '../../ui/components/method-label.js';
|
|
10
8
|
import { getTypescriptSchema } from '../../utils/get-typescript-schema.js';
|
|
11
|
-
import { CopyResponseTypeScript } from '
|
|
12
|
-
import { SelectTab, SelectTabs, SelectTabTrigger } from '../../ui/select-tabs.js';
|
|
9
|
+
import { CopyResponseTypeScript, SelectTab, SelectTabs, SelectTabTrigger, } from './client.js';
|
|
13
10
|
import { AccordionContent, AccordionHeader, AccordionItem, Accordions, AccordionTrigger, } from '../../ui/components/accordion.js';
|
|
14
11
|
import { isMediaTypeSupported } from '../../requests/media/adapter.js';
|
|
12
|
+
import { cn } from 'fumadocs-ui/utils/cn';
|
|
13
|
+
import { APIPlayground } from '../../playground/index.js';
|
|
14
|
+
import { OperationProviderLazy } from '../contexts/operation.lazy.js';
|
|
15
15
|
const ParamTypes = {
|
|
16
16
|
path: 'Path Parameters',
|
|
17
17
|
query: 'Query Parameters',
|
|
18
18
|
header: 'Header Parameters',
|
|
19
19
|
cookie: 'Cookie Parameters',
|
|
20
20
|
};
|
|
21
|
-
export function Operation({ type = 'operation', path, method, ctx, hasHead, headingLevel = 2, }) {
|
|
21
|
+
export async function Operation({ type = 'operation', path, method, ctx, hasHead, headingLevel = 2, }) {
|
|
22
22
|
const { schema: { dereferenced }, } = ctx;
|
|
23
23
|
const body = method.requestBody;
|
|
24
24
|
let headNode = null;
|
|
@@ -29,12 +29,12 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
|
|
|
29
29
|
if (hasHead) {
|
|
30
30
|
const title = method.summary ??
|
|
31
31
|
(method.operationId ? idToTitle(method.operationId) : path);
|
|
32
|
-
headNode = (_jsxs(_Fragment, { children: [
|
|
32
|
+
headNode = (_jsxs(_Fragment, { children: [ctx.renderHeading(headingLevel, title), method.description && ctx.renderMarkdown(method.description)] }));
|
|
33
33
|
headingLevel++;
|
|
34
34
|
}
|
|
35
35
|
const contentTypes = body ? Object.entries(body.content) : null;
|
|
36
36
|
if (body && contentTypes && contentTypes.length > 0) {
|
|
37
|
-
bodyNode = (_jsxs(SelectTabs, { defaultValue: contentTypes[0][0], children: [_jsxs("div", { className: "flex gap-2 items-end justify-between", children: [
|
|
37
|
+
bodyNode = (_jsxs(SelectTabs, { defaultValue: contentTypes[0][0], children: [_jsxs("div", { className: "flex gap-2 items-end justify-between", children: [ctx.renderHeading(headingLevel, 'Request Body'), _jsx(SelectTabTrigger, { items: contentTypes.map((v) => v[0]), className: "mb-4" })] }), body.description && ctx.renderMarkdown(body.description), contentTypes.map(([type, content]) => {
|
|
38
38
|
if (!isMediaTypeSupported(type, ctx.mediaAdapters)) {
|
|
39
39
|
throw new Error(`Media type ${type} is not supported (in ${path})`);
|
|
40
40
|
}
|
|
@@ -43,13 +43,13 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
|
|
|
43
43
|
}
|
|
44
44
|
if (method.responses && ctx.showResponseSchema !== false) {
|
|
45
45
|
const statuses = Object.keys(method.responses);
|
|
46
|
-
responseNode = (_jsxs(_Fragment, { children: [
|
|
46
|
+
responseNode = (_jsxs(_Fragment, { children: [ctx.renderHeading(headingLevel, 'Response Body'), _jsx(Accordions, { type: "multiple", children: statuses.map((status) => (_jsx(AccordionItem, { value: status, children: _jsx(ResponseAccordion, { status: status, operation: method, ctx: ctx }) }, status))) })] }));
|
|
47
47
|
}
|
|
48
48
|
const parameterNode = Object.entries(ParamTypes).map(([type, title]) => {
|
|
49
49
|
const params = method.parameters?.filter((param) => param.in === type);
|
|
50
50
|
if (!params || params.length === 0)
|
|
51
51
|
return;
|
|
52
|
-
return (_jsxs(Fragment, { children: [
|
|
52
|
+
return (_jsxs(Fragment, { children: [ctx.renderHeading(headingLevel, title), _jsx("div", { className: "flex flex-col", children: params.map((param) => (_jsx(Schema, { name: param.name, root: {
|
|
53
53
|
...param.schema,
|
|
54
54
|
description: param.description ?? param.schema?.description,
|
|
55
55
|
deprecated: (param.deprecated ?? false) ||
|
|
@@ -60,7 +60,7 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
|
|
|
60
60
|
if (type === 'operation' && securities.length > 0) {
|
|
61
61
|
const securitySchemes = dereferenced.components?.securitySchemes;
|
|
62
62
|
const names = securities.map((security) => Object.keys(security).join(' & '));
|
|
63
|
-
authNode = (_jsxs(SelectTabs, { defaultValue: names[0], children: [_jsxs("div", { className: "flex items-end justify-between gap-2", children: [
|
|
63
|
+
authNode = (_jsxs(SelectTabs, { defaultValue: names[0], children: [_jsxs("div", { className: "flex items-end justify-between gap-2", children: [ctx.renderHeading(headingLevel, 'Authorization'), _jsx(SelectTabTrigger, { items: names, className: "mb-4" })] }), securities.map((security, i) => (_jsx(SelectTab, { value: names[i], children: Object.entries(security).map(([key, scopes]) => {
|
|
64
64
|
const scheme = securitySchemes?.[key];
|
|
65
65
|
if (!scheme)
|
|
66
66
|
return;
|
|
@@ -69,29 +69,52 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
|
|
|
69
69
|
}
|
|
70
70
|
if (method.callbacks) {
|
|
71
71
|
const callbacks = Object.entries(method.callbacks);
|
|
72
|
-
callbacksNode = (_jsxs(SelectTabs, { defaultValue: callbacks[0][0], children: [_jsxs("div", { className: "flex justify-between gap-2 items-end", children: [
|
|
72
|
+
callbacksNode = (_jsxs(SelectTabs, { defaultValue: callbacks[0][0], children: [_jsxs("div", { className: "flex justify-between gap-2 items-end", children: [ctx.renderHeading(headingLevel, 'Callbacks'), _jsx(SelectTabTrigger, { items: callbacks.map((v) => v[0]), className: "mb-4" })] }), callbacks.map(([name, callback]) => (_jsx(SelectTab, { value: name, children: _jsx(WebhookCallback, { callback: callback, ctx: ctx, headingLevel: headingLevel }) }, name)))] }));
|
|
73
73
|
}
|
|
74
|
-
|
|
74
|
+
let { renderOperationLayout, renderWebhookLayout } = ctx.content ?? {};
|
|
75
75
|
if (type === 'operation') {
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
renderOperationLayout ?? (renderOperationLayout = (slots) => {
|
|
77
|
+
return (_jsxs("div", { className: "flex flex-col gap-x-6 gap-y-4 xl:flex-row xl:items-start", style: {
|
|
78
|
+
'--fd-api-info-top': 'calc(12px + var(--fd-nav-height) + var(--fd-banner-height) + var(--fd-tocnav-height, 0px))',
|
|
79
|
+
}, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [slots.header, slots.apiPlayground, slots.authSchemes, slots.paremeters, slots.body, slots.responses, slots.callbacks] }), slots.apiExample] }));
|
|
80
|
+
});
|
|
81
|
+
const playgroundEnabled = ctx.playground?.enabled ?? true;
|
|
82
|
+
const content = await renderOperationLayout({
|
|
83
|
+
header: headNode,
|
|
84
|
+
authSchemes: authNode,
|
|
85
|
+
body: bodyNode,
|
|
86
|
+
callbacks: callbacksNode,
|
|
87
|
+
paremeters: parameterNode,
|
|
88
|
+
responses: responseNode,
|
|
89
|
+
apiPlayground: playgroundEnabled ? (_jsx(APIPlayground, { path: path, method: method, ctx: ctx })) : (_jsxs("div", { className: "flex flex-row items-center gap-2.5 p-3 rounded-xl border bg-fd-card text-fd-card-foreground not-prose", children: [_jsx(MethodLabel, { className: "text-xs", children: method.method }), _jsx("code", { className: "flex-1 overflow-auto text-nowrap text-[13px] text-fd-muted-foreground", children: path })] })),
|
|
90
|
+
apiExample: _jsx(APIExample, { method: method, ctx: ctx }),
|
|
91
|
+
}, ctx, method);
|
|
92
|
+
return (_jsx(OperationProviderLazy, { defaultExampleId: method['x-exclusiveCodeSample'] ?? method['x-selectedCodeSample'], route: path, examples: getAPIExamples(path, method, ctx), children: content }));
|
|
78
93
|
}
|
|
79
94
|
else {
|
|
80
|
-
|
|
95
|
+
renderWebhookLayout ?? (renderWebhookLayout = (slots) => (_jsxs("div", { children: [slots.header, slots.authSchemes, slots.paremeters, slots.body, slots.responses, slots.callbacks] })));
|
|
96
|
+
return renderWebhookLayout({
|
|
97
|
+
header: headNode,
|
|
98
|
+
authSchemes: authNode,
|
|
99
|
+
body: bodyNode,
|
|
100
|
+
callbacks: callbacksNode,
|
|
101
|
+
paremeters: parameterNode,
|
|
102
|
+
responses: responseNode,
|
|
103
|
+
});
|
|
81
104
|
}
|
|
82
105
|
}
|
|
83
106
|
async function ResponseAccordion({ status, operation, ctx, }) {
|
|
84
107
|
const response = operation.responses[status];
|
|
85
108
|
const { generateTypeScriptSchema } = ctx;
|
|
86
109
|
const contentTypes = response.content ? Object.entries(response.content) : [];
|
|
87
|
-
return (_jsxs(SelectTabs, { defaultValue: contentTypes.at(0)?.[0], children: [_jsxs(AccordionHeader, { children: [_jsx(AccordionTrigger, { className: "font-mono", children: status }), contentTypes.length > 1 && (_jsx(SelectTabTrigger, { items: contentTypes.map((v) => v[0]) })), contentTypes.length === 1 && (_jsx("p", { className: "text-[13px] text-fd-muted-foreground", children: contentTypes[0][0] }))] }), _jsxs(AccordionContent, { className: "ps-4.5", children: [response.description && (_jsx("div", { className: "prose-no-margin", children:
|
|
110
|
+
return (_jsxs(SelectTabs, { defaultValue: contentTypes.at(0)?.[0], children: [_jsxs(AccordionHeader, { children: [_jsx(AccordionTrigger, { className: "font-mono", children: status }), contentTypes.length > 1 && (_jsx(SelectTabTrigger, { items: contentTypes.map((v) => v[0]) })), contentTypes.length === 1 && (_jsx("p", { className: "text-[13px] text-fd-muted-foreground", children: contentTypes[0][0] }))] }), _jsxs(AccordionContent, { className: "ps-4.5", children: [response.description && (_jsx("div", { className: "prose-no-margin", children: ctx.renderMarkdown(response.description) })), contentTypes?.map(async ([type, resType]) => {
|
|
88
111
|
const schema = resType.schema;
|
|
89
112
|
let ts;
|
|
90
113
|
if (generateTypeScriptSchema) {
|
|
91
114
|
ts = await generateTypeScriptSchema(operation, status);
|
|
92
115
|
}
|
|
93
116
|
else if (generateTypeScriptSchema === undefined && schema) {
|
|
94
|
-
ts = await getTypescriptSchema(ctx
|
|
117
|
+
ts = await getTypescriptSchema(schema, ctx);
|
|
95
118
|
}
|
|
96
119
|
return (_jsxs(SelectTab, { value: type, className: "my-2", children: [ts && _jsx(CopyResponseTypeScript, { code: ts }), schema && (_jsx("div", { className: "border px-3 py-2 rounded-lg", children: _jsx(Schema, { name: "response", root: schema, as: "body", readOnly: true, ctx: ctx }) }))] }, type));
|
|
97
120
|
})] })] }));
|
|
@@ -108,17 +131,20 @@ function WebhookCallback({ callback, ctx, headingLevel, }) {
|
|
|
108
131
|
return (_jsxs(AccordionItem, { value: path, children: [_jsx(AccordionHeader, { children: _jsx(AccordionTrigger, { className: "font-mono", children: path }) }), _jsx(AccordionContent, { children: pathNodes })] }, path));
|
|
109
132
|
}) }));
|
|
110
133
|
}
|
|
111
|
-
function AuthScheme({ scheme: schema, scopes, ctx
|
|
134
|
+
function AuthScheme({ scheme: schema, scopes, ctx, }) {
|
|
112
135
|
const scopeElement = scopes.length > 0 ? (_jsxs("p", { children: ["Scope: ", _jsx("code", { children: scopes.join(', ') })] })) : null;
|
|
113
136
|
if (schema.type === 'http' || schema.type === 'oauth2') {
|
|
114
|
-
return (_jsxs(
|
|
137
|
+
return (_jsxs(AuthProperty, { name: "Authorization", type: schema.type === 'http' && schema.scheme === 'basic'
|
|
115
138
|
? `Basic <token>`
|
|
116
|
-
: 'Bearer <token>',
|
|
139
|
+
: 'Bearer <token>', children: [schema.description && ctx.renderMarkdown(schema.description), _jsxs("p", { children: ["In: ", _jsx("code", { children: "header" })] }), scopeElement] }));
|
|
117
140
|
}
|
|
118
141
|
if (schema.type === 'apiKey') {
|
|
119
|
-
return (_jsxs(
|
|
142
|
+
return (_jsxs(AuthProperty, { name: schema.name, type: "<token>", children: [schema.description && ctx.renderMarkdown(schema.description), _jsxs("p", { children: ["In: ", _jsx("code", { children: schema.in }), scopeElement] })] }));
|
|
120
143
|
}
|
|
121
144
|
if (schema.type === 'openIdConnect') {
|
|
122
|
-
return (_jsxs(
|
|
145
|
+
return (_jsxs(AuthProperty, { name: "OpenID Connect", type: "<token>", children: [schema.description && ctx.renderMarkdown(schema.description), scopeElement] }));
|
|
123
146
|
}
|
|
124
147
|
}
|
|
148
|
+
function AuthProperty({ name, type, ...props }) {
|
|
149
|
+
return (_jsxs("div", { className: cn('text-sm border-t py-4 first:border-t-0', props.className), children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3 not-prose", children: [_jsx("span", { className: "font-medium font-mono text-fd-primary", children: name }), _jsx("span", { className: "text-sm font-mono text-fd-muted-foreground", children: type })] }), _jsx("div", { className: "prose-no-margin pt-2.5 empty:hidden", children: props.children })] }));
|
|
150
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SchemaUIGeneratedData } from '../../ui/schema/index.js';
|
|
2
|
+
export interface SchemaUIProps {
|
|
3
|
+
name: string;
|
|
4
|
+
required?: boolean;
|
|
5
|
+
as?: 'property' | 'body';
|
|
6
|
+
readOnly?: boolean;
|
|
7
|
+
writeOnly?: boolean;
|
|
8
|
+
generated: SchemaUIGeneratedData;
|
|
9
|
+
}
|
|
10
|
+
export declare function SchemaUI({ name, required, as, generated, readOnly, writeOnly, }: SchemaUIProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/ui/schema/client.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAc,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAuDrE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAEzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,qBAAqB,CAAC;CAClC;AAED,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,QAAgB,EAChB,EAAe,EACf,SAAS,EACT,QAAQ,EACR,SAAS,GACV,EAAE,aAAa,2CA2Bf"}
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { createContext, Fragment, use, useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
4
4
|
import { Tabs, TabsContent, TabsList, TabsTrigger, } from 'fumadocs-ui/components/tabs';
|
|
5
|
-
import {
|
|
5
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from 'fumadocs-ui/components/ui/collapsible';
|
|
6
|
+
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
|
|
7
|
+
import { ChevronDown } from '../../icons.js';
|
|
8
|
+
import { Badge } from '../../ui/components/method-label.js';
|
|
6
9
|
import { Popover, PopoverContent, PopoverTrigger, } from 'fumadocs-ui/components/ui/popover';
|
|
7
10
|
import { cn } from 'fumadocs-ui/utils/cn';
|
|
8
11
|
import { cva } from 'class-variance-authority';
|
|
@@ -17,24 +20,23 @@ const PropertyContext = createContext({
|
|
|
17
20
|
renderRef: (props) => _jsx(RootRef, { ...props }),
|
|
18
21
|
});
|
|
19
22
|
const DataContext = createContext(null);
|
|
20
|
-
export function SchemaUIProvider(props) {
|
|
21
|
-
return _jsx(DataContext, { value: props.value, children: props.children });
|
|
22
|
-
}
|
|
23
23
|
function useData() {
|
|
24
24
|
return use(DataContext);
|
|
25
25
|
}
|
|
26
26
|
function useProperty() {
|
|
27
27
|
return use(PropertyContext);
|
|
28
28
|
}
|
|
29
|
-
export function SchemaUI({ name, required = false, as = 'property', }) {
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
export function SchemaUI({ name, required = false, as = 'property', generated, readOnly, writeOnly, }) {
|
|
30
|
+
const schema = generated.refs[generated.$root];
|
|
31
|
+
const context = useMemo(() => ({
|
|
32
|
+
...generated,
|
|
33
|
+
readOnly,
|
|
34
|
+
writeOnly,
|
|
35
|
+
}), [generated, readOnly, writeOnly]);
|
|
36
|
+
const isProperty = as === 'property' || !isExpandable(schema);
|
|
37
|
+
return (_jsx(DataContext, { value: context, children: isProperty ? (_jsx(SchemaUIProperty, { name: name, "$type": generated.$root, overrides: {
|
|
34
38
|
required,
|
|
35
|
-
} }));
|
|
36
|
-
}
|
|
37
|
-
return _jsx(SchemaUIContent, { "$type": $root });
|
|
39
|
+
} })) : (_jsx(SchemaUIContent, { "$type": generated.$root })) }));
|
|
38
40
|
}
|
|
39
41
|
function SchemaUIContent({ $type }) {
|
|
40
42
|
const { refs, readOnly, writeOnly } = useData();
|
|
@@ -134,6 +136,14 @@ function LinkRef({ $ref, pathName, onInsert, text, }) {
|
|
|
134
136
|
onInsert(pathName, $ref);
|
|
135
137
|
}, children: text }));
|
|
136
138
|
}
|
|
139
|
+
function ObjectCollapsible(props) {
|
|
140
|
+
return (_jsxs(Collapsible, { className: "my-2", ...props, children: [_jsxs(CollapsibleTrigger, { className: cn(buttonVariants({ color: 'secondary', size: 'sm' }), 'group px-3 py-2 data-[state=open]:rounded-b-none'), children: [props.name, _jsx(ChevronDown, { className: "size-4 text-fd-muted-foreground group-data-[state=open]:rotate-180" })] }), _jsx(CollapsibleContent, { className: "-mt-px *:bg-fd-card", children: props.children })] }));
|
|
141
|
+
}
|
|
142
|
+
function Property({ name, type, required, deprecated, nested = false, ...props }) {
|
|
143
|
+
return (_jsxs("div", { className: cn('text-sm border-t', nested
|
|
144
|
+
? 'p-3 border-x bg-fd-card last:rounded-b-xl first:rounded-tr-xl last:border-b'
|
|
145
|
+
: 'py-4 first:border-t-0', props.className), children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3 not-prose", children: [_jsxs("span", { className: "font-medium font-mono text-fd-primary", children: [name, required === false && (_jsx("span", { className: "text-fd-muted-foreground", children: "?" }))] }), typeof type === 'string' ? (_jsx("span", { className: "text-sm font-mono text-fd-muted-foreground", children: type })) : (type), deprecated && (_jsx(Badge, { color: "yellow", className: "ms-auto text-xs", children: "Deprecated" }))] }), _jsx("div", { className: "prose-no-margin pt-2.5 empty:hidden", children: props.children })] }));
|
|
146
|
+
}
|
|
137
147
|
function isExpandable(schema) {
|
|
138
148
|
return schema.type !== 'primitive';
|
|
139
149
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
2
|
import type { ResolvedSchema } from '../../utils/schema.js';
|
|
3
3
|
import type { RenderContext } from '../../types.js';
|
|
4
|
+
import type { SchemaUIProps } from '../../ui/schema/client.js';
|
|
4
5
|
export interface FieldBase {
|
|
5
6
|
description?: ReactNode;
|
|
6
7
|
infoTags?: ReactNode[];
|
|
@@ -35,9 +36,9 @@ export interface SchemaUIOptions {
|
|
|
35
36
|
root: ResolvedSchema;
|
|
36
37
|
ctx: RenderContext;
|
|
37
38
|
}
|
|
38
|
-
export interface
|
|
39
|
+
export interface SchemaUIGeneratedData {
|
|
39
40
|
$root: string;
|
|
40
41
|
refs: Record<string, SchemaData>;
|
|
41
42
|
}
|
|
42
|
-
export declare function
|
|
43
|
-
//# sourceMappingURL=
|
|
43
|
+
export declare function Schema({ ctx, root, ...props }: SchemaUIOptions & Omit<SchemaUIProps, 'generated'>): string | number | bigint | boolean | Iterable<ReactNode> | Promise<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/schema/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD,MAAM,WAAW,SAAS;IACxB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;IAEvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAElB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAChC,CACI;IACE,IAAI,EAAE,WAAW,CAAC;CACnB,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,OAAO,CAAC;KACnB,EAAE,CAAC;CACL,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH,GACD;IACE,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;CACL,CACJ,CAAC;AAEJ,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,aAAa,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CAClC;AAED,wBAAgB,MAAM,CAAC,EACrB,GAAG,EACH,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,eAAe,GAAG,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,8IAQpD"}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { FormatFlags, schemaToString } from '../../utils/schema-to-string.js';
|
|
3
|
-
import { Markdown } from '../../render/markdown.js';
|
|
4
3
|
import { combineSchema } from '../../utils/combine-schema.js';
|
|
5
|
-
|
|
4
|
+
import { SchemaUILazy } from '../../ui/schema/lazy.js';
|
|
5
|
+
export function Schema({ ctx, root, ...props }) {
|
|
6
|
+
if (ctx.schemaUI?.render) {
|
|
7
|
+
return ctx.schemaUI.render({ root, ...props }, ctx);
|
|
8
|
+
}
|
|
9
|
+
return (_jsx(SchemaUILazy, { ...props, generated: generateSchemaUI({ ctx, root }) }));
|
|
10
|
+
}
|
|
11
|
+
function generateSchemaUI({ ctx, root, }) {
|
|
6
12
|
const refs = {};
|
|
7
|
-
const {
|
|
13
|
+
const { showExample = false } = ctx.schemaUI ?? {};
|
|
8
14
|
function generateInfoTags(schema) {
|
|
9
15
|
const fields = [];
|
|
10
16
|
function field(key, value) {
|
|
@@ -37,7 +43,7 @@ export function generateSchemaUI({ ctx, root }) {
|
|
|
37
43
|
if (schema.enum) {
|
|
38
44
|
fields.push(field('Value in', schema.enum.map((value) => JSON.stringify(value)).join(' | ')));
|
|
39
45
|
}
|
|
40
|
-
if (
|
|
46
|
+
if (showExample && schema.examples) {
|
|
41
47
|
for (const example of schema.examples) {
|
|
42
48
|
fields.push(field('Example', JSON.stringify(example, null, 2)));
|
|
43
49
|
}
|
|
@@ -68,7 +74,7 @@ export function generateSchemaUI({ ctx, root }) {
|
|
|
68
74
|
};
|
|
69
75
|
}
|
|
70
76
|
return {
|
|
71
|
-
description: schema.description &&
|
|
77
|
+
description: schema.description && ctx.renderMarkdown(schema.description),
|
|
72
78
|
infoTags: generateInfoTags(schema),
|
|
73
79
|
typeName: schemaToString(schema, ctx.schema),
|
|
74
80
|
aliasName: schemaToString(schema, ctx.schema, FormatFlags.UseAlias),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../../../src/ui/schema/lazy.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,oCAExB,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type { SchemaObject } from 'ajv';
|
|
2
|
+
import type { RenderContext } from '../types.js';
|
|
3
|
+
export declare function getTypescriptSchema(schema: SchemaObject, ctx: RenderContext): Promise<string | undefined>;
|
|
3
4
|
//# sourceMappingURL=get-typescript-schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-typescript-schema.d.ts","sourceRoot":"","sources":["../../src/utils/get-typescript-schema.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-typescript-schema.d.ts","sourceRoot":"","sources":["../../src/utils/get-typescript-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAsB7B"}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export async function getTypescriptSchema(schema, ctx) {
|
|
2
|
+
const { compile } = await import('@fumari/json-schema-to-typescript');
|
|
3
3
|
try {
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
const input = structuredClone({
|
|
5
|
+
schema,
|
|
6
|
+
idToSchema: ctx.schema._internal_idToSchema(),
|
|
7
|
+
});
|
|
8
|
+
const schemaToId = new WeakMap();
|
|
9
|
+
for (const [k, v] of input.idToSchema) {
|
|
10
|
+
schemaToId.set(v, k);
|
|
11
|
+
}
|
|
12
|
+
return await compile(input.schema, 'Response', {
|
|
9
13
|
enableConstEnums: false,
|
|
14
|
+
schemaToId,
|
|
10
15
|
});
|
|
11
16
|
}
|
|
12
17
|
catch (e) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../../src/utils/lazy.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAQ,MAAM,OAAO,CAAC;AAMjD,wBAAgB,QAAQ,CAAC,CAAC,SAAS,aAAa,CAAC,GAAG,CAAC,EACnD,IAAI,EAAE,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC,GAClC,CAAC,CAMH"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { lazy } from 'react';
|
|
3
|
+
// Waku wraps all export functions of a "use client" file in `React.lazy`, but `lazy(lazy(() => ...))` causes error.
|
|
4
|
+
// we wrap another layer of component such that it is valid
|
|
5
|
+
// TODO: perhaps we can remove it once Waku migrated to vite-rsc
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- type infer
|
|
7
|
+
export function wrapLazy(load) {
|
|
8
|
+
const V = lazy(load);
|
|
9
|
+
return function wrapper(props) {
|
|
10
|
+
return _jsx(V, { ...props });
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ProcessedDocument } from '../../utils/process-document.js';
|
|
2
2
|
import type { OpenAPIServer } from '../../server/index.js';
|
|
3
|
-
import type { OperationItem, WebhookItem } from '../../
|
|
3
|
+
import type { OperationItem, WebhookItem } from '../../ui/api-page.js';
|
|
4
4
|
import type { OperationObject, PathItemObject, TagObject } from '../../types.js';
|
|
5
5
|
import { type NoReference } from '../../utils/schema.js';
|
|
6
6
|
interface BaseEntry {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../src/utils/pages/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../src/utils/pages/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,KAAK,EAEV,eAAe,EACf,cAAc,EACd,SAAS,EACV,MAAM,SAAS,CAAC;AACjB,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,gBAAgB,CAAC;AAIxB,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,SAAS,CAAC;IAClB,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GACnB,SAAS,GACT,eAAe,GACf,aAAa,GACb,WAAW,CAAC;AAEhB,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,iBAAiB,CAAC;IAC5B;;;;OAIG;IACH,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAErC;;OAEG;IACH,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAE9C;;OAEG;IACH,OAAO,EAAE,MAAM,aAAa,CAAC;IAC7B,oBAAoB,EAAE,CAAC,IAAI,EAAE,WAAW,KACpC;QACE,IAAI,WAAW,IAAI,MAAM,CAAC;QAC1B,QAAQ,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;QACtC,SAAS,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC;KACzC,GACD,SAAS,CAAC;IACd,sBAAsB,EAAE,CAAC,IAAI,EAAE,aAAa,KACxC;QACE,IAAI,WAAW,IAAI,MAAM,CAAC;QAC1B,QAAQ,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;QACtC,SAAS,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC;KACzC,GACD,SAAS,CAAC;IACd,OAAO,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK;QAC3B,IAAI,WAAW,IAAI,MAAM,CAAC;KAC3B,CAAC;IACF,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KACrB;QACE,IAAI,EAAE,SAAS,CAAC;QAChB,IAAI,WAAW,IAAI,MAAM,CAAC;KAC3B,GACD,SAAS,CAAC;CACf;AAED,UAAU,aAAa;IACrB,QAAQ,EAAE,CAAC,WAAW,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,EAAE,CAAC;IAChD,UAAU,EAAE,CAAC,aAAa,GAAG;QAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;KACjB,CAAC,EAAE,CAAC;CACN;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAcxC;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,kBAAkB,GACzB,WAAW,EAAE,CA2Ef"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { ApiPageProps } from '../../
|
|
2
|
-
import type { OpenAPIServer } from '../../server/index.js';
|
|
1
|
+
import type { ApiPageProps } from '../../ui/api-page.js';
|
|
3
2
|
import type { OutputEntry } from '../../utils/pages/builder.js';
|
|
4
|
-
export declare function toBody(
|
|
3
|
+
export declare function toBody(entry: OutputEntry): ApiPageProps;
|
|
5
4
|
//# sourceMappingURL=to-body.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"to-body.d.ts","sourceRoot":"","sources":["../../../src/utils/pages/to-body.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"to-body.d.ts","sourceRoot":"","sources":["../../../src/utils/pages/to-body.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CAoBvD"}
|