next-openapi-gen 0.1.2 → 0.2.1

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/README.md CHANGED
@@ -9,6 +9,7 @@
9
9
 
10
10
  ## Interfaces
11
11
 
12
+ - Scalar
12
13
  - Swagger
13
14
  - Redoc
14
15
  - Stoplight Elements
@@ -19,7 +20,7 @@
19
20
  - **Automatic OpenAPI Generation**: Generate OpenAPI 3.0 documentation from your Next.js routes, automatically parsing TypeScript types for parameters, request bodies and responses. Field comments in TypeScript types are reflected as descriptions in the OpenAPI schema.
20
21
  - **Complex TypeScript Types**: Use complex TypeScript types, such as `nested objects`, `arrays`, `enums` and `unions` (mapped to anyOf). This enables a more comprehensive representation of data structures directly in the OpenAPI schema.
21
22
  - **JSDoc-Based Documentation**: Document API routes with optional JSDoc comments, including tags like `@openapi`, `@auth`, `@desc`, `@params`, `@body`, and `@response` to easily define route metadata.
22
- - **Multiple UI Interfaces**: Choose between `Swagger UI`, `Redoc`, `Stoplight Elements` or `RapiDoc` to visualize your API documentation. Customize the interface to fit your preferences.
23
+ - **Multiple UI Interfaces**: Choose between `Scalar`, `Swagger UI`, `Redoc`, `Stoplight Elements` or `RapiDoc` to visualize your API documentation. Customize the interface to fit your preferences.
23
24
  - **Real-time Documentation**: As your API evolves, regenerate the OpenAPI documentation with a single command, ensuring your documentation is always up to date.
24
25
  - **Easy configuration**: Customize generator behavior using the `next.openapi.json` configuration file, allowing for quick adjustments without modifying the code.
25
26
 
@@ -33,20 +34,20 @@ yarn add next-openapi-gen
33
34
 
34
35
  ### Step 1: Initialize Configuration and Setup
35
36
 
36
- Run the following command to generate the `next.openapi.json` configuration file and automatically set up Swagger UI with `/api-docs` routes:
37
+ Run the following command to generate the `next.openapi.json` configuration file and automatically set up Scalar UI with `/api-docs` routes:
37
38
 
38
39
  ```bash
39
- npx next-openapi-gen init --ui swagger --docs-url api-docs
40
+ npx next-openapi-gen init --ui scalar --docs-url api-docs
40
41
  ```
41
42
 
42
43
  Parameters:
43
- - **ui**: `swagger` | `redoc` | `stoplight` | `rapidoc`
44
+ - **ui**: `scalar` | `swagger` | `redoc` | `stoplight` | `rapidoc`
44
45
  - **docs-url**: url on which api docs will be visible
45
46
 
46
47
  This command does the following:
47
48
 
48
49
  - Generates a `next.openapi.json` file, which stores the OpenAPI configuration for your project.
49
- - Installs Swagger UI to provide an API documentation interface.
50
+ - Installs Scalar UI to provide an API documentation interface.
50
51
  - Adds an `/api-docs` route in the Next.js app for visualizing the generated OpenAPI documentation.
51
52
 
52
53
  ### Step 2: Add JSDoc Comments to Your API Routes
@@ -57,7 +58,7 @@ Annotate your API routes using JSDoc comments. Here's an example:
57
58
  <table>
58
59
  <tr>
59
60
  <th>Login route</th>
60
- <th>Swagger</th>
61
+ <th>Scalar / Swagger</th>
61
62
  </tr>
62
63
  <tr>
63
64
  <td>
@@ -87,13 +88,14 @@ Annotate your API routes using JSDoc comments. Here's an example:
87
88
  ```
88
89
  </td>
89
90
  <td>
90
- <img width="340" alt="api-login" src="https://raw.githubusercontent.com/tazo90/next-openapi-gen/refs/heads/main/assets/api-login.png" alt-text="api-login"/>
91
+ <img width="340" alt="api-login-scalar" src="https://raw.githubusercontent.com/tazo90/next-openapi-gen/refs/heads/main/assets/api-login-scalar.png" alt-text="api-login"/>
92
+ <img width="340" alt="api-login-swagger" src="https://raw.githubusercontent.com/tazo90/next-openapi-gen/refs/heads/main/assets/api-login-swagger.png" alt-text="api-login-swagger"/>
91
93
  </td>
92
94
  </tr>
93
95
 
94
96
  <tr>
95
97
  <th>Users route</th>
96
- <th>Swagger</th>
98
+ <th>Scalar / Swagger</th>
97
99
  </tr>
98
100
  <tr>
99
101
  <td>
@@ -145,7 +147,8 @@ Annotate your API routes using JSDoc comments. Here's an example:
145
147
  ```
146
148
  </td>
147
149
  <td>
148
- <img width="340" alt="api-users" src="https://raw.githubusercontent.com/tazo90/next-openapi-gen/refs/heads/main/assets/api-users.png" alt-text="api-users"/>
150
+ <img width="340" alt="api-users-scalar" src="https://raw.githubusercontent.com/tazo90/next-openapi-gen/refs/heads/main/assets/api-users-scalar.png" alt-text="api-users-scalar"/>
151
+ <img width="340" alt="api-users-swagger" src="https://raw.githubusercontent.com/tazo90/next-openapi-gen/refs/heads/main/assets/api-users-swagger.png" alt-text="api-users-swagger"/>
149
152
  </td>
150
153
  </tr>
151
154
  </table>
@@ -159,11 +162,11 @@ Run the following command to generate the OpenAPI schema based on your API route
159
162
  npx next-openapi-gen generate
160
163
  ```
161
164
 
162
- This command processes all your API routes, extracts the necessary information from JSDoc comments, and generates the OpenAPI schema, typically saved to a `swagger.json` file in the `public` folder.
165
+ This command processes all your API routes, extracts the necessary information from JSDoc comments, and generates the OpenAPI schema, typically saved to a `openapi.json` file in the `public` folder.
163
166
 
164
167
  ### Step 4: View API Documentation
165
168
 
166
- With the `/api-docs` route generated from the init command, you can now access your API documentation through Swagger UI by navigating to `http://localhost:3000/api-docs`.
169
+ With the `/api-docs` route generated from the init command, you can now access your API documentation through Scalar UI by navigating to `http://localhost:3000/api-docs`.
167
170
 
168
171
  ## JSDoc tags
169
172
 
@@ -181,8 +184,8 @@ The `next.openapi.json` file allows you to configure the behavior of the OpenAPI
181
184
  - **apiDir**: (default: `./src/app/api`) The directory where your API routes are stored.
182
185
  - **schemaDir**: (default: `./src`) The directory where your schema definitions are stored.
183
186
  - **docsUrl**: (default: `./api-docs`) Route where OpenAPI UI is available.
184
- - **ui**: (default: `swagger`) OpenAPI UI interface.
185
- - **outputFile**: (default: `./swagger.json`) The file where the generated OpenAPI specification will be saved in `public` folder.
187
+ - **ui**: (default: `scalar`) OpenAPI UI interface.
188
+ - **outputFile**: (default: `./openapi.json`) The file where the generated OpenAPI specification will be saved in `public` folder.
186
189
  - **includeOpenApiRoutes**: (default: `false`) When `true`, the generator will only include routes that have the `@openapi` tag in their JSDoc comments.
187
190
 
188
191
  ## Interface providers
@@ -190,7 +193,8 @@ The `next.openapi.json` file allows you to configure the behavior of the OpenAPI
190
193
  <div align="center">
191
194
  <table>
192
195
  <thead>
193
- <th>SwaggerUI</th>
196
+ <th>Scalar</th>
197
+ <th>Swagger</th>
194
198
  <th>Redoc</th>
195
199
  <th>Stoplight Elements</th>
196
200
  <th>RapiDoc</th>
@@ -1,21 +1,21 @@
1
- import fs from "fs";
2
- import fse from "fs-extra";
3
- import path from "path";
4
- import ora from "ora";
5
- import { OpenApiGenerator } from "../lib/openapi-generator.js";
6
- export async function generate() {
7
- const spinner = ora("Generating OpenAPI specification...\n").start();
8
- const generator = new OpenApiGenerator();
9
- const config = generator.getConfig();
10
- // Create api dir if not exists
11
- const apiDir = path.resolve(config.apiDir);
12
- await fse.ensureDir(apiDir);
13
- // Create public dir if not exists
14
- const outputDir = path.resolve("./public");
15
- await fse.ensureDir(outputDir);
16
- const apiDocs = generator.generate();
17
- // Write api docs
18
- const outputFile = path.join(outputDir, config.outputFile);
19
- fs.writeFileSync(outputFile, JSON.stringify(apiDocs, null, 2));
20
- spinner.succeed(`OpenAPI specification generated at ${outputFile}`);
21
- }
1
+ import fs from "fs";
2
+ import fse from "fs-extra";
3
+ import path from "path";
4
+ import ora from "ora";
5
+ import { OpenApiGenerator } from "../lib/openapi-generator.js";
6
+ export async function generate() {
7
+ const spinner = ora("Generating OpenAPI specification...\n").start();
8
+ const generator = new OpenApiGenerator();
9
+ const config = generator.getConfig();
10
+ // Create api dir if not exists
11
+ const apiDir = path.resolve(config.apiDir);
12
+ await fse.ensureDir(apiDir);
13
+ // Create public dir if not exists
14
+ const outputDir = path.resolve("./public");
15
+ await fse.ensureDir(outputDir);
16
+ const apiDocs = generator.generate();
17
+ // Write api docs
18
+ const outputFile = path.join(outputDir, config.outputFile);
19
+ fs.writeFileSync(outputFile, JSON.stringify(apiDocs, null, 2));
20
+ spinner.succeed(`OpenAPI specification generated at ${outputFile}`);
21
+ }
@@ -1,104 +1,111 @@
1
- import path from "path";
2
- import fse from "fs-extra";
3
- import fs from "fs";
4
- import ora from "ora";
5
- import { exec } from "child_process";
6
- import util from "util";
7
- import openapiTemplate from "../openapi-template.js";
8
- import { swaggerDeps, SwaggerUI } from "../components/swagger.js";
9
- import { redocDeps, RedocUI } from "../components/redoc.js";
10
- import { stoplightDeps, StoplightUI } from "../components/stoplight.js";
11
- import { rapidocDeps, RapidocUI } from "../components/rapidoc.js";
12
- const execPromise = util.promisify(exec);
13
- const spinner = ora("Initializing project with OpenAPI template...\n");
14
- const getPackageManager = async () => {
15
- let currentDir = process.cwd();
16
- while (true) {
17
- // Check for Yarn lock file
18
- if (fs.existsSync(path.join(currentDir, "yarn.lock"))) {
19
- return "yarn";
20
- }
21
- // Check for PNPM lock file
22
- if (fs.existsSync(path.join(currentDir, "pnpm-lock.yaml"))) {
23
- return "pnpm";
24
- }
25
- // If we're at the root directory, break the loop
26
- const parentDir = path.dirname(currentDir);
27
- if (parentDir === currentDir) {
28
- break; // We've reached the root
29
- }
30
- currentDir = parentDir; // Move up one directory
31
- }
32
- // Default to npm if no lock files are found
33
- return "npm";
34
- };
35
- function getDocsPage(ui, outputFile) {
36
- let DocsComponent = SwaggerUI;
37
- if (ui === "redoc") {
38
- DocsComponent = RedocUI;
39
- }
40
- else if (ui === "stoplight") {
41
- DocsComponent = StoplightUI;
42
- }
43
- else if (ui === "rapidoc") {
44
- DocsComponent = RapidocUI;
45
- }
46
- return DocsComponent(outputFile);
47
- }
48
- function getDocsPageDependencies(ui) {
49
- let deps = [];
50
- if (ui === "swagger") {
51
- deps = swaggerDeps;
52
- }
53
- else if (ui === "redoc") {
54
- deps = redocDeps;
55
- }
56
- else if (ui === "stoplight") {
57
- deps = stoplightDeps;
58
- }
59
- else if (ui === "rapidoc") {
60
- deps = rapidocDeps;
61
- }
62
- return deps.join(" ");
63
- }
64
- async function createDocsPage(ui, outputFile) {
65
- const paths = ["app", "api-docs"];
66
- const srcPath = path.join(process.cwd(), "src");
67
- if (fs.existsSync(srcPath)) {
68
- paths.unshift("src");
69
- }
70
- const docsDir = path.join(process.cwd(), ...paths);
71
- await fs.promises.mkdir(docsDir, { recursive: true });
72
- const docsPage = getDocsPage(ui, outputFile);
73
- const componentPath = path.join(docsDir, "page.tsx");
74
- await fs.promises.writeFile(componentPath, docsPage.trim());
75
- spinner.succeed(`Created ${paths.join("/")}/page.tsx for ${ui}.`);
76
- }
77
- async function installDependencies(ui) {
78
- const packageManager = await getPackageManager();
79
- const installCmd = `${packageManager} ${packageManager === "npm" ? "install" : "add"}`;
80
- const deps = getDocsPageDependencies(ui);
81
- spinner.succeed(`Installing ${deps} dependencies...`);
82
- const resp = await execPromise(`${installCmd} ${deps}`);
83
- spinner.succeed(`Successfully installed ${deps}.`);
84
- }
85
- function extendOpenApiTemplate(spec, options) {
86
- spec.ui = options.ui ?? spec.ui;
87
- spec.docsUrl = options.docsUrl ?? spec.docsUrl;
88
- }
89
- export async function init(options) {
90
- const { ui, docsUrl } = options;
91
- spinner.start();
92
- try {
93
- const outputPath = path.join(process.cwd(), "next.openapi.json");
94
- const template = { ...openapiTemplate };
95
- extendOpenApiTemplate(template, { docsUrl, ui });
96
- await fse.writeJson(outputPath, template, { spaces: 2 });
97
- spinner.succeed(`Created OpenAPI template in next.openapi.json`);
98
- createDocsPage(ui, template.outputFile);
99
- installDependencies(ui);
100
- }
101
- catch (error) {
102
- spinner.fail(`Failed to initialize project: ${error.message}`);
103
- }
104
- }
1
+ import path from "path";
2
+ import fse from "fs-extra";
3
+ import fs from "fs";
4
+ import ora from "ora";
5
+ import { exec } from "child_process";
6
+ import util from "util";
7
+ import openapiTemplate from "../openapi-template.js";
8
+ import { scalarDeps, ScalarUI } from "../components/scalar.js";
9
+ import { swaggerDeps, SwaggerUI } from "../components/swagger.js";
10
+ import { redocDeps, RedocUI } from "../components/redoc.js";
11
+ import { stoplightDeps, StoplightUI } from "../components/stoplight.js";
12
+ import { rapidocDeps, RapidocUI } from "../components/rapidoc.js";
13
+ const execPromise = util.promisify(exec);
14
+ const spinner = ora("Initializing project with OpenAPI template...\n");
15
+ const getPackageManager = async () => {
16
+ let currentDir = process.cwd();
17
+ while (true) {
18
+ // Check for Yarn lock file
19
+ if (fs.existsSync(path.join(currentDir, "yarn.lock"))) {
20
+ return "yarn";
21
+ }
22
+ // Check for PNPM lock file
23
+ if (fs.existsSync(path.join(currentDir, "pnpm-lock.yaml"))) {
24
+ return "pnpm";
25
+ }
26
+ // If we're at the root directory, break the loop
27
+ const parentDir = path.dirname(currentDir);
28
+ if (parentDir === currentDir) {
29
+ break; // We've reached the root
30
+ }
31
+ currentDir = parentDir; // Move up one directory
32
+ }
33
+ // Default to npm if no lock files are found
34
+ return "npm";
35
+ };
36
+ function getDocsPage(ui, outputFile) {
37
+ let DocsComponent = ScalarUI;
38
+ if (ui === "swagger") {
39
+ DocsComponent = SwaggerUI;
40
+ }
41
+ else if (ui === "redoc") {
42
+ DocsComponent = RedocUI;
43
+ }
44
+ else if (ui === "stoplight") {
45
+ DocsComponent = StoplightUI;
46
+ }
47
+ else if (ui === "rapidoc") {
48
+ DocsComponent = RapidocUI;
49
+ }
50
+ return DocsComponent(outputFile);
51
+ }
52
+ function getDocsPageDependencies(ui) {
53
+ let deps = [];
54
+ if (ui === "scalar") {
55
+ deps = scalarDeps;
56
+ }
57
+ else if (ui === "swagger") {
58
+ deps = swaggerDeps;
59
+ }
60
+ else if (ui === "redoc") {
61
+ deps = redocDeps;
62
+ }
63
+ else if (ui === "stoplight") {
64
+ deps = stoplightDeps;
65
+ }
66
+ else if (ui === "rapidoc") {
67
+ deps = rapidocDeps;
68
+ }
69
+ return deps.join(" ");
70
+ }
71
+ async function createDocsPage(ui, outputFile) {
72
+ const paths = ["app", "api-docs"];
73
+ const srcPath = path.join(process.cwd(), "src");
74
+ if (fs.existsSync(srcPath)) {
75
+ paths.unshift("src");
76
+ }
77
+ const docsDir = path.join(process.cwd(), ...paths);
78
+ await fs.promises.mkdir(docsDir, { recursive: true });
79
+ const docsPage = getDocsPage(ui, outputFile);
80
+ const componentPath = path.join(docsDir, "page.tsx");
81
+ await fs.promises.writeFile(componentPath, docsPage.trim());
82
+ spinner.succeed(`Created ${paths.join("/")}/page.tsx for ${ui}.`);
83
+ }
84
+ async function installDependencies(ui) {
85
+ const packageManager = await getPackageManager();
86
+ const installCmd = `${packageManager} ${packageManager === "npm" ? "install" : "add"}`;
87
+ const deps = getDocsPageDependencies(ui);
88
+ spinner.succeed(`Installing ${deps} dependencies...`);
89
+ const resp = await execPromise(`${installCmd} ${deps}`);
90
+ spinner.succeed(`Successfully installed ${deps}.`);
91
+ }
92
+ function extendOpenApiTemplate(spec, options) {
93
+ spec.ui = options.ui ?? spec.ui;
94
+ spec.docsUrl = options.docsUrl ?? spec.docsUrl;
95
+ }
96
+ export async function init(options) {
97
+ const { ui, docsUrl } = options;
98
+ spinner.start();
99
+ try {
100
+ const outputPath = path.join(process.cwd(), "next.openapi.json");
101
+ const template = { ...openapiTemplate };
102
+ extendOpenApiTemplate(template, { docsUrl, ui });
103
+ await fse.writeJson(outputPath, template, { spaces: 2 });
104
+ spinner.succeed(`Created OpenAPI template in next.openapi.json`);
105
+ createDocsPage(ui, template.outputFile);
106
+ installDependencies(ui);
107
+ }
108
+ catch (error) {
109
+ spinner.fail(`Failed to initialize project: ${error.message}`);
110
+ }
111
+ }
@@ -1,5 +1,5 @@
1
- export const rapidocDeps = ["rapidoc"];
2
- export function RapidocUI(outputFile) {
1
+ export const rapidocDeps = ["rapidoc"];
2
+ export function RapidocUI(outputFile) {
3
3
  return `
4
4
  "use client";
5
5
 
@@ -16,5 +16,5 @@ export default function ApiDocsPage() {
16
16
  </section>
17
17
  );
18
18
  }
19
- `;
20
- }
19
+ `;
20
+ }
@@ -1,5 +1,5 @@
1
- export const redocDeps = ["redoc"];
2
- export function RedocUI(outputFile) {
1
+ export const redocDeps = ["redoc"];
2
+ export function RedocUI(outputFile) {
3
3
  return `
4
4
  "use client";
5
5
 
@@ -12,5 +12,5 @@ export default async function ApiDocsPage() {
12
12
  </section>
13
13
  );
14
14
  }
15
- `;
16
- }
15
+ `;
16
+ }
@@ -0,0 +1,20 @@
1
+ export const scalarDeps = ["@scalar/api-reference-react", "ajv"];
2
+ export function ScalarUI(outputFile) {
3
+ return `
4
+ "use client";
5
+
6
+ import { ApiReferenceReact } from "@scalar/api-reference-react";
7
+
8
+ import "@scalar/api-reference-react/style.css";
9
+
10
+ export default function ApiDocsPage() {
11
+ return (
12
+ <ApiReferenceReact
13
+ configuration={{
14
+ url: "/${outputFile}",
15
+ }}
16
+ />
17
+ );
18
+ }
19
+ `;
20
+ }
@@ -1,5 +1,5 @@
1
- export const stoplightDeps = ["@stoplight/elements"];
2
- export function StoplightUI(outputFile) {
1
+ export const stoplightDeps = ["@stoplight/elements"];
2
+ export function StoplightUI(outputFile) {
3
3
  return `
4
4
  "use client";
5
5
 
@@ -13,5 +13,5 @@ export default function ApiDocsPage() {
13
13
  </section>
14
14
  );
15
15
  }
16
- `;
17
- }
16
+ `;
17
+ }
@@ -1,9 +1,9 @@
1
- export const swaggerDeps = [
2
- "swagger-ui",
3
- "swagger-ui-react",
4
- "--legacy-peer-deps", // @temp: swagger-ui-react does not support React 19 now.
5
- ];
6
- export function SwaggerUI(outputFile) {
1
+ export const swaggerDeps = [
2
+ "swagger-ui",
3
+ "swagger-ui-react",
4
+ "--legacy-peer-deps", // @temp: swagger-ui-react does not support React 19 now.
5
+ ];
6
+ export function SwaggerUI(outputFile) {
7
7
  return `
8
8
  import "swagger-ui-react/swagger-ui.css";
9
9
 
@@ -21,5 +21,5 @@ export default async function ApiDocsPage() {
21
21
  </section>
22
22
  );
23
23
  }
24
- `;
25
- }
24
+ `;
25
+ }
package/dist/index.js CHANGED
@@ -1,22 +1,22 @@
1
- #!/usr/bin/env node
2
- import { Command, Option } from "commander";
3
- import { init } from "./commands/init.js";
4
- import { generate } from "./commands/generate.js";
5
- const program = new Command();
6
- program
7
- .name("next-openapi-gen")
8
- .version("0.0.1")
9
- .description("Super fast and easy way to generate OpenAPI documentation for Next.js");
10
- program
11
- .command("init")
12
- .addOption(new Option("-i, --ui <type>", "Specify the UI type, e.g., swagger")
13
- .choices(["swagger", "redoc", "stoplight", "rapidoc"])
14
- .default("swagger"))
15
- .option("-u, --docs-url <url>", "Specify the docs URL", "api-docs")
16
- .description("Initialize a openapi specification")
17
- .action(init);
18
- program
19
- .command("generate")
20
- .description("Generate a specification based on api routes")
21
- .action(generate);
22
- program.parse(process.argv);
1
+ #!/usr/bin/env node
2
+ import { Command, Option } from "commander";
3
+ import { init } from "./commands/init.js";
4
+ import { generate } from "./commands/generate.js";
5
+ const program = new Command();
6
+ program
7
+ .name("next-openapi-gen")
8
+ .version("0.0.1")
9
+ .description("Super fast and easy way to generate OpenAPI documentation for Next.js");
10
+ program
11
+ .command("init")
12
+ .addOption(new Option("-i, --ui <type>", "Specify the UI type, e.g., scalar")
13
+ .choices(["scalar", "swagger", "redoc", "stoplight", "rapidoc"])
14
+ .default("swagger"))
15
+ .option("-u, --docs-url <url>", "Specify the docs URL", "api-docs")
16
+ .description("Initialize a openapi specification")
17
+ .action(init);
18
+ program
19
+ .command("generate")
20
+ .description("Generate a specification based on api routes")
21
+ .action(generate);
22
+ program.parse(process.argv);
@@ -1,34 +1,34 @@
1
- import path from "path";
2
- import fs from "fs";
3
- import { RouteProcessor } from "./route-processor.js";
4
- import { cleanSpec } from "./utils.js";
5
- export class OpenApiGenerator {
6
- config;
7
- template;
8
- routeProcessor;
9
- constructor() {
10
- const templatePath = path.resolve("./next.openapi.json");
11
- this.template = JSON.parse(fs.readFileSync(templatePath, "utf-8"));
12
- this.config = this.getConfig();
13
- this.routeProcessor = new RouteProcessor(this.config);
14
- }
15
- getConfig() {
16
- // @ts-ignore
17
- const { apiDir, schemaDir, docsUrl, ui, outputFile, includeOpenApiRoutes } = this.template;
18
- return {
19
- apiDir,
20
- schemaDir,
21
- docsUrl,
22
- ui,
23
- outputFile,
24
- includeOpenApiRoutes,
25
- };
26
- }
27
- generate() {
28
- const { apiDir } = this.config;
29
- this.routeProcessor.scanApiRoutes(apiDir);
30
- this.template.paths = this.routeProcessor.getSwaggerPaths();
31
- const openapiSpec = cleanSpec(this.template);
32
- return openapiSpec;
33
- }
34
- }
1
+ import path from "path";
2
+ import fs from "fs";
3
+ import { RouteProcessor } from "./route-processor.js";
4
+ import { cleanSpec } from "./utils.js";
5
+ export class OpenApiGenerator {
6
+ config;
7
+ template;
8
+ routeProcessor;
9
+ constructor() {
10
+ const templatePath = path.resolve("./next.openapi.json");
11
+ this.template = JSON.parse(fs.readFileSync(templatePath, "utf-8"));
12
+ this.config = this.getConfig();
13
+ this.routeProcessor = new RouteProcessor(this.config);
14
+ }
15
+ getConfig() {
16
+ // @ts-ignore
17
+ const { apiDir, schemaDir, docsUrl, ui, outputFile, includeOpenApiRoutes } = this.template;
18
+ return {
19
+ apiDir,
20
+ schemaDir,
21
+ docsUrl,
22
+ ui,
23
+ outputFile,
24
+ includeOpenApiRoutes,
25
+ };
26
+ }
27
+ generate() {
28
+ const { apiDir } = this.config;
29
+ this.routeProcessor.scanApiRoutes(apiDir);
30
+ this.template.paths = this.routeProcessor.getSwaggerPaths();
31
+ const openapiSpec = cleanSpec(this.template);
32
+ return openapiSpec;
33
+ }
34
+ }