docusaurus-plugin-openapi-docs 0.0.0-393 → 0.0.0-396

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/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-393",
4
+ "version": "0.0.0-396",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "openapi",
@@ -28,8 +28,8 @@
28
28
  "watch": "tsc --watch"
29
29
  },
30
30
  "devDependencies": {
31
- "@docusaurus/module-type-aliases": "2.0.0-beta.21",
32
- "@docusaurus/types": "2.0.0-beta.21",
31
+ "@docusaurus/module-type-aliases": "2.0.0-beta.22",
32
+ "@docusaurus/types": "2.0.0-beta.22",
33
33
  "@types/fs-extra": "^9.0.13",
34
34
  "@types/js-yaml": "^4.0.5",
35
35
  "@types/json-pointer": "^1.0.31",
@@ -40,10 +40,10 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@apidevtools/json-schema-ref-parser": "^9.0.9",
43
- "@docusaurus/mdx-loader": "2.0.0-beta.21",
44
- "@docusaurus/plugin-content-docs": "2.0.0-beta.21",
45
- "@docusaurus/utils": "2.0.0-beta.21",
46
- "@docusaurus/utils-validation": "2.0.0-beta.21",
43
+ "@docusaurus/mdx-loader": "2.0.0-beta.22",
44
+ "@docusaurus/plugin-content-docs": "2.0.0-beta.22",
45
+ "@docusaurus/utils": "2.0.0-beta.22",
46
+ "@docusaurus/utils-validation": "2.0.0-beta.22",
47
47
  "@paloaltonetworks/openapi-to-postmanv2": "3.1.0-hotfix.1",
48
48
  "@paloaltonetworks/postman-collection": "^4.1.0",
49
49
  "@redocly/openapi-core": "^1.0.0-beta.103",
@@ -67,5 +67,5 @@
67
67
  "engines": {
68
68
  "node": ">=14"
69
69
  },
70
- "gitHead": "6b19eaff1627c28fe3c4a9267dd28d0433b7f616"
70
+ "gitHead": "958b9c6e0b370afe79572dfea950d2be33f41cc0"
71
71
  }
@@ -5,18 +5,9 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import { createSchemaDetails } from "./createSchemaDetails";
8
+ import { createRows } from "./createSchemaDetails";
9
9
  import { create } from "./utils";
10
10
 
11
- // {
12
- // 'application/json': {
13
- // schema: { properties: [Object], required: [Array], type: 'object' }
14
- // }
15
- // }
16
- // {
17
- // 'application/json': { schema: { allOf: [Array], example: [Object] } }
18
- // }
19
-
20
11
  export function createAnyOneOf(anyOneOf: any[], type: string) {
21
12
  if (anyOneOf === undefined) {
22
13
  return undefined;
@@ -34,49 +25,21 @@ export function createAnyOneOf(anyOneOf: any[], type: string) {
34
25
  }),
35
26
  create("SchemaTabs", {
36
27
  children: anyOneOf.map((schema, index) => {
37
- // Prep schema details
38
- let schemaDetails: any = {};
39
- schemaDetails["application/json"] = {}; // Placeholder content type
40
- schemaDetails["application/json"].schema = {};
41
28
  const label = schema.title ? schema.title : `MOD${index + 1}`;
42
29
 
43
30
  if (schema.properties !== undefined) {
44
- schemaDetails["application/json"].schema.properties =
45
- schema.properties;
46
- schemaDetails["application/json"].schema.required = schema.required;
47
- schemaDetails["application/json"].schema.type = "object";
48
31
  return create("TabItem", {
49
32
  label: label,
50
33
  value: `${index}-properties`,
51
- children: [
52
- create("div", {
53
- children: createSchemaDetails({
54
- title: "Schema",
55
- body: {
56
- content: schemaDetails,
57
- },
58
- }),
59
- }),
60
- ],
34
+ children: [createRows({ schema: schema })],
61
35
  });
62
36
  }
63
37
 
64
38
  if (schema.allOf !== undefined) {
65
- schemaDetails["application/json"].schema.allOf = schema.allOf;
66
- schemaDetails["application/json"].schema.example = schema.example;
67
39
  return create("TabItem", {
68
40
  label: label,
69
41
  value: `${index}-allOf`,
70
- children: [
71
- create("div", {
72
- children: createSchemaDetails({
73
- title: "Schema",
74
- body: {
75
- content: schemaDetails,
76
- },
77
- }),
78
- }),
79
- ],
42
+ children: [createRows({ schema: schema })],
80
43
  });
81
44
  }
82
45
 
@@ -17,7 +17,6 @@ const mergeAllOf = require("json-schema-merge-allof");
17
17
 
18
18
  function resolveAllOf(allOf: SchemaObject[]) {
19
19
  // Use external library to resolve and merge nested allOf schemas
20
- let properties: SchemaObject = {};
21
20
  const mergedSchemas = mergeAllOf(allOf, {
22
21
  resolvers: {
23
22
  readOnly: function () {
@@ -29,10 +28,6 @@ function resolveAllOf(allOf: SchemaObject[]) {
29
28
  },
30
29
  });
31
30
 
32
- if (mergedSchemas.properties) {
33
- properties = mergedSchemas.properties;
34
- }
35
-
36
31
  const required = allOf.reduce((acc, cur) => {
37
32
  if (Array.isArray(cur.required)) {
38
33
  const next = [...acc, ...cur.required];
@@ -41,7 +36,7 @@ function resolveAllOf(allOf: SchemaObject[]) {
41
36
  return acc;
42
37
  }, [] as string[]);
43
38
 
44
- return { properties, required };
39
+ return { mergedSchemas, required };
45
40
  }
46
41
 
47
42
  interface RowProps {
@@ -51,7 +46,58 @@ interface RowProps {
51
46
  }
52
47
 
53
48
  function createRow({ name, schema, required }: RowProps) {
54
- const schemaName = getSchemaName(schema, true);
49
+ const schemaName = getSchemaName(schema);
50
+
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
+ }
100
+
55
101
  if (schemaName && (schemaName === "object" || schemaName === "object[]")) {
56
102
  return create("SchemaItem", {
57
103
  collapsible: true,
@@ -101,12 +147,13 @@ function createRow({ name, schema, required }: RowProps) {
101
147
  });
102
148
  }
103
149
 
150
+ // primitive
104
151
  return create("SchemaItem", {
105
152
  collapsible: false,
106
153
  name,
107
154
  required,
108
155
  schemaDescription: schema.description,
109
- schemaName: getSchemaName(schema, true),
156
+ schemaName: schemaName,
110
157
  qualifierMessage: getQualifierMessage(schema),
111
158
  });
112
159
  }
@@ -115,7 +162,17 @@ interface RowsProps {
115
162
  schema: SchemaObject;
116
163
  }
117
164
 
118
- function createRows({ schema }: RowsProps): string | undefined {
165
+ export function createRows({ schema }: RowsProps): string | undefined {
166
+ // oneOf
167
+ if (schema.oneOf !== undefined) {
168
+ return createAnyOneOf(schema.oneOf, "oneOf");
169
+ }
170
+
171
+ // anyOf
172
+ if (schema.anyOf !== undefined) {
173
+ return createAnyOneOf(schema.anyOf, "anyOf");
174
+ }
175
+
119
176
  // object
120
177
  if (schema.properties !== undefined) {
121
178
  return create("ul", {
@@ -131,39 +188,49 @@ function createRows({ schema }: RowsProps): string | undefined {
131
188
  });
132
189
  }
133
190
 
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
191
+ // allOf
135
192
  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
- ],
152
- });
153
- }
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
+ }
154
203
 
155
- // Adds support one more level deep
156
- if (schema.oneOf !== undefined) {
157
- return createAnyOneOf(schema.oneOf, "oneOf");
158
- }
204
+ if (mergedSchemas.anyOf !== undefined) {
205
+ return createAnyOneOf(mergedSchemas.anyOf, "anyOf");
206
+ }
159
207
 
160
- if (schema.anyOf !== undefined) {
161
- return createAnyOneOf(schema.anyOf, "anyOf");
162
- }
208
+ // array
209
+ if (mergedSchemas.items !== undefined) {
210
+ return createRows({ schema: schema.items as SchemaObject });
211
+ }
163
212
 
164
- // array
165
- if (schema.items !== undefined) {
166
- return createRows({ schema: schema.items });
213
+ if (mergedSchemas.properties !== undefined) {
214
+ return create("div", {
215
+ 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
+ ),
231
+ ],
232
+ });
233
+ }
167
234
  }
168
235
 
169
236
  // primitive
@@ -188,9 +255,14 @@ function createRowsRoot({ schema }: RowsRootProps): any {
188
255
  );
189
256
  }
190
257
 
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
258
+ // allOf
192
259
  if (schema.allOf !== undefined) {
193
- const { properties, required } = resolveAllOf(schema.allOf);
260
+ const {
261
+ mergedSchemas,
262
+ required,
263
+ }: { mergedSchemas: SchemaObject; required: string[] } = resolveAllOf(
264
+ schema.allOf
265
+ );
194
266
  return create("div", {
195
267
  children: [
196
268
  create("span", {
@@ -198,22 +270,26 @@ function createRowsRoot({ schema }: RowsRootProps): any {
198
270
  style: { marginBottom: "1rem" },
199
271
  children: "allOf",
200
272
  }),
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
- })
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
+ })
207
282
  ),
208
283
  ],
209
284
  });
210
285
  }
211
286
 
212
- // TODO: This is top-level only - add support for nested oneOf/anyOf
287
+ // oneOf
213
288
  if (schema.oneOf !== undefined) {
214
289
  return createAnyOneOf(schema.oneOf, "oneOf");
215
290
  }
216
291
 
292
+ // anyOf
217
293
  if (schema.anyOf !== undefined) {
218
294
  return createAnyOneOf(schema.anyOf, "anyOf");
219
295
  }
@@ -8,22 +8,36 @@
8
8
  import { SchemaObject } from "../openapi/types";
9
9
 
10
10
  function prettyName(schema: SchemaObject, circular?: boolean) {
11
- if (schema.$ref) {
12
- return schema.$ref.replace("#/components/schemas/", "") + circular
13
- ? " (circular)"
14
- : "";
15
- }
16
-
17
11
  if (schema.format) {
18
12
  return schema.format;
19
13
  }
20
14
 
21
15
  if (schema.allOf) {
16
+ if (typeof schema.allOf[0] === "string") {
17
+ // @ts-ignore
18
+ if (schema.allOf[0].includes("circular")) {
19
+ return schema.allOf[0];
20
+ }
21
+ }
22
+ return "object";
23
+ }
24
+
25
+ if (schema.oneOf) {
26
+ return "object";
27
+ }
28
+
29
+ if (schema.anyOf) {
22
30
  return "object";
23
31
  }
24
32
 
25
33
  if (schema.type === "object") {
26
34
  return schema.xml?.name ?? schema.type;
35
+ // return schema.type;
36
+ }
37
+
38
+ if (schema.type === "array") {
39
+ return schema.xml?.name ?? schema.type;
40
+ // return schema.type;
27
41
  }
28
42
 
29
43
  return schema.title ?? schema.type;
@@ -42,8 +56,6 @@ export function getSchemaName(
42
56
 
43
57
  export function getQualifierMessage(schema?: SchemaObject): string | undefined {
44
58
  // TODO:
45
- // - maxItems
46
- // - minItems
47
59
  // - uniqueItems
48
60
  // - maxProperties
49
61
  // - minProperties
@@ -52,9 +64,10 @@ export function getQualifierMessage(schema?: SchemaObject): string | undefined {
52
64
  return undefined;
53
65
  }
54
66
 
55
- if (schema.items) {
56
- return getQualifierMessage(schema.items);
57
- }
67
+ // TODO: This doesn't seem right
68
+ // if (schema.items) {
69
+ // return getQualifierMessage(schema.items);
70
+ // }
58
71
 
59
72
  let message = "**Possible values:** ";
60
73
 
@@ -107,6 +120,14 @@ export function getQualifierMessage(schema?: SchemaObject): string | undefined {
107
120
  qualifierGroups.push(`[${schema.enum.map((e) => `\`${e}\``).join(", ")}]`);
108
121
  }
109
122
 
123
+ if (schema.minItems) {
124
+ qualifierGroups.push(`items >= ${schema.minItems}`);
125
+ }
126
+
127
+ if (schema.maxItems) {
128
+ qualifierGroups.push(`items <= ${schema.maxItems}`);
129
+ }
130
+
110
131
  if (qualifierGroups.length === 0) {
111
132
  return undefined;
112
133
  }
@@ -13,7 +13,6 @@ import sdk from "@paloaltonetworks/postman-collection";
13
13
  import Collection from "@paloaltonetworks/postman-collection";
14
14
  import chalk from "chalk";
15
15
  import fs from "fs-extra";
16
- import JsonRefs from "json-refs";
17
16
  import { kebabCase } from "lodash";
18
17
 
19
18
  import { isURL } from "../index";
@@ -26,16 +25,8 @@ import {
26
25
  TagPageMetadata,
27
26
  } from "../types";
28
27
  import { sampleFromSchema } from "./createExample";
29
- import { OpenApiObject, OpenApiObjectWithRef, TagObject } from "./types";
30
- import { loadAndBundleSpec } from "./utils/loadAndBundleSpec";
31
-
32
- /**
33
- * Finds any reference objects in the OpenAPI definition and resolves them to a finalized value.
34
- */
35
- async function resolveRefs(openapiData: OpenApiObjectWithRef) {
36
- const { resolved } = await JsonRefs.resolveRefs(openapiData);
37
- return resolved as OpenApiObject;
38
- }
28
+ import { OpenApiObject, TagObject } from "./types";
29
+ import { loadAndResolveSpec } from "./utils/loadAndResolveSpec";
39
30
 
40
31
  /**
41
32
  * Convenience function for converting raw JSON to a Postman Collection object.
@@ -62,7 +53,7 @@ function jsonToCollection(data: OpenApiObject): Promise<Collection> {
62
53
  async function createPostmanCollection(
63
54
  openapiData: OpenApiObject
64
55
  ): Promise<Collection> {
65
- const data = JSON.parse(JSON.stringify(openapiData)) as OpenApiObject;
56
+ const data = openapiData as OpenApiObject;
66
57
 
67
58
  // Including `servers` breaks postman, so delete all of them.
68
59
  delete data.servers;
@@ -243,17 +234,13 @@ function bindCollectionToApiItems(
243
234
  interface OpenApiFiles {
244
235
  source: string;
245
236
  sourceDirName: string;
246
- data: OpenApiObjectWithRef;
237
+ data: OpenApiObject;
247
238
  }
248
239
 
249
240
  export async function readOpenapiFiles(
250
241
  openapiPath: string,
251
242
  options: APIOptions
252
243
  ): Promise<OpenApiFiles[]> {
253
- // TODO: determine if this should be an API option
254
- // Forces the json-schema-ref-parser
255
- const parseJsonRefs = true;
256
-
257
244
  if (!isURL(openapiPath)) {
258
245
  const stat = await fs.lstat(openapiPath);
259
246
  if (stat.isDirectory()) {
@@ -274,10 +261,9 @@ export async function readOpenapiFiles(
274
261
  sources.map(async (source) => {
275
262
  // TODO: make a function for this
276
263
  const fullPath = path.join(openapiPath, source);
277
- const data = (await loadAndBundleSpec(
278
- fullPath,
279
- parseJsonRefs
280
- )) as OpenApiObjectWithRef;
264
+ const data = (await loadAndResolveSpec(
265
+ fullPath
266
+ )) as unknown as OpenApiObject;
281
267
  return {
282
268
  source: fullPath, // This will be aliased in process.
283
269
  sourceDirName: path.dirname(source),
@@ -287,10 +273,9 @@ export async function readOpenapiFiles(
287
273
  );
288
274
  }
289
275
  }
290
- const data = (await loadAndBundleSpec(
291
- openapiPath,
292
- parseJsonRefs
293
- )) as OpenApiObjectWithRef;
276
+ const data = (await loadAndResolveSpec(
277
+ openapiPath
278
+ )) as unknown as OpenApiObject;
294
279
  return [
295
280
  {
296
281
  source: openapiPath, // This will be aliased in process.
@@ -305,30 +290,46 @@ export async function processOpenapiFiles(
305
290
  sidebarOptions: SidebarOptions
306
291
  ): Promise<[ApiMetadata[], TagObject[]]> {
307
292
  const promises = files.map(async (file) => {
308
- const processedFile = await processOpenapiFile(file.data, sidebarOptions);
309
- const itemsObjectsArray = processedFile[0].map((item) => ({
310
- ...item,
311
- }));
312
- const tags = processedFile[1];
313
- return [itemsObjectsArray, tags];
293
+ if (file.data !== undefined) {
294
+ const processedFile = await processOpenapiFile(file.data, sidebarOptions);
295
+ const itemsObjectsArray = processedFile[0].map((item) => ({
296
+ ...item,
297
+ }));
298
+ const tags = processedFile[1];
299
+ return [itemsObjectsArray, tags];
300
+ }
301
+ console.warn(
302
+ chalk.yellow(
303
+ `WARNING: the following OpenAPI spec returned undefined: ${file.source}`
304
+ )
305
+ );
306
+ return [];
314
307
  });
315
308
  const metadata = await Promise.all(promises);
316
309
  const items = metadata
317
310
  .map(function (x) {
318
311
  return x[0];
319
312
  })
320
- .flat();
321
- const tags = metadata.map(function (x) {
322
- return x[1];
323
- });
313
+ .flat()
314
+ .filter(function (x) {
315
+ // Remove undefined items due to transient parsing errors
316
+ return x !== undefined;
317
+ });
318
+ const tags = metadata
319
+ .map(function (x) {
320
+ return x[1];
321
+ })
322
+ .filter(function (x) {
323
+ // Remove undefined tags due to transient parsing errors
324
+ return x !== undefined;
325
+ });
324
326
  return [items as ApiMetadata[], tags as TagObject[]];
325
327
  }
326
328
 
327
329
  export async function processOpenapiFile(
328
- openapiDataWithRefs: OpenApiObjectWithRef,
330
+ openapiData: OpenApiObject,
329
331
  sidebarOptions: SidebarOptions
330
332
  ): Promise<[ApiMetadata[], TagObject[]]> {
331
- const openapiData = await resolveRefs(openapiDataWithRefs);
332
333
  const postmanCollection = await createPostmanCollection(openapiData);
333
334
  const items = createItems(openapiData, sidebarOptions);
334
335
 
@@ -20,6 +20,7 @@ export interface OpenApiObject {
20
20
  security?: SecurityRequirementObject[];
21
21
  tags?: TagObject[];
22
22
  externalDocs?: ExternalDocumentationObject;
23
+ swagger?: string;
23
24
  }
24
25
 
25
26
  export interface OpenApiObjectWithRef {