next-openapi-gen 0.6.7 → 0.6.8
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 +85 -84
- package/dist/commands/init.js +3 -2
- package/dist/components/rapidoc.js +16 -16
- package/dist/components/redoc.js +12 -12
- package/dist/components/stoplight.js +13 -13
- package/dist/index.js +2 -1
- package/dist/openapi-template.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# next-openapi-gen
|
|
2
2
|
|
|
3
|
-
Automatically generate OpenAPI 3.0 documentation from Next.js projects, with support for
|
|
3
|
+
Automatically generate OpenAPI 3.0 documentation from Next.js projects, with support for Zod schemas and TypeScript types.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- ✅ Automatic OpenAPI documentation generation from Next.js code
|
|
8
8
|
- ✅ Support for Next.js App Router (including `/api/users/[id]/route.ts` routes)
|
|
9
|
-
- ✅ TypeScript types support
|
|
10
9
|
- ✅ Zod schemas support
|
|
10
|
+
- ✅ TypeScript types support
|
|
11
11
|
- ✅ JSDoc comments support
|
|
12
12
|
- ✅ Multiple UI interfaces: `Scalar`, `Swagger`, `Redoc`, `Stoplight` and `Rapidoc` available at `/api-docs` url
|
|
13
13
|
- ✅ Path parameters detection (`/users/{id}`)
|
|
@@ -32,7 +32,7 @@ npm install next-openapi-gen --save-dev
|
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
# Initialize OpenAPI configuration
|
|
35
|
-
npx next-openapi-gen init --ui scalar --docs-url api-docs
|
|
35
|
+
npx next-openapi-gen init --ui scalar --docs-url api-docs --schema zod
|
|
36
36
|
|
|
37
37
|
# Generate OpenAPI documentation
|
|
38
38
|
npx next-openapi-gen generate
|
|
@@ -58,7 +58,7 @@ During initialization (`npx next-openapi-gen init`), a configuration file `next.
|
|
|
58
58
|
],
|
|
59
59
|
"apiDir": "src/app/api",
|
|
60
60
|
"schemaDir": "src/types", // or "src/schemas" for Zod schemas
|
|
61
|
-
"schemaType": "
|
|
61
|
+
"schemaType": "zod", // or "typescript" for TypeScript types
|
|
62
62
|
"outputFile": "openapi.json",
|
|
63
63
|
"docsUrl": "/api-docs",
|
|
64
64
|
"includeOpenApiRoutes": false,
|
|
@@ -72,7 +72,7 @@ During initialization (`npx next-openapi-gen init`), a configuration file `next.
|
|
|
72
72
|
| ---------------------- | ------------------------------------------------ |
|
|
73
73
|
| `apiDir` | Path to the API directory |
|
|
74
74
|
| `schemaDir` | Path to the types/schemas directory |
|
|
75
|
-
| `schemaType` | Schema type: `"
|
|
75
|
+
| `schemaType` | Schema type: `"zod"` or `"typescript"` |
|
|
76
76
|
| `outputFile` | Path to the OpenAPI output file |
|
|
77
77
|
| `docsUrl` | API documentation URL (for Swagger UI) |
|
|
78
78
|
| `includeOpenApiRoutes` | Whether to include only routes with @openapi tag |
|
|
@@ -83,28 +83,29 @@ During initialization (`npx next-openapi-gen init`), a configuration file `next.
|
|
|
83
83
|
|
|
84
84
|
## Documenting Your API
|
|
85
85
|
|
|
86
|
-
### With
|
|
86
|
+
### With Zod Schemas
|
|
87
87
|
|
|
88
88
|
```typescript
|
|
89
|
-
// src/app/api/
|
|
89
|
+
// src/app/api/products/[id]/route.ts
|
|
90
90
|
|
|
91
91
|
import { NextRequest, NextResponse } from "next/server";
|
|
92
|
+
import { z } from "zod";
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
id: string
|
|
95
|
-
};
|
|
94
|
+
export const ProductParams = z.object({
|
|
95
|
+
id: z.string().describe("Product ID"),
|
|
96
|
+
});
|
|
96
97
|
|
|
97
|
-
|
|
98
|
-
id: string
|
|
99
|
-
name: string
|
|
100
|
-
|
|
101
|
-
};
|
|
98
|
+
export const ProductResponse = z.object({
|
|
99
|
+
id: z.string().describe("Product ID"),
|
|
100
|
+
name: z.string().describe("Product name"),
|
|
101
|
+
price: z.number().positive().describe("Product price"),
|
|
102
|
+
});
|
|
102
103
|
|
|
103
104
|
/**
|
|
104
|
-
* Get
|
|
105
|
-
* @description Fetches detailed
|
|
106
|
-
* @pathParams
|
|
107
|
-
* @response
|
|
105
|
+
* Get product information
|
|
106
|
+
* @description Fetches detailed product information by ID
|
|
107
|
+
* @pathParams ProductParams
|
|
108
|
+
* @response ProductResponse
|
|
108
109
|
* @openapi
|
|
109
110
|
*/
|
|
110
111
|
export async function GET(
|
|
@@ -115,29 +116,28 @@ export async function GET(
|
|
|
115
116
|
}
|
|
116
117
|
```
|
|
117
118
|
|
|
118
|
-
### With
|
|
119
|
+
### With TypeScript Types
|
|
119
120
|
|
|
120
121
|
```typescript
|
|
121
|
-
// src/app/api/
|
|
122
|
+
// src/app/api/users/[id]/route.ts
|
|
122
123
|
|
|
123
124
|
import { NextRequest, NextResponse } from "next/server";
|
|
124
|
-
import { z } from "zod";
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
id:
|
|
128
|
-
}
|
|
126
|
+
type UserParams = {
|
|
127
|
+
id: string; // User ID
|
|
128
|
+
};
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
id:
|
|
132
|
-
name:
|
|
133
|
-
|
|
134
|
-
}
|
|
130
|
+
type UserResponse = {
|
|
131
|
+
id: string; // User ID
|
|
132
|
+
name: string; // Full name
|
|
133
|
+
email: string; // Email address
|
|
134
|
+
};
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
|
-
* Get
|
|
138
|
-
* @description Fetches detailed
|
|
139
|
-
* @pathParams
|
|
140
|
-
* @response
|
|
137
|
+
* Get user information
|
|
138
|
+
* @description Fetches detailed user information by ID
|
|
139
|
+
* @pathParams UserParams
|
|
140
|
+
* @response UserResponse
|
|
141
141
|
* @openapi
|
|
142
142
|
*/
|
|
143
143
|
export async function GET(
|
|
@@ -178,8 +178,9 @@ npx next-openapi-gen init
|
|
|
178
178
|
This command will generate following elements:
|
|
179
179
|
|
|
180
180
|
- Generate `next.openapi.json` configuration file
|
|
181
|
-
-
|
|
181
|
+
- Set up `Scalar` UI for documentation display
|
|
182
182
|
- Add `/api-docs` page to display OpenAPI documentation
|
|
183
|
+
- Configure `zod` as the default schema tool
|
|
183
184
|
|
|
184
185
|
### 2. Generate Documentation
|
|
185
186
|
|
|
@@ -192,7 +193,7 @@ This command will generate OpenAPI documentation based on your API code:
|
|
|
192
193
|
- Scan API directories for routes
|
|
193
194
|
- Analyze types/schemas
|
|
194
195
|
- Generate OpenAPI file (`openapi.json`) in `public` folder
|
|
195
|
-
- Create Swagger
|
|
196
|
+
- Create Scalar/Swagger UI endpoint and page (if enabled)
|
|
196
197
|
|
|
197
198
|
### 3. View API Documentation
|
|
198
199
|
|
|
@@ -205,16 +206,16 @@ To see API documenation go to `http://localhost:3000/api-docs`
|
|
|
205
206
|
```typescript
|
|
206
207
|
// src/app/api/users/[id]/route.ts
|
|
207
208
|
|
|
208
|
-
//
|
|
209
|
-
type UserParams = {
|
|
210
|
-
id: string; // User ID
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
// Or Zod
|
|
209
|
+
// Zod
|
|
214
210
|
const UserParams = z.object({
|
|
215
211
|
id: z.string().describe("User ID"),
|
|
216
212
|
});
|
|
217
213
|
|
|
214
|
+
// Or TypeScript
|
|
215
|
+
type UserParams = {
|
|
216
|
+
id: string; // User ID
|
|
217
|
+
};
|
|
218
|
+
|
|
218
219
|
/**
|
|
219
220
|
* @pathParams UserParams
|
|
220
221
|
*/
|
|
@@ -228,20 +229,20 @@ export async function GET() {
|
|
|
228
229
|
```typescript
|
|
229
230
|
// src/app/api/users/route.ts
|
|
230
231
|
|
|
231
|
-
//
|
|
232
|
-
type UsersQueryParams = {
|
|
233
|
-
page?: number; // Page number
|
|
234
|
-
limit?: number; // Results per page
|
|
235
|
-
search?: string; // Search phrase
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
// Or Zod
|
|
232
|
+
// Zod
|
|
239
233
|
const UsersQueryParams = z.object({
|
|
240
234
|
page: z.number().optional().describe("Page number"),
|
|
241
235
|
limit: z.number().optional().describe("Results per page"),
|
|
242
236
|
search: z.string().optional().describe("Search phrase"),
|
|
243
237
|
});
|
|
244
238
|
|
|
239
|
+
// Or TypeScript
|
|
240
|
+
type UsersQueryParams = {
|
|
241
|
+
page?: number; // Page number
|
|
242
|
+
limit?: number; // Results per page
|
|
243
|
+
search?: string; // Search phrase
|
|
244
|
+
};
|
|
245
|
+
|
|
245
246
|
/**
|
|
246
247
|
* @params UsersQueryParams
|
|
247
248
|
*/
|
|
@@ -255,20 +256,20 @@ export async function GET() {
|
|
|
255
256
|
```typescript
|
|
256
257
|
// src/app/api/users/route.ts
|
|
257
258
|
|
|
258
|
-
//
|
|
259
|
-
type CreateUserBody = {
|
|
260
|
-
name: string; // Full name
|
|
261
|
-
email: string; // Email address
|
|
262
|
-
password: string; // Password
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
// Or Zod
|
|
259
|
+
// Zod
|
|
266
260
|
const CreateUserBody = z.object({
|
|
267
261
|
name: z.string().describe("Full name"),
|
|
268
262
|
email: z.string().email().describe("Email address"),
|
|
269
263
|
password: z.string().min(8).describe("Password"),
|
|
270
264
|
});
|
|
271
265
|
|
|
266
|
+
// Or TypeScript
|
|
267
|
+
type CreateUserBody = {
|
|
268
|
+
name: string; // Full name
|
|
269
|
+
email: string; // Email address
|
|
270
|
+
password: string; // Password
|
|
271
|
+
};
|
|
272
|
+
|
|
272
273
|
/**
|
|
273
274
|
* @body CreateUserBody
|
|
274
275
|
* @bodyDescription User registration data including email and password
|
|
@@ -283,15 +284,7 @@ export async function POST() {
|
|
|
283
284
|
```typescript
|
|
284
285
|
// src/app/api/users/route.ts
|
|
285
286
|
|
|
286
|
-
//
|
|
287
|
-
type UserResponse = {
|
|
288
|
-
id: string; // User ID
|
|
289
|
-
name: string; // Full name
|
|
290
|
-
email: string; // Email address
|
|
291
|
-
createdAt: Date; // Creation date
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
// Or Zod
|
|
287
|
+
// Zod
|
|
295
288
|
const UserResponse = z.object({
|
|
296
289
|
id: z.string().describe("User ID"),
|
|
297
290
|
name: z.string().describe("Full name"),
|
|
@@ -299,6 +292,14 @@ const UserResponse = z.object({
|
|
|
299
292
|
createdAt: z.date().describe("Creation date"),
|
|
300
293
|
});
|
|
301
294
|
|
|
295
|
+
// Or TypeScript
|
|
296
|
+
type UserResponse = {
|
|
297
|
+
id: string; // User ID
|
|
298
|
+
name: string; // Full name
|
|
299
|
+
email: string; // Email address
|
|
300
|
+
createdAt: Date; // Creation date
|
|
301
|
+
};
|
|
302
|
+
|
|
302
303
|
/**
|
|
303
304
|
* @response UserResponse
|
|
304
305
|
* @responseDescription Returns newly created user object
|
|
@@ -326,7 +327,15 @@ export async function GET() {
|
|
|
326
327
|
```typescript
|
|
327
328
|
// src/app/api/v1/route.ts
|
|
328
329
|
|
|
329
|
-
//
|
|
330
|
+
// Zod
|
|
331
|
+
const UserSchema = z.object({
|
|
332
|
+
id: z.string(),
|
|
333
|
+
name: z.string(),
|
|
334
|
+
fullName: z.string().optional().describe("@deprecated Use name instead"),
|
|
335
|
+
email: z.string().email(),
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// Or TypeScript
|
|
330
339
|
type UserResponse = {
|
|
331
340
|
id: string;
|
|
332
341
|
name: string;
|
|
@@ -335,14 +344,6 @@ type UserResponse = {
|
|
|
335
344
|
email: string;
|
|
336
345
|
};
|
|
337
346
|
|
|
338
|
-
// Or Zod
|
|
339
|
-
const UserSchema = z.object({
|
|
340
|
-
id: z.string(),
|
|
341
|
-
name: z.string(),
|
|
342
|
-
fullName: z.string().optional().describe("@deprecated Use name instead"),
|
|
343
|
-
email: z.string().email(),
|
|
344
|
-
});
|
|
345
|
-
|
|
346
347
|
/**
|
|
347
348
|
* @body UserSchema
|
|
348
349
|
* @response UserResponse
|
|
@@ -357,20 +358,20 @@ export async function GET() {
|
|
|
357
358
|
```typescript
|
|
358
359
|
// src/app/api/upload/route.ts
|
|
359
360
|
|
|
360
|
-
//
|
|
361
|
-
type FileUploadFormData = {
|
|
362
|
-
file: File;
|
|
363
|
-
description?: string;
|
|
364
|
-
category: string;
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
// Or Zod
|
|
361
|
+
// Zod
|
|
368
362
|
const FileUploadSchema = z.object({
|
|
369
363
|
file: z.custom<File>().describe("Image file (PNG/JPG)"),
|
|
370
364
|
description: z.string().optional().describe("File description"),
|
|
371
365
|
category: z.string().describe("File category"),
|
|
372
366
|
});
|
|
373
367
|
|
|
368
|
+
// Or TypeScript
|
|
369
|
+
type FileUploadFormData = {
|
|
370
|
+
file: File;
|
|
371
|
+
description?: string;
|
|
372
|
+
category: string;
|
|
373
|
+
};
|
|
374
|
+
|
|
374
375
|
/**
|
|
375
376
|
* @body FileUploadSchema
|
|
376
377
|
* @contentType multipart/form-data
|
package/dist/commands/init.js
CHANGED
|
@@ -92,14 +92,15 @@ async function installDependencies(ui) {
|
|
|
92
92
|
function extendOpenApiTemplate(spec, options) {
|
|
93
93
|
spec.ui = options.ui ?? spec.ui;
|
|
94
94
|
spec.docsUrl = options.docsUrl ?? spec.docsUrl;
|
|
95
|
+
spec.schemaType = options.schemaType ?? spec.schemaType;
|
|
95
96
|
}
|
|
96
97
|
export async function init(options) {
|
|
97
|
-
const { ui, docsUrl } = options;
|
|
98
|
+
const { ui, docsUrl, schemaType } = options;
|
|
98
99
|
spinner.start();
|
|
99
100
|
try {
|
|
100
101
|
const outputPath = path.join(process.cwd(), "next.openapi.json");
|
|
101
102
|
const template = { ...openapiTemplate };
|
|
102
|
-
extendOpenApiTemplate(template, { docsUrl, ui });
|
|
103
|
+
extendOpenApiTemplate(template, { docsUrl, ui, schemaType });
|
|
103
104
|
await fse.writeJson(outputPath, template, { spaces: 2 });
|
|
104
105
|
spinner.succeed(`Created OpenAPI template in next.openapi.json`);
|
|
105
106
|
createDocsPage(ui, template.outputFile);
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
export const rapidocDeps = ["rapidoc"];
|
|
2
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
|
-
}
|
|
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
19
|
`;
|
|
20
20
|
}
|
package/dist/components/redoc.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
export const redocDeps = ["redoc"];
|
|
2
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
|
-
}
|
|
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
15
|
`;
|
|
16
16
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
export const stoplightDeps = ["@stoplight/elements"];
|
|
2
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
|
-
}
|
|
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
16
|
`;
|
|
17
17
|
}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { generate } from "./commands/generate.js";
|
|
|
5
5
|
const program = new Command();
|
|
6
6
|
program
|
|
7
7
|
.name("next-openapi-gen")
|
|
8
|
-
.version("0.
|
|
8
|
+
.version("0.6.7")
|
|
9
9
|
.description("Super fast and easy way to generate OpenAPI documentation for Next.js");
|
|
10
10
|
program
|
|
11
11
|
.command("init")
|
|
@@ -13,6 +13,7 @@ program
|
|
|
13
13
|
.choices(["scalar", "swagger", "redoc", "stoplight", "rapidoc"])
|
|
14
14
|
.default("swagger"))
|
|
15
15
|
.option("-u, --docs-url <url>", "Specify the docs URL", "api-docs")
|
|
16
|
+
.option("-s, --schema <schemaType>", "Specify the schema type", "zod")
|
|
16
17
|
.description("Initialize a openapi specification")
|
|
17
18
|
.action(init);
|
|
18
19
|
program
|
package/dist/openapi-template.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-openapi-gen",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"description": "Automatically generate OpenAPI 3.0 documentation from Next.js projects, with support for
|
|
3
|
+
"version": "0.6.8",
|
|
4
|
+
"description": "Automatically generate OpenAPI 3.0 documentation from Next.js projects, with support for Zod schemas and TypeScript types.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.mjs",
|