fumadocs-openapi 5.0.1 → 5.0.3
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/index.js
CHANGED
|
@@ -202,16 +202,19 @@ function pageContent(doc, props) {
|
|
|
202
202
|
heading: structuredData.headings.at(-1)?.id
|
|
203
203
|
});
|
|
204
204
|
}
|
|
205
|
+
// modify toc and structured data if possible
|
|
206
|
+
// it may not be compatible with other content sources except Fumadocs MDX
|
|
207
|
+
// TODO: Maybe add to frontmatter and let developers to handle them?
|
|
205
208
|
return `<APIPage operations={${JSON.stringify(props.operations)}} hasHead={${JSON.stringify(props.hasHead)}} />
|
|
206
209
|
|
|
207
210
|
export function startup() {
|
|
208
|
-
if (toc) {
|
|
211
|
+
if (typeof toc !== 'undefined') {
|
|
209
212
|
// toc might be immutable
|
|
210
213
|
while (toc.length > 0) toc.pop()
|
|
211
214
|
toc.push(...${JSON.stringify(toc)})
|
|
212
215
|
}
|
|
213
216
|
|
|
214
|
-
if (structuredData) {
|
|
217
|
+
if (typeof structuredData !== 'undefined') {
|
|
215
218
|
structuredData.headings = ${JSON.stringify(structuredData.headings)}
|
|
216
219
|
structuredData.contents = ${JSON.stringify(structuredData.contents)}
|
|
217
220
|
}
|
package/dist/server/index.js
CHANGED
|
@@ -28,7 +28,28 @@ function getPreferredType(body) {
|
|
|
28
28
|
return typeof value === 'string' ? value : JSON.stringify(value, null, 2);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function
|
|
31
|
+
function getSecurities(requirement, document) {
|
|
32
|
+
const results = [];
|
|
33
|
+
const schemas = document.components?.securitySchemes ?? {};
|
|
34
|
+
for (const [key, scopes] of Object.entries(requirement)){
|
|
35
|
+
if (!(key in schemas)) return [];
|
|
36
|
+
const schema = noRef(schemas[key]);
|
|
37
|
+
results.push({
|
|
38
|
+
...schema,
|
|
39
|
+
scopes
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
function getSecurityPrefix(security) {
|
|
45
|
+
if (security.type === 'http') return ({
|
|
46
|
+
basic: 'Basic',
|
|
47
|
+
bearer: 'Bearer'
|
|
48
|
+
})[security.scheme];
|
|
49
|
+
if (security.type === 'oauth2') return 'Bearer';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function generateSample(path, method, { baseUrl, document }) {
|
|
32
53
|
const params = [];
|
|
33
54
|
const responses = {};
|
|
34
55
|
for (const param of method.parameters){
|
|
@@ -51,6 +72,20 @@ function generateSample(path, method, baseUrl) {
|
|
|
51
72
|
});
|
|
52
73
|
}
|
|
53
74
|
}
|
|
75
|
+
const requirements = method.security ?? document.security;
|
|
76
|
+
if (requirements && requirements.length > 0) {
|
|
77
|
+
for (const security of getSecurities(requirements[0], document)){
|
|
78
|
+
const prefix = getSecurityPrefix(security);
|
|
79
|
+
params.push({
|
|
80
|
+
name: 'Authorization',
|
|
81
|
+
schema: {
|
|
82
|
+
type: 'string'
|
|
83
|
+
},
|
|
84
|
+
sample: prefix ? `${prefix} <token>` : '<token>',
|
|
85
|
+
in: 'header'
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
54
89
|
let bodyOutput;
|
|
55
90
|
if (method.requestBody) {
|
|
56
91
|
const body = noRef(method.requestBody).content;
|
|
@@ -199,7 +234,7 @@ func main() {
|
|
|
199
234
|
${Array.from(variables.entries()).map(([k, v])=>` ${k} := ${v}`).join('\n')}
|
|
200
235
|
${additional.join('\n ')}
|
|
201
236
|
req, _ := http.NewRequest("${endpoint.method}", url, ${variables.has('payload') ? 'payload' : 'nil'})
|
|
202
|
-
${Array.from(headers.entries()).map(([key, value])=>`req.Header.Add("${key}", ${value})`).join('\n')}
|
|
237
|
+
${Array.from(headers.entries()).map(([key, value])=>`req.Header.Add("${key}", ${value})`).join('\n ')}
|
|
203
238
|
res, _ := http.DefaultClient.Do(req)
|
|
204
239
|
defer res.Body.Close()
|
|
205
240
|
body, _ := ioutil.ReadAll(res.Body)
|
|
@@ -220,20 +255,6 @@ async function getTypescriptSchema(endpoint, code) {
|
|
|
220
255
|
}
|
|
221
256
|
}
|
|
222
257
|
|
|
223
|
-
function getScheme(requirement, document) {
|
|
224
|
-
const results = [];
|
|
225
|
-
const schemas = document.components?.securitySchemes ?? {};
|
|
226
|
-
for (const [key, scopes] of Object.entries(requirement)){
|
|
227
|
-
if (!(key in schemas)) return [];
|
|
228
|
-
const schema = noRef(schemas[key]);
|
|
229
|
-
results.push({
|
|
230
|
-
...schema,
|
|
231
|
-
scopes
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
return results;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
258
|
function Playground({ path, method, ctx }) {
|
|
238
259
|
let currentId = 0;
|
|
239
260
|
const bodyContent = noRef(method.requestBody)?.content;
|
|
@@ -266,7 +287,7 @@ function getAuthorizationField(method, ctx) {
|
|
|
266
287
|
if (security.length === 0) return;
|
|
267
288
|
const singular = security.find((requirements)=>Object.keys(requirements).length === 1);
|
|
268
289
|
if (!singular) return;
|
|
269
|
-
const scheme =
|
|
290
|
+
const scheme = getSecurities(singular, ctx.document)[0];
|
|
270
291
|
return {
|
|
271
292
|
type: 'string',
|
|
272
293
|
name: 'Authorization',
|
|
@@ -676,7 +697,7 @@ function Operation({ path, method, ctx, hasHead }) {
|
|
|
676
697
|
}, "body"));
|
|
677
698
|
}
|
|
678
699
|
const parameterGroups = new Map();
|
|
679
|
-
const endpoint = generateSample(path, method, ctx
|
|
700
|
+
const endpoint = generateSample(path, method, ctx);
|
|
680
701
|
for (const param of method.parameters){
|
|
681
702
|
const pInfo = endpoint.parameters.find((item)=>item.name === param.name && item.in === param.in);
|
|
682
703
|
if (!pInfo) continue;
|
|
@@ -778,15 +799,12 @@ function AuthSection({ ctx: { document, renderer }, requirements }) {
|
|
|
778
799
|
let id = 0;
|
|
779
800
|
const info = [];
|
|
780
801
|
for (const requirement of requirements){
|
|
781
|
-
|
|
782
|
-
|
|
802
|
+
for (const schema of getSecurities(requirement, document)){
|
|
803
|
+
const prefix = getSecurityPrefix(schema);
|
|
783
804
|
if (schema.type === 'http') {
|
|
784
805
|
info.push(/*#__PURE__*/ jsxs(renderer.Property, {
|
|
785
806
|
name: "Authorization",
|
|
786
|
-
type: {
|
|
787
|
-
basic: 'Basic <token>',
|
|
788
|
-
bearer: 'Bearer <token>'
|
|
789
|
-
}[schema.scheme] ?? '<token>',
|
|
807
|
+
type: prefix ? `${prefix} <token>` : '<token>',
|
|
790
808
|
required: true,
|
|
791
809
|
children: [
|
|
792
810
|
schema.description ? /*#__PURE__*/ jsx(Markdown, {
|
|
@@ -806,7 +824,7 @@ function AuthSection({ ctx: { document, renderer }, requirements }) {
|
|
|
806
824
|
if (schema.type === 'oauth2') {
|
|
807
825
|
info.push(/*#__PURE__*/ jsxs(renderer.Property, {
|
|
808
826
|
name: "Authorization",
|
|
809
|
-
type:
|
|
827
|
+
type: prefix ? `${prefix} <token>` : '<token>',
|
|
810
828
|
required: true,
|
|
811
829
|
children: [
|
|
812
830
|
schema.description ? /*#__PURE__*/ jsx(Markdown, {
|
|
@@ -820,15 +838,14 @@ function AuthSection({ ctx: { document, renderer }, requirements }) {
|
|
|
820
838
|
})
|
|
821
839
|
]
|
|
822
840
|
}),
|
|
823
|
-
/*#__PURE__*/ jsxs("p", {
|
|
841
|
+
schema.scopes.length > 0 ? /*#__PURE__*/ jsxs("p", {
|
|
824
842
|
children: [
|
|
825
|
-
"Scope:",
|
|
826
|
-
' ',
|
|
843
|
+
"Scope: ",
|
|
827
844
|
/*#__PURE__*/ jsx("code", {
|
|
828
|
-
children: schema.scopes.
|
|
845
|
+
children: schema.scopes.join(', ')
|
|
829
846
|
})
|
|
830
847
|
]
|
|
831
|
-
})
|
|
848
|
+
}) : null
|
|
832
849
|
]
|
|
833
850
|
}, id++));
|
|
834
851
|
}
|
|
@@ -27,14 +27,20 @@ async function initHighlighter() {
|
|
|
27
27
|
loadWasm: getWasm
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
|
+
let highlighterInstance;
|
|
30
31
|
function ApiProvider({ defaultBaseUrl, children }) {
|
|
31
32
|
const [highlighter, setHighlighter] = useState(null);
|
|
32
33
|
const [baseUrl, setBaseUrl] = useState(defaultBaseUrl);
|
|
33
34
|
useEffect(()=>{
|
|
34
35
|
setBaseUrl((prev)=>localStorage.getItem('apiBaseUrl') ?? prev);
|
|
35
|
-
|
|
36
|
-
setHighlighter(
|
|
37
|
-
}
|
|
36
|
+
if (highlighterInstance) {
|
|
37
|
+
setHighlighter(highlighterInstance);
|
|
38
|
+
} else {
|
|
39
|
+
void initHighlighter().then((res)=>{
|
|
40
|
+
highlighterInstance = res;
|
|
41
|
+
setHighlighter(res);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
38
44
|
}, []);
|
|
39
45
|
useEffect(()=>{
|
|
40
46
|
if (baseUrl) localStorage.setItem('apiBaseUrl', baseUrl);
|
|
@@ -58,7 +64,7 @@ function useSchemaContext() {
|
|
|
58
64
|
return ctx;
|
|
59
65
|
}
|
|
60
66
|
|
|
61
|
-
const APIPlayground = dynamic(()=>import('./playground-client-
|
|
67
|
+
const APIPlayground = dynamic(()=>import('./playground-client-CjCikhf6.js').then((mod)=>mod.APIPlayground));
|
|
62
68
|
function Root({ children, baseUrl, className, ...props }) {
|
|
63
69
|
return /*#__PURE__*/ jsx("div", {
|
|
64
70
|
className: cn('flex flex-col gap-24 text-sm text-fd-muted-foreground', className),
|
package/dist/ui/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import { cn } from 'fumadocs-ui/components/api';
|
|
|
3
3
|
import { Fragment } from 'react';
|
|
4
4
|
import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
|
|
5
5
|
import { cva } from 'class-variance-authority';
|
|
6
|
-
import { C as CopyRouteButton } from './client-client-
|
|
7
|
-
export { A as APIPlayground, R as Root, u as useSchemaContext } from './client-client-
|
|
6
|
+
import { C as CopyRouteButton } from './client-client-BIwAR59x.js';
|
|
7
|
+
export { A as APIPlayground, R as Root, u as useSchemaContext } from './client-client-BIwAR59x.js';
|
|
8
8
|
|
|
9
9
|
const badgeVariants = cva('rounded border px-1.5 py-1 text-xs font-medium leading-[12px]', {
|
|
10
10
|
variants: {
|
|
@@ -59,7 +59,7 @@ function APIInfo({ children, className, route, badgeClassname, method = 'GET', .
|
|
|
59
59
|
...props,
|
|
60
60
|
children: [
|
|
61
61
|
/*#__PURE__*/ jsxs("div", {
|
|
62
|
-
className: cn('sticky top-24 z-
|
|
62
|
+
className: cn('sticky top-24 z-20 mb-4 flex flex-row items-center gap-2 rounded-lg border bg-fd-card px-3 py-2 md:top-12 lg:top-1'),
|
|
63
63
|
children: [
|
|
64
64
|
/*#__PURE__*/ jsx("span", {
|
|
65
65
|
className: cn(badgeVariants({
|
|
@@ -85,7 +85,7 @@ function APIInfo({ children, className, route, badgeClassname, method = 'GET', .
|
|
|
85
85
|
}
|
|
86
86
|
function API({ className, children, ...props }) {
|
|
87
87
|
return /*#__PURE__*/ jsx("div", {
|
|
88
|
-
className: cn('flex flex-col gap-x-6 gap-y-
|
|
88
|
+
className: cn('flex flex-col gap-x-6 gap-y-4 xl:flex-row xl:items-start', className),
|
|
89
89
|
...props,
|
|
90
90
|
children: children
|
|
91
91
|
});
|
|
@@ -124,7 +124,7 @@ function Property({ name, type, required, deprecated, children }) {
|
|
|
124
124
|
}
|
|
125
125
|
function APIExample({ children, className, ...props }) {
|
|
126
126
|
return /*#__PURE__*/ jsx("div", {
|
|
127
|
-
className: cn('sticky top-
|
|
127
|
+
className: cn('prose-no-margin md:sticky md:top-12 lg:top-1 xl:w-[400px]', className),
|
|
128
128
|
...props,
|
|
129
129
|
children: children
|
|
130
130
|
});
|
|
@@ -6,7 +6,7 @@ import { FormProvider, Controller, useFormContext, useFieldArray, useForm, useWa
|
|
|
6
6
|
import useSWRImmutable from 'swr/immutable';
|
|
7
7
|
import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
|
|
8
8
|
import { cn, buttonVariants } from 'fumadocs-ui/components/api';
|
|
9
|
-
import { u as useSchemaContext, a as useApiContext, S as SchemaContext } from './client-client-
|
|
9
|
+
import { u as useSchemaContext, a as useApiContext, S as SchemaContext } from './client-client-BIwAR59x.js';
|
|
10
10
|
import { Slot } from '@radix-ui/react-slot';
|
|
11
11
|
import { cva } from 'class-variance-authority';
|
|
12
12
|
import { CircleCheckIcon, CircleXIcon, ChevronDown, ChevronUp, Check, Trash2, Plus } from 'lucide-react';
|
|
@@ -343,7 +343,7 @@ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
|
343
343
|
const Input = /*#__PURE__*/ React.forwardRef(({ className, type, ...props }, ref)=>{
|
|
344
344
|
return /*#__PURE__*/ jsx("input", {
|
|
345
345
|
type: type,
|
|
346
|
-
className: cn('flex h-9 w-full rounded-md border bg-transparent px-
|
|
346
|
+
className: cn('flex h-9 w-full rounded-md border bg-transparent px-2 py-1.5 text-sm text-fd-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),
|
|
347
347
|
ref: ref,
|
|
348
348
|
...props
|
|
349
349
|
});
|
|
@@ -919,7 +919,7 @@ function APIPlayground({ route, method = 'GET', bodyType, authorization, path =
|
|
|
919
919
|
schemas
|
|
920
920
|
]),
|
|
921
921
|
children: /*#__PURE__*/ jsxs("form", {
|
|
922
|
-
className: "not-prose flex flex-col gap-5 rounded-lg border bg-fd-card p-
|
|
922
|
+
className: "not-prose flex flex-col gap-5 rounded-lg border bg-fd-card p-3",
|
|
923
923
|
onSubmit: onSubmit,
|
|
924
924
|
children: [
|
|
925
925
|
/*#__PURE__*/ jsxs("div", {
|
|
@@ -941,7 +941,7 @@ function APIPlayground({ route, method = 'GET', bodyType, authorization, path =
|
|
|
941
941
|
authorization ? renderCustomField('authorization', authorization, fields.auth) : null,
|
|
942
942
|
/*#__PURE__*/ jsxs(Accordions, {
|
|
943
943
|
type: "multiple",
|
|
944
|
-
className: cn('-m-
|
|
944
|
+
className: cn('-m-3 border-0 text-sm', path.length === 0 && query.length === 0 && header.length === 0 && !body && 'hidden'),
|
|
945
945
|
children: [
|
|
946
946
|
path.length > 0 ? /*#__PURE__*/ jsx(Accordion, {
|
|
947
947
|
title: "Path",
|
|
@@ -998,7 +998,7 @@ function RouteDisplay({ route }) {
|
|
|
998
998
|
pathInput
|
|
999
999
|
]);
|
|
1000
1000
|
return /*#__PURE__*/ jsx("code", {
|
|
1001
|
-
className: "flex-1 overflow-auto text-nowrap rounded-lg border bg-fd-muted px-
|
|
1001
|
+
className: "flex-1 overflow-auto text-nowrap rounded-lg border bg-fd-muted px-2 py-1.5 text-sm text-fd-muted-foreground",
|
|
1002
1002
|
children: pathname
|
|
1003
1003
|
});
|
|
1004
1004
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fumadocs-openapi",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.3",
|
|
4
4
|
"description": "Generate MDX docs for your OpenAPI spec",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NextJs",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"remark": "^15.0.0",
|
|
61
61
|
"shiki": "^1.11.1",
|
|
62
62
|
"swr": "^2.2.5",
|
|
63
|
-
"fumadocs-core": "13.
|
|
64
|
-
"fumadocs-ui": "13.
|
|
63
|
+
"fumadocs-core": "13.2.0",
|
|
64
|
+
"fumadocs-ui": "13.2.0"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@types/js-yaml": "^4.0.9",
|