fumadocs-openapi 4.4.2 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +113 -36
- package/dist/index.js +252 -1030
- package/dist/server/index.d.ts +211 -0
- package/dist/server/index.js +1094 -0
- package/dist/ui/client-client-CMzXLiVt.js +93 -0
- package/dist/ui/index.d.ts +87 -43
- package/dist/ui/index.js +126 -185
- package/dist/ui/playground-client-Cn3a3hra.js +1033 -0
- package/package.json +15 -10
- package/dist/chunk-N4P4W4VJ.js +0 -61
- package/dist/chunk-UG2WFM5D.js +0 -70
- package/dist/playground-GIGTWHCL.js +0 -1065
- package/dist/playground-vSsfCaVw.d.ts +0 -56
- package/dist/source/index.d.ts +0 -10
- package/dist/source/index.js +0 -39
|
@@ -0,0 +1,1094 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
2
|
+
import Parser from '@apidevtools/json-schema-ref-parser';
|
|
3
|
+
import Slugger from 'github-slugger';
|
|
4
|
+
import { createElement, Fragment, useMemo } from 'react';
|
|
5
|
+
import { sample } from 'openapi-sampler';
|
|
6
|
+
import { compile } from 'json-schema-to-typescript';
|
|
7
|
+
import { createProcessor } from '@mdx-js/mdx';
|
|
8
|
+
import { remarkGfm, rehypeCode } from 'fumadocs-core/mdx-plugins';
|
|
9
|
+
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
|
10
|
+
import { Heading } from 'fumadocs-ui/components/heading';
|
|
11
|
+
import { Tabs, Tab } from 'fumadocs-ui/components/tabs';
|
|
12
|
+
import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
|
|
13
|
+
import * as Base from 'fumadocs-ui/components/codeblock';
|
|
14
|
+
import { createHighlighter, bundledThemes, bundledLanguages } from 'shiki';
|
|
15
|
+
import { Root, API, APIInfo, APIExample as APIExample$1, Property, ObjectCollapsible, APIPlayground } from '../ui/index.js';
|
|
16
|
+
import { cva } from 'class-variance-authority';
|
|
17
|
+
|
|
18
|
+
function noRef(v) {
|
|
19
|
+
return v;
|
|
20
|
+
}
|
|
21
|
+
function getPreferredType(body) {
|
|
22
|
+
if ('application/json' in body) return 'application/json';
|
|
23
|
+
return Object.keys(body)[0];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Convert to JSON string if necessary
|
|
27
|
+
*/ function toSampleInput(value) {
|
|
28
|
+
return typeof value === 'string' ? value : JSON.stringify(value, null, 2);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function generateSample(path, method, baseUrl) {
|
|
32
|
+
const params = [];
|
|
33
|
+
const responses = {};
|
|
34
|
+
for (const param of method.parameters){
|
|
35
|
+
if (param.schema) {
|
|
36
|
+
params.push({
|
|
37
|
+
name: param.name,
|
|
38
|
+
in: param.in,
|
|
39
|
+
schema: noRef(param.schema),
|
|
40
|
+
sample: param.example ?? sample(param.schema)
|
|
41
|
+
});
|
|
42
|
+
} else if (param.content) {
|
|
43
|
+
const key = getPreferredType(param.content);
|
|
44
|
+
const content = key ? param.content[key] : undefined;
|
|
45
|
+
if (!key || !content?.schema) throw new Error(`Cannot find parameter schema for ${param.name} in ${path} ${method.method}`);
|
|
46
|
+
params.push({
|
|
47
|
+
name: param.name,
|
|
48
|
+
in: param.in,
|
|
49
|
+
schema: noRef(content.schema),
|
|
50
|
+
sample: content.example ?? param.example ?? sample(content.schema)
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
let bodyOutput;
|
|
55
|
+
if (method.requestBody) {
|
|
56
|
+
const body = noRef(method.requestBody).content;
|
|
57
|
+
const type = getPreferredType(body);
|
|
58
|
+
const schema = type ? noRef(body[type].schema) : undefined;
|
|
59
|
+
if (!type || !schema) throw new Error(`Cannot find body schema for ${path} ${method.method}`);
|
|
60
|
+
bodyOutput = {
|
|
61
|
+
schema,
|
|
62
|
+
mediaType: type,
|
|
63
|
+
sample: body[type].example ?? generateBody(method.method, schema)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
for (const [code, value] of Object.entries(method.responses)){
|
|
67
|
+
const content = noRef(value).content;
|
|
68
|
+
if (!content) continue;
|
|
69
|
+
const mediaType = getPreferredType(content);
|
|
70
|
+
if (!mediaType) continue;
|
|
71
|
+
const responseSchema = noRef(content[mediaType].schema);
|
|
72
|
+
if (!responseSchema) continue;
|
|
73
|
+
responses[code] = {
|
|
74
|
+
mediaType,
|
|
75
|
+
sample: content[mediaType].example ?? generateBody(method.method, responseSchema),
|
|
76
|
+
schema: responseSchema
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
let pathWithParameters = path;
|
|
80
|
+
const queryParams = new URLSearchParams();
|
|
81
|
+
for (const param of params){
|
|
82
|
+
const value = generateBody(method.method, param.schema);
|
|
83
|
+
if (param.in === 'query') queryParams.append(param.name, toSampleInput(value));
|
|
84
|
+
if (param.in === 'path') pathWithParameters = pathWithParameters.replace(`{${param.name}}`, toSampleInput(value));
|
|
85
|
+
}
|
|
86
|
+
if (queryParams.size > 0) pathWithParameters = `${pathWithParameters}?${queryParams.toString()}`;
|
|
87
|
+
return {
|
|
88
|
+
url: new URL(`${baseUrl}${pathWithParameters}`).toString(),
|
|
89
|
+
body: bodyOutput,
|
|
90
|
+
responses,
|
|
91
|
+
method: method.method,
|
|
92
|
+
parameters: params
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function generateBody(method, schema) {
|
|
96
|
+
return sample(schema, {
|
|
97
|
+
skipReadOnly: method !== 'GET',
|
|
98
|
+
skipWriteOnly: method === 'GET'
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function getSampleRequest$2(endpoint) {
|
|
103
|
+
const s = [];
|
|
104
|
+
s.push(`curl -X ${endpoint.method} "${endpoint.url}"`);
|
|
105
|
+
for (const param of endpoint.parameters){
|
|
106
|
+
if (param.in === 'header') {
|
|
107
|
+
const header = `${param.name}: ${toSampleInput(param.sample)}`;
|
|
108
|
+
s.push(`-H "${header}"`);
|
|
109
|
+
}
|
|
110
|
+
if (param.in === 'cookie') {
|
|
111
|
+
const cookie = JSON.stringify(`${param.name}=${toSampleInput(param.sample)}`);
|
|
112
|
+
s.push(`--cookie ${cookie}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (endpoint.body?.mediaType === 'multipart/form-data') {
|
|
116
|
+
const sample = endpoint.body.sample;
|
|
117
|
+
if (sample && typeof sample === 'object') {
|
|
118
|
+
for (const [key, value] of Object.entries(sample)){
|
|
119
|
+
s.push(`-F ${key}=${JSON.stringify(value, null, 2)}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
} else if (endpoint.body) {
|
|
123
|
+
s.push(`-H "Content-Type: application/json"`);
|
|
124
|
+
s.push(`-d '${toSampleInput(endpoint.body.sample)}'`);
|
|
125
|
+
}
|
|
126
|
+
return s.flatMap((v, i)=>v.split('\n').map((line)=>i > 0 ? ` ${line}` : line).join('\n')).join(' \\\n');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function getSampleRequest$1(endpoint) {
|
|
130
|
+
const s = [];
|
|
131
|
+
const options = new Map();
|
|
132
|
+
const headers = new Map();
|
|
133
|
+
const cookies = new Map();
|
|
134
|
+
for (const param of endpoint.parameters){
|
|
135
|
+
if (param.in === 'header') {
|
|
136
|
+
headers.set(param.name, param.sample);
|
|
137
|
+
}
|
|
138
|
+
if (param.in === 'cookie') {
|
|
139
|
+
cookies.set(param.name, param.sample);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (cookies.size > 0) {
|
|
143
|
+
headers.set('cookie', Array.from(cookies.entries()).map(([key, value])=>`${key}=${toSampleInput(value)}`).join('; '));
|
|
144
|
+
}
|
|
145
|
+
if (headers.size > 0) {
|
|
146
|
+
options.set('headers', JSON.stringify(Object.fromEntries(headers.entries()), undefined, 2).replaceAll('\n', '\n '));
|
|
147
|
+
}
|
|
148
|
+
if (endpoint.body?.mediaType === 'multipart/form-data' && typeof endpoint.body.sample === 'object' && endpoint.body.sample) {
|
|
149
|
+
s.push(`const formData = new FormData();`);
|
|
150
|
+
for (const [key, value] of Object.entries(endpoint.body.sample))s.push(`formData.set(${key}, ${JSON.stringify(value)})`);
|
|
151
|
+
options.set('body', 'formData');
|
|
152
|
+
} else if (endpoint.body) {
|
|
153
|
+
options.set('body', `JSON.stringify(${JSON.stringify(endpoint.body.sample, null, 2).replaceAll('\n', '\n ')})`);
|
|
154
|
+
}
|
|
155
|
+
const optionsStr = Array.from(options.entries()).map(([k, v])=>` ${k}: ${v}`).join(',\n');
|
|
156
|
+
s.push(`fetch(${JSON.stringify(endpoint.url)}, {\n${optionsStr}\n});`);
|
|
157
|
+
return s.join('\n\n');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function getSampleRequest(endpoint) {
|
|
161
|
+
const imports = [
|
|
162
|
+
'fmt',
|
|
163
|
+
'net/http',
|
|
164
|
+
'io/ioutil'
|
|
165
|
+
];
|
|
166
|
+
const headers = new Map();
|
|
167
|
+
const cookies = new Map();
|
|
168
|
+
const variables = new Map();
|
|
169
|
+
// additional lines before initializing request
|
|
170
|
+
const additional = [];
|
|
171
|
+
for (const p of endpoint.parameters){
|
|
172
|
+
if (p.in === 'header') headers.set(p.name, JSON.stringify(p.sample));
|
|
173
|
+
if (p.in === 'cookie') cookies.set(p.name, toSampleInput(p.sample));
|
|
174
|
+
}
|
|
175
|
+
variables.set('url', JSON.stringify(endpoint.url));
|
|
176
|
+
if (cookies.size > 0) headers.set('Cookie', JSON.stringify(Array.from(cookies.entries()).map(([key, value])=>`${key}=${value}`).join('; ')));
|
|
177
|
+
if (endpoint.body) {
|
|
178
|
+
headers.set('Content-Type', `"${endpoint.body.mediaType}"`);
|
|
179
|
+
if (endpoint.body.mediaType === 'application/json') {
|
|
180
|
+
imports.push('strings');
|
|
181
|
+
variables.set('payload', `strings.NewReader(\`${JSON.stringify(endpoint.body.sample, null, 2).replaceAll('\n', '\n ')}\`)`);
|
|
182
|
+
}
|
|
183
|
+
if (endpoint.body.mediaType === 'multipart/form-data' && typeof endpoint.body.sample === 'object') {
|
|
184
|
+
imports.push('mime/multipart', 'bytes');
|
|
185
|
+
variables.set('payload', `new(bytes.Buffer)`);
|
|
186
|
+
variables.set('mp', 'multipart.NewWriter(payload)');
|
|
187
|
+
for (const [key, value] of Object.entries(endpoint.body.sample ?? {})){
|
|
188
|
+
additional.push(`mp.WriteField("${key}", ${JSON.stringify(toSampleInput(value))})`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return `package main
|
|
193
|
+
|
|
194
|
+
import (
|
|
195
|
+
${imports.map((v)=>` "${v}"`).join('\n')}
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
func main() {
|
|
199
|
+
${Array.from(variables.entries()).map(([k, v])=>` ${k} := ${v}`).join('\n')}
|
|
200
|
+
${additional.join('\n ')}
|
|
201
|
+
req, _ := http.NewRequest("${endpoint.method}", url, ${variables.has('payload') ? 'payload' : 'nil'})
|
|
202
|
+
${Array.from(headers.entries()).map(([key, value])=>`req.Header.Add("${key}", ${value})`).join('\n')}
|
|
203
|
+
res, _ := http.DefaultClient.Do(req)
|
|
204
|
+
defer res.Body.Close()
|
|
205
|
+
body, _ := ioutil.ReadAll(res.Body)
|
|
206
|
+
|
|
207
|
+
fmt.Println(res)
|
|
208
|
+
fmt.Println(string(body))
|
|
209
|
+
}`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async function getTypescriptSchema(endpoint, code) {
|
|
213
|
+
if (code in endpoint.responses) {
|
|
214
|
+
return compile(endpoint.responses[code].schema, 'Response', {
|
|
215
|
+
bannerComment: '',
|
|
216
|
+
additionalProperties: false,
|
|
217
|
+
format: true,
|
|
218
|
+
enableConstEnums: false
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function getScheme(requirement, document) {
|
|
224
|
+
const results = [];
|
|
225
|
+
const schemas = document.components?.securitySchemes ?? {};
|
|
226
|
+
for (const [key, scopes] of Object.entries(requirement)){
|
|
227
|
+
if (!(key in schemas)) return [];
|
|
228
|
+
const schema = noRef(schemas[key]);
|
|
229
|
+
results.push({
|
|
230
|
+
...schema,
|
|
231
|
+
scopes
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
return results;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function Playground({ path, method, ctx }) {
|
|
238
|
+
let currentId = 0;
|
|
239
|
+
const bodyContent = noRef(method.requestBody)?.content;
|
|
240
|
+
const mediaType = bodyContent ? getPreferredType(bodyContent) : undefined;
|
|
241
|
+
const context = {
|
|
242
|
+
allowFile: mediaType === 'multipart/form-data',
|
|
243
|
+
schema: {},
|
|
244
|
+
nextId () {
|
|
245
|
+
return String(currentId++);
|
|
246
|
+
},
|
|
247
|
+
registered: new WeakMap()
|
|
248
|
+
};
|
|
249
|
+
const props = {
|
|
250
|
+
authorization: getAuthorizationField(method, ctx),
|
|
251
|
+
method: method.method,
|
|
252
|
+
route: path,
|
|
253
|
+
bodyType: mediaType === 'multipart/form-data' ? 'form-data' : 'json',
|
|
254
|
+
path: method.parameters.filter((v)=>v.in === 'path').map((v)=>parameterToField(v, context)),
|
|
255
|
+
query: method.parameters.filter((v)=>v.in === 'query').map((v)=>parameterToField(v, context)),
|
|
256
|
+
header: method.parameters.filter((v)=>v.in === 'header').map((v)=>parameterToField(v, context)),
|
|
257
|
+
body: bodyContent && mediaType && bodyContent[mediaType].schema ? toSchema(noRef(bodyContent[mediaType].schema), true, context) : undefined,
|
|
258
|
+
schemas: context.schema
|
|
259
|
+
};
|
|
260
|
+
return /*#__PURE__*/ jsx(ctx.renderer.APIPlayground, {
|
|
261
|
+
...props
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
function getAuthorizationField(method, ctx) {
|
|
265
|
+
const security = method.security ?? ctx.document.security ?? [];
|
|
266
|
+
if (security.length === 0) return;
|
|
267
|
+
const singular = security.find((requirements)=>Object.keys(requirements).length === 1);
|
|
268
|
+
if (!singular) return;
|
|
269
|
+
const scheme = getScheme(singular, ctx.document)[0];
|
|
270
|
+
return {
|
|
271
|
+
type: 'string',
|
|
272
|
+
name: 'Authorization',
|
|
273
|
+
defaultValue: scheme.type === 'oauth2' || scheme.type === 'http' && scheme.scheme === 'bearer' ? 'Bearer' : 'Basic',
|
|
274
|
+
isRequired: security.every((requirements)=>Object.keys(requirements).length > 0),
|
|
275
|
+
description: 'The Authorization access token'
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function getIdFromSchema(schema, required, ctx) {
|
|
279
|
+
const registered = ctx.registered.get(schema);
|
|
280
|
+
if (registered === undefined) {
|
|
281
|
+
const id = ctx.nextId();
|
|
282
|
+
ctx.registered.set(schema, id);
|
|
283
|
+
ctx.schema[id] = toSchema(schema, required, ctx);
|
|
284
|
+
return id;
|
|
285
|
+
}
|
|
286
|
+
return registered;
|
|
287
|
+
}
|
|
288
|
+
function parameterToField(v, ctx) {
|
|
289
|
+
return {
|
|
290
|
+
name: v.name,
|
|
291
|
+
...toSchema(noRef(v.schema) ?? {
|
|
292
|
+
type: 'string'
|
|
293
|
+
}, v.required ?? false, ctx)
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
function toReference(schema, required, ctx) {
|
|
297
|
+
return {
|
|
298
|
+
type: 'ref',
|
|
299
|
+
isRequired: required,
|
|
300
|
+
schema: getIdFromSchema(schema, false, ctx)
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function toSchema(schema, required, ctx) {
|
|
304
|
+
if (schema.type === 'array') {
|
|
305
|
+
return {
|
|
306
|
+
type: 'array',
|
|
307
|
+
description: schema.description ?? schema.title,
|
|
308
|
+
isRequired: required,
|
|
309
|
+
items: getIdFromSchema(noRef(schema.items), false, ctx)
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
if (schema.type === 'object' || schema.properties !== undefined || schema.allOf !== undefined) {
|
|
313
|
+
const properties = {};
|
|
314
|
+
Object.entries(schema.properties ?? {}).forEach(([key, prop])=>{
|
|
315
|
+
properties[key] = toReference(noRef(prop), schema.required?.includes(key) ?? false, ctx);
|
|
316
|
+
});
|
|
317
|
+
schema.allOf?.forEach((c)=>{
|
|
318
|
+
const field = toSchema(noRef(c), true, ctx);
|
|
319
|
+
if (field.type === 'object') Object.assign(properties, field.properties);
|
|
320
|
+
});
|
|
321
|
+
const additional = noRef(schema.additionalProperties);
|
|
322
|
+
let additionalProperties;
|
|
323
|
+
if (additional && typeof additional === 'object') {
|
|
324
|
+
if (!additional.type && !additional.anyOf && !additional.allOf && !additional.oneOf) {
|
|
325
|
+
additionalProperties = true;
|
|
326
|
+
} else {
|
|
327
|
+
additionalProperties = getIdFromSchema(additional, false, ctx);
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
additionalProperties = additional;
|
|
331
|
+
}
|
|
332
|
+
return {
|
|
333
|
+
type: 'object',
|
|
334
|
+
isRequired: required,
|
|
335
|
+
description: schema.description ?? schema.title,
|
|
336
|
+
properties,
|
|
337
|
+
additionalProperties
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
if (schema.type === undefined) {
|
|
341
|
+
const combine = schema.anyOf ?? schema.oneOf;
|
|
342
|
+
if (combine) {
|
|
343
|
+
return {
|
|
344
|
+
type: 'switcher',
|
|
345
|
+
description: schema.description ?? schema.title,
|
|
346
|
+
items: Object.fromEntries(combine.map((c, idx)=>{
|
|
347
|
+
const item = noRef(c);
|
|
348
|
+
return [
|
|
349
|
+
item.title ?? item.type ?? `Item ${idx.toString()}`,
|
|
350
|
+
toReference(item, true, ctx)
|
|
351
|
+
];
|
|
352
|
+
})),
|
|
353
|
+
isRequired: required
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
type: 'null',
|
|
358
|
+
isRequired: false
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
if (ctx.allowFile && schema.type === 'string' && schema.format === 'binary') {
|
|
362
|
+
return {
|
|
363
|
+
type: 'file',
|
|
364
|
+
isRequired: required,
|
|
365
|
+
description: schema.description ?? schema.title
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
type: schema.type === 'integer' ? 'number' : schema.type,
|
|
370
|
+
defaultValue: schema.example ?? '',
|
|
371
|
+
isRequired: required,
|
|
372
|
+
description: schema.description ?? schema.title
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function idToTitle(id) {
|
|
377
|
+
let result = [];
|
|
378
|
+
for (const c of id){
|
|
379
|
+
if (result.length === 0) result.push(c.toLocaleUpperCase());
|
|
380
|
+
else if (c === '.') result = [];
|
|
381
|
+
else if (/^[A-Z]$/.test(c) && result.at(-1) !== ' ') result.push(' ', c);
|
|
382
|
+
else if (c === '-') result.push(' ');
|
|
383
|
+
else result.push(c);
|
|
384
|
+
}
|
|
385
|
+
return result.join('');
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const processor = createProcessor({
|
|
389
|
+
remarkPlugins: [
|
|
390
|
+
remarkGfm
|
|
391
|
+
],
|
|
392
|
+
rehypePlugins: [
|
|
393
|
+
rehypeCode
|
|
394
|
+
],
|
|
395
|
+
outputFormat: 'function-body',
|
|
396
|
+
development: process.env.NODE_ENV === 'development'
|
|
397
|
+
});
|
|
398
|
+
async function Markdown({ text }) {
|
|
399
|
+
const result = await processor.process({
|
|
400
|
+
value: text
|
|
401
|
+
});
|
|
402
|
+
const jsxRuntime = process.env.NODE_ENV === 'development' ? await import('react/jsx-dev-runtime') : await import('react/jsx-runtime');
|
|
403
|
+
const fullScope = {
|
|
404
|
+
opts: jsxRuntime
|
|
405
|
+
};
|
|
406
|
+
const keys = Object.keys(fullScope);
|
|
407
|
+
const values = Object.values(fullScope);
|
|
408
|
+
const hydrateFn = Reflect.construct(Function, keys.concat(String(result.value)));
|
|
409
|
+
const rendered = hydrateFn.apply(hydrateFn, values);
|
|
410
|
+
return /*#__PURE__*/ createElement(rendered.default, {
|
|
411
|
+
components: defaultMdxComponents
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function heading(depth, child, ctx) {
|
|
416
|
+
const id = ctx.slugger.slug(child);
|
|
417
|
+
return /*#__PURE__*/ jsx(Heading, {
|
|
418
|
+
id: id,
|
|
419
|
+
as: `h${depth.toString()}`,
|
|
420
|
+
children: child.trim()
|
|
421
|
+
}, id);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const keys = {
|
|
425
|
+
example: 'Example',
|
|
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
|
+
const child = [];
|
|
443
|
+
function field(key, value) {
|
|
444
|
+
child.push(/*#__PURE__*/ jsxs("span", {
|
|
445
|
+
children: [
|
|
446
|
+
key,
|
|
447
|
+
": ",
|
|
448
|
+
/*#__PURE__*/ jsx("code", {
|
|
449
|
+
children: value
|
|
450
|
+
})
|
|
451
|
+
]
|
|
452
|
+
}, key));
|
|
453
|
+
}
|
|
454
|
+
// object type
|
|
455
|
+
if (isObject(schema) && parseObject) {
|
|
456
|
+
const { additionalProperties, properties } = schema;
|
|
457
|
+
if (additionalProperties === true) {
|
|
458
|
+
child.push(/*#__PURE__*/ jsx(renderer.Property, {
|
|
459
|
+
name: "[key: string]",
|
|
460
|
+
type: "any"
|
|
461
|
+
}, "additionalProperties"));
|
|
462
|
+
} else if (additionalProperties) {
|
|
463
|
+
child.push(/*#__PURE__*/ jsx(Schema, {
|
|
464
|
+
name: "[key: string]",
|
|
465
|
+
schema: noRef(additionalProperties),
|
|
466
|
+
ctx: {
|
|
467
|
+
...ctx,
|
|
468
|
+
required: false,
|
|
469
|
+
parseObject: false
|
|
470
|
+
}
|
|
471
|
+
}, "additionalProperties"));
|
|
472
|
+
}
|
|
473
|
+
if (properties) {
|
|
474
|
+
const rendered = Object.entries(properties).map(([key, value])=>{
|
|
475
|
+
return /*#__PURE__*/ jsx(Schema, {
|
|
476
|
+
name: key,
|
|
477
|
+
schema: noRef(value),
|
|
478
|
+
ctx: {
|
|
479
|
+
...ctx,
|
|
480
|
+
required: schema.required?.includes(key) ?? false,
|
|
481
|
+
parseObject: false
|
|
482
|
+
}
|
|
483
|
+
}, key);
|
|
484
|
+
});
|
|
485
|
+
child.push(...rendered);
|
|
486
|
+
}
|
|
487
|
+
return child;
|
|
488
|
+
}
|
|
489
|
+
if (schema.description) child.push(/*#__PURE__*/ jsx(Markdown, {
|
|
490
|
+
text: schema.description
|
|
491
|
+
}, "description"));
|
|
492
|
+
for (const [key, value] of Object.entries(keys)){
|
|
493
|
+
if (key in schema) {
|
|
494
|
+
field(value, JSON.stringify(schema[key]));
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
// enum types
|
|
498
|
+
if (schema.enum) {
|
|
499
|
+
field('Value in', schema.enum.map((value)=>JSON.stringify(value)).join(' | '));
|
|
500
|
+
}
|
|
501
|
+
if (isObject(schema) && !parseObject) {
|
|
502
|
+
child.push(/*#__PURE__*/ jsx(renderer.ObjectCollapsible, {
|
|
503
|
+
name: "Attributes",
|
|
504
|
+
children: /*#__PURE__*/ jsx(Schema, {
|
|
505
|
+
name: name,
|
|
506
|
+
schema: schema,
|
|
507
|
+
ctx: {
|
|
508
|
+
...ctx,
|
|
509
|
+
parseObject: true,
|
|
510
|
+
required: false
|
|
511
|
+
}
|
|
512
|
+
})
|
|
513
|
+
}, "attributes"));
|
|
514
|
+
} else if (schema.allOf) {
|
|
515
|
+
child.push(/*#__PURE__*/ jsx(renderer.ObjectCollapsible, {
|
|
516
|
+
name: name,
|
|
517
|
+
children: /*#__PURE__*/ jsx(Schema, {
|
|
518
|
+
name: name,
|
|
519
|
+
schema: combineSchema(schema.allOf.map(noRef)),
|
|
520
|
+
ctx: {
|
|
521
|
+
...ctx,
|
|
522
|
+
parseObject: true,
|
|
523
|
+
required: false
|
|
524
|
+
}
|
|
525
|
+
})
|
|
526
|
+
}, "attributes"));
|
|
527
|
+
} else {
|
|
528
|
+
const mentionedObjectTypes = [
|
|
529
|
+
...schema.anyOf ?? schema.oneOf ?? [],
|
|
530
|
+
...schema.not ? [
|
|
531
|
+
schema.not
|
|
532
|
+
] : [],
|
|
533
|
+
...schema.type === 'array' ? [
|
|
534
|
+
schema.items
|
|
535
|
+
] : []
|
|
536
|
+
].map(noRef).filter((s)=>isComplexType(s) && !stack.includes(s));
|
|
537
|
+
const renderedMentionedTypes = mentionedObjectTypes.map((s, idx)=>{
|
|
538
|
+
return /*#__PURE__*/ jsx(renderer.ObjectCollapsible, {
|
|
539
|
+
name: s.title ?? `Object ${(idx + 1).toString()}`,
|
|
540
|
+
children: /*#__PURE__*/ jsx(Schema, {
|
|
541
|
+
name: "element",
|
|
542
|
+
schema: noRef(s),
|
|
543
|
+
ctx: {
|
|
544
|
+
...ctx,
|
|
545
|
+
stack: [
|
|
546
|
+
schema,
|
|
547
|
+
...stack
|
|
548
|
+
],
|
|
549
|
+
parseObject: true,
|
|
550
|
+
required: false
|
|
551
|
+
}
|
|
552
|
+
})
|
|
553
|
+
}, `mentioned:${idx.toString()}`);
|
|
554
|
+
});
|
|
555
|
+
child.push(...renderedMentionedTypes);
|
|
556
|
+
}
|
|
557
|
+
return /*#__PURE__*/ jsx(renderer.Property, {
|
|
558
|
+
name: name,
|
|
559
|
+
type: getSchemaType(schema, ctx),
|
|
560
|
+
deprecated: schema.deprecated,
|
|
561
|
+
children: child
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Combine multiple object schemas into one
|
|
566
|
+
*/ function combineSchema(schema) {
|
|
567
|
+
const result = {
|
|
568
|
+
type: 'object'
|
|
569
|
+
};
|
|
570
|
+
function add(s) {
|
|
571
|
+
var _result, _result1;
|
|
572
|
+
(_result = result).properties ?? (_result.properties = {});
|
|
573
|
+
if (s.properties) {
|
|
574
|
+
Object.assign(result.properties, s.properties);
|
|
575
|
+
}
|
|
576
|
+
(_result1 = result).additionalProperties ?? (_result1.additionalProperties = {});
|
|
577
|
+
if (s.additionalProperties === true) {
|
|
578
|
+
result.additionalProperties = true;
|
|
579
|
+
} else if (s.additionalProperties && typeof result.additionalProperties !== 'boolean') {
|
|
580
|
+
Object.assign(result.additionalProperties, s.additionalProperties);
|
|
581
|
+
}
|
|
582
|
+
if (s.allOf) {
|
|
583
|
+
add(combineSchema(s.allOf.map(noRef)));
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
schema.forEach(add);
|
|
587
|
+
return result;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Check if the schema needs another collapsible to explain
|
|
591
|
+
*/ function isComplexType(schema) {
|
|
592
|
+
if (schema.anyOf ?? schema.oneOf ?? schema.allOf) return true;
|
|
593
|
+
return isObject(schema) || schema.type === 'array';
|
|
594
|
+
}
|
|
595
|
+
function getSchemaType(schema, ctx) {
|
|
596
|
+
if (schema.nullable) {
|
|
597
|
+
const type = getSchemaType({
|
|
598
|
+
...schema,
|
|
599
|
+
nullable: false
|
|
600
|
+
}, ctx);
|
|
601
|
+
// null if schema only contains `nullable`
|
|
602
|
+
return type === 'unknown' ? 'null' : `${type} | null`;
|
|
603
|
+
}
|
|
604
|
+
if (schema.title) return schema.title;
|
|
605
|
+
if (schema.type === 'array') return `array<${getSchemaType(noRef(schema.items), ctx)}>`;
|
|
606
|
+
if (schema.oneOf) return schema.oneOf.map((one)=>getSchemaType(noRef(one), ctx)).join(' | ');
|
|
607
|
+
if (schema.allOf) return schema.allOf.map((one)=>getSchemaType(noRef(one), ctx)).join(' & ');
|
|
608
|
+
if (schema.not) return `not ${getSchemaType(noRef(schema.not), ctx)}`;
|
|
609
|
+
if (schema.anyOf) {
|
|
610
|
+
return `Any properties in ${schema.anyOf.map((one)=>getSchemaType(noRef(one), ctx)).join(', ')}`;
|
|
611
|
+
}
|
|
612
|
+
if (schema.type === 'string' && schema.format === 'binary' && ctx.allowFile) return 'file';
|
|
613
|
+
if (schema.type) return schema.type;
|
|
614
|
+
if (isObject(schema)) return 'object';
|
|
615
|
+
return 'unknown';
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function Operation({ path, method, ctx, hasHead }) {
|
|
619
|
+
let level = 2;
|
|
620
|
+
const body = noRef(method.requestBody);
|
|
621
|
+
const security = method.security ?? ctx.document.security;
|
|
622
|
+
const info = [];
|
|
623
|
+
if (hasHead) {
|
|
624
|
+
info.push(heading(level, method.summary ?? (method.operationId ? idToTitle(method.operationId) : path), ctx));
|
|
625
|
+
level++;
|
|
626
|
+
if (method.description) {
|
|
627
|
+
info.push(/*#__PURE__*/ jsx(Markdown, {
|
|
628
|
+
text: method.description
|
|
629
|
+
}, "description"));
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
info.push(/*#__PURE__*/ jsx(Playground, {
|
|
633
|
+
path: path,
|
|
634
|
+
method: method,
|
|
635
|
+
ctx: ctx
|
|
636
|
+
}, "playground"));
|
|
637
|
+
if (security) {
|
|
638
|
+
info.push(heading(level, 'Authorization', ctx));
|
|
639
|
+
info.push(/*#__PURE__*/ jsx(AuthSection, {
|
|
640
|
+
requirements: security,
|
|
641
|
+
ctx: ctx
|
|
642
|
+
}, "auth"));
|
|
643
|
+
}
|
|
644
|
+
if (body) {
|
|
645
|
+
const type = getPreferredType(body.content);
|
|
646
|
+
if (!type) throw new Error(`No supported media type for body content: ${path}`);
|
|
647
|
+
info.push(/*#__PURE__*/ jsxs(Fragment, {
|
|
648
|
+
children: [
|
|
649
|
+
heading(level, 'Request Body', ctx),
|
|
650
|
+
/*#__PURE__*/ jsxs("div", {
|
|
651
|
+
className: "mb-8 flex flex-row items-center justify-between gap-2",
|
|
652
|
+
children: [
|
|
653
|
+
/*#__PURE__*/ jsx("code", {
|
|
654
|
+
children: type
|
|
655
|
+
}),
|
|
656
|
+
/*#__PURE__*/ jsx("span", {
|
|
657
|
+
children: body.required ? 'Required' : 'Optional'
|
|
658
|
+
})
|
|
659
|
+
]
|
|
660
|
+
}),
|
|
661
|
+
body.description ? /*#__PURE__*/ jsx(Markdown, {
|
|
662
|
+
text: body.description
|
|
663
|
+
}) : null,
|
|
664
|
+
/*#__PURE__*/ jsx(Schema, {
|
|
665
|
+
name: "body",
|
|
666
|
+
schema: noRef(body.content[type].schema ?? {}),
|
|
667
|
+
ctx: {
|
|
668
|
+
readOnly: method.method === 'GET',
|
|
669
|
+
writeOnly: method.method !== 'GET',
|
|
670
|
+
required: body.required ?? false,
|
|
671
|
+
render: ctx,
|
|
672
|
+
allowFile: type === 'multipart/form-data'
|
|
673
|
+
}
|
|
674
|
+
})
|
|
675
|
+
]
|
|
676
|
+
}, "body"));
|
|
677
|
+
}
|
|
678
|
+
const parameterGroups = new Map();
|
|
679
|
+
const endpoint = generateSample(path, method, ctx.baseUrl);
|
|
680
|
+
for (const param of method.parameters){
|
|
681
|
+
const pInfo = endpoint.parameters.find((item)=>item.name === param.name && item.in === param.in);
|
|
682
|
+
if (!pInfo) continue;
|
|
683
|
+
const schema = pInfo.schema;
|
|
684
|
+
const groupName = {
|
|
685
|
+
path: 'Path Parameters',
|
|
686
|
+
query: 'Query Parameters',
|
|
687
|
+
header: 'Header Parameters',
|
|
688
|
+
cookie: 'Cookie Parameters'
|
|
689
|
+
}[param.in] ?? 'Other Parameters';
|
|
690
|
+
const group = parameterGroups.get(groupName) ?? [];
|
|
691
|
+
group.push(/*#__PURE__*/ jsx(Schema, {
|
|
692
|
+
name: param.name,
|
|
693
|
+
schema: {
|
|
694
|
+
...schema,
|
|
695
|
+
description: param.description ?? schema.description,
|
|
696
|
+
deprecated: (param.deprecated ?? false) || (schema.deprecated ?? false)
|
|
697
|
+
},
|
|
698
|
+
ctx: {
|
|
699
|
+
parseObject: false,
|
|
700
|
+
readOnly: method.method === 'GET',
|
|
701
|
+
writeOnly: method.method !== 'GET',
|
|
702
|
+
required: param.required ?? false,
|
|
703
|
+
render: ctx
|
|
704
|
+
}
|
|
705
|
+
}, param.name));
|
|
706
|
+
parameterGroups.set(groupName, group);
|
|
707
|
+
}
|
|
708
|
+
for (const [group, parameters] of Array.from(parameterGroups.entries())){
|
|
709
|
+
info.push(heading(level, group, ctx), ...parameters);
|
|
710
|
+
}
|
|
711
|
+
return /*#__PURE__*/ jsxs(ctx.renderer.API, {
|
|
712
|
+
children: [
|
|
713
|
+
/*#__PURE__*/ jsx(ctx.renderer.APIInfo, {
|
|
714
|
+
method: method.method,
|
|
715
|
+
route: path,
|
|
716
|
+
children: info
|
|
717
|
+
}),
|
|
718
|
+
/*#__PURE__*/ jsx(APIExample, {
|
|
719
|
+
method: method,
|
|
720
|
+
endpoint: endpoint,
|
|
721
|
+
ctx: ctx
|
|
722
|
+
})
|
|
723
|
+
]
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
async function APIExample({ method, endpoint, ctx }) {
|
|
727
|
+
const renderer = ctx.renderer;
|
|
728
|
+
const children = [];
|
|
729
|
+
const samples = dedupe([
|
|
730
|
+
{
|
|
731
|
+
label: 'cURL',
|
|
732
|
+
source: getSampleRequest$2(endpoint),
|
|
733
|
+
lang: 'bash'
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
label: 'JavaScript',
|
|
737
|
+
source: getSampleRequest$1(endpoint),
|
|
738
|
+
lang: 'js'
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
label: 'Go',
|
|
742
|
+
source: getSampleRequest(endpoint),
|
|
743
|
+
lang: 'go'
|
|
744
|
+
},
|
|
745
|
+
...ctx.generateCodeSamples ? await ctx.generateCodeSamples(endpoint) : [],
|
|
746
|
+
...method['x-codeSamples'] ?? []
|
|
747
|
+
]);
|
|
748
|
+
children.push(/*#__PURE__*/ jsx(renderer.Requests, {
|
|
749
|
+
items: samples.map((s)=>s.label),
|
|
750
|
+
children: samples.map((s)=>/*#__PURE__*/ jsx(renderer.Request, {
|
|
751
|
+
name: s.label,
|
|
752
|
+
code: s.source,
|
|
753
|
+
language: s.lang
|
|
754
|
+
}, s.label))
|
|
755
|
+
}, "requests"));
|
|
756
|
+
children.push(/*#__PURE__*/ jsx(ResponseTabs, {
|
|
757
|
+
operation: method,
|
|
758
|
+
ctx: ctx,
|
|
759
|
+
endpoint: endpoint
|
|
760
|
+
}, "responses"));
|
|
761
|
+
return /*#__PURE__*/ jsx(renderer.APIExample, {
|
|
762
|
+
children: children
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Remove duplicated labels
|
|
767
|
+
*/ function dedupe(samples) {
|
|
768
|
+
const set = new Set();
|
|
769
|
+
const out = [];
|
|
770
|
+
for(let i = samples.length - 1; i >= 0; i--){
|
|
771
|
+
if (set.has(samples[i].label)) continue;
|
|
772
|
+
set.add(samples[i].label);
|
|
773
|
+
out.unshift(samples[i]);
|
|
774
|
+
}
|
|
775
|
+
return out;
|
|
776
|
+
}
|
|
777
|
+
function AuthSection({ ctx: { document, renderer }, requirements }) {
|
|
778
|
+
let id = 0;
|
|
779
|
+
const info = [];
|
|
780
|
+
for (const requirement of requirements){
|
|
781
|
+
if (info.length > 0) info.push(`---`);
|
|
782
|
+
for (const schema of getScheme(requirement, document)){
|
|
783
|
+
if (schema.type === 'http') {
|
|
784
|
+
info.push(/*#__PURE__*/ jsxs(renderer.Property, {
|
|
785
|
+
name: "Authorization",
|
|
786
|
+
type: {
|
|
787
|
+
basic: 'Basic <token>',
|
|
788
|
+
bearer: 'Bearer <token>'
|
|
789
|
+
}[schema.scheme] ?? '<token>',
|
|
790
|
+
required: true,
|
|
791
|
+
children: [
|
|
792
|
+
schema.description ? /*#__PURE__*/ jsx(Markdown, {
|
|
793
|
+
text: schema.description
|
|
794
|
+
}) : null,
|
|
795
|
+
/*#__PURE__*/ jsxs("p", {
|
|
796
|
+
children: [
|
|
797
|
+
"In: ",
|
|
798
|
+
/*#__PURE__*/ jsx("code", {
|
|
799
|
+
children: "header"
|
|
800
|
+
})
|
|
801
|
+
]
|
|
802
|
+
})
|
|
803
|
+
]
|
|
804
|
+
}, id++));
|
|
805
|
+
}
|
|
806
|
+
if (schema.type === 'oauth2') {
|
|
807
|
+
info.push(/*#__PURE__*/ jsxs(renderer.Property, {
|
|
808
|
+
name: "Authorization",
|
|
809
|
+
type: "Bearer <token>",
|
|
810
|
+
required: true,
|
|
811
|
+
children: [
|
|
812
|
+
schema.description ? /*#__PURE__*/ jsx(Markdown, {
|
|
813
|
+
text: schema.description
|
|
814
|
+
}) : null,
|
|
815
|
+
/*#__PURE__*/ jsxs("p", {
|
|
816
|
+
children: [
|
|
817
|
+
"In: ",
|
|
818
|
+
/*#__PURE__*/ jsx("code", {
|
|
819
|
+
children: "header"
|
|
820
|
+
})
|
|
821
|
+
]
|
|
822
|
+
}),
|
|
823
|
+
/*#__PURE__*/ jsxs("p", {
|
|
824
|
+
children: [
|
|
825
|
+
"Scope:",
|
|
826
|
+
' ',
|
|
827
|
+
/*#__PURE__*/ jsx("code", {
|
|
828
|
+
children: schema.scopes.length > 0 ? schema.scopes.join(', ') : 'none'
|
|
829
|
+
})
|
|
830
|
+
]
|
|
831
|
+
})
|
|
832
|
+
]
|
|
833
|
+
}, id++));
|
|
834
|
+
}
|
|
835
|
+
if (schema.type === 'apiKey') {
|
|
836
|
+
info.push(/*#__PURE__*/ jsxs(renderer.Property, {
|
|
837
|
+
name: schema.name,
|
|
838
|
+
type: "<token>",
|
|
839
|
+
children: [
|
|
840
|
+
schema.description ? /*#__PURE__*/ jsx(Markdown, {
|
|
841
|
+
text: schema.description
|
|
842
|
+
}) : null,
|
|
843
|
+
/*#__PURE__*/ jsxs("p", {
|
|
844
|
+
children: [
|
|
845
|
+
"In: ",
|
|
846
|
+
/*#__PURE__*/ jsx("code", {
|
|
847
|
+
children: schema.in
|
|
848
|
+
})
|
|
849
|
+
]
|
|
850
|
+
})
|
|
851
|
+
]
|
|
852
|
+
}, id++));
|
|
853
|
+
}
|
|
854
|
+
if (schema.type === 'openIdConnect') {
|
|
855
|
+
info.push(/*#__PURE__*/ jsx(renderer.Property, {
|
|
856
|
+
name: "OpenID Connect",
|
|
857
|
+
type: "<token>",
|
|
858
|
+
required: true,
|
|
859
|
+
children: schema.description ? /*#__PURE__*/ jsx(Markdown, {
|
|
860
|
+
text: schema.description
|
|
861
|
+
}) : null
|
|
862
|
+
}, id++));
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
return info;
|
|
867
|
+
}
|
|
868
|
+
async function ResponseTabs({ endpoint, operation, ctx: { renderer, generateTypeScriptSchema } }) {
|
|
869
|
+
const items = [];
|
|
870
|
+
const children = [];
|
|
871
|
+
for (const code of Object.keys(operation.responses)){
|
|
872
|
+
const types = [];
|
|
873
|
+
let description = noRef(operation.responses[code]).description;
|
|
874
|
+
if (!description && code in endpoint.responses) description = endpoint.responses[code].schema.description ?? '';
|
|
875
|
+
if (code in endpoint.responses) {
|
|
876
|
+
types.push({
|
|
877
|
+
lang: 'json',
|
|
878
|
+
label: 'Response',
|
|
879
|
+
code: JSON.stringify(endpoint.responses[code].sample, null, 2)
|
|
880
|
+
});
|
|
881
|
+
}
|
|
882
|
+
let ts;
|
|
883
|
+
if (generateTypeScriptSchema) {
|
|
884
|
+
ts = await generateTypeScriptSchema(endpoint, code);
|
|
885
|
+
} else if (generateTypeScriptSchema === undefined) {
|
|
886
|
+
ts = await getTypescriptSchema(endpoint, code);
|
|
887
|
+
}
|
|
888
|
+
if (ts) {
|
|
889
|
+
types.push({
|
|
890
|
+
code: ts,
|
|
891
|
+
lang: 'ts',
|
|
892
|
+
label: 'TypeScript'
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
items.push(code);
|
|
896
|
+
children.push(/*#__PURE__*/ jsxs(renderer.Response, {
|
|
897
|
+
value: code,
|
|
898
|
+
children: [
|
|
899
|
+
/*#__PURE__*/ jsx(Markdown, {
|
|
900
|
+
text: description
|
|
901
|
+
}),
|
|
902
|
+
types.length > 0 ? /*#__PURE__*/ jsx(renderer.ResponseTypes, {
|
|
903
|
+
children: types.map((type)=>/*#__PURE__*/ jsx(renderer.ResponseType, {
|
|
904
|
+
...type
|
|
905
|
+
}, type.lang))
|
|
906
|
+
}) : null
|
|
907
|
+
]
|
|
908
|
+
}, code));
|
|
909
|
+
}
|
|
910
|
+
if (items.length === 0) return null;
|
|
911
|
+
return /*#__PURE__*/ jsx(renderer.Responses, {
|
|
912
|
+
items: items,
|
|
913
|
+
children: children
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
function createMethod(method, operation) {
|
|
918
|
+
return {
|
|
919
|
+
...operation,
|
|
920
|
+
parameters: operation.parameters ?? [],
|
|
921
|
+
method: method.toUpperCase()
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
const highlighter = await createHighlighter({
|
|
926
|
+
themes: Object.values(bundledThemes),
|
|
927
|
+
langs: Object.values(bundledLanguages)
|
|
928
|
+
});
|
|
929
|
+
function CodeBlock({ code, lang, ...props }) {
|
|
930
|
+
const html = useMemo(()=>{
|
|
931
|
+
return highlighter.codeToHtml(code, {
|
|
932
|
+
lang,
|
|
933
|
+
defaultColor: false,
|
|
934
|
+
themes: {
|
|
935
|
+
light: 'github-light',
|
|
936
|
+
dark: 'github-dark'
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
}, [
|
|
940
|
+
code,
|
|
941
|
+
lang
|
|
942
|
+
]);
|
|
943
|
+
return /*#__PURE__*/ jsx(Base.CodeBlock, {
|
|
944
|
+
className: "my-0",
|
|
945
|
+
children: /*#__PURE__*/ jsx(Base.Pre, {
|
|
946
|
+
...props,
|
|
947
|
+
dangerouslySetInnerHTML: {
|
|
948
|
+
__html: html
|
|
949
|
+
}
|
|
950
|
+
})
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
const defaultRenderer = {
|
|
955
|
+
Root,
|
|
956
|
+
API,
|
|
957
|
+
APIInfo,
|
|
958
|
+
APIExample: APIExample$1,
|
|
959
|
+
Responses: Tabs,
|
|
960
|
+
Response: Tab,
|
|
961
|
+
ResponseTypes: (props)=>/*#__PURE__*/ jsx(Accordions, {
|
|
962
|
+
type: "single",
|
|
963
|
+
className: "!-m-4 border-none pt-2",
|
|
964
|
+
defaultValue: "Response",
|
|
965
|
+
children: props.children
|
|
966
|
+
}),
|
|
967
|
+
ResponseType: (props)=>/*#__PURE__*/ jsx(Accordion, {
|
|
968
|
+
title: props.label,
|
|
969
|
+
children: /*#__PURE__*/ jsx(CodeBlock, {
|
|
970
|
+
code: props.code,
|
|
971
|
+
lang: props.lang
|
|
972
|
+
})
|
|
973
|
+
}),
|
|
974
|
+
Property,
|
|
975
|
+
ObjectCollapsible,
|
|
976
|
+
Requests: Tabs,
|
|
977
|
+
Request: (props)=>/*#__PURE__*/ jsx(Tab, {
|
|
978
|
+
value: props.name,
|
|
979
|
+
children: /*#__PURE__*/ jsx(CodeBlock, {
|
|
980
|
+
lang: props.language,
|
|
981
|
+
code: props.code
|
|
982
|
+
})
|
|
983
|
+
}),
|
|
984
|
+
APIPlayground
|
|
985
|
+
};
|
|
986
|
+
|
|
987
|
+
function APIPage(props) {
|
|
988
|
+
const { operations, document, hasHead = true } = props;
|
|
989
|
+
const ctx = getContext(document, props);
|
|
990
|
+
return /*#__PURE__*/ jsx(ctx.renderer.Root, {
|
|
991
|
+
baseUrl: ctx.baseUrl,
|
|
992
|
+
children: operations.map((item)=>{
|
|
993
|
+
const operation = document.paths[item.path]?.[item.method];
|
|
994
|
+
if (!operation) return null;
|
|
995
|
+
const method = createMethod(item.method, operation);
|
|
996
|
+
return /*#__PURE__*/ jsx(Operation, {
|
|
997
|
+
method: method,
|
|
998
|
+
path: item.path,
|
|
999
|
+
ctx: ctx,
|
|
1000
|
+
hasHead: hasHead
|
|
1001
|
+
}, `${item.path}:${item.method}`);
|
|
1002
|
+
})
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
function getContext(document, options) {
|
|
1006
|
+
return {
|
|
1007
|
+
document,
|
|
1008
|
+
renderer: {
|
|
1009
|
+
...defaultRenderer,
|
|
1010
|
+
...options.renderer
|
|
1011
|
+
},
|
|
1012
|
+
generateTypeScriptSchema: options.generateTypeScriptSchema,
|
|
1013
|
+
generateCodeSamples: options.generateCodeSamples,
|
|
1014
|
+
baseUrl: document.servers?.[0].url ?? 'https://example.com',
|
|
1015
|
+
slugger: new Slugger()
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
function createOpenAPI(options) {
|
|
1020
|
+
const document = Parser.dereference(options.documentOrPath);
|
|
1021
|
+
return {
|
|
1022
|
+
APIPage: async (props)=>{
|
|
1023
|
+
return /*#__PURE__*/ jsx(APIPage, {
|
|
1024
|
+
document: await document,
|
|
1025
|
+
...props
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
cva('rounded border px-1.5 py-1 text-xs font-medium leading-[12px]', {
|
|
1032
|
+
variants: {
|
|
1033
|
+
color: {
|
|
1034
|
+
green: 'border-green-400/50 bg-green-400/20 text-green-600 dark:text-green-400',
|
|
1035
|
+
yellow: 'border-yellow-400/50 bg-yellow-400/20 text-yellow-600 dark:text-yellow-400',
|
|
1036
|
+
red: 'border-red-400/50 bg-red-400/20 text-red-600 dark:text-red-400',
|
|
1037
|
+
blue: 'border-blue-400/50 bg-blue-400/20 text-blue-600 dark:text-blue-400',
|
|
1038
|
+
orange: 'border-orange-400/50 bg-orange-400/20 text-orange-600 dark:text-orange-400'
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
});
|
|
1042
|
+
function getBadgeColor(method) {
|
|
1043
|
+
switch(method){
|
|
1044
|
+
case 'PUT':
|
|
1045
|
+
return 'yellow';
|
|
1046
|
+
case 'PATCH':
|
|
1047
|
+
return 'orange';
|
|
1048
|
+
case 'POST':
|
|
1049
|
+
return 'blue';
|
|
1050
|
+
case 'DELETE':
|
|
1051
|
+
return 'red';
|
|
1052
|
+
default:
|
|
1053
|
+
return 'green';
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
/**
|
|
1058
|
+
* Source API Integration
|
|
1059
|
+
*
|
|
1060
|
+
* Add this to page tree builder options
|
|
1061
|
+
*/ const attachFile = (node, file)=>{
|
|
1062
|
+
if (!file) return node;
|
|
1063
|
+
const data = file.data.data;
|
|
1064
|
+
if ('method' in data && typeof data.method === 'string') {
|
|
1065
|
+
const color = getBadgeColor(data.method);
|
|
1066
|
+
node.name = /*#__PURE__*/ jsxs(Fragment$1, {
|
|
1067
|
+
children: [
|
|
1068
|
+
node.name,
|
|
1069
|
+
' ',
|
|
1070
|
+
/*#__PURE__*/ jsx("span", {
|
|
1071
|
+
className: badgeVariants({
|
|
1072
|
+
className: 'ms-auto text-nowrap',
|
|
1073
|
+
color
|
|
1074
|
+
}),
|
|
1075
|
+
children: data.method
|
|
1076
|
+
})
|
|
1077
|
+
]
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
return node;
|
|
1081
|
+
};
|
|
1082
|
+
const badgeVariants = cva('rounded-full border px-1.5 text-xs font-medium', {
|
|
1083
|
+
variants: {
|
|
1084
|
+
color: {
|
|
1085
|
+
green: 'bg-green-400/20 text-green-600 dark:text-green-400',
|
|
1086
|
+
yellow: 'bg-yellow-400/20 text-yellow-600 dark:text-yellow-400',
|
|
1087
|
+
red: 'bg-red-400/20 text-red-600 dark:text-red-400',
|
|
1088
|
+
blue: 'bg-blue-400/20 text-blue-600 dark:text-blue-400',
|
|
1089
|
+
orange: 'bg-orange-400/20 text-orange-600 dark:text-orange-400'
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
|
|
1094
|
+
export { attachFile, createOpenAPI };
|