fumadocs-openapi 5.11.8 → 6.0.0

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.
@@ -46,9 +46,20 @@ interface CodeSample {
46
46
  source: string | ((endpoint: EndpointSample) => string | undefined) | false;
47
47
  }
48
48
 
49
+ type ProcessedDocument = {
50
+ document: NoReference<Document>;
51
+ dereferenceMap: DereferenceMap;
52
+ downloaded: Document;
53
+ };
54
+
49
55
  type Document = OpenAPIV3_1.Document;
56
+ type OperationObject = OpenAPIV3_1.OperationObject;
57
+ type SecuritySchemeObject = OpenAPIV3_1.SecuritySchemeObject;
50
58
  type ReferenceObject = OpenAPIV3_1.ReferenceObject;
51
59
  type ServerObject = NoReference<OpenAPIV3_1.ServerObject>;
60
+ type MethodInformation = NoReference<OperationObject> & {
61
+ method: string;
62
+ };
52
63
  type Awaitable<T> = T | Promise<T>;
53
64
  /**
54
65
  * Dereferenced value and its original `$ref` value
@@ -60,14 +71,13 @@ interface RenderContext {
60
71
  */
61
72
  proxyUrl?: string;
62
73
  renderer: Renderer;
63
- /**
64
- * dereferenced schema
65
- */
66
- document: NoReference<Document>;
67
74
  baseUrl: string;
68
75
  servers: ServerObject[];
69
76
  slugger: Slugger;
70
- dereferenceMap: DereferenceMap;
77
+ /**
78
+ * dereferenced schema
79
+ */
80
+ schema: ProcessedDocument;
71
81
  /**
72
82
  * Generate TypeScript definitions from response schema.
73
83
  *
@@ -88,6 +98,10 @@ interface RenderContext {
88
98
  showResponseSchema?: boolean;
89
99
  }
90
100
 
101
+ type Security = SecuritySchemeObject & {
102
+ scopes: string[];
103
+ };
104
+
91
105
  interface BaseRequestField {
92
106
  name: string;
93
107
  description?: string;
@@ -117,7 +131,7 @@ interface FileSchema extends BaseSchema {
117
131
  }
118
132
  interface ObjectSchema extends BaseSchema {
119
133
  type: 'object';
120
- properties: Record<string, ReferenceSchema>;
134
+ properties: Record<string, RequestSchema | ReferenceSchema>;
121
135
  /**
122
136
  * Reference to schema, or true if it's `any`
123
137
  */
@@ -134,9 +148,7 @@ type RequestSchema = PrimitiveSchema | ArraySchema | ObjectSchema | SwitcherSche
134
148
  interface APIPlaygroundProps {
135
149
  route: string;
136
150
  method: string;
137
- authorization?: PrimitiveRequestField & {
138
- authType: string;
139
- };
151
+ authorization?: Security;
140
152
  path?: PrimitiveRequestField[];
141
153
  query?: PrimitiveRequestField[];
142
154
  header?: PrimitiveRequestField[];
@@ -212,7 +224,11 @@ interface Renderer {
212
224
  */
213
225
  ObjectCollapsible: ComponentType<ObjectCollapsibleProps>;
214
226
  Property: ComponentType<PropertyProps>;
215
- APIPlayground: ComponentType<APIPlaygroundProps>;
227
+ APIPlayground: ComponentType<{
228
+ path: string;
229
+ method: MethodInformation;
230
+ ctx: RenderContext;
231
+ }>;
216
232
  }
217
233
 
218
234
  interface SchemaContextType {
@@ -235,7 +251,10 @@ interface FetchResult {
235
251
  }
236
252
 
237
253
  interface FormValues {
238
- authorization: string;
254
+ authorization: string | {
255
+ username: string;
256
+ password: string;
257
+ };
239
258
  path: Record<string, unknown>;
240
259
  query: Record<string, unknown>;
241
260
  header: Record<string, unknown>;
@@ -255,7 +274,7 @@ interface CustomField<TName extends FieldPath<FormValues>, Info> {
255
274
 
256
275
  declare const APIPlayground: react.ComponentType<APIPlaygroundProps & {
257
276
  fields?: {
258
- auth?: CustomField<"authorization", PrimitiveRequestField>;
277
+ auth?: CustomField<"authorization", RequestSchema>;
259
278
  path?: CustomField<`path.${string}`, PrimitiveRequestField>;
260
279
  query?: CustomField<`query.${string}`, PrimitiveRequestField>;
261
280
  header?: CustomField<`header.${string}`, PrimitiveRequestField>;
@@ -271,9 +290,7 @@ declare function Root({ children, baseUrl, className, shikiOptions, servers, ...
271
290
  shikiOptions: RenderContext['shikiOptions'];
272
291
  } & HTMLAttributes<HTMLDivElement>): ReactNode;
273
292
 
274
- declare function APIInfo({ className, route, badgeClassname, method, head, ...props }: APIInfoProps & HTMLAttributes<HTMLDivElement> & {
275
- badgeClassname?: string;
276
- }): react_jsx_runtime.JSX.Element;
293
+ declare function APIInfo({ className, ...props }: HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
277
294
  declare function API({ children, ...props }: HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
278
295
  declare function Property({ name, type, required, deprecated, children, }: PropertyProps): react_jsx_runtime.JSX.Element;
279
296
  declare function APIExample(props: HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
package/dist/ui/index.js CHANGED
@@ -1,10 +1,9 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { cn } from 'fumadocs-ui/components/api';
3
- import { Fragment } from 'react';
4
- import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { cn, buttonVariants } from 'fumadocs-ui/components/api';
5
3
  import { cva } from 'class-variance-authority';
6
- import { h as CopyRouteButton, i as ServerSelect } from './client-client-B06fJG48.js';
7
- export { A as APIPlayground, R as Root, u as useSchemaContext } from './client-client-B06fJG48.js';
4
+ import { Collapsible, CollapsibleTrigger, CollapsibleContent } from 'fumadocs-ui/components/ui/collapsible';
5
+ export { A as APIPlayground, R as Root, u as useSchemaContext } from './client-client-CpwKrzlY.js';
6
+ import { C as ChevronDown } from './index-client-CehDtJk-.js';
8
7
 
9
8
  const badgeVariants = cva('rounded-xl border px-1.5 py-1 text-xs font-medium leading-[12px]', {
10
9
  variants: {
@@ -17,77 +16,12 @@ const badgeVariants = cva('rounded-xl border px-1.5 py-1 text-xs font-medium lea
17
16
  }
18
17
  }
19
18
  });
20
- function getBadgeColor(method) {
21
- switch(method){
22
- case 'PUT':
23
- return 'yellow';
24
- case 'PATCH':
25
- return 'orange';
26
- case 'POST':
27
- return 'blue';
28
- case 'DELETE':
29
- return 'red';
30
- default:
31
- return 'green';
32
- }
33
- }
34
19
 
35
- function Route({ route }) {
36
- const segments = route.split('/').filter((part)=>part.length > 0);
20
+ function APIInfo({ className, ...props }) {
37
21
  return /*#__PURE__*/ jsx("div", {
38
- className: "not-prose flex flex-row items-center gap-0.5 overflow-auto text-nowrap text-xs",
39
- children: segments.map((part, index)=>/*#__PURE__*/ jsxs(Fragment, {
40
- children: [
41
- /*#__PURE__*/ jsx("span", {
42
- className: "text-fd-muted-foreground",
43
- children: "/"
44
- }),
45
- part.startsWith('{') && part.endsWith('}') ? /*#__PURE__*/ jsx("code", {
46
- className: "bg-fd-primary/10 text-fd-primary",
47
- children: part
48
- }) : /*#__PURE__*/ jsx("code", {
49
- className: "text-fd-foreground",
50
- children: part
51
- })
52
- ]
53
- }, index))
54
- });
55
- }
56
- function APIInfo({ className, route, badgeClassname, method = 'GET', head, ...props }) {
57
- return /*#__PURE__*/ jsxs("div", {
58
22
  className: cn('min-w-0 flex-1', className),
59
23
  ...props,
60
- children: [
61
- head,
62
- /*#__PURE__*/ jsxs("div", {
63
- className: "not-prose mb-4 rounded-lg border bg-fd-card p-3 text-fd-card-foreground shadow-lg",
64
- children: [
65
- /*#__PURE__*/ jsxs("div", {
66
- className: "-mx-1 flex flex-row items-center gap-1.5",
67
- children: [
68
- /*#__PURE__*/ jsx("span", {
69
- className: cn(badgeVariants({
70
- color: getBadgeColor(method)
71
- }), badgeClassname),
72
- children: method
73
- }),
74
- /*#__PURE__*/ jsx(Route, {
75
- route: route
76
- }),
77
- /*#__PURE__*/ jsx(CopyRouteButton, {
78
- className: "ms-auto size-6 p-1.5",
79
- route: route
80
- })
81
- ]
82
- }),
83
- /*#__PURE__*/ jsx(ServerSelect, {})
84
- ]
85
- }),
86
- /*#__PURE__*/ jsx("div", {
87
- className: "prose-no-margin",
88
- children: props.children
89
- })
90
- ]
24
+ children: props.children
91
25
  });
92
26
  }
93
27
  function API({ children, ...props }) {
@@ -103,9 +37,9 @@ function API({ children, ...props }) {
103
37
  }
104
38
  function Property({ name, type, required, deprecated, children }) {
105
39
  return /*#__PURE__*/ jsxs("div", {
106
- className: "mb-4 rounded-lg border bg-fd-card p-3 prose-no-margin",
40
+ className: "rounded-xl border bg-fd-card p-3 prose-no-margin",
107
41
  children: [
108
- /*#__PURE__*/ jsxs("h4", {
42
+ /*#__PURE__*/ jsxs("div", {
109
43
  className: "flex flex-row flex-wrap items-center gap-4",
110
44
  children: [
111
45
  /*#__PURE__*/ jsx("code", {
@@ -124,7 +58,7 @@ function Property({ name, type, required, deprecated, children }) {
124
58
  children: "Deprecated"
125
59
  }) : null,
126
60
  /*#__PURE__*/ jsx("span", {
127
- className: "ms-auto font-mono text-[13px] text-fd-muted-foreground",
61
+ className: "ms-auto text-xs font-mono text-fd-muted-foreground",
128
62
  children: type
129
63
  })
130
64
  ]
@@ -141,12 +75,29 @@ function APIExample(props) {
141
75
  });
142
76
  }
143
77
  function ObjectCollapsible(props) {
144
- return /*#__PURE__*/ jsx(Accordions, {
145
- type: "single",
146
- children: /*#__PURE__*/ jsx(Accordion, {
147
- title: props.name,
148
- children: props.children
149
- })
78
+ return /*#__PURE__*/ jsxs(Collapsible, {
79
+ ...props,
80
+ children: [
81
+ /*#__PURE__*/ jsxs(CollapsibleTrigger, {
82
+ className: cn(buttonVariants({
83
+ color: 'outline',
84
+ size: 'sm'
85
+ }), 'group rounded-full px-2 py-1.5 text-fd-muted-foreground'),
86
+ children: [
87
+ props.name,
88
+ /*#__PURE__*/ jsx(ChevronDown, {
89
+ className: "size-4 group-data-[state=open]:rotate-180"
90
+ })
91
+ ]
92
+ }),
93
+ /*#__PURE__*/ jsx(CollapsibleContent, {
94
+ className: "-mx-2",
95
+ children: /*#__PURE__*/ jsx("div", {
96
+ className: "flex flex-col gap-2 p-2",
97
+ children: props.children
98
+ })
99
+ })
100
+ ]
150
101
  });
151
102
  }
152
103
 
@@ -0,0 +1,86 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { a as useApiContext, b as useServerSelectContext } from './client-client-CpwKrzlY.js';
4
+ import { S as Select, a as SelectTrigger, b as SelectValue, c as SelectContent, d as SelectItem, l as labelVariants, I as Input } from './index-client-CehDtJk-.js';
5
+ import { cn } from 'fumadocs-ui/components/api';
6
+
7
+ function ServerSelect(props) {
8
+ const { servers } = useApiContext();
9
+ const { server, setServer, setServerVariables } = useServerSelectContext();
10
+ if (servers.length <= 1) return null;
11
+ const schema = server ? servers.find((item)=>item.url === server.url) : undefined;
12
+ return /*#__PURE__*/ jsxs("div", {
13
+ ...props,
14
+ className: cn('flex flex-col gap-4', props.className),
15
+ children: [
16
+ /*#__PURE__*/ jsxs(Select, {
17
+ value: server?.url,
18
+ onValueChange: setServer,
19
+ children: [
20
+ /*#__PURE__*/ jsx(SelectTrigger, {
21
+ className: "h-auto break-all",
22
+ children: /*#__PURE__*/ jsx(SelectValue, {})
23
+ }),
24
+ /*#__PURE__*/ jsx(SelectContent, {
25
+ children: servers.map((item)=>/*#__PURE__*/ jsxs(SelectItem, {
26
+ value: item.url,
27
+ children: [
28
+ item.url,
29
+ /*#__PURE__*/ jsx("p", {
30
+ className: "text-start text-fd-muted-foreground",
31
+ children: item.description
32
+ })
33
+ ]
34
+ }, item.url))
35
+ })
36
+ ]
37
+ }),
38
+ Object.entries(schema?.variables ?? {}).map(([key, variable])=>{
39
+ if (!server) return;
40
+ const id = `fd_server_select_${key}`;
41
+ return /*#__PURE__*/ jsxs("fieldset", {
42
+ className: "flex flex-col gap-1",
43
+ children: [
44
+ /*#__PURE__*/ jsx("label", {
45
+ className: cn(labelVariants()),
46
+ htmlFor: id,
47
+ children: key
48
+ }),
49
+ /*#__PURE__*/ jsx("p", {
50
+ className: "text-xs text-fd-muted-foreground empty:hidden",
51
+ children: variable.description
52
+ }),
53
+ variable.enum ? /*#__PURE__*/ jsxs(Select, {
54
+ value: server.variables[key],
55
+ onValueChange: (v)=>setServerVariables({
56
+ ...server?.variables,
57
+ [key]: v
58
+ }),
59
+ children: [
60
+ /*#__PURE__*/ jsx(SelectTrigger, {
61
+ id: id,
62
+ children: /*#__PURE__*/ jsx(SelectValue, {})
63
+ }),
64
+ /*#__PURE__*/ jsx(SelectContent, {
65
+ children: variable.enum.map((value)=>/*#__PURE__*/ jsx(SelectItem, {
66
+ value: value,
67
+ children: value
68
+ }, value))
69
+ })
70
+ ]
71
+ }) : /*#__PURE__*/ jsx(Input, {
72
+ id: id,
73
+ value: server.variables[key],
74
+ onChange: (e)=>setServerVariables({
75
+ ...server?.variables,
76
+ [key]: e.target.value
77
+ })
78
+ })
79
+ ]
80
+ }, key);
81
+ })
82
+ ]
83
+ });
84
+ }
85
+
86
+ export { ServerSelect as S };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-openapi",
3
- "version": "5.11.8",
3
+ "version": "6.0.0",
4
4
  "description": "Generate MDX docs for your OpenAPI spec",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -20,6 +20,10 @@
20
20
  "import": "./dist/ui/index.js",
21
21
  "types": "./dist/ui/index.d.ts"
22
22
  },
23
+ "./scalar": {
24
+ "import": "./dist/scalar/index.js",
25
+ "types": "./dist/scalar/index.d.ts"
26
+ },
23
27
  "./server": {
24
28
  "import": "./dist/server/index.js",
25
29
  "types": "./dist/server/index.d.ts"
@@ -32,7 +36,7 @@
32
36
  ],
33
37
  "dependencies": {
34
38
  "@fumari/json-schema-to-typescript": "^1.1.2",
35
- "@radix-ui/react-select": "^2.1.4",
39
+ "@radix-ui/react-select": "^2.1.5",
36
40
  "@radix-ui/react-slot": "^1.1.1",
37
41
  "@scalar/openapi-parser": "0.10.4",
38
42
  "ajv-draft-04": "^1.0.0",
@@ -41,32 +45,41 @@
41
45
  "github-slugger": "^2.0.0",
42
46
  "hast-util-to-jsx-runtime": "^2.3.2",
43
47
  "js-yaml": "^4.1.0",
48
+ "next-themes": "^0.4.4",
44
49
  "openapi-sampler": "^1.6.1",
45
50
  "react-hook-form": "^7.54.2",
46
51
  "remark": "^15.0.1",
47
52
  "remark-rehype": "^11.1.1",
48
- "shiki": "^2.0.3",
53
+ "shiki": "^2.2.0",
49
54
  "xml-js": "^1.6.11",
50
- "fumadocs-core": "14.7.7",
51
- "fumadocs-ui": "14.7.7"
55
+ "fumadocs-core": "15.0.0",
56
+ "fumadocs-ui": "15.0.0"
52
57
  },
53
58
  "devDependencies": {
59
+ "@scalar/api-client-react": "^1.1.22",
54
60
  "@types/js-yaml": "^4.0.9",
55
- "@types/node": "22.10.7",
61
+ "@types/node": "22.13.0",
56
62
  "@types/openapi-sampler": "^1.0.3",
57
- "@types/react": "^19.0.7",
63
+ "@types/react": "^19.0.8",
58
64
  "bunchee": "^6.3.2",
59
- "lucide-react": "^0.473.0",
60
- "next": "15.1.5",
65
+ "lucide-react": "^0.474.0",
66
+ "next": "15.1.6",
61
67
  "openapi-types": "^12.1.3",
62
- "eslint-config-custom": "0.0.0",
63
- "tsconfig": "0.0.0"
68
+ "tailwindcss": "^4.0.2",
69
+ "tsconfig": "0.0.0",
70
+ "eslint-config-custom": "0.0.0"
64
71
  },
65
72
  "peerDependencies": {
73
+ "@scalar/api-client-react": "*",
66
74
  "next": "14.x.x || 15.x.x",
67
75
  "react": "18.x.x || 19.x.x",
68
76
  "react-dom": "18.x.x || 19.x.x"
69
77
  },
78
+ "peerDependenciesMeta": {
79
+ "@scalar/api-client-react": {
80
+ "optional": true
81
+ }
82
+ },
70
83
  "publishConfig": {
71
84
  "access": "public"
72
85
  },