docusaurus-plugin-openapi-docs 1.1.9 → 1.1.12

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/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { LoadContext, Plugin } from "@docusaurus/types";
2
2
  import type { PluginOptions, LoadedContent } from "./types";
3
3
  export declare function isURL(str: string): boolean;
4
- export declare function getDocsData(dataArray: any[], filter: string): Object | undefined;
4
+ export declare function getDocsPluginConfig(presetsPlugins: any[], pluginId: string): Object | undefined;
5
5
  declare function pluginOpenAPIDocs(context: LoadContext, options: PluginOptions): Plugin<LoadedContent>;
6
6
  declare namespace pluginOpenAPIDocs {
7
7
  var validateOptions: ({ options, validate }: any) => any;
package/lib/index.js CHANGED
@@ -9,7 +9,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
9
9
  return (mod && mod.__esModule) ? mod : { "default": mod };
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.getDocsData = exports.isURL = void 0;
12
+ exports.getDocsPluginConfig = exports.isURL = void 0;
13
13
  const fs_1 = __importDefault(require("fs"));
14
14
  const path_1 = __importDefault(require("path"));
15
15
  const utils_1 = require("@docusaurus/utils");
@@ -23,36 +23,44 @@ function isURL(str) {
23
23
  return /^(https?:)\/\//m.test(str);
24
24
  }
25
25
  exports.isURL = isURL;
26
- function getDocsData(dataArray, filter) {
26
+ function getDocsPluginConfig(presetsPlugins, pluginId) {
27
27
  // eslint-disable-next-line array-callback-return
28
- const filteredData = dataArray.filter((data) => {
29
- if (data[0] === filter) {
28
+ const filteredConfig = presetsPlugins.filter((data) => {
29
+ if (data[0] === pluginId) {
30
30
  return data[1];
31
31
  }
32
32
  // Search plugin-content-docs instances
33
33
  if (data[0] === "@docusaurus/plugin-content-docs") {
34
- const pluginId = data[1].id ? data[1].id : "default";
35
- if (pluginId === filter) {
34
+ const configPluginId = data[1].id ? data[1].id : "default";
35
+ if (configPluginId === pluginId) {
36
36
  return data[1];
37
37
  }
38
38
  }
39
39
  })[0];
40
- if (filteredData) {
40
+ if (filteredConfig) {
41
41
  // Search presets, e.g. "classic"
42
- if (filteredData[0] === filter) {
43
- return filteredData[1].docs;
42
+ if (filteredConfig[0] === pluginId) {
43
+ return filteredConfig[1].docs;
44
44
  }
45
45
  // Search plugin-content-docs instances
46
- if (filteredData[0] === "@docusaurus/plugin-content-docs") {
47
- const pluginId = filteredData[1].id ? filteredData[1].id : "default";
48
- if (pluginId === filter) {
49
- return filteredData[1];
46
+ if (filteredConfig[0] === "@docusaurus/plugin-content-docs") {
47
+ const configPluginId = filteredConfig[1].id
48
+ ? filteredConfig[1].id
49
+ : "default";
50
+ if (configPluginId === pluginId) {
51
+ return filteredConfig[1];
50
52
  }
51
53
  }
52
54
  }
53
55
  return;
54
56
  }
55
- exports.getDocsData = getDocsData;
57
+ exports.getDocsPluginConfig = getDocsPluginConfig;
58
+ function getPluginConfig(plugins, pluginId) {
59
+ return plugins.filter((data) => data[1].id === pluginId)[0][1];
60
+ }
61
+ function getPluginInstances(plugins) {
62
+ return plugins.filter((data) => data[0] === "docusaurus-plugin-openapi-docs");
63
+ }
56
64
  function pluginOpenAPIDocs(context, options) {
57
65
  const { config, docsPluginId } = options;
58
66
  const { siteDir, siteConfig } = context;
@@ -60,7 +68,7 @@ function pluginOpenAPIDocs(context, options) {
60
68
  const presets = siteConfig.presets;
61
69
  const plugins = siteConfig.plugins;
62
70
  const presetsPlugins = presets.concat(plugins);
63
- const docData = getDocsData(presetsPlugins, docsPluginId);
71
+ const docData = getDocsPluginConfig(presetsPlugins, docsPluginId);
64
72
  const docRouteBasePath = docData ? docData.routeBasePath : undefined;
65
73
  const docPath = docData ? (docData.path ? docData.path : "docs") : undefined;
66
74
  async function generateApiDocs(options) {
@@ -83,9 +91,7 @@ function pluginOpenAPIDocs(context, options) {
83
91
  // TODO: figure out better way to set default
84
92
  if (Object.keys(sidebarOptions !== null && sidebarOptions !== void 0 ? sidebarOptions : {}).length > 0) {
85
93
  const sidebarSlice = (0, sidebars_1.default)(sidebarOptions, options, loadedApi, tags, docPath);
86
- const sidebarSliceTemplate = template
87
- ? fs_1.default.readFileSync(template).toString()
88
- : `module.exports = {{{slice}}};`;
94
+ const sidebarSliceTemplate = `module.exports = {{{slice}}};`;
89
95
  const view = (0, mustache_1.render)(sidebarSliceTemplate, {
90
96
  slice: JSON.stringify(sidebarSlice),
91
97
  });
@@ -129,12 +135,11 @@ info_path: {{{infoPath}}}
129
135
 
130
136
  {{{markdown}}}
131
137
  `;
132
- const infoMdTemplate = template
133
- ? fs_1.default.readFileSync(template).toString()
134
- : `---
138
+ const infoMdTemplate = `---
135
139
  id: {{{id}}}
136
140
  sidebar_label: {{{title}}}
137
141
  hide_title: true
142
+ custom_edit_url: null
138
143
  ---
139
144
 
140
145
  {{{markdown}}}
@@ -146,12 +151,11 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
146
151
  <DocCardList items={useCurrentSidebarCategory().items}/>
147
152
  \`\`\`
148
153
  `;
149
- const tagMdTemplate = template
150
- ? fs_1.default.readFileSync(template).toString()
151
- : `---
154
+ const tagMdTemplate = `---
152
155
  id: {{{id}}}
153
156
  title: {{{description}}}
154
157
  description: {{{description}}}
158
+ custom_edit_url: null
155
159
  ---
156
160
 
157
161
  {{{markdown}}}
@@ -296,22 +300,45 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
296
300
  .description(`Generates OpenAPI docs in MDX file format and sidebar.js (if enabled).`)
297
301
  .usage("<id>")
298
302
  .arguments("<id>")
299
- .action(async (id) => {
303
+ .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
304
+ .action(async (id, instance) => {
305
+ var _a;
306
+ const options = instance.opts();
307
+ const pluginId = options.pluginId;
308
+ const pluginInstances = getPluginInstances(plugins);
309
+ let targetConfig;
310
+ if (pluginId) {
311
+ try {
312
+ const pluginConfig = getPluginConfig(plugins, pluginId);
313
+ targetConfig = (_a = pluginConfig.config) !== null && _a !== void 0 ? _a : {};
314
+ }
315
+ catch {
316
+ console.error(chalk_1.default.red(`OpenAPI docs plugin ID '${pluginId}' not found.`));
317
+ return;
318
+ }
319
+ }
320
+ else {
321
+ if (pluginInstances.length > 1) {
322
+ console.error(chalk_1.default.red("OpenAPI docs plugin ID must be specified when more than one plugin instance exists."));
323
+ return;
324
+ }
325
+ targetConfig = config;
326
+ }
300
327
  if (id === "all") {
301
- if (config[id]) {
328
+ if (targetConfig[id]) {
302
329
  console.error(chalk_1.default.red("Can't use id 'all' for OpenAPI docs configuration key."));
303
330
  }
304
331
  else {
305
- Object.keys(config).forEach(async function (key) {
306
- await generateApiDocs(config[key]);
332
+ Object.keys(targetConfig).forEach(async function (key) {
333
+ await generateApiDocs(targetConfig[key]);
307
334
  });
308
335
  }
309
336
  }
310
- else if (!config[id]) {
337
+ else if (!targetConfig[id]) {
311
338
  console.error(chalk_1.default.red(`ID '${id}' does not exist in OpenAPI docs config.`));
312
339
  }
313
340
  else {
314
- await generateApiDocs(config[id]);
341
+ await generateApiDocs(targetConfig[id]);
315
342
  }
316
343
  });
317
344
  cli
@@ -319,15 +346,38 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
319
346
  .description(`Generates versioned OpenAPI docs in MDX file format, versions.js and sidebar.js (if enabled).`)
320
347
  .usage("<id:version>")
321
348
  .arguments("<id:version>")
322
- .action(async (id) => {
349
+ .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
350
+ .action(async (id, instance) => {
351
+ var _a;
352
+ const options = instance.opts();
353
+ const pluginId = options.pluginId;
354
+ const pluginInstances = getPluginInstances(plugins);
355
+ let targetConfig;
356
+ if (pluginId) {
357
+ try {
358
+ const pluginConfig = getPluginConfig(plugins, pluginId);
359
+ targetConfig = (_a = pluginConfig.config) !== null && _a !== void 0 ? _a : {};
360
+ }
361
+ catch {
362
+ console.error(chalk_1.default.red(`OpenAPI docs plugin ID '${pluginId}' not found.`));
363
+ return;
364
+ }
365
+ }
366
+ else {
367
+ if (pluginInstances.length > 1) {
368
+ console.error(chalk_1.default.red("OpenAPI docs plugin ID must be specified when more than one plugin instance exists."));
369
+ return;
370
+ }
371
+ targetConfig = config;
372
+ }
323
373
  const [parentId, versionId] = id.split(":");
324
- const parentConfig = Object.assign({}, config[parentId]);
374
+ const parentConfig = Object.assign({}, targetConfig[parentId]);
325
375
  const version = parentConfig.version;
326
376
  const label = parentConfig.label;
327
377
  const baseUrl = parentConfig.baseUrl;
328
378
  let parentVersion = {};
329
379
  parentVersion[version] = { label: label, baseUrl: baseUrl };
330
- const { versions } = config[parentId];
380
+ const { versions } = targetConfig[parentId];
331
381
  const mergedVersions = Object.assign(parentVersion, versions);
332
382
  // Prepare for merge
333
383
  delete parentConfig.versions;
@@ -369,19 +419,42 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
369
419
  .description(`Clears the generated OpenAPI docs MDX files and sidebar.js (if enabled).`)
370
420
  .usage("<id>")
371
421
  .arguments("<id>")
372
- .action(async (id) => {
422
+ .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
423
+ .action(async (id, instance) => {
424
+ var _a;
425
+ const options = instance.opts();
426
+ const pluginId = options.pluginId;
427
+ const pluginInstances = getPluginInstances(plugins);
428
+ let targetConfig;
429
+ if (pluginId) {
430
+ try {
431
+ const pluginConfig = getPluginConfig(plugins, pluginId);
432
+ targetConfig = (_a = pluginConfig.config) !== null && _a !== void 0 ? _a : {};
433
+ }
434
+ catch {
435
+ console.error(chalk_1.default.red(`OpenAPI docs plugin ID '${pluginId}' not found.`));
436
+ return;
437
+ }
438
+ }
439
+ else {
440
+ if (pluginInstances.length > 1) {
441
+ console.error(chalk_1.default.red("OpenAPI docs plugin ID must be specified when more than one plugin instance exists."));
442
+ return;
443
+ }
444
+ targetConfig = config;
445
+ }
373
446
  if (id === "all") {
374
- if (config[id]) {
447
+ if (targetConfig[id]) {
375
448
  console.error(chalk_1.default.red("Can't use id 'all' for OpenAPI docs configuration key."));
376
449
  }
377
450
  else {
378
- Object.keys(config).forEach(async function (key) {
379
- await cleanApiDocs(config[key]);
451
+ Object.keys(targetConfig).forEach(async function (key) {
452
+ await cleanApiDocs(targetConfig[key]);
380
453
  });
381
454
  }
382
455
  }
383
456
  else {
384
- await cleanApiDocs(config[id]);
457
+ await cleanApiDocs(targetConfig[id]);
385
458
  }
386
459
  });
387
460
  cli
@@ -389,10 +462,33 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
389
462
  .description(`Clears the versioned, generated OpenAPI docs MDX files, versions.json and sidebar.js (if enabled).`)
390
463
  .usage("<id:version>")
391
464
  .arguments("<id:version>")
392
- .action(async (id) => {
465
+ .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
466
+ .action(async (id, instance) => {
467
+ var _a;
468
+ const options = instance.opts();
469
+ const pluginId = options.pluginId;
470
+ const pluginInstances = getPluginInstances(plugins);
471
+ let targetConfig;
472
+ if (pluginId) {
473
+ try {
474
+ const pluginConfig = getPluginConfig(plugins, pluginId);
475
+ targetConfig = (_a = pluginConfig.config) !== null && _a !== void 0 ? _a : {};
476
+ }
477
+ catch {
478
+ console.error(chalk_1.default.red(`OpenAPI docs plugin ID '${pluginId}' not found.`));
479
+ return;
480
+ }
481
+ }
482
+ else {
483
+ if (pluginInstances.length > 1) {
484
+ console.error(chalk_1.default.red("OpenAPI docs plugin ID must be specified when more than one plugin instance exists."));
485
+ return;
486
+ }
487
+ targetConfig = config;
488
+ }
393
489
  const [parentId, versionId] = id.split(":");
394
- const { versions } = config[parentId];
395
- const parentConfig = Object.assign({}, config[parentId]);
490
+ const { versions } = targetConfig[parentId];
491
+ const parentConfig = Object.assign({}, targetConfig[parentId]);
396
492
  delete parentConfig.versions;
397
493
  if (versionId === "all") {
398
494
  if (versions[id]) {
@@ -344,7 +344,9 @@ function createDetailsNode(name, schemaName, schema, required) {
344
344
  style: { opacity: "0.6" },
345
345
  children: ` ${schemaName}`,
346
346
  }),
347
- (0, utils_1.guard)(schema.required && schema.required === true, () => [
347
+ (0, utils_1.guard)(Array.isArray(required)
348
+ ? required.includes(name)
349
+ : required === true, () => [
348
350
  (0, utils_1.create)("strong", {
349
351
  style: {
350
352
  fontSize: "var(--ifm-code-font-size)",
@@ -60,15 +60,17 @@ function sampleResponseFromProp(name, prop, obj) {
60
60
  }
61
61
  const sampleResponseFromSchema = (schema = {}) => {
62
62
  try {
63
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
63
64
  let { type, example, allOf, oneOf, anyOf, properties, items } = schema;
64
- if (example !== undefined) {
65
- return example;
66
- }
65
+ // TODO: determine if we should always ignore the example when creating from schema
66
+ // if (example !== undefined) {
67
+ // return example;
68
+ // }
67
69
  if (allOf) {
68
70
  const { mergedSchemas } = (0, createResponseSchema_1.mergeAllOf)(allOf);
69
71
  if (mergedSchemas.properties) {
70
72
  for (const [key, value] of Object.entries(mergedSchemas.properties)) {
71
- if (value.readOnly && value.readOnly === true) {
73
+ if (value.writeOnly && value.writeOnly === true) {
72
74
  delete mergedSchemas.properties[key];
73
75
  }
74
76
  }
@@ -99,14 +101,14 @@ const sampleResponseFromSchema = (schema = {}) => {
99
101
  for (let [name, prop] of Object.entries(properties !== null && properties !== void 0 ? properties : {})) {
100
102
  if (prop.properties) {
101
103
  for (const [key, value] of Object.entries(prop.properties)) {
102
- if (value.readOnly && value.readOnly === true) {
104
+ if (value.writeOnly && value.writeOnly === true) {
103
105
  delete prop.properties[key];
104
106
  }
105
107
  }
106
108
  }
107
109
  if (prop.items && prop.items.properties) {
108
110
  for (const [key, value] of Object.entries(prop.items.properties)) {
109
- if (value.readOnly && value.readOnly === true) {
111
+ if (value.writeOnly && value.writeOnly === true) {
110
112
  delete prop.items.properties[key];
111
113
  }
112
114
  }
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": "1.1.9",
4
+ "version": "1.1.12",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "openapi",
@@ -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.1",
44
- "@docusaurus/plugin-content-docs": "2.0.1",
45
- "@docusaurus/utils": "2.0.1",
46
- "@docusaurus/utils-validation": "2.0.1",
43
+ "@docusaurus/mdx-loader": "^2.0.1",
44
+ "@docusaurus/plugin-content-docs": "^2.0.1",
45
+ "@docusaurus/utils": "^2.0.1",
46
+ "@docusaurus/utils-validation": "^2.0.1",
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",
@@ -68,5 +68,5 @@
68
68
  "engines": {
69
69
  "node": ">=14"
70
70
  },
71
- "gitHead": "c9153730f9f180dbd199fbc9cb66f8470339c877"
71
+ "gitHead": "a45dcbd12f26156147a50f5f61026c3adee4b1c8"
72
72
  }
package/src/index.ts CHANGED
@@ -23,41 +23,51 @@ export function isURL(str: string): boolean {
23
23
  return /^(https?:)\/\//m.test(str);
24
24
  }
25
25
 
26
- export function getDocsData(
27
- dataArray: any[],
28
- filter: string
26
+ export function getDocsPluginConfig(
27
+ presetsPlugins: any[],
28
+ pluginId: string
29
29
  ): Object | undefined {
30
30
  // eslint-disable-next-line array-callback-return
31
- const filteredData = dataArray.filter((data) => {
32
- if (data[0] === filter) {
31
+ const filteredConfig = presetsPlugins.filter((data) => {
32
+ if (data[0] === pluginId) {
33
33
  return data[1];
34
34
  }
35
35
 
36
36
  // Search plugin-content-docs instances
37
37
  if (data[0] === "@docusaurus/plugin-content-docs") {
38
- const pluginId = data[1].id ? data[1].id : "default";
39
- if (pluginId === filter) {
38
+ const configPluginId = data[1].id ? data[1].id : "default";
39
+ if (configPluginId === pluginId) {
40
40
  return data[1];
41
41
  }
42
42
  }
43
43
  })[0];
44
- if (filteredData) {
44
+ if (filteredConfig) {
45
45
  // Search presets, e.g. "classic"
46
- if (filteredData[0] === filter) {
47
- return filteredData[1].docs;
46
+ if (filteredConfig[0] === pluginId) {
47
+ return filteredConfig[1].docs;
48
48
  }
49
49
 
50
50
  // Search plugin-content-docs instances
51
- if (filteredData[0] === "@docusaurus/plugin-content-docs") {
52
- const pluginId = filteredData[1].id ? filteredData[1].id : "default";
53
- if (pluginId === filter) {
54
- return filteredData[1];
51
+ if (filteredConfig[0] === "@docusaurus/plugin-content-docs") {
52
+ const configPluginId = filteredConfig[1].id
53
+ ? filteredConfig[1].id
54
+ : "default";
55
+ if (configPluginId === pluginId) {
56
+ return filteredConfig[1];
55
57
  }
56
58
  }
57
59
  }
58
60
  return;
59
61
  }
60
62
 
63
+ function getPluginConfig(plugins: any[], pluginId: string): any {
64
+ return plugins.filter((data) => data[1].id === pluginId)[0][1];
65
+ }
66
+
67
+ function getPluginInstances(plugins: any[]): any {
68
+ return plugins.filter((data) => data[0] === "docusaurus-plugin-openapi-docs");
69
+ }
70
+
61
71
  export default function pluginOpenAPIDocs(
62
72
  context: LoadContext,
63
73
  options: PluginOptions
@@ -69,7 +79,7 @@ export default function pluginOpenAPIDocs(
69
79
  const presets: any = siteConfig.presets;
70
80
  const plugins: any = siteConfig.plugins;
71
81
  const presetsPlugins = presets.concat(plugins);
72
- const docData: any = getDocsData(presetsPlugins, docsPluginId);
82
+ const docData: any = getDocsPluginConfig(presetsPlugins, docsPluginId);
73
83
  const docRouteBasePath = docData ? docData.routeBasePath : undefined;
74
84
  const docPath = docData ? (docData.path ? docData.path : "docs") : undefined;
75
85
 
@@ -108,9 +118,7 @@ export default function pluginOpenAPIDocs(
108
118
  docPath
109
119
  );
110
120
 
111
- const sidebarSliceTemplate = template
112
- ? fs.readFileSync(template).toString()
113
- : `module.exports = {{{slice}}};`;
121
+ const sidebarSliceTemplate = `module.exports = {{{slice}}};`;
114
122
 
115
123
  const view = render(sidebarSliceTemplate, {
116
124
  slice: JSON.stringify(sidebarSlice),
@@ -162,12 +170,11 @@ info_path: {{{infoPath}}}
162
170
  {{{markdown}}}
163
171
  `;
164
172
 
165
- const infoMdTemplate = template
166
- ? fs.readFileSync(template).toString()
167
- : `---
173
+ const infoMdTemplate = `---
168
174
  id: {{{id}}}
169
175
  sidebar_label: {{{title}}}
170
176
  hide_title: true
177
+ custom_edit_url: null
171
178
  ---
172
179
 
173
180
  {{{markdown}}}
@@ -180,12 +187,11 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
180
187
  \`\`\`
181
188
  `;
182
189
 
183
- const tagMdTemplate = template
184
- ? fs.readFileSync(template).toString()
185
- : `---
190
+ const tagMdTemplate = `---
186
191
  id: {{{id}}}
187
192
  title: {{{description}}}
188
193
  description: {{{description}}}
194
+ custom_edit_url: null
189
195
  ---
190
196
 
191
197
  {{{markdown}}}
@@ -392,25 +398,52 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
392
398
  )
393
399
  .usage("<id>")
394
400
  .arguments("<id>")
395
- .action(async (id) => {
401
+ .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
402
+ .action(async (id, instance) => {
403
+ const options = instance.opts();
404
+ const pluginId = options.pluginId;
405
+ const pluginInstances = getPluginInstances(plugins);
406
+ let targetConfig: any;
407
+ if (pluginId) {
408
+ try {
409
+ const pluginConfig = getPluginConfig(plugins, pluginId);
410
+ targetConfig = pluginConfig.config ?? {};
411
+ } catch {
412
+ console.error(
413
+ chalk.red(`OpenAPI docs plugin ID '${pluginId}' not found.`)
414
+ );
415
+ return;
416
+ }
417
+ } else {
418
+ if (pluginInstances.length > 1) {
419
+ console.error(
420
+ chalk.red(
421
+ "OpenAPI docs plugin ID must be specified when more than one plugin instance exists."
422
+ )
423
+ );
424
+ return;
425
+ }
426
+ targetConfig = config;
427
+ }
428
+
396
429
  if (id === "all") {
397
- if (config[id]) {
430
+ if (targetConfig[id]) {
398
431
  console.error(
399
432
  chalk.red(
400
433
  "Can't use id 'all' for OpenAPI docs configuration key."
401
434
  )
402
435
  );
403
436
  } else {
404
- Object.keys(config).forEach(async function (key) {
405
- await generateApiDocs(config[key]);
437
+ Object.keys(targetConfig).forEach(async function (key) {
438
+ await generateApiDocs(targetConfig[key]);
406
439
  });
407
440
  }
408
- } else if (!config[id]) {
441
+ } else if (!targetConfig[id]) {
409
442
  console.error(
410
443
  chalk.red(`ID '${id}' does not exist in OpenAPI docs config.`)
411
444
  );
412
445
  } else {
413
- await generateApiDocs(config[id]);
446
+ await generateApiDocs(targetConfig[id]);
414
447
  }
415
448
  });
416
449
 
@@ -421,9 +454,35 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
421
454
  )
422
455
  .usage("<id:version>")
423
456
  .arguments("<id:version>")
424
- .action(async (id) => {
457
+ .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
458
+ .action(async (id, instance) => {
459
+ const options = instance.opts();
460
+ const pluginId = options.pluginId;
461
+ const pluginInstances = getPluginInstances(plugins);
462
+ let targetConfig: any;
463
+ if (pluginId) {
464
+ try {
465
+ const pluginConfig = getPluginConfig(plugins, pluginId);
466
+ targetConfig = pluginConfig.config ?? {};
467
+ } catch {
468
+ console.error(
469
+ chalk.red(`OpenAPI docs plugin ID '${pluginId}' not found.`)
470
+ );
471
+ return;
472
+ }
473
+ } else {
474
+ if (pluginInstances.length > 1) {
475
+ console.error(
476
+ chalk.red(
477
+ "OpenAPI docs plugin ID must be specified when more than one plugin instance exists."
478
+ )
479
+ );
480
+ return;
481
+ }
482
+ targetConfig = config;
483
+ }
425
484
  const [parentId, versionId] = id.split(":");
426
- const parentConfig = Object.assign({}, config[parentId]);
485
+ const parentConfig = Object.assign({}, targetConfig[parentId]);
427
486
 
428
487
  const version = parentConfig.version as string;
429
488
  const label = parentConfig.label as string;
@@ -432,7 +491,7 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
432
491
  let parentVersion = {} as any;
433
492
  parentVersion[version] = { label: label, baseUrl: baseUrl };
434
493
 
435
- const { versions } = config[parentId] as any;
494
+ const { versions } = targetConfig[parentId] as any;
436
495
  const mergedVersions = Object.assign(parentVersion, versions);
437
496
 
438
497
  // Prepare for merge
@@ -484,21 +543,47 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
484
543
  )
485
544
  .usage("<id>")
486
545
  .arguments("<id>")
487
- .action(async (id) => {
546
+ .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
547
+ .action(async (id, instance) => {
548
+ const options = instance.opts();
549
+ const pluginId = options.pluginId;
550
+ const pluginInstances = getPluginInstances(plugins);
551
+ let targetConfig: any;
552
+ if (pluginId) {
553
+ try {
554
+ const pluginConfig = getPluginConfig(plugins, pluginId);
555
+ targetConfig = pluginConfig.config ?? {};
556
+ } catch {
557
+ console.error(
558
+ chalk.red(`OpenAPI docs plugin ID '${pluginId}' not found.`)
559
+ );
560
+ return;
561
+ }
562
+ } else {
563
+ if (pluginInstances.length > 1) {
564
+ console.error(
565
+ chalk.red(
566
+ "OpenAPI docs plugin ID must be specified when more than one plugin instance exists."
567
+ )
568
+ );
569
+ return;
570
+ }
571
+ targetConfig = config;
572
+ }
488
573
  if (id === "all") {
489
- if (config[id]) {
574
+ if (targetConfig[id]) {
490
575
  console.error(
491
576
  chalk.red(
492
577
  "Can't use id 'all' for OpenAPI docs configuration key."
493
578
  )
494
579
  );
495
580
  } else {
496
- Object.keys(config).forEach(async function (key) {
497
- await cleanApiDocs(config[key]);
581
+ Object.keys(targetConfig).forEach(async function (key) {
582
+ await cleanApiDocs(targetConfig[key]);
498
583
  });
499
584
  }
500
585
  } else {
501
- await cleanApiDocs(config[id]);
586
+ await cleanApiDocs(targetConfig[id]);
502
587
  }
503
588
  });
504
589
 
@@ -509,11 +594,37 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
509
594
  )
510
595
  .usage("<id:version>")
511
596
  .arguments("<id:version>")
512
- .action(async (id) => {
597
+ .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
598
+ .action(async (id, instance) => {
599
+ const options = instance.opts();
600
+ const pluginId = options.pluginId;
601
+ const pluginInstances = getPluginInstances(plugins);
602
+ let targetConfig: any;
603
+ if (pluginId) {
604
+ try {
605
+ const pluginConfig = getPluginConfig(plugins, pluginId);
606
+ targetConfig = pluginConfig.config ?? {};
607
+ } catch {
608
+ console.error(
609
+ chalk.red(`OpenAPI docs plugin ID '${pluginId}' not found.`)
610
+ );
611
+ return;
612
+ }
613
+ } else {
614
+ if (pluginInstances.length > 1) {
615
+ console.error(
616
+ chalk.red(
617
+ "OpenAPI docs plugin ID must be specified when more than one plugin instance exists."
618
+ )
619
+ );
620
+ return;
621
+ }
622
+ targetConfig = config;
623
+ }
513
624
  const [parentId, versionId] = id.split(":");
514
- const { versions } = config[parentId] as any;
625
+ const { versions } = targetConfig[parentId] as any;
515
626
 
516
- const parentConfig = Object.assign({}, config[parentId]);
627
+ const parentConfig = Object.assign({}, targetConfig[parentId]);
517
628
  delete parentConfig.versions;
518
629
 
519
630
  if (versionId === "all") {
@@ -407,15 +407,20 @@ function createDetailsNode(
407
407
  style: { opacity: "0.6" },
408
408
  children: ` ${schemaName}`,
409
409
  }),
410
- guard(schema.required && schema.required === true, () => [
411
- create("strong", {
412
- style: {
413
- fontSize: "var(--ifm-code-font-size)",
414
- color: "var(--openapi-required)",
415
- },
416
- children: " required",
417
- }),
418
- ]),
410
+ guard(
411
+ Array.isArray(required)
412
+ ? required.includes(name)
413
+ : required === true,
414
+ () => [
415
+ create("strong", {
416
+ style: {
417
+ fontSize: "var(--ifm-code-font-size)",
418
+ color: "var(--openapi-required)",
419
+ },
420
+ children: " required",
421
+ }),
422
+ ]
423
+ ),
419
424
  ],
420
425
  }),
421
426
  create("div", {
@@ -77,18 +77,20 @@ function sampleResponseFromProp(name: string, prop: any, obj: any): any {
77
77
 
78
78
  export const sampleResponseFromSchema = (schema: SchemaObject = {}): any => {
79
79
  try {
80
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
80
81
  let { type, example, allOf, oneOf, anyOf, properties, items } = schema;
81
82
 
82
- if (example !== undefined) {
83
- return example;
84
- }
83
+ // TODO: determine if we should always ignore the example when creating from schema
84
+ // if (example !== undefined) {
85
+ // return example;
86
+ // }
85
87
 
86
88
  if (allOf) {
87
89
  const { mergedSchemas }: { mergedSchemas: SchemaObject } =
88
90
  mergeAllOf(allOf);
89
91
  if (mergedSchemas.properties) {
90
92
  for (const [key, value] of Object.entries(mergedSchemas.properties)) {
91
- if (value.readOnly && value.readOnly === true) {
93
+ if (value.writeOnly && value.writeOnly === true) {
92
94
  delete mergedSchemas.properties[key];
93
95
  }
94
96
  }
@@ -121,7 +123,7 @@ export const sampleResponseFromSchema = (schema: SchemaObject = {}): any => {
121
123
  for (let [name, prop] of Object.entries(properties ?? {})) {
122
124
  if (prop.properties) {
123
125
  for (const [key, value] of Object.entries(prop.properties)) {
124
- if (value.readOnly && value.readOnly === true) {
126
+ if (value.writeOnly && value.writeOnly === true) {
125
127
  delete prop.properties[key];
126
128
  }
127
129
  }
@@ -129,7 +131,7 @@ export const sampleResponseFromSchema = (schema: SchemaObject = {}): any => {
129
131
 
130
132
  if (prop.items && prop.items.properties) {
131
133
  for (const [key, value] of Object.entries(prop.items.properties)) {
132
- if (value.readOnly && value.readOnly === true) {
134
+ if (value.writeOnly && value.writeOnly === true) {
133
135
  delete prop.items.properties[key];
134
136
  }
135
137
  }