@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/index.d.mts CHANGED
@@ -187,6 +187,98 @@ interface OpenApiGeneratorOptions {
187
187
  * Always generates Zod schemas for runtime validation
188
188
  */
189
189
  response?: ResponseOptions;
190
+ /**
191
+ * Filter which operations to include/exclude from generation
192
+ * Useful for generating separate schemas for different API subsets
193
+ *
194
+ * Filtering logic:
195
+ * 1. If no filters specified, all operations are included
196
+ * 2. Empty arrays are treated as "no constraint" (not as "exclude all")
197
+ * 3. Include filters are applied first (allowlist)
198
+ * 4. Exclude filters are applied second (blocklist)
199
+ * 5. Exclude rules always win over include rules
200
+ *
201
+ * Supports glob patterns for paths and operationIds (e.g., "/api/v1/**", "get*")
202
+ *
203
+ * @example
204
+ * // Only generate schemas for user-related endpoints
205
+ * operationFilters: {
206
+ * includeTags: ["users"]
207
+ * }
208
+ *
209
+ * @example
210
+ * // Generate only GET endpoints, excluding deprecated ones
211
+ * operationFilters: {
212
+ * includeMethods: ["get"],
213
+ * excludeDeprecated: true
214
+ * }
215
+ *
216
+ * @example
217
+ * // Generate only v1 API endpoints
218
+ * operationFilters: {
219
+ * includePaths: ["/api/v1/**"]
220
+ * }
221
+ */
222
+ operationFilters?: OperationFilters;
223
+ }
224
+ /**
225
+ * Operation filtering options
226
+ * Controls which operations from the OpenAPI spec are included in generation
227
+ */
228
+ interface OperationFilters {
229
+ /**
230
+ * Include only operations with these tags
231
+ * If specified, only operations with at least one matching tag are included
232
+ * Empty array = no constraint
233
+ */
234
+ includeTags?: string[];
235
+ /**
236
+ * Exclude operations with these tags
237
+ * Operations with any matching tag are excluded
238
+ * Empty array = no constraint
239
+ */
240
+ excludeTags?: string[];
241
+ /**
242
+ * Include only operations matching these path patterns
243
+ * Supports glob patterns (e.g., "/users/**", "/api/v1/*")
244
+ * Empty array = no constraint
245
+ */
246
+ includePaths?: string[];
247
+ /**
248
+ * Exclude operations matching these path patterns
249
+ * Supports glob patterns (e.g., "/internal/**", "/admin/*")
250
+ * Empty array = no constraint
251
+ */
252
+ excludePaths?: string[];
253
+ /**
254
+ * Include only these HTTP methods
255
+ * Valid values: "get", "post", "put", "patch", "delete", "head", "options"
256
+ * Empty array = no constraint
257
+ */
258
+ includeMethods?: string[];
259
+ /**
260
+ * Exclude these HTTP methods
261
+ * Valid values: "get", "post", "put", "patch", "delete", "head", "options"
262
+ * Empty array = no constraint
263
+ */
264
+ excludeMethods?: string[];
265
+ /**
266
+ * Include only operations matching these operationId patterns
267
+ * Supports glob patterns (e.g., "getUser*", "*Admin")
268
+ * Empty array = no constraint
269
+ */
270
+ includeOperationIds?: string[];
271
+ /**
272
+ * Exclude operations matching these operationId patterns
273
+ * Supports glob patterns (e.g., "deleteUser*", "*Internal")
274
+ * Empty array = no constraint
275
+ */
276
+ excludeOperationIds?: string[];
277
+ /**
278
+ * Whether to exclude deprecated operations
279
+ * @default false
280
+ */
281
+ excludeDeprecated?: boolean;
190
282
  }
191
283
  interface OpenAPISchema {
192
284
  type?: string | string[];
@@ -311,6 +403,7 @@ declare class OpenApiGenerator {
311
403
  private requestOptions;
312
404
  private responseOptions;
313
405
  private needsZodImport;
406
+ private filterStats;
314
407
  constructor(options: OpenApiGeneratorOptions);
315
408
  /**
316
409
  * Generate schemas as a string (without writing to file)
@@ -377,6 +470,11 @@ declare class OpenApiGenerator {
377
470
  * Generate query parameter schemas for each operation
378
471
  */
379
472
  private generateQueryParameterSchemas;
473
+ /**
474
+ * Generate header parameter schemas for each operation
475
+ * Header parameters are always string type (HTTP header semantics)
476
+ */
477
+ private generateHeaderParameterSchemas;
380
478
  /**
381
479
  * Generate Zod type for a query parameter schema
382
480
  */
@@ -412,4 +510,55 @@ declare class OpenApiGenerator {
412
510
  private generateStats;
413
511
  }
414
512
 
415
- export { CircularReferenceError, CliOptionsError, type ConfigFile, ConfigValidationError, type ExecutionMode, FileOperationError, GeneratorError, type OpenAPISpec, OpenApiGenerator, type OpenApiGeneratorOptions, SchemaGenerationError, SpecValidationError, defineConfig };
513
+ /**
514
+ * Filter statistics to track which operations were included/excluded
515
+ */
516
+ interface FilterStatistics {
517
+ totalOperations: number;
518
+ includedOperations: number;
519
+ filteredByTags: number;
520
+ filteredByPaths: number;
521
+ filteredByMethods: number;
522
+ filteredByOperationIds: number;
523
+ filteredByDeprecated: number;
524
+ }
525
+ /**
526
+ * Create a new filter statistics object with all counters initialized to zero
527
+ */
528
+ declare function createFilterStatistics(): FilterStatistics;
529
+ /**
530
+ * Determine if an operation should be included based on filter criteria
531
+ *
532
+ * Filter logic:
533
+ * 1. If no filters specified, include all operations
534
+ * 2. Empty arrays are treated as "no constraint" (not as "exclude all")
535
+ * 3. Include filters are applied first (allowlist)
536
+ * 4. Exclude filters are applied second (blocklist)
537
+ * 5. Exclude rules always win over include rules
538
+ *
539
+ * @param operation - The OpenAPI operation object
540
+ * @param path - The operation path (e.g., "/users/{id}")
541
+ * @param method - The HTTP method (e.g., "get", "post")
542
+ * @param filters - Optional filter configuration
543
+ * @param stats - Optional statistics object to track filtering reasons
544
+ * @returns true if the operation should be included, false otherwise
545
+ */
546
+ declare function shouldIncludeOperation(operation: any, path: string, method: string, filters?: OperationFilters, stats?: FilterStatistics): boolean;
547
+ /**
548
+ * Validate filter statistics and emit warnings for filters that matched nothing
549
+ * Helps users debug filter configurations that might be too restrictive or contain typos
550
+ *
551
+ * @param stats - Filter statistics object
552
+ * @param filters - The filter configuration to validate
553
+ */
554
+ declare function validateFilters(stats: FilterStatistics, filters?: OperationFilters): void;
555
+ /**
556
+ * Format filter statistics for display in generated output
557
+ * Returns a formatted string suitable for inclusion in comments
558
+ *
559
+ * @param stats - Filter statistics object
560
+ * @returns Formatted statistics string
561
+ */
562
+ declare function formatFilterStatistics(stats: FilterStatistics): string;
563
+
564
+ export { CircularReferenceError, CliOptionsError, type ConfigFile, ConfigValidationError, type ExecutionMode, FileOperationError, type FilterStatistics, GeneratorError, type OpenAPISpec, OpenApiGenerator, type OpenApiGeneratorOptions, type OperationFilters, SchemaGenerationError, SpecValidationError, createFilterStatistics, defineConfig, formatFilterStatistics, shouldIncludeOperation, validateFilters };
package/dist/index.d.ts CHANGED
@@ -187,6 +187,98 @@ interface OpenApiGeneratorOptions {
187
187
  * Always generates Zod schemas for runtime validation
188
188
  */
189
189
  response?: ResponseOptions;
190
+ /**
191
+ * Filter which operations to include/exclude from generation
192
+ * Useful for generating separate schemas for different API subsets
193
+ *
194
+ * Filtering logic:
195
+ * 1. If no filters specified, all operations are included
196
+ * 2. Empty arrays are treated as "no constraint" (not as "exclude all")
197
+ * 3. Include filters are applied first (allowlist)
198
+ * 4. Exclude filters are applied second (blocklist)
199
+ * 5. Exclude rules always win over include rules
200
+ *
201
+ * Supports glob patterns for paths and operationIds (e.g., "/api/v1/**", "get*")
202
+ *
203
+ * @example
204
+ * // Only generate schemas for user-related endpoints
205
+ * operationFilters: {
206
+ * includeTags: ["users"]
207
+ * }
208
+ *
209
+ * @example
210
+ * // Generate only GET endpoints, excluding deprecated ones
211
+ * operationFilters: {
212
+ * includeMethods: ["get"],
213
+ * excludeDeprecated: true
214
+ * }
215
+ *
216
+ * @example
217
+ * // Generate only v1 API endpoints
218
+ * operationFilters: {
219
+ * includePaths: ["/api/v1/**"]
220
+ * }
221
+ */
222
+ operationFilters?: OperationFilters;
223
+ }
224
+ /**
225
+ * Operation filtering options
226
+ * Controls which operations from the OpenAPI spec are included in generation
227
+ */
228
+ interface OperationFilters {
229
+ /**
230
+ * Include only operations with these tags
231
+ * If specified, only operations with at least one matching tag are included
232
+ * Empty array = no constraint
233
+ */
234
+ includeTags?: string[];
235
+ /**
236
+ * Exclude operations with these tags
237
+ * Operations with any matching tag are excluded
238
+ * Empty array = no constraint
239
+ */
240
+ excludeTags?: string[];
241
+ /**
242
+ * Include only operations matching these path patterns
243
+ * Supports glob patterns (e.g., "/users/**", "/api/v1/*")
244
+ * Empty array = no constraint
245
+ */
246
+ includePaths?: string[];
247
+ /**
248
+ * Exclude operations matching these path patterns
249
+ * Supports glob patterns (e.g., "/internal/**", "/admin/*")
250
+ * Empty array = no constraint
251
+ */
252
+ excludePaths?: string[];
253
+ /**
254
+ * Include only these HTTP methods
255
+ * Valid values: "get", "post", "put", "patch", "delete", "head", "options"
256
+ * Empty array = no constraint
257
+ */
258
+ includeMethods?: string[];
259
+ /**
260
+ * Exclude these HTTP methods
261
+ * Valid values: "get", "post", "put", "patch", "delete", "head", "options"
262
+ * Empty array = no constraint
263
+ */
264
+ excludeMethods?: string[];
265
+ /**
266
+ * Include only operations matching these operationId patterns
267
+ * Supports glob patterns (e.g., "getUser*", "*Admin")
268
+ * Empty array = no constraint
269
+ */
270
+ includeOperationIds?: string[];
271
+ /**
272
+ * Exclude operations matching these operationId patterns
273
+ * Supports glob patterns (e.g., "deleteUser*", "*Internal")
274
+ * Empty array = no constraint
275
+ */
276
+ excludeOperationIds?: string[];
277
+ /**
278
+ * Whether to exclude deprecated operations
279
+ * @default false
280
+ */
281
+ excludeDeprecated?: boolean;
190
282
  }
191
283
  interface OpenAPISchema {
192
284
  type?: string | string[];
@@ -311,6 +403,7 @@ declare class OpenApiGenerator {
311
403
  private requestOptions;
312
404
  private responseOptions;
313
405
  private needsZodImport;
406
+ private filterStats;
314
407
  constructor(options: OpenApiGeneratorOptions);
315
408
  /**
316
409
  * Generate schemas as a string (without writing to file)
@@ -377,6 +470,11 @@ declare class OpenApiGenerator {
377
470
  * Generate query parameter schemas for each operation
378
471
  */
379
472
  private generateQueryParameterSchemas;
473
+ /**
474
+ * Generate header parameter schemas for each operation
475
+ * Header parameters are always string type (HTTP header semantics)
476
+ */
477
+ private generateHeaderParameterSchemas;
380
478
  /**
381
479
  * Generate Zod type for a query parameter schema
382
480
  */
@@ -412,4 +510,55 @@ declare class OpenApiGenerator {
412
510
  private generateStats;
413
511
  }
414
512
 
415
- export { CircularReferenceError, CliOptionsError, type ConfigFile, ConfigValidationError, type ExecutionMode, FileOperationError, GeneratorError, type OpenAPISpec, OpenApiGenerator, type OpenApiGeneratorOptions, SchemaGenerationError, SpecValidationError, defineConfig };
513
+ /**
514
+ * Filter statistics to track which operations were included/excluded
515
+ */
516
+ interface FilterStatistics {
517
+ totalOperations: number;
518
+ includedOperations: number;
519
+ filteredByTags: number;
520
+ filteredByPaths: number;
521
+ filteredByMethods: number;
522
+ filteredByOperationIds: number;
523
+ filteredByDeprecated: number;
524
+ }
525
+ /**
526
+ * Create a new filter statistics object with all counters initialized to zero
527
+ */
528
+ declare function createFilterStatistics(): FilterStatistics;
529
+ /**
530
+ * Determine if an operation should be included based on filter criteria
531
+ *
532
+ * Filter logic:
533
+ * 1. If no filters specified, include all operations
534
+ * 2. Empty arrays are treated as "no constraint" (not as "exclude all")
535
+ * 3. Include filters are applied first (allowlist)
536
+ * 4. Exclude filters are applied second (blocklist)
537
+ * 5. Exclude rules always win over include rules
538
+ *
539
+ * @param operation - The OpenAPI operation object
540
+ * @param path - The operation path (e.g., "/users/{id}")
541
+ * @param method - The HTTP method (e.g., "get", "post")
542
+ * @param filters - Optional filter configuration
543
+ * @param stats - Optional statistics object to track filtering reasons
544
+ * @returns true if the operation should be included, false otherwise
545
+ */
546
+ declare function shouldIncludeOperation(operation: any, path: string, method: string, filters?: OperationFilters, stats?: FilterStatistics): boolean;
547
+ /**
548
+ * Validate filter statistics and emit warnings for filters that matched nothing
549
+ * Helps users debug filter configurations that might be too restrictive or contain typos
550
+ *
551
+ * @param stats - Filter statistics object
552
+ * @param filters - The filter configuration to validate
553
+ */
554
+ declare function validateFilters(stats: FilterStatistics, filters?: OperationFilters): void;
555
+ /**
556
+ * Format filter statistics for display in generated output
557
+ * Returns a formatted string suitable for inclusion in comments
558
+ *
559
+ * @param stats - Filter statistics object
560
+ * @returns Formatted statistics string
561
+ */
562
+ declare function formatFilterStatistics(stats: FilterStatistics): string;
563
+
564
+ export { CircularReferenceError, CliOptionsError, type ConfigFile, ConfigValidationError, type ExecutionMode, FileOperationError, type FilterStatistics, GeneratorError, type OpenAPISpec, OpenApiGenerator, type OpenApiGeneratorOptions, type OperationFilters, SchemaGenerationError, SpecValidationError, createFilterStatistics, defineConfig, formatFilterStatistics, shouldIncludeOperation, validateFilters };
package/dist/index.js CHANGED
@@ -28,7 +28,11 @@ __export(src_exports, {
28
28
  OpenApiGenerator: () => OpenApiGenerator,
29
29
  SchemaGenerationError: () => SchemaGenerationError,
30
30
  SpecValidationError: () => SpecValidationError,
31
- defineConfig: () => defineConfig
31
+ createFilterStatistics: () => createFilterStatistics,
32
+ defineConfig: () => defineConfig,
33
+ formatFilterStatistics: () => formatFilterStatistics,
34
+ shouldIncludeOperation: () => shouldIncludeOperation,
35
+ validateFilters: () => validateFilters
32
36
  });
33
37
  module.exports = __toCommonJS(src_exports);
34
38
 
@@ -1279,6 +1283,140 @@ _PropertyGenerator.INCLUSION_RULES = {
1279
1283
  };
1280
1284
  var PropertyGenerator = _PropertyGenerator;
1281
1285
 
1286
+ // src/utils/operation-filters.ts
1287
+ var import_minimatch = require("minimatch");
1288
+ function createFilterStatistics() {
1289
+ return {
1290
+ totalOperations: 0,
1291
+ includedOperations: 0,
1292
+ filteredByTags: 0,
1293
+ filteredByPaths: 0,
1294
+ filteredByMethods: 0,
1295
+ filteredByOperationIds: 0,
1296
+ filteredByDeprecated: 0
1297
+ };
1298
+ }
1299
+ function matchesAnyPattern(value, patterns) {
1300
+ if (!patterns || patterns.length === 0) {
1301
+ return false;
1302
+ }
1303
+ if (!value) {
1304
+ return false;
1305
+ }
1306
+ return patterns.some((pattern) => (0, import_minimatch.minimatch)(value, pattern));
1307
+ }
1308
+ function containsAny(arr, values) {
1309
+ if (!values || values.length === 0) {
1310
+ return false;
1311
+ }
1312
+ if (!arr || arr.length === 0) {
1313
+ return false;
1314
+ }
1315
+ return values.some((value) => arr.includes(value));
1316
+ }
1317
+ function shouldIncludeOperation(operation, path, method, filters, stats) {
1318
+ if (!filters) {
1319
+ return true;
1320
+ }
1321
+ const methodLower = method.toLowerCase();
1322
+ const operationId = operation == null ? void 0 : operation.operationId;
1323
+ const tags = (operation == null ? void 0 : operation.tags) || [];
1324
+ const deprecated = (operation == null ? void 0 : operation.deprecated) === true;
1325
+ if (filters.includeTags && filters.includeTags.length > 0) {
1326
+ if (!containsAny(tags, filters.includeTags)) {
1327
+ if (stats) stats.filteredByTags++;
1328
+ return false;
1329
+ }
1330
+ }
1331
+ if (filters.includePaths && filters.includePaths.length > 0) {
1332
+ if (!matchesAnyPattern(path, filters.includePaths)) {
1333
+ if (stats) stats.filteredByPaths++;
1334
+ return false;
1335
+ }
1336
+ }
1337
+ if (filters.includeMethods && filters.includeMethods.length > 0) {
1338
+ const methodsLower = filters.includeMethods.map((m) => m.toLowerCase());
1339
+ if (!methodsLower.includes(methodLower)) {
1340
+ if (stats) stats.filteredByMethods++;
1341
+ return false;
1342
+ }
1343
+ }
1344
+ if (filters.includeOperationIds && filters.includeOperationIds.length > 0) {
1345
+ if (!matchesAnyPattern(operationId, filters.includeOperationIds)) {
1346
+ if (stats) stats.filteredByOperationIds++;
1347
+ return false;
1348
+ }
1349
+ }
1350
+ if (filters.excludeDeprecated === true && deprecated) {
1351
+ if (stats) stats.filteredByDeprecated++;
1352
+ return false;
1353
+ }
1354
+ if (filters.excludeTags && filters.excludeTags.length > 0) {
1355
+ if (containsAny(tags, filters.excludeTags)) {
1356
+ if (stats) stats.filteredByTags++;
1357
+ return false;
1358
+ }
1359
+ }
1360
+ if (filters.excludePaths && filters.excludePaths.length > 0) {
1361
+ if (matchesAnyPattern(path, filters.excludePaths)) {
1362
+ if (stats) stats.filteredByPaths++;
1363
+ return false;
1364
+ }
1365
+ }
1366
+ if (filters.excludeMethods && filters.excludeMethods.length > 0) {
1367
+ const methodsLower = filters.excludeMethods.map((m) => m.toLowerCase());
1368
+ if (methodsLower.includes(methodLower)) {
1369
+ if (stats) stats.filteredByMethods++;
1370
+ return false;
1371
+ }
1372
+ }
1373
+ if (filters.excludeOperationIds && filters.excludeOperationIds.length > 0) {
1374
+ if (matchesAnyPattern(operationId, filters.excludeOperationIds)) {
1375
+ if (stats) stats.filteredByOperationIds++;
1376
+ return false;
1377
+ }
1378
+ }
1379
+ return true;
1380
+ }
1381
+ function validateFilters(stats, filters) {
1382
+ if (!filters || stats.totalOperations === 0) {
1383
+ return;
1384
+ }
1385
+ if (stats.includedOperations === 0) {
1386
+ console.warn(
1387
+ `\u26A0\uFE0F Warning: All ${stats.totalOperations} operations were filtered out. Check your operationFilters configuration.`
1388
+ );
1389
+ const filterBreakdown = [];
1390
+ if (stats.filteredByTags > 0) filterBreakdown.push(`${stats.filteredByTags} by tags`);
1391
+ if (stats.filteredByPaths > 0) filterBreakdown.push(`${stats.filteredByPaths} by paths`);
1392
+ if (stats.filteredByMethods > 0) filterBreakdown.push(`${stats.filteredByMethods} by methods`);
1393
+ if (stats.filteredByOperationIds > 0) filterBreakdown.push(`${stats.filteredByOperationIds} by operationIds`);
1394
+ if (stats.filteredByDeprecated > 0) filterBreakdown.push(`${stats.filteredByDeprecated} by deprecated flag`);
1395
+ if (filterBreakdown.length > 0) {
1396
+ console.warn(` Filtered: ${filterBreakdown.join(", ")}`);
1397
+ }
1398
+ }
1399
+ }
1400
+ function formatFilterStatistics(stats) {
1401
+ if (stats.totalOperations === 0) {
1402
+ return "";
1403
+ }
1404
+ const lines = [];
1405
+ lines.push("Operation Filtering:");
1406
+ lines.push(` Total operations: ${stats.totalOperations}`);
1407
+ lines.push(` Included operations: ${stats.includedOperations}`);
1408
+ const filteredCount = stats.filteredByTags + stats.filteredByPaths + stats.filteredByMethods + stats.filteredByOperationIds + stats.filteredByDeprecated;
1409
+ if (filteredCount > 0) {
1410
+ lines.push(` Filtered operations: ${filteredCount}`);
1411
+ if (stats.filteredByTags > 0) lines.push(` - By tags: ${stats.filteredByTags}`);
1412
+ if (stats.filteredByPaths > 0) lines.push(` - By paths: ${stats.filteredByPaths}`);
1413
+ if (stats.filteredByMethods > 0) lines.push(` - By methods: ${stats.filteredByMethods}`);
1414
+ if (stats.filteredByOperationIds > 0) lines.push(` - By operationIds: ${stats.filteredByOperationIds}`);
1415
+ if (stats.filteredByDeprecated > 0) lines.push(` - By deprecated: ${stats.filteredByDeprecated}`);
1416
+ }
1417
+ return lines.join("\n");
1418
+ }
1419
+
1282
1420
  // src/openapi-generator.ts
1283
1421
  var OpenApiGenerator = class {
1284
1422
  constructor(options) {
@@ -1290,6 +1428,7 @@ var OpenApiGenerator = class {
1290
1428
  this.schemaUsageMap = /* @__PURE__ */ new Map();
1291
1429
  this.schemaTypeModeMap = /* @__PURE__ */ new Map();
1292
1430
  this.needsZodImport = false;
1431
+ this.filterStats = createFilterStatistics();
1293
1432
  var _a, _b, _c;
1294
1433
  if (!options.input) {
1295
1434
  throw new ConfigurationError("Input path is required", { providedOptions: options });
@@ -1307,7 +1446,8 @@ var OpenApiGenerator = class {
1307
1446
  showStats: (_c = options.showStats) != null ? _c : true,
1308
1447
  nativeEnumType: options.nativeEnumType || "union",
1309
1448
  request: options.request,
1310
- response: options.response
1449
+ response: options.response,
1450
+ operationFilters: options.operationFilters
1311
1451
  };
1312
1452
  try {
1313
1453
  const fs = require("fs");
@@ -1412,6 +1552,8 @@ var OpenApiGenerator = class {
1412
1552
  this.generateComponentSchema(name, schema);
1413
1553
  }
1414
1554
  this.generateQueryParameterSchemas();
1555
+ this.generateHeaderParameterSchemas();
1556
+ validateFilters(this.filterStats, this.options.operationFilters);
1415
1557
  const orderedSchemaNames = this.topologicalSort();
1416
1558
  const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
1417
1559
  if (this.options.showStats === true) {
@@ -1505,9 +1647,16 @@ var OpenApiGenerator = class {
1505
1647
  const requestSchemas = /* @__PURE__ */ new Set();
1506
1648
  const responseSchemas = /* @__PURE__ */ new Set();
1507
1649
  if (this.spec.paths) {
1508
- for (const [, pathItem] of Object.entries(this.spec.paths)) {
1509
- for (const [, operation] of Object.entries(pathItem)) {
1650
+ for (const [path, pathItem] of Object.entries(this.spec.paths)) {
1651
+ const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
1652
+ for (const method of methods) {
1653
+ const operation = pathItem[method];
1510
1654
  if (typeof operation !== "object" || !operation) continue;
1655
+ this.filterStats.totalOperations++;
1656
+ if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters, this.filterStats)) {
1657
+ continue;
1658
+ }
1659
+ this.filterStats.includedOperations++;
1511
1660
  if ("requestBody" in operation && operation.requestBody && typeof operation.requestBody === "object" && "content" in operation.requestBody && operation.requestBody.content) {
1512
1661
  for (const mediaType of Object.values(operation.requestBody.content)) {
1513
1662
  if (mediaType && typeof mediaType === "object" && "schema" in mediaType && mediaType.schema) {
@@ -1857,12 +2006,15 @@ ${typeCode}`;
1857
2006
  if (!this.spec.paths) {
1858
2007
  return;
1859
2008
  }
1860
- for (const [_path, pathItem] of Object.entries(this.spec.paths)) {
2009
+ for (const [path, pathItem] of Object.entries(this.spec.paths)) {
1861
2010
  if (!pathItem || typeof pathItem !== "object") continue;
1862
2011
  const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
1863
2012
  for (const method of methods) {
1864
2013
  const operation = pathItem[method];
1865
2014
  if (!operation) continue;
2015
+ if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
2016
+ continue;
2017
+ }
1866
2018
  if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
1867
2019
  continue;
1868
2020
  }
@@ -1923,6 +2075,80 @@ ${propsCode}
1923
2075
  const jsdoc = `/**
1924
2076
  * Query parameters for ${operation.operationId}
1925
2077
  */
2078
+ `;
2079
+ const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
2080
+ this.schemas.set(schemaName, fullSchemaCode);
2081
+ this.needsZodImport = true;
2082
+ }
2083
+ }
2084
+ }
2085
+ /**
2086
+ * Generate header parameter schemas for each operation
2087
+ * Header parameters are always string type (HTTP header semantics)
2088
+ */
2089
+ generateHeaderParameterSchemas() {
2090
+ var _a;
2091
+ if (!this.spec.paths) {
2092
+ return;
2093
+ }
2094
+ for (const [path, pathItem] of Object.entries(this.spec.paths)) {
2095
+ if (!pathItem || typeof pathItem !== "object") continue;
2096
+ const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
2097
+ for (const method of methods) {
2098
+ const operation = pathItem[method];
2099
+ if (!operation) continue;
2100
+ if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
2101
+ continue;
2102
+ }
2103
+ if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
2104
+ continue;
2105
+ }
2106
+ const headerParams = operation.parameters.filter(
2107
+ (param) => param && typeof param === "object" && param.in === "header"
2108
+ );
2109
+ if (headerParams.length === 0) {
2110
+ continue;
2111
+ }
2112
+ const pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
2113
+ const schemaName = `${pascalOperationId}HeaderParams`;
2114
+ if (!this.schemaDependencies.has(schemaName)) {
2115
+ this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
2116
+ }
2117
+ const properties = {};
2118
+ for (const param of headerParams) {
2119
+ const paramName = param.name;
2120
+ const paramSchema = param.schema;
2121
+ if (!paramSchema) continue;
2122
+ let zodType = "z.string()";
2123
+ if (param.description && this.requestOptions.includeDescriptions) {
2124
+ if (this.requestOptions.useDescribe) {
2125
+ zodType = `${zodType}.describe(${JSON.stringify(param.description)})`;
2126
+ }
2127
+ }
2128
+ zodType = `${zodType}.optional()`;
2129
+ properties[paramName] = zodType;
2130
+ if (paramSchema.$ref) {
2131
+ const refName = resolveRef(paramSchema.$ref);
2132
+ (_a = this.schemaDependencies.get(schemaName)) == null ? void 0 : _a.add(refName);
2133
+ }
2134
+ }
2135
+ const objectMode = this.requestOptions.mode;
2136
+ const zodMethod = objectMode === "strict" ? "strictObject" : objectMode === "loose" ? "looseObject" : "object";
2137
+ const propsCode = Object.entries(properties).map(([key, value]) => {
2138
+ const needsQuotes = !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key);
2139
+ const quotedKey = needsQuotes ? `"${key}"` : key;
2140
+ return ` ${quotedKey}: ${value}`;
2141
+ }).join(",\n");
2142
+ const schemaCode = `z.${zodMethod}({
2143
+ ${propsCode}
2144
+ })`;
2145
+ const operationName = pascalOperationId;
2146
+ const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
2147
+ const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
2148
+ const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}HeaderParamsSchema`;
2149
+ const jsdoc = `/**
2150
+ * Header parameters for ${operation.operationId}
2151
+ */
1926
2152
  `;
1927
2153
  const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
1928
2154
  this.schemas.set(schemaName, fullSchemaCode);
@@ -2200,15 +2426,23 @@ ${props.join("\n")}
2200
2426
  stats.withConstraints++;
2201
2427
  }
2202
2428
  }
2203
- return [
2429
+ const output = [
2204
2430
  "// Generation Statistics:",
2205
2431
  `// Total schemas: ${stats.totalSchemas}`,
2206
2432
  `// Enums: ${stats.enums}`,
2207
2433
  `// Circular references: ${stats.withCircularRefs}`,
2208
2434
  `// Discriminated unions: ${stats.withDiscriminators}`,
2209
- `// With constraints: ${stats.withConstraints}`,
2210
- `// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`
2435
+ `// With constraints: ${stats.withConstraints}`
2211
2436
  ];
2437
+ if (this.options.operationFilters && this.filterStats.totalOperations > 0) {
2438
+ output.push("//");
2439
+ const filterStatsStr = formatFilterStatistics(this.filterStats);
2440
+ for (const line of filterStatsStr.split("\n")) {
2441
+ output.push(`// ${line}`);
2442
+ }
2443
+ }
2444
+ output.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
2445
+ return output;
2212
2446
  }
2213
2447
  };
2214
2448
 
@@ -2226,6 +2460,10 @@ function defineConfig(config) {
2226
2460
  OpenApiGenerator,
2227
2461
  SchemaGenerationError,
2228
2462
  SpecValidationError,
2229
- defineConfig
2463
+ createFilterStatistics,
2464
+ defineConfig,
2465
+ formatFilterStatistics,
2466
+ shouldIncludeOperation,
2467
+ validateFilters
2230
2468
  });
2231
2469
  //# sourceMappingURL=index.js.map