docusaurus-plugin-openapi-docs 1.0.1 → 1.0.4

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 (66) hide show
  1. package/README.md +110 -21
  2. package/lib/index.d.ts +7 -1
  3. package/lib/index.js +257 -22
  4. package/lib/markdown/createAuthentication.d.ts +2 -0
  5. package/lib/markdown/createAuthentication.js +139 -0
  6. package/lib/markdown/createContactInfo.d.ts +2 -0
  7. package/lib/markdown/createContactInfo.js +49 -0
  8. package/lib/markdown/createLicense.d.ts +2 -0
  9. package/lib/markdown/createLicense.js +33 -0
  10. package/lib/markdown/createParamsDetails.js +2 -0
  11. package/lib/markdown/createSchemaDetails.js +6 -1
  12. package/lib/markdown/createStatusCodes.js +1 -1
  13. package/lib/markdown/createTermsOfService.d.ts +1 -0
  14. package/lib/markdown/createTermsOfService.js +32 -0
  15. package/lib/markdown/index.d.ts +3 -2
  16. package/lib/markdown/index.js +17 -3
  17. package/lib/openapi/createExample.js +59 -49
  18. package/lib/openapi/openapi.d.ts +5 -4
  19. package/lib/openapi/openapi.js +94 -50
  20. package/lib/openapi/openapi.test.js +0 -6
  21. package/lib/openapi/types.d.ts +5 -1
  22. package/lib/openapi/utils/loadAndBundleSpec.d.ts +3 -0
  23. package/lib/openapi/utils/loadAndBundleSpec.js +44 -0
  24. package/lib/openapi/utils/types.d.ts +306 -0
  25. package/lib/{markdown/createRequestBodyTable.js → openapi/utils/types.js} +0 -6
  26. package/lib/options.d.ts +0 -2
  27. package/lib/options.js +36 -7
  28. package/lib/sidebars/index.d.ts +2 -1
  29. package/lib/sidebars/index.js +91 -35
  30. package/lib/sidebars/utils.d.ts +2 -0
  31. package/lib/sidebars/utils.js +31 -0
  32. package/lib/types.d.ts +35 -11
  33. package/package.json +10 -9
  34. package/src/index.ts +332 -25
  35. package/src/markdown/createAuthentication.ts +160 -0
  36. package/src/markdown/createContactInfo.ts +52 -0
  37. package/src/markdown/createLicense.ts +34 -0
  38. package/src/markdown/createParamsDetails.ts +2 -0
  39. package/src/markdown/createSchemaDetails.ts +8 -2
  40. package/src/markdown/createStatusCodes.ts +1 -1
  41. package/src/markdown/createTermsOfService.ts +30 -0
  42. package/src/markdown/index.ts +23 -3
  43. package/src/openapi/createExample.ts +59 -50
  44. package/src/openapi/openapi.test.ts +0 -6
  45. package/src/openapi/openapi.ts +115 -53
  46. package/src/openapi/types.ts +5 -1
  47. package/src/openapi/utils/loadAndBundleSpec.ts +62 -0
  48. package/src/openapi/utils/types.ts +303 -0
  49. package/src/options.ts +41 -8
  50. package/src/{markdown/createRequestBodyTable.ts → postman-collection.d.ts} +2 -9
  51. package/src/sidebars/index.ts +116 -36
  52. package/src/sidebars/utils.ts +29 -0
  53. package/src/types.ts +36 -10
  54. package/lib/markdown/createFullWidthTable.d.ts +0 -2
  55. package/lib/markdown/createFullWidthTable.js +0 -18
  56. package/lib/markdown/createParamsTable.d.ts +0 -7
  57. package/lib/markdown/createParamsTable.js +0 -80
  58. package/lib/markdown/createRequestBodyTable.d.ts +0 -6
  59. package/lib/markdown/createSchemaTable.d.ts +0 -14
  60. package/lib/markdown/createSchemaTable.js +0 -217
  61. package/src/markdown/createFullWidthTable.ts +0 -16
  62. package/src/markdown/createParamsTable.ts +0 -102
  63. package/src/markdown/createSchemaTable.ts +0 -275
  64. package/src/openapi/__fixtures__/examples/yogurtstore/_category_.json +0 -4
  65. package/src/openapi/__fixtures__/examples/yogurtstore/froyo.yaml +0 -13
  66. package/src/openapi/__fixtures__/examples/yogurtstore/nested/nested.yaml +0 -13
package/src/index.ts CHANGED
@@ -13,27 +13,79 @@ import { Globby } from "@docusaurus/utils";
13
13
  import chalk from "chalk";
14
14
  import { render } from "mustache";
15
15
 
16
- import { createApiPageMD, createInfoPageMD } from "./markdown";
16
+ import { createApiPageMD, createInfoPageMD, createTagPageMD } from "./markdown";
17
17
  import { readOpenapiFiles, processOpenapiFiles } from "./openapi";
18
+ import { OptionsSchema } from "./options";
18
19
  import generateSidebarSlice from "./sidebars";
19
20
  import type { PluginOptions, LoadedContent, APIOptions } from "./types";
20
21
 
21
- export default function pluginOpenAPI(
22
+ export function isURL(str: string): boolean {
23
+ return /^(https?:)\/\//m.test(str);
24
+ }
25
+
26
+ export function getDocsData(
27
+ dataArray: any[],
28
+ filter: string
29
+ ): Object | undefined {
30
+ // eslint-disable-next-line array-callback-return
31
+ const filteredData = dataArray.filter((data) => {
32
+ if (data[0] === filter) {
33
+ return data[1];
34
+ }
35
+
36
+ // Search plugin-content-docs instances
37
+ if (data[0] === "@docusaurus/plugin-content-docs") {
38
+ const pluginId = data[1].id ? data[1].id : "default";
39
+ if (pluginId === filter) {
40
+ return data[1];
41
+ }
42
+ }
43
+ })[0];
44
+ if (filteredData) {
45
+ // Search presets, e.g. "classic"
46
+ if (filteredData[0] === filter) {
47
+ return filteredData[1].docs;
48
+ }
49
+
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];
55
+ }
56
+ }
57
+ }
58
+ return;
59
+ }
60
+
61
+ export default function pluginOpenAPIDocs(
22
62
  context: LoadContext,
23
63
  options: PluginOptions
24
64
  ): Plugin<LoadedContent> {
25
- let { config } = options;
26
- let { siteDir } = context;
65
+ const { config, docPluginId } = options;
66
+ const { siteDir, siteConfig } = context;
67
+
68
+ // Get routeBasePath and path from plugin-content-docs or preset
69
+ const presets: any = siteConfig.presets;
70
+ const plugins: any = siteConfig.plugins;
71
+ const presetsPlugins = presets.concat(plugins);
72
+ const docData: any = getDocsData(presetsPlugins, docPluginId);
73
+ const docRouteBasePath = docData ? docData.routeBasePath : undefined;
74
+ const docPath = docData ? (docData.path ? docData.path : "docs") : undefined;
27
75
 
28
76
  async function generateApiDocs(options: APIOptions) {
29
77
  let { specPath, outputDir, template, sidebarOptions } = options;
30
78
 
31
- const contentPath = path.resolve(siteDir, specPath);
79
+ const contentPath = isURL(specPath)
80
+ ? specPath
81
+ : path.resolve(siteDir, specPath);
32
82
 
33
83
  try {
34
84
  const openapiFiles = await readOpenapiFiles(contentPath, {});
35
- const loadedApi = await processOpenapiFiles(openapiFiles);
36
-
85
+ const [loadedApi, tags] = await processOpenapiFiles(
86
+ openapiFiles,
87
+ sidebarOptions!
88
+ );
37
89
  if (!fs.existsSync(outputDir)) {
38
90
  try {
39
91
  fs.mkdirSync(outputDir, { recursive: true });
@@ -49,9 +101,11 @@ export default function pluginOpenAPI(
49
101
  // TODO: figure out better way to set default
50
102
  if (Object.keys(sidebarOptions ?? {}).length > 0) {
51
103
  const sidebarSlice = generateSidebarSlice(
52
- sidebarOptions!, // TODO: find a better way to handle null
104
+ sidebarOptions!,
53
105
  options,
54
- loadedApi
106
+ loadedApi,
107
+ tags,
108
+ docPath
55
109
  );
56
110
 
57
111
  const sidebarSliceTemplate = template
@@ -81,7 +135,12 @@ export default function pluginOpenAPI(
81
135
  ? fs.readFileSync(template).toString()
82
136
  : `---
83
137
  id: {{{id}}}
138
+ {{^api}}
139
+ sidebar_label: Introduction
140
+ {{/api}}
141
+ {{#api}}
84
142
  sidebar_label: {{{title}}}
143
+ {{/api}}
85
144
  {{^api}}
86
145
  sidebar_position: 0
87
146
  {{/api}}
@@ -95,19 +154,73 @@ api: {{{json}}}
95
154
  {{#api.method}}
96
155
  sidebar_class_name: "{{{api.method}}} api-method"
97
156
  {{/api.method}}
157
+ {{#infoPath}}
158
+ info_path: {{{infoPath}}}
159
+ {{/infoPath}}
160
+ ---
161
+
162
+ {{{markdown}}}
163
+ `;
164
+
165
+ const infoMdTemplate = template
166
+ ? fs.readFileSync(template).toString()
167
+ : `---
168
+ id: {{{id}}}
169
+ sidebar_label: {{{title}}}
170
+ hide_title: true
171
+ ---
172
+
173
+ {{{markdown}}}
174
+
175
+ \`\`\`mdx-code-block
176
+ import DocCardList from '@theme/DocCardList';
177
+ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
178
+
179
+ <DocCardList items={useCurrentSidebarCategory().items}/>
180
+ \`\`\`
181
+ `;
182
+
183
+ const tagMdTemplate = template
184
+ ? fs.readFileSync(template).toString()
185
+ : `---
186
+ id: {{{id}}}
187
+ title: {{{description}}}
188
+ description: {{{description}}}
98
189
  ---
99
190
 
100
191
  {{{markdown}}}
192
+
193
+ \`\`\`mdx-code-block
194
+ import DocCardList from '@theme/DocCardList';
195
+ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
196
+
197
+ <DocCardList items={useCurrentSidebarCategory().items}/>
198
+ \`\`\`
101
199
  `;
102
200
 
103
201
  loadedApi.map(async (item) => {
104
202
  const markdown =
105
- item.type === "api" ? createApiPageMD(item) : createInfoPageMD(item);
203
+ item.type === "api"
204
+ ? createApiPageMD(item)
205
+ : item.type === "info"
206
+ ? createInfoPageMD(item)
207
+ : createTagPageMD(item);
106
208
  item.markdown = markdown;
107
209
  if (item.type === "api") {
108
210
  item.json = JSON.stringify(item.api);
211
+ let infoBasePath = `${outputDir}/${item.infoId}`;
212
+ if (docRouteBasePath) {
213
+ infoBasePath = `${docRouteBasePath}/${outputDir
214
+ .split(docPath!)[1]
215
+ .replace(/^\/+/g, "")}/${item.infoId}`.replace(/^\/+/g, "");
216
+ }
217
+ if (item.infoId) item.infoPath = infoBasePath;
109
218
  }
219
+
110
220
  const view = render(mdTemplate, item);
221
+ const utils = render(infoMdTemplate, item);
222
+ // eslint-disable-next-line testing-library/render-result-naming-convention
223
+ const tagUtils = render(tagMdTemplate, item);
111
224
 
112
225
  if (item.type === "api") {
113
226
  if (!fs.existsSync(`${outputDir}/${item.id}.api.mdx`)) {
@@ -129,15 +242,49 @@ sidebar_class_name: "{{{api.method}}} api-method"
129
242
 
130
243
  // TODO: determine if we actually want/need this
131
244
  if (item.type === "info") {
132
- if (!fs.existsSync(`${outputDir}/index.api.mdx`)) {
245
+ if (!fs.existsSync(`${outputDir}/${item.id}.info.mdx`)) {
246
+ try {
247
+ sidebarOptions?.categoryLinkSource === "info" // Only use utils template if set to "info"
248
+ ? fs.writeFileSync(
249
+ `${outputDir}/${item.id}.info.mdx`,
250
+ utils,
251
+ "utf8"
252
+ )
253
+ : fs.writeFileSync(
254
+ `${outputDir}/${item.id}.info.mdx`,
255
+ view,
256
+ "utf8"
257
+ );
258
+ console.log(
259
+ chalk.green(
260
+ `Successfully created "${outputDir}/${item.id}.info.mdx"`
261
+ )
262
+ );
263
+ } catch (err) {
264
+ console.error(
265
+ chalk.red(`Failed to write "${outputDir}/${item.id}.info.mdx"`),
266
+ chalk.yellow(err)
267
+ );
268
+ }
269
+ }
270
+ }
271
+
272
+ if (item.type === "tag") {
273
+ if (!fs.existsSync(`${outputDir}/${item.id}.tag.mdx`)) {
133
274
  try {
134
- fs.writeFileSync(`${outputDir}/index.api.mdx`, view, "utf8");
275
+ fs.writeFileSync(
276
+ `${outputDir}/${item.id}.tag.mdx`,
277
+ tagUtils,
278
+ "utf8"
279
+ );
135
280
  console.log(
136
- chalk.green(`Successfully created "${outputDir}/index.api.mdx"`)
281
+ chalk.green(
282
+ `Successfully created "${outputDir}/${item.id}.tag.mdx"`
283
+ )
137
284
  );
138
285
  } catch (err) {
139
286
  console.error(
140
- chalk.red(`Failed to write "${outputDir}/index.api.mdx"`),
287
+ chalk.red(`Failed to write "${outputDir}/${item.id}.tag.mdx"`),
141
288
  chalk.yellow(err)
142
289
  );
143
290
  }
@@ -145,6 +292,7 @@ sidebar_class_name: "{{{api.method}}} api-method"
145
292
  }
146
293
  return;
147
294
  });
295
+
148
296
  return;
149
297
  } catch (e) {
150
298
  console.error(chalk.red(`Loading of api failed for "${contentPath}"`));
@@ -155,11 +303,13 @@ sidebar_class_name: "{{{api.method}}} api-method"
155
303
  async function cleanApiDocs(options: APIOptions) {
156
304
  const { outputDir } = options;
157
305
  const apiDir = path.join(siteDir, outputDir);
158
- const apiMdxFiles = await Globby(["*.api.mdx"], {
306
+ const apiMdxFiles = await Globby(["*.api.mdx", "*.info.mdx", "*.tag.mdx"], {
159
307
  cwd: path.resolve(apiDir),
308
+ deep: 1,
160
309
  });
161
310
  const sidebarFile = await Globby(["sidebar.js"], {
162
311
  cwd: path.resolve(apiDir),
312
+ deep: 1,
163
313
  });
164
314
  apiMdxFiles.map((mdx) =>
165
315
  fs.unlink(`${apiDir}/${mdx}`, (err) => {
@@ -190,21 +340,66 @@ sidebar_class_name: "{{{api.method}}} api-method"
190
340
  );
191
341
  }
192
342
 
343
+ async function generateVersions(versions: object, outputDir: string) {
344
+ let versionsArray = [] as object[];
345
+ for (const [version, metadata] of Object.entries(versions)) {
346
+ versionsArray.push({
347
+ version: version,
348
+ label: metadata.label,
349
+ baseUrl: metadata.baseUrl,
350
+ });
351
+ }
352
+
353
+ const versionsJson = JSON.stringify(versionsArray, null, 2);
354
+ try {
355
+ fs.writeFileSync(`${outputDir}/versions.json`, versionsJson, "utf8");
356
+ console.log(
357
+ chalk.green(`Successfully created "${outputDir}/versions.json"`)
358
+ );
359
+ } catch (err) {
360
+ console.error(
361
+ chalk.red(`Failed to write "${outputDir}/versions.json"`),
362
+ chalk.yellow(err)
363
+ );
364
+ }
365
+ }
366
+
367
+ async function cleanVersions(outputDir: string) {
368
+ if (fs.existsSync(`${outputDir}/versions.json`)) {
369
+ fs.unlink(`${outputDir}/versions.json`, (err) => {
370
+ if (err) {
371
+ console.error(
372
+ chalk.red(`Cleanup failed for "${outputDir}/versions.json"`),
373
+ chalk.yellow(err)
374
+ );
375
+ } else {
376
+ console.log(
377
+ chalk.green(`Cleanup succeeded for "${outputDir}/versions.json"`)
378
+ );
379
+ }
380
+ });
381
+ }
382
+ }
383
+
193
384
  return {
194
- name: `docusaurus-plugin-openapi`,
385
+ name: `docusaurus-plugin-openapi-docs`,
195
386
 
196
387
  extendCli(cli): void {
197
388
  cli
198
389
  .command(`gen-api-docs`)
199
- .description(`Generates API Docs mdx and sidebars.`)
200
- .usage(
201
- "[options] <id key value in plugin config within docusaurus.config.js>"
390
+ .description(
391
+ `Generates OpenAPI docs in MDX file format and sidebar.js (if enabled).`
202
392
  )
393
+ .usage("<id>")
203
394
  .arguments("<id>")
204
395
  .action(async (id) => {
205
396
  if (id === "all") {
206
397
  if (config[id]) {
207
- console.error(chalk.red("Can't use id 'all' for API Doc."));
398
+ console.error(
399
+ chalk.red(
400
+ "Can't use id 'all' for OpenAPI docs configuration key."
401
+ )
402
+ );
208
403
  } else {
209
404
  Object.keys(config).forEach(async function (key) {
210
405
  await generateApiDocs(config[key]);
@@ -212,24 +407,91 @@ sidebar_class_name: "{{{api.method}}} api-method"
212
407
  }
213
408
  } else if (!config[id]) {
214
409
  console.error(
215
- chalk.red(`ID ${id} does not exist in openapi-plugin config`)
410
+ chalk.red(`ID '${id}' does not exist in OpenAPI docs config.`)
216
411
  );
217
412
  } else {
218
413
  await generateApiDocs(config[id]);
219
414
  }
220
415
  });
221
416
 
417
+ cli
418
+ .command(`gen-api-docs:version`)
419
+ .description(
420
+ `Generates versioned OpenAPI docs in MDX file format, versions.js and sidebar.js (if enabled).`
421
+ )
422
+ .usage("<id:version>")
423
+ .arguments("<id:version>")
424
+ .action(async (id) => {
425
+ const [parentId, versionId] = id.split(":");
426
+ const parentConfig = Object.assign({}, config[parentId]);
427
+
428
+ const version = parentConfig.version as string;
429
+ const label = parentConfig.label as string;
430
+ const baseUrl = parentConfig.baseUrl as string;
431
+
432
+ let parentVersion = {} as any;
433
+ parentVersion[version] = { label: label, baseUrl: baseUrl };
434
+
435
+ const { versions } = config[parentId] as any;
436
+ const mergedVersions = Object.assign(parentVersion, versions);
437
+
438
+ // Prepare for merge
439
+ delete parentConfig.versions;
440
+ delete parentConfig.version;
441
+ delete parentConfig.label;
442
+ delete parentConfig.baseUrl;
443
+
444
+ // TODO: handle when no versions are defined by version command is passed
445
+ if (versionId === "all") {
446
+ if (versions[id]) {
447
+ console.error(
448
+ chalk.red(
449
+ "Can't use id 'all' for OpenAPI docs versions configuration key."
450
+ )
451
+ );
452
+ } else {
453
+ await generateVersions(mergedVersions, parentConfig.outputDir);
454
+ Object.keys(versions).forEach(async (key) => {
455
+ const versionConfig = versions[key];
456
+ const mergedConfig = {
457
+ ...parentConfig,
458
+ ...versionConfig,
459
+ };
460
+ await generateApiDocs(mergedConfig);
461
+ });
462
+ }
463
+ } else if (!versions[versionId]) {
464
+ console.error(
465
+ chalk.red(
466
+ `Version ID '${versionId}' does not exist in OpenAPI docs versions config.`
467
+ )
468
+ );
469
+ } else {
470
+ const versionConfig = versions[versionId];
471
+ const mergedConfig = {
472
+ ...parentConfig,
473
+ ...versionConfig,
474
+ };
475
+ await generateVersions(mergedVersions, parentConfig.outputDir);
476
+ await generateApiDocs(mergedConfig);
477
+ }
478
+ });
479
+
222
480
  cli
223
481
  .command(`clean-api-docs`)
224
- .description(`Clears the Generated API Docs mdx and sidebars.`)
225
- .usage(
226
- "[options] <id key value in plugin config within docusaurus.config.js>"
482
+ .description(
483
+ `Clears the generated OpenAPI docs MDX files and sidebar.js (if enabled).`
227
484
  )
485
+ .usage("<id>")
228
486
  .arguments("<id>")
229
487
  .action(async (id) => {
230
488
  if (id === "all") {
231
489
  if (config[id]) {
232
- console.error(chalk.red("Can't use id 'all' for API Doc."));
490
+ console.error(
491
+ chalk.red(
492
+ "Can't use id 'all' for OpenAPI docs configuration key."
493
+ )
494
+ );
233
495
  } else {
234
496
  Object.keys(config).forEach(async function (key) {
235
497
  await cleanApiDocs(config[key]);
@@ -239,6 +501,51 @@ sidebar_class_name: "{{{api.method}}} api-method"
239
501
  await cleanApiDocs(config[id]);
240
502
  }
241
503
  });
504
+
505
+ cli
506
+ .command(`clean-api-docs:version`)
507
+ .description(
508
+ `Clears the versioned, generated OpenAPI docs MDX files, versions.json and sidebar.js (if enabled).`
509
+ )
510
+ .usage("<id:version>")
511
+ .arguments("<id:version>")
512
+ .action(async (id) => {
513
+ const [parentId, versionId] = id.split(":");
514
+ const { versions } = config[parentId] as any;
515
+
516
+ const parentConfig = Object.assign({}, config[parentId]);
517
+ delete parentConfig.versions;
518
+
519
+ if (versionId === "all") {
520
+ if (versions[id]) {
521
+ chalk.red(
522
+ "Can't use id 'all' for OpenAPI docs versions configuration key."
523
+ );
524
+ } else {
525
+ await cleanVersions(parentConfig.outputDir);
526
+ Object.keys(versions).forEach(async (key) => {
527
+ const versionConfig = versions[key];
528
+ const mergedConfig = {
529
+ ...parentConfig,
530
+ ...versionConfig,
531
+ };
532
+ await cleanApiDocs(mergedConfig);
533
+ });
534
+ }
535
+ } else {
536
+ const versionConfig = versions[versionId];
537
+ const mergedConfig = {
538
+ ...parentConfig,
539
+ ...versionConfig,
540
+ };
541
+ await cleanApiDocs(mergedConfig);
542
+ }
543
+ });
242
544
  },
243
545
  };
244
546
  }
547
+
548
+ pluginOpenAPIDocs.validateOptions = ({ options, validate }: any) => {
549
+ const validatedOptions = validate(OptionsSchema, options);
550
+ return validatedOptions;
551
+ };
@@ -0,0 +1,160 @@
1
+ /* ============================================================================
2
+ * Copyright (c) Palo Alto Networks
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ * ========================================================================== */
7
+
8
+ import { OAuthFlowObject, SecuritySchemeObject } from "../openapi/types";
9
+ import { createDescription } from "./createDescription";
10
+ import { create, guard } from "./utils";
11
+
12
+ export function createAuthentication(securitySchemes: SecuritySchemeObject) {
13
+ if (!securitySchemes || !Object.keys(securitySchemes).length) return "";
14
+
15
+ const createAuthenticationTable = (securityScheme: any) => {
16
+ const { bearerFormat, flows, name, scheme, type } = securityScheme;
17
+
18
+ const createSecuritySchemeTypeRow = () =>
19
+ create("tr", {
20
+ children: [
21
+ create("th", { children: "Security Scheme Type:" }),
22
+ create("td", { children: type }),
23
+ ],
24
+ });
25
+
26
+ const createOAuthFlowRows = () => {
27
+ const flowRows = Object.entries(flows).map(([flowType, flowObj]) => {
28
+ const { authorizationUrl, tokenUrl, refreshUrl, scopes } =
29
+ flowObj as OAuthFlowObject;
30
+
31
+ return create("tr", {
32
+ children: [
33
+ create("th", { children: `${flowType} OAuth Flow:` }),
34
+ create("td", {
35
+ children: [
36
+ guard(tokenUrl, () =>
37
+ create("p", { children: `Token URL: ${tokenUrl}` })
38
+ ),
39
+ guard(authorizationUrl, () =>
40
+ create("p", {
41
+ children: `Authorization URL: ${authorizationUrl}`,
42
+ })
43
+ ),
44
+ guard(refreshUrl, () =>
45
+ create("p", { children: `Refresh URL: ${refreshUrl}` })
46
+ ),
47
+ create("span", { children: "Scopes:" }),
48
+ create("ul", {
49
+ children: Object.entries(scopes).map(([scope, description]) =>
50
+ create("li", { children: `${scope}: ${description}` })
51
+ ),
52
+ }),
53
+ ],
54
+ }),
55
+ ],
56
+ });
57
+ });
58
+
59
+ return flowRows.join("");
60
+ };
61
+
62
+ switch (type) {
63
+ case "apiKey":
64
+ return create("div", {
65
+ children: [
66
+ create("table", {
67
+ children: create("tbody", {
68
+ children: [
69
+ createSecuritySchemeTypeRow(),
70
+ create("tr", {
71
+ children: [
72
+ create("th", { children: "Header parameter name:" }),
73
+ create("td", { children: name }),
74
+ ],
75
+ }),
76
+ ],
77
+ }),
78
+ }),
79
+ ],
80
+ });
81
+ case "http":
82
+ return create("div", {
83
+ children: [
84
+ create("table", {
85
+ children: create("tbody", {
86
+ children: [
87
+ createSecuritySchemeTypeRow(),
88
+ create("tr", {
89
+ children: [
90
+ create("th", { children: "HTTP Authorization Scheme:" }),
91
+ create("td", { children: scheme }),
92
+ ],
93
+ }),
94
+ create("tr", {
95
+ children: [
96
+ create("th", { children: "Bearer format:" }),
97
+ create("td", { children: bearerFormat }),
98
+ ],
99
+ }),
100
+ ],
101
+ }),
102
+ }),
103
+ ],
104
+ });
105
+ case "oauth2":
106
+ return create("div", {
107
+ children: [
108
+ create("table", {
109
+ children: create("tbody", {
110
+ children: [
111
+ createSecuritySchemeTypeRow(),
112
+ createOAuthFlowRows(),
113
+ ],
114
+ }),
115
+ }),
116
+ ],
117
+ });
118
+ default:
119
+ return "";
120
+ }
121
+ };
122
+
123
+ const formatTabLabel = (str: string) => {
124
+ const formattedLabel = str
125
+ .replace(/(_|-)/g, " ")
126
+ .trim()
127
+ .replace(/\w\S*/g, (str) => str.charAt(0).toUpperCase() + str.substr(1))
128
+ .replace(/([a-z])([A-Z])/g, "$1 $2")
129
+ .replace(/([A-Z])([A-Z][a-z])/g, "$1 $2");
130
+
131
+ const isOAuth = formattedLabel.toLowerCase().includes("oauth2");
132
+ const isApiKey = formattedLabel.toLowerCase().includes("api");
133
+
134
+ return isOAuth ? "OAuth 2.0" : isApiKey ? "API Key" : formattedLabel;
135
+ };
136
+
137
+ return create("div", {
138
+ children: [
139
+ create("h2", {
140
+ children: "Authentication",
141
+ id: "authentication",
142
+ style: { marginBottom: "1rem" },
143
+ }),
144
+ create("Tabs", {
145
+ children: Object.entries(securitySchemes).map(
146
+ ([schemeType, schemeObj]) =>
147
+ create("TabItem", {
148
+ label: formatTabLabel(schemeType),
149
+ value: `${schemeType}`,
150
+ children: [
151
+ createDescription(schemeObj.description),
152
+ createAuthenticationTable(schemeObj),
153
+ ],
154
+ })
155
+ ),
156
+ }),
157
+ ],
158
+ style: { marginBottom: "2rem" },
159
+ });
160
+ }
@@ -0,0 +1,52 @@
1
+ /* ============================================================================
2
+ * Copyright (c) Palo Alto Networks
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ * ========================================================================== */
7
+
8
+ import { ContactObject } from "../openapi/types";
9
+ import { create, guard } from "./utils";
10
+
11
+ export function createContactInfo(contact: ContactObject) {
12
+ if (!contact || !Object.keys(contact).length) return "";
13
+ const { name, url, email } = contact;
14
+
15
+ return create("div", {
16
+ style: {
17
+ display: "flex",
18
+ flexDirection: "column",
19
+ marginBottom: "var(--ifm-paragraph-margin-bottom)",
20
+ },
21
+ children: [
22
+ create("h3", {
23
+ style: {
24
+ marginBottom: "0.25rem",
25
+ },
26
+ children: "Contact",
27
+ }),
28
+ create("span", {
29
+ children: [
30
+ guard(name, () => `${name}: `),
31
+ guard(email, () =>
32
+ create("a", {
33
+ href: `mailto:${email}`,
34
+ children: `${email}`,
35
+ })
36
+ ),
37
+ ],
38
+ }),
39
+ guard(url, () =>
40
+ create("span", {
41
+ children: [
42
+ "URL: ",
43
+ create("a", {
44
+ href: `${url}`,
45
+ children: `${url}`,
46
+ }),
47
+ ],
48
+ })
49
+ ),
50
+ ],
51
+ });
52
+ }