next-openapi-gen 0.0.12 → 0.0.14

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
@@ -2,17 +2,26 @@
2
2
 
3
3
  **next-openapi-gen** super fast and easy way to generate OpenAPI 3.0 documentation automatically from API routes in a Next.js 14.
4
4
 
5
+ With support for multiple user interfaces next-openapi-gen makes documenting your API a breeze!
6
+
5
7
  ## Prerequisites
6
8
 
7
9
  - Nextjs >= 14
8
10
  - Node >= 18
9
11
 
12
+ ## Supported interfaces
13
+
14
+ - Swagger
15
+ - Redoc
16
+ - Stoplight Elements
17
+ - RapiDoc
18
+
10
19
  ## Features
11
20
 
12
21
  - **Automatic OpenAPI Generation**: Generate OpenAPI 3.0 documentation from your Next.js routes, automatically parsing TypeScript types for parameters, request bodies and responses.
13
22
  - **TypeScript Type Scanning**: Automatically resolve TypeScript types for params, body, and responses based on your API endpoint's TypeScript definitions. Field comments in TypeScript types are reflected as descriptions in the OpenAPI schema.
14
- - **JSDoc-Based Documentation**: Document API routes with JSDoc comments, including tags like `@openapi`, `@auth`, `@desc`, `@params`, `@body`, and `@response` to easily define route metadata.
15
- - **UI Interface Options**: Choose between Swagger UI, Elements, or Redoc to visualize your API documentation. Customize the interface to fit your preferences.
23
+ - **JSDoc-Based Documentation (Optional)**: Document API routes with JSDoc comments, including tags like `@openapi`, `@auth`, `@desc`, `@params`, `@body`, and `@response` to easily define route metadata.
24
+ - **UI Interface Options**: Choose between `Swagger UI`, `Redoc`, `Stoplight Elements` or `RapiDoc` to visualize your API documentation. Customize the interface to fit your preferences.
16
25
  - **Real-time Documentation**: As your API evolves, regenerate the OpenAPI documentation with a single command, ensuring your documentation is always up to date.
17
26
  - **Easy configuration**: Customize generator behavior using the `next.openapi.json` configuration file, allowing for quick adjustments without modifying the code.
18
27
 
@@ -29,9 +38,13 @@ yarn add next-openapi-gen
29
38
  Run the following command to generate the `next.openapi.json` configuration file and automatically set up Swagger UI with `/api-docs` routes:
30
39
 
31
40
  ```bash
32
- npx next-openapi-gen init
41
+ npx next-openapi-gen init --ui swagger --docs-url api-docs
33
42
  ```
34
43
 
44
+ Parameters:
45
+ - **ui**: `swagger` | `redoc` | `stoplight` | `rapidoc`
46
+ - **docs-url**: url on which api docs will be visible
47
+
35
48
  This command does the following:
36
49
 
37
50
  - Generates a `next.openapi.json` file, which stores the OpenAPI configuration for your project.
@@ -5,6 +5,10 @@ import ora from "ora";
5
5
  import { exec } from "child_process";
6
6
  import util from "util";
7
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";
8
12
  const execPromise = util.promisify(exec);
9
13
  const spinner = ora("Initializing project with OpenAPI template...\n");
10
14
  const getPackageManager = async () => {
@@ -28,43 +32,55 @@ const getPackageManager = async () => {
28
32
  // Default to npm if no lock files are found
29
33
  return "npm";
30
34
  };
31
- async function createDocsPage() {
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) {
32
65
  const paths = ["app", "api-docs"];
33
66
  const srcPath = path.join(process.cwd(), "src");
34
- const { outputFile } = openapiTemplate;
35
67
  if (fs.existsSync(srcPath)) {
36
68
  paths.unshift("src");
37
69
  }
38
70
  const docsDir = path.join(process.cwd(), ...paths);
39
71
  await fs.promises.mkdir(docsDir, { recursive: true });
40
- const swaggerComponent = `
41
- import "swagger-ui-react/swagger-ui.css";
42
-
43
- import dynamic from "next/dynamic";
44
-
45
- const SwaggerUI = dynamic(() => import("swagger-ui-react"), {
46
- ssr: false,
47
- loading: () => <p>Loading Component...</p>,
48
- });
49
-
50
- export default async function ApiDocsPage() {
51
- return (
52
- <section>
53
- <SwaggerUI url="/${outputFile}" />
54
- </section>
55
- );
56
- }
57
- `;
72
+ const docsPage = getDocsPage(ui, outputFile);
58
73
  const componentPath = path.join(docsDir, "page.tsx");
59
- await fs.promises.writeFile(componentPath, swaggerComponent.trim());
60
- spinner.succeed(`Created ${paths.join("/")}/page.tsx for Swagger UI.`);
74
+ await fs.promises.writeFile(componentPath, docsPage.trim());
75
+ spinner.succeed(`Created ${paths.join("/")}/page.tsx for ${ui}.`);
61
76
  }
62
- async function installSwagger() {
77
+ async function installDependencies(ui) {
63
78
  const packageManager = await getPackageManager();
64
79
  const installCmd = `${packageManager} ${packageManager === "npm" ? "install" : "add"}`;
65
- spinner.succeed("Installing swagger-ui-react...");
66
- const resp = await execPromise(`${installCmd} swagger-ui-react`);
67
- spinner.succeed("Successfully installed swagger-ui-react.");
80
+ const deps = getDocsPageDependencies(ui);
81
+ spinner.succeed(`Installing ${deps} dependencies...`);
82
+ const resp = await execPromise(`${installCmd} ${deps}`);
83
+ spinner.succeed(`Successfully installed ${deps}.`);
68
84
  }
69
85
  function extendOpenApiTemplate(spec, options) {
70
86
  spec.ui = options.ui ?? spec.ui;
@@ -79,10 +95,8 @@ export async function init(options) {
79
95
  extendOpenApiTemplate(template, { docsUrl, ui });
80
96
  await fse.writeJson(outputPath, template, { spaces: 2 });
81
97
  spinner.succeed(`Created OpenAPI template in next.openapi.json`);
82
- if (ui === "swagger") {
83
- createDocsPage();
84
- installSwagger();
85
- }
98
+ createDocsPage(ui, template.outputFile);
99
+ installDependencies(ui);
86
100
  }
87
101
  catch (error) {
88
102
  spinner.fail(`Failed to initialize project: ${error.message}`);
@@ -0,0 +1,20 @@
1
+ export const rapidocDeps = ["rapidoc"];
2
+ export function RapidocUI(outputFile) {
3
+ return `
4
+ "use client";
5
+
6
+ import "rapidoc";
7
+
8
+ export default function ApiDocsPage() {
9
+ return (
10
+ <section style={{ height: "100vh" }}>
11
+ <rapi-doc
12
+ spec-url="${outputFile}"
13
+ render-style="read"
14
+ style={{ height: "100vh", width: "100%" }}
15
+ ></rapi-doc>
16
+ </section>
17
+ );
18
+ }
19
+ `;
20
+ }
@@ -0,0 +1,16 @@
1
+ export const redocDeps = ["redoc"];
2
+ export function RedocUI(outputFile) {
3
+ return `
4
+ "use client";
5
+
6
+ import { RedocStandalone } from "redoc";
7
+
8
+ export default async function ApiDocsPage() {
9
+ return (
10
+ <section>
11
+ <RedocStandalone specUrl="/${outputFile}" />
12
+ </section>
13
+ );
14
+ }
15
+ `;
16
+ }
@@ -0,0 +1,17 @@
1
+ export const stoplightDeps = ["@stoplight/element"];
2
+ export function StoplightUI(outputFile) {
3
+ return `
4
+ "use client";
5
+
6
+ import { API } from "@stoplight/elements";
7
+ import "@stoplight/elements/styles.min.css";
8
+
9
+ export default function ApiDocsPage() {
10
+ return (
11
+ <section style={{ height: "100vh" }}>
12
+ <API apiDescriptionUrl="${outputFile}" />
13
+ </section>
14
+ );
15
+ }
16
+ `;
17
+ }
@@ -0,0 +1,21 @@
1
+ export const swaggerDeps = ["swagger-ui"];
2
+ export function SwaggerUI(outputFile) {
3
+ return `
4
+ import "swagger-ui-react/swagger-ui.css";
5
+
6
+ import dynamic from "next/dynamic";
7
+
8
+ const SwaggerUI = dynamic(() => import("swagger-ui-react"), {
9
+ ssr: false,
10
+ loading: () => <p>Loading Component...</p>,
11
+ });
12
+
13
+ export default async function ApiDocsPage() {
14
+ return (
15
+ <section>
16
+ <SwaggerUI url="/${outputFile}" />
17
+ </section>
18
+ );
19
+ }
20
+ `;
21
+ }
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ program
10
10
  program
11
11
  .command("init")
12
12
  .addOption(new Option("-i, --ui <type>", "Specify the UI type, e.g., swagger")
13
- .choices(["swagger", "element", "redoc"])
13
+ .choices(["swagger", "redoc", "stoplight", "rapidoc"])
14
14
  .default("swagger"))
15
15
  .option("-u, --docs-url <url>", "Specify the docs URL", "api-docs")
16
16
  .description("Initialize a openapi specification")
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "next-openapi-gen",
3
- "version": "0.0.12",
4
- "description": "Super fast and easy way to generate OpenAPI documentation automatically from API routes in a NextJS 14.",
3
+ "version": "0.0.14",
4
+ "description": "Super fast and easy way to generate OpenAPI documentation automatically from API routes in a NextJS 14",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",