@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/README.md +49 -0
- package/dist/cli.js +89 -26
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +93 -27
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +21 -4
- package/dist/index.d.ts +21 -4
- package/dist/index.js +88 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +92 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
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
|
-
|
|
100
|
-
|
|
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
|
-
|
|
122
|
-
|
|
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
|
-
|
|
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 = [
|
|
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 = [
|
|
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
|
|
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("//");
|