@cerios/openapi-to-zod 1.2.0 → 1.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/dist/index.mjs CHANGED
@@ -403,12 +403,56 @@ function generateArrayValidation(schema, context) {
403
403
  }
404
404
 
405
405
  // src/validators/composition-validator.ts
406
+ function isDiscriminatorRequired(schemas, discriminator, context) {
407
+ const invalidSchemas = [];
408
+ for (const schema of schemas) {
409
+ const resolved = resolveSchema(schema, context);
410
+ const required = resolved.required || [];
411
+ if (!required.includes(discriminator)) {
412
+ const schemaName = schema.$ref ? schema.$ref.split("/").pop() || "inline" : "inline";
413
+ invalidSchemas.push(schemaName);
414
+ }
415
+ }
416
+ return {
417
+ valid: invalidSchemas.length === 0,
418
+ invalidSchemas
419
+ };
420
+ }
406
421
  function generateUnion(schemas, discriminator, isNullable2, context, options, currentSchema) {
422
+ if (schemas.length === 0) {
423
+ console.warn(
424
+ "[openapi-to-zod] Warning: Empty oneOf/anyOf array encountered. This is likely a malformed OpenAPI spec. Generating z.never() as fallback."
425
+ );
426
+ return wrapNullable(
427
+ 'z.never().describe("Empty oneOf/anyOf in OpenAPI spec - no valid schema defined")',
428
+ isNullable2
429
+ );
430
+ }
431
+ if (schemas.length === 1) {
432
+ let singleSchema = context.generatePropertySchema(schemas[0], currentSchema);
433
+ if ((options == null ? void 0 : options.passthrough) && !singleSchema.includes(".catchall(")) {
434
+ singleSchema = `${singleSchema}.catchall(z.unknown())`;
435
+ }
436
+ return wrapNullable(singleSchema, isNullable2);
437
+ }
407
438
  if (discriminator) {
408
439
  let resolvedSchemas = schemas;
409
440
  if ((options == null ? void 0 : options.discriminatorMapping) && context.resolveDiscriminatorMapping) {
410
441
  resolvedSchemas = context.resolveDiscriminatorMapping(options.discriminatorMapping, schemas);
411
442
  }
443
+ const discriminatorCheck = isDiscriminatorRequired(resolvedSchemas, discriminator, context);
444
+ if (!discriminatorCheck.valid) {
445
+ console.warn(
446
+ `[openapi-to-zod] Warning: Discriminator "${discriminator}" is not required in schemas: ${discriminatorCheck.invalidSchemas.join(", ")}. Falling back to z.union() instead of z.discriminatedUnion().`
447
+ );
448
+ let schemaStrings3 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema));
449
+ if (options == null ? void 0 : options.passthrough) {
450
+ schemaStrings3 = schemaStrings3.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
451
+ }
452
+ const fallbackDescription = `Discriminator "${discriminator}" is optional in some schemas (${discriminatorCheck.invalidSchemas.join(", ")}), using z.union() instead of z.discriminatedUnion()`;
453
+ const union3 = `z.union([${schemaStrings3.join(", ")}]).describe("${fallbackDescription}")`;
454
+ return wrapNullable(union3, isNullable2);
455
+ }
412
456
  let schemaStrings2 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema));
413
457
  if (options == null ? void 0 : options.passthrough) {
414
458
  schemaStrings2 = schemaStrings2.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
@@ -423,25 +467,102 @@ function generateUnion(schemas, discriminator, isNullable2, context, options, cu
423
467
  const union = `z.union([${schemaStrings.join(", ")}])`;
424
468
  return wrapNullable(union, isNullable2);
425
469
  }
470
+ function resolveSchema(schema, context) {
471
+ if (schema.$ref && context.resolveSchemaRef) {
472
+ const resolved = context.resolveSchemaRef(schema.$ref);
473
+ if (resolved) {
474
+ return resolved;
475
+ }
476
+ }
477
+ return schema;
478
+ }
479
+ function collectProperties(schema, context) {
480
+ const resolved = resolveSchema(schema, context);
481
+ const props = /* @__PURE__ */ new Map();
482
+ const sourceName = schema.$ref ? schema.$ref.split("/").pop() || "unknown" : "inline";
483
+ if (resolved.properties) {
484
+ for (const [key, value] of Object.entries(resolved.properties)) {
485
+ props.set(key, { schema: value, source: sourceName });
486
+ }
487
+ }
488
+ if (resolved.allOf) {
489
+ for (const subSchema of resolved.allOf) {
490
+ const subProps = collectProperties(subSchema, context);
491
+ for (const [key, value] of subProps) {
492
+ if (!props.has(key)) {
493
+ props.set(key, value);
494
+ }
495
+ }
496
+ }
497
+ }
498
+ return props;
499
+ }
500
+ function schemasMatch(a, b) {
501
+ return JSON.stringify(a) === JSON.stringify(b);
502
+ }
503
+ function detectConflictingProperties(schemas, context) {
504
+ const conflicts = [];
505
+ const propertyMap = /* @__PURE__ */ new Map();
506
+ for (const schema of schemas) {
507
+ const schemaProps = collectProperties(schema, context);
508
+ for (const [propName, propInfo] of schemaProps) {
509
+ const existing = propertyMap.get(propName);
510
+ if (existing) {
511
+ if (!schemasMatch(existing.schema, propInfo.schema)) {
512
+ conflicts.push(
513
+ `Property "${propName}" has conflicting definitions in ${existing.source} and ${propInfo.source}`
514
+ );
515
+ }
516
+ } else {
517
+ propertyMap.set(propName, propInfo);
518
+ }
519
+ }
520
+ }
521
+ return conflicts;
522
+ }
426
523
  function generateAllOf(schemas, isNullable2, context, currentSchema) {
427
524
  if (schemas.length === 1) {
428
525
  const singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false);
429
526
  return wrapNullable(singleSchema, isNullable2);
430
527
  }
528
+ const conflicts = detectConflictingProperties(schemas, context);
529
+ let conflictDescription = "";
530
+ if (conflicts.length > 0) {
531
+ for (const conflict of conflicts) {
532
+ console.warn(`[openapi-to-zod] Warning: allOf composition conflict - ${conflict}`);
533
+ }
534
+ conflictDescription = `allOf property conflicts detected: ${conflicts.join("; ")}`;
535
+ }
431
536
  const allObjects = schemas.every((s) => s.type === "object" || s.properties || s.$ref || s.allOf);
432
- const schemaStrings = schemas.map((s) => context.generatePropertySchema(s, currentSchema, false));
537
+ let result;
433
538
  if (allObjects) {
434
- let merged2 = schemaStrings[0];
539
+ let merged = context.generatePropertySchema(schemas[0], currentSchema, false);
540
+ for (let i = 1; i < schemas.length; i++) {
541
+ const schema = schemas[i];
542
+ if (schema.$ref) {
543
+ const refSchema = context.generatePropertySchema(schema, currentSchema, false);
544
+ merged = `${merged}.extend(${refSchema}.shape)`;
545
+ } else if (context.generateInlineObjectShape && (schema.properties || schema.type === "object")) {
546
+ const inlineShape = context.generateInlineObjectShape(schema, currentSchema);
547
+ merged = `${merged}.extend(${inlineShape})`;
548
+ } else {
549
+ const schemaString = context.generatePropertySchema(schema, currentSchema, false);
550
+ merged = `${merged}.extend(${schemaString}.shape)`;
551
+ }
552
+ }
553
+ result = merged;
554
+ } else {
555
+ const schemaStrings = schemas.map((s) => context.generatePropertySchema(s, currentSchema, false));
556
+ let merged = schemaStrings[0];
435
557
  for (let i = 1; i < schemaStrings.length; i++) {
436
- merged2 = `${merged2}.merge(${schemaStrings[i]})`;
558
+ merged = `${merged}.and(${schemaStrings[i]})`;
437
559
  }
438
- return wrapNullable(merged2, isNullable2);
560
+ result = merged;
439
561
  }
440
- let merged = schemaStrings[0];
441
- for (let i = 1; i < schemaStrings.length; i++) {
442
- merged = `${merged}.and(${schemaStrings[i]})`;
562
+ if (conflictDescription) {
563
+ result = `${result}.describe("${conflictDescription}")`;
443
564
  }
444
- return wrapNullable(merged, isNullable2);
565
+ return wrapNullable(result, isNullable2);
445
566
  }
446
567
 
447
568
  // src/validators/number-validator.ts
@@ -1117,6 +1238,15 @@ var _PropertyGenerator = class _PropertyGenerator {
1117
1238
  }
1118
1239
  return mappedSchemas;
1119
1240
  }
1241
+ /**
1242
+ * Resolve a $ref string to the actual schema
1243
+ */
1244
+ resolveSchemaRef(ref) {
1245
+ var _a, _b;
1246
+ const schemaName = ref.split("/").pop();
1247
+ if (!schemaName) return void 0;
1248
+ return (_b = (_a = this.context.spec.components) == null ? void 0 : _a.schemas) == null ? void 0 : _b[schemaName];
1249
+ }
1120
1250
  /**
1121
1251
  * Resolve a schema name through any aliases to get the actual schema name
1122
1252
  * If the schema is an alias (allOf with single $ref), return the target name
@@ -1194,7 +1324,7 @@ var _PropertyGenerator = class _PropertyGenerator {
1194
1324
  let schemaWithCatchall = baseSchema;
1195
1325
  if (baseSchema.includes(".union([") || baseSchema.includes(".discriminatedUnion(")) {
1196
1326
  schemaWithCatchall = baseSchema;
1197
- } else if (baseSchema.includes(".merge(")) {
1327
+ } else if (baseSchema.includes(".extend(")) {
1198
1328
  schemaWithCatchall = `${baseSchema}.catchall(z.unknown())`;
1199
1329
  }
1200
1330
  if (schema.unevaluatedProperties === false) {
@@ -1221,7 +1351,11 @@ var _PropertyGenerator = class _PropertyGenerator {
1221
1351
  if ((this.context.schemaType === "request" || this.context.schemaType === "response") && schema.properties) {
1222
1352
  schema = this.filterNestedProperties(schema);
1223
1353
  }
1224
- const effectiveDefaultNullable = isTopLevel ? false : this.context.defaultNullable;
1354
+ const isSchemaRef = !!schema.$ref;
1355
+ const isEnum = !!schema.enum;
1356
+ const isConst = schema.const !== void 0;
1357
+ const shouldApplyDefaultNullable = !isTopLevel && !isSchemaRef && !isEnum && !isConst;
1358
+ const effectiveDefaultNullable = shouldApplyDefaultNullable ? this.context.defaultNullable : false;
1225
1359
  const nullable = isNullable(schema, effectiveDefaultNullable);
1226
1360
  if (hasMultipleTypes(schema)) {
1227
1361
  const union = this.generateMultiTypeUnion(schema, currentSchema);
@@ -1274,7 +1408,11 @@ var _PropertyGenerator = class _PropertyGenerator {
1274
1408
  let composition = generateAllOf(
1275
1409
  schema.allOf,
1276
1410
  nullable,
1277
- { generatePropertySchema: this.generatePropertySchema.bind(this) },
1411
+ {
1412
+ generatePropertySchema: this.generatePropertySchema.bind(this),
1413
+ generateInlineObjectShape: this.generateInlineObjectShape.bind(this),
1414
+ resolveSchemaRef: this.resolveSchemaRef.bind(this)
1415
+ },
1278
1416
  currentSchema
1279
1417
  );
1280
1418
  if (schema.unevaluatedProperties !== void 0) {
@@ -1290,7 +1428,8 @@ var _PropertyGenerator = class _PropertyGenerator {
1290
1428
  nullable,
1291
1429
  {
1292
1430
  generatePropertySchema: this.generatePropertySchema.bind(this),
1293
- resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this)
1431
+ resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
1432
+ resolveSchemaRef: this.resolveSchemaRef.bind(this)
1294
1433
  },
1295
1434
  {
1296
1435
  passthrough: needsPassthrough,
@@ -1311,7 +1450,8 @@ var _PropertyGenerator = class _PropertyGenerator {
1311
1450
  nullable,
1312
1451
  {
1313
1452
  generatePropertySchema: this.generatePropertySchema.bind(this),
1314
- resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this)
1453
+ resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
1454
+ resolveSchemaRef: this.resolveSchemaRef.bind(this)
1315
1455
  },
1316
1456
  {
1317
1457
  passthrough: needsPassthrough,
@@ -1374,7 +1514,17 @@ var _PropertyGenerator = class _PropertyGenerator {
1374
1514
  );
1375
1515
  validation = addDescription(validation, schema.description, this.context.useDescribe);
1376
1516
  } else {
1377
- validation = "z.record(z.string(), z.unknown())";
1517
+ switch (this.context.emptyObjectBehavior) {
1518
+ case "strict":
1519
+ validation = "z.strictObject({})";
1520
+ break;
1521
+ case "loose":
1522
+ validation = "z.looseObject({})";
1523
+ break;
1524
+ default:
1525
+ validation = "z.record(z.string(), z.unknown())";
1526
+ break;
1527
+ }
1378
1528
  validation = addDescription(validation, schema.description, this.context.useDescribe);
1379
1529
  }
1380
1530
  break;
@@ -1389,6 +1539,44 @@ var _PropertyGenerator = class _PropertyGenerator {
1389
1539
  }
1390
1540
  return result;
1391
1541
  }
1542
+ /**
1543
+ * Generate inline object shape for use with .extend()
1544
+ * Returns just the shape object literal: { prop1: z.string(), prop2: z.number() }
1545
+ *
1546
+ * This method is specifically for allOf compositions where we need to pass
1547
+ * the shape directly to .extend() instead of using z.object({...}).shape.
1548
+ * This avoids the .nullable().shape bug when inline objects have nullable: true.
1549
+ *
1550
+ * According to Zod docs (https://zod.dev/api?id=extend):
1551
+ * - .extend() accepts an object of shape definitions
1552
+ * - e.g., baseSchema.extend({ prop: z.string() })
1553
+ */
1554
+ generateInlineObjectShape(schema, currentSchema) {
1555
+ const required = new Set(schema.required || []);
1556
+ const properties = [];
1557
+ if (schema.properties) {
1558
+ for (const [propName, propSchema] of Object.entries(schema.properties)) {
1559
+ if (!this.shouldIncludeProperty(propSchema)) {
1560
+ continue;
1561
+ }
1562
+ const isRequired = required.has(propName);
1563
+ const zodSchema = this.generatePropertySchema(propSchema, currentSchema);
1564
+ const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
1565
+ const quotedPropName = validIdentifier.test(propName) ? propName : `"${propName}"`;
1566
+ let propertyDef = `${quotedPropName}: ${zodSchema}`;
1567
+ if (!isRequired) {
1568
+ propertyDef += ".optional()";
1569
+ }
1570
+ properties.push(propertyDef);
1571
+ }
1572
+ }
1573
+ if (properties.length === 0) {
1574
+ return "{}";
1575
+ }
1576
+ return `{
1577
+ ${properties.map((p) => ` ${p}`).join(",\n")}
1578
+ }`;
1579
+ }
1392
1580
  };
1393
1581
  // Performance optimization: Lookup table for faster inclusion checks
1394
1582
  _PropertyGenerator.INCLUSION_RULES = {
@@ -1532,6 +1720,59 @@ function formatFilterStatistics(stats) {
1532
1720
  return lines.join("\n");
1533
1721
  }
1534
1722
 
1723
+ // src/utils/ref-resolver.ts
1724
+ function resolveRef2(obj, spec, maxDepth = 10) {
1725
+ var _a, _b, _c, _d;
1726
+ if (!obj || typeof obj !== "object" || maxDepth <= 0) return obj;
1727
+ if (!obj.$ref) return obj;
1728
+ const ref = obj.$ref;
1729
+ let resolved = null;
1730
+ const paramMatch = ref.match(/^#\/components\/parameters\/(.+)$/);
1731
+ const requestBodyMatch = ref.match(/^#\/components\/requestBodies\/(.+)$/);
1732
+ const responseMatch = ref.match(/^#\/components\/responses\/(.+)$/);
1733
+ const schemaMatch = ref.match(/^#\/components\/schemas\/(.+)$/);
1734
+ if (paramMatch && ((_a = spec.components) == null ? void 0 : _a.parameters)) {
1735
+ const name = paramMatch[1];
1736
+ resolved = spec.components.parameters[name];
1737
+ } else if (requestBodyMatch && ((_b = spec.components) == null ? void 0 : _b.requestBodies)) {
1738
+ const name = requestBodyMatch[1];
1739
+ resolved = spec.components.requestBodies[name];
1740
+ } else if (responseMatch && ((_c = spec.components) == null ? void 0 : _c.responses)) {
1741
+ const name = responseMatch[1];
1742
+ resolved = spec.components.responses[name];
1743
+ } else if (schemaMatch && ((_d = spec.components) == null ? void 0 : _d.schemas)) {
1744
+ const name = schemaMatch[1];
1745
+ resolved = spec.components.schemas[name];
1746
+ }
1747
+ if (resolved) {
1748
+ if (resolved.$ref) {
1749
+ return resolveRef2(resolved, spec, maxDepth - 1);
1750
+ }
1751
+ return resolved;
1752
+ }
1753
+ return obj;
1754
+ }
1755
+ function resolveParameterRef(param, spec) {
1756
+ return resolveRef2(param, spec);
1757
+ }
1758
+ function mergeParameters(pathParams, operationParams, spec) {
1759
+ const resolvedPathParams = (pathParams || []).map((p) => resolveParameterRef(p, spec));
1760
+ const resolvedOperationParams = (operationParams || []).map((p) => resolveParameterRef(p, spec));
1761
+ const merged = [...resolvedPathParams];
1762
+ for (const opParam of resolvedOperationParams) {
1763
+ if (!opParam || typeof opParam !== "object") continue;
1764
+ const existingIndex = merged.findIndex(
1765
+ (p) => p && typeof p === "object" && p.name === opParam.name && p.in === opParam.in
1766
+ );
1767
+ if (existingIndex >= 0) {
1768
+ merged[existingIndex] = opParam;
1769
+ } else {
1770
+ merged.push(opParam);
1771
+ }
1772
+ }
1773
+ return merged;
1774
+ }
1775
+
1535
1776
  // src/openapi-generator.ts
1536
1777
  var OpenApiGenerator = class {
1537
1778
  constructor(options) {
@@ -1541,7 +1782,7 @@ var OpenApiGenerator = class {
1541
1782
  this.schemaUsageMap = /* @__PURE__ */ new Map();
1542
1783
  this.needsZodImport = true;
1543
1784
  this.filterStats = createFilterStatistics();
1544
- var _a, _b, _c, _d, _e, _f, _g;
1785
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1545
1786
  if (!options.input) {
1546
1787
  throw new ConfigurationError("Input path is required", { providedOptions: options });
1547
1788
  }
@@ -1552,18 +1793,19 @@ var OpenApiGenerator = class {
1552
1793
  includeDescriptions: (_a = options.includeDescriptions) != null ? _a : true,
1553
1794
  useDescribe: (_b = options.useDescribe) != null ? _b : false,
1554
1795
  defaultNullable: (_c = options.defaultNullable) != null ? _c : false,
1796
+ emptyObjectBehavior: (_d = options.emptyObjectBehavior) != null ? _d : "loose",
1555
1797
  schemaType: options.schemaType || "all",
1556
1798
  prefix: options.prefix,
1557
1799
  suffix: options.suffix,
1558
1800
  stripSchemaPrefix: options.stripSchemaPrefix,
1559
1801
  stripPathPrefix: options.stripPathPrefix,
1560
- showStats: (_d = options.showStats) != null ? _d : true,
1802
+ showStats: (_e = options.showStats) != null ? _e : true,
1561
1803
  request: options.request,
1562
1804
  response: options.response,
1563
1805
  operationFilters: options.operationFilters,
1564
1806
  ignoreHeaders: options.ignoreHeaders,
1565
- cacheSize: (_e = options.cacheSize) != null ? _e : 1e3,
1566
- batchSize: (_f = options.batchSize) != null ? _f : 10,
1807
+ cacheSize: (_f = options.cacheSize) != null ? _f : 1e3,
1808
+ batchSize: (_g = options.batchSize) != null ? _g : 10,
1567
1809
  customDateTimeFormatRegex: options.customDateTimeFormatRegex
1568
1810
  };
1569
1811
  if (this.options.cacheSize) {
@@ -1634,7 +1876,8 @@ var OpenApiGenerator = class {
1634
1876
  mode: this.requestOptions.mode,
1635
1877
  includeDescriptions: this.requestOptions.includeDescriptions,
1636
1878
  useDescribe: this.requestOptions.useDescribe,
1637
- defaultNullable: (_g = this.options.defaultNullable) != null ? _g : false,
1879
+ defaultNullable: (_h = this.options.defaultNullable) != null ? _h : false,
1880
+ emptyObjectBehavior: (_i = this.options.emptyObjectBehavior) != null ? _i : "loose",
1638
1881
  namingOptions: {
1639
1882
  prefix: this.options.prefix,
1640
1883
  suffix: this.options.suffix
@@ -1988,7 +2231,7 @@ var OpenApiGenerator = class {
1988
2231
  * Generate schema for a component
1989
2232
  */
1990
2233
  generateComponentSchema(name, schema) {
1991
- var _a, _b, _c;
2234
+ var _a, _b, _c, _d;
1992
2235
  if (!this.schemaDependencies.has(name)) {
1993
2236
  this.schemaDependencies.set(name, /* @__PURE__ */ new Set());
1994
2237
  }
@@ -2021,6 +2264,7 @@ ${typeCode}`;
2021
2264
  includeDescriptions: resolvedOptions.includeDescriptions,
2022
2265
  useDescribe: resolvedOptions.useDescribe,
2023
2266
  defaultNullable: (_b = this.options.defaultNullable) != null ? _b : false,
2267
+ emptyObjectBehavior: (_c = this.options.emptyObjectBehavior) != null ? _c : "loose",
2024
2268
  namingOptions: {
2025
2269
  prefix: this.options.prefix,
2026
2270
  suffix: this.options.suffix
@@ -2037,7 +2281,7 @@ ${typeCode}`;
2037
2281
  const depMatch = ref.match(/^([a-z][a-zA-Z0-9]*?)Schema$/);
2038
2282
  if (depMatch) {
2039
2283
  const depName = depMatch[1].charAt(0).toUpperCase() + depMatch[1].slice(1);
2040
- (_c = this.schemaDependencies.get(name)) == null ? void 0 : _c.add(depName);
2284
+ (_d = this.schemaDependencies.get(name)) == null ? void 0 : _d.add(depName);
2041
2285
  }
2042
2286
  }
2043
2287
  }
@@ -2061,10 +2305,8 @@ ${typeCode}`;
2061
2305
  if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
2062
2306
  continue;
2063
2307
  }
2064
- if (!operation.parameters || !Array.isArray(operation.parameters)) {
2065
- continue;
2066
- }
2067
- const queryParams = operation.parameters.filter(
2308
+ const allParams = mergeParameters(pathItem.parameters, operation.parameters, this.spec);
2309
+ const queryParams = allParams.filter(
2068
2310
  (param) => param && typeof param === "object" && param.in === "query"
2069
2311
  );
2070
2312
  if (queryParams.length === 0) {
@@ -2200,10 +2442,8 @@ ${propsCode}
2200
2442
  if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
2201
2443
  continue;
2202
2444
  }
2203
- if (!operation.parameters || !Array.isArray(operation.parameters)) {
2204
- continue;
2205
- }
2206
- const headerParams = operation.parameters.filter(
2445
+ const allParams = mergeParameters(pathItem.parameters, operation.parameters, this.spec);
2446
+ const headerParams = allParams.filter(
2207
2447
  (param) => param && typeof param === "object" && param.in === "header" && !this.shouldIgnoreHeader(param.name)
2208
2448
  );
2209
2449
  if (headerParams.length === 0) {
@@ -2293,13 +2533,23 @@ ${propsCode}
2293
2533
  }
2294
2534
  const type = schema.type;
2295
2535
  if (type === "string") {
2536
+ const formatMap = {
2537
+ email: "z.email()",
2538
+ uri: "z.url()",
2539
+ url: "z.url()",
2540
+ uuid: "z.uuid()"
2541
+ };
2542
+ if (schema.format && formatMap[schema.format]) {
2543
+ let zodType2 = formatMap[schema.format];
2544
+ if (schema.minLength !== void 0) zodType2 = `${zodType2}.min(${schema.minLength})`;
2545
+ if (schema.maxLength !== void 0) zodType2 = `${zodType2}.max(${schema.maxLength})`;
2546
+ if (schema.pattern) zodType2 = `${zodType2}.regex(/${schema.pattern}/)`;
2547
+ return zodType2;
2548
+ }
2296
2549
  let zodType = "z.string()";
2297
2550
  if (schema.minLength !== void 0) zodType = `${zodType}.min(${schema.minLength})`;
2298
2551
  if (schema.maxLength !== void 0) zodType = `${zodType}.max(${schema.maxLength})`;
2299
2552
  if (schema.pattern) zodType = `${zodType}.regex(/${schema.pattern}/)`;
2300
- if (schema.format === "email") zodType = `${zodType}.email()`;
2301
- if (schema.format === "uri" || schema.format === "url") zodType = `${zodType}.url()`;
2302
- if (schema.format === "uuid") zodType = `${zodType}.uuid()`;
2303
2553
  return zodType;
2304
2554
  }
2305
2555
  if (type === "number" || type === "integer") {
@@ -2324,11 +2574,6 @@ ${propsCode}
2324
2574
  }
2325
2575
  return "z.unknown()";
2326
2576
  }
2327
- // REMOVED: generateNativeEnum method - no longer needed as we only generate Zod schemas
2328
- // REMOVED: toEnumKey method - was only used by generateNativeEnum
2329
- // REMOVED: addConstraintsToJSDoc method - was only used for native TypeScript types
2330
- // REMOVED: generateNativeTypeDefinition method - was only used for native TypeScript types
2331
- // REMOVED: generateObjectType method - was only used for native TypeScript types
2332
2577
  /**
2333
2578
  * Topological sort for schema dependencies
2334
2579
  * Returns schemas in the order they should be declared