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.
Files changed (49) hide show
  1. package/dist/generate-file.d.ts +55 -20
  2. package/dist/generate-file.d.ts.map +1 -1
  3. package/dist/generate-file.js +93 -68
  4. package/dist/generate.d.ts +10 -10
  5. package/dist/generate.d.ts.map +1 -1
  6. package/dist/generate.js +33 -64
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +0 -1
  10. package/dist/playground/inputs.d.ts +4 -8
  11. package/dist/playground/inputs.d.ts.map +1 -1
  12. package/dist/playground/inputs.js +56 -37
  13. package/dist/render/api-page.d.ts.map +1 -1
  14. package/dist/render/markdown.d.ts.map +1 -1
  15. package/dist/render/markdown.js +15 -11
  16. package/dist/render/operation/api-example.js +10 -6
  17. package/dist/render/operation/index.d.ts +1 -1
  18. package/dist/render/operation/index.d.ts.map +1 -1
  19. package/dist/render/operation/index.js +4 -16
  20. package/dist/render/renderer.d.ts +1 -0
  21. package/dist/render/renderer.d.ts.map +1 -1
  22. package/dist/render/schema.d.ts +5 -15
  23. package/dist/render/schema.d.ts.map +1 -1
  24. package/dist/render/schema.js +178 -97
  25. package/dist/server/create.d.ts +1 -7
  26. package/dist/server/create.d.ts.map +1 -1
  27. package/dist/server/proxy.d.ts +11 -1
  28. package/dist/server/proxy.d.ts.map +1 -1
  29. package/dist/server/proxy.js +10 -3
  30. package/dist/server/source-api.d.ts +3 -2
  31. package/dist/server/source-api.d.ts.map +1 -1
  32. package/dist/ui/client.js +1 -1
  33. package/dist/ui/index.d.ts +1 -1
  34. package/dist/ui/index.d.ts.map +1 -1
  35. package/dist/ui/index.js +4 -4
  36. package/dist/utils/combine-schema.d.ts.map +1 -1
  37. package/dist/utils/combine-schema.js +22 -27
  38. package/dist/utils/generate-document.d.ts +4 -7
  39. package/dist/utils/generate-document.d.ts.map +1 -1
  40. package/dist/utils/generate-document.js +10 -6
  41. package/dist/utils/process-document.d.ts +1 -1
  42. package/dist/utils/process-document.d.ts.map +1 -1
  43. package/dist/utils/process-document.js +8 -5
  44. package/dist/utils/schema-to-string.d.ts.map +1 -1
  45. package/dist/utils/schema-to-string.js +8 -21
  46. package/dist/utils/schema.d.ts +1 -1
  47. package/dist/utils/schema.d.ts.map +1 -1
  48. package/dist/utils/schema.js +5 -8
  49. package/package.json +12 -12
@@ -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, parseObject = true, ctx, }) {
15
- const { render: { renderer }, stack = [], } = ctx;
16
- if (schema === true) {
17
- return _jsx(renderer.Property, { name: name, type: "any" });
18
- }
19
- else if (schema === false) {
20
- return _jsx(renderer.Property, { name: name, type: "never" });
21
- }
22
- if ((schema.readOnly === true && !ctx.readOnly) ||
23
- (schema.writeOnly === true && !ctx.writeOnly))
24
- return null;
25
- if (Array.isArray(schema.type) && schema.type.length === 1) {
26
- return (_jsx(Schema, { name: name, required: required, parseObject: parseObject, schema: {
27
- ...schema,
28
- type: schema.type[0],
29
- }, ctx: {
30
- ...ctx,
31
- stack: [schema, ...stack],
32
- } }));
33
- }
34
- if (schema.allOf || schema.anyOf) {
35
- return (_jsx(Schema, { name: name, parseObject: parseObject, required: required, schema: combineSchema([
36
- ...(schema.allOf ?? []),
37
- ...(schema.anyOf ?? []),
38
- ]), ctx: {
39
- ...ctx,
40
- stack: [schema, ...stack],
41
- } }));
42
- }
43
- // object type
44
- if (schema.type === 'object' && parseObject) {
45
- const { additionalProperties, patternProperties, properties } = schema;
46
- return (_jsxs("div", { className: "flex flex-col gap-4", children: [properties &&
47
- Object.entries(properties).map(([key, value]) => {
48
- return (_jsx(Schema, { name: key, schema: value, parseObject: false, required: schema.required?.includes(key) ?? false, ctx: {
49
- ...ctx,
50
- stack: [schema, ...stack],
51
- } }, key));
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
- let footer;
64
- const fields = [];
65
- for (const [key, value] of Object.entries(keys)) {
66
- if (key in schema) {
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: value,
69
- value: JSON.stringify(schema[key]),
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
- if (schema.enum) {
74
- fields.push({
75
- key: 'Value in',
76
- value: schema.enum.map((value) => JSON.stringify(value)).join(' | '),
77
- });
78
- }
79
- if (schema.type === 'object' && !parseObject && !stack.includes(schema)) {
80
- footer = (_jsx(renderer.ObjectCollapsible, { name: "Show Attributes", children: _jsx(Schema, { name: name, schema: schema, ctx: {
81
- ...ctx,
82
- stack: [schema, ...stack],
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
- else {
86
- let mentionedObjectTypes = [];
87
- if (Array.isArray(schema.type)) {
88
- mentionedObjectTypes.push(...schema.type.map((type) => ({
89
- ...schema,
90
- type,
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.oneOf)
94
- mentionedObjectTypes.push(...schema.oneOf);
95
- if (schema.not)
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
- return (_jsxs(renderer.Property, { name: name, type: schemaToString(schema), required: required, deprecated: schema.deprecated, children: [schema.description ? _jsx(Markdown, { text: schema.description }) : null, fields.length > 0 ? (_jsx("div", { className: "flex flex-col gap-2", children: fields.map((field) => (_jsxs("span", { children: [field.key, ": ", _jsx("code", { children: field.value })] }, field.key))) })) : null, footer] }));
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
- if (schema.anyOf ?? schema.oneOf ?? schema.allOf)
179
+ const arr = schema.anyOf ?? schema.oneOf ?? schema.allOf;
180
+ if (arr && arr.some(isComplexType))
121
181
  return true;
122
- return schema.type === 'object' || schema.type === 'array';
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
  }
@@ -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 interface OpenAPIOptions extends Omit<Partial<ApiPageProps>, 'document'> {
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,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,UAAU,CAAC;IAC/C;;OAEG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,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"}
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"}
@@ -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
- export declare function createProxy(allowedUrls?: string[]): Proxy;
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,wBAAgB,WAAW,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,CAoEzD"}
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"}
@@ -1,5 +1,6 @@
1
1
  const keys = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'];
2
- export function createProxy(allowedUrls) {
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
- const clonedReq = new Request(url, {
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
- const res = await fetch(clonedReq).catch((e) => new Error(e.toString()));
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 { BuildPageTreeOptions } from 'fumadocs-core/source';
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: BuildPageTreeOptions['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,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGjE;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,oBAAoB,CAAC,YAAY,CAyBzD,CAAC"}
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-fd-foreground mb-2", children: "TypeScript Definitions" }), _jsx("p", { className: "text-xs", children: "Use the response body type in TypeScript." })] }), _jsxs("button", { onClick: onCopy, className: cn(buttonVariants({
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',
@@ -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, children, }: PropertyProps): import("react/jsx-runtime").JSX.Element;
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;
@@ -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,2CAyB5C;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,QAAQ,GACT,EAAE,aAAa,2CAsBf;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,2CAiBA;AAED,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,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 text-fd-muted-foreground', 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 }) }));
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, children, }) {
21
- return (_jsxs("div", { className: "rounded-xl border bg-fd-card p-3 prose-no-margin", children: [_jsxs("div", { className: "flex flex-row flex-wrap items-center gap-4 mb-2", children: [_jsx("code", { children: name }), required ? (_jsx(Badge, { color: "red", className: "text-xs", children: "Required" })) : null, deprecated ? (_jsx(Badge, { color: "yellow", className: "text-xs", children: "Deprecated" })) : null, _jsx("span", { className: "ms-auto text-xs font-mono text-fd-muted-foreground", children: type })] }), children] }));
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: 'outline', size: 'sm' }), 'group rounded-full px-2 py-1.5 text-fd-muted-foreground'), children: [props.name, _jsx(ChevronDown, { className: "size-4 group-data-[state=open]:rotate-180" })] }), _jsx(CollapsibleContent, { className: "-mx-2", children: _jsx("div", { className: "flex flex-col gap-2 p-2", children: props.children }) })] }));
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,CA+DlE"}
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
- type: undefined,
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
- if (Array.isArray(result.type) && !result.type.includes(v)) {
22
- result.type.push(v);
23
- }
19
+ types.add(v);
24
20
  }
25
21
  }
26
- if (s.properties) {
27
- result.properties ?? (result.properties = {});
28
- Object.assign(result.properties, s.properties);
22
+ for (const key of ['oneOf', 'required', 'enum']) {
23
+ if (!s[key])
24
+ continue;
25
+ result[key] = [...s[key], ...(result[key] ?? [])];
29
26
  }
30
- if (s.patternProperties) {
31
- result.patternProperties ?? (result.patternProperties = {});
32
- Object.assign(result.patternProperties, s.patternProperties);
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
- if (s.required) {
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 { Document, TagObject } from '../types.js';
4
- import type { NoReference } from '../utils/schema.js';
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
- context: DocumentContext;
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,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAOlD,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,OAAO,EAAE,eAAe,GAAG;IACzB,YAAY,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,eAAe,CAAC;CAC1B,GACA,MAAM,CAkER"}
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, options.context);
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 (options.page.operations?.length === 1) {
10
- const operation = options.page.operations[0];
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(options.dereferenced, options.page);
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(options.page));
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(document: DocumentInput, disableCache?: boolean): Promise<ProcessedDocument>;
13
+ export declare function processDocument(input: DocumentInput, disableCache?: boolean): Promise<ProcessedDocument>;
14
14
  //# sourceMappingURL=process-document.d.ts.map