@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 +268 -10
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +275 -11
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +150 -1
- package/dist/index.d.ts +150 -1
- package/dist/index.js +247 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +242 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -1252,6 +1252,140 @@ _PropertyGenerator.INCLUSION_RULES = {
|
|
|
1252
1252
|
};
|
|
1253
1253
|
var PropertyGenerator = _PropertyGenerator;
|
|
1254
1254
|
|
|
1255
|
+
// src/utils/operation-filters.ts
|
|
1256
|
+
import { minimatch } from "minimatch";
|
|
1257
|
+
function createFilterStatistics() {
|
|
1258
|
+
return {
|
|
1259
|
+
totalOperations: 0,
|
|
1260
|
+
includedOperations: 0,
|
|
1261
|
+
filteredByTags: 0,
|
|
1262
|
+
filteredByPaths: 0,
|
|
1263
|
+
filteredByMethods: 0,
|
|
1264
|
+
filteredByOperationIds: 0,
|
|
1265
|
+
filteredByDeprecated: 0
|
|
1266
|
+
};
|
|
1267
|
+
}
|
|
1268
|
+
function matchesAnyPattern(value, patterns) {
|
|
1269
|
+
if (!patterns || patterns.length === 0) {
|
|
1270
|
+
return false;
|
|
1271
|
+
}
|
|
1272
|
+
if (!value) {
|
|
1273
|
+
return false;
|
|
1274
|
+
}
|
|
1275
|
+
return patterns.some((pattern) => minimatch(value, pattern));
|
|
1276
|
+
}
|
|
1277
|
+
function containsAny(arr, values) {
|
|
1278
|
+
if (!values || values.length === 0) {
|
|
1279
|
+
return false;
|
|
1280
|
+
}
|
|
1281
|
+
if (!arr || arr.length === 0) {
|
|
1282
|
+
return false;
|
|
1283
|
+
}
|
|
1284
|
+
return values.some((value) => arr.includes(value));
|
|
1285
|
+
}
|
|
1286
|
+
function shouldIncludeOperation(operation, path, method, filters, stats) {
|
|
1287
|
+
if (!filters) {
|
|
1288
|
+
return true;
|
|
1289
|
+
}
|
|
1290
|
+
const methodLower = method.toLowerCase();
|
|
1291
|
+
const operationId = operation == null ? void 0 : operation.operationId;
|
|
1292
|
+
const tags = (operation == null ? void 0 : operation.tags) || [];
|
|
1293
|
+
const deprecated = (operation == null ? void 0 : operation.deprecated) === true;
|
|
1294
|
+
if (filters.includeTags && filters.includeTags.length > 0) {
|
|
1295
|
+
if (!containsAny(tags, filters.includeTags)) {
|
|
1296
|
+
if (stats) stats.filteredByTags++;
|
|
1297
|
+
return false;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
if (filters.includePaths && filters.includePaths.length > 0) {
|
|
1301
|
+
if (!matchesAnyPattern(path, filters.includePaths)) {
|
|
1302
|
+
if (stats) stats.filteredByPaths++;
|
|
1303
|
+
return false;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
if (filters.includeMethods && filters.includeMethods.length > 0) {
|
|
1307
|
+
const methodsLower = filters.includeMethods.map((m) => m.toLowerCase());
|
|
1308
|
+
if (!methodsLower.includes(methodLower)) {
|
|
1309
|
+
if (stats) stats.filteredByMethods++;
|
|
1310
|
+
return false;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
if (filters.includeOperationIds && filters.includeOperationIds.length > 0) {
|
|
1314
|
+
if (!matchesAnyPattern(operationId, filters.includeOperationIds)) {
|
|
1315
|
+
if (stats) stats.filteredByOperationIds++;
|
|
1316
|
+
return false;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
if (filters.excludeDeprecated === true && deprecated) {
|
|
1320
|
+
if (stats) stats.filteredByDeprecated++;
|
|
1321
|
+
return false;
|
|
1322
|
+
}
|
|
1323
|
+
if (filters.excludeTags && filters.excludeTags.length > 0) {
|
|
1324
|
+
if (containsAny(tags, filters.excludeTags)) {
|
|
1325
|
+
if (stats) stats.filteredByTags++;
|
|
1326
|
+
return false;
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
if (filters.excludePaths && filters.excludePaths.length > 0) {
|
|
1330
|
+
if (matchesAnyPattern(path, filters.excludePaths)) {
|
|
1331
|
+
if (stats) stats.filteredByPaths++;
|
|
1332
|
+
return false;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
if (filters.excludeMethods && filters.excludeMethods.length > 0) {
|
|
1336
|
+
const methodsLower = filters.excludeMethods.map((m) => m.toLowerCase());
|
|
1337
|
+
if (methodsLower.includes(methodLower)) {
|
|
1338
|
+
if (stats) stats.filteredByMethods++;
|
|
1339
|
+
return false;
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
if (filters.excludeOperationIds && filters.excludeOperationIds.length > 0) {
|
|
1343
|
+
if (matchesAnyPattern(operationId, filters.excludeOperationIds)) {
|
|
1344
|
+
if (stats) stats.filteredByOperationIds++;
|
|
1345
|
+
return false;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
return true;
|
|
1349
|
+
}
|
|
1350
|
+
function validateFilters(stats, filters) {
|
|
1351
|
+
if (!filters || stats.totalOperations === 0) {
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
if (stats.includedOperations === 0) {
|
|
1355
|
+
console.warn(
|
|
1356
|
+
`\u26A0\uFE0F Warning: All ${stats.totalOperations} operations were filtered out. Check your operationFilters configuration.`
|
|
1357
|
+
);
|
|
1358
|
+
const filterBreakdown = [];
|
|
1359
|
+
if (stats.filteredByTags > 0) filterBreakdown.push(`${stats.filteredByTags} by tags`);
|
|
1360
|
+
if (stats.filteredByPaths > 0) filterBreakdown.push(`${stats.filteredByPaths} by paths`);
|
|
1361
|
+
if (stats.filteredByMethods > 0) filterBreakdown.push(`${stats.filteredByMethods} by methods`);
|
|
1362
|
+
if (stats.filteredByOperationIds > 0) filterBreakdown.push(`${stats.filteredByOperationIds} by operationIds`);
|
|
1363
|
+
if (stats.filteredByDeprecated > 0) filterBreakdown.push(`${stats.filteredByDeprecated} by deprecated flag`);
|
|
1364
|
+
if (filterBreakdown.length > 0) {
|
|
1365
|
+
console.warn(` Filtered: ${filterBreakdown.join(", ")}`);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
function formatFilterStatistics(stats) {
|
|
1370
|
+
if (stats.totalOperations === 0) {
|
|
1371
|
+
return "";
|
|
1372
|
+
}
|
|
1373
|
+
const lines = [];
|
|
1374
|
+
lines.push("Operation Filtering:");
|
|
1375
|
+
lines.push(` Total operations: ${stats.totalOperations}`);
|
|
1376
|
+
lines.push(` Included operations: ${stats.includedOperations}`);
|
|
1377
|
+
const filteredCount = stats.filteredByTags + stats.filteredByPaths + stats.filteredByMethods + stats.filteredByOperationIds + stats.filteredByDeprecated;
|
|
1378
|
+
if (filteredCount > 0) {
|
|
1379
|
+
lines.push(` Filtered operations: ${filteredCount}`);
|
|
1380
|
+
if (stats.filteredByTags > 0) lines.push(` - By tags: ${stats.filteredByTags}`);
|
|
1381
|
+
if (stats.filteredByPaths > 0) lines.push(` - By paths: ${stats.filteredByPaths}`);
|
|
1382
|
+
if (stats.filteredByMethods > 0) lines.push(` - By methods: ${stats.filteredByMethods}`);
|
|
1383
|
+
if (stats.filteredByOperationIds > 0) lines.push(` - By operationIds: ${stats.filteredByOperationIds}`);
|
|
1384
|
+
if (stats.filteredByDeprecated > 0) lines.push(` - By deprecated: ${stats.filteredByDeprecated}`);
|
|
1385
|
+
}
|
|
1386
|
+
return lines.join("\n");
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1255
1389
|
// src/openapi-generator.ts
|
|
1256
1390
|
var OpenApiGenerator = class {
|
|
1257
1391
|
constructor(options) {
|
|
@@ -1263,6 +1397,7 @@ var OpenApiGenerator = class {
|
|
|
1263
1397
|
this.schemaUsageMap = /* @__PURE__ */ new Map();
|
|
1264
1398
|
this.schemaTypeModeMap = /* @__PURE__ */ new Map();
|
|
1265
1399
|
this.needsZodImport = false;
|
|
1400
|
+
this.filterStats = createFilterStatistics();
|
|
1266
1401
|
var _a, _b, _c;
|
|
1267
1402
|
if (!options.input) {
|
|
1268
1403
|
throw new ConfigurationError("Input path is required", { providedOptions: options });
|
|
@@ -1280,7 +1415,8 @@ var OpenApiGenerator = class {
|
|
|
1280
1415
|
showStats: (_c = options.showStats) != null ? _c : true,
|
|
1281
1416
|
nativeEnumType: options.nativeEnumType || "union",
|
|
1282
1417
|
request: options.request,
|
|
1283
|
-
response: options.response
|
|
1418
|
+
response: options.response,
|
|
1419
|
+
operationFilters: options.operationFilters
|
|
1284
1420
|
};
|
|
1285
1421
|
try {
|
|
1286
1422
|
const fs = __require("fs");
|
|
@@ -1385,6 +1521,8 @@ var OpenApiGenerator = class {
|
|
|
1385
1521
|
this.generateComponentSchema(name, schema);
|
|
1386
1522
|
}
|
|
1387
1523
|
this.generateQueryParameterSchemas();
|
|
1524
|
+
this.generateHeaderParameterSchemas();
|
|
1525
|
+
validateFilters(this.filterStats, this.options.operationFilters);
|
|
1388
1526
|
const orderedSchemaNames = this.topologicalSort();
|
|
1389
1527
|
const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
|
|
1390
1528
|
if (this.options.showStats === true) {
|
|
@@ -1478,9 +1616,16 @@ var OpenApiGenerator = class {
|
|
|
1478
1616
|
const requestSchemas = /* @__PURE__ */ new Set();
|
|
1479
1617
|
const responseSchemas = /* @__PURE__ */ new Set();
|
|
1480
1618
|
if (this.spec.paths) {
|
|
1481
|
-
for (const [, pathItem] of Object.entries(this.spec.paths)) {
|
|
1482
|
-
|
|
1619
|
+
for (const [path, pathItem] of Object.entries(this.spec.paths)) {
|
|
1620
|
+
const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
1621
|
+
for (const method of methods) {
|
|
1622
|
+
const operation = pathItem[method];
|
|
1483
1623
|
if (typeof operation !== "object" || !operation) continue;
|
|
1624
|
+
this.filterStats.totalOperations++;
|
|
1625
|
+
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters, this.filterStats)) {
|
|
1626
|
+
continue;
|
|
1627
|
+
}
|
|
1628
|
+
this.filterStats.includedOperations++;
|
|
1484
1629
|
if ("requestBody" in operation && operation.requestBody && typeof operation.requestBody === "object" && "content" in operation.requestBody && operation.requestBody.content) {
|
|
1485
1630
|
for (const mediaType of Object.values(operation.requestBody.content)) {
|
|
1486
1631
|
if (mediaType && typeof mediaType === "object" && "schema" in mediaType && mediaType.schema) {
|
|
@@ -1830,12 +1975,15 @@ ${typeCode}`;
|
|
|
1830
1975
|
if (!this.spec.paths) {
|
|
1831
1976
|
return;
|
|
1832
1977
|
}
|
|
1833
|
-
for (const [
|
|
1978
|
+
for (const [path, pathItem] of Object.entries(this.spec.paths)) {
|
|
1834
1979
|
if (!pathItem || typeof pathItem !== "object") continue;
|
|
1835
1980
|
const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
1836
1981
|
for (const method of methods) {
|
|
1837
1982
|
const operation = pathItem[method];
|
|
1838
1983
|
if (!operation) continue;
|
|
1984
|
+
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
|
|
1985
|
+
continue;
|
|
1986
|
+
}
|
|
1839
1987
|
if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
|
|
1840
1988
|
continue;
|
|
1841
1989
|
}
|
|
@@ -1896,6 +2044,80 @@ ${propsCode}
|
|
|
1896
2044
|
const jsdoc = `/**
|
|
1897
2045
|
* Query parameters for ${operation.operationId}
|
|
1898
2046
|
*/
|
|
2047
|
+
`;
|
|
2048
|
+
const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
|
|
2049
|
+
this.schemas.set(schemaName, fullSchemaCode);
|
|
2050
|
+
this.needsZodImport = true;
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
/**
|
|
2055
|
+
* Generate header parameter schemas for each operation
|
|
2056
|
+
* Header parameters are always string type (HTTP header semantics)
|
|
2057
|
+
*/
|
|
2058
|
+
generateHeaderParameterSchemas() {
|
|
2059
|
+
var _a;
|
|
2060
|
+
if (!this.spec.paths) {
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
2063
|
+
for (const [path, pathItem] of Object.entries(this.spec.paths)) {
|
|
2064
|
+
if (!pathItem || typeof pathItem !== "object") continue;
|
|
2065
|
+
const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
2066
|
+
for (const method of methods) {
|
|
2067
|
+
const operation = pathItem[method];
|
|
2068
|
+
if (!operation) continue;
|
|
2069
|
+
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
|
|
2070
|
+
continue;
|
|
2071
|
+
}
|
|
2072
|
+
if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
|
|
2073
|
+
continue;
|
|
2074
|
+
}
|
|
2075
|
+
const headerParams = operation.parameters.filter(
|
|
2076
|
+
(param) => param && typeof param === "object" && param.in === "header"
|
|
2077
|
+
);
|
|
2078
|
+
if (headerParams.length === 0) {
|
|
2079
|
+
continue;
|
|
2080
|
+
}
|
|
2081
|
+
const pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
|
|
2082
|
+
const schemaName = `${pascalOperationId}HeaderParams`;
|
|
2083
|
+
if (!this.schemaDependencies.has(schemaName)) {
|
|
2084
|
+
this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
|
|
2085
|
+
}
|
|
2086
|
+
const properties = {};
|
|
2087
|
+
for (const param of headerParams) {
|
|
2088
|
+
const paramName = param.name;
|
|
2089
|
+
const paramSchema = param.schema;
|
|
2090
|
+
if (!paramSchema) continue;
|
|
2091
|
+
let zodType = "z.string()";
|
|
2092
|
+
if (param.description && this.requestOptions.includeDescriptions) {
|
|
2093
|
+
if (this.requestOptions.useDescribe) {
|
|
2094
|
+
zodType = `${zodType}.describe(${JSON.stringify(param.description)})`;
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
zodType = `${zodType}.optional()`;
|
|
2098
|
+
properties[paramName] = zodType;
|
|
2099
|
+
if (paramSchema.$ref) {
|
|
2100
|
+
const refName = resolveRef(paramSchema.$ref);
|
|
2101
|
+
(_a = this.schemaDependencies.get(schemaName)) == null ? void 0 : _a.add(refName);
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
const objectMode = this.requestOptions.mode;
|
|
2105
|
+
const zodMethod = objectMode === "strict" ? "strictObject" : objectMode === "loose" ? "looseObject" : "object";
|
|
2106
|
+
const propsCode = Object.entries(properties).map(([key, value]) => {
|
|
2107
|
+
const needsQuotes = !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key);
|
|
2108
|
+
const quotedKey = needsQuotes ? `"${key}"` : key;
|
|
2109
|
+
return ` ${quotedKey}: ${value}`;
|
|
2110
|
+
}).join(",\n");
|
|
2111
|
+
const schemaCode = `z.${zodMethod}({
|
|
2112
|
+
${propsCode}
|
|
2113
|
+
})`;
|
|
2114
|
+
const operationName = pascalOperationId;
|
|
2115
|
+
const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
|
|
2116
|
+
const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
|
|
2117
|
+
const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}HeaderParamsSchema`;
|
|
2118
|
+
const jsdoc = `/**
|
|
2119
|
+
* Header parameters for ${operation.operationId}
|
|
2120
|
+
*/
|
|
1899
2121
|
`;
|
|
1900
2122
|
const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
|
|
1901
2123
|
this.schemas.set(schemaName, fullSchemaCode);
|
|
@@ -2173,15 +2395,23 @@ ${props.join("\n")}
|
|
|
2173
2395
|
stats.withConstraints++;
|
|
2174
2396
|
}
|
|
2175
2397
|
}
|
|
2176
|
-
|
|
2398
|
+
const output = [
|
|
2177
2399
|
"// Generation Statistics:",
|
|
2178
2400
|
`// Total schemas: ${stats.totalSchemas}`,
|
|
2179
2401
|
`// Enums: ${stats.enums}`,
|
|
2180
2402
|
`// Circular references: ${stats.withCircularRefs}`,
|
|
2181
2403
|
`// Discriminated unions: ${stats.withDiscriminators}`,
|
|
2182
|
-
`// With constraints: ${stats.withConstraints}
|
|
2183
|
-
`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`
|
|
2404
|
+
`// With constraints: ${stats.withConstraints}`
|
|
2184
2405
|
];
|
|
2406
|
+
if (this.options.operationFilters && this.filterStats.totalOperations > 0) {
|
|
2407
|
+
output.push("//");
|
|
2408
|
+
const filterStatsStr = formatFilterStatistics(this.filterStats);
|
|
2409
|
+
for (const line of filterStatsStr.split("\n")) {
|
|
2410
|
+
output.push(`// ${line}`);
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
output.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
2414
|
+
return output;
|
|
2185
2415
|
}
|
|
2186
2416
|
};
|
|
2187
2417
|
|
|
@@ -2198,6 +2428,10 @@ export {
|
|
|
2198
2428
|
OpenApiGenerator,
|
|
2199
2429
|
SchemaGenerationError,
|
|
2200
2430
|
SpecValidationError,
|
|
2201
|
-
|
|
2431
|
+
createFilterStatistics,
|
|
2432
|
+
defineConfig,
|
|
2433
|
+
formatFilterStatistics,
|
|
2434
|
+
shouldIncludeOperation,
|
|
2435
|
+
validateFilters
|
|
2202
2436
|
};
|
|
2203
2437
|
//# sourceMappingURL=index.mjs.map
|