@cerios/openapi-to-zod 1.5.1 → 1.6.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
@@ -234,6 +234,18 @@ interface OpenApiGeneratorOptions extends BaseGeneratorOptions {
234
234
  */
235
235
  typeAssertionThreshold?: number;
236
236
  }
237
+ /**
238
+ * Internal options that extend public options with internal-only properties
239
+ * @internal
240
+ */
241
+ interface InternalOpenApiGeneratorOptions extends OpenApiGeneratorOptions {
242
+ /**
243
+ * Whether to include the auto-generated header comment in output
244
+ * Used internally by downstream packages for consistent branding
245
+ * @internal
246
+ */
247
+ includeHeader?: boolean;
248
+ }
237
249
  /**
238
250
  * Root configuration file structure
239
251
  */
@@ -322,6 +334,11 @@ interface PropertyGeneratorContext {
322
334
  * @default false
323
335
  */
324
336
  separateTypesFile: boolean;
337
+ /**
338
+ * Warning function for non-fatal issues during schema generation
339
+ * If not provided, warnings are silently ignored
340
+ */
341
+ warn?: (message: string) => void;
325
342
  }
326
343
  /**
327
344
  * Property schema generator with memoization for performance
@@ -429,13 +446,13 @@ declare class OpenApiGenerator {
429
446
  private patternCache;
430
447
  /** Instance-level date-time validation string for parallel-safe execution */
431
448
  private dateTimeValidation;
432
- /** Track total allOf conflicts detected across all schemas */
433
- private allOfConflictCount;
434
449
  /** Track schemas involved in circular dependency chains */
435
450
  private circularDependencies;
436
451
  /** Separate schemas mode - when outputZodSchemas is specified */
437
452
  private separateSchemasMode;
438
- constructor(options: OpenApiGeneratorOptions);
453
+ /** Warning collector for deferred output */
454
+ private readonly warningCollector;
455
+ constructor(options: OpenApiGeneratorOptions | InternalOpenApiGeneratorOptions);
439
456
  /**
440
457
  * Generate schemas as a string (without writing to file)
441
458
  * When separateSchemasMode is active, generates Zod schemas with explicit type annotations
@@ -574,4 +591,4 @@ declare class OpenApiGenerator {
574
591
  */
575
592
  declare function buildDateTimeValidation(pattern?: string | RegExp): string;
576
593
 
577
- export { type CommonSchemaOptions, type ConfigFile, OpenApiGenerator, type OpenApiGeneratorOptions, PropertyGenerator, type PropertyGeneratorContext, type RequestOptions, type ResponseOptions, buildDateTimeValidation, defineConfig };
594
+ export { type CommonSchemaOptions, type ConfigFile, type InternalOpenApiGeneratorOptions, OpenApiGenerator, type OpenApiGeneratorOptions, PropertyGenerator, type PropertyGeneratorContext, type RequestOptions, type ResponseOptions, buildDateTimeValidation, defineConfig };
package/dist/index.d.ts CHANGED
@@ -234,6 +234,18 @@ interface OpenApiGeneratorOptions extends BaseGeneratorOptions {
234
234
  */
235
235
  typeAssertionThreshold?: number;
236
236
  }
237
+ /**
238
+ * Internal options that extend public options with internal-only properties
239
+ * @internal
240
+ */
241
+ interface InternalOpenApiGeneratorOptions extends OpenApiGeneratorOptions {
242
+ /**
243
+ * Whether to include the auto-generated header comment in output
244
+ * Used internally by downstream packages for consistent branding
245
+ * @internal
246
+ */
247
+ includeHeader?: boolean;
248
+ }
237
249
  /**
238
250
  * Root configuration file structure
239
251
  */
@@ -322,6 +334,11 @@ interface PropertyGeneratorContext {
322
334
  * @default false
323
335
  */
324
336
  separateTypesFile: boolean;
337
+ /**
338
+ * Warning function for non-fatal issues during schema generation
339
+ * If not provided, warnings are silently ignored
340
+ */
341
+ warn?: (message: string) => void;
325
342
  }
326
343
  /**
327
344
  * Property schema generator with memoization for performance
@@ -429,13 +446,13 @@ declare class OpenApiGenerator {
429
446
  private patternCache;
430
447
  /** Instance-level date-time validation string for parallel-safe execution */
431
448
  private dateTimeValidation;
432
- /** Track total allOf conflicts detected across all schemas */
433
- private allOfConflictCount;
434
449
  /** Track schemas involved in circular dependency chains */
435
450
  private circularDependencies;
436
451
  /** Separate schemas mode - when outputZodSchemas is specified */
437
452
  private separateSchemasMode;
438
- constructor(options: OpenApiGeneratorOptions);
453
+ /** Warning collector for deferred output */
454
+ private readonly warningCollector;
455
+ constructor(options: OpenApiGeneratorOptions | InternalOpenApiGeneratorOptions);
439
456
  /**
440
457
  * Generate schemas as a string (without writing to file)
441
458
  * When separateSchemasMode is active, generates Zod schemas with explicit type annotations
@@ -574,4 +591,4 @@ declare class OpenApiGenerator {
574
591
  */
575
592
  declare function buildDateTimeValidation(pattern?: string | RegExp): string;
576
593
 
577
- export { type CommonSchemaOptions, type ConfigFile, OpenApiGenerator, type OpenApiGeneratorOptions, PropertyGenerator, type PropertyGeneratorContext, type RequestOptions, type ResponseOptions, buildDateTimeValidation, defineConfig };
594
+ export { type CommonSchemaOptions, type ConfigFile, type InternalOpenApiGeneratorOptions, OpenApiGenerator, type OpenApiGeneratorOptions, PropertyGenerator, type PropertyGeneratorContext, type RequestOptions, type ResponseOptions, buildDateTimeValidation, defineConfig };
package/dist/index.js CHANGED
@@ -112,9 +112,11 @@ function isDiscriminatorRequired(schemas, discriminator, context) {
112
112
  };
113
113
  }
114
114
  function generateUnion(schemas, discriminator, isNullable2, context, options, currentSchema) {
115
+ var _a, _b;
115
116
  if (schemas.length === 0) {
116
- console.warn(
117
- "[openapi-to-zod] Warning: Empty oneOf/anyOf array encountered. This is likely a malformed OpenAPI spec. Generating z.never() as fallback."
117
+ (_a = context.warn) == null ? void 0 : _a.call(
118
+ context,
119
+ "Empty oneOf/anyOf array encountered. This is likely a malformed OpenAPI spec. Generating z.never() as fallback."
118
120
  );
119
121
  return wrapNullable(
120
122
  'z.never().describe("Empty oneOf/anyOf in OpenAPI spec - no valid schema defined")',
@@ -135,8 +137,9 @@ function generateUnion(schemas, discriminator, isNullable2, context, options, cu
135
137
  }
136
138
  const discriminatorCheck = isDiscriminatorRequired(resolvedSchemas, discriminator, context);
137
139
  if (!discriminatorCheck.valid) {
138
- console.warn(
139
- `[openapi-to-zod] Warning: Discriminator "${discriminator}" is not required in schemas: ${discriminatorCheck.invalidSchemas.join(", ")}. Falling back to z.union() instead of z.discriminatedUnion().`
140
+ (_b = context.warn) == null ? void 0 : _b.call(
141
+ context,
142
+ `Discriminator "${discriminator}" is not required in schemas: ${discriminatorCheck.invalidSchemas.join(", ")}. Falling back to z.union() instead of z.discriminatedUnion().`
140
143
  );
141
144
  let schemaStrings3 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema, false, true));
142
145
  if (options == null ? void 0 : options.passthrough) {
@@ -214,6 +217,7 @@ function detectConflictingProperties(schemas, context) {
214
217
  return conflicts;
215
218
  }
216
219
  function generateAllOf(schemas, isNullable2, context, currentSchema) {
220
+ var _a;
217
221
  if (schemas.length === 1) {
218
222
  const singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false, true);
219
223
  return { schema: wrapNullable(singleSchema, isNullable2), conflicts: [] };
@@ -222,7 +226,7 @@ function generateAllOf(schemas, isNullable2, context, currentSchema) {
222
226
  const uniqueConflicts = [...new Set(conflicts)];
223
227
  if (uniqueConflicts.length > 0) {
224
228
  for (const conflict of uniqueConflicts) {
225
- console.warn(`[openapi-to-zod] Warning: allOf composition conflict - ${conflict}`);
229
+ (_a = context.warn) == null ? void 0 : _a.call(context, `allOf composition conflict - ${conflict}`);
226
230
  }
227
231
  }
228
232
  const allObjects = schemas.every((s) => s.type === "object" || s.properties || s.$ref || s.allOf);
@@ -1184,7 +1188,8 @@ var _PropertyGenerator = class _PropertyGenerator {
1184
1188
  {
1185
1189
  generatePropertySchema: this.generatePropertySchema.bind(this),
1186
1190
  generateInlineObjectShape: this.generateInlineObjectShape.bind(this),
1187
- resolveSchemaRef: this.resolveSchemaRef.bind(this)
1191
+ resolveSchemaRef: this.resolveSchemaRef.bind(this),
1192
+ warn: this.context.warn
1188
1193
  },
1189
1194
  currentSchema
1190
1195
  );
@@ -1207,7 +1212,8 @@ var _PropertyGenerator = class _PropertyGenerator {
1207
1212
  {
1208
1213
  generatePropertySchema: this.generatePropertySchema.bind(this),
1209
1214
  resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
1210
- resolveSchemaRef: this.resolveSchemaRef.bind(this)
1215
+ resolveSchemaRef: this.resolveSchemaRef.bind(this),
1216
+ warn: this.context.warn
1211
1217
  },
1212
1218
  {
1213
1219
  passthrough: needsPassthrough,
@@ -1230,7 +1236,8 @@ var _PropertyGenerator = class _PropertyGenerator {
1230
1236
  {
1231
1237
  generatePropertySchema: this.generatePropertySchema.bind(this),
1232
1238
  resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
1233
- resolveSchemaRef: this.resolveSchemaRef.bind(this)
1239
+ resolveSchemaRef: this.resolveSchemaRef.bind(this),
1240
+ warn: this.context.warn
1234
1241
  },
1235
1242
  {
1236
1243
  passthrough: needsPassthrough,
@@ -1421,8 +1428,6 @@ var OpenApiGenerator = class {
1421
1428
  this.schemaUsageMap = /* @__PURE__ */ new Map();
1422
1429
  this.needsZodImport = true;
1423
1430
  this.filterStats = (0, import_openapi_core6.createFilterStatistics)();
1424
- /** Track total allOf conflicts detected across all schemas */
1425
- this.allOfConflictCount = 0;
1426
1431
  /** Track schemas involved in circular dependency chains */
1427
1432
  this.circularDependencies = /* @__PURE__ */ new Set();
1428
1433
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
@@ -1430,6 +1435,11 @@ var OpenApiGenerator = class {
1430
1435
  throw new import_openapi_core6.ConfigurationError("Input path is required", { providedOptions: options });
1431
1436
  }
1432
1437
  this.separateSchemasMode = Boolean(options.outputZodSchemas);
1438
+ const showWarnings = options.showWarnings !== false;
1439
+ this.warningCollector = new import_openapi_core6.WarningCollector({
1440
+ packageName: "@cerios/openapi-to-zod",
1441
+ enabled: showWarnings
1442
+ });
1433
1443
  this.options = {
1434
1444
  mode: options.mode || "normal",
1435
1445
  input: options.input,
@@ -1448,13 +1458,16 @@ var OpenApiGenerator = class {
1448
1458
  stripPathPrefix: options.stripPathPrefix,
1449
1459
  useOperationId: (_f = options.useOperationId) != null ? _f : true,
1450
1460
  showStats: (_g = options.showStats) != null ? _g : true,
1461
+ showWarnings,
1451
1462
  request: options.request,
1452
1463
  response: options.response,
1453
1464
  operationFilters: options.operationFilters,
1454
1465
  ignoreHeaders: options.ignoreHeaders,
1455
1466
  cacheSize: (_h = options.cacheSize) != null ? _h : 1e3,
1456
1467
  batchSize: (_i = options.batchSize) != null ? _i : 10,
1457
- customDateTimeFormatRegex: options.customDateTimeFormatRegex
1468
+ customDateTimeFormatRegex: options.customDateTimeFormatRegex,
1469
+ includeHeader: options.includeHeader,
1470
+ fileHeader: options.fileHeader
1458
1471
  };
1459
1472
  this.patternCache = new import_openapi_core6.LRUCache((_j = this.options.cacheSize) != null ? _j : 1e3);
1460
1473
  this.dateTimeValidation = buildDateTimeValidation(this.options.customDateTimeFormatRegex);
@@ -1479,7 +1492,10 @@ var OpenApiGenerator = class {
1479
1492
  stripSchemaPrefix: this.options.stripSchemaPrefix,
1480
1493
  dateTimeValidation: this.dateTimeValidation,
1481
1494
  patternCache: this.patternCache,
1482
- separateTypesFile: this.separateSchemasMode
1495
+ separateTypesFile: this.separateSchemasMode,
1496
+ warn: (msg) => {
1497
+ this.warningCollector.add(msg);
1498
+ }
1483
1499
  });
1484
1500
  }
1485
1501
  /**
@@ -1488,7 +1504,7 @@ var OpenApiGenerator = class {
1488
1504
  * @returns The generated TypeScript code as a string
1489
1505
  */
1490
1506
  generateString() {
1491
- var _a;
1507
+ var _a, _b, _c;
1492
1508
  if (!((_a = this.spec.components) == null ? void 0 : _a.schemas)) {
1493
1509
  throw new import_openapi_core6.SpecValidationError("No schemas found in OpenAPI spec", { filePath: this.options.input });
1494
1510
  }
@@ -1505,9 +1521,26 @@ var OpenApiGenerator = class {
1505
1521
  }
1506
1522
  this.generateQueryParameterSchemas();
1507
1523
  this.generateHeaderParameterSchemas();
1508
- (0, import_openapi_core6.validateFilters)(this.filterStats, this.options.operationFilters);
1524
+ (0, import_openapi_core6.validateFilters)(this.filterStats, this.options.operationFilters, (msg) => {
1525
+ this.warningCollector.add(msg);
1526
+ });
1509
1527
  const orderedSchemaNames = this.topologicalSort();
1510
- const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
1528
+ const output = [];
1529
+ const customHeader = (0, import_openapi_core6.generateCustomFileHeader)(this.options.fileHeader);
1530
+ if (customHeader) {
1531
+ output.push(customHeader.trimEnd());
1532
+ output.push("");
1533
+ }
1534
+ if (this.options.includeHeader !== false) {
1535
+ output.push(
1536
+ (0, import_openapi_core6.generateFileHeader)({
1537
+ packageName: "@cerios/openapi-to-zod",
1538
+ apiTitle: (_b = this.spec.info) == null ? void 0 : _b.title,
1539
+ apiVersion: (_c = this.spec.info) == null ? void 0 : _c.version
1540
+ }).trimEnd()
1541
+ );
1542
+ output.push("");
1543
+ }
1511
1544
  if (this.options.showStats === true) {
1512
1545
  output.push(...this.generateStats());
1513
1546
  output.push("");
@@ -1534,6 +1567,7 @@ var OpenApiGenerator = class {
1534
1567
  output.push("");
1535
1568
  }
1536
1569
  }
1570
+ this.warningCollector.flush();
1537
1571
  return output.join("\n");
1538
1572
  }
1539
1573
  /**
@@ -1573,6 +1607,7 @@ var OpenApiGenerator = class {
1573
1607
  (0, import_node_fs.writeFileSync)(normalizedOutput, output);
1574
1608
  console.log(` \u2713 Generated ${normalizedOutput}`);
1575
1609
  }
1610
+ this.warningCollector.flush();
1576
1611
  }
1577
1612
  /**
1578
1613
  * Generate Zod schemas with explicit type annotations (for outputZodSchemas mode)
@@ -1580,7 +1615,7 @@ var OpenApiGenerator = class {
1580
1615
  * @returns The generated Zod schemas TypeScript code
1581
1616
  */
1582
1617
  generateSeparateSchemasString() {
1583
- var _a;
1618
+ var _a, _b, _c;
1584
1619
  const schemas = (_a = this.spec.components) == null ? void 0 : _a.schemas;
1585
1620
  if (!schemas) {
1586
1621
  return "";
@@ -1599,9 +1634,24 @@ var OpenApiGenerator = class {
1599
1634
  }
1600
1635
  this.generateQueryParameterSchemas();
1601
1636
  this.generateHeaderParameterSchemas();
1602
- (0, import_openapi_core6.validateFilters)(this.filterStats, this.options.operationFilters);
1637
+ (0, import_openapi_core6.validateFilters)(this.filterStats, this.options.operationFilters, (msg) => {
1638
+ this.warningCollector.add(msg);
1639
+ });
1603
1640
  const orderedSchemaNames = this.topologicalSort();
1604
- const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
1641
+ const output = [];
1642
+ const customHeader = (0, import_openapi_core6.generateCustomFileHeader)(this.options.fileHeader);
1643
+ if (customHeader) {
1644
+ output.push(customHeader.trimEnd());
1645
+ output.push("");
1646
+ }
1647
+ output.push(
1648
+ (0, import_openapi_core6.generateFileHeader)({
1649
+ packageName: "@cerios/openapi-to-zod",
1650
+ apiTitle: (_b = this.spec.info) == null ? void 0 : _b.title,
1651
+ apiVersion: (_c = this.spec.info) == null ? void 0 : _c.version
1652
+ }).trimEnd()
1653
+ );
1654
+ output.push("");
1605
1655
  if (this.options.showStats === true) {
1606
1656
  output.push(...this.generateStats());
1607
1657
  output.push("");
@@ -1639,8 +1689,8 @@ var OpenApiGenerator = class {
1639
1689
  * @returns The generated TypeScript types code
1640
1690
  */
1641
1691
  generateTypesString() {
1642
- var _a;
1643
- const tsGenerator = new import_openapi_to_typescript.TypeScriptGenerator({
1692
+ var _a, _b, _c;
1693
+ const internalOptions = {
1644
1694
  input: this.options.input,
1645
1695
  outputTypes: this.options.outputTypes,
1646
1696
  includeDescriptions: this.options.includeDescriptions,
@@ -1651,9 +1701,20 @@ var OpenApiGenerator = class {
1651
1701
  stripPathPrefix: this.options.stripPathPrefix,
1652
1702
  operationFilters: this.options.operationFilters,
1653
1703
  showStats: this.options.showStats,
1654
- enumFormat: (_a = this.options.enumFormat) != null ? _a : "const-object"
1704
+ enumFormat: (_a = this.options.enumFormat) != null ? _a : "const-object",
1705
+ includeHeader: false,
1706
+ // We add our own header for consistent branding
1707
+ showWarnings: false
1708
+ // We handle warnings ourselves
1709
+ };
1710
+ const tsGenerator = new import_openapi_to_typescript.TypeScriptGenerator(internalOptions);
1711
+ const customHeader = (0, import_openapi_core6.generateCustomFileHeader)(this.options.fileHeader);
1712
+ const header = (0, import_openapi_core6.generateFileHeader)({
1713
+ packageName: "@cerios/openapi-to-zod",
1714
+ apiTitle: (_b = this.spec.info) == null ? void 0 : _b.title,
1715
+ apiVersion: (_c = this.spec.info) == null ? void 0 : _c.version
1655
1716
  });
1656
- return tsGenerator.generateString();
1717
+ return customHeader + header + tsGenerator.generateString();
1657
1718
  }
1658
1719
  /**
1659
1720
  * Add explicit type annotation to a schema declaration
@@ -1972,14 +2033,16 @@ ${typeCode}`;
1972
2033
  stripSchemaPrefix: this.options.stripSchemaPrefix,
1973
2034
  dateTimeValidation: this.dateTimeValidation,
1974
2035
  patternCache: this.patternCache,
1975
- separateTypesFile: this.separateSchemasMode
2036
+ separateTypesFile: this.separateSchemasMode,
2037
+ warn: (msg) => {
2038
+ this.warningCollector.add(msg);
2039
+ }
1976
2040
  });
1977
2041
  this.propertyGenerator.setCircularDependencies(this.circularDependencies);
1978
2042
  this.propertyGenerator.clearAllOfConflicts();
1979
2043
  const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, true);
1980
2044
  const allOfConflicts = this.propertyGenerator.getAllOfConflicts();
1981
2045
  if (allOfConflicts.length > 0) {
1982
- this.allOfConflictCount += allOfConflicts.length;
1983
2046
  const conflictWarning = this.generateConflictJSDoc(allOfConflicts);
1984
2047
  if (jsdoc) {
1985
2048
  jsdoc = jsdoc.replace(/ \*\/\n$/, `
@@ -2343,8 +2406,7 @@ ${propsCode}
2343
2406
  `// Total schemas: ${stats.totalSchemas}`,
2344
2407
  `// Circular references: ${stats.withCircularRefs}`,
2345
2408
  `// Discriminated unions: ${stats.withDiscriminators}`,
2346
- `// With constraints: ${stats.withConstraints}`,
2347
- `// AllOf conflicts: ${this.allOfConflictCount}`
2409
+ `// With constraints: ${stats.withConstraints}`
2348
2410
  ];
2349
2411
  if (this.options.operationFilters && this.filterStats.totalOperations > 0) {
2350
2412
  output.push("//");