docusaurus-plugin-openapi-docs 4.1.0 → 4.3.0

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.
Files changed (41) hide show
  1. package/README.md +21 -1
  2. package/lib/index.d.ts +1 -1
  3. package/lib/index.js +66 -0
  4. package/lib/markdown/createAuthentication.js +3 -3
  5. package/lib/markdown/createContactInfo.js +1 -1
  6. package/lib/markdown/createParamsDetails.d.ts +1 -2
  7. package/lib/markdown/createParamsDetails.js +7 -42
  8. package/lib/markdown/createRequestBodyDetails.d.ts +1 -1
  9. package/lib/markdown/createRequestSchema.d.ts +1 -1
  10. package/lib/markdown/createRequestSchema.js +8 -132
  11. package/lib/markdown/createResponseSchema.d.ts +1 -1
  12. package/lib/markdown/createResponseSchema.js +8 -94
  13. package/lib/markdown/createSchema.d.ts +1 -4
  14. package/lib/markdown/createSchema.js +32 -56
  15. package/lib/markdown/createStatusCodes.d.ts +1 -4
  16. package/lib/markdown/createStatusCodes.js +10 -259
  17. package/lib/markdown/createTermsOfService.js +1 -1
  18. package/lib/markdown/index.js +11 -22
  19. package/lib/openapi/createRequestExample.js +2 -2
  20. package/lib/openapi/createResponseExample.js +2 -2
  21. package/lib/openapi/openapi.js +3 -1
  22. package/lib/openapi/types.d.ts +1 -0
  23. package/lib/options.js +1 -0
  24. package/package.json +9 -6
  25. package/src/index.ts +88 -5
  26. package/src/markdown/__snapshots__/createSchema.test.ts.snap +55 -0
  27. package/src/markdown/createAuthentication.ts +3 -3
  28. package/src/markdown/createContactInfo.ts +1 -1
  29. package/src/markdown/createParamsDetails.ts +7 -49
  30. package/src/markdown/createRequestSchema.ts +9 -143
  31. package/src/markdown/createResponseSchema.ts +9 -112
  32. package/src/markdown/createSchema.ts +29 -61
  33. package/src/markdown/createStatusCodes.ts +9 -268
  34. package/src/markdown/createTermsOfService.ts +1 -1
  35. package/src/markdown/index.ts +11 -22
  36. package/src/openapi/createRequestExample.ts +2 -5
  37. package/src/openapi/createResponseExample.ts +2 -5
  38. package/src/openapi/openapi.ts +3 -1
  39. package/src/openapi/types.ts +1 -0
  40. package/src/openapi/utils/loadAndResolveSpec.ts +1 -1
  41. package/src/options.ts +1 -0
package/src/index.ts CHANGED
@@ -21,18 +21,18 @@ import {
21
21
  createSchemaPageMD,
22
22
  createTagPageMD,
23
23
  } from "./markdown";
24
- import { readOpenapiFiles, processOpenapiFiles } from "./openapi";
24
+ import { processOpenapiFiles, readOpenapiFiles } from "./openapi";
25
25
  import { OptionsSchema } from "./options";
26
26
  import generateSidebarSlice from "./sidebars";
27
27
  import type {
28
- PluginOptions,
29
- LoadedContent,
30
- APIOptions,
31
28
  ApiMetadata,
29
+ APIOptions,
32
30
  ApiPageMetadata,
33
31
  InfoPageMetadata,
34
- TagPageMetadata,
32
+ LoadedContent,
33
+ PluginOptions,
35
34
  SchemaPageMetadata,
35
+ TagPageMetadata,
36
36
  } from "./types";
37
37
 
38
38
  export function isURL(str: string): boolean {
@@ -278,7 +278,11 @@ title: "{{{title}}}"
278
278
  description: "{{{frontMatter.description}}}"
279
279
  sidebar_label: "{{{title}}}"
280
280
  hide_title: true
281
+ {{#schema}}
282
+ hide_table_of_contents: true
283
+ {{/schema}}
281
284
  schema: true
285
+ sample: {{{frontMatter.sample}}}
282
286
  custom_edit_url: null
283
287
  ---
284
288
 
@@ -582,6 +586,66 @@ custom_edit_url: null
582
586
  }
583
587
  }
584
588
 
589
+ async function generateAllVersions(options: APIOptions, pluginId: any) {
590
+ const parentOptions = Object.assign({}, options);
591
+ const { versions } = parentOptions as any;
592
+
593
+ if (versions != null && Object.keys(versions).length > 0) {
594
+ const version = parentOptions.version as string;
595
+ const label = parentOptions.label as string;
596
+
597
+ const baseUrl = parentOptions.baseUrl as string;
598
+ let parentVersion = {} as any;
599
+
600
+ parentVersion[version] = { label: label, baseUrl: baseUrl };
601
+ const mergedVersions = Object.assign(parentVersion, versions);
602
+
603
+ // Prepare for merge
604
+ delete parentOptions.versions;
605
+ delete parentOptions.version;
606
+ delete parentOptions.label;
607
+ delete parentOptions.baseUrl;
608
+ delete parentOptions.downloadUrl;
609
+
610
+ await generateVersions(mergedVersions, parentOptions.outputDir);
611
+ Object.keys(versions).forEach(async (key) => {
612
+ if (key === "all") {
613
+ console.error(
614
+ chalk.red(
615
+ "Can't use id 'all' for OpenAPI docs versions configuration key."
616
+ )
617
+ );
618
+ }
619
+ const versionOptions = versions[key];
620
+ const mergedOptions = {
621
+ ...parentOptions,
622
+ ...versionOptions,
623
+ };
624
+ await generateApiDocs(mergedOptions, pluginId);
625
+ });
626
+ }
627
+ }
628
+
629
+ async function cleanAllVersions(options: APIOptions) {
630
+ const parentOptions = Object.assign({}, options);
631
+
632
+ const { versions } = parentOptions as any;
633
+
634
+ delete parentOptions.versions;
635
+
636
+ if (versions != null && Object.keys(versions).length > 0) {
637
+ await cleanVersions(parentOptions.outputDir);
638
+ Object.keys(versions).forEach(async (key) => {
639
+ const versionOptions = versions[key];
640
+ const mergedOptions = {
641
+ ...parentOptions,
642
+ ...versionOptions,
643
+ };
644
+ await cleanApiDocs(mergedOptions);
645
+ });
646
+ }
647
+ }
648
+
585
649
  return {
586
650
  name: `docusaurus-plugin-openapi-docs`,
587
651
 
@@ -594,9 +658,11 @@ custom_edit_url: null
594
658
  .usage("<id>")
595
659
  .arguments("<id>")
596
660
  .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
661
+ .option("--all-versions", "Generate all versions.")
597
662
  .action(async (id, instance) => {
598
663
  const options = instance.opts();
599
664
  const pluginId = options.pluginId;
665
+ const allVersions = options.allVersions;
600
666
  const pluginInstances = getPluginInstances(plugins);
601
667
  let targetConfig: any;
602
668
  let targetDocsPluginId: any;
@@ -633,6 +699,12 @@ custom_edit_url: null
633
699
  } else {
634
700
  Object.keys(targetConfig).forEach(async function (key) {
635
701
  await generateApiDocs(targetConfig[key], targetDocsPluginId);
702
+ if (allVersions) {
703
+ await generateAllVersions(
704
+ targetConfig[key],
705
+ targetDocsPluginId
706
+ );
707
+ }
636
708
  });
637
709
  }
638
710
  } else if (!targetConfig[id]) {
@@ -641,6 +713,9 @@ custom_edit_url: null
641
713
  );
642
714
  } else {
643
715
  await generateApiDocs(targetConfig[id], targetDocsPluginId);
716
+ if (allVersions) {
717
+ await generateAllVersions(targetConfig[id], targetDocsPluginId);
718
+ }
644
719
  }
645
720
  });
646
721
 
@@ -744,9 +819,11 @@ custom_edit_url: null
744
819
  .usage("<id>")
745
820
  .arguments("<id>")
746
821
  .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
822
+ .option("--all-versions", "Clean all versions.")
747
823
  .action(async (id, instance) => {
748
824
  const options = instance.opts();
749
825
  const pluginId = options.pluginId;
826
+ const allVersions = options.allVersions;
750
827
  const pluginInstances = getPluginInstances(plugins);
751
828
  let targetConfig: any;
752
829
  if (pluginId) {
@@ -780,10 +857,16 @@ custom_edit_url: null
780
857
  } else {
781
858
  Object.keys(targetConfig).forEach(async function (key) {
782
859
  await cleanApiDocs(targetConfig[key]);
860
+ if (allVersions) {
861
+ await cleanAllVersions(targetConfig[key]);
862
+ }
783
863
  });
784
864
  }
785
865
  } else {
786
866
  await cleanApiDocs(targetConfig[id]);
867
+ if (allVersions) {
868
+ await cleanAllVersions(targetConfig[id]);
869
+ }
787
870
  }
788
871
  });
789
872
 
@@ -364,6 +364,24 @@ Array [
364
364
  qualifierMessage={undefined}
365
365
  schema={{ type: \\"string\\" }}
366
366
  ></SchemaItem>;
367
+ ",
368
+ "<SchemaItem
369
+ collapsible={false}
370
+ name={\\"parentProp1\\"}
371
+ required={false}
372
+ schemaName={\\"string\\"}
373
+ qualifierMessage={undefined}
374
+ schema={{ type: \\"string\\" }}
375
+ ></SchemaItem>;
376
+ ",
377
+ "<SchemaItem
378
+ collapsible={false}
379
+ name={\\"parentProp2\\"}
380
+ required={false}
381
+ schemaName={\\"string\\"}
382
+ qualifierMessage={undefined}
383
+ schema={{ type: \\"string\\" }}
384
+ ></SchemaItem>;
367
385
  ",
368
386
  ]
369
387
  `;
@@ -711,6 +729,15 @@ Array [
711
729
  qualifierMessage={undefined}
712
730
  schema={{ type: \\"string\\" }}
713
731
  ></SchemaItem>;
732
+ ",
733
+ "<SchemaItem
734
+ collapsible={false}
735
+ name={\\"type\\"}
736
+ required={false}
737
+ schemaName={\\"string\\"}
738
+ qualifierMessage={undefined}
739
+ schema={{ type: \\"string\\" }}
740
+ ></SchemaItem>;
714
741
  ",
715
742
  ]
716
743
  `;
@@ -797,6 +824,34 @@ Array [
797
824
  qualifierMessage={undefined}
798
825
  schema={{ type: \\"string\\" }}
799
826
  ></SchemaItem>;
827
+ ",
828
+ "<div className={\\"openapi-discriminator__item openapi-schema__list-item\\"}>
829
+ <div>
830
+ <span className={\\"openapi-schema__container\\"}>
831
+ <strong
832
+ className={\\"openapi-discriminator__name openapi-schema__property\\"}
833
+ >
834
+ type
835
+ </strong>
836
+ <span className={\\"openapi-schema__name\\"}>string</span>
837
+ </span>
838
+ <div style={{ paddingLeft: \\"1rem\\" }}>
839
+ **Possible values:** [\`typeA\`, \`typeB\`]
840
+ </div>
841
+ <DiscriminatorTabs className={\\"openapi-tabs__discriminator\\"}>
842
+ <TabItem label={\\"typeA\\"} value={\\"0-item-discriminator\\"}>
843
+ <div style={{ marginTop: \\".5rem\\", marginBottom: \\".5rem\\" }}>
844
+ #/definitions/TypeA
845
+ </div>
846
+ </TabItem>
847
+ <TabItem label={\\"typeB\\"} value={\\"1-item-discriminator\\"}>
848
+ <div style={{ marginTop: \\".5rem\\", marginBottom: \\".5rem\\" }}>
849
+ #/definitions/TypeB
850
+ </div>
851
+ </TabItem>
852
+ </DiscriminatorTabs>
853
+ </div>
854
+ </div>;
800
855
  ",
801
856
  ]
802
857
  `;
@@ -35,15 +35,15 @@ export function createAuthentication(securitySchemes: SecuritySchemeObject) {
35
35
  create("td", {
36
36
  children: [
37
37
  guard(tokenUrl, () =>
38
- create("p", { children: `Token URL: ${tokenUrl}` })
38
+ create("div", { children: `Token URL: ${tokenUrl}` })
39
39
  ),
40
40
  guard(authorizationUrl, () =>
41
- create("p", {
41
+ create("div", {
42
42
  children: `Authorization URL: ${authorizationUrl}`,
43
43
  })
44
44
  ),
45
45
  guard(refreshUrl, () =>
46
- create("p", { children: `Refresh URL: ${refreshUrl}` })
46
+ create("div", { children: `Refresh URL: ${refreshUrl}` })
47
47
  ),
48
48
  create("span", { children: "Scopes:" }),
49
49
  create("ul", {
@@ -33,7 +33,7 @@ export function createContactInfo(contact: ContactObject) {
33
33
  }),
34
34
  guard(url, () =>
35
35
  create("span", {
36
- children: ["URL: ", `[${url}](mailto:${url})`],
36
+ children: ["URL: ", `[${url}](${url})`],
37
37
  })
38
38
  ),
39
39
  ],
@@ -5,60 +5,18 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import { createDetails } from "./createDetails";
9
- import { createDetailsSummary } from "./createDetailsSummary";
10
8
  import { create } from "./utils";
11
9
  import { ApiItem } from "../types";
12
10
 
13
11
  interface Props {
14
12
  parameters: ApiItem["parameters"];
15
- type: "path" | "query" | "header" | "cookie";
16
13
  }
17
14
 
18
- export function createParamsDetails({ parameters, type }: Props) {
19
- if (parameters === undefined) {
20
- return undefined;
21
- }
22
- const params = parameters.filter((param) => param?.in === type);
23
- if (params.length === 0) {
24
- return undefined;
25
- }
26
-
27
- return createDetails({
28
- className: "openapi-markdown__details",
29
- "data-collapsed": false,
30
- open: true,
31
- style: { marginBottom: "1rem" },
32
- children: [
33
- createDetailsSummary({
34
- children: [
35
- create("h3", {
36
- className: "openapi-markdown__details-summary-header-params",
37
- children: `${
38
- type.charAt(0).toUpperCase() + type.slice(1)
39
- } Parameters`,
40
- }),
41
- ],
42
- }),
43
- create("div", {
44
- children: [
45
- create("ul", {
46
- children: params.map((param) => {
47
- return create("ParamsItem", {
48
- className: "paramsItem",
49
- param: {
50
- ...param,
51
- enumDescriptions: Object.entries(
52
- param?.schema?.["x-enumDescriptions"] ??
53
- param?.schema?.items?.["x-enumDescriptions"] ??
54
- {}
55
- ),
56
- },
57
- });
58
- }),
59
- }),
60
- ],
61
- }),
62
- ],
63
- });
15
+ export function createParamsDetails({ parameters }: Props) {
16
+ return [
17
+ create("ParamsDetails", {
18
+ parameters: parameters,
19
+ }),
20
+ "\n\n",
21
+ ];
64
22
  }
@@ -5,11 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import { createDescription } from "./createDescription";
9
- import { createDetails } from "./createDetails";
10
- import { createDetailsSummary } from "./createDetailsSummary";
11
- import { createNodes } from "./createSchema";
12
- import { create, guard } from "./utils";
8
+ import { create } from "./utils";
13
9
  import { MediaTypeObject } from "../openapi/types";
14
10
 
15
11
  interface Props {
@@ -25,142 +21,12 @@ interface Props {
25
21
  }
26
22
 
27
23
  export function createRequestSchema({ title, body, ...rest }: Props) {
28
- if (
29
- body === undefined ||
30
- body.content === undefined ||
31
- Object.keys(body).length === 0 ||
32
- Object.keys(body.content).length === 0
33
- ) {
34
- return undefined;
35
- }
36
-
37
- // Get all MIME types, including vendor-specific
38
- const mimeTypes = Object.keys(body.content);
39
-
40
- if (mimeTypes && mimeTypes.length > 1) {
41
- return create("MimeTabs", {
42
- className: "openapi-tabs__mime",
43
- schemaType: "request",
44
- children: mimeTypes.map((mimeType) => {
45
- const firstBody = body.content![mimeType].schema;
46
- if (firstBody === undefined) {
47
- return undefined;
48
- }
49
- if (firstBody.properties !== undefined) {
50
- if (Object.keys(firstBody.properties).length === 0) {
51
- return undefined;
52
- }
53
- }
54
- return create("TabItem", {
55
- label: mimeType,
56
- value: `${mimeType}`,
57
- children: [
58
- createDetails({
59
- className: "openapi-markdown__details mime",
60
- "data-collapsed": false,
61
- open: true,
62
- ...rest,
63
- children: [
64
- createDetailsSummary({
65
- className: "openapi-markdown__details-summary-mime",
66
- children: [
67
- create("h3", {
68
- className:
69
- "openapi-markdown__details-summary-header-body",
70
- children: `${title}`,
71
- }),
72
- guard(body.required && body.required === true, () => [
73
- create("span", {
74
- className: "openapi-schema__required",
75
- children: "required",
76
- }),
77
- ]),
78
- ],
79
- }),
80
- create("div", {
81
- style: { textAlign: "left", marginLeft: "1rem" },
82
- children: [
83
- guard(body.description, () => [
84
- create("div", {
85
- style: { marginTop: "1rem", marginBottom: "1rem" },
86
- children: createDescription(body.description),
87
- }),
88
- ]),
89
- ],
90
- }),
91
- create("ul", {
92
- style: { marginLeft: "1rem" },
93
- children: createNodes(firstBody, "request"),
94
- }),
95
- ],
96
- }),
97
- ],
98
- });
99
- }),
100
- });
101
- }
102
-
103
- const randomFirstKey = Object.keys(body.content)[0];
104
- const firstBody: any =
105
- body.content[randomFirstKey].schema ?? body.content![randomFirstKey];
106
-
107
- if (firstBody === undefined) {
108
- return undefined;
109
- }
110
-
111
- return create("MimeTabs", {
112
- className: "openapi-tabs__mime",
113
- children: [
114
- create("TabItem", {
115
- label: randomFirstKey,
116
- value: `${randomFirstKey}-schema`,
117
- children: [
118
- createDetails({
119
- className: "openapi-markdown__details mime",
120
- "data-collapsed": false,
121
- open: true,
122
- ...rest,
123
- children: [
124
- createDetailsSummary({
125
- className: "openapi-markdown__details-summary-mime",
126
- children: [
127
- create("h3", {
128
- className: "openapi-markdown__details-summary-header-body",
129
- children: `${title}`,
130
- }),
131
- guard(firstBody.type === "array", (format) =>
132
- create("span", {
133
- style: { opacity: "0.6" },
134
- children: ` array`,
135
- })
136
- ),
137
- guard(body.required, () => [
138
- create("strong", {
139
- className: "openapi-schema__required",
140
- children: "required",
141
- }),
142
- ]),
143
- ],
144
- }),
145
- create("div", {
146
- style: { textAlign: "left", marginLeft: "1rem" },
147
- children: [
148
- guard(body.description, () => [
149
- create("div", {
150
- style: { marginTop: "1rem", marginBottom: "1rem" },
151
- children: createDescription(body.description),
152
- }),
153
- ]),
154
- ],
155
- }),
156
- create("ul", {
157
- style: { marginLeft: "1rem" },
158
- children: createNodes(firstBody, "request"),
159
- }),
160
- ],
161
- }),
162
- ],
163
- }),
164
- ],
165
- });
24
+ return [
25
+ create("RequestSchema", {
26
+ title: title,
27
+ body: body,
28
+ ...rest,
29
+ }),
30
+ "\n\n",
31
+ ];
166
32
  }
@@ -5,16 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import { createDescription } from "./createDescription";
9
- import { createDetails } from "./createDetails";
10
- import { createDetailsSummary } from "./createDetailsSummary";
11
- import { createNodes } from "./createSchema";
12
- import {
13
- createExampleFromSchema,
14
- createResponseExample,
15
- createResponseExamples,
16
- } from "./createStatusCodes";
17
- import { create, guard } from "./utils";
8
+ import { create } from "./utils";
18
9
  import { MediaTypeObject } from "../openapi/types";
19
10
 
20
11
  interface Props {
@@ -30,106 +21,12 @@ interface Props {
30
21
  }
31
22
 
32
23
  export function createResponseSchema({ title, body, ...rest }: Props) {
33
- if (
34
- body === undefined ||
35
- body.content === undefined ||
36
- Object.keys(body).length === 0 ||
37
- Object.keys(body.content).length === 0
38
- ) {
39
- return undefined;
40
- }
41
-
42
- // Get all MIME types, including vendor-specific
43
- const mimeTypes = Object.keys(body.content);
44
-
45
- if (mimeTypes && mimeTypes.length) {
46
- return create("MimeTabs", {
47
- className: "openapi-tabs__mime",
48
- schemaType: "response",
49
- children: mimeTypes.map((mimeType: any) => {
50
- const responseExamples = body.content![mimeType].examples;
51
- const responseExample = body.content![mimeType].example;
52
- const firstBody: any =
53
- body.content![mimeType].schema ?? body.content![mimeType];
54
-
55
- if (
56
- firstBody === undefined &&
57
- responseExample === undefined &&
58
- responseExamples === undefined
59
- ) {
60
- return undefined;
61
- }
62
-
63
- return create("TabItem", {
64
- label: `${mimeType}`,
65
- value: `${mimeType}`,
66
- children: [
67
- create("SchemaTabs", {
68
- className: "openapi-tabs__schema",
69
- // TODO: determine if we should persist this
70
- // groupId: "schema-tabs",
71
- children: [
72
- firstBody &&
73
- create("TabItem", {
74
- label: `${title}`,
75
- value: `${title}`,
76
- children: [
77
- createDetails({
78
- className: "openapi-markdown__details response",
79
- "data-collapsed": false,
80
- open: true,
81
- ...rest,
82
- children: [
83
- createDetailsSummary({
84
- className:
85
- "openapi-markdown__details-summary-response",
86
- children: [
87
- create("strong", { children: `${title}` }),
88
- guard(
89
- body.required && body.required === true,
90
- () => [
91
- create("span", {
92
- className: "openapi-schema__required",
93
- children: "required",
94
- }),
95
- ]
96
- ),
97
- ],
98
- }),
99
- create("div", {
100
- style: { textAlign: "left", marginLeft: "1rem" },
101
- children: [
102
- guard(body.description, () => [
103
- create("div", {
104
- style: {
105
- marginTop: "1rem",
106
- marginBottom: "1rem",
107
- },
108
- children: createDescription(body.description),
109
- }),
110
- ]),
111
- ],
112
- }),
113
- create("ul", {
114
- style: { marginLeft: "1rem" },
115
- children: createNodes(firstBody!, "response"),
116
- }),
117
- ],
118
- }),
119
- ],
120
- }),
121
- firstBody && createExampleFromSchema(firstBody, mimeType),
122
- responseExamples &&
123
- createResponseExamples(responseExamples, mimeType),
124
- responseExample &&
125
- createResponseExample(responseExample, mimeType),
126
- ],
127
- }),
128
- ],
129
- });
130
- }),
131
- });
132
- }
133
-
134
- return undefined;
24
+ return [
25
+ create("ResponseSchema", {
26
+ title: title,
27
+ body: body,
28
+ ...rest,
29
+ }),
30
+ "\n\n",
31
+ ];
135
32
  }