@cerios/openapi-to-zod 0.5.3 → 0.6.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 +7 -16
- package/dist/cli.js +56 -325
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +56 -325
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +1 -77
- package/dist/index.d.ts +1 -77
- package/dist/index.js +51 -312
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +51 -312
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Transform OpenAPI YAML specifications into Zod v4 compliant schemas with full Ty
|
|
|
6
6
|
|
|
7
7
|
- ✅ **Zod v4 Compatible**: Uses latest Zod features, no deprecated methods
|
|
8
8
|
- 📝 **TypeScript Types**: Automatically generates TypeScript types from schemas using `z.infer`
|
|
9
|
-
- 🎯 **Enums**: Creates
|
|
9
|
+
- 🎯 **Zod Enums**: Creates Zod enum schemas from OpenAPI enums
|
|
10
10
|
- 🔧 **Flexible Modes**: Strict, normal, or loose validation
|
|
11
11
|
- 📐 **Format Support**: Full support for string formats (uuid, email, url, date, etc.)
|
|
12
12
|
- 🎨 **camelCase Schemas**: Schemas follow camelCase naming with Schema suffix
|
|
@@ -128,12 +128,6 @@ export default defineConfig({
|
|
|
128
128
|
|
|
129
129
|
**openapi-to-zod.config.json:**
|
|
130
130
|
|
|
131
|
-
```json
|
|
132
|
-
{
|
|
133
|
-
"defaults": {
|
|
134
|
-
"mode": "strict",
|
|
135
|
-
"includeDescriptions": true,
|
|
136
|
-
"enumType": "zod",
|
|
137
131
|
```json
|
|
138
132
|
{
|
|
139
133
|
"defaults": {
|
|
@@ -218,15 +212,13 @@ openapi-to-zod
|
|
|
218
212
|
| `output` | `string` | Output TypeScript file path (required) |
|
|
219
213
|
| `mode` | `"strict"` \| `"normal"` \| `"loose"` | Validation mode |
|
|
220
214
|
| `includeDescriptions` | `boolean` | Include JSDoc comments |
|
|
221
|
-
| `enumType` | `"zod"` \| `"typescript"` | Enum generation type |
|
|
222
215
|
| `useDescribe` | `boolean` | Add `.describe()` calls |
|
|
223
216
|
| `schemaType` | `"all"` \| `"request"` \| `"response"` | Schema filtering |
|
|
224
217
|
| `prefix` | `string` | Prefix for schema names |
|
|
225
218
|
| `suffix` | `string` | Suffix for schema names |
|
|
226
219
|
| `showStats` | `boolean` | Include generation statistics |
|
|
227
|
-
| `
|
|
228
|
-
| `
|
|
229
|
-
| `response` | `object` | Response-specific options (mode, enumType, etc.) |
|
|
220
|
+
| `request` | `object` | Request-specific options (mode, includeDescriptions, etc.) |
|
|
221
|
+
| `response` | `object` | Response-specific options (mode, includeDescriptions, etc.) |
|
|
230
222
|
|
|
231
223
|
### Batch Execution
|
|
232
224
|
|
|
@@ -440,10 +432,10 @@ OpenAPI's `nullable: true` is converted to `.nullable()`
|
|
|
440
432
|
|
|
441
433
|
### Enums
|
|
442
434
|
|
|
443
|
-
Enums are generated as
|
|
444
|
-
-
|
|
445
|
-
- Original string values
|
|
435
|
+
Enums are generated as Zod enums with:
|
|
436
|
+
- Proper string value handling
|
|
446
437
|
- Zod schema using `z.enum()`
|
|
438
|
+
- TypeScript type inference from the Zod schema
|
|
447
439
|
|
|
448
440
|
## Schema Naming
|
|
449
441
|
|
|
@@ -475,7 +467,6 @@ Statistics are **included by default** in generated files. Use `--no-stats` to d
|
|
|
475
467
|
```typescript
|
|
476
468
|
// Generation Statistics:
|
|
477
469
|
// Total schemas: 42
|
|
478
|
-
// Enums: 8
|
|
479
470
|
// Circular references: 3
|
|
480
471
|
// Discriminated unions: 5
|
|
481
472
|
// With constraints: 18
|
|
@@ -877,7 +868,7 @@ interface OpenApiGeneratorOptions {
|
|
|
877
868
|
Comprehensive test suite with **364 passing tests** covering:
|
|
878
869
|
|
|
879
870
|
- ✅ **Basic Schema Generation** (14 tests) - Core OpenAPI types, references, nested objects
|
|
880
|
-
- ✅ **Enum Generation** (
|
|
871
|
+
- ✅ **Enum Generation** (4 tests) - Zod enum generation and handling
|
|
881
872
|
- ✅ **Circular References** (5 tests) - Self-references, mutual references, validation
|
|
882
873
|
- ✅ **Format Support** (9 tests) - UUID, email, URL, date-time, and 15+ other formats
|
|
883
874
|
- ✅ **Validation Modes** (7 tests) - Strict, normal, loose object validation
|
package/dist/cli.js
CHANGED
|
@@ -5054,34 +5054,11 @@ function resolveRef(ref) {
|
|
|
5054
5054
|
|
|
5055
5055
|
// src/generators/enum-generator.ts
|
|
5056
5056
|
function generateEnum(name, values, options) {
|
|
5057
|
-
const enumName = name.endsWith("EnumOptions") ? name.replace("EnumOptions", "Enum") : `${name}Enum`;
|
|
5058
5057
|
const schemaName = `${toCamelCase(name, options)}Schema`;
|
|
5059
|
-
if (options.enumType === "typescript") {
|
|
5060
|
-
const usedKeys = /* @__PURE__ */ new Set();
|
|
5061
|
-
const enumEntries = values.map((value) => {
|
|
5062
|
-
let key = toPascalCase(value);
|
|
5063
|
-
if (usedKeys.has(key)) {
|
|
5064
|
-
let counter = 2;
|
|
5065
|
-
while (usedKeys.has(`${key}${counter}`)) {
|
|
5066
|
-
counter++;
|
|
5067
|
-
}
|
|
5068
|
-
key = `${key}${counter}`;
|
|
5069
|
-
}
|
|
5070
|
-
usedKeys.add(key);
|
|
5071
|
-
const stringValue = typeof value === "string" ? `"${value}"` : value;
|
|
5072
|
-
return ` ${key} = ${stringValue},`;
|
|
5073
|
-
}).join("\n");
|
|
5074
|
-
const enumCode = `export enum ${enumName} {
|
|
5075
|
-
${enumEntries}
|
|
5076
|
-
}`;
|
|
5077
|
-
const schemaCode2 = `export const ${schemaName} = z.nativeEnum(${enumName});`;
|
|
5078
|
-
const typeCode2 = `export type ${name} = z.infer<typeof ${schemaName}>;`;
|
|
5079
|
-
return { enumCode, schemaCode: schemaCode2, typeCode: typeCode2 };
|
|
5080
|
-
}
|
|
5081
5058
|
const enumValues = values.map((v) => `"${v}"`).join(", ");
|
|
5082
5059
|
const schemaCode = `export const ${schemaName} = z.enum([${enumValues}]);`;
|
|
5083
5060
|
const typeCode = `export type ${name} = z.infer<typeof ${schemaName}>;`;
|
|
5084
|
-
return {
|
|
5061
|
+
return { schemaCode, typeCode };
|
|
5085
5062
|
}
|
|
5086
5063
|
|
|
5087
5064
|
// src/generators/jsdoc-generator.ts
|
|
@@ -6362,12 +6339,9 @@ var OpenApiGenerator = class {
|
|
|
6362
6339
|
constructor(options) {
|
|
6363
6340
|
this.schemas = /* @__PURE__ */ new Map();
|
|
6364
6341
|
this.types = /* @__PURE__ */ new Map();
|
|
6365
|
-
this.enums = /* @__PURE__ */ new Map();
|
|
6366
|
-
this.nativeEnums = /* @__PURE__ */ new Map();
|
|
6367
6342
|
this.schemaDependencies = /* @__PURE__ */ new Map();
|
|
6368
6343
|
this.schemaUsageMap = /* @__PURE__ */ new Map();
|
|
6369
|
-
this.
|
|
6370
|
-
this.needsZodImport = false;
|
|
6344
|
+
this.needsZodImport = true;
|
|
6371
6345
|
this.filterStats = createFilterStatistics();
|
|
6372
6346
|
var _a, _b, _c;
|
|
6373
6347
|
if (!options.input) {
|
|
@@ -6378,13 +6352,11 @@ var OpenApiGenerator = class {
|
|
|
6378
6352
|
input: options.input,
|
|
6379
6353
|
output: options.output,
|
|
6380
6354
|
includeDescriptions: (_a = options.includeDescriptions) != null ? _a : true,
|
|
6381
|
-
enumType: options.enumType || "zod",
|
|
6382
6355
|
useDescribe: (_b = options.useDescribe) != null ? _b : false,
|
|
6383
6356
|
schemaType: options.schemaType || "all",
|
|
6384
6357
|
prefix: options.prefix,
|
|
6385
6358
|
suffix: options.suffix,
|
|
6386
6359
|
showStats: (_c = options.showStats) != null ? _c : true,
|
|
6387
|
-
nativeEnumType: options.nativeEnumType || "union",
|
|
6388
6360
|
request: options.request,
|
|
6389
6361
|
response: options.response,
|
|
6390
6362
|
operationFilters: options.operationFilters
|
|
@@ -6444,7 +6416,6 @@ var OpenApiGenerator = class {
|
|
|
6444
6416
|
this.requestOptions = this.resolveOptionsForContext("request");
|
|
6445
6417
|
this.responseOptions = this.resolveOptionsForContext("response");
|
|
6446
6418
|
this.analyzeSchemaUsage();
|
|
6447
|
-
this.determineSchemaTypeModes();
|
|
6448
6419
|
this.propertyGenerator = new PropertyGenerator({
|
|
6449
6420
|
spec: this.spec,
|
|
6450
6421
|
schemaDependencies: this.schemaDependencies,
|
|
@@ -6452,8 +6423,6 @@ var OpenApiGenerator = class {
|
|
|
6452
6423
|
mode: this.requestOptions.mode,
|
|
6453
6424
|
includeDescriptions: this.requestOptions.includeDescriptions,
|
|
6454
6425
|
useDescribe: this.requestOptions.useDescribe,
|
|
6455
|
-
typeMode: this.requestOptions.typeMode,
|
|
6456
|
-
nativeEnumType: this.requestOptions.nativeEnumType,
|
|
6457
6426
|
namingOptions: {
|
|
6458
6427
|
prefix: this.options.prefix,
|
|
6459
6428
|
suffix: this.options.suffix
|
|
@@ -6469,25 +6438,6 @@ var OpenApiGenerator = class {
|
|
|
6469
6438
|
if (!((_a = this.spec.components) == null ? void 0 : _a.schemas)) {
|
|
6470
6439
|
throw new SpecValidationError("No schemas found in OpenAPI spec", { filePath: this.options.input });
|
|
6471
6440
|
}
|
|
6472
|
-
for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
|
|
6473
|
-
if (schema.enum) {
|
|
6474
|
-
const context = this.schemaUsageMap.get(name);
|
|
6475
|
-
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
6476
|
-
if (resolvedOptions.enumType === "typescript") {
|
|
6477
|
-
this.generateNativeEnum(name, schema);
|
|
6478
|
-
} else {
|
|
6479
|
-
const { enumCode } = generateEnum(name, schema.enum, {
|
|
6480
|
-
enumType: "zod",
|
|
6481
|
-
prefix: this.options.prefix,
|
|
6482
|
-
suffix: this.options.suffix
|
|
6483
|
-
});
|
|
6484
|
-
if (enumCode) {
|
|
6485
|
-
this.enums.set(name, enumCode);
|
|
6486
|
-
this.needsZodImport = true;
|
|
6487
|
-
}
|
|
6488
|
-
}
|
|
6489
|
-
}
|
|
6490
|
-
}
|
|
6491
6441
|
for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
|
|
6492
6442
|
this.generateComponentSchema(name, schema);
|
|
6493
6443
|
}
|
|
@@ -6504,22 +6454,11 @@ var OpenApiGenerator = class {
|
|
|
6504
6454
|
output.push('import { z } from "zod";');
|
|
6505
6455
|
output.push("");
|
|
6506
6456
|
}
|
|
6507
|
-
if (this.nativeEnums.size > 0) {
|
|
6508
|
-
output.push("// Native Enums");
|
|
6509
|
-
for (const enumCode of this.nativeEnums.values()) {
|
|
6510
|
-
output.push(enumCode);
|
|
6511
|
-
output.push("");
|
|
6512
|
-
}
|
|
6513
|
-
}
|
|
6514
6457
|
output.push("// Schemas and Types");
|
|
6515
6458
|
for (const name of orderedSchemaNames) {
|
|
6516
|
-
const enumCode = this.enums.get(name);
|
|
6517
6459
|
const schemaCode = this.schemas.get(name);
|
|
6518
6460
|
const typeCode = this.types.get(name);
|
|
6519
|
-
if (
|
|
6520
|
-
output.push(enumCode);
|
|
6521
|
-
output.push("");
|
|
6522
|
-
} else if (schemaCode) {
|
|
6461
|
+
if (schemaCode) {
|
|
6523
6462
|
output.push(schemaCode);
|
|
6524
6463
|
if (!schemaCode.includes(`export type ${name}`)) {
|
|
6525
6464
|
const schemaName = `${toCamelCase(name, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
|
|
@@ -6561,21 +6500,14 @@ var OpenApiGenerator = class {
|
|
|
6561
6500
|
/**
|
|
6562
6501
|
* Resolve options for a specific context (request or response)
|
|
6563
6502
|
* Nested options silently override root-level options
|
|
6564
|
-
* Response schemas always use 'inferred' mode (Zod schemas)
|
|
6565
6503
|
*/
|
|
6566
6504
|
resolveOptionsForContext(context) {
|
|
6567
|
-
var _a, _b, _c, _d, _e, _f
|
|
6505
|
+
var _a, _b, _c, _d, _e, _f;
|
|
6568
6506
|
const contextOptions = context === "request" ? this.options.request : this.options.response;
|
|
6569
|
-
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";
|
|
6570
6507
|
return {
|
|
6571
|
-
mode: (
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
includeDescriptions: (_l = (_k = contextOptions == null ? void 0 : contextOptions.includeDescriptions) != null ? _k : this.options.includeDescriptions) != null ? _l : true,
|
|
6575
|
-
// Response schemas always use 'inferred' mode (Zod schemas are required)
|
|
6576
|
-
// Request schemas can optionally use 'native' mode
|
|
6577
|
-
typeMode: context === "response" ? "inferred" : (_n = (_m = this.options.request) == null ? void 0 : _m.typeMode) != null ? _n : "inferred",
|
|
6578
|
-
nativeEnumType
|
|
6508
|
+
mode: (_b = (_a = contextOptions == null ? void 0 : contextOptions.mode) != null ? _a : this.options.mode) != null ? _b : "normal",
|
|
6509
|
+
useDescribe: (_d = (_c = contextOptions == null ? void 0 : contextOptions.useDescribe) != null ? _c : this.options.useDescribe) != null ? _d : false,
|
|
6510
|
+
includeDescriptions: (_f = (_e = contextOptions == null ? void 0 : contextOptions.includeDescriptions) != null ? _e : this.options.includeDescriptions) != null ? _f : true
|
|
6579
6511
|
};
|
|
6580
6512
|
}
|
|
6581
6513
|
/**
|
|
@@ -6766,28 +6698,6 @@ var OpenApiGenerator = class {
|
|
|
6766
6698
|
detectCycle(name);
|
|
6767
6699
|
}
|
|
6768
6700
|
}
|
|
6769
|
-
/**
|
|
6770
|
-
* Determine the typeMode for each schema based on its usage context
|
|
6771
|
-
* Response schemas always use 'inferred' mode
|
|
6772
|
-
*/
|
|
6773
|
-
determineSchemaTypeModes() {
|
|
6774
|
-
var _a;
|
|
6775
|
-
for (const [name] of Object.entries(((_a = this.spec.components) == null ? void 0 : _a.schemas) || {})) {
|
|
6776
|
-
const context = this.schemaUsageMap.get(name);
|
|
6777
|
-
if (context === "request") {
|
|
6778
|
-
this.schemaTypeModeMap.set(name, this.requestOptions.typeMode);
|
|
6779
|
-
} else if (context === "response") {
|
|
6780
|
-
this.schemaTypeModeMap.set(name, "inferred");
|
|
6781
|
-
} else if (context === "both") {
|
|
6782
|
-
this.schemaTypeModeMap.set(name, "inferred");
|
|
6783
|
-
} else {
|
|
6784
|
-
this.schemaTypeModeMap.set(name, "inferred");
|
|
6785
|
-
}
|
|
6786
|
-
if (this.schemaTypeModeMap.get(name) === "inferred") {
|
|
6787
|
-
this.needsZodImport = true;
|
|
6788
|
-
}
|
|
6789
|
-
}
|
|
6790
|
-
}
|
|
6791
6701
|
/**
|
|
6792
6702
|
* Validate the OpenAPI specification
|
|
6793
6703
|
*/
|
|
@@ -6863,80 +6773,54 @@ var OpenApiGenerator = class {
|
|
|
6863
6773
|
if (!this.schemaDependencies.has(name)) {
|
|
6864
6774
|
this.schemaDependencies.set(name, /* @__PURE__ */ new Set());
|
|
6865
6775
|
}
|
|
6866
|
-
const typeMode = this.schemaTypeModeMap.get(name) || "inferred";
|
|
6867
6776
|
const context = this.schemaUsageMap.get(name);
|
|
6868
6777
|
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
6869
6778
|
if (schema.enum) {
|
|
6870
|
-
const
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
});
|
|
6877
|
-
const enumSchemaCode = `${jsdoc}${schemaCode}
|
|
6878
|
-
${typeCode}`;
|
|
6879
|
-
this.schemas.set(name, enumSchemaCode);
|
|
6880
|
-
} else {
|
|
6881
|
-
const { enumCode, schemaCode, typeCode } = generateEnum(name, schema.enum, {
|
|
6882
|
-
enumType: "zod",
|
|
6883
|
-
prefix: this.options.prefix,
|
|
6884
|
-
suffix: this.options.suffix
|
|
6885
|
-
});
|
|
6886
|
-
if (enumCode) {
|
|
6887
|
-
this.enums.set(name, enumCode);
|
|
6888
|
-
}
|
|
6889
|
-
const enumSchemaCode = `${jsdoc}${schemaCode}
|
|
6779
|
+
const jsdoc2 = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
6780
|
+
const { schemaCode, typeCode } = generateEnum(name, schema.enum, {
|
|
6781
|
+
prefix: this.options.prefix,
|
|
6782
|
+
suffix: this.options.suffix
|
|
6783
|
+
});
|
|
6784
|
+
const enumSchemaCode = `${jsdoc2}${schemaCode}
|
|
6890
6785
|
${typeCode}`;
|
|
6891
|
-
|
|
6892
|
-
}
|
|
6786
|
+
this.schemas.set(name, enumSchemaCode);
|
|
6893
6787
|
return;
|
|
6894
6788
|
}
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
const
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
if (zodSchema.includes("z.discriminatedUnion(")) {
|
|
6926
|
-
const match = zodSchema.match(/z\.discriminatedUnion\([^,]+,\s*\[([^\]]+)\]/);
|
|
6927
|
-
if (match) {
|
|
6928
|
-
const refs = match[1].split(",").map((ref) => ref.trim());
|
|
6929
|
-
for (const ref of refs) {
|
|
6930
|
-
const depMatch = ref.match(/^([a-z][a-zA-Z0-9]*?)Schema$/);
|
|
6931
|
-
if (depMatch) {
|
|
6932
|
-
const depName = depMatch[1].charAt(0).toUpperCase() + depMatch[1].slice(1);
|
|
6933
|
-
(_b = this.schemaDependencies.get(name)) == null ? void 0 : _b.add(depName);
|
|
6934
|
-
}
|
|
6789
|
+
const schemaName = `${toCamelCase(name, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
|
|
6790
|
+
const jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
6791
|
+
if (schema.allOf && schema.allOf.length === 1 && schema.allOf[0].$ref) {
|
|
6792
|
+
const refName = resolveRef(schema.allOf[0].$ref);
|
|
6793
|
+
(_a = this.schemaDependencies.get(name)) == null ? void 0 : _a.add(refName);
|
|
6794
|
+
}
|
|
6795
|
+
this.propertyGenerator = new PropertyGenerator({
|
|
6796
|
+
spec: this.spec,
|
|
6797
|
+
schemaDependencies: this.schemaDependencies,
|
|
6798
|
+
schemaType: this.options.schemaType || "all",
|
|
6799
|
+
mode: resolvedOptions.mode,
|
|
6800
|
+
includeDescriptions: resolvedOptions.includeDescriptions,
|
|
6801
|
+
useDescribe: resolvedOptions.useDescribe,
|
|
6802
|
+
namingOptions: {
|
|
6803
|
+
prefix: this.options.prefix,
|
|
6804
|
+
suffix: this.options.suffix
|
|
6805
|
+
}
|
|
6806
|
+
});
|
|
6807
|
+
const isAlias = !!(schema.$ref && !schema.properties && !schema.allOf && !schema.oneOf && !schema.anyOf);
|
|
6808
|
+
const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, isAlias);
|
|
6809
|
+
const zodSchemaCode = `${jsdoc}export const ${schemaName} = ${zodSchema};`;
|
|
6810
|
+
if (zodSchema.includes("z.discriminatedUnion(")) {
|
|
6811
|
+
const match = zodSchema.match(/z\.discriminatedUnion\([^,]+,\s*\[([^\]]+)\]/);
|
|
6812
|
+
if (match) {
|
|
6813
|
+
const refs = match[1].split(",").map((ref) => ref.trim());
|
|
6814
|
+
for (const ref of refs) {
|
|
6815
|
+
const depMatch = ref.match(/^([a-z][a-zA-Z0-9]*?)Schema$/);
|
|
6816
|
+
if (depMatch) {
|
|
6817
|
+
const depName = depMatch[1].charAt(0).toUpperCase() + depMatch[1].slice(1);
|
|
6818
|
+
(_b = this.schemaDependencies.get(name)) == null ? void 0 : _b.add(depName);
|
|
6935
6819
|
}
|
|
6936
6820
|
}
|
|
6937
6821
|
}
|
|
6938
|
-
this.schemas.set(name, zodSchemaCode);
|
|
6939
6822
|
}
|
|
6823
|
+
this.schemas.set(name, zodSchemaCode);
|
|
6940
6824
|
}
|
|
6941
6825
|
/**
|
|
6942
6826
|
* Generate query parameter schemas for each operation
|
|
@@ -7142,151 +7026,11 @@ ${propsCode}
|
|
|
7142
7026
|
}
|
|
7143
7027
|
return "z.unknown()";
|
|
7144
7028
|
}
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
const context = this.schemaUsageMap.get(name);
|
|
7151
|
-
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
7152
|
-
const jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
7153
|
-
if (resolvedOptions.nativeEnumType === "enum") {
|
|
7154
|
-
const enumName = `${name}Enum`;
|
|
7155
|
-
const members = schema.enum.map((value) => {
|
|
7156
|
-
const key = typeof value === "string" ? this.toEnumKey(value) : `N${value}`;
|
|
7157
|
-
const val = typeof value === "string" ? `"${value}"` : value;
|
|
7158
|
-
return ` ${key} = ${val}`;
|
|
7159
|
-
}).join(",\n");
|
|
7160
|
-
const enumCode = `${jsdoc}export enum ${enumName} {
|
|
7161
|
-
${members}
|
|
7162
|
-
}`;
|
|
7163
|
-
this.nativeEnums.set(name, enumCode);
|
|
7164
|
-
const typeCode = `export type ${name} = ${enumName};`;
|
|
7165
|
-
this.types.set(name, typeCode);
|
|
7166
|
-
} else {
|
|
7167
|
-
const unionType = schema.enum.map((v) => typeof v === "string" ? `"${v}"` : v).join(" | ");
|
|
7168
|
-
const typeCode = `${jsdoc}export type ${name} = ${unionType};`;
|
|
7169
|
-
this.types.set(name, typeCode);
|
|
7170
|
-
}
|
|
7171
|
-
}
|
|
7172
|
-
/**
|
|
7173
|
-
* Convert string to valid enum key
|
|
7174
|
-
*/
|
|
7175
|
-
toEnumKey(value) {
|
|
7176
|
-
const cleaned = value.replace(/[^a-zA-Z0-9]/g, "_");
|
|
7177
|
-
const pascalCase = cleaned.split("_").map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
|
|
7178
|
-
return pascalCase || "Value";
|
|
7179
|
-
}
|
|
7180
|
-
/**
|
|
7181
|
-
* Add constraint annotations to JSDoc for native types
|
|
7182
|
-
*/
|
|
7183
|
-
addConstraintsToJSDoc(jsdoc, schema, includeDescriptions) {
|
|
7184
|
-
if (!includeDescriptions) return jsdoc;
|
|
7185
|
-
const constraints = [];
|
|
7186
|
-
if (schema.minLength !== void 0) constraints.push(`@minLength ${schema.minLength}`);
|
|
7187
|
-
if (schema.maxLength !== void 0) constraints.push(`@maxLength ${schema.maxLength}`);
|
|
7188
|
-
if (schema.pattern) constraints.push(`@pattern ${schema.pattern}`);
|
|
7189
|
-
if (schema.minimum !== void 0) constraints.push(`@minimum ${schema.minimum}`);
|
|
7190
|
-
if (schema.maximum !== void 0) constraints.push(`@maximum ${schema.maximum}`);
|
|
7191
|
-
if (schema.minItems !== void 0) constraints.push(`@minItems ${schema.minItems}`);
|
|
7192
|
-
if (schema.maxItems !== void 0) constraints.push(`@maxItems ${schema.maxItems}`);
|
|
7193
|
-
if (schema.minProperties !== void 0) constraints.push(`@minProperties ${schema.minProperties}`);
|
|
7194
|
-
if (schema.maxProperties !== void 0) constraints.push(`@maxProperties ${schema.maxProperties}`);
|
|
7195
|
-
if (schema.multipleOf !== void 0) constraints.push(`@multipleOf ${schema.multipleOf}`);
|
|
7196
|
-
if (schema.format) constraints.push(`@format ${schema.format}`);
|
|
7197
|
-
if (constraints.length === 0) return jsdoc;
|
|
7198
|
-
if (jsdoc) {
|
|
7199
|
-
const lines = jsdoc.trim().split("\n");
|
|
7200
|
-
if (lines[0] === "/**" && lines[lines.length - 1] === " */") {
|
|
7201
|
-
const newLines = [...lines.slice(0, -1), ...constraints.map((c) => ` * ${c}`), " */\n"];
|
|
7202
|
-
return newLines.join("\n");
|
|
7203
|
-
}
|
|
7204
|
-
const content = jsdoc.replace("/** ", "").replace(" */\n", "");
|
|
7205
|
-
return `/**
|
|
7206
|
-
* ${content}
|
|
7207
|
-
${constraints.map((c) => ` * ${c}`).join("\n")}
|
|
7208
|
-
*/
|
|
7209
|
-
`;
|
|
7210
|
-
}
|
|
7211
|
-
return `/**
|
|
7212
|
-
${constraints.map((c) => ` * ${c}`).join("\n")}
|
|
7213
|
-
*/
|
|
7214
|
-
`;
|
|
7215
|
-
}
|
|
7216
|
-
/**
|
|
7217
|
-
* Generate native TypeScript type definition from OpenAPI schema
|
|
7218
|
-
*/
|
|
7219
|
-
generateNativeTypeDefinition(schema, _schemaName) {
|
|
7220
|
-
if (schema.$ref) {
|
|
7221
|
-
return resolveRef(schema.$ref);
|
|
7222
|
-
}
|
|
7223
|
-
if (schema.const !== void 0) {
|
|
7224
|
-
return typeof schema.const === "string" ? `"${schema.const}"` : String(schema.const);
|
|
7225
|
-
}
|
|
7226
|
-
const isNullable2 = schema.nullable || Array.isArray(schema.type) && schema.type.includes("null");
|
|
7227
|
-
const wrapNullable2 = (type) => isNullable2 ? `(${type}) | null` : type;
|
|
7228
|
-
const primaryType = Array.isArray(schema.type) ? schema.type.find((t) => t !== "null") : schema.type;
|
|
7229
|
-
switch (primaryType) {
|
|
7230
|
-
case "string":
|
|
7231
|
-
return wrapNullable2("string");
|
|
7232
|
-
case "number":
|
|
7233
|
-
case "integer":
|
|
7234
|
-
return wrapNullable2("number");
|
|
7235
|
-
case "boolean":
|
|
7236
|
-
return wrapNullable2("boolean");
|
|
7237
|
-
case "array":
|
|
7238
|
-
if (schema.items) {
|
|
7239
|
-
const itemType = this.generateNativeTypeDefinition(schema.items);
|
|
7240
|
-
return wrapNullable2(`${itemType}[]`);
|
|
7241
|
-
}
|
|
7242
|
-
return wrapNullable2("unknown[]");
|
|
7243
|
-
case "object":
|
|
7244
|
-
return wrapNullable2(this.generateObjectType(schema));
|
|
7245
|
-
default:
|
|
7246
|
-
if (schema.allOf) {
|
|
7247
|
-
const types = schema.allOf.map((s) => this.generateNativeTypeDefinition(s));
|
|
7248
|
-
return wrapNullable2(types.join(" & "));
|
|
7249
|
-
}
|
|
7250
|
-
if (schema.oneOf || schema.anyOf) {
|
|
7251
|
-
const schemas = schema.oneOf || schema.anyOf || [];
|
|
7252
|
-
const types = schemas.map((s) => this.generateNativeTypeDefinition(s));
|
|
7253
|
-
return wrapNullable2(types.join(" | "));
|
|
7254
|
-
}
|
|
7255
|
-
return wrapNullable2("unknown");
|
|
7256
|
-
}
|
|
7257
|
-
}
|
|
7258
|
-
/**
|
|
7259
|
-
* Generate TypeScript object type definition
|
|
7260
|
-
*/
|
|
7261
|
-
generateObjectType(schema) {
|
|
7262
|
-
if (!schema.properties || Object.keys(schema.properties).length === 0) {
|
|
7263
|
-
return "Record<string, unknown>";
|
|
7264
|
-
}
|
|
7265
|
-
const context = this.schemaUsageMap.get(schema.$ref ? resolveRef(schema.$ref) : "");
|
|
7266
|
-
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
7267
|
-
const required = new Set(schema.required || []);
|
|
7268
|
-
const props = [];
|
|
7269
|
-
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
7270
|
-
const propType = this.generateNativeTypeDefinition(propSchema);
|
|
7271
|
-
const optional = !required.has(propName) ? "?" : "";
|
|
7272
|
-
let propJsdoc = generateJSDoc(propSchema, propName, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
7273
|
-
if (resolvedOptions.includeDescriptions && !propJsdoc) {
|
|
7274
|
-
propJsdoc = this.addConstraintsToJSDoc("", propSchema, resolvedOptions.includeDescriptions);
|
|
7275
|
-
} else if (propJsdoc && resolvedOptions.includeDescriptions) {
|
|
7276
|
-
propJsdoc = this.addConstraintsToJSDoc(propJsdoc, propSchema, resolvedOptions.includeDescriptions);
|
|
7277
|
-
}
|
|
7278
|
-
if (propJsdoc) {
|
|
7279
|
-
const cleanJsdoc = propJsdoc.trimEnd();
|
|
7280
|
-
props.push(` ${cleanJsdoc}
|
|
7281
|
-
${propName}${optional}: ${propType};`);
|
|
7282
|
-
} else {
|
|
7283
|
-
props.push(` ${propName}${optional}: ${propType};`);
|
|
7284
|
-
}
|
|
7285
|
-
}
|
|
7286
|
-
return `{
|
|
7287
|
-
${props.join("\n")}
|
|
7288
|
-
}`;
|
|
7289
|
-
}
|
|
7029
|
+
// REMOVED: generateNativeEnum method - no longer needed as we only generate Zod schemas
|
|
7030
|
+
// REMOVED: toEnumKey method - was only used by generateNativeEnum
|
|
7031
|
+
// REMOVED: addConstraintsToJSDoc method - was only used for native TypeScript types
|
|
7032
|
+
// REMOVED: generateNativeTypeDefinition method - was only used for native TypeScript types
|
|
7033
|
+
// REMOVED: generateObjectType method - was only used for native TypeScript types
|
|
7290
7034
|
/**
|
|
7291
7035
|
* Topological sort for schema dependencies
|
|
7292
7036
|
* Returns schemas in the order they should be declared
|
|
@@ -7298,9 +7042,6 @@ ${props.join("\n")}
|
|
|
7298
7042
|
const aliases = [];
|
|
7299
7043
|
const circularDeps = /* @__PURE__ */ new Set();
|
|
7300
7044
|
const codeCache = /* @__PURE__ */ new Map();
|
|
7301
|
-
for (const [name, code] of this.enums) {
|
|
7302
|
-
codeCache.set(name, code);
|
|
7303
|
-
}
|
|
7304
7045
|
for (const [name, code] of this.schemas) {
|
|
7305
7046
|
codeCache.set(name, code);
|
|
7306
7047
|
}
|
|
@@ -7325,7 +7066,7 @@ ${props.join("\n")}
|
|
|
7325
7066
|
const deps = this.schemaDependencies.get(name);
|
|
7326
7067
|
if (deps && deps.size > 0) {
|
|
7327
7068
|
for (const dep of deps) {
|
|
7328
|
-
if (this.
|
|
7069
|
+
if (this.schemas.has(dep) || this.types.has(dep)) {
|
|
7329
7070
|
visit(dep);
|
|
7330
7071
|
}
|
|
7331
7072
|
}
|
|
@@ -7336,7 +7077,7 @@ ${props.join("\n")}
|
|
|
7336
7077
|
sorted.push(name);
|
|
7337
7078
|
}
|
|
7338
7079
|
};
|
|
7339
|
-
const allNames = /* @__PURE__ */ new Set([...this.
|
|
7080
|
+
const allNames = /* @__PURE__ */ new Set([...this.schemas.keys(), ...this.types.keys()]);
|
|
7340
7081
|
for (const name of allNames) {
|
|
7341
7082
|
visit(name);
|
|
7342
7083
|
}
|
|
@@ -7354,7 +7095,6 @@ ${props.join("\n")}
|
|
|
7354
7095
|
generateStats() {
|
|
7355
7096
|
const stats = {
|
|
7356
7097
|
totalSchemas: this.schemas.size,
|
|
7357
|
-
enums: this.enums.size,
|
|
7358
7098
|
withCircularRefs: 0,
|
|
7359
7099
|
withDiscriminators: 0,
|
|
7360
7100
|
withConstraints: 0
|
|
@@ -7369,7 +7109,6 @@ ${props.join("\n")}
|
|
|
7369
7109
|
const output = [
|
|
7370
7110
|
"// Generation Statistics:",
|
|
7371
7111
|
`// Total schemas: ${stats.totalSchemas}`,
|
|
7372
|
-
`// Enums: ${stats.enums}`,
|
|
7373
7112
|
`// Circular references: ${stats.withCircularRefs}`,
|
|
7374
7113
|
`// Discriminated unions: ${stats.withDiscriminators}`,
|
|
7375
7114
|
`// With constraints: ${stats.withConstraints}`
|
|
@@ -7491,15 +7230,10 @@ function getBatchExitCode(summary) {
|
|
|
7491
7230
|
init_cjs_shims();
|
|
7492
7231
|
var import_cosmiconfig = require("cosmiconfig");
|
|
7493
7232
|
var import_zod = require("zod");
|
|
7494
|
-
var TypeModeSchema = import_zod.z.enum(["inferred", "native"]);
|
|
7495
|
-
var NativeEnumTypeSchema = import_zod.z.enum(["union", "enum"]);
|
|
7496
7233
|
var RequestResponseOptionsSchema = import_zod.z.strictObject({
|
|
7497
7234
|
mode: import_zod.z.enum(["strict", "normal", "loose"]).optional(),
|
|
7498
|
-
enumType: import_zod.z.enum(["zod", "typescript"]).optional(),
|
|
7499
7235
|
useDescribe: import_zod.z.boolean().optional(),
|
|
7500
|
-
includeDescriptions: import_zod.z.boolean().optional()
|
|
7501
|
-
typeMode: TypeModeSchema.optional(),
|
|
7502
|
-
nativeEnumType: NativeEnumTypeSchema.optional()
|
|
7236
|
+
includeDescriptions: import_zod.z.boolean().optional()
|
|
7503
7237
|
});
|
|
7504
7238
|
var OperationFiltersSchema = import_zod.z.strictObject({
|
|
7505
7239
|
includeTags: import_zod.z.array(import_zod.z.string()).optional(),
|
|
@@ -7517,13 +7251,11 @@ var OpenApiGeneratorOptionsSchema = import_zod.z.strictObject({
|
|
|
7517
7251
|
input: import_zod.z.string(),
|
|
7518
7252
|
output: import_zod.z.string(),
|
|
7519
7253
|
includeDescriptions: import_zod.z.boolean().optional(),
|
|
7520
|
-
enumType: import_zod.z.enum(["zod", "typescript"]).optional(),
|
|
7521
7254
|
useDescribe: import_zod.z.boolean().optional(),
|
|
7522
7255
|
schemaType: import_zod.z.enum(["all", "request", "response"]).optional(),
|
|
7523
7256
|
prefix: import_zod.z.string().optional(),
|
|
7524
7257
|
suffix: import_zod.z.string().optional(),
|
|
7525
7258
|
showStats: import_zod.z.boolean().optional(),
|
|
7526
|
-
nativeEnumType: NativeEnumTypeSchema.optional(),
|
|
7527
7259
|
request: RequestResponseOptionsSchema.optional(),
|
|
7528
7260
|
response: RequestResponseOptionsSchema.optional(),
|
|
7529
7261
|
name: import_zod.z.string().optional(),
|
|
@@ -7533,13 +7265,11 @@ var ConfigFileSchema = import_zod.z.strictObject({
|
|
|
7533
7265
|
defaults: import_zod.z.strictObject({
|
|
7534
7266
|
mode: import_zod.z.enum(["strict", "normal", "loose"]).optional(),
|
|
7535
7267
|
includeDescriptions: import_zod.z.boolean().optional(),
|
|
7536
|
-
enumType: import_zod.z.enum(["zod", "typescript"]).optional(),
|
|
7537
7268
|
useDescribe: import_zod.z.boolean().optional(),
|
|
7538
7269
|
schemaType: import_zod.z.enum(["all", "request", "response"]).optional(),
|
|
7539
7270
|
prefix: import_zod.z.string().optional(),
|
|
7540
7271
|
suffix: import_zod.z.string().optional(),
|
|
7541
7272
|
showStats: import_zod.z.boolean().optional(),
|
|
7542
|
-
nativeEnumType: NativeEnumTypeSchema.optional(),
|
|
7543
7273
|
request: RequestResponseOptionsSchema.optional(),
|
|
7544
7274
|
response: RequestResponseOptionsSchema.optional(),
|
|
7545
7275
|
operationFilters: OperationFiltersSchema.optional()
|
|
@@ -7635,7 +7365,6 @@ function mergeConfigWithDefaults(config) {
|
|
|
7635
7365
|
// Apply defaults first
|
|
7636
7366
|
mode: defaults.mode,
|
|
7637
7367
|
includeDescriptions: defaults.includeDescriptions,
|
|
7638
|
-
enumType: defaults.enumType,
|
|
7639
7368
|
useDescribe: defaults.useDescribe,
|
|
7640
7369
|
schemaType: defaults.schemaType,
|
|
7641
7370
|
prefix: defaults.prefix,
|
|
@@ -7834,7 +7563,7 @@ async function initConfigFile() {
|
|
|
7834
7563
|
{
|
|
7835
7564
|
type: "confirm",
|
|
7836
7565
|
name: "includeDefaults",
|
|
7837
|
-
message: "Include commonly-used defaults?
|
|
7566
|
+
message: "Include commonly-used recommended defaults?",
|
|
7838
7567
|
initial: true
|
|
7839
7568
|
}
|
|
7840
7569
|
]);
|
|
@@ -7855,7 +7584,9 @@ export default defineConfig({
|
|
|
7855
7584
|
defaults: {
|
|
7856
7585
|
mode: 'strict',
|
|
7857
7586
|
includeDescriptions: true,
|
|
7587
|
+
useDescribe: false,
|
|
7858
7588
|
showStats: false,
|
|
7589
|
+
schemaType: 'all',
|
|
7859
7590
|
},
|
|
7860
7591
|
specs: [
|
|
7861
7592
|
{
|