fumadocs-openapi 10.2.4 → 10.2.6
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.js.map +1 -1
- package/dist/playground/client.d.ts +11 -12
- package/dist/playground/client.d.ts.map +1 -1
- package/dist/playground/client.js +70 -74
- package/dist/playground/client.js.map +1 -1
- package/dist/playground/components/inputs.js +198 -187
- package/dist/playground/components/inputs.js.map +1 -1
- package/dist/playground/components/oauth-dialog.js +2 -2
- package/dist/playground/components/server-select.js +24 -25
- package/dist/playground/components/server-select.js.map +1 -1
- package/dist/playground/fetcher.js.map +1 -1
- package/dist/playground/index.js.map +1 -1
- package/dist/playground/schema.d.ts +1 -0
- package/dist/playground/schema.d.ts.map +1 -1
- package/dist/playground/schema.js +10 -12
- package/dist/playground/schema.js.map +1 -1
- package/dist/playground/status-info.js.map +1 -1
- package/dist/requests/generators/csharp.js.map +1 -1
- package/dist/requests/generators/curl.js.map +1 -1
- package/dist/requests/generators/go.js.map +1 -1
- package/dist/requests/generators/index.js.map +1 -1
- package/dist/requests/generators/java.js.map +1 -1
- package/dist/requests/generators/javascript.js.map +1 -1
- package/dist/requests/generators/python.js.map +1 -1
- package/dist/requests/media/adapter.d.ts.map +1 -1
- package/dist/requests/media/adapter.js.map +1 -1
- package/dist/requests/media/encode.js.map +1 -1
- package/dist/requests/media/resolve-adapter.js +4 -0
- package/dist/requests/media/resolve-adapter.js.map +1 -1
- package/dist/server/create.js +1 -1
- package/dist/server/create.js.map +1 -1
- package/dist/server/proxy.js.map +1 -1
- package/dist/server/source-api.js.map +1 -1
- package/dist/ui/api-page.js.map +1 -1
- package/dist/ui/contexts/api.js.map +1 -1
- package/dist/ui/operation/index.js.map +1 -1
- package/dist/ui/operation/request-tabs.js.map +1 -1
- package/dist/ui/operation/response-tabs.js.map +1 -1
- package/dist/ui/operation/usage-tabs/client.js.map +1 -1
- package/dist/ui/operation/usage-tabs/index.js.map +1 -1
- package/dist/ui/schema/client.d.ts.map +1 -1
- package/dist/ui/schema/client.js +120 -114
- package/dist/ui/schema/client.js.map +1 -1
- package/dist/ui/schema/index.js +1 -1
- package/dist/ui/schema/index.js.map +1 -1
- package/dist/utils/id-to-title.js.map +1 -1
- package/dist/utils/merge-schema.js.map +1 -1
- package/dist/utils/pages/builder.js.map +1 -1
- package/dist/utils/pages/preset-auto.js.map +1 -1
- package/dist/utils/pages/to-static-data.js.map +1 -1
- package/dist/utils/pages/to-text.js.map +1 -1
- package/package.json +11 -10
package/dist/ui/schema/client.js
CHANGED
|
@@ -6,98 +6,101 @@ import { Fragment, createContext, use, useCallback, useEffect, useMemo, useRef,
|
|
|
6
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { ChevronDown } from "lucide-react";
|
|
8
8
|
import { cva } from "class-variance-authority";
|
|
9
|
-
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
|
10
9
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "fumadocs-ui/components/ui/collapsible";
|
|
10
|
+
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
|
11
11
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "fumadocs-ui/components/tabs";
|
|
12
12
|
import { Popover, PopoverContent, PopoverTrigger } from "fumadocs-ui/components/ui/popover";
|
|
13
13
|
|
|
14
14
|
//#region src/ui/schema/client.tsx
|
|
15
15
|
const typeVariants = cva("text-sm text-start text-fd-muted-foreground font-mono", { variants: { variant: { trigger: "underline hover:text-fd-accent-foreground data-[state=open]:text-fd-accent-foreground" } } });
|
|
16
|
-
const
|
|
16
|
+
const PopoverContext = createContext({ renderTrigger: (props) => /* @__PURE__ */ jsx(RootPopoverTrigger, { ...props }) });
|
|
17
17
|
const DataContext = createContext(null);
|
|
18
18
|
function useData() {
|
|
19
19
|
return use(DataContext);
|
|
20
20
|
}
|
|
21
|
-
function
|
|
22
|
-
return use(
|
|
21
|
+
function usePopover() {
|
|
22
|
+
return use(PopoverContext);
|
|
23
23
|
}
|
|
24
24
|
function SchemaUI({ name, required = false, as = "property", generated }) {
|
|
25
|
-
const schema = generated.refs[generated.$root];
|
|
26
25
|
return /* @__PURE__ */ jsx(DataContext, {
|
|
27
|
-
value:
|
|
28
|
-
children:
|
|
26
|
+
value: generated,
|
|
27
|
+
children: /* @__PURE__ */ jsx(SchemaUIProperty, {
|
|
29
28
|
name,
|
|
30
29
|
$type: generated.$root,
|
|
31
|
-
overrides: { required }
|
|
32
|
-
|
|
30
|
+
overrides: { required },
|
|
31
|
+
variant: as === "property" || generated.refs[generated.$root].type === "primitive" ? "default" : "expand"
|
|
32
|
+
})
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
function
|
|
36
|
-
const { refs } = useData();
|
|
37
|
-
const schema = refs[$type];
|
|
38
|
-
let child = null;
|
|
39
|
-
if (schema.type === "or" && schema.items.length > 0) child = /* @__PURE__ */ jsxs(Fragment$1, { children: [child, /* @__PURE__ */ jsxs(Tabs, {
|
|
40
|
-
defaultValue: schema.items[0].$type,
|
|
41
|
-
children: [/* @__PURE__ */ jsx(TabsList, { children: schema.items.map((item) => /* @__PURE__ */ jsx(TabsTrigger, {
|
|
42
|
-
value: item.$type,
|
|
43
|
-
children: item.name
|
|
44
|
-
}, item.$type)) }), schema.items.map((item) => /* @__PURE__ */ jsx(TabsContent, {
|
|
45
|
-
value: item.$type,
|
|
46
|
-
forceMount: void 0,
|
|
47
|
-
className: "py-0",
|
|
48
|
-
children: /* @__PURE__ */ jsx(SchemaUIContent, { ...item })
|
|
49
|
-
}, item.$type))]
|
|
50
|
-
})] });
|
|
51
|
-
if (schema.type === "object" && schema.props.length > 0) child = /* @__PURE__ */ jsxs(Fragment$1, { children: [child, schema.props.map((prop) => /* @__PURE__ */ jsx(SchemaUIProperty, {
|
|
52
|
-
name: prop.name,
|
|
53
|
-
$type: prop.$type,
|
|
54
|
-
overrides: { required: prop.required }
|
|
55
|
-
}, prop.name))] });
|
|
56
|
-
if (schema.type === "array") child = /* @__PURE__ */ jsxs(Fragment$1, { children: [child, /* @__PURE__ */ jsxs(Collapsible, {
|
|
57
|
-
className: "my-2",
|
|
58
|
-
children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, {
|
|
59
|
-
className: cn(buttonVariants({
|
|
60
|
-
color: "secondary",
|
|
61
|
-
size: "sm"
|
|
62
|
-
}), "group px-3 py-2 data-[state=open]:rounded-b-none"),
|
|
63
|
-
children: ["Array Item", /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 text-fd-muted-foreground group-data-[state=open]:rotate-180" })]
|
|
64
|
-
}), /* @__PURE__ */ jsx(CollapsibleContent, {
|
|
65
|
-
className: "-mt-px bg-fd-card px-3 rounded-lg rounded-tl-none border shadow-sm",
|
|
66
|
-
children: /* @__PURE__ */ jsx(SchemaUIContent, { $type: schema.item.$type })
|
|
67
|
-
})]
|
|
68
|
-
})] });
|
|
69
|
-
return child;
|
|
70
|
-
}
|
|
71
|
-
function SchemaUIProperty({ name, $type, overrides }) {
|
|
72
|
-
const { renderRef } = useProperty();
|
|
35
|
+
function SchemaUIProperty({ name, $type, variant = "default", overrides }) {
|
|
73
36
|
const { refs } = useData();
|
|
74
37
|
const schema = refs[$type];
|
|
38
|
+
const renderRef = useRenderRef();
|
|
75
39
|
let type = schema.typeName;
|
|
76
|
-
if ((schema.type === "or" || schema.type === "and") && schema.items.length > 0)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
40
|
+
if ((schema.type === "or" || schema.type === "and") && schema.items.length > 0) {
|
|
41
|
+
if (variant === "expand") return /* @__PURE__ */ jsxs(Tabs, {
|
|
42
|
+
defaultValue: schema.items[0].$type,
|
|
43
|
+
children: [/* @__PURE__ */ jsx(TabsList, { children: schema.items.map((item) => /* @__PURE__ */ jsx(TabsTrigger, {
|
|
44
|
+
value: item.$type,
|
|
45
|
+
children: item.name
|
|
46
|
+
}, item.$type)) }), schema.items.map((item) => /* @__PURE__ */ jsx(TabsContent, {
|
|
47
|
+
value: item.$type,
|
|
48
|
+
forceMount: void 0,
|
|
49
|
+
className: "py-0",
|
|
50
|
+
children: /* @__PURE__ */ jsx(SchemaUIProperty, {
|
|
51
|
+
...item,
|
|
52
|
+
variant: "expand"
|
|
53
|
+
})
|
|
54
|
+
}, item.$type))]
|
|
55
|
+
});
|
|
56
|
+
type = renderRef({
|
|
57
|
+
pathName: name,
|
|
58
|
+
$ref: $type
|
|
59
|
+
});
|
|
60
|
+
} else if (schema.type === "object" && schema.props.length > 0) {
|
|
61
|
+
if (variant === "expand") return schema.props.map((prop) => /* @__PURE__ */ jsx(SchemaUIProperty, {
|
|
62
|
+
name: prop.name,
|
|
63
|
+
$type: prop.$type,
|
|
64
|
+
overrides: { required: prop.required }
|
|
65
|
+
}, prop.name));
|
|
66
|
+
type = renderRef({
|
|
67
|
+
pathName: name,
|
|
68
|
+
$ref: $type
|
|
69
|
+
});
|
|
70
|
+
} else if (schema.type === "array") {
|
|
71
|
+
if (variant === "expand") return /* @__PURE__ */ jsxs(Collapsible, {
|
|
72
|
+
className: "my-2",
|
|
73
|
+
children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, {
|
|
74
|
+
className: cn(buttonVariants({
|
|
75
|
+
color: "secondary",
|
|
76
|
+
size: "sm"
|
|
77
|
+
}), "group px-3 py-2 data-[state=open]:rounded-b-none"),
|
|
78
|
+
children: ["Array Item", /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 text-fd-muted-foreground group-data-[state=open]:rotate-180" })]
|
|
79
|
+
}), /* @__PURE__ */ jsx(CollapsibleContent, {
|
|
80
|
+
className: "-mt-px bg-fd-card px-3 rounded-lg rounded-tl-none border shadow-sm",
|
|
81
|
+
children: /* @__PURE__ */ jsx(SchemaUIProperty, {
|
|
82
|
+
name: "",
|
|
83
|
+
$type: schema.item.$type,
|
|
84
|
+
variant: "expand"
|
|
85
|
+
})
|
|
86
|
+
})]
|
|
87
|
+
});
|
|
88
|
+
type = renderRef({
|
|
89
|
+
pathName: name,
|
|
90
|
+
$ref: $type
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
const child = /* @__PURE__ */ jsxs(Fragment$1, { children: [schema.description, schema.infoTags && schema.infoTags.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
94
|
+
className: "flex flex-row gap-2 flex-wrap my-2 not-prose empty:hidden",
|
|
95
|
+
children: schema.infoTags.map((tag, i) => /* @__PURE__ */ jsx(Fragment, { children: tag }, i))
|
|
96
|
+
})] });
|
|
97
|
+
if (variant === "expand") return child;
|
|
98
|
+
return /* @__PURE__ */ jsx(Property, {
|
|
93
99
|
name,
|
|
94
100
|
type,
|
|
95
101
|
deprecated: schema.deprecated,
|
|
96
102
|
...overrides,
|
|
97
|
-
children:
|
|
98
|
-
className: "flex flex-row gap-2 flex-wrap my-2 not-prose empty:hidden",
|
|
99
|
-
children: schema.infoTags.map((tag, i) => /* @__PURE__ */ jsx(Fragment, { children: tag }, i))
|
|
100
|
-
})]
|
|
103
|
+
children: child
|
|
101
104
|
});
|
|
102
105
|
}
|
|
103
106
|
function SchemaUIPopover({ initialPath }) {
|
|
@@ -109,14 +112,13 @@ function SchemaUIPopover({ initialPath }) {
|
|
|
109
112
|
if (!element || !element.parentElement) return;
|
|
110
113
|
element.parentElement.scrollTop = 0;
|
|
111
114
|
}, [last?.$ref]);
|
|
112
|
-
const context = useMemo(() => ({
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
115
|
+
const context = useMemo(() => ({ renderTrigger: ({ $ref, pathName, children }) => /* @__PURE__ */ jsx("button", {
|
|
116
|
+
className: cn(typeVariants({ variant: "trigger" })),
|
|
117
|
+
onClick: () => setPath((path$1) => [...path$1, {
|
|
118
|
+
name: pathName,
|
|
119
|
+
$ref
|
|
120
|
+
}]),
|
|
121
|
+
children
|
|
120
122
|
}) }), []);
|
|
121
123
|
if (!last) return;
|
|
122
124
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
@@ -133,63 +135,70 @@ function SchemaUIPopover({ initialPath }) {
|
|
|
133
135
|
});
|
|
134
136
|
return /* @__PURE__ */ jsxs(Fragment, { children: [i > 0 && ".", node] }, i);
|
|
135
137
|
})
|
|
136
|
-
}), /* @__PURE__ */ jsx(
|
|
138
|
+
}), /* @__PURE__ */ jsx(PopoverContext, {
|
|
137
139
|
value: context,
|
|
138
140
|
children: /* @__PURE__ */ jsx("div", {
|
|
139
141
|
ref,
|
|
140
142
|
className: "px-2",
|
|
141
|
-
children: /* @__PURE__ */ jsx(
|
|
143
|
+
children: /* @__PURE__ */ jsx(SchemaUIProperty, {
|
|
144
|
+
name: "",
|
|
145
|
+
$type: last.$ref,
|
|
146
|
+
variant: "expand"
|
|
147
|
+
})
|
|
142
148
|
})
|
|
143
149
|
})] });
|
|
144
150
|
}
|
|
145
|
-
function
|
|
151
|
+
function useRenderRef() {
|
|
146
152
|
const { refs } = useData();
|
|
153
|
+
const { renderTrigger } = usePopover();
|
|
154
|
+
return function renderRef({ pathName, $ref, text }) {
|
|
155
|
+
const schema = refs[$ref];
|
|
156
|
+
if (schema.type === "and" || schema.type === "or") {
|
|
157
|
+
const sep = schema.type === "and" ? "&" : "|";
|
|
158
|
+
return /* @__PURE__ */ jsx("span", {
|
|
159
|
+
className: cn(typeVariants(), "flex flex-row gap-2 items-center flex-wrap"),
|
|
160
|
+
children: schema.items.map((item, i) => /* @__PURE__ */ jsxs(Fragment, { children: [i > 0 && /* @__PURE__ */ jsx("span", { children: sep }), renderRef({
|
|
161
|
+
pathName,
|
|
162
|
+
text: item.name,
|
|
163
|
+
$ref: item.$type
|
|
164
|
+
})] }, item.$type))
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if (schema.type === "array") return /* @__PURE__ */ jsxs("span", {
|
|
168
|
+
className: cn(typeVariants(), "flex flex-row items-center flex-wrap"),
|
|
169
|
+
children: [
|
|
170
|
+
"array<",
|
|
171
|
+
renderRef({
|
|
172
|
+
pathName: /* @__PURE__ */ jsxs(Fragment$1, { children: [pathName, "[]"] }),
|
|
173
|
+
$ref: schema.item.$type
|
|
174
|
+
}),
|
|
175
|
+
">"
|
|
176
|
+
]
|
|
177
|
+
});
|
|
178
|
+
return renderTrigger({
|
|
179
|
+
$ref,
|
|
180
|
+
pathName,
|
|
181
|
+
children: text ?? schema.aliasName
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function RootPopoverTrigger({ $ref, pathName, children }) {
|
|
147
186
|
const ref = useCallback((element) => {
|
|
148
187
|
if (!element || element.style.getPropertyValue("--initial-height")) return;
|
|
149
188
|
element.style.setProperty("--initial-height", `${element.clientHeight}px`);
|
|
150
189
|
}, []);
|
|
151
|
-
const schema = refs[$ref];
|
|
152
|
-
if (inlineUnion && (schema.type === "and" || schema.type === "or")) {
|
|
153
|
-
const sep = schema.type === "and" ? "&" : "|";
|
|
154
|
-
return /* @__PURE__ */ jsx("span", {
|
|
155
|
-
className: cn(typeVariants(), "flex flex-row gap-2 items-center flex-wrap"),
|
|
156
|
-
children: schema.items.map((item, i) => /* @__PURE__ */ jsxs(Fragment, { children: [i > 0 && /* @__PURE__ */ jsx("span", { children: sep }), /* @__PURE__ */ jsx(RootRef, {
|
|
157
|
-
pathName,
|
|
158
|
-
text: item.name,
|
|
159
|
-
$ref: item.$type
|
|
160
|
-
})] }, item.$type))
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
if (!isExpandable(refs[$ref])) return /* @__PURE__ */ jsx("span", {
|
|
164
|
-
className: cn(typeVariants()),
|
|
165
|
-
children: text
|
|
166
|
-
});
|
|
167
190
|
return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
168
191
|
className: cn(typeVariants({ variant: "trigger" })),
|
|
169
|
-
children
|
|
192
|
+
children
|
|
170
193
|
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
171
194
|
ref,
|
|
172
195
|
className: "w-[600px] min-h-(--initial-height,0) max-h-[460px] p-0",
|
|
173
196
|
children: /* @__PURE__ */ jsx(SchemaUIPopover, { initialPath: [{
|
|
174
|
-
name:
|
|
197
|
+
name: pathName,
|
|
175
198
|
$ref
|
|
176
199
|
}] })
|
|
177
200
|
})] });
|
|
178
201
|
}
|
|
179
|
-
function LinkRef({ $ref, pathName, onInsert, text }) {
|
|
180
|
-
const { refs } = useData();
|
|
181
|
-
if (!isExpandable(refs[$ref])) return /* @__PURE__ */ jsx("span", {
|
|
182
|
-
className: cn(typeVariants()),
|
|
183
|
-
children: text
|
|
184
|
-
});
|
|
185
|
-
return /* @__PURE__ */ jsx("button", {
|
|
186
|
-
className: cn(typeVariants({ variant: "trigger" })),
|
|
187
|
-
onClick: () => {
|
|
188
|
-
onInsert(pathName, $ref);
|
|
189
|
-
},
|
|
190
|
-
children: text
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
202
|
function Property({ name, type, required, deprecated, nested = false, className, ...props }) {
|
|
194
203
|
return /* @__PURE__ */ jsxs("div", {
|
|
195
204
|
className: cn("text-sm border-t", nested ? "p-3 border-x bg-fd-card last:rounded-b-xl first:rounded-tr-xl last:border-b" : "py-4 first:border-t-0", className),
|
|
@@ -222,9 +231,6 @@ function Property({ name, type, required, deprecated, nested = false, className,
|
|
|
222
231
|
})]
|
|
223
232
|
});
|
|
224
233
|
}
|
|
225
|
-
function isExpandable(schema) {
|
|
226
|
-
return schema.type !== "primitive";
|
|
227
|
-
}
|
|
228
234
|
|
|
229
235
|
//#endregion
|
|
230
236
|
export { SchemaUI };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["child: ReactNode","type: ReactNode","context: PropertyContextType","path"],"sources":["../../../src/ui/schema/client.tsx"],"sourcesContent":["'use client';\nimport {\n createContext,\n Fragment,\n type ReactNode,\n use,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from 'fumadocs-ui/components/tabs';\nimport type { SchemaData, SchemaUIGeneratedData } from '@/ui/schema';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from 'fumadocs-ui/components/ui/collapsible';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { ChevronDown } from 'lucide-react';\nimport { Badge } from '@/ui/components/method-label';\nimport { Popover, PopoverContent, PopoverTrigger } from 'fumadocs-ui/components/ui/popover';\nimport { cn } from '@/utils/cn';\nimport { cva } from 'class-variance-authority';\n\ntype DataContextType = SchemaUIGeneratedData;\n\ninterface PropertyContextType {\n renderRef: (options: RenderRefOptions) => ReactNode;\n}\n\ninterface RenderRefOptions {\n text: ReactNode;\n pathName: ReactNode;\n $ref: string;\n\n inlineUnion?: boolean;\n}\n\nconst typeVariants = cva('text-sm text-start text-fd-muted-foreground font-mono', {\n variants: {\n variant: {\n trigger:\n 'underline hover:text-fd-accent-foreground data-[state=open]:text-fd-accent-foreground',\n },\n },\n});\n\nconst PropertyContext = createContext<PropertyContextType>({\n renderRef: (props) => <RootRef {...props} />,\n});\n\nconst DataContext = createContext<DataContextType | null>(null);\n\nfunction useData() {\n return use(DataContext)!;\n}\n\nfunction useProperty() {\n return use(PropertyContext);\n}\n\nexport interface SchemaUIProps {\n name: string;\n required?: boolean;\n as?: 'property' | 'body';\n\n generated: SchemaUIGeneratedData;\n}\n\nexport function SchemaUI({ name, required = false, as = 'property', generated }: SchemaUIProps) {\n const schema = generated.refs[generated.$root];\n const context: DataContextType = useMemo(() => generated, [generated]);\n const isProperty = as === 'property' || !isExpandable(schema);\n\n return (\n <DataContext value={context}>\n {isProperty ? (\n <SchemaUIProperty\n name={name}\n $type={generated.$root}\n overrides={{\n required,\n }}\n />\n ) : (\n <SchemaUIContent $type={generated.$root} />\n )}\n </DataContext>\n );\n}\n\nfunction SchemaUIContent({ $type }: { $type: string }) {\n const { refs } = useData();\n const schema = refs[$type];\n let child: ReactNode = null;\n\n if (schema.type === 'or' && schema.items.length > 0) {\n child = (\n <>\n {child}\n <Tabs defaultValue={schema.items[0].$type}>\n <TabsList>\n {schema.items.map((item) => (\n <TabsTrigger key={item.$type} value={item.$type}>\n {item.name}\n </TabsTrigger>\n ))}\n </TabsList>\n {schema.items.map((item) => (\n <TabsContent\n key={item.$type}\n value={item.$type}\n forceMount={undefined}\n className=\"py-0\"\n >\n <SchemaUIContent {...item} />\n </TabsContent>\n ))}\n </Tabs>\n </>\n );\n }\n\n if (schema.type === 'object' && schema.props.length > 0) {\n child = (\n <>\n {child}\n {schema.props.map((prop) => (\n <SchemaUIProperty\n key={prop.name}\n name={prop.name}\n $type={prop.$type}\n overrides={{ required: prop.required }}\n />\n ))}\n </>\n );\n }\n\n if (schema.type === 'array') {\n child = (\n <>\n {child}\n <Collapsible className=\"my-2\">\n <CollapsibleTrigger\n className={cn(\n buttonVariants({ color: 'secondary', size: 'sm' }),\n 'group px-3 py-2 data-[state=open]:rounded-b-none',\n )}\n >\n Array Item\n <ChevronDown className=\"size-4 text-fd-muted-foreground group-data-[state=open]:rotate-180\" />\n </CollapsibleTrigger>\n <CollapsibleContent className=\"-mt-px bg-fd-card px-3 rounded-lg rounded-tl-none border shadow-sm\">\n <SchemaUIContent $type={schema.item.$type} />\n </CollapsibleContent>\n </Collapsible>\n </>\n );\n }\n\n return child;\n}\n\nfunction SchemaUIProperty({\n name,\n $type,\n overrides,\n}: {\n name: ReactNode;\n $type: string;\n overrides?: Partial<PropertyProps>;\n}) {\n const { renderRef } = useProperty();\n const { refs } = useData();\n const schema = refs[$type];\n\n let type: ReactNode = schema.typeName;\n if ((schema.type === 'or' || schema.type === 'and') && schema.items.length > 0) {\n type = renderRef({\n text: schema.aliasName,\n pathName: name,\n $ref: $type,\n inlineUnion: true,\n });\n }\n\n if (schema.type === 'object' && schema.props.length > 0) {\n type = renderRef({\n text: schema.aliasName,\n pathName: name,\n $ref: $type,\n });\n }\n\n if (schema.type === 'array') {\n type = renderRef({\n text: schema.aliasName,\n pathName: name,\n $ref: schema.item.$type,\n });\n }\n\n return (\n <Property name={name} type={type} deprecated={schema.deprecated} {...overrides}>\n {schema.description}\n {schema.infoTags && schema.infoTags.length > 0 && (\n <div className=\"flex flex-row gap-2 flex-wrap my-2 not-prose empty:hidden\">\n {schema.infoTags.map((tag, i) => (\n <Fragment key={i}>{tag}</Fragment>\n ))}\n </div>\n )}\n </Property>\n );\n}\n\nfunction SchemaUIPopover({ initialPath }: { initialPath: { name: ReactNode; $ref?: string }[] }) {\n const [path, setPath] = useState(initialPath);\n const ref = useRef<HTMLDivElement>(null);\n const last = path.findLast((item) => item.$ref !== undefined);\n\n useEffect(() => {\n const element = ref.current;\n if (!element || !element.parentElement) return;\n\n // reset scroll\n element.parentElement.scrollTop = 0;\n }, [last?.$ref]);\n\n const context: PropertyContextType = useMemo(\n () => ({\n renderRef: (props) => (\n <LinkRef\n {...props}\n onInsert={(name, $ref) => {\n setPath((path) => [...path, { name, $ref }]);\n }}\n />\n ),\n }),\n [],\n );\n\n if (!last) return;\n\n return (\n <>\n <div className=\"sticky top-0 flex flex-row flex-wrap items-center text-sm font-medium font-mono bg-fd-muted p-2\">\n {path.map((item, i) => {\n const isDuplicated = path.some((other, j) => j < i && other.$ref === item.$ref);\n const className = cn(\n isDuplicated && 'text-orange-400',\n item.$ref && 'hover:underline hover:text-fd-accent-foreground',\n );\n\n const node = item.$ref ? (\n <button onClick={() => setPath((path) => path.slice(0, i + 1))} className={className}>\n {item.name}\n </button>\n ) : (\n <span className={className}>{item.name}</span>\n );\n\n return (\n <Fragment key={i}>\n {i > 0 && '.'}\n {node}\n </Fragment>\n );\n })}\n </div>\n <PropertyContext value={context}>\n <div ref={ref} className=\"px-2\">\n <SchemaUIContent $type={last.$ref!} />\n </div>\n </PropertyContext>\n </>\n );\n}\n\nfunction RootRef({ text, $ref, pathName, inlineUnion }: RenderRefOptions) {\n const { refs } = useData();\n const ref = useCallback((element: HTMLDivElement | null) => {\n if (!element || element.style.getPropertyValue('--initial-height')) return;\n\n element.style.setProperty('--initial-height', `${element.clientHeight}px`);\n }, []);\n\n const schema = refs[$ref];\n\n if (inlineUnion && (schema.type === 'and' || schema.type === 'or')) {\n const sep = schema.type === 'and' ? '&' : '|';\n return (\n <span className={cn(typeVariants(), 'flex flex-row gap-2 items-center flex-wrap')}>\n {schema.items.map((item, i) => (\n <Fragment key={item.$type}>\n {i > 0 && <span>{sep}</span>}\n <RootRef pathName={pathName} text={item.name} $ref={item.$type} />\n </Fragment>\n ))}\n </span>\n );\n }\n\n if (!isExpandable(refs[$ref])) {\n return <span className={cn(typeVariants())}>{text}</span>;\n }\n\n return (\n <Popover>\n <PopoverTrigger className={cn(typeVariants({ variant: 'trigger' }))}>{text}</PopoverTrigger>\n <PopoverContent ref={ref} className=\"w-[600px] min-h-(--initial-height,0) max-h-[460px] p-0\">\n <SchemaUIPopover\n initialPath={[\n {\n name: (\n <>\n {pathName}\n {schema.type === 'array' && '[]'}\n </>\n ),\n $ref: $ref,\n },\n ]}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction LinkRef({\n $ref,\n pathName,\n onInsert,\n text,\n}: RenderRefOptions & {\n onInsert: (name: ReactNode, $ref: string) => void;\n}) {\n const { refs } = useData();\n if (!isExpandable(refs[$ref])) {\n return <span className={cn(typeVariants())}>{text}</span>;\n }\n\n return (\n <button\n className={cn(typeVariants({ variant: 'trigger' }))}\n onClick={() => {\n onInsert(pathName, $ref);\n }}\n >\n {text}\n </button>\n );\n}\n\ninterface PropertyProps {\n name: ReactNode;\n type: ReactNode;\n required?: boolean;\n deprecated?: boolean;\n nested?: boolean;\n\n children?: ReactNode;\n className?: string;\n}\n\nfunction Property({\n name,\n type,\n required,\n deprecated,\n nested = false,\n className,\n ...props\n}: PropertyProps) {\n return (\n <div\n className={cn(\n 'text-sm border-t',\n nested\n ? 'p-3 border-x bg-fd-card last:rounded-b-xl first:rounded-tr-xl last:border-b'\n : 'py-4 first:border-t-0',\n className,\n )}\n >\n <div className=\"flex flex-wrap items-center gap-3 not-prose\">\n <span className=\"font-medium font-mono text-fd-primary\">\n {name}\n {required ? (\n <span className=\"text-red-400\">*</span>\n ) : (\n <span className=\"text-fd-muted-foreground\">?</span>\n )}\n </span>\n {typeof type === 'string' ? (\n <span className=\"text-sm font-mono text-fd-muted-foreground\">{type}</span>\n ) : (\n type\n )}\n {deprecated && (\n <Badge color=\"yellow\" className=\"ms-auto text-xs\">\n Deprecated\n </Badge>\n )}\n </div>\n <div className=\"prose-no-margin pt-2.5 empty:hidden\">{props.children}</div>\n </div>\n );\n}\n\nfunction isExpandable(schema: SchemaData) {\n return schema.type !== 'primitive';\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["path"],"sources":["../../../src/ui/schema/client.tsx"],"sourcesContent":["'use client';\nimport {\n createContext,\n Fragment,\n type ReactNode,\n use,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from 'fumadocs-ui/components/tabs';\nimport type { SchemaUIGeneratedData } from '@/ui/schema';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from 'fumadocs-ui/components/ui/collapsible';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { ChevronDown } from 'lucide-react';\nimport { Badge } from '@/ui/components/method-label';\nimport { Popover, PopoverContent, PopoverTrigger } from 'fumadocs-ui/components/ui/popover';\nimport { cn } from '@/utils/cn';\nimport { cva } from 'class-variance-authority';\n\ntype DataContextType = SchemaUIGeneratedData;\n\ninterface PopoverContextType {\n renderTrigger: (props: { pathName: ReactNode; $ref: string; children: ReactNode }) => ReactNode;\n}\n\nconst typeVariants = cva('text-sm text-start text-fd-muted-foreground font-mono', {\n variants: {\n variant: {\n trigger:\n 'underline hover:text-fd-accent-foreground data-[state=open]:text-fd-accent-foreground',\n },\n },\n});\n\nconst PopoverContext = createContext<PopoverContextType>({\n renderTrigger: (props) => <RootPopoverTrigger {...props} />,\n});\n\nconst DataContext = createContext<DataContextType | null>(null);\n\nfunction useData() {\n return use(DataContext)!;\n}\n\nfunction usePopover() {\n return use(PopoverContext);\n}\n\nexport interface SchemaUIProps {\n name: string;\n required?: boolean;\n as?: 'property' | 'body';\n\n generated: SchemaUIGeneratedData;\n}\n\nexport function SchemaUI({ name, required = false, as = 'property', generated }: SchemaUIProps) {\n return (\n <DataContext value={generated}>\n <SchemaUIProperty\n name={name}\n $type={generated.$root}\n overrides={{\n required,\n }}\n variant={\n as === 'property' || generated.refs[generated.$root].type === 'primitive'\n ? 'default'\n : 'expand'\n }\n />\n </DataContext>\n );\n}\n\nfunction SchemaUIProperty({\n name,\n $type,\n variant = 'default',\n overrides,\n}: {\n name: ReactNode;\n $type: string;\n variant?: 'default' | 'expand';\n overrides?: Partial<PropertyProps>;\n}) {\n const { refs } = useData();\n const schema = refs[$type];\n const renderRef = useRenderRef();\n let type: ReactNode = schema.typeName;\n\n if ((schema.type === 'or' || schema.type === 'and') && schema.items.length > 0) {\n if (variant === 'expand')\n return (\n <Tabs defaultValue={schema.items[0].$type}>\n <TabsList>\n {schema.items.map((item) => (\n <TabsTrigger key={item.$type} value={item.$type}>\n {item.name}\n </TabsTrigger>\n ))}\n </TabsList>\n {schema.items.map((item) => (\n <TabsContent\n key={item.$type}\n value={item.$type}\n forceMount={undefined}\n className=\"py-0\"\n >\n <SchemaUIProperty {...item} variant=\"expand\" />\n </TabsContent>\n ))}\n </Tabs>\n );\n type = renderRef({\n pathName: name,\n $ref: $type,\n });\n } else if (schema.type === 'object' && schema.props.length > 0) {\n if (variant === 'expand')\n return schema.props.map((prop) => (\n <SchemaUIProperty\n key={prop.name}\n name={prop.name}\n $type={prop.$type}\n overrides={{ required: prop.required }}\n />\n ));\n type = renderRef({\n pathName: name,\n $ref: $type,\n });\n } else if (schema.type === 'array') {\n if (variant === 'expand')\n return (\n <Collapsible className=\"my-2\">\n <CollapsibleTrigger\n className={cn(\n buttonVariants({ color: 'secondary', size: 'sm' }),\n 'group px-3 py-2 data-[state=open]:rounded-b-none',\n )}\n >\n Array Item\n <ChevronDown className=\"size-4 text-fd-muted-foreground group-data-[state=open]:rotate-180\" />\n </CollapsibleTrigger>\n <CollapsibleContent className=\"-mt-px bg-fd-card px-3 rounded-lg rounded-tl-none border shadow-sm\">\n <SchemaUIProperty name=\"\" $type={schema.item.$type} variant=\"expand\" />\n </CollapsibleContent>\n </Collapsible>\n );\n\n type = renderRef({\n pathName: name,\n $ref: $type,\n });\n }\n\n const child = (\n <>\n {schema.description}\n {schema.infoTags && schema.infoTags.length > 0 && (\n <div className=\"flex flex-row gap-2 flex-wrap my-2 not-prose empty:hidden\">\n {schema.infoTags.map((tag, i) => (\n <Fragment key={i}>{tag}</Fragment>\n ))}\n </div>\n )}\n </>\n );\n if (variant === 'expand') return child;\n return (\n <Property name={name} type={type} deprecated={schema.deprecated} {...overrides}>\n {child}\n </Property>\n );\n}\n\nfunction SchemaUIPopover({ initialPath }: { initialPath: { name: ReactNode; $ref?: string }[] }) {\n const [path, setPath] = useState(initialPath);\n const ref = useRef<HTMLDivElement>(null);\n const last = path.findLast((item) => item.$ref !== undefined);\n\n useEffect(() => {\n const element = ref.current;\n if (!element || !element.parentElement) return;\n\n // reset scroll\n element.parentElement.scrollTop = 0;\n }, [last?.$ref]);\n\n const context: PopoverContextType = useMemo(\n () => ({\n renderTrigger: ({ $ref, pathName, children }) => (\n <button\n className={cn(typeVariants({ variant: 'trigger' }))}\n onClick={() => setPath((path) => [...path, { name: pathName, $ref }])}\n >\n {children}\n </button>\n ),\n }),\n [],\n );\n\n if (!last) return;\n\n return (\n <>\n <div className=\"sticky top-0 flex flex-row flex-wrap items-center text-sm font-medium font-mono bg-fd-muted p-2\">\n {path.map((item, i) => {\n const isDuplicated = path.some((other, j) => j < i && other.$ref === item.$ref);\n const className = cn(\n isDuplicated && 'text-orange-400',\n item.$ref && 'hover:underline hover:text-fd-accent-foreground',\n );\n const node = item.$ref ? (\n <button onClick={() => setPath((path) => path.slice(0, i + 1))} className={className}>\n {item.name}\n </button>\n ) : (\n <span className={className}>{item.name}</span>\n );\n\n return (\n <Fragment key={i}>\n {i > 0 && '.'}\n {node}\n </Fragment>\n );\n })}\n </div>\n <PopoverContext value={context}>\n <div ref={ref} className=\"px-2\">\n <SchemaUIProperty name=\"\" $type={last.$ref!} variant=\"expand\" />\n </div>\n </PopoverContext>\n </>\n );\n}\n\nfunction useRenderRef() {\n const { refs } = useData();\n const { renderTrigger } = usePopover();\n return function renderRef({\n pathName,\n $ref,\n text,\n }: {\n pathName: ReactNode;\n $ref: string;\n text?: ReactNode;\n }) {\n const schema = refs[$ref];\n\n if (schema.type === 'and' || schema.type === 'or') {\n const sep = schema.type === 'and' ? '&' : '|';\n return (\n <span className={cn(typeVariants(), 'flex flex-row gap-2 items-center flex-wrap')}>\n {schema.items.map((item, i) => (\n <Fragment key={item.$type}>\n {i > 0 && <span>{sep}</span>}\n {renderRef({ pathName, text: item.name, $ref: item.$type })}\n </Fragment>\n ))}\n </span>\n );\n }\n\n if (schema.type === 'array') {\n return (\n <span className={cn(typeVariants(), 'flex flex-row items-center flex-wrap')}>\n {'array<'}\n {renderRef({ pathName: <>{pathName}[]</>, $ref: schema.item.$type })}\n {'>'}\n </span>\n );\n }\n\n return renderTrigger({ $ref, pathName, children: text ?? schema.aliasName });\n };\n}\n\nfunction RootPopoverTrigger({\n $ref,\n pathName,\n children,\n}: {\n pathName: ReactNode;\n $ref: string;\n children: ReactNode;\n}) {\n const ref = useCallback((element: HTMLDivElement | null) => {\n if (!element || element.style.getPropertyValue('--initial-height')) return;\n\n element.style.setProperty('--initial-height', `${element.clientHeight}px`);\n }, []);\n\n return (\n <Popover>\n <PopoverTrigger className={cn(typeVariants({ variant: 'trigger' }))}>\n {children}\n </PopoverTrigger>\n <PopoverContent ref={ref} className=\"w-[600px] min-h-(--initial-height,0) max-h-[460px] p-0\">\n <SchemaUIPopover\n initialPath={[\n {\n name: pathName,\n $ref: $ref,\n },\n ]}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\ninterface PropertyProps {\n name: ReactNode;\n type: ReactNode;\n required?: boolean;\n deprecated?: boolean;\n nested?: boolean;\n\n children?: ReactNode;\n className?: string;\n}\n\nfunction Property({\n name,\n type,\n required,\n deprecated,\n nested = false,\n className,\n ...props\n}: PropertyProps) {\n return (\n <div\n className={cn(\n 'text-sm border-t',\n nested\n ? 'p-3 border-x bg-fd-card last:rounded-b-xl first:rounded-tr-xl last:border-b'\n : 'py-4 first:border-t-0',\n className,\n )}\n >\n <div className=\"flex flex-wrap items-center gap-3 not-prose\">\n <span className=\"font-medium font-mono text-fd-primary\">\n {name}\n {required ? (\n <span className=\"text-red-400\">*</span>\n ) : (\n <span className=\"text-fd-muted-foreground\">?</span>\n )}\n </span>\n {typeof type === 'string' ? (\n <span className=\"text-sm font-mono text-fd-muted-foreground\">{type}</span>\n ) : (\n type\n )}\n {deprecated && (\n <Badge color=\"yellow\" className=\"ms-auto text-xs\">\n Deprecated\n </Badge>\n )}\n </div>\n <div className=\"prose-no-margin pt-2.5 empty:hidden\">{props.children}</div>\n </div>\n );\n}\n"],"mappings":"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"}
|
package/dist/ui/schema/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FormatFlags, schemaToString } from "../../utils/schema-to-string.js";
|
|
2
1
|
import { mergeAllOf } from "../../utils/merge-schema.js";
|
|
2
|
+
import { FormatFlags, schemaToString } from "../../utils/schema-to-string.js";
|
|
3
3
|
import { SchemaUILazy } from "./lazy.js";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["refs: Record<string, SchemaData>","fields: ReactNode[]","out: SchemaData","out: string[]"],"sources":["../../../src/ui/schema/index.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { ResolvedSchema } from '@/utils/schema';\nimport type { RenderContext } from '@/types';\nimport { FormatFlags, schemaToString } from '@/utils/schema-to-string';\nimport { mergeAllOf } from '@/utils/merge-schema';\nimport type { SchemaUIProps } from '@/ui/schema/client';\nimport { SchemaUILazy } from '@/ui/schema/lazy';\n\nexport interface FieldBase {\n description?: ReactNode;\n infoTags?: ReactNode[];\n\n typeName: string;\n aliasName: string;\n\n deprecated?: boolean;\n}\n\nexport type SchemaData = FieldBase &\n (\n | {\n type: 'primitive';\n }\n | {\n type: 'object';\n props: {\n name: string;\n $type: string;\n required: boolean;\n }[];\n }\n | {\n type: 'array';\n item: {\n $type: string;\n };\n }\n | {\n type: 'or';\n items: {\n name: string;\n $type: string;\n }[];\n }\n | {\n type: 'and';\n items: {\n name: string;\n $type: string;\n }[];\n }\n );\n\nexport interface SchemaUIOptions {\n root: ResolvedSchema;\n client: Omit<SchemaUIProps, 'generated'>;\n\n /**\n * include read only props\n */\n readOnly?: boolean;\n /**\n * include write only props\n */\n writeOnly?: boolean;\n}\n\nexport interface SchemaUIGeneratedData {\n $root: string;\n refs: Record<string, SchemaData>;\n}\n\nexport function Schema({\n ctx,\n ...options\n}: SchemaUIOptions & {\n ctx: RenderContext;\n}) {\n if (ctx.schemaUI?.render) {\n return ctx.schemaUI.render(options, ctx);\n }\n\n return <SchemaUILazy {...options.client} generated={generateSchemaUI(options, ctx)} />;\n}\n\nexport function generateSchemaUI(\n { root, readOnly, writeOnly }: SchemaUIOptions,\n ctx: RenderContext,\n): SchemaUIGeneratedData {\n const refs: Record<string, SchemaData> = {};\n const { showExample = false } = ctx.schemaUI ?? {};\n\n function generateInfoTags(schema: Exclude<ResolvedSchema, boolean>) {\n const fields: ReactNode[] = [];\n\n function field(key: string, value: ReactNode) {\n return (\n <div className=\"bg-fd-secondary border rounded-lg text-xs p-1.5 shadow-md\">\n <span className=\"font-medium me-2\">{key}</span>\n <code className=\"text-fd-muted-foreground\">{value}</code>\n </div>\n );\n }\n\n if (schema.default !== undefined) {\n fields.push(field('Default', JSON.stringify(schema.default)));\n }\n\n if (schema.pattern) {\n fields.push(field('Match', schema.pattern));\n }\n\n if (schema.format) {\n fields.push(field('Format', schema.format));\n }\n\n if (schema.multipleOf) {\n fields.push(field('Multiple Of', schema.multipleOf));\n }\n\n let range = formatRange(\n 'value',\n schema.minimum,\n schema.exclusiveMinimum,\n schema.maximum,\n schema.exclusiveMaximum,\n );\n if (range) fields.push(field('Range', range));\n\n range = formatRange('length', schema.minLength, undefined, schema.maxLength, undefined);\n if (range) fields.push(field('Length', range));\n\n range = formatRange(\n 'properties',\n schema.minProperties,\n undefined,\n schema.maxProperties,\n undefined,\n );\n if (range) fields.push(field('Properties', range));\n\n range = formatRange('items', schema.minItems, undefined, schema.maxItems, undefined);\n if (range) fields.push(field('Items', range));\n\n if (schema.enum) {\n fields.push(field('Value in', schema.enum.map((value) => JSON.stringify(value)).join(' | ')));\n }\n\n if (showExample && schema.examples) {\n for (const example of schema.examples) {\n fields.push(field('Example', JSON.stringify(example, null, 2)));\n }\n }\n\n return fields;\n }\n\n let _counter = 0;\n const autoIds = new WeakMap();\n function getSchemaId(schema: ResolvedSchema) {\n if (typeof schema === 'boolean') return String(schema);\n const raw = ctx.schema.getRawRef(schema);\n if (raw) return raw;\n\n const prev = autoIds.get(schema);\n if (prev) return prev;\n\n const generated = `__${_counter++}`;\n autoIds.set(schema, generated);\n return generated;\n }\n\n function isVisible(schema: ResolvedSchema): boolean {\n if (typeof schema === 'boolean') return true;\n if (schema.writeOnly) return writeOnly ?? false;\n if (schema.readOnly) return readOnly ?? false;\n return true;\n }\n\n function base(schema: ResolvedSchema): FieldBase {\n if (typeof schema === 'boolean') {\n const name = schema ? 'any' : 'never';\n return {\n typeName: name,\n aliasName: name,\n };\n }\n\n return {\n description: schema.description && ctx.renderMarkdown(schema.description),\n infoTags: generateInfoTags(schema),\n typeName: schemaToString(schema, ctx.schema),\n aliasName: schemaToString(schema, ctx.schema, FormatFlags.UseAlias),\n deprecated: schema.deprecated,\n };\n }\n\n function scanRefs(id: string, schema: ResolvedSchema) {\n if (id in refs) return;\n if (typeof schema === 'boolean') {\n refs[id] = {\n type: 'primitive',\n ...base(schema),\n };\n return;\n }\n\n if (Array.isArray(schema.type)) {\n const out: SchemaData = {\n type: 'or',\n items: [],\n ...base(schema),\n };\n refs[id] = out;\n\n for (const type of schema.type) {\n const key = `${id}_type:${type}`;\n scanRefs(key, {\n ...schema,\n type,\n });\n out.items.push({\n name: type,\n $type: key,\n });\n }\n return;\n }\n\n if (schema.oneOf && schema.anyOf) {\n const out: SchemaData = {\n type: 'and',\n items: [],\n ...base(schema),\n };\n refs[id] = out;\n for (const omit of ['anyOf', 'oneOf'] as const) {\n const $type = `${id}_omit:${omit}`;\n scanRefs($type, { ...schema, [omit]: undefined });\n\n out.items.push({\n name: refs[$type].aliasName,\n $type,\n });\n }\n return;\n }\n\n // display both `oneOf` & `anyOf` as OR for simplified overview\n const union = schema.oneOf ?? schema.anyOf;\n if (union) {\n const out: SchemaData = {\n type: 'or',\n items: [],\n ...base(schema),\n };\n refs[id] = out;\n\n for (const item of union) {\n if (typeof item !== 'object' || !isVisible(item)) continue;\n const itemId = getSchemaId(item);\n const key = `${id}_extends:${itemId}`;\n\n scanRefs(key, {\n ...schema,\n oneOf: undefined,\n anyOf: undefined,\n ...item,\n properties: {\n ...schema.properties,\n ...item.properties,\n },\n });\n out.items.push({\n $type: key,\n name: refs[itemId]?.aliasName ?? schemaToString(item, ctx.schema, FormatFlags.UseAlias),\n });\n }\n return;\n }\n\n if (schema.allOf) {\n scanRefs(id, mergeAllOf(schema));\n return;\n }\n\n if (schema.type === 'object') {\n const out: SchemaData = {\n type: 'object',\n props: [],\n ...base(schema),\n };\n refs[id] = out;\n\n const { properties = {}, patternProperties, additionalProperties } = schema;\n const props = Object.entries(properties);\n if (patternProperties) props.push(...Object.entries(patternProperties));\n\n for (const [key, prop] of props) {\n if (!isVisible(prop)) continue;\n const $type = getSchemaId(prop);\n scanRefs($type, prop);\n out.props.push({\n $type,\n name: key,\n required: schema.required?.includes(key) ?? false,\n });\n }\n\n if (additionalProperties !== undefined && isVisible(additionalProperties)) {\n const $type = getSchemaId(additionalProperties);\n scanRefs($type, additionalProperties);\n\n out.props.push({\n $type,\n name: '[key: string]',\n required: false,\n });\n }\n return;\n }\n\n if (schema.type === 'array') {\n const items = schema.items ?? true;\n const $type = getSchemaId(items);\n\n refs[id] = {\n type: 'array',\n item: {\n $type,\n },\n ...base(schema),\n };\n scanRefs($type, items);\n return;\n }\n\n refs[id] = {\n type: 'primitive',\n ...base(schema),\n };\n }\n\n const $root = getSchemaId(root);\n scanRefs($root, root);\n return {\n refs,\n $root,\n };\n}\n\nfunction formatRange(\n value: string,\n min: number | undefined,\n exclusiveMin: number | undefined,\n max: number | undefined,\n exclusiveMax: number | undefined,\n) {\n const out: string[] = [];\n if (min !== undefined) {\n out.push(`${min} <=`);\n } else if (exclusiveMin !== undefined) {\n out.push(`${exclusiveMin} <`);\n }\n\n out.push(value);\n if (max !== undefined) {\n out.push(`<= ${max}`);\n } else if (exclusiveMax !== undefined) {\n out.push(`< ${exclusiveMax}`);\n }\n if (out.length > 1) return out.join(' ');\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/ui/schema/index.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { ResolvedSchema } from '@/utils/schema';\nimport type { RenderContext } from '@/types';\nimport { FormatFlags, schemaToString } from '@/utils/schema-to-string';\nimport { mergeAllOf } from '@/utils/merge-schema';\nimport type { SchemaUIProps } from '@/ui/schema/client';\nimport { SchemaUILazy } from '@/ui/schema/lazy';\n\nexport interface FieldBase {\n description?: ReactNode;\n infoTags?: ReactNode[];\n\n typeName: string;\n aliasName: string;\n\n deprecated?: boolean;\n}\n\nexport type SchemaData = FieldBase &\n (\n | {\n type: 'primitive';\n }\n | {\n type: 'object';\n props: {\n name: string;\n $type: string;\n required: boolean;\n }[];\n }\n | {\n type: 'array';\n item: {\n $type: string;\n };\n }\n | {\n type: 'or';\n items: {\n name: string;\n $type: string;\n }[];\n }\n | {\n type: 'and';\n items: {\n name: string;\n $type: string;\n }[];\n }\n );\n\nexport interface SchemaUIOptions {\n root: ResolvedSchema;\n client: Omit<SchemaUIProps, 'generated'>;\n\n /**\n * include read only props\n */\n readOnly?: boolean;\n /**\n * include write only props\n */\n writeOnly?: boolean;\n}\n\nexport interface SchemaUIGeneratedData {\n $root: string;\n refs: Record<string, SchemaData>;\n}\n\nexport function Schema({\n ctx,\n ...options\n}: SchemaUIOptions & {\n ctx: RenderContext;\n}) {\n if (ctx.schemaUI?.render) {\n return ctx.schemaUI.render(options, ctx);\n }\n\n return <SchemaUILazy {...options.client} generated={generateSchemaUI(options, ctx)} />;\n}\n\nexport function generateSchemaUI(\n { root, readOnly, writeOnly }: SchemaUIOptions,\n ctx: RenderContext,\n): SchemaUIGeneratedData {\n const refs: Record<string, SchemaData> = {};\n const { showExample = false } = ctx.schemaUI ?? {};\n\n function generateInfoTags(schema: Exclude<ResolvedSchema, boolean>) {\n const fields: ReactNode[] = [];\n\n function field(key: string, value: ReactNode) {\n return (\n <div className=\"bg-fd-secondary border rounded-lg text-xs p-1.5 shadow-md\">\n <span className=\"font-medium me-2\">{key}</span>\n <code className=\"text-fd-muted-foreground\">{value}</code>\n </div>\n );\n }\n\n if (schema.default !== undefined) {\n fields.push(field('Default', JSON.stringify(schema.default)));\n }\n\n if (schema.pattern) {\n fields.push(field('Match', schema.pattern));\n }\n\n if (schema.format) {\n fields.push(field('Format', schema.format));\n }\n\n if (schema.multipleOf) {\n fields.push(field('Multiple Of', schema.multipleOf));\n }\n\n let range = formatRange(\n 'value',\n schema.minimum,\n schema.exclusiveMinimum,\n schema.maximum,\n schema.exclusiveMaximum,\n );\n if (range) fields.push(field('Range', range));\n\n range = formatRange('length', schema.minLength, undefined, schema.maxLength, undefined);\n if (range) fields.push(field('Length', range));\n\n range = formatRange(\n 'properties',\n schema.minProperties,\n undefined,\n schema.maxProperties,\n undefined,\n );\n if (range) fields.push(field('Properties', range));\n\n range = formatRange('items', schema.minItems, undefined, schema.maxItems, undefined);\n if (range) fields.push(field('Items', range));\n\n if (schema.enum) {\n fields.push(field('Value in', schema.enum.map((value) => JSON.stringify(value)).join(' | ')));\n }\n\n if (showExample && schema.examples) {\n for (const example of schema.examples) {\n fields.push(field('Example', JSON.stringify(example, null, 2)));\n }\n }\n\n return fields;\n }\n\n let _counter = 0;\n const autoIds = new WeakMap();\n function getSchemaId(schema: ResolvedSchema) {\n if (typeof schema === 'boolean') return String(schema);\n const raw = ctx.schema.getRawRef(schema);\n if (raw) return raw;\n\n const prev = autoIds.get(schema);\n if (prev) return prev;\n\n const generated = `__${_counter++}`;\n autoIds.set(schema, generated);\n return generated;\n }\n\n function isVisible(schema: ResolvedSchema): boolean {\n if (typeof schema === 'boolean') return true;\n if (schema.writeOnly) return writeOnly ?? false;\n if (schema.readOnly) return readOnly ?? false;\n return true;\n }\n\n function base(schema: ResolvedSchema): FieldBase {\n if (typeof schema === 'boolean') {\n const name = schema ? 'any' : 'never';\n return {\n typeName: name,\n aliasName: name,\n };\n }\n\n return {\n description: schema.description && ctx.renderMarkdown(schema.description),\n infoTags: generateInfoTags(schema),\n typeName: schemaToString(schema, ctx.schema),\n aliasName: schemaToString(schema, ctx.schema, FormatFlags.UseAlias),\n deprecated: schema.deprecated,\n };\n }\n\n function scanRefs(id: string, schema: ResolvedSchema) {\n if (id in refs) return;\n if (typeof schema === 'boolean') {\n refs[id] = {\n type: 'primitive',\n ...base(schema),\n };\n return;\n }\n\n if (Array.isArray(schema.type)) {\n const out: SchemaData = {\n type: 'or',\n items: [],\n ...base(schema),\n };\n refs[id] = out;\n\n for (const type of schema.type) {\n const key = `${id}_type:${type}`;\n scanRefs(key, {\n ...schema,\n type,\n });\n out.items.push({\n name: type,\n $type: key,\n });\n }\n return;\n }\n\n if (schema.oneOf && schema.anyOf) {\n const out: SchemaData = {\n type: 'and',\n items: [],\n ...base(schema),\n };\n refs[id] = out;\n for (const omit of ['anyOf', 'oneOf'] as const) {\n const $type = `${id}_omit:${omit}`;\n scanRefs($type, { ...schema, [omit]: undefined });\n\n out.items.push({\n name: refs[$type].aliasName,\n $type,\n });\n }\n return;\n }\n\n // display both `oneOf` & `anyOf` as OR for simplified overview\n const union = schema.oneOf ?? schema.anyOf;\n if (union) {\n const out: SchemaData = {\n type: 'or',\n items: [],\n ...base(schema),\n };\n refs[id] = out;\n\n for (const item of union) {\n if (typeof item !== 'object' || !isVisible(item)) continue;\n const itemId = getSchemaId(item);\n const key = `${id}_extends:${itemId}`;\n\n scanRefs(key, {\n ...schema,\n oneOf: undefined,\n anyOf: undefined,\n ...item,\n properties: {\n ...schema.properties,\n ...item.properties,\n },\n });\n out.items.push({\n $type: key,\n name: refs[itemId]?.aliasName ?? schemaToString(item, ctx.schema, FormatFlags.UseAlias),\n });\n }\n return;\n }\n\n if (schema.allOf) {\n scanRefs(id, mergeAllOf(schema));\n return;\n }\n\n if (schema.type === 'object') {\n const out: SchemaData = {\n type: 'object',\n props: [],\n ...base(schema),\n };\n refs[id] = out;\n\n const { properties = {}, patternProperties, additionalProperties } = schema;\n const props = Object.entries(properties);\n if (patternProperties) props.push(...Object.entries(patternProperties));\n\n for (const [key, prop] of props) {\n if (!isVisible(prop)) continue;\n const $type = getSchemaId(prop);\n scanRefs($type, prop);\n out.props.push({\n $type,\n name: key,\n required: schema.required?.includes(key) ?? false,\n });\n }\n\n if (additionalProperties !== undefined && isVisible(additionalProperties)) {\n const $type = getSchemaId(additionalProperties);\n scanRefs($type, additionalProperties);\n\n out.props.push({\n $type,\n name: '[key: string]',\n required: false,\n });\n }\n return;\n }\n\n if (schema.type === 'array') {\n const items = schema.items ?? true;\n const $type = getSchemaId(items);\n\n refs[id] = {\n type: 'array',\n item: {\n $type,\n },\n ...base(schema),\n };\n scanRefs($type, items);\n return;\n }\n\n refs[id] = {\n type: 'primitive',\n ...base(schema),\n };\n }\n\n const $root = getSchemaId(root);\n scanRefs($root, root);\n return {\n refs,\n $root,\n };\n}\n\nfunction formatRange(\n value: string,\n min: number | undefined,\n exclusiveMin: number | undefined,\n max: number | undefined,\n exclusiveMax: number | undefined,\n) {\n const out: string[] = [];\n if (min !== undefined) {\n out.push(`${min} <=`);\n } else if (exclusiveMin !== undefined) {\n out.push(`${exclusiveMin} <`);\n }\n\n out.push(value);\n if (max !== undefined) {\n out.push(`<= ${max}`);\n } else if (exclusiveMax !== undefined) {\n out.push(`< ${exclusiveMax}`);\n }\n if (out.length > 1) return out.join(' ');\n}\n"],"mappings":";;;;;;AAwEA,SAAgB,OAAO,EACrB,KACA,GAAG,WAGF;AACD,KAAI,IAAI,UAAU,OAChB,QAAO,IAAI,SAAS,OAAO,SAAS,IAAI;AAG1C,QAAO,oBAAC;EAAa,GAAI,QAAQ;EAAQ,WAAW,iBAAiB,SAAS,IAAI;GAAI;;AAGxF,SAAgB,iBACd,EAAE,MAAM,UAAU,aAClB,KACuB;CACvB,MAAM,OAAmC,EAAE;CAC3C,MAAM,EAAE,cAAc,UAAU,IAAI,YAAY,EAAE;CAElD,SAAS,iBAAiB,QAA0C;EAClE,MAAM,SAAsB,EAAE;EAE9B,SAAS,MAAM,KAAa,OAAkB;AAC5C,UACE,qBAAC;IAAI,WAAU;eACb,oBAAC;KAAK,WAAU;eAAoB;MAAW,EAC/C,oBAAC;KAAK,WAAU;eAA4B;MAAa;KACrD;;AAIV,MAAI,OAAO,YAAY,OACrB,QAAO,KAAK,MAAM,WAAW,KAAK,UAAU,OAAO,QAAQ,CAAC,CAAC;AAG/D,MAAI,OAAO,QACT,QAAO,KAAK,MAAM,SAAS,OAAO,QAAQ,CAAC;AAG7C,MAAI,OAAO,OACT,QAAO,KAAK,MAAM,UAAU,OAAO,OAAO,CAAC;AAG7C,MAAI,OAAO,WACT,QAAO,KAAK,MAAM,eAAe,OAAO,WAAW,CAAC;EAGtD,IAAI,QAAQ,YACV,SACA,OAAO,SACP,OAAO,kBACP,OAAO,SACP,OAAO,iBACR;AACD,MAAI,MAAO,QAAO,KAAK,MAAM,SAAS,MAAM,CAAC;AAE7C,UAAQ,YAAY,UAAU,OAAO,WAAW,QAAW,OAAO,WAAW,OAAU;AACvF,MAAI,MAAO,QAAO,KAAK,MAAM,UAAU,MAAM,CAAC;AAE9C,UAAQ,YACN,cACA,OAAO,eACP,QACA,OAAO,eACP,OACD;AACD,MAAI,MAAO,QAAO,KAAK,MAAM,cAAc,MAAM,CAAC;AAElD,UAAQ,YAAY,SAAS,OAAO,UAAU,QAAW,OAAO,UAAU,OAAU;AACpF,MAAI,MAAO,QAAO,KAAK,MAAM,SAAS,MAAM,CAAC;AAE7C,MAAI,OAAO,KACT,QAAO,KAAK,MAAM,YAAY,OAAO,KAAK,KAAK,UAAU,KAAK,UAAU,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;AAG/F,MAAI,eAAe,OAAO,SACxB,MAAK,MAAM,WAAW,OAAO,SAC3B,QAAO,KAAK,MAAM,WAAW,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC,CAAC;AAInE,SAAO;;CAGT,IAAI,WAAW;CACf,MAAM,0BAAU,IAAI,SAAS;CAC7B,SAAS,YAAY,QAAwB;AAC3C,MAAI,OAAO,WAAW,UAAW,QAAO,OAAO,OAAO;EACtD,MAAM,MAAM,IAAI,OAAO,UAAU,OAAO;AACxC,MAAI,IAAK,QAAO;EAEhB,MAAM,OAAO,QAAQ,IAAI,OAAO;AAChC,MAAI,KAAM,QAAO;EAEjB,MAAM,YAAY,KAAK;AACvB,UAAQ,IAAI,QAAQ,UAAU;AAC9B,SAAO;;CAGT,SAAS,UAAU,QAAiC;AAClD,MAAI,OAAO,WAAW,UAAW,QAAO;AACxC,MAAI,OAAO,UAAW,QAAO,aAAa;AAC1C,MAAI,OAAO,SAAU,QAAO,YAAY;AACxC,SAAO;;CAGT,SAAS,KAAK,QAAmC;AAC/C,MAAI,OAAO,WAAW,WAAW;GAC/B,MAAM,OAAO,SAAS,QAAQ;AAC9B,UAAO;IACL,UAAU;IACV,WAAW;IACZ;;AAGH,SAAO;GACL,aAAa,OAAO,eAAe,IAAI,eAAe,OAAO,YAAY;GACzE,UAAU,iBAAiB,OAAO;GAClC,UAAU,eAAe,QAAQ,IAAI,OAAO;GAC5C,WAAW,eAAe,QAAQ,IAAI,QAAQ,YAAY,SAAS;GACnE,YAAY,OAAO;GACpB;;CAGH,SAAS,SAAS,IAAY,QAAwB;AACpD,MAAI,MAAM,KAAM;AAChB,MAAI,OAAO,WAAW,WAAW;AAC/B,QAAK,MAAM;IACT,MAAM;IACN,GAAG,KAAK,OAAO;IAChB;AACD;;AAGF,MAAI,MAAM,QAAQ,OAAO,KAAK,EAAE;GAC9B,MAAM,MAAkB;IACtB,MAAM;IACN,OAAO,EAAE;IACT,GAAG,KAAK,OAAO;IAChB;AACD,QAAK,MAAM;AAEX,QAAK,MAAM,QAAQ,OAAO,MAAM;IAC9B,MAAM,MAAM,GAAG,GAAG,QAAQ;AAC1B,aAAS,KAAK;KACZ,GAAG;KACH;KACD,CAAC;AACF,QAAI,MAAM,KAAK;KACb,MAAM;KACN,OAAO;KACR,CAAC;;AAEJ;;AAGF,MAAI,OAAO,SAAS,OAAO,OAAO;GAChC,MAAM,MAAkB;IACtB,MAAM;IACN,OAAO,EAAE;IACT,GAAG,KAAK,OAAO;IAChB;AACD,QAAK,MAAM;AACX,QAAK,MAAM,QAAQ,CAAC,SAAS,QAAQ,EAAW;IAC9C,MAAM,QAAQ,GAAG,GAAG,QAAQ;AAC5B,aAAS,OAAO;KAAE,GAAG;MAAS,OAAO;KAAW,CAAC;AAEjD,QAAI,MAAM,KAAK;KACb,MAAM,KAAK,OAAO;KAClB;KACD,CAAC;;AAEJ;;EAIF,MAAM,QAAQ,OAAO,SAAS,OAAO;AACrC,MAAI,OAAO;GACT,MAAM,MAAkB;IACtB,MAAM;IACN,OAAO,EAAE;IACT,GAAG,KAAK,OAAO;IAChB;AACD,QAAK,MAAM;AAEX,QAAK,MAAM,QAAQ,OAAO;AACxB,QAAI,OAAO,SAAS,YAAY,CAAC,UAAU,KAAK,CAAE;IAClD,MAAM,SAAS,YAAY,KAAK;IAChC,MAAM,MAAM,GAAG,GAAG,WAAW;AAE7B,aAAS,KAAK;KACZ,GAAG;KACH,OAAO;KACP,OAAO;KACP,GAAG;KACH,YAAY;MACV,GAAG,OAAO;MACV,GAAG,KAAK;MACT;KACF,CAAC;AACF,QAAI,MAAM,KAAK;KACb,OAAO;KACP,MAAM,KAAK,SAAS,aAAa,eAAe,MAAM,IAAI,QAAQ,YAAY,SAAS;KACxF,CAAC;;AAEJ;;AAGF,MAAI,OAAO,OAAO;AAChB,YAAS,IAAI,WAAW,OAAO,CAAC;AAChC;;AAGF,MAAI,OAAO,SAAS,UAAU;GAC5B,MAAM,MAAkB;IACtB,MAAM;IACN,OAAO,EAAE;IACT,GAAG,KAAK,OAAO;IAChB;AACD,QAAK,MAAM;GAEX,MAAM,EAAE,aAAa,EAAE,EAAE,mBAAmB,yBAAyB;GACrE,MAAM,QAAQ,OAAO,QAAQ,WAAW;AACxC,OAAI,kBAAmB,OAAM,KAAK,GAAG,OAAO,QAAQ,kBAAkB,CAAC;AAEvE,QAAK,MAAM,CAAC,KAAK,SAAS,OAAO;AAC/B,QAAI,CAAC,UAAU,KAAK,CAAE;IACtB,MAAM,QAAQ,YAAY,KAAK;AAC/B,aAAS,OAAO,KAAK;AACrB,QAAI,MAAM,KAAK;KACb;KACA,MAAM;KACN,UAAU,OAAO,UAAU,SAAS,IAAI,IAAI;KAC7C,CAAC;;AAGJ,OAAI,yBAAyB,UAAa,UAAU,qBAAqB,EAAE;IACzE,MAAM,QAAQ,YAAY,qBAAqB;AAC/C,aAAS,OAAO,qBAAqB;AAErC,QAAI,MAAM,KAAK;KACb;KACA,MAAM;KACN,UAAU;KACX,CAAC;;AAEJ;;AAGF,MAAI,OAAO,SAAS,SAAS;GAC3B,MAAM,QAAQ,OAAO,SAAS;GAC9B,MAAM,QAAQ,YAAY,MAAM;AAEhC,QAAK,MAAM;IACT,MAAM;IACN,MAAM,EACJ,OACD;IACD,GAAG,KAAK,OAAO;IAChB;AACD,YAAS,OAAO,MAAM;AACtB;;AAGF,OAAK,MAAM;GACT,MAAM;GACN,GAAG,KAAK,OAAO;GAChB;;CAGH,MAAM,QAAQ,YAAY,KAAK;AAC/B,UAAS,OAAO,KAAK;AACrB,QAAO;EACL;EACA;EACD;;AAGH,SAAS,YACP,OACA,KACA,cACA,KACA,cACA;CACA,MAAM,MAAgB,EAAE;AACxB,KAAI,QAAQ,OACV,KAAI,KAAK,GAAG,IAAI,KAAK;UACZ,iBAAiB,OAC1B,KAAI,KAAK,GAAG,aAAa,IAAI;AAG/B,KAAI,KAAK,MAAM;AACf,KAAI,QAAQ,OACV,KAAI,KAAK,MAAM,MAAM;UACZ,iBAAiB,OAC1B,KAAI,KAAK,KAAK,eAAe;AAE/B,KAAI,IAAI,SAAS,EAAG,QAAO,IAAI,KAAK,IAAI"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id-to-title.js","names":[
|
|
1
|
+
{"version":3,"file":"id-to-title.js","names":[],"sources":["../../src/utils/id-to-title.ts"],"sourcesContent":["export function idToTitle(id: string): string {\n let result: string[] = [];\n\n for (const c of id) {\n if (result.length === 0) result.push(c.toLocaleUpperCase());\n // ignore the other parts surrounded with '.', like 'migrations.dev' -> 'dev'\n else if (c === '.') result = [];\n else if (/^[A-Z]$/.test(c) && result.at(-1) !== ' ') result.push(' ', c);\n else if (c === '-') result.push(' ');\n else result.push(c);\n }\n\n return result.join('');\n}\n"],"mappings":";AAAA,SAAgB,UAAU,IAAoB;CAC5C,IAAI,SAAmB,EAAE;AAEzB,MAAK,MAAM,KAAK,GACd,KAAI,OAAO,WAAW,EAAG,QAAO,KAAK,EAAE,mBAAmB,CAAC;UAElD,MAAM,IAAK,UAAS,EAAE;UACtB,UAAU,KAAK,EAAE,IAAI,OAAO,GAAG,GAAG,KAAK,IAAK,QAAO,KAAK,KAAK,EAAE;UAC/D,MAAM,IAAK,QAAO,KAAK,IAAI;KAC/B,QAAO,KAAK,EAAE;AAGrB,QAAO,OAAO,KAAK,GAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-schema.js","names":[
|
|
1
|
+
{"version":3,"file":"merge-schema.js","names":[],"sources":["../../src/utils/merge-schema.ts"],"sourcesContent":["import { type ParsedSchema } from '@/utils/schema';\nimport { deepEqual } from './deep-equal';\n\n/**\n * Merge `allOf` object schema\n */\nexport function mergeAllOf(schema: ParsedSchema): ParsedSchema {\n if (typeof schema === 'boolean' || !schema.allOf) return schema;\n\n const { allOf, ...rest } = schema;\n let result: ParsedSchema = rest;\n for (const item of allOf) {\n result = intersection(result, item);\n }\n return result;\n}\n\nexport function intersection(a: ParsedSchema, b: ParsedSchema): ParsedSchema {\n a = mergeAllOf(a);\n b = mergeAllOf(b);\n if (typeof a === 'boolean' && typeof b === 'boolean') return a && b;\n if (typeof a === 'boolean') return a;\n if (typeof b === 'boolean') return b;\n\n const result: ParsedSchema = { ...a };\n for (const _k in b) {\n const key = _k as keyof typeof b;\n\n switch (key) {\n case '$id':\n case '$comment':\n case 'description':\n case 'additionalItems':\n case 'examples':\n case 'allOf':\n case 'writeOnly':\n case 'readOnly':\n // ignored\n break;\n case 'title': {\n const value = b[key];\n if (value === undefined) break;\n if (result[key]) {\n result[key] = `${result[key]} & ${value}`;\n } else {\n result[key] = value;\n }\n break;\n }\n case 'minItems':\n case 'minimum':\n case 'exclusiveMinimum':\n case 'minProperties':\n case 'minContains':\n case 'minLength': {\n const value = b[key];\n if (value === undefined) break;\n result[key] = result[key] === undefined ? value : Math.max(result[key], value);\n break;\n }\n case 'maxContains':\n case 'maxItems':\n case 'maxLength':\n case 'maxProperties':\n case 'maximum':\n case 'exclusiveMaximum': {\n const value = b[key];\n if (value === undefined) break;\n result[key] = result[key] === undefined ? value : Math.min(result[key], value);\n break;\n }\n // intersection\n case 'enum':\n case 'anyOf':\n case 'oneOf': {\n const value = b[key];\n if (value === undefined) break;\n\n result[key] = result[key] === undefined ? value : intersectArray(result[key], value);\n break;\n }\n // require same\n case 'format':\n case 'const':\n case 'type': {\n const value = b[key];\n if (value === undefined) break;\n result[key] ??= value;\n\n if (!deepEqual(result[key], value)) return false;\n break;\n }\n // add\n case 'required': {\n const value = b[key];\n if (value === undefined) break;\n result[key] = [...(result[key] ?? []), ...value];\n break;\n }\n case 'properties':\n case 'patternProperties': {\n const value = b[key];\n if (value === undefined) break;\n\n if (result[key] === undefined) {\n result[key] = value;\n break;\n }\n\n const out: Record<string, ParsedSchema> = {};\n const allProps = new Set<string>();\n for (const k in result[key]) allProps.add(k);\n for (const k in value) allProps.add(k);\n\n for (const prop of allProps) {\n const aProp = result[key][prop];\n const bProp = value[prop];\n if (aProp === undefined) {\n out[prop] = bProp;\n } else if (bProp === undefined) {\n out[prop] = aProp;\n } else {\n out[prop] = intersection(aProp, bProp);\n }\n }\n\n result[key] = out;\n break;\n }\n case 'additionalProperties':\n case 'contains':\n case 'items': {\n const value = b[key];\n if (value === undefined) break;\n\n result[key] = result[key] === undefined ? value : intersection(result[key], value);\n break;\n }\n case 'not': {\n const value = b[key];\n if (value === undefined) break;\n\n if (result[key] && value) {\n result.not = { anyOf: [result[key], value] };\n } else if (value) {\n result.not = value;\n }\n break;\n }\n default:\n result[key] = b[key];\n }\n }\n\n return result;\n}\n\nfunction intersectArray<T>(a: readonly T[], b: readonly T[]): T[] {\n const out = new Set<T>();\n for (const item of a) {\n if (b.includes(item)) out.add(item);\n }\n for (const item of b) {\n if (a.includes(item)) out.add(item);\n }\n return Array.from(out);\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","names":[
|
|
1
|
+
{"version":3,"file":"builder.js","names":[],"sources":["../../../src/utils/pages/builder.ts"],"sourcesContent":["import type { ProcessedDocument } from '@/utils/process-document';\nimport type { OpenAPIServer } from '@/server';\nimport type { OperationItem, WebhookItem } from '@/ui/api-page';\nimport type { Document, OperationObject, PathItemObject, TagObject } from '@/types';\nimport { getTagDisplayName, methodKeys, type NoReference } from '@/utils/schema';\nimport type { OpenAPIV3_1 } from 'openapi-types';\nimport { idToTitle } from '@/utils/id-to-title';\n\ninterface BaseEntry {\n path: string;\n schemaId: string;\n info: {\n title: string;\n description?: string;\n };\n}\n\nexport interface OperationOutput extends BaseEntry {\n type: 'operation';\n item: OperationItem;\n}\n\nexport interface WebhookOutput extends BaseEntry {\n type: 'webhook';\n item: WebhookItem;\n}\n\nexport interface TagOutput extends BaseEntry {\n type: 'tag';\n tag: string;\n rawTag: TagObject;\n operations: OperationItem[];\n webhooks: WebhookItem[];\n}\n\nexport interface OutputGroup extends BaseEntry {\n type: 'group';\n operations: OperationItem[];\n webhooks: WebhookItem[];\n}\n\nexport type OutputEntry = TagOutput | OperationOutput | WebhookOutput | OutputGroup;\n\nexport interface PagesBuilderConfig {\n toPages: (builder: PagesBuilder) => void;\n}\n\nexport interface PagesBuilder {\n /**\n * the input ID in OpenAPI server\n */\n id: string;\n document: ProcessedDocument;\n /**\n * add output entry.\n *\n * When the `path` property is unspecified, it will generate one.\n */\n create: (entry: OutputEntry) => void;\n\n /**\n * get file path from operation path, useful for generating output paths.\n */\n routePathToFilePath: (path: string) => string;\n\n /**\n * Extract useful info for rendering\n */\n extract: () => ExtractedInfo;\n fromExtractedWebhook: (item: WebhookItem) =>\n | {\n get displayName(): string;\n pathItem: NoReference<PathItemObject>;\n operation: NoReference<OperationObject>;\n }\n | undefined;\n fromExtractedOperation: (item: OperationItem) =>\n | {\n get displayName(): string;\n pathItem: NoReference<PathItemObject>;\n operation: NoReference<OperationObject>;\n }\n | undefined;\n fromTag: (tag: TagObject) => {\n get displayName(): string;\n };\n fromTagName: (tag: string) =>\n | {\n info: TagObject;\n get displayName(): string;\n }\n | undefined;\n}\n\ninterface ExtractedInfo {\n webhooks: (WebhookItem & { tags?: string[] })[];\n operations: (OperationItem & {\n tags?: string[];\n })[];\n}\n\nexport async function fromServer(\n server: OpenAPIServer,\n config: PagesBuilderConfig,\n): Promise<Record<string, OutputEntry[]>> {\n const schemas = await server.getSchemas();\n const generated: Record<string, OutputEntry[]> = {};\n\n const entries = Object.entries(schemas);\n if (entries.length === 0) {\n throw new Error('No input files found.');\n }\n\n for (const [id, schema] of entries) {\n generated[id] = fromSchema(id, schema, config);\n }\n\n return generated;\n}\n\nexport function fromSchema(\n schemaId: string,\n processed: ProcessedDocument,\n config: PagesBuilderConfig,\n): OutputEntry[] {\n const files: OutputEntry[] = [];\n const { toPages } = config;\n const { dereferenced } = processed;\n\n toPages({\n id: schemaId,\n document: processed,\n create(entry) {\n files.push(entry);\n },\n extract: () => extractInfo(dereferenced),\n routePathToFilePath(path) {\n return path\n .toLowerCase()\n .replaceAll('.', '-')\n .split('/')\n .flatMap((v) => {\n if (v.startsWith('{') && v.endsWith('}')) return v.slice(1, -1);\n if (v.length === 0) return [];\n return v;\n })\n .join('/');\n },\n fromExtractedWebhook(item) {\n const pathItem = dereferenced.webhooks?.[item.name];\n if (!pathItem) return;\n const operation = pathItem?.[item.method];\n if (!operation) return;\n return {\n pathItem,\n operation,\n get displayName() {\n return operation.summary || pathItem.summary || idToTitle(item.name);\n },\n };\n },\n fromExtractedOperation(item) {\n const pathItem = dereferenced.paths?.[item.path];\n if (!pathItem) return;\n const operation = pathItem?.[item.method];\n if (!operation) return;\n return {\n pathItem,\n operation,\n get displayName() {\n return (\n operation.summary ||\n pathItem.summary ||\n (operation.operationId ? idToTitle(operation.operationId) : item.path)\n );\n },\n };\n },\n fromTag(tag) {\n return {\n get displayName() {\n return getTagDisplayName(tag);\n },\n };\n },\n fromTagName(name) {\n const tag = dereferenced.tags?.find((item) => item.name === name);\n if (!tag) return;\n\n return {\n info: tag,\n ...this.fromTag(tag),\n };\n },\n });\n\n return files;\n}\n\nfunction extractInfo(document: NoReference<Document>): ExtractedInfo {\n const result: ExtractedInfo = { webhooks: [], operations: [] };\n\n for (const [path, pathItem] of Object.entries(document.paths ?? {})) {\n if (!pathItem) continue;\n\n for (const methodKey of methodKeys) {\n if (!pathItem[methodKey]) continue;\n\n result.operations.push({\n method: methodKey as OpenAPIV3_1.HttpMethods,\n path,\n tags: pathItem[methodKey]?.tags,\n });\n }\n }\n\n for (const [name, pathItem] of Object.entries(document.webhooks ?? {})) {\n if (!pathItem) continue;\n\n for (const methodKey of methodKeys) {\n if (!pathItem[methodKey]) continue;\n\n result.webhooks.push({\n method: methodKey as OpenAPIV3_1.HttpMethods,\n name,\n tags: pathItem[methodKey]?.tags,\n });\n }\n }\n\n return result;\n}\n"],"mappings":";;;;AAqGA,eAAsB,WACpB,QACA,QACwC;CACxC,MAAM,UAAU,MAAM,OAAO,YAAY;CACzC,MAAM,YAA2C,EAAE;CAEnD,MAAM,UAAU,OAAO,QAAQ,QAAQ;AACvC,KAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,MAAM,wBAAwB;AAG1C,MAAK,MAAM,CAAC,IAAI,WAAW,QACzB,WAAU,MAAM,WAAW,IAAI,QAAQ,OAAO;AAGhD,QAAO;;AAGT,SAAgB,WACd,UACA,WACA,QACe;CACf,MAAM,QAAuB,EAAE;CAC/B,MAAM,EAAE,YAAY;CACpB,MAAM,EAAE,iBAAiB;AAEzB,SAAQ;EACN,IAAI;EACJ,UAAU;EACV,OAAO,OAAO;AACZ,SAAM,KAAK,MAAM;;EAEnB,eAAe,YAAY,aAAa;EACxC,oBAAoB,MAAM;AACxB,UAAO,KACJ,aAAa,CACb,WAAW,KAAK,IAAI,CACpB,MAAM,IAAI,CACV,SAAS,MAAM;AACd,QAAI,EAAE,WAAW,IAAI,IAAI,EAAE,SAAS,IAAI,CAAE,QAAO,EAAE,MAAM,GAAG,GAAG;AAC/D,QAAI,EAAE,WAAW,EAAG,QAAO,EAAE;AAC7B,WAAO;KACP,CACD,KAAK,IAAI;;EAEd,qBAAqB,MAAM;GACzB,MAAM,WAAW,aAAa,WAAW,KAAK;AAC9C,OAAI,CAAC,SAAU;GACf,MAAM,YAAY,WAAW,KAAK;AAClC,OAAI,CAAC,UAAW;AAChB,UAAO;IACL;IACA;IACA,IAAI,cAAc;AAChB,YAAO,UAAU,WAAW,SAAS,WAAW,UAAU,KAAK,KAAK;;IAEvE;;EAEH,uBAAuB,MAAM;GAC3B,MAAM,WAAW,aAAa,QAAQ,KAAK;AAC3C,OAAI,CAAC,SAAU;GACf,MAAM,YAAY,WAAW,KAAK;AAClC,OAAI,CAAC,UAAW;AAChB,UAAO;IACL;IACA;IACA,IAAI,cAAc;AAChB,YACE,UAAU,WACV,SAAS,YACR,UAAU,cAAc,UAAU,UAAU,YAAY,GAAG,KAAK;;IAGtE;;EAEH,QAAQ,KAAK;AACX,UAAO,EACL,IAAI,cAAc;AAChB,WAAO,kBAAkB,IAAI;MAEhC;;EAEH,YAAY,MAAM;GAChB,MAAM,MAAM,aAAa,MAAM,MAAM,SAAS,KAAK,SAAS,KAAK;AACjE,OAAI,CAAC,IAAK;AAEV,UAAO;IACL,MAAM;IACN,GAAG,KAAK,QAAQ,IAAI;IACrB;;EAEJ,CAAC;AAEF,QAAO;;AAGT,SAAS,YAAY,UAAgD;CACnE,MAAM,SAAwB;EAAE,UAAU,EAAE;EAAE,YAAY,EAAE;EAAE;AAE9D,MAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,SAAS,SAAS,EAAE,CAAC,EAAE;AACnE,MAAI,CAAC,SAAU;AAEf,OAAK,MAAM,aAAa,YAAY;AAClC,OAAI,CAAC,SAAS,WAAY;AAE1B,UAAO,WAAW,KAAK;IACrB,QAAQ;IACR;IACA,MAAM,SAAS,YAAY;IAC5B,CAAC;;;AAIN,MAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,SAAS,YAAY,EAAE,CAAC,EAAE;AACtE,MAAI,CAAC,SAAU;AAEf,OAAK,MAAM,aAAa,YAAY;AAClC,OAAI,CAAC,SAAS,WAAY;AAE1B,UAAO,SAAS,KAAK;IACnB,QAAQ;IACR;IACA,MAAM,SAAS,YAAY;IAC5B,CAAC;;;AAIN,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preset-auto.js","names":["nameFn: NameFn<OutputEntry>","entry: OutputGroup","entry: TagOutput","entry: OperationOutput","entry: WebhookOutput"],"sources":["../../../src/utils/pages/preset-auto.ts"],"sourcesContent":["import * as path from 'node:path';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport type {\n OperationOutput,\n OutputEntry,\n OutputGroup,\n PagesBuilder,\n PagesBuilderConfig,\n TagOutput,\n WebhookOutput,\n} from '@/utils/pages/builder';\nimport { isUrl } from '@/utils/url';\n\ninterface OperationConfig extends BaseConfig {\n /**\n * Generate a page for each API endpoint/operation (default).\n */\n per?: 'operation';\n\n /**\n * Group output using folders (Only works on `operation` mode)\n * - tag: `{tag}/{file}`\n * - route: `{endpoint}/{method}` (it will ignore the `name` option)\n * - none: `{file}` (default)\n * - a function that aligns group name (folder path) to each entry\n *\n * @defaultValue 'none'\n */\n groupBy?: 'tag' | 'route' | 'none' | ((entry: OperationOutput | WebhookOutput) => string);\n\n /**\n * Specify name for output file\n */\n name?: NameFn<OperationOutput | WebhookOutput> | NameFnOptions;\n}\n\ninterface TagConfig extends BaseConfig {\n /**\n * Generate a page for each tag.\n */\n per: 'tag';\n\n /**\n * Specify name for output file\n */\n name?: NameFn<TagOutput> | NameFnOptions;\n}\n\ninterface SchemaConfig extends BaseConfig {\n /**\n * Generate a page for each schema file.\n */\n per: 'file';\n\n /**\n * Specify name for output file\n */\n name?: NameFn<OutputGroup> | NameFnOptions;\n}\n\nexport type SchemaToPagesOptions =\n | SchemaConfig\n | TagConfig\n | OperationConfig\n | ({\n per: 'custom';\n } & PagesBuilderConfig);\n\ntype NameFn<Entry> = (\n this: PagesBuilder,\n output: Entry,\n document: ProcessedDocument['dereferenced'],\n) => string;\n\ninterface NameFnOptions {\n /**\n * The version of algorithm used to generate file paths.\n *\n * v1: Fumadocs OpenAPI v8\n * v2: Fumadocs OpenAPI v9\n *\n * @defaultValue v2\n */\n algorithm?: 'v2' | 'v1';\n}\n\ninterface BaseConfig {\n /**\n * Custom function to convert names into file names.\n *\n * By default, it only escapes whitespaces and upper case (English) characters\n */\n slugify?: (name: string) => string;\n}\n\nexport function createAutoPreset(options: SchemaToPagesOptions): PagesBuilderConfig {\n if (options.per === 'custom') return options;\n const {\n slugify = (s) => {\n return s.replace(/\\s+/g, '-').toLowerCase();\n },\n } = options;\n let nameFn: NameFn<OutputEntry>;\n\n if (typeof options.name === 'function') {\n nameFn = options.name as NameFn<OutputEntry>;\n } else {\n const { algorithm = 'v2' } = options.name ?? {};\n\n nameFn = function (result, document) {\n if (result.type === 'tag') {\n return slugify(result.tag);\n }\n\n if (result.type === 'group') {\n const schemaId = result.schemaId;\n\n return isUrl(schemaId) ? 'index' : path.basename(schemaId, path.extname(schemaId));\n }\n\n if (result.type === 'operation') {\n const operation = document.paths![result.item.path]![result.item.method]!;\n\n if (algorithm === 'v2' && operation.operationId) {\n return operation.operationId;\n }\n\n return path.join(\n this.routePathToFilePath(result.item.path),\n result.item.method.toLowerCase(),\n );\n }\n\n const hook = document.webhooks![result.item.name][result.item.method]!;\n\n if (algorithm === 'v2' && hook.operationId) {\n return hook.operationId;\n }\n\n return slugify(result.item.name);\n };\n }\n\n function groupOutput(builder: PagesBuilder, entry: OperationOutput | WebhookOutput): string[] {\n const { dereferenced } = builder.document;\n const { groupBy = 'none' } = options as OperationConfig;\n\n if (groupBy === 'route') {\n return [\n path.join(\n builder.routePathToFilePath(\n entry.type === 'operation' ? entry.item.path : entry.item.name,\n ),\n `${entry.item.method.toLowerCase()}.mdx`,\n ),\n ];\n }\n\n const file = nameFn.call(builder, entry, dereferenced);\n if (groupBy === 'tag') {\n let tags =\n entry.type === 'operation'\n ? dereferenced.paths![entry.item.path]![entry.item.method]!.tags\n : dereferenced.webhooks![entry.item.name][entry.item.method]!.tags;\n\n if (!tags || tags.length === 0) {\n console.warn(\n 'When `groupBy` is set to `tag`, make sure a `tags` is defined for every operation schema.',\n );\n\n tags = ['unknown'];\n }\n\n return tags.map((tag) => path.join(slugify(tag), `${file}.mdx`));\n }\n\n if (typeof groupBy === 'function') {\n return [path.join(slugify(groupBy(entry)), `${file}.mdx`)];\n }\n\n return [`${file}.mdx`];\n }\n\n return {\n toPages(builder) {\n const { dereferenced } = builder.document;\n const items = builder.extract();\n\n if (options.per === 'file') {\n const entry: OutputGroup = {\n type: 'group',\n schemaId: builder.id,\n path: '',\n info: {\n title: dereferenced.info.title,\n description: dereferenced.info.description,\n },\n ...items,\n };\n entry.path = nameFn.call(builder, entry, dereferenced) + '.mdx';\n builder.create(entry);\n return;\n }\n\n if (options.per === 'tag') {\n const tags = dereferenced.tags ?? [];\n for (const tag of tags) {\n const { displayName } = builder.fromTag(tag);\n const entry: TagOutput = {\n type: 'tag',\n path: '',\n schemaId: builder.id,\n info: {\n title: displayName,\n description: tag.description,\n },\n webhooks: items.webhooks.filter((webhook) => webhook.tags?.includes(tag.name)),\n operations: items.operations.filter((op) => op.tags?.includes(tag.name)),\n tag: tag.name,\n rawTag: tag,\n };\n\n entry.path = nameFn.call(builder, entry, dereferenced) + '.mdx';\n builder.create(entry);\n }\n\n return;\n }\n\n for (const op of items.operations) {\n const { pathItem, operation, displayName } = builder.fromExtractedOperation(op)!;\n\n const entry: OperationOutput = {\n type: 'operation',\n schemaId: builder.id,\n item: op,\n path: '',\n info: {\n title: displayName,\n description: operation.description ?? pathItem.description,\n },\n };\n\n for (const outputPath of groupOutput(builder, entry)) {\n builder.create({ ...entry, path: outputPath });\n }\n }\n\n for (const webhook of items.webhooks) {\n const { pathItem, operation, displayName } = builder.fromExtractedWebhook(webhook)!;\n\n const entry: WebhookOutput = {\n type: 'webhook',\n schemaId: builder.id,\n info: {\n title: displayName,\n description: operation.description ?? pathItem.description,\n },\n item: webhook,\n path: '',\n };\n\n for (const outputPath of groupOutput(builder, entry)) {\n builder.create({ ...entry, path: outputPath });\n }\n }\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"preset-auto.js","names":[],"sources":["../../../src/utils/pages/preset-auto.ts"],"sourcesContent":["import * as path from 'node:path';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport type {\n OperationOutput,\n OutputEntry,\n OutputGroup,\n PagesBuilder,\n PagesBuilderConfig,\n TagOutput,\n WebhookOutput,\n} from '@/utils/pages/builder';\nimport { isUrl } from '@/utils/url';\n\ninterface OperationConfig extends BaseConfig {\n /**\n * Generate a page for each API endpoint/operation (default).\n */\n per?: 'operation';\n\n /**\n * Group output using folders (Only works on `operation` mode)\n * - tag: `{tag}/{file}`\n * - route: `{endpoint}/{method}` (it will ignore the `name` option)\n * - none: `{file}` (default)\n * - a function that aligns group name (folder path) to each entry\n *\n * @defaultValue 'none'\n */\n groupBy?: 'tag' | 'route' | 'none' | ((entry: OperationOutput | WebhookOutput) => string);\n\n /**\n * Specify name for output file\n */\n name?: NameFn<OperationOutput | WebhookOutput> | NameFnOptions;\n}\n\ninterface TagConfig extends BaseConfig {\n /**\n * Generate a page for each tag.\n */\n per: 'tag';\n\n /**\n * Specify name for output file\n */\n name?: NameFn<TagOutput> | NameFnOptions;\n}\n\ninterface SchemaConfig extends BaseConfig {\n /**\n * Generate a page for each schema file.\n */\n per: 'file';\n\n /**\n * Specify name for output file\n */\n name?: NameFn<OutputGroup> | NameFnOptions;\n}\n\nexport type SchemaToPagesOptions =\n | SchemaConfig\n | TagConfig\n | OperationConfig\n | ({\n per: 'custom';\n } & PagesBuilderConfig);\n\ntype NameFn<Entry> = (\n this: PagesBuilder,\n output: Entry,\n document: ProcessedDocument['dereferenced'],\n) => string;\n\ninterface NameFnOptions {\n /**\n * The version of algorithm used to generate file paths.\n *\n * v1: Fumadocs OpenAPI v8\n * v2: Fumadocs OpenAPI v9\n *\n * @defaultValue v2\n */\n algorithm?: 'v2' | 'v1';\n}\n\ninterface BaseConfig {\n /**\n * Custom function to convert names into file names.\n *\n * By default, it only escapes whitespaces and upper case (English) characters\n */\n slugify?: (name: string) => string;\n}\n\nexport function createAutoPreset(options: SchemaToPagesOptions): PagesBuilderConfig {\n if (options.per === 'custom') return options;\n const {\n slugify = (s) => {\n return s.replace(/\\s+/g, '-').toLowerCase();\n },\n } = options;\n let nameFn: NameFn<OutputEntry>;\n\n if (typeof options.name === 'function') {\n nameFn = options.name as NameFn<OutputEntry>;\n } else {\n const { algorithm = 'v2' } = options.name ?? {};\n\n nameFn = function (result, document) {\n if (result.type === 'tag') {\n return slugify(result.tag);\n }\n\n if (result.type === 'group') {\n const schemaId = result.schemaId;\n\n return isUrl(schemaId) ? 'index' : path.basename(schemaId, path.extname(schemaId));\n }\n\n if (result.type === 'operation') {\n const operation = document.paths![result.item.path]![result.item.method]!;\n\n if (algorithm === 'v2' && operation.operationId) {\n return operation.operationId;\n }\n\n return path.join(\n this.routePathToFilePath(result.item.path),\n result.item.method.toLowerCase(),\n );\n }\n\n const hook = document.webhooks![result.item.name][result.item.method]!;\n\n if (algorithm === 'v2' && hook.operationId) {\n return hook.operationId;\n }\n\n return slugify(result.item.name);\n };\n }\n\n function groupOutput(builder: PagesBuilder, entry: OperationOutput | WebhookOutput): string[] {\n const { dereferenced } = builder.document;\n const { groupBy = 'none' } = options as OperationConfig;\n\n if (groupBy === 'route') {\n return [\n path.join(\n builder.routePathToFilePath(\n entry.type === 'operation' ? entry.item.path : entry.item.name,\n ),\n `${entry.item.method.toLowerCase()}.mdx`,\n ),\n ];\n }\n\n const file = nameFn.call(builder, entry, dereferenced);\n if (groupBy === 'tag') {\n let tags =\n entry.type === 'operation'\n ? dereferenced.paths![entry.item.path]![entry.item.method]!.tags\n : dereferenced.webhooks![entry.item.name][entry.item.method]!.tags;\n\n if (!tags || tags.length === 0) {\n console.warn(\n 'When `groupBy` is set to `tag`, make sure a `tags` is defined for every operation schema.',\n );\n\n tags = ['unknown'];\n }\n\n return tags.map((tag) => path.join(slugify(tag), `${file}.mdx`));\n }\n\n if (typeof groupBy === 'function') {\n return [path.join(slugify(groupBy(entry)), `${file}.mdx`)];\n }\n\n return [`${file}.mdx`];\n }\n\n return {\n toPages(builder) {\n const { dereferenced } = builder.document;\n const items = builder.extract();\n\n if (options.per === 'file') {\n const entry: OutputGroup = {\n type: 'group',\n schemaId: builder.id,\n path: '',\n info: {\n title: dereferenced.info.title,\n description: dereferenced.info.description,\n },\n ...items,\n };\n entry.path = nameFn.call(builder, entry, dereferenced) + '.mdx';\n builder.create(entry);\n return;\n }\n\n if (options.per === 'tag') {\n const tags = dereferenced.tags ?? [];\n for (const tag of tags) {\n const { displayName } = builder.fromTag(tag);\n const entry: TagOutput = {\n type: 'tag',\n path: '',\n schemaId: builder.id,\n info: {\n title: displayName,\n description: tag.description,\n },\n webhooks: items.webhooks.filter((webhook) => webhook.tags?.includes(tag.name)),\n operations: items.operations.filter((op) => op.tags?.includes(tag.name)),\n tag: tag.name,\n rawTag: tag,\n };\n\n entry.path = nameFn.call(builder, entry, dereferenced) + '.mdx';\n builder.create(entry);\n }\n\n return;\n }\n\n for (const op of items.operations) {\n const { pathItem, operation, displayName } = builder.fromExtractedOperation(op)!;\n\n const entry: OperationOutput = {\n type: 'operation',\n schemaId: builder.id,\n item: op,\n path: '',\n info: {\n title: displayName,\n description: operation.description ?? pathItem.description,\n },\n };\n\n for (const outputPath of groupOutput(builder, entry)) {\n builder.create({ ...entry, path: outputPath });\n }\n }\n\n for (const webhook of items.webhooks) {\n const { pathItem, operation, displayName } = builder.fromExtractedWebhook(webhook)!;\n\n const entry: WebhookOutput = {\n type: 'webhook',\n schemaId: builder.id,\n info: {\n title: displayName,\n description: operation.description ?? pathItem.description,\n },\n item: webhook,\n path: '',\n };\n\n for (const outputPath of groupOutput(builder, entry)) {\n builder.create({ ...entry, path: outputPath });\n }\n }\n },\n };\n}\n"],"mappings":"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"}
|