@cerios/openapi-to-zod 0.1.2 → 0.3.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 +112 -114
- package/dist/cli.js +5312 -192
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +5289 -197
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +30 -20
- package/dist/index.d.ts +30 -20
- package/dist/index.js +192 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +193 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
package/dist/index.d.mts
CHANGED
|
@@ -63,11 +63,9 @@ type TypeMode = "inferred" | "native";
|
|
|
63
63
|
*/
|
|
64
64
|
type NativeEnumType = "union" | "enum";
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
67
|
-
* These options override root-level options when specified.
|
|
68
|
-
* Resolution order: root options → request/response overrides (nested wins silently)
|
|
66
|
+
* Common options shared by both request and response contexts
|
|
69
67
|
*/
|
|
70
|
-
interface
|
|
68
|
+
interface CommonSchemaOptions {
|
|
71
69
|
/**
|
|
72
70
|
* Object validation mode
|
|
73
71
|
* - 'strict': Uses z.strictObject() - no additional properties allowed
|
|
@@ -90,10 +88,16 @@ interface RequestResponseOptions {
|
|
|
90
88
|
* Whether to include descriptions as JSDoc comments
|
|
91
89
|
*/
|
|
92
90
|
includeDescriptions?: boolean;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Request-specific options that can override root-level options
|
|
94
|
+
* Requests support native TypeScript type generation as an alternative to Zod schemas
|
|
95
|
+
*/
|
|
96
|
+
interface RequestOptions extends CommonSchemaOptions {
|
|
93
97
|
/**
|
|
94
|
-
* Type generation mode
|
|
98
|
+
* Type generation mode
|
|
95
99
|
* - 'inferred': Generate Zod schemas with z.infer types (default)
|
|
96
|
-
* - 'native': Generate native TypeScript types
|
|
100
|
+
* - 'native': Generate native TypeScript types without Zod validation
|
|
97
101
|
*/
|
|
98
102
|
typeMode?: TypeMode;
|
|
99
103
|
/**
|
|
@@ -103,6 +107,12 @@ interface RequestResponseOptions {
|
|
|
103
107
|
*/
|
|
104
108
|
nativeEnumType?: NativeEnumType;
|
|
105
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Response-specific options that can override root-level options
|
|
112
|
+
* Responses always use Zod schemas for runtime validation
|
|
113
|
+
*/
|
|
114
|
+
interface ResponseOptions extends CommonSchemaOptions {
|
|
115
|
+
}
|
|
106
116
|
interface GeneratorOptions {
|
|
107
117
|
/**
|
|
108
118
|
* Object validation mode
|
|
@@ -168,13 +178,15 @@ interface GeneratorOptions {
|
|
|
168
178
|
/**
|
|
169
179
|
* Request-specific options that override root-level options
|
|
170
180
|
* Applied when schemas are used in request contexts
|
|
181
|
+
* Supports native TypeScript type generation
|
|
171
182
|
*/
|
|
172
|
-
request?:
|
|
183
|
+
request?: RequestOptions;
|
|
173
184
|
/**
|
|
174
185
|
* Response-specific options that override root-level options
|
|
175
186
|
* Applied when schemas are used in response contexts
|
|
187
|
+
* Always generates Zod schemas for runtime validation
|
|
176
188
|
*/
|
|
177
|
-
response?:
|
|
189
|
+
response?: ResponseOptions;
|
|
178
190
|
}
|
|
179
191
|
interface OpenAPISchema {
|
|
180
192
|
type?: string | string[];
|
|
@@ -243,16 +255,6 @@ interface OpenAPISpec {
|
|
|
243
255
|
* - 'sequential': Process specs one at a time (safer for resource constraints)
|
|
244
256
|
*/
|
|
245
257
|
type ExecutionMode = "parallel" | "sequential";
|
|
246
|
-
/**
|
|
247
|
-
* Configuration for a single OpenAPI spec
|
|
248
|
-
* Extends GeneratorOptions with all the same properties
|
|
249
|
-
*/
|
|
250
|
-
interface SpecConfig extends GeneratorOptions {
|
|
251
|
-
/**
|
|
252
|
-
* Optional name/identifier for this spec (for logging purposes)
|
|
253
|
-
*/
|
|
254
|
-
name?: string;
|
|
255
|
-
}
|
|
256
258
|
/**
|
|
257
259
|
* Root configuration file structure
|
|
258
260
|
*/
|
|
@@ -266,7 +268,7 @@ interface ConfigFile {
|
|
|
266
268
|
* Array of OpenAPI specifications to process
|
|
267
269
|
* Each spec must have input and output paths
|
|
268
270
|
*/
|
|
269
|
-
specs:
|
|
271
|
+
specs: GeneratorOptions[];
|
|
270
272
|
/**
|
|
271
273
|
* Execution mode for batch processing
|
|
272
274
|
* @default "parallel"
|
|
@@ -371,6 +373,14 @@ declare class ZodSchemaGenerator {
|
|
|
371
373
|
* Generate schema for a component
|
|
372
374
|
*/
|
|
373
375
|
private generateComponentSchema;
|
|
376
|
+
/**
|
|
377
|
+
* Generate query parameter schemas for each operation
|
|
378
|
+
*/
|
|
379
|
+
private generateQueryParameterSchemas;
|
|
380
|
+
/**
|
|
381
|
+
* Generate Zod type for a query parameter schema
|
|
382
|
+
*/
|
|
383
|
+
private generateQueryParamType;
|
|
374
384
|
/**
|
|
375
385
|
* Generate native TypeScript enum
|
|
376
386
|
*/
|
|
@@ -402,4 +412,4 @@ declare class ZodSchemaGenerator {
|
|
|
402
412
|
private generateStats;
|
|
403
413
|
}
|
|
404
414
|
|
|
405
|
-
export { CircularReferenceError, CliOptionsError, type ConfigFile, ConfigValidationError, type ExecutionMode, FileOperationError, GeneratorError, type GeneratorOptions, type OpenAPISpec, SchemaGenerationError,
|
|
415
|
+
export { CircularReferenceError, CliOptionsError, type ConfigFile, ConfigValidationError, type ExecutionMode, FileOperationError, GeneratorError, type GeneratorOptions, type OpenAPISpec, SchemaGenerationError, SpecValidationError, ZodSchemaGenerator, defineConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -63,11 +63,9 @@ type TypeMode = "inferred" | "native";
|
|
|
63
63
|
*/
|
|
64
64
|
type NativeEnumType = "union" | "enum";
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
67
|
-
* These options override root-level options when specified.
|
|
68
|
-
* Resolution order: root options → request/response overrides (nested wins silently)
|
|
66
|
+
* Common options shared by both request and response contexts
|
|
69
67
|
*/
|
|
70
|
-
interface
|
|
68
|
+
interface CommonSchemaOptions {
|
|
71
69
|
/**
|
|
72
70
|
* Object validation mode
|
|
73
71
|
* - 'strict': Uses z.strictObject() - no additional properties allowed
|
|
@@ -90,10 +88,16 @@ interface RequestResponseOptions {
|
|
|
90
88
|
* Whether to include descriptions as JSDoc comments
|
|
91
89
|
*/
|
|
92
90
|
includeDescriptions?: boolean;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Request-specific options that can override root-level options
|
|
94
|
+
* Requests support native TypeScript type generation as an alternative to Zod schemas
|
|
95
|
+
*/
|
|
96
|
+
interface RequestOptions extends CommonSchemaOptions {
|
|
93
97
|
/**
|
|
94
|
-
* Type generation mode
|
|
98
|
+
* Type generation mode
|
|
95
99
|
* - 'inferred': Generate Zod schemas with z.infer types (default)
|
|
96
|
-
* - 'native': Generate native TypeScript types
|
|
100
|
+
* - 'native': Generate native TypeScript types without Zod validation
|
|
97
101
|
*/
|
|
98
102
|
typeMode?: TypeMode;
|
|
99
103
|
/**
|
|
@@ -103,6 +107,12 @@ interface RequestResponseOptions {
|
|
|
103
107
|
*/
|
|
104
108
|
nativeEnumType?: NativeEnumType;
|
|
105
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Response-specific options that can override root-level options
|
|
112
|
+
* Responses always use Zod schemas for runtime validation
|
|
113
|
+
*/
|
|
114
|
+
interface ResponseOptions extends CommonSchemaOptions {
|
|
115
|
+
}
|
|
106
116
|
interface GeneratorOptions {
|
|
107
117
|
/**
|
|
108
118
|
* Object validation mode
|
|
@@ -168,13 +178,15 @@ interface GeneratorOptions {
|
|
|
168
178
|
/**
|
|
169
179
|
* Request-specific options that override root-level options
|
|
170
180
|
* Applied when schemas are used in request contexts
|
|
181
|
+
* Supports native TypeScript type generation
|
|
171
182
|
*/
|
|
172
|
-
request?:
|
|
183
|
+
request?: RequestOptions;
|
|
173
184
|
/**
|
|
174
185
|
* Response-specific options that override root-level options
|
|
175
186
|
* Applied when schemas are used in response contexts
|
|
187
|
+
* Always generates Zod schemas for runtime validation
|
|
176
188
|
*/
|
|
177
|
-
response?:
|
|
189
|
+
response?: ResponseOptions;
|
|
178
190
|
}
|
|
179
191
|
interface OpenAPISchema {
|
|
180
192
|
type?: string | string[];
|
|
@@ -243,16 +255,6 @@ interface OpenAPISpec {
|
|
|
243
255
|
* - 'sequential': Process specs one at a time (safer for resource constraints)
|
|
244
256
|
*/
|
|
245
257
|
type ExecutionMode = "parallel" | "sequential";
|
|
246
|
-
/**
|
|
247
|
-
* Configuration for a single OpenAPI spec
|
|
248
|
-
* Extends GeneratorOptions with all the same properties
|
|
249
|
-
*/
|
|
250
|
-
interface SpecConfig extends GeneratorOptions {
|
|
251
|
-
/**
|
|
252
|
-
* Optional name/identifier for this spec (for logging purposes)
|
|
253
|
-
*/
|
|
254
|
-
name?: string;
|
|
255
|
-
}
|
|
256
258
|
/**
|
|
257
259
|
* Root configuration file structure
|
|
258
260
|
*/
|
|
@@ -266,7 +268,7 @@ interface ConfigFile {
|
|
|
266
268
|
* Array of OpenAPI specifications to process
|
|
267
269
|
* Each spec must have input and output paths
|
|
268
270
|
*/
|
|
269
|
-
specs:
|
|
271
|
+
specs: GeneratorOptions[];
|
|
270
272
|
/**
|
|
271
273
|
* Execution mode for batch processing
|
|
272
274
|
* @default "parallel"
|
|
@@ -371,6 +373,14 @@ declare class ZodSchemaGenerator {
|
|
|
371
373
|
* Generate schema for a component
|
|
372
374
|
*/
|
|
373
375
|
private generateComponentSchema;
|
|
376
|
+
/**
|
|
377
|
+
* Generate query parameter schemas for each operation
|
|
378
|
+
*/
|
|
379
|
+
private generateQueryParameterSchemas;
|
|
380
|
+
/**
|
|
381
|
+
* Generate Zod type for a query parameter schema
|
|
382
|
+
*/
|
|
383
|
+
private generateQueryParamType;
|
|
374
384
|
/**
|
|
375
385
|
* Generate native TypeScript enum
|
|
376
386
|
*/
|
|
@@ -402,4 +412,4 @@ declare class ZodSchemaGenerator {
|
|
|
402
412
|
private generateStats;
|
|
403
413
|
}
|
|
404
414
|
|
|
405
|
-
export { CircularReferenceError, CliOptionsError, type ConfigFile, ConfigValidationError, type ExecutionMode, FileOperationError, GeneratorError, type GeneratorOptions, type OpenAPISpec, SchemaGenerationError,
|
|
415
|
+
export { CircularReferenceError, CliOptionsError, type ConfigFile, ConfigValidationError, type ExecutionMode, FileOperationError, GeneratorError, type GeneratorOptions, type OpenAPISpec, SchemaGenerationError, SpecValidationError, ZodSchemaGenerator, defineConfig };
|
package/dist/index.js
CHANGED
|
@@ -147,7 +147,7 @@ function generateEnum(name, values, options) {
|
|
|
147
147
|
const enumCode = `export enum ${enumName} {
|
|
148
148
|
${enumEntries}
|
|
149
149
|
}`;
|
|
150
|
-
const schemaCode2 = `export const ${schemaName} = z.
|
|
150
|
+
const schemaCode2 = `export const ${schemaName} = z.nativeEnum(${enumName});`;
|
|
151
151
|
const typeCode2 = `export type ${name} = z.infer<typeof ${schemaName}>;`;
|
|
152
152
|
return { enumCode, schemaCode: schemaCode2, typeCode: typeCode2 };
|
|
153
153
|
}
|
|
@@ -330,20 +330,20 @@ function generateArrayValidation(schema, context) {
|
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
// src/validators/composition-validator.ts
|
|
333
|
-
function generateUnion(schemas, discriminator, isNullable2, context, options) {
|
|
333
|
+
function generateUnion(schemas, discriminator, isNullable2, context, options, currentSchema) {
|
|
334
334
|
if (discriminator) {
|
|
335
335
|
let resolvedSchemas = schemas;
|
|
336
336
|
if ((options == null ? void 0 : options.discriminatorMapping) && context.resolveDiscriminatorMapping) {
|
|
337
337
|
resolvedSchemas = context.resolveDiscriminatorMapping(options.discriminatorMapping, schemas);
|
|
338
338
|
}
|
|
339
|
-
let schemaStrings2 = resolvedSchemas.map((s) => context.generatePropertySchema(s));
|
|
339
|
+
let schemaStrings2 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema));
|
|
340
340
|
if (options == null ? void 0 : options.passthrough) {
|
|
341
341
|
schemaStrings2 = schemaStrings2.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
|
|
342
342
|
}
|
|
343
343
|
const union2 = `z.discriminatedUnion("${discriminator}", [${schemaStrings2.join(", ")}])`;
|
|
344
344
|
return wrapNullable(union2, isNullable2);
|
|
345
345
|
}
|
|
346
|
-
let schemaStrings = schemas.map((s) => context.generatePropertySchema(s));
|
|
346
|
+
let schemaStrings = schemas.map((s) => context.generatePropertySchema(s, currentSchema));
|
|
347
347
|
if (options == null ? void 0 : options.passthrough) {
|
|
348
348
|
schemaStrings = schemaStrings.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
|
|
349
349
|
}
|
|
@@ -1176,7 +1176,8 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1176
1176
|
{
|
|
1177
1177
|
passthrough: needsPassthrough,
|
|
1178
1178
|
discriminatorMapping: (_c = schema.discriminator) == null ? void 0 : _c.mapping
|
|
1179
|
-
}
|
|
1179
|
+
},
|
|
1180
|
+
currentSchema
|
|
1180
1181
|
);
|
|
1181
1182
|
if (schema.unevaluatedProperties !== void 0) {
|
|
1182
1183
|
composition = this.applyUnevaluatedProperties(composition, schema);
|
|
@@ -1196,7 +1197,8 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1196
1197
|
{
|
|
1197
1198
|
passthrough: needsPassthrough,
|
|
1198
1199
|
discriminatorMapping: (_e = schema.discriminator) == null ? void 0 : _e.mapping
|
|
1199
|
-
}
|
|
1200
|
+
},
|
|
1201
|
+
currentSchema
|
|
1200
1202
|
);
|
|
1201
1203
|
if (schema.unevaluatedProperties !== void 0) {
|
|
1202
1204
|
composition = this.applyUnevaluatedProperties(composition, schema);
|
|
@@ -1367,10 +1369,13 @@ var ZodSchemaGenerator = class {
|
|
|
1367
1369
|
}
|
|
1368
1370
|
for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
|
|
1369
1371
|
if (schema.enum) {
|
|
1370
|
-
const
|
|
1371
|
-
|
|
1372
|
+
const context = this.schemaUsageMap.get(name);
|
|
1373
|
+
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
1374
|
+
if (resolvedOptions.enumType === "typescript") {
|
|
1375
|
+
this.generateNativeEnum(name, schema);
|
|
1376
|
+
} else {
|
|
1372
1377
|
const { enumCode } = generateEnum(name, schema.enum, {
|
|
1373
|
-
enumType:
|
|
1378
|
+
enumType: "zod",
|
|
1374
1379
|
prefix: this.options.prefix,
|
|
1375
1380
|
suffix: this.options.suffix
|
|
1376
1381
|
});
|
|
@@ -1378,14 +1383,13 @@ var ZodSchemaGenerator = class {
|
|
|
1378
1383
|
this.enums.set(name, enumCode);
|
|
1379
1384
|
this.needsZodImport = true;
|
|
1380
1385
|
}
|
|
1381
|
-
} else {
|
|
1382
|
-
this.generateNativeEnum(name, schema);
|
|
1383
1386
|
}
|
|
1384
1387
|
}
|
|
1385
1388
|
}
|
|
1386
1389
|
for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
|
|
1387
1390
|
this.generateComponentSchema(name, schema);
|
|
1388
1391
|
}
|
|
1392
|
+
this.generateQueryParameterSchemas();
|
|
1389
1393
|
const orderedSchemaNames = this.topologicalSort();
|
|
1390
1394
|
const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
|
|
1391
1395
|
if (this.options.showStats === true) {
|
|
@@ -1396,12 +1400,8 @@ var ZodSchemaGenerator = class {
|
|
|
1396
1400
|
output.push('import { z } from "zod";');
|
|
1397
1401
|
output.push("");
|
|
1398
1402
|
}
|
|
1399
|
-
if (this.
|
|
1400
|
-
output.push("// Enums");
|
|
1401
|
-
for (const enumCode of this.enums.values()) {
|
|
1402
|
-
output.push(enumCode);
|
|
1403
|
-
output.push("");
|
|
1404
|
-
}
|
|
1403
|
+
if (this.nativeEnums.size > 0) {
|
|
1404
|
+
output.push("// Native Enums");
|
|
1405
1405
|
for (const enumCode of this.nativeEnums.values()) {
|
|
1406
1406
|
output.push(enumCode);
|
|
1407
1407
|
output.push("");
|
|
@@ -1409,9 +1409,13 @@ var ZodSchemaGenerator = class {
|
|
|
1409
1409
|
}
|
|
1410
1410
|
output.push("// Schemas and Types");
|
|
1411
1411
|
for (const name of orderedSchemaNames) {
|
|
1412
|
+
const enumCode = this.enums.get(name);
|
|
1412
1413
|
const schemaCode = this.schemas.get(name);
|
|
1413
1414
|
const typeCode = this.types.get(name);
|
|
1414
|
-
if (
|
|
1415
|
+
if (enumCode) {
|
|
1416
|
+
output.push(enumCode);
|
|
1417
|
+
output.push("");
|
|
1418
|
+
} else if (schemaCode) {
|
|
1415
1419
|
output.push(schemaCode);
|
|
1416
1420
|
if (!schemaCode.includes(`export type ${name}`)) {
|
|
1417
1421
|
const schemaName = `${toCamelCase(name, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
|
|
@@ -1429,7 +1433,8 @@ var ZodSchemaGenerator = class {
|
|
|
1429
1433
|
* Ensure directory exists for a file path
|
|
1430
1434
|
*/
|
|
1431
1435
|
ensureDirectoryExists(filePath) {
|
|
1432
|
-
const
|
|
1436
|
+
const normalizedPath = (0, import_node_path.normalize)(filePath);
|
|
1437
|
+
const dir = (0, import_node_path.dirname)(normalizedPath);
|
|
1433
1438
|
if (!(0, import_node_fs.existsSync)(dir)) {
|
|
1434
1439
|
(0, import_node_fs.mkdirSync)(dir, { recursive: true });
|
|
1435
1440
|
}
|
|
@@ -1445,8 +1450,9 @@ var ZodSchemaGenerator = class {
|
|
|
1445
1450
|
);
|
|
1446
1451
|
}
|
|
1447
1452
|
const output = this.generateString();
|
|
1448
|
-
|
|
1449
|
-
|
|
1453
|
+
const normalizedOutput = (0, import_node_path.normalize)(this.options.output);
|
|
1454
|
+
this.ensureDirectoryExists(normalizedOutput);
|
|
1455
|
+
(0, import_node_fs.writeFileSync)(normalizedOutput, output);
|
|
1450
1456
|
}
|
|
1451
1457
|
/**
|
|
1452
1458
|
* Resolve options for a specific context (request or response)
|
|
@@ -1454,17 +1460,18 @@ var ZodSchemaGenerator = class {
|
|
|
1454
1460
|
* Response schemas always use 'inferred' mode (Zod schemas)
|
|
1455
1461
|
*/
|
|
1456
1462
|
resolveOptionsForContext(context) {
|
|
1457
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
1463
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
1458
1464
|
const contextOptions = context === "request" ? this.options.request : this.options.response;
|
|
1465
|
+
const nativeEnumType = context === "request" ? (_c = (_b = (_a = this.options.request) == null ? void 0 : _a.nativeEnumType) != null ? _b : this.options.nativeEnumType) != null ? _c : "union" : (_d = this.options.nativeEnumType) != null ? _d : "union";
|
|
1459
1466
|
return {
|
|
1460
|
-
mode: (
|
|
1461
|
-
enumType: (
|
|
1462
|
-
useDescribe: (
|
|
1463
|
-
includeDescriptions: (
|
|
1467
|
+
mode: (_f = (_e = contextOptions == null ? void 0 : contextOptions.mode) != null ? _e : this.options.mode) != null ? _f : "normal",
|
|
1468
|
+
enumType: (_h = (_g = contextOptions == null ? void 0 : contextOptions.enumType) != null ? _g : this.options.enumType) != null ? _h : "zod",
|
|
1469
|
+
useDescribe: (_j = (_i = contextOptions == null ? void 0 : contextOptions.useDescribe) != null ? _i : this.options.useDescribe) != null ? _j : false,
|
|
1470
|
+
includeDescriptions: (_l = (_k = contextOptions == null ? void 0 : contextOptions.includeDescriptions) != null ? _k : this.options.includeDescriptions) != null ? _l : true,
|
|
1464
1471
|
// Response schemas always use 'inferred' mode (Zod schemas are required)
|
|
1465
1472
|
// Request schemas can optionally use 'native' mode
|
|
1466
|
-
typeMode: context === "response" ? "inferred" : (
|
|
1467
|
-
nativeEnumType
|
|
1473
|
+
typeMode: context === "response" ? "inferred" : (_n = (_m = this.options.request) == null ? void 0 : _m.typeMode) != null ? _n : "inferred",
|
|
1474
|
+
nativeEnumType
|
|
1468
1475
|
};
|
|
1469
1476
|
}
|
|
1470
1477
|
/**
|
|
@@ -1749,10 +1756,19 @@ var ZodSchemaGenerator = class {
|
|
|
1749
1756
|
const context = this.schemaUsageMap.get(name);
|
|
1750
1757
|
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
1751
1758
|
if (schema.enum) {
|
|
1752
|
-
|
|
1753
|
-
|
|
1759
|
+
const jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
1760
|
+
if (resolvedOptions.enumType === "typescript") {
|
|
1761
|
+
const { schemaCode, typeCode } = generateEnum(name, schema.enum, {
|
|
1762
|
+
enumType: "typescript",
|
|
1763
|
+
prefix: this.options.prefix,
|
|
1764
|
+
suffix: this.options.suffix
|
|
1765
|
+
});
|
|
1766
|
+
const enumSchemaCode = `${jsdoc}${schemaCode}
|
|
1767
|
+
${typeCode}`;
|
|
1768
|
+
this.schemas.set(name, enumSchemaCode);
|
|
1769
|
+
} else {
|
|
1754
1770
|
const { enumCode, schemaCode, typeCode } = generateEnum(name, schema.enum, {
|
|
1755
|
-
enumType:
|
|
1771
|
+
enumType: "zod",
|
|
1756
1772
|
prefix: this.options.prefix,
|
|
1757
1773
|
suffix: this.options.suffix
|
|
1758
1774
|
});
|
|
@@ -1811,6 +1827,133 @@ ${typeCode}`;
|
|
|
1811
1827
|
this.schemas.set(name, zodSchemaCode);
|
|
1812
1828
|
}
|
|
1813
1829
|
}
|
|
1830
|
+
/**
|
|
1831
|
+
* Generate query parameter schemas for each operation
|
|
1832
|
+
*/
|
|
1833
|
+
generateQueryParameterSchemas() {
|
|
1834
|
+
var _a;
|
|
1835
|
+
if (!this.spec.paths) {
|
|
1836
|
+
return;
|
|
1837
|
+
}
|
|
1838
|
+
for (const [_path, pathItem] of Object.entries(this.spec.paths)) {
|
|
1839
|
+
if (!pathItem || typeof pathItem !== "object") continue;
|
|
1840
|
+
const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
1841
|
+
for (const method of methods) {
|
|
1842
|
+
const operation = pathItem[method];
|
|
1843
|
+
if (!operation) continue;
|
|
1844
|
+
if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
|
|
1845
|
+
continue;
|
|
1846
|
+
}
|
|
1847
|
+
const queryParams = operation.parameters.filter(
|
|
1848
|
+
(param) => param && typeof param === "object" && param.in === "query"
|
|
1849
|
+
);
|
|
1850
|
+
if (queryParams.length === 0) {
|
|
1851
|
+
continue;
|
|
1852
|
+
}
|
|
1853
|
+
const pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
|
|
1854
|
+
const schemaName = `${pascalOperationId}QueryParams`;
|
|
1855
|
+
if (!this.schemaDependencies.has(schemaName)) {
|
|
1856
|
+
this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
|
|
1857
|
+
}
|
|
1858
|
+
const properties = {};
|
|
1859
|
+
const required = [];
|
|
1860
|
+
for (const param of queryParams) {
|
|
1861
|
+
const paramName = param.name;
|
|
1862
|
+
const isRequired = param.required === true;
|
|
1863
|
+
const paramSchema = param.schema;
|
|
1864
|
+
if (!paramSchema) continue;
|
|
1865
|
+
let zodType = this.generateQueryParamType(paramSchema, param);
|
|
1866
|
+
if (paramSchema.type === "array" && paramSchema.items) {
|
|
1867
|
+
const itemType = this.generateQueryParamType(paramSchema.items, param);
|
|
1868
|
+
zodType = `z.array(${itemType})`;
|
|
1869
|
+
}
|
|
1870
|
+
if (param.description && this.requestOptions.includeDescriptions) {
|
|
1871
|
+
if (this.requestOptions.useDescribe) {
|
|
1872
|
+
zodType = `${zodType}.describe(${JSON.stringify(param.description)})`;
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
if (!isRequired) {
|
|
1876
|
+
zodType = `${zodType}.optional()`;
|
|
1877
|
+
}
|
|
1878
|
+
properties[paramName] = zodType;
|
|
1879
|
+
if (isRequired) {
|
|
1880
|
+
required.push(paramName);
|
|
1881
|
+
}
|
|
1882
|
+
if (paramSchema.$ref) {
|
|
1883
|
+
const refName = resolveRef(paramSchema.$ref);
|
|
1884
|
+
(_a = this.schemaDependencies.get(schemaName)) == null ? void 0 : _a.add(refName);
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
const objectMode = this.requestOptions.mode;
|
|
1888
|
+
const zodMethod = objectMode === "strict" ? "strictObject" : objectMode === "loose" ? "looseObject" : "object";
|
|
1889
|
+
const propsCode = Object.entries(properties).map(([key, value]) => {
|
|
1890
|
+
const needsQuotes = !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key);
|
|
1891
|
+
const quotedKey = needsQuotes ? `"${key}"` : key;
|
|
1892
|
+
return ` ${quotedKey}: ${value}`;
|
|
1893
|
+
}).join(",\n");
|
|
1894
|
+
const schemaCode = `z.${zodMethod}({
|
|
1895
|
+
${propsCode}
|
|
1896
|
+
})`;
|
|
1897
|
+
const operationName = pascalOperationId;
|
|
1898
|
+
const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
|
|
1899
|
+
const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
|
|
1900
|
+
const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}QueryParamsSchema`;
|
|
1901
|
+
const jsdoc = `/**
|
|
1902
|
+
* Query parameters for ${operation.operationId}
|
|
1903
|
+
*/
|
|
1904
|
+
`;
|
|
1905
|
+
const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
|
|
1906
|
+
this.schemas.set(schemaName, fullSchemaCode);
|
|
1907
|
+
this.needsZodImport = true;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
/**
|
|
1912
|
+
* Generate Zod type for a query parameter schema
|
|
1913
|
+
*/
|
|
1914
|
+
generateQueryParamType(schema, param) {
|
|
1915
|
+
if (schema.$ref) {
|
|
1916
|
+
const refName = resolveRef(schema.$ref);
|
|
1917
|
+
const schemaName = toCamelCase(refName, { prefix: this.options.prefix, suffix: this.options.suffix });
|
|
1918
|
+
return `${schemaName}Schema`;
|
|
1919
|
+
}
|
|
1920
|
+
if (schema.enum) {
|
|
1921
|
+
const enumValues = schema.enum.map((v) => typeof v === "string" ? `"${v}"` : v).join(", ");
|
|
1922
|
+
return `z.enum([${enumValues}])`;
|
|
1923
|
+
}
|
|
1924
|
+
const type = schema.type;
|
|
1925
|
+
if (type === "string") {
|
|
1926
|
+
let zodType = "z.string()";
|
|
1927
|
+
if (schema.minLength !== void 0) zodType = `${zodType}.min(${schema.minLength})`;
|
|
1928
|
+
if (schema.maxLength !== void 0) zodType = `${zodType}.max(${schema.maxLength})`;
|
|
1929
|
+
if (schema.pattern) zodType = `${zodType}.regex(/${schema.pattern}/)`;
|
|
1930
|
+
if (schema.format === "email") zodType = `${zodType}.email()`;
|
|
1931
|
+
if (schema.format === "uri" || schema.format === "url") zodType = `${zodType}.url()`;
|
|
1932
|
+
if (schema.format === "uuid") zodType = `${zodType}.uuid()`;
|
|
1933
|
+
return zodType;
|
|
1934
|
+
}
|
|
1935
|
+
if (type === "number" || type === "integer") {
|
|
1936
|
+
let zodType = type === "integer" ? "z.number().int()" : "z.number()";
|
|
1937
|
+
if (schema.minimum !== void 0) {
|
|
1938
|
+
zodType = schema.exclusiveMinimum ? `${zodType}.gt(${schema.minimum})` : `${zodType}.gte(${schema.minimum})`;
|
|
1939
|
+
}
|
|
1940
|
+
if (schema.maximum !== void 0) {
|
|
1941
|
+
zodType = schema.exclusiveMaximum ? `${zodType}.lt(${schema.maximum})` : `${zodType}.lte(${schema.maximum})`;
|
|
1942
|
+
}
|
|
1943
|
+
return zodType;
|
|
1944
|
+
}
|
|
1945
|
+
if (type === "boolean") {
|
|
1946
|
+
return "z.boolean()";
|
|
1947
|
+
}
|
|
1948
|
+
if (type === "array" && schema.items) {
|
|
1949
|
+
const itemType = this.generateQueryParamType(schema.items, param);
|
|
1950
|
+
let arrayType = `z.array(${itemType})`;
|
|
1951
|
+
if (schema.minItems !== void 0) arrayType = `${arrayType}.min(${schema.minItems})`;
|
|
1952
|
+
if (schema.maxItems !== void 0) arrayType = `${arrayType}.max(${schema.maxItems})`;
|
|
1953
|
+
return arrayType;
|
|
1954
|
+
}
|
|
1955
|
+
return "z.unknown()";
|
|
1956
|
+
}
|
|
1814
1957
|
/**
|
|
1815
1958
|
* Generate native TypeScript enum
|
|
1816
1959
|
*/
|
|
@@ -1821,8 +1964,8 @@ ${typeCode}`;
|
|
|
1821
1964
|
const jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
1822
1965
|
if (resolvedOptions.nativeEnumType === "enum") {
|
|
1823
1966
|
const enumName = `${name}Enum`;
|
|
1824
|
-
const members = schema.enum.map((value
|
|
1825
|
-
const key = typeof value === "string" ? this.toEnumKey(value) : `
|
|
1967
|
+
const members = schema.enum.map((value) => {
|
|
1968
|
+
const key = typeof value === "string" ? this.toEnumKey(value) : `N${value}`;
|
|
1826
1969
|
const val = typeof value === "string" ? `"${value}"` : value;
|
|
1827
1970
|
return ` ${key} = ${val}`;
|
|
1828
1971
|
}).join(",\n");
|
|
@@ -1965,7 +2108,11 @@ ${props.join("\n")}
|
|
|
1965
2108
|
const visited = /* @__PURE__ */ new Set();
|
|
1966
2109
|
const visiting = /* @__PURE__ */ new Set();
|
|
1967
2110
|
const aliases = [];
|
|
2111
|
+
const circularDeps = /* @__PURE__ */ new Set();
|
|
1968
2112
|
const codeCache = /* @__PURE__ */ new Map();
|
|
2113
|
+
for (const [name, code] of this.enums) {
|
|
2114
|
+
codeCache.set(name, code);
|
|
2115
|
+
}
|
|
1969
2116
|
for (const [name, code] of this.schemas) {
|
|
1970
2117
|
codeCache.set(name, code);
|
|
1971
2118
|
}
|
|
@@ -1975,6 +2122,7 @@ ${props.join("\n")}
|
|
|
1975
2122
|
const visit = (name) => {
|
|
1976
2123
|
if (visited.has(name)) return;
|
|
1977
2124
|
if (visiting.has(name)) {
|
|
2125
|
+
circularDeps.add(name);
|
|
1978
2126
|
return;
|
|
1979
2127
|
}
|
|
1980
2128
|
visiting.add(name);
|
|
@@ -1989,19 +2137,27 @@ ${props.join("\n")}
|
|
|
1989
2137
|
const deps = this.schemaDependencies.get(name);
|
|
1990
2138
|
if (deps && deps.size > 0) {
|
|
1991
2139
|
for (const dep of deps) {
|
|
1992
|
-
if (this.schemas.has(dep) || this.types.has(dep)) {
|
|
2140
|
+
if (this.enums.has(dep) || this.schemas.has(dep) || this.types.has(dep)) {
|
|
1993
2141
|
visit(dep);
|
|
1994
2142
|
}
|
|
1995
2143
|
}
|
|
1996
2144
|
}
|
|
1997
2145
|
visiting.delete(name);
|
|
1998
2146
|
visited.add(name);
|
|
1999
|
-
|
|
2147
|
+
if (!circularDeps.has(name)) {
|
|
2148
|
+
sorted.push(name);
|
|
2149
|
+
}
|
|
2000
2150
|
};
|
|
2001
|
-
const allNames = /* @__PURE__ */ new Set([...this.schemas.keys(), ...this.types.keys()]);
|
|
2151
|
+
const allNames = /* @__PURE__ */ new Set([...this.enums.keys(), ...this.schemas.keys(), ...this.types.keys()]);
|
|
2002
2152
|
for (const name of allNames) {
|
|
2003
2153
|
visit(name);
|
|
2004
2154
|
}
|
|
2155
|
+
for (const name of circularDeps) {
|
|
2156
|
+
if (!visited.has(name)) {
|
|
2157
|
+
sorted.push(name);
|
|
2158
|
+
visited.add(name);
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2005
2161
|
return [...sorted, ...aliases];
|
|
2006
2162
|
}
|
|
2007
2163
|
/**
|