fumadocs-openapi 10.0.11 → 10.1.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 +6 -5
- package/dist/generate-file.d.ts.map +1 -1
- package/dist/generate-file.js +44 -37
- package/dist/playground/client.d.ts +9 -7
- package/dist/playground/client.d.ts.map +1 -1
- package/dist/playground/client.js +7 -7
- package/dist/playground/components/inputs.d.ts +6 -6
- package/dist/playground/components/inputs.d.ts.map +1 -1
- package/dist/playground/components/inputs.js +13 -12
- package/dist/playground/get-default-values.d.ts +2 -2
- package/dist/playground/get-default-values.d.ts.map +1 -1
- package/dist/playground/index.d.ts +1 -2
- package/dist/playground/index.d.ts.map +1 -1
- package/dist/playground/index.js +2 -0
- package/dist/playground/schema.d.ts +22 -8
- package/dist/playground/schema.d.ts.map +1 -1
- package/dist/playground/schema.js +29 -34
- package/dist/requests/generators/index.d.ts +1 -1
- package/dist/requests/generators/index.d.ts.map +1 -1
- package/dist/server/create.d.ts +1 -1
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/source-api.d.ts +5 -3
- package/dist/server/source-api.d.ts.map +1 -1
- package/dist/server/source-api.js +13 -7
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/api-page.d.ts +16 -8
- package/dist/ui/api-page.d.ts.map +1 -1
- package/dist/ui/api-page.js +7 -7
- package/dist/ui/client/index.d.ts +2 -2
- package/dist/ui/client/index.d.ts.map +1 -1
- package/dist/ui/operation/client.d.ts +5 -2
- package/dist/ui/operation/client.d.ts.map +1 -1
- package/dist/ui/operation/client.js +2 -2
- package/dist/ui/operation/index.d.ts +4 -3
- package/dist/ui/operation/index.d.ts.map +1 -1
- package/dist/ui/operation/index.js +67 -33
- package/dist/ui/operation/request-tabs.d.ts +18 -0
- package/dist/ui/operation/request-tabs.d.ts.map +1 -0
- package/dist/ui/operation/request-tabs.js +143 -0
- package/dist/ui/operation/response-tabs.d.ts +32 -0
- package/dist/ui/operation/response-tabs.d.ts.map +1 -0
- package/dist/ui/operation/response-tabs.js +59 -0
- package/dist/ui/operation/usage-tabs/client.d.ts +23 -0
- package/dist/ui/operation/usage-tabs/client.d.ts.map +1 -0
- package/dist/ui/operation/{example-panel → usage-tabs}/client.js +50 -6
- package/dist/ui/operation/usage-tabs/index.d.ts +26 -0
- package/dist/ui/operation/usage-tabs/index.d.ts.map +1 -0
- package/dist/ui/operation/usage-tabs/index.js +52 -0
- package/dist/ui/operation/usage-tabs/lazy.d.ts +4 -0
- package/dist/ui/operation/usage-tabs/lazy.d.ts.map +1 -0
- package/dist/ui/operation/usage-tabs/lazy.js +5 -0
- package/dist/ui/schema/client.d.ts +1 -3
- package/dist/ui/schema/client.d.ts.map +1 -1
- package/dist/ui/schema/client.js +13 -17
- package/dist/ui/schema/index.d.ts +19 -5
- package/dist/ui/schema/index.d.ts.map +1 -1
- package/dist/ui/schema/index.js +69 -29
- package/dist/utils/deep-equal.d.ts +2 -0
- package/dist/utils/deep-equal.d.ts.map +1 -0
- package/dist/utils/deep-equal.js +27 -0
- package/dist/utils/merge-schema.d.ts +7 -0
- package/dist/utils/merge-schema.d.ts.map +1 -0
- package/dist/utils/merge-schema.js +179 -0
- package/dist/utils/pages/to-body.d.ts.map +1 -1
- package/dist/utils/pages/to-body.js +2 -3
- package/dist/utils/pages/to-text.d.ts.map +1 -1
- package/dist/utils/pages/to-text.js +31 -16
- package/dist/utils/schema-to-string.d.ts.map +1 -1
- package/dist/utils/schema-to-string.js +8 -5
- package/dist/utils/use-query.d.ts +1 -0
- package/dist/utils/use-query.d.ts.map +1 -1
- package/dist/utils/use-query.js +5 -0
- package/package.json +14 -14
- package/dist/ui/contexts/operation.d.ts +0 -20
- package/dist/ui/contexts/operation.d.ts.map +0 -1
- package/dist/ui/contexts/operation.js +0 -48
- package/dist/ui/contexts/operation.lazy.d.ts +0 -2
- package/dist/ui/contexts/operation.lazy.d.ts.map +0 -1
- package/dist/ui/contexts/operation.lazy.js +0 -3
- package/dist/ui/operation/example-panel/client.d.ts +0 -4
- package/dist/ui/operation/example-panel/client.d.ts.map +0 -1
- package/dist/ui/operation/example-panel/index.d.ts +0 -58
- package/dist/ui/operation/example-panel/index.d.ts.map +0 -1
- package/dist/ui/operation/example-panel/index.js +0 -140
- package/dist/ui/operation/example-panel/lazy.d.ts +0 -3
- package/dist/ui/operation/example-panel/lazy.d.ts.map +0 -1
- package/dist/ui/operation/example-panel/lazy.js +0 -4
- package/dist/ui/operation/get-request-data.d.ts +0 -4
- package/dist/ui/operation/get-request-data.d.ts.map +0 -1
- package/dist/ui/operation/get-request-data.js +0 -70
- package/dist/utils/combine-schema.d.ts +0 -6
- package/dist/utils/combine-schema.d.ts.map +0 -1
- package/dist/utils/combine-schema.js +0 -51
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } 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
5
|
import { Schema } from '../schema/index.js';
|
|
6
|
-
import {
|
|
6
|
+
import { UsageTabs } from '../../ui/operation/usage-tabs/index.js';
|
|
7
7
|
import { MethodLabel } from '../../ui/components/method-label.js';
|
|
8
8
|
import { getTypescriptSchema } from '../../utils/get-typescript-schema.js';
|
|
9
9
|
import { CopyResponseTypeScript, SelectTab, SelectTabs, SelectTabTrigger, } from './client.js';
|
|
@@ -11,35 +11,48 @@ import { AccordionContent, AccordionHeader, AccordionItem, Accordions, Accordion
|
|
|
11
11
|
import { isMediaTypeSupported } from '../../requests/media/adapter.js';
|
|
12
12
|
import { cn } from 'fumadocs-ui/utils/cn';
|
|
13
13
|
import { APIPlayground } from '../../playground/index.js';
|
|
14
|
-
import {
|
|
14
|
+
import { RequestTabs, getExampleRequests } from './request-tabs.js';
|
|
15
|
+
import { UsageTabsProviderLazy } from './usage-tabs/lazy.js';
|
|
15
16
|
const ParamTypes = {
|
|
16
17
|
path: 'Path Parameters',
|
|
17
18
|
query: 'Query Parameters',
|
|
18
19
|
header: 'Header Parameters',
|
|
19
20
|
cookie: 'Cookie Parameters',
|
|
20
21
|
};
|
|
21
|
-
export async function Operation({ type = 'operation', path, method, ctx,
|
|
22
|
+
export async function Operation({ type = 'operation', path, method, ctx, showTitle, showDescription, headingLevel = 2, }) {
|
|
22
23
|
const { schema: { dereferenced }, } = ctx;
|
|
23
24
|
const body = method.requestBody;
|
|
24
25
|
let headNode = null;
|
|
26
|
+
const descriptionNode = showDescription &&
|
|
27
|
+
method.description &&
|
|
28
|
+
ctx.renderMarkdown(method.description);
|
|
25
29
|
let bodyNode = null;
|
|
26
30
|
let authNode = null;
|
|
27
31
|
let responseNode = null;
|
|
28
32
|
let callbacksNode = null;
|
|
29
|
-
if (
|
|
33
|
+
if (showTitle) {
|
|
30
34
|
const title = method.summary ??
|
|
31
35
|
(method.operationId ? idToTitle(method.operationId) : path);
|
|
32
|
-
headNode =
|
|
36
|
+
headNode = ctx.renderHeading(headingLevel, title);
|
|
33
37
|
headingLevel++;
|
|
34
38
|
}
|
|
35
39
|
const contentTypes = body ? Object.entries(body.content) : null;
|
|
36
40
|
if (body && contentTypes && contentTypes.length > 0) {
|
|
37
|
-
const
|
|
38
|
-
|
|
41
|
+
const items = contentTypes.map(([key]) => ({
|
|
42
|
+
label: _jsx("code", { className: "text-xs", children: key }),
|
|
43
|
+
value: key,
|
|
44
|
+
}));
|
|
45
|
+
bodyNode = (_jsxs(SelectTabs, { defaultValue: items[0].value, children: [_jsxs("div", { className: "flex gap-2 items-center justify-between", children: [ctx.renderHeading(headingLevel, 'Request Body', {
|
|
46
|
+
className: 'my-0!',
|
|
47
|
+
}), contentTypes.length > 1 ? (_jsx(SelectTabTrigger, { items: items, className: "font-medium" })) : (_jsx("p", { className: "text-fd-muted-foreground not-prose", children: items[0].label }))] }), body.description && ctx.renderMarkdown(body.description), contentTypes.map(([type, content]) => {
|
|
39
48
|
if (!isMediaTypeSupported(type, ctx.mediaAdapters)) {
|
|
40
49
|
throw new Error(`Media type ${type} is not supported (in ${path})`);
|
|
41
50
|
}
|
|
42
|
-
return (_jsx(SelectTab, { value: type, children: _jsx(Schema, {
|
|
51
|
+
return (_jsx(SelectTab, { value: type, children: _jsx(Schema, { client: {
|
|
52
|
+
name: 'body',
|
|
53
|
+
as: 'body',
|
|
54
|
+
required: body.required,
|
|
55
|
+
}, root: (content.schema ?? {}), readOnly: method.method === 'GET', writeOnly: method.method !== 'GET', ctx: ctx }) }, type));
|
|
43
56
|
})] }));
|
|
44
57
|
}
|
|
45
58
|
if (method.responses && ctx.showResponseSchema !== false) {
|
|
@@ -50,18 +63,28 @@ export async function Operation({ type = 'operation', path, method, ctx, hasHead
|
|
|
50
63
|
const params = method.parameters?.filter((param) => param.in === type);
|
|
51
64
|
if (!params || params.length === 0)
|
|
52
65
|
return;
|
|
53
|
-
return (_jsxs(Fragment, { children: [ctx.renderHeading(headingLevel, title), _jsx("div", { className: "flex flex-col", children: params.map((param) => (_jsx(Schema, {
|
|
66
|
+
return (_jsxs(Fragment, { children: [ctx.renderHeading(headingLevel, title), _jsx("div", { className: "flex flex-col", children: params.map((param) => (_jsx(Schema, { client: {
|
|
67
|
+
name: param.name,
|
|
68
|
+
required: param.required,
|
|
69
|
+
}, root: {
|
|
54
70
|
...param.schema,
|
|
55
71
|
description: param.description ?? param.schema?.description,
|
|
56
72
|
deprecated: (param.deprecated ?? false) ||
|
|
57
73
|
(param.schema?.deprecated ?? false),
|
|
58
|
-
},
|
|
74
|
+
}, readOnly: method.method === 'GET', writeOnly: method.method !== 'GET', ctx: ctx }, param.name))) })] }, type));
|
|
59
75
|
});
|
|
60
76
|
const securities = (method.security ?? dereferenced.security ?? []).filter((v) => Object.keys(v).length > 0);
|
|
61
77
|
if (type === 'operation' && securities.length > 0) {
|
|
62
78
|
const securitySchemes = dereferenced.components?.securitySchemes;
|
|
63
|
-
const
|
|
64
|
-
|
|
79
|
+
const items = securities.map((security, i) => {
|
|
80
|
+
return {
|
|
81
|
+
value: String(i),
|
|
82
|
+
label: (_jsx("div", { className: "flex flex-col text-xs min-w-0", children: Object.entries(security).map(([key, scopes]) => (_jsxs("code", { className: "truncate", children: [_jsx("span", { className: "font-medium", children: key }), ' ', scopes.length > 0 && (_jsx("span", { className: "text-fd-muted-foreground", children: scopes.join(', ') }))] }, key))) })),
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
authNode = (_jsxs(SelectTabs, { defaultValue: items[0].value, children: [_jsxs("div", { className: "flex items-start justify-between gap-2 mt-10 mb-5", children: [ctx.renderHeading(headingLevel, 'Authorization', {
|
|
86
|
+
className: 'my-0!',
|
|
87
|
+
}), items.length > 1 ? (_jsx(SelectTabTrigger, { items: items })) : (_jsx("p", { className: "not-prose", children: items[0].label }))] }), securities.map((security, i) => (_jsx(SelectTab, { value: items[i].value, children: Object.entries(security).map(([key, scopes]) => {
|
|
65
88
|
const scheme = securitySchemes?.[key];
|
|
66
89
|
if (!scheme)
|
|
67
90
|
return;
|
|
@@ -70,38 +93,44 @@ export async function Operation({ type = 'operation', path, method, ctx, hasHead
|
|
|
70
93
|
}
|
|
71
94
|
const callbacks = method.callbacks ? Object.entries(method.callbacks) : null;
|
|
72
95
|
if (callbacks && callbacks.length > 0) {
|
|
73
|
-
const
|
|
74
|
-
|
|
96
|
+
const items = callbacks.map(([key]) => ({
|
|
97
|
+
label: _jsx("code", { className: "text-xs", children: key }),
|
|
98
|
+
value: key,
|
|
99
|
+
}));
|
|
100
|
+
callbacksNode = (_jsxs(SelectTabs, { defaultValue: items[0].value, children: [_jsxs("div", { className: "flex justify-between gap-2 items-end mt-10 mb-5", children: [ctx.renderHeading(headingLevel, 'Callbacks', {
|
|
101
|
+
className: 'my-0!',
|
|
102
|
+
}), callbacks.length > 1 ? (_jsx(SelectTabTrigger, { items: items, className: "font-medium" })) : (_jsx("p", { className: "text-fd-muted-foreground not-prose", children: items[0].label }))] }), callbacks.map(([name, callback]) => (_jsx(SelectTab, { value: name, children: _jsx(WebhookCallback, { callback: callback, ctx: ctx, headingLevel: headingLevel }) }, name)))] }));
|
|
75
103
|
}
|
|
76
104
|
let { renderOperationLayout, renderWebhookLayout } = ctx.content ?? {};
|
|
77
105
|
if (type === 'operation') {
|
|
78
106
|
renderOperationLayout ?? (renderOperationLayout = (slots) => {
|
|
79
|
-
return (_jsxs("div", { className: "flex flex-col gap-x-6 gap-y-4
|
|
80
|
-
'--fd-api-info-top': 'calc(12px + var(--fd-nav-height) + var(--fd-banner-height) + var(--fd-tocnav-height, 0px))',
|
|
81
|
-
}, 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] }));
|
|
107
|
+
return (_jsxs("div", { className: "flex flex-col gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [slots.header, slots.apiPlayground, slots.description, slots.authSchemes, slots.paremeters, slots.body, slots.responses, slots.callbacks] }), _jsx("div", { className: "@4xl:sticky @4xl:top-[calc(var(--fd-docs-row-1,2rem)+1rem)] @4xl:w-[400px]", children: slots.apiExample })] }));
|
|
82
108
|
});
|
|
83
109
|
const playgroundEnabled = ctx.playground?.enabled ?? true;
|
|
84
110
|
const content = await renderOperationLayout({
|
|
85
111
|
header: headNode,
|
|
112
|
+
description: descriptionNode,
|
|
86
113
|
authSchemes: authNode,
|
|
87
114
|
body: bodyNode,
|
|
88
115
|
callbacks: callbacksNode,
|
|
89
116
|
paremeters: parameterNode,
|
|
90
117
|
responses: responseNode,
|
|
91
118
|
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-[0.8125rem] text-fd-muted-foreground", children: path })] })),
|
|
92
|
-
apiExample: _jsx(
|
|
119
|
+
apiExample: _jsx(UsageTabs, { method: method, ctx: ctx }),
|
|
93
120
|
}, ctx, method);
|
|
94
|
-
return (_jsx(
|
|
121
|
+
return (_jsx(UsageTabsProviderLazy, { defaultExampleId: method['x-exclusiveCodeSample'] ?? method['x-selectedCodeSample'], route: path, examples: getExampleRequests(path, method, ctx), children: content }));
|
|
95
122
|
}
|
|
96
123
|
else {
|
|
97
|
-
renderWebhookLayout ?? (renderWebhookLayout = (slots) => (_jsxs("div", { children: [slots.header, slots.authSchemes, slots.paremeters, slots.body, slots.responses, slots.callbacks] })));
|
|
124
|
+
renderWebhookLayout ?? (renderWebhookLayout = (slots) => (_jsxs("div", { className: "flex flex-col-reverse gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [slots.header, slots.description, slots.authSchemes, slots.paremeters, slots.body, slots.responses, slots.callbacks] }), _jsx("div", { className: "@4xl:sticky @4xl:top-[calc(var(--fd-docs-row-1,2rem)+1rem)] @4xl:w-[400px]", children: slots.requests })] })));
|
|
98
125
|
return renderWebhookLayout({
|
|
99
126
|
header: headNode,
|
|
127
|
+
description: descriptionNode,
|
|
100
128
|
authSchemes: authNode,
|
|
101
129
|
body: bodyNode,
|
|
102
130
|
callbacks: callbacksNode,
|
|
103
131
|
paremeters: parameterNode,
|
|
104
132
|
responses: responseNode,
|
|
133
|
+
requests: _jsx(RequestTabs, { path: path, operation: method, ctx: ctx }),
|
|
105
134
|
});
|
|
106
135
|
}
|
|
107
136
|
}
|
|
@@ -112,12 +141,15 @@ async function ResponseAccordion({ status, operation, ctx, }) {
|
|
|
112
141
|
let wrapper = (children) => children;
|
|
113
142
|
let selectorNode = null;
|
|
114
143
|
if (contentTypes.length > 0) {
|
|
115
|
-
const
|
|
144
|
+
const items = contentTypes.map(([key]) => ({
|
|
145
|
+
label: _jsx("code", { className: "text-xs", children: key }),
|
|
146
|
+
value: key,
|
|
147
|
+
}));
|
|
116
148
|
selectorNode =
|
|
117
|
-
|
|
118
|
-
wrapper = (children) => (_jsx(SelectTabs, { defaultValue:
|
|
149
|
+
items.length === 1 ? (_jsx("p", { className: "text-fd-muted-foreground not-prose", children: items[0].label })) : (_jsx(SelectTabTrigger, { items: items }));
|
|
150
|
+
wrapper = (children) => (_jsx(SelectTabs, { defaultValue: items[0].value, children: children }));
|
|
119
151
|
}
|
|
120
|
-
return wrapper(_jsxs(AccordionItem, { value: status, children: [_jsxs(AccordionHeader, { children: [_jsx(AccordionTrigger, { className: "font-mono", children: status }), selectorNode] }), _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]) => {
|
|
152
|
+
return wrapper(_jsxs(AccordionItem, { value: status, children: [_jsxs(AccordionHeader, { children: [_jsx(AccordionTrigger, { className: "font-mono", children: status }), selectorNode] }), _jsxs(AccordionContent, { className: "ps-4.5", children: [response.description && (_jsx("div", { className: "prose-no-margin mb-2", children: ctx.renderMarkdown(response.description) })), contentTypes.map(async ([type, resType]) => {
|
|
121
153
|
const schema = resType.schema;
|
|
122
154
|
let ts;
|
|
123
155
|
if (generateTypeScriptSchema) {
|
|
@@ -126,7 +158,10 @@ async function ResponseAccordion({ status, operation, ctx, }) {
|
|
|
126
158
|
else if (generateTypeScriptSchema === undefined && schema) {
|
|
127
159
|
ts = await getTypescriptSchema(schema, ctx);
|
|
128
160
|
}
|
|
129
|
-
return (_jsxs(SelectTab, { value: type, className: "
|
|
161
|
+
return (_jsxs(SelectTab, { value: type, className: "mb-2", children: [ts && _jsx(CopyResponseTypeScript, { code: ts }), schema && (_jsx("div", { className: "border px-3 py-2 rounded-lg", children: _jsx(Schema, { client: {
|
|
162
|
+
name: 'response',
|
|
163
|
+
as: 'body',
|
|
164
|
+
}, root: schema, readOnly: true, ctx: ctx }) }))] }, type));
|
|
130
165
|
})] })] }));
|
|
131
166
|
}
|
|
132
167
|
function WebhookCallback({ callback, ctx, headingLevel, }) {
|
|
@@ -136,25 +171,24 @@ function WebhookCallback({ callback, ctx, headingLevel, }) {
|
|
|
136
171
|
const operation = pathItem[method];
|
|
137
172
|
if (!operation)
|
|
138
173
|
return null;
|
|
139
|
-
return (_jsx("div", { className: "border p-3 my-2 prose-no-margin rounded-lg", children: _jsx(Operation, { type: "webhook", path: path, headingLevel: headingLevel + 1, method: createMethod(method, pathItem, operation), ctx: ctx }) }, method));
|
|
174
|
+
return (_jsx("div", { className: "border p-3 my-2 @container prose-no-margin rounded-lg", children: _jsx(Operation, { type: "webhook", path: path, headingLevel: headingLevel + 1, method: createMethod(method, pathItem, operation), ctx: ctx }) }, method));
|
|
140
175
|
});
|
|
141
176
|
return (_jsxs(AccordionItem, { value: path, children: [_jsx(AccordionHeader, { children: _jsx(AccordionTrigger, { className: "font-mono", children: path }) }), _jsx(AccordionContent, { children: pathNodes })] }, path));
|
|
142
177
|
}) }));
|
|
143
178
|
}
|
|
144
179
|
function AuthScheme({ scheme: schema, scopes, ctx, }) {
|
|
145
|
-
const scopeElement = scopes.length > 0 ? (_jsxs("p", { children: ["Scope: ", _jsx("code", { children: scopes.join(', ') })] })) : null;
|
|
146
180
|
if (schema.type === 'http' || schema.type === 'oauth2') {
|
|
147
181
|
return (_jsxs(AuthProperty, { name: "Authorization", type: schema.type === 'http' && schema.scheme === 'basic'
|
|
148
182
|
? `Basic <token>`
|
|
149
|
-
: 'Bearer <token>', children: [schema.description && ctx.renderMarkdown(schema.description), _jsxs("p", { children: ["In: ", _jsx("code", { children: "header" })] })
|
|
183
|
+
: 'Bearer <token>', scopes: scopes, children: [schema.description && ctx.renderMarkdown(schema.description), _jsxs("p", { children: ["In: ", _jsx("code", { children: "header" })] })] }));
|
|
150
184
|
}
|
|
151
185
|
if (schema.type === 'apiKey') {
|
|
152
|
-
return (_jsxs(AuthProperty, { name: schema.name, type: "<token>", children: [schema.description && ctx.renderMarkdown(schema.description), _jsxs("p", { children: ["In: ", _jsx("code", { children: schema.in })
|
|
186
|
+
return (_jsxs(AuthProperty, { name: schema.name, type: "<token>", scopes: scopes, children: [schema.description && ctx.renderMarkdown(schema.description), _jsxs("p", { children: ["In: ", _jsx("code", { children: schema.in })] })] }));
|
|
153
187
|
}
|
|
154
188
|
if (schema.type === 'openIdConnect') {
|
|
155
|
-
return (
|
|
189
|
+
return (_jsx(AuthProperty, { name: "OpenID Connect", type: "<token>", scopes: scopes, children: schema.description && ctx.renderMarkdown(schema.description) }));
|
|
156
190
|
}
|
|
157
191
|
}
|
|
158
|
-
function AuthProperty({ name, type, ...props }) {
|
|
159
|
-
return (_jsxs("div", { className: cn('text-sm border-t py-4 first:border-t-0',
|
|
192
|
+
function AuthProperty({ name, type, scopes = [], className, ...props }) {
|
|
193
|
+
return (_jsxs("div", { className: cn('text-sm border-t py-4 first:border-t-0', 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 })] }), _jsxs("div", { className: "prose-no-margin pt-2.5 empty:hidden", children: [props.children, scopes.length > 0 && (_jsxs("p", { children: ["Scope: ", _jsx("code", { children: scopes.join(', ') })] }))] })] }));
|
|
160
194
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { MethodInformation, RenderContext } from '../../types.js';
|
|
2
|
+
import { type NoReference } from '../../utils/schema.js';
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
import type { RawRequestData, RequestData } from '../../requests/types.js';
|
|
5
|
+
export interface ExampleRequestItem {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
data: RawRequestData;
|
|
10
|
+
encoded: RequestData;
|
|
11
|
+
}
|
|
12
|
+
export declare function getExampleRequests(path: string, operation: NoReference<MethodInformation>, ctx: RenderContext): ExampleRequestItem[];
|
|
13
|
+
export declare function RequestTabs({ path, operation, ctx, }: {
|
|
14
|
+
path: string;
|
|
15
|
+
operation: NoReference<MethodInformation>;
|
|
16
|
+
ctx: RenderContext;
|
|
17
|
+
}): Promise<string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<ReactNode> | null | undefined>;
|
|
18
|
+
//# sourceMappingURL=request-tabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-tabs.d.ts","sourceRoot":"","sources":["../../../src/ui/operation/request-tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,KAAK,WAAW,EAAoB,MAAM,gBAAgB,CAAC;AASpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAWpE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,WAAW,CAAC,iBAAiB,CAAC,EACzC,GAAG,EAAE,aAAa,GACjB,kBAAkB,EAAE,CA0CtB;AAkFD,wBAAsB,WAAW,CAAC,EAChC,IAAI,EACJ,SAAS,EACT,GAAG,GACJ,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC;IAC1C,GAAG,EAAE,aAAa,CAAC;CACpB,kIASA"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { getPreferredType } from '../../utils/schema.js';
|
|
3
|
+
import { Accordions, AccordionItem, AccordionHeader, AccordionTrigger, AccordionContent, } from '../../ui/components/accordion.js';
|
|
4
|
+
import { sample } from 'openapi-sampler';
|
|
5
|
+
import { encodeRequestData } from '../../requests/media/encode.js';
|
|
6
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger, } from 'fumadocs-ui/components/tabs';
|
|
7
|
+
import { resolveRequestData } from '../../utils/url.js';
|
|
8
|
+
import { MethodLabel } from '../components/method-label.js';
|
|
9
|
+
export function getExampleRequests(path, operation, ctx) {
|
|
10
|
+
const media = operation.requestBody
|
|
11
|
+
? getPreferredType(operation.requestBody.content)
|
|
12
|
+
: null;
|
|
13
|
+
const bodyOfType = media ? operation.requestBody?.content[media] : null;
|
|
14
|
+
if (bodyOfType?.examples) {
|
|
15
|
+
const result = [];
|
|
16
|
+
for (const [key, value] of Object.entries(bodyOfType.examples)) {
|
|
17
|
+
const data = getRequestData(path, operation, key, ctx);
|
|
18
|
+
result.push({
|
|
19
|
+
id: key,
|
|
20
|
+
name: value.summary ?? key,
|
|
21
|
+
description: value.description,
|
|
22
|
+
data,
|
|
23
|
+
encoded: encodeRequestData(data, ctx.mediaAdapters, operation.parameters ?? []),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (result.length > 0)
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
const data = getRequestData(path, operation, null, ctx);
|
|
30
|
+
return [
|
|
31
|
+
{
|
|
32
|
+
id: '_default',
|
|
33
|
+
name: 'Default',
|
|
34
|
+
description: bodyOfType?.schema?.description,
|
|
35
|
+
data,
|
|
36
|
+
encoded: encodeRequestData(data, ctx.mediaAdapters, operation.parameters ?? []),
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
function getRequestData(path, method, sampleKey, _ctx) {
|
|
41
|
+
const result = {
|
|
42
|
+
path: {},
|
|
43
|
+
cookie: {},
|
|
44
|
+
header: {},
|
|
45
|
+
query: {},
|
|
46
|
+
method: method.method,
|
|
47
|
+
};
|
|
48
|
+
for (const param of method.parameters ?? []) {
|
|
49
|
+
let schema = param.schema;
|
|
50
|
+
let value;
|
|
51
|
+
if (!schema && param.content) {
|
|
52
|
+
const type = getPreferredType(param.content);
|
|
53
|
+
const content = type ? param.content[type] : undefined;
|
|
54
|
+
if (!content || !content.schema)
|
|
55
|
+
throw new Error(`Cannot find parameter schema for ${param.name} in ${path} ${method.method}`);
|
|
56
|
+
schema = content.schema;
|
|
57
|
+
value = content.example ?? param.example;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
value = param.example;
|
|
61
|
+
}
|
|
62
|
+
if (param.required) {
|
|
63
|
+
value ?? (value = sample(schema));
|
|
64
|
+
}
|
|
65
|
+
else if (value === undefined) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
switch (param.in) {
|
|
69
|
+
case 'cookie':
|
|
70
|
+
result.cookie[param.name] = value;
|
|
71
|
+
break;
|
|
72
|
+
case 'header':
|
|
73
|
+
result.header[param.name] = value;
|
|
74
|
+
break;
|
|
75
|
+
case 'query':
|
|
76
|
+
result.query[param.name] = value;
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
result.path[param.name] = value;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (method.requestBody) {
|
|
83
|
+
const body = method.requestBody.content;
|
|
84
|
+
const type = getPreferredType(body);
|
|
85
|
+
if (!type)
|
|
86
|
+
throw new Error(`Cannot find body schema for ${path} ${method.method}: missing media type`);
|
|
87
|
+
result.bodyMediaType = type;
|
|
88
|
+
const bodyOfType = body[type];
|
|
89
|
+
if (bodyOfType.examples && sampleKey) {
|
|
90
|
+
result.body = bodyOfType.examples[sampleKey].value;
|
|
91
|
+
}
|
|
92
|
+
else if (bodyOfType.example) {
|
|
93
|
+
result.body = bodyOfType.example;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
result.body = sample((bodyOfType?.schema ?? {}), {
|
|
97
|
+
skipReadOnly: method.method !== 'GET',
|
|
98
|
+
skipWriteOnly: method.method === 'GET',
|
|
99
|
+
skipNonRequired: true,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
export async function RequestTabs({ path, operation, ctx, }) {
|
|
106
|
+
if (!operation.requestBody)
|
|
107
|
+
return null;
|
|
108
|
+
const { renderRequestTabs = renderRequestTabsDefault } = ctx.content ?? {};
|
|
109
|
+
return renderRequestTabs(getExampleRequests(path, operation, ctx), {
|
|
110
|
+
...ctx,
|
|
111
|
+
route: path,
|
|
112
|
+
operation,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
function renderRequestTabsDefault(items, ctx) {
|
|
116
|
+
function renderItem(item) {
|
|
117
|
+
const requestData = item.data;
|
|
118
|
+
const displayNames = {
|
|
119
|
+
body: (_jsxs(_Fragment, { children: ["Body", _jsx("code", { className: "text-xs text-fd-muted-foreground ms-auto", children: requestData.bodyMediaType })] })),
|
|
120
|
+
cookie: 'Cookie',
|
|
121
|
+
header: 'Header',
|
|
122
|
+
query: 'Query Parameters',
|
|
123
|
+
path: 'Path Parameters',
|
|
124
|
+
};
|
|
125
|
+
return (_jsxs(_Fragment, { children: [item.description && ctx.renderMarkdown(item.description), _jsxs("div", { className: "flex flex-row gap-2 items-center justify-between", children: [_jsx(MethodLabel, { children: requestData.method }), _jsx("code", { children: resolveRequestData(ctx.route, item.encoded) })] }), _jsx(Accordions, { type: "multiple", className: "mt-2", children: Object.entries(displayNames).map(([k, v]) => {
|
|
126
|
+
const data = requestData[k];
|
|
127
|
+
if (!data || Object.keys(data).length === 0)
|
|
128
|
+
return;
|
|
129
|
+
return (_jsxs(AccordionItem, { value: k, children: [_jsx(AccordionHeader, { children: _jsx(AccordionTrigger, { children: v }) }), _jsx(AccordionContent, { className: "prose-no-margin", children: ctx.renderCodeBlock('json', JSON.stringify(data, null, 2)) })] }, k));
|
|
130
|
+
}) })] }));
|
|
131
|
+
}
|
|
132
|
+
let children;
|
|
133
|
+
if (items.length > 1) {
|
|
134
|
+
children = (_jsxs(Tabs, { defaultValue: items[0].id, children: [_jsx(TabsList, { children: items.map((item) => (_jsx(TabsTrigger, { value: item.id, children: item.name }, item.id))) }), items.map((item) => (_jsx(TabsContent, { value: item.id, children: renderItem(item) }, item.id)))] }));
|
|
135
|
+
}
|
|
136
|
+
else if (items.length === 1) {
|
|
137
|
+
children = renderItem(items[0]);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
children = _jsx("p", { className: "text-fd-muted-foreground text-xs", children: "Empty" });
|
|
141
|
+
}
|
|
142
|
+
return (_jsxs("div", { className: "p-3 rounded-xl border prose-no-margin bg-fd-card text-fd-card-foreground shadow-md", children: [_jsx("p", { className: "font-semibold border-b pb-2", children: "Example Requests" }), children] }));
|
|
143
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { MethodInformation, RenderContext, ResponseObject } from '../../types.js';
|
|
2
|
+
import { type NoReference } from '../../utils/schema.js';
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
export interface ResponseTab {
|
|
5
|
+
/**
|
|
6
|
+
* HTTP response code
|
|
7
|
+
*/
|
|
8
|
+
code: string;
|
|
9
|
+
response: NoReference<ResponseObject>;
|
|
10
|
+
/**
|
|
11
|
+
* media type of response
|
|
12
|
+
*/
|
|
13
|
+
mediaType: string | null;
|
|
14
|
+
examples?: ResponseExample[];
|
|
15
|
+
}
|
|
16
|
+
interface ResponseExample {
|
|
17
|
+
/**
|
|
18
|
+
* generated/defined example data
|
|
19
|
+
*/
|
|
20
|
+
sample: unknown;
|
|
21
|
+
label: string;
|
|
22
|
+
/**
|
|
23
|
+
* description (in Markdown)
|
|
24
|
+
*/
|
|
25
|
+
description?: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function ResponseTabs({ operation, ctx, }: {
|
|
28
|
+
operation: NoReference<MethodInformation>;
|
|
29
|
+
ctx: RenderContext;
|
|
30
|
+
}): ReactNode | Promise<ReactNode>;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=response-tabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-tabs.d.ts","sourceRoot":"","sources":["../../../src/ui/operation/response-tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAChF,OAAO,EAAE,KAAK,WAAW,EAAoB,MAAM,gBAAgB,CAAC;AAUpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;IACtC;;OAEG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAC9B;AAED,UAAU,eAAe;IACvB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,GAAG,GACJ,EAAE;IACD,SAAS,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC;IAC1C,GAAG,EAAE,aAAa,CAAC;CACpB,kCAwCA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { getPreferredType } from '../../utils/schema.js';
|
|
3
|
+
import { Accordions, AccordionItem, AccordionHeader, AccordionTrigger, AccordionContent, } from '../../ui/components/accordion.js';
|
|
4
|
+
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
|
5
|
+
import { sample } from 'openapi-sampler';
|
|
6
|
+
export function ResponseTabs({ operation, ctx, }) {
|
|
7
|
+
if (!operation.responses)
|
|
8
|
+
return null;
|
|
9
|
+
const tabs = [];
|
|
10
|
+
for (const [code, response] of Object.entries(operation.responses)) {
|
|
11
|
+
const media = response.content ? getPreferredType(response.content) : null;
|
|
12
|
+
const responseOfType = media ? response.content?.[media] : null;
|
|
13
|
+
const tab = {
|
|
14
|
+
code,
|
|
15
|
+
response,
|
|
16
|
+
mediaType: media,
|
|
17
|
+
};
|
|
18
|
+
if (responseOfType?.examples) {
|
|
19
|
+
tab.examples ?? (tab.examples = []);
|
|
20
|
+
for (const [key, sample] of Object.entries(responseOfType.examples)) {
|
|
21
|
+
const title = sample?.summary ?? `Example ${key}`;
|
|
22
|
+
tab.examples.push({
|
|
23
|
+
label: title,
|
|
24
|
+
sample: sample.value,
|
|
25
|
+
description: sample?.description,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else if (responseOfType?.example || responseOfType?.schema) {
|
|
30
|
+
tab.examples ?? (tab.examples = []);
|
|
31
|
+
tab.examples.push({
|
|
32
|
+
label: 'Example',
|
|
33
|
+
sample: responseOfType.example ?? sample(responseOfType.schema),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
tabs.push(tab);
|
|
37
|
+
}
|
|
38
|
+
const { renderResponseTabs = renderResponseTabsDefault } = ctx.content ?? {};
|
|
39
|
+
return renderResponseTabs(tabs, ctx);
|
|
40
|
+
}
|
|
41
|
+
function renderResponseTabsDefault(tabs, ctx) {
|
|
42
|
+
function renderExampleContent(example) {
|
|
43
|
+
return (_jsxs(_Fragment, { children: [example.description && ctx.renderMarkdown(example.description), ctx.renderCodeBlock('json', JSON.stringify(example.sample, null, 2))] }));
|
|
44
|
+
}
|
|
45
|
+
async function renderResponse(tab) {
|
|
46
|
+
const { examples = [] } = tab;
|
|
47
|
+
let slot = 'Empty';
|
|
48
|
+
if (examples.length > 1) {
|
|
49
|
+
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 }) }), _jsx(AccordionContent, { className: "prose-no-margin", children: renderExampleContent(example) })] }, i))) }));
|
|
50
|
+
}
|
|
51
|
+
else if (examples.length === 1) {
|
|
52
|
+
slot = renderExampleContent(examples[0]);
|
|
53
|
+
}
|
|
54
|
+
return _jsx(Tab, { value: tab.code, children: slot });
|
|
55
|
+
}
|
|
56
|
+
if (tabs.length === 0)
|
|
57
|
+
return null;
|
|
58
|
+
return (_jsx(Tabs, { groupId: "fumadocs_openapi_responses", items: tabs.map((tab) => tab.code), children: tabs.map(renderResponse) }));
|
|
59
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import type { CodeUsageGenerator } from './index.js';
|
|
3
|
+
import type { ExampleRequestItem } from '../request-tabs.js';
|
|
4
|
+
import type { RawRequestData, RequestData } from '../../../requests/types.js';
|
|
5
|
+
export type ExampleUpdateListener = (data: RawRequestData, encoded: RequestData) => void;
|
|
6
|
+
export declare function UsageTabsProvider({ route, examples, defaultExampleId, children, }: {
|
|
7
|
+
route: string;
|
|
8
|
+
examples: ExampleRequestItem[];
|
|
9
|
+
defaultExampleId?: string;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export declare function useExampleRequests(): {
|
|
13
|
+
route: string;
|
|
14
|
+
examples: ExampleRequestItem[];
|
|
15
|
+
example: string | undefined;
|
|
16
|
+
setExample: (id: string) => void;
|
|
17
|
+
setExampleData: (data: RawRequestData, encoded: RequestData) => void;
|
|
18
|
+
addListener: (listener: ExampleUpdateListener) => void;
|
|
19
|
+
removeListener: (listener: ExampleUpdateListener) => void;
|
|
20
|
+
};
|
|
21
|
+
export declare function UsageTabsSelector(): import("react/jsx-runtime").JSX.Element | null;
|
|
22
|
+
export declare function UsageTab(sample: CodeUsageGenerator): import("react/jsx-runtime").JSX.Element | null;
|
|
23
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/ui/operation/usage-tabs/client.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAKL,SAAS,EAGV,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,GAAG,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpE,MAAM,MAAM,qBAAqB,GAAG,CAClC,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,WAAW,KACjB,IAAI,CAAC;AAaV,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAwDA;AAED,wBAAgB,kBAAkB;WA9EzB,MAAM;cACH,kBAAkB,EAAE;aACrB,MAAM,GAAG,SAAS;gBACf,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI;oBAChB,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,KAAK,IAAI;iBAEvD,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI;oBACtC,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI;EAyE1D;AAED,wBAAgB,iBAAiB,mDAkChC;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,kDAkDlD"}
|
|
@@ -1,13 +1,57 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useApiContext, useServerSelectContext } from '../../../ui/contexts/api.js';
|
|
4
|
-
import { useOperationContext, } from '../../../ui/contexts/operation.js';
|
|
5
4
|
import { joinURL, withBase, resolveServerUrl, resolveRequestData, } from '../../../utils/url.js';
|
|
6
5
|
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, } from '../../../ui/components/select.js';
|
|
7
6
|
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
|
|
8
|
-
import { useState, useEffect, useMemo } from 'react';
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
import { useState, useEffect, useMemo, createContext, useRef, use, } from 'react';
|
|
8
|
+
const Context = createContext(null);
|
|
9
|
+
export function UsageTabsProvider({ route, examples, defaultExampleId, children, }) {
|
|
10
|
+
const [example, setExample] = useState(() => defaultExampleId ?? examples.at(0)?.id);
|
|
11
|
+
const listeners = useRef([]);
|
|
12
|
+
return (_jsx(Context, { value: useMemo(() => ({
|
|
13
|
+
example,
|
|
14
|
+
route,
|
|
15
|
+
setExample: (newKey) => {
|
|
16
|
+
const example = examples.find((example) => example.id === newKey);
|
|
17
|
+
if (!example)
|
|
18
|
+
return;
|
|
19
|
+
setExample(newKey);
|
|
20
|
+
for (const listener of listeners.current) {
|
|
21
|
+
listener(example.data, example.encoded);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
examples,
|
|
25
|
+
setExampleData(data, encoded) {
|
|
26
|
+
for (const item of examples) {
|
|
27
|
+
if (item.id === example) {
|
|
28
|
+
// persistent changes
|
|
29
|
+
item.data = data;
|
|
30
|
+
item.encoded = encoded;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
for (const listener of listeners.current) {
|
|
35
|
+
listener(data, encoded);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
removeListener(listener) {
|
|
39
|
+
listeners.current = listeners.current.filter((item) => item !== listener);
|
|
40
|
+
},
|
|
41
|
+
addListener(listener) {
|
|
42
|
+
// initial call to listeners to ensure their data is the latest
|
|
43
|
+
// this is necessary to avoid race conditions between `useEffect()`
|
|
44
|
+
const active = examples.find((item) => item.id === example);
|
|
45
|
+
listener(active.data, active.encoded);
|
|
46
|
+
listeners.current.push(listener);
|
|
47
|
+
},
|
|
48
|
+
}), [example, route, examples]), children: children }));
|
|
49
|
+
}
|
|
50
|
+
export function useExampleRequests() {
|
|
51
|
+
return use(Context);
|
|
52
|
+
}
|
|
53
|
+
export function UsageTabsSelector() {
|
|
54
|
+
const { example: key, setExample: setKey, examples } = useExampleRequests();
|
|
11
55
|
const { APIExampleSelector: Override } = useApiContext().client.operation ?? {};
|
|
12
56
|
if (Override) {
|
|
13
57
|
return _jsx(Override, { items: examples, value: key, onValueChange: setKey });
|
|
@@ -20,9 +64,9 @@ export function APIExampleSelector() {
|
|
|
20
64
|
const selected = examples.find((item) => item.id === key);
|
|
21
65
|
return (_jsxs(Select, { value: key, onValueChange: setKey, children: [_jsx(SelectTrigger, { className: "not-prose mb-2", children: selected && _jsx(SelectValue, { asChild: true, children: renderItem(selected) }) }), _jsx(SelectContent, { children: examples.map((item) => (_jsx(SelectItem, { value: item.id, children: renderItem(item) }, item.id))) })] }));
|
|
22
66
|
}
|
|
23
|
-
export function
|
|
67
|
+
export function UsageTab(sample) {
|
|
24
68
|
const { shikiOptions, mediaAdapters } = useApiContext();
|
|
25
|
-
const { examples, example: selectedExampleId, route, addListener, removeListener, } =
|
|
69
|
+
const { examples, example: selectedExampleId, route, addListener, removeListener, } = useExampleRequests();
|
|
26
70
|
const { server } = useServerSelectContext();
|
|
27
71
|
const [data, setData] = useState(() => examples.find((example) => example.id === selectedExampleId)?.encoded);
|
|
28
72
|
useEffect(() => {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { MethodInformation, RenderContext } from '../../../types.js';
|
|
2
|
+
import type { SampleGenerator } from '../../../requests/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Generate code example for given programming language
|
|
5
|
+
*/
|
|
6
|
+
export interface CodeUsageGenerator<T = unknown> {
|
|
7
|
+
id: string;
|
|
8
|
+
lang: string;
|
|
9
|
+
label?: string;
|
|
10
|
+
/**
|
|
11
|
+
* either:
|
|
12
|
+
* - code
|
|
13
|
+
* - a function imported from a file with "use client" directive
|
|
14
|
+
* - false (disabled)
|
|
15
|
+
*/
|
|
16
|
+
source?: string | SampleGenerator<T> | false;
|
|
17
|
+
/**
|
|
18
|
+
* Pass extra context to client-side source generator
|
|
19
|
+
*/
|
|
20
|
+
serverContext?: T;
|
|
21
|
+
}
|
|
22
|
+
export declare function UsageTabs({ method, ctx, }: {
|
|
23
|
+
method: MethodInformation;
|
|
24
|
+
ctx: RenderContext;
|
|
25
|
+
}): Promise<import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | (string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined)>;
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ui/operation/usage-tabs/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAWxD;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,OAAO;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IAE7C;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,CAAC;CACnB;AAED,wBAAsB,SAAS,CAAC,EAC9B,MAAM,EACN,GAAG,GACJ,EAAE;IACD,MAAM,EAAE,iBAAiB,CAAC;IAC1B,GAAG,EAAE,aAAa,CAAC;CACpB,wWAmEA"}
|