next-openapi-gen 0.7.1 → 0.7.3
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/dist/lib/route-processor.js +2 -6
- package/dist/lib/schema-processor.js +16 -12
- package/dist/lib/utils.js +20 -0
- package/dist/lib/zod-converter.js +19 -17
- package/package.json +1 -1
|
@@ -2,9 +2,8 @@ import * as t from "@babel/types";
|
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import traverse from "@babel/traverse";
|
|
5
|
-
import { parse } from "@babel/parser";
|
|
6
5
|
import { SchemaProcessor } from "./schema-processor.js";
|
|
7
|
-
import { capitalize, extractJSDocComments, extractPathParameters, getOperationId, } from "./utils.js";
|
|
6
|
+
import { capitalize, extractJSDocComments, parseTypeScriptFile, extractPathParameters, getOperationId, } from "./utils.js";
|
|
8
7
|
import { logger } from "./logger.js";
|
|
9
8
|
const HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
10
9
|
const MUTATION_HTTP_METHODS = ["PATCH", "POST", "PUT"];
|
|
@@ -118,10 +117,7 @@ export class RouteProcessor {
|
|
|
118
117
|
if (this.processFileTracker[filePath])
|
|
119
118
|
return;
|
|
120
119
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
121
|
-
const ast =
|
|
122
|
-
sourceType: "module",
|
|
123
|
-
plugins: ["typescript", "decorators-legacy"],
|
|
124
|
-
});
|
|
120
|
+
const ast = parseTypeScriptFile(content);
|
|
125
121
|
traverse.default(ast, {
|
|
126
122
|
ExportNamedDeclaration: (path) => {
|
|
127
123
|
const declaration = path.node.declaration;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { parse } from "@babel/parser";
|
|
4
3
|
import traverse from "@babel/traverse";
|
|
5
4
|
import * as t from "@babel/types";
|
|
5
|
+
import { parseTypeScriptFile } from "./utils.js";
|
|
6
6
|
import { ZodSchemaConverter } from "./zod-converter.js";
|
|
7
7
|
import { logger } from "./logger.js";
|
|
8
8
|
export class SchemaProcessor {
|
|
@@ -167,10 +167,14 @@ export class SchemaProcessor {
|
|
|
167
167
|
const enumValues = this.processEnum(typeNode);
|
|
168
168
|
return enumValues;
|
|
169
169
|
}
|
|
170
|
-
if (t.isTSTypeLiteral(typeNode) ||
|
|
170
|
+
if (t.isTSTypeLiteral(typeNode) ||
|
|
171
|
+
t.isTSInterfaceBody(typeNode) ||
|
|
172
|
+
t.isTSInterfaceDeclaration(typeNode)) {
|
|
171
173
|
const properties = {};
|
|
172
174
|
// Handle interface extends clause
|
|
173
|
-
if (t.isTSInterfaceDeclaration(typeNode) &&
|
|
175
|
+
if (t.isTSInterfaceDeclaration(typeNode) &&
|
|
176
|
+
typeNode.extends &&
|
|
177
|
+
typeNode.extends.length > 0) {
|
|
174
178
|
typeNode.extends.forEach((extendedType) => {
|
|
175
179
|
const extendedSchema = this.resolveTSNodeType(extendedType);
|
|
176
180
|
if (extendedSchema.properties) {
|
|
@@ -179,7 +183,9 @@ export class SchemaProcessor {
|
|
|
179
183
|
});
|
|
180
184
|
}
|
|
181
185
|
// Get members from interface declaration body or direct members
|
|
182
|
-
const members = t.isTSInterfaceDeclaration(typeNode)
|
|
186
|
+
const members = t.isTSInterfaceDeclaration(typeNode)
|
|
187
|
+
? typeNode.body.body
|
|
188
|
+
: typeNode.members;
|
|
183
189
|
if (members) {
|
|
184
190
|
(members || []).forEach((member) => {
|
|
185
191
|
if (t.isTSPropertySignature(member) && t.isIdentifier(member.key)) {
|
|
@@ -270,9 +276,9 @@ export class SchemaProcessor {
|
|
|
270
276
|
if (t.isIdentifier(node.expression)) {
|
|
271
277
|
// Convert to TSTypeReference-like structure for processing
|
|
272
278
|
const syntheticNode = {
|
|
273
|
-
type:
|
|
279
|
+
type: "TSTypeReference",
|
|
274
280
|
typeName: node.expression,
|
|
275
|
-
typeParameters: node.typeParameters
|
|
281
|
+
typeParameters: node.typeParameters,
|
|
276
282
|
};
|
|
277
283
|
return this.resolveTSNodeType(syntheticNode);
|
|
278
284
|
}
|
|
@@ -322,13 +328,14 @@ export class SchemaProcessor {
|
|
|
322
328
|
const properties = {};
|
|
323
329
|
const keyNames = this.extractKeysFromLiteralType(keysParam);
|
|
324
330
|
if (typeName === "Pick") {
|
|
325
|
-
keyNames.forEach(key => {
|
|
331
|
+
keyNames.forEach((key) => {
|
|
326
332
|
if (baseType.properties[key]) {
|
|
327
333
|
properties[key] = baseType.properties[key];
|
|
328
334
|
}
|
|
329
335
|
});
|
|
330
336
|
}
|
|
331
|
-
else {
|
|
337
|
+
else {
|
|
338
|
+
// Omit
|
|
332
339
|
Object.entries(baseType.properties).forEach(([key, value]) => {
|
|
333
340
|
if (!keyNames.includes(key)) {
|
|
334
341
|
properties[key] = value;
|
|
@@ -460,10 +467,7 @@ export class SchemaProcessor {
|
|
|
460
467
|
try {
|
|
461
468
|
// Recognizes different elements of TS like variable, type, interface, enum
|
|
462
469
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
463
|
-
const ast =
|
|
464
|
-
sourceType: "module",
|
|
465
|
-
plugins: ["typescript", "decorators-legacy"],
|
|
466
|
-
});
|
|
470
|
+
const ast = parseTypeScriptFile(content);
|
|
467
471
|
this.collectTypeDefinitions(ast, schemaName);
|
|
468
472
|
// Reset the set of processed types before each schema processing
|
|
469
473
|
this.processingTypes.clear();
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parse } from "@babel/parser";
|
|
1
2
|
export function capitalize(string) {
|
|
2
3
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
3
4
|
}
|
|
@@ -208,3 +209,22 @@ export function getOperationId(routePath, method) {
|
|
|
208
209
|
const operation = routePath.replaceAll(/\//g, "-").replace(/^-/, "");
|
|
209
210
|
return `${method}-${operation}`;
|
|
210
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Common Babel parser configuration for TypeScript files with JSX support
|
|
214
|
+
*/
|
|
215
|
+
const DEFAULT_PARSER_OPTIONS = {
|
|
216
|
+
sourceType: "module",
|
|
217
|
+
plugins: ["typescript", "jsx", "decorators-legacy"],
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Parse TypeScript/TSX file content with the standard configuration
|
|
221
|
+
* @param content - File content to parse
|
|
222
|
+
* @param options - Optional parser options to override defaults
|
|
223
|
+
* @returns Parsed AST
|
|
224
|
+
*/
|
|
225
|
+
export function parseTypeScriptFile(content, options) {
|
|
226
|
+
return parse(content, {
|
|
227
|
+
...DEFAULT_PARSER_OPTIONS,
|
|
228
|
+
...options,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { parse } from "@babel/parser";
|
|
4
3
|
import traverse from "@babel/traverse";
|
|
5
4
|
import * as t from "@babel/types";
|
|
5
|
+
import { parseTypeScriptFile } from "./utils.js";
|
|
6
6
|
import { logger } from "./logger.js";
|
|
7
7
|
/**
|
|
8
8
|
* Class for converting Zod schemas to OpenAPI specifications
|
|
@@ -146,10 +146,7 @@ export class ZodSchemaConverter {
|
|
|
146
146
|
return;
|
|
147
147
|
}
|
|
148
148
|
// Parse the file
|
|
149
|
-
const ast =
|
|
150
|
-
sourceType: "module",
|
|
151
|
-
plugins: ["typescript", "decorators-legacy"],
|
|
152
|
-
});
|
|
149
|
+
const ast = parseTypeScriptFile(content);
|
|
153
150
|
// Create a map to store imported modules
|
|
154
151
|
const importedModules = {};
|
|
155
152
|
// Look for all exported Zod schemas
|
|
@@ -459,10 +456,7 @@ export class ZodSchemaConverter {
|
|
|
459
456
|
processAllSchemasInFile(filePath) {
|
|
460
457
|
try {
|
|
461
458
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
462
|
-
const ast =
|
|
463
|
-
sourceType: "module",
|
|
464
|
-
plugins: ["typescript", "decorators-legacy"],
|
|
465
|
-
});
|
|
459
|
+
const ast = parseTypeScriptFile(content);
|
|
466
460
|
traverse.default(ast, {
|
|
467
461
|
ExportNamedDeclaration: (path) => {
|
|
468
462
|
if (t.isVariableDeclaration(path.node.declaration)) {
|
|
@@ -511,6 +505,20 @@ export class ZodSchemaConverter {
|
|
|
511
505
|
}
|
|
512
506
|
return this.processZodChain(node);
|
|
513
507
|
}
|
|
508
|
+
// Handle z.coerce.TYPE() patterns
|
|
509
|
+
if (t.isCallExpression(node) &&
|
|
510
|
+
t.isMemberExpression(node.callee) &&
|
|
511
|
+
t.isMemberExpression(node.callee.object) &&
|
|
512
|
+
t.isIdentifier(node.callee.object.object) &&
|
|
513
|
+
node.callee.object.object.name === "z" &&
|
|
514
|
+
t.isIdentifier(node.callee.object.property) &&
|
|
515
|
+
node.callee.object.property.name === "coerce" &&
|
|
516
|
+
t.isIdentifier(node.callee.property)) {
|
|
517
|
+
const coerceType = node.callee.property.name;
|
|
518
|
+
// Create a synthetic node for the underlying type using Babel types
|
|
519
|
+
const syntheticNode = t.callExpression(t.memberExpression(t.identifier("z"), t.identifier(coerceType)), []);
|
|
520
|
+
return this.processZodPrimitive(syntheticNode);
|
|
521
|
+
}
|
|
514
522
|
// Handle z.object({...})
|
|
515
523
|
if (t.isCallExpression(node) &&
|
|
516
524
|
t.isMemberExpression(node.callee) &&
|
|
@@ -1329,10 +1337,7 @@ export class ZodSchemaConverter {
|
|
|
1329
1337
|
scanFileForTypeMappings(filePath) {
|
|
1330
1338
|
try {
|
|
1331
1339
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
1332
|
-
const ast =
|
|
1333
|
-
sourceType: "module",
|
|
1334
|
-
plugins: ["typescript", "decorators-legacy"],
|
|
1335
|
-
});
|
|
1340
|
+
const ast = parseTypeScriptFile(content);
|
|
1336
1341
|
traverse.default(ast, {
|
|
1337
1342
|
TSTypeAliasDeclaration: (path) => {
|
|
1338
1343
|
if (t.isIdentifier(path.node.id)) {
|
|
@@ -1399,10 +1404,7 @@ export class ZodSchemaConverter {
|
|
|
1399
1404
|
preprocessAllSchemasInFile(filePath) {
|
|
1400
1405
|
try {
|
|
1401
1406
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
1402
|
-
const ast =
|
|
1403
|
-
sourceType: "module",
|
|
1404
|
-
plugins: ["typescript", "decorators-legacy"],
|
|
1405
|
-
});
|
|
1407
|
+
const ast = parseTypeScriptFile(content);
|
|
1406
1408
|
// Collect all exported Zod schemas
|
|
1407
1409
|
traverse.default(ast, {
|
|
1408
1410
|
ExportNamedDeclaration: (path) => {
|
package/package.json
CHANGED