docusaurus-plugin-openapi-docs 0.0.0-396 → 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,18 +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
- 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, {
21
22
  resolvers: {
22
23
  readOnly: function () {
23
24
  return true;
@@ -34,298 +35,438 @@ function resolveAllOf(allOf: SchemaObject[]) {
34
35
  return next;
35
36
  }
36
37
  return acc;
37
- }, [] as string[]);
38
+ }, [] as any);
38
39
 
39
40
  return { mergedSchemas, required };
40
41
  }
41
42
 
42
- interface RowProps {
43
- name: string;
44
- schema: SchemaObject;
45
- 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
+ });
46
99
  }
47
100
 
48
- function createRow({ name, schema, required }: RowProps) {
49
- const schemaName = getSchemaName(schema);
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
+ }
50
112
 
51
- // array
52
- if (schema.type === "array" && schema.items) {
53
- return create("SchemaItem", {
54
- collapsible: true,
55
- className: "schemaItem",
56
- children: [
57
- createDetails({
58
- children: [
59
- createDetailsSummary({
60
- children: [
61
- create("strong", { children: name }),
62
- create("span", {
63
- style: { opacity: "0.6" },
64
- children: ` ${schemaName}`,
65
- }),
66
- guard(required, () => [
67
- create("strong", {
68
- style: {
69
- fontSize: "var(--ifm-code-font-size)",
70
- color: "var(--openapi-required)",
71
- },
72
- children: " required",
73
- }),
74
- ]),
75
- ],
76
- }),
77
- create("div", {
78
- style: { marginLeft: "1rem" },
79
- children: [
80
- guard(getQualifierMessage(schema), (message) =>
81
- create("div", {
82
- style: { marginTop: ".5rem", marginBottom: ".5rem" },
83
- children: createDescription(message),
84
- })
85
- ),
86
- guard(schema.description, (description) =>
87
- create("div", {
88
- style: { marginTop: ".5rem", marginBottom: ".5rem" },
89
- children: createDescription(description),
90
- })
91
- ),
92
- createRows({ schema: schema.items }),
93
- ],
94
- }),
95
- ],
96
- }),
97
- ],
98
- });
99
- }
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
+ // }
100
142
 
101
- if (schemaName && (schemaName === "object" || schemaName === "object[]")) {
102
- return create("SchemaItem", {
103
- collapsible: true,
104
- className: "schemaItem",
105
- children: [
106
- createDetails({
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", {
107
158
  children: [
108
- createDetailsSummary({
109
- children: [
110
- create("strong", { children: name }),
111
- create("span", {
112
- style: { opacity: "0.6" },
113
- children: ` ${schemaName}`,
114
- }),
115
- guard(required, () => [
116
- create("strong", {
117
- style: {
118
- fontSize: "var(--ifm-code-font-size)",
119
- color: "var(--openapi-required)",
120
- },
121
- children: " required",
122
- }),
123
- ]),
124
- ],
125
- }),
126
- create("div", {
127
- style: { marginLeft: "1rem" },
128
- children: [
129
- guard(getQualifierMessage(schema), (message) =>
130
- create("div", {
131
- style: { marginTop: ".5rem", marginBottom: ".5rem" },
132
- children: createDescription(message),
133
- })
134
- ),
135
- guard(schema.description, (description) =>
136
- create("div", {
137
- style: { marginTop: ".5rem", marginBottom: ".5rem" },
138
- children: createDescription(description),
139
- })
140
- ),
141
- createRows({ schema: schema }),
142
- ],
143
- }),
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
+ ),
144
178
  ],
145
179
  }),
146
- ],
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
+ }),
147
200
  });
148
201
  }
149
-
150
- // primitive
151
- return create("SchemaItem", {
152
- collapsible: false,
153
- name,
154
- required,
155
- schemaDescription: schema.description,
156
- schemaName: schemaName,
157
- qualifierMessage: getQualifierMessage(schema),
158
- });
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
+ );
159
211
  }
160
212
 
161
- interface RowsProps {
162
- schema: SchemaObject;
163
- }
164
-
165
- export function createRows({ schema }: RowsProps): string | undefined {
166
- // oneOf
167
- if (schema.oneOf !== undefined) {
168
- return createAnyOneOf(schema.oneOf, "oneOf");
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);
169
217
  }
170
218
 
171
- // anyOf
172
- if (schema.anyOf !== undefined) {
173
- return createAnyOneOf(schema.anyOf, "anyOf");
219
+ if (schema.items?.additionalProperties !== undefined) {
220
+ return createAdditionalProperties(schema.items);
174
221
  }
175
222
 
176
- // object
177
- if (schema.properties !== undefined) {
178
- return create("ul", {
179
- children: Object.entries(schema.properties).map(([key, val]) =>
180
- createRow({
181
- name: key,
182
- schema: val,
183
- required: Array.isArray(schema.required)
184
- ? schema.required.includes(key)
185
- : false,
186
- })
187
- ),
188
- });
223
+ if (schema.items?.oneOf !== undefined || schema.items?.anyOf !== undefined) {
224
+ return createAnyOneOf(schema.items!);
189
225
  }
190
226
 
191
- // allOf
192
- if (schema.allOf !== undefined) {
193
- const {
194
- mergedSchemas,
195
- required,
196
- }: { mergedSchemas: SchemaObject; required: string[] } = resolveAllOf(
197
- schema.allOf
198
- );
199
- // Adds support one more level deep
200
- if (mergedSchemas.oneOf !== undefined) {
201
- return createAnyOneOf(mergedSchemas.oneOf, "oneOf");
202
- }
227
+ if (schema.items?.allOf !== undefined) {
228
+ const { mergedSchemas }: { mergedSchemas: SchemaObject; required: any } =
229
+ mergeAllOf(schema.items?.allOf);
203
230
 
204
- if (mergedSchemas.anyOf !== undefined) {
205
- return createAnyOneOf(mergedSchemas.anyOf, "anyOf");
206
- }
207
-
208
- // array
209
- if (mergedSchemas.items !== undefined) {
210
- return createRows({ schema: schema.items as SchemaObject });
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
+ });
211
243
  }
212
244
 
213
- if (mergedSchemas.properties !== undefined) {
245
+ // Handles only anyOf/oneOf
246
+ if (
247
+ mergedSchemas.oneOf !== undefined ||
248
+ mergedSchemas.anyOf !== undefined
249
+ ) {
214
250
  return create("div", {
215
251
  children: [
216
- create("span", {
217
- className: "badge badge--info",
218
- style: { marginBottom: "1rem" },
219
- children: "allOf",
220
- }),
221
- Object.entries(mergedSchemas.properties as SchemaObject).map(
222
- ([key, val]) =>
223
- createRow({
224
- name: key,
225
- schema: val as SchemaObject,
226
- required: Array.isArray(required)
227
- ? required.includes(key)
228
- : false,
229
- })
230
- ),
252
+ createAnyOneOf(mergedSchemas),
253
+ createProperties(mergedSchemas),
231
254
  ],
232
255
  });
233
256
  }
234
257
  }
235
258
 
236
- // primitive
237
- return undefined;
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
+ );
238
278
  }
239
279
 
240
- interface RowsRootProps {
280
+ function createDetailsNode(
281
+ name: string,
282
+ schemaName: string,
283
+ schema: SchemaObject,
284
+ required: any
285
+ ): any {
286
+ return create("SchemaItem", {
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
+ ],
331
+ });
332
+ }
333
+
334
+ interface EdgeProps {
335
+ name: string;
241
336
  schema: SchemaObject;
337
+ required: boolean;
242
338
  }
243
339
 
244
- function createRowsRoot({ schema }: RowsRootProps): any {
245
- // object
246
- if (schema.properties !== undefined) {
247
- return Object.entries(schema.properties).map(([key, val]) =>
248
- createRow({
249
- name: key,
250
- schema: val,
251
- required: Array.isArray(schema.required)
252
- ? schema.required.includes(key)
253
- : false,
254
- })
255
- );
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);
256
348
  }
257
349
 
258
- // allOf
259
350
  if (schema.allOf !== undefined) {
260
351
  const {
261
352
  mergedSchemas,
262
353
  required,
263
- }: { mergedSchemas: SchemaObject; required: string[] } = resolveAllOf(
354
+ }: { mergedSchemas: SchemaObject; required: any } = mergeAllOf(
264
355
  schema.allOf
265
356
  );
266
- return create("div", {
267
- children: [
268
- create("span", {
269
- className: "badge badge--info",
270
- style: { marginBottom: "1rem" },
271
- children: "allOf",
272
- }),
273
- Object.entries(mergedSchemas.properties as SchemaObject).map(
274
- ([key, val]) =>
275
- createRow({
276
- name: key,
277
- schema: val as SchemaObject,
278
- required: Array.isArray(required)
279
- ? required.includes(key)
280
- : false,
281
- })
282
- ),
283
- ],
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),
284
381
  });
285
382
  }
286
383
 
287
- // oneOf
288
- if (schema.oneOf !== undefined) {
289
- return createAnyOneOf(schema.oneOf, "oneOf");
384
+ if (schema.properties !== undefined) {
385
+ return createDetailsNode(name, schemaName, schema, required);
386
+ }
387
+
388
+ if (schema.additionalProperties !== undefined) {
389
+ return createDetailsNode(name, schemaName, schema, required);
390
+ }
391
+
392
+ // array of objects
393
+ if (schema.items?.properties !== undefined) {
394
+ return createDetailsNode(name, schemaName, schema, required);
395
+ }
396
+
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
+ });
406
+ }
407
+
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);
290
414
  }
291
415
 
292
- // anyOf
293
- if (schema.anyOf !== undefined) {
294
- return createAnyOneOf(schema.anyOf, "anyOf");
416
+ if (schema.allOf !== undefined) {
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
+ }
423
+ }
424
+
425
+ if (schema.properties !== undefined) {
426
+ return createProperties(schema);
295
427
  }
296
428
 
297
- // array
429
+ if (schema.additionalProperties !== undefined) {
430
+ return createAdditionalProperties(schema);
431
+ }
432
+
433
+ // TODO: figure out how to handle array of objects
298
434
  if (schema.items !== undefined) {
435
+ return createItems(schema);
436
+ }
437
+
438
+ // primitive
439
+ if (schema.type !== undefined) {
299
440
  return create("li", {
300
441
  children: create("div", {
301
- 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
+ ],
302
463
  }),
303
464
  });
304
465
  }
305
466
 
306
- // primitive
307
- return create("li", {
308
- children: create("div", {
309
- children: [
310
- create("span", {
311
- style: { opacity: "0.6" },
312
- children: ` ${schema.type}`,
313
- }),
314
- guard(getQualifierMessage(schema), (message) =>
315
- create("div", {
316
- style: { marginTop: "var(--ifm-table-cell-padding)" },
317
- children: createDescription(message),
318
- })
319
- ),
320
- guard(schema.description, (description) =>
321
- create("div", {
322
- style: { marginTop: "var(--ifm-table-cell-padding)" },
323
- children: createDescription(description),
324
- })
325
- ),
326
- ],
327
- }),
328
- });
467
+ // Unknown node/schema type should return undefined
468
+ // So far, haven't seen this hit in testing
469
+ return undefined;
329
470
  }
330
471
 
331
472
  interface Props {
@@ -350,7 +491,6 @@ export function createSchemaDetails({ title, body, ...rest }: Props) {
350
491
  return undefined;
351
492
  }
352
493
 
353
- // TODO:
354
494
  // NOTE: We just pick a random content-type.
355
495
  // How common is it to have multiple?
356
496
  const randomFirstKey = Object.keys(body.content)[0];
@@ -367,6 +507,7 @@ export function createSchemaDetails({ title, body, ...rest }: Props) {
367
507
  }
368
508
  }
369
509
 
510
+ // Root-level schema dropdown
370
511
  return createDetails({
371
512
  "data-collapsed": false,
372
513
  open: true,
@@ -376,6 +517,12 @@ export function createSchemaDetails({ title, body, ...rest }: Props) {
376
517
  style: { textAlign: "left" },
377
518
  children: [
378
519
  create("strong", { children: `${title}` }),
520
+ guard(firstBody.type === "array", (format) =>
521
+ create("span", {
522
+ style: { opacity: "0.6" },
523
+ children: ` array`,
524
+ })
525
+ ),
379
526
  guard(body.required, () => [
380
527
  create("strong", {
381
528
  style: {
@@ -400,7 +547,7 @@ export function createSchemaDetails({ title, body, ...rest }: Props) {
400
547
  }),
401
548
  create("ul", {
402
549
  style: { marginLeft: "1rem" },
403
- children: createRowsRoot({ schema: firstBody }),
550
+ children: createNodes(firstBody),
404
551
  }),
405
552
  ],
406
553
  });