fumadocs-openapi 6.0.1 → 6.0.3

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 (155) hide show
  1. package/dist/build-routes.d.ts +15 -0
  2. package/dist/build-routes.d.ts.map +1 -0
  3. package/dist/build-routes.js +38 -0
  4. package/dist/generate-file.d.ts +38 -0
  5. package/dist/generate-file.d.ts.map +1 -0
  6. package/dist/generate-file.js +118 -0
  7. package/dist/generate.d.ts +48 -0
  8. package/dist/generate.d.ts.map +1 -0
  9. package/dist/generate.js +129 -0
  10. package/dist/index.d.ts +4 -274
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +3 -389
  13. package/dist/render/codeblock.d.ts +9 -0
  14. package/dist/render/codeblock.d.ts.map +1 -0
  15. package/dist/render/codeblock.js +13 -0
  16. package/dist/render/heading.d.ts +4 -0
  17. package/dist/render/heading.d.ts.map +1 -0
  18. package/dist/render/heading.js +6 -0
  19. package/dist/render/markdown.d.ts +5 -0
  20. package/dist/render/markdown.d.ts.map +1 -0
  21. package/dist/render/markdown.js +25 -0
  22. package/dist/render/operation.d.ts +17 -0
  23. package/dist/render/operation.d.ts.map +1 -0
  24. package/dist/render/operation.js +230 -0
  25. package/dist/render/playground.d.ts +66 -0
  26. package/dist/render/playground.d.ts.map +1 -0
  27. package/dist/render/playground.js +181 -0
  28. package/dist/render/renderer.d.ts +76 -0
  29. package/dist/render/renderer.d.ts.map +1 -0
  30. package/dist/render/renderer.js +23 -0
  31. package/dist/render/schema.d.ts +29 -0
  32. package/dist/render/schema.d.ts.map +1 -0
  33. package/dist/render/schema.js +151 -0
  34. package/dist/requests/curl.d.ts +3 -0
  35. package/dist/requests/curl.d.ts.map +1 -0
  36. package/dist/requests/curl.js +33 -0
  37. package/dist/requests/go.d.ts +3 -0
  38. package/dist/requests/go.d.ts.map +1 -0
  39. package/dist/requests/go.js +54 -0
  40. package/dist/requests/javascript.d.ts +3 -0
  41. package/dist/requests/javascript.d.ts.map +1 -0
  42. package/dist/requests/javascript.js +49 -0
  43. package/dist/requests/python.d.ts +3 -0
  44. package/dist/requests/python.d.ts.map +1 -0
  45. package/dist/requests/python.js +45 -0
  46. package/dist/scalar/client.d.ts +6 -0
  47. package/dist/scalar/client.d.ts.map +1 -0
  48. package/dist/scalar/client.js +25 -0
  49. package/dist/scalar/index.d.ts +4 -173
  50. package/dist/scalar/index.d.ts.map +1 -0
  51. package/dist/scalar/index.js +4 -11
  52. package/dist/server/api-page.d.ts +33 -0
  53. package/dist/server/api-page.d.ts.map +1 -0
  54. package/dist/server/api-page.js +59 -0
  55. package/dist/server/create-method.d.ts +7 -0
  56. package/dist/server/create-method.d.ts.map +1 -0
  57. package/dist/server/create-method.js +12 -0
  58. package/dist/server/create.d.ts +16 -0
  59. package/dist/server/create.d.ts.map +1 -0
  60. package/dist/server/create.js +11 -0
  61. package/dist/server/index.d.ts +3 -221
  62. package/dist/server/index.d.ts.map +1 -0
  63. package/dist/server/index.js +2 -1493
  64. package/dist/server/proxy.d.ts +8 -0
  65. package/dist/server/proxy.d.ts.map +1 -0
  66. package/dist/server/proxy.js +53 -0
  67. package/dist/server/source-api.d.ts +8 -0
  68. package/dist/server/source-api.d.ts.map +1 -0
  69. package/dist/server/source-api.js +34 -0
  70. package/dist/types.d.ts +60 -0
  71. package/dist/types.d.ts.map +1 -0
  72. package/dist/types.js +1 -0
  73. package/dist/ui/client.d.ts +22 -0
  74. package/dist/ui/client.d.ts.map +1 -0
  75. package/dist/ui/client.js +10 -0
  76. package/dist/ui/components/input.d.ts +6 -0
  77. package/dist/ui/components/input.d.ts.map +1 -0
  78. package/dist/ui/components/input.js +10 -0
  79. package/dist/ui/components/method-label.d.ts +5 -0
  80. package/dist/ui/components/method-label.d.ts.map +1 -0
  81. package/dist/ui/components/method-label.js +33 -0
  82. package/dist/ui/components/select.d.ts +14 -0
  83. package/dist/ui/components/select.d.ts.map +1 -0
  84. package/dist/ui/components/select.js +24 -0
  85. package/dist/ui/components/variants.d.ts +6 -0
  86. package/dist/ui/components/variants.d.ts.map +1 -0
  87. package/dist/ui/components/variants.js +26 -0
  88. package/dist/ui/contexts/api.d.ts +28 -0
  89. package/dist/ui/contexts/api.d.ts.map +1 -0
  90. package/dist/ui/contexts/api.js +74 -0
  91. package/dist/ui/contexts/schema.d.ts +17 -0
  92. package/dist/ui/contexts/schema.d.ts.map +1 -0
  93. package/dist/ui/contexts/schema.js +8 -0
  94. package/dist/ui/index.d.ts +12 -302
  95. package/dist/ui/index.d.ts.map +1 -0
  96. package/dist/ui/index.js +18 -98
  97. package/dist/ui/playground/fetcher.d.ts +34 -0
  98. package/dist/ui/playground/fetcher.d.ts.map +1 -0
  99. package/dist/ui/{fetcher-CsHhplmD.js → playground/fetcher.js} +45 -44
  100. package/dist/ui/playground/get-default-values.d.ts +4 -0
  101. package/dist/ui/playground/get-default-values.d.ts.map +1 -0
  102. package/dist/ui/playground/get-default-values.js +24 -0
  103. package/dist/ui/playground/index.d.ts +44 -0
  104. package/dist/ui/playground/index.d.ts.map +1 -0
  105. package/dist/ui/playground/index.js +187 -0
  106. package/dist/ui/playground/inputs.d.ts +23 -0
  107. package/dist/ui/playground/inputs.d.ts.map +1 -0
  108. package/dist/ui/playground/inputs.js +172 -0
  109. package/dist/ui/playground/resolve.d.ts +6 -0
  110. package/dist/ui/playground/resolve.d.ts.map +1 -0
  111. package/dist/ui/playground/resolve.js +14 -0
  112. package/dist/ui/playground/status-info.d.ts +8 -0
  113. package/dist/ui/playground/status-info.d.ts.map +1 -0
  114. package/dist/ui/playground/status-info.js +40 -0
  115. package/dist/ui/server-select.d.ts +3 -0
  116. package/dist/ui/server-select.d.ts.map +1 -0
  117. package/dist/ui/server-select.js +27 -0
  118. package/dist/utils/combine-schema.d.ts +6 -0
  119. package/dist/utils/combine-schema.d.ts.map +1 -0
  120. package/dist/utils/combine-schema.js +46 -0
  121. package/dist/utils/generate-document.d.ts +20 -0
  122. package/dist/utils/generate-document.d.ts.map +1 -0
  123. package/dist/utils/generate-document.js +82 -0
  124. package/dist/utils/generate-sample.d.ts +33 -0
  125. package/dist/utils/generate-sample.d.ts.map +1 -0
  126. package/dist/utils/generate-sample.js +97 -0
  127. package/dist/utils/get-security.d.ts +8 -0
  128. package/dist/utils/get-security.d.ts.map +1 -0
  129. package/dist/utils/get-security.js +23 -0
  130. package/dist/utils/get-typescript-schema.d.ts +4 -0
  131. package/dist/utils/get-typescript-schema.d.ts.map +1 -0
  132. package/dist/utils/get-typescript-schema.js +18 -0
  133. package/dist/utils/id-to-title.d.ts +2 -0
  134. package/dist/utils/id-to-title.d.ts.map +1 -0
  135. package/dist/utils/id-to-title.js +17 -0
  136. package/dist/utils/input-to-string.d.ts +5 -0
  137. package/dist/utils/input-to-string.d.ts.map +1 -0
  138. package/dist/utils/input-to-string.js +21 -0
  139. package/dist/utils/process-document.d.ts +14 -0
  140. package/dist/utils/process-document.d.ts.map +1 -0
  141. package/dist/utils/process-document.js +32 -0
  142. package/dist/utils/schema.d.ts +9 -0
  143. package/dist/utils/schema.d.ts.map +1 -0
  144. package/dist/utils/schema.js +16 -0
  145. package/dist/utils/server-url.d.ts +2 -0
  146. package/dist/utils/server-url.d.ts.map +1 -0
  147. package/dist/utils/server-url.js +7 -0
  148. package/dist/utils/use-query.d.ts +6 -0
  149. package/dist/utils/use-query.d.ts.map +1 -0
  150. package/dist/utils/use-query.js +22 -0
  151. package/package.json +8 -8
  152. package/dist/scalar/client-client-BXAjVueF.js +0 -93
  153. package/dist/ui/client-client-CYO00OiB.js +0 -107
  154. package/dist/ui/index-client-BUeWwFWK.js +0 -1116
  155. package/dist/ui/server-select-client-Ct_HJ46K.js +0 -86
@@ -1,1493 +1,2 @@
1
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import Slugger from 'github-slugger';
3
- import { Fragment as Fragment$1 } from 'react';
4
- import { sample } from 'openapi-sampler';
5
- import { js2xml } from 'xml-js';
6
- import { compile } from '@fumari/json-schema-to-typescript';
7
- import { remarkGfm, remarkImage, rehypeCode } from 'fumadocs-core/mdx-plugins';
8
- import defaultMdxComponents from 'fumadocs-ui/mdx';
9
- import { remark } from 'remark';
10
- import remarkRehype from 'remark-rehype';
11
- import { toJsxRuntime } from 'hast-util-to-jsx-runtime';
12
- import { Heading } from 'fumadocs-ui/components/heading';
13
- import { Tabs, Tab } from 'fumadocs-ui/components/tabs';
14
- import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
15
- import * as Base from 'fumadocs-ui/components/codeblock';
16
- import { highlight } from 'fumadocs-core/server';
17
- import { APIPlayground, Root, API, APIInfo, APIExample as APIExample$1, Property, ObjectCollapsible } from '../ui/index.js';
18
- import { load, upgrade, dereference } from '@scalar/openapi-parser';
19
- import { fetchUrls } from '@scalar/openapi-parser/plugins/fetch-urls';
20
- import { readFiles } from '@scalar/openapi-parser/plugins/read-files';
21
- import { cva } from 'class-variance-authority';
22
-
23
- function getPreferredType(body) {
24
- if ('application/json' in body) return 'application/json';
25
- return Object.keys(body)[0];
26
- }
27
- function isNullable(schema, includeOneOf = true) {
28
- if (Array.isArray(schema.type) && schema.type.includes('null')) return true;
29
- if (includeOneOf && (schema.anyOf || schema.oneOf)) {
30
- if (schema.anyOf?.some((item)=>isNullable(item))) return true;
31
- if (schema.oneOf?.some((item)=>isNullable(item))) return true;
32
- }
33
- return false;
34
- }
35
-
36
- function getSecurities(requirement, document) {
37
- const results = [];
38
- const schemas = document.components?.securitySchemes ?? {};
39
- for (const [key, scopes] of Object.entries(requirement)){
40
- if (!(key in schemas)) return [];
41
- const schema = schemas[key];
42
- results.push({
43
- ...schema,
44
- scopes
45
- });
46
- }
47
- return results;
48
- }
49
- function getSecurityPrefix(security) {
50
- if (security.type === 'http') return ({
51
- basic: 'Basic',
52
- bearer: 'Bearer'
53
- })[security.scheme];
54
- if (security.type === 'oauth2') return 'Bearer';
55
- }
56
-
57
- function generateSample(path, method, { baseUrl, schema: { document } }) {
58
- const params = [];
59
- const responses = {};
60
- for (const param of method.parameters ?? []){
61
- if (param.schema) {
62
- params.push({
63
- name: param.name,
64
- in: param.in,
65
- schema: param.schema,
66
- sample: param.example ?? sample(param.schema)
67
- });
68
- } else if (param.content) {
69
- const key = getPreferredType(param.content);
70
- const content = key ? param.content[key] : undefined;
71
- if (!key || !content) throw new Error(`Cannot find parameter schema for ${param.name} in ${path} ${method.method}`);
72
- params.push({
73
- name: param.name,
74
- in: param.in,
75
- schema: content.schema ?? {},
76
- sample: content.example ?? param.example ?? sample(content.schema)
77
- });
78
- }
79
- }
80
- const requirements = method.security ?? document.security;
81
- if (requirements && requirements.length > 0) {
82
- for (const security of getSecurities(requirements[0], document)){
83
- const prefix = getSecurityPrefix(security);
84
- params.push({
85
- name: security.type === 'apiKey' ? security.name : 'Authorization',
86
- schema: {
87
- type: 'string'
88
- },
89
- sample: prefix ? `${prefix} <token>` : '<token>',
90
- in: 'header'
91
- });
92
- }
93
- }
94
- let bodyOutput;
95
- if (method.requestBody) {
96
- const body = method.requestBody.content;
97
- const type = getPreferredType(body);
98
- if (!type) throw new Error(`Cannot find body schema for ${path} ${method.method}: missing media type`);
99
- const schema = (type ? body[type].schema : undefined) ?? {};
100
- bodyOutput = {
101
- schema,
102
- mediaType: type,
103
- sample: body[type].example ?? generateBody(method.method, schema)
104
- };
105
- }
106
- for (const [code, response] of Object.entries(method.responses ?? {})){
107
- const content = response.content;
108
- if (!content) continue;
109
- const mediaType = getPreferredType(content);
110
- if (!mediaType) continue;
111
- const responseSchema = content[mediaType].schema;
112
- if (!responseSchema) continue;
113
- responses[code] = {
114
- mediaType,
115
- sample: content[mediaType].example ?? generateBody(method.method, responseSchema),
116
- schema: responseSchema
117
- };
118
- }
119
- let pathWithParameters = path;
120
- const queryParams = new URLSearchParams();
121
- for (const param of params){
122
- const value = generateBody(method.method, param.schema);
123
- if (param.in === 'query') queryParams.append(param.name, String(value));
124
- if (param.in === 'path') pathWithParameters = pathWithParameters.replace(`{${param.name}}`, String(value));
125
- }
126
- if (queryParams.size > 0) pathWithParameters = `${pathWithParameters}?${queryParams.toString()}`;
127
- return {
128
- url: new URL(`${baseUrl}${pathWithParameters}`).toString(),
129
- body: bodyOutput,
130
- responses,
131
- method: method.method,
132
- parameters: params
133
- };
134
- }
135
- function generateBody(method, schema) {
136
- return sample(schema, {
137
- skipReadOnly: method !== 'GET',
138
- skipWriteOnly: method === 'GET'
139
- });
140
- }
141
-
142
- /**
143
- * Convert input value to hardcoded string (with quotes)
144
- */ function inputToString(value, mediaType = 'application/json', multiLine = 'none') {
145
- const getStr = (v)=>{
146
- if (multiLine === 'none') return JSON.stringify(v);
147
- const delimit = multiLine === 'backtick' ? `\`` : `'`;
148
- return `${delimit}${v.replaceAll(delimit, `\\${delimit}`)}${delimit}`;
149
- };
150
- if (typeof value === 'string') return getStr(value);
151
- if (mediaType === 'application/json' || mediaType === 'multipart/form-data') {
152
- return getStr(JSON.stringify(value, null, 2));
153
- }
154
- if (mediaType === 'application/xml') {
155
- return getStr(js2xml(value, {
156
- compact: true,
157
- spaces: 2
158
- }));
159
- }
160
- throw new Error(`Unsupported media type: ${mediaType}`);
161
- }
162
-
163
- function getSampleRequest$3(endpoint) {
164
- const s = [];
165
- s.push(`curl -X ${endpoint.method} "${endpoint.url}"`);
166
- for (const param of endpoint.parameters){
167
- if (param.in === 'header') {
168
- const header = `${param.name}: ${param.sample}`;
169
- s.push(`-H "${header}"`);
170
- }
171
- if (param.in === 'cookie') {
172
- const cookie = JSON.stringify(`${param.name}=${param.sample}`);
173
- s.push(`--cookie ${cookie}`);
174
- }
175
- }
176
- if (endpoint.body?.mediaType === 'multipart/form-data') {
177
- const sample = endpoint.body.sample;
178
- if (sample && typeof sample === 'object') {
179
- for (const [key, value] of Object.entries(sample)){
180
- s.push(`-F ${key}=${inputToString(value)}`);
181
- }
182
- }
183
- } else if (endpoint.body) {
184
- s.push(`-H "Content-Type: ${endpoint.body.mediaType}"`);
185
- s.push(`-d ${inputToString(endpoint.body.sample, endpoint.body.mediaType, 'single-quote')}`);
186
- }
187
- return s.flatMap((v, i)=>v.split('\n').map((line)=>i > 0 ? ` ${line}` : line).join('\n')).join(' \\\n');
188
- }
189
-
190
- function getSampleRequest$2(endpoint) {
191
- const s = [];
192
- const options = new Map();
193
- const headers = new Map();
194
- const cookies = new Map();
195
- for (const param of endpoint.parameters){
196
- if (param.in === 'header') {
197
- headers.set(param.name, param.sample);
198
- }
199
- if (param.in === 'cookie') {
200
- cookies.set(param.name, param.sample);
201
- }
202
- }
203
- if (cookies.size > 0) {
204
- headers.set('cookie', Array.from(cookies.entries()).map(([key, value])=>`${key}=${value}`).join('; '));
205
- }
206
- if (headers.size > 0) {
207
- options.set('headers', JSON.stringify(Object.fromEntries(headers.entries()), null, 2).replaceAll('\n', '\n '));
208
- }
209
- if (endpoint.body?.mediaType === 'multipart/form-data' && typeof endpoint.body.sample === 'object' && endpoint.body.sample) {
210
- s.push(`const formData = new FormData();`);
211
- for (const [key, value] of Object.entries(endpoint.body.sample))s.push(`formData.set(${key}, ${inputToString(value)})`);
212
- options.set('body', 'formData');
213
- } else if (endpoint.body) {
214
- let code;
215
- if (endpoint.body.mediaType === 'application/json') {
216
- code = typeof endpoint.body.sample === 'string' ? inputToString(endpoint.body.sample, endpoint.body.mediaType, 'backtick') : `JSON.stringify(${JSON.stringify(endpoint.body.sample, null, 2)})`;
217
- } else {
218
- code = inputToString(endpoint.body.sample, endpoint.body.mediaType, 'backtick');
219
- }
220
- options.set('body', code.replaceAll('\n', '\n '));
221
- }
222
- const optionsStr = Array.from(options.entries()).map(([k, v])=>` ${k}: ${v}`).join(',\n');
223
- s.push(`fetch(${JSON.stringify(endpoint.url)}, {\n${optionsStr}\n});`);
224
- return s.join('\n\n');
225
- }
226
-
227
- function getSampleRequest$1(endpoint) {
228
- const imports = [
229
- 'fmt',
230
- 'net/http',
231
- 'io/ioutil'
232
- ];
233
- const headers = new Map();
234
- const variables = new Map();
235
- // additional lines before initializing request
236
- const additional = [];
237
- for (const p of endpoint.parameters){
238
- if (p.in === 'header') headers.set(p.name, JSON.stringify(p.sample));
239
- }
240
- const cookies = endpoint.parameters.filter((p)=>p.in === 'cookie');
241
- variables.set('url', JSON.stringify(endpoint.url));
242
- if (cookies.length > 0) headers.set('Cookie', JSON.stringify(cookies.map((p)=>`${p.name}=${p.sample}`).join('; ')));
243
- if (endpoint.body) {
244
- headers.set('Content-Type', `"${endpoint.body.mediaType}"`);
245
- if (endpoint.body.mediaType === 'multipart/form-data' && typeof endpoint.body.sample === 'object') {
246
- imports.push('mime/multipart', 'bytes');
247
- variables.set('payload', `new(bytes.Buffer)`);
248
- variables.set('mp', 'multipart.NewWriter(payload)');
249
- for (const [key, value] of Object.entries(endpoint.body.sample ?? {})){
250
- additional.push(`mp.WriteField("${key}", ${inputToString(value, undefined, 'backtick')})`);
251
- }
252
- } else {
253
- imports.push('strings');
254
- variables.set('payload', `strings.NewReader(${inputToString(endpoint.body.sample, endpoint.body.mediaType, 'backtick').replaceAll('\n', '\n ')})`);
255
- }
256
- }
257
- return `package main
258
-
259
- import (
260
- ${imports.map((v)=>` "${v}"`).join('\n')}
261
- )
262
-
263
- func main() {
264
- ${Array.from(variables.entries()).map(([k, v])=>` ${k} := ${v}`).join('\n')}
265
- ${additional.join('\n ')}
266
- req, _ := http.NewRequest("${endpoint.method}", url, ${variables.has('payload') ? 'payload' : 'nil'})
267
- ${Array.from(headers.entries()).map(([key, value])=>`req.Header.Add("${key}", ${value})`).join('\n ')}
268
- res, _ := http.DefaultClient.Do(req)
269
- defer res.Body.Close()
270
- body, _ := ioutil.ReadAll(res.Body)
271
-
272
- fmt.Println(res)
273
- fmt.Println(string(body))
274
- }`;
275
- }
276
-
277
- function getSampleRequest(endpoint) {
278
- const headers = new Map();
279
- const cookies = new Map();
280
- const variables = new Map();
281
- for (const param of endpoint.parameters){
282
- if (param.in === 'header') headers.set(param.name, param.sample);
283
- if (param.in === 'cookie') cookies.set(param.name, param.sample);
284
- }
285
- if (endpoint.body) {
286
- switch(endpoint.body.mediaType){
287
- case 'application/json':
288
- variables.set('json', JSON.stringify(endpoint.body.sample, null, 2));
289
- break;
290
- case 'multipart/form-data':
291
- headers.set('Content-Type', endpoint.body.mediaType);
292
- variables.set('data', JSON.stringify(endpoint.body.sample, null, 2));
293
- break;
294
- default:
295
- headers.set('Content-Type', endpoint.body.mediaType);
296
- variables.set('data', inputToString(endpoint.body.sample, endpoint.body.mediaType, 'backtick'));
297
- }
298
- }
299
- if (headers.size > 0) {
300
- variables.set('headers', JSON.stringify(Object.fromEntries(headers.entries()), null, 2));
301
- }
302
- if (cookies.size > 0) {
303
- variables.set('cookies', JSON.stringify(Object.fromEntries(cookies.entries()), null, 2));
304
- }
305
- return `import requests
306
-
307
- url = ${JSON.stringify(endpoint.url)}
308
- ${Array.from(variables.entries()).map(([k, v])=>`${k} = ${v}`).join('\n')}
309
- response = requests.request("${endpoint.method}", url${variables.size > 0 ? `, ${Array.from(variables.keys()).map((k)=>`${k}=${k}`).join(', ')}` : ''})
310
-
311
- print(response.text)`;
312
- }
313
-
314
- async function getTypescriptSchema(endpoint, code, dereferenceMap) {
315
- if (code in endpoint.responses) {
316
- return compile(// re-running on the same schema results in error
317
- // because it uses `defineProperty` to define internal references
318
- // we clone the schema to fix this problem
319
- // @ts-expect-error any types
320
- endpoint.responses[code].schema, 'Response', {
321
- $refOptions: false,
322
- schemaToId: dereferenceMap,
323
- bannerComment: '',
324
- additionalProperties: false,
325
- format: true,
326
- enableConstEnums: false
327
- });
328
- }
329
- }
330
-
331
- function idToTitle(id) {
332
- let result = [];
333
- for (const c of id){
334
- if (result.length === 0) result.push(c.toLocaleUpperCase());
335
- else if (c === '.') result = [];
336
- else if (/^[A-Z]$/.test(c) && result.at(-1) !== ' ') result.push(' ', c);
337
- else if (c === '-') result.push(' ');
338
- else result.push(c);
339
- }
340
- return result.join('');
341
- }
342
-
343
- const processor = remark().use(remarkGfm).use(remarkImage, {
344
- useImport: false
345
- }).use(remarkRehype).use(rehypeCode, {
346
- langs: [],
347
- lazy: true
348
- });
349
- async function Markdown({ text }) {
350
- const nodes = processor.parse({
351
- value: text
352
- });
353
- const hast = await processor.run(nodes);
354
- return toJsxRuntime(hast, {
355
- development: false,
356
- jsx: jsx,
357
- jsxs: jsxs,
358
- Fragment,
359
- components: defaultMdxComponents
360
- });
361
- }
362
-
363
- function heading(depth, child, ctx) {
364
- const id = ctx.slugger.slug(child);
365
- return /*#__PURE__*/ jsx(Heading, {
366
- id: id,
367
- as: `h${depth.toString()}`,
368
- children: child.trim()
369
- }, id);
370
- }
371
-
372
- /**
373
- * Combine multiple object schemas into one
374
- */ function combineSchema(schema) {
375
- const result = {
376
- type: undefined
377
- };
378
- function add(s) {
379
- if (s.type) {
380
- var _result;
381
- (_result = result).type ?? (_result.type = []);
382
- if (!Array.isArray(result.type)) {
383
- result.type = [
384
- result.type
385
- ];
386
- }
387
- for (const v of Array.isArray(s.type) ? s.type : [
388
- s.type
389
- ]){
390
- if (!result.type.includes(v)) {
391
- result.type.push(v);
392
- }
393
- }
394
- }
395
- if (s.properties) {
396
- var _result1;
397
- (_result1 = result).properties ?? (_result1.properties = {});
398
- Object.assign(result.properties, s.properties);
399
- }
400
- if (s.additionalProperties === true) {
401
- result.additionalProperties = true;
402
- } else if (s.additionalProperties && typeof result.additionalProperties !== 'boolean') {
403
- var _result2;
404
- (_result2 = result).additionalProperties ?? (_result2.additionalProperties = {});
405
- Object.assign(result.additionalProperties, s.additionalProperties);
406
- }
407
- if (s.required) {
408
- var _result3;
409
- (_result3 = result).required ?? (_result3.required = []);
410
- result.required.push(...s.required);
411
- }
412
- if (s.enum && s.enum.length > 0) {
413
- var _result4;
414
- (_result4 = result).enum ?? (_result4.enum = []);
415
- result.enum.push(...s.enum);
416
- }
417
- if (s.allOf) {
418
- s.allOf.forEach(add);
419
- }
420
- }
421
- schema.forEach(add);
422
- return result;
423
- }
424
-
425
- const keys$1 = {
426
- default: 'Default',
427
- minimum: 'Minimum',
428
- maximum: 'Maximum',
429
- minLength: 'Minimum length',
430
- maxLength: 'Maximum length',
431
- pattern: 'Pattern',
432
- format: 'Format'
433
- };
434
- function isObject(schema) {
435
- return schema.type === 'object' || schema.properties !== undefined || schema.additionalProperties !== undefined;
436
- }
437
- function Schema({ name, schema, ctx }) {
438
- if (schema.readOnly === true && !ctx.readOnly || schema.writeOnly === true && !ctx.writeOnly) return null;
439
- const parseObject = ctx.parseObject ?? true;
440
- const stack = ctx.stack ?? [];
441
- const { renderer } = ctx.render;
442
- // object type
443
- if (isObject(schema) && parseObject && (schema.additionalProperties || schema.properties)) {
444
- let body = null;
445
- let footer = null;
446
- const { additionalProperties, properties } = schema;
447
- if (additionalProperties === true) {
448
- footer = /*#__PURE__*/ jsx(renderer.Property, {
449
- name: "[key: string]",
450
- type: "any"
451
- });
452
- } else if (additionalProperties) {
453
- footer = /*#__PURE__*/ jsx(Schema, {
454
- name: "[key: string]",
455
- schema: additionalProperties,
456
- ctx: {
457
- ...ctx,
458
- required: false,
459
- parseObject: false
460
- }
461
- });
462
- }
463
- if (properties) {
464
- body = Object.entries(properties).map(([key, value])=>{
465
- return /*#__PURE__*/ jsx(Schema, {
466
- name: key,
467
- schema: value,
468
- ctx: {
469
- ...ctx,
470
- required: schema.required?.includes(key) ?? false,
471
- parseObject: false
472
- }
473
- }, key);
474
- });
475
- }
476
- return /*#__PURE__*/ jsxs("div", {
477
- className: "flex flex-col gap-4",
478
- children: [
479
- body,
480
- footer
481
- ]
482
- });
483
- }
484
- if (schema.allOf && parseObject) {
485
- return /*#__PURE__*/ jsx(Schema, {
486
- name: name,
487
- schema: combineSchema(schema.allOf),
488
- ctx: ctx
489
- });
490
- }
491
- let footer = null;
492
- const fields = [];
493
- for (const [key, value] of Object.entries(keys$1)){
494
- if (key in schema) {
495
- fields.push({
496
- key: value,
497
- value: JSON.stringify(schema[key])
498
- });
499
- }
500
- }
501
- if (schema.enum) {
502
- fields.push({
503
- key: 'Value in',
504
- value: schema.enum.map((value)=>JSON.stringify(value)).join(' | ')
505
- });
506
- }
507
- if (isObject(schema) && !parseObject && !stack.includes(schema)) {
508
- footer = /*#__PURE__*/ jsx(renderer.ObjectCollapsible, {
509
- name: "Show Attributes",
510
- children: /*#__PURE__*/ jsx(Schema, {
511
- name: name,
512
- schema: schema,
513
- ctx: {
514
- ...ctx,
515
- parseObject: true,
516
- required: false,
517
- stack: [
518
- schema,
519
- ...stack
520
- ]
521
- }
522
- })
523
- });
524
- } else {
525
- const mentionedObjectTypes = [
526
- ...schema.anyOf ?? schema.oneOf ?? [],
527
- ...schema.not ? [
528
- schema.not
529
- ] : [],
530
- ...schema.type === 'array' ? [
531
- schema.items
532
- ] : []
533
- ].filter((s)=>isComplexType(s) && !stack.includes(s));
534
- footer = mentionedObjectTypes.map((s, idx)=>{
535
- return /*#__PURE__*/ jsx(renderer.ObjectCollapsible, {
536
- name: s.title ?? (mentionedObjectTypes.length === 1 ? 'Show Attributes' : `Object ${idx + 1}`),
537
- children: /*#__PURE__*/ jsx(Schema, {
538
- name: "element",
539
- schema: s,
540
- ctx: {
541
- ...ctx,
542
- stack: [
543
- schema,
544
- ...stack
545
- ],
546
- parseObject: true,
547
- required: false
548
- }
549
- })
550
- }, idx);
551
- });
552
- }
553
- return /*#__PURE__*/ jsxs(renderer.Property, {
554
- name: name,
555
- type: getSchemaType(schema, ctx),
556
- required: ctx.required,
557
- deprecated: schema.deprecated,
558
- children: [
559
- schema.description ? /*#__PURE__*/ jsx(Markdown, {
560
- text: schema.description
561
- }) : null,
562
- fields.length > 0 ? /*#__PURE__*/ jsx("div", {
563
- className: "flex flex-col gap-2",
564
- children: fields.map((field)=>/*#__PURE__*/ jsxs("span", {
565
- children: [
566
- field.key,
567
- ": ",
568
- /*#__PURE__*/ jsx("code", {
569
- children: field.value
570
- })
571
- ]
572
- }, field.key))
573
- }) : null,
574
- footer
575
- ]
576
- });
577
- }
578
- /**
579
- * Check if the schema needs another collapsible to explain
580
- */ function isComplexType(schema) {
581
- if (schema.anyOf ?? schema.oneOf ?? schema.allOf) return true;
582
- return isObject(schema) || schema.type === 'array';
583
- }
584
- function getSchemaType(schema, ctx, isRoot = true) {
585
- if (isNullable(schema) && isRoot) {
586
- const type = getSchemaType(schema, ctx, false);
587
- // null if schema only contains `nullable`
588
- return type === 'unknown' ? 'null' : `${type} | null`;
589
- }
590
- if (schema.title) return schema.title;
591
- if (schema.type === 'array') return `array<${getSchemaType(schema.items, ctx)}>`;
592
- if (schema.oneOf) return schema.oneOf.map((one)=>getSchemaType(one, ctx, false)).filter((v)=>v !== 'unknown').join(' | ');
593
- if (schema.allOf) {
594
- return schema.allOf.map((one)=>getSchemaType(one, ctx, false)).filter((v)=>v !== 'unknown').join(' & ');
595
- }
596
- if (schema.not) return `not ${getSchemaType(schema.not, ctx, false)}`;
597
- if (schema.anyOf) {
598
- return `Any properties in ${schema.anyOf.map((one)=>getSchemaType(one, ctx, false)).filter((v)=>v !== 'unknown').join(', ')}`;
599
- }
600
- if (schema.type === 'string' && schema.format === 'binary' && ctx.allowFile) return 'file';
601
- if (schema.type && Array.isArray(schema.type)) {
602
- const nonNullTypes = schema.type.filter((v)=>v !== 'null');
603
- if (nonNullTypes.length > 0) return nonNullTypes.join(' | ');
604
- } else if (schema.type && schema.type !== 'null') {
605
- return schema.type;
606
- }
607
- if (isObject(schema)) return 'object';
608
- return 'unknown';
609
- }
610
-
611
- /**
612
- * Summarize method endpoint information
613
- */ function createMethod(method, path, operation) {
614
- return {
615
- description: path.description,
616
- summary: path.summary,
617
- ...operation,
618
- parameters: [
619
- ...operation.parameters ?? [],
620
- ...path.parameters ?? []
621
- ],
622
- method: method.toUpperCase()
623
- };
624
- }
625
-
626
- const methodKeys = [
627
- 'get',
628
- 'post',
629
- 'patch',
630
- 'delete',
631
- 'head',
632
- 'put'
633
- ];
634
-
635
- function Operation({ type = 'operation', path, method, ctx, hasHead, headingLevel = 2 }) {
636
- const body = method.requestBody;
637
- const security = method.security ?? ctx.schema.document.security;
638
- let headNode = null;
639
- let bodyNode = null;
640
- let responseNode = null;
641
- let callbacksNode = null;
642
- if (hasHead) {
643
- const title = method.summary ?? (method.operationId ? idToTitle(method.operationId) : path);
644
- headNode = /*#__PURE__*/ jsxs(Fragment, {
645
- children: [
646
- heading(headingLevel, title, ctx),
647
- method.description ? /*#__PURE__*/ jsx(Markdown, {
648
- text: method.description
649
- }, "description") : null
650
- ]
651
- });
652
- headingLevel++;
653
- }
654
- if (body) {
655
- const type = getPreferredType(body.content);
656
- if (!type) throw new Error(`No supported media type for body content: ${path}`);
657
- bodyNode = /*#__PURE__*/ jsxs(Fragment, {
658
- children: [
659
- heading(headingLevel, 'Request Body', ctx),
660
- /*#__PURE__*/ jsxs("div", {
661
- className: "mb-8 flex flex-row items-center justify-between gap-2",
662
- children: [
663
- /*#__PURE__*/ jsx("code", {
664
- children: type
665
- }),
666
- /*#__PURE__*/ jsx("span", {
667
- children: body.required ? 'Required' : 'Optional'
668
- })
669
- ]
670
- }),
671
- body.description ? /*#__PURE__*/ jsx(Markdown, {
672
- text: body.description
673
- }) : null,
674
- /*#__PURE__*/ jsx(Schema, {
675
- name: "body",
676
- schema: body.content[type].schema ?? {},
677
- ctx: {
678
- readOnly: method.method === 'GET',
679
- writeOnly: method.method !== 'GET',
680
- required: body.required ?? false,
681
- render: ctx,
682
- allowFile: type === 'multipart/form-data'
683
- }
684
- })
685
- ]
686
- });
687
- }
688
- if (method.responses && ctx.showResponseSchema) {
689
- responseNode = /*#__PURE__*/ jsxs(Fragment, {
690
- children: [
691
- heading(headingLevel, 'Response Body', ctx),
692
- Object.entries(method.responses).map(([status, response])=>{
693
- if (!response.content) return;
694
- const mediaType = getPreferredType(response.content);
695
- if (!mediaType) return null;
696
- const content = response.content[mediaType];
697
- if (!content.schema) return null;
698
- return /*#__PURE__*/ jsxs(Fragment$1, {
699
- children: [
700
- heading(headingLevel + 1, status, ctx),
701
- /*#__PURE__*/ jsx(Markdown, {
702
- text: response.description
703
- }),
704
- /*#__PURE__*/ jsx(Schema, {
705
- name: "response",
706
- schema: content.schema,
707
- ctx: {
708
- render: ctx,
709
- writeOnly: false,
710
- readOnly: true,
711
- required: true
712
- }
713
- })
714
- ]
715
- }, status);
716
- })
717
- ]
718
- });
719
- }
720
- const parameterGroups = new Map();
721
- const endpoint = generateSample(path, method, ctx);
722
- for (const param of method.parameters ?? []){
723
- const pInfo = endpoint.parameters.find((item)=>item.name === param.name && item.in === param.in);
724
- if (!pInfo) continue;
725
- const schema = pInfo.schema;
726
- const groupName = {
727
- path: 'Path Parameters',
728
- query: 'Query Parameters',
729
- header: 'Header Parameters',
730
- cookie: 'Cookie Parameters'
731
- }[param.in] ?? 'Other Parameters';
732
- const group = parameterGroups.get(groupName) ?? [];
733
- group.push(/*#__PURE__*/ jsx(Schema, {
734
- name: param.name,
735
- schema: {
736
- ...schema,
737
- description: param.description ?? schema.description,
738
- deprecated: (param.deprecated ?? false) || (schema.deprecated ?? false)
739
- },
740
- ctx: {
741
- parseObject: false,
742
- readOnly: method.method === 'GET',
743
- writeOnly: method.method !== 'GET',
744
- required: param.required ?? false,
745
- render: ctx
746
- }
747
- }, param.name));
748
- parameterGroups.set(groupName, group);
749
- }
750
- if (method.callbacks) {
751
- callbacksNode = /*#__PURE__*/ jsxs(Fragment, {
752
- children: [
753
- heading(headingLevel, 'Webhooks', ctx),
754
- Object.entries(method.callbacks).map(([name, callback])=>/*#__PURE__*/ jsx(WebhookCallback, {
755
- callback: callback,
756
- ctx: ctx,
757
- headingLevel: headingLevel
758
- }, name))
759
- ]
760
- });
761
- }
762
- const info = /*#__PURE__*/ jsxs(ctx.renderer.APIInfo, {
763
- head: headNode,
764
- method: method.method,
765
- route: path,
766
- children: [
767
- type === 'operation' ? /*#__PURE__*/ jsx(ctx.renderer.APIPlayground, {
768
- path: path,
769
- method: method,
770
- ctx: ctx
771
- }) : null,
772
- security ? /*#__PURE__*/ jsxs(Fragment, {
773
- children: [
774
- heading(headingLevel, 'Authorization', ctx),
775
- /*#__PURE__*/ jsx(AuthSection, {
776
- requirements: security,
777
- ctx: ctx
778
- })
779
- ]
780
- }) : null,
781
- bodyNode,
782
- Array.from(parameterGroups.entries()).map(([group, params])=>{
783
- return /*#__PURE__*/ jsxs(Fragment$1, {
784
- children: [
785
- heading(headingLevel, group, ctx),
786
- params
787
- ]
788
- }, group);
789
- }),
790
- responseNode,
791
- callbacksNode
792
- ]
793
- });
794
- if (type === 'operation') {
795
- return /*#__PURE__*/ jsxs(ctx.renderer.API, {
796
- children: [
797
- info,
798
- /*#__PURE__*/ jsx(APIExample, {
799
- method: method,
800
- endpoint: endpoint,
801
- ctx: ctx
802
- })
803
- ]
804
- });
805
- } else {
806
- return info;
807
- }
808
- }
809
- const defaultSamples = [
810
- {
811
- label: 'cURL',
812
- source: getSampleRequest$3,
813
- lang: 'bash'
814
- },
815
- {
816
- label: 'JavaScript',
817
- source: getSampleRequest$2,
818
- lang: 'js'
819
- },
820
- {
821
- label: 'Go',
822
- source: getSampleRequest$1,
823
- lang: 'go'
824
- },
825
- {
826
- label: 'Python',
827
- source: getSampleRequest,
828
- lang: 'python'
829
- }
830
- ];
831
- async function APIExample({ method, endpoint, ctx }) {
832
- const renderer = ctx.renderer;
833
- const children = [];
834
- const samples = dedupe([
835
- ...defaultSamples,
836
- ...ctx.generateCodeSamples ? await ctx.generateCodeSamples(endpoint) : [],
837
- ...method['x-codeSamples'] ?? []
838
- ]).flatMap((sample)=>{
839
- if (sample.source === false) return [];
840
- const result = typeof sample.source === 'function' ? sample.source(endpoint) : sample.source;
841
- if (result === undefined) return [];
842
- return {
843
- ...sample,
844
- source: result
845
- };
846
- });
847
- if (samples.length > 0) {
848
- children.push(/*#__PURE__*/ jsx(renderer.Requests, {
849
- items: samples.map((s)=>s.label),
850
- children: samples.map((s)=>/*#__PURE__*/ jsx(renderer.Request, {
851
- name: s.label,
852
- code: s.source,
853
- language: s.lang
854
- }, s.label))
855
- }, "requests"));
856
- }
857
- children.push(/*#__PURE__*/ jsx(ResponseTabs, {
858
- operation: method,
859
- ctx: ctx,
860
- endpoint: endpoint
861
- }, "responses"));
862
- return /*#__PURE__*/ jsx(renderer.APIExample, {
863
- children: children
864
- });
865
- }
866
- function WebhookCallback({ callback, ctx, headingLevel }) {
867
- return Object.entries(callback).map(([path, pathItem])=>{
868
- const pathNodes = methodKeys.map((method)=>{
869
- const operation = pathItem[method];
870
- if (!operation) return null;
871
- return /*#__PURE__*/ jsx(Operation, {
872
- type: "webhook",
873
- hasHead: true,
874
- path: path,
875
- headingLevel: headingLevel + 1,
876
- method: createMethod(method, pathItem, operation),
877
- ctx: ctx
878
- }, method);
879
- });
880
- return /*#__PURE__*/ jsx(Fragment$1, {
881
- children: pathNodes
882
- }, path);
883
- });
884
- }
885
- /**
886
- * Remove duplicated labels
887
- */ function dedupe(samples) {
888
- const set = new Set();
889
- const out = [];
890
- for(let i = samples.length - 1; i >= 0; i--){
891
- if (set.has(samples[i].label)) continue;
892
- set.add(samples[i].label);
893
- out.unshift(samples[i]);
894
- }
895
- return out;
896
- }
897
- function AuthSection({ ctx: { schema: { document }, renderer }, requirements }) {
898
- let id = 0;
899
- const info = [];
900
- for (const requirement of requirements){
901
- for (const schema of getSecurities(requirement, document)){
902
- const prefix = getSecurityPrefix(schema);
903
- const scopeElement = schema.scopes.length > 0 ? /*#__PURE__*/ jsxs("p", {
904
- children: [
905
- "Scope: ",
906
- /*#__PURE__*/ jsx("code", {
907
- children: schema.scopes.join(', ')
908
- })
909
- ]
910
- }) : null;
911
- if (schema.type === 'http' || schema.type === 'oauth2') {
912
- info.push(/*#__PURE__*/ jsxs(renderer.Property, {
913
- name: "Authorization",
914
- type: prefix ? `${prefix} <token>` : '<token>',
915
- required: true,
916
- children: [
917
- schema.description ? /*#__PURE__*/ jsx(Markdown, {
918
- text: schema.description
919
- }) : null,
920
- /*#__PURE__*/ jsxs("p", {
921
- children: [
922
- "In: ",
923
- /*#__PURE__*/ jsx("code", {
924
- children: "header"
925
- })
926
- ]
927
- }),
928
- scopeElement
929
- ]
930
- }, id++));
931
- }
932
- if (schema.type === 'apiKey') {
933
- info.push(/*#__PURE__*/ jsxs(renderer.Property, {
934
- name: schema.name,
935
- type: "<token>",
936
- children: [
937
- schema.description ? /*#__PURE__*/ jsx(Markdown, {
938
- text: schema.description
939
- }) : null,
940
- /*#__PURE__*/ jsxs("p", {
941
- children: [
942
- "In: ",
943
- /*#__PURE__*/ jsx("code", {
944
- children: schema.in
945
- }),
946
- scopeElement
947
- ]
948
- })
949
- ]
950
- }, id++));
951
- }
952
- if (schema.type === 'openIdConnect') {
953
- info.push(/*#__PURE__*/ jsxs(renderer.Property, {
954
- name: "OpenID Connect",
955
- type: "<token>",
956
- required: true,
957
- children: [
958
- schema.description ? /*#__PURE__*/ jsx(Markdown, {
959
- text: schema.description
960
- }) : null,
961
- scopeElement
962
- ]
963
- }, id++));
964
- }
965
- }
966
- }
967
- return info;
968
- }
969
- async function ResponseTabs({ endpoint, operation, ctx: { renderer, generateTypeScriptSchema, schema } }) {
970
- const items = [];
971
- const children = [];
972
- if (!operation.responses) return null;
973
- for (const code of Object.keys(operation.responses)){
974
- const types = [];
975
- let description = operation.responses[code].description;
976
- if (!description && code in endpoint.responses) description = endpoint.responses[code].schema.description ?? '';
977
- if (code in endpoint.responses) {
978
- types.push({
979
- lang: 'json',
980
- label: 'Response',
981
- code: JSON.stringify(endpoint.responses[code].sample, null, 2)
982
- });
983
- }
984
- let ts;
985
- if (generateTypeScriptSchema) {
986
- ts = await generateTypeScriptSchema(endpoint, code);
987
- } else if (generateTypeScriptSchema === undefined) {
988
- ts = await getTypescriptSchema(endpoint, code, schema.dereferenceMap);
989
- }
990
- if (ts) {
991
- types.push({
992
- code: ts,
993
- lang: 'ts',
994
- label: 'TypeScript'
995
- });
996
- }
997
- items.push(code);
998
- children.push(/*#__PURE__*/ jsxs(renderer.Response, {
999
- value: code,
1000
- children: [
1001
- /*#__PURE__*/ jsx(Markdown, {
1002
- text: description
1003
- }),
1004
- types.length > 0 ? /*#__PURE__*/ jsx(renderer.ResponseTypes, {
1005
- children: types.map((type)=>/*#__PURE__*/ jsx(renderer.ResponseType, {
1006
- ...type
1007
- }, type.lang))
1008
- }) : null
1009
- ]
1010
- }, code));
1011
- }
1012
- if (items.length === 0) return null;
1013
- return /*#__PURE__*/ jsx(renderer.Responses, {
1014
- items: items,
1015
- children: children
1016
- });
1017
- }
1018
-
1019
- async function CodeBlock({ code, lang, options, ...rest }) {
1020
- const rendered = await highlight(code, {
1021
- lang,
1022
- ...options,
1023
- components: {
1024
- pre: (props)=>/*#__PURE__*/ jsx(Base.Pre, {
1025
- ...props,
1026
- ...rest
1027
- })
1028
- }
1029
- });
1030
- return /*#__PURE__*/ jsx(Base.CodeBlock, {
1031
- className: "my-0",
1032
- children: rendered
1033
- });
1034
- }
1035
-
1036
- function Playground({ path, method, ctx }) {
1037
- let currentId = 0;
1038
- const bodyContent = method.requestBody?.content;
1039
- const mediaType = bodyContent ? getPreferredType(bodyContent) : undefined;
1040
- const context = {
1041
- allowFile: mediaType === 'multipart/form-data',
1042
- references: {},
1043
- nextId () {
1044
- return String(currentId++);
1045
- },
1046
- registered: new WeakMap(),
1047
- render: ctx
1048
- };
1049
- const bodySchema = bodyContent && mediaType && bodyContent[mediaType].schema ? toSchema(bodyContent[mediaType].schema, true, context) : undefined;
1050
- const props = {
1051
- authorization: getAuthorizationField(method, ctx),
1052
- method: method.method,
1053
- route: path,
1054
- path: method.parameters?.filter((v)=>v.in === 'path').map((v)=>parameterToField(v, context)),
1055
- query: method.parameters?.filter((v)=>v.in === 'query').map((v)=>parameterToField(v, context)),
1056
- header: method.parameters?.filter((v)=>v.in === 'header').map((v)=>parameterToField(v, context)),
1057
- body: bodySchema && mediaType ? {
1058
- ...bodySchema,
1059
- mediaType: mediaType
1060
- } : undefined,
1061
- schemas: context.references,
1062
- proxyUrl: ctx.proxyUrl
1063
- };
1064
- return /*#__PURE__*/ jsx(APIPlayground, {
1065
- ...props
1066
- });
1067
- }
1068
- function getAuthorizationField(method, { schema: { document } }) {
1069
- const security = method.security ?? document.security ?? [];
1070
- if (security.length === 0) return;
1071
- const singular = security.find((requirements)=>Object.keys(requirements).length === 1);
1072
- if (!singular) return;
1073
- return getSecurities(singular, document)[0];
1074
- }
1075
- function getIdFromSchema(schema, required, ctx) {
1076
- const registered = ctx.registered.get(schema);
1077
- if (registered === undefined) {
1078
- const id = ctx.nextId();
1079
- ctx.registered.set(schema, id);
1080
- ctx.references[id] = toSchema(schema, required, ctx);
1081
- return id;
1082
- }
1083
- return registered;
1084
- }
1085
- function parameterToField(v, ctx) {
1086
- return {
1087
- name: v.name,
1088
- ...toSchema(v.schema ?? {
1089
- type: 'string'
1090
- }, v.required ?? false, ctx)
1091
- };
1092
- }
1093
- function toReference(schema, required, ctx) {
1094
- return {
1095
- type: 'ref',
1096
- isRequired: required,
1097
- schema: getIdFromSchema(schema, false, ctx)
1098
- };
1099
- }
1100
- function toSchema(schema, required, ctx) {
1101
- if (schema.type === 'array') {
1102
- return {
1103
- type: 'array',
1104
- description: schema.description ?? schema.title,
1105
- isRequired: required,
1106
- items: getIdFromSchema(schema.items, false, ctx)
1107
- };
1108
- }
1109
- if (schema.type === 'object' || schema.properties !== undefined || schema.allOf !== undefined) {
1110
- const properties = {};
1111
- Object.entries(schema.properties ?? {}).forEach(([key, prop])=>{
1112
- properties[key] = toReference(prop, schema.required?.includes(key) ?? false, ctx);
1113
- });
1114
- schema.allOf?.forEach((c)=>{
1115
- const field = toSchema(c, true, ctx);
1116
- if (field.type === 'object') Object.assign(properties, field.properties);
1117
- });
1118
- const additional = schema.additionalProperties;
1119
- let additionalProperties;
1120
- if (additional && typeof additional === 'object') {
1121
- if ((!additional.type || additional.type.length === 0) && !additional.anyOf && !additional.allOf && !additional.oneOf) {
1122
- additionalProperties = true;
1123
- } else {
1124
- additionalProperties = getIdFromSchema(additional, false, ctx);
1125
- }
1126
- } else {
1127
- additionalProperties = additional;
1128
- }
1129
- return {
1130
- type: 'object',
1131
- isRequired: required,
1132
- description: schema.description ?? schema.title,
1133
- properties,
1134
- additionalProperties
1135
- };
1136
- }
1137
- if (schema.type === undefined) {
1138
- const combine = schema.anyOf ?? schema.oneOf;
1139
- if (combine) {
1140
- return {
1141
- type: 'switcher',
1142
- description: schema.description ?? schema.title,
1143
- items: Object.fromEntries(combine.map((item, idx)=>{
1144
- return [
1145
- item.title ?? item.type ?? `Item ${idx.toString()}`,
1146
- toReference(item, true, ctx)
1147
- ];
1148
- })),
1149
- isRequired: required
1150
- };
1151
- }
1152
- return {
1153
- type: 'null',
1154
- isRequired: false
1155
- };
1156
- }
1157
- if (ctx.allowFile && schema.type === 'string' && schema.format === 'binary') {
1158
- return {
1159
- type: 'file',
1160
- isRequired: required,
1161
- description: schema.description ?? schema.title
1162
- };
1163
- }
1164
- if (Array.isArray(schema.type)) {
1165
- const items = {};
1166
- for (const type of schema.type){
1167
- if (type === 'array') {
1168
- items[type] = {
1169
- type,
1170
- items: 'items' in schema && schema.items ? toSchema(schema.items, false, ctx) : toSchema({}, required, ctx),
1171
- isRequired: required
1172
- };
1173
- } else {
1174
- items[type] = toSchema({
1175
- ...schema,
1176
- type
1177
- }, required, ctx);
1178
- }
1179
- }
1180
- return {
1181
- type: 'switcher',
1182
- description: schema.description ?? schema.title,
1183
- items,
1184
- isRequired: required
1185
- };
1186
- }
1187
- return {
1188
- type: schema.type === 'integer' ? 'number' : schema.type,
1189
- defaultValue: schema.example ?? '',
1190
- isRequired: required,
1191
- description: schema.description ?? schema.title
1192
- };
1193
- }
1194
-
1195
- function createRenders(shikiOptions) {
1196
- return {
1197
- Root: (props)=>/*#__PURE__*/ jsx(Root, {
1198
- shikiOptions: shikiOptions,
1199
- ...props,
1200
- children: props.children
1201
- }),
1202
- API,
1203
- APIInfo: ({ children, head })=>/*#__PURE__*/ jsxs(APIInfo, {
1204
- children: [
1205
- head,
1206
- children
1207
- ]
1208
- }),
1209
- APIExample: APIExample$1,
1210
- Responses: Tabs,
1211
- Response: Tab,
1212
- ResponseTypes: (props)=>/*#__PURE__*/ jsx(Accordions, {
1213
- type: "single",
1214
- className: "!-m-4 border-none pt-2",
1215
- defaultValue: "Response",
1216
- children: props.children
1217
- }),
1218
- ResponseType: (props)=>/*#__PURE__*/ jsx(Accordion, {
1219
- title: props.label,
1220
- children: /*#__PURE__*/ jsx(CodeBlock, {
1221
- code: props.code,
1222
- lang: props.lang,
1223
- options: shikiOptions
1224
- })
1225
- }),
1226
- Property,
1227
- ObjectCollapsible,
1228
- Requests: (props)=>/*#__PURE__*/ jsx(Tabs, {
1229
- groupId: "fumadocs_openapi_requests",
1230
- ...props
1231
- }),
1232
- Request: (props)=>/*#__PURE__*/ jsx(Tab, {
1233
- value: props.name,
1234
- children: /*#__PURE__*/ jsx(CodeBlock, {
1235
- lang: props.language,
1236
- code: props.code,
1237
- options: shikiOptions
1238
- })
1239
- }),
1240
- APIPlayground: Playground
1241
- };
1242
- }
1243
-
1244
- const cache = new Map();
1245
- /**
1246
- * process & reference input document to a Fumadocs OpenAPI compatible format
1247
- */ async function processDocument(document, disableCache = false) {
1248
- const cached = !disableCache && typeof document === 'string' ? cache.get(document) : null;
1249
- if (cached) return cached;
1250
- const dereferenceMap = new Map();
1251
- const loaded = await load(document, {
1252
- plugins: [
1253
- readFiles(),
1254
- fetchUrls()
1255
- ]
1256
- });
1257
- // upgrade
1258
- loaded.specification = upgrade(loaded.specification).specification;
1259
- const { schema: dereferenced } = await dereference(loaded.filesystem, {
1260
- onDereference ({ ref, schema }) {
1261
- dereferenceMap.set(schema, ref);
1262
- }
1263
- });
1264
- const processed = {
1265
- document: dereferenced,
1266
- dereferenceMap,
1267
- downloaded: loaded.specification
1268
- };
1269
- if (!disableCache && typeof document === 'string') {
1270
- cache.set(document, processed);
1271
- }
1272
- return processed;
1273
- }
1274
-
1275
- function getUrl(url, variables) {
1276
- let out = url;
1277
- for (const [key, value] of Object.entries(variables)){
1278
- out = out.replaceAll(`{${key}}`, value);
1279
- }
1280
- return out;
1281
- }
1282
-
1283
- async function APIPage(props) {
1284
- const { operations, hasHead = true, webhooks, disableCache = process.env.NODE_ENV === 'development' } = props;
1285
- const processed = await processDocument(props.document, disableCache);
1286
- const ctx = await getContext(processed, props);
1287
- const { document } = processed;
1288
- return /*#__PURE__*/ jsxs(ctx.renderer.Root, {
1289
- baseUrl: ctx.baseUrl,
1290
- servers: ctx.servers,
1291
- children: [
1292
- operations?.map((item)=>{
1293
- const pathItem = document.paths?.[item.path];
1294
- if (!pathItem) return null;
1295
- const operation = pathItem[item.method];
1296
- if (!operation) return null;
1297
- const method = createMethod(item.method, pathItem, operation);
1298
- return /*#__PURE__*/ jsx(Operation, {
1299
- method: method,
1300
- path: item.path,
1301
- ctx: ctx,
1302
- hasHead: hasHead
1303
- }, `${item.path}:${item.method}`);
1304
- }),
1305
- webhooks?.map((item)=>{
1306
- const webhook = document.webhooks?.[item.name];
1307
- if (!webhook) return;
1308
- const hook = webhook[item.method];
1309
- if (!hook) return;
1310
- const method = createMethod(item.method, webhook, hook);
1311
- return /*#__PURE__*/ jsx(Operation, {
1312
- type: "webhook",
1313
- method: method,
1314
- ctx: {
1315
- ...ctx,
1316
- baseUrl: 'http://localhost:8080'
1317
- },
1318
- path: `/${item.name}`,
1319
- hasHead: hasHead
1320
- }, `${item.name}:${item.method}`);
1321
- })
1322
- ]
1323
- });
1324
- }
1325
- async function getContext(schema, options = {}) {
1326
- const document = schema.document;
1327
- const servers = document.servers && document.servers.length > 0 ? document.servers : [
1328
- {
1329
- url: 'https://example.com'
1330
- }
1331
- ];
1332
- const server = servers[0];
1333
- return {
1334
- schema,
1335
- proxyUrl: options.proxyUrl,
1336
- showResponseSchema: options.showResponseSchema,
1337
- renderer: {
1338
- ...createRenders(options.shikiOptions),
1339
- ...options.renderer
1340
- },
1341
- shikiOptions: options.shikiOptions,
1342
- generateTypeScriptSchema: options.generateTypeScriptSchema,
1343
- generateCodeSamples: options.generateCodeSamples,
1344
- baseUrl: getUrl(server.url, server.variables ? Object.fromEntries(Object.entries(server.variables).map(([k, v])=>[
1345
- k,
1346
- v.default
1347
- ])) : {}),
1348
- servers,
1349
- slugger: new Slugger()
1350
- };
1351
- }
1352
-
1353
- const keys = [
1354
- 'GET',
1355
- 'POST',
1356
- 'PUT',
1357
- 'DELETE',
1358
- 'PATCH',
1359
- 'HEAD'
1360
- ];
1361
- function createProxy(allowedUrls) {
1362
- const handlers = {};
1363
- async function handler(req) {
1364
- const url = req.nextUrl.searchParams.get('url');
1365
- if (!url) {
1366
- return Response.json('A `url` query parameter is required for proxy url', {
1367
- status: 400
1368
- });
1369
- }
1370
- if (allowedUrls && allowedUrls.every((allowedUrl)=>!allowedUrl.startsWith(url))) {
1371
- return Response.json('The given `url` query parameter is not allowed', {
1372
- status: 400
1373
- });
1374
- }
1375
- const clonedReq = new Request(url, {
1376
- ...req,
1377
- cache: 'no-cache',
1378
- mode: 'cors'
1379
- });
1380
- clonedReq.headers.forEach((_value, originalKey)=>{
1381
- const key = originalKey.toLowerCase();
1382
- const notAllowed = key === 'origin';
1383
- if (notAllowed) {
1384
- clonedReq.headers.delete(originalKey);
1385
- }
1386
- });
1387
- const res = await fetch(clonedReq).catch((e)=>new Error(e.toString()));
1388
- if (res instanceof Error) {
1389
- return Response.json(`Failed to proxy request: ${res.message}`, {
1390
- status: 400
1391
- });
1392
- }
1393
- const headers = new Headers(res.headers);
1394
- headers.forEach((_value, originalKey)=>{
1395
- const key = originalKey.toLowerCase();
1396
- const notAllowed = key.startsWith('access-control-') || key === 'content-encoding';
1397
- if (notAllowed) {
1398
- headers.delete(originalKey);
1399
- }
1400
- });
1401
- headers.set('X-Forwarded-Host', res.url);
1402
- return new Response(res.body, {
1403
- ...res,
1404
- headers
1405
- });
1406
- }
1407
- for (const key of keys){
1408
- handlers[key] = handler;
1409
- }
1410
- return handlers;
1411
- }
1412
-
1413
- function createOpenAPI(options = {}) {
1414
- return {
1415
- createProxy,
1416
- APIPage (props) {
1417
- return /*#__PURE__*/ jsx(APIPage, {
1418
- ...options,
1419
- ...props
1420
- });
1421
- }
1422
- };
1423
- }
1424
-
1425
- cva('rounded-xl border px-1.5 py-1 text-xs font-medium leading-[12px]', {
1426
- variants: {
1427
- color: {
1428
- green: 'bg-green-400/20 text-green-600 dark:text-green-400',
1429
- yellow: 'bg-yellow-400/20 text-yellow-600 dark:text-yellow-400',
1430
- red: 'bg-red-400/20 text-red-600 dark:text-red-400',
1431
- blue: 'bg-blue-400/20 text-blue-600 dark:text-blue-400',
1432
- orange: 'bg-orange-400/20 text-orange-600 dark:text-orange-400'
1433
- }
1434
- }
1435
- });
1436
- function getBadgeColor(method) {
1437
- switch(method){
1438
- case 'PUT':
1439
- return 'yellow';
1440
- case 'PATCH':
1441
- return 'orange';
1442
- case 'POST':
1443
- return 'blue';
1444
- case 'DELETE':
1445
- return 'red';
1446
- default:
1447
- return 'green';
1448
- }
1449
- }
1450
-
1451
- /**
1452
- * Source API Integration
1453
- *
1454
- * Add this to page tree builder options
1455
- */ const attachFile = (node, file)=>{
1456
- if (!file) return node;
1457
- const data = file.data.data;
1458
- let method;
1459
- if ('_openapi' in data && typeof data._openapi === 'object') {
1460
- const meta = data._openapi;
1461
- method = meta.method;
1462
- }
1463
- if (method) {
1464
- const color = getBadgeColor(method);
1465
- node.name = /*#__PURE__*/ jsxs(Fragment, {
1466
- children: [
1467
- node.name,
1468
- ' ',
1469
- /*#__PURE__*/ jsx("span", {
1470
- className: badgeVariants({
1471
- className: 'ms-auto text-nowrap',
1472
- color
1473
- }),
1474
- children: method
1475
- })
1476
- ]
1477
- });
1478
- }
1479
- return node;
1480
- };
1481
- const badgeVariants = cva('rounded-full border px-1.5 text-xs font-medium', {
1482
- variants: {
1483
- color: {
1484
- green: 'bg-green-400/20 text-green-600 dark:text-green-400',
1485
- yellow: 'bg-yellow-400/20 text-yellow-600 dark:text-yellow-400',
1486
- red: 'bg-red-400/20 text-red-600 dark:text-red-400',
1487
- blue: 'bg-blue-400/20 text-blue-600 dark:text-blue-400',
1488
- orange: 'bg-orange-400/20 text-orange-600 dark:text-orange-400'
1489
- }
1490
- }
1491
- });
1492
-
1493
- export { attachFile, createOpenAPI };
1
+ export * from './create.js';
2
+ export * from './source-api.js';