@cerios/openapi-to-zod 1.3.1 → 1.4.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.d.mts CHANGED
@@ -65,6 +65,10 @@ declare class OpenApiGenerator {
65
65
  private responseOptions;
66
66
  private needsZodImport;
67
67
  private filterStats;
68
+ /** Instance-level pattern cache for parallel-safe execution */
69
+ private patternCache;
70
+ /** Instance-level date-time validation string for parallel-safe execution */
71
+ private dateTimeValidation;
68
72
  constructor(options: OpenApiGeneratorOptions);
69
73
  /**
70
74
  * Generate schemas as a string (without writing to file)
package/dist/index.d.ts CHANGED
@@ -65,6 +65,10 @@ declare class OpenApiGenerator {
65
65
  private responseOptions;
66
66
  private needsZodImport;
67
67
  private filterStats;
68
+ /** Instance-level pattern cache for parallel-safe execution */
69
+ private patternCache;
70
+ /** Instance-level date-time validation string for parallel-safe execution */
71
+ private dateTimeValidation;
68
72
  constructor(options: OpenApiGeneratorOptions);
69
73
  /**
70
74
  * Generate schemas as a string (without writing to file)
package/dist/index.js CHANGED
@@ -182,7 +182,7 @@ function escapeDescription(str) {
182
182
  return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
183
183
  }
184
184
  function escapePattern(str) {
185
- return str.replace(/\//g, "\\/");
185
+ return str.replace(/(?<!\\)\//g, "\\/");
186
186
  }
187
187
  function escapeJSDoc(str) {
188
188
  return str.replace(/\*\//g, "*\\/");
@@ -456,7 +456,7 @@ function generateUnion(schemas, discriminator, isNullable2, context, options, cu
456
456
  );
457
457
  }
458
458
  if (schemas.length === 1) {
459
- let singleSchema = context.generatePropertySchema(schemas[0], currentSchema);
459
+ let singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false, true);
460
460
  if ((options == null ? void 0 : options.passthrough) && !singleSchema.includes(".catchall(")) {
461
461
  singleSchema = `${singleSchema}.catchall(z.unknown())`;
462
462
  }
@@ -472,7 +472,7 @@ function generateUnion(schemas, discriminator, isNullable2, context, options, cu
472
472
  console.warn(
473
473
  `[openapi-to-zod] Warning: Discriminator "${discriminator}" is not required in schemas: ${discriminatorCheck.invalidSchemas.join(", ")}. Falling back to z.union() instead of z.discriminatedUnion().`
474
474
  );
475
- let schemaStrings3 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema));
475
+ let schemaStrings3 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema, false, true));
476
476
  if (options == null ? void 0 : options.passthrough) {
477
477
  schemaStrings3 = schemaStrings3.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
478
478
  }
@@ -480,14 +480,14 @@ function generateUnion(schemas, discriminator, isNullable2, context, options, cu
480
480
  const union3 = `z.union([${schemaStrings3.join(", ")}]).describe("${fallbackDescription}")`;
481
481
  return wrapNullable(union3, isNullable2);
482
482
  }
483
- let schemaStrings2 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema));
483
+ let schemaStrings2 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema, false, true));
484
484
  if (options == null ? void 0 : options.passthrough) {
485
485
  schemaStrings2 = schemaStrings2.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
486
486
  }
487
487
  const union2 = `z.discriminatedUnion("${discriminator}", [${schemaStrings2.join(", ")}])`;
488
488
  return wrapNullable(union2, isNullable2);
489
489
  }
490
- let schemaStrings = schemas.map((s) => context.generatePropertySchema(s, currentSchema));
490
+ let schemaStrings = schemas.map((s) => context.generatePropertySchema(s, currentSchema, false, true));
491
491
  if (options == null ? void 0 : options.passthrough) {
492
492
  schemaStrings = schemaStrings.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
493
493
  }
@@ -547,9 +547,9 @@ function detectConflictingProperties(schemas, context) {
547
547
  }
548
548
  return conflicts;
549
549
  }
550
- function generateAllOf(schemas, isNullable2, context, currentSchema, explicitNullableFalse = false) {
550
+ function generateAllOf(schemas, isNullable2, context, currentSchema) {
551
551
  if (schemas.length === 1) {
552
- const singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false, explicitNullableFalse);
552
+ const singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false, true);
553
553
  return wrapNullable(singleSchema, isNullable2);
554
554
  }
555
555
  const conflicts = detectConflictingProperties(schemas, context);
@@ -563,23 +563,23 @@ function generateAllOf(schemas, isNullable2, context, currentSchema, explicitNul
563
563
  const allObjects = schemas.every((s) => s.type === "object" || s.properties || s.$ref || s.allOf);
564
564
  let result;
565
565
  if (allObjects) {
566
- let merged = context.generatePropertySchema(schemas[0], currentSchema, false);
566
+ let merged = context.generatePropertySchema(schemas[0], currentSchema, false, true);
567
567
  for (let i = 1; i < schemas.length; i++) {
568
568
  const schema = schemas[i];
569
569
  if (schema.$ref) {
570
- const refSchema = context.generatePropertySchema(schema, currentSchema, false);
570
+ const refSchema = context.generatePropertySchema(schema, currentSchema, false, true);
571
571
  merged = `${merged}.extend(${refSchema}.shape)`;
572
572
  } else if (context.generateInlineObjectShape && (schema.properties || schema.type === "object")) {
573
573
  const inlineShape = context.generateInlineObjectShape(schema, currentSchema);
574
574
  merged = `${merged}.extend(${inlineShape})`;
575
575
  } else {
576
- const schemaString = context.generatePropertySchema(schema, currentSchema, false);
576
+ const schemaString = context.generatePropertySchema(schema, currentSchema, false, true);
577
577
  merged = `${merged}.extend(${schemaString}.shape)`;
578
578
  }
579
579
  }
580
580
  result = merged;
581
581
  } else {
582
- const schemaStrings = schemas.map((s) => context.generatePropertySchema(s, currentSchema, false));
582
+ const schemaStrings = schemas.map((s) => context.generatePropertySchema(s, currentSchema, false, true));
583
583
  let merged = schemaStrings[0];
584
584
  for (let i = 1; i < schemaStrings.length; i++) {
585
585
  merged = `${merged}.and(${schemaStrings[i]})`;
@@ -1022,12 +1022,6 @@ ${properties.join(",\n")}
1022
1022
  }
1023
1023
 
1024
1024
  // src/validators/string-validator.ts
1025
- var PATTERN_CACHE = new LRUCache(1e3);
1026
- function configurePatternCache(size) {
1027
- if (size > 0 && size !== PATTERN_CACHE.capacity) {
1028
- PATTERN_CACHE = new LRUCache(size);
1029
- }
1030
- }
1031
1025
  var DEFAULT_FORMAT_MAP = {
1032
1026
  uuid: "z.uuid()",
1033
1027
  email: "z.email()",
@@ -1056,19 +1050,13 @@ var DEFAULT_FORMAT_MAP = {
1056
1050
  "json-pointer": 'z.string().refine((val) => val === "" || /^(\\/([^~/]|~0|~1)+)+$/.test(val), { message: "Must be a valid JSON Pointer (RFC 6901)" })',
1057
1051
  "relative-json-pointer": 'z.string().refine((val) => /^(0|[1-9]\\d*)(#|(\\/([^~/]|~0|~1)+)*)$/.test(val), { message: "Must be a valid relative JSON Pointer" })'
1058
1052
  };
1059
- var FORMAT_MAP = {
1060
- ...DEFAULT_FORMAT_MAP,
1061
- "date-time": "z.iso.datetime()"
1062
- };
1063
- function configureDateTimeFormat(pattern) {
1053
+ function buildDateTimeValidation(pattern) {
1064
1054
  if (!pattern) {
1065
- FORMAT_MAP["date-time"] = "z.iso.datetime()";
1066
- return;
1055
+ return "z.iso.datetime()";
1067
1056
  }
1068
1057
  const patternStr = pattern instanceof RegExp ? pattern.source : pattern;
1069
1058
  if (patternStr === "") {
1070
- FORMAT_MAP["date-time"] = "z.iso.datetime()";
1071
- return;
1059
+ return "z.iso.datetime()";
1072
1060
  }
1073
1061
  try {
1074
1062
  new RegExp(patternStr);
@@ -1078,10 +1066,16 @@ function configureDateTimeFormat(pattern) {
1078
1066
  );
1079
1067
  }
1080
1068
  const escapedPattern = escapePattern(patternStr);
1081
- FORMAT_MAP["date-time"] = `z.string().regex(/${escapedPattern}/)`;
1069
+ return `z.string().regex(/${escapedPattern}/)`;
1082
1070
  }
1083
- function generateStringValidation(schema, useDescribe) {
1084
- let validation = FORMAT_MAP[schema.format || ""] || "z.string()";
1071
+ function generateStringValidation(schema, useDescribe, context) {
1072
+ let validation;
1073
+ const format = schema.format || "";
1074
+ if (format === "date-time") {
1075
+ validation = context.dateTimeValidation;
1076
+ } else {
1077
+ validation = DEFAULT_FORMAT_MAP[format] || "z.string()";
1078
+ }
1085
1079
  if (schema.minLength !== void 0) {
1086
1080
  validation += `.min(${schema.minLength})`;
1087
1081
  }
@@ -1089,10 +1083,10 @@ function generateStringValidation(schema, useDescribe) {
1089
1083
  validation += `.max(${schema.maxLength})`;
1090
1084
  }
1091
1085
  if (schema.pattern) {
1092
- let escapedPattern = PATTERN_CACHE.get(schema.pattern);
1086
+ let escapedPattern = context.patternCache.get(schema.pattern);
1093
1087
  if (escapedPattern === void 0) {
1094
1088
  escapedPattern = escapePattern(schema.pattern);
1095
- PATTERN_CACHE.set(schema.pattern, escapedPattern);
1089
+ context.patternCache.set(schema.pattern, escapedPattern);
1096
1090
  }
1097
1091
  validation += `.regex(/${escapedPattern}/)`;
1098
1092
  }
@@ -1122,10 +1116,10 @@ function generateStringValidation(schema, useDescribe) {
1122
1116
  validation += `.max(${schema.maxLength})`;
1123
1117
  }
1124
1118
  if (schema.pattern) {
1125
- let escapedPattern = PATTERN_CACHE.get(schema.pattern);
1119
+ let escapedPattern = context.patternCache.get(schema.pattern);
1126
1120
  if (escapedPattern === void 0) {
1127
1121
  escapedPattern = escapePattern(schema.pattern);
1128
- PATTERN_CACHE.set(schema.pattern, escapedPattern);
1122
+ context.patternCache.set(schema.pattern, escapedPattern);
1129
1123
  }
1130
1124
  validation += `.regex(/${escapedPattern}/)`;
1131
1125
  }
@@ -1440,17 +1434,16 @@ var _PropertyGenerator = class _PropertyGenerator {
1440
1434
  return wrapNullable(zodUnion, nullable);
1441
1435
  }
1442
1436
  if (schema.allOf) {
1443
- const explicitNullableFalse = schema.nullable === false;
1437
+ const compositionNullable = isNullable(schema, false);
1444
1438
  let composition = generateAllOf(
1445
1439
  schema.allOf,
1446
- nullable,
1440
+ compositionNullable,
1447
1441
  {
1448
1442
  generatePropertySchema: this.generatePropertySchema.bind(this),
1449
1443
  generateInlineObjectShape: this.generateInlineObjectShape.bind(this),
1450
1444
  resolveSchemaRef: this.resolveSchemaRef.bind(this)
1451
1445
  },
1452
- currentSchema,
1453
- explicitNullableFalse
1446
+ currentSchema
1454
1447
  );
1455
1448
  if (schema.unevaluatedProperties !== void 0) {
1456
1449
  composition = this.applyUnevaluatedProperties(composition, schema);
@@ -1458,11 +1451,12 @@ var _PropertyGenerator = class _PropertyGenerator {
1458
1451
  return composition;
1459
1452
  }
1460
1453
  if (schema.oneOf) {
1454
+ const compositionNullable = isNullable(schema, false);
1461
1455
  const needsPassthrough = schema.unevaluatedProperties !== void 0;
1462
1456
  let composition = generateUnion(
1463
1457
  schema.oneOf,
1464
1458
  (_b = schema.discriminator) == null ? void 0 : _b.propertyName,
1465
- nullable,
1459
+ compositionNullable,
1466
1460
  {
1467
1461
  generatePropertySchema: this.generatePropertySchema.bind(this),
1468
1462
  resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
@@ -1480,11 +1474,12 @@ var _PropertyGenerator = class _PropertyGenerator {
1480
1474
  return composition;
1481
1475
  }
1482
1476
  if (schema.anyOf) {
1477
+ const compositionNullable = isNullable(schema, false);
1483
1478
  const needsPassthrough = schema.unevaluatedProperties !== void 0;
1484
1479
  let composition = generateUnion(
1485
1480
  schema.anyOf,
1486
1481
  (_d = schema.discriminator) == null ? void 0 : _d.propertyName,
1487
- nullable,
1482
+ compositionNullable,
1488
1483
  {
1489
1484
  generatePropertySchema: this.generatePropertySchema.bind(this),
1490
1485
  resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
@@ -1517,7 +1512,10 @@ var _PropertyGenerator = class _PropertyGenerator {
1517
1512
  const primaryType = getPrimaryType(schema);
1518
1513
  switch (primaryType) {
1519
1514
  case "string":
1520
- validation = generateStringValidation(schema, this.context.useDescribe);
1515
+ validation = generateStringValidation(schema, this.context.useDescribe, {
1516
+ dateTimeValidation: this.context.dateTimeValidation,
1517
+ patternCache: this.context.patternCache
1518
+ });
1521
1519
  break;
1522
1520
  case "number":
1523
1521
  validation = generateNumberValidation(schema, false, this.context.useDescribe);
@@ -1819,7 +1817,7 @@ var OpenApiGenerator = class {
1819
1817
  this.schemaUsageMap = /* @__PURE__ */ new Map();
1820
1818
  this.needsZodImport = true;
1821
1819
  this.filterStats = createFilterStatistics();
1822
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1820
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1823
1821
  if (!options.input) {
1824
1822
  throw new ConfigurationError("Input path is required", { providedOptions: options });
1825
1823
  }
@@ -1845,12 +1843,8 @@ var OpenApiGenerator = class {
1845
1843
  batchSize: (_g = options.batchSize) != null ? _g : 10,
1846
1844
  customDateTimeFormatRegex: options.customDateTimeFormatRegex
1847
1845
  };
1848
- if (this.options.cacheSize) {
1849
- configurePatternCache(this.options.cacheSize);
1850
- }
1851
- if (this.options.customDateTimeFormatRegex) {
1852
- configureDateTimeFormat(this.options.customDateTimeFormatRegex);
1853
- }
1846
+ this.patternCache = new LRUCache((_h = this.options.cacheSize) != null ? _h : 1e3);
1847
+ this.dateTimeValidation = buildDateTimeValidation(this.options.customDateTimeFormatRegex);
1854
1848
  try {
1855
1849
  const fs = require("fs");
1856
1850
  if (!fs.existsSync(this.options.input)) {
@@ -1913,13 +1907,15 @@ var OpenApiGenerator = class {
1913
1907
  mode: this.requestOptions.mode,
1914
1908
  includeDescriptions: this.requestOptions.includeDescriptions,
1915
1909
  useDescribe: this.requestOptions.useDescribe,
1916
- defaultNullable: (_h = this.options.defaultNullable) != null ? _h : false,
1917
- emptyObjectBehavior: (_i = this.options.emptyObjectBehavior) != null ? _i : "loose",
1910
+ defaultNullable: (_i = this.options.defaultNullable) != null ? _i : false,
1911
+ emptyObjectBehavior: (_j = this.options.emptyObjectBehavior) != null ? _j : "loose",
1918
1912
  namingOptions: {
1919
1913
  prefix: this.options.prefix,
1920
1914
  suffix: this.options.suffix
1921
1915
  },
1922
- stripSchemaPrefix: this.options.stripSchemaPrefix
1916
+ stripSchemaPrefix: this.options.stripSchemaPrefix,
1917
+ dateTimeValidation: this.dateTimeValidation,
1918
+ patternCache: this.patternCache
1923
1919
  });
1924
1920
  }
1925
1921
  /**
@@ -2300,7 +2296,9 @@ ${typeCode}`;
2300
2296
  prefix: this.options.prefix,
2301
2297
  suffix: this.options.suffix
2302
2298
  },
2303
- stripSchemaPrefix: this.options.stripSchemaPrefix
2299
+ stripSchemaPrefix: this.options.stripSchemaPrefix,
2300
+ dateTimeValidation: this.dateTimeValidation,
2301
+ patternCache: this.patternCache
2304
2302
  });
2305
2303
  const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, true);
2306
2304
  const zodSchemaCode = `${jsdoc}export const ${schemaName} = ${zodSchema};`;