@spikers/next-openapi-json-generator 1.0.3 → 1.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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Omer Mecitoglu
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Omer Mecitoglu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,211 +1,211 @@
1
- # Next OpenAPI JSON Generator
2
-
3
- [![npm version](https://img.shields.io/npm/v/@omer-x/next-openapi-json-generator?logo=npm&logoColor=CB3837&color=CB3837)](https://www.npmjs.com/package/@omer-x/next-openapi-json-generator)
4
- [![npm downloads](https://img.shields.io/npm/dm/@omer-x/next-openapi-json-generator?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTI4OCAzMmMwLTE3LjctMTQuMy0zMi0zMi0zMnMtMzIgMTQuMy0zMiAzMmwwIDI0Mi43LTczLjQtNzMuNGMtMTIuNS0xMi41LTMyLjgtMTIuNS00NS4zIDBzLTEyLjUgMzIuOCAwIDQ1LjNsMTI4IDEyOGMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxMjgtMTI4YzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDI4OCAyNzQuNyAyODggMzJ6TTY0IDM1MmMtMzUuMyAwLTY0IDI4LjctNjQgNjRsMCAzMmMwIDM1LjMgMjguNyA2NCA2NCA2NGwzODQgMGMzNS4zIDAgNjQtMjguNyA2NC02NGwwLTMyYzAtMzUuMy0yOC43LTY0LTY0LTY0bC0xMDEuNSAwLTQ1LjMgNDUuM2MtMjUgMjUtNjUuNSAyNS05MC41IDBMMTY1LjUgMzUyIDY0IDM1MnptMzY4IDU2YTI0IDI0IDAgMSAxIDAgNDggMjQgMjQgMCAxIDEgMC00OHoiIGZpbGw9IiMwMDc4MjAiIC8+PC9zdmc+&color=007820)](https://www.npmjs.com/package/@omer-x/next-openapi-json-generator)
5
- [![codecov](https://codecov.io/gh/omermecitoglu/next-openapi-json-generator/branch/main/graph/badge.svg)](https://codecov.io/gh/omermecitoglu/next-openapi-json-generator)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTM4NCAzMmwxMjggMGMxNy43IDAgMzIgMTQuMyAzMiAzMnMtMTQuMyAzMi0zMiAzMkwzOTguNCA5NmMtNS4yIDI1LjgtMjIuOSA0Ny4xLTQ2LjQgNTcuM0wzNTIgNDQ4bDE2MCAwYzE3LjcgMCAzMiAxNC4zIDMyIDMycy0xNC4zIDMyLTMyIDMybC0xOTIgMC0xOTIgMGMtMTcuNyAwLTMyLTE0LjMtMzItMzJzMTQuMy0zMiAzMi0zMmwxNjAgMCAwLTI5NC43Yy0yMy41LTEwLjMtNDEuMi0zMS42LTQ2LjQtNTcuM0wxMjggOTZjLTE3LjcgMC0zMi0xNC4zLTMyLTMyczE0LjMtMzIgMzItMzJsMTI4IDBjMTQuNi0xOS40IDM3LjgtMzIgNjQtMzJzNDkuNCAxMi42IDY0IDMyem01NS42IDI4OGwxNDQuOSAwTDUxMiAxOTUuOCA0MzkuNiAzMjB6TTUxMiA0MTZjLTYyLjkgMC0xMTUuMi0zNC0xMjYtNzguOWMtMi42LTExIDEtMjIuMyA2LjctMzIuMWw5NS4yLTE2My4yYzUtOC42IDE0LjItMTMuOCAyNC4xLTEzLjhzMTkuMSA1LjMgMjQuMSAxMy44bDk1LjIgMTYzLjJjNS43IDkuOCA5LjMgMjEuMSA2LjcgMzIuMUM2MjcuMiAzODIgNTc0LjkgNDE2IDUxMiA0MTZ6TTEyNi44IDE5NS44TDU0LjQgMzIwbDE0NC45IDBMMTI2LjggMTk1Ljh6TS45IDMzNy4xYy0yLjYtMTEgMS0yMi4zIDYuNy0zMi4xbDk1LjItMTYzLjJjNS04LjYgMTQuMi0xMy44IDI0LjEtMTMuOHMxOS4xIDUuMyAyNC4xIDEzLjhsOTUuMiAxNjMuMmM1LjcgOS44IDkuMyAyMS4xIDYuNyAzMi4xQzI0MiAzODIgMTg5LjcgNDE2IDEyNi44IDQxNlMxMS43IDM4MiAuOSAzMzcuMXoiIGZpbGw9IiNEMEE4MUMiIC8+PC9zdmc+)](https://opensource.org/licenses/MIT)
7
- [![GitHub last commit](https://img.shields.io/github/last-commit/omermecitoglu/next-openapi-json-generator?color=c977be&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTMyMCAzMzZhODAgODAgMCAxIDAgMC0xNjAgODAgODAgMCAxIDAgMCAxNjB6bTE1Ni44LTQ4QzQ2MiAzNjEgMzk3LjQgNDE2IDMyMCA0MTZzLTE0Mi01NS0xNTYuOC0xMjhMMzIgMjg4Yy0xNy43IDAtMzItMTQuMy0zMi0zMnMxNC4zLTMyIDMyLTMybDEzMS4yIDBDMTc4IDE1MSAyNDIuNiA5NiAzMjAgOTZzMTQyIDU1IDE1Ni44IDEyOEw2MDggMjI0YzE3LjcgMCAzMiAxNC4zIDMyIDMycy0xNC4zIDMyLTMyIDMybC0xMzEuMiAweiIgZmlsbD0iI0M5NzdCRSIgLz48L3N2Zz4=)](https://github.com/omermecitoglu/next-openapi-json-generator/commits/main/)
8
- [![GitHub issues](https://img.shields.io/github/issues/omermecitoglu/next-openapi-json-generator?color=a38eed&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij4KICA8cGF0aCBkPSJNOCA5LjVhMS41IDEuNSAwIDEgMCAwLTMgMS41IDEuNSAwIDAgMCAwIDNaIiBmaWxsPSIjQTM4RUVEIj48L3BhdGg+CiAgPHBhdGggZD0iTTggMGE4IDggMCAxIDEgMCAxNkE4IDggMCAwIDEgOCAwWk0xLjUgOGE2LjUgNi41IDAgMSAwIDEzIDAgNi41IDYuNSAwIDAgMC0xMyAwWiIgZmlsbD0iI0EzOEVFRCI+PC9wYXRoPgo8L3N2Zz4=)](https://github.com/omermecitoglu/next-openapi-json-generator/issues)
9
- [![GitHub stars](https://img.shields.io/github/stars/omermecitoglu/next-openapi-json-generator?style=social)](https://github.com/omermecitoglu/next-openapi-json-generator)
10
-
11
- ## Overview
12
-
13
- `Next OpenAPI JSON Generator` is an open-source Next.js plugin that extracts and generates OpenAPI JSON specifications from your route handlers defined using `@omer-x/next-openapi-route-handler`. It simplifies the process of generating and maintaining OpenAPI documentation by leveraging TypeScript and Zod schemas.
14
-
15
- **Key Features:**
16
- - **Automated OpenAPI Generation**: Automatically generates OpenAPI JSON specs from your route handlers.
17
- - **TypeScript Integration**: Seamlessly integrates with TypeScript for strong type-checking.
18
- - **Zod Schema Support**: Uses Zod schemas for validation and generates JSON schemas for OpenAPI.
19
- - **Next.js Compatibility**: Works seamlessly with Next.js and integrates with other server-side libraries.
20
-
21
- > **Note:** This package works in conjunction with [`Next OpenAPI Route Handler`](https://www.npmjs.com/package/@omer-x/next-openapi-route-handler) to extract the generated OpenAPI JSON.
22
-
23
- ## Requirements
24
-
25
- To use `@omer-x/next-openapi-json-generator`, you'll need the following dependencies in your Next.js project:
26
-
27
- - [TypeScript](https://www.typescriptlang.org/) >= v5
28
- - [Next.js](https://nextjs.org/) >= v13
29
- - [Zod](https://zod.dev/) >= v3
30
- - [Next OpenAPI Route Handler](https://www.npmjs.com/package/@omer-x/next-openapi-route-handler)
31
-
32
- ## Installation
33
-
34
- To install this package, along with its peer dependency, run:
35
-
36
- ```sh
37
- npm install @omer-x/next-openapi-json-generator @omer-x/next-openapi-route-handler
38
- ```
39
-
40
- ## Usage
41
-
42
- The `generateOpenApiSpec` function is used to extract and generate the OpenAPI JSON specification from your defined models. Here's a description of how to use it:
43
-
44
- ### Example
45
-
46
- ```typescript
47
- import generateOpenApiSpec from "@omer-x/next-openapi-json-generator";
48
- import { NewUserDTO, UserDTO, UserPatchDTO } from "../models/user";
49
-
50
- const Page = async () => {
51
- const spec = await generateOpenApiSpec({
52
- UserDTO,
53
- NewUserDTO,
54
- UserPatchDTO,
55
- }, {
56
- // options
57
- });
58
- return <ReactSwagger spec={spec} />;
59
- };
60
-
61
- export default Page;
62
- ```
63
-
64
- ### Parameters
65
-
66
- The `generateOpenApiSpec` function takes an object with the following properties:
67
-
68
- | Property | Type | Description |
69
- | -------- | ------------------------------------------ | ---------------------------------------------------------------------------------- |
70
- | models | Record<string, [ZodType](https://zod.dev)> | An object where keys are model names and values are Zod schemas |
71
- | options | Object | `(Optional)` An object to customize the functionality of the generator (see below) |
72
-
73
- #### Options
74
-
75
- | Property | Type | Description |
76
- | ---------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
77
- | include | string[] | `(Optional)` An array of strings which specifies the routes will be included to the JSON output |
78
- | exclude | string[] | `(Optional)` An array of strings which specifies the routes will be excluded from the JSON output |
79
- | routeDefinerName | string | `(Optional)` Name of the function that was exported from the [`Next OpenAPI Route Handler`](https://www.npmjs.com/package/@omer-x/next-openapi-route-handler) (Default: `defineRoute`) |
80
-
81
- ### Result
82
-
83
- The function returns a promise that resolves to an OpenAPI JSON specification.
84
-
85
- ```json
86
- {
87
- "openapi": "3.1.0",
88
- "info": {
89
- "title": "User Service",
90
- "version": "1.0.0"
91
- },
92
- "paths": {
93
- "/users": {
94
- "get": {
95
- ...
96
- },
97
- "post": {
98
- ...
99
- }
100
- },
101
- "/users/{id}": {
102
- "get": {
103
- "operationId": "getUser",
104
- "summary": "Get a specific user by ID",
105
- "description": "Retrieve details of a specific user by their ID",
106
- "tags": [
107
- "Users"
108
- ],
109
- "parameters": [
110
- {
111
- "in": "path",
112
- "name": "id",
113
- "required": true,
114
- "description": "ID of the user",
115
- "schema": {
116
- "type": "string",
117
- "description": "ID of the user"
118
- }
119
- }
120
- ],
121
- "responses": {
122
- "200": {
123
- "description": "User details retrieved successfully",
124
- "content": {
125
- "application/json": {
126
- "schema": {
127
- "$ref": "#/components/schemas/UserDTO"
128
- }
129
- }
130
- }
131
- },
132
- "404": {
133
- "description": "User not found"
134
- }
135
- }
136
- },
137
- "patch": {
138
- ...
139
- },
140
- "delete": {
141
- ...
142
- }
143
- }
144
- },
145
- "components": {
146
- "schemas": {
147
- "UserDTO": {
148
- "type": "object",
149
- "properties": {
150
- "id": {
151
- "type": "string",
152
- "format": "uuid",
153
- "description": "Unique identifier of the user"
154
- },
155
- "name": {
156
- "type": "string",
157
- "description": "Display name of the user"
158
- },
159
- "email": {
160
- "type": "string",
161
- "description": "Email address of the user"
162
- },
163
- "password": {
164
- "type": "string",
165
- "maxLength": 72,
166
- "description": "Encrypted password of the user"
167
- },
168
- "createdAt": {
169
- "type": "string",
170
- "format": "date-time",
171
- "description": "Creation date of the user"
172
- },
173
- "updatedAt": {
174
- "type": "string",
175
- "format": "date-time",
176
- "description": "Modification date of the user"
177
- }
178
- },
179
- "required": [
180
- "id",
181
- "name",
182
- "email",
183
- "password",
184
- "createdAt",
185
- "updatedAt"
186
- ],
187
- "additionalProperties": false,
188
- "description": "Represents the data of a user in the system."
189
- },
190
- "NewUserDTO": {
191
- ...
192
- },
193
- "UserPatchDTO": {
194
- ...
195
- }
196
- }
197
- }
198
- }
199
- ```
200
-
201
- [An example can be found here](https://github.com/omermecitoglu/example-user-service)
202
-
203
- ## Screenshots
204
-
205
- | <a href="https://i.imgur.com/ru3muBc.png" target="_blank"><img src="https://i.imgur.com/ru3muBc.png" alt="screenshot-1"></a> | <a href="https://i.imgur.com/utHaZ6X.png" target="_blank"><img src="https://i.imgur.com/utHaZ6X.png" alt="screenshot-2"></a> | <a href="https://i.imgur.com/2f24kPE.png" target="_blank"><img src="https://i.imgur.com/2f24kPE.png" alt="screenshot-3"></a> | <a href="https://i.imgur.com/z3KIJQ1.png" target="_blank"><img src="https://i.imgur.com/z3KIJQ1.png" alt="screenshot-4"></a> |
206
- |:--------------:|:--------------:|:--------------:|:--------------:|
207
- | <a href="https://i.imgur.com/IFKXOiX.png" target="_blank"><img src="https://i.imgur.com/IFKXOiX.png" alt="screenshot-5"></a> | <a href="https://i.imgur.com/xzVjAPq.png" target="_blank"><img src="https://i.imgur.com/xzVjAPq.png" alt="screenshot-6"></a> | <a href="https://i.imgur.com/HrWuHOR.png" target="_blank"><img src="https://i.imgur.com/HrWuHOR.png" alt="screenshot-7"></a> | |
208
-
209
- ## License
210
-
211
- This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
1
+ # Next OpenAPI JSON Generator
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@omer-x/next-openapi-json-generator?logo=npm&logoColor=CB3837&color=CB3837)](https://www.npmjs.com/package/@omer-x/next-openapi-json-generator)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@omer-x/next-openapi-json-generator?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTI4OCAzMmMwLTE3LjctMTQuMy0zMi0zMi0zMnMtMzIgMTQuMy0zMiAzMmwwIDI0Mi43LTczLjQtNzMuNGMtMTIuNS0xMi41LTMyLjgtMTIuNS00NS4zIDBzLTEyLjUgMzIuOCAwIDQ1LjNsMTI4IDEyOGMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxMjgtMTI4YzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDI4OCAyNzQuNyAyODggMzJ6TTY0IDM1MmMtMzUuMyAwLTY0IDI4LjctNjQgNjRsMCAzMmMwIDM1LjMgMjguNyA2NCA2NCA2NGwzODQgMGMzNS4zIDAgNjQtMjguNyA2NC02NGwwLTMyYzAtMzUuMy0yOC43LTY0LTY0LTY0bC0xMDEuNSAwLTQ1LjMgNDUuM2MtMjUgMjUtNjUuNSAyNS05MC41IDBMMTY1LjUgMzUyIDY0IDM1MnptMzY4IDU2YTI0IDI0IDAgMSAxIDAgNDggMjQgMjQgMCAxIDEgMC00OHoiIGZpbGw9IiMwMDc4MjAiIC8+PC9zdmc+&color=007820)](https://www.npmjs.com/package/@omer-x/next-openapi-json-generator)
5
+ [![codecov](https://codecov.io/gh/omermecitoglu/next-openapi-json-generator/branch/main/graph/badge.svg)](https://codecov.io/gh/omermecitoglu/next-openapi-json-generator)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTM4NCAzMmwxMjggMGMxNy43IDAgMzIgMTQuMyAzMiAzMnMtMTQuMyAzMi0zMiAzMkwzOTguNCA5NmMtNS4yIDI1LjgtMjIuOSA0Ny4xLTQ2LjQgNTcuM0wzNTIgNDQ4bDE2MCAwYzE3LjcgMCAzMiAxNC4zIDMyIDMycy0xNC4zIDMyLTMyIDMybC0xOTIgMC0xOTIgMGMtMTcuNyAwLTMyLTE0LjMtMzItMzJzMTQuMy0zMiAzMi0zMmwxNjAgMCAwLTI5NC43Yy0yMy41LTEwLjMtNDEuMi0zMS42LTQ2LjQtNTcuM0wxMjggOTZjLTE3LjcgMC0zMi0xNC4zLTMyLTMyczE0LjMtMzIgMzItMzJsMTI4IDBjMTQuNi0xOS40IDM3LjgtMzIgNjQtMzJzNDkuNCAxMi42IDY0IDMyem01NS42IDI4OGwxNDQuOSAwTDUxMiAxOTUuOCA0MzkuNiAzMjB6TTUxMiA0MTZjLTYyLjkgMC0xMTUuMi0zNC0xMjYtNzguOWMtMi42LTExIDEtMjIuMyA2LjctMzIuMWw5NS4yLTE2My4yYzUtOC42IDE0LjItMTMuOCAyNC4xLTEzLjhzMTkuMSA1LjMgMjQuMSAxMy44bDk1LjIgMTYzLjJjNS43IDkuOCA5LjMgMjEuMSA2LjcgMzIuMUM2MjcuMiAzODIgNTc0LjkgNDE2IDUxMiA0MTZ6TTEyNi44IDE5NS44TDU0LjQgMzIwbDE0NC45IDBMMTI2LjggMTk1Ljh6TS45IDMzNy4xYy0yLjYtMTEgMS0yMi4zIDYuNy0zMi4xbDk1LjItMTYzLjJjNS04LjYgMTQuMi0xMy44IDI0LjEtMTMuOHMxOS4xIDUuMyAyNC4xIDEzLjhsOTUuMiAxNjMuMmM1LjcgOS44IDkuMyAyMS4xIDYuNyAzMi4xQzI0MiAzODIgMTg5LjcgNDE2IDEyNi44IDQxNlMxMS43IDM4MiAuOSAzMzcuMXoiIGZpbGw9IiNEMEE4MUMiIC8+PC9zdmc+)](https://opensource.org/licenses/MIT)
7
+ [![GitHub last commit](https://img.shields.io/github/last-commit/omermecitoglu/next-openapi-json-generator?color=c977be&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTMyMCAzMzZhODAgODAgMCAxIDAgMC0xNjAgODAgODAgMCAxIDAgMCAxNjB6bTE1Ni44LTQ4QzQ2MiAzNjEgMzk3LjQgNDE2IDMyMCA0MTZzLTE0Mi01NS0xNTYuOC0xMjhMMzIgMjg4Yy0xNy43IDAtMzItMTQuMy0zMi0zMnMxNC4zLTMyIDMyLTMybDEzMS4yIDBDMTc4IDE1MSAyNDIuNiA5NiAzMjAgOTZzMTQyIDU1IDE1Ni44IDEyOEw2MDggMjI0YzE3LjcgMCAzMiAxNC4zIDMyIDMycy0xNC4zIDMyLTMyIDMybC0xMzEuMiAweiIgZmlsbD0iI0M5NzdCRSIgLz48L3N2Zz4=)](https://github.com/omermecitoglu/next-openapi-json-generator/commits/main/)
8
+ [![GitHub issues](https://img.shields.io/github/issues/omermecitoglu/next-openapi-json-generator?color=a38eed&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij4KICA8cGF0aCBkPSJNOCA5LjVhMS41IDEuNSAwIDEgMCAwLTMgMS41IDEuNSAwIDAgMCAwIDNaIiBmaWxsPSIjQTM4RUVEIj48L3BhdGg+CiAgPHBhdGggZD0iTTggMGE4IDggMCAxIDEgMCAxNkE4IDggMCAwIDEgOCAwWk0xLjUgOGE2LjUgNi41IDAgMSAwIDEzIDAgNi41IDYuNSAwIDAgMC0xMyAwWiIgZmlsbD0iI0EzOEVFRCI+PC9wYXRoPgo8L3N2Zz4=)](https://github.com/omermecitoglu/next-openapi-json-generator/issues)
9
+ [![GitHub stars](https://img.shields.io/github/stars/omermecitoglu/next-openapi-json-generator?style=social)](https://github.com/omermecitoglu/next-openapi-json-generator)
10
+
11
+ ## Overview
12
+
13
+ `Next OpenAPI JSON Generator` is an open-source Next.js plugin that extracts and generates OpenAPI JSON specifications from your route handlers defined using `@omer-x/next-openapi-route-handler`. It simplifies the process of generating and maintaining OpenAPI documentation by leveraging TypeScript and Zod schemas.
14
+
15
+ **Key Features:**
16
+ - **Automated OpenAPI Generation**: Automatically generates OpenAPI JSON specs from your route handlers.
17
+ - **TypeScript Integration**: Seamlessly integrates with TypeScript for strong type-checking.
18
+ - **Zod Schema Support**: Uses Zod schemas for validation and generates JSON schemas for OpenAPI.
19
+ - **Next.js Compatibility**: Works seamlessly with Next.js and integrates with other server-side libraries.
20
+
21
+ > **Note:** This package works in conjunction with [`Next OpenAPI Route Handler`](https://www.npmjs.com/package/@omer-x/next-openapi-route-handler) to extract the generated OpenAPI JSON.
22
+
23
+ ## Requirements
24
+
25
+ To use `@omer-x/next-openapi-json-generator`, you'll need the following dependencies in your Next.js project:
26
+
27
+ - [TypeScript](https://www.typescriptlang.org/) >= v5
28
+ - [Next.js](https://nextjs.org/) >= v13
29
+ - [Zod](https://zod.dev/) >= v3
30
+ - [Next OpenAPI Route Handler](https://www.npmjs.com/package/@omer-x/next-openapi-route-handler)
31
+
32
+ ## Installation
33
+
34
+ To install this package, along with its peer dependency, run:
35
+
36
+ ```sh
37
+ npm install @omer-x/next-openapi-json-generator @omer-x/next-openapi-route-handler
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ The `generateOpenApiSpec` function is used to extract and generate the OpenAPI JSON specification from your defined models. Here's a description of how to use it:
43
+
44
+ ### Example
45
+
46
+ ```typescript
47
+ import generateOpenApiSpec from "@omer-x/next-openapi-json-generator";
48
+ import { NewUserDTO, UserDTO, UserPatchDTO } from "../models/user";
49
+
50
+ const Page = async () => {
51
+ const spec = await generateOpenApiSpec({
52
+ UserDTO,
53
+ NewUserDTO,
54
+ UserPatchDTO,
55
+ }, {
56
+ // options
57
+ });
58
+ return <ReactSwagger spec={spec} />;
59
+ };
60
+
61
+ export default Page;
62
+ ```
63
+
64
+ ### Parameters
65
+
66
+ The `generateOpenApiSpec` function takes an object with the following properties:
67
+
68
+ | Property | Type | Description |
69
+ | -------- | ------------------------------------------ | ---------------------------------------------------------------------------------- |
70
+ | models | Record<string, [ZodType](https://zod.dev)> | An object where keys are model names and values are Zod schemas |
71
+ | options | Object | `(Optional)` An object to customize the functionality of the generator (see below) |
72
+
73
+ #### Options
74
+
75
+ | Property | Type | Description |
76
+ | ---------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
77
+ | include | string[] | `(Optional)` An array of strings which specifies the routes will be included to the JSON output |
78
+ | exclude | string[] | `(Optional)` An array of strings which specifies the routes will be excluded from the JSON output |
79
+ | routeDefinerName | string | `(Optional)` Name of the function that was exported from the [`Next OpenAPI Route Handler`](https://www.npmjs.com/package/@omer-x/next-openapi-route-handler) (Default: `defineRoute`) |
80
+
81
+ ### Result
82
+
83
+ The function returns a promise that resolves to an OpenAPI JSON specification.
84
+
85
+ ```json
86
+ {
87
+ "openapi": "3.1.0",
88
+ "info": {
89
+ "title": "User Service",
90
+ "version": "1.0.0"
91
+ },
92
+ "paths": {
93
+ "/users": {
94
+ "get": {
95
+ ...
96
+ },
97
+ "post": {
98
+ ...
99
+ }
100
+ },
101
+ "/users/{id}": {
102
+ "get": {
103
+ "operationId": "getUser",
104
+ "summary": "Get a specific user by ID",
105
+ "description": "Retrieve details of a specific user by their ID",
106
+ "tags": [
107
+ "Users"
108
+ ],
109
+ "parameters": [
110
+ {
111
+ "in": "path",
112
+ "name": "id",
113
+ "required": true,
114
+ "description": "ID of the user",
115
+ "schema": {
116
+ "type": "string",
117
+ "description": "ID of the user"
118
+ }
119
+ }
120
+ ],
121
+ "responses": {
122
+ "200": {
123
+ "description": "User details retrieved successfully",
124
+ "content": {
125
+ "application/json": {
126
+ "schema": {
127
+ "$ref": "#/components/schemas/UserDTO"
128
+ }
129
+ }
130
+ }
131
+ },
132
+ "404": {
133
+ "description": "User not found"
134
+ }
135
+ }
136
+ },
137
+ "patch": {
138
+ ...
139
+ },
140
+ "delete": {
141
+ ...
142
+ }
143
+ }
144
+ },
145
+ "components": {
146
+ "schemas": {
147
+ "UserDTO": {
148
+ "type": "object",
149
+ "properties": {
150
+ "id": {
151
+ "type": "string",
152
+ "format": "uuid",
153
+ "description": "Unique identifier of the user"
154
+ },
155
+ "name": {
156
+ "type": "string",
157
+ "description": "Display name of the user"
158
+ },
159
+ "email": {
160
+ "type": "string",
161
+ "description": "Email address of the user"
162
+ },
163
+ "password": {
164
+ "type": "string",
165
+ "maxLength": 72,
166
+ "description": "Encrypted password of the user"
167
+ },
168
+ "createdAt": {
169
+ "type": "string",
170
+ "format": "date-time",
171
+ "description": "Creation date of the user"
172
+ },
173
+ "updatedAt": {
174
+ "type": "string",
175
+ "format": "date-time",
176
+ "description": "Modification date of the user"
177
+ }
178
+ },
179
+ "required": [
180
+ "id",
181
+ "name",
182
+ "email",
183
+ "password",
184
+ "createdAt",
185
+ "updatedAt"
186
+ ],
187
+ "additionalProperties": false,
188
+ "description": "Represents the data of a user in the system."
189
+ },
190
+ "NewUserDTO": {
191
+ ...
192
+ },
193
+ "UserPatchDTO": {
194
+ ...
195
+ }
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
201
+ [An example can be found here](https://github.com/omermecitoglu/example-user-service)
202
+
203
+ ## Screenshots
204
+
205
+ | <a href="https://i.imgur.com/ru3muBc.png" target="_blank"><img src="https://i.imgur.com/ru3muBc.png" alt="screenshot-1"></a> | <a href="https://i.imgur.com/utHaZ6X.png" target="_blank"><img src="https://i.imgur.com/utHaZ6X.png" alt="screenshot-2"></a> | <a href="https://i.imgur.com/2f24kPE.png" target="_blank"><img src="https://i.imgur.com/2f24kPE.png" alt="screenshot-3"></a> | <a href="https://i.imgur.com/z3KIJQ1.png" target="_blank"><img src="https://i.imgur.com/z3KIJQ1.png" alt="screenshot-4"></a> |
206
+ |:--------------:|:--------------:|:--------------:|:--------------:|
207
+ | <a href="https://i.imgur.com/IFKXOiX.png" target="_blank"><img src="https://i.imgur.com/IFKXOiX.png" alt="screenshot-5"></a> | <a href="https://i.imgur.com/xzVjAPq.png" target="_blank"><img src="https://i.imgur.com/xzVjAPq.png" alt="screenshot-6"></a> | <a href="https://i.imgur.com/HrWuHOR.png" target="_blank"><img src="https://i.imgur.com/HrWuHOR.png" alt="screenshot-7"></a> | |
208
+
209
+ ## License
210
+
211
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
package/dist/index.cjs CHANGED
@@ -91,7 +91,7 @@ async function getDirectoryItems(dirPath, targetFileName) {
91
91
  const children = await getDirectoryItems(itemPath, targetFileName);
92
92
  collection.push(...children);
93
93
  } else if (itemName === targetFileName) {
94
- collection.push(itemPath);
94
+ collection.push(itemPath.split(import_node_path.default.sep).join("/").replace(/^[A-Z]:/i, ""));
95
95
  }
96
96
  }
97
97
  return collection;
@@ -109,9 +109,9 @@ function filterDirectoryItems(rootPath, items, include, exclude) {
109
109
 
110
110
  // src/core/isDocumentedRoute.ts
111
111
  var import_promises2 = __toESM(require("fs/promises"), 1);
112
- async function isDocumentedRoute(routePath2) {
112
+ async function isDocumentedRoute(routePath) {
113
113
  try {
114
- const rawCode = await import_promises2.default.readFile(routePath2, "utf-8");
114
+ const rawCode = await import_promises2.default.readFile(routePath, "utf-8");
115
115
  return rawCode.includes("@omer-x/next-openapi-route-handler");
116
116
  } catch {
117
117
  return false;
@@ -128,9 +128,9 @@ function generateRandomString(length) {
128
128
  }
129
129
 
130
130
  // src/utils/string-preservation.ts
131
- function preserveStrings(code2) {
131
+ function preserveStrings(code) {
132
132
  let replacements = {};
133
- const output = code2.replace(/(['"`])((?:\\.|(?!\1).)*)\1/g, (match, quote, content) => {
133
+ const output = code.replace(/(['"`])((?:\\.|(?!\1).)*)\1/g, (match, quote, content) => {
134
134
  const replacementId = generateRandomString(32);
135
135
  replacements = {
136
136
  ...replacements,
@@ -140,22 +140,22 @@ function preserveStrings(code2) {
140
140
  });
141
141
  return { output, replacements };
142
142
  }
143
- function restoreStrings(code2, replacements) {
144
- return code2.replace(/<@~(.*?)~@>/g, (_, replacementId) => {
143
+ function restoreStrings(code, replacements) {
144
+ return code.replace(/<@~(.*?)~@>/g, (_, replacementId) => {
145
145
  return replacements[replacementId];
146
146
  });
147
147
  }
148
148
 
149
149
  // src/core/injectSchemas.ts
150
- function injectSchemas(code2, refName) {
151
- const { output: preservedCode, replacements } = preserveStrings(code2);
150
+ function injectSchemas(code, refName) {
151
+ const { output: preservedCode, replacements } = preserveStrings(code);
152
152
  const preservedCodeWithSchemasInjected = preservedCode.replace(new RegExp(`\\b${refName}\\.`, "g"), `global.schemas[${refName}].`).replace(new RegExp(`\\b${refName}\\b`, "g"), `"${refName}"`).replace(new RegExp(`queryParams:\\s*['"\`]${refName}['"\`]`, "g"), `queryParams: global.schemas["${refName}"]`).replace(new RegExp(`pathParams:\\s*['"\`]${refName}['"\`]`, "g"), `pathParams: global.schemas["${refName}"]`);
153
153
  return restoreStrings(preservedCodeWithSchemasInjected, replacements);
154
154
  }
155
155
 
156
156
  // src/core/middleware.ts
157
- function detectMiddlewareName(code2) {
158
- const match = code2.match(/middleware:\s*(\w+)/);
157
+ function detectMiddlewareName(code) {
158
+ const match = code.match(/middleware:\s*(\w+)/);
159
159
  return match ? match[1] : null;
160
160
  }
161
161
 
@@ -163,30 +163,30 @@ function detectMiddlewareName(code2) {
163
163
  var import_typescript = require("typescript");
164
164
 
165
165
  // src/utils/removeImports.ts
166
- function removeImports(code2) {
167
- return code2.replace(/(^import\s+[^;]+;?$|^import\s+[^;]*\sfrom\s.+;?$)/gm, "").replace(/(^import\s+{[\s\S]+?}\s+from\s+["'][^"']+["'];?)/gm, "").trim();
166
+ function removeImports(code) {
167
+ return code.replace(/(^import\s+[^;]+;?$|^import\s+[^;]*\sfrom\s.+;?$)/gm, "").replace(/(^import\s+{[\s\S]+?}\s+from\s+["'][^"']+["'];?)/gm, "").trim();
168
168
  }
169
169
 
170
170
  // src/core/transpile.ts
171
- function fixExports(code2) {
171
+ function fixExports(code) {
172
172
  const validMethods = ["GET", "POST", "PUT", "PATCH", "DELETE"];
173
173
  const exportFixer1 = validMethods.map((method) => `exports.${method} = void 0;
174
174
  `);
175
175
  const exportFixer2 = `module.exports = { ${validMethods.map((m) => `${m}: exports.${m}`).join(", ")} }`;
176
176
  return `${exportFixer1}
177
- ${code2}
177
+ ${code}
178
178
  ${exportFixer2}`;
179
179
  }
180
180
  function injectMiddlewareFixer(middlewareName) {
181
181
  return `const ${middlewareName} = (handler) => handler;`;
182
182
  }
183
183
  function transpile(rawCode, routeDefinerName, middlewareName) {
184
- const code2 = fixExports(removeImports(rawCode));
184
+ const code = fixExports(removeImports(rawCode));
185
185
  const parts = [
186
186
  `import ${routeDefinerName} from '@omer-x/next-openapi-route-handler';`,
187
187
  "import z from 'zod';",
188
188
  middlewareName ? injectMiddlewareFixer(middlewareName) : "",
189
- code2
189
+ code
190
190
  ];
191
191
  return (0, import_typescript.transpile)(parts.join("\n"));
192
192
  }
@@ -205,19 +205,30 @@ async function findAppFolderPath() {
205
205
  }
206
206
  function safeEval(code, routePath) {
207
207
  try {
208
- return eval(code);
208
+ const fn = new Function("global", "require", `
209
+ const module = { exports: {} };
210
+ const exports = module.exports;
211
+
212
+ const NextResponse = { json: () => ({}) };
213
+ const next = { server: { NextResponse } };
214
+
215
+ ${code}
216
+
217
+ return module.exports;
218
+ `);
219
+ return fn(global, require);
209
220
  } catch (error) {
210
221
  console.log(`An error occured while evaluating the route exports from "${routePath}"`);
211
222
  throw error;
212
223
  }
213
224
  }
214
- async function getRouteExports(routePath2, routeDefinerName, schemas) {
215
- const rawCode = await import_promises3.default.readFile(routePath2, "utf-8");
225
+ async function getRouteExports(routePath, routeDefinerName, schemas) {
226
+ const rawCode = await import_promises3.default.readFile(routePath, "utf-8");
216
227
  const middlewareName = detectMiddlewareName(rawCode);
217
- const code2 = transpile(rawCode, routeDefinerName, middlewareName);
218
- const fixedCode = Object.keys(schemas).reduce(injectSchemas, code2);
228
+ const code = transpile(rawCode, routeDefinerName, middlewareName);
229
+ const fixedCode = Object.keys(schemas).reduce(injectSchemas, code);
219
230
  global.schemas = schemas;
220
- const result = safeEval(fixedCode, routePath2);
231
+ const result = safeEval(fixedCode, routePath);
221
232
  delete global.schemas;
222
233
  return result;
223
234
  }
@@ -246,7 +257,7 @@ function verifyOptions(include, exclude) {
246
257
  var import_node_path3 = __toESM(require("path"), 1);
247
258
  function getRoutePathName(filePath, rootPath) {
248
259
  const dirName = import_node_path3.default.dirname(filePath);
249
- import_node_path3.default.relative(rootPath, dirName).replaceAll("[", "{").replaceAll("]", "}").replaceAll("\\", "/").replace(/\([^)]+\)\/|\/\([^)]+\)|\([^)]+\)/g, "");
260
+ return "/" + import_node_path3.default.relative(rootPath, dirName).replaceAll("[", "{").replaceAll("]", "}").replaceAll("\\", "/").replace(/\([^)]+\)\/|\/\([^)]+\)|\([^)]+\)/g, "");
250
261
  }
251
262
 
252
263
  // src/utils/deepEqual.ts
package/dist/index.js CHANGED
@@ -1,3 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/core/generateOpenApiSpec.ts
2
9
  import path4 from "path";
3
10
  import getPackageMetadata from "@omer-x/package-metadata";
@@ -55,7 +62,7 @@ async function getDirectoryItems(dirPath, targetFileName) {
55
62
  const children = await getDirectoryItems(itemPath, targetFileName);
56
63
  collection.push(...children);
57
64
  } else if (itemName === targetFileName) {
58
- collection.push(itemPath);
65
+ collection.push(itemPath.split(path.sep).join("/").replace(/^[A-Z]:/i, ""));
59
66
  }
60
67
  }
61
68
  return collection;
@@ -73,9 +80,9 @@ function filterDirectoryItems(rootPath, items, include, exclude) {
73
80
 
74
81
  // src/core/isDocumentedRoute.ts
75
82
  import fs2 from "fs/promises";
76
- async function isDocumentedRoute(routePath2) {
83
+ async function isDocumentedRoute(routePath) {
77
84
  try {
78
- const rawCode = await fs2.readFile(routePath2, "utf-8");
85
+ const rawCode = await fs2.readFile(routePath, "utf-8");
79
86
  return rawCode.includes("@omer-x/next-openapi-route-handler");
80
87
  } catch {
81
88
  return false;
@@ -92,9 +99,9 @@ function generateRandomString(length) {
92
99
  }
93
100
 
94
101
  // src/utils/string-preservation.ts
95
- function preserveStrings(code2) {
102
+ function preserveStrings(code) {
96
103
  let replacements = {};
97
- const output = code2.replace(/(['"`])((?:\\.|(?!\1).)*)\1/g, (match, quote, content) => {
104
+ const output = code.replace(/(['"`])((?:\\.|(?!\1).)*)\1/g, (match, quote, content) => {
98
105
  const replacementId = generateRandomString(32);
99
106
  replacements = {
100
107
  ...replacements,
@@ -104,22 +111,22 @@ function preserveStrings(code2) {
104
111
  });
105
112
  return { output, replacements };
106
113
  }
107
- function restoreStrings(code2, replacements) {
108
- return code2.replace(/<@~(.*?)~@>/g, (_, replacementId) => {
114
+ function restoreStrings(code, replacements) {
115
+ return code.replace(/<@~(.*?)~@>/g, (_, replacementId) => {
109
116
  return replacements[replacementId];
110
117
  });
111
118
  }
112
119
 
113
120
  // src/core/injectSchemas.ts
114
- function injectSchemas(code2, refName) {
115
- const { output: preservedCode, replacements } = preserveStrings(code2);
121
+ function injectSchemas(code, refName) {
122
+ const { output: preservedCode, replacements } = preserveStrings(code);
116
123
  const preservedCodeWithSchemasInjected = preservedCode.replace(new RegExp(`\\b${refName}\\.`, "g"), `global.schemas[${refName}].`).replace(new RegExp(`\\b${refName}\\b`, "g"), `"${refName}"`).replace(new RegExp(`queryParams:\\s*['"\`]${refName}['"\`]`, "g"), `queryParams: global.schemas["${refName}"]`).replace(new RegExp(`pathParams:\\s*['"\`]${refName}['"\`]`, "g"), `pathParams: global.schemas["${refName}"]`);
117
124
  return restoreStrings(preservedCodeWithSchemasInjected, replacements);
118
125
  }
119
126
 
120
127
  // src/core/middleware.ts
121
- function detectMiddlewareName(code2) {
122
- const match = code2.match(/middleware:\s*(\w+)/);
128
+ function detectMiddlewareName(code) {
129
+ const match = code.match(/middleware:\s*(\w+)/);
123
130
  return match ? match[1] : null;
124
131
  }
125
132
 
@@ -127,30 +134,30 @@ function detectMiddlewareName(code2) {
127
134
  import { transpile as tsTranspile } from "typescript";
128
135
 
129
136
  // src/utils/removeImports.ts
130
- function removeImports(code2) {
131
- return code2.replace(/(^import\s+[^;]+;?$|^import\s+[^;]*\sfrom\s.+;?$)/gm, "").replace(/(^import\s+{[\s\S]+?}\s+from\s+["'][^"']+["'];?)/gm, "").trim();
137
+ function removeImports(code) {
138
+ return code.replace(/(^import\s+[^;]+;?$|^import\s+[^;]*\sfrom\s.+;?$)/gm, "").replace(/(^import\s+{[\s\S]+?}\s+from\s+["'][^"']+["'];?)/gm, "").trim();
132
139
  }
133
140
 
134
141
  // src/core/transpile.ts
135
- function fixExports(code2) {
142
+ function fixExports(code) {
136
143
  const validMethods = ["GET", "POST", "PUT", "PATCH", "DELETE"];
137
144
  const exportFixer1 = validMethods.map((method) => `exports.${method} = void 0;
138
145
  `);
139
146
  const exportFixer2 = `module.exports = { ${validMethods.map((m) => `${m}: exports.${m}`).join(", ")} }`;
140
147
  return `${exportFixer1}
141
- ${code2}
148
+ ${code}
142
149
  ${exportFixer2}`;
143
150
  }
144
151
  function injectMiddlewareFixer(middlewareName) {
145
152
  return `const ${middlewareName} = (handler) => handler;`;
146
153
  }
147
154
  function transpile(rawCode, routeDefinerName, middlewareName) {
148
- const code2 = fixExports(removeImports(rawCode));
155
+ const code = fixExports(removeImports(rawCode));
149
156
  const parts = [
150
157
  `import ${routeDefinerName} from '@omer-x/next-openapi-route-handler';`,
151
158
  "import z from 'zod';",
152
159
  middlewareName ? injectMiddlewareFixer(middlewareName) : "",
153
- code2
160
+ code
154
161
  ];
155
162
  return tsTranspile(parts.join("\n"));
156
163
  }
@@ -169,19 +176,30 @@ async function findAppFolderPath() {
169
176
  }
170
177
  function safeEval(code, routePath) {
171
178
  try {
172
- return eval(code);
179
+ const fn = new Function("global", "require", `
180
+ const module = { exports: {} };
181
+ const exports = module.exports;
182
+
183
+ const NextResponse = { json: () => ({}) };
184
+ const next = { server: { NextResponse } };
185
+
186
+ ${code}
187
+
188
+ return module.exports;
189
+ `);
190
+ return fn(global, __require);
173
191
  } catch (error) {
174
192
  console.log(`An error occured while evaluating the route exports from "${routePath}"`);
175
193
  throw error;
176
194
  }
177
195
  }
178
- async function getRouteExports(routePath2, routeDefinerName, schemas) {
179
- const rawCode = await fs3.readFile(routePath2, "utf-8");
196
+ async function getRouteExports(routePath, routeDefinerName, schemas) {
197
+ const rawCode = await fs3.readFile(routePath, "utf-8");
180
198
  const middlewareName = detectMiddlewareName(rawCode);
181
- const code2 = transpile(rawCode, routeDefinerName, middlewareName);
182
- const fixedCode = Object.keys(schemas).reduce(injectSchemas, code2);
199
+ const code = transpile(rawCode, routeDefinerName, middlewareName);
200
+ const fixedCode = Object.keys(schemas).reduce(injectSchemas, code);
183
201
  global.schemas = schemas;
184
- const result = safeEval(fixedCode, routePath2);
202
+ const result = safeEval(fixedCode, routePath);
185
203
  delete global.schemas;
186
204
  return result;
187
205
  }
@@ -210,7 +228,7 @@ function verifyOptions(include, exclude) {
210
228
  import path3 from "path";
211
229
  function getRoutePathName(filePath, rootPath) {
212
230
  const dirName = path3.dirname(filePath);
213
- path3.relative(rootPath, dirName).replaceAll("[", "{").replaceAll("]", "}").replaceAll("\\", "/").replace(/\([^)]+\)\/|\/\([^)]+\)|\([^)]+\)/g, "");
231
+ return "/" + path3.relative(rootPath, dirName).replaceAll("[", "{").replaceAll("]", "}").replaceAll("\\", "/").replace(/\([^)]+\)\/|\/\([^)]+\)|\([^)]+\)/g, "");
214
232
  }
215
233
 
216
234
  // src/utils/deepEqual.ts
package/package.json CHANGED
@@ -1,62 +1,62 @@
1
- {
2
- "name": "@spikers/next-openapi-json-generator",
3
- "version": "1.0.3",
4
- "description": "a Next.js plugin to generate OpenAPI documentation from route handlers",
5
- "keywords": [
6
- "next.js",
7
- "swagger",
8
- "openapi",
9
- "swagger.json",
10
- "openapi.json",
11
- "generator"
12
- ],
13
- "repository": {
14
- "type": "git",
15
- "url": "git+https://github.com/sqikerz/next-openapi-json-generator.git"
16
- },
17
- "bugs": {
18
- "url": "https://github.com/sqikerz/next-openapi-json-generator/issues"
19
- },
20
- "homepage": "https://github.com/sqikerz/next-openapi-json-generator#readme",
21
- "private": false,
22
- "publishConfig": {
23
- "access": "public"
24
- },
25
- "license": "MIT",
26
- "type": "module",
27
- "files": [
28
- "dist/"
29
- ],
30
- "exports": {
31
- ".": {
32
- "types": "./dist/index.d.ts",
33
- "import": "./dist/index.js",
34
- "require": "./dist/index.cjs"
35
- }
36
- },
37
- "scripts": {
38
- "test": "jest",
39
- "dev": "tsup --watch",
40
- "build": "tsup"
41
- },
42
- "dependencies": {
43
- "@omer-x/package-metadata": "^1.0.2",
44
- "minimatch": "^10.0.1",
45
- "typescript": "^5.7.2",
46
- "zod-to-json-schema": "^3.24.1"
47
- },
48
- "devDependencies": {
49
- "@omer-x/eslint-config": "^2.1.2",
50
- "@types/node": "^22.10.2",
51
- "eslint": "^9.16.0",
52
- "semantic-release": "^24.2.0",
53
- "ts-jest": "^29.2.5",
54
- "ts-node": "^10.9.2",
55
- "tsup": "^8.3.5",
56
- "zod": "^3.24.1"
57
- },
58
- "peerDependencies": {
59
- "@omer-x/next-openapi-route-handler": "^1",
60
- "@omer-x/openapi-types": "^1"
61
- }
62
- }
1
+ {
2
+ "name": "@spikers/next-openapi-json-generator",
3
+ "version": "1.1.0",
4
+ "description": "a Next.js plugin to generate OpenAPI documentation from route handlers",
5
+ "keywords": [
6
+ "next.js",
7
+ "swagger",
8
+ "openapi",
9
+ "swagger.json",
10
+ "openapi.json",
11
+ "generator"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/sqikerz/next-openapi-json-generator.git"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/sqikerz/next-openapi-json-generator/issues"
19
+ },
20
+ "homepage": "https://github.com/sqikerz/next-openapi-json-generator#readme",
21
+ "private": false,
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "license": "MIT",
26
+ "type": "module",
27
+ "files": [
28
+ "dist/"
29
+ ],
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "import": "./dist/index.js",
34
+ "require": "./dist/index.cjs"
35
+ }
36
+ },
37
+ "scripts": {
38
+ "test": "jest",
39
+ "dev": "tsup --watch",
40
+ "build": "tsup"
41
+ },
42
+ "dependencies": {
43
+ "@omer-x/package-metadata": "^1.0.2",
44
+ "minimatch": "^10.0.1",
45
+ "typescript": "^5.7.2",
46
+ "zod-to-json-schema": "^3.24.1"
47
+ },
48
+ "devDependencies": {
49
+ "@omer-x/eslint-config": "^2.1.2",
50
+ "@types/node": "^22.10.2",
51
+ "eslint": "^9.16.0",
52
+ "semantic-release": "^24.2.0",
53
+ "ts-jest": "^29.2.5",
54
+ "ts-node": "^10.9.2",
55
+ "tsup": "^8.3.5",
56
+ "zod": "^3.24.1"
57
+ },
58
+ "peerDependencies": {
59
+ "@omer-x/next-openapi-route-handler": "^1",
60
+ "@omer-x/openapi-types": "^1"
61
+ }
62
+ }