@cerios/openapi-to-zod 1.1.0 → 1.2.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/cli.js CHANGED
@@ -5129,7 +5129,7 @@ function getBatchExitCode(summary) {
5129
5129
  init_cjs_shims();
5130
5130
  var import_node_fs = require("fs");
5131
5131
  var import_node_path = require("path");
5132
- var import_minimatch2 = require("minimatch");
5132
+ var import_minimatch3 = require("minimatch");
5133
5133
  var import_yaml = require("yaml");
5134
5134
 
5135
5135
  // src/generators/enum-generator.ts
@@ -5192,8 +5192,26 @@ function resolveRef(ref) {
5192
5192
  function generateEnum(name, values, options) {
5193
5193
  const schemaName = `${toCamelCase(name, options)}Schema`;
5194
5194
  const typeName = toPascalCase(name);
5195
- const enumValues = values.map((v) => `"${v}"`).join(", ");
5196
- const schemaCode = `export const ${schemaName} = z.enum([${enumValues}]);`;
5195
+ const allBooleans = values.every((v) => typeof v === "boolean");
5196
+ if (allBooleans) {
5197
+ const schemaCode2 = `export const ${schemaName} = z.boolean();`;
5198
+ const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
5199
+ return { schemaCode: schemaCode2, typeCode: typeCode2 };
5200
+ }
5201
+ const allStrings = values.every((v) => typeof v === "string");
5202
+ if (allStrings) {
5203
+ const enumValues = values.map((v) => `"${v}"`).join(", ");
5204
+ const schemaCode2 = `export const ${schemaName} = z.enum([${enumValues}]);`;
5205
+ const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
5206
+ return { schemaCode: schemaCode2, typeCode: typeCode2 };
5207
+ }
5208
+ const literalValues = values.map((v) => {
5209
+ if (typeof v === "string") {
5210
+ return `z.literal("${v}")`;
5211
+ }
5212
+ return `z.literal(${v})`;
5213
+ }).join(", ");
5214
+ const schemaCode = `export const ${schemaName} = z.union([${literalValues}]);`;
5197
5215
  const typeCode = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
5198
5216
  return { schemaCode, typeCode };
5199
5217
  }
@@ -5207,7 +5225,7 @@ function escapeDescription(str) {
5207
5225
  return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
5208
5226
  }
5209
5227
  function escapePattern(str) {
5210
- return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
5228
+ return str.replace(/\//g, "\\/");
5211
5229
  }
5212
5230
  function escapeJSDoc(str) {
5213
5231
  return str.replace(/\*\//g, "*\\/");
@@ -5215,14 +5233,17 @@ function escapeJSDoc(str) {
5215
5233
  function wrapNullable(validation, isNullable2) {
5216
5234
  return isNullable2 ? `${validation}.nullable()` : validation;
5217
5235
  }
5218
- function isNullable(schema) {
5236
+ function isNullable(schema, defaultNullable = false) {
5219
5237
  if (schema.nullable === true) {
5220
5238
  return true;
5221
5239
  }
5240
+ if (schema.nullable === false) {
5241
+ return false;
5242
+ }
5222
5243
  if (Array.isArray(schema.type)) {
5223
5244
  return schema.type.includes("null");
5224
5245
  }
5225
- return false;
5246
+ return defaultNullable;
5226
5247
  }
5227
5248
  function getPrimaryType(schema) {
5228
5249
  if (Array.isArray(schema.type)) {
@@ -5337,61 +5358,36 @@ var LRUCache = class {
5337
5358
 
5338
5359
  // src/utils/pattern-utils.ts
5339
5360
  init_cjs_shims();
5340
- function isRegexPattern(pattern) {
5341
- if (pattern.startsWith("^") || pattern.endsWith("$")) {
5342
- return true;
5343
- }
5344
- if (/\\[dDwWsS]/.test(pattern)) {
5345
- return true;
5346
- }
5347
- if (/\.\*|\.\+/.test(pattern)) {
5348
- return true;
5349
- }
5350
- if (/[[\]()]/.test(pattern)) {
5351
- return true;
5352
- }
5353
- if (/[^/][+?*]\{/.test(pattern)) {
5361
+ var import_minimatch = require("minimatch");
5362
+ function isValidGlobPattern(pattern) {
5363
+ try {
5364
+ new import_minimatch.minimatch.Minimatch(pattern);
5354
5365
  return true;
5366
+ } catch {
5367
+ return false;
5355
5368
  }
5356
- return false;
5357
5369
  }
5358
- function patternToRegex(pattern) {
5359
- if (pattern instanceof RegExp) {
5360
- return pattern;
5361
- }
5362
- if (isRegexPattern(pattern)) {
5363
- try {
5364
- return new RegExp(pattern);
5365
- } catch (error) {
5366
- console.warn(`\u26A0\uFE0F Invalid regex pattern "${pattern}": ${error instanceof Error ? error.message : String(error)}`);
5367
- return null;
5368
- }
5369
- }
5370
- return null;
5370
+ function isGlobPattern(pattern) {
5371
+ return /[*?[\]{}!]/.test(pattern);
5371
5372
  }
5372
5373
  function stripPrefix(input, pattern, ensureLeadingChar) {
5373
5374
  if (!pattern) {
5374
5375
  return input;
5375
5376
  }
5376
- const regex = patternToRegex(pattern);
5377
- if (regex) {
5378
- const match = input.match(regex);
5379
- if (match && match.index === 0) {
5380
- const stripped = input.substring(match[0].length);
5381
- if (ensureLeadingChar) {
5382
- if (stripped === "") {
5383
- return ensureLeadingChar;
5384
- }
5385
- if (!stripped.startsWith(ensureLeadingChar)) {
5386
- return `${ensureLeadingChar}${stripped}`;
5387
- }
5377
+ if (isGlobPattern(pattern) && !isValidGlobPattern(pattern)) {
5378
+ console.warn(`\u26A0\uFE0F Invalid glob pattern "${pattern}": Pattern is malformed`);
5379
+ return input;
5380
+ }
5381
+ if (isGlobPattern(pattern)) {
5382
+ let longestMatch = -1;
5383
+ for (let i = 1; i <= input.length; i++) {
5384
+ const testPrefix = input.substring(0, i);
5385
+ if ((0, import_minimatch.minimatch)(testPrefix, pattern)) {
5386
+ longestMatch = i;
5388
5387
  }
5389
- return stripped;
5390
5388
  }
5391
- } else {
5392
- const stringPattern = pattern;
5393
- if (input.startsWith(stringPattern)) {
5394
- const stripped = input.substring(stringPattern.length);
5389
+ if (longestMatch > 0) {
5390
+ const stripped = input.substring(longestMatch);
5395
5391
  if (ensureLeadingChar) {
5396
5392
  if (stripped === "") {
5397
5393
  return ensureLeadingChar;
@@ -5400,11 +5396,40 @@ function stripPrefix(input, pattern, ensureLeadingChar) {
5400
5396
  return `${ensureLeadingChar}${stripped}`;
5401
5397
  }
5402
5398
  }
5403
- return stripped;
5399
+ return stripped === "" && !ensureLeadingChar ? input : stripped;
5400
+ }
5401
+ return input;
5402
+ }
5403
+ if (input.startsWith(pattern)) {
5404
+ const stripped = input.substring(pattern.length);
5405
+ if (ensureLeadingChar) {
5406
+ if (stripped === "") {
5407
+ return ensureLeadingChar;
5408
+ }
5409
+ if (!stripped.startsWith(ensureLeadingChar)) {
5410
+ return `${ensureLeadingChar}${stripped}`;
5411
+ }
5404
5412
  }
5413
+ return stripped;
5405
5414
  }
5406
5415
  return input;
5407
5416
  }
5417
+ function stripPathPrefix(path, pattern) {
5418
+ if (!pattern) {
5419
+ return path;
5420
+ }
5421
+ if (!isGlobPattern(pattern)) {
5422
+ let normalizedPattern = pattern.trim();
5423
+ if (!normalizedPattern.startsWith("/")) {
5424
+ normalizedPattern = `/${normalizedPattern}`;
5425
+ }
5426
+ if (normalizedPattern.endsWith("/") && normalizedPattern !== "/") {
5427
+ normalizedPattern = normalizedPattern.slice(0, -1);
5428
+ }
5429
+ return stripPrefix(path, normalizedPattern, "/");
5430
+ }
5431
+ return stripPrefix(path, pattern, "/");
5432
+ }
5408
5433
 
5409
5434
  // src/validators/array-validator.ts
5410
5435
  init_cjs_shims();
@@ -5938,7 +5963,7 @@ function configurePatternCache(size) {
5938
5963
  PATTERN_CACHE = new LRUCache(size);
5939
5964
  }
5940
5965
  }
5941
- var FORMAT_MAP = {
5966
+ var DEFAULT_FORMAT_MAP = {
5942
5967
  uuid: "z.uuid()",
5943
5968
  email: "z.email()",
5944
5969
  uri: "z.url()",
@@ -5948,7 +5973,6 @@ var FORMAT_MAP = {
5948
5973
  byte: "z.base64()",
5949
5974
  binary: "z.string()",
5950
5975
  date: "z.iso.date()",
5951
- "date-time": "z.iso.datetime()",
5952
5976
  time: "z.iso.time()",
5953
5977
  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" })',
5954
5978
  ipv4: "z.ipv4()",
@@ -5967,6 +5991,30 @@ var FORMAT_MAP = {
5967
5991
  "json-pointer": 'z.string().refine((val) => val === "" || /^(\\/([^~/]|~0|~1)+)+$/.test(val), { message: "Must be a valid JSON Pointer (RFC 6901)" })',
5968
5992
  "relative-json-pointer": 'z.string().refine((val) => /^(0|[1-9]\\d*)(#|(\\/([^~/]|~0|~1)+)*)$/.test(val), { message: "Must be a valid relative JSON Pointer" })'
5969
5993
  };
5994
+ var FORMAT_MAP = {
5995
+ ...DEFAULT_FORMAT_MAP,
5996
+ "date-time": "z.iso.datetime()"
5997
+ };
5998
+ function configureDateTimeFormat(pattern) {
5999
+ if (!pattern) {
6000
+ FORMAT_MAP["date-time"] = "z.iso.datetime()";
6001
+ return;
6002
+ }
6003
+ const patternStr = pattern instanceof RegExp ? pattern.source : pattern;
6004
+ if (patternStr === "") {
6005
+ FORMAT_MAP["date-time"] = "z.iso.datetime()";
6006
+ return;
6007
+ }
6008
+ try {
6009
+ new RegExp(patternStr);
6010
+ } catch (error) {
6011
+ throw new Error(
6012
+ `Invalid regular expression pattern for customDateTimeFormatRegex: ${patternStr}. ${error instanceof Error ? error.message : "Pattern is malformed"}`
6013
+ );
6014
+ }
6015
+ const escapedPattern = escapePattern(patternStr);
6016
+ FORMAT_MAP["date-time"] = `z.string().regex(/${escapedPattern}/)`;
6017
+ }
5970
6018
  function generateStringValidation(schema, useDescribe) {
5971
6019
  let validation = FORMAT_MAP[schema.format || ""] || "z.string()";
5972
6020
  if (schema.minLength !== void 0) {
@@ -6256,7 +6304,8 @@ var _PropertyGenerator = class _PropertyGenerator {
6256
6304
  if ((this.context.schemaType === "request" || this.context.schemaType === "response") && schema.properties) {
6257
6305
  schema = this.filterNestedProperties(schema);
6258
6306
  }
6259
- const nullable = isNullable(schema);
6307
+ const effectiveDefaultNullable = isTopLevel ? false : this.context.defaultNullable;
6308
+ const nullable = isNullable(schema, effectiveDefaultNullable);
6260
6309
  if (hasMultipleTypes(schema)) {
6261
6310
  const union = this.generateMultiTypeUnion(schema, currentSchema);
6262
6311
  return wrapNullable(union, nullable);
@@ -6284,9 +6333,25 @@ var _PropertyGenerator = class _PropertyGenerator {
6284
6333
  return wrapNullable(zodLiteral, nullable);
6285
6334
  }
6286
6335
  if (schema.enum) {
6287
- const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
6288
- const zodEnum = `z.enum([${enumValues}])`;
6289
- return wrapNullable(zodEnum, nullable);
6336
+ const allBooleans = schema.enum.every((v) => typeof v === "boolean");
6337
+ if (allBooleans) {
6338
+ const zodBoolean = "z.boolean()";
6339
+ return wrapNullable(zodBoolean, nullable);
6340
+ }
6341
+ const allStrings = schema.enum.every((v) => typeof v === "string");
6342
+ if (allStrings) {
6343
+ const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
6344
+ const zodEnum = `z.enum([${enumValues}])`;
6345
+ return wrapNullable(zodEnum, nullable);
6346
+ }
6347
+ const literalValues = schema.enum.map((v) => {
6348
+ if (typeof v === "string") {
6349
+ return `z.literal("${v}")`;
6350
+ }
6351
+ return `z.literal(${v})`;
6352
+ }).join(", ");
6353
+ const zodUnion = `z.union([${literalValues}])`;
6354
+ return wrapNullable(zodUnion, nullable);
6290
6355
  }
6291
6356
  if (schema.allOf) {
6292
6357
  let composition = generateAllOf(
@@ -6418,7 +6483,7 @@ var PropertyGenerator = _PropertyGenerator;
6418
6483
 
6419
6484
  // src/utils/operation-filters.ts
6420
6485
  init_cjs_shims();
6421
- var import_minimatch = require("minimatch");
6486
+ var import_minimatch2 = require("minimatch");
6422
6487
  function createFilterStatistics() {
6423
6488
  return {
6424
6489
  totalOperations: 0,
@@ -6437,7 +6502,7 @@ function matchesAnyPattern(value, patterns) {
6437
6502
  if (!value) {
6438
6503
  return false;
6439
6504
  }
6440
- return patterns.some((pattern) => (0, import_minimatch.minimatch)(value, pattern));
6505
+ return patterns.some((pattern) => (0, import_minimatch2.minimatch)(value, pattern));
6441
6506
  }
6442
6507
  function containsAny(arr, values) {
6443
6508
  if (!values || values.length === 0) {
@@ -6560,7 +6625,7 @@ var OpenApiGenerator = class {
6560
6625
  this.schemaUsageMap = /* @__PURE__ */ new Map();
6561
6626
  this.needsZodImport = true;
6562
6627
  this.filterStats = createFilterStatistics();
6563
- var _a, _b, _c, _d, _e;
6628
+ var _a, _b, _c, _d, _e, _f, _g;
6564
6629
  if (!options.input) {
6565
6630
  throw new ConfigurationError("Input path is required", { providedOptions: options });
6566
6631
  }
@@ -6570,21 +6635,27 @@ var OpenApiGenerator = class {
6570
6635
  output: options.output,
6571
6636
  includeDescriptions: (_a = options.includeDescriptions) != null ? _a : true,
6572
6637
  useDescribe: (_b = options.useDescribe) != null ? _b : false,
6638
+ defaultNullable: (_c = options.defaultNullable) != null ? _c : false,
6573
6639
  schemaType: options.schemaType || "all",
6574
6640
  prefix: options.prefix,
6575
6641
  suffix: options.suffix,
6576
6642
  stripSchemaPrefix: options.stripSchemaPrefix,
6577
- showStats: (_c = options.showStats) != null ? _c : true,
6643
+ stripPathPrefix: options.stripPathPrefix,
6644
+ showStats: (_d = options.showStats) != null ? _d : true,
6578
6645
  request: options.request,
6579
6646
  response: options.response,
6580
6647
  operationFilters: options.operationFilters,
6581
6648
  ignoreHeaders: options.ignoreHeaders,
6582
- cacheSize: (_d = options.cacheSize) != null ? _d : 1e3,
6583
- batchSize: (_e = options.batchSize) != null ? _e : 10
6649
+ cacheSize: (_e = options.cacheSize) != null ? _e : 1e3,
6650
+ batchSize: (_f = options.batchSize) != null ? _f : 10,
6651
+ customDateTimeFormatRegex: options.customDateTimeFormatRegex
6584
6652
  };
6585
6653
  if (this.options.cacheSize) {
6586
6654
  configurePatternCache(this.options.cacheSize);
6587
6655
  }
6656
+ if (this.options.customDateTimeFormatRegex) {
6657
+ configureDateTimeFormat(this.options.customDateTimeFormatRegex);
6658
+ }
6588
6659
  try {
6589
6660
  const fs = require("fs");
6590
6661
  if (!fs.existsSync(this.options.input)) {
@@ -6647,6 +6718,7 @@ var OpenApiGenerator = class {
6647
6718
  mode: this.requestOptions.mode,
6648
6719
  includeDescriptions: this.requestOptions.includeDescriptions,
6649
6720
  useDescribe: this.requestOptions.useDescribe,
6721
+ defaultNullable: (_g = this.options.defaultNullable) != null ? _g : false,
6650
6722
  namingOptions: {
6651
6723
  prefix: this.options.prefix,
6652
6724
  suffix: this.options.suffix
@@ -6664,6 +6736,9 @@ var OpenApiGenerator = class {
6664
6736
  throw new SpecValidationError("No schemas found in OpenAPI spec", { filePath: this.options.input });
6665
6737
  }
6666
6738
  for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
6739
+ if (this.options.operationFilters && this.schemaUsageMap.size > 0 && !this.schemaUsageMap.has(name)) {
6740
+ continue;
6741
+ }
6667
6742
  this.generateComponentSchema(name, schema);
6668
6743
  }
6669
6744
  this.generateQueryParameterSchemas();
@@ -6997,7 +7072,7 @@ var OpenApiGenerator = class {
6997
7072
  * Generate schema for a component
6998
7073
  */
6999
7074
  generateComponentSchema(name, schema) {
7000
- var _a, _b;
7075
+ var _a, _b, _c;
7001
7076
  if (!this.schemaDependencies.has(name)) {
7002
7077
  this.schemaDependencies.set(name, /* @__PURE__ */ new Set());
7003
7078
  }
@@ -7029,14 +7104,14 @@ ${typeCode}`;
7029
7104
  mode: resolvedOptions.mode,
7030
7105
  includeDescriptions: resolvedOptions.includeDescriptions,
7031
7106
  useDescribe: resolvedOptions.useDescribe,
7107
+ defaultNullable: (_b = this.options.defaultNullable) != null ? _b : false,
7032
7108
  namingOptions: {
7033
7109
  prefix: this.options.prefix,
7034
7110
  suffix: this.options.suffix
7035
7111
  },
7036
7112
  stripSchemaPrefix: this.options.stripSchemaPrefix
7037
7113
  });
7038
- const isAlias = !!(schema.$ref && !schema.properties && !schema.allOf && !schema.oneOf && !schema.anyOf);
7039
- const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, isAlias);
7114
+ const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, true);
7040
7115
  const zodSchemaCode = `${jsdoc}export const ${schemaName} = ${zodSchema};`;
7041
7116
  if (zodSchema.includes("z.discriminatedUnion(")) {
7042
7117
  const match = zodSchema.match(/z\.discriminatedUnion\([^,]+,\s*\[([^\]]+)\]/);
@@ -7046,7 +7121,7 @@ ${typeCode}`;
7046
7121
  const depMatch = ref.match(/^([a-z][a-zA-Z0-9]*?)Schema$/);
7047
7122
  if (depMatch) {
7048
7123
  const depName = depMatch[1].charAt(0).toUpperCase() + depMatch[1].slice(1);
7049
- (_b = this.schemaDependencies.get(name)) == null ? void 0 : _b.add(depName);
7124
+ (_c = this.schemaDependencies.get(name)) == null ? void 0 : _c.add(depName);
7050
7125
  }
7051
7126
  }
7052
7127
  }
@@ -7070,7 +7145,7 @@ ${typeCode}`;
7070
7145
  if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
7071
7146
  continue;
7072
7147
  }
7073
- if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
7148
+ if (!operation.parameters || !Array.isArray(operation.parameters)) {
7074
7149
  continue;
7075
7150
  }
7076
7151
  const queryParams = operation.parameters.filter(
@@ -7079,7 +7154,13 @@ ${typeCode}`;
7079
7154
  if (queryParams.length === 0) {
7080
7155
  continue;
7081
7156
  }
7082
- const pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
7157
+ let pascalOperationId;
7158
+ if (operation.operationId) {
7159
+ pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
7160
+ } else {
7161
+ const strippedPath = stripPathPrefix(path, this.options.stripPathPrefix);
7162
+ pascalOperationId = this.generateMethodNameFromPath(method, strippedPath);
7163
+ }
7083
7164
  const schemaName = `${pascalOperationId}QueryParams`;
7084
7165
  if (!this.schemaDependencies.has(schemaName)) {
7085
7166
  this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
@@ -7127,8 +7208,9 @@ ${propsCode}
7127
7208
  const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
7128
7209
  const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
7129
7210
  const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}QueryParamsSchema`;
7211
+ const jsdocOperationName = operation.operationId || `${method.toUpperCase()} ${path}`;
7130
7212
  const jsdoc = `/**
7131
- * Query parameters for ${operation.operationId}
7213
+ * Query parameters for ${jsdocOperationName}
7132
7214
  */
7133
7215
  `;
7134
7216
  const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
@@ -7137,6 +7219,35 @@ ${propsCode}
7137
7219
  }
7138
7220
  }
7139
7221
  }
7222
+ /**
7223
+ * Generate a PascalCase method name from HTTP method and path
7224
+ * Used as fallback when operationId is not available
7225
+ * @internal
7226
+ */
7227
+ generateMethodNameFromPath(method, path) {
7228
+ const segments = path.split("/").filter(Boolean).map((segment) => {
7229
+ if (segment.startsWith("{") && segment.endsWith("}")) {
7230
+ const paramName = segment.slice(1, -1);
7231
+ return `By${this.capitalizeSegment(paramName)}`;
7232
+ }
7233
+ return this.capitalizeSegment(segment);
7234
+ }).join("");
7235
+ const capitalizedMethod = method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
7236
+ return `${capitalizedMethod}${segments}`;
7237
+ }
7238
+ /**
7239
+ * Capitalizes a path segment, handling special characters like dashes, underscores, and dots
7240
+ * @internal
7241
+ */
7242
+ capitalizeSegment(str) {
7243
+ if (str.includes("-") || str.includes("_") || str.includes(".")) {
7244
+ return str.split(/[-_.]/).map((part) => {
7245
+ if (!part) return "";
7246
+ return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
7247
+ }).join("");
7248
+ }
7249
+ return str.charAt(0).toUpperCase() + str.slice(1);
7250
+ }
7140
7251
  /**
7141
7252
  * Check if a header should be ignored based on filter patterns
7142
7253
  * @internal
@@ -7152,7 +7263,7 @@ ${propsCode}
7152
7263
  const headerLower = headerName.toLowerCase();
7153
7264
  return ignorePatterns.some((pattern) => {
7154
7265
  const patternLower = pattern.toLowerCase();
7155
- return (0, import_minimatch2.minimatch)(headerLower, patternLower);
7266
+ return (0, import_minimatch3.minimatch)(headerLower, patternLower);
7156
7267
  });
7157
7268
  }
7158
7269
  /**
@@ -7173,7 +7284,7 @@ ${propsCode}
7173
7284
  if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
7174
7285
  continue;
7175
7286
  }
7176
- if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
7287
+ if (!operation.parameters || !Array.isArray(operation.parameters)) {
7177
7288
  continue;
7178
7289
  }
7179
7290
  const headerParams = operation.parameters.filter(
@@ -7182,7 +7293,13 @@ ${propsCode}
7182
7293
  if (headerParams.length === 0) {
7183
7294
  continue;
7184
7295
  }
7185
- const pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
7296
+ let pascalOperationId;
7297
+ if (operation.operationId) {
7298
+ pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
7299
+ } else {
7300
+ const strippedPath = stripPathPrefix(path, this.options.stripPathPrefix);
7301
+ pascalOperationId = this.generateMethodNameFromPath(method, strippedPath);
7302
+ }
7186
7303
  const schemaName = `${pascalOperationId}HeaderParams`;
7187
7304
  if (!this.schemaDependencies.has(schemaName)) {
7188
7305
  this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
@@ -7219,8 +7336,9 @@ ${propsCode}
7219
7336
  const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
7220
7337
  const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
7221
7338
  const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}HeaderParamsSchema`;
7339
+ const jsdocOperationName = operation.operationId || `${method.toUpperCase()} ${path}`;
7222
7340
  const jsdoc = `/**
7223
- * Header parameters for ${operation.operationId}
7341
+ * Header parameters for ${jsdocOperationName}
7224
7342
  */
7225
7343
  `;
7226
7344
  const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
@@ -7240,8 +7358,22 @@ ${propsCode}
7240
7358
  return `${schemaName}Schema`;
7241
7359
  }
7242
7360
  if (schema.enum) {
7243
- const enumValues = schema.enum.map((v) => typeof v === "string" ? `"${v}"` : v).join(", ");
7244
- return `z.enum([${enumValues}])`;
7361
+ const allBooleans = schema.enum.every((v) => typeof v === "boolean");
7362
+ if (allBooleans) {
7363
+ return "z.boolean()";
7364
+ }
7365
+ const allStrings = schema.enum.every((v) => typeof v === "string");
7366
+ if (allStrings) {
7367
+ const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
7368
+ return `z.enum([${enumValues}])`;
7369
+ }
7370
+ const literalValues = schema.enum.map((v) => {
7371
+ if (typeof v === "string") {
7372
+ return `z.literal("${v}")`;
7373
+ }
7374
+ return `z.literal(${v})`;
7375
+ }).join(", ");
7376
+ return `z.union([${literalValues}])`;
7245
7377
  }
7246
7378
  const type = schema.type;
7247
7379
  if (type === "string") {
@@ -7386,7 +7518,8 @@ var import_zod = require("zod");
7386
7518
  var RequestResponseOptionsSchema = import_zod.z.strictObject({
7387
7519
  mode: import_zod.z.enum(["strict", "normal", "loose"]).optional(),
7388
7520
  useDescribe: import_zod.z.boolean().optional(),
7389
- includeDescriptions: import_zod.z.boolean().optional()
7521
+ includeDescriptions: import_zod.z.boolean().optional(),
7522
+ defaultNullable: import_zod.z.boolean().optional()
7390
7523
  });
7391
7524
  var OperationFiltersSchema = import_zod.z.strictObject({
7392
7525
  includeTags: import_zod.z.array(import_zod.z.string()).optional(),
@@ -7469,6 +7602,7 @@ var OpenApiGeneratorOptionsSchema = import_zod2.z.strictObject({
7469
7602
  output: import_zod2.z.string(),
7470
7603
  includeDescriptions: import_zod2.z.boolean().optional(),
7471
7604
  useDescribe: import_zod2.z.boolean().optional(),
7605
+ defaultNullable: import_zod2.z.boolean().optional(),
7472
7606
  schemaType: import_zod2.z.enum(["all", "request", "response"]).optional(),
7473
7607
  prefix: import_zod2.z.string().optional(),
7474
7608
  suffix: import_zod2.z.string().optional(),
@@ -7479,13 +7613,28 @@ var OpenApiGeneratorOptionsSchema = import_zod2.z.strictObject({
7479
7613
  name: import_zod2.z.string().optional(),
7480
7614
  operationFilters: OperationFiltersSchema.optional(),
7481
7615
  cacheSize: import_zod2.z.number().positive().optional(),
7482
- batchSize: import_zod2.z.number().positive().optional()
7616
+ batchSize: import_zod2.z.number().positive().optional(),
7617
+ customDateTimeFormatRegex: import_zod2.z.union([
7618
+ import_zod2.z.string().refine(
7619
+ (pattern) => {
7620
+ try {
7621
+ new RegExp(pattern);
7622
+ return true;
7623
+ } catch {
7624
+ return false;
7625
+ }
7626
+ },
7627
+ { message: "Must be a valid regular expression pattern" }
7628
+ ),
7629
+ import_zod2.z.instanceof(RegExp)
7630
+ ]).optional()
7483
7631
  });
7484
7632
  var ConfigFileSchema = import_zod2.z.strictObject({
7485
7633
  defaults: import_zod2.z.strictObject({
7486
7634
  mode: import_zod2.z.enum(["strict", "normal", "loose"]).optional(),
7487
7635
  includeDescriptions: import_zod2.z.boolean().optional(),
7488
7636
  useDescribe: import_zod2.z.boolean().optional(),
7637
+ defaultNullable: import_zod2.z.boolean().optional(),
7489
7638
  schemaType: import_zod2.z.enum(["all", "request", "response"]).optional(),
7490
7639
  prefix: import_zod2.z.string().optional(),
7491
7640
  suffix: import_zod2.z.string().optional(),
@@ -7495,7 +7644,21 @@ var ConfigFileSchema = import_zod2.z.strictObject({
7495
7644
  response: RequestResponseOptionsSchema.optional(),
7496
7645
  operationFilters: OperationFiltersSchema.optional(),
7497
7646
  cacheSize: import_zod2.z.number().positive().optional(),
7498
- batchSize: import_zod2.z.number().positive().optional()
7647
+ batchSize: import_zod2.z.number().positive().optional(),
7648
+ customDateTimeFormatRegex: import_zod2.z.union([
7649
+ import_zod2.z.string().refine(
7650
+ (pattern) => {
7651
+ try {
7652
+ new RegExp(pattern);
7653
+ return true;
7654
+ } catch {
7655
+ return false;
7656
+ }
7657
+ },
7658
+ { message: "Must be a valid regular expression pattern" }
7659
+ ),
7660
+ import_zod2.z.instanceof(RegExp)
7661
+ ]).optional()
7499
7662
  }).optional(),
7500
7663
  specs: import_zod2.z.array(OpenApiGeneratorOptionsSchema).min(1, {
7501
7664
  message: "Configuration must include at least one specification. Each specification should have 'input' and 'output' paths."
@@ -7544,10 +7707,12 @@ function mergeConfigWithDefaults(config) {
7544
7707
  mode: defaults.mode,
7545
7708
  includeDescriptions: defaults.includeDescriptions,
7546
7709
  useDescribe: defaults.useDescribe,
7710
+ defaultNullable: defaults.defaultNullable,
7547
7711
  schemaType: defaults.schemaType,
7548
7712
  prefix: defaults.prefix,
7549
7713
  suffix: defaults.suffix,
7550
7714
  showStats: defaults.showStats,
7715
+ customDateTimeFormatRegex: defaults.customDateTimeFormatRegex,
7551
7716
  // Override with spec-specific values (including required input/output)
7552
7717
  ...spec
7553
7718
  };