@cerios/openapi-to-zod 0.6.0 → 1.1.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 +448 -51
- package/dist/cli.js +355 -186
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +418 -224
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +9 -344
- package/dist/index.d.ts +9 -344
- package/dist/index.js +156 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +155 -22
- package/dist/index.mjs.map +1 -1
- package/dist/internal.d.mts +257 -0
- package/dist/internal.d.ts +257 -0
- package/dist/internal.js +592 -0
- package/dist/internal.js.map +1 -0
- package/dist/internal.mjs +547 -0
- package/dist/internal.mjs.map +1 -0
- package/dist/types-B7ePTDjr.d.mts +345 -0
- package/dist/types-B7ePTDjr.d.ts +345 -0
- package/package.json +102 -78
package/dist/cli.js
CHANGED
|
@@ -5013,10 +5013,123 @@ var ConfigurationError = class extends GeneratorError {
|
|
|
5013
5013
|
}
|
|
5014
5014
|
};
|
|
5015
5015
|
|
|
5016
|
+
// src/batch-executor.ts
|
|
5017
|
+
async function processSpec(spec, index, total, createGenerator) {
|
|
5018
|
+
const specInput = spec.input || "spec";
|
|
5019
|
+
const specOutput = spec.output || "output";
|
|
5020
|
+
console.log(`Processing [${index + 1}/${total}] ${specInput}...`);
|
|
5021
|
+
try {
|
|
5022
|
+
const generator = createGenerator(spec);
|
|
5023
|
+
generator.generate();
|
|
5024
|
+
return {
|
|
5025
|
+
spec,
|
|
5026
|
+
success: true
|
|
5027
|
+
};
|
|
5028
|
+
} catch (error) {
|
|
5029
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5030
|
+
console.error(`\u2717 Failed to generate ${specOutput}: ${errorMessage}`);
|
|
5031
|
+
return {
|
|
5032
|
+
spec,
|
|
5033
|
+
success: false,
|
|
5034
|
+
error: errorMessage
|
|
5035
|
+
};
|
|
5036
|
+
}
|
|
5037
|
+
}
|
|
5038
|
+
async function executeParallel(specs, createGenerator, batchSize) {
|
|
5039
|
+
console.log(`
|
|
5040
|
+
Executing ${specs.length} specification(s) in parallel (batch size: ${batchSize})...
|
|
5041
|
+
`);
|
|
5042
|
+
const results = [];
|
|
5043
|
+
for (let i = 0; i < specs.length; i += batchSize) {
|
|
5044
|
+
const batch = specs.slice(i, Math.min(i + batchSize, specs.length));
|
|
5045
|
+
const batchPromises = batch.map(
|
|
5046
|
+
(spec, batchIndex) => processSpec(spec, i + batchIndex, specs.length, createGenerator)
|
|
5047
|
+
);
|
|
5048
|
+
const batchResults = await Promise.allSettled(batchPromises);
|
|
5049
|
+
for (let j = 0; j < batchResults.length; j++) {
|
|
5050
|
+
const result = batchResults[j];
|
|
5051
|
+
if (result.status === "fulfilled") {
|
|
5052
|
+
results.push(result.value);
|
|
5053
|
+
} else {
|
|
5054
|
+
results.push({
|
|
5055
|
+
spec: batch[j],
|
|
5056
|
+
success: false,
|
|
5057
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
5058
|
+
});
|
|
5059
|
+
}
|
|
5060
|
+
}
|
|
5061
|
+
}
|
|
5062
|
+
return results;
|
|
5063
|
+
}
|
|
5064
|
+
async function executeSequential(specs, createGenerator) {
|
|
5065
|
+
console.log(`
|
|
5066
|
+
Executing ${specs.length} spec(s) sequentially...
|
|
5067
|
+
`);
|
|
5068
|
+
const results = [];
|
|
5069
|
+
for (let i = 0; i < specs.length; i++) {
|
|
5070
|
+
const result = await processSpec(specs[i], i, specs.length, createGenerator);
|
|
5071
|
+
results.push(result);
|
|
5072
|
+
}
|
|
5073
|
+
return results;
|
|
5074
|
+
}
|
|
5075
|
+
function printSummary(summary) {
|
|
5076
|
+
console.log(`
|
|
5077
|
+
${"=".repeat(50)}`);
|
|
5078
|
+
console.log("Batch Execution Summary");
|
|
5079
|
+
console.log("=".repeat(50));
|
|
5080
|
+
console.log(`Total specs: ${summary.total}`);
|
|
5081
|
+
console.log(`Successful: ${summary.successful}`);
|
|
5082
|
+
console.log(`Failed: ${summary.failed}`);
|
|
5083
|
+
if (summary.failed > 0) {
|
|
5084
|
+
console.log("\nFailed specs:");
|
|
5085
|
+
for (const result of summary.results) {
|
|
5086
|
+
if (!result.success) {
|
|
5087
|
+
const specInput = result.spec.input || "spec";
|
|
5088
|
+
console.error(` \u2717 ${specInput}`);
|
|
5089
|
+
console.error(` Error: ${result.error}`);
|
|
5090
|
+
}
|
|
5091
|
+
}
|
|
5092
|
+
}
|
|
5093
|
+
console.log(`${"=".repeat(50)}
|
|
5094
|
+
`);
|
|
5095
|
+
}
|
|
5096
|
+
async function executeBatch(specs, executionMode = "parallel", createGenerator, batchSize) {
|
|
5097
|
+
if (specs.length === 0) {
|
|
5098
|
+
throw new ConfigurationError("No specs provided for batch execution", { specsCount: 0, executionMode });
|
|
5099
|
+
}
|
|
5100
|
+
let results = [];
|
|
5101
|
+
try {
|
|
5102
|
+
results = executionMode === "parallel" ? await executeParallel(specs, createGenerator, batchSize) : await executeSequential(specs, createGenerator);
|
|
5103
|
+
const summary = {
|
|
5104
|
+
total: results.length,
|
|
5105
|
+
successful: results.filter((r) => r.success).length,
|
|
5106
|
+
failed: results.filter((r) => !r.success).length,
|
|
5107
|
+
results
|
|
5108
|
+
};
|
|
5109
|
+
printSummary(summary);
|
|
5110
|
+
return summary;
|
|
5111
|
+
} finally {
|
|
5112
|
+
if (results.length > batchSize) {
|
|
5113
|
+
for (const result of results) {
|
|
5114
|
+
if (result.spec) {
|
|
5115
|
+
result.spec = null;
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
5118
|
+
if (global.gc) {
|
|
5119
|
+
global.gc();
|
|
5120
|
+
}
|
|
5121
|
+
}
|
|
5122
|
+
}
|
|
5123
|
+
}
|
|
5124
|
+
function getBatchExitCode(summary) {
|
|
5125
|
+
return summary.failed > 0 ? 1 : 0;
|
|
5126
|
+
}
|
|
5127
|
+
|
|
5016
5128
|
// src/openapi-generator.ts
|
|
5017
5129
|
init_cjs_shims();
|
|
5018
5130
|
var import_node_fs = require("fs");
|
|
5019
5131
|
var import_node_path = require("path");
|
|
5132
|
+
var import_minimatch2 = require("minimatch");
|
|
5020
5133
|
var import_yaml = require("yaml");
|
|
5021
5134
|
|
|
5022
5135
|
// src/generators/enum-generator.ts
|
|
@@ -5024,8 +5137,20 @@ init_cjs_shims();
|
|
|
5024
5137
|
|
|
5025
5138
|
// src/utils/name-utils.ts
|
|
5026
5139
|
init_cjs_shims();
|
|
5140
|
+
function sanitizeIdentifier(str) {
|
|
5141
|
+
return str.replace(/[^a-zA-Z0-9._\-\s]+/g, "_");
|
|
5142
|
+
}
|
|
5027
5143
|
function toCamelCase(str, options) {
|
|
5028
|
-
|
|
5144
|
+
const sanitized = sanitizeIdentifier(str);
|
|
5145
|
+
const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
|
|
5146
|
+
let name;
|
|
5147
|
+
if (words.length === 0) {
|
|
5148
|
+
name = str.charAt(0).toLowerCase() + str.slice(1);
|
|
5149
|
+
} else if (words.length === 1) {
|
|
5150
|
+
name = words[0].charAt(0).toLowerCase() + words[0].slice(1);
|
|
5151
|
+
} else {
|
|
5152
|
+
name = words[0].charAt(0).toLowerCase() + words[0].slice(1) + words.slice(1).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
5153
|
+
}
|
|
5029
5154
|
if (options == null ? void 0 : options.prefix) {
|
|
5030
5155
|
const prefix = options.prefix.toLowerCase();
|
|
5031
5156
|
name = prefix + name.charAt(0).toUpperCase() + name.slice(1);
|
|
@@ -5038,12 +5163,23 @@ function toCamelCase(str, options) {
|
|
|
5038
5163
|
}
|
|
5039
5164
|
function toPascalCase(str) {
|
|
5040
5165
|
const stringValue = String(str);
|
|
5041
|
-
|
|
5166
|
+
const isAlreadyValidCase = /^[a-zA-Z][a-zA-Z0-9]*$/.test(stringValue);
|
|
5167
|
+
if (isAlreadyValidCase) {
|
|
5168
|
+
return stringValue.charAt(0).toUpperCase() + stringValue.slice(1);
|
|
5169
|
+
}
|
|
5170
|
+
const sanitized = sanitizeIdentifier(stringValue);
|
|
5171
|
+
const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
|
|
5172
|
+
let result;
|
|
5173
|
+
if (words.length === 0) {
|
|
5174
|
+
result = "Value";
|
|
5175
|
+
} else {
|
|
5176
|
+
result = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
5177
|
+
}
|
|
5042
5178
|
if (/^\d/.test(result)) {
|
|
5043
5179
|
result = `N${result}`;
|
|
5044
5180
|
}
|
|
5045
5181
|
if (!result || /^_+$/.test(result)) {
|
|
5046
|
-
|
|
5182
|
+
return "Value";
|
|
5047
5183
|
}
|
|
5048
5184
|
return result;
|
|
5049
5185
|
}
|
|
@@ -5055,9 +5191,10 @@ function resolveRef(ref) {
|
|
|
5055
5191
|
// src/generators/enum-generator.ts
|
|
5056
5192
|
function generateEnum(name, values, options) {
|
|
5057
5193
|
const schemaName = `${toCamelCase(name, options)}Schema`;
|
|
5194
|
+
const typeName = toPascalCase(name);
|
|
5058
5195
|
const enumValues = values.map((v) => `"${v}"`).join(", ");
|
|
5059
5196
|
const schemaCode = `export const ${schemaName} = z.enum([${enumValues}]);`;
|
|
5060
|
-
const typeCode = `export type ${
|
|
5197
|
+
const typeCode = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
|
|
5061
5198
|
return { schemaCode, typeCode };
|
|
5062
5199
|
}
|
|
5063
5200
|
|
|
@@ -5165,6 +5302,9 @@ var LRUCache = class {
|
|
|
5165
5302
|
this.cache = /* @__PURE__ */ new Map();
|
|
5166
5303
|
this.maxSize = maxSize;
|
|
5167
5304
|
}
|
|
5305
|
+
get capacity() {
|
|
5306
|
+
return this.maxSize;
|
|
5307
|
+
}
|
|
5168
5308
|
get(key) {
|
|
5169
5309
|
if (!this.cache.has(key)) return void 0;
|
|
5170
5310
|
const value = this.cache.get(key);
|
|
@@ -5195,6 +5335,77 @@ var LRUCache = class {
|
|
|
5195
5335
|
}
|
|
5196
5336
|
};
|
|
5197
5337
|
|
|
5338
|
+
// src/utils/pattern-utils.ts
|
|
5339
|
+
init_cjs_shims();
|
|
5340
|
+
function isRegexPattern(pattern) {
|
|
5341
|
+
if (pattern.startsWith("^") || pattern.endsWith("$")) {
|
|
5342
|
+
return true;
|
|
5343
|
+
}
|
|
5344
|
+
if (/\\[dDwWsS]/.test(pattern)) {
|
|
5345
|
+
return true;
|
|
5346
|
+
}
|
|
5347
|
+
if (/\.\*|\.\+/.test(pattern)) {
|
|
5348
|
+
return true;
|
|
5349
|
+
}
|
|
5350
|
+
if (/[[\]()]/.test(pattern)) {
|
|
5351
|
+
return true;
|
|
5352
|
+
}
|
|
5353
|
+
if (/[^/][+?*]\{/.test(pattern)) {
|
|
5354
|
+
return true;
|
|
5355
|
+
}
|
|
5356
|
+
return false;
|
|
5357
|
+
}
|
|
5358
|
+
function patternToRegex(pattern) {
|
|
5359
|
+
if (pattern instanceof RegExp) {
|
|
5360
|
+
return pattern;
|
|
5361
|
+
}
|
|
5362
|
+
if (isRegexPattern(pattern)) {
|
|
5363
|
+
try {
|
|
5364
|
+
return new RegExp(pattern);
|
|
5365
|
+
} catch (error) {
|
|
5366
|
+
console.warn(`\u26A0\uFE0F Invalid regex pattern "${pattern}": ${error instanceof Error ? error.message : String(error)}`);
|
|
5367
|
+
return null;
|
|
5368
|
+
}
|
|
5369
|
+
}
|
|
5370
|
+
return null;
|
|
5371
|
+
}
|
|
5372
|
+
function stripPrefix(input, pattern, ensureLeadingChar) {
|
|
5373
|
+
if (!pattern) {
|
|
5374
|
+
return input;
|
|
5375
|
+
}
|
|
5376
|
+
const regex = patternToRegex(pattern);
|
|
5377
|
+
if (regex) {
|
|
5378
|
+
const match = input.match(regex);
|
|
5379
|
+
if (match && match.index === 0) {
|
|
5380
|
+
const stripped = input.substring(match[0].length);
|
|
5381
|
+
if (ensureLeadingChar) {
|
|
5382
|
+
if (stripped === "") {
|
|
5383
|
+
return ensureLeadingChar;
|
|
5384
|
+
}
|
|
5385
|
+
if (!stripped.startsWith(ensureLeadingChar)) {
|
|
5386
|
+
return `${ensureLeadingChar}${stripped}`;
|
|
5387
|
+
}
|
|
5388
|
+
}
|
|
5389
|
+
return stripped;
|
|
5390
|
+
}
|
|
5391
|
+
} else {
|
|
5392
|
+
const stringPattern = pattern;
|
|
5393
|
+
if (input.startsWith(stringPattern)) {
|
|
5394
|
+
const stripped = input.substring(stringPattern.length);
|
|
5395
|
+
if (ensureLeadingChar) {
|
|
5396
|
+
if (stripped === "") {
|
|
5397
|
+
return ensureLeadingChar;
|
|
5398
|
+
}
|
|
5399
|
+
if (!stripped.startsWith(ensureLeadingChar)) {
|
|
5400
|
+
return `${ensureLeadingChar}${stripped}`;
|
|
5401
|
+
}
|
|
5402
|
+
}
|
|
5403
|
+
return stripped;
|
|
5404
|
+
}
|
|
5405
|
+
}
|
|
5406
|
+
return input;
|
|
5407
|
+
}
|
|
5408
|
+
|
|
5198
5409
|
// src/validators/array-validator.ts
|
|
5199
5410
|
init_cjs_shims();
|
|
5200
5411
|
function generateArrayValidation(schema, context) {
|
|
@@ -5722,6 +5933,11 @@ ${properties.join(",\n")}
|
|
|
5722
5933
|
// src/validators/string-validator.ts
|
|
5723
5934
|
init_cjs_shims();
|
|
5724
5935
|
var PATTERN_CACHE = new LRUCache(1e3);
|
|
5936
|
+
function configurePatternCache(size) {
|
|
5937
|
+
if (size > 0 && size !== PATTERN_CACHE.capacity) {
|
|
5938
|
+
PATTERN_CACHE = new LRUCache(size);
|
|
5939
|
+
}
|
|
5940
|
+
}
|
|
5725
5941
|
var FORMAT_MAP = {
|
|
5726
5942
|
uuid: "z.uuid()",
|
|
5727
5943
|
email: "z.email()",
|
|
@@ -6054,8 +6270,9 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
6054
6270
|
}
|
|
6055
6271
|
(_a = this.context.schemaDependencies.get(currentSchema)) == null ? void 0 : _a.add(refName);
|
|
6056
6272
|
}
|
|
6057
|
-
const
|
|
6058
|
-
|
|
6273
|
+
const strippedRefName = stripPrefix(resolvedRefName, this.context.stripSchemaPrefix);
|
|
6274
|
+
const schemaName = `${toCamelCase(strippedRefName, this.context.namingOptions)}Schema`;
|
|
6275
|
+
if (currentSchema && (refName === currentSchema || this.isCircularThroughAlias(currentSchema, refName))) {
|
|
6059
6276
|
const lazySchema = `z.lazy((): z.ZodTypeAny => ${schemaName})`;
|
|
6060
6277
|
return wrapNullable(lazySchema, nullable);
|
|
6061
6278
|
}
|
|
@@ -6343,7 +6560,7 @@ var OpenApiGenerator = class {
|
|
|
6343
6560
|
this.schemaUsageMap = /* @__PURE__ */ new Map();
|
|
6344
6561
|
this.needsZodImport = true;
|
|
6345
6562
|
this.filterStats = createFilterStatistics();
|
|
6346
|
-
var _a, _b, _c;
|
|
6563
|
+
var _a, _b, _c, _d, _e;
|
|
6347
6564
|
if (!options.input) {
|
|
6348
6565
|
throw new ConfigurationError("Input path is required", { providedOptions: options });
|
|
6349
6566
|
}
|
|
@@ -6356,11 +6573,18 @@ var OpenApiGenerator = class {
|
|
|
6356
6573
|
schemaType: options.schemaType || "all",
|
|
6357
6574
|
prefix: options.prefix,
|
|
6358
6575
|
suffix: options.suffix,
|
|
6576
|
+
stripSchemaPrefix: options.stripSchemaPrefix,
|
|
6359
6577
|
showStats: (_c = options.showStats) != null ? _c : true,
|
|
6360
6578
|
request: options.request,
|
|
6361
6579
|
response: options.response,
|
|
6362
|
-
operationFilters: options.operationFilters
|
|
6580
|
+
operationFilters: options.operationFilters,
|
|
6581
|
+
ignoreHeaders: options.ignoreHeaders,
|
|
6582
|
+
cacheSize: (_d = options.cacheSize) != null ? _d : 1e3,
|
|
6583
|
+
batchSize: (_e = options.batchSize) != null ? _e : 10
|
|
6363
6584
|
};
|
|
6585
|
+
if (this.options.cacheSize) {
|
|
6586
|
+
configurePatternCache(this.options.cacheSize);
|
|
6587
|
+
}
|
|
6364
6588
|
try {
|
|
6365
6589
|
const fs = require("fs");
|
|
6366
6590
|
if (!fs.existsSync(this.options.input)) {
|
|
@@ -6426,7 +6650,8 @@ var OpenApiGenerator = class {
|
|
|
6426
6650
|
namingOptions: {
|
|
6427
6651
|
prefix: this.options.prefix,
|
|
6428
6652
|
suffix: this.options.suffix
|
|
6429
|
-
}
|
|
6653
|
+
},
|
|
6654
|
+
stripSchemaPrefix: this.options.stripSchemaPrefix
|
|
6430
6655
|
});
|
|
6431
6656
|
}
|
|
6432
6657
|
/**
|
|
@@ -6460,9 +6685,11 @@ var OpenApiGenerator = class {
|
|
|
6460
6685
|
const typeCode = this.types.get(name);
|
|
6461
6686
|
if (schemaCode) {
|
|
6462
6687
|
output.push(schemaCode);
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6688
|
+
const strippedName = stripPrefix(name, this.options.stripSchemaPrefix);
|
|
6689
|
+
const typeName = toPascalCase(strippedName);
|
|
6690
|
+
if (!schemaCode.includes(`export type ${typeName}`)) {
|
|
6691
|
+
const schemaName = `${toCamelCase(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
|
|
6692
|
+
output.push(`export type ${typeName} = z.infer<typeof ${schemaName}>;`);
|
|
6466
6693
|
}
|
|
6467
6694
|
output.push("");
|
|
6468
6695
|
} else if (typeCode) {
|
|
@@ -6496,6 +6723,7 @@ var OpenApiGenerator = class {
|
|
|
6496
6723
|
const normalizedOutput = (0, import_node_path.normalize)(this.options.output);
|
|
6497
6724
|
this.ensureDirectoryExists(normalizedOutput);
|
|
6498
6725
|
(0, import_node_fs.writeFileSync)(normalizedOutput, output);
|
|
6726
|
+
console.log(` \u2713 Generated ${normalizedOutput}`);
|
|
6499
6727
|
}
|
|
6500
6728
|
/**
|
|
6501
6729
|
* Resolve options for a specific context (request or response)
|
|
@@ -6777,7 +7005,8 @@ var OpenApiGenerator = class {
|
|
|
6777
7005
|
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
6778
7006
|
if (schema.enum) {
|
|
6779
7007
|
const jsdoc2 = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
6780
|
-
const
|
|
7008
|
+
const strippedName2 = stripPrefix(name, this.options.stripSchemaPrefix);
|
|
7009
|
+
const { schemaCode, typeCode } = generateEnum(strippedName2, schema.enum, {
|
|
6781
7010
|
prefix: this.options.prefix,
|
|
6782
7011
|
suffix: this.options.suffix
|
|
6783
7012
|
});
|
|
@@ -6786,7 +7015,8 @@ ${typeCode}`;
|
|
|
6786
7015
|
this.schemas.set(name, enumSchemaCode);
|
|
6787
7016
|
return;
|
|
6788
7017
|
}
|
|
6789
|
-
const
|
|
7018
|
+
const strippedName = stripPrefix(name, this.options.stripSchemaPrefix);
|
|
7019
|
+
const schemaName = `${toCamelCase(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
|
|
6790
7020
|
const jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
6791
7021
|
if (schema.allOf && schema.allOf.length === 1 && schema.allOf[0].$ref) {
|
|
6792
7022
|
const refName = resolveRef(schema.allOf[0].$ref);
|
|
@@ -6802,7 +7032,8 @@ ${typeCode}`;
|
|
|
6802
7032
|
namingOptions: {
|
|
6803
7033
|
prefix: this.options.prefix,
|
|
6804
7034
|
suffix: this.options.suffix
|
|
6805
|
-
}
|
|
7035
|
+
},
|
|
7036
|
+
stripSchemaPrefix: this.options.stripSchemaPrefix
|
|
6806
7037
|
});
|
|
6807
7038
|
const isAlias = !!(schema.$ref && !schema.properties && !schema.allOf && !schema.oneOf && !schema.anyOf);
|
|
6808
7039
|
const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, isAlias);
|
|
@@ -6906,6 +7137,24 @@ ${propsCode}
|
|
|
6906
7137
|
}
|
|
6907
7138
|
}
|
|
6908
7139
|
}
|
|
7140
|
+
/**
|
|
7141
|
+
* Check if a header should be ignored based on filter patterns
|
|
7142
|
+
* @internal
|
|
7143
|
+
*/
|
|
7144
|
+
shouldIgnoreHeader(headerName) {
|
|
7145
|
+
const ignorePatterns = this.options.ignoreHeaders;
|
|
7146
|
+
if (!ignorePatterns || ignorePatterns.length === 0) {
|
|
7147
|
+
return false;
|
|
7148
|
+
}
|
|
7149
|
+
if (ignorePatterns.includes("*")) {
|
|
7150
|
+
return true;
|
|
7151
|
+
}
|
|
7152
|
+
const headerLower = headerName.toLowerCase();
|
|
7153
|
+
return ignorePatterns.some((pattern) => {
|
|
7154
|
+
const patternLower = pattern.toLowerCase();
|
|
7155
|
+
return (0, import_minimatch2.minimatch)(headerLower, patternLower);
|
|
7156
|
+
});
|
|
7157
|
+
}
|
|
6909
7158
|
/**
|
|
6910
7159
|
* Generate header parameter schemas for each operation
|
|
6911
7160
|
* Header parameters are always string type (HTTP header semantics)
|
|
@@ -6928,7 +7177,7 @@ ${propsCode}
|
|
|
6928
7177
|
continue;
|
|
6929
7178
|
}
|
|
6930
7179
|
const headerParams = operation.parameters.filter(
|
|
6931
|
-
(param) => param && typeof param === "object" && param.in === "header"
|
|
7180
|
+
(param) => param && typeof param === "object" && param.in === "header" && !this.shouldIgnoreHeader(param.name)
|
|
6932
7181
|
);
|
|
6933
7182
|
if (headerParams.length === 0) {
|
|
6934
7183
|
continue;
|
|
@@ -6986,7 +7235,8 @@ ${propsCode}
|
|
|
6986
7235
|
generateQueryParamType(schema, param) {
|
|
6987
7236
|
if (schema.$ref) {
|
|
6988
7237
|
const refName = resolveRef(schema.$ref);
|
|
6989
|
-
const
|
|
7238
|
+
const strippedRefName = stripPrefix(refName, this.options.stripSchemaPrefix);
|
|
7239
|
+
const schemaName = toCamelCase(strippedRefName, { prefix: this.options.prefix, suffix: this.options.suffix });
|
|
6990
7240
|
return `${schemaName}Schema`;
|
|
6991
7241
|
}
|
|
6992
7242
|
if (schema.enum) {
|
|
@@ -7125,110 +7375,13 @@ ${propsCode}
|
|
|
7125
7375
|
}
|
|
7126
7376
|
};
|
|
7127
7377
|
|
|
7128
|
-
// src/batch-executor.ts
|
|
7129
|
-
async function processSpec(spec, index, total) {
|
|
7130
|
-
console.log(`Processing [${index + 1}/${total}] ${spec.input}...`);
|
|
7131
|
-
try {
|
|
7132
|
-
const generator = new OpenApiGenerator(spec);
|
|
7133
|
-
generator.generate();
|
|
7134
|
-
console.log(`\u2713 Successfully generated ${spec.output}`);
|
|
7135
|
-
return {
|
|
7136
|
-
spec,
|
|
7137
|
-
success: true
|
|
7138
|
-
};
|
|
7139
|
-
} catch (error) {
|
|
7140
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
7141
|
-
console.error(`\u2717 Failed to generate ${spec.output}: ${errorMessage}`);
|
|
7142
|
-
return {
|
|
7143
|
-
spec,
|
|
7144
|
-
success: false,
|
|
7145
|
-
error: errorMessage
|
|
7146
|
-
};
|
|
7147
|
-
}
|
|
7148
|
-
}
|
|
7149
|
-
async function executeParallel(specs) {
|
|
7150
|
-
console.log(`
|
|
7151
|
-
Executing ${specs.length} spec(s) in parallel...
|
|
7152
|
-
`);
|
|
7153
|
-
const promises = specs.map((spec, index) => processSpec(spec, index, specs.length));
|
|
7154
|
-
const results = await Promise.allSettled(promises);
|
|
7155
|
-
return results.map((result, index) => {
|
|
7156
|
-
if (result.status === "fulfilled") {
|
|
7157
|
-
return result.value;
|
|
7158
|
-
}
|
|
7159
|
-
return {
|
|
7160
|
-
spec: specs[index],
|
|
7161
|
-
success: false,
|
|
7162
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
7163
|
-
};
|
|
7164
|
-
});
|
|
7165
|
-
}
|
|
7166
|
-
async function executeSequential(specs) {
|
|
7167
|
-
console.log(`
|
|
7168
|
-
Executing ${specs.length} spec(s) sequentially...
|
|
7169
|
-
`);
|
|
7170
|
-
const results = [];
|
|
7171
|
-
for (let i = 0; i < specs.length; i++) {
|
|
7172
|
-
const result = await processSpec(specs[i], i, specs.length);
|
|
7173
|
-
results.push(result);
|
|
7174
|
-
}
|
|
7175
|
-
return results;
|
|
7176
|
-
}
|
|
7177
|
-
function printSummary(summary) {
|
|
7178
|
-
console.log(`
|
|
7179
|
-
${"=".repeat(50)}`);
|
|
7180
|
-
console.log("Batch Execution Summary");
|
|
7181
|
-
console.log("=".repeat(50));
|
|
7182
|
-
console.log(`Total specs: ${summary.total}`);
|
|
7183
|
-
console.log(`Successful: ${summary.successful}`);
|
|
7184
|
-
console.log(`Failed: ${summary.failed}`);
|
|
7185
|
-
if (summary.failed > 0) {
|
|
7186
|
-
console.log("\nFailed specs:");
|
|
7187
|
-
for (const result of summary.results) {
|
|
7188
|
-
if (!result.success) {
|
|
7189
|
-
console.error(` \u2717 ${result.spec.input}`);
|
|
7190
|
-
console.error(` Error: ${result.error}`);
|
|
7191
|
-
}
|
|
7192
|
-
}
|
|
7193
|
-
}
|
|
7194
|
-
console.log(`${"=".repeat(50)}
|
|
7195
|
-
`);
|
|
7196
|
-
}
|
|
7197
|
-
async function executeBatch(specs, executionMode = "parallel") {
|
|
7198
|
-
if (specs.length === 0) {
|
|
7199
|
-
throw new ConfigurationError("No specs provided for batch execution", { specsCount: 0, executionMode });
|
|
7200
|
-
}
|
|
7201
|
-
let results = [];
|
|
7202
|
-
try {
|
|
7203
|
-
results = executionMode === "parallel" ? await executeParallel(specs) : await executeSequential(specs);
|
|
7204
|
-
const summary = {
|
|
7205
|
-
total: results.length,
|
|
7206
|
-
successful: results.filter((r) => r.success).length,
|
|
7207
|
-
failed: results.filter((r) => !r.success).length,
|
|
7208
|
-
results
|
|
7209
|
-
};
|
|
7210
|
-
printSummary(summary);
|
|
7211
|
-
return summary;
|
|
7212
|
-
} finally {
|
|
7213
|
-
if (results.length > 10) {
|
|
7214
|
-
for (const result of results) {
|
|
7215
|
-
if (result.spec) {
|
|
7216
|
-
result.spec = null;
|
|
7217
|
-
}
|
|
7218
|
-
}
|
|
7219
|
-
if (global.gc) {
|
|
7220
|
-
global.gc();
|
|
7221
|
-
}
|
|
7222
|
-
}
|
|
7223
|
-
}
|
|
7224
|
-
}
|
|
7225
|
-
function getBatchExitCode(summary) {
|
|
7226
|
-
return summary.failed > 0 ? 1 : 0;
|
|
7227
|
-
}
|
|
7228
|
-
|
|
7229
7378
|
// src/utils/config-loader.ts
|
|
7230
7379
|
init_cjs_shims();
|
|
7231
7380
|
var import_cosmiconfig = require("cosmiconfig");
|
|
7381
|
+
var import_zod2 = require("zod");
|
|
7382
|
+
|
|
7383
|
+
// src/utils/config-schemas.ts
|
|
7384
|
+
init_cjs_shims();
|
|
7232
7385
|
var import_zod = require("zod");
|
|
7233
7386
|
var RequestResponseOptionsSchema = import_zod.z.strictObject({
|
|
7234
7387
|
mode: import_zod.z.enum(["strict", "normal", "loose"]).optional(),
|
|
@@ -7246,38 +7399,37 @@ var OperationFiltersSchema = import_zod.z.strictObject({
|
|
|
7246
7399
|
excludeOperationIds: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7247
7400
|
excludeDeprecated: import_zod.z.boolean().optional()
|
|
7248
7401
|
});
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
var createTypeScriptLoader = () => {
|
|
7402
|
+
|
|
7403
|
+
// src/utils/config-validation.ts
|
|
7404
|
+
init_cjs_shims();
|
|
7405
|
+
function formatConfigValidationError(error, filepath, configPath, additionalNotes) {
|
|
7406
|
+
var _a;
|
|
7407
|
+
const formattedErrors = ((_a = error.issues) == null ? void 0 : _a.map((err) => {
|
|
7408
|
+
const path = err.path.length > 0 ? err.path.join(".") : "root";
|
|
7409
|
+
return ` - ${path}: ${err.message}`;
|
|
7410
|
+
}).join("\n")) || "Unknown validation error";
|
|
7411
|
+
const configSource = filepath || configPath || "config file";
|
|
7412
|
+
const lines = [
|
|
7413
|
+
`Invalid configuration file at: ${configSource}`,
|
|
7414
|
+
"",
|
|
7415
|
+
"Validation errors:",
|
|
7416
|
+
formattedErrors,
|
|
7417
|
+
"",
|
|
7418
|
+
"Please check your configuration file and ensure:",
|
|
7419
|
+
" - All required fields are present (specs array with input/output)",
|
|
7420
|
+
" - Field names are spelled correctly (no typos)",
|
|
7421
|
+
" - Values match the expected types (e.g., mode: 'strict' | 'normal' | 'loose')",
|
|
7422
|
+
" - No unknown/extra properties are included"
|
|
7423
|
+
];
|
|
7424
|
+
if (additionalNotes && additionalNotes.length > 0) {
|
|
7425
|
+
lines.push(...additionalNotes.map((note) => ` - ${note}`));
|
|
7426
|
+
}
|
|
7427
|
+
return lines.join("\n");
|
|
7428
|
+
}
|
|
7429
|
+
|
|
7430
|
+
// src/utils/typescript-loader.ts
|
|
7431
|
+
init_cjs_shims();
|
|
7432
|
+
function createTypeScriptLoader() {
|
|
7281
7433
|
return async (filepath) => {
|
|
7282
7434
|
try {
|
|
7283
7435
|
const esbuild = await import("esbuild");
|
|
@@ -7308,9 +7460,51 @@ var createTypeScriptLoader = () => {
|
|
|
7308
7460
|
);
|
|
7309
7461
|
}
|
|
7310
7462
|
};
|
|
7311
|
-
}
|
|
7463
|
+
}
|
|
7464
|
+
|
|
7465
|
+
// src/utils/config-loader.ts
|
|
7466
|
+
var OpenApiGeneratorOptionsSchema = import_zod2.z.strictObject({
|
|
7467
|
+
mode: import_zod2.z.enum(["strict", "normal", "loose"]).optional(),
|
|
7468
|
+
input: import_zod2.z.string(),
|
|
7469
|
+
output: import_zod2.z.string(),
|
|
7470
|
+
includeDescriptions: import_zod2.z.boolean().optional(),
|
|
7471
|
+
useDescribe: import_zod2.z.boolean().optional(),
|
|
7472
|
+
schemaType: import_zod2.z.enum(["all", "request", "response"]).optional(),
|
|
7473
|
+
prefix: import_zod2.z.string().optional(),
|
|
7474
|
+
suffix: import_zod2.z.string().optional(),
|
|
7475
|
+
stripSchemaPrefix: import_zod2.z.string().optional(),
|
|
7476
|
+
showStats: import_zod2.z.boolean().optional(),
|
|
7477
|
+
request: RequestResponseOptionsSchema.optional(),
|
|
7478
|
+
response: RequestResponseOptionsSchema.optional(),
|
|
7479
|
+
name: import_zod2.z.string().optional(),
|
|
7480
|
+
operationFilters: OperationFiltersSchema.optional(),
|
|
7481
|
+
cacheSize: import_zod2.z.number().positive().optional(),
|
|
7482
|
+
batchSize: import_zod2.z.number().positive().optional()
|
|
7483
|
+
});
|
|
7484
|
+
var ConfigFileSchema = import_zod2.z.strictObject({
|
|
7485
|
+
defaults: import_zod2.z.strictObject({
|
|
7486
|
+
mode: import_zod2.z.enum(["strict", "normal", "loose"]).optional(),
|
|
7487
|
+
includeDescriptions: import_zod2.z.boolean().optional(),
|
|
7488
|
+
useDescribe: import_zod2.z.boolean().optional(),
|
|
7489
|
+
schemaType: import_zod2.z.enum(["all", "request", "response"]).optional(),
|
|
7490
|
+
prefix: import_zod2.z.string().optional(),
|
|
7491
|
+
suffix: import_zod2.z.string().optional(),
|
|
7492
|
+
stripSchemaPrefix: import_zod2.z.string().optional(),
|
|
7493
|
+
showStats: import_zod2.z.boolean().optional(),
|
|
7494
|
+
request: RequestResponseOptionsSchema.optional(),
|
|
7495
|
+
response: RequestResponseOptionsSchema.optional(),
|
|
7496
|
+
operationFilters: OperationFiltersSchema.optional(),
|
|
7497
|
+
cacheSize: import_zod2.z.number().positive().optional(),
|
|
7498
|
+
batchSize: import_zod2.z.number().positive().optional()
|
|
7499
|
+
}).optional(),
|
|
7500
|
+
specs: import_zod2.z.array(OpenApiGeneratorOptionsSchema).min(1, {
|
|
7501
|
+
message: "Configuration must include at least one specification. Each specification should have 'input' and 'output' paths."
|
|
7502
|
+
}).refine((specs) => specs.every((spec) => spec.input && spec.output), {
|
|
7503
|
+
message: "Each specification must have both 'input' and 'output' paths defined"
|
|
7504
|
+
}),
|
|
7505
|
+
executionMode: import_zod2.z.enum(["parallel", "sequential"]).optional()
|
|
7506
|
+
});
|
|
7312
7507
|
async function loadConfig(configPath) {
|
|
7313
|
-
var _a;
|
|
7314
7508
|
const explorer = (0, import_cosmiconfig.cosmiconfig)("openapi-to-zod", {
|
|
7315
7509
|
searchPlaces: ["openapi-to-zod.config.ts", "openapi-to-zod.config.json", "package.json"],
|
|
7316
7510
|
loaders: {
|
|
@@ -7325,31 +7519,15 @@ async function loadConfig(configPath) {
|
|
|
7325
7519
|
}
|
|
7326
7520
|
if (!result || !result.config) {
|
|
7327
7521
|
throw new Error(
|
|
7328
|
-
configPath ? `Config file not found at: ${configPath}` : "No config file found. Searched for: openapi-to-zod.config.ts, openapi-to-zod.config.json, package.json (openapi-to-zod key)"
|
|
7522
|
+
configPath ? `Config file not found at: ${configPath}` : "No config file found. Searched for: openapi-to-zod.config.ts, openapi-to-zod.config.json, package.json (openapi-to-zod key)\nRun 'openapi-to-zod init' to create a new config file."
|
|
7329
7523
|
);
|
|
7330
7524
|
}
|
|
7331
7525
|
try {
|
|
7332
7526
|
const validatedConfig = ConfigFileSchema.parse(result.config);
|
|
7333
7527
|
return validatedConfig;
|
|
7334
7528
|
} catch (error) {
|
|
7335
|
-
if (error instanceof
|
|
7336
|
-
const
|
|
7337
|
-
const path = err.path.length > 0 ? err.path.join(".") : "root";
|
|
7338
|
-
return ` - ${path}: ${err.message}`;
|
|
7339
|
-
}).join("\n")) || "Unknown validation error";
|
|
7340
|
-
const configSource = result.filepath || configPath || "config file";
|
|
7341
|
-
const errorMessage = [
|
|
7342
|
-
`Invalid configuration file at: ${configSource}`,
|
|
7343
|
-
"",
|
|
7344
|
-
"Validation errors:",
|
|
7345
|
-
formattedErrors,
|
|
7346
|
-
"",
|
|
7347
|
-
"Please check your configuration file and ensure:",
|
|
7348
|
-
" - All required fields are present (specs array with input/output)",
|
|
7349
|
-
" - Field names are spelled correctly (no typos)",
|
|
7350
|
-
" - Values match the expected types (e.g., mode: 'strict' | 'normal' | 'loose')",
|
|
7351
|
-
" - No unknown/extra properties are included"
|
|
7352
|
-
].join("\n");
|
|
7529
|
+
if (error instanceof import_zod2.z.ZodError) {
|
|
7530
|
+
const errorMessage = formatConfigValidationError(error, result.filepath, configPath);
|
|
7353
7531
|
throw new Error(errorMessage);
|
|
7354
7532
|
}
|
|
7355
7533
|
throw error;
|
|
@@ -7384,17 +7562,13 @@ program.name("openapi-to-zod").description("Generate Zod v4 schemas from OpenAPI
|
|
|
7384
7562
|
`
|
|
7385
7563
|
Examples:
|
|
7386
7564
|
# Create a new config file
|
|
7387
|
-
$ openapi-to-zod
|
|
7565
|
+
$ openapi-to-zod init
|
|
7388
7566
|
|
|
7389
7567
|
# Generate with auto-discovered config
|
|
7390
7568
|
$ openapi-to-zod
|
|
7391
7569
|
|
|
7392
7570
|
# Generate with custom config path
|
|
7393
7571
|
$ openapi-to-zod --config custom.config.ts
|
|
7394
|
-
|
|
7395
|
-
Breaking Changes (v2.0):
|
|
7396
|
-
CLI options removed. Use configuration file instead.
|
|
7397
|
-
Run 'openapi-to-zod --init' to create a config file.
|
|
7398
7572
|
`
|
|
7399
7573
|
).action(async (options) => {
|
|
7400
7574
|
try {
|
|
@@ -7451,17 +7625,12 @@ function findSpecFiles() {
|
|
|
7451
7625
|
return { files, totalCount };
|
|
7452
7626
|
}
|
|
7453
7627
|
async function executeConfigMode(options) {
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
config = await loadConfig(options.config);
|
|
7457
|
-
} catch {
|
|
7458
|
-
throw new CliOptionsError("No config file found. Run 'openapi-to-zod --init' to create one.", {
|
|
7459
|
-
configPath: options.config
|
|
7460
|
-
});
|
|
7461
|
-
}
|
|
7628
|
+
var _a, _b;
|
|
7629
|
+
const config = await loadConfig(options.config);
|
|
7462
7630
|
const specs = mergeConfigWithDefaults(config);
|
|
7463
7631
|
const executionMode = config.executionMode || "parallel";
|
|
7464
|
-
const
|
|
7632
|
+
const batchSize = (_b = (_a = specs[0]) == null ? void 0 : _a.batchSize) != null ? _b : 10;
|
|
7633
|
+
const summary = await executeBatch(specs, executionMode, (spec) => new OpenApiGenerator(spec), batchSize);
|
|
7465
7634
|
const exitCode = getBatchExitCode(summary);
|
|
7466
7635
|
if (exitCode !== 0) {
|
|
7467
7636
|
process.exit(exitCode);
|
|
@@ -7585,7 +7754,7 @@ export default defineConfig({
|
|
|
7585
7754
|
mode: 'strict',
|
|
7586
7755
|
includeDescriptions: true,
|
|
7587
7756
|
useDescribe: false,
|
|
7588
|
-
showStats:
|
|
7757
|
+
showStats: true,
|
|
7589
7758
|
schemaType: 'all',
|
|
7590
7759
|
},
|
|
7591
7760
|
specs: [
|