@xyd-js/openapi 0.1.0-xyd.10 → 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 +24 -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,354 @@
|
|
|
1
|
+
import {OpenAPIV3} from "openapi-types";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Definition,
|
|
5
|
+
ExampleGroup,
|
|
6
|
+
Reference,
|
|
7
|
+
ReferenceCategory,
|
|
8
|
+
OpenAPIReferenceContext,
|
|
9
|
+
DefinitionVariantOpenAPIMeta,
|
|
10
|
+
DefinitionVariant,
|
|
11
|
+
DefinitionOpenAPIMeta,
|
|
12
|
+
SymbolDef,
|
|
13
|
+
DefinitionProperty
|
|
14
|
+
} from "@xyd-js/uniform";
|
|
15
|
+
|
|
16
|
+
import {oapParametersToDefinitionProperties} from "./oas-parameters";
|
|
17
|
+
import {oapRequestBodyToDefinitionProperties} from "./oas-requestBody";
|
|
18
|
+
import {oasResponseToDefinitionProperties} from "./oas-responses";
|
|
19
|
+
import {
|
|
20
|
+
httpMethodToUniformMethod,
|
|
21
|
+
slug
|
|
22
|
+
} from "../utils";
|
|
23
|
+
import {OasJSONSchema} from "../types";
|
|
24
|
+
import path from "node:path";
|
|
25
|
+
|
|
26
|
+
// oapPathToReference converts an OpenAPI path to a uniform Reference
|
|
27
|
+
export function oapPathToReference(
|
|
28
|
+
schema: OpenAPIV3.Document,
|
|
29
|
+
httpMethod: string,
|
|
30
|
+
path: string,
|
|
31
|
+
oapPath: OpenAPIV3.PathItemObject,
|
|
32
|
+
): Reference | null {
|
|
33
|
+
const mType = httpMethodToUniformMethod(httpMethod)
|
|
34
|
+
|
|
35
|
+
if (!mType) {
|
|
36
|
+
console.error(`Unsupported method: ${httpMethod}`)
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const definitions: Definition[] = []
|
|
41
|
+
const exampleGroups: ExampleGroup[] = []
|
|
42
|
+
|
|
43
|
+
const oapMethod = oapPath?.[httpMethod as keyof OpenAPIV3.PathItemObject] as OpenAPIV3.OperationObject
|
|
44
|
+
if (!oapMethod) {
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const tag = getFirstTag(oapMethod)
|
|
49
|
+
const group = [tag]
|
|
50
|
+
|
|
51
|
+
const endpointRef: Reference = {
|
|
52
|
+
title: title(oapMethod, httpMethod, path),
|
|
53
|
+
canonical: canonical(oapMethod, httpMethod, path),
|
|
54
|
+
description: oapMethod?.description || oapMethod?.summary,
|
|
55
|
+
type: mType,
|
|
56
|
+
category: ReferenceCategory.REST,
|
|
57
|
+
|
|
58
|
+
context: {
|
|
59
|
+
method: httpMethod,
|
|
60
|
+
path: `${encodeURIComponent(path)}`,
|
|
61
|
+
fullPath: path,
|
|
62
|
+
group,
|
|
63
|
+
} as OpenAPIReferenceContext,
|
|
64
|
+
|
|
65
|
+
examples: {
|
|
66
|
+
groups: exampleGroups,
|
|
67
|
+
},
|
|
68
|
+
definitions: definitions,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (oapMethod.parameters) {
|
|
72
|
+
const parameters = oapMethod.parameters as OpenAPIV3.ParameterObject[]
|
|
73
|
+
|
|
74
|
+
const paramtersMap = oapParametersToDefinitionProperties(parameters)
|
|
75
|
+
|
|
76
|
+
Object.entries(paramtersMap).forEach(([key, definitionProperties]) => {
|
|
77
|
+
let title: string
|
|
78
|
+
|
|
79
|
+
switch (key) {
|
|
80
|
+
case 'path':
|
|
81
|
+
title = "Path parameters"
|
|
82
|
+
break
|
|
83
|
+
case 'query':
|
|
84
|
+
title = "Query parameters"
|
|
85
|
+
break
|
|
86
|
+
case 'header':
|
|
87
|
+
title = "Headers"
|
|
88
|
+
break
|
|
89
|
+
default:
|
|
90
|
+
console.error(`Unsupported parameter type: ${key} for ${httpMethod} ${path}`)
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
definitions.push({
|
|
95
|
+
title,
|
|
96
|
+
properties: definitionProperties
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
definitions.push(...oapOperationToDefinitions(oapMethod))
|
|
102
|
+
|
|
103
|
+
// TODO: !!!! better api !!!!
|
|
104
|
+
endpointRef.__UNSAFE_selector = function __UNSAFE_selector(selector: string) {
|
|
105
|
+
switch (selector) {
|
|
106
|
+
case "[schema]": {
|
|
107
|
+
return schema
|
|
108
|
+
}
|
|
109
|
+
case "[method]": {
|
|
110
|
+
return {
|
|
111
|
+
oapPath,
|
|
112
|
+
httpMethod,
|
|
113
|
+
path
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
case "[method] [path]": {
|
|
118
|
+
return oapMethod
|
|
119
|
+
}
|
|
120
|
+
default:
|
|
121
|
+
return null
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return endpointRef
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function oapOperationToDefinitions(
|
|
129
|
+
oapMethod: OpenAPIV3.OperationObject,
|
|
130
|
+
): Definition[] {
|
|
131
|
+
const definitions: Definition[] = []
|
|
132
|
+
|
|
133
|
+
if (oapMethod.requestBody) {
|
|
134
|
+
const definition = oapRequestOperationToUniformDefinition(oapMethod)
|
|
135
|
+
definitions.push(definition)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (oapMethod.responses) {
|
|
139
|
+
const definition = oapResponseOperationToUniformDefinition(oapMethod)
|
|
140
|
+
definitions.push(definition)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return definitions
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function oapRequestOperationToUniformDefinition(
|
|
147
|
+
oapOperation: OpenAPIV3.OperationObject,
|
|
148
|
+
): Definition {
|
|
149
|
+
const reqBody = oapOperation.requestBody as OpenAPIV3.RequestBodyObject
|
|
150
|
+
const variants: DefinitionVariant<DefinitionVariantOpenAPIMeta>[] = []
|
|
151
|
+
|
|
152
|
+
for (const contentType of Object.keys(reqBody.content)) {
|
|
153
|
+
const schema = reqBody.content[contentType]?.schema as OpenAPIV3.SchemaObject
|
|
154
|
+
|
|
155
|
+
let properties: DefinitionProperty[] = []
|
|
156
|
+
let rootProperty: DefinitionProperty | undefined
|
|
157
|
+
let propertiesResp = oapRequestBodyToDefinitionProperties(reqBody, contentType) || []
|
|
158
|
+
|
|
159
|
+
if (Array.isArray(propertiesResp)) {
|
|
160
|
+
properties = propertiesResp
|
|
161
|
+
} else {
|
|
162
|
+
rootProperty = propertiesResp
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const meta: DefinitionVariantOpenAPIMeta[] = [
|
|
166
|
+
{
|
|
167
|
+
name: "contentType",
|
|
168
|
+
value: contentType || "",
|
|
169
|
+
},
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
if (schema?.required) {
|
|
173
|
+
meta.push({
|
|
174
|
+
name: "required",
|
|
175
|
+
value: schema.required ? "true" : "false",
|
|
176
|
+
})
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
variants.push({
|
|
180
|
+
title: contentType,
|
|
181
|
+
description: schema.description || "",
|
|
182
|
+
properties,
|
|
183
|
+
rootProperty,
|
|
184
|
+
meta,
|
|
185
|
+
symbolDef: definitionPropertyTypeDef(schema),
|
|
186
|
+
})
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const meta: DefinitionOpenAPIMeta[] = []
|
|
190
|
+
|
|
191
|
+
if (reqBody.required) {
|
|
192
|
+
meta.push({
|
|
193
|
+
name: "required",
|
|
194
|
+
value: "true",
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
title: 'Request body',
|
|
200
|
+
variants,
|
|
201
|
+
properties: [],
|
|
202
|
+
meta
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function oapResponseOperationToUniformDefinition(
|
|
207
|
+
oapOperation: OpenAPIV3.OperationObject,
|
|
208
|
+
): Definition {
|
|
209
|
+
|
|
210
|
+
const responses = oapOperation.responses as OpenAPIV3.ResponsesObject
|
|
211
|
+
|
|
212
|
+
const variants: DefinitionVariant<DefinitionVariantOpenAPIMeta>[] = []
|
|
213
|
+
|
|
214
|
+
Object.keys(responses).forEach((code) => {
|
|
215
|
+
const responseObject = responses[code] as OpenAPIV3.ResponseObject
|
|
216
|
+
if (!responseObject?.content) {
|
|
217
|
+
variants.push({
|
|
218
|
+
title: code,
|
|
219
|
+
description: responseObject.description,
|
|
220
|
+
properties: [],
|
|
221
|
+
meta: [
|
|
222
|
+
{
|
|
223
|
+
name: "status",
|
|
224
|
+
value: code || "",
|
|
225
|
+
},
|
|
226
|
+
],
|
|
227
|
+
})
|
|
228
|
+
return null
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const contentTypes = Object.keys(responseObject.content)
|
|
232
|
+
|
|
233
|
+
for (const contentType of contentTypes) {
|
|
234
|
+
let properties: DefinitionProperty[] = []
|
|
235
|
+
let rootProperty: DefinitionProperty | undefined
|
|
236
|
+
const schema = responseObject.content[contentType]?.schema as OpenAPIV3.SchemaObject
|
|
237
|
+
const respProperties = oasResponseToDefinitionProperties(responses, code, contentType) || []
|
|
238
|
+
|
|
239
|
+
if (respProperties && "properties" in respProperties && respProperties?.properties) {
|
|
240
|
+
if (Array.isArray(respProperties.properties)) {
|
|
241
|
+
properties = respProperties.properties
|
|
242
|
+
} else {
|
|
243
|
+
rootProperty = respProperties.properties
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
let definitionDescription = ""
|
|
248
|
+
if ("description" in respProperties) {
|
|
249
|
+
definitionDescription = respProperties.description || ""
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
variants.push({
|
|
253
|
+
title: code,
|
|
254
|
+
description: responseObject.description,
|
|
255
|
+
properties,
|
|
256
|
+
rootProperty,
|
|
257
|
+
meta: [
|
|
258
|
+
{
|
|
259
|
+
name: "status",
|
|
260
|
+
value: code || "",
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: "contentType",
|
|
264
|
+
value: contentType || "",
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
name: "definitionDescription",
|
|
268
|
+
value: definitionDescription
|
|
269
|
+
}
|
|
270
|
+
],
|
|
271
|
+
symbolDef: definitionPropertyTypeDef(schema),
|
|
272
|
+
})
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
title: 'Response',
|
|
279
|
+
variants,
|
|
280
|
+
properties: []
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function definitionPropertyTypeDef(
|
|
285
|
+
schema: OpenAPIV3.SchemaObject | undefined,
|
|
286
|
+
) {
|
|
287
|
+
if (!schema) {
|
|
288
|
+
return
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
let typeDef: SymbolDef | undefined
|
|
292
|
+
let oasSchema = schema as OasJSONSchema
|
|
293
|
+
if (oasSchema.type === "array") {
|
|
294
|
+
oasSchema = oasSchema.items as OasJSONSchema
|
|
295
|
+
}
|
|
296
|
+
if (oasSchema?.__internal_getRefPath) {
|
|
297
|
+
const symbolId = oasSchema.__internal_getRefPath()
|
|
298
|
+
|
|
299
|
+
typeDef = {
|
|
300
|
+
id: symbolId,
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return typeDef
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
function title(
|
|
309
|
+
oapMethod: OpenAPIV3.OperationObject,
|
|
310
|
+
httpMethod: string,
|
|
311
|
+
httpPath: string,
|
|
312
|
+
) {
|
|
313
|
+
const tit = oapMethod?.summary || oapMethod.operationId || ""
|
|
314
|
+
if (tit) {
|
|
315
|
+
return tit
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (!httpMethod || !httpPath) {
|
|
319
|
+
throw new Error("httpMethod and path are required to generate title")
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return path.join(httpMethod, cleanPath(httpPath))
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function canonical(
|
|
326
|
+
oapMethod: OpenAPIV3.OperationObject,
|
|
327
|
+
httpMethod: string,
|
|
328
|
+
httpPath: string,
|
|
329
|
+
) {
|
|
330
|
+
let canon = oapMethod.operationId || slug(oapMethod?.summary || "")
|
|
331
|
+
|
|
332
|
+
if (canon) {
|
|
333
|
+
return canon
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (!httpMethod || !httpPath) {
|
|
337
|
+
throw new Error("httpMethod and path are required to generate canonical")
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return path.join(httpMethod, cleanPath(httpPath))
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function getFirstTag(oapMethod: OpenAPIV3.OperationObject) {
|
|
344
|
+
for (const tag of oapMethod?.tags || []) {
|
|
345
|
+
return tag
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return ""
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Helper function to remove curly braces from path parameters
|
|
352
|
+
function cleanPath(httpPath: string): string {
|
|
353
|
+
return httpPath.replace(/\{([^}]+)\}/g, '$1')
|
|
354
|
+
}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import {OpenAPIV3} from "openapi-types";
|
|
2
|
-
import {DefinitionProperty} from "@xyd-js/uniform";
|
|
3
2
|
|
|
4
|
-
import {
|
|
3
|
+
import {DefinitionProperty, DEFINED_DEFINITION_PROPERTY_TYPE} from "@xyd-js/uniform";
|
|
4
|
+
|
|
5
|
+
import {schemaObjectToUniformDefinitionProperties} from "../oas-core";
|
|
5
6
|
|
|
6
7
|
// oapRequestBodyToDefinitionProperties converts OpenAPI request body to uniform DefinitionProperties
|
|
7
8
|
export function oapRequestBodyToDefinitionProperties(
|
|
8
|
-
reqBody: OpenAPIV3.RequestBodyObject
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const schema = reqBody.content[
|
|
9
|
+
reqBody: OpenAPIV3.RequestBodyObject,
|
|
10
|
+
contentType: string
|
|
11
|
+
): DefinitionProperty[] | DefinitionProperty | null {
|
|
12
|
+
const schema = reqBody.content[contentType].schema as OpenAPIV3.SchemaObject
|
|
13
|
+
if (!schema) {
|
|
14
|
+
return null
|
|
15
|
+
}
|
|
12
16
|
|
|
13
17
|
let schemaObject: OpenAPIV3.SchemaObject | undefined
|
|
14
18
|
|
|
@@ -16,19 +20,26 @@ export function oapRequestBodyToDefinitionProperties(
|
|
|
16
20
|
return schema.allOf.reduce((acc, of) => {
|
|
17
21
|
const fakeBody: OpenAPIV3.RequestBodyObject = {
|
|
18
22
|
content: {
|
|
19
|
-
|
|
23
|
+
[contentType]: {
|
|
20
24
|
schema: of
|
|
21
25
|
}
|
|
22
26
|
}
|
|
23
27
|
}
|
|
24
28
|
|
|
29
|
+
const properties = oapRequestBodyToDefinitionProperties(fakeBody, contentType) || []
|
|
30
|
+
if (!Array.isArray(properties)) {
|
|
31
|
+
return acc
|
|
32
|
+
}
|
|
33
|
+
|
|
25
34
|
return [
|
|
26
35
|
...acc,
|
|
27
|
-
...
|
|
36
|
+
...properties
|
|
28
37
|
]
|
|
29
38
|
}, [] as DefinitionProperty[])
|
|
30
39
|
}
|
|
31
40
|
|
|
41
|
+
let array = false
|
|
42
|
+
|
|
32
43
|
switch (schema.type) {
|
|
33
44
|
case 'object': {
|
|
34
45
|
schemaObject = schema
|
|
@@ -36,10 +47,11 @@ export function oapRequestBodyToDefinitionProperties(
|
|
|
36
47
|
}
|
|
37
48
|
case 'array': {
|
|
38
49
|
const arrSchema = schema as OpenAPIV3.ArraySchemaObject
|
|
39
|
-
|
|
40
50
|
const items = arrSchema.items as OpenAPIV3.SchemaObject
|
|
41
51
|
|
|
42
52
|
schemaObject = items
|
|
53
|
+
array = true
|
|
54
|
+
|
|
43
55
|
break
|
|
44
56
|
}
|
|
45
57
|
default:
|
|
@@ -51,5 +63,13 @@ export function oapRequestBodyToDefinitionProperties(
|
|
|
51
63
|
return null
|
|
52
64
|
}
|
|
53
65
|
|
|
54
|
-
|
|
66
|
+
const properties = schemaObjectToUniformDefinitionProperties(schemaObject)
|
|
67
|
+
if (array) {
|
|
68
|
+
return {
|
|
69
|
+
type: DEFINED_DEFINITION_PROPERTY_TYPE.ARRAY,
|
|
70
|
+
properties,
|
|
71
|
+
} as DefinitionProperty
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return properties
|
|
55
75
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {OpenAPIV3} from "openapi-types";
|
|
2
|
+
import {DefinitionProperty, DEFINED_DEFINITION_PROPERTY_TYPE} from "@xyd-js/uniform";
|
|
3
|
+
|
|
4
|
+
import {schemaObjectToUniformDefinitionProperties} from "../oas-core";
|
|
5
|
+
|
|
6
|
+
export function oasResponseToDefinitionProperties(
|
|
7
|
+
responses: OpenAPIV3.ResponsesObject,
|
|
8
|
+
code: string,
|
|
9
|
+
contentType: string,
|
|
10
|
+
): {
|
|
11
|
+
properties: DefinitionProperty | DefinitionProperty[],
|
|
12
|
+
description?: string,
|
|
13
|
+
} | null {
|
|
14
|
+
let schemaObject: OpenAPIV3.SchemaObject | undefined
|
|
15
|
+
let responseObject: OpenAPIV3.ResponseObject | undefined
|
|
16
|
+
|
|
17
|
+
if (responses[code]) {
|
|
18
|
+
responseObject = responses[code] as OpenAPIV3.ResponseObject
|
|
19
|
+
if (!responseObject?.content) {
|
|
20
|
+
return null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
schemaObject = responseObject?.content[contentType]?.schema as OpenAPIV3.SchemaObject
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!schemaObject) {
|
|
27
|
+
return {
|
|
28
|
+
properties: [
|
|
29
|
+
{
|
|
30
|
+
description: responseObject?.description || "",
|
|
31
|
+
name: "",
|
|
32
|
+
type: ""
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let array = false
|
|
39
|
+
|
|
40
|
+
switch (schemaObject.type) {
|
|
41
|
+
case 'array':
|
|
42
|
+
const arrSchema = schemaObject as OpenAPIV3.ArraySchemaObject
|
|
43
|
+
const items = arrSchema.items as OpenAPIV3.SchemaObject
|
|
44
|
+
|
|
45
|
+
schemaObject = items
|
|
46
|
+
array = true
|
|
47
|
+
default:
|
|
48
|
+
break
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const properties = schemaObjectToUniformDefinitionProperties(schemaObject, true)
|
|
52
|
+
|
|
53
|
+
let description = ""
|
|
54
|
+
|
|
55
|
+
if (schemaObject.allOf) {
|
|
56
|
+
for (const item of schemaObject.allOf) {
|
|
57
|
+
if ("description" in item) {
|
|
58
|
+
description += item.description + "\n";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (array) {
|
|
64
|
+
return {
|
|
65
|
+
properties: {
|
|
66
|
+
type: DEFINED_DEFINITION_PROPERTY_TYPE.ARRAY,
|
|
67
|
+
properties,
|
|
68
|
+
} as DefinitionProperty
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
properties: properties || [],
|
|
74
|
+
description: description || "",
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
import { OpenAPIV3 } from "openapi-types";
|
|
4
|
+
import Oas from "oas";
|
|
5
|
+
|
|
6
|
+
import type { Reference, OpenAPIReferenceContext, ReferenceContext } from "@xyd-js/uniform";
|
|
7
|
+
|
|
8
|
+
import { SUPPORTED_HTTP_METHODS } from "../const";
|
|
9
|
+
import { oapPathToReference } from "./oas-paths";
|
|
10
|
+
import { oapExamples } from "./oas-examples";
|
|
11
|
+
import { uniformOasOptions } from "../types";
|
|
12
|
+
import { schemaComponentsToUniformReferences } from "./oas-componentSchemas";
|
|
13
|
+
import {httpMethodToUniformMethod} from "../utils";
|
|
14
|
+
|
|
15
|
+
// TODO: support one-of
|
|
16
|
+
// TODO: support $ref - currently we use $refParser.dereference that converts $ref into objects
|
|
17
|
+
// TODO: better method check system - currently we need to manually check that in few methods
|
|
18
|
+
|
|
19
|
+
// oapSchemaToReferences converts an OpenAPI schema to a list of uniform References
|
|
20
|
+
export function oapSchemaToReferences(
|
|
21
|
+
schema: OpenAPIV3.Document,
|
|
22
|
+
options?: uniformOasOptions,
|
|
23
|
+
): Reference[] {
|
|
24
|
+
if (!schema) {
|
|
25
|
+
return []
|
|
26
|
+
}
|
|
27
|
+
const references: Reference[] = [];
|
|
28
|
+
const oas = new Oas(schema as any);
|
|
29
|
+
|
|
30
|
+
const server = schema.servers?.[0]?.url || ""
|
|
31
|
+
|
|
32
|
+
Object.entries(schema.paths).forEach(([endpointPath, oapPath]) => {
|
|
33
|
+
SUPPORTED_HTTP_METHODS.forEach((eachMethod) => {
|
|
34
|
+
const httpMethod = eachMethod.toLowerCase() as OpenAPIV3.HttpMethods
|
|
35
|
+
|
|
36
|
+
const found = httpMethodToUniformMethod(httpMethod)
|
|
37
|
+
if (!found) {
|
|
38
|
+
console.warn(`Unsupported method: ${httpMethod} for path: ${endpointPath}`)
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Check if this method/path combination should be included based on regions
|
|
43
|
+
if (options?.regions && options.regions.length > 0) {
|
|
44
|
+
const regionKey = `${eachMethod.toUpperCase()} ${endpointPath}`
|
|
45
|
+
if (!options.regions.some(region => region === regionKey)) {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const reference = oapPathToReference(
|
|
51
|
+
schema,
|
|
52
|
+
httpMethod,
|
|
53
|
+
endpointPath,
|
|
54
|
+
oapPath as OpenAPIV3.PathItemObject
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
if (reference) {
|
|
58
|
+
const ctx = reference.context as OpenAPIReferenceContext
|
|
59
|
+
ctx.path = endpointPath
|
|
60
|
+
ctx.fullPath = path.join(server, endpointPath)
|
|
61
|
+
|
|
62
|
+
const operation = oas.operation(endpointPath, httpMethod);
|
|
63
|
+
reference.examples.groups = oapExamples(oas, operation)
|
|
64
|
+
|
|
65
|
+
const scopes: string[] = []
|
|
66
|
+
const oapMethod = oapPath?.[httpMethod] as OpenAPIV3.OperationObject
|
|
67
|
+
if (schema?.security?.length) {
|
|
68
|
+
for (const security of schema.security) {
|
|
69
|
+
for (const securityKey of Object.keys(security)) {
|
|
70
|
+
if (securityKey === "oauth2" || securityKey === "OAuth2") {
|
|
71
|
+
const securityScopes = security[securityKey]
|
|
72
|
+
if (Array.isArray(securityScopes)) {
|
|
73
|
+
scopes.push(...securityScopes)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (oapMethod?.security) {
|
|
80
|
+
if (!oapMethod?.security?.length) {
|
|
81
|
+
scopes.length = 0
|
|
82
|
+
}
|
|
83
|
+
for (const security of oapMethod.security) {
|
|
84
|
+
for (const securityKey of Object.keys(security)) {
|
|
85
|
+
const securityScheme = schema?.components?.securitySchemes?.[securityKey]
|
|
86
|
+
|
|
87
|
+
// TODO: support other scope-like security schemes
|
|
88
|
+
if (securityScheme && "type" in securityScheme && securityScheme.type === "oauth2") {
|
|
89
|
+
const methodScopes = security[securityKey]
|
|
90
|
+
if (Array.isArray(methodScopes)) {
|
|
91
|
+
scopes.push(...methodScopes)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
ctx.scopes = scopes
|
|
99
|
+
|
|
100
|
+
references.push(reference)
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const schemas = schemaComponentsToUniformReferences(
|
|
106
|
+
schema,
|
|
107
|
+
options,
|
|
108
|
+
)
|
|
109
|
+
references.push(...schemas)
|
|
110
|
+
|
|
111
|
+
const tags = oas.getTags()
|
|
112
|
+
sortReferencesByTags(references, tags)
|
|
113
|
+
|
|
114
|
+
// TODO: in the future better API
|
|
115
|
+
// @ts-ignore
|
|
116
|
+
references.__internal_options = () => options
|
|
117
|
+
|
|
118
|
+
return references
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function sortReferencesByTags(references: Reference[], tags: string[]) {
|
|
122
|
+
return references.sort((prev, next) => {
|
|
123
|
+
const aTags = prev.context?.group || []
|
|
124
|
+
const bTags = next.context?.group || []
|
|
125
|
+
|
|
126
|
+
// Find the first tag that exists in both arrays
|
|
127
|
+
for (const tag of tags) {
|
|
128
|
+
const aIndex = aTags.indexOf(tag)
|
|
129
|
+
const bIndex = bTags.indexOf(tag)
|
|
130
|
+
|
|
131
|
+
if (aIndex !== -1 && bIndex !== -1) {
|
|
132
|
+
return aIndex - bIndex
|
|
133
|
+
}
|
|
134
|
+
if (aIndex !== -1) return -1
|
|
135
|
+
if (bIndex !== -1) return 1
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// If no matching tags found, sort by first tag
|
|
139
|
+
return (aTags[0] || '').localeCompare(bTags[0] || '')
|
|
140
|
+
})
|
|
141
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
export * from "./const"
|
|
2
2
|
|
|
3
|
-
export * from "./parameters"
|
|
3
|
+
export * from "./converters/oas-parameters"
|
|
4
4
|
|
|
5
|
-
export * from "./
|
|
5
|
+
export * from "./converters/oas-paths"
|
|
6
6
|
|
|
7
|
-
export * from "./
|
|
7
|
+
export * from "./oas-core"
|
|
8
8
|
|
|
9
|
-
export * from "./
|
|
9
|
+
export * from "./converters/oas-requestBody"
|
|
10
10
|
|
|
11
|
-
export * from "./
|
|
11
|
+
export * from "./converters/oas-responses"
|
|
12
|
+
|
|
13
|
+
export * from "./converters/oas-schema"
|
|
12
14
|
|
|
13
15
|
export * from "./utils"
|
|
16
|
+
|
|
17
|
+
export * from "./xdocs/types"
|
|
18
|
+
|
|
19
|
+
export {getXDocs} from "./xdocs"
|
|
20
|
+
|
|
21
|
+
export {uniformPluginXDocsSidebar} from "./xdocs/pluginSidebar"
|