@cerios/openapi-to-zod 0.4.0 → 0.5.1

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
@@ -6222,6 +6222,141 @@ _PropertyGenerator.INCLUSION_RULES = {
6222
6222
  };
6223
6223
  var PropertyGenerator = _PropertyGenerator;
6224
6224
 
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
+
6225
6360
  // src/openapi-generator.ts
6226
6361
  var OpenApiGenerator = class {
6227
6362
  constructor(options) {
@@ -6233,6 +6368,7 @@ var OpenApiGenerator = class {
6233
6368
  this.schemaUsageMap = /* @__PURE__ */ new Map();
6234
6369
  this.schemaTypeModeMap = /* @__PURE__ */ new Map();
6235
6370
  this.needsZodImport = false;
6371
+ this.filterStats = createFilterStatistics();
6236
6372
  var _a, _b, _c;
6237
6373
  if (!options.input) {
6238
6374
  throw new ConfigurationError("Input path is required", { providedOptions: options });
@@ -6250,7 +6386,8 @@ var OpenApiGenerator = class {
6250
6386
  showStats: (_c = options.showStats) != null ? _c : true,
6251
6387
  nativeEnumType: options.nativeEnumType || "union",
6252
6388
  request: options.request,
6253
- response: options.response
6389
+ response: options.response,
6390
+ operationFilters: options.operationFilters
6254
6391
  };
6255
6392
  try {
6256
6393
  const fs = require("fs");
@@ -6355,6 +6492,8 @@ var OpenApiGenerator = class {
6355
6492
  this.generateComponentSchema(name, schema);
6356
6493
  }
6357
6494
  this.generateQueryParameterSchemas();
6495
+ this.generateHeaderParameterSchemas();
6496
+ validateFilters(this.filterStats, this.options.operationFilters);
6358
6497
  const orderedSchemaNames = this.topologicalSort();
6359
6498
  const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
6360
6499
  if (this.options.showStats === true) {
@@ -6448,9 +6587,16 @@ var OpenApiGenerator = class {
6448
6587
  const requestSchemas = /* @__PURE__ */ new Set();
6449
6588
  const responseSchemas = /* @__PURE__ */ new Set();
6450
6589
  if (this.spec.paths) {
6451
- for (const [, pathItem] of Object.entries(this.spec.paths)) {
6452
- 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];
6453
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++;
6454
6600
  if ("requestBody" in operation && operation.requestBody && typeof operation.requestBody === "object" && "content" in operation.requestBody && operation.requestBody.content) {
6455
6601
  for (const mediaType of Object.values(operation.requestBody.content)) {
6456
6602
  if (mediaType && typeof mediaType === "object" && "schema" in mediaType && mediaType.schema) {
@@ -6800,12 +6946,15 @@ ${typeCode}`;
6800
6946
  if (!this.spec.paths) {
6801
6947
  return;
6802
6948
  }
6803
- for (const [_path, pathItem] of Object.entries(this.spec.paths)) {
6949
+ for (const [path, pathItem] of Object.entries(this.spec.paths)) {
6804
6950
  if (!pathItem || typeof pathItem !== "object") continue;
6805
6951
  const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
6806
6952
  for (const method of methods) {
6807
6953
  const operation = pathItem[method];
6808
6954
  if (!operation) continue;
6955
+ if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
6956
+ continue;
6957
+ }
6809
6958
  if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
6810
6959
  continue;
6811
6960
  }
@@ -6866,6 +7015,80 @@ ${propsCode}
6866
7015
  const jsdoc = `/**
6867
7016
  * Query parameters for ${operation.operationId}
6868
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
+ */
6869
7092
  `;
6870
7093
  const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
6871
7094
  this.schemas.set(schemaName, fullSchemaCode);
@@ -7143,15 +7366,23 @@ ${props.join("\n")}
7143
7366
  stats.withConstraints++;
7144
7367
  }
7145
7368
  }
7146
- return [
7369
+ const output = [
7147
7370
  "// Generation Statistics:",
7148
7371
  `// Total schemas: ${stats.totalSchemas}`,
7149
7372
  `// Enums: ${stats.enums}`,
7150
7373
  `// Circular references: ${stats.withCircularRefs}`,
7151
7374
  `// Discriminated unions: ${stats.withDiscriminators}`,
7152
- `// With constraints: ${stats.withConstraints}`,
7153
- `// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`
7375
+ `// With constraints: ${stats.withConstraints}`
7154
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;
7155
7386
  }
7156
7387
  };
7157
7388
 
@@ -7270,6 +7501,17 @@ var RequestResponseOptionsSchema = import_zod.z.strictObject({
7270
7501
  typeMode: TypeModeSchema.optional(),
7271
7502
  nativeEnumType: NativeEnumTypeSchema.optional()
7272
7503
  });
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
+ });
7273
7515
  var OpenApiGeneratorOptionsSchema = import_zod.z.strictObject({
7274
7516
  mode: import_zod.z.enum(["strict", "normal", "loose"]).optional(),
7275
7517
  input: import_zod.z.string(),
@@ -7284,7 +7526,8 @@ var OpenApiGeneratorOptionsSchema = import_zod.z.strictObject({
7284
7526
  nativeEnumType: NativeEnumTypeSchema.optional(),
7285
7527
  request: RequestResponseOptionsSchema.optional(),
7286
7528
  response: RequestResponseOptionsSchema.optional(),
7287
- name: import_zod.z.string().optional()
7529
+ name: import_zod.z.string().optional(),
7530
+ operationFilters: OperationFiltersSchema.optional()
7288
7531
  });
7289
7532
  var ConfigFileSchema = import_zod.z.strictObject({
7290
7533
  defaults: import_zod.z.strictObject({
@@ -7298,7 +7541,8 @@ var ConfigFileSchema = import_zod.z.strictObject({
7298
7541
  showStats: import_zod.z.boolean().optional(),
7299
7542
  nativeEnumType: NativeEnumTypeSchema.optional(),
7300
7543
  request: RequestResponseOptionsSchema.optional(),
7301
- response: RequestResponseOptionsSchema.optional()
7544
+ response: RequestResponseOptionsSchema.optional(),
7545
+ operationFilters: OperationFiltersSchema.optional()
7302
7546
  }).optional(),
7303
7547
  specs: import_zod.z.array(OpenApiGeneratorOptionsSchema).min(1, "At least one spec is required"),
7304
7548
  executionMode: import_zod.z.enum(["parallel", "sequential"]).optional()
@@ -7660,6 +7904,20 @@ export default defineConfig({
7660
7904
  console.log("\nNext steps:");
7661
7905
  console.log(" 1. Review and customize your config file if needed");
7662
7906
  console.log(" 2. Run 'openapi-to-zod' to generate schemas\n");
7663
- 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
+ `);
7664
7922
  }
7665
7923
  //# sourceMappingURL=cli.js.map