docusaurus-plugin-openapi-docs 0.0.0-394 → 0.0.0-397

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.
@@ -6,19 +6,19 @@
6
6
  * ========================================================================== */
7
7
 
8
8
  import { MediaTypeObject, SchemaObject } from "../openapi/types";
9
- import { createAnyOneOf } from "./createAnyOneOf";
10
9
  import { createDescription } from "./createDescription";
11
10
  import { createDetails } from "./createDetails";
12
11
  import { createDetailsSummary } from "./createDetailsSummary";
13
12
  import { getQualifierMessage, getSchemaName } from "./schema";
14
13
  import { create, guard } from "./utils";
15
14
 
16
- const mergeAllOf = require("json-schema-merge-allof");
15
+ const jsonSchemaMergeAllOf = require("json-schema-merge-allof");
17
16
 
18
- function resolveAllOf(allOf: SchemaObject[]) {
19
- // Use external library to resolve and merge nested allOf schemas
20
- let properties: SchemaObject = {};
21
- const mergedSchemas = mergeAllOf(allOf, {
17
+ /**
18
+ * Returns a merged representation of allOf array of schemas.
19
+ */
20
+ function mergeAllOf(allOf: SchemaObject[]) {
21
+ const mergedSchemas = jsonSchemaMergeAllOf(allOf, {
22
22
  resolvers: {
23
23
  readOnly: function () {
24
24
  return true;
@@ -29,227 +29,444 @@ function resolveAllOf(allOf: SchemaObject[]) {
29
29
  },
30
30
  });
31
31
 
32
- if (mergedSchemas.properties) {
33
- properties = mergedSchemas.properties;
34
- }
35
-
36
32
  const required = allOf.reduce((acc, cur) => {
37
33
  if (Array.isArray(cur.required)) {
38
34
  const next = [...acc, ...cur.required];
39
35
  return next;
40
36
  }
41
37
  return acc;
42
- }, [] as string[]);
38
+ }, [] as any);
43
39
 
44
- return { properties, required };
40
+ return { mergedSchemas, required };
45
41
  }
46
42
 
47
- interface RowProps {
48
- name: string;
49
- schema: SchemaObject;
50
- required: boolean;
43
+ /**
44
+ * For handling nested anyOf/oneOf.
45
+ */
46
+ function createAnyOneOf(schema: SchemaObject): any {
47
+ const type = schema.oneOf ? "oneOf" : "anyOf";
48
+ return create("li", {
49
+ children: [
50
+ create("div", {
51
+ children: [
52
+ create("span", {
53
+ className: "badge badge--info",
54
+ children: type,
55
+ }),
56
+ create("SchemaTabs", {
57
+ children: schema[type]!.map((anyOneSchema, index) => {
58
+ const label = anyOneSchema.title
59
+ ? anyOneSchema.title
60
+ : `MOD${index + 1}`;
61
+ const anyOneChildren = [];
62
+
63
+ if (anyOneSchema.properties !== undefined) {
64
+ anyOneChildren.push(createProperties(anyOneSchema));
65
+ }
66
+
67
+ if (anyOneSchema.allOf !== undefined) {
68
+ anyOneChildren.push(createNodes(anyOneSchema));
69
+ }
70
+
71
+ if (anyOneSchema.items !== undefined) {
72
+ anyOneChildren.push(createItems(anyOneSchema));
73
+ }
74
+
75
+ if (
76
+ anyOneSchema.type === "string" ||
77
+ anyOneSchema.type === "number" ||
78
+ anyOneSchema.type === "integer" ||
79
+ anyOneSchema.type === "boolean"
80
+ ) {
81
+ anyOneChildren.push(createNodes(anyOneSchema));
82
+ }
83
+
84
+ if (anyOneChildren.length) {
85
+ return create("TabItem", {
86
+ label: label,
87
+ value: `${index}-item-properties`,
88
+ children: anyOneChildren,
89
+ });
90
+ }
91
+
92
+ return undefined;
93
+ }),
94
+ }),
95
+ ],
96
+ }),
97
+ ],
98
+ });
51
99
  }
52
100
 
53
- function createRow({ name, schema, required }: RowProps) {
54
- const schemaName = getSchemaName(schema, true);
55
- if (schemaName && (schemaName === "object" || schemaName === "object[]")) {
56
- return create("SchemaItem", {
57
- collapsible: true,
58
- className: "schemaItem",
59
- children: [
60
- createDetails({
101
+ function createProperties(schema: SchemaObject) {
102
+ return Object.entries(schema.properties!).map(([key, val]) =>
103
+ createEdges({
104
+ name: key,
105
+ schema: val,
106
+ required: Array.isArray(schema.required)
107
+ ? schema.required.includes(key)
108
+ : false,
109
+ })
110
+ );
111
+ }
112
+
113
+ function createAdditionalProperties(schema: SchemaObject) {
114
+ // TODO?:
115
+ // {
116
+ // description: 'Integration configuration. See \n' +
117
+ // '[Integration Configurations](https://prisma.pan.dev/api/cloud/api-integration-config/).\n',
118
+ // example: { webhookUrl: 'https://hooks.slack.com/abcdef' },
119
+ // externalDocs: { url: 'https://prisma.pan.dev/api/cloud/api-integration-config' },
120
+ // type: 'object'
121
+ // }
122
+
123
+ // TODO?:
124
+ // {
125
+ // items: {
126
+ // properties: {
127
+ // aliasField: [Object],
128
+ // displayName: [Object],
129
+ // fieldName: [Object],
130
+ // maxLength: [Object],
131
+ // options: [Object],
132
+ // redlockMapping: [Object],
133
+ // required: [Object],
134
+ // type: [Object],
135
+ // typeaheadUri: [Object],
136
+ // value: [Object]
137
+ // },
138
+ // type: 'object'
139
+ // },
140
+ // type: 'array'
141
+ // }
142
+
143
+ if (
144
+ schema.additionalProperties?.type === "string" ||
145
+ schema.additionalProperties?.type === "object" ||
146
+ schema.additionalProperties?.type === "boolean" ||
147
+ schema.additionalProperties?.type === "integer" ||
148
+ schema.additionalProperties?.type === "number"
149
+ ) {
150
+ const type = schema.additionalProperties?.type;
151
+ const additionalProperties =
152
+ schema.additionalProperties?.additionalProperties;
153
+ if (additionalProperties !== undefined) {
154
+ const type = schema.additionalProperties?.additionalProperties?.type;
155
+ const format = schema.additionalProperties?.additionalProperties?.format;
156
+ return create("li", {
157
+ children: create("div", {
61
158
  children: [
62
- createDetailsSummary({
63
- children: [
64
- create("strong", { children: name }),
65
- create("span", {
66
- style: { opacity: "0.6" },
67
- children: ` ${schemaName}`,
68
- }),
69
- guard(required, () => [
70
- create("strong", {
71
- style: {
72
- fontSize: "var(--ifm-code-font-size)",
73
- color: "var(--openapi-required)",
74
- },
75
- children: " required",
76
- }),
77
- ]),
78
- ],
79
- }),
80
- create("div", {
81
- style: { marginLeft: "1rem" },
82
- children: [
83
- guard(getQualifierMessage(schema), (message) =>
84
- create("div", {
85
- style: { marginTop: ".5rem", marginBottom: ".5rem" },
86
- children: createDescription(message),
87
- })
88
- ),
89
- guard(schema.description, (description) =>
90
- create("div", {
91
- style: { marginTop: ".5rem", marginBottom: ".5rem" },
92
- children: createDescription(description),
93
- })
94
- ),
95
- createRows({ schema: schema }),
96
- ],
97
- }),
159
+ create("code", { children: `property name*` }),
160
+ guard(type, (type) =>
161
+ create("span", {
162
+ style: { opacity: "0.6" },
163
+ children: ` ${type}`,
164
+ })
165
+ ),
166
+ guard(format, (format) =>
167
+ create("span", {
168
+ style: { opacity: "0.6" },
169
+ children: ` (${format})`,
170
+ })
171
+ ),
172
+ guard(getQualifierMessage(schema.additionalProperties), (message) =>
173
+ create("div", {
174
+ style: { marginTop: "var(--ifm-table-cell-padding)" },
175
+ children: createDescription(message),
176
+ })
177
+ ),
98
178
  ],
99
179
  }),
100
- ],
180
+ });
181
+ }
182
+ return create("li", {
183
+ children: create("div", {
184
+ children: [
185
+ create("code", { children: `property name*` }),
186
+ guard(type, (type) =>
187
+ create("span", {
188
+ style: { opacity: "0.6" },
189
+ children: ` ${type}`,
190
+ })
191
+ ),
192
+ guard(getQualifierMessage(schema.additionalProperties), (message) =>
193
+ create("div", {
194
+ style: { marginTop: "var(--ifm-table-cell-padding)" },
195
+ children: createDescription(message),
196
+ })
197
+ ),
198
+ ],
199
+ }),
101
200
  });
102
201
  }
202
+ return Object.entries(schema.additionalProperties!).map(([key, val]) =>
203
+ createEdges({
204
+ name: key,
205
+ schema: val,
206
+ required: Array.isArray(schema.required)
207
+ ? schema.required.includes(key)
208
+ : false,
209
+ })
210
+ );
211
+ }
212
+
213
+ // TODO: figure out how to handle array of objects
214
+ function createItems(schema: SchemaObject) {
215
+ if (schema.items?.properties !== undefined) {
216
+ return createProperties(schema.items);
217
+ }
218
+
219
+ if (schema.items?.additionalProperties !== undefined) {
220
+ return createAdditionalProperties(schema.items);
221
+ }
103
222
 
223
+ if (schema.items?.oneOf !== undefined || schema.items?.anyOf !== undefined) {
224
+ return createAnyOneOf(schema.items!);
225
+ }
226
+
227
+ if (schema.items?.allOf !== undefined) {
228
+ const { mergedSchemas }: { mergedSchemas: SchemaObject; required: any } =
229
+ mergeAllOf(schema.items?.allOf);
230
+
231
+ // Handles combo anyOf/oneOf + properties
232
+ if (
233
+ (mergedSchemas.oneOf !== undefined ||
234
+ mergedSchemas.anyOf !== undefined) &&
235
+ mergedSchemas.properties
236
+ ) {
237
+ return create("div", {
238
+ children: [
239
+ createAnyOneOf(mergedSchemas),
240
+ createProperties(mergedSchemas),
241
+ ],
242
+ });
243
+ }
244
+
245
+ // Handles only anyOf/oneOf
246
+ if (
247
+ mergedSchemas.oneOf !== undefined ||
248
+ mergedSchemas.anyOf !== undefined
249
+ ) {
250
+ return create("div", {
251
+ children: [
252
+ createAnyOneOf(mergedSchemas),
253
+ createProperties(mergedSchemas),
254
+ ],
255
+ });
256
+ }
257
+ }
258
+
259
+ if (
260
+ schema.items?.type === "string" ||
261
+ schema.items?.type === "number" ||
262
+ schema.items?.type === "integer" ||
263
+ schema.items?.type === "boolean"
264
+ ) {
265
+ return createNodes(schema.items);
266
+ }
267
+
268
+ // TODO: clean this up or eliminate it?
269
+ return Object.entries(schema.items!).map(([key, val]) =>
270
+ createEdges({
271
+ name: key,
272
+ schema: val,
273
+ required: Array.isArray(schema.required)
274
+ ? schema.required.includes(key)
275
+ : false,
276
+ })
277
+ );
278
+ }
279
+
280
+ function createDetailsNode(
281
+ name: string,
282
+ schemaName: string,
283
+ schema: SchemaObject,
284
+ required: any
285
+ ): any {
104
286
  return create("SchemaItem", {
105
- collapsible: false,
106
- name,
107
- required,
108
- schemaDescription: schema.description,
109
- schemaName: getSchemaName(schema, true),
110
- qualifierMessage: getQualifierMessage(schema),
287
+ collapsible: true,
288
+ className: "schemaItem",
289
+ children: [
290
+ createDetails({
291
+ children: [
292
+ createDetailsSummary({
293
+ children: [
294
+ create("strong", { children: name }),
295
+ create("span", {
296
+ style: { opacity: "0.6" },
297
+ children: ` ${schemaName}`,
298
+ }),
299
+ guard(required, () => [
300
+ create("strong", {
301
+ style: {
302
+ fontSize: "var(--ifm-code-font-size)",
303
+ color: "var(--openapi-required)",
304
+ },
305
+ children: " required",
306
+ }),
307
+ ]),
308
+ ],
309
+ }),
310
+ create("div", {
311
+ style: { marginLeft: "1rem" },
312
+ children: [
313
+ guard(getQualifierMessage(schema), (message) =>
314
+ create("div", {
315
+ style: { marginTop: ".5rem", marginBottom: ".5rem" },
316
+ children: createDescription(message),
317
+ })
318
+ ),
319
+ guard(schema.description, (description) =>
320
+ create("div", {
321
+ style: { marginTop: ".5rem", marginBottom: ".5rem" },
322
+ children: createDescription(description),
323
+ })
324
+ ),
325
+ createNodes(schema),
326
+ ],
327
+ }),
328
+ ],
329
+ }),
330
+ ],
111
331
  });
112
332
  }
113
333
 
114
- interface RowsProps {
334
+ interface EdgeProps {
335
+ name: string;
115
336
  schema: SchemaObject;
337
+ required: boolean;
116
338
  }
117
339
 
118
- function createRows({ schema }: RowsProps): string | undefined {
119
- // object
120
- if (schema.properties !== undefined) {
121
- return create("ul", {
122
- children: Object.entries(schema.properties).map(([key, val]) =>
123
- createRow({
124
- name: key,
125
- schema: val,
126
- required: Array.isArray(schema.required)
127
- ? schema.required.includes(key)
128
- : false,
129
- })
130
- ),
131
- });
340
+ /**
341
+ * Creates the edges or "leaves" of a schema tree. Edges can branch into sub-nodes with createDetails().
342
+ */
343
+ function createEdges({ name, schema, required }: EdgeProps): any {
344
+ const schemaName = getSchemaName(schema);
345
+
346
+ if (schema.oneOf !== undefined || schema.anyOf !== undefined) {
347
+ return createDetailsNode(name, schemaName, schema, required);
132
348
  }
133
349
 
134
- // TODO: This can be a bit complicated types can be missmatched and there can be nested allOfs which need to be resolved before merging properties
135
350
  if (schema.allOf !== undefined) {
136
- const { properties, required } = resolveAllOf(schema.allOf);
137
- return create("div", {
138
- children: [
139
- create("span", {
140
- className: "badge badge--info",
141
- style: { marginBottom: "1rem" },
142
- children: "allOf",
143
- }),
144
- Object.entries(properties).map(([key, val]) =>
145
- createRow({
146
- name: key,
147
- schema: val,
148
- required: Array.isArray(required) ? required.includes(key) : false,
149
- })
150
- ),
151
- ],
351
+ const {
352
+ mergedSchemas,
353
+ required,
354
+ }: { mergedSchemas: SchemaObject; required: any } = mergeAllOf(
355
+ schema.allOf
356
+ );
357
+ const mergedSchemaName = getSchemaName(mergedSchemas);
358
+
359
+ if (
360
+ mergedSchemas.oneOf !== undefined ||
361
+ mergedSchemas.anyOf !== undefined
362
+ ) {
363
+ return createDetailsNode(name, mergedSchemaName, mergedSchemas, required);
364
+ }
365
+
366
+ if (mergedSchemas.properties !== undefined) {
367
+ return createDetailsNode(name, mergedSchemaName, mergedSchemas, required);
368
+ }
369
+
370
+ if (mergedSchemas.additionalProperties !== undefined) {
371
+ return createDetailsNode(name, mergedSchemaName, mergedSchemas, required);
372
+ }
373
+
374
+ return create("SchemaItem", {
375
+ collapsible: false,
376
+ name,
377
+ required,
378
+ schemaDescription: mergedSchemas.description,
379
+ schemaName: schemaName,
380
+ qualifierMessage: getQualifierMessage(schema),
152
381
  });
153
382
  }
154
383
 
155
- // Adds support one more level deep
156
- if (schema.oneOf !== undefined) {
157
- return createAnyOneOf(schema.oneOf, "oneOf");
384
+ if (schema.properties !== undefined) {
385
+ return createDetailsNode(name, schemaName, schema, required);
158
386
  }
159
387
 
160
- if (schema.anyOf !== undefined) {
161
- return createAnyOneOf(schema.anyOf, "anyOf");
388
+ if (schema.additionalProperties !== undefined) {
389
+ return createDetailsNode(name, schemaName, schema, required);
162
390
  }
163
391
 
164
- // array
165
- if (schema.items !== undefined) {
166
- return createRows({ schema: schema.items });
392
+ // array of objects
393
+ if (schema.items?.properties !== undefined) {
394
+ return createDetailsNode(name, schemaName, schema, required);
167
395
  }
168
396
 
169
- // primitive
170
- return undefined;
171
- }
172
-
173
- interface RowsRootProps {
174
- schema: SchemaObject;
397
+ // primitives and array of non-objects
398
+ return create("SchemaItem", {
399
+ collapsible: false,
400
+ name,
401
+ required,
402
+ schemaDescription: schema.description,
403
+ schemaName: schemaName,
404
+ qualifierMessage: getQualifierMessage(schema),
405
+ });
175
406
  }
176
407
 
177
- function createRowsRoot({ schema }: RowsRootProps): any {
178
- // object
179
- if (schema.properties !== undefined) {
180
- return Object.entries(schema.properties).map(([key, val]) =>
181
- createRow({
182
- name: key,
183
- schema: val,
184
- required: Array.isArray(schema.required)
185
- ? schema.required.includes(key)
186
- : false,
187
- })
188
- );
408
+ /**
409
+ * Creates a hierarchical level of a schema tree. Nodes produce edges that can branch into sub-nodes with edges, recursively.
410
+ */
411
+ function createNodes(schema: SchemaObject): any {
412
+ if (schema.oneOf !== undefined || schema.anyOf !== undefined) {
413
+ return createAnyOneOf(schema);
189
414
  }
190
415
 
191
- // TODO: This can be a bit complicated types can be missmatched and there can be nested allOfs which need to be resolved before merging properties
192
416
  if (schema.allOf !== undefined) {
193
- const { properties, required } = resolveAllOf(schema.allOf);
194
- return create("div", {
195
- children: [
196
- create("span", {
197
- className: "badge badge--info",
198
- style: { marginBottom: "1rem" },
199
- children: "allOf",
200
- }),
201
- Object.entries(properties).map(([key, val]) =>
202
- createRow({
203
- name: key,
204
- schema: val,
205
- required: Array.isArray(required) ? required.includes(key) : false,
206
- })
207
- ),
208
- ],
209
- });
417
+ const { mergedSchemas } = mergeAllOf(schema.allOf);
418
+
419
+ // allOf seems to always result in properties
420
+ if (mergedSchemas.properties !== undefined) {
421
+ return createProperties(mergedSchemas);
422
+ }
210
423
  }
211
424
 
212
- // TODO: This is top-level only - add support for nested oneOf/anyOf
213
- if (schema.oneOf !== undefined) {
214
- return createAnyOneOf(schema.oneOf, "oneOf");
425
+ if (schema.properties !== undefined) {
426
+ return createProperties(schema);
215
427
  }
216
428
 
217
- if (schema.anyOf !== undefined) {
218
- return createAnyOneOf(schema.anyOf, "anyOf");
429
+ if (schema.additionalProperties !== undefined) {
430
+ return createAdditionalProperties(schema);
219
431
  }
220
432
 
221
- // array
433
+ // TODO: figure out how to handle array of objects
222
434
  if (schema.items !== undefined) {
435
+ return createItems(schema);
436
+ }
437
+
438
+ // primitive
439
+ if (schema.type !== undefined) {
223
440
  return create("li", {
224
441
  children: create("div", {
225
- children: [createRows({ schema: schema.items })],
442
+ children: [
443
+ create("strong", { children: schema.type }),
444
+ guard(schema.format, (format) =>
445
+ create("span", {
446
+ style: { opacity: "0.6" },
447
+ children: ` ${format}`,
448
+ })
449
+ ),
450
+ guard(getQualifierMessage(schema), (message) =>
451
+ create("div", {
452
+ style: { marginTop: "var(--ifm-table-cell-padding)" },
453
+ children: createDescription(message),
454
+ })
455
+ ),
456
+ guard(schema.description, (description) =>
457
+ create("div", {
458
+ style: { marginTop: "var(--ifm-table-cell-padding)" },
459
+ children: createDescription(description),
460
+ })
461
+ ),
462
+ ],
226
463
  }),
227
464
  });
228
465
  }
229
466
 
230
- // primitive
231
- return create("li", {
232
- children: create("div", {
233
- children: [
234
- create("span", {
235
- style: { opacity: "0.6" },
236
- children: ` ${schema.type}`,
237
- }),
238
- guard(getQualifierMessage(schema), (message) =>
239
- create("div", {
240
- style: { marginTop: "var(--ifm-table-cell-padding)" },
241
- children: createDescription(message),
242
- })
243
- ),
244
- guard(schema.description, (description) =>
245
- create("div", {
246
- style: { marginTop: "var(--ifm-table-cell-padding)" },
247
- children: createDescription(description),
248
- })
249
- ),
250
- ],
251
- }),
252
- });
467
+ // Unknown node/schema type should return undefined
468
+ // So far, haven't seen this hit in testing
469
+ return undefined;
253
470
  }
254
471
 
255
472
  interface Props {
@@ -274,7 +491,6 @@ export function createSchemaDetails({ title, body, ...rest }: Props) {
274
491
  return undefined;
275
492
  }
276
493
 
277
- // TODO:
278
494
  // NOTE: We just pick a random content-type.
279
495
  // How common is it to have multiple?
280
496
  const randomFirstKey = Object.keys(body.content)[0];
@@ -291,6 +507,7 @@ export function createSchemaDetails({ title, body, ...rest }: Props) {
291
507
  }
292
508
  }
293
509
 
510
+ // Root-level schema dropdown
294
511
  return createDetails({
295
512
  "data-collapsed": false,
296
513
  open: true,
@@ -300,6 +517,12 @@ export function createSchemaDetails({ title, body, ...rest }: Props) {
300
517
  style: { textAlign: "left" },
301
518
  children: [
302
519
  create("strong", { children: `${title}` }),
520
+ guard(firstBody.type === "array", (format) =>
521
+ create("span", {
522
+ style: { opacity: "0.6" },
523
+ children: ` array`,
524
+ })
525
+ ),
303
526
  guard(body.required, () => [
304
527
  create("strong", {
305
528
  style: {
@@ -324,7 +547,7 @@ export function createSchemaDetails({ title, body, ...rest }: Props) {
324
547
  }),
325
548
  create("ul", {
326
549
  style: { marginLeft: "1rem" },
327
- children: createRowsRoot({ schema: firstBody }),
550
+ children: createNodes(firstBody),
328
551
  }),
329
552
  ],
330
553
  });