fumadocs-openapi 7.0.0-beta.0 → 7.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/playground/client.d.ts +7 -8
- package/dist/playground/client.d.ts.map +1 -1
- package/dist/playground/client.js +32 -34
- package/dist/playground/fetcher.d.ts.map +1 -1
- package/dist/playground/fetcher.js +23 -4
- package/dist/playground/index.d.ts +3 -1
- package/dist/playground/index.d.ts.map +1 -1
- package/dist/playground/index.js +6 -10
- package/dist/playground/inputs.d.ts +1 -1
- package/dist/playground/inputs.d.ts.map +1 -1
- package/dist/playground/inputs.js +3 -3
- package/dist/scalar/client.js +1 -1
- package/dist/ui/components/input.js +2 -2
- package/dist/ui/components/select.js +1 -1
- package/dist/ui/server-select.js +1 -1
- package/dist/utils/generate-document.js +1 -1
- package/package.json +12 -12
|
@@ -29,19 +29,18 @@ export type ClientProps = HTMLAttributes<HTMLFormElement> & {
|
|
|
29
29
|
route: string;
|
|
30
30
|
method: string;
|
|
31
31
|
authorization?: Security;
|
|
32
|
-
|
|
33
|
-
query?: PrimitiveRequestField[];
|
|
34
|
-
header?: PrimitiveRequestField[];
|
|
32
|
+
parameters?: PrimitiveRequestField[];
|
|
35
33
|
body?: RequestSchema & {
|
|
36
34
|
mediaType: string;
|
|
37
35
|
};
|
|
38
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Resolver for reference schemas you've passed
|
|
38
|
+
*/
|
|
39
|
+
references: Record<string, RequestSchema>;
|
|
39
40
|
proxyUrl?: string;
|
|
40
41
|
fields?: {
|
|
42
|
+
parameter?: CustomField<`${PrimitiveRequestField['in']}.${string}`, PrimitiveRequestField>;
|
|
41
43
|
auth?: CustomField<'authorization', RequestSchema>;
|
|
42
|
-
path?: CustomField<`path.${string}`, PrimitiveRequestField>;
|
|
43
|
-
query?: CustomField<`query.${string}`, PrimitiveRequestField>;
|
|
44
|
-
header?: CustomField<`header.${string}`, PrimitiveRequestField>;
|
|
45
44
|
body?: CustomField<'body', RequestSchema>;
|
|
46
45
|
};
|
|
47
46
|
components?: Partial<{
|
|
@@ -62,6 +61,6 @@ export type DynamicField = {
|
|
|
62
61
|
schema: RequestSchema | ReferenceSchema;
|
|
63
62
|
};
|
|
64
63
|
export declare function useSchemaContext(): SchemaContextType;
|
|
65
|
-
export declare function Client({ route, method, authorization,
|
|
64
|
+
export declare function Client({ route, method, authorization, parameters, body, fields, references, proxyUrl, components: { ResultDisplay }, ...props }: ClientProps): import("react/jsx-runtime").JSX.Element;
|
|
66
65
|
export {};
|
|
67
66
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/playground/client.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,cAAc,EAInB,KAAK,EAAE,EAGP,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/playground/client.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx,
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useMemo, useRef, useEffect, Fragment, createContext, useContext, useState, } from 'react';
|
|
4
|
-
import { Controller, FormProvider, useForm } from 'react-hook-form';
|
|
4
|
+
import { Controller, FormProvider, useForm, useFormContext, } from 'react-hook-form';
|
|
5
5
|
import { cn, buttonVariants } from 'fumadocs-ui/components/api';
|
|
6
6
|
import { useApiContext, useServerSelectContext } from '../ui/contexts/api.js';
|
|
7
7
|
import { FieldSet, ObjectInput } from './inputs.js';
|
|
@@ -34,9 +34,17 @@ function toRequestData(method, mediaType, value) {
|
|
|
34
34
|
query: value.query,
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
-
export function Client({ route, method = 'GET', authorization,
|
|
37
|
+
export function Client({ route, method = 'GET', authorization, parameters = [], body, fields = {}, references, proxyUrl, components: { ResultDisplay = DefaultResultDisplay } = {}, ...props }) {
|
|
38
38
|
const { servers } = useApiContext();
|
|
39
39
|
const { server, setServer, setServerVariables } = useServerSelectContext();
|
|
40
|
+
const params = useMemo(() => {
|
|
41
|
+
return {
|
|
42
|
+
headers: parameters.filter((v) => v.in === 'header'),
|
|
43
|
+
cookies: parameters.filter((v) => v.in === 'cookie'),
|
|
44
|
+
queries: parameters.filter((v) => v.in === 'query'),
|
|
45
|
+
paths: parameters.filter((v) => v.in === 'path'),
|
|
46
|
+
};
|
|
47
|
+
}, [parameters]);
|
|
40
48
|
const dynamicRef = useRef(new Map());
|
|
41
49
|
const requestData = useRequestData();
|
|
42
50
|
const authInfo = usePersistentAuthInfo(authorization);
|
|
@@ -70,7 +78,7 @@ export function Client({ route, method = 'GET', authorization, path = [], header
|
|
|
70
78
|
const value = _value;
|
|
71
79
|
if (authorization && value.authorization) {
|
|
72
80
|
authInfo.saveInfo(value.authorization);
|
|
73
|
-
writeAuthHeader(authorization, value.authorization, value.header, value.query);
|
|
81
|
+
writeAuthHeader(authorization, value.authorization, value.header, value.query, value.cookie);
|
|
74
82
|
}
|
|
75
83
|
requestData.saveData(toRequestData(method, body?.mediaType, value));
|
|
76
84
|
});
|
|
@@ -88,11 +96,19 @@ export function Client({ route, method = 'GET', authorization, path = [], header
|
|
|
88
96
|
}
|
|
89
97
|
return (_jsx(FieldSet, { name: info.name, fieldName: fieldName, field: info }, key));
|
|
90
98
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
99
|
+
return (_jsx(FormProvider, { ...form, children: _jsx(SchemaContext.Provider, { value: useMemo(() => ({ references: references, dynamic: dynamicRef }), [references]), children: _jsx(AuthProvider, { authorization: authorization, children: _jsxs("form", { ...props, className: cn('not-prose flex flex-col rounded-xl border p-3 gap-3 shadow-md overflow-hidden', props.className), onSubmit: onSubmit, children: [_jsx(FormHeader, { method: method, route: route, isLoading: testQuery.isLoading }), servers.length > 1 ? (_jsx(CollapsiblePanel, { title: "Server URL", children: _jsx(ServerSelect, { server: server, onServerChanged: setServer, onVariablesChanged: setServerVariables }) })) : null, params.headers.length > 0 || authorization ? (_jsxs(CollapsiblePanel, { title: "Headers", children: [authorization ? (_jsx(AuthField, { authorization: authorization })) : null, params.headers.map((field) => renderCustomField(`header.${field.name}`, field, fields.parameter, field.name))] })) : null, params.paths.length > 0 ? (_jsx(CollapsiblePanel, { title: "Path", children: params.paths.map((field) => renderCustomField(`path.${field.name}`, field, fields.parameter, field.name)) })) : null, params.queries.length > 0 ? (_jsx(CollapsiblePanel, { title: "Query", children: params.queries.map((field) => renderCustomField(`query.${field.name}`, field, fields.parameter, field.name)) })) : null, params.cookies.length > 0 ? (_jsx(CollapsiblePanel, { title: "Cookies", children: params.cookies.map((field) => renderCustomField(`cookie.${field.name}`, field, fields.parameter, field.name)) })) : null, body ? (_jsx(CollapsiblePanel, { title: "Body", children: body.type === 'object' && !fields.body ? (_jsx(ObjectInput, { field: body, fieldName: "body" })) : (renderCustomField('body', body, fields.body)) })) : null, testQuery.data ? _jsx(ResultDisplay, { data: testQuery.data }) : null] }) }) }) }));
|
|
100
|
+
}
|
|
101
|
+
function AuthProvider({ authorization, children, }) {
|
|
102
|
+
const form = useFormContext();
|
|
103
|
+
if (!authorization || authorization.type !== 'oauth2')
|
|
104
|
+
return children;
|
|
105
|
+
// only the first one, so it looks simpler :)
|
|
106
|
+
const flow = Object.keys(authorization.flows)[0];
|
|
107
|
+
return (_jsx(OauthDialog, { flow: flow, scheme: authorization, setToken: (token) => form.setValue('authorization', `Bearer ${token}`), children: children }));
|
|
108
|
+
}
|
|
109
|
+
function AuthField({ authorization }) {
|
|
110
|
+
return (_jsxs(_Fragment, { children: [_jsx(FieldSet, { fieldName: "authorization", name: "Authorization", field: authorization?.type === 'http' && authorization.scheme === 'basic'
|
|
94
111
|
? {
|
|
95
|
-
name: 'Authorization',
|
|
96
112
|
type: 'object',
|
|
97
113
|
isRequired: true,
|
|
98
114
|
properties: {
|
|
@@ -107,28 +123,19 @@ export function Client({ route, method = 'GET', authorization, path = [], header
|
|
|
107
123
|
},
|
|
108
124
|
}
|
|
109
125
|
: {
|
|
110
|
-
name: 'Authorization',
|
|
111
126
|
type: 'string',
|
|
112
127
|
isRequired: true,
|
|
113
128
|
description: 'The Authorization access token',
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
let children = (_jsxs("form", { ...props, className: cn('not-prose flex flex-col gap-2 rounded-xl border p-3 shadow-md', props.className), onSubmit: onSubmit, children: [_jsx(FormHeader, { method: method, route: route, isLoading: testQuery.isLoading }), servers.length > 1 ? (_jsx(CollapsiblePanel, { title: "Server URL", children: _jsx(ServerSelect, { server: server, onServerChanged: setServer, onVariablesChanged: setServerVariables }) })) : null, header.length > 0 || authorization ? (_jsxs(CollapsiblePanel, { title: "Headers", children: [authField, header.map((field) => renderCustomField(`header.${field.name}`, field, fields.header, field.name))] })) : null, path.length > 0 ? (_jsx(CollapsiblePanel, { title: "Path", children: path.map((field) => renderCustomField(`path.${field.name}`, field, fields.path, field.name)) })) : null, query.length > 0 ? (_jsx(CollapsiblePanel, { title: "Query", children: query.map((field) => renderCustomField(`query.${field.name}`, field, fields.query, field.name)) })) : null, body ? (_jsx(CollapsiblePanel, { title: "Body", children: body.type === 'object' && !fields.body ? (_jsx(ObjectInput, { field: body, fieldName: "body" })) : (renderCustomField('body', body, fields.body)) })) : null, testQuery.data ? _jsx(ResultDisplay, { data: testQuery.data }) : null] }));
|
|
119
|
-
if (authorization?.type === 'oauth2') {
|
|
120
|
-
// only the first one, so it looks simpler :)
|
|
121
|
-
const flow = Object.keys(authorization.flows)[0];
|
|
122
|
-
children = (_jsx(OauthDialog, { flow: flow, scheme: authorization, setToken: (token) => form.setValue('authorization', `Bearer ${token}`), children: children }));
|
|
123
|
-
}
|
|
124
|
-
return (_jsx(FormProvider, { ...form, children: _jsx(SchemaContext.Provider, { value: useMemo(() => ({ references: schemas, dynamic: dynamicRef }), [schemas]), children: children }) }));
|
|
129
|
+
} }), authorization?.type === 'oauth2' && (_jsx(OauthDialogTrigger, { type: "button", className: cn(buttonVariants({
|
|
130
|
+
color: 'secondary',
|
|
131
|
+
})), children: "Open" }))] }));
|
|
125
132
|
}
|
|
126
133
|
function Route({ route, ...props }) {
|
|
127
134
|
const segments = route.split('/').filter((part) => part.length > 0);
|
|
128
135
|
return (_jsx("div", { ...props, className: cn('flex flex-row items-center gap-0.5 overflow-auto text-nowrap', props.className), children: segments.map((part, index) => (_jsxs(Fragment, { children: [_jsx("span", { className: "text-fd-muted-foreground", children: "/" }), part.startsWith('{') && part.endsWith('}') ? (_jsx("code", { className: "bg-fd-primary/10 text-fd-primary", children: part })) : (_jsx("code", { className: "text-fd-foreground", children: part }))] }, index))) }));
|
|
129
136
|
}
|
|
130
|
-
function FormHeader({ route, method, isLoading, }) {
|
|
131
|
-
return (_jsxs("div", { className:
|
|
137
|
+
function FormHeader({ route, method, isLoading, ...props }) {
|
|
138
|
+
return (_jsxs("div", { ...props, className: cn('flex flex-row items-center gap-2 text-sm', props.className), children: [_jsx(MethodLabel, { children: method }), _jsx(Route, { route: route, className: "flex-1" }), _jsx("button", { type: "submit", className: cn(buttonVariants({ color: 'primary', size: 'sm' }), 'px-3 py-1.5'), disabled: isLoading, children: "Send" })] }));
|
|
132
139
|
}
|
|
133
140
|
function DefaultResultDisplay({ data }) {
|
|
134
141
|
const statusInfo = useMemo(() => getStatusInfo(data.status), [data.status]);
|
|
@@ -172,9 +179,9 @@ function usePersistentAuthInfo(authorization) {
|
|
|
172
179
|
};
|
|
173
180
|
}
|
|
174
181
|
function CollapsiblePanel({ title, children, ...props }) {
|
|
175
|
-
return (_jsxs(Collapsible, { ...props, className: "
|
|
182
|
+
return (_jsxs(Collapsible, { ...props, className: "rounded-xl bg-fd-card border text-fd-card-foreground", children: [_jsxs(CollapsibleTrigger, { className: "group w-full inline-flex items-center gap-2 p-3 text-sm font-medium", children: [title, _jsx(ChevronDown, { className: "ms-auto size-4 text-fd-muted-foreground group-data-[state=open]:rotate-180" })] }), _jsx(CollapsibleContent, { children: _jsx("div", { className: "flex flex-col gap-3 p-3", children: children }) })] }));
|
|
176
183
|
}
|
|
177
|
-
function writeAuthHeader(authorization, input, header, query) {
|
|
184
|
+
function writeAuthHeader(authorization, input, header, query, cookie) {
|
|
178
185
|
if (authorization.type === 'apiKey') {
|
|
179
186
|
if (authorization.in === 'header') {
|
|
180
187
|
header[authorization.name] = input;
|
|
@@ -183,16 +190,7 @@ function writeAuthHeader(authorization, input, header, query) {
|
|
|
183
190
|
query[authorization.name] = input;
|
|
184
191
|
}
|
|
185
192
|
if (authorization.in === 'cookie') {
|
|
186
|
-
|
|
187
|
-
header.Cookie = header.cookie;
|
|
188
|
-
delete header.cookie;
|
|
189
|
-
}
|
|
190
|
-
header.Cookie = [
|
|
191
|
-
header.Cookie,
|
|
192
|
-
`${authorization.name}=${input}`,
|
|
193
|
-
]
|
|
194
|
-
.filter((s) => s.length > 0)
|
|
195
|
-
.join('; ');
|
|
193
|
+
cookie[authorization.name] = input;
|
|
196
194
|
}
|
|
197
195
|
return;
|
|
198
196
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../../src/playground/fetcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACvE;AAED,wBAAgB,oBAAoB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../../src/playground/fetcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACvE;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAkF9C;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC,eAAe,CAAC,EACjD,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,CAqC5B"}
|
|
@@ -12,11 +12,30 @@ export function createBrowserFetcher() {
|
|
|
12
12
|
if (paramValue.length > 0)
|
|
13
13
|
headers.append(key, paramValue.toString());
|
|
14
14
|
}
|
|
15
|
+
const proxyUrl = options.proxyUrl
|
|
16
|
+
? new URL(options.proxyUrl, window.location.origin)
|
|
17
|
+
: null;
|
|
18
|
+
if (typeof document !== 'undefined') {
|
|
19
|
+
for (const key in options.cookie) {
|
|
20
|
+
const value = options.cookie[key];
|
|
21
|
+
if (!value)
|
|
22
|
+
continue;
|
|
23
|
+
document.cookie = [
|
|
24
|
+
`${key}=${value}`,
|
|
25
|
+
'HttpOnly',
|
|
26
|
+
proxyUrl && proxyUrl.origin !== window.location.origin
|
|
27
|
+
? `domain=${proxyUrl.host}`
|
|
28
|
+
: false,
|
|
29
|
+
'path=/',
|
|
30
|
+
]
|
|
31
|
+
.filter(Boolean)
|
|
32
|
+
.join(';');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
15
35
|
let url = getPathnameFromInput(route, options.path, options.query);
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
url = updated.toString();
|
|
36
|
+
if (proxyUrl) {
|
|
37
|
+
proxyUrl.searchParams.append('url', url);
|
|
38
|
+
url = proxyUrl.toString();
|
|
20
39
|
}
|
|
21
40
|
return fetch(url, {
|
|
22
41
|
method: options.method,
|
|
@@ -8,7 +8,9 @@ interface BaseSchema {
|
|
|
8
8
|
description?: string;
|
|
9
9
|
isRequired: boolean;
|
|
10
10
|
}
|
|
11
|
-
export type PrimitiveRequestField = BaseRequestField & PrimitiveSchema
|
|
11
|
+
export type PrimitiveRequestField = BaseRequestField & PrimitiveSchema & {
|
|
12
|
+
in: 'cookie' | 'header' | 'query' | 'path';
|
|
13
|
+
};
|
|
12
14
|
interface PrimitiveSchema extends BaseSchema {
|
|
13
15
|
type: 'boolean' | 'string' | 'number';
|
|
14
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/playground/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAEjB,aAAa,EACd,MAAM,SAAS,CAAC;AAOjB,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,UAAU;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/playground/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAEjB,aAAa,EACd,MAAM,SAAS,CAAC;AAOjB,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,UAAU;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,GAClD,eAAe,GAAG;IAChB,EAAE,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;CAC5C,CAAC;AAEJ,UAAU,eAAgB,SAAQ,UAAU;IAC1C,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACvC;AAED,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,IAAI,EAAE,KAAK,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,WAAY,SAAQ,UAAU;IACtC,IAAI,EAAE,OAAO,CAAC;IACd;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;CAC/B;AAED,UAAU,UAAW,SAAQ,UAAU;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,YAAa,SAAQ,UAAU;IACvC,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,eAAe,CAAC,CAAC;IAE5D;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CACzC;AAED,UAAU,cAAe,SAAQ,UAAU;IACzC,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,aAAa,CAAC,CAAC;CACxD;AAED,UAAU,UAAW,SAAQ,UAAU;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,aAAa,GACrB,eAAe,GACf,WAAW,GACX,YAAY,GACZ,cAAc,GACd,UAAU,GACV,UAAU,CAAC;AAUf,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,GAAG,EAAE,aAAa,CAAC;IAEnB,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC/B;AAED,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEzD,wBAAsB,aAAa,CAAC,EAClC,IAAI,EACJ,MAAM,EACN,GAAG,EACH,MAAM,GACP,EAAE,kBAAkB,oDAuCpB"}
|
package/dist/playground/index.js
CHANGED
|
@@ -22,22 +22,14 @@ export async function APIPlayground({ path, method, ctx, client, }) {
|
|
|
22
22
|
authorization: getAuthorizationField(method, ctx),
|
|
23
23
|
method: method.method,
|
|
24
24
|
route: path,
|
|
25
|
-
|
|
26
|
-
?.filter((v) => v.in === 'path')
|
|
27
|
-
.map((v) => parameterToField(v, context)),
|
|
28
|
-
query: method.parameters
|
|
29
|
-
?.filter((v) => v.in === 'query')
|
|
30
|
-
.map((v) => parameterToField(v, context)),
|
|
31
|
-
header: method.parameters
|
|
32
|
-
?.filter((v) => v.in === 'header')
|
|
33
|
-
.map((v) => parameterToField(v, context)),
|
|
25
|
+
parameters: method.parameters?.map((v) => parameterToField(v, context)),
|
|
34
26
|
body: bodySchema && mediaType
|
|
35
27
|
? {
|
|
36
28
|
...bodySchema,
|
|
37
29
|
mediaType: mediaType,
|
|
38
30
|
}
|
|
39
31
|
: undefined,
|
|
40
|
-
|
|
32
|
+
references: context.references,
|
|
41
33
|
proxyUrl: ctx.proxyUrl,
|
|
42
34
|
...client,
|
|
43
35
|
};
|
|
@@ -73,8 +65,12 @@ function getIdFromSchema(schema, required, ctx) {
|
|
|
73
65
|
return registered;
|
|
74
66
|
}
|
|
75
67
|
function parameterToField(v, ctx) {
|
|
68
|
+
const allowed = ['header', 'cookie', 'query', 'path'];
|
|
69
|
+
if (!allowed.includes(v.in))
|
|
70
|
+
throw new Error(`Unsupported parameter in: "${v.in}"`);
|
|
76
71
|
return {
|
|
77
72
|
name: v.name,
|
|
73
|
+
in: v.in,
|
|
78
74
|
...toSchema(v.schema ?? { type: 'string' }, v.required ?? false, ctx),
|
|
79
75
|
};
|
|
80
76
|
}
|
|
@@ -14,7 +14,7 @@ export declare function FieldInput({ field, fieldName, ...props }: HTMLAttribute
|
|
|
14
14
|
fieldName: string;
|
|
15
15
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
16
16
|
export declare function FieldSet({ field, fieldName, toolbar, name, ...props }: HTMLAttributes<HTMLElement> & {
|
|
17
|
-
name?:
|
|
17
|
+
name?: ReactNode;
|
|
18
18
|
field: RequestSchema;
|
|
19
19
|
fieldName: string;
|
|
20
20
|
toolbar?: ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputs.d.ts","sourceRoot":"","sources":["../../src/playground/inputs.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAWf,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMxD,KAAK,WAAW,CAAC,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC;AA6BhE,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACT,EAAE;IACD,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,cAAc,CAAC,cAAc,CAAC,2CAqBjC;AA+ID,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,WAAW,CAAC,GAAG;IAC/B,KAAK,EAAE,OAAO,CAAC,aAAa,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IACpD,SAAS,EAAE,MAAM,CAAC;CACnB,kDAmGA;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,SAAS,EACT,OAAO,EACP,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,WAAW,CAAC,GAAG;IAC/B,IAAI,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"inputs.d.ts","sourceRoot":"","sources":["../../src/playground/inputs.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAWf,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMxD,KAAK,WAAW,CAAC,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC;AA6BhE,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACT,EAAE;IACD,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,cAAc,CAAC,cAAc,CAAC,2CAqBjC;AA+ID,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,WAAW,CAAC,GAAG;IAC/B,KAAK,EAAE,OAAO,CAAC,aAAa,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IACpD,SAAS,EAAE,MAAM,CAAC;CACnB,kDAmGA;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,SAAS,EACT,OAAO,EACP,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,WAAW,CAAC,GAAG;IAC/B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB,kDAgGA"}
|
|
@@ -102,10 +102,10 @@ export function FieldInput({ field, fieldName, ...props }) {
|
|
|
102
102
|
if (field.type === 'null')
|
|
103
103
|
return null;
|
|
104
104
|
if (field.type === 'object') {
|
|
105
|
-
return (_jsx(ObjectInput, { field: field, fieldName: fieldName, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-
|
|
105
|
+
return (_jsx(ObjectInput, { field: field, fieldName: fieldName, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-3 shadow-sm', props.className) }));
|
|
106
106
|
}
|
|
107
107
|
if (field.type === 'array') {
|
|
108
|
-
return (_jsx(ArrayInput, { fieldName: fieldName, field: field, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background p-3 shadow-sm', props.className) }));
|
|
108
|
+
return (_jsx(ArrayInput, { fieldName: fieldName, field: field, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-3 shadow-sm', props.className) }));
|
|
109
109
|
}
|
|
110
110
|
if (field.type === 'file') {
|
|
111
111
|
return (_jsx(Controller, { control: control, name: fieldName, render: ({ field: { value: _, onChange, ...restField } }) => (_jsx("input", { id: fieldName, type: "file", multiple: false, onChange: (e) => {
|
|
@@ -172,7 +172,7 @@ function ArrayInput({ fieldName, field, ...props }) {
|
|
|
172
172
|
const { fields, append, remove } = useFieldArray({
|
|
173
173
|
name: fieldName,
|
|
174
174
|
});
|
|
175
|
-
return (_jsxs("div", { ...props, className: cn('flex flex-col gap-2', props.className), children: [fields.map((item, index) => (_jsx(FieldSet, { name:
|
|
175
|
+
return (_jsxs("div", { ...props, className: cn('flex flex-col gap-2', props.className), children: [fields.map((item, index) => (_jsx(FieldSet, { name: _jsxs("span", { className: "text-fd-muted-foreground", children: [fieldName.split('.').at(-1), "[", index, "]"] }), field: items, fieldName: `${fieldName}.${index}`, toolbar: _jsx("button", { type: "button", "aria-label": "Remove Item", className: cn(buttonVariants({
|
|
176
176
|
color: 'secondary',
|
|
177
177
|
size: 'sm',
|
|
178
178
|
})), onClick: () => {
|
package/dist/scalar/client.js
CHANGED
|
@@ -13,7 +13,7 @@ export default function ScalarPlayground({ path, method, spec, }) {
|
|
|
13
13
|
setMounted(true);
|
|
14
14
|
}, []);
|
|
15
15
|
return (_jsxs("div", { className: cn('flex flex-row items-center gap-2.5 p-3 rounded-xl border bg-fd-card text-fd-card-foreground not-prose', mounted ? `${resolvedTheme}-mode` : null), children: [_jsx(MethodLabel, { className: "text-xs", children: method }), _jsx("code", { className: "flex-1 overflow-auto text-nowrap text-[13px] text-fd-muted-foreground", children: path }), _jsx(ApiClientModalProvider, { configuration: {
|
|
16
|
-
|
|
16
|
+
theme: 'moon',
|
|
17
17
|
spec: {
|
|
18
18
|
content: spec,
|
|
19
19
|
},
|
|
@@ -2,9 +2,9 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { cn } from 'fumadocs-ui/components/api';
|
|
4
4
|
import { cva } from 'class-variance-authority';
|
|
5
|
-
export const labelVariants = cva('text-[13px]
|
|
5
|
+
export const labelVariants = cva('text-[13px] text-fd-card-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70');
|
|
6
6
|
const Input = React.forwardRef(({ className, type, ...props }, ref) => {
|
|
7
|
-
return (_jsx("input", { type: type, className: cn('flex h-9 w-full rounded-md border bg-
|
|
7
|
+
return (_jsx("input", { type: type, className: cn('flex h-9 w-full rounded-md border bg-fd-secondary px-2 py-1.5 text-[13px] text-fd-secondary-foreground transition-colors placeholder:text-fd-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-fd-ring disabled:cursor-not-allowed disabled:opacity-50', className), ref: ref, ...props }));
|
|
8
8
|
});
|
|
9
9
|
Input.displayName = 'Input';
|
|
10
10
|
export { Input };
|
|
@@ -6,7 +6,7 @@ import { cn } from 'fumadocs-ui/components/api';
|
|
|
6
6
|
const Select = SelectPrimitive.Root;
|
|
7
7
|
const SelectGroup = SelectPrimitive.Group;
|
|
8
8
|
const SelectValue = SelectPrimitive.Value;
|
|
9
|
-
const SelectTrigger = forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn('flex min-h-10 items-center w-full rounded-md border px-3 py-2 text-start text-[13px] text-fd-foreground hover:bg-fd-accent focus:outline-none focus:ring
|
|
9
|
+
const SelectTrigger = forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn('flex min-h-10 items-center w-full rounded-md border px-3 py-2 text-start text-[13px] text-fd-secondary-foreground bg-fd-secondary hover:bg-fd-accent focus:outline-none focus:ring focus:ring-fd-ring disabled:cursor-not-allowed disabled:opacity-50', className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(ChevronDown, { className: "ms-auto size-4 text-fd-muted-foreground" }) })] })));
|
|
10
10
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
11
11
|
const SelectScrollUpButton = forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.ScrollUpButton, { ref: ref, className: cn('flex items-center justify-center py-1', className), ...props, children: _jsx(ChevronUp, { className: "size-4" }) })));
|
|
12
12
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
package/dist/ui/server-select.js
CHANGED
|
@@ -11,7 +11,7 @@ export default function ServerSelect({ server, onServerChanged, onVariablesChang
|
|
|
11
11
|
const schema = server
|
|
12
12
|
? servers.find((item) => item.url === server.url)
|
|
13
13
|
: null;
|
|
14
|
-
return (_jsxs("div", { ...props, className: cn('flex flex-col gap-4', props.className), children: [_jsxs(Select, { value: server?.url, onValueChange: onServerChanged, children: [_jsx(SelectTrigger, { className: "
|
|
14
|
+
return (_jsxs("div", { ...props, className: cn('flex flex-col gap-4', props.className), children: [_jsxs(Select, { value: server?.url, onValueChange: onServerChanged, children: [_jsx(SelectTrigger, { className: "break-all", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: servers.map((item) => (_jsxs(SelectItem, { value: item.url, children: [item.url, _jsx("p", { className: "text-start text-fd-muted-foreground", children: item.description })] }, item.url))) })] }), Object.entries(schema?.variables ?? {}).map(([key, variable]) => {
|
|
15
15
|
if (!server)
|
|
16
16
|
return;
|
|
17
17
|
const id = `fd_server_select_${key}`;
|
|
@@ -28,7 +28,7 @@ export function generateDocument(options) {
|
|
|
28
28
|
if (banner.length > 0)
|
|
29
29
|
out.push(`---\n${banner}\n---`);
|
|
30
30
|
if (addGeneratedComment !== false) {
|
|
31
|
-
let commentContent = 'This file was generated by Fumadocs
|
|
31
|
+
let commentContent = 'This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again.';
|
|
32
32
|
if (typeof addGeneratedComment === 'string') {
|
|
33
33
|
commentContent = addGeneratedComment;
|
|
34
34
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fumadocs-openapi",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.1",
|
|
4
4
|
"description": "Generate MDX docs for your OpenAPI spec",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NextJs",
|
|
@@ -47,33 +47,33 @@
|
|
|
47
47
|
"@radix-ui/react-dialog": "^1.1.6",
|
|
48
48
|
"@radix-ui/react-select": "^2.1.6",
|
|
49
49
|
"@radix-ui/react-slot": "^1.1.2",
|
|
50
|
-
"@scalar/openapi-parser": "0.10.
|
|
50
|
+
"@scalar/openapi-parser": "0.10.10",
|
|
51
51
|
"ajv-draft-04": "^1.0.0",
|
|
52
52
|
"class-variance-authority": "^0.7.1",
|
|
53
53
|
"fast-glob": "^3.3.3",
|
|
54
54
|
"github-slugger": "^2.0.0",
|
|
55
|
-
"hast-util-to-jsx-runtime": "^2.3.
|
|
55
|
+
"hast-util-to-jsx-runtime": "^2.3.6",
|
|
56
56
|
"js-yaml": "^4.1.0",
|
|
57
|
-
"lucide-react": "^0.
|
|
58
|
-
"next-themes": "^0.4.
|
|
57
|
+
"lucide-react": "^0.479.0",
|
|
58
|
+
"next-themes": "^0.4.6",
|
|
59
59
|
"openapi-sampler": "^1.6.1",
|
|
60
60
|
"react-hook-form": "^7.54.2",
|
|
61
61
|
"remark": "^15.0.1",
|
|
62
62
|
"remark-rehype": "^11.1.1",
|
|
63
|
-
"shiki": "^3.1
|
|
63
|
+
"shiki": "^3.2.1",
|
|
64
64
|
"xml-js": "^1.6.11",
|
|
65
|
-
"fumadocs-
|
|
66
|
-
"fumadocs-
|
|
65
|
+
"fumadocs-core": "15.0.17",
|
|
66
|
+
"fumadocs-ui": "15.0.17"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@scalar/api-client-react": "^1.1
|
|
69
|
+
"@scalar/api-client-react": "^1.2.1",
|
|
70
70
|
"@types/js-yaml": "^4.0.9",
|
|
71
|
-
"@types/node": "22.13.
|
|
71
|
+
"@types/node": "22.13.10",
|
|
72
72
|
"@types/openapi-sampler": "^1.0.3",
|
|
73
73
|
"@types/react": "^19.0.10",
|
|
74
|
-
"next": "15.2.
|
|
74
|
+
"next": "15.2.2",
|
|
75
75
|
"openapi-types": "^12.1.3",
|
|
76
|
-
"tailwindcss": "^4.0.
|
|
76
|
+
"tailwindcss": "^4.0.14",
|
|
77
77
|
"tsc-alias": "^1.8.11",
|
|
78
78
|
"eslint-config-custom": "0.0.0",
|
|
79
79
|
"tsconfig": "0.0.0"
|