next-openapi-gen 0.0.18 → 0.1.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.
- package/README.md +113 -54
- package/dist/components/swagger.js +18 -18
- package/dist/lib/schema-processor.js +10 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
# next-openapi-gen
|
|
2
2
|
|
|
3
|
-
**next-openapi-gen** super fast and easy way to generate OpenAPI 3.0 documentation automatically from API routes in
|
|
4
|
-
|
|
5
|
-
With support for multiple user interfaces next-openapi-gen makes documenting your API a breeze!
|
|
3
|
+
**next-openapi-gen** super fast and easy way to generate OpenAPI 3.0 documentation automatically from API routes in NextJS.
|
|
6
4
|
|
|
7
5
|
## Prerequisites
|
|
8
6
|
|
|
9
|
-
-
|
|
7
|
+
- Next.js >= 14
|
|
10
8
|
- Node >= 18
|
|
11
9
|
|
|
12
|
-
##
|
|
10
|
+
## Interfaces
|
|
13
11
|
|
|
14
12
|
- Swagger
|
|
15
13
|
- Redoc
|
|
@@ -18,15 +16,13 @@ With support for multiple user interfaces next-openapi-gen makes documenting you
|
|
|
18
16
|
|
|
19
17
|
## Features
|
|
20
18
|
|
|
21
|
-
- **Automatic OpenAPI Generation**: Generate OpenAPI 3.0 documentation from your Next.js routes, automatically parsing TypeScript types for parameters, request bodies and responses.
|
|
22
|
-
- **TypeScript
|
|
23
|
-
- **JSDoc-Based Documentation
|
|
24
|
-
- **UI
|
|
19
|
+
- **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
|
+
- **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
|
+
- **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.
|
|
25
23
|
- **Real-time Documentation**: As your API evolves, regenerate the OpenAPI documentation with a single command, ensuring your documentation is always up to date.
|
|
26
24
|
- **Easy configuration**: Customize generator behavior using the `next.openapi.json` configuration file, allowing for quick adjustments without modifying the code.
|
|
27
25
|
|
|
28
|
-

|
|
29
|
-
|
|
30
26
|
## Installation
|
|
31
27
|
|
|
32
28
|
```bash
|
|
@@ -57,49 +53,103 @@ This command does the following:
|
|
|
57
53
|
|
|
58
54
|
Annotate your API routes using JSDoc comments. Here's an example:
|
|
59
55
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
56
|
+
<div align="center">
|
|
57
|
+
<table>
|
|
58
|
+
<tr>
|
|
59
|
+
<th>Login route</th>
|
|
60
|
+
<th>Swagger</th>
|
|
61
|
+
</tr>
|
|
62
|
+
<tr>
|
|
63
|
+
<td>
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
//app/api/auth/login/route.ts
|
|
67
|
+
|
|
68
|
+
type LoginBody = {
|
|
69
|
+
email: string; // user email
|
|
70
|
+
password: string; // user password
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
type LoginResponse = {
|
|
74
|
+
token: string; // auth token
|
|
75
|
+
refresh_token: string; // refresh token
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Authenticate as a user.
|
|
80
|
+
* @desc: Login a user
|
|
81
|
+
* @body: LoginBody
|
|
82
|
+
* @response: LoginResponse
|
|
83
|
+
*/
|
|
84
|
+
export async function POST(req: Request) {
|
|
85
|
+
...
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
</td>
|
|
89
|
+
<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
|
+
</td>
|
|
92
|
+
</tr>
|
|
93
|
+
|
|
94
|
+
<tr>
|
|
95
|
+
<th>Users route</th>
|
|
96
|
+
<th>Swagger</th>
|
|
97
|
+
</tr>
|
|
98
|
+
<tr>
|
|
99
|
+
<td>
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
//app/api/users/route.ts
|
|
103
|
+
|
|
104
|
+
enum ROLE {
|
|
105
|
+
OWNER,
|
|
106
|
+
MEMBER,
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
type User = {
|
|
110
|
+
id: number;
|
|
111
|
+
name: string;
|
|
112
|
+
email: string;
|
|
113
|
+
role: ROLE;
|
|
114
|
+
address: Address;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
type Address = {
|
|
118
|
+
line1: string;
|
|
119
|
+
line2?: string;
|
|
120
|
+
city: string;
|
|
121
|
+
postalCode: string;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
type UsersParams = {
|
|
125
|
+
search: string; // search by
|
|
126
|
+
role?: ROLE; // filter by role
|
|
127
|
+
page?: number; // page number
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
type UsersResponse = {
|
|
131
|
+
page?: number;
|
|
132
|
+
count?: number;
|
|
133
|
+
data: User[];
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* List all users.
|
|
138
|
+
* @auth: bearer
|
|
139
|
+
* @params: UsersParams
|
|
140
|
+
* @response: UsersResponse
|
|
141
|
+
*/
|
|
142
|
+
export async function GET(req: Request) {
|
|
143
|
+
...
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
</td>
|
|
147
|
+
<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"/>
|
|
149
|
+
</td>
|
|
150
|
+
</tr>
|
|
151
|
+
</table>
|
|
152
|
+
</div>
|
|
103
153
|
|
|
104
154
|
### Step 3: Generate the OpenAPI Specification
|
|
105
155
|
|
|
@@ -115,6 +165,15 @@ This command processes all your API routes, extracts the necessary information f
|
|
|
115
165
|
|
|
116
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`.
|
|
117
167
|
|
|
168
|
+
## JSDoc tags
|
|
169
|
+
|
|
170
|
+
- `@openapi`: Marks the route for inclusion in the OpenAPI specification.
|
|
171
|
+
- `@auth`: Specifies authentication type used for API route (`basic`, `bearer`, `apikey`).
|
|
172
|
+
- `@desc`: Provides a detailed description of the API route.
|
|
173
|
+
- `@params`: Specifies the TypeScript interface for the query parameters.
|
|
174
|
+
- `@body`: Specifies the TypeScript interface for the request body.
|
|
175
|
+
- `@response`: Specifies the TypeScript interface for the response.
|
|
176
|
+
|
|
118
177
|
## Configuration Options
|
|
119
178
|
|
|
120
179
|
The `next.openapi.json` file allows you to configure the behavior of the OpenAPI generator, including options such as:
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
export const swaggerDeps = ["swagger-ui"];
|
|
1
|
+
export const swaggerDeps = ["swagger-ui", "swagger-ui-react"];
|
|
2
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
|
-
}
|
|
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
20
|
`;
|
|
21
21
|
}
|
|
@@ -121,6 +121,16 @@ export class SchemaProcessor {
|
|
|
121
121
|
});
|
|
122
122
|
return { type: "object", properties };
|
|
123
123
|
}
|
|
124
|
+
if (t.isTSUnionType(node)) {
|
|
125
|
+
return {
|
|
126
|
+
anyOf: node.types.map((subNode) => this.resolveTSNodeType(subNode)),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// case where a type is a reference to another defined type
|
|
130
|
+
if (t.isTSTypeReference(node) && t.isIdentifier(node.typeName)) {
|
|
131
|
+
return { $ref: `#/components/schemas/${node.typeName.name}` };
|
|
132
|
+
}
|
|
133
|
+
console.warn("Unrecognized TypeScript type node:", node);
|
|
124
134
|
return {};
|
|
125
135
|
}
|
|
126
136
|
processSchemaFile(filePath, schemaName) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-openapi-gen",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "Super fast and easy way to generate OpenAPI documentation automatically from API routes in
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Super fast and easy way to generate OpenAPI documentation automatically from API routes in NextJS.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.mjs",
|