@cerios/openapi-to-zod 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/internal.mjs CHANGED
@@ -135,6 +135,1502 @@ function getBatchExitCode(summary) {
135
135
  return summary.failed > 0 ? 1 : 0;
136
136
  }
137
137
 
138
+ // src/utils/lru-cache.ts
139
+ var LRUCache = class {
140
+ constructor(maxSize) {
141
+ this.cache = /* @__PURE__ */ new Map();
142
+ this.maxSize = maxSize;
143
+ }
144
+ get capacity() {
145
+ return this.maxSize;
146
+ }
147
+ get(key) {
148
+ if (!this.cache.has(key)) return void 0;
149
+ const value = this.cache.get(key);
150
+ if (value === void 0) return void 0;
151
+ this.cache.delete(key);
152
+ this.cache.set(key, value);
153
+ return value;
154
+ }
155
+ set(key, value) {
156
+ if (this.cache.has(key)) {
157
+ this.cache.delete(key);
158
+ } else if (this.cache.size >= this.maxSize) {
159
+ const firstKey = this.cache.keys().next().value;
160
+ if (firstKey !== void 0) {
161
+ this.cache.delete(firstKey);
162
+ }
163
+ }
164
+ this.cache.set(key, value);
165
+ }
166
+ has(key) {
167
+ return this.cache.has(key);
168
+ }
169
+ clear() {
170
+ this.cache.clear();
171
+ }
172
+ size() {
173
+ return this.cache.size;
174
+ }
175
+ };
176
+
177
+ // src/utils/name-utils.ts
178
+ function sanitizeIdentifier(str) {
179
+ return str.replace(/[^a-zA-Z0-9._\-\s]+/g, "_");
180
+ }
181
+ function toCamelCase(str, options) {
182
+ const sanitized = sanitizeIdentifier(str);
183
+ const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
184
+ let name;
185
+ if (words.length === 0) {
186
+ name = str.charAt(0).toLowerCase() + str.slice(1);
187
+ } else if (words.length === 1) {
188
+ name = words[0].charAt(0).toLowerCase() + words[0].slice(1);
189
+ } else {
190
+ name = words[0].charAt(0).toLowerCase() + words[0].slice(1) + words.slice(1).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
191
+ }
192
+ if (options == null ? void 0 : options.prefix) {
193
+ const prefix = options.prefix.charAt(0).toLowerCase() + options.prefix.slice(1);
194
+ name = prefix + name.charAt(0).toUpperCase() + name.slice(1);
195
+ }
196
+ if (options == null ? void 0 : options.suffix) {
197
+ const suffix = options.suffix.charAt(0).toUpperCase() + options.suffix.slice(1);
198
+ name = name + suffix;
199
+ }
200
+ return name;
201
+ }
202
+ function toPascalCase(str) {
203
+ const stringValue = String(str);
204
+ const isAlreadyValidCase = /^[a-zA-Z][a-zA-Z0-9]*$/.test(stringValue);
205
+ if (isAlreadyValidCase) {
206
+ return stringValue.charAt(0).toUpperCase() + stringValue.slice(1);
207
+ }
208
+ const sanitized = sanitizeIdentifier(stringValue);
209
+ const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
210
+ let result;
211
+ if (words.length === 0) {
212
+ result = "Value";
213
+ } else {
214
+ result = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
215
+ }
216
+ if (/^\d/.test(result)) {
217
+ result = `N${result}`;
218
+ }
219
+ if (!result || /^_+$/.test(result)) {
220
+ return "Value";
221
+ }
222
+ return result;
223
+ }
224
+ function resolveRef(ref) {
225
+ const parts = ref.split("/");
226
+ return parts[parts.length - 1];
227
+ }
228
+
229
+ // src/utils/pattern-utils.ts
230
+ import { minimatch } from "minimatch";
231
+ function isValidGlobPattern(pattern) {
232
+ try {
233
+ new minimatch.Minimatch(pattern);
234
+ return true;
235
+ } catch {
236
+ return false;
237
+ }
238
+ }
239
+ function isGlobPattern(pattern) {
240
+ return /[*?[\]{}!]/.test(pattern);
241
+ }
242
+ function stripPrefix(input, pattern, ensureLeadingChar) {
243
+ if (!pattern) {
244
+ return input;
245
+ }
246
+ if (isGlobPattern(pattern) && !isValidGlobPattern(pattern)) {
247
+ console.warn(`\u26A0\uFE0F Invalid glob pattern "${pattern}": Pattern is malformed`);
248
+ return input;
249
+ }
250
+ if (isGlobPattern(pattern)) {
251
+ let longestMatch = -1;
252
+ for (let i = 1; i <= input.length; i++) {
253
+ const testPrefix = input.substring(0, i);
254
+ if (minimatch(testPrefix, pattern)) {
255
+ longestMatch = i;
256
+ }
257
+ }
258
+ if (longestMatch > 0) {
259
+ const stripped = input.substring(longestMatch);
260
+ if (ensureLeadingChar) {
261
+ if (stripped === "") {
262
+ return ensureLeadingChar;
263
+ }
264
+ if (!stripped.startsWith(ensureLeadingChar)) {
265
+ return `${ensureLeadingChar}${stripped}`;
266
+ }
267
+ }
268
+ return stripped === "" && !ensureLeadingChar ? input : stripped;
269
+ }
270
+ return input;
271
+ }
272
+ if (input.startsWith(pattern)) {
273
+ const stripped = input.substring(pattern.length);
274
+ if (ensureLeadingChar) {
275
+ if (stripped === "") {
276
+ return ensureLeadingChar;
277
+ }
278
+ if (!stripped.startsWith(ensureLeadingChar)) {
279
+ return `${ensureLeadingChar}${stripped}`;
280
+ }
281
+ }
282
+ return stripped;
283
+ }
284
+ return input;
285
+ }
286
+ function stripPathPrefix(path, pattern) {
287
+ if (!pattern) {
288
+ return path;
289
+ }
290
+ if (!isGlobPattern(pattern)) {
291
+ let normalizedPattern = pattern.trim();
292
+ if (!normalizedPattern.startsWith("/")) {
293
+ normalizedPattern = `/${normalizedPattern}`;
294
+ }
295
+ if (normalizedPattern.endsWith("/") && normalizedPattern !== "/") {
296
+ normalizedPattern = normalizedPattern.slice(0, -1);
297
+ }
298
+ return stripPrefix(path, normalizedPattern, "/");
299
+ }
300
+ return stripPrefix(path, pattern, "/");
301
+ }
302
+
303
+ // src/utils/string-utils.ts
304
+ function escapeDescription(str) {
305
+ return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
306
+ }
307
+ function escapePattern(str) {
308
+ return str.replace(/(?<!\\)\//g, "\\/");
309
+ }
310
+ function escapeJSDoc(str) {
311
+ return str.replace(/\*\//g, "*\\/");
312
+ }
313
+ function wrapNullable(validation, isNullable2) {
314
+ return isNullable2 ? `${validation}.nullable()` : validation;
315
+ }
316
+ function isNullable(schema, defaultNullable = false) {
317
+ if (schema.nullable === true) {
318
+ return true;
319
+ }
320
+ if (schema.nullable === false) {
321
+ return false;
322
+ }
323
+ if (Array.isArray(schema.type)) {
324
+ return schema.type.includes("null");
325
+ }
326
+ return defaultNullable;
327
+ }
328
+ function getPrimaryType(schema) {
329
+ if (Array.isArray(schema.type)) {
330
+ const nonNullType = schema.type.find((t) => t !== "null");
331
+ return nonNullType;
332
+ }
333
+ return schema.type;
334
+ }
335
+ function hasMultipleTypes(schema) {
336
+ if (Array.isArray(schema.type)) {
337
+ const nonNullTypes = schema.type.filter((t) => t !== "null");
338
+ return nonNullTypes.length > 1;
339
+ }
340
+ return false;
341
+ }
342
+ function addDescription(validation, description, useDescribe) {
343
+ if (!description || !useDescribe) return validation;
344
+ const escapedDesc = escapeDescription(description);
345
+ return `${validation}.describe("${escapedDesc}")`;
346
+ }
347
+
348
+ // src/validators/array-validator.ts
349
+ function generateArrayValidation(schema, context) {
350
+ var _a;
351
+ let validation;
352
+ if (schema.prefixItems && schema.prefixItems.length > 0) {
353
+ const tupleItems = schema.prefixItems.map((item) => context.generatePropertySchema(item, context.currentSchema));
354
+ validation = `z.tuple([${tupleItems.join(", ")}])`;
355
+ if (schema.items) {
356
+ const restSchema = context.generatePropertySchema(schema.items, context.currentSchema);
357
+ validation += `.rest(${restSchema})`;
358
+ } else if (schema.unevaluatedItems && typeof schema.unevaluatedItems === "object") {
359
+ const restSchema = context.generatePropertySchema(schema.unevaluatedItems, context.currentSchema);
360
+ validation += `.rest(${restSchema})`;
361
+ }
362
+ } else if (schema.items) {
363
+ const itemSchema = context.generatePropertySchema(schema.items, context.currentSchema);
364
+ validation = `z.array(${itemSchema})`;
365
+ if (schema.minItems !== void 0) {
366
+ validation += `.min(${schema.minItems})`;
367
+ }
368
+ if (schema.maxItems !== void 0) {
369
+ validation += `.max(${schema.maxItems})`;
370
+ }
371
+ if (schema.uniqueItems === true) {
372
+ validation += `.refine((items) => new Set(items).size === items.length, { message: "Array items must be unique" })`;
373
+ }
374
+ } else {
375
+ validation = "z.array(z.unknown())";
376
+ }
377
+ if (schema.contains) {
378
+ const containsSchema = context.generatePropertySchema(schema.contains, context.currentSchema);
379
+ const minCount = (_a = schema.minContains) != null ? _a : 1;
380
+ const maxCount = schema.maxContains;
381
+ if (maxCount !== void 0) {
382
+ validation += `.refine((arr) => { const matches = arr.filter(item => ${containsSchema}.safeParse(item).success); return matches.length >= ${minCount} && matches.length <= ${maxCount}; }, { message: "Array must contain between ${minCount} and ${maxCount} items matching the schema" })`;
383
+ } else {
384
+ validation += `.refine((arr) => arr.filter(item => ${containsSchema}.safeParse(item).success).length >= ${minCount}, { message: "Array must contain at least ${minCount} item(s) matching the schema" })`;
385
+ }
386
+ }
387
+ if (schema.unevaluatedItems === false && schema.prefixItems && schema.prefixItems.length > 0 && !schema.items) {
388
+ const prefixCount = schema.prefixItems.length;
389
+ validation += `.refine((arr) => arr.length <= ${prefixCount}, { message: "No unevaluated items allowed beyond prefix items" })`;
390
+ }
391
+ return addDescription(validation, schema.description, context.useDescribe);
392
+ }
393
+
394
+ // src/validators/composition-validator.ts
395
+ function isDiscriminatorRequired(schemas, discriminator, context) {
396
+ const invalidSchemas = [];
397
+ for (const schema of schemas) {
398
+ const resolved = resolveSchema(schema, context);
399
+ const required = resolved.required || [];
400
+ if (!required.includes(discriminator)) {
401
+ const schemaName = schema.$ref ? schema.$ref.split("/").pop() || "inline" : "inline";
402
+ invalidSchemas.push(schemaName);
403
+ }
404
+ }
405
+ return {
406
+ valid: invalidSchemas.length === 0,
407
+ invalidSchemas
408
+ };
409
+ }
410
+ function generateUnion(schemas, discriminator, isNullable2, context, options, currentSchema) {
411
+ if (schemas.length === 0) {
412
+ console.warn(
413
+ "[openapi-to-zod] Warning: Empty oneOf/anyOf array encountered. This is likely a malformed OpenAPI spec. Generating z.never() as fallback."
414
+ );
415
+ return wrapNullable(
416
+ 'z.never().describe("Empty oneOf/anyOf in OpenAPI spec - no valid schema defined")',
417
+ isNullable2
418
+ );
419
+ }
420
+ if (schemas.length === 1) {
421
+ let singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false, true);
422
+ if ((options == null ? void 0 : options.passthrough) && !singleSchema.includes(".catchall(")) {
423
+ singleSchema = `${singleSchema}.catchall(z.unknown())`;
424
+ }
425
+ return wrapNullable(singleSchema, isNullable2);
426
+ }
427
+ if (discriminator) {
428
+ let resolvedSchemas = schemas;
429
+ if ((options == null ? void 0 : options.discriminatorMapping) && context.resolveDiscriminatorMapping) {
430
+ resolvedSchemas = context.resolveDiscriminatorMapping(options.discriminatorMapping, schemas);
431
+ }
432
+ const discriminatorCheck = isDiscriminatorRequired(resolvedSchemas, discriminator, context);
433
+ if (!discriminatorCheck.valid) {
434
+ console.warn(
435
+ `[openapi-to-zod] Warning: Discriminator "${discriminator}" is not required in schemas: ${discriminatorCheck.invalidSchemas.join(", ")}. Falling back to z.union() instead of z.discriminatedUnion().`
436
+ );
437
+ let schemaStrings3 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema, false, true));
438
+ if (options == null ? void 0 : options.passthrough) {
439
+ schemaStrings3 = schemaStrings3.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
440
+ }
441
+ const fallbackDescription = `Discriminator "${discriminator}" is optional in some schemas (${discriminatorCheck.invalidSchemas.join(", ")}), using z.union() instead of z.discriminatedUnion()`;
442
+ const union3 = `z.union([${schemaStrings3.join(", ")}]).describe("${fallbackDescription}")`;
443
+ return wrapNullable(union3, isNullable2);
444
+ }
445
+ let schemaStrings2 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema, false, true));
446
+ if (options == null ? void 0 : options.passthrough) {
447
+ schemaStrings2 = schemaStrings2.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
448
+ }
449
+ const union2 = `z.discriminatedUnion("${discriminator}", [${schemaStrings2.join(", ")}])`;
450
+ return wrapNullable(union2, isNullable2);
451
+ }
452
+ let schemaStrings = schemas.map((s) => context.generatePropertySchema(s, currentSchema, false, true));
453
+ if (options == null ? void 0 : options.passthrough) {
454
+ schemaStrings = schemaStrings.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
455
+ }
456
+ const union = `z.union([${schemaStrings.join(", ")}])`;
457
+ return wrapNullable(union, isNullable2);
458
+ }
459
+ function resolveSchema(schema, context) {
460
+ if (schema.$ref && context.resolveSchemaRef) {
461
+ const resolved = context.resolveSchemaRef(schema.$ref);
462
+ if (resolved) {
463
+ return resolved;
464
+ }
465
+ }
466
+ return schema;
467
+ }
468
+ function collectProperties(schema, context) {
469
+ const resolved = resolveSchema(schema, context);
470
+ const props = /* @__PURE__ */ new Map();
471
+ const sourceName = schema.$ref ? schema.$ref.split("/").pop() || "unknown" : "inline";
472
+ if (resolved.properties) {
473
+ for (const [key, value] of Object.entries(resolved.properties)) {
474
+ props.set(key, { schema: value, source: sourceName });
475
+ }
476
+ }
477
+ if (resolved.allOf) {
478
+ for (const subSchema of resolved.allOf) {
479
+ const subProps = collectProperties(subSchema, context);
480
+ for (const [key, value] of subProps) {
481
+ if (!props.has(key)) {
482
+ props.set(key, value);
483
+ }
484
+ }
485
+ }
486
+ }
487
+ return props;
488
+ }
489
+ function schemasMatch(a, b) {
490
+ return JSON.stringify(a) === JSON.stringify(b);
491
+ }
492
+ function detectConflictingProperties(schemas, context) {
493
+ const conflicts = [];
494
+ const propertyMap = /* @__PURE__ */ new Map();
495
+ for (const schema of schemas) {
496
+ const schemaProps = collectProperties(schema, context);
497
+ for (const [propName, propInfo] of schemaProps) {
498
+ const existing = propertyMap.get(propName);
499
+ if (existing) {
500
+ if (!schemasMatch(existing.schema, propInfo.schema)) {
501
+ conflicts.push(
502
+ `Property "${propName}" has conflicting definitions in ${existing.source} and ${propInfo.source}`
503
+ );
504
+ }
505
+ } else {
506
+ propertyMap.set(propName, propInfo);
507
+ }
508
+ }
509
+ }
510
+ return conflicts;
511
+ }
512
+ function generateAllOf(schemas, isNullable2, context, currentSchema) {
513
+ if (schemas.length === 1) {
514
+ const singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false, true);
515
+ return wrapNullable(singleSchema, isNullable2);
516
+ }
517
+ const conflicts = detectConflictingProperties(schemas, context);
518
+ let conflictDescription = "";
519
+ if (conflicts.length > 0) {
520
+ for (const conflict of conflicts) {
521
+ console.warn(`[openapi-to-zod] Warning: allOf composition conflict - ${conflict}`);
522
+ }
523
+ conflictDescription = `allOf property conflicts detected: ${conflicts.join("; ")}`;
524
+ }
525
+ const allObjects = schemas.every((s) => s.type === "object" || s.properties || s.$ref || s.allOf);
526
+ let result;
527
+ if (allObjects) {
528
+ let merged = context.generatePropertySchema(schemas[0], currentSchema, false, true);
529
+ for (let i = 1; i < schemas.length; i++) {
530
+ const schema = schemas[i];
531
+ if (schema.$ref) {
532
+ const refSchema = context.generatePropertySchema(schema, currentSchema, false, true);
533
+ merged = `${merged}.extend(${refSchema}.shape)`;
534
+ } else if (context.generateInlineObjectShape && (schema.properties || schema.type === "object")) {
535
+ const inlineShape = context.generateInlineObjectShape(schema, currentSchema);
536
+ merged = `${merged}.extend(${inlineShape})`;
537
+ } else {
538
+ const schemaString = context.generatePropertySchema(schema, currentSchema, false, true);
539
+ merged = `${merged}.extend(${schemaString}.shape)`;
540
+ }
541
+ }
542
+ result = merged;
543
+ } else {
544
+ const schemaStrings = schemas.map((s) => context.generatePropertySchema(s, currentSchema, false, true));
545
+ let merged = schemaStrings[0];
546
+ for (let i = 1; i < schemaStrings.length; i++) {
547
+ merged = `${merged}.and(${schemaStrings[i]})`;
548
+ }
549
+ result = merged;
550
+ }
551
+ if (conflictDescription) {
552
+ result = `${result}.describe("${conflictDescription}")`;
553
+ }
554
+ return wrapNullable(result, isNullable2);
555
+ }
556
+
557
+ // src/validators/number-validator.ts
558
+ function generateNumberValidation(schema, isInt, useDescribe) {
559
+ let validation = isInt ? "z.number().int()" : "z.number()";
560
+ if (schema.minimum !== void 0) {
561
+ const isExclusive = schema.exclusiveMinimum === true;
562
+ validation += isExclusive ? `.gt(${schema.minimum})` : `.gte(${schema.minimum})`;
563
+ } else if (typeof schema.exclusiveMinimum === "number") {
564
+ validation += `.gt(${schema.exclusiveMinimum})`;
565
+ }
566
+ if (schema.maximum !== void 0) {
567
+ const isExclusive = schema.exclusiveMaximum === true;
568
+ validation += isExclusive ? `.lt(${schema.maximum})` : `.lte(${schema.maximum})`;
569
+ } else if (typeof schema.exclusiveMaximum === "number") {
570
+ validation += `.lt(${schema.exclusiveMaximum})`;
571
+ }
572
+ if (schema.multipleOf !== void 0) {
573
+ validation += `.multipleOf(${schema.multipleOf})`;
574
+ }
575
+ return addDescription(validation, schema.description, useDescribe);
576
+ }
577
+
578
+ // src/generators/jsdoc-generator.ts
579
+ function generateJSDoc(schema, name, options = { includeDescriptions: true }) {
580
+ if (!schema || typeof schema !== "object") {
581
+ return "";
582
+ }
583
+ if (!options.includeDescriptions) {
584
+ if (schema.deprecated) {
585
+ return "/** @deprecated */\n";
586
+ }
587
+ return "";
588
+ }
589
+ if (!schema.description && !schema.title && !schema.deprecated && !schema.examples && schema.example === void 0) {
590
+ return "";
591
+ }
592
+ const parts = [];
593
+ if (schema.title && typeof schema.title === "string" && (!name || schema.title !== name)) {
594
+ const sanitizedTitle = escapeJSDoc(schema.title).replace(/@/g, "\\@");
595
+ parts.push(sanitizedTitle);
596
+ }
597
+ if (schema.description && typeof schema.description === "string") {
598
+ const sanitizedDesc = escapeJSDoc(schema.description).replace(/@/g, "\\@").replace(/\*\//g, "*\\/");
599
+ parts.push(sanitizedDesc);
600
+ }
601
+ if (schema.examples && Array.isArray(schema.examples) && schema.examples.length > 0) {
602
+ try {
603
+ const examplesStr = schema.examples.map((ex) => JSON.stringify(ex)).join(", ");
604
+ parts.push(`@example ${examplesStr}`);
605
+ } catch (error) {
606
+ console.warn("Warning: Could not serialize schema examples", error);
607
+ }
608
+ } else if (schema.example !== void 0) {
609
+ try {
610
+ parts.push(`@example ${JSON.stringify(schema.example)}`);
611
+ } catch (error) {
612
+ console.warn("Warning: Could not serialize schema example", error);
613
+ }
614
+ }
615
+ if (schema.deprecated) {
616
+ parts.push("@deprecated");
617
+ }
618
+ if (parts.length === 0) {
619
+ return "";
620
+ }
621
+ const fullComment = parts.join(" ");
622
+ return `/** ${fullComment} */
623
+ `;
624
+ }
625
+
626
+ // src/validators/conditional-validator.ts
627
+ function generatePropertyAccess(propName) {
628
+ const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
629
+ return validIdentifier.test(propName) ? `obj.${propName}` : `obj["${propName}"]`;
630
+ }
631
+ function generateDependencies(schema, generatePropertySchema, currentSchema) {
632
+ if (!schema.dependencies) {
633
+ return "";
634
+ }
635
+ let result = "";
636
+ for (const [prop, dependency] of Object.entries(schema.dependencies)) {
637
+ if (Array.isArray(dependency)) {
638
+ if (dependency.length === 0) {
639
+ continue;
640
+ }
641
+ const propAccess = generatePropertyAccess(prop);
642
+ const checkLogic = dependency.map((p) => {
643
+ const pAccess = generatePropertyAccess(p);
644
+ return `if (${pAccess} === undefined) missing.push('${p}');`;
645
+ }).join("\n ");
646
+ result += `.superRefine((obj, ctx) => {
647
+ if (${propAccess} === undefined) return;
648
+ const missing: string[] = [];
649
+ ${checkLogic}
650
+ if (missing.length > 0) {
651
+ ctx.addIssue({
652
+ code: "custom",
653
+ message: \`When '${prop}' is present, the following properties are required: \${missing.join(', ')}\`,
654
+ path: []
655
+ });
656
+ }
657
+ })`;
658
+ } else if (generatePropertySchema) {
659
+ const depSchema = { ...dependency, type: dependency.type || "object" };
660
+ const depSchemaValidation = generatePropertySchema(depSchema, currentSchema);
661
+ const propAccess = generatePropertyAccess(prop);
662
+ result += `.superRefine((obj, ctx) => {
663
+ if (${propAccess} === undefined) return;
664
+ const validation = ${depSchemaValidation}.safeParse(obj);
665
+ if (!validation.success) {
666
+ const errors = validation.error.issues.map(i => \` - \${i.path.join('.')}: \${i.message}\`).join('\\n');
667
+ ctx.addIssue({
668
+ code: "custom",
669
+ message: \`When '${prop}' is present, object must satisfy additional constraints:\\n\${errors}\`,
670
+ path: []
671
+ });
672
+ }
673
+ })`;
674
+ }
675
+ }
676
+ return result;
677
+ }
678
+ function generateConditionalCheck(schema) {
679
+ const conditions = [];
680
+ if (schema.properties) {
681
+ for (const [prop, propSchema] of Object.entries(schema.properties)) {
682
+ const propAccess = generatePropertyAccess(prop);
683
+ if (propSchema.type) {
684
+ conditions.push(`typeof ${propAccess} === "${propSchema.type}"`);
685
+ }
686
+ if (propSchema.const !== void 0) {
687
+ const value = typeof propSchema.const === "string" ? `"${propSchema.const}"` : propSchema.const;
688
+ conditions.push(`${propAccess} === ${value}`);
689
+ }
690
+ if (propSchema.minimum !== void 0) {
691
+ conditions.push(`${propAccess} >= ${propSchema.minimum}`);
692
+ }
693
+ if (propSchema.maximum !== void 0) {
694
+ conditions.push(`${propAccess} <= ${propSchema.maximum}`);
695
+ }
696
+ }
697
+ }
698
+ if (schema.required) {
699
+ for (const prop of schema.required) {
700
+ conditions.push(`${generatePropertyAccess(prop)} !== undefined`);
701
+ }
702
+ }
703
+ return conditions.length > 0 ? conditions.join(" && ") : "true";
704
+ }
705
+ function generateConditionalValidation(schema) {
706
+ const checks = [];
707
+ if (schema.required) {
708
+ for (const prop of schema.required) {
709
+ checks.push(`${generatePropertyAccess(prop)} !== undefined`);
710
+ }
711
+ }
712
+ if (schema.properties) {
713
+ for (const [prop, propSchema] of Object.entries(schema.properties)) {
714
+ const propAccess = generatePropertyAccess(prop);
715
+ if (propSchema.minimum !== void 0) {
716
+ checks.push(`${propAccess} === undefined || ${propAccess} >= ${propSchema.minimum}`);
717
+ }
718
+ if (propSchema.maximum !== void 0) {
719
+ checks.push(`${propAccess} === undefined || ${propAccess} <= ${propSchema.maximum}`);
720
+ }
721
+ }
722
+ }
723
+ return checks.length > 0 ? checks.join(" && ") : "true";
724
+ }
725
+ function generateIfThenElse(schema) {
726
+ if (!schema.if || !schema.then && !schema.else) {
727
+ return "";
728
+ }
729
+ const ifCondition = generateConditionalCheck(schema.if);
730
+ if (schema.then && schema.else) {
731
+ const thenValidation = generateConditionalValidation(schema.then);
732
+ const elseValidation2 = generateConditionalValidation(schema.else);
733
+ const thenRequiredProps = schema.then.required || [];
734
+ const elseRequiredProps2 = schema.else.required || [];
735
+ return `.superRefine((obj, ctx) => {
736
+ const ifConditionMet = ${ifCondition};
737
+ if (ifConditionMet) {
738
+ // Then branch
739
+ const thenValid = ${thenValidation};
740
+ if (!thenValid) {
741
+ ${thenRequiredProps.length > 0 ? `
742
+ const missingThenProps = ${JSON.stringify(thenRequiredProps)}.filter(p => obj[p] === undefined);
743
+ const message = missingThenProps.length > 0
744
+ ? \`When condition is met, required properties are missing: \${missingThenProps.join(', ')}\`
745
+ : "When condition is met, validation constraints failed";
746
+ ` : `
747
+ const message = "When condition is met, validation constraints failed";
748
+ `}
749
+ ctx.addIssue({
750
+ code: "custom",
751
+ message: message,
752
+ path: []
753
+ });
754
+ }
755
+ } else {
756
+ // Else branch
757
+ const elseValid = ${elseValidation2};
758
+ if (!elseValid) {
759
+ ${elseRequiredProps2.length > 0 ? `
760
+ const missingElseProps = ${JSON.stringify(elseRequiredProps2)}.filter(p => obj[p] === undefined);
761
+ const message = missingElseProps.length > 0
762
+ ? \`When condition is not met, required properties are missing: \${missingElseProps.join(', ')}\`
763
+ : "When condition is not met, validation constraints failed";
764
+ ` : `
765
+ const message = "When condition is not met, validation constraints failed";
766
+ `}
767
+ ctx.addIssue({
768
+ code: "custom",
769
+ message: message,
770
+ path: []
771
+ });
772
+ }
773
+ }
774
+ })`;
775
+ }
776
+ if (schema.then) {
777
+ const thenValidation = generateConditionalValidation(schema.then);
778
+ const thenRequiredProps = schema.then.required || [];
779
+ return `.superRefine((obj, ctx) => {
780
+ const ifConditionMet = ${ifCondition};
781
+ if (ifConditionMet) {
782
+ const thenValid = ${thenValidation};
783
+ if (!thenValid) {
784
+ ${thenRequiredProps.length > 0 ? `
785
+ const missingProps = ${JSON.stringify(thenRequiredProps)}.filter(p => obj[p] === undefined);
786
+ const message = missingProps.length > 0
787
+ ? \`When condition is met, required properties are missing: \${missingProps.join(', ')}\`
788
+ : "When condition is met, validation constraints failed";
789
+ ` : `
790
+ const message = "When condition is met, validation constraints failed";
791
+ `}
792
+ ctx.addIssue({
793
+ code: "custom",
794
+ message: message,
795
+ path: []
796
+ });
797
+ }
798
+ }
799
+ })`;
800
+ }
801
+ if (!schema.else) return "";
802
+ const elseValidation = generateConditionalValidation(schema.else);
803
+ const elseRequiredProps = schema.else.required || [];
804
+ return `.superRefine((obj, ctx) => {
805
+ const ifConditionMet = ${ifCondition};
806
+ if (!ifConditionMet) {
807
+ const elseValid = ${elseValidation};
808
+ if (!elseValid) {
809
+ ${elseRequiredProps.length > 0 ? `
810
+ const missingProps = ${JSON.stringify(elseRequiredProps)}.filter(p => obj[p] === undefined);
811
+ const message = missingProps.length > 0
812
+ ? \`When condition is not met, required properties are missing: \${missingProps.join(', ')}\`
813
+ : "When condition is not met, validation constraints failed";
814
+ ` : `
815
+ const message = "When condition is not met, validation constraints failed";
816
+ `}
817
+ ctx.addIssue({
818
+ code: "custom",
819
+ message: message,
820
+ path: []
821
+ });
822
+ }
823
+ }
824
+ })`;
825
+ }
826
+ function generateDependentRequired(schema) {
827
+ if (!schema.dependentRequired) {
828
+ return "";
829
+ }
830
+ let result = "";
831
+ for (const [prop, requiredProps] of Object.entries(schema.dependentRequired)) {
832
+ if (requiredProps.length === 0) {
833
+ continue;
834
+ }
835
+ const propAccess = generatePropertyAccess(prop);
836
+ const checkLogic = requiredProps.map((rp) => {
837
+ const rpAccess = generatePropertyAccess(rp);
838
+ return `if (${rpAccess} === undefined) missing.push('${rp}');`;
839
+ }).join("\n ");
840
+ result += `.superRefine((obj, ctx) => {
841
+ if (${propAccess} === undefined) return;
842
+ const missing: string[] = [];
843
+ ${checkLogic}
844
+ if (missing.length > 0) {
845
+ ctx.addIssue({
846
+ code: "custom",
847
+ message: \`When '${prop}' is present, the following properties are required: \${missing.join(', ')}\`,
848
+ path: []
849
+ });
850
+ }
851
+ })`;
852
+ }
853
+ return result;
854
+ }
855
+
856
+ // src/validators/object-validator.ts
857
+ function needsQuoting(propName) {
858
+ const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
859
+ return !validIdentifier.test(propName);
860
+ }
861
+ function generatePropertyAccess2(propName) {
862
+ return needsQuoting(propName) ? `obj["${propName}"]` : `obj.${propName}`;
863
+ }
864
+ function generateObjectSchema(schema, context, currentSchema) {
865
+ const required = new Set(schema.required || []);
866
+ const properties = [];
867
+ if (schema.properties) {
868
+ for (const [propName, propSchema] of Object.entries(schema.properties)) {
869
+ if (!context.shouldIncludeProperty(propSchema)) {
870
+ continue;
871
+ }
872
+ const isRequired = required.has(propName);
873
+ const zodSchema = context.generatePropertySchema(propSchema, currentSchema);
874
+ const quotedPropName = needsQuoting(propName) ? `"${propName}"` : propName;
875
+ let propertyDef = ` ${quotedPropName}: ${zodSchema}`;
876
+ if (!isRequired) {
877
+ propertyDef += ".optional()";
878
+ }
879
+ const jsdoc = generateJSDoc(propSchema, propName, { includeDescriptions: context.includeDescriptions });
880
+ if (jsdoc) {
881
+ properties.push(`${jsdoc.trimEnd()}
882
+ ${propertyDef}`);
883
+ } else {
884
+ properties.push(propertyDef);
885
+ }
886
+ }
887
+ }
888
+ let objectMethod;
889
+ if (schema.additionalProperties === false) {
890
+ objectMethod = "z.strictObject";
891
+ } else {
892
+ switch (context.mode) {
893
+ case "strict":
894
+ objectMethod = "z.strictObject";
895
+ break;
896
+ case "loose":
897
+ objectMethod = "z.looseObject";
898
+ break;
899
+ default:
900
+ objectMethod = "z.object";
901
+ }
902
+ }
903
+ let objectDef = `${objectMethod}({
904
+ ${properties.join(",\n")}
905
+ })`;
906
+ if (schema.additionalProperties !== void 0) {
907
+ if (typeof schema.additionalProperties === "object") {
908
+ const additionalSchema = context.generatePropertySchema(schema.additionalProperties, currentSchema);
909
+ objectDef += `.catchall(${additionalSchema})`;
910
+ } else if (schema.additionalProperties === true) {
911
+ objectDef += ".catchall(z.unknown())";
912
+ }
913
+ } else if (schema.patternProperties) {
914
+ objectDef += ".catchall(z.unknown())";
915
+ }
916
+ if (schema.minProperties !== void 0 || schema.maxProperties !== void 0) {
917
+ const conditions = [];
918
+ if (schema.minProperties !== void 0) {
919
+ conditions.push(`Object.keys(obj).length >= ${schema.minProperties}`);
920
+ }
921
+ if (schema.maxProperties !== void 0) {
922
+ conditions.push(`Object.keys(obj).length <= ${schema.maxProperties}`);
923
+ }
924
+ const condition = conditions.join(" && ");
925
+ let message = "Object ";
926
+ if (schema.minProperties !== void 0 && schema.maxProperties !== void 0) {
927
+ message += `must have between ${schema.minProperties} and ${schema.maxProperties} properties`;
928
+ } else if (schema.minProperties !== void 0) {
929
+ message += `must have at least ${schema.minProperties} ${schema.minProperties === 1 ? "property" : "properties"}`;
930
+ } else {
931
+ message += `must have at most ${schema.maxProperties} ${schema.maxProperties === 1 ? "property" : "properties"}`;
932
+ }
933
+ objectDef += `.refine((obj) => ${condition}, { message: "${message}" })`;
934
+ }
935
+ const definedProps = new Set(Object.keys(schema.properties || {}));
936
+ const undefinedRequired = (schema.required || []).filter((prop) => !definedProps.has(prop));
937
+ if (undefinedRequired.length > 0) {
938
+ if (!objectDef.includes(".catchall(")) {
939
+ objectDef += ".catchall(z.unknown())";
940
+ }
941
+ const requiredChecks = undefinedRequired.map((prop) => `${generatePropertyAccess2(prop)} !== undefined`).join(" && ");
942
+ const propList = undefinedRequired.join(", ");
943
+ objectDef += `.refine((obj) => ${requiredChecks}, { message: "Missing required fields: ${propList}" })`;
944
+ }
945
+ if (schema.patternProperties) {
946
+ const definedProps2 = Object.keys(schema.properties || {});
947
+ const definedPropsSet = `new Set(${JSON.stringify(definedProps2)})`;
948
+ const patterns = Object.entries(schema.patternProperties);
949
+ const patternSchemas = patterns.map(([pattern, patternSchema]) => ({
950
+ pattern,
951
+ escapedPattern: pattern.replace(/\\/g, "\\\\").replace(/'/g, "\\'"),
952
+ zodSchema: context.generatePropertySchema(patternSchema, currentSchema)
953
+ }));
954
+ objectDef += `.superRefine((obj, ctx) => {
955
+ const definedPropsSet = ${definedPropsSet};
956
+ const patterns = ${JSON.stringify(patternSchemas.map((p) => ({ pattern: p.escapedPattern })))};
957
+ const schemas = [${patternSchemas.map((p) => p.zodSchema).join(", ")}];
958
+ const regexps = patterns.map(p => new RegExp(p.pattern));
959
+
960
+ // Check all object keys
961
+ for (const key of Object.keys(obj)) {
962
+ // Skip properties that are explicitly defined
963
+ if (definedPropsSet.has(key)) continue;
964
+
965
+ // Find first matching pattern (first-match-wins priority)
966
+ for (let i = 0; i < regexps.length; i++) {
967
+ if (regexps[i].test(key)) {
968
+ const validation = schemas[i].safeParse(obj[key]);
969
+ if (!validation.success) {
970
+ // Add detailed error messages with property name and pattern
971
+ for (const issue of validation.error.issues) {
972
+ ctx.addIssue({
973
+ ...issue,
974
+ path: [key, ...issue.path],
975
+ message: \`Property '\${key}' (pattern '\${patterns[i].pattern}'): \${issue.message}\`
976
+ });
977
+ }
978
+ }
979
+ break; // First match wins, stop checking other patterns
980
+ }
981
+ }
982
+ }
983
+ })`;
984
+ }
985
+ if (schema.propertyNames) {
986
+ const hasPattern = schema.propertyNames.pattern !== void 0;
987
+ const hasMinLength = schema.propertyNames.minLength !== void 0;
988
+ const hasMaxLength = schema.propertyNames.maxLength !== void 0;
989
+ if (hasPattern || hasMinLength || hasMaxLength) {
990
+ const escapedPattern = hasPattern && schema.propertyNames.pattern ? schema.propertyNames.pattern.replace(/\\/g, "\\\\").replace(/'/g, "\\'") : null;
991
+ const minLen = schema.propertyNames.minLength;
992
+ const maxLen = schema.propertyNames.maxLength;
993
+ objectDef += `.superRefine((obj, ctx) => {
994
+ ${escapedPattern ? `const pattern = /${escapedPattern}/;` : ""}
995
+
996
+ for (const key of Object.keys(obj)) {
997
+ const failures: string[] = [];
998
+
999
+ ${hasPattern ? `
1000
+ if (!pattern.test(key)) {
1001
+ failures.push("must match pattern '${schema.propertyNames.pattern}'");
1002
+ }
1003
+ ` : ""}
1004
+
1005
+ ${hasMinLength ? `
1006
+ if (key.length < ${minLen}) {
1007
+ failures.push("must be at least ${minLen} characters");
1008
+ }
1009
+ ` : ""}
1010
+
1011
+ ${hasMaxLength ? `
1012
+ if (key.length > ${maxLen}) {
1013
+ failures.push("must be at most ${maxLen} characters");
1014
+ }
1015
+ ` : ""}
1016
+
1017
+ if (failures.length > 0) {
1018
+ ctx.addIssue({
1019
+ code: "custom",
1020
+ message: \`Property name '\${key}' \${failures.join(", ")}\`,
1021
+ path: [key]
1022
+ });
1023
+ }
1024
+ }
1025
+ })`;
1026
+ }
1027
+ }
1028
+ objectDef += generateDependencies(schema, context.generatePropertySchema, currentSchema);
1029
+ objectDef += generateDependentRequired(schema);
1030
+ objectDef += generateIfThenElse(schema);
1031
+ return objectDef;
1032
+ }
1033
+
1034
+ // src/validators/string-validator.ts
1035
+ var DEFAULT_FORMAT_MAP = {
1036
+ uuid: "z.uuid()",
1037
+ email: "z.email()",
1038
+ uri: "z.url()",
1039
+ url: "z.url()",
1040
+ "uri-reference": 'z.string().refine((val) => !/\\s/.test(val), { message: "Must be a valid URI reference" })',
1041
+ hostname: 'z.string().refine((val) => /^(?=.{1,253}$)(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.)*(?!-)[A-Za-z0-9-]{1,63}(?<!-)$/.test(val), { message: "Must be a valid hostname" })',
1042
+ byte: "z.base64()",
1043
+ binary: "z.string()",
1044
+ date: "z.iso.date()",
1045
+ time: "z.iso.time()",
1046
+ duration: 'z.string().refine((val) => /^P(?:(?:\\d+Y)?(?:\\d+M)?(?:\\d+D)?(?:T(?:\\d+H)?(?:\\d+M)?(?:\\d+(?:\\.\\d+)?S)?)?|\\d+W)$/.test(val) && !/^PT?$/.test(val), { message: "Must be a valid ISO 8601 duration" })',
1047
+ ipv4: "z.ipv4()",
1048
+ ipv6: "z.ipv6()",
1049
+ emoji: "z.emoji()",
1050
+ base64: "z.base64()",
1051
+ base64url: "z.base64url()",
1052
+ nanoid: "z.nanoid()",
1053
+ cuid: "z.cuid()",
1054
+ cuid2: "z.cuid2()",
1055
+ ulid: "z.ulid()",
1056
+ cidr: "z.cidrv4()",
1057
+ // Default to v4
1058
+ cidrv4: "z.cidrv4()",
1059
+ cidrv6: "z.cidrv6()",
1060
+ "json-pointer": 'z.string().refine((val) => val === "" || /^(\\/([^~/]|~0|~1)+)+$/.test(val), { message: "Must be a valid JSON Pointer (RFC 6901)" })',
1061
+ "relative-json-pointer": 'z.string().refine((val) => /^(0|[1-9]\\d*)(#|(\\/([^~/]|~0|~1)+)*)$/.test(val), { message: "Must be a valid relative JSON Pointer" })'
1062
+ };
1063
+ function buildDateTimeValidation(pattern) {
1064
+ if (!pattern) {
1065
+ return "z.iso.datetime()";
1066
+ }
1067
+ const patternStr = pattern instanceof RegExp ? pattern.source : pattern;
1068
+ if (patternStr === "") {
1069
+ return "z.iso.datetime()";
1070
+ }
1071
+ try {
1072
+ new RegExp(patternStr);
1073
+ } catch (error) {
1074
+ throw new Error(
1075
+ `Invalid regular expression pattern for customDateTimeFormatRegex: ${patternStr}. ${error instanceof Error ? error.message : "Pattern is malformed"}`
1076
+ );
1077
+ }
1078
+ const escapedPattern = escapePattern(patternStr);
1079
+ return `z.string().regex(/${escapedPattern}/)`;
1080
+ }
1081
+ function generateStringValidation(schema, useDescribe, context) {
1082
+ let validation;
1083
+ const format = schema.format || "";
1084
+ if (format === "date-time") {
1085
+ validation = context.dateTimeValidation;
1086
+ } else {
1087
+ validation = DEFAULT_FORMAT_MAP[format] || "z.string()";
1088
+ }
1089
+ if (schema.minLength !== void 0) {
1090
+ validation += `.min(${schema.minLength})`;
1091
+ }
1092
+ if (schema.maxLength !== void 0) {
1093
+ validation += `.max(${schema.maxLength})`;
1094
+ }
1095
+ if (schema.pattern) {
1096
+ let escapedPattern = context.patternCache.get(schema.pattern);
1097
+ if (escapedPattern === void 0) {
1098
+ escapedPattern = escapePattern(schema.pattern);
1099
+ context.patternCache.set(schema.pattern, escapedPattern);
1100
+ }
1101
+ validation += `.regex(/${escapedPattern}/)`;
1102
+ }
1103
+ if (schema.contentEncoding && !schema.format) {
1104
+ switch (schema.contentEncoding) {
1105
+ case "base64":
1106
+ validation = "z.base64()";
1107
+ break;
1108
+ case "base64url":
1109
+ validation = "z.base64url()";
1110
+ break;
1111
+ case "quoted-printable":
1112
+ validation = 'z.string().refine((val) => /^[\\x20-\\x7E\\r\\n=]*$/.test(val), { message: "Must be valid quoted-printable encoding" })';
1113
+ break;
1114
+ case "7bit":
1115
+ case "8bit":
1116
+ case "binary":
1117
+ validation = "z.string()";
1118
+ break;
1119
+ default:
1120
+ validation = `z.string().describe("Content encoding: ${schema.contentEncoding}")`;
1121
+ }
1122
+ if (schema.minLength !== void 0) {
1123
+ validation += `.min(${schema.minLength})`;
1124
+ }
1125
+ if (schema.maxLength !== void 0) {
1126
+ validation += `.max(${schema.maxLength})`;
1127
+ }
1128
+ if (schema.pattern) {
1129
+ let escapedPattern = context.patternCache.get(schema.pattern);
1130
+ if (escapedPattern === void 0) {
1131
+ escapedPattern = escapePattern(schema.pattern);
1132
+ context.patternCache.set(schema.pattern, escapedPattern);
1133
+ }
1134
+ validation += `.regex(/${escapedPattern}/)`;
1135
+ }
1136
+ } else if (schema.contentMediaType) {
1137
+ const mediaType = schema.contentMediaType;
1138
+ if (mediaType === "application/json") {
1139
+ validation += `.refine((val) => { try { JSON.parse(val); return true; } catch { return false; } }, { message: "Must be valid JSON" })`;
1140
+ } else if (mediaType === "application/xml" || mediaType === "text/xml") {
1141
+ validation += `.refine((val) => { try { if (typeof DOMParser !== "undefined") { const parser = new DOMParser(); const doc = parser.parseFromString(val, "text/xml"); return !doc.querySelector("parsererror"); } return /^\\s*<[^>]+>/.test(val); } catch { return false; } }, { message: "Must be valid XML" })`;
1142
+ } else if (mediaType === "application/yaml" || mediaType === "application/x-yaml" || mediaType === "text/yaml") {
1143
+ validation += `.refine((val) => { try { return val.trim().length > 0 && !/^[[{]/.test(val.trim()); } catch { return false; } }, { message: "Must be valid YAML" })`;
1144
+ } else if (mediaType === "text/html") {
1145
+ validation += `.refine((val) => /<[^>]+>/.test(val), { message: "Must contain HTML tags" })`;
1146
+ } else if (mediaType === "text/plain") {
1147
+ validation += `.refine(() => true, { message: "Plain text content" })`;
1148
+ }
1149
+ }
1150
+ return addDescription(validation, schema.description, useDescribe);
1151
+ }
1152
+
1153
+ // src/generators/property-generator.ts
1154
+ var _PropertyGenerator = class _PropertyGenerator {
1155
+ constructor(context) {
1156
+ // Performance optimization: Memoize filtered property results
1157
+ this.filteredPropsCache = /* @__PURE__ */ new Map();
1158
+ // Performance optimization: LRU cache for generated schemas
1159
+ this.schemaCache = new LRUCache(500);
1160
+ this.context = context;
1161
+ }
1162
+ /**
1163
+ * Check if a property should be included based on schemaType and readOnly/writeOnly flags
1164
+ */
1165
+ shouldIncludeProperty(schema) {
1166
+ const rule = _PropertyGenerator.INCLUSION_RULES[this.context.schemaType];
1167
+ return rule(schema);
1168
+ }
1169
+ /**
1170
+ * Recursively filter any schema type (helper for composition schemas)
1171
+ */
1172
+ filterSchemaRecursive(schema) {
1173
+ if (schema.$ref) {
1174
+ return schema;
1175
+ }
1176
+ if (schema.properties) {
1177
+ return this.filterNestedProperties(schema);
1178
+ }
1179
+ if (schema.type === "array" && schema.items && typeof schema.items === "object" && schema.items.properties) {
1180
+ return {
1181
+ ...schema,
1182
+ items: this.filterNestedProperties(schema.items)
1183
+ };
1184
+ }
1185
+ return schema;
1186
+ }
1187
+ /**
1188
+ * Recursively filter properties in nested objects based on readOnly/writeOnly
1189
+ * Performance optimized with memoization
1190
+ */
1191
+ filterNestedProperties(schema) {
1192
+ var _a, _b;
1193
+ const propKeys = schema.properties ? Object.keys(schema.properties).sort().join(",") : "";
1194
+ const cacheKey = `${this.context.schemaType}:${schema.type || "unknown"}:${propKeys}:${((_a = schema.required) == null ? void 0 : _a.join(",")) || ""}`;
1195
+ const cached = this.filteredPropsCache.get(cacheKey);
1196
+ if (cached) {
1197
+ return cached;
1198
+ }
1199
+ if (!schema.properties) {
1200
+ return schema;
1201
+ }
1202
+ const filteredProperties = {};
1203
+ const filteredRequired = [];
1204
+ for (const [propName, propSchema] of Object.entries(schema.properties)) {
1205
+ if (!this.shouldIncludeProperty(propSchema)) {
1206
+ continue;
1207
+ }
1208
+ let filteredPropSchema = propSchema;
1209
+ if (propSchema.type === "object" && propSchema.properties) {
1210
+ filteredPropSchema = this.filterNestedProperties(propSchema);
1211
+ } else if (propSchema.type === "array" && propSchema.items && typeof propSchema.items === "object" && propSchema.items.properties) {
1212
+ filteredPropSchema = {
1213
+ ...propSchema,
1214
+ items: this.filterNestedProperties(propSchema.items)
1215
+ };
1216
+ } else if (propSchema.allOf || propSchema.oneOf || propSchema.anyOf) {
1217
+ if (propSchema.allOf) {
1218
+ filteredPropSchema = {
1219
+ ...propSchema,
1220
+ allOf: propSchema.allOf.map((s) => this.filterSchemaRecursive(s))
1221
+ };
1222
+ } else if (propSchema.oneOf) {
1223
+ filteredPropSchema = {
1224
+ ...propSchema,
1225
+ oneOf: propSchema.oneOf.map((s) => this.filterSchemaRecursive(s))
1226
+ };
1227
+ } else if (propSchema.anyOf) {
1228
+ filteredPropSchema = {
1229
+ ...propSchema,
1230
+ anyOf: propSchema.anyOf.map((s) => this.filterSchemaRecursive(s))
1231
+ };
1232
+ }
1233
+ }
1234
+ filteredProperties[propName] = filteredPropSchema;
1235
+ if ((_b = schema.required) == null ? void 0 : _b.includes(propName)) {
1236
+ filteredRequired.push(propName);
1237
+ }
1238
+ }
1239
+ const result = {
1240
+ ...schema,
1241
+ properties: filteredProperties,
1242
+ required: filteredRequired.length > 0 ? filteredRequired : void 0
1243
+ };
1244
+ this.filteredPropsCache.set(cacheKey, result);
1245
+ return result;
1246
+ }
1247
+ /**
1248
+ * Resolve discriminator mapping to actual schema references
1249
+ */
1250
+ resolveDiscriminatorMapping(mapping, schemas) {
1251
+ const mappedSchemas = [];
1252
+ for (const [_, schemaRef] of Object.entries(mapping)) {
1253
+ const matchingSchema = schemas.find((s) => {
1254
+ if (s.$ref) {
1255
+ return s.$ref === schemaRef || s.$ref.endsWith(schemaRef);
1256
+ }
1257
+ return false;
1258
+ });
1259
+ if (matchingSchema) {
1260
+ mappedSchemas.push(matchingSchema);
1261
+ } else {
1262
+ mappedSchemas.push({ $ref: schemaRef });
1263
+ }
1264
+ }
1265
+ for (const schema of schemas) {
1266
+ if (!mappedSchemas.includes(schema)) {
1267
+ mappedSchemas.push(schema);
1268
+ }
1269
+ }
1270
+ return mappedSchemas;
1271
+ }
1272
+ /**
1273
+ * Resolve a $ref string to the actual schema
1274
+ */
1275
+ resolveSchemaRef(ref) {
1276
+ var _a, _b;
1277
+ const schemaName = ref.split("/").pop();
1278
+ if (!schemaName) return void 0;
1279
+ return (_b = (_a = this.context.spec.components) == null ? void 0 : _a.schemas) == null ? void 0 : _b[schemaName];
1280
+ }
1281
+ /**
1282
+ * Resolve a schema name through any aliases to get the actual schema name
1283
+ * If the schema is an alias (allOf with single $ref), return the target name
1284
+ */
1285
+ resolveSchemaAlias(schemaName) {
1286
+ var _a, _b;
1287
+ const schema = (_b = (_a = this.context.spec.components) == null ? void 0 : _a.schemas) == null ? void 0 : _b[schemaName];
1288
+ if (!schema) return schemaName;
1289
+ if (schema.allOf && schema.allOf.length === 1 && schema.allOf[0].$ref && !schema.properties && !schema.oneOf && !schema.anyOf) {
1290
+ const targetName = resolveRef(schema.allOf[0].$ref);
1291
+ return this.resolveSchemaAlias(targetName);
1292
+ }
1293
+ return schemaName;
1294
+ }
1295
+ /**
1296
+ * Check if this is a circular dependency through aliases
1297
+ */
1298
+ isCircularThroughAlias(fromSchema, toSchema) {
1299
+ var _a, _b;
1300
+ const toSchemaSpec = (_b = (_a = this.context.spec.components) == null ? void 0 : _a.schemas) == null ? void 0 : _b[toSchema];
1301
+ if (!toSchemaSpec) return false;
1302
+ if (toSchemaSpec.allOf && toSchemaSpec.allOf.length === 1 && toSchemaSpec.allOf[0].$ref) {
1303
+ const aliasTarget = resolveRef(toSchemaSpec.allOf[0].$ref);
1304
+ return aliasTarget === fromSchema;
1305
+ }
1306
+ return false;
1307
+ }
1308
+ /**
1309
+ * Generate union for multiple types (OpenAPI 3.1)
1310
+ */
1311
+ generateMultiTypeUnion(schema, currentSchema) {
1312
+ if (!Array.isArray(schema.type)) {
1313
+ return "z.unknown()";
1314
+ }
1315
+ const nonNullTypes = schema.type.filter((t) => t !== "null");
1316
+ const schemas = nonNullTypes.map((type) => {
1317
+ const typeSchema = { ...schema, type };
1318
+ return this.generatePropertySchema(typeSchema, currentSchema);
1319
+ });
1320
+ return `z.union([${schemas.join(", ")}])`;
1321
+ }
1322
+ /**
1323
+ * Apply unevaluatedProperties validation to a schema
1324
+ */
1325
+ applyUnevaluatedProperties(baseSchema, schema) {
1326
+ const evaluatedProps = /* @__PURE__ */ new Set();
1327
+ if (schema.properties) {
1328
+ for (const propName of Object.keys(schema.properties)) {
1329
+ evaluatedProps.add(propName);
1330
+ }
1331
+ }
1332
+ const collectPropsFromComposition = (schemas) => {
1333
+ var _a, _b;
1334
+ if (!schemas) return;
1335
+ for (const subSchema of schemas) {
1336
+ if (subSchema.properties) {
1337
+ for (const propName of Object.keys(subSchema.properties)) {
1338
+ evaluatedProps.add(propName);
1339
+ }
1340
+ }
1341
+ if (subSchema.$ref) {
1342
+ const refSchema = (_b = (_a = this.context.spec.components) == null ? void 0 : _a.schemas) == null ? void 0 : _b[subSchema.$ref.split("/").pop() || ""];
1343
+ if (refSchema == null ? void 0 : refSchema.properties) {
1344
+ for (const propName of Object.keys(refSchema.properties)) {
1345
+ evaluatedProps.add(propName);
1346
+ }
1347
+ }
1348
+ }
1349
+ }
1350
+ };
1351
+ collectPropsFromComposition(schema.allOf);
1352
+ collectPropsFromComposition(schema.oneOf);
1353
+ collectPropsFromComposition(schema.anyOf);
1354
+ const evaluatedPropsSet = `new Set(${JSON.stringify([...evaluatedProps])})`;
1355
+ let schemaWithCatchall = baseSchema;
1356
+ if (baseSchema.includes(".union([") || baseSchema.includes(".discriminatedUnion(")) {
1357
+ schemaWithCatchall = baseSchema;
1358
+ } else if (baseSchema.includes(".extend(")) {
1359
+ schemaWithCatchall = `${baseSchema}.catchall(z.unknown())`;
1360
+ }
1361
+ if (schema.unevaluatedProperties === false) {
1362
+ return `${schemaWithCatchall}.refine((obj) => Object.keys(obj).every(key => ${evaluatedPropsSet}.has(key)), { message: "No unevaluated properties allowed" })`;
1363
+ } else if (typeof schema.unevaluatedProperties === "object") {
1364
+ const unevalSchema = this.generatePropertySchema(schema.unevaluatedProperties);
1365
+ return `${schemaWithCatchall}.refine((obj) => Object.keys(obj).filter(key => !${evaluatedPropsSet}.has(key)).every(key => ${unevalSchema}.safeParse(obj[key]).success), { message: "Unevaluated properties must match the schema" })`;
1366
+ }
1367
+ return baseSchema;
1368
+ }
1369
+ /**
1370
+ * Generate Zod schema for a property
1371
+ * @param schema - The OpenAPI schema to generate
1372
+ * @param currentSchema - The name of the current schema being processed (for circular ref detection)
1373
+ * @param isTopLevel - Whether this is a top-level schema definition
1374
+ * @param suppressDefaultNullable - When true, don't apply defaultNullable (used when outer schema has explicit nullable: false)
1375
+ */
1376
+ generatePropertySchema(schema, currentSchema, isTopLevel = false, suppressDefaultNullable = false) {
1377
+ var _a, _b, _c, _d, _e;
1378
+ const isCacheable = !schema.$ref && !schema.allOf && !schema.oneOf && !schema.anyOf && !currentSchema;
1379
+ if (isCacheable) {
1380
+ const cacheKey = JSON.stringify({
1381
+ schema,
1382
+ type: this.context.schemaType,
1383
+ mode: this.context.mode,
1384
+ suppressDefaultNullable
1385
+ });
1386
+ const cached = this.schemaCache.get(cacheKey);
1387
+ if (cached) {
1388
+ return cached;
1389
+ }
1390
+ }
1391
+ if ((this.context.schemaType === "request" || this.context.schemaType === "response") && schema.properties) {
1392
+ schema = this.filterNestedProperties(schema);
1393
+ }
1394
+ const isEnum = !!schema.enum;
1395
+ const isConst = schema.const !== void 0;
1396
+ const shouldApplyDefaultNullable = !isTopLevel && !isEnum && !isConst && !suppressDefaultNullable;
1397
+ const effectiveDefaultNullable = shouldApplyDefaultNullable ? this.context.defaultNullable : false;
1398
+ const nullable = isNullable(schema, effectiveDefaultNullable);
1399
+ if (hasMultipleTypes(schema)) {
1400
+ const union = this.generateMultiTypeUnion(schema, currentSchema);
1401
+ return wrapNullable(union, nullable);
1402
+ }
1403
+ if (schema.$ref) {
1404
+ const refName = resolveRef(schema.$ref);
1405
+ const resolvedRefName = this.resolveSchemaAlias(refName);
1406
+ if (currentSchema && refName !== currentSchema && !isTopLevel) {
1407
+ if (!this.context.schemaDependencies.has(currentSchema)) {
1408
+ this.context.schemaDependencies.set(currentSchema, /* @__PURE__ */ new Set());
1409
+ }
1410
+ (_a = this.context.schemaDependencies.get(currentSchema)) == null ? void 0 : _a.add(refName);
1411
+ }
1412
+ const strippedRefName = stripPrefix(resolvedRefName, this.context.stripSchemaPrefix);
1413
+ const schemaName = `${toCamelCase(strippedRefName, this.context.namingOptions)}Schema`;
1414
+ if (currentSchema && (refName === currentSchema || this.isCircularThroughAlias(currentSchema, refName))) {
1415
+ const lazySchema = `z.lazy((): z.ZodTypeAny => ${schemaName})`;
1416
+ return wrapNullable(lazySchema, nullable);
1417
+ }
1418
+ return wrapNullable(schemaName, nullable);
1419
+ }
1420
+ if (schema.const !== void 0) {
1421
+ const literalValue = typeof schema.const === "string" ? `"${schema.const}"` : schema.const;
1422
+ const zodLiteral = `z.literal(${literalValue})`;
1423
+ return wrapNullable(zodLiteral, nullable);
1424
+ }
1425
+ if (schema.enum) {
1426
+ const allBooleans = schema.enum.every((v) => typeof v === "boolean");
1427
+ if (allBooleans) {
1428
+ const zodBoolean = "z.boolean()";
1429
+ return wrapNullable(zodBoolean, nullable);
1430
+ }
1431
+ const allStrings = schema.enum.every((v) => typeof v === "string");
1432
+ if (allStrings) {
1433
+ const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
1434
+ const zodEnum = `z.enum([${enumValues}])`;
1435
+ return wrapNullable(zodEnum, nullable);
1436
+ }
1437
+ const literalValues = schema.enum.map((v) => {
1438
+ if (typeof v === "string") {
1439
+ return `z.literal("${v}")`;
1440
+ }
1441
+ return `z.literal(${v})`;
1442
+ }).join(", ");
1443
+ const zodUnion = `z.union([${literalValues}])`;
1444
+ return wrapNullable(zodUnion, nullable);
1445
+ }
1446
+ if (schema.allOf) {
1447
+ const compositionNullable = isNullable(schema, false);
1448
+ let composition = generateAllOf(
1449
+ schema.allOf,
1450
+ compositionNullable,
1451
+ {
1452
+ generatePropertySchema: this.generatePropertySchema.bind(this),
1453
+ generateInlineObjectShape: this.generateInlineObjectShape.bind(this),
1454
+ resolveSchemaRef: this.resolveSchemaRef.bind(this)
1455
+ },
1456
+ currentSchema
1457
+ );
1458
+ if (schema.unevaluatedProperties !== void 0) {
1459
+ composition = this.applyUnevaluatedProperties(composition, schema);
1460
+ }
1461
+ return composition;
1462
+ }
1463
+ if (schema.oneOf) {
1464
+ const compositionNullable = isNullable(schema, false);
1465
+ const needsPassthrough = schema.unevaluatedProperties !== void 0;
1466
+ let composition = generateUnion(
1467
+ schema.oneOf,
1468
+ (_b = schema.discriminator) == null ? void 0 : _b.propertyName,
1469
+ compositionNullable,
1470
+ {
1471
+ generatePropertySchema: this.generatePropertySchema.bind(this),
1472
+ resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
1473
+ resolveSchemaRef: this.resolveSchemaRef.bind(this)
1474
+ },
1475
+ {
1476
+ passthrough: needsPassthrough,
1477
+ discriminatorMapping: (_c = schema.discriminator) == null ? void 0 : _c.mapping
1478
+ },
1479
+ currentSchema
1480
+ );
1481
+ if (schema.unevaluatedProperties !== void 0) {
1482
+ composition = this.applyUnevaluatedProperties(composition, schema);
1483
+ }
1484
+ return composition;
1485
+ }
1486
+ if (schema.anyOf) {
1487
+ const compositionNullable = isNullable(schema, false);
1488
+ const needsPassthrough = schema.unevaluatedProperties !== void 0;
1489
+ let composition = generateUnion(
1490
+ schema.anyOf,
1491
+ (_d = schema.discriminator) == null ? void 0 : _d.propertyName,
1492
+ compositionNullable,
1493
+ {
1494
+ generatePropertySchema: this.generatePropertySchema.bind(this),
1495
+ resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
1496
+ resolveSchemaRef: this.resolveSchemaRef.bind(this)
1497
+ },
1498
+ {
1499
+ passthrough: needsPassthrough,
1500
+ discriminatorMapping: (_e = schema.discriminator) == null ? void 0 : _e.mapping
1501
+ },
1502
+ currentSchema
1503
+ );
1504
+ if (schema.unevaluatedProperties !== void 0) {
1505
+ composition = this.applyUnevaluatedProperties(composition, schema);
1506
+ }
1507
+ return composition;
1508
+ }
1509
+ if (schema.not) {
1510
+ const notSchema = this.generatePropertySchema(schema.not, currentSchema);
1511
+ let baseValidation;
1512
+ if (schema.type || schema.properties || schema.items) {
1513
+ const { not: _, ...baseSchema } = schema;
1514
+ baseValidation = this.generatePropertySchema(baseSchema, currentSchema);
1515
+ } else {
1516
+ baseValidation = "z.unknown()";
1517
+ }
1518
+ const refined = `${baseValidation}.refine((val) => !${notSchema}.safeParse(val).success, { message: "Value must not match the excluded schema" })`;
1519
+ return wrapNullable(refined, nullable);
1520
+ }
1521
+ let validation = "";
1522
+ const primaryType = getPrimaryType(schema);
1523
+ switch (primaryType) {
1524
+ case "string":
1525
+ validation = generateStringValidation(schema, this.context.useDescribe, {
1526
+ dateTimeValidation: this.context.dateTimeValidation,
1527
+ patternCache: this.context.patternCache
1528
+ });
1529
+ break;
1530
+ case "number":
1531
+ validation = generateNumberValidation(schema, false, this.context.useDescribe);
1532
+ break;
1533
+ case "integer":
1534
+ validation = generateNumberValidation(schema, true, this.context.useDescribe);
1535
+ break;
1536
+ case "boolean":
1537
+ validation = "z.boolean()";
1538
+ validation = addDescription(validation, schema.description, this.context.useDescribe);
1539
+ break;
1540
+ case "array":
1541
+ validation = generateArrayValidation(schema, {
1542
+ generatePropertySchema: this.generatePropertySchema.bind(this),
1543
+ useDescribe: this.context.useDescribe,
1544
+ currentSchema
1545
+ });
1546
+ break;
1547
+ case "object":
1548
+ if (schema.properties || schema.required || schema.minProperties !== void 0 || schema.maxProperties !== void 0 || schema.patternProperties || schema.propertyNames) {
1549
+ validation = generateObjectSchema(
1550
+ schema,
1551
+ {
1552
+ generatePropertySchema: this.generatePropertySchema.bind(this),
1553
+ shouldIncludeProperty: this.shouldIncludeProperty.bind(this),
1554
+ mode: this.context.mode,
1555
+ includeDescriptions: this.context.includeDescriptions,
1556
+ useDescribe: this.context.useDescribe
1557
+ },
1558
+ currentSchema
1559
+ );
1560
+ validation = addDescription(validation, schema.description, this.context.useDescribe);
1561
+ } else {
1562
+ switch (this.context.emptyObjectBehavior) {
1563
+ case "strict":
1564
+ validation = "z.strictObject({})";
1565
+ break;
1566
+ case "loose":
1567
+ validation = "z.looseObject({})";
1568
+ break;
1569
+ default:
1570
+ validation = "z.record(z.string(), z.unknown())";
1571
+ break;
1572
+ }
1573
+ validation = addDescription(validation, schema.description, this.context.useDescribe);
1574
+ }
1575
+ break;
1576
+ default:
1577
+ validation = "z.unknown()";
1578
+ validation = addDescription(validation, schema.description, this.context.useDescribe);
1579
+ }
1580
+ const result = wrapNullable(validation, nullable);
1581
+ if (isCacheable) {
1582
+ const cacheKey = JSON.stringify({ schema, type: this.context.schemaType, mode: this.context.mode });
1583
+ this.schemaCache.set(cacheKey, result);
1584
+ }
1585
+ return result;
1586
+ }
1587
+ /**
1588
+ * Generate inline object shape for use with .extend()
1589
+ * Returns just the shape object literal: { prop1: z.string(), prop2: z.number() }
1590
+ *
1591
+ * This method is specifically for allOf compositions where we need to pass
1592
+ * the shape directly to .extend() instead of using z.object({...}).shape.
1593
+ * This avoids the .nullable().shape bug when inline objects have nullable: true.
1594
+ *
1595
+ * According to Zod docs (https://zod.dev/api?id=extend):
1596
+ * - .extend() accepts an object of shape definitions
1597
+ * - e.g., baseSchema.extend({ prop: z.string() })
1598
+ */
1599
+ generateInlineObjectShape(schema, currentSchema) {
1600
+ const required = new Set(schema.required || []);
1601
+ const properties = [];
1602
+ if (schema.properties) {
1603
+ for (const [propName, propSchema] of Object.entries(schema.properties)) {
1604
+ if (!this.shouldIncludeProperty(propSchema)) {
1605
+ continue;
1606
+ }
1607
+ const isRequired = required.has(propName);
1608
+ const zodSchema = this.generatePropertySchema(propSchema, currentSchema);
1609
+ const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
1610
+ const quotedPropName = validIdentifier.test(propName) ? propName : `"${propName}"`;
1611
+ let propertyDef = `${quotedPropName}: ${zodSchema}`;
1612
+ if (!isRequired) {
1613
+ propertyDef += ".optional()";
1614
+ }
1615
+ properties.push(propertyDef);
1616
+ }
1617
+ }
1618
+ if (properties.length === 0) {
1619
+ return "{}";
1620
+ }
1621
+ return `{
1622
+ ${properties.map((p) => ` ${p}`).join(",\n")}
1623
+ }`;
1624
+ }
1625
+ };
1626
+ // Performance optimization: Lookup table for faster inclusion checks
1627
+ _PropertyGenerator.INCLUSION_RULES = {
1628
+ request: (schema) => !schema.readOnly,
1629
+ response: (schema) => !schema.writeOnly,
1630
+ all: () => true
1631
+ };
1632
+ var PropertyGenerator = _PropertyGenerator;
1633
+
138
1634
  // src/utils/config-schemas.ts
139
1635
  import { z } from "zod";
140
1636
  var RequestResponseOptionsSchema = z.strictObject({
@@ -221,95 +1717,8 @@ function getResponseParseMethod(contentType, fallback = "text") {
221
1717
  return { method: fallback, isUnknown: true };
222
1718
  }
223
1719
 
224
- // src/utils/lru-cache.ts
225
- var LRUCache = class {
226
- constructor(maxSize) {
227
- this.cache = /* @__PURE__ */ new Map();
228
- this.maxSize = maxSize;
229
- }
230
- get capacity() {
231
- return this.maxSize;
232
- }
233
- get(key) {
234
- if (!this.cache.has(key)) return void 0;
235
- const value = this.cache.get(key);
236
- if (value === void 0) return void 0;
237
- this.cache.delete(key);
238
- this.cache.set(key, value);
239
- return value;
240
- }
241
- set(key, value) {
242
- if (this.cache.has(key)) {
243
- this.cache.delete(key);
244
- } else if (this.cache.size >= this.maxSize) {
245
- const firstKey = this.cache.keys().next().value;
246
- if (firstKey !== void 0) {
247
- this.cache.delete(firstKey);
248
- }
249
- }
250
- this.cache.set(key, value);
251
- }
252
- has(key) {
253
- return this.cache.has(key);
254
- }
255
- clear() {
256
- this.cache.clear();
257
- }
258
- size() {
259
- return this.cache.size;
260
- }
261
- };
262
-
263
- // src/utils/name-utils.ts
264
- function sanitizeIdentifier(str) {
265
- return str.replace(/[^a-zA-Z0-9._\-\s]+/g, "_");
266
- }
267
- function toCamelCase(str, options) {
268
- const sanitized = sanitizeIdentifier(str);
269
- const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
270
- let name;
271
- if (words.length === 0) {
272
- name = str.charAt(0).toLowerCase() + str.slice(1);
273
- } else if (words.length === 1) {
274
- name = words[0].charAt(0).toLowerCase() + words[0].slice(1);
275
- } else {
276
- name = words[0].charAt(0).toLowerCase() + words[0].slice(1) + words.slice(1).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
277
- }
278
- if (options == null ? void 0 : options.prefix) {
279
- const prefix = options.prefix.charAt(0).toLowerCase() + options.prefix.slice(1);
280
- name = prefix + name.charAt(0).toUpperCase() + name.slice(1);
281
- }
282
- if (options == null ? void 0 : options.suffix) {
283
- const suffix = options.suffix.charAt(0).toUpperCase() + options.suffix.slice(1);
284
- name = name + suffix;
285
- }
286
- return name;
287
- }
288
- function toPascalCase(str) {
289
- const stringValue = String(str);
290
- const isAlreadyValidCase = /^[a-zA-Z][a-zA-Z0-9]*$/.test(stringValue);
291
- if (isAlreadyValidCase) {
292
- return stringValue.charAt(0).toUpperCase() + stringValue.slice(1);
293
- }
294
- const sanitized = sanitizeIdentifier(stringValue);
295
- const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
296
- let result;
297
- if (words.length === 0) {
298
- result = "Value";
299
- } else {
300
- result = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
301
- }
302
- if (/^\d/.test(result)) {
303
- result = `N${result}`;
304
- }
305
- if (!result || /^_+$/.test(result)) {
306
- return "Value";
307
- }
308
- return result;
309
- }
310
-
311
1720
  // src/utils/operation-filters.ts
312
- import { minimatch } from "minimatch";
1721
+ import { minimatch as minimatch2 } from "minimatch";
313
1722
  function createFilterStatistics() {
314
1723
  return {
315
1724
  totalOperations: 0,
@@ -328,7 +1737,7 @@ function matchesAnyPattern(value, patterns) {
328
1737
  if (!value) {
329
1738
  return false;
330
1739
  }
331
- return patterns.some((pattern) => minimatch(value, pattern));
1740
+ return patterns.some((pattern) => minimatch2(value, pattern));
332
1741
  }
333
1742
  function containsAny(arr, values) {
334
1743
  if (!values || values.length === 0) {
@@ -442,82 +1851,8 @@ function formatFilterStatistics(stats) {
442
1851
  return lines.join("\n");
443
1852
  }
444
1853
 
445
- // src/utils/pattern-utils.ts
446
- import { minimatch as minimatch2 } from "minimatch";
447
- function isValidGlobPattern(pattern) {
448
- try {
449
- new minimatch2.Minimatch(pattern);
450
- return true;
451
- } catch {
452
- return false;
453
- }
454
- }
455
- function isGlobPattern(pattern) {
456
- return /[*?[\]{}!]/.test(pattern);
457
- }
458
- function stripPrefix(input, pattern, ensureLeadingChar) {
459
- if (!pattern) {
460
- return input;
461
- }
462
- if (isGlobPattern(pattern) && !isValidGlobPattern(pattern)) {
463
- console.warn(`\u26A0\uFE0F Invalid glob pattern "${pattern}": Pattern is malformed`);
464
- return input;
465
- }
466
- if (isGlobPattern(pattern)) {
467
- let longestMatch = -1;
468
- for (let i = 1; i <= input.length; i++) {
469
- const testPrefix = input.substring(0, i);
470
- if (minimatch2(testPrefix, pattern)) {
471
- longestMatch = i;
472
- }
473
- }
474
- if (longestMatch > 0) {
475
- const stripped = input.substring(longestMatch);
476
- if (ensureLeadingChar) {
477
- if (stripped === "") {
478
- return ensureLeadingChar;
479
- }
480
- if (!stripped.startsWith(ensureLeadingChar)) {
481
- return `${ensureLeadingChar}${stripped}`;
482
- }
483
- }
484
- return stripped === "" && !ensureLeadingChar ? input : stripped;
485
- }
486
- return input;
487
- }
488
- if (input.startsWith(pattern)) {
489
- const stripped = input.substring(pattern.length);
490
- if (ensureLeadingChar) {
491
- if (stripped === "") {
492
- return ensureLeadingChar;
493
- }
494
- if (!stripped.startsWith(ensureLeadingChar)) {
495
- return `${ensureLeadingChar}${stripped}`;
496
- }
497
- }
498
- return stripped;
499
- }
500
- return input;
501
- }
502
- function stripPathPrefix(path, pattern) {
503
- if (!pattern) {
504
- return path;
505
- }
506
- if (!isGlobPattern(pattern)) {
507
- let normalizedPattern = pattern.trim();
508
- if (!normalizedPattern.startsWith("/")) {
509
- normalizedPattern = `/${normalizedPattern}`;
510
- }
511
- if (normalizedPattern.endsWith("/") && normalizedPattern !== "/") {
512
- normalizedPattern = normalizedPattern.slice(0, -1);
513
- }
514
- return stripPrefix(path, normalizedPattern, "/");
515
- }
516
- return stripPrefix(path, pattern, "/");
517
- }
518
-
519
1854
  // src/utils/ref-resolver.ts
520
- function resolveRef(obj, spec, maxDepth = 10) {
1855
+ function resolveRef2(obj, spec, maxDepth = 10) {
521
1856
  var _a, _b, _c, _d;
522
1857
  if (!obj || typeof obj !== "object" || maxDepth <= 0) return obj;
523
1858
  if (!obj.$ref) return obj;
@@ -542,20 +1877,20 @@ function resolveRef(obj, spec, maxDepth = 10) {
542
1877
  }
543
1878
  if (resolved) {
544
1879
  if (resolved.$ref) {
545
- return resolveRef(resolved, spec, maxDepth - 1);
1880
+ return resolveRef2(resolved, spec, maxDepth - 1);
546
1881
  }
547
1882
  return resolved;
548
1883
  }
549
1884
  return obj;
550
1885
  }
551
1886
  function resolveParameterRef(param, spec) {
552
- return resolveRef(param, spec);
1887
+ return resolveRef2(param, spec);
553
1888
  }
554
1889
  function resolveRequestBodyRef(requestBody, spec) {
555
- return resolveRef(requestBody, spec);
1890
+ return resolveRef2(requestBody, spec);
556
1891
  }
557
1892
  function resolveResponseRef(response, spec) {
558
- return resolveRef(response, spec);
1893
+ return resolveRef2(response, spec);
559
1894
  }
560
1895
  function mergeParameters(pathParams, operationParams, spec) {
561
1896
  const resolvedPathParams = (pathParams || []).map((p) => resolveParameterRef(p, spec));
@@ -575,14 +1910,6 @@ function mergeParameters(pathParams, operationParams, spec) {
575
1910
  return merged;
576
1911
  }
577
1912
 
578
- // src/utils/string-utils.ts
579
- function escapePattern(str) {
580
- return str.replace(/\//g, "\\/");
581
- }
582
- function escapeJSDoc(str) {
583
- return str.replace(/\*\//g, "*\\/");
584
- }
585
-
586
1913
  // src/utils/typescript-loader.ts
587
1914
  function createTypeScriptLoader() {
588
1915
  return async (filepath) => {
@@ -616,72 +1943,12 @@ function createTypeScriptLoader() {
616
1943
  }
617
1944
  };
618
1945
  }
619
-
620
- // src/validators/string-validator.ts
621
- var PATTERN_CACHE = new LRUCache(1e3);
622
- var DEFAULT_FORMAT_MAP = {
623
- uuid: "z.uuid()",
624
- email: "z.email()",
625
- uri: "z.url()",
626
- url: "z.url()",
627
- "uri-reference": 'z.string().refine((val) => !/\\s/.test(val), { message: "Must be a valid URI reference" })',
628
- hostname: 'z.string().refine((val) => /^(?=.{1,253}$)(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.)*(?!-)[A-Za-z0-9-]{1,63}(?<!-)$/.test(val), { message: "Must be a valid hostname" })',
629
- byte: "z.base64()",
630
- binary: "z.string()",
631
- date: "z.iso.date()",
632
- time: "z.iso.time()",
633
- duration: 'z.string().refine((val) => /^P(?:(?:\\d+Y)?(?:\\d+M)?(?:\\d+D)?(?:T(?:\\d+H)?(?:\\d+M)?(?:\\d+(?:\\.\\d+)?S)?)?|\\d+W)$/.test(val) && !/^PT?$/.test(val), { message: "Must be a valid ISO 8601 duration" })',
634
- ipv4: "z.ipv4()",
635
- ipv6: "z.ipv6()",
636
- emoji: "z.emoji()",
637
- base64: "z.base64()",
638
- base64url: "z.base64url()",
639
- nanoid: "z.nanoid()",
640
- cuid: "z.cuid()",
641
- cuid2: "z.cuid2()",
642
- ulid: "z.ulid()",
643
- cidr: "z.cidrv4()",
644
- // Default to v4
645
- cidrv4: "z.cidrv4()",
646
- cidrv6: "z.cidrv6()",
647
- "json-pointer": 'z.string().refine((val) => val === "" || /^(\\/([^~/]|~0|~1)+)+$/.test(val), { message: "Must be a valid JSON Pointer (RFC 6901)" })',
648
- "relative-json-pointer": 'z.string().refine((val) => /^(0|[1-9]\\d*)(#|(\\/([^~/]|~0|~1)+)*)$/.test(val), { message: "Must be a valid relative JSON Pointer" })'
649
- };
650
- var FORMAT_MAP = {
651
- ...DEFAULT_FORMAT_MAP,
652
- "date-time": "z.iso.datetime()"
653
- };
654
- function configureDateTimeFormat(pattern) {
655
- if (!pattern) {
656
- FORMAT_MAP["date-time"] = "z.iso.datetime()";
657
- return;
658
- }
659
- const patternStr = pattern instanceof RegExp ? pattern.source : pattern;
660
- if (patternStr === "") {
661
- FORMAT_MAP["date-time"] = "z.iso.datetime()";
662
- return;
663
- }
664
- try {
665
- new RegExp(patternStr);
666
- } catch (error) {
667
- throw new Error(
668
- `Invalid regular expression pattern for customDateTimeFormatRegex: ${patternStr}. ${error instanceof Error ? error.message : "Pattern is malformed"}`
669
- );
670
- }
671
- const escapedPattern = escapePattern(patternStr);
672
- FORMAT_MAP["date-time"] = `z.string().regex(/${escapedPattern}/)`;
673
- }
674
- function resetFormatMap() {
675
- FORMAT_MAP = {
676
- ...DEFAULT_FORMAT_MAP,
677
- "date-time": "z.iso.datetime()"
678
- };
679
- }
680
1946
  export {
681
1947
  LRUCache,
682
1948
  OperationFiltersSchema,
1949
+ PropertyGenerator,
683
1950
  RequestResponseOptionsSchema,
684
- configureDateTimeFormat,
1951
+ buildDateTimeValidation,
685
1952
  createFilterStatistics,
686
1953
  createTypeScriptLoader,
687
1954
  escapeJSDoc,
@@ -691,9 +1958,8 @@ export {
691
1958
  getBatchExitCode,
692
1959
  getResponseParseMethod,
693
1960
  mergeParameters,
694
- resetFormatMap,
695
1961
  resolveParameterRef,
696
- resolveRef,
1962
+ resolveRef2 as resolveRef,
697
1963
  resolveRequestBodyRef,
698
1964
  resolveResponseRef,
699
1965
  shouldIncludeOperation,