fumadocs-openapi 10.3.18 → 10.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/generated/shared.css +64 -17
- package/dist/i18n.d.ts +100 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +113 -0
- package/dist/i18n.js.map +1 -0
- package/dist/playground/client.d.ts +1 -1
- package/dist/playground/client.d.ts.map +1 -1
- package/dist/playground/client.js +40 -30
- package/dist/playground/client.js.map +1 -1
- package/dist/playground/components/inputs.js +16 -12
- package/dist/playground/components/inputs.js.map +1 -1
- package/dist/playground/components/oauth-dialog.js +45 -44
- package/dist/playground/components/oauth-dialog.js.map +1 -1
- package/dist/playground/components/server-select.js +7 -4
- package/dist/playground/components/server-select.js.map +1 -1
- package/dist/playground/status-info.js +18 -11
- package/dist/playground/status-info.js.map +1 -1
- package/dist/requests/generators/index.d.ts +1 -1
- package/dist/requests/generators/index.js +2 -2
- package/dist/requests/generators/index.js.map +1 -1
- package/dist/types.d.ts +3 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/base.d.ts +9 -8
- package/dist/ui/base.d.ts.map +1 -1
- package/dist/ui/base.js +13 -7
- package/dist/ui/base.js.map +1 -1
- package/dist/ui/client/i18n.js +19 -0
- package/dist/ui/client/i18n.js.map +1 -0
- package/dist/ui/components/codeblock.d.ts +15 -0
- package/dist/ui/components/codeblock.d.ts.map +1 -0
- package/dist/ui/components/codeblock.js +27 -0
- package/dist/ui/components/codeblock.js.map +1 -0
- package/dist/ui/components/dialog.js +17 -13
- package/dist/ui/components/dialog.js.map +1 -1
- package/dist/ui/full.client.js +6 -7
- package/dist/ui/full.client.js.map +1 -1
- package/dist/ui/full.d.ts.map +1 -1
- package/dist/ui/full.js +8 -4
- package/dist/ui/full.js.map +1 -1
- package/dist/ui/operation/client.js +7 -8
- package/dist/ui/operation/client.js.map +1 -1
- package/dist/ui/operation/index.js +46 -23
- package/dist/ui/operation/index.js.map +1 -1
- package/dist/ui/operation/request-tabs.d.ts.map +1 -1
- package/dist/ui/operation/request-tabs.js +9 -8
- package/dist/ui/operation/request-tabs.js.map +1 -1
- package/dist/ui/operation/response-tabs.d.ts +1 -1
- package/dist/ui/operation/response-tabs.d.ts.map +1 -1
- package/dist/ui/operation/response-tabs.js +13 -12
- package/dist/ui/operation/response-tabs.js.map +1 -1
- package/dist/ui/operation/usage-tabs/client.js +4 -5
- package/dist/ui/operation/usage-tabs/client.js.map +1 -1
- package/dist/ui/schema/client.d.ts.map +1 -1
- package/dist/ui/schema/client.js +32 -21
- package/dist/ui/schema/client.js.map +1 -1
- package/dist/ui/schema/index.d.ts +1 -1
- package/dist/ui/schema/index.d.ts.map +1 -1
- package/dist/ui/schema/index.js +11 -10
- package/dist/ui/schema/index.js.map +1 -1
- package/dist/utils/process-document.d.ts +1 -1
- package/dist/utils/process-document.js +19 -15
- package/dist/utils/process-document.js.map +1 -1
- package/package.json +19 -12
package/dist/ui/schema/client.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../utils/cn.js";
|
|
3
3
|
import { Badge } from "../components/method-label.js";
|
|
4
|
+
import { useTranslations } from "../client/i18n.js";
|
|
4
5
|
import { Fragment, Suspense, createContext, use, useCallback, useDeferredValue, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { ChevronDown, FilterIcon } from "lucide-react";
|
|
@@ -65,23 +66,7 @@ function SchemaUIProperty({ name, $type, variant = "default", overrides, objectS
|
|
|
65
66
|
$ref: $type
|
|
66
67
|
});
|
|
67
68
|
} else if (schema.type === "array") {
|
|
68
|
-
if (variant === "expand") return /* @__PURE__ */
|
|
69
|
-
className: "my-2",
|
|
70
|
-
children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, {
|
|
71
|
-
className: cn(buttonVariants({
|
|
72
|
-
color: "secondary",
|
|
73
|
-
size: "sm"
|
|
74
|
-
}), "group px-3 py-2 data-[state=open]:rounded-b-none"),
|
|
75
|
-
children: ["Array Item", /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 text-fd-muted-foreground group-data-[state=open]:rotate-180" })]
|
|
76
|
-
}), /* @__PURE__ */ jsx(CollapsibleContent, {
|
|
77
|
-
className: "-mt-px bg-fd-card px-3 rounded-lg rounded-tl-none border shadow-sm",
|
|
78
|
-
children: /* @__PURE__ */ jsx(SchemaUIProperty, {
|
|
79
|
-
name: "",
|
|
80
|
-
$type: schema.item.$type,
|
|
81
|
-
variant: "expand"
|
|
82
|
-
})
|
|
83
|
-
})]
|
|
84
|
-
});
|
|
69
|
+
if (variant === "expand") return /* @__PURE__ */ jsx(ArrayItemCollapsible, { schema });
|
|
85
70
|
type = renderRef({
|
|
86
71
|
pathName: name,
|
|
87
72
|
$ref: $type
|
|
@@ -89,7 +74,7 @@ function SchemaUIProperty({ name, $type, variant = "default", overrides, objectS
|
|
|
89
74
|
}
|
|
90
75
|
const child = /* @__PURE__ */ jsxs(Fragment$1, { children: [schema.description, schema.infoTags && schema.infoTags.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
91
76
|
className: "flex flex-row gap-2 flex-wrap my-2 not-prose empty:hidden",
|
|
92
|
-
children: schema.infoTags.map((tag) => /* @__PURE__ */ jsx(InfoTag, { tag },
|
|
77
|
+
children: schema.infoTags.map((tag, i) => /* @__PURE__ */ jsx(InfoTag, { tag }, i))
|
|
93
78
|
})] });
|
|
94
79
|
if (variant === "expand") return child;
|
|
95
80
|
return /* @__PURE__ */ jsx(Property, {
|
|
@@ -100,11 +85,35 @@ function SchemaUIProperty({ name, $type, variant = "default", overrides, objectS
|
|
|
100
85
|
children: child
|
|
101
86
|
});
|
|
102
87
|
}
|
|
88
|
+
function ArrayItemCollapsible({ schema }) {
|
|
89
|
+
const [open, setOpen] = useState(false);
|
|
90
|
+
const t = useTranslations();
|
|
91
|
+
return /* @__PURE__ */ jsxs(Collapsible, {
|
|
92
|
+
className: "my-2",
|
|
93
|
+
open,
|
|
94
|
+
onOpenChange: setOpen,
|
|
95
|
+
children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, {
|
|
96
|
+
className: cn(buttonVariants({
|
|
97
|
+
color: "secondary",
|
|
98
|
+
size: "sm"
|
|
99
|
+
}), "group px-3 py-2 data-[state=open]:rounded-b-none"),
|
|
100
|
+
children: [open ? t.schemaHideArray : t.schemaShowArray, /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 text-fd-muted-foreground group-data-[state=open]:rotate-180" })]
|
|
101
|
+
}), /* @__PURE__ */ jsx(CollapsibleContent, {
|
|
102
|
+
className: "-mt-px bg-fd-card px-3 rounded-lg rounded-tl-none border shadow-sm",
|
|
103
|
+
children: /* @__PURE__ */ jsx(SchemaUIProperty, {
|
|
104
|
+
name: "",
|
|
105
|
+
$type: schema.item.$type,
|
|
106
|
+
variant: "expand"
|
|
107
|
+
})
|
|
108
|
+
})]
|
|
109
|
+
});
|
|
110
|
+
}
|
|
103
111
|
function ObjectSearch({ properties, container, open }) {
|
|
104
112
|
const [search, setSearch] = useState("");
|
|
105
113
|
const deferredValue = useDeferredValue(search);
|
|
106
114
|
const firstItemRef = useRef(null);
|
|
107
115
|
const prevProperties = useRef(properties);
|
|
116
|
+
const t = useTranslations();
|
|
108
117
|
if (prevProperties.current !== properties) {
|
|
109
118
|
prevProperties.current = properties;
|
|
110
119
|
setSearch("");
|
|
@@ -116,7 +125,7 @@ function ObjectSearch({ properties, container, open }) {
|
|
|
116
125
|
value: search,
|
|
117
126
|
"data-object-search-input": "",
|
|
118
127
|
onChange: (e) => setSearch(e.target.value),
|
|
119
|
-
placeholder:
|
|
128
|
+
placeholder: t.schemaFilterPropertiesPlaceholder,
|
|
120
129
|
className: "text-sm ps-2 py-2 flex-1 outline-none placeholder:text-fd-muted-foreground",
|
|
121
130
|
onKeyDown: (e) => {
|
|
122
131
|
if (e.key === "Enter" && open) {
|
|
@@ -132,6 +141,7 @@ function ObjectSearch({ properties, container, open }) {
|
|
|
132
141
|
}) })] });
|
|
133
142
|
}
|
|
134
143
|
function ObjectSearchContent({ search: rawSearch, firstItemRef, properties }) {
|
|
144
|
+
const t = useTranslations();
|
|
135
145
|
const filtered = useMemo(() => {
|
|
136
146
|
const search = rawSearch.trim().toLowerCase();
|
|
137
147
|
return search.length > 0 ? properties.filter((prop) => prop.name.toLowerCase().includes(search)) : properties;
|
|
@@ -140,7 +150,7 @@ function ObjectSearchContent({ search: rawSearch, firstItemRef, properties }) {
|
|
|
140
150
|
if (filtered.length === 0) return /* @__PURE__ */ jsxs("p", {
|
|
141
151
|
className: "text-fd-muted-foreground text-sm px-2",
|
|
142
152
|
children: [
|
|
143
|
-
|
|
153
|
+
t.schemaFilterPropertiesEmpty,
|
|
144
154
|
" ",
|
|
145
155
|
/* @__PURE__ */ jsx("span", {
|
|
146
156
|
className: "text-fd-foreground font-medium",
|
|
@@ -302,6 +312,7 @@ function RootPopoverTrigger({ $ref, pathName, children }) {
|
|
|
302
312
|
})] });
|
|
303
313
|
}
|
|
304
314
|
function Property({ name, type, required, deprecated, nested = false, className, ...props }) {
|
|
315
|
+
const t = useTranslations();
|
|
305
316
|
return /* @__PURE__ */ jsxs("div", {
|
|
306
317
|
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),
|
|
307
318
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
@@ -324,7 +335,7 @@ function Property({ name, type, required, deprecated, nested = false, className,
|
|
|
324
335
|
deprecated && /* @__PURE__ */ jsx(Badge, {
|
|
325
336
|
color: "yellow",
|
|
326
337
|
className: "ms-auto text-xs",
|
|
327
|
-
children:
|
|
338
|
+
children: t.deprecated
|
|
328
339
|
})
|
|
329
340
|
]
|
|
330
341
|
}), /* @__PURE__ */ jsx("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":[],"sources":["../../../src/ui/schema/client.tsx"],"sourcesContent":["'use client';\nimport {\n type ComponentProps,\n createContext,\n Fragment,\n type ReactNode,\n type RefObject,\n Suspense,\n use,\n useCallback,\n useDeferredValue,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from 'fumadocs-ui/components/tabs';\nimport type { InfoTag, SchemaDataObjectProperty, 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, FilterIcon } 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 objectSearchOverrides,\n}: {\n name: ReactNode;\n $type: string;\n variant?: 'default' | 'expand';\n overrides?: Partial<PropertyProps>;\n objectSearchOverrides?: Partial<ObjectSearchProps>;\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=\"pt-2 pb-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 <ObjectSearch properties={schema.props} {...objectSearchOverrides} />;\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) => (\n <InfoTag key={tag.label} tag={tag} />\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\ninterface ObjectSearchProps {\n properties: SchemaDataObjectProperty[];\n container?: ComponentProps<'div'>;\n open?: (item: SchemaDataObjectProperty) => void;\n}\n\nfunction ObjectSearch({ properties, container, open }: ObjectSearchProps) {\n const [search, setSearch] = useState('');\n const deferredValue = useDeferredValue(search);\n const firstItemRef = useRef<SchemaDataObjectProperty>(null);\n const prevProperties = useRef(properties);\n\n if (prevProperties.current !== properties) {\n prevProperties.current = properties;\n setSearch('');\n }\n\n return (\n <>\n <div\n {...container}\n className={cn(\n 'flex items-center border my-2 rounded-md bg-fd-secondary text-fd-secondary-foreground transition-colors shadow-sm focus-within:ring-2 focus-within:ring-fd-ring',\n container?.className,\n )}\n >\n <FilterIcon className=\"text-fd-muted-foreground ms-2 size-3.5\" />\n <input\n value={search}\n data-object-search-input=\"\"\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Filter Properties\"\n className=\"text-sm ps-2 py-2 flex-1 outline-none placeholder:text-fd-muted-foreground\"\n onKeyDown={(e) => {\n if (e.key === 'Enter' && open) {\n if (firstItemRef.current) open(firstItemRef.current);\n e.preventDefault();\n }\n }}\n />\n </div>\n <Suspense>\n <ObjectSearchContent\n search={deferredValue}\n properties={properties}\n firstItemRef={firstItemRef}\n />\n </Suspense>\n </>\n );\n}\n\nfunction ObjectSearchContent({\n search: rawSearch,\n firstItemRef,\n properties,\n}: {\n search: string;\n firstItemRef: RefObject<SchemaDataObjectProperty | null>;\n properties: SchemaDataObjectProperty[];\n}) {\n const filtered = useMemo(() => {\n const search = rawSearch.trim().toLowerCase();\n return search.length > 0\n ? properties.filter((prop) => prop.name.toLowerCase().includes(search))\n : properties;\n }, [properties, rawSearch]);\n\n firstItemRef.current = filtered.length > 0 ? filtered[0] : null;\n\n if (filtered.length === 0)\n return (\n <p className=\"text-fd-muted-foreground text-sm px-2\">\n No property matching{' '}\n <span className=\"text-fd-foreground font-medium\">{`\"${rawSearch}\"`}</span>\n </p>\n );\n\n return filtered.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\nfunction InfoTag({ tag }: { tag: InfoTag }) {\n const ref = useRef<HTMLElement>(null);\n const [isTruncated, setTruncated] = useState(false);\n const [open, setOpen] = useState(false);\n useEffect(() => {\n const element = ref.current;\n if (!element) return;\n // assume the tag width will never change\n setTruncated(element.scrollWidth !== element.offsetWidth);\n }, []);\n\n return (\n <div className=\"flex flex-row items-start gap-2 bg-fd-secondary border rounded-lg text-xs p-1.5 shadow-md max-w-full\">\n <span className=\"font-medium\">{tag.label}</span>\n <code\n ref={ref}\n className={cn(\n 'min-w-0 flex-1 text-fd-muted-foreground',\n open ? 'wrap-break-word' : 'truncate',\n )}\n >\n {tag.value}\n </code>\n {isTruncated && (\n <button\n className={cn(buttonVariants({ size: 'icon-xs', variant: 'ghost' }))}\n onClick={() => setOpen((prev) => !prev)}\n >\n <ChevronDown />\n </button>\n )}\n </div>\n );\n}\n\ninterface PathItemType {\n name: ReactNode;\n $ref?: string;\n scrollTop?: number;\n}\n\nfunction SchemaUIPopover({\n containerRef,\n initialPath,\n}: {\n containerRef: RefObject<HTMLDivElement | null>;\n initialPath: PathItemType[];\n}) {\n const [path, setPath] = useState(initialPath);\n\n useLayoutEffect(() => {\n const last = path[0];\n const element = containerRef.current;\n if (!element || !last || !element.parentElement) return;\n\n // recover scroll\n element.parentElement.scrollTop = last.scrollTop ?? 0;\n return () => {\n if (element.parentElement) last.scrollTop = element.parentElement.scrollTop;\n };\n }, [containerRef, path]);\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 const currentRef = path.findLast((item) => item.$ref !== undefined);\n\n return (\n <>\n <div className=\"sticky top-0 -mx-2 flex flex-row flex-wrap items-center text-sm font-medium font-mono bg-fd-popover px-2 h-8 border-b\">\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 {currentRef?.$ref && (\n <SchemaUIProperty\n name=\"\"\n $type={currentRef.$ref}\n variant=\"expand\"\n objectSearchOverrides={{\n container: {\n className: 'sticky top-10',\n },\n open(item) {\n setPath((path) => [...path, { name: item.name, $ref: item.$type }]);\n },\n }}\n />\n )}\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 = useRef<HTMLDivElement>(null);\n const refCallback = useCallback((element: HTMLDivElement | null) => {\n ref.current = element;\n if (!element || element.style.getPropertyValue('--initial-height')) return;\n\n element.style.setProperty('--initial-height', `${element.clientHeight + 2}px`);\n }, []);\n\n return (\n <Popover>\n <PopoverTrigger className={cn(typeVariants({ variant: 'trigger' }))}>\n {children}\n </PopoverTrigger>\n <PopoverContent\n ref={refCallback}\n onOpenAutoFocus={(e) => {\n if (!ref.current) return;\n const input = ref.current.querySelector('input[data-object-search-input]');\n if (!(input instanceof HTMLInputElement)) return;\n input.focus({ preventScroll: true });\n e.preventDefault();\n }}\n className=\"w-[600px] min-h-(--initial-height,0) max-h-[460px] px-2 py-0\"\n >\n <SchemaUIPopover\n containerRef={ref}\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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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../../../src/ui/schema/client.tsx"],"sourcesContent":["'use client';\nimport {\n type ComponentProps,\n createContext,\n Fragment,\n type ReactNode,\n type RefObject,\n Suspense,\n use,\n useCallback,\n useDeferredValue,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from 'fumadocs-ui/components/tabs';\nimport { useTranslations } from '@/ui/client/i18n';\nimport type {\n InfoTag,\n SchemaData,\n SchemaDataObjectProperty,\n SchemaUIGeneratedData,\n} 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, FilterIcon } 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 objectSearchOverrides,\n}: {\n name: ReactNode;\n $type: string;\n variant?: 'default' | 'expand';\n overrides?: Partial<PropertyProps>;\n objectSearchOverrides?: Partial<ObjectSearchProps>;\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=\"pt-2 pb-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 <ObjectSearch properties={schema.props} {...objectSearchOverrides} />;\n\n type = renderRef({\n pathName: name,\n $ref: $type,\n });\n } else if (schema.type === 'array') {\n if (variant === 'expand') return <ArrayItemCollapsible schema={schema} />;\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 <InfoTag key={i} tag={tag} />\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 ArrayItemCollapsible({ schema }: { schema: Extract<SchemaData, { type: 'array' }> }) {\n const [open, setOpen] = useState(false);\n const t = useTranslations();\n\n return (\n <Collapsible className=\"my-2\" open={open} onOpenChange={setOpen}>\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 {open ? t.schemaHideArray : t.schemaShowArray}\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\ninterface ObjectSearchProps {\n properties: SchemaDataObjectProperty[];\n container?: ComponentProps<'div'>;\n open?: (item: SchemaDataObjectProperty) => void;\n}\n\nfunction ObjectSearch({ properties, container, open }: ObjectSearchProps) {\n const [search, setSearch] = useState('');\n const deferredValue = useDeferredValue(search);\n const firstItemRef = useRef<SchemaDataObjectProperty>(null);\n const prevProperties = useRef(properties);\n const t = useTranslations();\n\n if (prevProperties.current !== properties) {\n prevProperties.current = properties;\n setSearch('');\n }\n\n return (\n <>\n <div\n {...container}\n className={cn(\n 'flex items-center border my-2 rounded-md bg-fd-secondary text-fd-secondary-foreground transition-colors shadow-sm focus-within:ring-2 focus-within:ring-fd-ring',\n container?.className,\n )}\n >\n <FilterIcon className=\"text-fd-muted-foreground ms-2 size-3.5\" />\n <input\n value={search}\n data-object-search-input=\"\"\n onChange={(e) => setSearch(e.target.value)}\n placeholder={t.schemaFilterPropertiesPlaceholder}\n className=\"text-sm ps-2 py-2 flex-1 outline-none placeholder:text-fd-muted-foreground\"\n onKeyDown={(e) => {\n if (e.key === 'Enter' && open) {\n if (firstItemRef.current) open(firstItemRef.current);\n e.preventDefault();\n }\n }}\n />\n </div>\n <Suspense>\n <ObjectSearchContent\n search={deferredValue}\n properties={properties}\n firstItemRef={firstItemRef}\n />\n </Suspense>\n </>\n );\n}\n\nfunction ObjectSearchContent({\n search: rawSearch,\n firstItemRef,\n properties,\n}: {\n search: string;\n firstItemRef: RefObject<SchemaDataObjectProperty | null>;\n properties: SchemaDataObjectProperty[];\n}) {\n const t = useTranslations();\n const filtered = useMemo(() => {\n const search = rawSearch.trim().toLowerCase();\n return search.length > 0\n ? properties.filter((prop) => prop.name.toLowerCase().includes(search))\n : properties;\n }, [properties, rawSearch]);\n\n firstItemRef.current = filtered.length > 0 ? filtered[0] : null;\n\n if (filtered.length === 0)\n return (\n <p className=\"text-fd-muted-foreground text-sm px-2\">\n {t.schemaFilterPropertiesEmpty}{' '}\n <span className=\"text-fd-foreground font-medium\">{`\"${rawSearch}\"`}</span>\n </p>\n );\n\n return filtered.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\nfunction InfoTag({ tag }: { tag: InfoTag }) {\n const ref = useRef<HTMLElement>(null);\n const [isTruncated, setTruncated] = useState(false);\n const [open, setOpen] = useState(false);\n useEffect(() => {\n const element = ref.current;\n if (!element) return;\n // assume the tag width will never change\n setTruncated(element.scrollWidth !== element.offsetWidth);\n }, []);\n\n return (\n <div className=\"flex flex-row items-start gap-2 bg-fd-secondary border rounded-lg text-xs p-1.5 shadow-md max-w-full\">\n <span className=\"font-medium\">{tag.label}</span>\n <code\n ref={ref}\n className={cn(\n 'min-w-0 flex-1 text-fd-muted-foreground',\n open ? 'wrap-break-word' : 'truncate',\n )}\n >\n {tag.value}\n </code>\n {isTruncated && (\n <button\n className={cn(buttonVariants({ size: 'icon-xs', variant: 'ghost' }))}\n onClick={() => setOpen((prev) => !prev)}\n >\n <ChevronDown />\n </button>\n )}\n </div>\n );\n}\n\ninterface PathItemType {\n name: ReactNode;\n $ref?: string;\n scrollTop?: number;\n}\n\nfunction SchemaUIPopover({\n containerRef,\n initialPath,\n}: {\n containerRef: RefObject<HTMLDivElement | null>;\n initialPath: PathItemType[];\n}) {\n const [path, setPath] = useState(initialPath);\n\n useLayoutEffect(() => {\n const last = path[0];\n const element = containerRef.current;\n if (!element || !last || !element.parentElement) return;\n\n // recover scroll\n element.parentElement.scrollTop = last.scrollTop ?? 0;\n return () => {\n if (element.parentElement) last.scrollTop = element.parentElement.scrollTop;\n };\n }, [containerRef, path]);\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 const currentRef = path.findLast((item) => item.$ref !== undefined);\n\n return (\n <>\n <div className=\"sticky top-0 -mx-2 flex flex-row flex-wrap items-center text-sm font-medium font-mono bg-fd-popover px-2 h-8 border-b\">\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 {currentRef?.$ref && (\n <SchemaUIProperty\n name=\"\"\n $type={currentRef.$ref}\n variant=\"expand\"\n objectSearchOverrides={{\n container: {\n className: 'sticky top-10',\n },\n open(item) {\n setPath((path) => [...path, { name: item.name, $ref: item.$type }]);\n },\n }}\n />\n )}\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 = useRef<HTMLDivElement>(null);\n const refCallback = useCallback((element: HTMLDivElement | null) => {\n ref.current = element;\n if (!element || element.style.getPropertyValue('--initial-height')) return;\n\n element.style.setProperty('--initial-height', `${element.clientHeight + 2}px`);\n }, []);\n\n return (\n <Popover>\n <PopoverTrigger className={cn(typeVariants({ variant: 'trigger' }))}>\n {children}\n </PopoverTrigger>\n <PopoverContent\n ref={refCallback}\n onOpenAutoFocus={(e) => {\n if (!ref.current) return;\n const input = ref.current.querySelector('input[data-object-search-input]');\n if (!(input instanceof HTMLInputElement)) return;\n input.focus({ preventScroll: true });\n e.preventDefault();\n }}\n className=\"w-[600px] min-h-(--initial-height,0) max-h-[460px] px-2 py-0\"\n >\n <SchemaUIPopover\n containerRef={ref}\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 const t = useTranslations();\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 {t.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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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/ui/schema/index.tsx"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/ui/schema/index.tsx"],"mappings":";;;;UASiB,SAAA;EACf,WAAA,GAAc,SAAA;EACd,QAAA,GAAW,OAAA;EAEX,QAAA;EACA,SAAA;EAEA,UAAA;AAAA;AAAA,UAGe,OAAA;EACf,KAAA,EAAO,SAAA;EACP,KAAA;AAAA;AAAA,UAGe,wBAAA;EACf,IAAA;EACA,KAAA;EACA,QAAA;AAAA;AAAA,KAGU,UAAA,GAAa,SAAA;EAGjB,IAAA;AAAA;EAGA,IAAA;EACA,KAAA,EAAO,wBAAA;AAAA;EAGP,IAAA;EACA,IAAA;IACE,KAAA;EAAA;AAAA;EAIF,IAAA;EACA,KAAA;IACE,IAAA;IACA,KAAA;EAAA;AAAA;EAIF,IAAA;EACA,KAAA;IACE,IAAA;IACA,KAAA;EAAA;AAAA;AAAA,UAKO,eAAA;EACf,IAAA,EAAM,cAAA;EACN,MAAA,EAAQ,IAAA,CAAK,aAAA;EA1BA;;;EA+Bb,QAAA;EAtBM;;;EA0BN,SAAA;AAAA;AAAA,UAGe,qBAAA;EACf,KAAA;EACA,IAAA,EAAM,MAAA,SAAe,UAAA;AAAA"}
|
package/dist/ui/schema/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mergeAllOf } from "../../utils/merge-schema.js";
|
|
2
2
|
import { FormatFlags, schemaToString } from "../../utils/schema-to-string.js";
|
|
3
|
+
import { I18nLabel } from "../client/i18n.js";
|
|
3
4
|
import { SchemaUILazy } from "./lazy.js";
|
|
4
5
|
import { jsx } from "react/jsx-runtime";
|
|
5
6
|
//#region src/ui/schema/index.tsx
|
|
@@ -16,47 +17,47 @@ function generateSchemaUI({ root, readOnly, writeOnly }, ctx) {
|
|
|
16
17
|
function generateInfoTags(schema) {
|
|
17
18
|
const fields = [];
|
|
18
19
|
if (schema.default !== void 0) fields.push({
|
|
19
|
-
label: "
|
|
20
|
+
label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaDefault" }),
|
|
20
21
|
value: JSON.stringify(schema.default)
|
|
21
22
|
});
|
|
22
23
|
if (schema.pattern) fields.push({
|
|
23
|
-
label: "
|
|
24
|
+
label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaMatch" }),
|
|
24
25
|
value: schema.pattern
|
|
25
26
|
});
|
|
26
27
|
if (schema.format) fields.push({
|
|
27
|
-
label: "
|
|
28
|
+
label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaFormat" }),
|
|
28
29
|
value: schema.format
|
|
29
30
|
});
|
|
30
31
|
if (schema.multipleOf) fields.push({
|
|
31
|
-
label: "
|
|
32
|
+
label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaMultipleOf" }),
|
|
32
33
|
value: schema.multipleOf.toString()
|
|
33
34
|
});
|
|
34
35
|
let range = formatRange("value", schema.minimum, schema.exclusiveMinimum, schema.maximum, schema.exclusiveMaximum);
|
|
35
36
|
if (range) fields.push({
|
|
36
|
-
label: "
|
|
37
|
+
label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaRange" }),
|
|
37
38
|
value: range
|
|
38
39
|
});
|
|
39
40
|
range = formatRange("length", schema.minLength, void 0, schema.maxLength, void 0);
|
|
40
41
|
if (range) fields.push({
|
|
41
|
-
label: "
|
|
42
|
+
label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaLength" }),
|
|
42
43
|
value: range
|
|
43
44
|
});
|
|
44
45
|
range = formatRange("properties", schema.minProperties, void 0, schema.maxProperties, void 0);
|
|
45
46
|
if (range) fields.push({
|
|
46
|
-
label: "
|
|
47
|
+
label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaProperties" }),
|
|
47
48
|
value: range
|
|
48
49
|
});
|
|
49
50
|
range = formatRange("items", schema.minItems, void 0, schema.maxItems, void 0);
|
|
50
51
|
if (range) fields.push({
|
|
51
|
-
label: "
|
|
52
|
+
label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaItems" }),
|
|
52
53
|
value: range
|
|
53
54
|
});
|
|
54
55
|
if (schema.enum) fields.push({
|
|
55
|
-
label: "
|
|
56
|
+
label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaValueIn" }),
|
|
56
57
|
value: schema.enum.map((value) => JSON.stringify(value)).join(" | ")
|
|
57
58
|
});
|
|
58
59
|
if (showExample && schema.examples) for (const example of schema.examples) fields.push({
|
|
59
|
-
label: "
|
|
60
|
+
label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaExample" }),
|
|
60
61
|
value: JSON.stringify(example, null, 2)
|
|
61
62
|
});
|
|
62
63
|
return fields;
|
|
@@ -1 +1 @@
|
|
|
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?: InfoTag[];\n\n typeName: string;\n aliasName: string;\n\n deprecated?: boolean;\n}\n\nexport interface InfoTag {\n label: string;\n value: string;\n}\n\nexport interface SchemaDataObjectProperty {\n name: string;\n $type: string;\n required: boolean;\n}\n\nexport type SchemaData = FieldBase &\n (\n | {\n type: 'primitive';\n }\n | {\n type: 'object';\n props: SchemaDataObjectProperty[];\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: InfoTag[] = [];\n\n if (schema.default !== undefined) {\n fields.push({ label: 'Default', value: JSON.stringify(schema.default) });\n }\n\n if (schema.pattern) {\n fields.push({ label: 'Match', value: schema.pattern });\n }\n\n if (schema.format) {\n fields.push({ label: 'Format', value: schema.format });\n }\n\n if (schema.multipleOf) {\n fields.push({ label: 'Multiple Of', value: schema.multipleOf.toString() });\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({ label: 'Range', value: range });\n\n range = formatRange('length', schema.minLength, undefined, schema.maxLength, undefined);\n if (range) fields.push({ label: 'Length', value: range });\n\n range = formatRange(\n 'properties',\n schema.minProperties,\n undefined,\n schema.maxProperties,\n undefined,\n );\n if (range) fields.push({ label: 'Properties', value: range });\n\n range = formatRange('items', schema.minItems, undefined, schema.maxItems, undefined);\n if (range) fields.push({ label: 'Items', value: range });\n\n if (schema.enum) {\n fields.push({\n label: 'Value in',\n value: schema.enum.map((value) => JSON.stringify(value)).join(' | '),\n });\n }\n\n if (showExample && schema.examples) {\n for (const example of schema.examples) {\n fields.push({ label: 'Example', value: JSON.stringify(example, null, 2) });\n }\n }\n\n return fields;\n }\n\n let _counter = 0;\n const autoIds = new WeakMap<Exclude<ResolvedSchema, boolean>, string>();\n function getSchemaId(schema: ResolvedSchema): string {\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 (!item || 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 (!prop || !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 && 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';\nimport { I18nLabel } from '../client/i18n';\n\nexport interface FieldBase {\n description?: ReactNode;\n infoTags?: InfoTag[];\n\n typeName: string;\n aliasName: string;\n\n deprecated?: boolean;\n}\n\nexport interface InfoTag {\n label: ReactNode;\n value: string;\n}\n\nexport interface SchemaDataObjectProperty {\n name: string;\n $type: string;\n required: boolean;\n}\n\nexport type SchemaData = FieldBase &\n (\n | {\n type: 'primitive';\n }\n | {\n type: 'object';\n props: SchemaDataObjectProperty[];\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: InfoTag[] = [];\n\n if (schema.default !== undefined) {\n fields.push({\n label: <I18nLabel label=\"schemaDefault\" />,\n value: JSON.stringify(schema.default),\n });\n }\n\n if (schema.pattern) {\n fields.push({ label: <I18nLabel label=\"schemaMatch\" />, value: schema.pattern });\n }\n\n if (schema.format) {\n fields.push({ label: <I18nLabel label=\"schemaFormat\" />, value: schema.format });\n }\n\n if (schema.multipleOf) {\n fields.push({\n label: <I18nLabel label=\"schemaMultipleOf\" />,\n value: schema.multipleOf.toString(),\n });\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({ label: <I18nLabel label=\"schemaRange\" />, value: range });\n\n range = formatRange('length', schema.minLength, undefined, schema.maxLength, undefined);\n if (range) fields.push({ label: <I18nLabel label=\"schemaLength\" />, value: range });\n\n range = formatRange(\n 'properties',\n schema.minProperties,\n undefined,\n schema.maxProperties,\n undefined,\n );\n if (range) fields.push({ label: <I18nLabel label=\"schemaProperties\" />, value: range });\n\n range = formatRange('items', schema.minItems, undefined, schema.maxItems, undefined);\n if (range) fields.push({ label: <I18nLabel label=\"schemaItems\" />, value: range });\n\n if (schema.enum) {\n fields.push({\n label: <I18nLabel label=\"schemaValueIn\" />,\n value: schema.enum.map((value) => JSON.stringify(value)).join(' | '),\n });\n }\n\n if (showExample && schema.examples) {\n for (const example of schema.examples) {\n fields.push({\n label: <I18nLabel label=\"schemaExample\" />,\n value: JSON.stringify(example, null, 2),\n });\n }\n }\n\n return fields;\n }\n\n let _counter = 0;\n const autoIds = new WeakMap<Exclude<ResolvedSchema, boolean>, string>();\n function getSchemaId(schema: ResolvedSchema): string {\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 (!item || 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 (!prop || !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 && 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":";;;;;;AAgFA,SAAgB,OAAO,EACrB,KACA,GAAG,WAGF;AACD,KAAI,IAAI,UAAU,OAChB,QAAO,IAAI,SAAS,OAAO,SAAS,IAAI;AAG1C,QAAO,oBAAC,cAAD;EAAc,GAAI,QAAQ;EAAQ,WAAW,iBAAiB,SAAS,IAAI;EAAI,CAAA;;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,SAAoB,EAAE;AAE5B,MAAI,OAAO,YAAY,KAAA,EACrB,QAAO,KAAK;GACV,OAAO,oBAAC,WAAD,EAAW,OAAM,iBAAkB,CAAA;GAC1C,OAAO,KAAK,UAAU,OAAO,QAAQ;GACtC,CAAC;AAGJ,MAAI,OAAO,QACT,QAAO,KAAK;GAAE,OAAO,oBAAC,WAAD,EAAW,OAAM,eAAgB,CAAA;GAAE,OAAO,OAAO;GAAS,CAAC;AAGlF,MAAI,OAAO,OACT,QAAO,KAAK;GAAE,OAAO,oBAAC,WAAD,EAAW,OAAM,gBAAiB,CAAA;GAAE,OAAO,OAAO;GAAQ,CAAC;AAGlF,MAAI,OAAO,WACT,QAAO,KAAK;GACV,OAAO,oBAAC,WAAD,EAAW,OAAM,oBAAqB,CAAA;GAC7C,OAAO,OAAO,WAAW,UAAU;GACpC,CAAC;EAGJ,IAAI,QAAQ,YACV,SACA,OAAO,SACP,OAAO,kBACP,OAAO,SACP,OAAO,iBACR;AACD,MAAI,MAAO,QAAO,KAAK;GAAE,OAAO,oBAAC,WAAD,EAAW,OAAM,eAAgB,CAAA;GAAE,OAAO;GAAO,CAAC;AAElF,UAAQ,YAAY,UAAU,OAAO,WAAW,KAAA,GAAW,OAAO,WAAW,KAAA,EAAU;AACvF,MAAI,MAAO,QAAO,KAAK;GAAE,OAAO,oBAAC,WAAD,EAAW,OAAM,gBAAiB,CAAA;GAAE,OAAO;GAAO,CAAC;AAEnF,UAAQ,YACN,cACA,OAAO,eACP,KAAA,GACA,OAAO,eACP,KAAA,EACD;AACD,MAAI,MAAO,QAAO,KAAK;GAAE,OAAO,oBAAC,WAAD,EAAW,OAAM,oBAAqB,CAAA;GAAE,OAAO;GAAO,CAAC;AAEvF,UAAQ,YAAY,SAAS,OAAO,UAAU,KAAA,GAAW,OAAO,UAAU,KAAA,EAAU;AACpF,MAAI,MAAO,QAAO,KAAK;GAAE,OAAO,oBAAC,WAAD,EAAW,OAAM,eAAgB,CAAA;GAAE,OAAO;GAAO,CAAC;AAElF,MAAI,OAAO,KACT,QAAO,KAAK;GACV,OAAO,oBAAC,WAAD,EAAW,OAAM,iBAAkB,CAAA;GAC1C,OAAO,OAAO,KAAK,KAAK,UAAU,KAAK,UAAU,MAAM,CAAC,CAAC,KAAK,MAAM;GACrE,CAAC;AAGJ,MAAI,eAAe,OAAO,SACxB,MAAK,MAAM,WAAW,OAAO,SAC3B,QAAO,KAAK;GACV,OAAO,oBAAC,WAAD,EAAW,OAAM,iBAAkB,CAAA;GAC1C,OAAO,KAAK,UAAU,SAAS,MAAM,EAAE;GACxC,CAAC;AAIN,SAAO;;CAGT,IAAI,WAAW;CACf,MAAM,0BAAU,IAAI,SAAmD;CACvE,SAAS,YAAY,QAAgC;AACnD,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,KAAA;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,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,UAAU,KAAK,CAAE;IAC3D,MAAM,SAAS,YAAY,KAAK;IAChC,MAAM,MAAM,GAAG,GAAG,WAAW;AAE7B,aAAS,KAAK;KACZ,GAAG;KACH,OAAO,KAAA;KACP,OAAO,KAAA;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,QAAQ,CAAC,UAAU,KAAK,CAAE;IAC/B,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,wBAAwB,UAAU,qBAAqB,EAAE;IAC3D,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,KAAA,EACV,KAAI,KAAK,GAAG,IAAI,KAAK;UACZ,iBAAiB,KAAA,EAC1B,KAAI,KAAK,GAAG,aAAa,IAAI;AAG/B,KAAI,KAAK,MAAM;AACf,KAAI,QAAQ,KAAA,EACV,KAAI,KAAK,MAAM,MAAM;UACZ,iBAAiB,KAAA,EAC1B,KAAI,KAAK,KAAK,eAAe;AAE/B,KAAI,IAAI,SAAS,EAAG,QAAO,IAAI,KAAK,IAAI"}
|
|
@@ -19,9 +19,9 @@ async function processDocument(input) {
|
|
|
19
19
|
/**
|
|
20
20
|
* Dereferenced value and its original `$ref` value
|
|
21
21
|
*/
|
|
22
|
-
const dereferenceMap = /* @__PURE__ */ new
|
|
22
|
+
const dereferenceMap = /* @__PURE__ */ new Map();
|
|
23
23
|
return {
|
|
24
|
-
dereferenced: dereferenceSync(bundled, (
|
|
24
|
+
dereferenced: dereferenceSync(bundled, (schema, ref) => {
|
|
25
25
|
dereferenceMap.set(schema, ref);
|
|
26
26
|
}),
|
|
27
27
|
getRawRef(obj) {
|
|
@@ -33,29 +33,33 @@ async function processDocument(input) {
|
|
|
33
33
|
/**
|
|
34
34
|
* Resolves all $ref pointers in a schema and returns a new schema without any $ref pointers.
|
|
35
35
|
*/
|
|
36
|
-
function dereferenceSync(schema,
|
|
36
|
+
function dereferenceSync(schema, setOriginalRef) {
|
|
37
37
|
if (typeof schema === "boolean") return schema;
|
|
38
38
|
const visitedNodes = /* @__PURE__ */ new Set();
|
|
39
39
|
const cloned = structuredClone(schema);
|
|
40
|
-
function resolve(current
|
|
40
|
+
function resolve(current) {
|
|
41
41
|
if (typeof current === "object" && current !== null) {
|
|
42
42
|
if (visitedNodes.has(current)) return current;
|
|
43
43
|
visitedNodes.add(current);
|
|
44
|
-
if (Array.isArray(current))
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const ref = current["$ref"];
|
|
48
|
-
const out = dereference.resolveRefSync(cloned, ref);
|
|
49
|
-
onDereference(ref, out);
|
|
50
|
-
return out;
|
|
51
|
-
}
|
|
52
|
-
const obj = current;
|
|
53
|
-
for (const key in current) obj[key] = resolve(obj[key], `${path}/${key}`);
|
|
44
|
+
if (Array.isArray(current)) {
|
|
45
|
+
for (let index = 0; index < current.length; index++) current[index] = resolve(current[index]);
|
|
46
|
+
return current;
|
|
54
47
|
}
|
|
48
|
+
const obj = current;
|
|
49
|
+
if ("$ref" in current && typeof current["$ref"] === "string") {
|
|
50
|
+
const ref = current["$ref"];
|
|
51
|
+
delete current["$ref"];
|
|
52
|
+
const resolved = resolve(dereference.resolveRefSync(cloned, ref));
|
|
53
|
+
setOriginalRef(resolved, ref);
|
|
54
|
+
setOriginalRef(current, ref);
|
|
55
|
+
if (typeof resolved === "boolean") throw new Error("invalid schema");
|
|
56
|
+
for (const k in resolved) if (!(k in current)) obj[k] = resolved[k];
|
|
57
|
+
}
|
|
58
|
+
for (const key in current) obj[key] = resolve(obj[key]);
|
|
55
59
|
}
|
|
56
60
|
return current;
|
|
57
61
|
}
|
|
58
|
-
return resolve(cloned
|
|
62
|
+
return resolve(cloned);
|
|
59
63
|
}
|
|
60
64
|
//#endregion
|
|
61
65
|
export { processDocument };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-document.js","names":[],"sources":["../../src/utils/process-document.ts"],"sourcesContent":["import type { Document } from '@/types';\nimport type { NoReference } from '@/utils/schema';\nimport { bundle } from '@scalar/json-magic/bundle';\nimport { upgrade } from '@scalar/openapi-upgrader';\nimport { fetchUrls, readFiles } from '@scalar/json-magic/bundle/plugins/node';\nimport type { JSONSchema } from 'json-schema-typed/draft-2020-12';\nimport dereference from 'dereference-json-schema';\n\nexport interface ProcessedDocument {\n /**\n * dereferenced document\n */\n dereferenced: NoReference<Document>;\n\n /**\n * Get raw
|
|
1
|
+
{"version":3,"file":"process-document.js","names":[],"sources":["../../src/utils/process-document.ts"],"sourcesContent":["import type { Document } from '@/types';\nimport type { NoReference } from '@/utils/schema';\nimport { bundle } from '@scalar/json-magic/bundle';\nimport { upgrade } from '@scalar/openapi-upgrader';\nimport { fetchUrls, readFiles } from '@scalar/json-magic/bundle/plugins/node';\nimport type { JSONSchema } from 'json-schema-typed/draft-2020-12';\nimport dereference from 'dereference-json-schema';\n\nexport interface ProcessedDocument {\n /**\n * dereferenced document\n */\n dereferenced: NoReference<Document>;\n\n /**\n * Get raw $ref from dereferenced object\n */\n getRawRef: (obj: object) => string | undefined;\n\n bundled: Document;\n}\n\n/**\n * process & reference input document to a Fumadocs OpenAPI compatible format\n */\nexport async function processDocument(input: string | Document): Promise<ProcessedDocument> {\n const bundled: Document = await bundle(input, {\n plugins: [fetchUrls(), readFiles()],\n treeShake: true,\n hooks: {\n onResolveError(node) {\n throw new Error(`Failed to resolve ${node.$ref}`);\n },\n },\n })\n .then((v) => upgrade(v as never, '3.2') as Document)\n .catch((e) => {\n throw new Error(`[OpenAPI] Failed to resolve input: ${input}`, {\n cause: e,\n });\n });\n\n /**\n * Dereferenced value and its original `$ref` value\n */\n const dereferenceMap = new Map<object, string>();\n\n return {\n dereferenced: dereferenceSync(bundled as JSONSchema, (schema, ref) => {\n dereferenceMap.set(schema as object, ref);\n }) as NoReference<Document>,\n getRawRef(obj) {\n return dereferenceMap.get(obj);\n },\n bundled,\n };\n}\n\n/**\n * Resolves all $ref pointers in a schema and returns a new schema without any $ref pointers.\n */\nfunction dereferenceSync(\n schema: JSONSchema,\n setOriginalRef: (schema: JSONSchema, ref: string) => void,\n): JSONSchema {\n if (typeof schema === 'boolean') return schema;\n const visitedNodes = new Set<unknown>();\n const cloned = structuredClone(schema);\n\n function resolve(current: unknown): JSONSchema {\n if (typeof current === 'object' && current !== null) {\n // make sure we don't visit the same node twice\n if (visitedNodes.has(current)) {\n return current;\n }\n visitedNodes.add(current);\n\n if (Array.isArray(current)) {\n // array\n for (let index = 0; index < current.length; index++) {\n current[index] = resolve(current[index]);\n }\n\n return current as JSONSchema;\n }\n\n const obj = current as Record<string, unknown>;\n\n // object\n if ('$ref' in current && typeof current['$ref'] === 'string') {\n const ref = current['$ref'];\n delete current['$ref'];\n const resolved = resolve(dereference.resolveRefSync(cloned as never, ref) as JSONSchema);\n setOriginalRef(resolved, ref);\n setOriginalRef(current as JSONSchema, ref);\n\n if (typeof resolved === 'boolean') throw new Error('invalid schema');\n for (const k in resolved) {\n if (!(k in current)) {\n obj[k] = resolved[k as never];\n }\n }\n }\n\n for (const key in current) {\n obj[key] = resolve(obj[key]);\n }\n }\n\n return current as JSONSchema;\n }\n\n return resolve(cloned);\n}\n"],"mappings":";;;;;;;;AAyBA,eAAsB,gBAAgB,OAAsD;CAC1F,MAAM,UAAoB,MAAM,OAAO,OAAO;EAC5C,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;EACnC,WAAW;EACX,OAAO,EACL,eAAe,MAAM;AACnB,SAAM,IAAI,MAAM,qBAAqB,KAAK,OAAO;KAEpD;EACF,CAAC,CACC,MAAM,MAAM,QAAQ,GAAY,MAAM,CAAa,CACnD,OAAO,MAAM;AACZ,QAAM,IAAI,MAAM,sCAAsC,SAAS,EAC7D,OAAO,GACR,CAAC;GACF;;;;CAKJ,MAAM,iCAAiB,IAAI,KAAqB;AAEhD,QAAO;EACL,cAAc,gBAAgB,UAAwB,QAAQ,QAAQ;AACpE,kBAAe,IAAI,QAAkB,IAAI;IACzC;EACF,UAAU,KAAK;AACb,UAAO,eAAe,IAAI,IAAI;;EAEhC;EACD;;;;;AAMH,SAAS,gBACP,QACA,gBACY;AACZ,KAAI,OAAO,WAAW,UAAW,QAAO;CACxC,MAAM,+BAAe,IAAI,KAAc;CACvC,MAAM,SAAS,gBAAgB,OAAO;CAEtC,SAAS,QAAQ,SAA8B;AAC7C,MAAI,OAAO,YAAY,YAAY,YAAY,MAAM;AAEnD,OAAI,aAAa,IAAI,QAAQ,CAC3B,QAAO;AAET,gBAAa,IAAI,QAAQ;AAEzB,OAAI,MAAM,QAAQ,QAAQ,EAAE;AAE1B,SAAK,IAAI,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,QAC1C,SAAQ,SAAS,QAAQ,QAAQ,OAAO;AAG1C,WAAO;;GAGT,MAAM,MAAM;AAGZ,OAAI,UAAU,WAAW,OAAO,QAAQ,YAAY,UAAU;IAC5D,MAAM,MAAM,QAAQ;AACpB,WAAO,QAAQ;IACf,MAAM,WAAW,QAAQ,YAAY,eAAe,QAAiB,IAAI,CAAe;AACxF,mBAAe,UAAU,IAAI;AAC7B,mBAAe,SAAuB,IAAI;AAE1C,QAAI,OAAO,aAAa,UAAW,OAAM,IAAI,MAAM,iBAAiB;AACpE,SAAK,MAAM,KAAK,SACd,KAAI,EAAE,KAAK,SACT,KAAI,KAAK,SAAS;;AAKxB,QAAK,MAAM,OAAO,QAChB,KAAI,OAAO,QAAQ,IAAI,KAAK;;AAIhC,SAAO;;AAGT,QAAO,QAAQ,OAAO"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fumadocs-openapi",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.4.1",
|
|
4
4
|
"description": "Generate MDX docs for your OpenAPI spec",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Docs",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"types": "./dist/index.d.ts",
|
|
21
21
|
"exports": {
|
|
22
22
|
".": "./dist/index.js",
|
|
23
|
+
"./i18n": "./dist/i18n.js",
|
|
23
24
|
"./playground": "./dist/playground/index.js",
|
|
24
25
|
"./playground/client": "./dist/playground/client.js",
|
|
25
26
|
"./requests/generators": "./dist/requests/generators/index.js",
|
|
@@ -42,13 +43,14 @@
|
|
|
42
43
|
"access": "public"
|
|
43
44
|
},
|
|
44
45
|
"dependencies": {
|
|
46
|
+
"@fastify/deepmerge": "^3.2.1",
|
|
45
47
|
"@fumari/json-schema-ts": "^0.0.2",
|
|
46
48
|
"@radix-ui/react-accordion": "^1.2.12",
|
|
47
49
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
48
50
|
"@radix-ui/react-select": "^2.2.6",
|
|
49
51
|
"@radix-ui/react-slot": "^1.2.4",
|
|
50
|
-
"@scalar/json-magic": "^0.12.
|
|
51
|
-
"@scalar/openapi-upgrader": "^0.2.
|
|
52
|
+
"@scalar/json-magic": "^0.12.4",
|
|
53
|
+
"@scalar/openapi-upgrader": "^0.2.1",
|
|
52
54
|
"ajv": "^8.18.0",
|
|
53
55
|
"class-variance-authority": "^0.7.1",
|
|
54
56
|
"dereference-json-schema": "^0.2.2",
|
|
@@ -66,30 +68,35 @@
|
|
|
66
68
|
"@fumari/stf": "1.0.3"
|
|
67
69
|
},
|
|
68
70
|
"devDependencies": {
|
|
69
|
-
"@scalar/api-client-react": "^1.4.
|
|
71
|
+
"@scalar/api-client-react": "^1.4.11",
|
|
70
72
|
"@types/js-yaml": "^4.0.9",
|
|
71
|
-
"@types/node": "25.
|
|
73
|
+
"@types/node": "25.5.0",
|
|
72
74
|
"@types/openapi-sampler": "^1.0.3",
|
|
73
75
|
"@types/react": "^19.2.14",
|
|
74
76
|
"json-schema-typed": "^8.0.2",
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
+
"shiki": "^4.0.2",
|
|
78
|
+
"tailwindcss": "^4.2.2",
|
|
79
|
+
"tsdown": "0.21.4",
|
|
77
80
|
"@fumadocs/tailwind": "0.0.3",
|
|
78
81
|
"eslint-config-custom": "0.0.0",
|
|
79
|
-
"fumadocs-core": "16.
|
|
80
|
-
"fumadocs-ui": "16.
|
|
82
|
+
"fumadocs-core": "16.7.1",
|
|
83
|
+
"fumadocs-ui": "16.7.1",
|
|
81
84
|
"tsconfig": "0.0.0"
|
|
82
85
|
},
|
|
83
86
|
"peerDependencies": {
|
|
84
87
|
"@scalar/api-client-react": "*",
|
|
85
88
|
"@types/react": "*",
|
|
86
|
-
"fumadocs-core": "^16.
|
|
87
|
-
"fumadocs-ui": "^16.
|
|
89
|
+
"fumadocs-core": "^16.7.0",
|
|
90
|
+
"fumadocs-ui": "^16.7.0",
|
|
88
91
|
"json-schema-typed": "*",
|
|
89
92
|
"react": "^19.2.0",
|
|
90
|
-
"react-dom": "^19.2.0"
|
|
93
|
+
"react-dom": "^19.2.0",
|
|
94
|
+
"shiki": "*"
|
|
91
95
|
},
|
|
92
96
|
"peerDependenciesMeta": {
|
|
97
|
+
"shiki": {
|
|
98
|
+
"optional": true
|
|
99
|
+
},
|
|
93
100
|
"json-schema-typed": {
|
|
94
101
|
"optional": true
|
|
95
102
|
},
|