fumadocs-openapi 11.4.3 → 12.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.
Files changed (119) hide show
  1. package/css/generated/shared.css +1 -1
  2. package/css/preset.css +0 -1
  3. package/dist/_virtual/_rolldown/runtime.js +10 -1
  4. package/dist/generate-file.d.ts +2 -2
  5. package/dist/generate-file.js +1 -1
  6. package/dist/i18n.d.ts +6 -8
  7. package/dist/i18n.js +2 -17
  8. package/dist/index.browser.d.ts +13 -0
  9. package/dist/index.browser.js +11 -0
  10. package/dist/index.d.ts +5 -2
  11. package/dist/index.js +3 -1
  12. package/dist/operation.d.ts +133 -0
  13. package/dist/operation.js +296 -0
  14. package/dist/packages/shared-api/dist/.translations/index.d.ts +29 -0
  15. package/dist/packages/shared-api/dist/.translations/keys.js +28 -0
  16. package/dist/packages/shared-api/dist/auto-anchor/client.js +20 -0
  17. package/dist/packages/shared-api/dist/auto-anchor/index.js +17 -0
  18. package/dist/packages/shared-api/dist/codegen.d.ts +42 -0
  19. package/dist/packages/shared-api/dist/codegen.js +35 -0
  20. package/dist/packages/shared-api/dist/components/accordion.js +71 -0
  21. package/dist/packages/shared-api/dist/components/badge.js +21 -0
  22. package/dist/packages/shared-api/dist/components/collapsible.d.ts +7 -0
  23. package/dist/packages/shared-api/dist/components/collapsible.js +16 -0
  24. package/dist/packages/shared-api/dist/components/defaults.d.ts +20 -0
  25. package/dist/packages/shared-api/dist/components/defaults.js +70 -0
  26. package/dist/packages/shared-api/dist/components/dialog.js +55 -0
  27. package/dist/packages/shared-api/dist/components/input.js +14 -0
  28. package/dist/packages/shared-api/dist/components/label.js +11 -0
  29. package/dist/packages/shared-api/dist/components/playground/inputs.js +439 -0
  30. package/dist/packages/shared-api/dist/components/playground/schema.js +112 -0
  31. package/dist/packages/shared-api/dist/components/popover.js +23 -0
  32. package/dist/packages/shared-api/dist/components/schema/client.d.ts +12 -0
  33. package/dist/packages/shared-api/dist/components/schema/client.js +508 -0
  34. package/dist/packages/shared-api/dist/components/schema/index.d.ts +9 -0
  35. package/dist/packages/shared-api/dist/components/schema/index.js +28 -0
  36. package/dist/packages/shared-api/dist/components/select-tab.js +54 -0
  37. package/dist/packages/shared-api/dist/components/select.js +70 -0
  38. package/dist/packages/shared-api/dist/components/spinner.js +14 -0
  39. package/dist/packages/shared-api/dist/i18n.d.ts +3 -0
  40. package/dist/packages/shared-api/dist/i18n.js +7 -0
  41. package/dist/packages/shared-api/dist/utils/cn.js +2 -0
  42. package/dist/packages/shared-api/dist/utils/id-to-title.js +12 -0
  43. package/dist/packages/shared-api/dist/utils/is-plain-object.js +8 -0
  44. package/dist/packages/shared-api/dist/utils/merge-refs.js +11 -0
  45. package/dist/packages/shared-api/dist/utils/url.js +13 -0
  46. package/dist/{utils → packages/shared-api/dist/utils}/use-query.js +2 -1
  47. package/dist/packages/shared-api/dist/utils/use-server-store.js +56 -0
  48. package/dist/playground/auth.d.ts +37 -0
  49. package/dist/playground/auth.js +216 -21
  50. package/dist/playground/fetcher.d.ts +11 -1
  51. package/dist/playground/index.d.ts +3 -0
  52. package/dist/playground/index.js +3 -0
  53. package/dist/requests/generators/index.d.ts +4 -4
  54. package/dist/requests/generators/index.js +2 -2
  55. package/dist/requests/index.d.ts +4 -0
  56. package/dist/requests/index.js +3 -0
  57. package/dist/requests/media/adapter.d.ts +1 -0
  58. package/dist/requests/media/encode.d.ts +7 -2
  59. package/dist/requests/media/resolve-adapter.d.ts +20 -0
  60. package/dist/server/index.d.ts +4 -7
  61. package/dist/server/index.js +1 -7
  62. package/dist/types.d.ts +0 -14
  63. package/dist/ui/base.d.ts +3 -2
  64. package/dist/ui/base.js +15 -166
  65. package/dist/ui/components/codeblock.js +3 -10
  66. package/dist/ui/components/heading.js +10 -19
  67. package/dist/ui/components/markdown.js +4 -6
  68. package/dist/ui/components/method-label.js +2 -17
  69. package/dist/ui/components/schema.js +28 -0
  70. package/dist/ui/index.d.ts +7 -198
  71. package/dist/ui/index.js +1 -3
  72. package/dist/ui/operation/index.js +142 -229
  73. package/dist/ui/operation/request-tabs.js +15 -23
  74. package/dist/ui/operation/response-tabs.js +9 -53
  75. package/dist/ui/operation/usage-tabs.js +35 -93
  76. package/dist/{playground → ui/playground}/client.d.ts +10 -21
  77. package/dist/ui/playground/client.js +432 -0
  78. package/dist/{playground → ui/playground}/components/oauth-dialog.js +26 -91
  79. package/dist/{playground → ui/playground}/components/result-display.d.ts +2 -2
  80. package/dist/{playground → ui/playground}/components/result-display.js +7 -7
  81. package/dist/{playground → ui/playground}/components/server-select.js +12 -13
  82. package/dist/{playground → ui/playground}/status-info.js +2 -2
  83. package/dist/{scalar → ui/scalar}/client.js +7 -5
  84. package/dist/{scalar → ui/scalar}/index.d.ts +2 -2
  85. package/dist/{scalar → ui/scalar}/index.js +3 -7
  86. package/dist/utils/create-page.d.ts +216 -0
  87. package/dist/utils/create-page.js +221 -0
  88. package/dist/utils/document/dereference.d.ts +2 -2
  89. package/dist/utils/document/dereference.js +8 -3
  90. package/dist/utils/document/load.js +2 -2
  91. package/dist/utils/get-example-requests.js +11 -13
  92. package/dist/utils/pages/builder.d.ts +15 -2
  93. package/dist/utils/pages/builder.js +6 -6
  94. package/dist/utils/pages/preset-auto.d.ts +1 -1
  95. package/dist/utils/pages/preset-auto.js +3 -3
  96. package/dist/utils/pages/to-static-data.js +4 -4
  97. package/dist/utils/pages/to-text.d.ts +1 -1
  98. package/dist/utils/pages/to-text.js +3 -5
  99. package/dist/utils/schema.js +5 -5
  100. package/dist/utils/use-server.d.ts +24 -0
  101. package/dist/utils/use-server.js +57 -0
  102. package/package.json +28 -20
  103. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/2.0-to-3.0/upgrade-from-two-to-three.js +0 -508
  104. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/3.0-to-3.1/upgrade-from-three-to-three-one.js +0 -152
  105. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/3.1-to-3.2/upgrade-from-three-one-to-three-two.js +0 -61
  106. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/helpers/traverse.js +0 -25
  107. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/upgrade.js +0 -15
  108. package/dist/playground/client.js +0 -574
  109. package/dist/ui/contexts/api.d.ts +0 -17
  110. package/dist/ui/contexts/api.js +0 -84
  111. package/dist/ui/create-client.d.ts +0 -9
  112. package/dist/ui/create-client.js +0 -7
  113. package/dist/ui/operation/context.d.ts +0 -15
  114. package/dist/ui/operation/context.js +0 -48
  115. package/dist/ui/operation/request-tabs.d.ts +0 -12
  116. package/dist/ui/operation/response-tabs.d.ts +0 -30
  117. package/dist/utils/get-example-requests.d.ts +0 -11
  118. package/dist/utils/schema.d.ts +0 -3
  119. package/dist/utils/storage-key.js +0 -15
@@ -1,61 +1,48 @@
1
1
  "use client";
2
- import { methodKeys } from "../../utils/schema.js";
3
- import { ServerProvider, useRenderContext } from "../contexts/api.js";
4
- import { cn } from "../../utils/cn.js";
5
- import { Badge, MethodLabel } from "../components/method-label.js";
6
- import { isMediaTypeSupported } from "../../requests/media/resolve-adapter.js";
7
- import { OperationProvider } from "./context.js";
8
- import PlaygroundClient from "../../playground/client.js";
2
+ import { useOpenAPI, useRenderContext, useTypeScriptDefinitions } from "../../utils/create-page.js";
3
+ import { OperationProvider, useOperation } from "../../operation.js";
4
+ import { AnchorSection } from "../../packages/shared-api/dist/auto-anchor/client.js";
5
+ import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "../../packages/shared-api/dist/components/accordion.js";
9
6
  import { Markdown } from "../components/markdown.js";
10
7
  import { UsageTabs } from "./usage-tabs.js";
8
+ import { Badge } from "../../packages/shared-api/dist/components/badge.js";
9
+ import { MethodLabel } from "../components/method-label.js";
10
+ import { SchemaUI } from "../components/schema.js";
11
11
  import { RequestTabs } from "./request-tabs.js";
12
- import { getExampleRequests } from "../../utils/get-example-requests.js";
12
+ import { cn } from "../../utils/cn.js";
13
+ import { SelectTab, SelectTabTrigger, SelectTabs } from "../../packages/shared-api/dist/components/select-tab.js";
13
14
  import { Heading } from "../components/heading.js";
14
- import { idToTitle } from "@fumadocs/api-docs/utils/id-to-title";
15
- import { Fragment, use, useMemo } from "react";
15
+ import PlaygroundClient from "../playground/client.js";
16
+ import { Fragment } from "react";
16
17
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
17
- import { Check, Copy } from "lucide-react";
18
18
  import { useTranslations } from "@fuma-translate/react";
19
+ import { Check, Copy } from "lucide-react";
19
20
  import { buttonVariants } from "fumadocs-ui/components/ui/button";
20
- import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "@fumadocs/api-docs/components/accordion";
21
- import { SelectTab, SelectTabTrigger, SelectTabs } from "@fumadocs/api-docs/components/select-tab";
22
- import { Callout } from "fumadocs-ui/components/callout";
23
- import { AnchorSection } from "@fumadocs/api-docs/auto-anchor/client";
24
21
  import { useCopyButton } from "fumadocs-ui/utils/use-copy-button";
22
+ import { Callout } from "fumadocs-ui/components/callout";
25
23
  //#region src/ui/operation/index.tsx
26
- const paramTypeKeys = [
27
- "path",
28
- "query",
29
- "header",
30
- "cookie"
31
- ];
32
- function Operation({ type = "operation", path, operation, pathItem, method, showTitle, showDescription, headingLevel = 2 }) {
24
+ function Operation({ type, path, method, operation, pathItem, ...props }) {
25
+ return /* @__PURE__ */ jsx(OperationProvider, {
26
+ type,
27
+ path,
28
+ method,
29
+ operation,
30
+ pathItem,
31
+ children: /* @__PURE__ */ jsx(OperationContent, { ...props })
32
+ });
33
+ }
34
+ function OperationContent({ showTitle, showDescription, headingLevel = 2 }) {
33
35
  const t = useTranslations({ note: "operation page" });
36
+ const { resolve } = useOpenAPI().doc;
34
37
  const ctx = useRenderContext();
35
- const { schema: { dereferenced, resolve } } = ctx;
36
- const body = resolve(operation.requestBody);
38
+ const { type, path, method, operation, pathItem, title, description, requestBody, parameters, security, responses, callbacks } = useOperation();
37
39
  let headNode = null;
38
- const operationDescription = operation.description ?? pathItem.description;
39
- const descriptionNode = showDescription && operationDescription && /* @__PURE__ */ jsx(Markdown, { md: operationDescription });
40
+ const descriptionNode = showDescription && description && /* @__PURE__ */ jsx(Markdown, { md: description });
40
41
  let bodyNode = null;
41
42
  let authNode = null;
42
43
  let responseNode = null;
43
44
  let callbacksNode = null;
44
- const exampleRequests = useMemo(() => getExampleRequests({
45
- path,
46
- operation,
47
- method,
48
- pathItem,
49
- ctx
50
- }), [
51
- ctx,
52
- operation,
53
- method,
54
- pathItem,
55
- path
56
- ]);
57
45
  if (showTitle) {
58
- const title = operation.summary || pathItem.summary || (operation.operationId ? idToTitle(operation.operationId) : path);
59
46
  headNode = /* @__PURE__ */ jsxs("div", {
60
47
  className: "flex gap-2 items-center justify-between",
61
48
  children: [/* @__PURE__ */ jsx(Heading, {
@@ -75,14 +62,14 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
75
62
  title: t("Deprecated"),
76
63
  className: "mt-0!"
77
64
  });
78
- const contentTypes = body?.content ? Object.entries(body.content) : null;
79
- if (contentTypes && contentTypes.length > 0) {
80
- const items = contentTypes.map(([type]) => ({
65
+ if (requestBody) {
66
+ const contentTypes = Object.entries(requestBody.content);
67
+ const items = contentTypes.map(([mediaType]) => ({
81
68
  label: /* @__PURE__ */ jsx("code", {
82
69
  className: "text-xs",
83
- children: type
70
+ children: mediaType
84
71
  }),
85
- value: type
72
+ value: mediaType
86
73
  }));
87
74
  bodyNode = /* @__PURE__ */ jsxs(SelectTabs, {
88
75
  defaultValue: items[0].value,
@@ -102,53 +89,41 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
102
89
  children: items[0].label
103
90
  })]
104
91
  }),
105
- body?.description && /* @__PURE__ */ jsx(Markdown, { md: body.description }),
106
- contentTypes.map(([type, content]) => {
107
- if (!isMediaTypeSupported(type, ctx.mediaAdapters)) throw new Error(`Media type ${type} is not supported (in ${path})`);
108
- return /* @__PURE__ */ jsx(SelectTab, {
109
- anchorSegments: ["request-body", type],
110
- value: type,
111
- children: /* @__PURE__ */ jsx(RequestBodyContentItem, {
112
- content: resolve(content),
113
- operation,
114
- method
115
- })
116
- }, type);
117
- })
92
+ requestBody.description && /* @__PURE__ */ jsx(Markdown, { md: requestBody.description }),
93
+ contentTypes.map(([mediaType, content]) => /* @__PURE__ */ jsx(SelectTab, {
94
+ anchorSegments: ["request-body", mediaType],
95
+ value: mediaType,
96
+ children: /* @__PURE__ */ jsx(RequestBodyContentItem, {
97
+ content,
98
+ required: requestBody.required,
99
+ method
100
+ })
101
+ }, mediaType))
118
102
  ]
119
103
  });
120
104
  }
121
- if (operation.responses && ctx.showResponseSchema !== false) {
122
- const statuses = Object.keys(operation.responses);
123
- responseNode = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Heading, {
124
- id: "response-body",
125
- depth: headingLevel,
126
- children: t("Response Body")
127
- }), /* @__PURE__ */ jsx(Accordions, {
128
- type: "multiple",
129
- children: statuses.map((status) => /* @__PURE__ */ jsx(ResponseAccordion, {
130
- status,
131
- operation
132
- }, status))
133
- })] });
134
- }
135
- const parameters = [...operation.parameters ?? [], ...pathItem.parameters ?? []].map((param) => resolve(param));
136
- const parameterNode = paramTypeKeys.map((type) => {
137
- const params = parameters.filter((param) => param.in === type);
138
- if (!params || params.length === 0) return;
139
- const parameterLabel = type === "path" ? t("Path Parameters") : type === "query" ? t("Query Parameters") : type === "header" ? t("Header Parameters") : t("Cookie Parameters");
105
+ if (responses.length > 0 && ctx.showResponseSchema !== false) responseNode = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Heading, {
106
+ id: "response-body",
107
+ depth: headingLevel,
108
+ children: t("Response Body")
109
+ }), /* @__PURE__ */ jsx(Accordions, {
110
+ type: "multiple",
111
+ children: responses.map((item) => /* @__PURE__ */ jsx(ResponseAccordion, { item }, item.status))
112
+ })] });
113
+ const parameterNode = parameters.map(({ in: location, items }) => {
114
+ const parameterLabel = location === "path" ? t("Path Parameters") : location === "query" ? t("Query Parameters") : location === "header" ? t("Header Parameters") : t("Cookie Parameters");
140
115
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Heading, {
141
- id: `parameters-${type}`,
116
+ id: `parameters-${location}`,
142
117
  depth: headingLevel,
143
118
  children: parameterLabel
144
119
  }), /* @__PURE__ */ jsx(AnchorSection, {
145
- segments: ["parameters", type],
120
+ segments: ["parameters", location],
146
121
  children: /* @__PURE__ */ jsx("div", {
147
122
  className: "flex flex-col",
148
- children: params.map((param) => {
123
+ children: items.map((param) => {
149
124
  if (param.schema == null) return;
150
125
  const schema = resolve(param.schema);
151
- return /* @__PURE__ */ jsx(ctx.SchemaUI, {
126
+ return /* @__PURE__ */ jsx(SchemaUI, {
152
127
  client: {
153
128
  name: param.name,
154
129
  required: param.required
@@ -163,17 +138,15 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
163
138
  }, param.name);
164
139
  })
165
140
  })
166
- })] }, type);
141
+ })] }, location);
167
142
  });
168
- const securities = (operation.security ?? dereferenced.security ?? []).filter((v) => Object.keys(v).length > 0);
169
- if (type === "operation" && securities.length > 0) {
170
- const securitySchemes = dereferenced.components?.securitySchemes;
171
- const items = securities.map((security, i) => {
143
+ if (security.length > 0) {
144
+ const items = security.map((requirement, i) => {
172
145
  return {
173
146
  value: String(i),
174
147
  label: /* @__PURE__ */ jsx("div", {
175
148
  className: "flex flex-col text-xs min-w-0",
176
- children: Object.entries(security).map(([key, scopes]) => /* @__PURE__ */ jsxs("code", {
149
+ children: requirement.map(({ key, scopes }) => /* @__PURE__ */ jsxs("code", {
177
150
  className: "truncate",
178
151
  children: [
179
152
  /* @__PURE__ */ jsx("span", {
@@ -203,43 +176,22 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
203
176
  className: "not-prose",
204
177
  children: items[0].label
205
178
  })]
206
- }), securities.map((security, i) => /* @__PURE__ */ jsx(SelectTab, {
179
+ }), security.map((requirement, i) => /* @__PURE__ */ jsx(SelectTab, {
207
180
  value: items[i].value,
208
- children: Object.entries(security).map(([key, scopes]) => {
209
- const scheme = resolve(securitySchemes?.[key]);
210
- if (!scheme) return;
211
- return /* @__PURE__ */ jsx(AuthScheme, {
212
- scheme,
213
- scopes
214
- }, key);
215
- })
181
+ children: requirement.map(({ key, scopes, scheme }) => scheme && /* @__PURE__ */ jsx(AuthScheme, {
182
+ scheme,
183
+ scopes
184
+ }, key))
216
185
  }, i))]
217
186
  });
218
187
  }
219
- const webhookCallbacks = [];
220
- for (const [name, item] of Object.entries(operation.callbacks ?? {})) {
221
- const callbacks = resolve(item);
222
- for (const [path, pathItem] of Object.entries(callbacks)) {
223
- const callback = resolve(pathItem);
224
- for (const method of methodKeys) {
225
- if (!callback[method]) continue;
226
- webhookCallbacks.push({
227
- name,
228
- path,
229
- method,
230
- callback,
231
- operation: callback[method]
232
- });
233
- }
234
- }
235
- }
236
- if (webhookCallbacks.length > 0) callbacksNode = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Heading, {
188
+ if (callbacks.length > 0) callbacksNode = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Heading, {
237
189
  id: "callbacks",
238
190
  depth: headingLevel,
239
191
  children: t("Callbacks")
240
192
  }), /* @__PURE__ */ jsx(Accordions, {
241
193
  type: "multiple",
242
- children: webhookCallbacks.map((item, i) => /* @__PURE__ */ jsxs(AccordionItem, {
194
+ children: callbacks.map((item, i) => /* @__PURE__ */ jsxs(AccordionItem, {
243
195
  value: `${item.name}\0${item.path}\0${item.method}`,
244
196
  anchorSegments: [
245
197
  "callbacks",
@@ -266,51 +218,28 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
266
218
  path,
267
219
  headingLevel: headingLevel + 1,
268
220
  method: item.method,
269
- pathItem: item.callback,
221
+ pathItem: item.pathItem,
270
222
  operation: item.operation
271
223
  })
272
224
  }) })]
273
225
  }, i))
274
226
  })] });
275
- let { renderOperationLayout, renderWebhookLayout } = ctx.content ?? {};
276
227
  if (type === "operation") {
277
- renderOperationLayout ??= (slots) => {
278
- return /* @__PURE__ */ jsxs("div", {
279
- className: "flex flex-col gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start",
280
- children: [/* @__PURE__ */ jsxs("div", {
281
- className: "min-w-0 flex-1",
282
- children: [
283
- slots.header,
284
- slots.apiPlayground,
285
- slots.description,
286
- slots.authSchemes,
287
- slots.parameters,
288
- slots.body,
289
- slots.responses,
290
- slots.callbacks
291
- ]
292
- }), /* @__PURE__ */ jsx("div", {
293
- className: "@4xl:sticky @4xl:top-[calc(var(--fd-docs-row-1,2rem)+1rem)] @4xl:w-[400px]",
294
- children: slots.apiExample
295
- })]
296
- });
297
- };
228
+ const playground = ctx.playground;
298
229
  let apiPlayground;
299
- if (ctx.playground?.enabled ?? true) apiPlayground = ctx.playground?.render ? ctx.playground.render({
300
- path,
301
- method,
302
- operation,
303
- pathItem,
304
- ctx
305
- }) : /* @__PURE__ */ jsx(PlaygroundClient, {
306
- operation,
307
- pathItem,
308
- route: path,
309
- method,
310
- writeOnly: true,
311
- readOnly: false
312
- });
313
- else apiPlayground = /* @__PURE__ */ jsxs("div", {
230
+ if (playground?.enabled ?? true) {
231
+ const { enabled: _, render, ...options } = playground ?? {};
232
+ apiPlayground = render ? render({
233
+ path,
234
+ method,
235
+ operation,
236
+ pathItem
237
+ }) : /* @__PURE__ */ jsx(PlaygroundClient, {
238
+ ...options,
239
+ writeOnly: true,
240
+ readOnly: false
241
+ });
242
+ } else apiPlayground = /* @__PURE__ */ jsxs("div", {
314
243
  className: "flex flex-row items-center gap-2.5 p-3 rounded-xl border bg-fd-card text-fd-card-foreground not-prose",
315
244
  children: [/* @__PURE__ */ jsx(MethodLabel, {
316
245
  className: "text-xs",
@@ -320,7 +249,7 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
320
249
  children: path
321
250
  })]
322
251
  });
323
- let content = renderOperationLayout({
252
+ const slots = {
324
253
  header: headNode,
325
254
  description: descriptionNode,
326
255
  authSchemes: authNode,
@@ -329,37 +258,22 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
329
258
  parameters: parameterNode,
330
259
  responses: responseNode,
331
260
  apiPlayground,
332
- apiExample: /* @__PURE__ */ jsx(UsageTabs, {
333
- path,
334
- method,
335
- operation,
336
- pathItem
337
- })
338
- }, {
261
+ apiExample: /* @__PURE__ */ jsx(UsageTabs, {})
262
+ };
263
+ if (ctx.content?.renderOperationLayout) return ctx.content.renderOperationLayout(slots, {
339
264
  path,
340
265
  operation,
341
266
  method,
342
267
  pathItem,
343
268
  ctx
344
269
  });
345
- content = /* @__PURE__ */ jsx(OperationProvider, {
346
- defaultExampleId: operation["x-exclusiveCodeSample"] ?? operation["x-selectedCodeSample"],
347
- route: path,
348
- examples: exampleRequests,
349
- children: content
350
- });
351
- if (operation.servers || pathItem.servers) content = /* @__PURE__ */ jsx(ServerProvider, {
352
- servers: operation.servers ?? pathItem.servers,
353
- children: content
354
- });
355
- return content;
356
- } else {
357
- renderWebhookLayout ??= (slots) => /* @__PURE__ */ jsxs("div", {
358
- className: "flex flex-col-reverse gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start",
270
+ return /* @__PURE__ */ jsxs("div", {
271
+ className: "flex flex-col gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start",
359
272
  children: [/* @__PURE__ */ jsxs("div", {
360
- className: "min-w-0 flex-1 prose-no-margin",
273
+ className: "min-w-0 flex-1",
361
274
  children: [
362
275
  slots.header,
276
+ slots.apiPlayground,
363
277
  slots.description,
364
278
  slots.authSchemes,
365
279
  slots.parameters,
@@ -369,58 +283,63 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
369
283
  ]
370
284
  }), /* @__PURE__ */ jsx("div", {
371
285
  className: "@4xl:sticky @4xl:top-[calc(var(--fd-docs-row-1,2rem)+1rem)] @4xl:w-[400px]",
372
- children: slots.requests
286
+ children: slots.apiExample
373
287
  })]
374
288
  });
375
- return renderWebhookLayout({
376
- header: headNode,
377
- description: descriptionNode,
378
- authSchemes: authNode,
379
- body: bodyNode,
380
- callbacks: callbacksNode,
381
- parameters: parameterNode,
382
- responses: responseNode,
383
- requests: /* @__PURE__ */ jsx(RequestTabs, {
384
- examples: exampleRequests,
385
- path,
386
- method,
387
- pathItem,
388
- operation
389
- })
390
- });
391
289
  }
290
+ const slots = {
291
+ header: headNode,
292
+ description: descriptionNode,
293
+ authSchemes: authNode,
294
+ body: bodyNode,
295
+ callbacks: callbacksNode,
296
+ parameters: parameterNode,
297
+ responses: responseNode,
298
+ requests: /* @__PURE__ */ jsx(RequestTabs, {})
299
+ };
300
+ if (ctx.content?.renderWebhookLayout) return ctx.content.renderWebhookLayout(slots);
301
+ return /* @__PURE__ */ jsxs("div", {
302
+ className: "flex flex-col-reverse gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start",
303
+ children: [/* @__PURE__ */ jsxs("div", {
304
+ className: "min-w-0 flex-1 prose-no-margin",
305
+ children: [
306
+ slots.header,
307
+ slots.description,
308
+ slots.authSchemes,
309
+ slots.parameters,
310
+ slots.body,
311
+ slots.responses,
312
+ slots.callbacks
313
+ ]
314
+ }), /* @__PURE__ */ jsx("div", {
315
+ className: "@4xl:sticky @4xl:top-[calc(var(--fd-docs-row-1,2rem)+1rem)] @4xl:w-[400px]",
316
+ children: slots.requests
317
+ })]
318
+ });
392
319
  }
393
- function RequestBodyContentItem({ content, method, operation }) {
394
- const ctx = useRenderContext();
395
- let ts = useMemo(() => {
396
- if (!content.schema || !ctx.generateTypeScriptDefinitions) return;
397
- return ctx.generateTypeScriptDefinitions(content.schema, {
398
- name: "RequestBody",
399
- readOnly: false,
400
- writeOnly: true,
401
- ctx
402
- });
403
- }, [content.schema, ctx]);
404
- if (ts instanceof Promise) ts = use(ts);
320
+ function RequestBodyContentItem({ content, required, method }) {
321
+ const ts = useTypeScriptDefinitions(content.schema, {
322
+ name: "RequestBody",
323
+ readOnly: false,
324
+ writeOnly: true
325
+ });
405
326
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [ts && /* @__PURE__ */ jsx(CopyTypeScriptPanel, {
406
327
  name: "request body",
407
328
  code: ts,
408
329
  className: "my-4 last:mb-0"
409
- }), content.schema && /* @__PURE__ */ jsx(ctx.SchemaUI, {
330
+ }), content.schema && /* @__PURE__ */ jsx(SchemaUI, {
410
331
  client: {
411
332
  name: "body",
412
333
  as: "body",
413
- required: ctx.schema.resolve(operation.requestBody)?.required
334
+ required
414
335
  },
415
336
  root: content.schema,
416
337
  readOnly: method === "get",
417
338
  writeOnly: method !== "get"
418
339
  })] });
419
340
  }
420
- function ResponseAccordion({ status, operation }) {
421
- const { schema } = useRenderContext();
422
- const response = schema.resolve(operation.responses[status]);
423
- const contentTypes = response.content ? Object.entries(response.content) : [];
341
+ function ResponseAccordion({ item: { status, response, content } }) {
342
+ const contentTypes = Object.entries(content);
424
343
  const items = contentTypes.map(([key]) => ({
425
344
  label: /* @__PURE__ */ jsx("code", {
426
345
  className: "text-xs",
@@ -448,32 +367,26 @@ function ResponseAccordion({ status, operation }) {
448
367
  children: [response.description && /* @__PURE__ */ jsx("div", {
449
368
  className: "prose-no-margin mt-3 mb-2",
450
369
  children: /* @__PURE__ */ jsx(Markdown, { md: response.description })
451
- }), contentTypes.map(([type, item]) => /* @__PURE__ */ jsx(SelectTab, {
452
- value: type,
453
- anchorSegments: [type],
454
- children: /* @__PURE__ */ jsx(RepsonseAccordionItem, { item: schema.resolve(item) })
455
- }, type))]
370
+ }), contentTypes.map(([mediaType, media]) => /* @__PURE__ */ jsx(SelectTab, {
371
+ value: mediaType,
372
+ anchorSegments: [mediaType],
373
+ children: /* @__PURE__ */ jsx(ResponseAccordionItem, { item: media })
374
+ }, mediaType))]
456
375
  })]
457
376
  })
458
377
  });
459
378
  }
460
- function RepsonseAccordionItem({ item: { schema } }) {
461
- const ctx = useRenderContext();
462
- let ts = useMemo(() => {
463
- if (!schema || !ctx.generateTypeScriptDefinitions) return;
464
- return ctx.generateTypeScriptDefinitions(schema, {
465
- name: "ResponseBody",
466
- readOnly: true,
467
- writeOnly: false,
468
- ctx
469
- });
470
- }, [ctx, schema]);
471
- if (ts instanceof Promise) ts = use(ts);
379
+ function ResponseAccordionItem({ item: { schema } }) {
380
+ const ts = useTypeScriptDefinitions(schema, {
381
+ name: "ResponseBody",
382
+ readOnly: true,
383
+ writeOnly: false
384
+ });
472
385
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [ts && /* @__PURE__ */ jsx(CopyTypeScriptPanel, {
473
386
  name: "response body",
474
387
  code: ts,
475
388
  className: "mb-2"
476
- }), schema && /* @__PURE__ */ jsx(ctx.SchemaUI, {
389
+ }), schema && /* @__PURE__ */ jsx(SchemaUI, {
477
390
  client: {
478
391
  name: "response",
479
392
  as: "body"
@@ -1,32 +1,30 @@
1
1
  "use client";
2
- import { useRenderContext } from "../contexts/api.js";
2
+ import { useRenderContext } from "../../utils/create-page.js";
3
+ import { useExampleRequests, useOperation } from "../../operation.js";
4
+ import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "../../packages/shared-api/dist/components/accordion.js";
5
+ import { Markdown } from "../components/markdown.js";
3
6
  import { ClientCodeBlock } from "../components/codeblock.js";
4
- import { pathnameFromRequest } from "../../requests/generators/index.js";
5
7
  import { MethodLabel } from "../components/method-label.js";
6
- import { Markdown } from "../components/markdown.js";
7
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
9
  import { useTranslations } from "@fuma-translate/react";
9
- import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "@fumadocs/api-docs/components/accordion";
10
10
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "fumadocs-ui/components/tabs";
11
11
  //#region src/ui/operation/request-tabs.tsx
12
- function RequestTabs({ path, operation, method, pathItem, examples }) {
12
+ function RequestTabs() {
13
13
  const ctx = useRenderContext();
14
+ const { path, method, operation, pathItem } = useOperation();
15
+ const { items } = useExampleRequests();
14
16
  if (!operation.requestBody) return null;
15
- const { renderRequestTabs = renderRequestTabsDefault } = ctx.content ?? {};
16
- return renderRequestTabs({
17
- items: examples,
17
+ if (ctx.content?.renderRequestTabs) return ctx.content.renderRequestTabs({
18
+ items,
18
19
  route: path,
19
20
  method,
20
21
  pathItem,
21
22
  operation
22
23
  }, ctx);
24
+ return /* @__PURE__ */ jsx(RequestTabsDefaultContent, { items });
23
25
  }
24
- function renderRequestTabsDefault(options) {
25
- return /* @__PURE__ */ jsx(RequestTabsDefaultContent, { options });
26
- }
27
- function RequestTabsDefaultContent({ options }) {
26
+ function RequestTabsDefaultContent({ items }) {
28
27
  const t = useTranslations({ note: "operation page" });
29
- const { items } = options;
30
28
  let children;
31
29
  if (items.length > 1) children = /* @__PURE__ */ jsxs(Tabs, {
32
30
  defaultValue: items[0].id,
@@ -35,16 +33,10 @@ function RequestTabsDefaultContent({ options }) {
35
33
  children: item.id === "_default" ? t("Default") : item.name
36
34
  }, item.id)) }), items.map((item) => /* @__PURE__ */ jsx(TabsContent, {
37
35
  value: item.id,
38
- children: /* @__PURE__ */ jsx(RequestTabsItem, {
39
- item,
40
- options
41
- })
36
+ children: /* @__PURE__ */ jsx(RequestTabsItem, { item })
42
37
  }, item.id))]
43
38
  });
44
- else if (items.length === 1) children = /* @__PURE__ */ jsx(RequestTabsItem, {
45
- item: items[0],
46
- options
47
- });
39
+ else if (items.length === 1) children = /* @__PURE__ */ jsx(RequestTabsItem, { item: items[0] });
48
40
  else children = /* @__PURE__ */ jsx("p", {
49
41
  className: "text-fd-muted-foreground text-xs",
50
42
  children: t("Empty")
@@ -57,7 +49,7 @@ function RequestTabsDefaultContent({ options }) {
57
49
  }), children]
58
50
  });
59
51
  }
60
- function RequestTabsItem({ item, options }) {
52
+ function RequestTabsItem({ item }) {
61
53
  const t = useTranslations({ note: "operation page" });
62
54
  const requestData = item.data;
63
55
  const displayNames = {
@@ -74,7 +66,7 @@ function RequestTabsItem({ item, options }) {
74
66
  item.description && /* @__PURE__ */ jsx(Markdown, { md: item.description }),
75
67
  /* @__PURE__ */ jsxs("div", {
76
68
  className: "flex flex-row gap-2 items-center justify-between",
77
- children: [/* @__PURE__ */ jsx(MethodLabel, { children: requestData.method }), /* @__PURE__ */ jsx("code", { children: pathnameFromRequest(options.route, item.encoded) })]
69
+ children: [/* @__PURE__ */ jsx(MethodLabel, { children: requestData.method }), /* @__PURE__ */ jsx("code", { children: item.pathname })]
78
70
  }),
79
71
  /* @__PURE__ */ jsx(Accordions, {
80
72
  type: "multiple",