next-openapi-gen 0.10.4 → 1.0.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.
Files changed (44) hide show
  1. package/dist/cli.d.ts +4 -0
  2. package/dist/cli.js +8599 -0
  3. package/dist/index.d.ts +18 -0
  4. package/dist/index.js +8645 -26
  5. package/dist/next/index.d.ts +1 -0
  6. package/dist/next/index.js +7965 -0
  7. package/dist/react-router/index.d.ts +1 -0
  8. package/dist/react-router/index.js +7134 -0
  9. package/dist/vite/index.d.ts +1 -0
  10. package/dist/vite/index.js +7134 -0
  11. package/package.json +102 -79
  12. package/{dist/components/rapidoc.js → templates/init/ui/nextjs/rapidoc.tsx} +16 -20
  13. package/templates/init/ui/nextjs/redoc.tsx +11 -0
  14. package/{dist/components/scalar.js → templates/init/ui/nextjs/scalar.tsx} +15 -21
  15. package/{dist/components/stoplight.js → templates/init/ui/nextjs/stoplight.tsx} +11 -17
  16. package/templates/init/ui/nextjs/swagger.tsx +17 -0
  17. package/templates/init/ui/reactrouter/rapidoc.tsx +15 -0
  18. package/templates/init/ui/reactrouter/redoc.tsx +9 -0
  19. package/templates/init/ui/reactrouter/scalar.tsx +14 -0
  20. package/templates/init/ui/reactrouter/stoplight.tsx +10 -0
  21. package/templates/init/ui/reactrouter/swagger.tsx +11 -0
  22. package/templates/init/ui/tanstack/rapidoc.tsx +21 -0
  23. package/templates/init/ui/tanstack/redoc.tsx +14 -0
  24. package/templates/init/ui/tanstack/scalar.tsx +19 -0
  25. package/templates/init/ui/tanstack/stoplight.tsx +15 -0
  26. package/templates/init/ui/tanstack/swagger.tsx +16 -0
  27. package/templates/init/ui/template-types.d.ts +9 -0
  28. package/README.md +0 -1047
  29. package/dist/commands/generate.js +0 -24
  30. package/dist/commands/init.js +0 -194
  31. package/dist/components/redoc.js +0 -17
  32. package/dist/components/swagger.js +0 -21
  33. package/dist/lib/app-router-strategy.js +0 -66
  34. package/dist/lib/drizzle-zod-processor.js +0 -329
  35. package/dist/lib/logger.js +0 -39
  36. package/dist/lib/openapi-generator.js +0 -171
  37. package/dist/lib/pages-router-strategy.js +0 -198
  38. package/dist/lib/route-processor.js +0 -347
  39. package/dist/lib/router-strategy.js +0 -1
  40. package/dist/lib/schema-processor.js +0 -1612
  41. package/dist/lib/utils.js +0 -284
  42. package/dist/lib/zod-converter.js +0 -2133
  43. package/dist/openapi-template.js +0 -99
  44. package/dist/types.js +0 -1
package/dist/lib/utils.js DELETED
@@ -1,284 +0,0 @@
1
- import { parse } from "@babel/parser";
2
- export function capitalize(string) {
3
- return string.charAt(0).toUpperCase() + string.slice(1);
4
- }
5
- /**
6
- * Extract path parameters from a route path
7
- * e.g. /users/{id}/posts/{postId} -> ['id', 'postId']
8
- */
9
- export function extractPathParameters(routePath) {
10
- const paramRegex = /{([^}]+)}/g;
11
- const params = [];
12
- let match;
13
- while ((match = paramRegex.exec(routePath)) !== null) {
14
- params.push(match[1]);
15
- }
16
- return params;
17
- }
18
- export function extractJSDocComments(path) {
19
- const comments = path.node.leadingComments;
20
- let tag = "";
21
- let summary = "";
22
- let description = "";
23
- let paramsType = "";
24
- let pathParamsType = "";
25
- let bodyType = "";
26
- let auth = "";
27
- let isOpenApi = false;
28
- let isIgnored = false;
29
- let deprecated = false;
30
- let bodyDescription = "";
31
- let contentType = "";
32
- let responseType = "";
33
- let responseDescription = "";
34
- let responseSet = "";
35
- let addResponses = "";
36
- let successCode = "";
37
- let operationId = "";
38
- let method = "";
39
- if (comments) {
40
- comments.forEach((comment) => {
41
- const commentValue = cleanComment(comment.value);
42
- isOpenApi = commentValue.includes("@openapi");
43
- if (commentValue.includes("@ignore")) {
44
- isIgnored = true;
45
- }
46
- if (commentValue.includes("@deprecated")) {
47
- deprecated = true;
48
- }
49
- if (commentValue.includes("@bodyDescription")) {
50
- const regex = /@bodyDescription\s*(.*)/;
51
- const match = commentValue.match(regex);
52
- if (match && match[1]) {
53
- bodyDescription = match[1].trim();
54
- }
55
- }
56
- if (!summary) {
57
- const firstLine = commentValue.split("\n")[0];
58
- // Don't use tags as summary - only use actual descriptions
59
- if (!firstLine.trim().startsWith("@")) {
60
- summary = firstLine;
61
- }
62
- }
63
- if (commentValue.includes("@auth")) {
64
- const regex = /@auth\s*(.*)/;
65
- const value = commentValue.match(regex)[1].trim();
66
- switch (value) {
67
- case "bearer":
68
- auth = "BearerAuth";
69
- break;
70
- case "basic":
71
- auth = "BasicAuth";
72
- break;
73
- case "apikey":
74
- auth = "ApiKeyAuth";
75
- break;
76
- default:
77
- auth = performAuthPresetReplacements(value);
78
- }
79
- }
80
- if (commentValue.includes("@description")) {
81
- const regex = /@description\s*(.*)/;
82
- description = commentValue.match(regex)[1].trim();
83
- }
84
- if (commentValue.includes("@tag")) {
85
- const regex = /@tag\s*(.*)/;
86
- const match = commentValue.match(regex);
87
- if (match && match[1]) {
88
- tag = match[1].trim();
89
- }
90
- }
91
- if (commentValue.includes("@params") || commentValue.includes("@queryParams")) {
92
- paramsType = extractTypeFromComment(commentValue, "@queryParams") ||
93
- extractTypeFromComment(commentValue, "@params");
94
- }
95
- if (commentValue.includes("@pathParams")) {
96
- pathParamsType = extractTypeFromComment(commentValue, "@pathParams");
97
- }
98
- if (commentValue.includes("@body")) {
99
- bodyType = extractTypeFromComment(commentValue, "@body");
100
- }
101
- if (commentValue.includes("@response")) {
102
- responseType = extractTypeFromComment(commentValue, "@response");
103
- }
104
- if (commentValue.includes("@contentType")) {
105
- const regex = /@contentType\s*(.*)/;
106
- const match = commentValue.match(regex);
107
- if (match && match[1]) {
108
- contentType = match[1].trim();
109
- }
110
- }
111
- if (commentValue.includes("@responseDescription")) {
112
- const regex = /@responseDescription\s*(.*)/;
113
- const match = commentValue.match(regex);
114
- if (match && match[1]) {
115
- responseDescription = match[1].trim();
116
- }
117
- }
118
- if (commentValue.includes("@responseSet")) {
119
- const regex = /@responseSet\s*(.*)/;
120
- const match = commentValue.match(regex);
121
- if (match && match[1]) {
122
- responseSet = match[1].trim();
123
- }
124
- }
125
- if (commentValue.includes("@add")) {
126
- const regex = /@add\s*(.*)/;
127
- const match = commentValue.match(regex);
128
- if (match && match[1]) {
129
- addResponses = match[1].trim();
130
- }
131
- }
132
- if (commentValue.includes("@operationId")) {
133
- const regex = /@operationId\s+(\S+)/;
134
- const match = commentValue.match(regex);
135
- if (match && match[1]) {
136
- operationId = match[1].trim();
137
- }
138
- }
139
- if (commentValue.includes("@method")) {
140
- const regex = /@method\s+(\S+)/;
141
- const match = commentValue.match(regex);
142
- if (match && match[1]) {
143
- method = match[1].trim().toUpperCase();
144
- }
145
- }
146
- if (commentValue.includes("@response")) {
147
- // Updated regex to support generic types
148
- const responseMatch = commentValue.match(/@response\s+(?:(\d+):)?([^@\n\r]+)(?:\s+(.*))?/);
149
- if (responseMatch) {
150
- const [, code, type] = responseMatch;
151
- const trimmedType = type?.trim();
152
- // Check if the type is just a status code (e.g., "@response 204")
153
- if (!code && trimmedType && /^\d{3}$/.test(trimmedType)) {
154
- // Type is actually a status code without a schema
155
- successCode = trimmedType;
156
- responseType = undefined;
157
- }
158
- else {
159
- successCode = code || "";
160
- responseType = trimmedType;
161
- }
162
- }
163
- else {
164
- responseType = extractTypeFromComment(commentValue, "@response");
165
- }
166
- }
167
- });
168
- }
169
- return {
170
- tag,
171
- auth,
172
- summary,
173
- description,
174
- paramsType,
175
- pathParamsType,
176
- bodyType,
177
- isOpenApi,
178
- isIgnored,
179
- deprecated,
180
- bodyDescription,
181
- contentType,
182
- responseType,
183
- responseDescription,
184
- responseSet,
185
- addResponses,
186
- successCode,
187
- operationId,
188
- method,
189
- };
190
- }
191
- export function extractTypeFromComment(commentValue, tag) {
192
- // Updated regex to support generic types with angle brackets and array brackets
193
- // Use multiline mode (m flag) to match tag at start of line (after optional * from JSDoc)
194
- return (commentValue
195
- .match(new RegExp(`^\\s*\\*?\\s*${tag}\\s+([\\w<>,\\s\\[\\]]+)`, 'm'))?.[1]
196
- ?.trim() || "");
197
- }
198
- export function cleanComment(commentValue) {
199
- return commentValue.replace(/\*\s*/g, "").trim();
200
- }
201
- export function cleanSpec(spec) {
202
- const propsToRemove = [
203
- "apiDir",
204
- "routerType",
205
- "schemaDir",
206
- "docsUrl",
207
- "ui",
208
- "outputFile",
209
- "includeOpenApiRoutes",
210
- "ignoreRoutes",
211
- "schemaType",
212
- "defaultResponseSet",
213
- "responseSets",
214
- "errorConfig",
215
- "debug",
216
- "schemaFiles",
217
- "outputDir",
218
- ];
219
- const newSpec = { ...spec };
220
- propsToRemove.forEach((key) => delete newSpec[key]);
221
- // Process paths to ensure good examples for path parameters
222
- if (newSpec.paths) {
223
- Object.keys(newSpec.paths).forEach((path) => {
224
- // Check if path contains parameters
225
- if (path.includes("{") && path.includes("}")) {
226
- // For each HTTP method in this path
227
- Object.keys(newSpec.paths[path]).forEach((method) => {
228
- const operation = newSpec.paths[path][method];
229
- // Set example properties for each path parameter
230
- if (operation.parameters) {
231
- operation.parameters.forEach((param) => {
232
- if (param.in === "path" && !param.example) {
233
- // Generate an example based on parameter name
234
- if (param.name === "id" || param.name.endsWith("Id")) {
235
- param.example = 123;
236
- }
237
- else if (param.name === "slug") {
238
- param.example = "example-slug";
239
- }
240
- else {
241
- param.example = "example";
242
- }
243
- }
244
- });
245
- }
246
- });
247
- }
248
- });
249
- }
250
- return newSpec;
251
- }
252
- const AUTH_PRESET_REPLACEMENTS = {
253
- bearer: "BearerAuth",
254
- basic: "BasicAuth",
255
- apikey: "ApiKeyAuth",
256
- };
257
- export function performAuthPresetReplacements(authValue) {
258
- const authParts = authValue.split(",").map((part) => part.trim());
259
- const mappedParts = authParts.map((part) => AUTH_PRESET_REPLACEMENTS[part.toLowerCase()] || part);
260
- return mappedParts.join(",");
261
- }
262
- export function getOperationId(routePath, method) {
263
- const operation = routePath.replaceAll(/\//g, "-").replace(/^-/, "");
264
- return `${method}-${operation}`;
265
- }
266
- /**
267
- * Common Babel parser configuration for TypeScript files with JSX support
268
- */
269
- const DEFAULT_PARSER_OPTIONS = {
270
- sourceType: "module",
271
- plugins: ["typescript", "jsx", "decorators-legacy"],
272
- };
273
- /**
274
- * Parse TypeScript/TSX file content with the standard configuration
275
- * @param content - File content to parse
276
- * @param options - Optional parser options to override defaults
277
- * @returns Parsed AST
278
- */
279
- export function parseTypeScriptFile(content, options) {
280
- return parse(content, {
281
- ...DEFAULT_PARSER_OPTIONS,
282
- ...options,
283
- });
284
- }