@xyd-js/openapi 0.1.0-xyd.11 → 0.1.0-xyd.13
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/CHANGELOG.md +16 -0
- package/__fixtures__/-2.complex.openai/input.yaml +39848 -0
- package/__fixtures__/-2.complex.openai/output.json +321646 -0
- package/__fixtures__/-2.complex.openai/pluginOasOpenai.ts +553 -0
- package/__fixtures__/1.basic/input.yaml +226 -0
- package/__fixtures__/1.basic/output.json +1919 -0
- package/__fixtures__/2.more/input.yaml +76 -0
- package/__fixtures__/2.more/output.json +292 -0
- package/__fixtures__/3.multiple-responses/input.yaml +48 -0
- package/__fixtures__/3.multiple-responses/output.json +266 -0
- package/__fixtures__/4.abc/input.yaml +639 -0
- package/__fixtures__/4.abc/output.json +3828 -0
- package/__fixtures__/5.xdocs.codeLanguages/input.yaml +231 -0
- package/__fixtures__/5.xdocs.codeLanguages/output.json +1879 -0
- package/__fixtures__/5.xdocs.sidebar/input.yaml +256 -0
- package/__fixtures__/5.xdocs.sidebar/output.json +843 -0
- package/__fixtures__/6.codeSamples/input.yaml +75 -0
- package/__fixtures__/6.codeSamples/output.json +293 -0
- package/__tests__/oapSchemaToReferences.test.ts +88 -0
- package/__tests__/utils.ts +81 -0
- package/dist/index.cjs +1859 -162
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -4
- package/dist/index.d.ts +36 -4
- package/dist/index.js +1855 -155
- package/dist/index.js.map +1 -1
- package/index.ts +10 -2
- package/package.json +11 -6
- package/src/const.ts +5 -1
- package/src/converters/oas-componentSchemas.ts +205 -0
- package/src/converters/oas-examples.ts +417 -0
- package/src/{parameters.ts → converters/oas-parameters.ts} +17 -3
- package/src/converters/oas-paths.ts +354 -0
- package/src/{requestBody.ts → converters/oas-requestBody.ts} +30 -10
- package/src/converters/oas-responses.ts +76 -0
- package/src/converters/oas-schema.ts +141 -0
- package/src/index.ts +13 -5
- package/src/oas-core.ts +579 -0
- package/src/types.ts +18 -0
- package/src/utils.ts +103 -90
- package/src/xdocs/index.ts +18 -0
- package/src/xdocs/pluginSidebar.ts +580 -0
- package/src/xdocs/types.ts +26 -0
- package/vitest.config.ts +7 -0
- package/src/examples.ts +0 -116
- package/src/paths.ts +0 -103
- package/src/properties.ts +0 -37
- package/src/responses.ts +0 -38
- package/src/schema.ts +0 -62
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
import {OpenAPIV3} from "openapi-types";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
CodeBlockTab,
|
|
5
|
+
Example,
|
|
6
|
+
ExampleGroup,
|
|
7
|
+
Reference,
|
|
8
|
+
UniformPluginArgs,
|
|
9
|
+
OpenAPIReferenceContext
|
|
10
|
+
} from "@xyd-js/uniform";
|
|
11
|
+
|
|
12
|
+
import {XDocs, XDocsSidebar, XDocsPage} from "./types";
|
|
13
|
+
|
|
14
|
+
interface NavigationGroup {
|
|
15
|
+
id: string
|
|
16
|
+
title: string
|
|
17
|
+
beta: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface ComponentMeta {
|
|
21
|
+
name: string
|
|
22
|
+
|
|
23
|
+
group: string
|
|
24
|
+
|
|
25
|
+
example: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type ExtensionSchema = OpenAPIV3.Document & {
|
|
29
|
+
"x-docs"?: XDocs
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type NavigationGroupMap = {
|
|
33
|
+
[id: string]: NavigationGroup & {
|
|
34
|
+
index: number
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface OperationExample {
|
|
39
|
+
request: string | { [lang: string]: string }
|
|
40
|
+
response: string | { [lang: string]: string }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type Examples = string | OperationExample | OperationExample[]
|
|
44
|
+
|
|
45
|
+
export function uniformPluginXDocsSidebar({
|
|
46
|
+
references,
|
|
47
|
+
defer,
|
|
48
|
+
}: UniformPluginArgs) {
|
|
49
|
+
let schema: ExtensionSchema | undefined
|
|
50
|
+
const refByOperationId: {
|
|
51
|
+
[key: string]: Reference
|
|
52
|
+
} = {}
|
|
53
|
+
const refByComponentSchema: {
|
|
54
|
+
[key: string]: Reference
|
|
55
|
+
} = {}
|
|
56
|
+
|
|
57
|
+
defer(() => {
|
|
58
|
+
// @ts-ignore
|
|
59
|
+
if (typeof references.__internal_options === "function") {
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
const options = references.__internal_options()
|
|
62
|
+
|
|
63
|
+
if (options?.regions?.length) {
|
|
64
|
+
return {}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const output: Reference[] = []
|
|
69
|
+
if (!schema) {
|
|
70
|
+
return {}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const xDocs = schema["x-docs"]
|
|
74
|
+
|
|
75
|
+
if (!xDocs?.sidebar) {
|
|
76
|
+
return {}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const navigationMap: NavigationGroupMap = {}
|
|
80
|
+
|
|
81
|
+
// Process sidebar groups
|
|
82
|
+
for (let i = 0; i < xDocs.sidebar.length; i++) {
|
|
83
|
+
const navGroup: XDocsSidebar = xDocs.sidebar[i]
|
|
84
|
+
if (!navGroup) {
|
|
85
|
+
continue
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const uniqueKey = `${navGroup.group}-${i}`
|
|
89
|
+
navigationMap[uniqueKey] = {
|
|
90
|
+
id: navGroup.group,
|
|
91
|
+
title: navGroup.group,
|
|
92
|
+
beta: false,
|
|
93
|
+
index: i
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Process each group and its nested pages
|
|
98
|
+
for (let i = 0; i < xDocs.sidebar.length; i++) {
|
|
99
|
+
const group: XDocsSidebar = xDocs.sidebar[i]
|
|
100
|
+
const uniqueKey = `${group.group}-${i}`
|
|
101
|
+
const navGroup = navigationMap[uniqueKey]
|
|
102
|
+
if (!navGroup) {
|
|
103
|
+
console.warn(`No navigation group found for group: ${group.group}`)
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!Array.isArray(group.pages)) {
|
|
108
|
+
continue
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Process nested groups and pages
|
|
112
|
+
processGroupPages(xDocs, group.pages, [group.group], navGroup, output)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Clear references and set from output
|
|
116
|
+
if (Array.isArray(references)) {
|
|
117
|
+
references.length = 0
|
|
118
|
+
references.push(...output)
|
|
119
|
+
} else {
|
|
120
|
+
references = output[0] || references
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return {}
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
function processGroupPages(
|
|
127
|
+
xDocs: XDocs,
|
|
128
|
+
pages: (XDocsSidebar | XDocsPage)[],
|
|
129
|
+
groupPath: string[],
|
|
130
|
+
navGroup: NavigationGroup & { index: number },
|
|
131
|
+
output: Reference[],
|
|
132
|
+
parentPath?: string
|
|
133
|
+
) {
|
|
134
|
+
for (const page of pages) {
|
|
135
|
+
if ('pages' in page && Array.isArray(page.pages)) {
|
|
136
|
+
// This is a nested group
|
|
137
|
+
processGroupPages(xDocs, page.pages, [...groupPath, page.group], navGroup, output, page.path)
|
|
138
|
+
} else if ('type' in page && 'key' in page) {
|
|
139
|
+
// This is a page
|
|
140
|
+
processPage(xDocs, page, groupPath, navGroup, output, parentPath)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function processPage(
|
|
146
|
+
xDocs: XDocs,
|
|
147
|
+
page: XDocsPage,
|
|
148
|
+
groupPath: string[],
|
|
149
|
+
navGroup: NavigationGroup & { index: number },
|
|
150
|
+
output: Reference[],
|
|
151
|
+
parentPath?: string
|
|
152
|
+
) {
|
|
153
|
+
let uniformRef: Reference | undefined
|
|
154
|
+
|
|
155
|
+
switch (page.type) {
|
|
156
|
+
case "endpoint": {
|
|
157
|
+
const operationRef = refByOperationId[page.key]
|
|
158
|
+
if (!operationRef) {
|
|
159
|
+
console.warn(`No operation found for key: ${page.key} in group ${groupPath.join('/')}`)
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
uniformRef = operationRef
|
|
163
|
+
break
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
case "object": {
|
|
167
|
+
const componentRef = refByComponentSchema[page.key]
|
|
168
|
+
if (!componentRef) {
|
|
169
|
+
console.warn(`No component schema found for key: ${page.key} in group ${groupPath.join('/')}`)
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const selector = componentRef.__UNSAFE_selector
|
|
174
|
+
if (!selector || typeof selector !== "function") {
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const component = selector("[component]") as OpenAPIV3.SchemaObject | undefined
|
|
179
|
+
if (!component) {
|
|
180
|
+
console.warn(`No component schema found for key: ${page.key} in group ${groupPath.join('/')}`)
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
let componentMeta: ComponentMeta | undefined
|
|
185
|
+
if (component.allOf) {
|
|
186
|
+
let found = false
|
|
187
|
+
for (const item of component.allOf) {
|
|
188
|
+
const docsMeta = (item as any)["x-docs"] as ComponentMeta | undefined
|
|
189
|
+
|
|
190
|
+
if (docsMeta && found) {
|
|
191
|
+
console.warn(`Multiple x-docs found in allOf for component schema: ${page.key} in group ${groupPath.join('/')}`)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (docsMeta) {
|
|
195
|
+
found = true
|
|
196
|
+
componentMeta = docsMeta
|
|
197
|
+
break
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (!found) {
|
|
202
|
+
console.warn(`No x-docs found in allOf for component schema: ${page.key} in group ${groupPath.join('/')}`)
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
const docsMeta = (component as any)["x-docs"] as ComponentMeta | undefined
|
|
207
|
+
if (docsMeta) {
|
|
208
|
+
componentMeta = docsMeta
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
uniformRef = componentRef
|
|
213
|
+
if (!componentMeta) {
|
|
214
|
+
break
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
componentRef.title = componentMeta.name || componentRef.title
|
|
218
|
+
|
|
219
|
+
if (componentMeta.example) {
|
|
220
|
+
const exampleGroups = oasXDocsExamples(componentMeta.example)
|
|
221
|
+
uniformRef.examples = {
|
|
222
|
+
groups: exampleGroups,
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
break
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
default: {
|
|
229
|
+
console.warn(`Unknown page type: ${page.type} in group ${groupPath.join('/')}`)
|
|
230
|
+
return
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (!uniformRef) {
|
|
235
|
+
return
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (xDocs.sidebarPathStrategy === "inherit") {
|
|
239
|
+
const ctx = uniformRef.context as OpenAPIReferenceContext | undefined
|
|
240
|
+
let firstPart = ""
|
|
241
|
+
if (parentPath) {
|
|
242
|
+
firstPart = parentPath
|
|
243
|
+
} else {
|
|
244
|
+
firstPart = ctx?.path || ""
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const canonical = joinPaths(firstPart || "", page.path)
|
|
248
|
+
if (canonical) {
|
|
249
|
+
uniformRef.canonical = canonical
|
|
250
|
+
}
|
|
251
|
+
} else if (page.path) {
|
|
252
|
+
uniformRef.canonical = joinPaths(parentPath, page.path)
|
|
253
|
+
} else if (parentPath) {
|
|
254
|
+
uniformRef.canonical = parentPath
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (!uniformRef.context) {
|
|
258
|
+
uniformRef.context = {}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
uniformRef.context.group = groupPath
|
|
262
|
+
|
|
263
|
+
output.push(uniformRef)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return function pluginXDocsSidebarInner(ref: Reference) {
|
|
267
|
+
// @ts-ignore
|
|
268
|
+
const selector = ref.__UNSAFE_selector
|
|
269
|
+
if (!selector || typeof selector !== "function") {
|
|
270
|
+
return
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const oapSchema = selector("[schema]")
|
|
274
|
+
if (!oapSchema) {
|
|
275
|
+
return
|
|
276
|
+
}
|
|
277
|
+
schema = oapSchema
|
|
278
|
+
|
|
279
|
+
const ctx = ref.context as OpenAPIReferenceContext | undefined
|
|
280
|
+
if (ctx?.componentSchema) {
|
|
281
|
+
refByComponentSchema[ctx.componentSchema] = ref
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const methodPath = selector("[method] [path]") as OpenAPIV3.OperationObject | undefined
|
|
285
|
+
if (!methodPath) {
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const oapMethod = selector("[method]")
|
|
290
|
+
if (!oapMethod) {
|
|
291
|
+
return
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const operationId = methodPath.operationId
|
|
295
|
+
if (operationId) {
|
|
296
|
+
refByOperationId[operationId] = ref
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const methodId = (oapMethod?.httpMethod?.toUpperCase() + " " + oapMethod?.path || "").trim()
|
|
300
|
+
if (methodId) {
|
|
301
|
+
refByOperationId[methodId] = ref
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const meta = (methodPath as any)["x-docs"]
|
|
305
|
+
if (!meta) {
|
|
306
|
+
return
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (meta.name) {
|
|
310
|
+
ref.title = meta.name
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (meta.group) {
|
|
314
|
+
if (ref.context) {
|
|
315
|
+
ref.context.group = [meta.group]
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (!ref.description) {
|
|
320
|
+
ref.description = methodPath.summary || ""
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (meta.examples) {
|
|
324
|
+
const exampleGroups = oasXDocsExamples(meta.examples)
|
|
325
|
+
ref.examples = {
|
|
326
|
+
groups: exampleGroups,
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (meta.returns) {
|
|
331
|
+
if (ref.definitions?.length) {
|
|
332
|
+
ref.definitions[ref.definitions.length - 1] = {
|
|
333
|
+
title: ref.definitions[ref.definitions.length - 1].title,
|
|
334
|
+
description: meta.returns,
|
|
335
|
+
properties: []
|
|
336
|
+
}
|
|
337
|
+
} else {
|
|
338
|
+
ref.definitions = [
|
|
339
|
+
{
|
|
340
|
+
title: "Response",
|
|
341
|
+
description: meta.returns,
|
|
342
|
+
properties: []
|
|
343
|
+
}
|
|
344
|
+
]
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function oasXDocsExamples(examples: Examples) {
|
|
351
|
+
const groups: ExampleGroup[] = []
|
|
352
|
+
|
|
353
|
+
if (examples) {
|
|
354
|
+
if (Array.isArray(examples)) {
|
|
355
|
+
// Create request group
|
|
356
|
+
const requestExamples: Example[] = []
|
|
357
|
+
examples.forEach((example: {
|
|
358
|
+
title?: string;
|
|
359
|
+
request?: string | Record<string, string>;
|
|
360
|
+
response?: string | Record<string, string>;
|
|
361
|
+
}) => {
|
|
362
|
+
if (example.request) {
|
|
363
|
+
const tabs: CodeBlockTab[] = []
|
|
364
|
+
if (typeof example.request === "string") {
|
|
365
|
+
tabs.push({
|
|
366
|
+
title: "",
|
|
367
|
+
language: "json",
|
|
368
|
+
code: example.request
|
|
369
|
+
})
|
|
370
|
+
} else {
|
|
371
|
+
for (let lang of Object.keys(example.request)) {
|
|
372
|
+
const code = example.request[lang] || ""
|
|
373
|
+
const language = lang === "curl" ? "bash" :
|
|
374
|
+
lang === "node.js" ? "js" : lang
|
|
375
|
+
|
|
376
|
+
tabs.push({
|
|
377
|
+
title: lang,
|
|
378
|
+
language,
|
|
379
|
+
code
|
|
380
|
+
})
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if (tabs.length > 0) {
|
|
384
|
+
requestExamples.push({
|
|
385
|
+
description: example.title || "",
|
|
386
|
+
codeblock: {
|
|
387
|
+
title: example.title || "",
|
|
388
|
+
tabs
|
|
389
|
+
}
|
|
390
|
+
})
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
})
|
|
394
|
+
if (requestExamples.length > 0) {
|
|
395
|
+
groups.push({
|
|
396
|
+
description: "Example request",
|
|
397
|
+
examples: requestExamples
|
|
398
|
+
})
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Create response group
|
|
402
|
+
const responseExamples: Example[] = []
|
|
403
|
+
examples.forEach((example: {
|
|
404
|
+
title?: string;
|
|
405
|
+
request?: string | Record<string, string>;
|
|
406
|
+
response?: string | Record<string, string>;
|
|
407
|
+
}) => {
|
|
408
|
+
if (example.response) {
|
|
409
|
+
const tabs: CodeBlockTab[] = []
|
|
410
|
+
if (typeof example.response === "string") {
|
|
411
|
+
tabs.push({
|
|
412
|
+
title: "",
|
|
413
|
+
language: "json",
|
|
414
|
+
code: example.response
|
|
415
|
+
})
|
|
416
|
+
} else {
|
|
417
|
+
for (let lang of Object.keys(example.response)) {
|
|
418
|
+
const code = example.response[lang] || ""
|
|
419
|
+
const language = lang === "curl" ? "bash" :
|
|
420
|
+
lang === "node.js" ? "js" : lang
|
|
421
|
+
|
|
422
|
+
tabs.push({
|
|
423
|
+
title: lang,
|
|
424
|
+
language,
|
|
425
|
+
code
|
|
426
|
+
})
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (tabs.length > 0) {
|
|
430
|
+
responseExamples.push({
|
|
431
|
+
description: example.title || "",
|
|
432
|
+
codeblock: {
|
|
433
|
+
title: example.title || "",
|
|
434
|
+
tabs
|
|
435
|
+
}
|
|
436
|
+
})
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
})
|
|
440
|
+
if (responseExamples.length > 0) {
|
|
441
|
+
groups.push({
|
|
442
|
+
description: "Example response",
|
|
443
|
+
examples: responseExamples
|
|
444
|
+
})
|
|
445
|
+
}
|
|
446
|
+
} else {
|
|
447
|
+
if (typeof examples === "string") {
|
|
448
|
+
groups.push({
|
|
449
|
+
description: "Example",
|
|
450
|
+
examples: [
|
|
451
|
+
{
|
|
452
|
+
description: "",
|
|
453
|
+
codeblock: {
|
|
454
|
+
tabs: [
|
|
455
|
+
{
|
|
456
|
+
title: "",
|
|
457
|
+
language: "json",
|
|
458
|
+
code: examples
|
|
459
|
+
}
|
|
460
|
+
]
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
]
|
|
464
|
+
})
|
|
465
|
+
} else {
|
|
466
|
+
if (examples.request) {
|
|
467
|
+
const tabs: CodeBlockTab[] = []
|
|
468
|
+
|
|
469
|
+
if (typeof examples.request === "string") {
|
|
470
|
+
tabs.push({
|
|
471
|
+
title: "",
|
|
472
|
+
language: "json",
|
|
473
|
+
code: examples.request || "",
|
|
474
|
+
})
|
|
475
|
+
} else {
|
|
476
|
+
for (let lang of Object.keys(examples.request)) {
|
|
477
|
+
const code = examples.request[lang] || ""
|
|
478
|
+
|
|
479
|
+
switch (lang) {
|
|
480
|
+
case "curl":
|
|
481
|
+
lang = "bash"
|
|
482
|
+
break
|
|
483
|
+
case "node.js":
|
|
484
|
+
lang = "js"
|
|
485
|
+
break
|
|
486
|
+
default:
|
|
487
|
+
break
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
tabs.push({
|
|
491
|
+
title: lang,
|
|
492
|
+
language: lang,
|
|
493
|
+
code,
|
|
494
|
+
})
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
groups.push({
|
|
499
|
+
description: "Example request",
|
|
500
|
+
examples: [
|
|
501
|
+
{
|
|
502
|
+
description: "",
|
|
503
|
+
codeblock: {
|
|
504
|
+
tabs
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
]
|
|
508
|
+
})
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
if (examples.response) {
|
|
512
|
+
const tabs: CodeBlockTab[] = []
|
|
513
|
+
if (typeof examples.response === "string") {
|
|
514
|
+
tabs.push({
|
|
515
|
+
title: "",
|
|
516
|
+
language: "json",
|
|
517
|
+
code: examples.response || "",
|
|
518
|
+
})
|
|
519
|
+
} else {
|
|
520
|
+
for (let lang of Object.keys(examples.response)) {
|
|
521
|
+
const code = examples.response[lang] || ""
|
|
522
|
+
|
|
523
|
+
switch (lang) {
|
|
524
|
+
case "curl":
|
|
525
|
+
lang = "bash"
|
|
526
|
+
break
|
|
527
|
+
case "node.js":
|
|
528
|
+
lang = "js"
|
|
529
|
+
break
|
|
530
|
+
default:
|
|
531
|
+
break
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
tabs.push({
|
|
535
|
+
title: lang,
|
|
536
|
+
language: lang,
|
|
537
|
+
code,
|
|
538
|
+
})
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
groups.push({
|
|
543
|
+
description: "Example response",
|
|
544
|
+
examples: [
|
|
545
|
+
{
|
|
546
|
+
description: "",
|
|
547
|
+
codeblock: {
|
|
548
|
+
tabs
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
]
|
|
552
|
+
})
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
return groups
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function sanitizePath(path: string): string {
|
|
562
|
+
// Remove path parameters like {userId} or :userId
|
|
563
|
+
return path.replace(/\/\{[^}]+\}/g, '').replace(/\/:[^/]+/g, '')
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function joinPaths(...paths: (string | undefined)[]): string {
|
|
567
|
+
return paths
|
|
568
|
+
.filter(Boolean)
|
|
569
|
+
.map(path => {
|
|
570
|
+
// Remove leading and trailing slashes
|
|
571
|
+
path = path!.replace(/^\/+|\/+$/g, '')
|
|
572
|
+
// Ensure path starts with / if it's not empty
|
|
573
|
+
return path ? `/${path}` : ''
|
|
574
|
+
})
|
|
575
|
+
.join('')
|
|
576
|
+
.replace(/\/+/g, '/') // Replace multiple slashes with single slash
|
|
577
|
+
.replace(/\/\{[^}]+\}/g, '') // Remove {param} segments
|
|
578
|
+
.replace(/\/:[^/]+/g, '') // Remove :param segments
|
|
579
|
+
}
|
|
580
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface XDocs {
|
|
2
|
+
route?: string
|
|
3
|
+
|
|
4
|
+
codeLanguages?: string[]
|
|
5
|
+
|
|
6
|
+
sidebarPathStrategy?: "inherit"
|
|
7
|
+
|
|
8
|
+
sidebar?: XDocsSidebar[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// TODO: move to core settings like SidebarLite<XDocsSidebar>
|
|
12
|
+
export interface XDocsSidebar {
|
|
13
|
+
group: string
|
|
14
|
+
|
|
15
|
+
path?: string
|
|
16
|
+
|
|
17
|
+
pages: XDocsSidebar[] | XDocsPage[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface XDocsPage {
|
|
21
|
+
type: "endpoint" | "object"
|
|
22
|
+
|
|
23
|
+
key: string
|
|
24
|
+
|
|
25
|
+
path?: string
|
|
26
|
+
}
|