@cerios/openapi-to-zod 0.3.0 → 0.5.0
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 +2 -2
- package/dist/cli.js +397 -33
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +408 -38
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +155 -6
- package/dist/index.d.ts +155 -6
- package/dist/index.js +283 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +277 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/cli.mjs
CHANGED
|
@@ -6291,13 +6291,153 @@ var init_property_generator = __esm({
|
|
|
6291
6291
|
}
|
|
6292
6292
|
});
|
|
6293
6293
|
|
|
6294
|
-
// src/
|
|
6294
|
+
// src/utils/operation-filters.ts
|
|
6295
|
+
import { minimatch } from "minimatch";
|
|
6296
|
+
function createFilterStatistics() {
|
|
6297
|
+
return {
|
|
6298
|
+
totalOperations: 0,
|
|
6299
|
+
includedOperations: 0,
|
|
6300
|
+
filteredByTags: 0,
|
|
6301
|
+
filteredByPaths: 0,
|
|
6302
|
+
filteredByMethods: 0,
|
|
6303
|
+
filteredByOperationIds: 0,
|
|
6304
|
+
filteredByDeprecated: 0
|
|
6305
|
+
};
|
|
6306
|
+
}
|
|
6307
|
+
function matchesAnyPattern(value, patterns) {
|
|
6308
|
+
if (!patterns || patterns.length === 0) {
|
|
6309
|
+
return false;
|
|
6310
|
+
}
|
|
6311
|
+
if (!value) {
|
|
6312
|
+
return false;
|
|
6313
|
+
}
|
|
6314
|
+
return patterns.some((pattern) => minimatch(value, pattern));
|
|
6315
|
+
}
|
|
6316
|
+
function containsAny(arr, values) {
|
|
6317
|
+
if (!values || values.length === 0) {
|
|
6318
|
+
return false;
|
|
6319
|
+
}
|
|
6320
|
+
if (!arr || arr.length === 0) {
|
|
6321
|
+
return false;
|
|
6322
|
+
}
|
|
6323
|
+
return values.some((value) => arr.includes(value));
|
|
6324
|
+
}
|
|
6325
|
+
function shouldIncludeOperation(operation, path2, method, filters, stats) {
|
|
6326
|
+
if (!filters) {
|
|
6327
|
+
return true;
|
|
6328
|
+
}
|
|
6329
|
+
const methodLower = method.toLowerCase();
|
|
6330
|
+
const operationId = operation == null ? void 0 : operation.operationId;
|
|
6331
|
+
const tags = (operation == null ? void 0 : operation.tags) || [];
|
|
6332
|
+
const deprecated = (operation == null ? void 0 : operation.deprecated) === true;
|
|
6333
|
+
if (filters.includeTags && filters.includeTags.length > 0) {
|
|
6334
|
+
if (!containsAny(tags, filters.includeTags)) {
|
|
6335
|
+
if (stats) stats.filteredByTags++;
|
|
6336
|
+
return false;
|
|
6337
|
+
}
|
|
6338
|
+
}
|
|
6339
|
+
if (filters.includePaths && filters.includePaths.length > 0) {
|
|
6340
|
+
if (!matchesAnyPattern(path2, filters.includePaths)) {
|
|
6341
|
+
if (stats) stats.filteredByPaths++;
|
|
6342
|
+
return false;
|
|
6343
|
+
}
|
|
6344
|
+
}
|
|
6345
|
+
if (filters.includeMethods && filters.includeMethods.length > 0) {
|
|
6346
|
+
const methodsLower = filters.includeMethods.map((m) => m.toLowerCase());
|
|
6347
|
+
if (!methodsLower.includes(methodLower)) {
|
|
6348
|
+
if (stats) stats.filteredByMethods++;
|
|
6349
|
+
return false;
|
|
6350
|
+
}
|
|
6351
|
+
}
|
|
6352
|
+
if (filters.includeOperationIds && filters.includeOperationIds.length > 0) {
|
|
6353
|
+
if (!matchesAnyPattern(operationId, filters.includeOperationIds)) {
|
|
6354
|
+
if (stats) stats.filteredByOperationIds++;
|
|
6355
|
+
return false;
|
|
6356
|
+
}
|
|
6357
|
+
}
|
|
6358
|
+
if (filters.excludeDeprecated === true && deprecated) {
|
|
6359
|
+
if (stats) stats.filteredByDeprecated++;
|
|
6360
|
+
return false;
|
|
6361
|
+
}
|
|
6362
|
+
if (filters.excludeTags && filters.excludeTags.length > 0) {
|
|
6363
|
+
if (containsAny(tags, filters.excludeTags)) {
|
|
6364
|
+
if (stats) stats.filteredByTags++;
|
|
6365
|
+
return false;
|
|
6366
|
+
}
|
|
6367
|
+
}
|
|
6368
|
+
if (filters.excludePaths && filters.excludePaths.length > 0) {
|
|
6369
|
+
if (matchesAnyPattern(path2, filters.excludePaths)) {
|
|
6370
|
+
if (stats) stats.filteredByPaths++;
|
|
6371
|
+
return false;
|
|
6372
|
+
}
|
|
6373
|
+
}
|
|
6374
|
+
if (filters.excludeMethods && filters.excludeMethods.length > 0) {
|
|
6375
|
+
const methodsLower = filters.excludeMethods.map((m) => m.toLowerCase());
|
|
6376
|
+
if (methodsLower.includes(methodLower)) {
|
|
6377
|
+
if (stats) stats.filteredByMethods++;
|
|
6378
|
+
return false;
|
|
6379
|
+
}
|
|
6380
|
+
}
|
|
6381
|
+
if (filters.excludeOperationIds && filters.excludeOperationIds.length > 0) {
|
|
6382
|
+
if (matchesAnyPattern(operationId, filters.excludeOperationIds)) {
|
|
6383
|
+
if (stats) stats.filteredByOperationIds++;
|
|
6384
|
+
return false;
|
|
6385
|
+
}
|
|
6386
|
+
}
|
|
6387
|
+
return true;
|
|
6388
|
+
}
|
|
6389
|
+
function validateFilters(stats, filters) {
|
|
6390
|
+
if (!filters || stats.totalOperations === 0) {
|
|
6391
|
+
return;
|
|
6392
|
+
}
|
|
6393
|
+
if (stats.includedOperations === 0) {
|
|
6394
|
+
console.warn(
|
|
6395
|
+
`\u26A0\uFE0F Warning: All ${stats.totalOperations} operations were filtered out. Check your operationFilters configuration.`
|
|
6396
|
+
);
|
|
6397
|
+
const filterBreakdown = [];
|
|
6398
|
+
if (stats.filteredByTags > 0) filterBreakdown.push(`${stats.filteredByTags} by tags`);
|
|
6399
|
+
if (stats.filteredByPaths > 0) filterBreakdown.push(`${stats.filteredByPaths} by paths`);
|
|
6400
|
+
if (stats.filteredByMethods > 0) filterBreakdown.push(`${stats.filteredByMethods} by methods`);
|
|
6401
|
+
if (stats.filteredByOperationIds > 0) filterBreakdown.push(`${stats.filteredByOperationIds} by operationIds`);
|
|
6402
|
+
if (stats.filteredByDeprecated > 0) filterBreakdown.push(`${stats.filteredByDeprecated} by deprecated flag`);
|
|
6403
|
+
if (filterBreakdown.length > 0) {
|
|
6404
|
+
console.warn(` Filtered: ${filterBreakdown.join(", ")}`);
|
|
6405
|
+
}
|
|
6406
|
+
}
|
|
6407
|
+
}
|
|
6408
|
+
function formatFilterStatistics(stats) {
|
|
6409
|
+
if (stats.totalOperations === 0) {
|
|
6410
|
+
return "";
|
|
6411
|
+
}
|
|
6412
|
+
const lines = [];
|
|
6413
|
+
lines.push("Operation Filtering:");
|
|
6414
|
+
lines.push(` Total operations: ${stats.totalOperations}`);
|
|
6415
|
+
lines.push(` Included operations: ${stats.includedOperations}`);
|
|
6416
|
+
const filteredCount = stats.filteredByTags + stats.filteredByPaths + stats.filteredByMethods + stats.filteredByOperationIds + stats.filteredByDeprecated;
|
|
6417
|
+
if (filteredCount > 0) {
|
|
6418
|
+
lines.push(` Filtered operations: ${filteredCount}`);
|
|
6419
|
+
if (stats.filteredByTags > 0) lines.push(` - By tags: ${stats.filteredByTags}`);
|
|
6420
|
+
if (stats.filteredByPaths > 0) lines.push(` - By paths: ${stats.filteredByPaths}`);
|
|
6421
|
+
if (stats.filteredByMethods > 0) lines.push(` - By methods: ${stats.filteredByMethods}`);
|
|
6422
|
+
if (stats.filteredByOperationIds > 0) lines.push(` - By operationIds: ${stats.filteredByOperationIds}`);
|
|
6423
|
+
if (stats.filteredByDeprecated > 0) lines.push(` - By deprecated: ${stats.filteredByDeprecated}`);
|
|
6424
|
+
}
|
|
6425
|
+
return lines.join("\n");
|
|
6426
|
+
}
|
|
6427
|
+
var init_operation_filters = __esm({
|
|
6428
|
+
"src/utils/operation-filters.ts"() {
|
|
6429
|
+
"use strict";
|
|
6430
|
+
init_esm_shims();
|
|
6431
|
+
}
|
|
6432
|
+
});
|
|
6433
|
+
|
|
6434
|
+
// src/openapi-generator.ts
|
|
6295
6435
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
6296
6436
|
import { dirname, normalize } from "path";
|
|
6297
6437
|
import { parse } from "yaml";
|
|
6298
|
-
var
|
|
6299
|
-
var
|
|
6300
|
-
"src/generator.ts"() {
|
|
6438
|
+
var OpenApiGenerator;
|
|
6439
|
+
var init_openapi_generator = __esm({
|
|
6440
|
+
"src/openapi-generator.ts"() {
|
|
6301
6441
|
"use strict";
|
|
6302
6442
|
init_esm_shims();
|
|
6303
6443
|
init_errors();
|
|
@@ -6305,7 +6445,8 @@ var init_generator = __esm({
|
|
|
6305
6445
|
init_jsdoc_generator();
|
|
6306
6446
|
init_property_generator();
|
|
6307
6447
|
init_name_utils();
|
|
6308
|
-
|
|
6448
|
+
init_operation_filters();
|
|
6449
|
+
OpenApiGenerator = class {
|
|
6309
6450
|
constructor(options) {
|
|
6310
6451
|
this.schemas = /* @__PURE__ */ new Map();
|
|
6311
6452
|
this.types = /* @__PURE__ */ new Map();
|
|
@@ -6315,6 +6456,7 @@ var init_generator = __esm({
|
|
|
6315
6456
|
this.schemaUsageMap = /* @__PURE__ */ new Map();
|
|
6316
6457
|
this.schemaTypeModeMap = /* @__PURE__ */ new Map();
|
|
6317
6458
|
this.needsZodImport = false;
|
|
6459
|
+
this.filterStats = createFilterStatistics();
|
|
6318
6460
|
var _a, _b, _c;
|
|
6319
6461
|
if (!options.input) {
|
|
6320
6462
|
throw new ConfigurationError("Input path is required", { providedOptions: options });
|
|
@@ -6332,7 +6474,8 @@ var init_generator = __esm({
|
|
|
6332
6474
|
showStats: (_c = options.showStats) != null ? _c : true,
|
|
6333
6475
|
nativeEnumType: options.nativeEnumType || "union",
|
|
6334
6476
|
request: options.request,
|
|
6335
|
-
response: options.response
|
|
6477
|
+
response: options.response,
|
|
6478
|
+
operationFilters: options.operationFilters
|
|
6336
6479
|
};
|
|
6337
6480
|
try {
|
|
6338
6481
|
const fs = __require("fs");
|
|
@@ -6345,19 +6488,41 @@ var init_generator = __esm({
|
|
|
6345
6488
|
}
|
|
6346
6489
|
}
|
|
6347
6490
|
try {
|
|
6348
|
-
const
|
|
6349
|
-
|
|
6491
|
+
const content = readFileSync(this.options.input, "utf-8");
|
|
6492
|
+
try {
|
|
6493
|
+
this.spec = parse(content);
|
|
6494
|
+
} catch (yamlError) {
|
|
6495
|
+
try {
|
|
6496
|
+
this.spec = JSON.parse(content);
|
|
6497
|
+
} catch {
|
|
6498
|
+
if (yamlError instanceof Error) {
|
|
6499
|
+
const errorMessage = [
|
|
6500
|
+
`Failed to parse OpenAPI specification from: ${this.options.input}`,
|
|
6501
|
+
"",
|
|
6502
|
+
`Error: ${yamlError.message}`,
|
|
6503
|
+
"",
|
|
6504
|
+
"Please ensure:",
|
|
6505
|
+
" - The file exists and is readable",
|
|
6506
|
+
" - The file contains valid YAML or JSON syntax",
|
|
6507
|
+
" - The file is a valid OpenAPI 3.x specification"
|
|
6508
|
+
].join("\n");
|
|
6509
|
+
throw new SpecValidationError(errorMessage, {
|
|
6510
|
+
filePath: this.options.input,
|
|
6511
|
+
originalError: yamlError.message
|
|
6512
|
+
});
|
|
6513
|
+
}
|
|
6514
|
+
throw yamlError;
|
|
6515
|
+
}
|
|
6516
|
+
}
|
|
6350
6517
|
} catch (error) {
|
|
6518
|
+
if (error instanceof SpecValidationError) {
|
|
6519
|
+
throw error;
|
|
6520
|
+
}
|
|
6351
6521
|
if (error instanceof Error) {
|
|
6352
6522
|
const errorMessage = [
|
|
6353
|
-
`Failed to
|
|
6354
|
-
"",
|
|
6355
|
-
`Error: ${error.message}`,
|
|
6523
|
+
`Failed to read OpenAPI specification from: ${this.options.input}`,
|
|
6356
6524
|
"",
|
|
6357
|
-
|
|
6358
|
-
" - The file exists and is readable",
|
|
6359
|
-
" - The file contains valid YAML syntax",
|
|
6360
|
-
" - The file is a valid OpenAPI 3.x specification"
|
|
6525
|
+
`Error: ${error.message}`
|
|
6361
6526
|
].join("\n");
|
|
6362
6527
|
throw new SpecValidationError(errorMessage, { filePath: this.options.input, originalError: error.message });
|
|
6363
6528
|
}
|
|
@@ -6415,6 +6580,8 @@ var init_generator = __esm({
|
|
|
6415
6580
|
this.generateComponentSchema(name, schema);
|
|
6416
6581
|
}
|
|
6417
6582
|
this.generateQueryParameterSchemas();
|
|
6583
|
+
this.generateHeaderParameterSchemas();
|
|
6584
|
+
validateFilters(this.filterStats, this.options.operationFilters);
|
|
6418
6585
|
const orderedSchemaNames = this.topologicalSort();
|
|
6419
6586
|
const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
|
|
6420
6587
|
if (this.options.showStats === true) {
|
|
@@ -6508,9 +6675,16 @@ var init_generator = __esm({
|
|
|
6508
6675
|
const requestSchemas = /* @__PURE__ */ new Set();
|
|
6509
6676
|
const responseSchemas = /* @__PURE__ */ new Set();
|
|
6510
6677
|
if (this.spec.paths) {
|
|
6511
|
-
for (const [, pathItem] of Object.entries(this.spec.paths)) {
|
|
6512
|
-
|
|
6678
|
+
for (const [path2, pathItem] of Object.entries(this.spec.paths)) {
|
|
6679
|
+
const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
6680
|
+
for (const method of methods) {
|
|
6681
|
+
const operation = pathItem[method];
|
|
6513
6682
|
if (typeof operation !== "object" || !operation) continue;
|
|
6683
|
+
this.filterStats.totalOperations++;
|
|
6684
|
+
if (!shouldIncludeOperation(operation, path2, method, this.options.operationFilters, this.filterStats)) {
|
|
6685
|
+
continue;
|
|
6686
|
+
}
|
|
6687
|
+
this.filterStats.includedOperations++;
|
|
6514
6688
|
if ("requestBody" in operation && operation.requestBody && typeof operation.requestBody === "object" && "content" in operation.requestBody && operation.requestBody.content) {
|
|
6515
6689
|
for (const mediaType of Object.values(operation.requestBody.content)) {
|
|
6516
6690
|
if (mediaType && typeof mediaType === "object" && "schema" in mediaType && mediaType.schema) {
|
|
@@ -6860,12 +7034,15 @@ ${typeCode}`;
|
|
|
6860
7034
|
if (!this.spec.paths) {
|
|
6861
7035
|
return;
|
|
6862
7036
|
}
|
|
6863
|
-
for (const [
|
|
7037
|
+
for (const [path2, pathItem] of Object.entries(this.spec.paths)) {
|
|
6864
7038
|
if (!pathItem || typeof pathItem !== "object") continue;
|
|
6865
7039
|
const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
6866
7040
|
for (const method of methods) {
|
|
6867
7041
|
const operation = pathItem[method];
|
|
6868
7042
|
if (!operation) continue;
|
|
7043
|
+
if (!shouldIncludeOperation(operation, path2, method, this.options.operationFilters)) {
|
|
7044
|
+
continue;
|
|
7045
|
+
}
|
|
6869
7046
|
if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
|
|
6870
7047
|
continue;
|
|
6871
7048
|
}
|
|
@@ -6926,6 +7103,80 @@ ${propsCode}
|
|
|
6926
7103
|
const jsdoc = `/**
|
|
6927
7104
|
* Query parameters for ${operation.operationId}
|
|
6928
7105
|
*/
|
|
7106
|
+
`;
|
|
7107
|
+
const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
|
|
7108
|
+
this.schemas.set(schemaName, fullSchemaCode);
|
|
7109
|
+
this.needsZodImport = true;
|
|
7110
|
+
}
|
|
7111
|
+
}
|
|
7112
|
+
}
|
|
7113
|
+
/**
|
|
7114
|
+
* Generate header parameter schemas for each operation
|
|
7115
|
+
* Header parameters are always string type (HTTP header semantics)
|
|
7116
|
+
*/
|
|
7117
|
+
generateHeaderParameterSchemas() {
|
|
7118
|
+
var _a;
|
|
7119
|
+
if (!this.spec.paths) {
|
|
7120
|
+
return;
|
|
7121
|
+
}
|
|
7122
|
+
for (const [path2, pathItem] of Object.entries(this.spec.paths)) {
|
|
7123
|
+
if (!pathItem || typeof pathItem !== "object") continue;
|
|
7124
|
+
const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
7125
|
+
for (const method of methods) {
|
|
7126
|
+
const operation = pathItem[method];
|
|
7127
|
+
if (!operation) continue;
|
|
7128
|
+
if (!shouldIncludeOperation(operation, path2, method, this.options.operationFilters)) {
|
|
7129
|
+
continue;
|
|
7130
|
+
}
|
|
7131
|
+
if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
|
|
7132
|
+
continue;
|
|
7133
|
+
}
|
|
7134
|
+
const headerParams = operation.parameters.filter(
|
|
7135
|
+
(param) => param && typeof param === "object" && param.in === "header"
|
|
7136
|
+
);
|
|
7137
|
+
if (headerParams.length === 0) {
|
|
7138
|
+
continue;
|
|
7139
|
+
}
|
|
7140
|
+
const pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
|
|
7141
|
+
const schemaName = `${pascalOperationId}HeaderParams`;
|
|
7142
|
+
if (!this.schemaDependencies.has(schemaName)) {
|
|
7143
|
+
this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
|
|
7144
|
+
}
|
|
7145
|
+
const properties = {};
|
|
7146
|
+
for (const param of headerParams) {
|
|
7147
|
+
const paramName = param.name;
|
|
7148
|
+
const paramSchema = param.schema;
|
|
7149
|
+
if (!paramSchema) continue;
|
|
7150
|
+
let zodType = "z.string()";
|
|
7151
|
+
if (param.description && this.requestOptions.includeDescriptions) {
|
|
7152
|
+
if (this.requestOptions.useDescribe) {
|
|
7153
|
+
zodType = `${zodType}.describe(${JSON.stringify(param.description)})`;
|
|
7154
|
+
}
|
|
7155
|
+
}
|
|
7156
|
+
zodType = `${zodType}.optional()`;
|
|
7157
|
+
properties[paramName] = zodType;
|
|
7158
|
+
if (paramSchema.$ref) {
|
|
7159
|
+
const refName = resolveRef(paramSchema.$ref);
|
|
7160
|
+
(_a = this.schemaDependencies.get(schemaName)) == null ? void 0 : _a.add(refName);
|
|
7161
|
+
}
|
|
7162
|
+
}
|
|
7163
|
+
const objectMode = this.requestOptions.mode;
|
|
7164
|
+
const zodMethod = objectMode === "strict" ? "strictObject" : objectMode === "loose" ? "looseObject" : "object";
|
|
7165
|
+
const propsCode = Object.entries(properties).map(([key, value]) => {
|
|
7166
|
+
const needsQuotes = !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key);
|
|
7167
|
+
const quotedKey = needsQuotes ? `"${key}"` : key;
|
|
7168
|
+
return ` ${quotedKey}: ${value}`;
|
|
7169
|
+
}).join(",\n");
|
|
7170
|
+
const schemaCode = `z.${zodMethod}({
|
|
7171
|
+
${propsCode}
|
|
7172
|
+
})`;
|
|
7173
|
+
const operationName = pascalOperationId;
|
|
7174
|
+
const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
|
|
7175
|
+
const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
|
|
7176
|
+
const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}HeaderParamsSchema`;
|
|
7177
|
+
const jsdoc = `/**
|
|
7178
|
+
* Header parameters for ${operation.operationId}
|
|
7179
|
+
*/
|
|
6929
7180
|
`;
|
|
6930
7181
|
const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
|
|
6931
7182
|
this.schemas.set(schemaName, fullSchemaCode);
|
|
@@ -7203,15 +7454,23 @@ ${props.join("\n")}
|
|
|
7203
7454
|
stats.withConstraints++;
|
|
7204
7455
|
}
|
|
7205
7456
|
}
|
|
7206
|
-
|
|
7457
|
+
const output = [
|
|
7207
7458
|
"// Generation Statistics:",
|
|
7208
7459
|
`// Total schemas: ${stats.totalSchemas}`,
|
|
7209
7460
|
`// Enums: ${stats.enums}`,
|
|
7210
7461
|
`// Circular references: ${stats.withCircularRefs}`,
|
|
7211
7462
|
`// Discriminated unions: ${stats.withDiscriminators}`,
|
|
7212
|
-
`// With constraints: ${stats.withConstraints}
|
|
7213
|
-
`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`
|
|
7463
|
+
`// With constraints: ${stats.withConstraints}`
|
|
7214
7464
|
];
|
|
7465
|
+
if (this.options.operationFilters && this.filterStats.totalOperations > 0) {
|
|
7466
|
+
output.push("//");
|
|
7467
|
+
const filterStatsStr = formatFilterStatistics(this.filterStats);
|
|
7468
|
+
for (const line of filterStatsStr.split("\n")) {
|
|
7469
|
+
output.push(`// ${line}`);
|
|
7470
|
+
}
|
|
7471
|
+
}
|
|
7472
|
+
output.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
7473
|
+
return output;
|
|
7215
7474
|
}
|
|
7216
7475
|
};
|
|
7217
7476
|
}
|
|
@@ -7221,7 +7480,7 @@ ${props.join("\n")}
|
|
|
7221
7480
|
async function processSpec(spec, index, total) {
|
|
7222
7481
|
console.log(`Processing [${index + 1}/${total}] ${spec.input}...`);
|
|
7223
7482
|
try {
|
|
7224
|
-
const generator = new
|
|
7483
|
+
const generator = new OpenApiGenerator(spec);
|
|
7225
7484
|
generator.generate();
|
|
7226
7485
|
console.log(`\u2713 Successfully generated ${spec.output}`);
|
|
7227
7486
|
return {
|
|
@@ -7322,7 +7581,7 @@ var init_batch_executor = __esm({
|
|
|
7322
7581
|
"use strict";
|
|
7323
7582
|
init_esm_shims();
|
|
7324
7583
|
init_errors();
|
|
7325
|
-
|
|
7584
|
+
init_openapi_generator();
|
|
7326
7585
|
}
|
|
7327
7586
|
});
|
|
7328
7587
|
|
|
@@ -7397,7 +7656,7 @@ function mergeConfigWithDefaults(config) {
|
|
|
7397
7656
|
return merged;
|
|
7398
7657
|
});
|
|
7399
7658
|
}
|
|
7400
|
-
var TypeModeSchema, NativeEnumTypeSchema, RequestResponseOptionsSchema,
|
|
7659
|
+
var TypeModeSchema, NativeEnumTypeSchema, RequestResponseOptionsSchema, OperationFiltersSchema, OpenApiGeneratorOptionsSchema, ConfigFileSchema, createTypeScriptLoader;
|
|
7401
7660
|
var init_config_loader = __esm({
|
|
7402
7661
|
"src/utils/config-loader.ts"() {
|
|
7403
7662
|
"use strict";
|
|
@@ -7412,7 +7671,18 @@ var init_config_loader = __esm({
|
|
|
7412
7671
|
typeMode: TypeModeSchema.optional(),
|
|
7413
7672
|
nativeEnumType: NativeEnumTypeSchema.optional()
|
|
7414
7673
|
});
|
|
7415
|
-
|
|
7674
|
+
OperationFiltersSchema = z.strictObject({
|
|
7675
|
+
includeTags: z.array(z.string()).optional(),
|
|
7676
|
+
excludeTags: z.array(z.string()).optional(),
|
|
7677
|
+
includePaths: z.array(z.string()).optional(),
|
|
7678
|
+
excludePaths: z.array(z.string()).optional(),
|
|
7679
|
+
includeMethods: z.array(z.string()).optional(),
|
|
7680
|
+
excludeMethods: z.array(z.string()).optional(),
|
|
7681
|
+
includeOperationIds: z.array(z.string()).optional(),
|
|
7682
|
+
excludeOperationIds: z.array(z.string()).optional(),
|
|
7683
|
+
excludeDeprecated: z.boolean().optional()
|
|
7684
|
+
});
|
|
7685
|
+
OpenApiGeneratorOptionsSchema = z.strictObject({
|
|
7416
7686
|
mode: z.enum(["strict", "normal", "loose"]).optional(),
|
|
7417
7687
|
input: z.string(),
|
|
7418
7688
|
output: z.string(),
|
|
@@ -7426,7 +7696,8 @@ var init_config_loader = __esm({
|
|
|
7426
7696
|
nativeEnumType: NativeEnumTypeSchema.optional(),
|
|
7427
7697
|
request: RequestResponseOptionsSchema.optional(),
|
|
7428
7698
|
response: RequestResponseOptionsSchema.optional(),
|
|
7429
|
-
name: z.string().optional()
|
|
7699
|
+
name: z.string().optional(),
|
|
7700
|
+
operationFilters: OperationFiltersSchema.optional()
|
|
7430
7701
|
});
|
|
7431
7702
|
ConfigFileSchema = z.strictObject({
|
|
7432
7703
|
defaults: z.strictObject({
|
|
@@ -7440,9 +7711,10 @@ var init_config_loader = __esm({
|
|
|
7440
7711
|
showStats: z.boolean().optional(),
|
|
7441
7712
|
nativeEnumType: NativeEnumTypeSchema.optional(),
|
|
7442
7713
|
request: RequestResponseOptionsSchema.optional(),
|
|
7443
|
-
response: RequestResponseOptionsSchema.optional()
|
|
7714
|
+
response: RequestResponseOptionsSchema.optional(),
|
|
7715
|
+
operationFilters: OperationFiltersSchema.optional()
|
|
7444
7716
|
}).optional(),
|
|
7445
|
-
specs: z.array(
|
|
7717
|
+
specs: z.array(OpenApiGeneratorOptionsSchema).min(1, "At least one spec is required"),
|
|
7446
7718
|
executionMode: z.enum(["parallel", "sequential"]).optional()
|
|
7447
7719
|
});
|
|
7448
7720
|
createTypeScriptLoader = () => {
|
|
@@ -7481,7 +7753,8 @@ var init_config_loader = __esm({
|
|
|
7481
7753
|
});
|
|
7482
7754
|
|
|
7483
7755
|
// src/cli.ts
|
|
7484
|
-
import { existsSync as existsSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
7756
|
+
import { existsSync as existsSync2, readdirSync, statSync, writeFileSync as writeFileSync2 } from "fs";
|
|
7757
|
+
import { join } from "path";
|
|
7485
7758
|
import { Command } from "commander";
|
|
7486
7759
|
var require_cli = __commonJS({
|
|
7487
7760
|
"src/cli.ts"() {
|
|
@@ -7532,6 +7805,36 @@ Breaking Changes (v2.0):
|
|
|
7532
7805
|
}
|
|
7533
7806
|
});
|
|
7534
7807
|
program.parse();
|
|
7808
|
+
function findSpecFiles() {
|
|
7809
|
+
const specFolders = ["spec", "specs"];
|
|
7810
|
+
const validExtensions = [".yaml", ".yml", ".json"];
|
|
7811
|
+
const excludePatterns = ["node_modules", ".git", "dist", "build", "coverage"];
|
|
7812
|
+
const allFiles = [];
|
|
7813
|
+
for (const folder of specFolders) {
|
|
7814
|
+
if (!existsSync2(folder)) continue;
|
|
7815
|
+
try {
|
|
7816
|
+
const entries = readdirSync(folder, { recursive: true, encoding: "utf-8" });
|
|
7817
|
+
for (const entry of entries) {
|
|
7818
|
+
const fullPath = join(folder, entry);
|
|
7819
|
+
if (excludePatterns.some((pattern) => fullPath.includes(pattern))) continue;
|
|
7820
|
+
try {
|
|
7821
|
+
const stats = statSync(fullPath);
|
|
7822
|
+
if (!stats.isFile()) continue;
|
|
7823
|
+
const hasValidExt = validExtensions.some((ext) => fullPath.endsWith(ext));
|
|
7824
|
+
if (!hasValidExt) continue;
|
|
7825
|
+
const sizeKB = (stats.size / 1024).toFixed(2);
|
|
7826
|
+
allFiles.push({ path: fullPath.replace(/\\/g, "/"), size: `${sizeKB} KB` });
|
|
7827
|
+
} catch {
|
|
7828
|
+
}
|
|
7829
|
+
}
|
|
7830
|
+
} catch {
|
|
7831
|
+
}
|
|
7832
|
+
}
|
|
7833
|
+
allFiles.sort((a, b) => a.path.localeCompare(b.path));
|
|
7834
|
+
const totalCount = allFiles.length;
|
|
7835
|
+
const files = allFiles.slice(0, 20);
|
|
7836
|
+
return { files, totalCount };
|
|
7837
|
+
}
|
|
7535
7838
|
async function executeConfigMode(options) {
|
|
7536
7839
|
let config;
|
|
7537
7840
|
try {
|
|
@@ -7565,14 +7868,66 @@ Breaking Changes (v2.0):
|
|
|
7565
7868
|
return;
|
|
7566
7869
|
}
|
|
7567
7870
|
}
|
|
7568
|
-
const
|
|
7569
|
-
|
|
7871
|
+
const { files, totalCount } = findSpecFiles();
|
|
7872
|
+
if (totalCount > 20) {
|
|
7873
|
+
console.log(`Showing first 20 of ${totalCount} files found. Use manual entry to specify others.
|
|
7874
|
+
`);
|
|
7875
|
+
}
|
|
7876
|
+
let inputPath;
|
|
7877
|
+
if (files.length > 0) {
|
|
7878
|
+
const choices = [
|
|
7879
|
+
...files.map((f) => ({ title: `${f.path} (${f.size})`, value: f.path })),
|
|
7880
|
+
{ title: "\u2192 Enter manually...", value: "__MANUAL__" }
|
|
7881
|
+
];
|
|
7882
|
+
const inputResponse = await (0, import_prompts.default)({
|
|
7883
|
+
type: "select",
|
|
7884
|
+
name: "input",
|
|
7885
|
+
message: "Select OpenAPI spec file (YAML or JSON):",
|
|
7886
|
+
choices
|
|
7887
|
+
});
|
|
7888
|
+
if (!inputResponse.input) {
|
|
7889
|
+
console.log("\nInitialization cancelled.");
|
|
7890
|
+
return;
|
|
7891
|
+
}
|
|
7892
|
+
if (inputResponse.input === "__MANUAL__") {
|
|
7893
|
+
const manualResponse = await (0, import_prompts.default)({
|
|
7894
|
+
type: "text",
|
|
7895
|
+
name: "input",
|
|
7896
|
+
message: "Input OpenAPI file path (YAML or JSON):",
|
|
7897
|
+
initial: "openapi.{yaml,yml,json}",
|
|
7898
|
+
validate: (value) => {
|
|
7899
|
+
if (value.length === 0) return "Input path is required";
|
|
7900
|
+
if (!existsSync2(value)) return "\u26A0\uFE0F File does not exist. Continue anyway?";
|
|
7901
|
+
return true;
|
|
7902
|
+
}
|
|
7903
|
+
});
|
|
7904
|
+
if (!manualResponse.input) {
|
|
7905
|
+
console.log("\nInitialization cancelled.");
|
|
7906
|
+
return;
|
|
7907
|
+
}
|
|
7908
|
+
inputPath = manualResponse.input;
|
|
7909
|
+
} else {
|
|
7910
|
+
inputPath = inputResponse.input;
|
|
7911
|
+
}
|
|
7912
|
+
} else {
|
|
7913
|
+
const manualResponse = await (0, import_prompts.default)({
|
|
7570
7914
|
type: "text",
|
|
7571
7915
|
name: "input",
|
|
7572
|
-
message: "Input OpenAPI file path:",
|
|
7573
|
-
initial: "openapi.yaml",
|
|
7574
|
-
validate: (value) =>
|
|
7575
|
-
|
|
7916
|
+
message: "Input OpenAPI file path (YAML or JSON):",
|
|
7917
|
+
initial: "openapi.{yaml,yml,json}",
|
|
7918
|
+
validate: (value) => {
|
|
7919
|
+
if (value.length === 0) return "Input path is required";
|
|
7920
|
+
if (!existsSync2(value)) return "\u26A0\uFE0F File does not exist. Continue anyway?";
|
|
7921
|
+
return true;
|
|
7922
|
+
}
|
|
7923
|
+
});
|
|
7924
|
+
if (!manualResponse.input) {
|
|
7925
|
+
console.log("\nInitialization cancelled.");
|
|
7926
|
+
return;
|
|
7927
|
+
}
|
|
7928
|
+
inputPath = manualResponse.input;
|
|
7929
|
+
}
|
|
7930
|
+
const response = await (0, import_prompts.default)([
|
|
7576
7931
|
{
|
|
7577
7932
|
type: "text",
|
|
7578
7933
|
name: "output",
|
|
@@ -7597,11 +7952,12 @@ Breaking Changes (v2.0):
|
|
|
7597
7952
|
initial: true
|
|
7598
7953
|
}
|
|
7599
7954
|
]);
|
|
7600
|
-
if (!response.
|
|
7955
|
+
if (!response.output || !response.format) {
|
|
7601
7956
|
console.log("\nInitialization cancelled.");
|
|
7602
7957
|
return;
|
|
7603
7958
|
}
|
|
7604
|
-
const {
|
|
7959
|
+
const { output, format, includeDefaults } = response;
|
|
7960
|
+
const input = inputPath;
|
|
7605
7961
|
let configContent;
|
|
7606
7962
|
let configFilename;
|
|
7607
7963
|
if (format === "ts") {
|
|
@@ -7662,7 +8018,21 @@ export default defineConfig({
|
|
|
7662
8018
|
console.log("\nNext steps:");
|
|
7663
8019
|
console.log(" 1. Review and customize your config file if needed");
|
|
7664
8020
|
console.log(" 2. Run 'openapi-to-zod' to generate schemas\n");
|
|
7665
|
-
|
|
8021
|
+
const ceriosMessages = [
|
|
8022
|
+
"Things just got Cerios!",
|
|
8023
|
+
"Getting Cerios about schemas!",
|
|
8024
|
+
"Cerios business ahead!",
|
|
8025
|
+
"Don't take it too Cerios-ly!",
|
|
8026
|
+
"Time to get Cerios!",
|
|
8027
|
+
"We're dead Cerios about types!",
|
|
8028
|
+
"This is Cerios-ly awesome!",
|
|
8029
|
+
"Cerios-ly, you're all set!",
|
|
8030
|
+
"You are Cerios right now!",
|
|
8031
|
+
"Cerios vibes only!"
|
|
8032
|
+
];
|
|
8033
|
+
const randomMessage = ceriosMessages[Math.floor(Math.random() * ceriosMessages.length)];
|
|
8034
|
+
console.log(`${randomMessage}
|
|
8035
|
+
`);
|
|
7666
8036
|
}
|
|
7667
8037
|
}
|
|
7668
8038
|
});
|