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.
Files changed (63) hide show
  1. package/css/generated/shared.css +64 -17
  2. package/dist/i18n.d.ts +100 -0
  3. package/dist/i18n.d.ts.map +1 -0
  4. package/dist/i18n.js +113 -0
  5. package/dist/i18n.js.map +1 -0
  6. package/dist/playground/client.d.ts +1 -1
  7. package/dist/playground/client.d.ts.map +1 -1
  8. package/dist/playground/client.js +40 -30
  9. package/dist/playground/client.js.map +1 -1
  10. package/dist/playground/components/inputs.js +16 -12
  11. package/dist/playground/components/inputs.js.map +1 -1
  12. package/dist/playground/components/oauth-dialog.js +45 -44
  13. package/dist/playground/components/oauth-dialog.js.map +1 -1
  14. package/dist/playground/components/server-select.js +7 -4
  15. package/dist/playground/components/server-select.js.map +1 -1
  16. package/dist/playground/status-info.js +18 -11
  17. package/dist/playground/status-info.js.map +1 -1
  18. package/dist/requests/generators/index.d.ts +1 -1
  19. package/dist/requests/generators/index.js +2 -2
  20. package/dist/requests/generators/index.js.map +1 -1
  21. package/dist/types.d.ts +3 -1
  22. package/dist/types.d.ts.map +1 -1
  23. package/dist/ui/base.d.ts +9 -8
  24. package/dist/ui/base.d.ts.map +1 -1
  25. package/dist/ui/base.js +13 -7
  26. package/dist/ui/base.js.map +1 -1
  27. package/dist/ui/client/i18n.js +19 -0
  28. package/dist/ui/client/i18n.js.map +1 -0
  29. package/dist/ui/components/codeblock.d.ts +15 -0
  30. package/dist/ui/components/codeblock.d.ts.map +1 -0
  31. package/dist/ui/components/codeblock.js +27 -0
  32. package/dist/ui/components/codeblock.js.map +1 -0
  33. package/dist/ui/components/dialog.js +17 -13
  34. package/dist/ui/components/dialog.js.map +1 -1
  35. package/dist/ui/full.client.js +6 -7
  36. package/dist/ui/full.client.js.map +1 -1
  37. package/dist/ui/full.d.ts.map +1 -1
  38. package/dist/ui/full.js +8 -4
  39. package/dist/ui/full.js.map +1 -1
  40. package/dist/ui/operation/client.js +7 -8
  41. package/dist/ui/operation/client.js.map +1 -1
  42. package/dist/ui/operation/index.js +46 -23
  43. package/dist/ui/operation/index.js.map +1 -1
  44. package/dist/ui/operation/request-tabs.d.ts.map +1 -1
  45. package/dist/ui/operation/request-tabs.js +9 -8
  46. package/dist/ui/operation/request-tabs.js.map +1 -1
  47. package/dist/ui/operation/response-tabs.d.ts +1 -1
  48. package/dist/ui/operation/response-tabs.d.ts.map +1 -1
  49. package/dist/ui/operation/response-tabs.js +13 -12
  50. package/dist/ui/operation/response-tabs.js.map +1 -1
  51. package/dist/ui/operation/usage-tabs/client.js +4 -5
  52. package/dist/ui/operation/usage-tabs/client.js.map +1 -1
  53. package/dist/ui/schema/client.d.ts.map +1 -1
  54. package/dist/ui/schema/client.js +32 -21
  55. package/dist/ui/schema/client.js.map +1 -1
  56. package/dist/ui/schema/index.d.ts +1 -1
  57. package/dist/ui/schema/index.d.ts.map +1 -1
  58. package/dist/ui/schema/index.js +11 -10
  59. package/dist/ui/schema/index.js.map +1 -1
  60. package/dist/utils/process-document.d.ts +1 -1
  61. package/dist/utils/process-document.js +19 -15
  62. package/dist/utils/process-document.js.map +1 -1
  63. package/package.json +19 -12
@@ -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__ */ jsxs(Collapsible, {
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 }, tag.label))
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: "Filter Properties",
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
- "No property matching",
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: "Deprecated"
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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"}
@@ -10,7 +10,7 @@ interface FieldBase {
10
10
  deprecated?: boolean;
11
11
  }
12
12
  interface InfoTag {
13
- label: string;
13
+ label: ReactNode;
14
14
  value: string;
15
15
  }
16
16
  interface SchemaDataObjectProperty {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/ui/schema/index.tsx"],"mappings":";;;;UAQiB,SAAA;EACf,WAAA,GAAc,SAAA;EACd,QAAA,GAAW,OAAA;EAEX,QAAA;EACA,SAAA;EAEA,UAAA;AAAA;AAAA,UAGe,OAAA;EACf,KAAA;EACA,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;EAjBP;;;EAsBN,QAAA;EAfM;;;EAmBN,SAAA;AAAA;AAAA,UAGe,qBAAA;EACf,KAAA;EACA,IAAA,EAAM,MAAA,SAAe,UAAA;AAAA"}
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"}
@@ -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: "Default",
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: "Match",
24
+ label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaMatch" }),
24
25
  value: schema.pattern
25
26
  });
26
27
  if (schema.format) fields.push({
27
- label: "Format",
28
+ label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaFormat" }),
28
29
  value: schema.format
29
30
  });
30
31
  if (schema.multipleOf) fields.push({
31
- label: "Multiple Of",
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: "Range",
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: "Length",
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: "Properties",
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: "Items",
52
+ label: /* @__PURE__ */ jsx(I18nLabel, { label: "schemaItems" }),
52
53
  value: range
53
54
  });
54
55
  if (schema.enum) fields.push({
55
- label: "Value in",
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: "Example",
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":"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"}
@@ -8,7 +8,7 @@ interface ProcessedDocument {
8
8
  */
9
9
  dereferenced: NoReference<Document>;
10
10
  /**
11
- * Get raw object from dereferenced object
11
+ * Get raw $ref from dereferenced object
12
12
  */
13
13
  getRawRef: (obj: object) => string | undefined;
14
14
  bundled: Document;
@@ -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 WeakMap();
22
+ const dereferenceMap = /* @__PURE__ */ new Map();
23
23
  return {
24
- dereferenced: dereferenceSync(bundled, (ref, schema) => {
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, onDereference) {
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, path) {
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)) for (let index = 0; index < current.length; index++) current[index] = resolve(current[index], `${path}/${index}`);
45
- else {
46
- if ("$ref" in current && typeof current["$ref"] === "string") {
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 object 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 WeakMap<object, string>();\n\n return {\n dereferenced: dereferenceSync(bundled as JSONSchema, (ref, schema) => {\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 onDereference: (ref: string, schema: JSONSchema) => 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, path: string): 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], `${path}/${index}`);\n }\n } else {\n // object\n if ('$ref' in current && typeof current['$ref'] === 'string') {\n const ref = current['$ref'];\n const out = dereference.resolveRefSync(cloned as never, ref) as JSONSchema;\n onDereference(ref, out);\n return out;\n }\n\n const obj = current as Record<string, unknown>;\n for (const key in current) {\n obj[key] = resolve(obj[key], `${path}/${key}`);\n }\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,SAAyB;AAEpD,QAAO;EACL,cAAc,gBAAgB,UAAwB,KAAK,WAAW;AACpE,kBAAe,IAAI,QAAkB,IAAI;IACzC;EACF,UAAU,KAAK;AACb,UAAO,eAAe,IAAI,IAAI;;EAEhC;EACD;;;;;AAMH,SAAS,gBACP,QACA,eACY;AACZ,KAAI,OAAO,WAAW,UAAW,QAAO;CACxC,MAAM,+BAAe,IAAI,KAAc;CACvC,MAAM,SAAS,gBAAgB,OAAO;CAEtC,SAAS,QAAQ,SAAkB,MAA0B;AAC3D,MAAI,OAAO,YAAY,YAAY,YAAY,MAAM;AAEnD,OAAI,aAAa,IAAI,QAAQ,CAC3B,QAAO;AAET,gBAAa,IAAI,QAAQ;AAEzB,OAAI,MAAM,QAAQ,QAAQ,CAExB,MAAK,IAAI,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,QAC1C,SAAQ,SAAS,QAAQ,QAAQ,QAAQ,GAAG,KAAK,GAAG,QAAQ;QAEzD;AAEL,QAAI,UAAU,WAAW,OAAO,QAAQ,YAAY,UAAU;KAC5D,MAAM,MAAM,QAAQ;KACpB,MAAM,MAAM,YAAY,eAAe,QAAiB,IAAI;AAC5D,mBAAc,KAAK,IAAI;AACvB,YAAO;;IAGT,MAAM,MAAM;AACZ,SAAK,MAAM,OAAO,QAChB,KAAI,OAAO,QAAQ,IAAI,MAAM,GAAG,KAAK,GAAG,MAAM;;;AAKpD,SAAO;;AAGT,QAAO,QAAQ,QAAQ,IAAI"}
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.18",
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.2",
51
- "@scalar/openapi-upgrader": "^0.2.0",
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.5",
71
+ "@scalar/api-client-react": "^1.4.11",
70
72
  "@types/js-yaml": "^4.0.9",
71
- "@types/node": "25.4.0",
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
- "tailwindcss": "^4.2.1",
76
- "tsdown": "0.21.1",
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.6.15",
80
- "fumadocs-ui": "16.6.15",
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.5.0",
87
- "fumadocs-ui": "^16.5.0",
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
  },