Skip to content

Commit 013a591

Browse files
committed
feat: add CLI option for schema-only generation
1 parent b0d2b7d commit 013a591

File tree

7 files changed

+121
-13
lines changed

7 files changed

+121
-13
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,16 @@ yarn docusaurus gen-api-docs all --all-versions
282282

283283
> This will generate API docs for all versions of all the OpenAPI specification (OAS) files referenced in your `docusaurus-plugin-openapi-docs` config.
284284
285+
To generate only schema MDX files—without updating the sidebar or requiring `showSchemas` in your plugin config—use the `--schemas-only` flag:
286+
287+
```bash
288+
yarn docusaurus gen-api-docs petstore --schemas-only
289+
```
290+
291+
> This command writes the schema pages to the configured output directory while leaving other generated docs untouched.
292+
293+
The `--schemas-only` flag is also available for `gen-api-docs:version`.
294+
285295
### Cleaning API Docs
286296

287297
To clean/remove all API Docs, run the following command from the root directory of your project:

demo/docs/intro.mdx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,14 @@ Example:
338338
yarn docusaurus gen-api-docs petstore
339339
```
340340

341+
To generate only schema MDX files—without updating the sidebar or requiring `showSchemas` in your plugin config—use the `--schemas-only` flag:
342+
343+
```bash title="generating only schema docs for 'petstore'"
344+
yarn docusaurus gen-api-docs petstore --schemas-only
345+
```
346+
347+
> This command writes the schema pages to the configured output directory while leaving other generated docs untouched.
348+
341349
### Cleaning API Docs
342350

343351
To clean/remove all API Docs, run the following command from the root directory of your project:

packages/docusaurus-plugin-openapi-docs/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,16 @@ yarn docusaurus gen-api-docs all --all-versions
303303

304304
> This will generate API docs for all versions of all the OpenAPI specification (OAS) files referenced in your `docusaurus-plugin-openapi-docs` config.
305305
306+
To generate only schema MDX files—without updating the sidebar or requiring `showSchemas` in your plugin config—use the `--schemas-only` flag:
307+
308+
```bash
309+
yarn docusaurus gen-api-docs petstore --schemas-only
310+
```
311+
312+
> This command writes the schema pages to the configured output directory while leaving other generated docs untouched.
313+
314+
The `--schemas-only` flag is also available for `gen-api-docs:version`.
315+
306316
### Cleaning API Docs
307317

308318
To clean/remove all API Docs, run the following command from the root directory of your project:

packages/docusaurus-plugin-openapi-docs/src/index.ts

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,12 @@ export default function pluginOpenAPIDocs(
123123
markdownGenerators,
124124
downloadUrl,
125125
sidebarOptions,
126+
schemasOnly,
126127
disableCompression,
127128
} = options;
128129

130+
const isSchemasOnly = schemasOnly === true;
131+
129132
// Remove trailing slash before proceeding
130133
outputDir = outputDir.replace(/\/$/, "");
131134

@@ -160,7 +163,7 @@ export default function pluginOpenAPIDocs(
160163
}
161164

162165
// TODO: figure out better way to set default
163-
if (Object.keys(sidebarOptions ?? {}).length > 0) {
166+
if (!isSchemasOnly && Object.keys(sidebarOptions ?? {}).length > 0) {
164167
const sidebarSlice = generateSidebarSlice(
165168
sidebarOptions!,
166169
options,
@@ -332,6 +335,9 @@ custom_edit_url: null
332335
}
333336
const markdown = pageGeneratorByType[item.type](item as any);
334337
item.markdown = markdown;
338+
if (isSchemasOnly && item.type !== "schema") {
339+
return;
340+
}
335341
if (item.type === "api") {
336342
// opportunity to compress JSON
337343
// const serialize = (o: any) => {
@@ -668,10 +674,12 @@ custom_edit_url: null
668674
.arguments("<id>")
669675
.option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
670676
.option("--all-versions", "Generate all versions.")
677+
.option("--schemas-only", "Generate only schema docs.")
671678
.action(async (id, instance) => {
672679
const options = instance.opts();
673680
const pluginId = options.pluginId;
674681
const allVersions = options.allVersions;
682+
const schemasOnly = options.schemasOnly;
675683
const pluginInstances = getPluginInstances(plugins);
676684
let targetConfig: any;
677685
let targetDocsPluginId: any;
@@ -698,6 +706,9 @@ custom_edit_url: null
698706
targetConfig = config;
699707
}
700708

709+
const withSchemaOverride = (apiOptions: APIOptions): APIOptions =>
710+
schemasOnly ? { ...apiOptions, schemasOnly: true } : apiOptions;
711+
701712
if (id === "all") {
702713
if (targetConfig[id]) {
703714
console.error(
@@ -707,12 +718,10 @@ custom_edit_url: null
707718
);
708719
} else {
709720
Object.keys(targetConfig).forEach(async function (key) {
710-
await generateApiDocs(targetConfig[key], targetDocsPluginId);
721+
const apiOptions = withSchemaOverride(targetConfig[key]);
722+
await generateApiDocs(apiOptions, targetDocsPluginId);
711723
if (allVersions) {
712-
await generateAllVersions(
713-
targetConfig[key],
714-
targetDocsPluginId
715-
);
724+
await generateAllVersions(apiOptions, targetDocsPluginId);
716725
}
717726
});
718727
}
@@ -721,9 +730,10 @@ custom_edit_url: null
721730
chalk.red(`ID '${id}' does not exist in OpenAPI docs config.`)
722731
);
723732
} else {
724-
await generateApiDocs(targetConfig[id], targetDocsPluginId);
733+
const apiOptions = withSchemaOverride(targetConfig[id]);
734+
await generateApiDocs(apiOptions, targetDocsPluginId);
725735
if (allVersions) {
726-
await generateAllVersions(targetConfig[id], targetDocsPluginId);
736+
await generateAllVersions(apiOptions, targetDocsPluginId);
727737
}
728738
}
729739
});
@@ -736,9 +746,11 @@ custom_edit_url: null
736746
.usage("<id:version>")
737747
.arguments("<id:version>")
738748
.option("-p, --plugin-id <plugin>", "OpenAPI docs plugin ID.")
749+
.option("--schemas-only", "Generate only schema docs.")
739750
.action(async (id, instance) => {
740751
const options = instance.opts();
741752
const pluginId = options.pluginId;
753+
const schemasOnly = options.schemasOnly;
742754
const pluginInstances = getPluginInstances(plugins);
743755
let targetConfig: any;
744756
let targetDocsPluginId: any;
@@ -767,6 +779,9 @@ custom_edit_url: null
767779
const [parentId, versionId] = id.split(":");
768780
const parentConfig = Object.assign({}, targetConfig[parentId]);
769781

782+
const withSchemaOverride = (apiOptions: APIOptions): APIOptions =>
783+
schemasOnly ? { ...apiOptions, schemasOnly: true } : apiOptions;
784+
770785
const version = parentConfig.version as string;
771786
const label = parentConfig.label as string;
772787
const baseUrl = parentConfig.baseUrl as string;
@@ -796,10 +811,10 @@ custom_edit_url: null
796811
await generateVersions(mergedVersions, parentConfig.outputDir);
797812
Object.keys(versions).forEach(async (key) => {
798813
const versionConfig = versions[key];
799-
const mergedConfig = {
814+
const mergedConfig = withSchemaOverride({
800815
...parentConfig,
801816
...versionConfig,
802-
};
817+
});
803818
await generateApiDocs(mergedConfig, targetDocsPluginId);
804819
});
805820
}
@@ -811,10 +826,10 @@ custom_edit_url: null
811826
);
812827
} else {
813828
const versionConfig = versions[versionId];
814-
const mergedConfig = {
829+
const mergedConfig = withSchemaOverride({
815830
...parentConfig,
816831
...versionConfig,
817-
};
832+
});
818833
await generateVersions(mergedVersions, parentConfig.outputDir);
819834
await generateApiDocs(mergedConfig, targetDocsPluginId);
820835
}

packages/docusaurus-plugin-openapi-docs/src/openapi/openapi.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import path from "path";
1111
import { posixPath } from "@docusaurus/utils";
1212

1313
import { readOpenapiFiles } from ".";
14+
import { processOpenapiFile } from "./openapi";
15+
import type { APIOptions, SidebarOptions } from "../types";
1416

1517
// npx jest packages/docusaurus-plugin-openapi/src/openapi/openapi.test.ts --watch
1618

@@ -37,4 +39,60 @@ describe("openapi", () => {
3739
).toBeDefined();
3840
});
3941
});
42+
43+
describe("schemasOnly", () => {
44+
it("includes schema metadata when showSchemas is disabled", async () => {
45+
const openapiData = {
46+
openapi: "3.0.0",
47+
info: {
48+
title: "Schema Only",
49+
version: "1.0.0",
50+
},
51+
paths: {
52+
"/ping": {
53+
get: {
54+
summary: "Ping",
55+
responses: {
56+
"200": {
57+
description: "OK",
58+
},
59+
},
60+
},
61+
},
62+
},
63+
components: {
64+
schemas: {
65+
WithoutTags: {
66+
title: "Without Tags",
67+
type: "object",
68+
properties: {
69+
value: {
70+
type: "string",
71+
},
72+
},
73+
},
74+
},
75+
},
76+
};
77+
78+
const options: APIOptions = {
79+
specPath: "dummy", // required by the type but unused in this context
80+
outputDir: "build",
81+
showSchemas: false,
82+
schemasOnly: true,
83+
};
84+
85+
const sidebarOptions = {} as SidebarOptions;
86+
87+
const [items] = await processOpenapiFile(
88+
openapiData as any,
89+
options,
90+
sidebarOptions
91+
);
92+
93+
const schemaItems = items.filter((item) => item.type === "schema");
94+
expect(schemaItems).toHaveLength(1);
95+
expect(schemaItems[0].id).toBe("without-tags");
96+
});
97+
});
4098
});

packages/docusaurus-plugin-openapi-docs/src/openapi/openapi.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ function createItems(
9595
let items: PartialPage<ApiMetadata>[] = [];
9696
const infoIdSpaces = openapiData.info.title.replace(" ", "-").toLowerCase();
9797
const infoId = kebabCase(infoIdSpaces);
98+
const schemasOnly = options?.schemasOnly === true;
9899

99100
if (openapiData.info.description || openapiData.info.title) {
100101
// Only create an info page if we have a description.
@@ -434,6 +435,7 @@ function createItems(
434435
}
435436

436437
if (
438+
schemasOnly ||
437439
options?.showSchemas === true ||
438440
Object.entries(openapiData?.components?.schemas ?? {})
439441
.flatMap(([_, s]) => s["x-tags"])
@@ -443,7 +445,11 @@ function createItems(
443445
for (let [schema, schemaObject] of Object.entries(
444446
openapiData?.components?.schemas ?? {}
445447
)) {
446-
if (options?.showSchemas === true || schemaObject["x-tags"]) {
448+
if (
449+
schemasOnly ||
450+
options?.showSchemas === true ||
451+
schemaObject["x-tags"]
452+
) {
447453
const baseIdSpaces =
448454
schemaObject?.title?.replace(" ", "-").toLowerCase() ?? "";
449455
const baseId = kebabCase(baseIdSpaces);

packages/docusaurus-plugin-openapi-docs/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export interface APIOptions {
5151
proxy?: string;
5252
markdownGenerators?: MarkdownGenerator;
5353
showSchemas?: boolean;
54+
schemasOnly?: boolean;
5455
disableCompression?: boolean;
5556
maskCredentials?: boolean;
5657
}

0 commit comments

Comments
 (0)