@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.mjs CHANGED
@@ -95,9 +95,11 @@ function isDiscriminatorRequired(schemas, discriminator, context) {
95
95
  };
96
96
  }
97
97
  function generateUnion(schemas, discriminator, isNullable2, context, options, currentSchema) {
98
+ var _a, _b;
98
99
  if (schemas.length === 0) {
99
- console.warn(
100
- "[openapi-to-zod] Warning: Empty oneOf/anyOf array encountered. This is likely a malformed OpenAPI spec. Generating z.never() as fallback."
100
+ (_a = context.warn) == null ? void 0 : _a.call(
101
+ context,
102
+ "Empty oneOf/anyOf array encountered. This is likely a malformed OpenAPI spec. Generating z.never() as fallback."
101
103
  );
102
104
  return wrapNullable(
103
105
  'z.never().describe("Empty oneOf/anyOf in OpenAPI spec - no valid schema defined")',
@@ -118,8 +120,9 @@ function generateUnion(schemas, discriminator, isNullable2, context, options, cu
118
120
  }
119
121
  const discriminatorCheck = isDiscriminatorRequired(resolvedSchemas, discriminator, context);
120
122
  if (!discriminatorCheck.valid) {
121
- console.warn(
122
- `[openapi-to-zod] Warning: Discriminator "${discriminator}" is not required in schemas: ${discriminatorCheck.invalidSchemas.join(", ")}. Falling back to z.union() instead of z.discriminatedUnion().`
123
+ (_b = context.warn) == null ? void 0 : _b.call(
124
+ context,
125
+ `Discriminator "${discriminator}" is not required in schemas: ${discriminatorCheck.invalidSchemas.join(", ")}. Falling back to z.union() instead of z.discriminatedUnion().`
123
126
  );
124
127
  let schemaStrings3 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema, false, true));
125
128
  if (options == null ? void 0 : options.passthrough) {
@@ -197,6 +200,7 @@ function detectConflictingProperties(schemas, context) {
197
200
  return conflicts;
198
201
  }
199
202
  function generateAllOf(schemas, isNullable2, context, currentSchema) {
203
+ var _a;
200
204
  if (schemas.length === 1) {
201
205
  const singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false, true);
202
206
  return { schema: wrapNullable(singleSchema, isNullable2), conflicts: [] };
@@ -205,7 +209,7 @@ function generateAllOf(schemas, isNullable2, context, currentSchema) {
205
209
  const uniqueConflicts = [...new Set(conflicts)];
206
210
  if (uniqueConflicts.length > 0) {
207
211
  for (const conflict of uniqueConflicts) {
208
- console.warn(`[openapi-to-zod] Warning: allOf composition conflict - ${conflict}`);
212
+ (_a = context.warn) == null ? void 0 : _a.call(context, `allOf composition conflict - ${conflict}`);
209
213
  }
210
214
  }
211
215
  const allObjects = schemas.every((s) => s.type === "object" || s.properties || s.$ref || s.allOf);
@@ -1167,7 +1171,8 @@ var _PropertyGenerator = class _PropertyGenerator {
1167
1171
  {
1168
1172
  generatePropertySchema: this.generatePropertySchema.bind(this),
1169
1173
  generateInlineObjectShape: this.generateInlineObjectShape.bind(this),
1170
- resolveSchemaRef: this.resolveSchemaRef.bind(this)
1174
+ resolveSchemaRef: this.resolveSchemaRef.bind(this),
1175
+ warn: this.context.warn
1171
1176
  },
1172
1177
  currentSchema
1173
1178
  );
@@ -1190,7 +1195,8 @@ var _PropertyGenerator = class _PropertyGenerator {
1190
1195
  {
1191
1196
  generatePropertySchema: this.generatePropertySchema.bind(this),
1192
1197
  resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
1193
- resolveSchemaRef: this.resolveSchemaRef.bind(this)
1198
+ resolveSchemaRef: this.resolveSchemaRef.bind(this),
1199
+ warn: this.context.warn
1194
1200
  },
1195
1201
  {
1196
1202
  passthrough: needsPassthrough,
@@ -1213,7 +1219,8 @@ var _PropertyGenerator = class _PropertyGenerator {
1213
1219
  {
1214
1220
  generatePropertySchema: this.generatePropertySchema.bind(this),
1215
1221
  resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
1216
- resolveSchemaRef: this.resolveSchemaRef.bind(this)
1222
+ resolveSchemaRef: this.resolveSchemaRef.bind(this),
1223
+ warn: this.context.warn
1217
1224
  },
1218
1225
  {
1219
1226
  passthrough: needsPassthrough,
@@ -1363,6 +1370,8 @@ import {
1363
1370
  expandTransitiveReferences,
1364
1371
  extractSchemaRefs,
1365
1372
  formatFilterStatistics,
1373
+ generateCustomFileHeader,
1374
+ generateFileHeader,
1366
1375
  getOperationName,
1367
1376
  LRUCache as LRUCache2,
1368
1377
  loadOpenAPISpec,
@@ -1375,7 +1384,8 @@ import {
1375
1384
  stripPrefix as stripPrefix2,
1376
1385
  toCamelCase as toCamelCase3,
1377
1386
  toPascalCase as toPascalCase3,
1378
- validateFilters
1387
+ validateFilters,
1388
+ WarningCollector
1379
1389
  } from "@cerios/openapi-core";
1380
1390
  import { TypeScriptGenerator } from "@cerios/openapi-to-typescript";
1381
1391
  import { minimatch } from "minimatch";
@@ -1425,8 +1435,6 @@ var OpenApiGenerator = class {
1425
1435
  this.schemaUsageMap = /* @__PURE__ */ new Map();
1426
1436
  this.needsZodImport = true;
1427
1437
  this.filterStats = createFilterStatistics();
1428
- /** Track total allOf conflicts detected across all schemas */
1429
- this.allOfConflictCount = 0;
1430
1438
  /** Track schemas involved in circular dependency chains */
1431
1439
  this.circularDependencies = /* @__PURE__ */ new Set();
1432
1440
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
@@ -1434,6 +1442,11 @@ var OpenApiGenerator = class {
1434
1442
  throw new ConfigurationError("Input path is required", { providedOptions: options });
1435
1443
  }
1436
1444
  this.separateSchemasMode = Boolean(options.outputZodSchemas);
1445
+ const showWarnings = options.showWarnings !== false;
1446
+ this.warningCollector = new WarningCollector({
1447
+ packageName: "@cerios/openapi-to-zod",
1448
+ enabled: showWarnings
1449
+ });
1437
1450
  this.options = {
1438
1451
  mode: options.mode || "normal",
1439
1452
  input: options.input,
@@ -1452,13 +1465,16 @@ var OpenApiGenerator = class {
1452
1465
  stripPathPrefix: options.stripPathPrefix,
1453
1466
  useOperationId: (_f = options.useOperationId) != null ? _f : true,
1454
1467
  showStats: (_g = options.showStats) != null ? _g : true,
1468
+ showWarnings,
1455
1469
  request: options.request,
1456
1470
  response: options.response,
1457
1471
  operationFilters: options.operationFilters,
1458
1472
  ignoreHeaders: options.ignoreHeaders,
1459
1473
  cacheSize: (_h = options.cacheSize) != null ? _h : 1e3,
1460
1474
  batchSize: (_i = options.batchSize) != null ? _i : 10,
1461
- customDateTimeFormatRegex: options.customDateTimeFormatRegex
1475
+ customDateTimeFormatRegex: options.customDateTimeFormatRegex,
1476
+ includeHeader: options.includeHeader,
1477
+ fileHeader: options.fileHeader
1462
1478
  };
1463
1479
  this.patternCache = new LRUCache2((_j = this.options.cacheSize) != null ? _j : 1e3);
1464
1480
  this.dateTimeValidation = buildDateTimeValidation(this.options.customDateTimeFormatRegex);
@@ -1483,7 +1499,10 @@ var OpenApiGenerator = class {
1483
1499
  stripSchemaPrefix: this.options.stripSchemaPrefix,
1484
1500
  dateTimeValidation: this.dateTimeValidation,
1485
1501
  patternCache: this.patternCache,
1486
- separateTypesFile: this.separateSchemasMode
1502
+ separateTypesFile: this.separateSchemasMode,
1503
+ warn: (msg) => {
1504
+ this.warningCollector.add(msg);
1505
+ }
1487
1506
  });
1488
1507
  }
1489
1508
  /**
@@ -1492,7 +1511,7 @@ var OpenApiGenerator = class {
1492
1511
  * @returns The generated TypeScript code as a string
1493
1512
  */
1494
1513
  generateString() {
1495
- var _a;
1514
+ var _a, _b, _c;
1496
1515
  if (!((_a = this.spec.components) == null ? void 0 : _a.schemas)) {
1497
1516
  throw new SpecValidationError("No schemas found in OpenAPI spec", { filePath: this.options.input });
1498
1517
  }
@@ -1509,9 +1528,26 @@ var OpenApiGenerator = class {
1509
1528
  }
1510
1529
  this.generateQueryParameterSchemas();
1511
1530
  this.generateHeaderParameterSchemas();
1512
- validateFilters(this.filterStats, this.options.operationFilters);
1531
+ validateFilters(this.filterStats, this.options.operationFilters, (msg) => {
1532
+ this.warningCollector.add(msg);
1533
+ });
1513
1534
  const orderedSchemaNames = this.topologicalSort();
1514
- const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
1535
+ const output = [];
1536
+ const customHeader = generateCustomFileHeader(this.options.fileHeader);
1537
+ if (customHeader) {
1538
+ output.push(customHeader.trimEnd());
1539
+ output.push("");
1540
+ }
1541
+ if (this.options.includeHeader !== false) {
1542
+ output.push(
1543
+ generateFileHeader({
1544
+ packageName: "@cerios/openapi-to-zod",
1545
+ apiTitle: (_b = this.spec.info) == null ? void 0 : _b.title,
1546
+ apiVersion: (_c = this.spec.info) == null ? void 0 : _c.version
1547
+ }).trimEnd()
1548
+ );
1549
+ output.push("");
1550
+ }
1515
1551
  if (this.options.showStats === true) {
1516
1552
  output.push(...this.generateStats());
1517
1553
  output.push("");
@@ -1538,6 +1574,7 @@ var OpenApiGenerator = class {
1538
1574
  output.push("");
1539
1575
  }
1540
1576
  }
1577
+ this.warningCollector.flush();
1541
1578
  return output.join("\n");
1542
1579
  }
1543
1580
  /**
@@ -1577,6 +1614,7 @@ var OpenApiGenerator = class {
1577
1614
  writeFileSync(normalizedOutput, output);
1578
1615
  console.log(` \u2713 Generated ${normalizedOutput}`);
1579
1616
  }
1617
+ this.warningCollector.flush();
1580
1618
  }
1581
1619
  /**
1582
1620
  * Generate Zod schemas with explicit type annotations (for outputZodSchemas mode)
@@ -1584,7 +1622,7 @@ var OpenApiGenerator = class {
1584
1622
  * @returns The generated Zod schemas TypeScript code
1585
1623
  */
1586
1624
  generateSeparateSchemasString() {
1587
- var _a;
1625
+ var _a, _b, _c;
1588
1626
  const schemas = (_a = this.spec.components) == null ? void 0 : _a.schemas;
1589
1627
  if (!schemas) {
1590
1628
  return "";
@@ -1603,9 +1641,24 @@ var OpenApiGenerator = class {
1603
1641
  }
1604
1642
  this.generateQueryParameterSchemas();
1605
1643
  this.generateHeaderParameterSchemas();
1606
- validateFilters(this.filterStats, this.options.operationFilters);
1644
+ validateFilters(this.filterStats, this.options.operationFilters, (msg) => {
1645
+ this.warningCollector.add(msg);
1646
+ });
1607
1647
  const orderedSchemaNames = this.topologicalSort();
1608
- const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
1648
+ const output = [];
1649
+ const customHeader = generateCustomFileHeader(this.options.fileHeader);
1650
+ if (customHeader) {
1651
+ output.push(customHeader.trimEnd());
1652
+ output.push("");
1653
+ }
1654
+ output.push(
1655
+ generateFileHeader({
1656
+ packageName: "@cerios/openapi-to-zod",
1657
+ apiTitle: (_b = this.spec.info) == null ? void 0 : _b.title,
1658
+ apiVersion: (_c = this.spec.info) == null ? void 0 : _c.version
1659
+ }).trimEnd()
1660
+ );
1661
+ output.push("");
1609
1662
  if (this.options.showStats === true) {
1610
1663
  output.push(...this.generateStats());
1611
1664
  output.push("");
@@ -1643,8 +1696,8 @@ var OpenApiGenerator = class {
1643
1696
  * @returns The generated TypeScript types code
1644
1697
  */
1645
1698
  generateTypesString() {
1646
- var _a;
1647
- const tsGenerator = new TypeScriptGenerator({
1699
+ var _a, _b, _c;
1700
+ const internalOptions = {
1648
1701
  input: this.options.input,
1649
1702
  outputTypes: this.options.outputTypes,
1650
1703
  includeDescriptions: this.options.includeDescriptions,
@@ -1655,9 +1708,20 @@ var OpenApiGenerator = class {
1655
1708
  stripPathPrefix: this.options.stripPathPrefix,
1656
1709
  operationFilters: this.options.operationFilters,
1657
1710
  showStats: this.options.showStats,
1658
- enumFormat: (_a = this.options.enumFormat) != null ? _a : "const-object"
1711
+ enumFormat: (_a = this.options.enumFormat) != null ? _a : "const-object",
1712
+ includeHeader: false,
1713
+ // We add our own header for consistent branding
1714
+ showWarnings: false
1715
+ // We handle warnings ourselves
1716
+ };
1717
+ const tsGenerator = new TypeScriptGenerator(internalOptions);
1718
+ const customHeader = generateCustomFileHeader(this.options.fileHeader);
1719
+ const header = generateFileHeader({
1720
+ packageName: "@cerios/openapi-to-zod",
1721
+ apiTitle: (_b = this.spec.info) == null ? void 0 : _b.title,
1722
+ apiVersion: (_c = this.spec.info) == null ? void 0 : _c.version
1659
1723
  });
1660
- return tsGenerator.generateString();
1724
+ return customHeader + header + tsGenerator.generateString();
1661
1725
  }
1662
1726
  /**
1663
1727
  * Add explicit type annotation to a schema declaration
@@ -1976,14 +2040,16 @@ ${typeCode}`;
1976
2040
  stripSchemaPrefix: this.options.stripSchemaPrefix,
1977
2041
  dateTimeValidation: this.dateTimeValidation,
1978
2042
  patternCache: this.patternCache,
1979
- separateTypesFile: this.separateSchemasMode
2043
+ separateTypesFile: this.separateSchemasMode,
2044
+ warn: (msg) => {
2045
+ this.warningCollector.add(msg);
2046
+ }
1980
2047
  });
1981
2048
  this.propertyGenerator.setCircularDependencies(this.circularDependencies);
1982
2049
  this.propertyGenerator.clearAllOfConflicts();
1983
2050
  const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, true);
1984
2051
  const allOfConflicts = this.propertyGenerator.getAllOfConflicts();
1985
2052
  if (allOfConflicts.length > 0) {
1986
- this.allOfConflictCount += allOfConflicts.length;
1987
2053
  const conflictWarning = this.generateConflictJSDoc(allOfConflicts);
1988
2054
  if (jsdoc) {
1989
2055
  jsdoc = jsdoc.replace(/ \*\/\n$/, `
@@ -2347,8 +2413,7 @@ ${propsCode}
2347
2413
  `// Total schemas: ${stats.totalSchemas}`,
2348
2414
  `// Circular references: ${stats.withCircularRefs}`,
2349
2415
  `// Discriminated unions: ${stats.withDiscriminators}`,
2350
- `// With constraints: ${stats.withConstraints}`,
2351
- `// AllOf conflicts: ${this.allOfConflictCount}`
2416
+ `// With constraints: ${stats.withConstraints}`
2352
2417
  ];
2353
2418
  if (this.options.operationFilters && this.filterStats.totalOperations > 0) {
2354
2419
  output.push("//");