fumadocs-openapi 8.1.12 → 9.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 +55 -20
- package/dist/generate-file.d.ts.map +1 -1
- package/dist/generate-file.js +93 -68
- package/dist/generate.d.ts +10 -10
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +33 -64
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/playground/inputs.d.ts +4 -8
- package/dist/playground/inputs.d.ts.map +1 -1
- package/dist/playground/inputs.js +56 -37
- package/dist/render/api-page.d.ts.map +1 -1
- package/dist/render/markdown.d.ts.map +1 -1
- package/dist/render/markdown.js +15 -11
- package/dist/render/operation/api-example.js +10 -6
- package/dist/render/operation/index.d.ts +1 -1
- package/dist/render/operation/index.d.ts.map +1 -1
- package/dist/render/operation/index.js +4 -16
- package/dist/render/renderer.d.ts +1 -0
- package/dist/render/renderer.d.ts.map +1 -1
- package/dist/render/schema.d.ts +5 -15
- package/dist/render/schema.d.ts.map +1 -1
- package/dist/render/schema.js +178 -97
- package/dist/server/create.d.ts +1 -7
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/proxy.d.ts +11 -1
- package/dist/server/proxy.d.ts.map +1 -1
- package/dist/server/proxy.js +10 -3
- package/dist/server/source-api.d.ts +3 -2
- package/dist/server/source-api.d.ts.map +1 -1
- package/dist/ui/client.js +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +4 -4
- package/dist/utils/combine-schema.d.ts.map +1 -1
- package/dist/utils/combine-schema.js +22 -27
- package/dist/utils/generate-document.d.ts +4 -7
- package/dist/utils/generate-document.d.ts.map +1 -1
- package/dist/utils/generate-document.js +10 -6
- package/dist/utils/process-document.d.ts +1 -1
- package/dist/utils/process-document.d.ts.map +1 -1
- package/dist/utils/process-document.js +8 -5
- package/dist/utils/schema-to-string.d.ts.map +1 -1
- package/dist/utils/schema-to-string.js +8 -21
- package/dist/utils/schema.d.ts +1 -1
- package/dist/utils/schema.d.ts.map +1 -1
- package/dist/utils/schema.js +5 -8
- package/package.json +12 -12
package/dist/render/schema.js
CHANGED
|
@@ -1,115 +1,174 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment } from 'react';
|
|
2
3
|
import { combineSchema } from '../utils/combine-schema.js';
|
|
3
4
|
import { Markdown } from './markdown.js';
|
|
4
5
|
import { schemaToString } from '../utils/schema-to-string.js';
|
|
6
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger, } from 'fumadocs-ui/components/tabs';
|
|
5
7
|
const keys = {
|
|
6
8
|
default: 'Default',
|
|
7
|
-
minimum: 'Minimum',
|
|
8
|
-
maximum: 'Maximum',
|
|
9
|
-
minLength: 'Minimum length',
|
|
10
|
-
maxLength: 'Maximum length',
|
|
11
9
|
pattern: 'Pattern',
|
|
12
10
|
format: 'Format',
|
|
11
|
+
multipleOf: 'Multiple of',
|
|
13
12
|
};
|
|
14
|
-
export function Schema({ name, schema, required = false,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}), patternProperties &&
|
|
53
|
-
Object.entries(patternProperties).map(([key, value]) => {
|
|
54
|
-
return (_jsx(Schema, { name: key, schema: value, parseObject: false, ctx: {
|
|
55
|
-
...ctx,
|
|
56
|
-
stack: [schema, ...stack],
|
|
57
|
-
} }, key));
|
|
58
|
-
}), additionalProperties && (_jsx(Schema, { name: "[key: string]", schema: additionalProperties, parseObject: false, ctx: {
|
|
59
|
-
...ctx,
|
|
60
|
-
stack: [schema, ...stack],
|
|
61
|
-
} }))] }));
|
|
13
|
+
export function Schema({ name, schema, required = false, readOnly = false, writeOnly = false, as = 'property', ctx: { renderer }, }) {
|
|
14
|
+
function propertyBody(schema, renderPrimitive, ctx) {
|
|
15
|
+
if (Array.isArray(schema.type)) {
|
|
16
|
+
const items = schema.type.flatMap((type) => {
|
|
17
|
+
const composed = {
|
|
18
|
+
...schema,
|
|
19
|
+
type,
|
|
20
|
+
};
|
|
21
|
+
if (!isComplexType(composed))
|
|
22
|
+
return [];
|
|
23
|
+
return composed;
|
|
24
|
+
});
|
|
25
|
+
if (items.length === 0)
|
|
26
|
+
return;
|
|
27
|
+
if (items.length === 1)
|
|
28
|
+
return propertyBody(items[0], renderPrimitive, ctx);
|
|
29
|
+
return (_jsxs(Tabs, { defaultValue: items[0].type, children: [_jsx(TabsList, { children: items.map((item) => (_jsx(TabsTrigger, { value: item.type, children: schemaToString(item) }, item.type))) }), items.map((item) => (_jsxs(TabsContent, { value: item.type, children: [item.description && _jsx(Markdown, { text: item.description }), propertyInfo(item), renderPrimitive(item, ctx)] }, item.type)))] }));
|
|
30
|
+
}
|
|
31
|
+
if (schema.oneOf) {
|
|
32
|
+
const oneOf = schema.oneOf.filter((item) => isComplexType(item));
|
|
33
|
+
if (oneOf.length === 0)
|
|
34
|
+
return;
|
|
35
|
+
if (oneOf.length === 1) {
|
|
36
|
+
return propertyBody(oneOf[0], renderPrimitive, ctx);
|
|
37
|
+
}
|
|
38
|
+
return (_jsxs(Tabs, { defaultValue: "0", children: [_jsx(TabsList, { children: oneOf.map((item, i) => (_jsx(TabsTrigger, { value: i.toString(), children: schemaToString(item) }, i))) }), oneOf.map((item, i) => (_jsxs(TabsContent, { value: i.toString(), children: [item.description && _jsx(Markdown, { text: item.description }), propertyInfo(item), propertyBody(item, (child, ctx) => primitiveBody(child, ctx, false, true), ctx)] }, i)))] }));
|
|
39
|
+
}
|
|
40
|
+
const of = schema.allOf ?? schema.anyOf;
|
|
41
|
+
if (of) {
|
|
42
|
+
const arr = of.filter((item) => !ctx.stack.has(item));
|
|
43
|
+
if (arr.length === 0)
|
|
44
|
+
return;
|
|
45
|
+
const combined = combineSchema(arr);
|
|
46
|
+
if (typeof combined === 'boolean')
|
|
47
|
+
return;
|
|
48
|
+
return renderPrimitive(combined, ctx);
|
|
49
|
+
}
|
|
50
|
+
return renderPrimitive(schema, ctx);
|
|
62
51
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
52
|
+
function propertyInfo(schema) {
|
|
53
|
+
const fields = [];
|
|
54
|
+
for (const key in keys) {
|
|
55
|
+
if (key in schema) {
|
|
56
|
+
fields.push({
|
|
57
|
+
key: keys[key],
|
|
58
|
+
value: JSON.stringify(schema[key]),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
let range = getRange('value', schema.minimum, schema.exclusiveMinimum, schema.maximum, schema.exclusiveMaximum);
|
|
63
|
+
if (range)
|
|
64
|
+
fields.push({
|
|
65
|
+
key: 'Range',
|
|
66
|
+
value: range,
|
|
67
|
+
});
|
|
68
|
+
range = getRange('length', schema.minLength, undefined, schema.maxLength, undefined);
|
|
69
|
+
if (range)
|
|
70
|
+
fields.push({
|
|
71
|
+
key: 'Length',
|
|
72
|
+
value: range,
|
|
73
|
+
});
|
|
74
|
+
range = getRange('properties', schema.minProperties, undefined, schema.maxProperties, undefined);
|
|
75
|
+
if (range)
|
|
76
|
+
fields.push({
|
|
77
|
+
key: 'Properties',
|
|
78
|
+
value: range,
|
|
79
|
+
});
|
|
80
|
+
if (schema.enum) {
|
|
67
81
|
fields.push({
|
|
68
|
-
key:
|
|
69
|
-
value: JSON.stringify(
|
|
82
|
+
key: 'Value in',
|
|
83
|
+
value: schema.enum.map((value) => JSON.stringify(value)).join(' | '),
|
|
70
84
|
});
|
|
71
85
|
}
|
|
86
|
+
if (fields.length === 0)
|
|
87
|
+
return;
|
|
88
|
+
return (_jsx("div", { className: "flex flex-col border divide-y divide-fd-border bg-fd-muted rounded-lg not-prose", children: fields.map((field) => (_jsxs("div", { className: "flex items-center text-[13px] px-3 py-2.5 justify-between gap-2", children: [_jsx("span", { className: "font-medium", children: field.key }), _jsx("code", { className: "texxt-xs text-fd-muted-foreground", children: field.value })] }, field.key))) }));
|
|
72
89
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
function primitiveBody(schema, ctx, collapsible, nested) {
|
|
91
|
+
if (schema.type === 'object') {
|
|
92
|
+
if (ctx.stack.has(schema))
|
|
93
|
+
return _jsx("p", { children: "Recursive" });
|
|
94
|
+
const props = Object.entries(schema.properties ?? {});
|
|
95
|
+
const patternProps = Object.entries(schema.patternProperties ?? {});
|
|
96
|
+
const next = {
|
|
97
|
+
...ctx,
|
|
98
|
+
stack: ctx.stack.next(schema),
|
|
99
|
+
};
|
|
100
|
+
if (props.length === 0 && patternProps.length === 0)
|
|
101
|
+
return _jsx("p", { children: "Empty Object" });
|
|
102
|
+
const children = (_jsxs("div", { className: "flex flex-col gap-4", children: [props.map(([key, value]) => (_jsx(Fragment, { children: property(key, value, next, {
|
|
103
|
+
required: schema.required?.includes(key) ?? false,
|
|
104
|
+
nested,
|
|
105
|
+
}) }, key))), patternProps.map(([key, value]) => (_jsx(Fragment, { children: property(key, value, next, { nested }) }, key))), schema.additionalProperties &&
|
|
106
|
+
property('[key: string]', schema.additionalProperties, next, {
|
|
107
|
+
nested,
|
|
108
|
+
})] }));
|
|
109
|
+
if (!collapsible)
|
|
110
|
+
return children;
|
|
111
|
+
return (_jsx(renderer.ObjectCollapsible, { name: "Show Attributes", children: children }));
|
|
112
|
+
}
|
|
113
|
+
if (schema.type === 'array') {
|
|
114
|
+
const items = schema.items;
|
|
115
|
+
if (!items || !isComplexType(items) || ctx.stack.has(items))
|
|
116
|
+
return;
|
|
117
|
+
const children = (_jsxs("div", { className: "flex flex-col gap-4", children: [items.description && _jsx(Markdown, { text: items.description }), propertyBody(items, (child, ctx) => primitiveBody(child, ctx, false, true), {
|
|
118
|
+
...ctx,
|
|
119
|
+
stack: ctx.stack.next(schema),
|
|
120
|
+
})] }));
|
|
121
|
+
return (_jsx(renderer.ObjectCollapsible, { name: "Array Item", children: children }));
|
|
122
|
+
}
|
|
84
123
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
})));
|
|
124
|
+
function property(key, schema, ctx, props) {
|
|
125
|
+
if (schema === true) {
|
|
126
|
+
return _jsx(renderer.Property, { name: key, type: "any", ...props });
|
|
127
|
+
}
|
|
128
|
+
else if (schema === false) {
|
|
129
|
+
return _jsx(renderer.Property, { name: key, type: "never", ...props });
|
|
92
130
|
}
|
|
93
|
-
if (schema.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
mentionedObjectTypes.push(schema.not);
|
|
97
|
-
if (schema.type === 'array' && schema.items)
|
|
98
|
-
mentionedObjectTypes.push(schema.items);
|
|
99
|
-
mentionedObjectTypes = mentionedObjectTypes.filter((s) => isComplexType(s) && !stack.includes(s));
|
|
100
|
-
if (mentionedObjectTypes.length > 0)
|
|
101
|
-
footer = (_jsx("div", { className: "flex flex-col gap-2", children: mentionedObjectTypes.map((s, idx) => {
|
|
102
|
-
let title = typeof s === 'object' ? s.title : null;
|
|
103
|
-
title ?? (title = mentionedObjectTypes.length === 1
|
|
104
|
-
? 'Show Attributes'
|
|
105
|
-
: `Object ${idx + 1}`);
|
|
106
|
-
return (_jsx(renderer.ObjectCollapsible, { name: title, children: _jsx(Schema, { name: "element", schema: s, ctx: {
|
|
107
|
-
...ctx,
|
|
108
|
-
stack: [schema, ...stack],
|
|
109
|
-
} }) }, idx));
|
|
110
|
-
}) }));
|
|
131
|
+
if ((schema.readOnly && !readOnly) || (schema.writeOnly && !writeOnly))
|
|
132
|
+
return;
|
|
133
|
+
return (_jsxs(renderer.Property, { name: key, type: schemaToString(schema), deprecated: schema.deprecated, ...props, children: [schema.description && _jsx(Markdown, { text: schema.description }), propertyInfo(schema), propertyBody(schema, (child, ctx) => primitiveBody(child, ctx, true, true), ctx)] }));
|
|
111
134
|
}
|
|
112
|
-
|
|
135
|
+
const context = {
|
|
136
|
+
stack: schemaStack(),
|
|
137
|
+
};
|
|
138
|
+
if (typeof schema === 'boolean' ||
|
|
139
|
+
as === 'property' ||
|
|
140
|
+
!isComplexType(schema))
|
|
141
|
+
return property(name, schema, context, { required });
|
|
142
|
+
return propertyBody(schema, (child, ctx) => primitiveBody(child, ctx, false, false), context);
|
|
143
|
+
}
|
|
144
|
+
function schemaStack(parent) {
|
|
145
|
+
const titles = new Set();
|
|
146
|
+
const history = new WeakSet();
|
|
147
|
+
return {
|
|
148
|
+
next(...schemas) {
|
|
149
|
+
const child = schemaStack(this);
|
|
150
|
+
for (const item of schemas) {
|
|
151
|
+
child.add(item);
|
|
152
|
+
}
|
|
153
|
+
return child;
|
|
154
|
+
},
|
|
155
|
+
add(schema) {
|
|
156
|
+
if (typeof schema !== 'object')
|
|
157
|
+
return;
|
|
158
|
+
if (schema.title)
|
|
159
|
+
titles.add(schema.title);
|
|
160
|
+
history.add(schema);
|
|
161
|
+
},
|
|
162
|
+
has(schema) {
|
|
163
|
+
if (typeof schema !== 'object')
|
|
164
|
+
return false;
|
|
165
|
+
if (parent && parent.has(schema))
|
|
166
|
+
return true;
|
|
167
|
+
if (schema.title && titles.has(schema.title))
|
|
168
|
+
return true;
|
|
169
|
+
return history.has(schema);
|
|
170
|
+
},
|
|
171
|
+
};
|
|
113
172
|
}
|
|
114
173
|
/**
|
|
115
174
|
* Check if the schema needs another collapsible to explain
|
|
@@ -117,7 +176,29 @@ export function Schema({ name, schema, required = false, parseObject = true, ctx
|
|
|
117
176
|
function isComplexType(schema) {
|
|
118
177
|
if (typeof schema === 'boolean')
|
|
119
178
|
return false;
|
|
120
|
-
|
|
179
|
+
const arr = schema.anyOf ?? schema.oneOf ?? schema.allOf;
|
|
180
|
+
if (arr && arr.some(isComplexType))
|
|
121
181
|
return true;
|
|
122
|
-
return schema.type === 'object' ||
|
|
182
|
+
return (schema.type === 'object' ||
|
|
183
|
+
(schema.type === 'array' &&
|
|
184
|
+
schema.items != null &&
|
|
185
|
+
isComplexType(schema.items)));
|
|
186
|
+
}
|
|
187
|
+
function getRange(value, min, exclusiveMin, max, exclusiveMax) {
|
|
188
|
+
const out = [];
|
|
189
|
+
if (min) {
|
|
190
|
+
out.push(`${min} <=`);
|
|
191
|
+
}
|
|
192
|
+
else if (exclusiveMin) {
|
|
193
|
+
out.push(`${exclusiveMin} <`);
|
|
194
|
+
}
|
|
195
|
+
out.push(value);
|
|
196
|
+
if (max) {
|
|
197
|
+
out.push(`<= ${max}`);
|
|
198
|
+
}
|
|
199
|
+
else if (exclusiveMax) {
|
|
200
|
+
out.push(`< ${exclusiveMax}`);
|
|
201
|
+
}
|
|
202
|
+
if (out.length > 1)
|
|
203
|
+
return out.join(' ');
|
|
123
204
|
}
|
package/dist/server/create.d.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import type { ApiPageProps } from '../render/api-page.js';
|
|
2
|
-
import type { DocumentInput } from '../utils/process-document.js';
|
|
3
2
|
import { createProxy } from '../server/proxy.js';
|
|
4
|
-
export
|
|
5
|
-
/**
|
|
6
|
-
* @deprecated Pass document to `APIPage` instead
|
|
7
|
-
*/
|
|
8
|
-
documentOrPath?: DocumentInput;
|
|
9
|
-
}
|
|
3
|
+
export type OpenAPIOptions = Omit<Partial<ApiPageProps>, 'document'>;
|
|
10
4
|
export interface OpenAPIServer {
|
|
11
5
|
getAPIPageProps: (from: ApiPageProps) => ApiPageProps;
|
|
12
6
|
createProxy: typeof createProxy;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/server/create.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/server/create.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,UAAU,CAAC,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,YAAY,CAAC;IACtD,WAAW,EAAE,OAAO,WAAW,CAAC;CACjC;AAED,wBAAgB,aAAa,CAAC,OAAO,GAAE,cAAmB,GAAG,aAAa,CAUzE"}
|
package/dist/server/proxy.d.ts
CHANGED
|
@@ -3,6 +3,16 @@ declare const keys: readonly ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD"];
|
|
|
3
3
|
type Proxy = {
|
|
4
4
|
[K in (typeof keys)[number]]: (req: NextRequest) => Promise<Response>;
|
|
5
5
|
};
|
|
6
|
-
|
|
6
|
+
interface CreateProxyOptions {
|
|
7
|
+
allowedUrls?: string[];
|
|
8
|
+
/**
|
|
9
|
+
* Override original request/response with yours
|
|
10
|
+
*/
|
|
11
|
+
overrides?: {
|
|
12
|
+
request?: (request: Request) => Request;
|
|
13
|
+
response?: (response: Response) => Response;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export declare function createProxy(options?: CreateProxyOptions): Proxy;
|
|
7
17
|
export {};
|
|
8
18
|
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/server/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,QAAA,MAAM,IAAI,4DAA6D,CAAC;AAExE,KAAK,KAAK,GAAG;KACV,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC;CACtE,CAAC;AAEF,
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/server/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,QAAA,MAAM,IAAI,4DAA6D,CAAC;AAExE,KAAK,KAAK,GAAG;KACV,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC;CACtE,CAAC;AAEF,UAAU,kBAAkB;IAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB;;OAEG;IACH,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;QACxC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,QAAQ,CAAC;KAC7C,CAAC;CACH;AAED,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,KAAK,CA8EnE"}
|
package/dist/server/proxy.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const keys = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'];
|
|
2
|
-
export function createProxy(
|
|
2
|
+
export function createProxy(options = {}) {
|
|
3
|
+
const { allowedUrls, overrides } = options;
|
|
3
4
|
const handlers = {};
|
|
4
5
|
async function handler(req) {
|
|
5
6
|
const url = req.nextUrl.searchParams.get('url');
|
|
@@ -14,11 +15,14 @@ export function createProxy(allowedUrls) {
|
|
|
14
15
|
status: 400,
|
|
15
16
|
});
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
+
let clonedReq = new Request(url, {
|
|
18
19
|
...req,
|
|
19
20
|
cache: 'no-cache',
|
|
20
21
|
mode: 'cors',
|
|
21
22
|
});
|
|
23
|
+
if (overrides?.request) {
|
|
24
|
+
clonedReq = overrides.request(clonedReq);
|
|
25
|
+
}
|
|
22
26
|
clonedReq.headers.forEach((_value, originalKey) => {
|
|
23
27
|
const key = originalKey.toLowerCase();
|
|
24
28
|
const notAllowed = key === 'origin';
|
|
@@ -26,12 +30,15 @@ export function createProxy(allowedUrls) {
|
|
|
26
30
|
clonedReq.headers.delete(originalKey);
|
|
27
31
|
}
|
|
28
32
|
});
|
|
29
|
-
|
|
33
|
+
let res = await fetch(clonedReq).catch((e) => new Error(e.toString()));
|
|
30
34
|
if (res instanceof Error) {
|
|
31
35
|
return Response.json(`Failed to proxy request: ${res.message}`, {
|
|
32
36
|
status: 400,
|
|
33
37
|
});
|
|
34
38
|
}
|
|
39
|
+
if (overrides?.response) {
|
|
40
|
+
res = overrides.response(res);
|
|
41
|
+
}
|
|
35
42
|
const headers = new Headers(res.headers);
|
|
36
43
|
headers.forEach((_value, originalKey) => {
|
|
37
44
|
const key = originalKey.toLowerCase();
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FileSystem } from 'fumadocs-core/source';
|
|
2
|
+
import type { PageTree } from 'fumadocs-core/server';
|
|
2
3
|
/**
|
|
3
4
|
* Source API Integration
|
|
4
5
|
*
|
|
5
6
|
* Add this to page tree builder options
|
|
6
7
|
*/
|
|
7
|
-
export declare const attachFile:
|
|
8
|
+
export declare const attachFile: (node: PageTree.Item, file: FileSystem.PageFile | undefined) => PageTree.Item;
|
|
8
9
|
//# sourceMappingURL=source-api.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-api.d.ts","sourceRoot":"","sources":["../../src/server/source-api.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"source-api.d.ts","sourceRoot":"","sources":["../../src/server/source-api.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,UAAU,GACrB,MAAM,QAAQ,CAAC,IAAI,EACnB,MAAM,UAAU,CAAC,QAAQ,GAAG,SAAS,KACpC,QAAQ,CAAC,IAyBX,CAAC"}
|
package/dist/ui/client.js
CHANGED
|
@@ -8,7 +8,7 @@ export function CopyResponseTypeScript({ code }) {
|
|
|
8
8
|
const [isChecked, onCopy] = useCopyButton(() => {
|
|
9
9
|
void navigator.clipboard.writeText(code);
|
|
10
10
|
});
|
|
11
|
-
return (_jsxs("div", { className: "flex items-start justify-between gap-2 bg-fd-card border rounded-xl p-3 not-prose mb-4 last:mb-0", children: [_jsxs("div", { children: [_jsx("p", { className: "font-medium text-
|
|
11
|
+
return (_jsxs("div", { className: "flex items-start justify-between gap-2 bg-fd-card text-fd-card-foreground border rounded-xl p-3 not-prose mb-4 last:mb-0", children: [_jsxs("div", { children: [_jsx("p", { className: "font-medium text-sm mb-2", children: "TypeScript Definitions" }), _jsx("p", { className: "text-xs text-fd-muted-foreground", children: "Use the response body type in TypeScript." })] }), _jsxs("button", { onClick: onCopy, className: cn(buttonVariants({
|
|
12
12
|
color: 'secondary',
|
|
13
13
|
className: 'p-2 gap-2',
|
|
14
14
|
size: 'sm',
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { PropertyProps, RootProps } from '../render/renderer.js';
|
|
|
3
3
|
export declare function Root({ children, className, ctx, ...props }: RootProps & HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
|
|
4
4
|
export declare function APIInfo({ className, ...props }: HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
export declare function API({ children, ...props }: HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
|
|
6
|
-
export declare function Property({ name, type, required, deprecated,
|
|
6
|
+
export declare function Property({ name, type, required, deprecated, nested, ...props }: PropertyProps): import("react/jsx-runtime").JSX.Element;
|
|
7
7
|
export declare function APIExample(props: HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
|
|
8
8
|
export declare function ObjectCollapsible(props: {
|
|
9
9
|
name: string;
|
package/dist/ui/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAYlE,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,EACT,GAAG,EACH,GAAG,KAAK,EACT,EAAE,SAAS,GAAG,cAAc,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAYlE,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,EACT,GAAG,EACH,GAAG,KAAK,EACT,EAAE,SAAS,GAAG,cAAc,CAAC,cAAc,CAAC,2CAmB5C;AAED,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,cAAc,CAAC,2CAMhC;AAED,wBAAgB,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,cAAc,CAAC,2CAmBzE;AAED,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,MAAM,EACN,GAAG,KAAK,EACT,EAAE,aAAa,2CAyBf;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,cAAc,CAAC,2CAY/D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAmBA;AAED,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/ui/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { ApiProvider } from '../ui/lazy.js';
|
|
|
6
6
|
import { cn } from 'fumadocs-ui/utils/cn';
|
|
7
7
|
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
|
|
8
8
|
export function Root({ children, className, ctx, ...props }) {
|
|
9
|
-
return (_jsx("div", { className: cn('flex flex-col gap-24 text-sm
|
|
9
|
+
return (_jsx("div", { className: cn('flex flex-col gap-24 text-sm', className), ...props, children: _jsx(ApiProvider, { mediaAdapters: Object.fromEntries(Object.entries(ctx.mediaAdapters).filter(([_, v]) => typeof v !== 'boolean')), servers: ctx.servers, shikiOptions: ctx.shikiOptions, defaultBaseUrl: ctx.baseUrl, children: children }) }));
|
|
10
10
|
}
|
|
11
11
|
export function APIInfo({ className, ...props }) {
|
|
12
12
|
return (_jsx("div", { className: cn('min-w-0 flex-1', className), ...props, children: props.children }));
|
|
@@ -17,13 +17,13 @@ export function API({ children, ...props }) {
|
|
|
17
17
|
...props.style,
|
|
18
18
|
}, children: children }));
|
|
19
19
|
}
|
|
20
|
-
export function Property({ name, type, required, deprecated,
|
|
21
|
-
return (_jsxs("div", { className:
|
|
20
|
+
export function Property({ name, type, required, deprecated, nested, ...props }) {
|
|
21
|
+
return (_jsxs("div", { className: cn('flex flex-col gap-3 text-sm', !nested && 'p-3 border rounded-xl bg-fd-card'), children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3 not-prose", children: [_jsxs("span", { className: "px-1 py-0.5 border rounded-md border-fd-primary/10 bg-fd-primary/10 font-mono text-xs text-fd-primary sm:text-[13px]", children: [name, required === false && '?'] }), _jsx("span", { className: "text-xs me-auto font-mono text-fd-muted-foreground", children: type }), deprecated && (_jsx(Badge, { color: "yellow", className: "text-xs", children: "Deprecated" }))] }), _jsx("div", { className: "prose-no-margin empty:hidden", children: props.children })] }));
|
|
22
22
|
}
|
|
23
23
|
export function APIExample(props) {
|
|
24
24
|
return (_jsx("div", { ...props, className: cn('prose-no-margin md:sticky md:top-(--fd-api-info-top) xl:w-[400px]', props.className), children: props.children }));
|
|
25
25
|
}
|
|
26
26
|
export function ObjectCollapsible(props) {
|
|
27
|
-
return (_jsxs(Collapsible, { ...props, children: [_jsxs(CollapsibleTrigger, { className: cn(buttonVariants({ color: '
|
|
27
|
+
return (_jsxs(Collapsible, { ...props, children: [_jsxs(CollapsibleTrigger, { className: cn(buttonVariants({ color: 'secondary', size: 'sm' }), 'group px-3 py-2 data-[state=open]:rounded-b-none data-[state=open]:border-b-0'), children: [props.name, _jsx(ChevronDown, { className: "size-4 text-fd-muted-foreground group-data-[state=open]:rotate-180" })] }), _jsx(CollapsibleContent, { className: "-me-3", children: _jsx("div", { className: "border-s border-y rounded-b-lg p-3", children: props.children }) })] }));
|
|
28
28
|
}
|
|
29
29
|
export { APIPage } from '../render/api-page.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combine-schema.d.ts","sourceRoot":"","sources":["../../src/utils/combine-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"combine-schema.d.ts","sourceRoot":"","sources":["../../src/utils/combine-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,CAuDlE"}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Combine multiple object schemas into one
|
|
3
3
|
*/
|
|
4
4
|
export function combineSchema(schema) {
|
|
5
|
-
let result = {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
let result = {};
|
|
6
|
+
const types = new Set();
|
|
7
|
+
const title = new Set();
|
|
8
8
|
function add(s) {
|
|
9
9
|
if (typeof s === 'boolean') {
|
|
10
10
|
result = s;
|
|
@@ -12,24 +12,23 @@ export function combineSchema(schema) {
|
|
|
12
12
|
}
|
|
13
13
|
if (typeof result === 'boolean')
|
|
14
14
|
return;
|
|
15
|
+
if (s.title)
|
|
16
|
+
title.add(s.title);
|
|
15
17
|
if (s.type) {
|
|
16
|
-
result.type ?? (result.type = []);
|
|
17
|
-
if (!Array.isArray(result.type)) {
|
|
18
|
-
result.type = [result.type];
|
|
19
|
-
}
|
|
20
18
|
for (const v of Array.isArray(s.type) ? s.type : [s.type]) {
|
|
21
|
-
|
|
22
|
-
result.type.push(v);
|
|
23
|
-
}
|
|
19
|
+
types.add(v);
|
|
24
20
|
}
|
|
25
21
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
for (const key of ['oneOf', 'required', 'enum']) {
|
|
23
|
+
if (!s[key])
|
|
24
|
+
continue;
|
|
25
|
+
result[key] = [...s[key], ...(result[key] ?? [])];
|
|
29
26
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
for (const key of ['properties', 'patternProperties']) {
|
|
28
|
+
if (!s[key])
|
|
29
|
+
continue;
|
|
30
|
+
result[key] ?? (result[key] = {});
|
|
31
|
+
Object.assign(result[key], s[key]);
|
|
33
32
|
}
|
|
34
33
|
if (s.additionalProperties === true) {
|
|
35
34
|
result.additionalProperties = true;
|
|
@@ -39,18 +38,14 @@ export function combineSchema(schema) {
|
|
|
39
38
|
result.additionalProperties ?? (result.additionalProperties = {});
|
|
40
39
|
Object.assign(result.additionalProperties, s.additionalProperties);
|
|
41
40
|
}
|
|
42
|
-
|
|
43
|
-
result.required ?? (result.required = []);
|
|
44
|
-
result.required.push(...s.required);
|
|
45
|
-
}
|
|
46
|
-
if (s.enum && s.enum.length > 0) {
|
|
47
|
-
result.enum ?? (result.enum = []);
|
|
48
|
-
result.enum.push(...s.enum);
|
|
49
|
-
}
|
|
50
|
-
if (s.allOf) {
|
|
51
|
-
s.allOf.forEach(add);
|
|
52
|
-
}
|
|
41
|
+
(s.allOf ?? s.anyOf)?.forEach(add);
|
|
53
42
|
}
|
|
54
43
|
schema.forEach(add);
|
|
44
|
+
if (title.size > 0)
|
|
45
|
+
result.title = Array.from(title).join(' & ');
|
|
46
|
+
if (types.size > 0) {
|
|
47
|
+
const typeArr = Array.from(types.values());
|
|
48
|
+
result.type = typeArr.length === 1 ? typeArr[0] : typeArr;
|
|
49
|
+
}
|
|
55
50
|
return result;
|
|
56
51
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ApiPageProps } from '../render/api-page.js';
|
|
2
2
|
import type { GenerateOptions } from '../generate.js';
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
3
|
+
import type { TagObject } from '../types.js';
|
|
4
|
+
import type { DocumentInput, ProcessedDocument } from '../utils/process-document.js';
|
|
5
5
|
export type DocumentContext = {
|
|
6
6
|
type: 'tag';
|
|
7
7
|
tag: TagObject | undefined;
|
|
@@ -10,11 +10,8 @@ export type DocumentContext = {
|
|
|
10
10
|
} | {
|
|
11
11
|
type: 'file';
|
|
12
12
|
};
|
|
13
|
-
export declare function generateDocument(options: GenerateOptions & {
|
|
14
|
-
dereferenced: NoReference<Document>;
|
|
15
|
-
page: ApiPageProps;
|
|
13
|
+
export declare function generateDocument(input: DocumentInput, processed: ProcessedDocument, pageProps: Omit<ApiPageProps, 'document'>, options: GenerateOptions & {
|
|
16
14
|
title: string;
|
|
17
15
|
description?: string;
|
|
18
|
-
|
|
19
|
-
}): string;
|
|
16
|
+
}, context: DocumentContext): string;
|
|
20
17
|
//# sourceMappingURL=generate-document.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-document.d.ts","sourceRoot":"","sources":["../../src/utils/generate-document.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,YAAY,EAGb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"generate-document.d.ts","sourceRoot":"","sources":["../../src/utils/generate-document.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,YAAY,EAGb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,KAAK,EAAY,SAAS,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EAClB,MAAM,0BAA0B,CAAC;AAOlC,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,SAAS,GAAG,SAAS,CAAC;CAC5B,GACD;IACE,IAAI,EAAE,WAAW,CAAC;CACnB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEN,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,aAAa,EACpB,SAAS,EAAE,iBAAiB,EAC5B,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EACzC,OAAO,EAAE,eAAe,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,EACD,OAAO,EAAE,eAAe,GACvB,MAAM,CAkER"}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { dump } from 'js-yaml';
|
|
2
2
|
import Slugger from 'github-slugger';
|
|
3
3
|
import { idToTitle } from '../utils/id-to-title.js';
|
|
4
|
-
export function generateDocument(options) {
|
|
4
|
+
export function generateDocument(input, processed, pageProps, options, context) {
|
|
5
5
|
const { frontmatter, includeDescription = false, addGeneratedComment = true, } = options;
|
|
6
6
|
const out = [];
|
|
7
|
-
const extend = frontmatter?.(options.title, options.description,
|
|
7
|
+
const extend = frontmatter?.(options.title, options.description, context);
|
|
8
|
+
const page = {
|
|
9
|
+
...pageProps,
|
|
10
|
+
document: options.inlineDocument ? processed.downloaded : input,
|
|
11
|
+
};
|
|
8
12
|
let meta;
|
|
9
|
-
if (
|
|
10
|
-
const operation =
|
|
13
|
+
if (page.operations?.length === 1) {
|
|
14
|
+
const operation = page.operations[0];
|
|
11
15
|
meta = {
|
|
12
16
|
method: operation.method.toUpperCase(),
|
|
13
17
|
route: operation.path,
|
|
14
18
|
};
|
|
15
19
|
}
|
|
16
|
-
const data = generateStaticData(
|
|
20
|
+
const data = generateStaticData(processed.document, page);
|
|
17
21
|
const banner = dump({
|
|
18
22
|
title: options.title,
|
|
19
23
|
description: !includeDescription ? options.description : undefined,
|
|
@@ -43,7 +47,7 @@ export function generateDocument(options) {
|
|
|
43
47
|
}
|
|
44
48
|
if (options.description && includeDescription)
|
|
45
49
|
out.push(options.description);
|
|
46
|
-
out.push(pageContent(
|
|
50
|
+
out.push(pageContent(page));
|
|
47
51
|
return out.join('\n\n');
|
|
48
52
|
}
|
|
49
53
|
function generateStaticData(dereferenced, props) {
|
|
@@ -10,5 +10,5 @@ export type ProcessedDocument = {
|
|
|
10
10
|
/**
|
|
11
11
|
* process & reference input document to a Fumadocs OpenAPI compatible format
|
|
12
12
|
*/
|
|
13
|
-
export declare function processDocument(
|
|
13
|
+
export declare function processDocument(input: DocumentInput, disableCache?: boolean): Promise<ProcessedDocument>;
|
|
14
14
|
//# sourceMappingURL=process-document.d.ts.map
|