docusaurus-plugin-openapi-docs 0.0.0-404 → 0.0.0-407
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/lib/markdown/createSchemaDetails.js +156 -1
- package/lib/markdown/createStatusCodes.js +58 -0
- package/lib/markdown/index.js +1 -0
- package/lib/markdown/schema.js +6 -0
- package/lib/openapi/utils/loadAndResolveSpec.js +13 -0
- package/package.json +2 -2
- package/src/markdown/createSchemaDetails.ts +202 -1
- package/src/markdown/createStatusCodes.ts +68 -0
- package/src/markdown/index.ts +1 -0
- package/src/markdown/schema.ts +7 -0
- package/src/openapi/utils/loadAndResolveSpec.ts +13 -0
|
@@ -86,12 +86,14 @@ function createAnyOneOf(schema) {
|
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
88
|
function createProperties(schema) {
|
|
89
|
+
const discriminator = schema.discriminator;
|
|
89
90
|
return Object.entries(schema.properties).map(([key, val]) => createEdges({
|
|
90
91
|
name: key,
|
|
91
92
|
schema: val,
|
|
92
93
|
required: Array.isArray(schema.required)
|
|
93
94
|
? schema.required.includes(key)
|
|
94
95
|
: false,
|
|
96
|
+
discriminator,
|
|
95
97
|
}));
|
|
96
98
|
}
|
|
97
99
|
function createAdditionalProperties(schema) {
|
|
@@ -228,6 +230,93 @@ function createItems(schema) {
|
|
|
228
230
|
: false,
|
|
229
231
|
}));
|
|
230
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* For handling discriminators that do not map to a same-level property
|
|
235
|
+
*/
|
|
236
|
+
function createDiscriminator(schema) {
|
|
237
|
+
var _a;
|
|
238
|
+
const discriminator = schema.discriminator;
|
|
239
|
+
const propertyName = discriminator === null || discriminator === void 0 ? void 0 : discriminator.propertyName;
|
|
240
|
+
const propertyType = "string"; // should always be string
|
|
241
|
+
const mapping = discriminator === null || discriminator === void 0 ? void 0 : discriminator.mapping;
|
|
242
|
+
// Explicit mapping is required since we can't support implicit
|
|
243
|
+
if (mapping === undefined) {
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
// Attempt to get the property description we want to display
|
|
247
|
+
// TODO: how to make it predictable when handling allOf
|
|
248
|
+
let propertyDescription;
|
|
249
|
+
const firstMappingSchema = mapping[Object.keys(mapping)[0]];
|
|
250
|
+
if (firstMappingSchema.properties !== undefined) {
|
|
251
|
+
propertyDescription =
|
|
252
|
+
firstMappingSchema.properties[propertyName].description;
|
|
253
|
+
}
|
|
254
|
+
if (firstMappingSchema.allOf !== undefined) {
|
|
255
|
+
const { mergedSchemas } = mergeAllOf(firstMappingSchema.allOf);
|
|
256
|
+
if (mergedSchemas.properties !== undefined) {
|
|
257
|
+
propertyDescription =
|
|
258
|
+
(_a = mergedSchemas.properties[propertyName]) === null || _a === void 0 ? void 0 : _a.description;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (propertyDescription === undefined) {
|
|
262
|
+
if (schema.properties !== undefined &&
|
|
263
|
+
schema.properties[propertyName] !== undefined) {
|
|
264
|
+
propertyDescription = schema.properties[propertyName].description;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return (0, utils_1.create)("li", {
|
|
268
|
+
className: "discriminatorItem",
|
|
269
|
+
children: (0, utils_1.create)("div", {
|
|
270
|
+
children: [
|
|
271
|
+
(0, utils_1.create)("strong", {
|
|
272
|
+
style: { paddingLeft: "1rem" },
|
|
273
|
+
children: propertyName,
|
|
274
|
+
}),
|
|
275
|
+
(0, utils_1.guard)(propertyType, (name) => (0, utils_1.create)("span", {
|
|
276
|
+
style: { opacity: "0.6" },
|
|
277
|
+
children: ` ${propertyType}`,
|
|
278
|
+
})),
|
|
279
|
+
(0, utils_1.guard)((0, schema_1.getQualifierMessage)(schema.discriminator), (message) => (0, utils_1.create)("div", {
|
|
280
|
+
style: {
|
|
281
|
+
paddingLeft: "1rem",
|
|
282
|
+
},
|
|
283
|
+
children: (0, createDescription_1.createDescription)(message),
|
|
284
|
+
})),
|
|
285
|
+
(0, utils_1.guard)(propertyDescription, (description) => (0, utils_1.create)("div", {
|
|
286
|
+
style: {
|
|
287
|
+
paddingLeft: "1rem",
|
|
288
|
+
},
|
|
289
|
+
children: (0, createDescription_1.createDescription)(description),
|
|
290
|
+
})),
|
|
291
|
+
(0, utils_1.create)("DiscriminatorTabs", {
|
|
292
|
+
children: Object.keys(mapping).map((key, index) => {
|
|
293
|
+
if (mapping[key].allOf !== undefined) {
|
|
294
|
+
const { mergedSchemas } = mergeAllOf(mapping[key].allOf);
|
|
295
|
+
// Cleanup duplicate property from mapping schema
|
|
296
|
+
delete mergedSchemas.properties[propertyName];
|
|
297
|
+
mapping[key] = mergedSchemas;
|
|
298
|
+
}
|
|
299
|
+
if (mapping[key].properties !== undefined) {
|
|
300
|
+
// Cleanup duplicate property from mapping schema
|
|
301
|
+
delete mapping[key].properties[propertyName];
|
|
302
|
+
}
|
|
303
|
+
const label = key;
|
|
304
|
+
return (0, utils_1.create)("TabItem", {
|
|
305
|
+
label: label,
|
|
306
|
+
value: `${index}-item-discriminator`,
|
|
307
|
+
children: [
|
|
308
|
+
(0, utils_1.create)("div", {
|
|
309
|
+
style: { marginLeft: "-4px" },
|
|
310
|
+
children: createNodes(mapping[key]),
|
|
311
|
+
}),
|
|
312
|
+
],
|
|
313
|
+
});
|
|
314
|
+
}),
|
|
315
|
+
}),
|
|
316
|
+
],
|
|
317
|
+
}),
|
|
318
|
+
});
|
|
319
|
+
}
|
|
231
320
|
function createDetailsNode(name, schemaName, schema, required) {
|
|
232
321
|
return (0, utils_1.create)("SchemaItem", {
|
|
233
322
|
collapsible: true,
|
|
@@ -272,12 +361,75 @@ function createDetailsNode(name, schemaName, schema, required) {
|
|
|
272
361
|
],
|
|
273
362
|
});
|
|
274
363
|
}
|
|
364
|
+
/**
|
|
365
|
+
* For handling discriminators that map to a same-level property (like 'petType').
|
|
366
|
+
* Note: These should only be encountered while iterating through properties.
|
|
367
|
+
*/
|
|
368
|
+
function createPropertyDiscriminator(name, schemaName, schema, discriminator, required) {
|
|
369
|
+
if (schema === undefined) {
|
|
370
|
+
return undefined;
|
|
371
|
+
}
|
|
372
|
+
if (discriminator.mapping === undefined) {
|
|
373
|
+
return undefined;
|
|
374
|
+
}
|
|
375
|
+
return (0, utils_1.create)("li", {
|
|
376
|
+
className: "discriminatorItem",
|
|
377
|
+
children: (0, utils_1.create)("div", {
|
|
378
|
+
children: [
|
|
379
|
+
(0, utils_1.create)("strong", { style: { paddingLeft: "1rem" }, children: name }),
|
|
380
|
+
(0, utils_1.guard)(schemaName, (name) => (0, utils_1.create)("span", {
|
|
381
|
+
style: { opacity: "0.6" },
|
|
382
|
+
children: ` ${schemaName}`,
|
|
383
|
+
})),
|
|
384
|
+
(0, utils_1.guard)(required, () => [
|
|
385
|
+
(0, utils_1.create)("strong", {
|
|
386
|
+
style: {
|
|
387
|
+
fontSize: "var(--ifm-code-font-size)",
|
|
388
|
+
color: "var(--openapi-required)",
|
|
389
|
+
},
|
|
390
|
+
children: " required",
|
|
391
|
+
}),
|
|
392
|
+
]),
|
|
393
|
+
(0, utils_1.guard)((0, schema_1.getQualifierMessage)(discriminator), (message) => (0, utils_1.create)("div", {
|
|
394
|
+
style: {
|
|
395
|
+
paddingLeft: "1rem",
|
|
396
|
+
},
|
|
397
|
+
children: (0, createDescription_1.createDescription)(message),
|
|
398
|
+
})),
|
|
399
|
+
(0, utils_1.guard)(schema.description, (description) => (0, utils_1.create)("div", {
|
|
400
|
+
style: {
|
|
401
|
+
paddingLeft: "1rem",
|
|
402
|
+
},
|
|
403
|
+
children: (0, createDescription_1.createDescription)(description),
|
|
404
|
+
})),
|
|
405
|
+
(0, utils_1.create)("DiscriminatorTabs", {
|
|
406
|
+
children: Object.keys(discriminator === null || discriminator === void 0 ? void 0 : discriminator.mapping).map((key, index) => {
|
|
407
|
+
const label = key;
|
|
408
|
+
return (0, utils_1.create)("TabItem", {
|
|
409
|
+
label: label,
|
|
410
|
+
value: `${index}-item-discriminator`,
|
|
411
|
+
children: [
|
|
412
|
+
(0, utils_1.create)("div", {
|
|
413
|
+
style: { marginLeft: "-4px" },
|
|
414
|
+
children: createNodes(discriminator === null || discriminator === void 0 ? void 0 : discriminator.mapping[key]),
|
|
415
|
+
}),
|
|
416
|
+
],
|
|
417
|
+
});
|
|
418
|
+
}),
|
|
419
|
+
}),
|
|
420
|
+
],
|
|
421
|
+
}),
|
|
422
|
+
});
|
|
423
|
+
}
|
|
275
424
|
/**
|
|
276
425
|
* Creates the edges or "leaves" of a schema tree. Edges can branch into sub-nodes with createDetails().
|
|
277
426
|
*/
|
|
278
|
-
function createEdges({ name, schema, required }) {
|
|
427
|
+
function createEdges({ name, schema, required, discriminator, }) {
|
|
279
428
|
var _a;
|
|
280
429
|
const schemaName = (0, schema_1.getSchemaName)(schema);
|
|
430
|
+
if (discriminator !== undefined && discriminator.propertyName === name) {
|
|
431
|
+
return createPropertyDiscriminator(name, "string", schema, discriminator, required);
|
|
432
|
+
}
|
|
281
433
|
if (schema.oneOf !== undefined || schema.anyOf !== undefined) {
|
|
282
434
|
return createDetailsNode(name, schemaName, schema, required);
|
|
283
435
|
}
|
|
@@ -327,6 +479,9 @@ function createEdges({ name, schema, required }) {
|
|
|
327
479
|
* Creates a hierarchical level of a schema tree. Nodes produce edges that can branch into sub-nodes with edges, recursively.
|
|
328
480
|
*/
|
|
329
481
|
function createNodes(schema) {
|
|
482
|
+
if (schema.discriminator !== undefined) {
|
|
483
|
+
return createDiscriminator(schema);
|
|
484
|
+
}
|
|
330
485
|
if (schema.oneOf !== undefined || schema.anyOf !== undefined) {
|
|
331
486
|
return createAnyOneOf(schema);
|
|
332
487
|
}
|
|
@@ -8,8 +8,51 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.createStatusCodes = void 0;
|
|
10
10
|
const createDescription_1 = require("./createDescription");
|
|
11
|
+
const createDetails_1 = require("./createDetails");
|
|
12
|
+
const createDetailsSummary_1 = require("./createDetailsSummary");
|
|
11
13
|
const createSchemaDetails_1 = require("./createSchemaDetails");
|
|
12
14
|
const utils_1 = require("./utils");
|
|
15
|
+
const utils_2 = require("./utils");
|
|
16
|
+
function createResponseHeaders(responseHeaders) {
|
|
17
|
+
return (0, utils_2.guard)(responseHeaders, () => (0, utils_1.create)("ul", {
|
|
18
|
+
style: { marginLeft: "1rem" },
|
|
19
|
+
children: [
|
|
20
|
+
Object.entries(responseHeaders).map(([headerName, headerObj]) => {
|
|
21
|
+
const { description, schema: { type }, example, } = headerObj;
|
|
22
|
+
return (0, utils_1.create)("li", {
|
|
23
|
+
class: "schemaItem",
|
|
24
|
+
children: [
|
|
25
|
+
(0, createDetailsSummary_1.createDetailsSummary)({
|
|
26
|
+
children: [
|
|
27
|
+
(0, utils_1.create)("strong", { children: headerName }),
|
|
28
|
+
(0, utils_2.guard)(type, () => [
|
|
29
|
+
(0, utils_1.create)("span", {
|
|
30
|
+
style: { opacity: "0.6" },
|
|
31
|
+
children: ` ${type}`,
|
|
32
|
+
}),
|
|
33
|
+
]),
|
|
34
|
+
],
|
|
35
|
+
}),
|
|
36
|
+
(0, utils_1.create)("div", {
|
|
37
|
+
children: [
|
|
38
|
+
(0, utils_2.guard)(description, (description) => (0, utils_1.create)("div", {
|
|
39
|
+
style: {
|
|
40
|
+
marginTop: ".5rem",
|
|
41
|
+
marginBottom: ".5rem",
|
|
42
|
+
},
|
|
43
|
+
children: [
|
|
44
|
+
(0, utils_2.guard)(example, () => `Example: ${example}`),
|
|
45
|
+
(0, createDescription_1.createDescription)(description),
|
|
46
|
+
],
|
|
47
|
+
})),
|
|
48
|
+
],
|
|
49
|
+
}),
|
|
50
|
+
],
|
|
51
|
+
});
|
|
52
|
+
}),
|
|
53
|
+
],
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
13
56
|
function createStatusCodes({ responses }) {
|
|
14
57
|
if (responses === undefined) {
|
|
15
58
|
return undefined;
|
|
@@ -22,6 +65,7 @@ function createStatusCodes({ responses }) {
|
|
|
22
65
|
children: [
|
|
23
66
|
(0, utils_1.create)("ApiTabs", {
|
|
24
67
|
children: codes.map((code) => {
|
|
68
|
+
const responseHeaders = responses[code].headers;
|
|
25
69
|
return (0, utils_1.create)("TabItem", {
|
|
26
70
|
label: code,
|
|
27
71
|
value: code,
|
|
@@ -29,6 +73,20 @@ function createStatusCodes({ responses }) {
|
|
|
29
73
|
(0, utils_1.create)("div", {
|
|
30
74
|
children: (0, createDescription_1.createDescription)(responses[code].description),
|
|
31
75
|
}),
|
|
76
|
+
responseHeaders &&
|
|
77
|
+
(0, createDetails_1.createDetails)({
|
|
78
|
+
"data-collaposed": false,
|
|
79
|
+
open: true,
|
|
80
|
+
style: { textAlign: "left" },
|
|
81
|
+
children: [
|
|
82
|
+
(0, createDetailsSummary_1.createDetailsSummary)({
|
|
83
|
+
children: [
|
|
84
|
+
(0, utils_1.create)("strong", { children: "Response Headers" }),
|
|
85
|
+
],
|
|
86
|
+
}),
|
|
87
|
+
createResponseHeaders(responseHeaders),
|
|
88
|
+
],
|
|
89
|
+
}),
|
|
32
90
|
(0, utils_1.create)("div", {
|
|
33
91
|
children: (0, createSchemaDetails_1.createSchemaDetails)({
|
|
34
92
|
title: "Schema",
|
package/lib/markdown/index.js
CHANGED
|
@@ -25,6 +25,7 @@ function createApiPageMD({ title, api: { deprecated, "x-deprecated-description":
|
|
|
25
25
|
`import SchemaItem from "@theme/SchemaItem"\n`,
|
|
26
26
|
`import ApiTabs from "@theme/ApiTabs";\n`,
|
|
27
27
|
`import SchemaTabs from "@theme/SchemaTabs";\n`,
|
|
28
|
+
`import DiscriminatorTabs from "@theme/DiscriminatorTabs";\n`,
|
|
28
29
|
`import TabItem from "@theme/TabItem";\n\n`,
|
|
29
30
|
`## ${(0, lodash_1.escape)(title)}\n\n`,
|
|
30
31
|
(0, createDeprecationNotice_1.createDeprecationNotice)({ deprecated, description: deprecatedDescription }),
|
package/lib/markdown/schema.js
CHANGED
|
@@ -99,6 +99,12 @@ function getQualifierMessage(schema) {
|
|
|
99
99
|
if (schema.pattern) {
|
|
100
100
|
qualifierGroups.push(`Value must match regular expression \`${schema.pattern}\``);
|
|
101
101
|
}
|
|
102
|
+
// Check if discriminator mapping
|
|
103
|
+
const discriminator = schema;
|
|
104
|
+
if (discriminator.mapping) {
|
|
105
|
+
const values = Object.keys(discriminator.mapping);
|
|
106
|
+
qualifierGroups.push(`[${values.map((e) => `\`${e}\``).join(", ")}]`);
|
|
107
|
+
}
|
|
102
108
|
if (schema.enum) {
|
|
103
109
|
qualifierGroups.push(`[${schema.enum.map((e) => `\`${e}\``).join(", ")}]`);
|
|
104
110
|
}
|
|
@@ -15,6 +15,7 @@ const openapi_core_1 = require("@redocly/openapi-core");
|
|
|
15
15
|
const chalk_1 = __importDefault(require("chalk"));
|
|
16
16
|
// @ts-ignore
|
|
17
17
|
const swagger2openapi_1 = require("swagger2openapi");
|
|
18
|
+
const OpenAPIParser_1 = require("./services/OpenAPIParser");
|
|
18
19
|
function serializer(replacer, cycleReplacer) {
|
|
19
20
|
var stack = [], keys = [];
|
|
20
21
|
if (cycleReplacer === undefined)
|
|
@@ -24,6 +25,18 @@ function serializer(replacer, cycleReplacer) {
|
|
|
24
25
|
return value.title ? `circular(${value.title})` : "circular()";
|
|
25
26
|
};
|
|
26
27
|
return function (key, value) {
|
|
28
|
+
// Resolve discriminator ref pointers
|
|
29
|
+
if ((value === null || value === void 0 ? void 0 : value.discriminator) !== undefined) {
|
|
30
|
+
const parser = new OpenAPIParser_1.OpenAPIParser(stack[0]);
|
|
31
|
+
for (let [k, v] of Object.entries(value.discriminator.mapping)) {
|
|
32
|
+
const discriminator = k;
|
|
33
|
+
if (typeof v === "string" && v.charAt(0) === "#") {
|
|
34
|
+
const ref = v;
|
|
35
|
+
const resolvedRef = parser.byRef(ref);
|
|
36
|
+
value.discriminator.mapping[discriminator] = resolvedRef;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
27
40
|
if (stack.length > 0) {
|
|
28
41
|
// @ts-ignore
|
|
29
42
|
var thisPos = stack.indexOf(this);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docusaurus-plugin-openapi-docs",
|
|
3
3
|
"description": "OpenAPI plugin for Docusaurus.",
|
|
4
|
-
"version": "0.0.0-
|
|
4
|
+
"version": "0.0.0-407",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"openapi",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"engines": {
|
|
68
68
|
"node": ">=14"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "8dd2c3d99a5d48f98a5b37aeb3451f68d66ebac0"
|
|
71
71
|
}
|
|
@@ -99,6 +99,7 @@ function createAnyOneOf(schema: SchemaObject): any {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
function createProperties(schema: SchemaObject) {
|
|
102
|
+
const discriminator = schema.discriminator;
|
|
102
103
|
return Object.entries(schema.properties!).map(([key, val]) =>
|
|
103
104
|
createEdges({
|
|
104
105
|
name: key,
|
|
@@ -106,6 +107,7 @@ function createProperties(schema: SchemaObject) {
|
|
|
106
107
|
required: Array.isArray(schema.required)
|
|
107
108
|
? schema.required.includes(key)
|
|
108
109
|
: false,
|
|
110
|
+
discriminator,
|
|
109
111
|
})
|
|
110
112
|
);
|
|
111
113
|
}
|
|
@@ -277,6 +279,110 @@ function createItems(schema: SchemaObject) {
|
|
|
277
279
|
);
|
|
278
280
|
}
|
|
279
281
|
|
|
282
|
+
/**
|
|
283
|
+
* For handling discriminators that do not map to a same-level property
|
|
284
|
+
*/
|
|
285
|
+
function createDiscriminator(schema: SchemaObject) {
|
|
286
|
+
const discriminator = schema.discriminator;
|
|
287
|
+
const propertyName = discriminator?.propertyName;
|
|
288
|
+
const propertyType = "string"; // should always be string
|
|
289
|
+
const mapping: any = discriminator?.mapping;
|
|
290
|
+
|
|
291
|
+
// Explicit mapping is required since we can't support implicit
|
|
292
|
+
if (mapping === undefined) {
|
|
293
|
+
return undefined;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Attempt to get the property description we want to display
|
|
297
|
+
// TODO: how to make it predictable when handling allOf
|
|
298
|
+
let propertyDescription;
|
|
299
|
+
const firstMappingSchema = mapping[Object.keys(mapping)[0]];
|
|
300
|
+
if (firstMappingSchema.properties !== undefined) {
|
|
301
|
+
propertyDescription =
|
|
302
|
+
firstMappingSchema.properties![propertyName!].description;
|
|
303
|
+
}
|
|
304
|
+
if (firstMappingSchema.allOf !== undefined) {
|
|
305
|
+
const { mergedSchemas }: { mergedSchemas: SchemaObject } = mergeAllOf(
|
|
306
|
+
firstMappingSchema.allOf
|
|
307
|
+
);
|
|
308
|
+
if (mergedSchemas.properties !== undefined) {
|
|
309
|
+
propertyDescription =
|
|
310
|
+
mergedSchemas.properties[propertyName!]?.description;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (propertyDescription === undefined) {
|
|
315
|
+
if (
|
|
316
|
+
schema.properties !== undefined &&
|
|
317
|
+
schema.properties![propertyName!] !== undefined
|
|
318
|
+
) {
|
|
319
|
+
propertyDescription = schema.properties![propertyName!].description;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return create("li", {
|
|
324
|
+
className: "discriminatorItem",
|
|
325
|
+
children: create("div", {
|
|
326
|
+
children: [
|
|
327
|
+
create("strong", {
|
|
328
|
+
style: { paddingLeft: "1rem" },
|
|
329
|
+
children: propertyName,
|
|
330
|
+
}),
|
|
331
|
+
guard(propertyType, (name) =>
|
|
332
|
+
create("span", {
|
|
333
|
+
style: { opacity: "0.6" },
|
|
334
|
+
children: ` ${propertyType}`,
|
|
335
|
+
})
|
|
336
|
+
),
|
|
337
|
+
guard(getQualifierMessage(schema.discriminator as any), (message) =>
|
|
338
|
+
create("div", {
|
|
339
|
+
style: {
|
|
340
|
+
paddingLeft: "1rem",
|
|
341
|
+
},
|
|
342
|
+
children: createDescription(message),
|
|
343
|
+
})
|
|
344
|
+
),
|
|
345
|
+
guard(propertyDescription, (description) =>
|
|
346
|
+
create("div", {
|
|
347
|
+
style: {
|
|
348
|
+
paddingLeft: "1rem",
|
|
349
|
+
},
|
|
350
|
+
children: createDescription(description),
|
|
351
|
+
})
|
|
352
|
+
),
|
|
353
|
+
create("DiscriminatorTabs", {
|
|
354
|
+
children: Object.keys(mapping!).map((key, index) => {
|
|
355
|
+
if (mapping[key].allOf !== undefined) {
|
|
356
|
+
const { mergedSchemas }: { mergedSchemas: SchemaObject } =
|
|
357
|
+
mergeAllOf(mapping[key].allOf);
|
|
358
|
+
// Cleanup duplicate property from mapping schema
|
|
359
|
+
delete mergedSchemas.properties![propertyName!];
|
|
360
|
+
mapping[key] = mergedSchemas;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (mapping[key].properties !== undefined) {
|
|
364
|
+
// Cleanup duplicate property from mapping schema
|
|
365
|
+
delete mapping[key].properties![propertyName!];
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const label = key;
|
|
369
|
+
return create("TabItem", {
|
|
370
|
+
label: label,
|
|
371
|
+
value: `${index}-item-discriminator`,
|
|
372
|
+
children: [
|
|
373
|
+
create("div", {
|
|
374
|
+
style: { marginLeft: "-4px" },
|
|
375
|
+
children: createNodes(mapping[key]),
|
|
376
|
+
}),
|
|
377
|
+
],
|
|
378
|
+
});
|
|
379
|
+
}),
|
|
380
|
+
}),
|
|
381
|
+
],
|
|
382
|
+
}),
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
280
386
|
function createDetailsNode(
|
|
281
387
|
name: string,
|
|
282
388
|
schemaName: string,
|
|
@@ -331,18 +437,109 @@ function createDetailsNode(
|
|
|
331
437
|
});
|
|
332
438
|
}
|
|
333
439
|
|
|
440
|
+
/**
|
|
441
|
+
* For handling discriminators that map to a same-level property (like 'petType').
|
|
442
|
+
* Note: These should only be encountered while iterating through properties.
|
|
443
|
+
*/
|
|
444
|
+
function createPropertyDiscriminator(
|
|
445
|
+
name: string,
|
|
446
|
+
schemaName: string,
|
|
447
|
+
schema: SchemaObject,
|
|
448
|
+
discriminator: any,
|
|
449
|
+
required: any
|
|
450
|
+
): any {
|
|
451
|
+
if (schema === undefined) {
|
|
452
|
+
return undefined;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (discriminator.mapping === undefined) {
|
|
456
|
+
return undefined;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return create("li", {
|
|
460
|
+
className: "discriminatorItem",
|
|
461
|
+
children: create("div", {
|
|
462
|
+
children: [
|
|
463
|
+
create("strong", { style: { paddingLeft: "1rem" }, children: name }),
|
|
464
|
+
guard(schemaName, (name) =>
|
|
465
|
+
create("span", {
|
|
466
|
+
style: { opacity: "0.6" },
|
|
467
|
+
children: ` ${schemaName}`,
|
|
468
|
+
})
|
|
469
|
+
),
|
|
470
|
+
guard(required, () => [
|
|
471
|
+
create("strong", {
|
|
472
|
+
style: {
|
|
473
|
+
fontSize: "var(--ifm-code-font-size)",
|
|
474
|
+
color: "var(--openapi-required)",
|
|
475
|
+
},
|
|
476
|
+
children: " required",
|
|
477
|
+
}),
|
|
478
|
+
]),
|
|
479
|
+
guard(getQualifierMessage(discriminator), (message) =>
|
|
480
|
+
create("div", {
|
|
481
|
+
style: {
|
|
482
|
+
paddingLeft: "1rem",
|
|
483
|
+
},
|
|
484
|
+
children: createDescription(message),
|
|
485
|
+
})
|
|
486
|
+
),
|
|
487
|
+
guard(schema.description, (description) =>
|
|
488
|
+
create("div", {
|
|
489
|
+
style: {
|
|
490
|
+
paddingLeft: "1rem",
|
|
491
|
+
},
|
|
492
|
+
children: createDescription(description),
|
|
493
|
+
})
|
|
494
|
+
),
|
|
495
|
+
create("DiscriminatorTabs", {
|
|
496
|
+
children: Object.keys(discriminator?.mapping!).map((key, index) => {
|
|
497
|
+
const label = key;
|
|
498
|
+
return create("TabItem", {
|
|
499
|
+
label: label,
|
|
500
|
+
value: `${index}-item-discriminator`,
|
|
501
|
+
children: [
|
|
502
|
+
create("div", {
|
|
503
|
+
style: { marginLeft: "-4px" },
|
|
504
|
+
children: createNodes(discriminator?.mapping[key]),
|
|
505
|
+
}),
|
|
506
|
+
],
|
|
507
|
+
});
|
|
508
|
+
}),
|
|
509
|
+
}),
|
|
510
|
+
],
|
|
511
|
+
}),
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
|
|
334
515
|
interface EdgeProps {
|
|
335
516
|
name: string;
|
|
336
517
|
schema: SchemaObject;
|
|
337
518
|
required: boolean;
|
|
519
|
+
discriminator?: any | unknown;
|
|
338
520
|
}
|
|
339
521
|
|
|
340
522
|
/**
|
|
341
523
|
* Creates the edges or "leaves" of a schema tree. Edges can branch into sub-nodes with createDetails().
|
|
342
524
|
*/
|
|
343
|
-
function createEdges({
|
|
525
|
+
function createEdges({
|
|
526
|
+
name,
|
|
527
|
+
schema,
|
|
528
|
+
required,
|
|
529
|
+
discriminator,
|
|
530
|
+
}: EdgeProps): any {
|
|
344
531
|
const schemaName = getSchemaName(schema);
|
|
345
532
|
|
|
533
|
+
if (discriminator !== undefined && discriminator.propertyName === name) {
|
|
534
|
+
return createPropertyDiscriminator(
|
|
535
|
+
name,
|
|
536
|
+
"string",
|
|
537
|
+
schema,
|
|
538
|
+
discriminator,
|
|
539
|
+
required
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
|
|
346
543
|
if (schema.oneOf !== undefined || schema.anyOf !== undefined) {
|
|
347
544
|
return createDetailsNode(name, schemaName, schema, required);
|
|
348
545
|
}
|
|
@@ -409,6 +606,10 @@ function createEdges({ name, schema, required }: EdgeProps): any {
|
|
|
409
606
|
* Creates a hierarchical level of a schema tree. Nodes produce edges that can branch into sub-nodes with edges, recursively.
|
|
410
607
|
*/
|
|
411
608
|
function createNodes(schema: SchemaObject): any {
|
|
609
|
+
if (schema.discriminator !== undefined) {
|
|
610
|
+
return createDiscriminator(schema);
|
|
611
|
+
}
|
|
612
|
+
|
|
412
613
|
if (schema.oneOf !== undefined || schema.anyOf !== undefined) {
|
|
413
614
|
return createAnyOneOf(schema);
|
|
414
615
|
}
|
|
@@ -7,13 +7,66 @@
|
|
|
7
7
|
|
|
8
8
|
import { ApiItem } from "../types";
|
|
9
9
|
import { createDescription } from "./createDescription";
|
|
10
|
+
import { createDetails } from "./createDetails";
|
|
11
|
+
import { createDetailsSummary } from "./createDetailsSummary";
|
|
10
12
|
import { createSchemaDetails } from "./createSchemaDetails";
|
|
11
13
|
import { create } from "./utils";
|
|
14
|
+
import { guard } from "./utils";
|
|
12
15
|
|
|
13
16
|
interface Props {
|
|
14
17
|
responses: ApiItem["responses"];
|
|
15
18
|
}
|
|
16
19
|
|
|
20
|
+
function createResponseHeaders(responseHeaders: any) {
|
|
21
|
+
return guard(responseHeaders, () =>
|
|
22
|
+
create("ul", {
|
|
23
|
+
style: { marginLeft: "1rem" },
|
|
24
|
+
children: [
|
|
25
|
+
Object.entries(responseHeaders).map(([headerName, headerObj]) => {
|
|
26
|
+
const {
|
|
27
|
+
description,
|
|
28
|
+
schema: { type },
|
|
29
|
+
example,
|
|
30
|
+
}: any = headerObj;
|
|
31
|
+
|
|
32
|
+
return create("li", {
|
|
33
|
+
class: "schemaItem",
|
|
34
|
+
children: [
|
|
35
|
+
createDetailsSummary({
|
|
36
|
+
children: [
|
|
37
|
+
create("strong", { children: headerName }),
|
|
38
|
+
guard(type, () => [
|
|
39
|
+
create("span", {
|
|
40
|
+
style: { opacity: "0.6" },
|
|
41
|
+
children: ` ${type}`,
|
|
42
|
+
}),
|
|
43
|
+
]),
|
|
44
|
+
],
|
|
45
|
+
}),
|
|
46
|
+
create("div", {
|
|
47
|
+
children: [
|
|
48
|
+
guard(description, (description) =>
|
|
49
|
+
create("div", {
|
|
50
|
+
style: {
|
|
51
|
+
marginTop: ".5rem",
|
|
52
|
+
marginBottom: ".5rem",
|
|
53
|
+
},
|
|
54
|
+
children: [
|
|
55
|
+
guard(example, () => `Example: ${example}`),
|
|
56
|
+
createDescription(description),
|
|
57
|
+
],
|
|
58
|
+
})
|
|
59
|
+
),
|
|
60
|
+
],
|
|
61
|
+
}),
|
|
62
|
+
],
|
|
63
|
+
});
|
|
64
|
+
}),
|
|
65
|
+
],
|
|
66
|
+
})
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
17
70
|
export function createStatusCodes({ responses }: Props) {
|
|
18
71
|
if (responses === undefined) {
|
|
19
72
|
return undefined;
|
|
@@ -28,6 +81,7 @@ export function createStatusCodes({ responses }: Props) {
|
|
|
28
81
|
children: [
|
|
29
82
|
create("ApiTabs", {
|
|
30
83
|
children: codes.map((code) => {
|
|
84
|
+
const responseHeaders: any = responses[code].headers;
|
|
31
85
|
return create("TabItem", {
|
|
32
86
|
label: code,
|
|
33
87
|
value: code,
|
|
@@ -35,6 +89,20 @@ export function createStatusCodes({ responses }: Props) {
|
|
|
35
89
|
create("div", {
|
|
36
90
|
children: createDescription(responses[code].description),
|
|
37
91
|
}),
|
|
92
|
+
responseHeaders &&
|
|
93
|
+
createDetails({
|
|
94
|
+
"data-collaposed": false,
|
|
95
|
+
open: true,
|
|
96
|
+
style: { textAlign: "left" },
|
|
97
|
+
children: [
|
|
98
|
+
createDetailsSummary({
|
|
99
|
+
children: [
|
|
100
|
+
create("strong", { children: "Response Headers" }),
|
|
101
|
+
],
|
|
102
|
+
}),
|
|
103
|
+
createResponseHeaders(responseHeaders),
|
|
104
|
+
],
|
|
105
|
+
}),
|
|
38
106
|
create("div", {
|
|
39
107
|
children: createSchemaDetails({
|
|
40
108
|
title: "Schema",
|
package/src/markdown/index.ts
CHANGED
|
@@ -41,6 +41,7 @@ export function createApiPageMD({
|
|
|
41
41
|
`import SchemaItem from "@theme/SchemaItem"\n`,
|
|
42
42
|
`import ApiTabs from "@theme/ApiTabs";\n`,
|
|
43
43
|
`import SchemaTabs from "@theme/SchemaTabs";\n`,
|
|
44
|
+
`import DiscriminatorTabs from "@theme/DiscriminatorTabs";\n`,
|
|
44
45
|
`import TabItem from "@theme/TabItem";\n\n`,
|
|
45
46
|
`## ${escape(title)}\n\n`,
|
|
46
47
|
createDeprecationNotice({ deprecated, description: deprecatedDescription }),
|
package/src/markdown/schema.ts
CHANGED
|
@@ -115,6 +115,13 @@ export function getQualifierMessage(schema?: SchemaObject): string | undefined {
|
|
|
115
115
|
);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
// Check if discriminator mapping
|
|
119
|
+
const discriminator = schema as any;
|
|
120
|
+
if (discriminator.mapping) {
|
|
121
|
+
const values = Object.keys(discriminator.mapping);
|
|
122
|
+
qualifierGroups.push(`[${values.map((e) => `\`${e}\``).join(", ")}]`);
|
|
123
|
+
}
|
|
124
|
+
|
|
118
125
|
if (schema.enum) {
|
|
119
126
|
qualifierGroups.push(`[${schema.enum.map((e) => `\`${e}\``).join(", ")}]`);
|
|
120
127
|
}
|
|
@@ -14,6 +14,7 @@ import chalk from "chalk";
|
|
|
14
14
|
import { convertObj } from "swagger2openapi";
|
|
15
15
|
|
|
16
16
|
import { OpenApiObject } from "../types";
|
|
17
|
+
import { OpenAPIParser } from "./services/OpenAPIParser";
|
|
17
18
|
|
|
18
19
|
function serializer(replacer: any, cycleReplacer: any) {
|
|
19
20
|
var stack: any = [],
|
|
@@ -26,6 +27,18 @@ function serializer(replacer: any, cycleReplacer: any) {
|
|
|
26
27
|
};
|
|
27
28
|
|
|
28
29
|
return function (key: any, value: any) {
|
|
30
|
+
// Resolve discriminator ref pointers
|
|
31
|
+
if (value?.discriminator !== undefined) {
|
|
32
|
+
const parser = new OpenAPIParser(stack[0]);
|
|
33
|
+
for (let [k, v] of Object.entries(value.discriminator.mapping)) {
|
|
34
|
+
const discriminator = k as string;
|
|
35
|
+
if (typeof v === "string" && v.charAt(0) === "#") {
|
|
36
|
+
const ref = v as string;
|
|
37
|
+
const resolvedRef = parser.byRef(ref);
|
|
38
|
+
value.discriminator.mapping[discriminator] = resolvedRef;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
29
42
|
if (stack.length > 0) {
|
|
30
43
|
// @ts-ignore
|
|
31
44
|
var thisPos = stack.indexOf(this);
|