@cerios/openapi-to-zod 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -834,14 +834,14 @@ All errors include:
834
834
 
835
835
  ## API Reference
836
836
 
837
- ### `generateZodSchemas(options: GeneratorOptions): void`
837
+ ### `generateZodSchemas(options: OpenApiGeneratorOptions): void`
838
838
 
839
839
  Main function to generate schemas.
840
840
 
841
841
  #### Options
842
842
 
843
843
  ```typescript
844
- interface GeneratorOptions {
844
+ interface OpenApiGeneratorOptions {
845
845
  /**
846
846
  * Object validation mode
847
847
  * - 'strict': Uses z.strictObject() - no additional properties allowed
package/dist/cli.js CHANGED
@@ -4961,6 +4961,7 @@ var require_prompts3 = __commonJS({
4961
4961
  // src/cli.ts
4962
4962
  init_cjs_shims();
4963
4963
  var import_node_fs2 = require("fs");
4964
+ var import_node_path2 = require("path");
4964
4965
  var import_commander = require("commander");
4965
4966
  var import_prompts = __toESM(require_prompts3());
4966
4967
 
@@ -5012,7 +5013,7 @@ var ConfigurationError = class extends GeneratorError {
5012
5013
  }
5013
5014
  };
5014
5015
 
5015
- // src/generator.ts
5016
+ // src/openapi-generator.ts
5016
5017
  init_cjs_shims();
5017
5018
  var import_node_fs = require("fs");
5018
5019
  var import_node_path = require("path");
@@ -6221,8 +6222,143 @@ _PropertyGenerator.INCLUSION_RULES = {
6221
6222
  };
6222
6223
  var PropertyGenerator = _PropertyGenerator;
6223
6224
 
6224
- // src/generator.ts
6225
- var ZodSchemaGenerator = class {
6225
+ // src/utils/operation-filters.ts
6226
+ init_cjs_shims();
6227
+ var import_minimatch = require("minimatch");
6228
+ function createFilterStatistics() {
6229
+ return {
6230
+ totalOperations: 0,
6231
+ includedOperations: 0,
6232
+ filteredByTags: 0,
6233
+ filteredByPaths: 0,
6234
+ filteredByMethods: 0,
6235
+ filteredByOperationIds: 0,
6236
+ filteredByDeprecated: 0
6237
+ };
6238
+ }
6239
+ function matchesAnyPattern(value, patterns) {
6240
+ if (!patterns || patterns.length === 0) {
6241
+ return false;
6242
+ }
6243
+ if (!value) {
6244
+ return false;
6245
+ }
6246
+ return patterns.some((pattern) => (0, import_minimatch.minimatch)(value, pattern));
6247
+ }
6248
+ function containsAny(arr, values) {
6249
+ if (!values || values.length === 0) {
6250
+ return false;
6251
+ }
6252
+ if (!arr || arr.length === 0) {
6253
+ return false;
6254
+ }
6255
+ return values.some((value) => arr.includes(value));
6256
+ }
6257
+ function shouldIncludeOperation(operation, path, method, filters, stats) {
6258
+ if (!filters) {
6259
+ return true;
6260
+ }
6261
+ const methodLower = method.toLowerCase();
6262
+ const operationId = operation == null ? void 0 : operation.operationId;
6263
+ const tags = (operation == null ? void 0 : operation.tags) || [];
6264
+ const deprecated = (operation == null ? void 0 : operation.deprecated) === true;
6265
+ if (filters.includeTags && filters.includeTags.length > 0) {
6266
+ if (!containsAny(tags, filters.includeTags)) {
6267
+ if (stats) stats.filteredByTags++;
6268
+ return false;
6269
+ }
6270
+ }
6271
+ if (filters.includePaths && filters.includePaths.length > 0) {
6272
+ if (!matchesAnyPattern(path, filters.includePaths)) {
6273
+ if (stats) stats.filteredByPaths++;
6274
+ return false;
6275
+ }
6276
+ }
6277
+ if (filters.includeMethods && filters.includeMethods.length > 0) {
6278
+ const methodsLower = filters.includeMethods.map((m) => m.toLowerCase());
6279
+ if (!methodsLower.includes(methodLower)) {
6280
+ if (stats) stats.filteredByMethods++;
6281
+ return false;
6282
+ }
6283
+ }
6284
+ if (filters.includeOperationIds && filters.includeOperationIds.length > 0) {
6285
+ if (!matchesAnyPattern(operationId, filters.includeOperationIds)) {
6286
+ if (stats) stats.filteredByOperationIds++;
6287
+ return false;
6288
+ }
6289
+ }
6290
+ if (filters.excludeDeprecated === true && deprecated) {
6291
+ if (stats) stats.filteredByDeprecated++;
6292
+ return false;
6293
+ }
6294
+ if (filters.excludeTags && filters.excludeTags.length > 0) {
6295
+ if (containsAny(tags, filters.excludeTags)) {
6296
+ if (stats) stats.filteredByTags++;
6297
+ return false;
6298
+ }
6299
+ }
6300
+ if (filters.excludePaths && filters.excludePaths.length > 0) {
6301
+ if (matchesAnyPattern(path, filters.excludePaths)) {
6302
+ if (stats) stats.filteredByPaths++;
6303
+ return false;
6304
+ }
6305
+ }
6306
+ if (filters.excludeMethods && filters.excludeMethods.length > 0) {
6307
+ const methodsLower = filters.excludeMethods.map((m) => m.toLowerCase());
6308
+ if (methodsLower.includes(methodLower)) {
6309
+ if (stats) stats.filteredByMethods++;
6310
+ return false;
6311
+ }
6312
+ }
6313
+ if (filters.excludeOperationIds && filters.excludeOperationIds.length > 0) {
6314
+ if (matchesAnyPattern(operationId, filters.excludeOperationIds)) {
6315
+ if (stats) stats.filteredByOperationIds++;
6316
+ return false;
6317
+ }
6318
+ }
6319
+ return true;
6320
+ }
6321
+ function validateFilters(stats, filters) {
6322
+ if (!filters || stats.totalOperations === 0) {
6323
+ return;
6324
+ }
6325
+ if (stats.includedOperations === 0) {
6326
+ console.warn(
6327
+ `\u26A0\uFE0F Warning: All ${stats.totalOperations} operations were filtered out. Check your operationFilters configuration.`
6328
+ );
6329
+ const filterBreakdown = [];
6330
+ if (stats.filteredByTags > 0) filterBreakdown.push(`${stats.filteredByTags} by tags`);
6331
+ if (stats.filteredByPaths > 0) filterBreakdown.push(`${stats.filteredByPaths} by paths`);
6332
+ if (stats.filteredByMethods > 0) filterBreakdown.push(`${stats.filteredByMethods} by methods`);
6333
+ if (stats.filteredByOperationIds > 0) filterBreakdown.push(`${stats.filteredByOperationIds} by operationIds`);
6334
+ if (stats.filteredByDeprecated > 0) filterBreakdown.push(`${stats.filteredByDeprecated} by deprecated flag`);
6335
+ if (filterBreakdown.length > 0) {
6336
+ console.warn(` Filtered: ${filterBreakdown.join(", ")}`);
6337
+ }
6338
+ }
6339
+ }
6340
+ function formatFilterStatistics(stats) {
6341
+ if (stats.totalOperations === 0) {
6342
+ return "";
6343
+ }
6344
+ const lines = [];
6345
+ lines.push("Operation Filtering:");
6346
+ lines.push(` Total operations: ${stats.totalOperations}`);
6347
+ lines.push(` Included operations: ${stats.includedOperations}`);
6348
+ const filteredCount = stats.filteredByTags + stats.filteredByPaths + stats.filteredByMethods + stats.filteredByOperationIds + stats.filteredByDeprecated;
6349
+ if (filteredCount > 0) {
6350
+ lines.push(` Filtered operations: ${filteredCount}`);
6351
+ if (stats.filteredByTags > 0) lines.push(` - By tags: ${stats.filteredByTags}`);
6352
+ if (stats.filteredByPaths > 0) lines.push(` - By paths: ${stats.filteredByPaths}`);
6353
+ if (stats.filteredByMethods > 0) lines.push(` - By methods: ${stats.filteredByMethods}`);
6354
+ if (stats.filteredByOperationIds > 0) lines.push(` - By operationIds: ${stats.filteredByOperationIds}`);
6355
+ if (stats.filteredByDeprecated > 0) lines.push(` - By deprecated: ${stats.filteredByDeprecated}`);
6356
+ }
6357
+ return lines.join("\n");
6358
+ }
6359
+
6360
+ // src/openapi-generator.ts
6361
+ var OpenApiGenerator = class {
6226
6362
  constructor(options) {
6227
6363
  this.schemas = /* @__PURE__ */ new Map();
6228
6364
  this.types = /* @__PURE__ */ new Map();
@@ -6232,6 +6368,7 @@ var ZodSchemaGenerator = class {
6232
6368
  this.schemaUsageMap = /* @__PURE__ */ new Map();
6233
6369
  this.schemaTypeModeMap = /* @__PURE__ */ new Map();
6234
6370
  this.needsZodImport = false;
6371
+ this.filterStats = createFilterStatistics();
6235
6372
  var _a, _b, _c;
6236
6373
  if (!options.input) {
6237
6374
  throw new ConfigurationError("Input path is required", { providedOptions: options });
@@ -6249,7 +6386,8 @@ var ZodSchemaGenerator = class {
6249
6386
  showStats: (_c = options.showStats) != null ? _c : true,
6250
6387
  nativeEnumType: options.nativeEnumType || "union",
6251
6388
  request: options.request,
6252
- response: options.response
6389
+ response: options.response,
6390
+ operationFilters: options.operationFilters
6253
6391
  };
6254
6392
  try {
6255
6393
  const fs = require("fs");
@@ -6262,19 +6400,41 @@ var ZodSchemaGenerator = class {
6262
6400
  }
6263
6401
  }
6264
6402
  try {
6265
- const yamlContent = (0, import_node_fs.readFileSync)(this.options.input, "utf-8");
6266
- this.spec = (0, import_yaml.parse)(yamlContent);
6403
+ const content = (0, import_node_fs.readFileSync)(this.options.input, "utf-8");
6404
+ try {
6405
+ this.spec = (0, import_yaml.parse)(content);
6406
+ } catch (yamlError) {
6407
+ try {
6408
+ this.spec = JSON.parse(content);
6409
+ } catch {
6410
+ if (yamlError instanceof Error) {
6411
+ const errorMessage = [
6412
+ `Failed to parse OpenAPI specification from: ${this.options.input}`,
6413
+ "",
6414
+ `Error: ${yamlError.message}`,
6415
+ "",
6416
+ "Please ensure:",
6417
+ " - The file exists and is readable",
6418
+ " - The file contains valid YAML or JSON syntax",
6419
+ " - The file is a valid OpenAPI 3.x specification"
6420
+ ].join("\n");
6421
+ throw new SpecValidationError(errorMessage, {
6422
+ filePath: this.options.input,
6423
+ originalError: yamlError.message
6424
+ });
6425
+ }
6426
+ throw yamlError;
6427
+ }
6428
+ }
6267
6429
  } catch (error) {
6430
+ if (error instanceof SpecValidationError) {
6431
+ throw error;
6432
+ }
6268
6433
  if (error instanceof Error) {
6269
6434
  const errorMessage = [
6270
- `Failed to parse OpenAPI specification from: ${this.options.input}`,
6271
- "",
6272
- `Error: ${error.message}`,
6435
+ `Failed to read OpenAPI specification from: ${this.options.input}`,
6273
6436
  "",
6274
- "Please ensure:",
6275
- " - The file exists and is readable",
6276
- " - The file contains valid YAML syntax",
6277
- " - The file is a valid OpenAPI 3.x specification"
6437
+ `Error: ${error.message}`
6278
6438
  ].join("\n");
6279
6439
  throw new SpecValidationError(errorMessage, { filePath: this.options.input, originalError: error.message });
6280
6440
  }
@@ -6332,6 +6492,8 @@ var ZodSchemaGenerator = class {
6332
6492
  this.generateComponentSchema(name, schema);
6333
6493
  }
6334
6494
  this.generateQueryParameterSchemas();
6495
+ this.generateHeaderParameterSchemas();
6496
+ validateFilters(this.filterStats, this.options.operationFilters);
6335
6497
  const orderedSchemaNames = this.topologicalSort();
6336
6498
  const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
6337
6499
  if (this.options.showStats === true) {
@@ -6425,9 +6587,16 @@ var ZodSchemaGenerator = class {
6425
6587
  const requestSchemas = /* @__PURE__ */ new Set();
6426
6588
  const responseSchemas = /* @__PURE__ */ new Set();
6427
6589
  if (this.spec.paths) {
6428
- for (const [, pathItem] of Object.entries(this.spec.paths)) {
6429
- for (const [, operation] of Object.entries(pathItem)) {
6590
+ for (const [path, pathItem] of Object.entries(this.spec.paths)) {
6591
+ const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
6592
+ for (const method of methods) {
6593
+ const operation = pathItem[method];
6430
6594
  if (typeof operation !== "object" || !operation) continue;
6595
+ this.filterStats.totalOperations++;
6596
+ if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters, this.filterStats)) {
6597
+ continue;
6598
+ }
6599
+ this.filterStats.includedOperations++;
6431
6600
  if ("requestBody" in operation && operation.requestBody && typeof operation.requestBody === "object" && "content" in operation.requestBody && operation.requestBody.content) {
6432
6601
  for (const mediaType of Object.values(operation.requestBody.content)) {
6433
6602
  if (mediaType && typeof mediaType === "object" && "schema" in mediaType && mediaType.schema) {
@@ -6777,12 +6946,15 @@ ${typeCode}`;
6777
6946
  if (!this.spec.paths) {
6778
6947
  return;
6779
6948
  }
6780
- for (const [_path, pathItem] of Object.entries(this.spec.paths)) {
6949
+ for (const [path, pathItem] of Object.entries(this.spec.paths)) {
6781
6950
  if (!pathItem || typeof pathItem !== "object") continue;
6782
6951
  const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
6783
6952
  for (const method of methods) {
6784
6953
  const operation = pathItem[method];
6785
6954
  if (!operation) continue;
6955
+ if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
6956
+ continue;
6957
+ }
6786
6958
  if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
6787
6959
  continue;
6788
6960
  }
@@ -6843,6 +7015,80 @@ ${propsCode}
6843
7015
  const jsdoc = `/**
6844
7016
  * Query parameters for ${operation.operationId}
6845
7017
  */
7018
+ `;
7019
+ const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
7020
+ this.schemas.set(schemaName, fullSchemaCode);
7021
+ this.needsZodImport = true;
7022
+ }
7023
+ }
7024
+ }
7025
+ /**
7026
+ * Generate header parameter schemas for each operation
7027
+ * Header parameters are always string type (HTTP header semantics)
7028
+ */
7029
+ generateHeaderParameterSchemas() {
7030
+ var _a;
7031
+ if (!this.spec.paths) {
7032
+ return;
7033
+ }
7034
+ for (const [path, pathItem] of Object.entries(this.spec.paths)) {
7035
+ if (!pathItem || typeof pathItem !== "object") continue;
7036
+ const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
7037
+ for (const method of methods) {
7038
+ const operation = pathItem[method];
7039
+ if (!operation) continue;
7040
+ if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
7041
+ continue;
7042
+ }
7043
+ if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
7044
+ continue;
7045
+ }
7046
+ const headerParams = operation.parameters.filter(
7047
+ (param) => param && typeof param === "object" && param.in === "header"
7048
+ );
7049
+ if (headerParams.length === 0) {
7050
+ continue;
7051
+ }
7052
+ const pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
7053
+ const schemaName = `${pascalOperationId}HeaderParams`;
7054
+ if (!this.schemaDependencies.has(schemaName)) {
7055
+ this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
7056
+ }
7057
+ const properties = {};
7058
+ for (const param of headerParams) {
7059
+ const paramName = param.name;
7060
+ const paramSchema = param.schema;
7061
+ if (!paramSchema) continue;
7062
+ let zodType = "z.string()";
7063
+ if (param.description && this.requestOptions.includeDescriptions) {
7064
+ if (this.requestOptions.useDescribe) {
7065
+ zodType = `${zodType}.describe(${JSON.stringify(param.description)})`;
7066
+ }
7067
+ }
7068
+ zodType = `${zodType}.optional()`;
7069
+ properties[paramName] = zodType;
7070
+ if (paramSchema.$ref) {
7071
+ const refName = resolveRef(paramSchema.$ref);
7072
+ (_a = this.schemaDependencies.get(schemaName)) == null ? void 0 : _a.add(refName);
7073
+ }
7074
+ }
7075
+ const objectMode = this.requestOptions.mode;
7076
+ const zodMethod = objectMode === "strict" ? "strictObject" : objectMode === "loose" ? "looseObject" : "object";
7077
+ const propsCode = Object.entries(properties).map(([key, value]) => {
7078
+ const needsQuotes = !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key);
7079
+ const quotedKey = needsQuotes ? `"${key}"` : key;
7080
+ return ` ${quotedKey}: ${value}`;
7081
+ }).join(",\n");
7082
+ const schemaCode = `z.${zodMethod}({
7083
+ ${propsCode}
7084
+ })`;
7085
+ const operationName = pascalOperationId;
7086
+ const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
7087
+ const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
7088
+ const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}HeaderParamsSchema`;
7089
+ const jsdoc = `/**
7090
+ * Header parameters for ${operation.operationId}
7091
+ */
6846
7092
  `;
6847
7093
  const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
6848
7094
  this.schemas.set(schemaName, fullSchemaCode);
@@ -7120,15 +7366,23 @@ ${props.join("\n")}
7120
7366
  stats.withConstraints++;
7121
7367
  }
7122
7368
  }
7123
- return [
7369
+ const output = [
7124
7370
  "// Generation Statistics:",
7125
7371
  `// Total schemas: ${stats.totalSchemas}`,
7126
7372
  `// Enums: ${stats.enums}`,
7127
7373
  `// Circular references: ${stats.withCircularRefs}`,
7128
7374
  `// Discriminated unions: ${stats.withDiscriminators}`,
7129
- `// With constraints: ${stats.withConstraints}`,
7130
- `// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`
7375
+ `// With constraints: ${stats.withConstraints}`
7131
7376
  ];
7377
+ if (this.options.operationFilters && this.filterStats.totalOperations > 0) {
7378
+ output.push("//");
7379
+ const filterStatsStr = formatFilterStatistics(this.filterStats);
7380
+ for (const line of filterStatsStr.split("\n")) {
7381
+ output.push(`// ${line}`);
7382
+ }
7383
+ }
7384
+ output.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
7385
+ return output;
7132
7386
  }
7133
7387
  };
7134
7388
 
@@ -7136,7 +7390,7 @@ ${props.join("\n")}
7136
7390
  async function processSpec(spec, index, total) {
7137
7391
  console.log(`Processing [${index + 1}/${total}] ${spec.input}...`);
7138
7392
  try {
7139
- const generator = new ZodSchemaGenerator(spec);
7393
+ const generator = new OpenApiGenerator(spec);
7140
7394
  generator.generate();
7141
7395
  console.log(`\u2713 Successfully generated ${spec.output}`);
7142
7396
  return {
@@ -7247,7 +7501,18 @@ var RequestResponseOptionsSchema = import_zod.z.strictObject({
7247
7501
  typeMode: TypeModeSchema.optional(),
7248
7502
  nativeEnumType: NativeEnumTypeSchema.optional()
7249
7503
  });
7250
- var GeneratorOptionsSchema = import_zod.z.strictObject({
7504
+ var OperationFiltersSchema = import_zod.z.strictObject({
7505
+ includeTags: import_zod.z.array(import_zod.z.string()).optional(),
7506
+ excludeTags: import_zod.z.array(import_zod.z.string()).optional(),
7507
+ includePaths: import_zod.z.array(import_zod.z.string()).optional(),
7508
+ excludePaths: import_zod.z.array(import_zod.z.string()).optional(),
7509
+ includeMethods: import_zod.z.array(import_zod.z.string()).optional(),
7510
+ excludeMethods: import_zod.z.array(import_zod.z.string()).optional(),
7511
+ includeOperationIds: import_zod.z.array(import_zod.z.string()).optional(),
7512
+ excludeOperationIds: import_zod.z.array(import_zod.z.string()).optional(),
7513
+ excludeDeprecated: import_zod.z.boolean().optional()
7514
+ });
7515
+ var OpenApiGeneratorOptionsSchema = import_zod.z.strictObject({
7251
7516
  mode: import_zod.z.enum(["strict", "normal", "loose"]).optional(),
7252
7517
  input: import_zod.z.string(),
7253
7518
  output: import_zod.z.string(),
@@ -7261,7 +7526,8 @@ var GeneratorOptionsSchema = import_zod.z.strictObject({
7261
7526
  nativeEnumType: NativeEnumTypeSchema.optional(),
7262
7527
  request: RequestResponseOptionsSchema.optional(),
7263
7528
  response: RequestResponseOptionsSchema.optional(),
7264
- name: import_zod.z.string().optional()
7529
+ name: import_zod.z.string().optional(),
7530
+ operationFilters: OperationFiltersSchema.optional()
7265
7531
  });
7266
7532
  var ConfigFileSchema = import_zod.z.strictObject({
7267
7533
  defaults: import_zod.z.strictObject({
@@ -7275,9 +7541,10 @@ var ConfigFileSchema = import_zod.z.strictObject({
7275
7541
  showStats: import_zod.z.boolean().optional(),
7276
7542
  nativeEnumType: NativeEnumTypeSchema.optional(),
7277
7543
  request: RequestResponseOptionsSchema.optional(),
7278
- response: RequestResponseOptionsSchema.optional()
7544
+ response: RequestResponseOptionsSchema.optional(),
7545
+ operationFilters: OperationFiltersSchema.optional()
7279
7546
  }).optional(),
7280
- specs: import_zod.z.array(GeneratorOptionsSchema).min(1, "At least one spec is required"),
7547
+ specs: import_zod.z.array(OpenApiGeneratorOptionsSchema).min(1, "At least one spec is required"),
7281
7548
  executionMode: import_zod.z.enum(["parallel", "sequential"]).optional()
7282
7549
  });
7283
7550
  var createTypeScriptLoader = () => {
@@ -7424,6 +7691,36 @@ program.command("init").description("Initialize a new openapi-to-zod configurati
7424
7691
  }
7425
7692
  });
7426
7693
  program.parse();
7694
+ function findSpecFiles() {
7695
+ const specFolders = ["spec", "specs"];
7696
+ const validExtensions = [".yaml", ".yml", ".json"];
7697
+ const excludePatterns = ["node_modules", ".git", "dist", "build", "coverage"];
7698
+ const allFiles = [];
7699
+ for (const folder of specFolders) {
7700
+ if (!(0, import_node_fs2.existsSync)(folder)) continue;
7701
+ try {
7702
+ const entries = (0, import_node_fs2.readdirSync)(folder, { recursive: true, encoding: "utf-8" });
7703
+ for (const entry of entries) {
7704
+ const fullPath = (0, import_node_path2.join)(folder, entry);
7705
+ if (excludePatterns.some((pattern) => fullPath.includes(pattern))) continue;
7706
+ try {
7707
+ const stats = (0, import_node_fs2.statSync)(fullPath);
7708
+ if (!stats.isFile()) continue;
7709
+ const hasValidExt = validExtensions.some((ext) => fullPath.endsWith(ext));
7710
+ if (!hasValidExt) continue;
7711
+ const sizeKB = (stats.size / 1024).toFixed(2);
7712
+ allFiles.push({ path: fullPath.replace(/\\/g, "/"), size: `${sizeKB} KB` });
7713
+ } catch {
7714
+ }
7715
+ }
7716
+ } catch {
7717
+ }
7718
+ }
7719
+ allFiles.sort((a, b) => a.path.localeCompare(b.path));
7720
+ const totalCount = allFiles.length;
7721
+ const files = allFiles.slice(0, 20);
7722
+ return { files, totalCount };
7723
+ }
7427
7724
  async function executeConfigMode(options) {
7428
7725
  let config;
7429
7726
  try {
@@ -7457,14 +7754,66 @@ async function initConfigFile() {
7457
7754
  return;
7458
7755
  }
7459
7756
  }
7460
- const response = await (0, import_prompts.default)([
7461
- {
7757
+ const { files, totalCount } = findSpecFiles();
7758
+ if (totalCount > 20) {
7759
+ console.log(`Showing first 20 of ${totalCount} files found. Use manual entry to specify others.
7760
+ `);
7761
+ }
7762
+ let inputPath;
7763
+ if (files.length > 0) {
7764
+ const choices = [
7765
+ ...files.map((f) => ({ title: `${f.path} (${f.size})`, value: f.path })),
7766
+ { title: "\u2192 Enter manually...", value: "__MANUAL__" }
7767
+ ];
7768
+ const inputResponse = await (0, import_prompts.default)({
7769
+ type: "select",
7770
+ name: "input",
7771
+ message: "Select OpenAPI spec file (YAML or JSON):",
7772
+ choices
7773
+ });
7774
+ if (!inputResponse.input) {
7775
+ console.log("\nInitialization cancelled.");
7776
+ return;
7777
+ }
7778
+ if (inputResponse.input === "__MANUAL__") {
7779
+ const manualResponse = await (0, import_prompts.default)({
7780
+ type: "text",
7781
+ name: "input",
7782
+ message: "Input OpenAPI file path (YAML or JSON):",
7783
+ initial: "openapi.{yaml,yml,json}",
7784
+ validate: (value) => {
7785
+ if (value.length === 0) return "Input path is required";
7786
+ if (!(0, import_node_fs2.existsSync)(value)) return "\u26A0\uFE0F File does not exist. Continue anyway?";
7787
+ return true;
7788
+ }
7789
+ });
7790
+ if (!manualResponse.input) {
7791
+ console.log("\nInitialization cancelled.");
7792
+ return;
7793
+ }
7794
+ inputPath = manualResponse.input;
7795
+ } else {
7796
+ inputPath = inputResponse.input;
7797
+ }
7798
+ } else {
7799
+ const manualResponse = await (0, import_prompts.default)({
7462
7800
  type: "text",
7463
7801
  name: "input",
7464
- message: "Input OpenAPI file path:",
7465
- initial: "openapi.yaml",
7466
- validate: (value) => value.length > 0 || "Input path is required"
7467
- },
7802
+ message: "Input OpenAPI file path (YAML or JSON):",
7803
+ initial: "openapi.{yaml,yml,json}",
7804
+ validate: (value) => {
7805
+ if (value.length === 0) return "Input path is required";
7806
+ if (!(0, import_node_fs2.existsSync)(value)) return "\u26A0\uFE0F File does not exist. Continue anyway?";
7807
+ return true;
7808
+ }
7809
+ });
7810
+ if (!manualResponse.input) {
7811
+ console.log("\nInitialization cancelled.");
7812
+ return;
7813
+ }
7814
+ inputPath = manualResponse.input;
7815
+ }
7816
+ const response = await (0, import_prompts.default)([
7468
7817
  {
7469
7818
  type: "text",
7470
7819
  name: "output",
@@ -7489,11 +7838,12 @@ async function initConfigFile() {
7489
7838
  initial: true
7490
7839
  }
7491
7840
  ]);
7492
- if (!response.input || !response.output || !response.format) {
7841
+ if (!response.output || !response.format) {
7493
7842
  console.log("\nInitialization cancelled.");
7494
7843
  return;
7495
7844
  }
7496
- const { input, output, format, includeDefaults } = response;
7845
+ const { output, format, includeDefaults } = response;
7846
+ const input = inputPath;
7497
7847
  let configContent;
7498
7848
  let configFilename;
7499
7849
  if (format === "ts") {
@@ -7554,6 +7904,20 @@ export default defineConfig({
7554
7904
  console.log("\nNext steps:");
7555
7905
  console.log(" 1. Review and customize your config file if needed");
7556
7906
  console.log(" 2. Run 'openapi-to-zod' to generate schemas\n");
7557
- console.log("Things just got Cerios...\n");
7907
+ const ceriosMessages = [
7908
+ "Things just got Cerios!",
7909
+ "Getting Cerios about schemas!",
7910
+ "Cerios business ahead!",
7911
+ "Don't take it too Cerios-ly!",
7912
+ "Time to get Cerios!",
7913
+ "We're dead Cerios about types!",
7914
+ "This is Cerios-ly awesome!",
7915
+ "Cerios-ly, you're all set!",
7916
+ "You are Cerios right now!",
7917
+ "Cerios vibes only!"
7918
+ ];
7919
+ const randomMessage = ceriosMessages[Math.floor(Math.random() * ceriosMessages.length)];
7920
+ console.log(`${randomMessage}
7921
+ `);
7558
7922
  }
7559
7923
  //# sourceMappingURL=cli.js.map