fumadocs-openapi 8.1.12 → 9.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/generate-file.d.ts +55 -20
  2. package/dist/generate-file.d.ts.map +1 -1
  3. package/dist/generate-file.js +93 -68
  4. package/dist/generate.d.ts +10 -10
  5. package/dist/generate.d.ts.map +1 -1
  6. package/dist/generate.js +33 -64
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +0 -1
  10. package/dist/playground/inputs.d.ts +4 -8
  11. package/dist/playground/inputs.d.ts.map +1 -1
  12. package/dist/playground/inputs.js +56 -37
  13. package/dist/render/api-page.d.ts.map +1 -1
  14. package/dist/render/markdown.d.ts.map +1 -1
  15. package/dist/render/markdown.js +15 -11
  16. package/dist/render/operation/api-example.js +10 -6
  17. package/dist/render/operation/index.d.ts +1 -1
  18. package/dist/render/operation/index.d.ts.map +1 -1
  19. package/dist/render/operation/index.js +4 -16
  20. package/dist/render/renderer.d.ts +1 -0
  21. package/dist/render/renderer.d.ts.map +1 -1
  22. package/dist/render/schema.d.ts +5 -15
  23. package/dist/render/schema.d.ts.map +1 -1
  24. package/dist/render/schema.js +178 -97
  25. package/dist/server/create.d.ts +1 -7
  26. package/dist/server/create.d.ts.map +1 -1
  27. package/dist/server/proxy.d.ts +11 -1
  28. package/dist/server/proxy.d.ts.map +1 -1
  29. package/dist/server/proxy.js +10 -3
  30. package/dist/server/source-api.d.ts +3 -2
  31. package/dist/server/source-api.d.ts.map +1 -1
  32. package/dist/ui/client.js +1 -1
  33. package/dist/ui/index.d.ts +1 -1
  34. package/dist/ui/index.d.ts.map +1 -1
  35. package/dist/ui/index.js +4 -4
  36. package/dist/utils/combine-schema.d.ts.map +1 -1
  37. package/dist/utils/combine-schema.js +22 -27
  38. package/dist/utils/generate-document.d.ts +4 -7
  39. package/dist/utils/generate-document.d.ts.map +1 -1
  40. package/dist/utils/generate-document.js +10 -6
  41. package/dist/utils/process-document.d.ts +1 -1
  42. package/dist/utils/process-document.d.ts.map +1 -1
  43. package/dist/utils/process-document.js +8 -5
  44. package/dist/utils/schema-to-string.d.ts.map +1 -1
  45. package/dist/utils/schema-to-string.js +8 -21
  46. package/dist/utils/schema.d.ts +1 -1
  47. package/dist/utils/schema.d.ts.map +1 -1
  48. package/dist/utils/schema.js +5 -8
  49. package/package.json +12 -12
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState, } from 'react';
3
+ import { useMemo, useState, } from 'react';
4
4
  import { Plus, Trash2 } from '../icons.js';
5
5
  import { Controller, useController, useFieldArray, useFormContext, } from 'react-hook-form';
6
6
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/components/select.js';
@@ -11,11 +11,17 @@ import { buttonVariants } from 'fumadocs-ui/components/ui/button';
11
11
  import { combineSchema } from '../utils/combine-schema.js';
12
12
  import { schemaToString } from '../utils/schema-to-string.js';
13
13
  import { anyFields, useFieldInfo, useResolvedSchema, } from '../playground/schema.js';
14
- function FieldHeader({ name, required = false, type, ...props }) {
15
- return (_jsxs("label", { ...props, className: cn('w-full inline-flex items-center gap-1', props.className), children: [_jsxs("span", { className: cn(labelVariants()), children: [name, required ? _jsx("span", { className: "text-red-400/80 mx-1", children: "*" }) : null] }), _jsx("div", { className: "flex-1" }), type ? (_jsx("code", { "data-type": true, className: "text-xs text-fd-muted-foreground", children: type })) : null, props.children] }));
14
+ function FieldHeader({ name, required = false, ...props }) {
15
+ return (_jsxs("label", { ...props, className: cn('w-full inline-flex items-center gap-1', props.className), children: [_jsxs("span", { className: cn(labelVariants(), 'me-auto'), children: [name, required ? _jsx("span", { className: "text-red-400/80 mx-1", children: "*" }) : null] }), props.children] }));
16
+ }
17
+ function FieldHeaderCode(props) {
18
+ return (_jsx("code", { ...props, className: cn('text-xs text-fd-muted-foreground', props.className), children: props.children }));
16
19
  }
17
20
  export function ObjectInput({ field: _field, fieldName, ...props }) {
18
- const field = useResolvedSchema(combineSchema([_field, ...(_field.allOf ?? []), ...(_field.anyOf ?? [])]));
21
+ const resolved = useResolvedSchema(_field);
22
+ const field = useMemo(() => combineSchema([resolved]), [resolved]);
23
+ if (typeof field === 'boolean')
24
+ return;
19
25
  return (_jsxs("div", { ...props, className: cn('flex flex-col gap-6', props.className), children: [Object.entries(field.properties ?? {}).map(([key, child]) => (_jsx(FieldSet, { name: key, field: child, fieldName: `${fieldName}.${key}`, isRequired: field.required?.includes(key) }, key))), (field.additionalProperties || field.patternProperties) && (_jsx(DynamicProperties, { fieldName: fieldName, filterKey: (v) => !field.properties || !Object.keys(field.properties).includes(v), getType: (key) => {
20
26
  for (const pattern in field.patternProperties) {
21
27
  if (key.match(RegExp(pattern))) {
@@ -64,27 +70,25 @@ function DynamicProperties({ fieldName, filterKey = () => true, getType = () =>
64
70
  return [...p, name];
65
71
  });
66
72
  };
67
- return (_jsxs(_Fragment, { children: [properties.map((item) => (_jsx(FieldSet, { name: item, field: getType(item), fieldName: `${fieldName}.${item}`, toolbar: _jsx("button", { type: "button", "aria-label": "Remove Item", className: cn(buttonVariants({
68
- color: 'ghost',
69
- className: 'p-1',
70
- })), onClick: () => {
71
- setProperties((p) => p.filter((prop) => prop !== item));
72
- control.unregister(`${fieldName}.${item}`);
73
- }, children: _jsx(Trash2, { className: "size-4" }) }) }, item))), _jsxs("div", { className: "flex gap-2", children: [_jsx(Input, { value: nextName, placeholder: "Enter Property Name", onChange: (e) => setNextName(e.target.value), onKeyDown: (e) => {
73
+ return (_jsxs(_Fragment, { children: [properties.map((item) => {
74
+ const type = getType(item);
75
+ return (_jsx(FieldSet, { name: item, field: type, fieldName: `${fieldName}.${item}`, toolbar: _jsx("button", { type: "button", "aria-label": "Remove Item", className: cn(buttonVariants({
76
+ color: 'ghost',
77
+ size: 'icon-sm',
78
+ className: 'p-1',
79
+ })), onClick: () => {
80
+ setProperties((p) => p.filter((prop) => prop !== item));
81
+ control.unregister(`${fieldName}.${item}`);
82
+ }, children: _jsx(Trash2, {}) }) }, item));
83
+ }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Input, { value: nextName, placeholder: "Enter Property Name", onChange: (e) => setNextName(e.target.value), onKeyDown: (e) => {
74
84
  if (e.key === 'Enter') {
75
85
  onAppend();
76
86
  e.preventDefault();
77
87
  }
78
88
  } }), _jsx("button", { type: "button", className: cn(buttonVariants({ color: 'secondary', size: 'sm' }), 'px-4'), onClick: onAppend, children: "New" })] })] }));
79
89
  }
80
- export function FieldInput({ field, fieldName, isRequired, ...props }) {
90
+ function FieldInput({ field, fieldName, isRequired, ...props }) {
81
91
  const { control, register } = useFormContext();
82
- if (field.type === 'object') {
83
- return (_jsx(ObjectInput, { field: field, fieldName: fieldName, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-3 shadow-sm', props.className) }));
84
- }
85
- if (field.type === 'array') {
86
- return (_jsx(ArrayInput, { fieldName: fieldName, items: field.items ?? anyFields, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-3 shadow-sm', props.className) }));
87
- }
88
92
  if (field.type === 'string' && field.format === 'binary') {
89
93
  return (_jsx(Controller, { control: control, name: fieldName, render: ({ field: { value: _, onChange, ...restField } }) => (_jsx("input", { id: fieldName, type: "file", multiple: false, onChange: (e) => {
90
94
  if (!e.target.files)
@@ -95,39 +99,53 @@ export function FieldInput({ field, fieldName, isRequired, ...props }) {
95
99
  if (field.type === 'boolean') {
96
100
  return (_jsx(Controller, { control: control, name: fieldName, render: ({ field: { value, onChange, ...restField } }) => (_jsxs(Select, { value: String(value), onValueChange: (value) => onChange(value === 'null' ? null : value === 'true'), disabled: restField.disabled, children: [_jsx(SelectTrigger, { id: fieldName, className: props.className, ...restField, children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "true", children: "True" }), _jsx(SelectItem, { value: "false", children: "False" }), !isRequired && _jsx(SelectItem, { value: "null", children: "Null" })] })] })) }));
97
101
  }
102
+ if (field.type === 'null')
103
+ return;
98
104
  return (_jsx(Input, { id: fieldName, placeholder: "Enter value", type: field.type === 'string' ? 'text' : 'number', ...register(fieldName, {
99
105
  valueAsNumber: field.type === 'number' || field.type === 'integer',
100
106
  }), ...props }));
101
107
  }
102
- export function FieldSet({ field: _field, fieldName, toolbar, name, isRequired, depth = 0, ...props }) {
108
+ export function FieldSet({ field: _field, fieldName, toolbar, name, isRequired, depth = 0, slotType, ...props }) {
103
109
  const field = useResolvedSchema(_field);
104
- const [show, setShow] = useState(() => typeof _field !== 'object' ||
105
- !_field.$ref ||
106
- (field.type !== 'object' && !field.allOf && !field.oneOf && !field.anyOf));
110
+ const [show, setShow] = useState(false);
107
111
  const { info, updateInfo } = useFieldInfo(fieldName, field, depth);
108
112
  if (_field === false)
109
113
  return null;
110
- if (!show) {
111
- return (_jsxs(FieldHeader, { ...props, name: name, required: isRequired, children: [toolbar, _jsx("button", { type: "button", className: cn(buttonVariants({ size: 'sm' })), onClick: () => setShow(true), children: "Show" })] }));
114
+ const recursive = typeof _field !== 'boolean' &&
115
+ _field.$ref &&
116
+ (field.oneOf || field.type === 'object' || field.allOf || field.anyOf);
117
+ if (recursive && !show) {
118
+ return (_jsxs(FieldHeader, { ...props, name: name, required: isRequired, children: [slotType ?? _jsx(FieldHeaderCode, { children: schemaToString(field) }), toolbar, _jsx("button", { type: "button", className: cn(buttonVariants({
119
+ size: 'sm',
120
+ color: 'secondary',
121
+ })), onClick: () => setShow(true), children: "Open" })] }));
112
122
  }
113
123
  if (field.oneOf) {
114
- return (_jsx(FieldSet, { ...props, className: cn(props.className, '[&>label>[data-type]]:hidden'), name: name, fieldName: fieldName, isRequired: isRequired, field: field.oneOf[info.oneOf], depth: depth + 1, toolbar: _jsxs(_Fragment, { children: [_jsx("select", { className: "text-xs font-mono", value: info.oneOf, onChange: (e) => {
124
+ const showSelect = field.oneOf.length > 1;
125
+ return (_jsx(FieldSet, { ...props, name: name, fieldName: fieldName, isRequired: isRequired, field: field.oneOf[info.oneOf], depth: depth + 1, slotType: showSelect ? false : slotType, toolbar: _jsxs(_Fragment, { children: [showSelect && (_jsx("select", { className: "text-xs font-mono", value: info.oneOf, onChange: (e) => {
115
126
  updateInfo({
116
127
  oneOf: Number(e.target.value),
117
128
  });
118
- }, children: field.oneOf.map((item, i) => (_jsx("option", { value: i, children: schemaToString(item) }, i))) }), toolbar] }) }));
129
+ }, children: field.oneOf.map((item, i) => (_jsx("option", { value: i, children: schemaToString(item) }, i))) })), toolbar] }) }));
119
130
  }
120
131
  if (Array.isArray(field.type)) {
121
- return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(FieldHeader, { name: name, htmlFor: fieldName, required: isRequired, children: [_jsx("select", { className: "text-xs font-mono", value: info.selectedType, onChange: (e) => {
122
- updateInfo({
123
- selectedType: e.target.value,
124
- });
125
- }, children: field.type.map((item) => (_jsx("option", { value: item, children: item }, item))) }), toolbar] }), _jsx("p", { className: "text-xs text-fd-muted-foreground", children: field.description }), _jsx(FieldInput, { isRequired: isRequired, field: {
126
- ...field,
127
- type: info.selectedType,
128
- }, fieldName: fieldName })] }));
132
+ const showSelect = field.type.length > 1;
133
+ return (_jsx(FieldSet, { ...props, name: name, fieldName: fieldName, isRequired: isRequired, field: {
134
+ ...field,
135
+ type: info.selectedType,
136
+ }, depth: depth + 1, slotType: showSelect ? false : slotType, toolbar: _jsxs(_Fragment, { children: [showSelect && (_jsx("select", { className: "text-xs font-mono", value: info.selectedType, onChange: (e) => {
137
+ updateInfo({
138
+ selectedType: e.target.value,
139
+ });
140
+ }, children: field.type.map((item) => (_jsx("option", { value: item, children: item }, item))) })), toolbar] }) }));
141
+ }
142
+ if (field.type === 'object' || field.anyOf || field.allOf) {
143
+ return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(FieldHeader, { htmlFor: fieldName, name: name, required: isRequired, children: [slotType ?? (_jsx(FieldHeaderCode, { children: schemaToString(field) })), toolbar] }), _jsx(ObjectInput, { field: field, fieldName: fieldName, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-3 shadow-sm', props.className) })] }));
144
+ }
145
+ if (field.type === 'array') {
146
+ return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(FieldHeader, { htmlFor: fieldName, name: name, required: isRequired, children: [slotType ?? (_jsx(FieldHeaderCode, { children: schemaToString(field) })), toolbar] }), _jsx(ArrayInput, { fieldName: fieldName, items: field.items ?? anyFields, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-3 shadow-sm', props.className) })] }));
129
147
  }
130
- return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsx(FieldHeader, { htmlFor: fieldName, name: name, required: isRequired, type: field.oneOf ? undefined : schemaToString(field), children: toolbar }), show ? (_jsx(FieldInput, { field: field, fieldName: fieldName, isRequired: isRequired })) : (_jsx("div", { children: _jsx("button", { onClick: () => setShow((prev) => !prev), children: "Show" }) }))] }));
148
+ return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(FieldHeader, { htmlFor: fieldName, name: name, required: isRequired, children: [slotType ?? _jsx(FieldHeaderCode, { children: schemaToString(field) }), toolbar] }), _jsx(FieldInput, { field: field, fieldName: fieldName, isRequired: isRequired })] }));
131
149
  }
132
150
  function ArrayInput({ fieldName, items, ...props }) {
133
151
  const name = fieldName.split('.').at(-1) ?? '';
@@ -136,9 +154,10 @@ function ArrayInput({ fieldName, items, ...props }) {
136
154
  });
137
155
  return (_jsxs("div", { ...props, className: cn('flex flex-col gap-2', props.className), children: [fields.map((item, index) => (_jsx(FieldSet, { name: _jsxs("span", { className: "text-fd-muted-foreground", children: [name, "[", index, "]"] }), field: items, fieldName: `${fieldName}.${index}`, toolbar: _jsx("button", { type: "button", "aria-label": "Remove Item", className: cn(buttonVariants({
138
156
  color: 'ghost',
157
+ size: 'icon-sm',
139
158
  className: 'p-1',
140
- })), onClick: () => remove(index), children: _jsx(Trash2, { className: "size-4" }) }) }, item.id))), _jsxs("button", { type: "button", className: cn(buttonVariants({
141
- color: 'outline',
159
+ })), onClick: () => remove(index), children: _jsx(Trash2, {}) }) }, item.id))), _jsxs("button", { type: "button", className: cn(buttonVariants({
160
+ color: 'secondary',
142
161
  className: 'gap-1.5 py-2',
143
162
  size: 'sm',
144
163
  })), onClick: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"api-page.d.ts","sourceRoot":"","sources":["../../src/render/api-page.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,KAAK,aAAa,EAElB,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAIlC,KAAK,mBAAmB,GAAG,IAAI,CAC7B,OAAO,CAAC,aAAa,CAAC,EACpB,cAAc,GACd,0BAA0B,GAC1B,qBAAqB,GACrB,UAAU,GACV,oBAAoB,GACpB,mBAAmB,GACnB,eAAe,CAClB,CAAC;AAEF,MAAM,WAAW,YAAa,SAAQ,mBAAmB;IACvD,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IAEjB,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE7B;;OAEG;IACH,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAE7B,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IAEzB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC;CACjC;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,YAAY,oDAsEhD;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,mBAAmB,GAAG;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;CACzB,GACL,OAAO,CAAC,aAAa,CAAC,CA0CxB"}
1
+ {"version":3,"file":"api-page.d.ts","sourceRoot":"","sources":["../../src/render/api-page.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,KAAK,aAAa,EAElB,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAIlC,KAAK,mBAAmB,GAAG,IAAI,CAC7B,OAAO,CAAC,aAAa,CAAC,EACpB,cAAc,GACd,0BAA0B,GAC1B,qBAAqB,GACrB,UAAU,GACV,oBAAoB,GACpB,mBAAmB,GACnB,eAAe,CAClB,CAAC;AAEF,MAAM,WAAW,YAAa,SAAQ,mBAAmB;IACvD,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IAEjB,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE7B;;OAEG;IACH,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAE7B,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IAEzB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC;CACjC;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,YAAY,oDAqEhD;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,mBAAmB,GAAG;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;CACzB,GACL,OAAO,CAAC,aAAa,CAAC,CA0CxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/render/markdown.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAsB1C,wBAAsB,QAAQ,CAAC,EAC7B,IAAI,GACL,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,YAAY,CAAC,CAWxB"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/render/markdown.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAkC1C,wBAAsB,QAAQ,CAAC,EAC7B,IAAI,GACL,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,YAAY,CAAC,CAIxB"}
@@ -3,7 +3,7 @@ import defaultMdxComponents from 'fumadocs-ui/mdx';
3
3
  import { remark } from 'remark';
4
4
  import remarkRehype from 'remark-rehype';
5
5
  import { toJsxRuntime } from 'hast-util-to-jsx-runtime';
6
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+ import * as JsxRuntime from 'react/jsx-runtime';
7
7
  const processor = remark()
8
8
  .use(remarkGfm)
9
9
  .use(remarkImage, { useImport: false })
@@ -11,15 +11,19 @@ const processor = remark()
11
11
  .use(rehypeCode, {
12
12
  langs: [],
13
13
  lazy: true,
14
- });
14
+ })
15
+ .use(rehypeReact);
16
+ function rehypeReact() {
17
+ this.compiler = (tree, file) => {
18
+ return toJsxRuntime(tree, {
19
+ development: false,
20
+ filePath: file.path,
21
+ ...JsxRuntime,
22
+ components: defaultMdxComponents,
23
+ });
24
+ };
25
+ }
15
26
  export async function Markdown({ text, }) {
16
- const nodes = processor.parse({ value: text });
17
- const hast = await processor.run(nodes);
18
- return toJsxRuntime(hast, {
19
- development: false,
20
- jsx: jsx,
21
- jsxs: jsxs,
22
- Fragment,
23
- components: defaultMdxComponents,
24
- });
27
+ const out = await processor.process(text);
28
+ return out.result;
25
29
  }
@@ -45,7 +45,8 @@ export function getAPIExamples(path, method, ctx) {
45
45
  data: getRequestData(path, method, key, ctx),
46
46
  });
47
47
  }
48
- return result;
48
+ if (result.length > 0)
49
+ return result;
49
50
  }
50
51
  return [
51
52
  {
@@ -68,7 +69,7 @@ export async function APIExample({ method, examples, ctx, }) {
68
69
  title: sample.name,
69
70
  description: sample.description ? (_jsx(Markdown, { text: sample.description })) : null,
70
71
  value: sample.key,
71
- })) })), generators.length > 0 && (_jsx(renderer.Requests, { items: generators.map((s) => s.label), children: generators.map((generator) => (_jsx(renderer.Request, { name: generator.label, children: _jsx(CodeExample, { ...generator }) }, generator.label))) })), _jsx(ResponseTabs, { operation: method, ctx: ctx })] }));
72
+ })) })), generators.length > 0 && (_jsx(renderer.Requests, { items: generators.map((s) => s.label ?? s.lang), children: generators.map((generator, i) => (_jsx(renderer.Request, { name: generator.label ?? generator.lang, children: _jsx(CodeExample, { ...generator }) }, i))) })), _jsx(ResponseTabs, { operation: method, ctx: ctx })] }));
72
73
  }
73
74
  /**
74
75
  * Remove duplicated labels
@@ -77,10 +78,13 @@ function dedupe(samples) {
77
78
  const set = new Set();
78
79
  const out = [];
79
80
  for (let i = samples.length - 1; i >= 0; i--) {
80
- if (set.has(samples[i].label))
81
- continue;
82
- set.add(samples[i].label);
83
- out.unshift(samples[i]);
81
+ const item = samples[i];
82
+ if (item.label) {
83
+ if (set.has(item.label))
84
+ continue;
85
+ set.add(item.label);
86
+ }
87
+ out.unshift(item);
84
88
  }
85
89
  return out;
86
90
  }
@@ -3,7 +3,7 @@ import type { MethodInformation, RenderContext } from '../../types.js';
3
3
  import { type SampleGenerator } from '../../requests/_shared.js';
4
4
  export interface CodeSample {
5
5
  lang: string;
6
- label: string;
6
+ label?: string;
7
7
  source?: string | SampleGenerator | false;
8
8
  }
9
9
  export declare function Operation({ type, path, method, ctx, hasHead, headingLevel, }: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/render/operation/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,YAAY,EAAkB,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAEV,iBAAiB,EAEjB,aAAa,EAEd,MAAM,SAAS,CAAC;AAmBjB,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAK1D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,KAAK,CAAC;CAC3C;AASD,wBAAgB,SAAS,CAAC,EACxB,IAAkB,EAClB,IAAI,EACJ,MAAM,EACN,GAAG,EACH,OAAO,EACP,YAAgB,GACjB,EAAE;IACD,IAAI,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,GAAG,EAAE,aAAa,CAAC;IAEnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,YAAY,CA2Kf"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/render/operation/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,YAAY,EAAkB,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAEV,iBAAiB,EAEjB,aAAa,EAEd,MAAM,SAAS,CAAC;AAmBjB,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAK1D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,KAAK,CAAC;CAC3C;AASD,wBAAgB,SAAS,CAAC,EACxB,IAAkB,EAClB,IAAI,EACJ,MAAM,EACN,GAAG,EACH,OAAO,EACP,YAAgB,GACjB,EAAE;IACD,IAAI,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,GAAG,EAAE,aAAa,CAAC;IAEnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,YAAY,CA6Kf"}
@@ -9,7 +9,7 @@ import { Schema } from '../schema.js';
9
9
  import { createMethod } from '../../server/create-method.js';
10
10
  import { methodKeys } from '../../build-routes.js';
11
11
  import { APIExample, APIExampleProvider, getAPIExamples, } from '../../render/operation/api-example.js';
12
- import { MethodLabel } from '../../ui/components/method-label.js';
12
+ import { Badge, MethodLabel } from '../../ui/components/method-label.js';
13
13
  import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
14
14
  import { getTypescriptSchema } from '../../utils/get-typescript-schema.js';
15
15
  import { CopyResponseTypeScript } from '../../ui/client.js';
@@ -35,11 +35,7 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
35
35
  const type = getPreferredType(body.content);
36
36
  if (!type || !(type in ctx.mediaAdapters))
37
37
  throw new Error(`No supported media type for body content: ${path}, received: ${type}`);
38
- bodyNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Request Body', ctx), _jsxs("div", { className: "mb-4 p-3 bg-fd-card rounded-xl border flex flex-row items-center justify-between gap-2", children: [_jsx("code", { children: type }), _jsx("span", { className: "text-xs", children: body.required ? 'Required' : 'Optional' })] }), body.description ? _jsx(Markdown, { text: body.description }) : null, _jsx(Schema, { name: "body", schema: (body.content[type].schema ?? {}), required: body.required, ctx: {
39
- readOnly: method.method === 'GET',
40
- writeOnly: method.method !== 'GET',
41
- render: ctx,
42
- } })] }));
38
+ bodyNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Request Body', ctx), _jsxs("div", { className: "flex justify-between items-center gap-2 mb-4", children: [_jsx("code", { children: type }), body.required ? (_jsx(Badge, { color: "red", className: "text-xs", children: "Required" })) : (_jsx(Badge, { color: "yellow", className: "text-xs", children: "Optional" }))] }), body.description ? _jsx(Markdown, { text: body.description }) : null, _jsx(Schema, { name: "body", as: "body", schema: (body.content[type].schema ?? {}), required: body.required, readOnly: method.method === 'GET', writeOnly: method.method !== 'GET', ctx: ctx })] }));
43
39
  }
44
40
  if (method.responses && ctx.showResponseSchema !== false) {
45
41
  const statuses = Object.keys(method.responses);
@@ -54,11 +50,7 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
54
50
  description: param.description ?? param.schema?.description,
55
51
  deprecated: (param.deprecated ?? false) ||
56
52
  (param.schema?.deprecated ?? false),
57
- }, parseObject: false, required: param.required, ctx: {
58
- readOnly: method.method === 'GET',
59
- writeOnly: method.method !== 'GET',
60
- render: ctx,
61
- } }, param.name))) })] }, type));
53
+ }, required: param.required, readOnly: method.method === 'GET', writeOnly: method.method !== 'GET', ctx: ctx }, param.name))) })] }, type));
62
54
  });
63
55
  if (method.callbacks) {
64
56
  callbacksNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Webhooks', ctx), Object.entries(method.callbacks).map(([name, callback]) => (_jsx(WebhookCallback, { callback: callback, ctx: ctx, headingLevel: headingLevel }, name)))] }));
@@ -90,11 +82,7 @@ async function ResponseTab({ status, operation, ctx, }) {
90
82
  else if (generateTypeScriptSchema === undefined && responseOfType?.schema) {
91
83
  ts = await getTypescriptSchema(responseOfType?.schema, schema.dereferenceMap);
92
84
  }
93
- return (_jsxs(Tab, { value: status, children: [_jsx(Markdown, { text: description }), ts && _jsx(CopyResponseTypeScript, { code: ts }), responseOfType?.schema && (_jsx(Schema, { name: "response", schema: responseOfType.schema, required: true, ctx: {
94
- render: ctx,
95
- writeOnly: false,
96
- readOnly: true,
97
- } }))] }));
85
+ return (_jsxs(Tab, { value: status, children: [_jsx(Markdown, { text: description }), ts && _jsx(CopyResponseTypeScript, { code: ts }), responseOfType?.schema && (_jsx(Schema, { name: "response", schema: responseOfType.schema, as: "body", readOnly: true, ctx: ctx }))] }));
98
86
  }
99
87
  function WebhookCallback({ callback, ctx, headingLevel, }) {
100
88
  return Object.entries(callback).map(([path, pathItem]) => {
@@ -21,6 +21,7 @@ export interface PropertyProps {
21
21
  required?: boolean;
22
22
  deprecated?: boolean;
23
23
  children?: ReactNode;
24
+ nested?: boolean;
24
25
  }
25
26
  export interface ObjectCollapsibleProps {
26
27
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/render/renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAWtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGtE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,SAAS,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;CACL;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,aAAa,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IAC/B,GAAG,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,UAAU,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAEnD,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACzC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACvC,mBAAmB,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACjD,QAAQ,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAClE,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,aAAa,EAAE,aAAa,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC7E,YAAY,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IAE/C;;OAEG;IACH,iBAAiB,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IACzD,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACvC,aAAa,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CAClD;AAED,wBAAgB,aAAa,IAAI,QAAQ,CAqCxC"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/render/renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAWtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGtE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,SAAS,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;CACL;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,aAAa,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IAC/B,GAAG,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,UAAU,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAEnD,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACzC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACvC,mBAAmB,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACjD,QAAQ,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAClE,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,aAAa,EAAE,aAAa,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC7E,YAAY,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IAE/C;;OAEG;IACH,iBAAiB,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IACzD,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACvC,aAAa,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CAClD;AAED,wBAAgB,aAAa,IAAI,QAAQ,CAqCxC"}
@@ -1,23 +1,13 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import type { ResolvedSchema } from '../utils/schema.js';
3
3
  import type { RenderContext } from '../types.js';
4
- interface Context {
5
- readOnly: boolean;
6
- writeOnly: boolean;
7
- stack?: ResolvedSchema[];
8
- render: RenderContext;
9
- }
10
- export declare function Schema({ name, schema, required, parseObject, ctx, }: {
4
+ export declare function Schema({ name, schema, required, readOnly, writeOnly, as, ctx: { renderer }, }: {
11
5
  name: string;
12
6
  required?: boolean;
13
7
  schema: ResolvedSchema;
14
- /**
15
- * Render the full object
16
- *
17
- * @defaultValue true
18
- * */
19
- parseObject?: boolean;
20
- ctx: Context;
8
+ as?: 'property' | 'body';
9
+ readOnly?: boolean;
10
+ writeOnly?: boolean;
11
+ ctx: RenderContext;
21
12
  }): ReactNode;
22
- export {};
23
13
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/render/schema.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAiB7C,UAAU,OAAO;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IAEzB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,MAAM,EACN,QAAgB,EAChB,WAAkB,EAClB,GAAG,GACJ,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IAEvB;;;;SAIK;IACL,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,GAAG,EAAE,OAAO,CAAC;CACd,GAAG,SAAS,CAgNZ"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/render/schema.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAwB7C,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,MAAM,EACN,QAAgB,EAChB,QAAgB,EAChB,SAAiB,EACjB,EAAe,EACf,GAAG,EAAE,EAAE,QAAQ,EAAE,GAClB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAEzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,aAAa,CAAC;CACpB,GAAG,SAAS,CAoSZ"}