fumadocs-openapi 9.0.3 → 9.0.5
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/auth/oauth-dialog.d.ts +4 -2
- package/dist/playground/auth/oauth-dialog.d.ts.map +1 -1
- package/dist/playground/auth/oauth-dialog.js +113 -26
- package/dist/playground/client.d.ts.map +1 -1
- package/dist/playground/client.js +101 -63
- package/dist/playground/index.js +26 -15
- package/dist/playground/inputs.d.ts +8 -2
- package/dist/playground/inputs.d.ts.map +1 -1
- package/dist/playground/inputs.js +32 -31
- package/dist/render/heading.d.ts +1 -1
- package/dist/render/heading.d.ts.map +1 -1
- package/dist/render/heading.js +3 -3
- package/dist/render/markdown.d.ts +2 -2
- package/dist/render/markdown.d.ts.map +1 -1
- package/dist/render/markdown.js +4 -2
- package/dist/render/operation/index.d.ts.map +1 -1
- package/dist/render/operation/index.js +68 -58
- package/dist/render/renderer.d.ts.map +1 -1
- package/dist/render/renderer.js +3 -3
- package/dist/render/schema.d.ts.map +1 -1
- package/dist/render/schema.js +7 -8
- package/dist/server/proxy.d.ts +16 -1
- package/dist/server/proxy.d.ts.map +1 -1
- package/dist/server/proxy.js +31 -17
- package/dist/ui/components/accordion.d.ts +8 -0
- package/dist/ui/components/accordion.d.ts.map +1 -0
- package/dist/ui/components/accordion.js +20 -0
- package/dist/ui/components/input.js +1 -1
- package/dist/ui/components/select.js +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +4 -2
- package/dist/ui/select-tabs.d.ts +13 -0
- package/dist/ui/select-tabs.d.ts.map +1 -0
- package/dist/ui/select-tabs.js +20 -0
- package/dist/ui/server-select.d.ts.map +1 -1
- package/dist/ui/server-select.js +22 -15
- package/dist/utils/schema-to-string.d.ts.map +1 -1
- package/dist/utils/schema-to-string.js +10 -1
- package/dist/utils/schema.d.ts +0 -1
- package/dist/utils/schema.d.ts.map +1 -1
- package/dist/utils/schema.js +0 -10
- package/package.json +10 -9
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useMemo, useState, } from 'react';
|
|
4
|
-
import { Plus, Trash2 } from '../icons.js';
|
|
4
|
+
import { ChevronDown, Plus, Trash2 } from '../icons.js';
|
|
5
5
|
import { Controller, useController, useFieldArray, useFormContext, } from 'react-hook-form';
|
|
6
6
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/components/select.js';
|
|
7
7
|
import { Input, labelVariants } from '../ui/components/input.js';
|
|
@@ -11,10 +11,13 @@ import { buttonVariants } from 'fumadocs-ui/components/ui/button';
|
|
|
11
11
|
import { combineSchema } from '../utils/combine-schema.js';
|
|
12
12
|
import { schemaToString } from '../utils/schema-to-string.js';
|
|
13
13
|
import { anyFields, useFieldInfo, useResolvedSchema, } from '../playground/schema.js';
|
|
14
|
-
function
|
|
15
|
-
return (
|
|
14
|
+
function FieldLabel(props) {
|
|
15
|
+
return (_jsx("label", { ...props, className: cn('w-full inline-flex items-center gap-0.5', props.className), children: props.children }));
|
|
16
16
|
}
|
|
17
|
-
function
|
|
17
|
+
function FieldLabelName({ required = false, ...props }) {
|
|
18
|
+
return (_jsxs("span", { ...props, className: cn(labelVariants(), 'font-mono me-auto', props.className), children: [props.children, required && _jsx("span", { className: "text-red-400/80 mx-1", children: "*" })] }));
|
|
19
|
+
}
|
|
20
|
+
function FieldLabelType(props) {
|
|
18
21
|
return (_jsx("code", { ...props, className: cn('text-xs text-fd-muted-foreground', props.className), children: props.children }));
|
|
19
22
|
}
|
|
20
23
|
export function ObjectInput({ field: _field, fieldName, ...props }) {
|
|
@@ -22,7 +25,7 @@ export function ObjectInput({ field: _field, fieldName, ...props }) {
|
|
|
22
25
|
const field = useMemo(() => combineSchema([resolved]), [resolved]);
|
|
23
26
|
if (typeof field === 'boolean')
|
|
24
27
|
return;
|
|
25
|
-
return (_jsxs("div", { ...props, className: cn('
|
|
28
|
+
return (_jsxs("div", { ...props, className: cn('grid grid-cols-1 gap-4 @md:grid-cols-2', props.className), children: [Object.entries(field.properties ?? {}).map(([key, child]) => (_jsx(FieldSet, { name: key, field: child, fieldName: `${fieldName}.${key}`, isRequired: field.required?.includes(key) }, key))), (field.additionalProperties || field.patternProperties) && (_jsx(DynamicProperties, { fieldName: fieldName, filterKey: (v) => !field.properties || !Object.keys(field.properties).includes(v), getType: (key) => {
|
|
26
29
|
for (const pattern in field.patternProperties) {
|
|
27
30
|
if (key.match(RegExp(pattern))) {
|
|
28
31
|
return field.patternProperties[pattern];
|
|
@@ -73,9 +76,8 @@ function DynamicProperties({ fieldName, filterKey = () => true, getType = () =>
|
|
|
73
76
|
return (_jsxs(_Fragment, { children: [properties.map((item) => {
|
|
74
77
|
const type = getType(item);
|
|
75
78
|
return (_jsx(FieldSet, { name: item, field: type, fieldName: `${fieldName}.${item}`, toolbar: _jsx("button", { type: "button", "aria-label": "Remove Item", className: cn(buttonVariants({
|
|
76
|
-
color: '
|
|
77
|
-
size: 'icon-
|
|
78
|
-
className: 'p-1',
|
|
79
|
+
color: 'outline',
|
|
80
|
+
size: 'icon-xs',
|
|
79
81
|
})), onClick: () => {
|
|
80
82
|
setProperties((p) => p.filter((prop) => prop !== item));
|
|
81
83
|
control.unregister(`${fieldName}.${item}`);
|
|
@@ -87,14 +89,18 @@ function DynamicProperties({ fieldName, filterKey = () => true, getType = () =>
|
|
|
87
89
|
}
|
|
88
90
|
} }), _jsx("button", { type: "button", className: cn(buttonVariants({ color: 'secondary', size: 'sm' }), 'px-4'), onClick: onAppend, children: "New" })] })] }));
|
|
89
91
|
}
|
|
90
|
-
function FieldInput({ field, fieldName, isRequired, ...props }) {
|
|
92
|
+
export function FieldInput({ field, fieldName, isRequired, ...props }) {
|
|
91
93
|
const { control, register } = useFormContext();
|
|
92
94
|
if (field.type === 'string' && field.format === 'binary') {
|
|
93
|
-
return (_jsx(Controller, { control: control, name: fieldName, render: ({ field: { value
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
return (_jsx(Controller, { control: control, name: fieldName, render: ({ field: { value, onChange, ...restField } }) => (_jsxs("div", { ...props, children: [_jsx("label", { htmlFor: fieldName, className: cn(buttonVariants({
|
|
96
|
+
color: 'secondary',
|
|
97
|
+
size: 'sm',
|
|
98
|
+
className: 'w-full',
|
|
99
|
+
})), children: value ? value.name : 'Upload' }), _jsx("input", { id: fieldName, type: "file", multiple: false, onChange: (e) => {
|
|
100
|
+
if (!e.target.files)
|
|
101
|
+
return;
|
|
102
|
+
onChange(e.target.files.item(0));
|
|
103
|
+
}, hidden: true, ...restField })] })) }));
|
|
98
104
|
}
|
|
99
105
|
if (field.type === 'boolean') {
|
|
100
106
|
return (_jsx(Controller, { control: control, name: fieldName, render: ({ field: { value, onChange, ...restField } }) => (_jsxs(Select, { value: String(value), onValueChange: (value) => onChange(value === 'null' ? null : value === 'true'), disabled: restField.disabled, children: [_jsx(SelectTrigger, { id: fieldName, className: props.className, ...restField, children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "true", children: "True" }), _jsx(SelectItem, { value: "false", children: "False" }), !isRequired && _jsx(SelectItem, { value: "null", children: "Null" })] })] })) }));
|
|
@@ -105,21 +111,12 @@ function FieldInput({ field, fieldName, isRequired, ...props }) {
|
|
|
105
111
|
valueAsNumber: field.type === 'number' || field.type === 'integer',
|
|
106
112
|
}), ...props }));
|
|
107
113
|
}
|
|
108
|
-
export function FieldSet({ field: _field, fieldName, toolbar, name, isRequired, depth = 0, slotType, ...props }) {
|
|
114
|
+
export function FieldSet({ field: _field, fieldName, toolbar, name, isRequired, depth = 0, slotType, collapsible = true, ...props }) {
|
|
109
115
|
const field = useResolvedSchema(_field);
|
|
110
|
-
const [show, setShow] = useState(
|
|
116
|
+
const [show, setShow] = useState(!collapsible);
|
|
111
117
|
const { info, updateInfo } = useFieldInfo(fieldName, field, depth);
|
|
112
118
|
if (_field === false)
|
|
113
119
|
return null;
|
|
114
|
-
const recursive = typeof _field !== 'boolean' &&
|
|
115
|
-
_field.$ref &&
|
|
116
|
-
(field.oneOf || field.type === 'object' || field.allOf || field.anyOf);
|
|
117
|
-
if (recursive && !show) {
|
|
118
|
-
return (_jsxs(FieldHeader, { ...props, name: name, required: isRequired, children: [slotType ?? _jsx(FieldHeaderCode, { children: schemaToString(field) }), toolbar, _jsx("button", { type: "button", className: cn(buttonVariants({
|
|
119
|
-
size: 'sm',
|
|
120
|
-
color: 'secondary',
|
|
121
|
-
})), onClick: () => setShow(true), children: "Open" })] }));
|
|
122
|
-
}
|
|
123
120
|
if (field.oneOf) {
|
|
124
121
|
const showSelect = field.oneOf.length > 1;
|
|
125
122
|
return (_jsx(FieldSet, { ...props, name: name, fieldName: fieldName, isRequired: isRequired, field: field.oneOf[info.oneOf], depth: depth + 1, slotType: showSelect ? false : slotType, toolbar: _jsxs(_Fragment, { children: [showSelect && (_jsx("select", { className: "text-xs font-mono", value: info.oneOf, onChange: (e) => {
|
|
@@ -139,13 +136,18 @@ export function FieldSet({ field: _field, fieldName, toolbar, name, isRequired,
|
|
|
139
136
|
});
|
|
140
137
|
}, children: field.type.map((item) => (_jsx("option", { value: item, children: item }, item))) })), toolbar] }) }));
|
|
141
138
|
}
|
|
139
|
+
const showBn = collapsible && (_jsx("button", { type: "button", onClick: () => setShow((prev) => !prev), className: cn(buttonVariants({
|
|
140
|
+
size: 'icon-xs',
|
|
141
|
+
color: 'ghost',
|
|
142
|
+
className: 'text-fd-muted-foreground -ms-1',
|
|
143
|
+
})), children: _jsx(ChevronDown, { className: cn(show && 'rotate-180') }) }));
|
|
142
144
|
if (field.type === 'object' || field.anyOf || field.allOf) {
|
|
143
|
-
return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(
|
|
145
|
+
return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5 col-span-full @container', props.className), children: [_jsxs(FieldLabel, { htmlFor: fieldName, children: [showBn, _jsx(FieldLabelName, { required: isRequired, children: name }), slotType ?? _jsx(FieldLabelType, { children: schemaToString(field) }), toolbar] }), show && (_jsx(ObjectInput, { field: field, fieldName: fieldName, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm', props.className) }))] }));
|
|
144
146
|
}
|
|
145
147
|
if (field.type === 'array') {
|
|
146
|
-
return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(
|
|
148
|
+
return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5 col-span-full', props.className), children: [_jsxs(FieldLabel, { htmlFor: fieldName, children: [showBn, _jsx(FieldLabelName, { required: isRequired, children: name }), slotType ?? _jsx(FieldLabelType, { children: schemaToString(field) }), toolbar] }), show && (_jsx(ArrayInput, { fieldName: fieldName, items: field.items ?? anyFields, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm', props.className) }))] }));
|
|
147
149
|
}
|
|
148
|
-
return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(
|
|
150
|
+
return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(FieldLabel, { htmlFor: fieldName, children: [_jsx(FieldLabelName, { required: isRequired, children: name }), slotType ?? _jsx(FieldLabelType, { children: schemaToString(field) }), toolbar] }), _jsx(FieldInput, { field: field, fieldName: fieldName, isRequired: isRequired })] }));
|
|
149
151
|
}
|
|
150
152
|
function ArrayInput({ fieldName, items, ...props }) {
|
|
151
153
|
const name = fieldName.split('.').at(-1) ?? '';
|
|
@@ -153,9 +155,8 @@ function ArrayInput({ fieldName, items, ...props }) {
|
|
|
153
155
|
name: fieldName,
|
|
154
156
|
});
|
|
155
157
|
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: [name, "[", index, "]"] }), field: items, fieldName: `${fieldName}.${index}`, toolbar: _jsx("button", { type: "button", "aria-label": "Remove Item", className: cn(buttonVariants({
|
|
156
|
-
color: '
|
|
157
|
-
size: 'icon-
|
|
158
|
-
className: 'p-1',
|
|
158
|
+
color: 'outline',
|
|
159
|
+
size: 'icon-xs',
|
|
159
160
|
})), onClick: () => remove(index), children: _jsx(Trash2, {}) }) }, item.id))), _jsxs("button", { type: "button", className: cn(buttonVariants({
|
|
160
161
|
color: 'secondary',
|
|
161
162
|
className: 'gap-1.5 py-2',
|
package/dist/render/heading.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { RenderContext } from '../types.js';
|
|
3
|
-
export declare function heading(depth: number,
|
|
3
|
+
export declare function heading(depth: number, text: string, ctx: RenderContext, children?: ReactNode): ReactNode;
|
|
4
4
|
//# sourceMappingURL=heading.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../src/render/heading.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,wBAAgB,OAAO,CACrB,KAAK,EAAE,MAAM,EACb,
|
|
1
|
+
{"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../src/render/heading.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,wBAAgB,OAAO,CACrB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,aAAa,EAClB,QAAQ,GAAE,SAAgB,GACzB,SAAS,CAQX"}
|
package/dist/render/heading.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Heading } from 'fumadocs-ui/components/heading';
|
|
3
|
-
export function heading(depth,
|
|
4
|
-
const id = ctx.slugger.slug(
|
|
5
|
-
return (_jsx(Heading, { id: id, as: `h${depth.toString()}`, children:
|
|
3
|
+
export function heading(depth, text, ctx, children = text) {
|
|
4
|
+
const id = ctx.slugger.slug(text);
|
|
5
|
+
return (_jsx(Heading, { id: id, as: `h${depth.toString()}`, children: children }, id));
|
|
6
6
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReactElement } from 'react';
|
|
2
|
-
export declare function Markdown({ text
|
|
2
|
+
export declare function Markdown({ text }: {
|
|
3
3
|
text: string;
|
|
4
|
-
}): Promise<ReactElement
|
|
4
|
+
}): Promise<ReactElement<unknown, string | import("react").JSXElementConstructor<any>>>;
|
|
5
5
|
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/render/markdown.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAkC1C,wBAAsB,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/render/markdown.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAkC1C,wBAAsB,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,uFAMxD"}
|
package/dist/render/markdown.js
CHANGED
|
@@ -23,7 +23,9 @@ function rehypeReact() {
|
|
|
23
23
|
});
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
-
export async function Markdown({ text
|
|
27
|
-
const out = await processor.process(
|
|
26
|
+
export async function Markdown({ text }) {
|
|
27
|
+
const out = await processor.process({
|
|
28
|
+
value: text,
|
|
29
|
+
});
|
|
28
30
|
return out.result;
|
|
29
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/render/operation/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,YAAY,EAAkB,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAEV,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/render/operation/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,YAAY,EAAkB,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAEV,iBAAiB,EACjB,aAAa,EAEd,MAAM,SAAS,CAAC;AAcjB,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAY1D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,KAAK,CAAC;CAC3C;AASD,wBAAgB,SAAS,CAAC,EACxB,IAAkB,EAClB,IAAI,EACJ,MAAM,EACN,GAAG,EACH,OAAO,EACP,YAAgB,GACjB,EAAE;IACD,IAAI,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,GAAG,EAAE,aAAa,CAAC;IAEnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,YAAY,CAgNf"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Fragment } from 'react';
|
|
3
|
-
import { getPreferredType, } from '../../utils/schema.js';
|
|
4
3
|
import { idToTitle } from '../../utils/id-to-title.js';
|
|
5
4
|
import { Markdown } from '../markdown.js';
|
|
6
5
|
import { heading } from '../heading.js';
|
|
@@ -8,10 +7,11 @@ import { Schema } from '../schema.js';
|
|
|
8
7
|
import { createMethod } from '../../server/create-method.js';
|
|
9
8
|
import { methodKeys } from '../../build-routes.js';
|
|
10
9
|
import { APIExample, APIExampleProvider, getAPIExamples, } from '../../render/operation/api-example.js';
|
|
11
|
-
import {
|
|
12
|
-
import { Tab, Tabs, TabsContent, TabsList, TabsTrigger, } from 'fumadocs-ui/components/tabs';
|
|
10
|
+
import { MethodLabel } from '../../ui/components/method-label.js';
|
|
13
11
|
import { getTypescriptSchema } from '../../utils/get-typescript-schema.js';
|
|
14
12
|
import { CopyResponseTypeScript } from '../../ui/client.js';
|
|
13
|
+
import { SelectTab, SelectTabs, SelectTabTrigger } from '../../ui/select-tabs.js';
|
|
14
|
+
import { AccordionContent, AccordionHeader, AccordionItem, Accordions, AccordionTrigger, } from '../../ui/components/accordion.js';
|
|
15
15
|
const ParamTypes = {
|
|
16
16
|
path: 'Path Parameters',
|
|
17
17
|
query: 'Query Parameters',
|
|
@@ -22,6 +22,7 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
|
|
|
22
22
|
const body = method.requestBody;
|
|
23
23
|
let headNode = null;
|
|
24
24
|
let bodyNode = null;
|
|
25
|
+
let authNode = null;
|
|
25
26
|
let responseNode = null;
|
|
26
27
|
let callbacksNode = null;
|
|
27
28
|
if (hasHead) {
|
|
@@ -30,34 +31,48 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
|
|
|
30
31
|
headNode = (_jsxs(_Fragment, { children: [heading(headingLevel, title, ctx), method.description ? _jsx(Markdown, { text: method.description }) : null] }));
|
|
31
32
|
headingLevel++;
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
const contentTypes = body ? Object.entries(body.content) : null;
|
|
35
|
+
if (body && contentTypes && contentTypes.length > 0) {
|
|
36
|
+
bodyNode = (_jsxs(SelectTabs, { defaultValue: contentTypes[0][0], children: [_jsxs("div", { className: "flex gap-2 items-end justify-between", children: [heading(headingLevel, 'Request Body', ctx), _jsx(SelectTabTrigger, { items: contentTypes.map((v) => v[0]), className: "mb-4" })] }), body.description && _jsx(Markdown, { text: body.description }), contentTypes.map(([type, content]) => {
|
|
37
|
+
if (!(type in ctx.mediaAdapters)) {
|
|
38
|
+
throw new Error(`Media type ${type} is not supported (in ${path})`);
|
|
39
|
+
}
|
|
40
|
+
return (_jsx(SelectTab, { value: type, children: _jsx(Schema, { name: "body", as: "body", schema: (content.schema ?? {}), required: body.required, readOnly: method.method === 'GET', writeOnly: method.method !== 'GET', ctx: ctx }) }, type));
|
|
41
|
+
})] }));
|
|
38
42
|
}
|
|
39
43
|
if (method.responses && ctx.showResponseSchema !== false) {
|
|
40
44
|
const statuses = Object.keys(method.responses);
|
|
41
|
-
responseNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Response Body', ctx), _jsx(
|
|
45
|
+
responseNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Response Body', ctx), _jsx(Accordions, { type: "multiple", children: statuses.map((status) => (_jsx(AccordionItem, { value: status, children: _jsx(ResponseAccordion, { status: status, operation: method, ctx: ctx }) }, status))) })] }));
|
|
42
46
|
}
|
|
43
47
|
const parameterNode = Object.entries(ParamTypes).map(([type, title]) => {
|
|
44
48
|
const params = method.parameters?.filter((param) => param.in === type);
|
|
45
49
|
if (!params || params.length === 0)
|
|
46
50
|
return;
|
|
47
|
-
return (_jsxs(Fragment, { children: [heading(headingLevel, title, ctx), _jsx("div", { className: "flex flex-col
|
|
51
|
+
return (_jsxs(Fragment, { children: [heading(headingLevel, title, ctx), _jsx("div", { className: "flex flex-col", children: params.map((param) => (_jsx(Schema, { name: param.name, schema: {
|
|
48
52
|
...param.schema,
|
|
49
53
|
description: param.description ?? param.schema?.description,
|
|
50
54
|
deprecated: (param.deprecated ?? false) ||
|
|
51
55
|
(param.schema?.deprecated ?? false),
|
|
52
56
|
}, required: param.required, readOnly: method.method === 'GET', writeOnly: method.method !== 'GET', ctx: ctx }, param.name))) })] }, type));
|
|
53
57
|
});
|
|
54
|
-
|
|
55
|
-
callbacksNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Webhooks', ctx), Object.entries(method.callbacks).map(([name, callback]) => (_jsx(WebhookCallback, { callback: callback, ctx: ctx, headingLevel: headingLevel }, name)))] }));
|
|
56
|
-
}
|
|
57
|
-
const security = (method.security ??
|
|
58
|
+
const securities = (method.security ??
|
|
58
59
|
ctx.schema.document.security ??
|
|
59
60
|
[]).filter((v) => Object.keys(v).length > 0);
|
|
60
|
-
|
|
61
|
+
if (type === 'operation' && securities.length > 0) {
|
|
62
|
+
const securitySchemes = ctx.schema.document.components?.securitySchemes;
|
|
63
|
+
const names = securities.map((security) => Object.keys(security).join(' & '));
|
|
64
|
+
authNode = (_jsxs(SelectTabs, { defaultValue: names[0], children: [_jsxs("div", { className: "flex items-end justify-between gap-2", children: [heading(headingLevel, 'Authorization', ctx), _jsx(SelectTabTrigger, { items: names, className: "mb-4" })] }), securities.map((security, i) => (_jsx(SelectTab, { value: names[i], children: Object.entries(security).map(([key, scopes]) => {
|
|
65
|
+
const scheme = securitySchemes?.[key];
|
|
66
|
+
if (!scheme)
|
|
67
|
+
return;
|
|
68
|
+
return (_jsx(AuthScheme, { scheme: scheme, scopes: scopes, ctx: ctx }, key));
|
|
69
|
+
}) }, i)))] }));
|
|
70
|
+
}
|
|
71
|
+
if (method.callbacks) {
|
|
72
|
+
const callbacks = Object.entries(method.callbacks);
|
|
73
|
+
callbacksNode = (_jsxs(SelectTabs, { defaultValue: callbacks[0][0], children: [_jsxs("div", { className: "flex justify-between gap-2 items-end", children: [heading(headingLevel, 'Callbacks', ctx), _jsx(SelectTabTrigger, { items: callbacks.map((v) => v[0]), className: "mb-4" })] }), callbacks.map(([name, callback]) => (_jsx(SelectTab, { value: name, children: _jsx(WebhookCallback, { callback: callback, ctx: ctx, headingLevel: headingLevel }) }, name)))] }));
|
|
74
|
+
}
|
|
75
|
+
const info = (_jsxs(ctx.renderer.APIInfo, { head: headNode, method: method.method, route: path, children: [type === 'operation' ? (ctx.disablePlayground ? (_jsxs("div", { className: "flex flex-row items-center gap-2.5 p-3 rounded-xl border bg-fd-card text-fd-card-foreground not-prose", children: [_jsx(MethodLabel, { className: "text-xs", children: method.method }), _jsx("code", { className: "flex-1 overflow-auto text-nowrap text-[13px] text-fd-muted-foreground", children: path })] })) : (_jsx(ctx.renderer.APIPlayground, { path: path, method: method, ctx: ctx }))) : null, authNode, parameterNode, bodyNode, responseNode, callbacksNode] }));
|
|
61
76
|
if (type === 'operation') {
|
|
62
77
|
const examples = getAPIExamples(path, method, ctx);
|
|
63
78
|
return (_jsx(ctx.renderer.API, { children: _jsxs(APIExampleProvider, { route: path, examples: examples, method: method, children: [info, _jsx(APIExample, { examples: examples, method: method, ctx: ctx })] }) }));
|
|
@@ -66,52 +81,47 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
|
|
|
66
81
|
return info;
|
|
67
82
|
}
|
|
68
83
|
}
|
|
69
|
-
async function
|
|
84
|
+
async function ResponseAccordion({ status, operation, ctx, }) {
|
|
70
85
|
const response = operation.responses[status];
|
|
71
|
-
const { generateTypeScriptSchema, schema } = ctx;
|
|
72
|
-
const
|
|
73
|
-
?
|
|
86
|
+
const { generateTypeScriptSchema, schema: { dereferenceMap }, } = ctx;
|
|
87
|
+
const contentTypes = response.content
|
|
88
|
+
? Object.entries(response.content)
|
|
74
89
|
: null;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
90
|
+
return (_jsxs(SelectTabs, { defaultValue: contentTypes?.[0][0], children: [_jsxs(AccordionHeader, { children: [_jsx(AccordionTrigger, { className: "font-mono", children: status }), contentTypes && (_jsx(SelectTabTrigger, { items: contentTypes.map((v) => v[0]) }))] }), _jsxs(AccordionContent, { children: [response.description && (_jsx("div", { className: "prose-no-margin", children: _jsx(Markdown, { text: response.description }) })), contentTypes?.map(async ([type, resType]) => {
|
|
91
|
+
const schema = resType.schema;
|
|
92
|
+
let ts;
|
|
93
|
+
if (generateTypeScriptSchema) {
|
|
94
|
+
ts = await generateTypeScriptSchema(operation, status);
|
|
95
|
+
}
|
|
96
|
+
else if (generateTypeScriptSchema === undefined && schema) {
|
|
97
|
+
ts = await getTypescriptSchema(schema, dereferenceMap);
|
|
98
|
+
}
|
|
99
|
+
return (_jsxs(SelectTab, { value: type, className: "mt-2", children: [ts && _jsx(CopyResponseTypeScript, { code: ts }), schema && (_jsx("div", { className: "border px-3 rounded-lg my-2 overflow-auto max-h-[400px]", children: _jsx(Schema, { name: "response", schema: schema, as: "body", readOnly: true, ctx: ctx }) }))] }, type));
|
|
100
|
+
})] })] }));
|
|
85
101
|
}
|
|
86
102
|
function WebhookCallback({ callback, ctx, headingLevel, }) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
103
|
+
const pathItems = Object.entries(callback);
|
|
104
|
+
return (_jsx(Accordions, { type: "single", collapsible: true, children: pathItems.map(([path, pathItem]) => {
|
|
105
|
+
const pathNodes = methodKeys.map((method) => {
|
|
106
|
+
const operation = pathItem[method];
|
|
107
|
+
if (!operation)
|
|
108
|
+
return null;
|
|
109
|
+
return (_jsx("div", { className: "border p-3 my-2 prose-no-margin rounded-lg", children: _jsx(Operation, { type: "webhook", path: path, headingLevel: headingLevel + 1, method: createMethod(method, pathItem, operation), ctx: ctx }) }, method));
|
|
110
|
+
});
|
|
111
|
+
return (_jsxs(AccordionItem, { value: path, children: [_jsx(AccordionHeader, { children: _jsx(AccordionTrigger, { className: "font-mono", children: path }) }), _jsx(AccordionContent, { children: pathNodes })] }, path));
|
|
112
|
+
}) }));
|
|
96
113
|
}
|
|
97
|
-
function
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return (_jsxs(renderer.Property, { name: schema.name, type: "<token>", children: [schema.description && (_jsx(Markdown, { text: schema.description })), _jsxs("p", { children: ["In: ", _jsx("code", { children: schema.in }), scopeElement] })] }, key));
|
|
111
|
-
}
|
|
112
|
-
if (schema.type === 'openIdConnect') {
|
|
113
|
-
return (_jsxs(renderer.Property, { name: "OpenID Connect", type: "<token>", required: true, children: [schema.description && (_jsx(Markdown, { text: schema.description })), scopeElement] }, key));
|
|
114
|
-
}
|
|
115
|
-
}) }, i));
|
|
116
|
-
})] }));
|
|
114
|
+
function AuthScheme({ scheme: schema, scopes, ctx: { renderer }, }) {
|
|
115
|
+
const scopeElement = scopes.length > 0 ? (_jsxs("p", { children: ["Scope: ", _jsx("code", { children: scopes.join(', ') })] })) : null;
|
|
116
|
+
if (schema.type === 'http' || schema.type === 'oauth2') {
|
|
117
|
+
return (_jsxs(renderer.Property, { name: "Authorization", type: schema.type === 'http' && schema.scheme === 'basic'
|
|
118
|
+
? `Basic <token>`
|
|
119
|
+
: 'Bearer <token>', required: true, children: [schema.description && _jsx(Markdown, { text: schema.description }), _jsxs("p", { children: ["In: ", _jsx("code", { children: "header" })] }), scopeElement] }));
|
|
120
|
+
}
|
|
121
|
+
if (schema.type === 'apiKey') {
|
|
122
|
+
return (_jsxs(renderer.Property, { name: schema.name, type: "<token>", children: [schema.description && _jsx(Markdown, { text: schema.description }), _jsxs("p", { children: ["In: ", _jsx("code", { children: schema.in }), scopeElement] })] }));
|
|
123
|
+
}
|
|
124
|
+
if (schema.type === 'openIdConnect') {
|
|
125
|
+
return (_jsxs(renderer.Property, { name: "OpenID Connect", type: "<token>", required: true, children: [schema.description && _jsx(Markdown, { text: schema.description }), scopeElement] }));
|
|
126
|
+
}
|
|
117
127
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/render/renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/render/renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAiBtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGtE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,SAAS,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;CACL;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,aAAa,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IAC/B,GAAG,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,UAAU,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAEnD,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACzC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACvC,mBAAmB,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACjD,QAAQ,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAClE,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,aAAa,EAAE,aAAa,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC7E,YAAY,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IAE/C;;OAEG;IACH,iBAAiB,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IACzD,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACvC,aAAa,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CAClD;AAED,wBAAgB,aAAa,IAAI,QAAQ,CA4CxC"}
|
package/dist/render/renderer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
|
3
|
-
import {
|
|
3
|
+
import { AccordionContent, AccordionHeader, AccordionItem, Accordions, AccordionTrigger, } from '../ui/components/accordion.js';
|
|
4
4
|
import { API, APIExample, APIInfo, ObjectCollapsible, Property, Root, } from '../ui/index.js';
|
|
5
5
|
import { APIPlayground } from '../playground/index.js';
|
|
6
6
|
import { CodeExampleSelector } from '../ui/lazy.js';
|
|
@@ -12,8 +12,8 @@ export function createRenders() {
|
|
|
12
12
|
APIExample,
|
|
13
13
|
Responses: (props) => (_jsx(Tabs, { ...props, groupId: "fumadocs_openapi_responses" })),
|
|
14
14
|
Response: Tab,
|
|
15
|
-
ResponseTypes: (props) => (_jsx(Accordions, { type: "single", className: "
|
|
16
|
-
ResponseType: (props) => (_jsx(
|
|
15
|
+
ResponseTypes: (props) => (_jsx(Accordions, { type: "single", className: "pt-2", defaultValue: props.defaultValue, children: props.children })),
|
|
16
|
+
ResponseType: (props) => (_jsxs(AccordionItem, { value: props.label, children: [_jsx(AccordionHeader, { children: _jsx(AccordionTrigger, { children: props.label }) }), _jsx(AccordionContent, { className: "prose-no-margin", children: props.children })] })),
|
|
17
17
|
Property,
|
|
18
18
|
ObjectCollapsible,
|
|
19
19
|
Requests: (props) => (_jsx(Tabs, { groupId: "fumadocs_openapi_requests", ...props })),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/render/schema.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAwB7C,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,MAAM,EACN,QAAgB,EAChB,QAAgB,EAChB,SAAiB,EACjB,EAAe,EACf,GAAG,EAAE,EAAE,QAAQ,EAAE,GAClB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAEzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,aAAa,CAAC;CACpB,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/render/schema.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAwB7C,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,MAAM,EACN,QAAgB,EAChB,QAAgB,EAChB,SAAiB,EACjB,EAAe,EACf,GAAG,EAAE,EAAE,QAAQ,EAAE,GAClB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAEzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,aAAa,CAAC;CACpB,GAAG,SAAS,CAiSZ"}
|
package/dist/render/schema.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Fragment } from 'react';
|
|
3
3
|
import { combineSchema } from '../utils/combine-schema.js';
|
|
4
4
|
import { Markdown } from './markdown.js';
|
|
@@ -85,7 +85,7 @@ export function Schema({ name, schema, required = false, readOnly = false, write
|
|
|
85
85
|
}
|
|
86
86
|
if (fields.length === 0)
|
|
87
87
|
return;
|
|
88
|
-
return (_jsx("div", { className: "flex flex-
|
|
88
|
+
return (_jsx("div", { className: "flex flex-wrap gap-2 not-prose", children: fields.map((field) => (_jsxs("div", { className: "bg-fd-secondary text-fd-secondary-foreground border rounded-lg text-xs p-1.5 shadow-md", children: [_jsx("span", { className: "font-medium me-2", children: field.key }), _jsx("code", { className: "text-fd-muted-foreground", children: field.value })] }, field.key))) }));
|
|
89
89
|
}
|
|
90
90
|
function primitiveBody(schema, ctx, collapsible, nested) {
|
|
91
91
|
if (schema.type === 'object') {
|
|
@@ -99,7 +99,7 @@ export function Schema({ name, schema, required = false, readOnly = false, write
|
|
|
99
99
|
};
|
|
100
100
|
if (props.length === 0 && patternProps.length === 0)
|
|
101
101
|
return _jsx("p", { children: "Empty Object" });
|
|
102
|
-
const children = (_jsxs(
|
|
102
|
+
const children = (_jsxs(_Fragment, { children: [props.map(([key, value]) => (_jsx(Fragment, { children: property(key, value, next, {
|
|
103
103
|
required: schema.required?.includes(key) ?? false,
|
|
104
104
|
nested,
|
|
105
105
|
}) }, key))), patternProps.map(([key, value]) => (_jsx(Fragment, { children: property(key, value, next, { nested }) }, key))), schema.additionalProperties &&
|
|
@@ -114,11 +114,10 @@ export function Schema({ name, schema, required = false, readOnly = false, write
|
|
|
114
114
|
const items = schema.items;
|
|
115
115
|
if (!items || !isComplexType(items) || ctx.stack.has(items))
|
|
116
116
|
return;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return (_jsx(renderer.ObjectCollapsible, { name: "Array Item", children: children }));
|
|
117
|
+
return (_jsxs(_Fragment, { children: [items.description && (_jsx(Markdown, { text: 'Item: ' + items.description })), _jsx(renderer.ObjectCollapsible, { name: "Array Item", children: propertyBody(items, (child, ctx) => primitiveBody(child, ctx, false, true), {
|
|
118
|
+
...ctx,
|
|
119
|
+
stack: ctx.stack.next(schema),
|
|
120
|
+
}) })] }));
|
|
122
121
|
}
|
|
123
122
|
}
|
|
124
123
|
function property(key, schema, ctx, props) {
|
package/dist/server/proxy.d.ts
CHANGED
|
@@ -4,9 +4,24 @@ type Proxy = {
|
|
|
4
4
|
[K in (typeof keys)[number]]: (req: NextRequest) => Promise<Response>;
|
|
5
5
|
};
|
|
6
6
|
interface CreateProxyOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Filter by prefixes of request url
|
|
9
|
+
*
|
|
10
|
+
* @deprecated Use `allowedOrigins` for filtering origins, or `filterRequest` for more detailed rules.
|
|
11
|
+
*/
|
|
7
12
|
allowedUrls?: string[];
|
|
8
13
|
/**
|
|
9
|
-
*
|
|
14
|
+
* List of allowed origins to proxy to.
|
|
15
|
+
*/
|
|
16
|
+
allowedOrigins?: string[];
|
|
17
|
+
/**
|
|
18
|
+
* Determine if the proxied request is allowed.
|
|
19
|
+
*
|
|
20
|
+
* @returns true if allowed, otherwise forbidden.
|
|
21
|
+
*/
|
|
22
|
+
filterRequest?: (request: Request) => boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Override proxied request/response with yours
|
|
10
25
|
*/
|
|
11
26
|
overrides?: {
|
|
12
27
|
request?: (request: Request) => Request;
|
|
@@ -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,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,
|
|
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;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;IAE9C;;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,CAmGnE"}
|
package/dist/server/proxy.js
CHANGED
|
@@ -1,39 +1,53 @@
|
|
|
1
1
|
const keys = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'];
|
|
2
2
|
export function createProxy(options = {}) {
|
|
3
|
-
const { allowedUrls,
|
|
3
|
+
const { allowedOrigins, allowedUrls, filterRequest = (req) => {
|
|
4
|
+
return (!allowedUrls || allowedUrls.some((item) => req.url.startsWith(item)));
|
|
5
|
+
}, overrides, } = options;
|
|
4
6
|
const handlers = {};
|
|
5
7
|
async function handler(req) {
|
|
6
8
|
const url = req.nextUrl.searchParams.get('url');
|
|
7
9
|
if (!url) {
|
|
8
|
-
return Response.json('A `url` query parameter is required for proxy url', {
|
|
10
|
+
return Response.json('[Proxy] A `url` query parameter is required for proxy url', {
|
|
9
11
|
status: 400,
|
|
10
12
|
});
|
|
11
13
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
let parsedUrl;
|
|
15
|
+
try {
|
|
16
|
+
parsedUrl = new URL(url);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return Response.json('[Proxy] Invalid `url` parameter value.', {
|
|
20
|
+
status: 400,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
if (allowedOrigins && !allowedOrigins.includes(parsedUrl.origin)) {
|
|
24
|
+
return Response.json(`[Proxy] The origin "${parsedUrl.origin}" is not allowed.`, {
|
|
15
25
|
status: 400,
|
|
16
26
|
});
|
|
17
27
|
}
|
|
18
|
-
let
|
|
28
|
+
let proxied = new Request(parsedUrl, {
|
|
19
29
|
...req,
|
|
20
30
|
cache: 'no-cache',
|
|
21
31
|
mode: 'cors',
|
|
22
32
|
});
|
|
23
33
|
if (overrides?.request) {
|
|
24
|
-
|
|
34
|
+
proxied = overrides.request(proxied);
|
|
25
35
|
}
|
|
26
|
-
|
|
36
|
+
if (!filterRequest(proxied)) {
|
|
37
|
+
return Response.json('[Proxy] The proxied request is not allowed', {
|
|
38
|
+
status: 403,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
proxied.headers.forEach((_value, originalKey) => {
|
|
27
42
|
const key = originalKey.toLowerCase();
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
clonedReq.headers.delete(originalKey);
|
|
43
|
+
if (key === 'origin') {
|
|
44
|
+
proxied.headers.delete(originalKey);
|
|
31
45
|
}
|
|
32
46
|
});
|
|
33
|
-
let res = await fetch(
|
|
47
|
+
let res = await fetch(proxied).catch((e) => new Error(e.toString()));
|
|
34
48
|
if (res instanceof Error) {
|
|
35
|
-
return Response.json(`Failed to proxy request: ${res.message}`, {
|
|
36
|
-
status:
|
|
49
|
+
return Response.json(`[Proxy] Failed to proxy request: ${res.message}`, {
|
|
50
|
+
status: 500,
|
|
37
51
|
});
|
|
38
52
|
}
|
|
39
53
|
if (overrides?.response) {
|
|
@@ -42,14 +56,14 @@ export function createProxy(options = {}) {
|
|
|
42
56
|
const headers = new Headers(res.headers);
|
|
43
57
|
headers.forEach((_value, originalKey) => {
|
|
44
58
|
const key = originalKey.toLowerCase();
|
|
45
|
-
|
|
46
|
-
if (notAllowed) {
|
|
59
|
+
if (key.startsWith('access-control-') || key === 'content-encoding') {
|
|
47
60
|
headers.delete(originalKey);
|
|
48
61
|
}
|
|
49
62
|
});
|
|
50
63
|
headers.set('X-Forwarded-Host', res.url);
|
|
51
64
|
return new Response(res.body, {
|
|
52
|
-
|
|
65
|
+
status: res.status,
|
|
66
|
+
statusText: res.statusText,
|
|
53
67
|
headers,
|
|
54
68
|
});
|
|
55
69
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as Primitive from '@radix-ui/react-accordion';
|
|
2
|
+
import type { ComponentProps } from 'react';
|
|
3
|
+
export declare function Accordions(props: ComponentProps<typeof Primitive.Root>): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export declare function AccordionItem(props: ComponentProps<typeof Primitive.Item>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export declare function AccordionContent(props: ComponentProps<typeof Primitive.Content>): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export declare function AccordionHeader(props: ComponentProps<typeof Primitive.Header>): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare function AccordionTrigger(props: ComponentProps<typeof Primitive.Trigger>): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=accordion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accordion.d.ts","sourceRoot":"","sources":["../../../src/ui/components/accordion.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,SAAS,MAAM,2BAA2B,CAAC;AAEvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAG5C,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,2CAUtE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,2CAMzE;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,OAAO,CAAC,2CAahD;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,MAAM,CAAC,2CAa/C;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,OAAO,CAAC,2CAchD"}
|