docusaurus-plugin-openapi-docs 4.5.1 → 4.7.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 (39) hide show
  1. package/README.md +110 -22
  2. package/lib/index.js +122 -50
  3. package/lib/markdown/createHeading.js +1 -1
  4. package/lib/markdown/createRequestHeader.js +5 -3
  5. package/lib/markdown/createSchema.js +2 -2
  6. package/lib/markdown/index.js +3 -2
  7. package/lib/markdown/schema.js +5 -0
  8. package/lib/markdown/utils.d.ts +38 -1
  9. package/lib/markdown/utils.js +100 -2
  10. package/lib/openapi/createSchemaExample.js +16 -2
  11. package/lib/openapi/createSchemaExample.test.d.ts +1 -0
  12. package/lib/openapi/createSchemaExample.test.js +48 -0
  13. package/lib/openapi/openapi.js +38 -17
  14. package/lib/openapi/openapi.test.js +48 -0
  15. package/lib/openapi/webhooks.test.d.ts +1 -0
  16. package/lib/openapi/webhooks.test.js +23 -0
  17. package/lib/options.js +4 -0
  18. package/lib/sidebars/index.js +12 -3
  19. package/package.json +16 -16
  20. package/src/index.ts +165 -62
  21. package/src/markdown/createHeading.ts +2 -2
  22. package/src/markdown/createRequestHeader.ts +9 -11
  23. package/src/markdown/createSchema.ts +4 -2
  24. package/src/markdown/index.ts +3 -2
  25. package/src/markdown/schema.ts +6 -0
  26. package/src/markdown/utils.ts +153 -3
  27. package/src/openapi/__fixtures__/webhook/openapi.yaml +17 -0
  28. package/src/openapi/createSchemaExample.test.ts +57 -0
  29. package/src/openapi/createSchemaExample.ts +26 -2
  30. package/src/openapi/openapi.test.ts +58 -0
  31. package/src/openapi/openapi.ts +35 -6
  32. package/src/openapi/webhooks.test.ts +30 -0
  33. package/src/options.ts +4 -0
  34. package/src/plugin-openapi.d.ts +1 -1
  35. package/src/sidebars/index.ts +15 -3
  36. package/src/{types.ts → types.d.ts} +12 -2
  37. package/lib/types.d.ts +0 -135
  38. package/lib/types.js +0 -8
  39. package/src/plugin-content-docs-types.d.ts +0 -42
package/src/index.ts CHANGED
@@ -21,6 +21,7 @@ import {
21
21
  createSchemaPageMD,
22
22
  createTagPageMD,
23
23
  } from "./markdown";
24
+ import { ExternalFile, runWithExternalization } from "./markdown/utils";
24
25
  import { processOpenapiFiles, readOpenapiFiles } from "./openapi";
25
26
  import { OptionsSchema } from "./options";
26
27
  import generateSidebarSlice from "./sidebars";
@@ -123,9 +124,12 @@ export default function pluginOpenAPIDocs(
123
124
  markdownGenerators,
124
125
  downloadUrl,
125
126
  sidebarOptions,
127
+ schemasOnly,
126
128
  disableCompression,
127
129
  } = options;
128
130
 
131
+ const isSchemasOnly = schemasOnly === true;
132
+
129
133
  // Remove trailing slash before proceeding
130
134
  outputDir = outputDir.replace(/\/$/, "");
131
135
 
@@ -160,7 +164,7 @@ export default function pluginOpenAPIDocs(
160
164
  }
161
165
 
162
166
  // TODO: figure out better way to set default
163
- if (Object.keys(sidebarOptions ?? {}).length > 0) {
167
+ if (!isSchemasOnly && Object.keys(sidebarOptions ?? {}).length > 0) {
164
168
  const sidebarSlice = generateSidebarSlice(
165
169
  sidebarOptions!,
166
170
  options,
@@ -234,6 +238,9 @@ hide_send_button: true
234
238
  {{#frontMatter.show_extensions}}
235
239
  show_extensions: true
236
240
  {{/frontMatter.show_extensions}}
241
+ {{#frontMatter.mask_credentials_disabled}}
242
+ mask_credentials: false
243
+ {{/frontMatter.mask_credentials_disabled}}
237
244
  ---
238
245
 
239
246
  {{{markdown}}}
@@ -327,8 +334,24 @@ custom_edit_url: null
327
334
  if (downloadUrl) {
328
335
  item.downloadUrl = downloadUrl;
329
336
  }
330
- const markdown = pageGeneratorByType[item.type](item as any);
331
- item.markdown = markdown;
337
+
338
+ // Generate markdown, with externalization for API and schema pages
339
+ let externalFiles: ExternalFile[] = [];
340
+ if (
341
+ options.externalJsonProps &&
342
+ (item.type === "api" || item.type === "schema")
343
+ ) {
344
+ const result = runWithExternalization(item.id, () =>
345
+ pageGeneratorByType[item.type](item as any)
346
+ );
347
+ item.markdown = result.result;
348
+ externalFiles = result.files;
349
+ } else {
350
+ item.markdown = pageGeneratorByType[item.type](item as any);
351
+ }
352
+ if (isSchemasOnly && item.type !== "schema") {
353
+ return;
354
+ }
332
355
  if (item.type === "api") {
333
356
  // opportunity to compress JSON
334
357
  // const serialize = (o: any) => {
@@ -344,9 +367,18 @@ custom_edit_url: null
344
367
  .toString("base64"));
345
368
  let infoBasePath = `${outputDir}/${item.infoId}`;
346
369
  if (docRouteBasePath) {
347
- infoBasePath = `${docRouteBasePath}/${outputDir
348
- .split(docPath!)[1]
349
- .replace(/^\/+/g, "")}/${item.infoId}`.replace(/^\/+/g, "");
370
+ // Safely extract path segment, handling cases where docPath may not be in outputDir
371
+ const outputSegment =
372
+ docPath && outputDir.includes(docPath)
373
+ ? (outputDir.split(docPath)[1]?.replace(/^\/+/g, "") ?? "")
374
+ : outputDir
375
+ .slice(outputDir.indexOf("/", 1))
376
+ .replace(/^\/+/g, "");
377
+ infoBasePath =
378
+ `${docRouteBasePath}/${outputSegment}/${item.infoId}`.replace(
379
+ /^\/+/g,
380
+ ""
381
+ );
350
382
  }
351
383
  if (item.infoId) item.infoPath = infoBasePath;
352
384
  }
@@ -365,6 +397,18 @@ custom_edit_url: null
365
397
  "Operation must have summary or operationId defined"
366
398
  );
367
399
  }
400
+
401
+ // Write externalized JSON files
402
+ for (const jsonFile of externalFiles) {
403
+ const jsonPath = `${outputDir}/${jsonFile.filename}`;
404
+ if (!fs.existsSync(jsonPath)) {
405
+ fs.writeFileSync(jsonPath, jsonFile.content, "utf8");
406
+ console.log(
407
+ chalk.green(`Successfully created "${jsonPath}"`)
408
+ );
409
+ }
410
+ }
411
+
368
412
  fs.writeFileSync(`${outputDir}/${item.id}.api.mdx`, view, "utf8");
369
413
  console.log(
370
414
  chalk.green(
@@ -452,6 +496,18 @@ custom_edit_url: null
452
496
  }
453
497
  // eslint-disable-next-line testing-library/render-result-naming-convention
454
498
  const schemaView = render(schemaMdTemplate, item);
499
+
500
+ // Write externalized JSON files in schemas directory
501
+ for (const jsonFile of externalFiles) {
502
+ const jsonPath = `${outputDir}/schemas/${jsonFile.filename}`;
503
+ if (!fs.existsSync(jsonPath)) {
504
+ fs.writeFileSync(jsonPath, jsonFile.content, "utf8");
505
+ console.log(
506
+ chalk.green(`Successfully created "${jsonPath}"`)
507
+ );
508
+ }
509
+ }
510
+
455
511
  fs.writeFileSync(
456
512
  `${outputDir}/schemas/${item.id}.schema.mdx`,
457
513
  schemaView,
@@ -482,29 +538,74 @@ custom_edit_url: null
482
538
  }
483
539
  }
484
540
 
485
- async function cleanApiDocs(options: APIOptions) {
541
+ async function cleanApiDocs(options: APIOptions, schemasOnly = false) {
486
542
  const { outputDir } = options;
487
543
  const apiDir = posixPath(path.join(siteDir, outputDir));
488
- const apiMdxFiles = await Globby(["*.api.mdx", "*.info.mdx", "*.tag.mdx"], {
489
- cwd: path.resolve(apiDir),
490
- deep: 1,
491
- });
492
- const sidebarFile = await Globby(["sidebar.js", "sidebar.ts"], {
493
- cwd: path.resolve(apiDir),
494
- deep: 1,
495
- });
496
- apiMdxFiles.map((mdx) =>
497
- fs.unlink(`${apiDir}/${mdx}`, (err) => {
498
- if (err) {
499
- console.error(
500
- chalk.red(`Cleanup failed for "${apiDir}/${mdx}"`),
501
- chalk.yellow(err)
502
- );
503
- } else {
504
- console.log(chalk.green(`Cleanup succeeded for "${apiDir}/${mdx}"`));
544
+
545
+ // When schemasOnly is true, only clean the schemas directory
546
+ if (!schemasOnly) {
547
+ const apiMdxFiles = await Globby(
548
+ ["*.api.mdx", "*.info.mdx", "*.tag.mdx"],
549
+ {
550
+ cwd: path.resolve(apiDir),
551
+ deep: 1,
505
552
  }
506
- })
507
- );
553
+ );
554
+ const sidebarFile = await Globby(["sidebar.js", "sidebar.ts"], {
555
+ cwd: path.resolve(apiDir),
556
+ deep: 1,
557
+ });
558
+ // Clean up externalized JSON files
559
+ const jsonFiles = await Globby(["*.json", "!versions.json"], {
560
+ cwd: path.resolve(apiDir),
561
+ deep: 1,
562
+ });
563
+ apiMdxFiles.map((mdx) =>
564
+ fs.unlink(`${apiDir}/${mdx}`, (err) => {
565
+ if (err) {
566
+ console.error(
567
+ chalk.red(`Cleanup failed for "${apiDir}/${mdx}"`),
568
+ chalk.yellow(err)
569
+ );
570
+ } else {
571
+ console.log(
572
+ chalk.green(`Cleanup succeeded for "${apiDir}/${mdx}"`)
573
+ );
574
+ }
575
+ })
576
+ );
577
+
578
+ sidebarFile.map((sidebar) =>
579
+ fs.unlink(`${apiDir}/${sidebar}`, (err) => {
580
+ if (err) {
581
+ console.error(
582
+ chalk.red(`Cleanup failed for "${apiDir}/${sidebar}"`),
583
+ chalk.yellow(err)
584
+ );
585
+ } else {
586
+ console.log(
587
+ chalk.green(`Cleanup succeeded for "${apiDir}/${sidebar}"`)
588
+ );
589
+ }
590
+ })
591
+ );
592
+
593
+ // Clean up externalized JSON files
594
+ jsonFiles.map((jsonFile) =>
595
+ fs.unlink(`${apiDir}/${jsonFile}`, (err) => {
596
+ if (err) {
597
+ console.error(
598
+ chalk.red(`Cleanup failed for "${apiDir}/${jsonFile}"`),
599
+ chalk.yellow(err)
600
+ );
601
+ } else {
602
+ console.log(
603
+ chalk.green(`Cleanup succeeded for "${apiDir}/${jsonFile}"`)
604
+ );
605
+ }
606
+ })
607
+ );
608
+ }
508
609
 
509
610
  try {
510
611
  fs.rmSync(`${apiDir}/schemas`, { recursive: true });
@@ -517,21 +618,6 @@ custom_edit_url: null
517
618
  );
518
619
  }
519
620
  }
520
-
521
- sidebarFile.map((sidebar) =>
522
- fs.unlink(`${apiDir}/${sidebar}`, (err) => {
523
- if (err) {
524
- console.error(
525
- chalk.red(`Cleanup failed for "${apiDir}/${sidebar}"`),
526
- chalk.yellow(err)
527
- );
528
- } else {
529
- console.log(
530
- chalk.green(`Cleanup succeeded for "${apiDir}/${sidebar}"`)
531
- );
532
- }
533
- })
534
- );
535
621
  }
536
622
 
537
623
  async function generateVersions(versions: object, outputDir: string) {
@@ -632,7 +718,7 @@ custom_edit_url: null
632
718
  }
633
719
  }
634
720
 
635
- async function cleanAllVersions(options: APIOptions) {
721
+ async function cleanAllVersions(options: APIOptions, schemasOnly = false) {
636
722
  const parentOptions = Object.assign({}, options);
637
723
 
638
724
  const { versions } = parentOptions as any;
@@ -640,14 +726,16 @@ custom_edit_url: null
640
726
  delete parentOptions.versions;
641
727
 
642
728
  if (versions != null && Object.keys(versions).length > 0) {
643
- await cleanVersions(parentOptions.outputDir);
729
+ if (!schemasOnly) {
730
+ await cleanVersions(parentOptions.outputDir);
731
+ }
644
732
  Object.keys(versions).forEach(async (key) => {
645
733
  const versionOptions = versions[key];
646
734
  const mergedOptions = {
647
735
  ...parentOptions,
648
736
  ...versionOptions,
649
737
  };
650
- await cleanApiDocs(mergedOptions);
738
+ await cleanApiDocs(mergedOptions, schemasOnly);
651
739
  });
652
740
  }
653
741
  }
@@ -665,10 +753,12 @@ custom_edit_url: null
665
753
  .arguments("<id>")
666
754
  .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
667
755
  .option("--all-versions", "Generate all versions.")
756
+ .option("--schemas-only", "Generate only schema docs.")
668
757
  .action(async (id, instance) => {
669
758
  const options = instance.opts();
670
759
  const pluginId = options.pluginId;
671
760
  const allVersions = options.allVersions;
761
+ const schemasOnly = options.schemasOnly;
672
762
  const pluginInstances = getPluginInstances(plugins);
673
763
  let targetConfig: any;
674
764
  let targetDocsPluginId: any;
@@ -695,6 +785,9 @@ custom_edit_url: null
695
785
  targetConfig = config;
696
786
  }
697
787
 
788
+ const withSchemaOverride = (apiOptions: APIOptions): APIOptions =>
789
+ schemasOnly ? { ...apiOptions, schemasOnly: true } : apiOptions;
790
+
698
791
  if (id === "all") {
699
792
  if (targetConfig[id]) {
700
793
  console.error(
@@ -704,12 +797,10 @@ custom_edit_url: null
704
797
  );
705
798
  } else {
706
799
  Object.keys(targetConfig).forEach(async function (key) {
707
- await generateApiDocs(targetConfig[key], targetDocsPluginId);
800
+ const apiOptions = withSchemaOverride(targetConfig[key]);
801
+ await generateApiDocs(apiOptions, targetDocsPluginId);
708
802
  if (allVersions) {
709
- await generateAllVersions(
710
- targetConfig[key],
711
- targetDocsPluginId
712
- );
803
+ await generateAllVersions(apiOptions, targetDocsPluginId);
713
804
  }
714
805
  });
715
806
  }
@@ -718,9 +809,10 @@ custom_edit_url: null
718
809
  chalk.red(`ID '${id}' does not exist in OpenAPI docs config.`)
719
810
  );
720
811
  } else {
721
- await generateApiDocs(targetConfig[id], targetDocsPluginId);
812
+ const apiOptions = withSchemaOverride(targetConfig[id]);
813
+ await generateApiDocs(apiOptions, targetDocsPluginId);
722
814
  if (allVersions) {
723
- await generateAllVersions(targetConfig[id], targetDocsPluginId);
815
+ await generateAllVersions(apiOptions, targetDocsPluginId);
724
816
  }
725
817
  }
726
818
  });
@@ -733,9 +825,11 @@ custom_edit_url: null
733
825
  .usage("<id:version>")
734
826
  .arguments("<id:version>")
735
827
  .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
828
+ .option("--schemas-only", "Generate only schema docs.")
736
829
  .action(async (id, instance) => {
737
830
  const options = instance.opts();
738
831
  const pluginId = options.pluginId;
832
+ const schemasOnly = options.schemasOnly;
739
833
  const pluginInstances = getPluginInstances(plugins);
740
834
  let targetConfig: any;
741
835
  let targetDocsPluginId: any;
@@ -764,6 +858,9 @@ custom_edit_url: null
764
858
  const [parentId, versionId] = id.split(":");
765
859
  const parentConfig = Object.assign({}, targetConfig[parentId]);
766
860
 
861
+ const withSchemaOverride = (apiOptions: APIOptions): APIOptions =>
862
+ schemasOnly ? { ...apiOptions, schemasOnly: true } : apiOptions;
863
+
767
864
  const version = parentConfig.version as string;
768
865
  const label = parentConfig.label as string;
769
866
  const baseUrl = parentConfig.baseUrl as string;
@@ -793,10 +890,10 @@ custom_edit_url: null
793
890
  await generateVersions(mergedVersions, parentConfig.outputDir);
794
891
  Object.keys(versions).forEach(async (key) => {
795
892
  const versionConfig = versions[key];
796
- const mergedConfig = {
893
+ const mergedConfig = withSchemaOverride({
797
894
  ...parentConfig,
798
895
  ...versionConfig,
799
- };
896
+ });
800
897
  await generateApiDocs(mergedConfig, targetDocsPluginId);
801
898
  });
802
899
  }
@@ -808,10 +905,10 @@ custom_edit_url: null
808
905
  );
809
906
  } else {
810
907
  const versionConfig = versions[versionId];
811
- const mergedConfig = {
908
+ const mergedConfig = withSchemaOverride({
812
909
  ...parentConfig,
813
910
  ...versionConfig,
814
- };
911
+ });
815
912
  await generateVersions(mergedVersions, parentConfig.outputDir);
816
913
  await generateApiDocs(mergedConfig, targetDocsPluginId);
817
914
  }
@@ -826,10 +923,12 @@ custom_edit_url: null
826
923
  .arguments("<id>")
827
924
  .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
828
925
  .option("--all-versions", "Clean all versions.")
926
+ .option("--schemas-only", "Clean only schema docs.")
829
927
  .action(async (id, instance) => {
830
928
  const options = instance.opts();
831
929
  const pluginId = options.pluginId;
832
930
  const allVersions = options.allVersions;
931
+ const schemasOnly = options.schemasOnly;
833
932
  const pluginInstances = getPluginInstances(plugins);
834
933
  let targetConfig: any;
835
934
  if (pluginId) {
@@ -862,16 +961,16 @@ custom_edit_url: null
862
961
  );
863
962
  } else {
864
963
  Object.keys(targetConfig).forEach(async function (key) {
865
- await cleanApiDocs(targetConfig[key]);
964
+ await cleanApiDocs(targetConfig[key], schemasOnly);
866
965
  if (allVersions) {
867
- await cleanAllVersions(targetConfig[key]);
966
+ await cleanAllVersions(targetConfig[key], schemasOnly);
868
967
  }
869
968
  });
870
969
  }
871
970
  } else {
872
- await cleanApiDocs(targetConfig[id]);
971
+ await cleanApiDocs(targetConfig[id], schemasOnly);
873
972
  if (allVersions) {
874
- await cleanAllVersions(targetConfig[id]);
973
+ await cleanAllVersions(targetConfig[id], schemasOnly);
875
974
  }
876
975
  }
877
976
  });
@@ -884,9 +983,11 @@ custom_edit_url: null
884
983
  .usage("<id:version>")
885
984
  .arguments("<id:version>")
886
985
  .option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
986
+ .option("--schemas-only", "Clean only schema docs.")
887
987
  .action(async (id, instance) => {
888
988
  const options = instance.opts();
889
989
  const pluginId = options.pluginId;
990
+ const schemasOnly = options.schemasOnly;
890
991
  const pluginInstances = getPluginInstances(plugins);
891
992
  let targetConfig: any;
892
993
  if (pluginId) {
@@ -922,14 +1023,16 @@ custom_edit_url: null
922
1023
  "Can't use id 'all' for OpenAPI docs versions configuration key."
923
1024
  );
924
1025
  } else {
925
- await cleanVersions(parentConfig.outputDir);
1026
+ if (!schemasOnly) {
1027
+ await cleanVersions(parentConfig.outputDir);
1028
+ }
926
1029
  Object.keys(versions).forEach(async (key) => {
927
1030
  const versionConfig = versions[key];
928
1031
  const mergedConfig = {
929
1032
  ...parentConfig,
930
1033
  ...versionConfig,
931
1034
  };
932
- await cleanApiDocs(mergedConfig);
1035
+ await cleanApiDocs(mergedConfig, schemasOnly);
933
1036
  });
934
1037
  }
935
1038
  } else {
@@ -938,7 +1041,7 @@ custom_edit_url: null
938
1041
  ...parentConfig,
939
1042
  ...versionConfig,
940
1043
  };
941
- await cleanApiDocs(mergedConfig);
1044
+ await cleanApiDocs(mergedConfig, schemasOnly);
942
1045
  }
943
1046
  });
944
1047
  },
@@ -5,14 +5,14 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import { clean, create } from "./utils";
8
+ import { create } from "./utils";
9
9
 
10
10
  export function createHeading(heading: string) {
11
11
  return [
12
12
  create(
13
13
  "Heading",
14
14
  {
15
- children: clean(heading),
15
+ children: heading,
16
16
  as: "h1",
17
17
  className: "openapi__heading",
18
18
  },
@@ -9,16 +9,14 @@ import { create } from "./utils";
9
9
 
10
10
  export function createRequestHeader(header: string) {
11
11
  return [
12
- create(
13
- "Heading",
14
- {
15
- children: header,
16
- id: header.replace(" ", "-").toLowerCase(),
17
- as: "h2",
18
- className: "openapi-tabs__heading",
19
- },
20
- { inline: true }
21
- ),
22
- `\n\n`,
12
+ create("Heading", {
13
+ id: header.replace(" ", "-").toLowerCase(),
14
+ as: "h2",
15
+ className: "openapi-tabs__heading",
16
+ children: [
17
+ `<Translate id="theme.openapi.request.title">${header}</Translate>`,
18
+ ],
19
+ }),
20
+ "\n\n",
23
21
  ];
24
22
  }
@@ -375,7 +375,8 @@ function createDetailsNode(
375
375
  () => [
376
376
  create("span", {
377
377
  className: "openapi-schema__required",
378
- children: "required",
378
+ children:
379
+ "<Translate id='theme.openapi.schemaItem.required'>required</Translate>",
379
380
  }),
380
381
  ]
381
382
  ),
@@ -530,7 +531,8 @@ function createPropertyDiscriminator(
530
531
  guard(required, () => [
531
532
  create("span", {
532
533
  className: "openapi-schema__required",
533
- children: "required",
534
+ children:
535
+ "<Translate id='theme.openapi.schemaItem.required'>required</Translate>",
534
536
  }),
535
537
  ]),
536
538
  ],
@@ -72,7 +72,8 @@ export function createApiPageMD({
72
72
  `import StatusCodes from "@theme/StatusCodes";\n`,
73
73
  `import OperationTabs from "@theme/OperationTabs";\n`,
74
74
  `import TabItem from "@theme/TabItem";\n`,
75
- `import Heading from "@theme/Heading";\n\n`,
75
+ `import Heading from "@theme/Heading";\n`,
76
+ `import Translate from "@docusaurus/Translate";\n\n`,
76
77
  createHeading(title),
77
78
  createMethodEndpoint(method, path),
78
79
  infoPath && createAuthorization(infoPath),
@@ -134,7 +135,7 @@ export function createSchemaPageMD({ schema }: SchemaPageMetadata) {
134
135
  return render([
135
136
  `import Schema from "@theme/Schema";\n`,
136
137
  `import Heading from "@theme/Heading";\n\n`,
137
- createHeading(title.replace(lessThan, "&lt;").replace(greaterThan, "&gt;")),
138
+ createHeading(title),
138
139
  createDescription(description),
139
140
  create("Schema", {
140
141
  schema: schema,
@@ -8,6 +8,12 @@
8
8
  import { SchemaObject } from "../openapi/types";
9
9
 
10
10
  function prettyName(schema: SchemaObject, circular?: boolean) {
11
+ // Handle enum-only schemas (valid in JSON Schema)
12
+ // When enum is present without explicit type, treat as string
13
+ if (schema.enum && !schema.type) {
14
+ return "string";
15
+ }
16
+
11
17
  if (schema.format) {
12
18
  if (schema.type) {
13
19
  return `${schema.type}<${schema.format}>`;