@cerios/openapi-to-zod 1.3.2 → 1.5.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.js CHANGED
@@ -20,369 +20,35 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
- CircularReferenceError: () => CircularReferenceError,
24
- CliOptionsError: () => CliOptionsError,
25
- ConfigValidationError: () => ConfigValidationError,
26
- FileOperationError: () => FileOperationError,
27
- GeneratorError: () => GeneratorError,
23
+ CircularReferenceError: () => import_openapi_core7.CircularReferenceError,
24
+ CliOptionsError: () => import_openapi_core7.CliOptionsError,
25
+ ConfigValidationError: () => import_openapi_core7.ConfigValidationError,
26
+ FileOperationError: () => import_openapi_core7.FileOperationError,
27
+ GeneratorError: () => import_openapi_core7.GeneratorError,
28
28
  OpenApiGenerator: () => OpenApiGenerator,
29
- SchemaGenerationError: () => SchemaGenerationError,
30
- SpecValidationError: () => SpecValidationError,
29
+ PropertyGenerator: () => PropertyGenerator,
30
+ SchemaGenerationError: () => import_openapi_core7.SchemaGenerationError,
31
+ SpecValidationError: () => import_openapi_core7.SpecValidationError,
32
+ buildDateTimeValidation: () => buildDateTimeValidation,
31
33
  defineConfig: () => defineConfig
32
34
  });
33
35
  module.exports = __toCommonJS(src_exports);
36
+ var import_openapi_core7 = require("@cerios/openapi-core");
34
37
 
35
- // src/errors.ts
36
- var GeneratorError = class extends Error {
37
- constructor(message, code, context) {
38
- var _a;
39
- super(message);
40
- this.code = code;
41
- this.context = context;
42
- this.name = "GeneratorError";
43
- (_a = Error.captureStackTrace) == null ? void 0 : _a.call(Error, this, this.constructor);
44
- }
45
- };
46
- var SpecValidationError = class extends GeneratorError {
47
- constructor(message, context) {
48
- super(message, "SPEC_VALIDATION_ERROR", context);
49
- this.name = "SpecValidationError";
50
- }
51
- };
52
- var FileOperationError = class extends GeneratorError {
53
- constructor(message, filePath, context) {
54
- super(message, "FILE_OPERATION_ERROR", { ...context, filePath });
55
- this.filePath = filePath;
56
- this.name = "FileOperationError";
57
- }
58
- };
59
- var ConfigValidationError = class extends GeneratorError {
60
- constructor(message, configPath, context) {
61
- super(message, "CONFIG_VALIDATION_ERROR", { ...context, configPath });
62
- this.configPath = configPath;
63
- this.name = "ConfigValidationError";
64
- }
65
- };
66
- var SchemaGenerationError = class extends GeneratorError {
67
- constructor(message, schemaName, context) {
68
- super(message, "SCHEMA_GENERATION_ERROR", { ...context, schemaName });
69
- this.schemaName = schemaName;
70
- this.name = "SchemaGenerationError";
71
- }
72
- };
73
- var CircularReferenceError = class extends SchemaGenerationError {
74
- constructor(schemaName, referencePath) {
75
- const pathStr = referencePath.join(" -> ");
76
- super(`Circular reference detected in schema: ${pathStr}`, schemaName, { referencePath, circularPath: pathStr });
77
- this.referencePath = referencePath;
78
- this.name = "CircularReferenceError";
79
- }
80
- };
81
- var CliOptionsError = class extends GeneratorError {
82
- constructor(message, context) {
83
- super(message, "CLI_OPTIONS_ERROR", context);
84
- this.name = "CliOptionsError";
85
- }
86
- };
87
- var ConfigurationError = class extends GeneratorError {
88
- constructor(message, context) {
89
- super(message, "CONFIGURATION_ERROR", context);
90
- this.name = "ConfigurationError";
91
- }
92
- };
93
-
94
- // src/openapi-generator.ts
95
- var import_node_fs = require("fs");
96
- var import_node_path = require("path");
97
- var import_minimatch3 = require("minimatch");
98
- var import_yaml = require("yaml");
99
-
100
- // src/utils/name-utils.ts
101
- function sanitizeIdentifier(str) {
102
- return str.replace(/[^a-zA-Z0-9._\-\s]+/g, "_");
103
- }
104
- function toCamelCase(str, options) {
105
- const sanitized = sanitizeIdentifier(str);
106
- const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
107
- let name;
108
- if (words.length === 0) {
109
- name = str.charAt(0).toLowerCase() + str.slice(1);
110
- } else if (words.length === 1) {
111
- name = words[0].charAt(0).toLowerCase() + words[0].slice(1);
112
- } else {
113
- name = words[0].charAt(0).toLowerCase() + words[0].slice(1) + words.slice(1).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
114
- }
115
- if (options == null ? void 0 : options.prefix) {
116
- const prefix = options.prefix.charAt(0).toLowerCase() + options.prefix.slice(1);
117
- name = prefix + name.charAt(0).toUpperCase() + name.slice(1);
118
- }
119
- if (options == null ? void 0 : options.suffix) {
120
- const suffix = options.suffix.charAt(0).toUpperCase() + options.suffix.slice(1);
121
- name = name + suffix;
122
- }
123
- return name;
124
- }
125
- function toPascalCase(str) {
126
- const stringValue = String(str);
127
- const isAlreadyValidCase = /^[a-zA-Z][a-zA-Z0-9]*$/.test(stringValue);
128
- if (isAlreadyValidCase) {
129
- return stringValue.charAt(0).toUpperCase() + stringValue.slice(1);
130
- }
131
- const sanitized = sanitizeIdentifier(stringValue);
132
- const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
133
- let result;
134
- if (words.length === 0) {
135
- result = "Value";
136
- } else {
137
- result = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
138
- }
139
- if (/^\d/.test(result)) {
140
- result = `N${result}`;
141
- }
142
- if (!result || /^_+$/.test(result)) {
143
- return "Value";
144
- }
145
- return result;
146
- }
147
- function resolveRef(ref) {
148
- const parts = ref.split("/");
149
- return parts[parts.length - 1];
150
- }
151
-
152
- // src/generators/enum-generator.ts
153
- function generateEnum(name, values, options) {
154
- const schemaName = `${toCamelCase(name, options)}Schema`;
155
- const typeName = toPascalCase(name);
156
- const allBooleans = values.every((v) => typeof v === "boolean");
157
- if (allBooleans) {
158
- const schemaCode2 = `export const ${schemaName} = z.boolean();`;
159
- const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
160
- return { schemaCode: schemaCode2, typeCode: typeCode2 };
161
- }
162
- const allStrings = values.every((v) => typeof v === "string");
163
- if (allStrings) {
164
- const enumValues = values.map((v) => `"${v}"`).join(", ");
165
- const schemaCode2 = `export const ${schemaName} = z.enum([${enumValues}]);`;
166
- const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
167
- return { schemaCode: schemaCode2, typeCode: typeCode2 };
168
- }
169
- const literalValues = values.map((v) => {
170
- if (typeof v === "string") {
171
- return `z.literal("${v}")`;
172
- }
173
- return `z.literal(${v})`;
174
- }).join(", ");
175
- const schemaCode = `export const ${schemaName} = z.union([${literalValues}]);`;
176
- const typeCode = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
177
- return { schemaCode, typeCode };
178
- }
38
+ // src/generators/property-generator.ts
39
+ var import_openapi_core4 = require("@cerios/openapi-core");
179
40
 
180
41
  // src/utils/string-utils.ts
181
- function escapeDescription(str) {
182
- return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
183
- }
184
- function escapePattern(str) {
185
- return str.replace(/\//g, "\\/");
186
- }
187
- function escapeJSDoc(str) {
188
- return str.replace(/\*\//g, "*\\/");
189
- }
190
- function wrapNullable(validation, isNullable2) {
191
- return isNullable2 ? `${validation}.nullable()` : validation;
192
- }
193
- function isNullable(schema, defaultNullable = false) {
194
- if (schema.nullable === true) {
195
- return true;
196
- }
197
- if (schema.nullable === false) {
198
- return false;
199
- }
200
- if (Array.isArray(schema.type)) {
201
- return schema.type.includes("null");
202
- }
203
- return defaultNullable;
204
- }
205
- function getPrimaryType(schema) {
206
- if (Array.isArray(schema.type)) {
207
- const nonNullType = schema.type.find((t) => t !== "null");
208
- return nonNullType;
209
- }
210
- return schema.type;
211
- }
212
- function hasMultipleTypes(schema) {
213
- if (Array.isArray(schema.type)) {
214
- const nonNullTypes = schema.type.filter((t) => t !== "null");
215
- return nonNullTypes.length > 1;
216
- }
217
- return false;
42
+ var import_openapi_core = require("@cerios/openapi-core");
43
+ function wrapNullable(validation, nullable) {
44
+ return nullable ? `${validation}.nullable()` : validation;
218
45
  }
219
46
  function addDescription(validation, description, useDescribe) {
220
47
  if (!description || !useDescribe) return validation;
221
- const escapedDesc = escapeDescription(description);
48
+ const escapedDesc = (0, import_openapi_core.escapeDescription)(description);
222
49
  return `${validation}.describe("${escapedDesc}")`;
223
50
  }
224
51
 
225
- // src/generators/jsdoc-generator.ts
226
- function generateJSDoc(schema, name, options = { includeDescriptions: true }) {
227
- if (!schema || typeof schema !== "object") {
228
- return "";
229
- }
230
- if (!options.includeDescriptions) {
231
- if (schema.deprecated) {
232
- return "/** @deprecated */\n";
233
- }
234
- return "";
235
- }
236
- if (!schema.description && !schema.title && !schema.deprecated && !schema.examples && schema.example === void 0) {
237
- return "";
238
- }
239
- const parts = [];
240
- if (schema.title && typeof schema.title === "string" && (!name || schema.title !== name)) {
241
- const sanitizedTitle = escapeJSDoc(schema.title).replace(/@/g, "\\@");
242
- parts.push(sanitizedTitle);
243
- }
244
- if (schema.description && typeof schema.description === "string") {
245
- const sanitizedDesc = escapeJSDoc(schema.description).replace(/@/g, "\\@").replace(/\*\//g, "*\\/");
246
- parts.push(sanitizedDesc);
247
- }
248
- if (schema.examples && Array.isArray(schema.examples) && schema.examples.length > 0) {
249
- try {
250
- const examplesStr = schema.examples.map((ex) => JSON.stringify(ex)).join(", ");
251
- parts.push(`@example ${examplesStr}`);
252
- } catch (error) {
253
- console.warn("Warning: Could not serialize schema examples", error);
254
- }
255
- } else if (schema.example !== void 0) {
256
- try {
257
- parts.push(`@example ${JSON.stringify(schema.example)}`);
258
- } catch (error) {
259
- console.warn("Warning: Could not serialize schema example", error);
260
- }
261
- }
262
- if (schema.deprecated) {
263
- parts.push("@deprecated");
264
- }
265
- if (parts.length === 0) {
266
- return "";
267
- }
268
- const fullComment = parts.join(" ");
269
- return `/** ${fullComment} */
270
- `;
271
- }
272
-
273
- // src/utils/lru-cache.ts
274
- var LRUCache = class {
275
- constructor(maxSize) {
276
- this.cache = /* @__PURE__ */ new Map();
277
- this.maxSize = maxSize;
278
- }
279
- get capacity() {
280
- return this.maxSize;
281
- }
282
- get(key) {
283
- if (!this.cache.has(key)) return void 0;
284
- const value = this.cache.get(key);
285
- if (value === void 0) return void 0;
286
- this.cache.delete(key);
287
- this.cache.set(key, value);
288
- return value;
289
- }
290
- set(key, value) {
291
- if (this.cache.has(key)) {
292
- this.cache.delete(key);
293
- } else if (this.cache.size >= this.maxSize) {
294
- const firstKey = this.cache.keys().next().value;
295
- if (firstKey !== void 0) {
296
- this.cache.delete(firstKey);
297
- }
298
- }
299
- this.cache.set(key, value);
300
- }
301
- has(key) {
302
- return this.cache.has(key);
303
- }
304
- clear() {
305
- this.cache.clear();
306
- }
307
- size() {
308
- return this.cache.size;
309
- }
310
- };
311
-
312
- // src/utils/pattern-utils.ts
313
- var import_minimatch = require("minimatch");
314
- function isValidGlobPattern(pattern) {
315
- try {
316
- new import_minimatch.minimatch.Minimatch(pattern);
317
- return true;
318
- } catch {
319
- return false;
320
- }
321
- }
322
- function isGlobPattern(pattern) {
323
- return /[*?[\]{}!]/.test(pattern);
324
- }
325
- function stripPrefix(input, pattern, ensureLeadingChar) {
326
- if (!pattern) {
327
- return input;
328
- }
329
- if (isGlobPattern(pattern) && !isValidGlobPattern(pattern)) {
330
- console.warn(`\u26A0\uFE0F Invalid glob pattern "${pattern}": Pattern is malformed`);
331
- return input;
332
- }
333
- if (isGlobPattern(pattern)) {
334
- let longestMatch = -1;
335
- for (let i = 1; i <= input.length; i++) {
336
- const testPrefix = input.substring(0, i);
337
- if ((0, import_minimatch.minimatch)(testPrefix, pattern)) {
338
- longestMatch = i;
339
- }
340
- }
341
- if (longestMatch > 0) {
342
- const stripped = input.substring(longestMatch);
343
- if (ensureLeadingChar) {
344
- if (stripped === "") {
345
- return ensureLeadingChar;
346
- }
347
- if (!stripped.startsWith(ensureLeadingChar)) {
348
- return `${ensureLeadingChar}${stripped}`;
349
- }
350
- }
351
- return stripped === "" && !ensureLeadingChar ? input : stripped;
352
- }
353
- return input;
354
- }
355
- if (input.startsWith(pattern)) {
356
- const stripped = input.substring(pattern.length);
357
- if (ensureLeadingChar) {
358
- if (stripped === "") {
359
- return ensureLeadingChar;
360
- }
361
- if (!stripped.startsWith(ensureLeadingChar)) {
362
- return `${ensureLeadingChar}${stripped}`;
363
- }
364
- }
365
- return stripped;
366
- }
367
- return input;
368
- }
369
- function stripPathPrefix(path, pattern) {
370
- if (!pattern) {
371
- return path;
372
- }
373
- if (!isGlobPattern(pattern)) {
374
- let normalizedPattern = pattern.trim();
375
- if (!normalizedPattern.startsWith("/")) {
376
- normalizedPattern = `/${normalizedPattern}`;
377
- }
378
- if (normalizedPattern.endsWith("/") && normalizedPattern !== "/") {
379
- normalizedPattern = normalizedPattern.slice(0, -1);
380
- }
381
- return stripPrefix(path, normalizedPattern, "/");
382
- }
383
- return stripPrefix(path, pattern, "/");
384
- }
385
-
386
52
  // src/validators/array-validator.ts
387
53
  function generateArrayValidation(schema, context) {
388
54
  var _a;
@@ -550,15 +216,14 @@ function detectConflictingProperties(schemas, context) {
550
216
  function generateAllOf(schemas, isNullable2, context, currentSchema) {
551
217
  if (schemas.length === 1) {
552
218
  const singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false, true);
553
- return wrapNullable(singleSchema, isNullable2);
219
+ return { schema: wrapNullable(singleSchema, isNullable2), conflicts: [] };
554
220
  }
555
221
  const conflicts = detectConflictingProperties(schemas, context);
556
- let conflictDescription = "";
557
- if (conflicts.length > 0) {
558
- for (const conflict of conflicts) {
222
+ const uniqueConflicts = [...new Set(conflicts)];
223
+ if (uniqueConflicts.length > 0) {
224
+ for (const conflict of uniqueConflicts) {
559
225
  console.warn(`[openapi-to-zod] Warning: allOf composition conflict - ${conflict}`);
560
226
  }
561
- conflictDescription = `allOf property conflicts detected: ${conflicts.join("; ")}`;
562
227
  }
563
228
  const allObjects = schemas.every((s) => s.type === "object" || s.properties || s.$ref || s.allOf);
564
229
  let result;
@@ -586,10 +251,7 @@ function generateAllOf(schemas, isNullable2, context, currentSchema) {
586
251
  }
587
252
  result = merged;
588
253
  }
589
- if (conflictDescription) {
590
- result = `${result}.describe("${conflictDescription}")`;
591
- }
592
- return wrapNullable(result, isNullable2);
254
+ return { schema: wrapNullable(result, isNullable2), conflicts: uniqueConflicts };
593
255
  }
594
256
 
595
257
  // src/validators/number-validator.ts
@@ -613,6 +275,53 @@ function generateNumberValidation(schema, isInt, useDescribe) {
613
275
  return addDescription(validation, schema.description, useDescribe);
614
276
  }
615
277
 
278
+ // src/generators/jsdoc-generator.ts
279
+ var import_openapi_core2 = require("@cerios/openapi-core");
280
+ function generateJSDoc(schema, name, options = { includeDescriptions: true }) {
281
+ if (!schema || typeof schema !== "object") {
282
+ return "";
283
+ }
284
+ if (!options.includeDescriptions) {
285
+ if (schema.deprecated) {
286
+ return "/** @deprecated */\n";
287
+ }
288
+ return "";
289
+ }
290
+ if (!schema.description && !schema.title && !schema.deprecated && !schema.examples && schema.example === void 0) {
291
+ return "";
292
+ }
293
+ const parts = [];
294
+ if (schema.title && typeof schema.title === "string" && (!name || schema.title !== name)) {
295
+ parts.push((0, import_openapi_core2.escapeJSDoc)(schema.title));
296
+ }
297
+ if (schema.description && typeof schema.description === "string") {
298
+ parts.push((0, import_openapi_core2.escapeJSDoc)(schema.description));
299
+ }
300
+ if (schema.examples && Array.isArray(schema.examples) && schema.examples.length > 0) {
301
+ try {
302
+ const examplesStr = schema.examples.map((ex) => JSON.stringify(ex)).join(", ");
303
+ parts.push(`@example ${examplesStr}`);
304
+ } catch (error) {
305
+ console.warn("Warning: Could not serialize schema examples", error);
306
+ }
307
+ } else if (schema.example !== void 0) {
308
+ try {
309
+ parts.push(`@example ${JSON.stringify(schema.example)}`);
310
+ } catch (error) {
311
+ console.warn("Warning: Could not serialize schema example", error);
312
+ }
313
+ }
314
+ if (schema.deprecated) {
315
+ parts.push("@deprecated");
316
+ }
317
+ if (parts.length === 0) {
318
+ return "";
319
+ }
320
+ const fullComment = parts.join(" ");
321
+ return `/** ${fullComment} */
322
+ `;
323
+ }
324
+
616
325
  // src/validators/conditional-validator.ts
617
326
  function generatePropertyAccess(propName) {
618
327
  const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
@@ -671,7 +380,8 @@ function generateConditionalCheck(schema) {
671
380
  for (const [prop, propSchema] of Object.entries(schema.properties)) {
672
381
  const propAccess = generatePropertyAccess(prop);
673
382
  if (propSchema.type) {
674
- conditions.push(`typeof ${propAccess} === "${propSchema.type}"`);
383
+ const schemaType = Array.isArray(propSchema.type) ? propSchema.type[0] : propSchema.type;
384
+ conditions.push(`typeof ${propAccess} === "${schemaType}"`);
675
385
  }
676
386
  if (propSchema.const !== void 0) {
677
387
  const value = typeof propSchema.const === "string" ? `"${propSchema.const}"` : propSchema.const;
@@ -730,7 +440,7 @@ function generateIfThenElse(schema) {
730
440
  if (!thenValid) {
731
441
  ${thenRequiredProps.length > 0 ? `
732
442
  const missingThenProps = ${JSON.stringify(thenRequiredProps)}.filter(p => obj[p] === undefined);
733
- const message = missingThenProps.length > 0
443
+ const message = missingThenProps.length > 0
734
444
  ? \`When condition is met, required properties are missing: \${missingThenProps.join(', ')}\`
735
445
  : "When condition is met, validation constraints failed";
736
446
  ` : `
@@ -748,7 +458,7 @@ function generateIfThenElse(schema) {
748
458
  if (!elseValid) {
749
459
  ${elseRequiredProps2.length > 0 ? `
750
460
  const missingElseProps = ${JSON.stringify(elseRequiredProps2)}.filter(p => obj[p] === undefined);
751
- const message = missingElseProps.length > 0
461
+ const message = missingElseProps.length > 0
752
462
  ? \`When condition is not met, required properties are missing: \${missingElseProps.join(', ')}\`
753
463
  : "When condition is not met, validation constraints failed";
754
464
  ` : `
@@ -773,7 +483,7 @@ function generateIfThenElse(schema) {
773
483
  if (!thenValid) {
774
484
  ${thenRequiredProps.length > 0 ? `
775
485
  const missingProps = ${JSON.stringify(thenRequiredProps)}.filter(p => obj[p] === undefined);
776
- const message = missingProps.length > 0
486
+ const message = missingProps.length > 0
777
487
  ? \`When condition is met, required properties are missing: \${missingProps.join(', ')}\`
778
488
  : "When condition is met, validation constraints failed";
779
489
  ` : `
@@ -798,7 +508,7 @@ function generateIfThenElse(schema) {
798
508
  if (!elseValid) {
799
509
  ${elseRequiredProps.length > 0 ? `
800
510
  const missingProps = ${JSON.stringify(elseRequiredProps)}.filter(p => obj[p] === undefined);
801
- const message = missingProps.length > 0
511
+ const message = missingProps.length > 0
802
512
  ? \`When condition is not met, required properties are missing: \${missingProps.join(', ')}\`
803
513
  : "When condition is not met, validation constraints failed";
804
514
  ` : `
@@ -886,8 +596,9 @@ ${propertyDef}`);
886
596
  case "loose":
887
597
  objectMethod = "z.looseObject";
888
598
  break;
889
- default:
599
+ case "normal":
890
600
  objectMethod = "z.object";
601
+ break;
891
602
  }
892
603
  }
893
604
  let objectDef = `${objectMethod}({
@@ -897,7 +608,7 @@ ${properties.join(",\n")}
897
608
  if (typeof schema.additionalProperties === "object") {
898
609
  const additionalSchema = context.generatePropertySchema(schema.additionalProperties, currentSchema);
899
610
  objectDef += `.catchall(${additionalSchema})`;
900
- } else if (schema.additionalProperties === true) {
611
+ } else if (schema.additionalProperties) {
901
612
  objectDef += ".catchall(z.unknown())";
902
613
  }
903
614
  } else if (schema.patternProperties) {
@@ -1022,12 +733,7 @@ ${properties.join(",\n")}
1022
733
  }
1023
734
 
1024
735
  // 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
- }
736
+ var import_openapi_core3 = require("@cerios/openapi-core");
1031
737
  var DEFAULT_FORMAT_MAP = {
1032
738
  uuid: "z.uuid()",
1033
739
  email: "z.email()",
@@ -1056,19 +762,13 @@ var DEFAULT_FORMAT_MAP = {
1056
762
  "json-pointer": 'z.string().refine((val) => val === "" || /^(\\/([^~/]|~0|~1)+)+$/.test(val), { message: "Must be a valid JSON Pointer (RFC 6901)" })',
1057
763
  "relative-json-pointer": 'z.string().refine((val) => /^(0|[1-9]\\d*)(#|(\\/([^~/]|~0|~1)+)*)$/.test(val), { message: "Must be a valid relative JSON Pointer" })'
1058
764
  };
1059
- var FORMAT_MAP = {
1060
- ...DEFAULT_FORMAT_MAP,
1061
- "date-time": "z.iso.datetime()"
1062
- };
1063
- function configureDateTimeFormat(pattern) {
765
+ function buildDateTimeValidation(pattern) {
1064
766
  if (!pattern) {
1065
- FORMAT_MAP["date-time"] = "z.iso.datetime()";
1066
- return;
767
+ return "z.iso.datetime()";
1067
768
  }
1068
769
  const patternStr = pattern instanceof RegExp ? pattern.source : pattern;
1069
770
  if (patternStr === "") {
1070
- FORMAT_MAP["date-time"] = "z.iso.datetime()";
1071
- return;
771
+ return "z.iso.datetime()";
1072
772
  }
1073
773
  try {
1074
774
  new RegExp(patternStr);
@@ -1077,11 +777,17 @@ function configureDateTimeFormat(pattern) {
1077
777
  `Invalid regular expression pattern for customDateTimeFormatRegex: ${patternStr}. ${error instanceof Error ? error.message : "Pattern is malformed"}`
1078
778
  );
1079
779
  }
1080
- const escapedPattern = escapePattern(patternStr);
1081
- FORMAT_MAP["date-time"] = `z.string().regex(/${escapedPattern}/)`;
780
+ const escapedPattern = (0, import_openapi_core3.escapePattern)(patternStr);
781
+ return `z.string().regex(/${escapedPattern}/)`;
1082
782
  }
1083
- function generateStringValidation(schema, useDescribe) {
1084
- let validation = FORMAT_MAP[schema.format || ""] || "z.string()";
783
+ function generateStringValidation(schema, useDescribe, context) {
784
+ let validation;
785
+ const format = schema.format || "";
786
+ if (format === "date-time") {
787
+ validation = context.dateTimeValidation;
788
+ } else {
789
+ validation = DEFAULT_FORMAT_MAP[format] || "z.string()";
790
+ }
1085
791
  if (schema.minLength !== void 0) {
1086
792
  validation += `.min(${schema.minLength})`;
1087
793
  }
@@ -1089,10 +795,10 @@ function generateStringValidation(schema, useDescribe) {
1089
795
  validation += `.max(${schema.maxLength})`;
1090
796
  }
1091
797
  if (schema.pattern) {
1092
- let escapedPattern = PATTERN_CACHE.get(schema.pattern);
798
+ let escapedPattern = context.patternCache.get(schema.pattern);
1093
799
  if (escapedPattern === void 0) {
1094
- escapedPattern = escapePattern(schema.pattern);
1095
- PATTERN_CACHE.set(schema.pattern, escapedPattern);
800
+ escapedPattern = (0, import_openapi_core3.escapePattern)(schema.pattern);
801
+ context.patternCache.set(schema.pattern, escapedPattern);
1096
802
  }
1097
803
  validation += `.regex(/${escapedPattern}/)`;
1098
804
  }
@@ -1122,10 +828,10 @@ function generateStringValidation(schema, useDescribe) {
1122
828
  validation += `.max(${schema.maxLength})`;
1123
829
  }
1124
830
  if (schema.pattern) {
1125
- let escapedPattern = PATTERN_CACHE.get(schema.pattern);
831
+ let escapedPattern = context.patternCache.get(schema.pattern);
1126
832
  if (escapedPattern === void 0) {
1127
- escapedPattern = escapePattern(schema.pattern);
1128
- PATTERN_CACHE.set(schema.pattern, escapedPattern);
833
+ escapedPattern = (0, import_openapi_core3.escapePattern)(schema.pattern);
834
+ context.patternCache.set(schema.pattern, escapedPattern);
1129
835
  }
1130
836
  validation += `.regex(/${escapedPattern}/)`;
1131
837
  }
@@ -1152,9 +858,33 @@ var _PropertyGenerator = class _PropertyGenerator {
1152
858
  // Performance optimization: Memoize filtered property results
1153
859
  this.filteredPropsCache = /* @__PURE__ */ new Map();
1154
860
  // Performance optimization: LRU cache for generated schemas
1155
- this.schemaCache = new LRUCache(500);
861
+ this.schemaCache = new import_openapi_core4.LRUCache(500);
862
+ // Track allOf conflicts detected during schema generation
863
+ this.allOfConflicts = [];
864
+ // Schemas that are part of circular dependency chains (need z.lazy for forward refs)
865
+ this.circularDependencies = /* @__PURE__ */ new Set();
1156
866
  this.context = context;
1157
867
  }
868
+ /**
869
+ * Set the schemas that are involved in circular dependency chains.
870
+ * These schemas will use z.lazy() for forward references.
871
+ */
872
+ setCircularDependencies(deps) {
873
+ this.circularDependencies = deps;
874
+ }
875
+ /**
876
+ * Get allOf conflicts detected during the last schema generation
877
+ * @returns Array of conflict description strings
878
+ */
879
+ getAllOfConflicts() {
880
+ return [...this.allOfConflicts];
881
+ }
882
+ /**
883
+ * Clear tracked allOf conflicts (call before generating a new schema)
884
+ */
885
+ clearAllOfConflicts() {
886
+ this.allOfConflicts = [];
887
+ }
1158
888
  /**
1159
889
  * Check if a property should be included based on schemaType and readOnly/writeOnly flags
1160
890
  */
@@ -1187,7 +917,9 @@ var _PropertyGenerator = class _PropertyGenerator {
1187
917
  filterNestedProperties(schema) {
1188
918
  var _a, _b;
1189
919
  const propKeys = schema.properties ? Object.keys(schema.properties).sort().join(",") : "";
1190
- const cacheKey = `${this.context.schemaType}:${schema.type || "unknown"}:${propKeys}:${((_a = schema.required) == null ? void 0 : _a.join(",")) || ""}`;
920
+ const requiredKeys = Array.isArray(schema.required) ? schema.required.join(",") : String((_a = schema.required) != null ? _a : "");
921
+ const schemaType = Array.isArray(schema.type) ? schema.type.join("|") : schema.type || "unknown";
922
+ const cacheKey = `${this.context.schemaType}:${schemaType}:${propKeys}:${requiredKeys}`;
1191
923
  const cached = this.filteredPropsCache.get(cacheKey);
1192
924
  if (cached) {
1193
925
  return cached;
@@ -1283,7 +1015,7 @@ var _PropertyGenerator = class _PropertyGenerator {
1283
1015
  const schema = (_b = (_a = this.context.spec.components) == null ? void 0 : _a.schemas) == null ? void 0 : _b[schemaName];
1284
1016
  if (!schema) return schemaName;
1285
1017
  if (schema.allOf && schema.allOf.length === 1 && schema.allOf[0].$ref && !schema.properties && !schema.oneOf && !schema.anyOf) {
1286
- const targetName = resolveRef(schema.allOf[0].$ref);
1018
+ const targetName = (0, import_openapi_core4.resolveRefName)(schema.allOf[0].$ref);
1287
1019
  return this.resolveSchemaAlias(targetName);
1288
1020
  }
1289
1021
  return schemaName;
@@ -1296,7 +1028,7 @@ var _PropertyGenerator = class _PropertyGenerator {
1296
1028
  const toSchemaSpec = (_b = (_a = this.context.spec.components) == null ? void 0 : _a.schemas) == null ? void 0 : _b[toSchema];
1297
1029
  if (!toSchemaSpec) return false;
1298
1030
  if (toSchemaSpec.allOf && toSchemaSpec.allOf.length === 1 && toSchemaSpec.allOf[0].$ref) {
1299
- const aliasTarget = resolveRef(toSchemaSpec.allOf[0].$ref);
1031
+ const aliasTarget = (0, import_openapi_core4.resolveRefName)(toSchemaSpec.allOf[0].$ref);
1300
1032
  return aliasTarget === fromSchema;
1301
1033
  }
1302
1034
  return false;
@@ -1391,13 +1123,13 @@ var _PropertyGenerator = class _PropertyGenerator {
1391
1123
  const isConst = schema.const !== void 0;
1392
1124
  const shouldApplyDefaultNullable = !isTopLevel && !isEnum && !isConst && !suppressDefaultNullable;
1393
1125
  const effectiveDefaultNullable = shouldApplyDefaultNullable ? this.context.defaultNullable : false;
1394
- const nullable = isNullable(schema, effectiveDefaultNullable);
1395
- if (hasMultipleTypes(schema)) {
1126
+ const nullable = (0, import_openapi_core4.isNullable)(schema, effectiveDefaultNullable);
1127
+ if ((0, import_openapi_core4.hasMultipleTypes)(schema)) {
1396
1128
  const union = this.generateMultiTypeUnion(schema, currentSchema);
1397
1129
  return wrapNullable(union, nullable);
1398
1130
  }
1399
1131
  if (schema.$ref) {
1400
- const refName = resolveRef(schema.$ref);
1132
+ const refName = (0, import_openapi_core4.resolveRefName)(schema.$ref);
1401
1133
  const resolvedRefName = this.resolveSchemaAlias(refName);
1402
1134
  if (currentSchema && refName !== currentSchema && !isTopLevel) {
1403
1135
  if (!this.context.schemaDependencies.has(currentSchema)) {
@@ -1405,10 +1137,15 @@ var _PropertyGenerator = class _PropertyGenerator {
1405
1137
  }
1406
1138
  (_a = this.context.schemaDependencies.get(currentSchema)) == null ? void 0 : _a.add(refName);
1407
1139
  }
1408
- const strippedRefName = stripPrefix(resolvedRefName, this.context.stripSchemaPrefix);
1409
- const schemaName = `${toCamelCase(strippedRefName, this.context.namingOptions)}Schema`;
1410
- if (currentSchema && (refName === currentSchema || this.isCircularThroughAlias(currentSchema, refName))) {
1411
- const lazySchema = `z.lazy((): z.ZodTypeAny => ${schemaName})`;
1140
+ const strippedRefName = (0, import_openapi_core4.stripPrefix)(resolvedRefName, this.context.stripSchemaPrefix);
1141
+ const schemaName = `${(0, import_openapi_core4.toCamelCase)(strippedRefName, this.context.namingOptions)}Schema`;
1142
+ const typeName = (0, import_openapi_core4.toPascalCase)(strippedRefName);
1143
+ const isDirectSelfRef = currentSchema && refName === currentSchema;
1144
+ const isCircularAlias = currentSchema && this.isCircularThroughAlias(currentSchema, refName);
1145
+ const isMutuallyCircular = currentSchema && this.circularDependencies.has(currentSchema) && this.circularDependencies.has(refName);
1146
+ if (isDirectSelfRef || isCircularAlias || isMutuallyCircular) {
1147
+ const lazyTypeAnnotation = this.context.separateTypesFile ? `z.ZodType<${typeName}>` : "z.ZodTypeAny";
1148
+ const lazySchema = `z.lazy((): ${lazyTypeAnnotation} => ${schemaName})`;
1412
1149
  return wrapNullable(lazySchema, nullable);
1413
1150
  }
1414
1151
  return wrapNullable(schemaName, nullable);
@@ -1440,8 +1177,8 @@ var _PropertyGenerator = class _PropertyGenerator {
1440
1177
  return wrapNullable(zodUnion, nullable);
1441
1178
  }
1442
1179
  if (schema.allOf) {
1443
- const compositionNullable = isNullable(schema, false);
1444
- let composition = generateAllOf(
1180
+ const compositionNullable = (0, import_openapi_core4.isNullable)(schema, false);
1181
+ const allOfResult = generateAllOf(
1445
1182
  schema.allOf,
1446
1183
  compositionNullable,
1447
1184
  {
@@ -1451,13 +1188,17 @@ var _PropertyGenerator = class _PropertyGenerator {
1451
1188
  },
1452
1189
  currentSchema
1453
1190
  );
1191
+ if (allOfResult.conflicts.length > 0) {
1192
+ this.allOfConflicts.push(...allOfResult.conflicts);
1193
+ }
1194
+ let composition = allOfResult.schema;
1454
1195
  if (schema.unevaluatedProperties !== void 0) {
1455
1196
  composition = this.applyUnevaluatedProperties(composition, schema);
1456
1197
  }
1457
1198
  return composition;
1458
1199
  }
1459
1200
  if (schema.oneOf) {
1460
- const compositionNullable = isNullable(schema, false);
1201
+ const compositionNullable = (0, import_openapi_core4.isNullable)(schema, false);
1461
1202
  const needsPassthrough = schema.unevaluatedProperties !== void 0;
1462
1203
  let composition = generateUnion(
1463
1204
  schema.oneOf,
@@ -1480,7 +1221,7 @@ var _PropertyGenerator = class _PropertyGenerator {
1480
1221
  return composition;
1481
1222
  }
1482
1223
  if (schema.anyOf) {
1483
- const compositionNullable = isNullable(schema, false);
1224
+ const compositionNullable = (0, import_openapi_core4.isNullable)(schema, false);
1484
1225
  const needsPassthrough = schema.unevaluatedProperties !== void 0;
1485
1226
  let composition = generateUnion(
1486
1227
  schema.anyOf,
@@ -1515,10 +1256,13 @@ var _PropertyGenerator = class _PropertyGenerator {
1515
1256
  return wrapNullable(refined, nullable);
1516
1257
  }
1517
1258
  let validation = "";
1518
- const primaryType = getPrimaryType(schema);
1259
+ const primaryType = (0, import_openapi_core4.getPrimaryType)(schema);
1519
1260
  switch (primaryType) {
1520
1261
  case "string":
1521
- validation = generateStringValidation(schema, this.context.useDescribe);
1262
+ validation = generateStringValidation(schema, this.context.useDescribe, {
1263
+ dateTimeValidation: this.context.dateTimeValidation,
1264
+ patternCache: this.context.patternCache
1265
+ });
1522
1266
  break;
1523
1267
  case "number":
1524
1268
  validation = generateNumberValidation(schema, false, this.context.useDescribe);
@@ -1559,13 +1303,14 @@ var _PropertyGenerator = class _PropertyGenerator {
1559
1303
  case "loose":
1560
1304
  validation = "z.looseObject({})";
1561
1305
  break;
1562
- default:
1306
+ case "record":
1563
1307
  validation = "z.record(z.string(), z.unknown())";
1564
1308
  break;
1565
1309
  }
1566
1310
  validation = addDescription(validation, schema.description, this.context.useDescribe);
1567
1311
  }
1568
1312
  break;
1313
+ case void 0:
1569
1314
  default:
1570
1315
  validation = "z.unknown()";
1571
1316
  validation = addDescription(validation, schema.description, this.context.useDescribe);
@@ -1624,194 +1369,50 @@ _PropertyGenerator.INCLUSION_RULES = {
1624
1369
  };
1625
1370
  var PropertyGenerator = _PropertyGenerator;
1626
1371
 
1627
- // src/utils/operation-filters.ts
1628
- var import_minimatch2 = require("minimatch");
1629
- function createFilterStatistics() {
1630
- return {
1631
- totalOperations: 0,
1632
- includedOperations: 0,
1633
- filteredByTags: 0,
1634
- filteredByPaths: 0,
1635
- filteredByMethods: 0,
1636
- filteredByOperationIds: 0,
1637
- filteredByDeprecated: 0
1638
- };
1639
- }
1640
- function matchesAnyPattern(value, patterns) {
1641
- if (!patterns || patterns.length === 0) {
1642
- return false;
1643
- }
1644
- if (!value) {
1645
- return false;
1646
- }
1647
- return patterns.some((pattern) => (0, import_minimatch2.minimatch)(value, pattern));
1648
- }
1649
- function containsAny(arr, values) {
1650
- if (!values || values.length === 0) {
1651
- return false;
1372
+ // src/openapi-generator.ts
1373
+ var import_node_fs = require("fs");
1374
+ var import_node_path = require("path");
1375
+ var import_openapi_core6 = require("@cerios/openapi-core");
1376
+ var import_openapi_to_typescript = require("@cerios/openapi-to-typescript");
1377
+ var import_minimatch = require("minimatch");
1378
+
1379
+ // src/generators/enum-generator.ts
1380
+ var import_openapi_core5 = require("@cerios/openapi-core");
1381
+ function generateEnum(name, values, options) {
1382
+ const schemaName = `${(0, import_openapi_core5.toCamelCase)(name, options)}Schema`;
1383
+ const typeName = (0, import_openapi_core5.toPascalCase)(name);
1384
+ const allBooleans = values.every((v) => typeof v === "boolean");
1385
+ if (allBooleans) {
1386
+ const schemaCode2 = `export const ${schemaName} = z.boolean();`;
1387
+ const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
1388
+ return { schemaCode: schemaCode2, typeCode: typeCode2 };
1652
1389
  }
1653
- if (!arr || arr.length === 0) {
1654
- return false;
1390
+ const allStrings = values.every((v) => typeof v === "string");
1391
+ if (allStrings) {
1392
+ const enumValues = values.map((v) => `"${v}"`).join(", ");
1393
+ const schemaCode2 = `export const ${schemaName} = z.enum([${enumValues}]);`;
1394
+ const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
1395
+ return { schemaCode: schemaCode2, typeCode: typeCode2 };
1655
1396
  }
1656
- return values.some((value) => arr.includes(value));
1657
- }
1658
- function shouldIncludeOperation(operation, path, method, filters, stats) {
1659
- if (!filters) {
1660
- return true;
1661
- }
1662
- const methodLower = method.toLowerCase();
1663
- const operationId = operation == null ? void 0 : operation.operationId;
1664
- const tags = (operation == null ? void 0 : operation.tags) || [];
1665
- const deprecated = (operation == null ? void 0 : operation.deprecated) === true;
1666
- if (filters.includeTags && filters.includeTags.length > 0) {
1667
- if (!containsAny(tags, filters.includeTags)) {
1668
- if (stats) stats.filteredByTags++;
1669
- return false;
1670
- }
1671
- }
1672
- if (filters.includePaths && filters.includePaths.length > 0) {
1673
- if (!matchesAnyPattern(path, filters.includePaths)) {
1674
- if (stats) stats.filteredByPaths++;
1675
- return false;
1676
- }
1677
- }
1678
- if (filters.includeMethods && filters.includeMethods.length > 0) {
1679
- const methodsLower = filters.includeMethods.map((m) => m.toLowerCase());
1680
- if (!methodsLower.includes(methodLower)) {
1681
- if (stats) stats.filteredByMethods++;
1682
- return false;
1683
- }
1684
- }
1685
- if (filters.includeOperationIds && filters.includeOperationIds.length > 0) {
1686
- if (!matchesAnyPattern(operationId, filters.includeOperationIds)) {
1687
- if (stats) stats.filteredByOperationIds++;
1688
- return false;
1689
- }
1690
- }
1691
- if (filters.excludeDeprecated === true && deprecated) {
1692
- if (stats) stats.filteredByDeprecated++;
1693
- return false;
1694
- }
1695
- if (filters.excludeTags && filters.excludeTags.length > 0) {
1696
- if (containsAny(tags, filters.excludeTags)) {
1697
- if (stats) stats.filteredByTags++;
1698
- return false;
1699
- }
1700
- }
1701
- if (filters.excludePaths && filters.excludePaths.length > 0) {
1702
- if (matchesAnyPattern(path, filters.excludePaths)) {
1703
- if (stats) stats.filteredByPaths++;
1704
- return false;
1705
- }
1706
- }
1707
- if (filters.excludeMethods && filters.excludeMethods.length > 0) {
1708
- const methodsLower = filters.excludeMethods.map((m) => m.toLowerCase());
1709
- if (methodsLower.includes(methodLower)) {
1710
- if (stats) stats.filteredByMethods++;
1711
- return false;
1712
- }
1713
- }
1714
- if (filters.excludeOperationIds && filters.excludeOperationIds.length > 0) {
1715
- if (matchesAnyPattern(operationId, filters.excludeOperationIds)) {
1716
- if (stats) stats.filteredByOperationIds++;
1717
- return false;
1718
- }
1719
- }
1720
- return true;
1721
- }
1722
- function validateFilters(stats, filters) {
1723
- if (!filters || stats.totalOperations === 0) {
1724
- return;
1725
- }
1726
- if (stats.includedOperations === 0) {
1727
- console.warn(
1728
- `\u26A0\uFE0F Warning: All ${stats.totalOperations} operations were filtered out. Check your operationFilters configuration.`
1729
- );
1730
- const filterBreakdown = [];
1731
- if (stats.filteredByTags > 0) filterBreakdown.push(`${stats.filteredByTags} by tags`);
1732
- if (stats.filteredByPaths > 0) filterBreakdown.push(`${stats.filteredByPaths} by paths`);
1733
- if (stats.filteredByMethods > 0) filterBreakdown.push(`${stats.filteredByMethods} by methods`);
1734
- if (stats.filteredByOperationIds > 0) filterBreakdown.push(`${stats.filteredByOperationIds} by operationIds`);
1735
- if (stats.filteredByDeprecated > 0) filterBreakdown.push(`${stats.filteredByDeprecated} by deprecated flag`);
1736
- if (filterBreakdown.length > 0) {
1737
- console.warn(` Filtered: ${filterBreakdown.join(", ")}`);
1397
+ const literalValues = values.map((v) => {
1398
+ if (typeof v === "string") {
1399
+ return `z.literal("${v}")`;
1738
1400
  }
1739
- }
1740
- }
1741
- function formatFilterStatistics(stats) {
1742
- if (stats.totalOperations === 0) {
1743
- return "";
1744
- }
1745
- const lines = [];
1746
- lines.push("Operation Filtering:");
1747
- lines.push(` Total operations: ${stats.totalOperations}`);
1748
- lines.push(` Included operations: ${stats.includedOperations}`);
1749
- const filteredCount = stats.filteredByTags + stats.filteredByPaths + stats.filteredByMethods + stats.filteredByOperationIds + stats.filteredByDeprecated;
1750
- if (filteredCount > 0) {
1751
- lines.push(` Filtered operations: ${filteredCount}`);
1752
- if (stats.filteredByTags > 0) lines.push(` - By tags: ${stats.filteredByTags}`);
1753
- if (stats.filteredByPaths > 0) lines.push(` - By paths: ${stats.filteredByPaths}`);
1754
- if (stats.filteredByMethods > 0) lines.push(` - By methods: ${stats.filteredByMethods}`);
1755
- if (stats.filteredByOperationIds > 0) lines.push(` - By operationIds: ${stats.filteredByOperationIds}`);
1756
- if (stats.filteredByDeprecated > 0) lines.push(` - By deprecated: ${stats.filteredByDeprecated}`);
1757
- }
1758
- return lines.join("\n");
1401
+ return `z.literal(${v})`;
1402
+ }).join(", ");
1403
+ const schemaCode = `export const ${schemaName} = z.union([${literalValues}]);`;
1404
+ const typeCode = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
1405
+ return { schemaCode, typeCode };
1759
1406
  }
1760
1407
 
1761
- // src/utils/ref-resolver.ts
1762
- function resolveRef2(obj, spec, maxDepth = 10) {
1763
- var _a, _b, _c, _d;
1764
- if (!obj || typeof obj !== "object" || maxDepth <= 0) return obj;
1765
- if (!obj.$ref) return obj;
1766
- const ref = obj.$ref;
1767
- let resolved = null;
1768
- const paramMatch = ref.match(/^#\/components\/parameters\/(.+)$/);
1769
- const requestBodyMatch = ref.match(/^#\/components\/requestBodies\/(.+)$/);
1770
- const responseMatch = ref.match(/^#\/components\/responses\/(.+)$/);
1771
- const schemaMatch = ref.match(/^#\/components\/schemas\/(.+)$/);
1772
- if (paramMatch && ((_a = spec.components) == null ? void 0 : _a.parameters)) {
1773
- const name = paramMatch[1];
1774
- resolved = spec.components.parameters[name];
1775
- } else if (requestBodyMatch && ((_b = spec.components) == null ? void 0 : _b.requestBodies)) {
1776
- const name = requestBodyMatch[1];
1777
- resolved = spec.components.requestBodies[name];
1778
- } else if (responseMatch && ((_c = spec.components) == null ? void 0 : _c.responses)) {
1779
- const name = responseMatch[1];
1780
- resolved = spec.components.responses[name];
1781
- } else if (schemaMatch && ((_d = spec.components) == null ? void 0 : _d.schemas)) {
1782
- const name = schemaMatch[1];
1783
- resolved = spec.components.schemas[name];
1784
- }
1785
- if (resolved) {
1786
- if (resolved.$ref) {
1787
- return resolveRef2(resolved, spec, maxDepth - 1);
1788
- }
1789
- return resolved;
1790
- }
1791
- return obj;
1408
+ // src/openapi-generator.ts
1409
+ var HTTP_METHODS = ["get", "post", "put", "patch", "delete", "head", "options"];
1410
+ function isResolvedParameter(param) {
1411
+ return typeof param === "object" && param !== null && "name" in param && typeof param.name === "string" && "in" in param;
1792
1412
  }
1793
- function resolveParameterRef(param, spec) {
1794
- return resolveRef2(param, spec);
1413
+ function isOpenAPIPathItem(value) {
1414
+ return typeof value === "object" && value !== null;
1795
1415
  }
1796
- function mergeParameters(pathParams, operationParams, spec) {
1797
- const resolvedPathParams = (pathParams || []).map((p) => resolveParameterRef(p, spec));
1798
- const resolvedOperationParams = (operationParams || []).map((p) => resolveParameterRef(p, spec));
1799
- const merged = [...resolvedPathParams];
1800
- for (const opParam of resolvedOperationParams) {
1801
- if (!opParam || typeof opParam !== "object") continue;
1802
- const existingIndex = merged.findIndex(
1803
- (p) => p && typeof p === "object" && p.name === opParam.name && p.in === opParam.in
1804
- );
1805
- if (existingIndex >= 0) {
1806
- merged[existingIndex] = opParam;
1807
- } else {
1808
- merged.push(opParam);
1809
- }
1810
- }
1811
- return merged;
1812
- }
1813
-
1814
- // src/openapi-generator.ts
1815
1416
  var OpenApiGenerator = class {
1816
1417
  constructor(options) {
1817
1418
  this.schemas = /* @__PURE__ */ new Map();
@@ -1819,94 +1420,49 @@ var OpenApiGenerator = class {
1819
1420
  this.schemaDependencies = /* @__PURE__ */ new Map();
1820
1421
  this.schemaUsageMap = /* @__PURE__ */ new Map();
1821
1422
  this.needsZodImport = true;
1822
- this.filterStats = createFilterStatistics();
1823
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1423
+ this.filterStats = (0, import_openapi_core6.createFilterStatistics)();
1424
+ /** Track total allOf conflicts detected across all schemas */
1425
+ this.allOfConflictCount = 0;
1426
+ /** Track schemas involved in circular dependency chains */
1427
+ this.circularDependencies = /* @__PURE__ */ new Set();
1428
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
1824
1429
  if (!options.input) {
1825
- throw new ConfigurationError("Input path is required", { providedOptions: options });
1430
+ throw new import_openapi_core6.ConfigurationError("Input path is required", { providedOptions: options });
1826
1431
  }
1432
+ this.separateSchemasMode = Boolean(options.outputZodSchemas);
1827
1433
  this.options = {
1828
1434
  mode: options.mode || "normal",
1829
1435
  input: options.input,
1830
- output: options.output,
1831
- includeDescriptions: (_a = options.includeDescriptions) != null ? _a : true,
1832
- useDescribe: (_b = options.useDescribe) != null ? _b : false,
1833
- defaultNullable: (_c = options.defaultNullable) != null ? _c : false,
1834
- emptyObjectBehavior: (_d = options.emptyObjectBehavior) != null ? _d : "loose",
1436
+ outputTypes: options.outputTypes,
1437
+ outputZodSchemas: options.outputZodSchemas,
1438
+ enumFormat: options.enumFormat,
1439
+ typeAssertionThreshold: (_a = options.typeAssertionThreshold) != null ? _a : 0,
1440
+ includeDescriptions: (_b = options.includeDescriptions) != null ? _b : true,
1441
+ useDescribe: (_c = options.useDescribe) != null ? _c : false,
1442
+ defaultNullable: (_d = options.defaultNullable) != null ? _d : false,
1443
+ emptyObjectBehavior: (_e = options.emptyObjectBehavior) != null ? _e : "loose",
1835
1444
  schemaType: options.schemaType || "all",
1836
1445
  prefix: options.prefix,
1837
1446
  suffix: options.suffix,
1838
1447
  stripSchemaPrefix: options.stripSchemaPrefix,
1839
1448
  stripPathPrefix: options.stripPathPrefix,
1840
- showStats: (_e = options.showStats) != null ? _e : true,
1449
+ useOperationId: (_f = options.useOperationId) != null ? _f : true,
1450
+ showStats: (_g = options.showStats) != null ? _g : true,
1841
1451
  request: options.request,
1842
1452
  response: options.response,
1843
1453
  operationFilters: options.operationFilters,
1844
1454
  ignoreHeaders: options.ignoreHeaders,
1845
- cacheSize: (_f = options.cacheSize) != null ? _f : 1e3,
1846
- batchSize: (_g = options.batchSize) != null ? _g : 10,
1455
+ cacheSize: (_h = options.cacheSize) != null ? _h : 1e3,
1456
+ batchSize: (_i = options.batchSize) != null ? _i : 10,
1847
1457
  customDateTimeFormatRegex: options.customDateTimeFormatRegex
1848
1458
  };
1849
- if (this.options.cacheSize) {
1850
- configurePatternCache(this.options.cacheSize);
1851
- }
1852
- if (this.options.customDateTimeFormatRegex) {
1853
- configureDateTimeFormat(this.options.customDateTimeFormatRegex);
1854
- }
1855
- try {
1856
- const fs = require("fs");
1857
- if (!fs.existsSync(this.options.input)) {
1858
- throw new FileOperationError(`Input file not found: ${this.options.input}`, this.options.input);
1859
- }
1860
- } catch (error) {
1861
- if (error instanceof FileOperationError) {
1862
- throw error;
1863
- }
1864
- }
1865
- try {
1866
- const content = (0, import_node_fs.readFileSync)(this.options.input, "utf-8");
1867
- try {
1868
- this.spec = (0, import_yaml.parse)(content);
1869
- } catch (yamlError) {
1870
- try {
1871
- this.spec = JSON.parse(content);
1872
- } catch {
1873
- if (yamlError instanceof Error) {
1874
- const errorMessage = [
1875
- `Failed to parse OpenAPI specification from: ${this.options.input}`,
1876
- "",
1877
- `Error: ${yamlError.message}`,
1878
- "",
1879
- "Please ensure:",
1880
- " - The file exists and is readable",
1881
- " - The file contains valid YAML or JSON syntax",
1882
- " - The file is a valid OpenAPI 3.x specification"
1883
- ].join("\n");
1884
- throw new SpecValidationError(errorMessage, {
1885
- filePath: this.options.input,
1886
- originalError: yamlError.message
1887
- });
1888
- }
1889
- throw yamlError;
1890
- }
1891
- }
1892
- } catch (error) {
1893
- if (error instanceof SpecValidationError) {
1894
- throw error;
1895
- }
1896
- if (error instanceof Error) {
1897
- const errorMessage = [
1898
- `Failed to read OpenAPI specification from: ${this.options.input}`,
1899
- "",
1900
- `Error: ${error.message}`
1901
- ].join("\n");
1902
- throw new SpecValidationError(errorMessage, { filePath: this.options.input, originalError: error.message });
1903
- }
1904
- throw error;
1905
- }
1459
+ this.patternCache = new import_openapi_core6.LRUCache((_j = this.options.cacheSize) != null ? _j : 1e3);
1460
+ this.dateTimeValidation = buildDateTimeValidation(this.options.customDateTimeFormatRegex);
1461
+ this.spec = (0, import_openapi_core6.loadOpenAPISpec)(this.options.input);
1906
1462
  this.validateSpec();
1907
1463
  this.requestOptions = this.resolveOptionsForContext("request");
1908
1464
  this.responseOptions = this.resolveOptionsForContext("response");
1909
- this.analyzeSchemaUsage();
1465
+ this.initializeSchemaUsage();
1910
1466
  this.propertyGenerator = new PropertyGenerator({
1911
1467
  spec: this.spec,
1912
1468
  schemaDependencies: this.schemaDependencies,
@@ -1914,24 +1470,33 @@ var OpenApiGenerator = class {
1914
1470
  mode: this.requestOptions.mode,
1915
1471
  includeDescriptions: this.requestOptions.includeDescriptions,
1916
1472
  useDescribe: this.requestOptions.useDescribe,
1917
- defaultNullable: (_h = this.options.defaultNullable) != null ? _h : false,
1918
- emptyObjectBehavior: (_i = this.options.emptyObjectBehavior) != null ? _i : "loose",
1473
+ defaultNullable: (_k = this.options.defaultNullable) != null ? _k : false,
1474
+ emptyObjectBehavior: (_l = this.options.emptyObjectBehavior) != null ? _l : "loose",
1919
1475
  namingOptions: {
1920
1476
  prefix: this.options.prefix,
1921
1477
  suffix: this.options.suffix
1922
1478
  },
1923
- stripSchemaPrefix: this.options.stripSchemaPrefix
1479
+ stripSchemaPrefix: this.options.stripSchemaPrefix,
1480
+ dateTimeValidation: this.dateTimeValidation,
1481
+ patternCache: this.patternCache,
1482
+ separateTypesFile: this.separateSchemasMode
1924
1483
  });
1925
1484
  }
1926
1485
  /**
1927
1486
  * Generate schemas as a string (without writing to file)
1487
+ * When separateSchemasMode is active, generates Zod schemas with explicit type annotations
1928
1488
  * @returns The generated TypeScript code as a string
1929
1489
  */
1930
1490
  generateString() {
1931
1491
  var _a;
1932
1492
  if (!((_a = this.spec.components) == null ? void 0 : _a.schemas)) {
1933
- throw new SpecValidationError("No schemas found in OpenAPI spec", { filePath: this.options.input });
1493
+ throw new import_openapi_core6.SpecValidationError("No schemas found in OpenAPI spec", { filePath: this.options.input });
1934
1494
  }
1495
+ if (this.separateSchemasMode) {
1496
+ return this.generateSeparateSchemasString();
1497
+ }
1498
+ this.analyzeCircularDependencies();
1499
+ this.propertyGenerator.setCircularDependencies(this.circularDependencies);
1935
1500
  for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
1936
1501
  if (this.options.operationFilters && this.schemaUsageMap.size > 0 && !this.schemaUsageMap.has(name)) {
1937
1502
  continue;
@@ -1940,7 +1505,7 @@ var OpenApiGenerator = class {
1940
1505
  }
1941
1506
  this.generateQueryParameterSchemas();
1942
1507
  this.generateHeaderParameterSchemas();
1943
- validateFilters(this.filterStats, this.options.operationFilters);
1508
+ (0, import_openapi_core6.validateFilters)(this.filterStats, this.options.operationFilters);
1944
1509
  const orderedSchemaNames = this.topologicalSort();
1945
1510
  const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
1946
1511
  if (this.options.showStats === true) {
@@ -1957,10 +1522,10 @@ var OpenApiGenerator = class {
1957
1522
  const typeCode = this.types.get(name);
1958
1523
  if (schemaCode) {
1959
1524
  output.push(schemaCode);
1960
- const strippedName = stripPrefix(name, this.options.stripSchemaPrefix);
1961
- const typeName = toPascalCase(strippedName);
1525
+ const strippedName = (0, import_openapi_core6.stripPrefix)(name, this.options.stripSchemaPrefix);
1526
+ const typeName = (0, import_openapi_core6.toPascalCase)(strippedName);
1962
1527
  if (!schemaCode.includes(`export type ${typeName}`)) {
1963
- const schemaName = `${toCamelCase(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
1528
+ const schemaName = `${(0, import_openapi_core6.toCamelCase)(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
1964
1529
  output.push(`export type ${typeName} = z.infer<typeof ${schemaName}>;`);
1965
1530
  }
1966
1531
  output.push("");
@@ -1982,14 +1547,224 @@ var OpenApiGenerator = class {
1982
1547
  }
1983
1548
  }
1984
1549
  /**
1985
- * Generate the complete output file
1550
+ * Generate the complete output file(s)
1551
+ * When separateSchemasMode is active, generates both types and schemas files
1986
1552
  */
1987
1553
  generate() {
1988
- const output = this.generateString();
1989
- const normalizedOutput = (0, import_node_path.normalize)(this.options.output);
1990
- this.ensureDirectoryExists(normalizedOutput);
1991
- (0, import_node_fs.writeFileSync)(normalizedOutput, output);
1992
- console.log(` \u2713 Generated ${normalizedOutput}`);
1554
+ if (this.separateSchemasMode) {
1555
+ const typesContent = this.generateTypesString();
1556
+ const schemasContent = this.generateString();
1557
+ const normalizedTypes = (0, import_node_path.normalize)(this.options.outputTypes);
1558
+ this.ensureDirectoryExists(normalizedTypes);
1559
+ (0, import_node_fs.writeFileSync)(normalizedTypes, typesContent, "utf-8");
1560
+ console.log(` \u2713 Generated ${normalizedTypes}`);
1561
+ if (!this.options.outputZodSchemas) {
1562
+ throw new Error("Internal error: outputZodSchemas should be defined in separateSchemasMode");
1563
+ }
1564
+ const outputZodSchemas = this.options.outputZodSchemas;
1565
+ const normalizedSchemas = (0, import_node_path.normalize)(outputZodSchemas);
1566
+ this.ensureDirectoryExists(normalizedSchemas);
1567
+ (0, import_node_fs.writeFileSync)(normalizedSchemas, schemasContent, "utf-8");
1568
+ console.log(` \u2713 Generated ${normalizedSchemas}`);
1569
+ } else {
1570
+ const output = this.generateString();
1571
+ const normalizedOutput = (0, import_node_path.normalize)(this.options.outputTypes);
1572
+ this.ensureDirectoryExists(normalizedOutput);
1573
+ (0, import_node_fs.writeFileSync)(normalizedOutput, output);
1574
+ console.log(` \u2713 Generated ${normalizedOutput}`);
1575
+ }
1576
+ }
1577
+ /**
1578
+ * Generate Zod schemas with explicit type annotations (for outputZodSchemas mode)
1579
+ * Generates schemas like: `export const userSchema: z.ZodType<User> = z.object({...})`
1580
+ * @returns The generated Zod schemas TypeScript code
1581
+ */
1582
+ generateSeparateSchemasString() {
1583
+ var _a;
1584
+ const schemas = (_a = this.spec.components) == null ? void 0 : _a.schemas;
1585
+ if (!schemas) {
1586
+ return "";
1587
+ }
1588
+ if (!this.options.outputZodSchemas) {
1589
+ throw new Error("Internal error: outputZodSchemas should be defined in separateSchemasMode");
1590
+ }
1591
+ const outputZodSchemas = this.options.outputZodSchemas;
1592
+ this.analyzeCircularDependencies();
1593
+ this.propertyGenerator.setCircularDependencies(this.circularDependencies);
1594
+ for (const [name, schema] of Object.entries(schemas)) {
1595
+ if (this.options.operationFilters && this.schemaUsageMap.size > 0 && !this.schemaUsageMap.has(name)) {
1596
+ continue;
1597
+ }
1598
+ this.generateComponentSchema(name, schema);
1599
+ }
1600
+ this.generateQueryParameterSchemas();
1601
+ this.generateHeaderParameterSchemas();
1602
+ (0, import_openapi_core6.validateFilters)(this.filterStats, this.options.operationFilters);
1603
+ const orderedSchemaNames = this.topologicalSort();
1604
+ const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
1605
+ if (this.options.showStats === true) {
1606
+ output.push(...this.generateStats());
1607
+ output.push("");
1608
+ }
1609
+ output.push('import { z } from "zod";');
1610
+ const typesImportPath = this.calculateRelativeImportPath(outputZodSchemas, this.options.outputTypes);
1611
+ const typeNames = [];
1612
+ for (const name of orderedSchemaNames) {
1613
+ const strippedName = (0, import_openapi_core6.stripPrefix)(name, this.options.stripSchemaPrefix);
1614
+ const typeName = (0, import_openapi_core6.toPascalCase)(strippedName);
1615
+ typeNames.push(typeName);
1616
+ }
1617
+ if (typeNames.length > 0) {
1618
+ output.push(`import type { ${typeNames.join(", ")} } from "${typesImportPath}";`);
1619
+ }
1620
+ output.push("");
1621
+ output.push("// Schemas");
1622
+ for (const name of orderedSchemaNames) {
1623
+ const schemaCode = this.schemas.get(name);
1624
+ if (schemaCode) {
1625
+ const strippedName = (0, import_openapi_core6.stripPrefix)(name, this.options.stripSchemaPrefix);
1626
+ const typeName = (0, import_openapi_core6.toPascalCase)(strippedName);
1627
+ const schemaName = `${(0, import_openapi_core6.toCamelCase)(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
1628
+ const schemaDefinition = this.isRecordObject(schemas[name]) ? schemas[name] : void 0;
1629
+ const transformedCode = this.addExplicitTypeAnnotation(schemaCode, schemaName, typeName, schemaDefinition);
1630
+ output.push(transformedCode);
1631
+ output.push("");
1632
+ }
1633
+ }
1634
+ return output.join("\n");
1635
+ }
1636
+ /**
1637
+ * Generate TypeScript types as a string (for outputZodSchemas mode)
1638
+ * Uses @cerios/openapi-to-typescript internally
1639
+ * @returns The generated TypeScript types code
1640
+ */
1641
+ generateTypesString() {
1642
+ var _a;
1643
+ const tsGenerator = new import_openapi_to_typescript.TypeScriptGenerator({
1644
+ input: this.options.input,
1645
+ outputTypes: this.options.outputTypes,
1646
+ includeDescriptions: this.options.includeDescriptions,
1647
+ defaultNullable: this.options.defaultNullable,
1648
+ prefix: this.options.prefix,
1649
+ suffix: this.options.suffix,
1650
+ stripSchemaPrefix: this.options.stripSchemaPrefix,
1651
+ stripPathPrefix: this.options.stripPathPrefix,
1652
+ operationFilters: this.options.operationFilters,
1653
+ showStats: this.options.showStats,
1654
+ enumFormat: (_a = this.options.enumFormat) != null ? _a : "const-object"
1655
+ });
1656
+ return tsGenerator.generateString();
1657
+ }
1658
+ /**
1659
+ * Add explicit type annotation to a schema declaration
1660
+ * Transforms: `export const userSchema = z.object({...})`
1661
+ * To: `export const userSchema: z.ZodType<User> = z.object({...})` (annotation)
1662
+ * Or: `export const userSchema = z.object({...}) as unknown as z.ZodType<User>` (double assertion)
1663
+ *
1664
+ * Uses double assertion via `unknown` when typeAssertionThreshold is set and schema complexity
1665
+ * meets or exceeds the threshold. This completely bypasses TypeScript's structural checking
1666
+ * to avoid "Type instantiation is excessively deep" errors on very large schemas.
1667
+ *
1668
+ * Also removes any `export type X = z.infer<...>` lines since types
1669
+ * are imported from the separate types file.
1670
+ */
1671
+ addExplicitTypeAnnotation(schemaCode, schemaName, typeName, schemaDefinition) {
1672
+ var _a;
1673
+ const code = schemaCode.replace(/\nexport type \w+ = z\.infer<typeof \w+>;/g, "");
1674
+ const jsdocMatch = code.match(/^(\/\*\*[\s\S]*?\*\/\n)?/);
1675
+ const jsdoc = (jsdocMatch == null ? void 0 : jsdocMatch[1]) || "";
1676
+ const codeWithoutJsdoc = code.slice(jsdoc.length);
1677
+ const threshold = (_a = this.options.typeAssertionThreshold) != null ? _a : 0;
1678
+ const useAssertion = threshold > 0 && schemaDefinition && this.calculateSchemaComplexity(schemaDefinition) >= threshold;
1679
+ const pattern = new RegExp(`export const ${schemaName} = `);
1680
+ if (pattern.test(codeWithoutJsdoc)) {
1681
+ let schemaBody = codeWithoutJsdoc.replace(pattern, "");
1682
+ if (useAssertion) {
1683
+ schemaBody = schemaBody.replace(/;$/, "");
1684
+ return `${jsdoc}export const ${schemaName} = ${schemaBody} as unknown as z.ZodType<${typeName}>;`;
1685
+ }
1686
+ return `${jsdoc}export const ${schemaName}: z.ZodType<${typeName}> = ${schemaBody}`;
1687
+ }
1688
+ return code;
1689
+ }
1690
+ /**
1691
+ * Type guard to check if a value is a Record<string, unknown>
1692
+ */
1693
+ isRecordObject(value) {
1694
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1695
+ }
1696
+ /**
1697
+ * Calculate the complexity of a schema for threshold comparison
1698
+ * Complexity formula: properties + (nested levels * 10) + (array/union members * 2)
1699
+ */
1700
+ calculateSchemaComplexity(schema, depth = 0) {
1701
+ if (!schema || typeof schema !== "object") {
1702
+ return 0;
1703
+ }
1704
+ let complexity = depth * 10;
1705
+ if (schema.$ref) {
1706
+ return complexity + 5;
1707
+ }
1708
+ const properties = schema.properties;
1709
+ if (this.isRecordObject(properties)) {
1710
+ const propCount = Object.keys(properties).length;
1711
+ complexity += propCount;
1712
+ for (const prop of Object.values(properties)) {
1713
+ if (this.isRecordObject(prop)) {
1714
+ complexity += this.calculateSchemaComplexity(prop, depth + 1);
1715
+ }
1716
+ }
1717
+ }
1718
+ const allOf = schema.allOf;
1719
+ if (Array.isArray(allOf)) {
1720
+ complexity += allOf.length * 2;
1721
+ for (const subSchema of allOf) {
1722
+ if (this.isRecordObject(subSchema)) {
1723
+ complexity += this.calculateSchemaComplexity(subSchema, depth + 1);
1724
+ }
1725
+ }
1726
+ }
1727
+ const oneOf = schema.oneOf;
1728
+ if (Array.isArray(oneOf)) {
1729
+ complexity += oneOf.length * 2;
1730
+ for (const subSchema of oneOf) {
1731
+ if (this.isRecordObject(subSchema)) {
1732
+ complexity += this.calculateSchemaComplexity(subSchema, depth + 1);
1733
+ }
1734
+ }
1735
+ }
1736
+ const anyOf = schema.anyOf;
1737
+ if (Array.isArray(anyOf)) {
1738
+ complexity += anyOf.length * 2;
1739
+ for (const subSchema of anyOf) {
1740
+ if (this.isRecordObject(subSchema)) {
1741
+ complexity += this.calculateSchemaComplexity(subSchema, depth + 1);
1742
+ }
1743
+ }
1744
+ }
1745
+ const items = schema.items;
1746
+ if (this.isRecordObject(items)) {
1747
+ complexity += 2;
1748
+ complexity += this.calculateSchemaComplexity(items, depth + 1);
1749
+ }
1750
+ const additionalProps = schema.additionalProperties;
1751
+ if (this.isRecordObject(additionalProps)) {
1752
+ complexity += 2;
1753
+ complexity += this.calculateSchemaComplexity(additionalProps, depth + 1);
1754
+ }
1755
+ return complexity;
1756
+ }
1757
+ /**
1758
+ * Calculate relative import path from schema file to types file
1759
+ */
1760
+ calculateRelativeImportPath(fromPath, toPath) {
1761
+ const fromDir = (0, import_node_path.dirname)((0, import_node_path.normalize)(fromPath));
1762
+ const toFile = (0, import_node_path.normalize)(toPath).replace(/\.[tj]s$/, "");
1763
+ let relativePath = (0, import_node_path.relative)(fromDir, toFile);
1764
+ if (!relativePath.startsWith(".") && !relativePath.startsWith("..")) {
1765
+ relativePath = `./${relativePath}`;
1766
+ }
1767
+ return relativePath.replace(/\\/g, "/");
1993
1768
  }
1994
1769
  /**
1995
1770
  * Resolve options for a specific context (request or response)
@@ -2005,191 +1780,84 @@ var OpenApiGenerator = class {
2005
1780
  };
2006
1781
  }
2007
1782
  /**
2008
- * Analyze schema usage across the OpenAPI spec to determine if schemas
2009
- * are used in request, response, or both contexts
1783
+ * Initialize schema usage map using core utilities with operation filtering
1784
+ * This is a wrapper around core's analyzeSchemaUsage that adds operation filtering
2010
1785
  */
2011
- analyzeSchemaUsage() {
2012
- var _a, _b;
2013
- const requestSchemas = /* @__PURE__ */ new Set();
2014
- const responseSchemas = /* @__PURE__ */ new Set();
2015
- if (this.spec.paths) {
1786
+ initializeSchemaUsage() {
1787
+ var _a;
1788
+ if (this.options.operationFilters && this.spec.paths) {
1789
+ const requestSchemas = /* @__PURE__ */ new Set();
1790
+ const responseSchemas = /* @__PURE__ */ new Set();
2016
1791
  for (const [path, pathItem] of Object.entries(this.spec.paths)) {
2017
- const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
2018
- for (const method of methods) {
1792
+ if (!isOpenAPIPathItem(pathItem)) continue;
1793
+ for (const method of HTTP_METHODS) {
2019
1794
  const operation = pathItem[method];
2020
- if (typeof operation !== "object" || !operation) continue;
1795
+ if (!operation) continue;
2021
1796
  this.filterStats.totalOperations++;
2022
- if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters, this.filterStats)) {
1797
+ if (!(0, import_openapi_core6.shouldIncludeOperation)(operation, path, method, this.options.operationFilters, this.filterStats)) {
2023
1798
  continue;
2024
1799
  }
2025
1800
  this.filterStats.includedOperations++;
2026
- if ("requestBody" in operation && operation.requestBody && typeof operation.requestBody === "object" && "content" in operation.requestBody && operation.requestBody.content) {
2027
- for (const mediaType of Object.values(operation.requestBody.content)) {
2028
- if (mediaType && typeof mediaType === "object" && "schema" in mediaType && mediaType.schema) {
2029
- this.extractSchemaRefs(mediaType.schema, requestSchemas);
1801
+ if (operation.requestBody && typeof operation.requestBody === "object") {
1802
+ const reqBody = operation.requestBody;
1803
+ if (reqBody.content && typeof reqBody.content === "object") {
1804
+ for (const mediaType of Object.values(reqBody.content)) {
1805
+ if (mediaType && typeof mediaType === "object" && "schema" in mediaType && mediaType.schema) {
1806
+ (0, import_openapi_core6.extractSchemaRefs)(mediaType.schema, requestSchemas);
1807
+ }
2030
1808
  }
2031
1809
  }
2032
1810
  }
2033
- if ("responses" in operation && operation.responses && typeof operation.responses === "object") {
1811
+ if (operation.responses && typeof operation.responses === "object") {
2034
1812
  for (const response of Object.values(operation.responses)) {
2035
1813
  if (response && typeof response === "object" && "content" in response && response.content && typeof response.content === "object") {
2036
1814
  for (const mediaType of Object.values(response.content)) {
2037
1815
  if (mediaType && typeof mediaType === "object" && "schema" in mediaType && mediaType.schema) {
2038
- this.extractSchemaRefs(mediaType.schema, responseSchemas);
1816
+ (0, import_openapi_core6.extractSchemaRefs)(mediaType.schema, responseSchemas);
2039
1817
  }
2040
1818
  }
2041
1819
  }
2042
1820
  }
2043
1821
  }
2044
- if ("parameters" in operation && Array.isArray(operation.parameters)) {
1822
+ if (operation.parameters && Array.isArray(operation.parameters)) {
2045
1823
  for (const param of operation.parameters) {
2046
- if (param && typeof param === "object" && "schema" in param && param.schema) {
2047
- this.extractSchemaRefs(param.schema, requestSchemas);
1824
+ if (isResolvedParameter(param) && param.schema) {
1825
+ (0, import_openapi_core6.extractSchemaRefs)(param.schema, requestSchemas);
2048
1826
  }
2049
1827
  }
2050
1828
  }
2051
1829
  }
2052
1830
  }
2053
- this.expandTransitiveReferences(requestSchemas);
2054
- this.expandTransitiveReferences(responseSchemas);
2055
- }
2056
- if (!this.spec.paths || requestSchemas.size === 0 && responseSchemas.size === 0) {
2057
- for (const [name, schema] of Object.entries(((_a = this.spec.components) == null ? void 0 : _a.schemas) || {})) {
2058
- const hasReadOnly = this.hasReadOnlyProperties(schema);
2059
- const hasWriteOnly = this.hasWriteOnlyProperties(schema);
2060
- if (hasWriteOnly && !hasReadOnly) {
2061
- requestSchemas.add(name);
2062
- } else if (hasReadOnly && !hasWriteOnly) {
2063
- responseSchemas.add(name);
1831
+ (0, import_openapi_core6.expandTransitiveReferences)(requestSchemas, this.spec);
1832
+ (0, import_openapi_core6.expandTransitiveReferences)(responseSchemas, this.spec);
1833
+ for (const [name] of Object.entries(((_a = this.spec.components) == null ? void 0 : _a.schemas) || {})) {
1834
+ if (requestSchemas.has(name) && responseSchemas.has(name)) {
1835
+ this.schemaUsageMap.set(name, "both");
1836
+ } else if (requestSchemas.has(name)) {
1837
+ this.schemaUsageMap.set(name, "request");
1838
+ } else if (responseSchemas.has(name)) {
1839
+ this.schemaUsageMap.set(name, "response");
2064
1840
  }
2065
1841
  }
2066
- }
2067
- for (const [name] of Object.entries(((_b = this.spec.components) == null ? void 0 : _b.schemas) || {})) {
2068
- if (requestSchemas.has(name) && responseSchemas.has(name)) {
1842
+ const circularSchemas = (0, import_openapi_core6.detectCircularReferences)(this.spec);
1843
+ for (const name of circularSchemas) {
2069
1844
  this.schemaUsageMap.set(name, "both");
2070
- } else if (requestSchemas.has(name)) {
2071
- this.schemaUsageMap.set(name, "request");
2072
- } else if (responseSchemas.has(name)) {
2073
- this.schemaUsageMap.set(name, "response");
2074
- }
2075
- }
2076
- this.detectCircularReferences();
2077
- }
2078
- /**
2079
- * Expand a set of schemas to include all transitively referenced schemas
2080
- */
2081
- expandTransitiveReferences(schemas) {
2082
- var _a, _b;
2083
- const toProcess = Array.from(schemas);
2084
- const processed = /* @__PURE__ */ new Set();
2085
- while (toProcess.length > 0) {
2086
- const schemaName = toProcess.pop();
2087
- if (!schemaName || processed.has(schemaName)) continue;
2088
- processed.add(schemaName);
2089
- const schema = (_b = (_a = this.spec.components) == null ? void 0 : _a.schemas) == null ? void 0 : _b[schemaName];
2090
- if (schema) {
2091
- const refs = /* @__PURE__ */ new Set();
2092
- this.extractSchemaRefs(schema, refs);
2093
- for (const ref of refs) {
2094
- if (!schemas.has(ref)) {
2095
- schemas.add(ref);
2096
- toProcess.push(ref);
2097
- }
2098
- }
2099
- }
2100
- }
2101
- }
2102
- /**
2103
- * Extract schema names from $ref and nested structures
2104
- */
2105
- extractSchemaRefs(schema, refs) {
2106
- if (!schema) return;
2107
- if (schema.$ref) {
2108
- const refName = resolveRef(schema.$ref);
2109
- refs.add(refName);
2110
- }
2111
- if (schema.allOf) {
2112
- for (const subSchema of schema.allOf) {
2113
- this.extractSchemaRefs(subSchema, refs);
2114
- }
2115
- }
2116
- if (schema.oneOf) {
2117
- for (const subSchema of schema.oneOf) {
2118
- this.extractSchemaRefs(subSchema, refs);
2119
- }
2120
- }
2121
- if (schema.anyOf) {
2122
- for (const subSchema of schema.anyOf) {
2123
- this.extractSchemaRefs(subSchema, refs);
2124
- }
2125
- }
2126
- if (schema.items) {
2127
- this.extractSchemaRefs(schema.items, refs);
2128
- }
2129
- if (schema.properties) {
2130
- for (const prop of Object.values(schema.properties)) {
2131
- this.extractSchemaRefs(prop, refs);
2132
1845
  }
2133
- }
2134
- }
2135
- /**
2136
- * Check if schema has readOnly properties
2137
- */
2138
- hasReadOnlyProperties(schema) {
2139
- if (schema.readOnly) return true;
2140
- if (schema.properties) {
2141
- for (const prop of Object.values(schema.properties)) {
2142
- if (this.hasReadOnlyProperties(prop)) return true;
2143
- }
2144
- }
2145
- return false;
2146
- }
2147
- /**
2148
- * Check if schema has writeOnly properties
2149
- */
2150
- hasWriteOnlyProperties(schema) {
2151
- if (schema.writeOnly) return true;
2152
- if (schema.properties) {
2153
- for (const prop of Object.values(schema.properties)) {
2154
- if (this.hasWriteOnlyProperties(prop)) return true;
2155
- }
2156
- }
2157
- return false;
2158
- }
2159
- /**
2160
- * Detect circular references and mark them as "both" context for safety
2161
- */
2162
- detectCircularReferences() {
2163
- var _a;
2164
- const visited = /* @__PURE__ */ new Set();
2165
- const recursionStack = /* @__PURE__ */ new Set();
2166
- const detectCycle = (name) => {
2167
- var _a2, _b;
2168
- if (recursionStack.has(name)) {
2169
- return true;
2170
- }
2171
- if (visited.has(name)) {
2172
- return false;
2173
- }
2174
- visited.add(name);
2175
- recursionStack.add(name);
2176
- const schema = (_b = (_a2 = this.spec.components) == null ? void 0 : _a2.schemas) == null ? void 0 : _b[name];
2177
- if (schema) {
2178
- const refs = /* @__PURE__ */ new Set();
2179
- this.extractSchemaRefs(schema, refs);
2180
- for (const ref of refs) {
2181
- if (detectCycle(ref)) {
2182
- this.schemaUsageMap.set(name, "both");
2183
- recursionStack.delete(name);
2184
- return true;
1846
+ } else {
1847
+ const analysis = (0, import_openapi_core6.analyzeSchemaUsage)(this.spec);
1848
+ this.schemaUsageMap = analysis.usageMap;
1849
+ if (this.spec.paths) {
1850
+ for (const pathItem of Object.values(this.spec.paths)) {
1851
+ if (!isOpenAPIPathItem(pathItem)) continue;
1852
+ for (const method of HTTP_METHODS) {
1853
+ const operation = pathItem[method];
1854
+ if (typeof operation === "object" && operation) {
1855
+ this.filterStats.totalOperations++;
1856
+ this.filterStats.includedOperations++;
1857
+ }
2185
1858
  }
2186
1859
  }
2187
1860
  }
2188
- recursionStack.delete(name);
2189
- return false;
2190
- };
2191
- for (const name of Object.keys(((_a = this.spec.components) == null ? void 0 : _a.schemas) || {})) {
2192
- detectCycle(name);
2193
1861
  }
2194
1862
  }
2195
1863
  /**
@@ -2198,7 +1866,7 @@ var OpenApiGenerator = class {
2198
1866
  validateSpec() {
2199
1867
  var _a;
2200
1868
  if (!((_a = this.spec.components) == null ? void 0 : _a.schemas)) {
2201
- throw new SpecValidationError(
1869
+ throw new import_openapi_core6.SpecValidationError(
2202
1870
  `No schemas found in OpenAPI spec at ${this.options.input}. Expected to find schemas at components.schemas`,
2203
1871
  { filePath: this.options.input }
2204
1872
  );
@@ -2209,7 +1877,7 @@ var OpenApiGenerator = class {
2209
1877
  this.validateSchemaRefs(name, schema, allSchemas);
2210
1878
  } catch (error) {
2211
1879
  if (error instanceof Error) {
2212
- throw new SchemaGenerationError(`Invalid schema '${name}': ${error.message}`, name, {
1880
+ throw new import_openapi_core6.SchemaGenerationError(`Invalid schema '${name}': ${error.message}`, name, {
2213
1881
  originalError: error.message
2214
1882
  });
2215
1883
  }
@@ -2222,9 +1890,9 @@ var OpenApiGenerator = class {
2222
1890
  */
2223
1891
  validateSchemaRefs(schemaName, schema, allSchemas, path = "") {
2224
1892
  if (schema.$ref) {
2225
- const refName = resolveRef(schema.$ref);
1893
+ const refName = (0, import_openapi_core6.resolveRefName)(schema.$ref);
2226
1894
  if (!allSchemas.includes(refName)) {
2227
- throw new SpecValidationError(
1895
+ throw new import_openapi_core6.SpecValidationError(
2228
1896
  `Invalid reference${path ? ` at '${path}'` : ""}: '${schema.$ref}' points to non-existent schema '${refName}'`,
2229
1897
  { schemaName, path, ref: schema.$ref, refName }
2230
1898
  );
@@ -2271,7 +1939,7 @@ var OpenApiGenerator = class {
2271
1939
  const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
2272
1940
  if (schema.enum) {
2273
1941
  const jsdoc2 = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
2274
- const strippedName2 = stripPrefix(name, this.options.stripSchemaPrefix);
1942
+ const strippedName2 = (0, import_openapi_core6.stripPrefix)(name, this.options.stripSchemaPrefix);
2275
1943
  const { schemaCode, typeCode } = generateEnum(strippedName2, schema.enum, {
2276
1944
  prefix: this.options.prefix,
2277
1945
  suffix: this.options.suffix
@@ -2281,11 +1949,11 @@ ${typeCode}`;
2281
1949
  this.schemas.set(name, enumSchemaCode);
2282
1950
  return;
2283
1951
  }
2284
- const strippedName = stripPrefix(name, this.options.stripSchemaPrefix);
2285
- const schemaName = `${toCamelCase(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
2286
- const jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
1952
+ const strippedName = (0, import_openapi_core6.stripPrefix)(name, this.options.stripSchemaPrefix);
1953
+ const schemaName = `${(0, import_openapi_core6.toCamelCase)(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
1954
+ let jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
2287
1955
  if (schema.allOf && schema.allOf.length === 1 && schema.allOf[0].$ref) {
2288
- const refName = resolveRef(schema.allOf[0].$ref);
1956
+ const refName = (0, import_openapi_core6.resolveRefName)(schema.allOf[0].$ref);
2289
1957
  (_a = this.schemaDependencies.get(name)) == null ? void 0 : _a.add(refName);
2290
1958
  }
2291
1959
  this.propertyGenerator = new PropertyGenerator({
@@ -2301,9 +1969,28 @@ ${typeCode}`;
2301
1969
  prefix: this.options.prefix,
2302
1970
  suffix: this.options.suffix
2303
1971
  },
2304
- stripSchemaPrefix: this.options.stripSchemaPrefix
1972
+ stripSchemaPrefix: this.options.stripSchemaPrefix,
1973
+ dateTimeValidation: this.dateTimeValidation,
1974
+ patternCache: this.patternCache,
1975
+ separateTypesFile: this.separateSchemasMode
2305
1976
  });
1977
+ this.propertyGenerator.setCircularDependencies(this.circularDependencies);
1978
+ this.propertyGenerator.clearAllOfConflicts();
2306
1979
  const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, true);
1980
+ const allOfConflicts = this.propertyGenerator.getAllOfConflicts();
1981
+ if (allOfConflicts.length > 0) {
1982
+ this.allOfConflictCount += allOfConflicts.length;
1983
+ const conflictWarning = this.generateConflictJSDoc(allOfConflicts);
1984
+ if (jsdoc) {
1985
+ jsdoc = jsdoc.replace(/ \*\/\n$/, `
1986
+ ${conflictWarning} */
1987
+ `);
1988
+ } else {
1989
+ jsdoc = `/**
1990
+ ${conflictWarning} */
1991
+ `;
1992
+ }
1993
+ }
2307
1994
  const zodSchemaCode = `${jsdoc}export const ${schemaName} = ${zodSchema};`;
2308
1995
  if (zodSchema.includes("z.discriminatedUnion(")) {
2309
1996
  const match = zodSchema.match(/z\.discriminatedUnion\([^,]+,\s*\[([^\]]+)\]/);
@@ -2329,28 +2016,27 @@ ${typeCode}`;
2329
2016
  return;
2330
2017
  }
2331
2018
  for (const [path, pathItem] of Object.entries(this.spec.paths)) {
2332
- if (!pathItem || typeof pathItem !== "object") continue;
2333
- const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
2334
- for (const method of methods) {
2019
+ if (!isOpenAPIPathItem(pathItem)) continue;
2020
+ for (const method of HTTP_METHODS) {
2335
2021
  const operation = pathItem[method];
2336
2022
  if (!operation) continue;
2337
- if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
2023
+ if (!(0, import_openapi_core6.shouldIncludeOperation)(operation, path, method, this.options.operationFilters)) {
2338
2024
  continue;
2339
2025
  }
2340
- const allParams = mergeParameters(pathItem.parameters, operation.parameters, this.spec);
2026
+ const allParams = (0, import_openapi_core6.mergeParameters)(pathItem.parameters, operation.parameters, this.spec);
2341
2027
  const queryParams = allParams.filter(
2342
- (param) => param && typeof param === "object" && param.in === "query"
2028
+ (param) => isResolvedParameter(param) && param.in === "query"
2343
2029
  );
2344
2030
  if (queryParams.length === 0) {
2345
2031
  continue;
2346
2032
  }
2347
- let pascalOperationId;
2348
- if (operation.operationId) {
2349
- pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
2350
- } else {
2351
- const strippedPath = stripPathPrefix(path, this.options.stripPathPrefix);
2352
- pascalOperationId = this.generateMethodNameFromPath(method, strippedPath);
2353
- }
2033
+ const strippedPath = (0, import_openapi_core6.stripPathPrefix)(path, this.options.stripPathPrefix);
2034
+ const pascalOperationId = (0, import_openapi_core6.getOperationName)(
2035
+ operation.operationId,
2036
+ method,
2037
+ strippedPath,
2038
+ this.options.useOperationId
2039
+ );
2354
2040
  const schemaName = `${pascalOperationId}QueryParams`;
2355
2041
  if (!this.schemaDependencies.has(schemaName)) {
2356
2042
  this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
@@ -2380,7 +2066,7 @@ ${typeCode}`;
2380
2066
  required.push(paramName);
2381
2067
  }
2382
2068
  if (paramSchema.$ref) {
2383
- const refName = resolveRef(paramSchema.$ref);
2069
+ const refName = (0, import_openapi_core6.resolveRefName)(paramSchema.$ref);
2384
2070
  (_a = this.schemaDependencies.get(schemaName)) == null ? void 0 : _a.add(refName);
2385
2071
  }
2386
2072
  }
@@ -2395,9 +2081,7 @@ ${typeCode}`;
2395
2081
  ${propsCode}
2396
2082
  })`;
2397
2083
  const operationName = pascalOperationId;
2398
- const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
2399
- const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
2400
- const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}QueryParamsSchema`;
2084
+ const camelCaseSchemaName = `${(0, import_openapi_core6.toCamelCase)(operationName, { prefix: this.options.prefix, suffix: this.options.suffix })}QueryParamsSchema`;
2401
2085
  const jsdocOperationName = operation.operationId || `${method.toUpperCase()} ${path}`;
2402
2086
  const jsdoc = `/**
2403
2087
  * Query parameters for ${jsdocOperationName}
@@ -2409,35 +2093,6 @@ ${propsCode}
2409
2093
  }
2410
2094
  }
2411
2095
  }
2412
- /**
2413
- * Generate a PascalCase method name from HTTP method and path
2414
- * Used as fallback when operationId is not available
2415
- * @internal
2416
- */
2417
- generateMethodNameFromPath(method, path) {
2418
- const segments = path.split("/").filter(Boolean).map((segment) => {
2419
- if (segment.startsWith("{") && segment.endsWith("}")) {
2420
- const paramName = segment.slice(1, -1);
2421
- return `By${this.capitalizeSegment(paramName)}`;
2422
- }
2423
- return this.capitalizeSegment(segment);
2424
- }).join("");
2425
- const capitalizedMethod = method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
2426
- return `${capitalizedMethod}${segments}`;
2427
- }
2428
- /**
2429
- * Capitalizes a path segment, handling special characters like dashes, underscores, and dots
2430
- * @internal
2431
- */
2432
- capitalizeSegment(str) {
2433
- if (str.includes("-") || str.includes("_") || str.includes(".")) {
2434
- return str.split(/[-_.]/).map((part) => {
2435
- if (!part) return "";
2436
- return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
2437
- }).join("");
2438
- }
2439
- return str.charAt(0).toUpperCase() + str.slice(1);
2440
- }
2441
2096
  /**
2442
2097
  * Check if a header should be ignored based on filter patterns
2443
2098
  * @internal
@@ -2453,7 +2108,7 @@ ${propsCode}
2453
2108
  const headerLower = headerName.toLowerCase();
2454
2109
  return ignorePatterns.some((pattern) => {
2455
2110
  const patternLower = pattern.toLowerCase();
2456
- return (0, import_minimatch3.minimatch)(headerLower, patternLower);
2111
+ return (0, import_minimatch.minimatch)(headerLower, patternLower);
2457
2112
  });
2458
2113
  }
2459
2114
  /**
@@ -2466,28 +2121,27 @@ ${propsCode}
2466
2121
  return;
2467
2122
  }
2468
2123
  for (const [path, pathItem] of Object.entries(this.spec.paths)) {
2469
- if (!pathItem || typeof pathItem !== "object") continue;
2470
- const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
2471
- for (const method of methods) {
2124
+ if (!isOpenAPIPathItem(pathItem)) continue;
2125
+ for (const method of HTTP_METHODS) {
2472
2126
  const operation = pathItem[method];
2473
2127
  if (!operation) continue;
2474
- if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
2128
+ if (!(0, import_openapi_core6.shouldIncludeOperation)(operation, path, method, this.options.operationFilters)) {
2475
2129
  continue;
2476
2130
  }
2477
- const allParams = mergeParameters(pathItem.parameters, operation.parameters, this.spec);
2131
+ const allParams = (0, import_openapi_core6.mergeParameters)(pathItem.parameters, operation.parameters, this.spec);
2478
2132
  const headerParams = allParams.filter(
2479
- (param) => param && typeof param === "object" && param.in === "header" && !this.shouldIgnoreHeader(param.name)
2133
+ (param) => isResolvedParameter(param) && param.in === "header" && !this.shouldIgnoreHeader(param.name)
2480
2134
  );
2481
2135
  if (headerParams.length === 0) {
2482
2136
  continue;
2483
2137
  }
2484
- let pascalOperationId;
2485
- if (operation.operationId) {
2486
- pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
2487
- } else {
2488
- const strippedPath = stripPathPrefix(path, this.options.stripPathPrefix);
2489
- pascalOperationId = this.generateMethodNameFromPath(method, strippedPath);
2490
- }
2138
+ const strippedPath = (0, import_openapi_core6.stripPathPrefix)(path, this.options.stripPathPrefix);
2139
+ const pascalOperationId = (0, import_openapi_core6.getOperationName)(
2140
+ operation.operationId,
2141
+ method,
2142
+ strippedPath,
2143
+ this.options.useOperationId
2144
+ );
2491
2145
  const schemaName = `${pascalOperationId}HeaderParams`;
2492
2146
  if (!this.schemaDependencies.has(schemaName)) {
2493
2147
  this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
@@ -2506,7 +2160,7 @@ ${propsCode}
2506
2160
  zodType = `${zodType}.optional()`;
2507
2161
  properties[paramName] = zodType;
2508
2162
  if (paramSchema.$ref) {
2509
- const refName = resolveRef(paramSchema.$ref);
2163
+ const refName = (0, import_openapi_core6.resolveRefName)(paramSchema.$ref);
2510
2164
  (_a = this.schemaDependencies.get(schemaName)) == null ? void 0 : _a.add(refName);
2511
2165
  }
2512
2166
  }
@@ -2521,9 +2175,7 @@ ${propsCode}
2521
2175
  ${propsCode}
2522
2176
  })`;
2523
2177
  const operationName = pascalOperationId;
2524
- const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
2525
- const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
2526
- const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}HeaderParamsSchema`;
2178
+ const camelCaseSchemaName = `${(0, import_openapi_core6.toCamelCase)(operationName, { prefix: this.options.prefix, suffix: this.options.suffix })}HeaderParamsSchema`;
2527
2179
  const jsdocOperationName = operation.operationId || `${method.toUpperCase()} ${path}`;
2528
2180
  const jsdoc = `/**
2529
2181
  * Header parameters for ${jsdocOperationName}
@@ -2540,9 +2192,9 @@ ${propsCode}
2540
2192
  */
2541
2193
  generateQueryParamType(schema, param) {
2542
2194
  if (schema.$ref) {
2543
- const refName = resolveRef(schema.$ref);
2544
- const strippedRefName = stripPrefix(refName, this.options.stripSchemaPrefix);
2545
- const schemaName = toCamelCase(strippedRefName, { prefix: this.options.prefix, suffix: this.options.suffix });
2195
+ const refName = (0, import_openapi_core6.resolveRefName)(schema.$ref);
2196
+ const strippedRefName = (0, import_openapi_core6.stripPrefix)(refName, this.options.stripSchemaPrefix);
2197
+ const schemaName = (0, import_openapi_core6.toCamelCase)(strippedRefName, { prefix: this.options.prefix, suffix: this.options.suffix });
2546
2198
  return `${schemaName}Schema`;
2547
2199
  }
2548
2200
  if (schema.enum) {
@@ -2559,7 +2211,7 @@ ${propsCode}
2559
2211
  if (typeof v === "string") {
2560
2212
  return `z.literal("${v}")`;
2561
2213
  }
2562
- return `z.literal(${v})`;
2214
+ return `z.literal(${String(v)})`;
2563
2215
  }).join(", ");
2564
2216
  return `z.union([${literalValues}])`;
2565
2217
  }
@@ -2639,17 +2291,23 @@ ${propsCode}
2639
2291
  return;
2640
2292
  }
2641
2293
  const deps = this.schemaDependencies.get(name);
2294
+ let dependsOnCircular = false;
2642
2295
  if (deps && deps.size > 0) {
2643
2296
  for (const dep of deps) {
2644
2297
  if (this.schemas.has(dep) || this.types.has(dep)) {
2645
2298
  visit(dep);
2299
+ if (circularDeps.has(dep)) {
2300
+ dependsOnCircular = true;
2301
+ }
2646
2302
  }
2647
2303
  }
2648
2304
  }
2649
2305
  visiting.delete(name);
2650
2306
  visited.add(name);
2651
- if (!circularDeps.has(name)) {
2307
+ if (!circularDeps.has(name) && !dependsOnCircular) {
2652
2308
  sorted.push(name);
2309
+ } else if (dependsOnCircular && !circularDeps.has(name)) {
2310
+ circularDeps.add(name);
2653
2311
  }
2654
2312
  };
2655
2313
  const allNames = /* @__PURE__ */ new Set([...this.schemas.keys(), ...this.types.keys()]);
@@ -2657,9 +2315,8 @@ ${propsCode}
2657
2315
  visit(name);
2658
2316
  }
2659
2317
  for (const name of circularDeps) {
2660
- if (!visited.has(name)) {
2318
+ if (!sorted.includes(name)) {
2661
2319
  sorted.push(name);
2662
- visited.add(name);
2663
2320
  }
2664
2321
  }
2665
2322
  return [...sorted, ...aliases];
@@ -2686,11 +2343,12 @@ ${propsCode}
2686
2343
  `// Total schemas: ${stats.totalSchemas}`,
2687
2344
  `// Circular references: ${stats.withCircularRefs}`,
2688
2345
  `// Discriminated unions: ${stats.withDiscriminators}`,
2689
- `// With constraints: ${stats.withConstraints}`
2346
+ `// With constraints: ${stats.withConstraints}`,
2347
+ `// AllOf conflicts: ${this.allOfConflictCount}`
2690
2348
  ];
2691
2349
  if (this.options.operationFilters && this.filterStats.totalOperations > 0) {
2692
2350
  output.push("//");
2693
- const filterStatsStr = formatFilterStatistics(this.filterStats);
2351
+ const filterStatsStr = (0, import_openapi_core6.formatFilterStatistics)(this.filterStats);
2694
2352
  for (const line of filterStatsStr.split("\n")) {
2695
2353
  output.push(`// ${line}`);
2696
2354
  }
@@ -2698,6 +2356,106 @@ ${propsCode}
2698
2356
  output.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
2699
2357
  return output;
2700
2358
  }
2359
+ /**
2360
+ * Pre-analyze schemas to detect circular dependencies before code generation.
2361
+ * This allows the property generator to use z.lazy() for forward references.
2362
+ */
2363
+ analyzeCircularDependencies() {
2364
+ var _a;
2365
+ if (!((_a = this.spec.components) == null ? void 0 : _a.schemas)) return;
2366
+ const dependencies = /* @__PURE__ */ new Map();
2367
+ const collectDependencies = (name, schema, visited2 = /* @__PURE__ */ new Set()) => {
2368
+ if (visited2.has(name)) return /* @__PURE__ */ new Set();
2369
+ visited2.add(name);
2370
+ const deps = /* @__PURE__ */ new Set();
2371
+ if (schema.$ref) {
2372
+ const refName = (0, import_openapi_core6.resolveRefName)(schema.$ref);
2373
+ deps.add(refName);
2374
+ }
2375
+ if (schema.allOf) {
2376
+ for (const item of schema.allOf) {
2377
+ const itemDeps = collectDependencies(`${name}_allOf`, item, new Set(visited2));
2378
+ for (const dep of itemDeps) deps.add(dep);
2379
+ }
2380
+ }
2381
+ if (schema.oneOf) {
2382
+ for (const item of schema.oneOf) {
2383
+ const itemDeps = collectDependencies(`${name}_oneOf`, item, new Set(visited2));
2384
+ for (const dep of itemDeps) deps.add(dep);
2385
+ }
2386
+ }
2387
+ if (schema.anyOf) {
2388
+ for (const item of schema.anyOf) {
2389
+ const itemDeps = collectDependencies(`${name}_anyOf`, item, new Set(visited2));
2390
+ for (const dep of itemDeps) deps.add(dep);
2391
+ }
2392
+ }
2393
+ if (schema.properties) {
2394
+ for (const propSchema of Object.values(schema.properties)) {
2395
+ const propDeps = collectDependencies(`${name}_prop`, propSchema, new Set(visited2));
2396
+ for (const dep of propDeps) deps.add(dep);
2397
+ }
2398
+ }
2399
+ if (schema.items) {
2400
+ const itemDeps = collectDependencies(`${name}_items`, schema.items, new Set(visited2));
2401
+ for (const dep of itemDeps) deps.add(dep);
2402
+ }
2403
+ if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
2404
+ const addDeps = collectDependencies(`${name}_additional`, schema.additionalProperties, new Set(visited2));
2405
+ for (const dep of addDeps) deps.add(dep);
2406
+ }
2407
+ return deps;
2408
+ };
2409
+ for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
2410
+ if (this.options.operationFilters && this.schemaUsageMap.size > 0 && !this.schemaUsageMap.has(name)) {
2411
+ continue;
2412
+ }
2413
+ dependencies.set(name, collectDependencies(name, schema));
2414
+ }
2415
+ const visited = /* @__PURE__ */ new Set();
2416
+ const visiting = /* @__PURE__ */ new Set();
2417
+ const detectCircular = (name, path = []) => {
2418
+ if (visited.has(name)) return;
2419
+ if (visiting.has(name)) {
2420
+ const cycleStart = path.indexOf(name);
2421
+ if (cycleStart >= 0) {
2422
+ for (let i = cycleStart; i < path.length; i++) {
2423
+ this.circularDependencies.add(path[i]);
2424
+ }
2425
+ }
2426
+ this.circularDependencies.add(name);
2427
+ return;
2428
+ }
2429
+ visiting.add(name);
2430
+ path.push(name);
2431
+ const deps = dependencies.get(name);
2432
+ if (deps) {
2433
+ for (const dep of deps) {
2434
+ if (dependencies.has(dep)) {
2435
+ detectCircular(dep, [...path]);
2436
+ }
2437
+ }
2438
+ }
2439
+ visiting.delete(name);
2440
+ visited.add(name);
2441
+ };
2442
+ for (const name of dependencies.keys()) {
2443
+ detectCircular(name, []);
2444
+ }
2445
+ }
2446
+ /**
2447
+ * Generate JSDoc warning for allOf conflicts
2448
+ * @param conflicts Array of conflict description strings
2449
+ * @returns JSDoc formatted warning string
2450
+ */
2451
+ generateConflictJSDoc(conflicts) {
2452
+ const lines = [" * @warning allOf property conflicts detected:"];
2453
+ for (const conflict of conflicts) {
2454
+ lines.push(` * - ${conflict}`);
2455
+ }
2456
+ return `${lines.join("\n")}
2457
+ `;
2458
+ }
2701
2459
  };
2702
2460
 
2703
2461
  // src/types.ts
@@ -2712,8 +2470,10 @@ function defineConfig(config) {
2712
2470
  FileOperationError,
2713
2471
  GeneratorError,
2714
2472
  OpenApiGenerator,
2473
+ PropertyGenerator,
2715
2474
  SchemaGenerationError,
2716
2475
  SpecValidationError,
2476
+ buildDateTimeValidation,
2717
2477
  defineConfig
2718
2478
  });
2719
2479
  //# sourceMappingURL=index.js.map