@cerios/openapi-to-zod 0.5.3 → 1.0.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 +275 -65
- package/dist/cli.js +290 -489
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +344 -525
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +9 -420
- package/dist/index.d.ts +9 -420
- package/dist/index.js +90 -325
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +89 -320
- package/dist/index.mjs.map +1 -1
- package/dist/internal.d.mts +200 -0
- package/dist/internal.d.ts +200 -0
- package/dist/internal.js +464 -0
- package/dist/internal.js.map +1 -0
- package/dist/internal.mjs +422 -0
- package/dist/internal.mjs.map +1 -0
- package/dist/types-BjoP91vk.d.mts +314 -0
- package/dist/types-BjoP91vk.d.ts +314 -0
- package/package.json +21 -10
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
|
|
@@ -5054,34 +5167,11 @@ function resolveRef(ref) {
|
|
|
5054
5167
|
|
|
5055
5168
|
// src/generators/enum-generator.ts
|
|
5056
5169
|
function generateEnum(name, values, options) {
|
|
5057
|
-
const enumName = name.endsWith("EnumOptions") ? name.replace("EnumOptions", "Enum") : `${name}Enum`;
|
|
5058
5170
|
const schemaName = `${toCamelCase(name, options)}Schema`;
|
|
5059
|
-
if (options.enumType === "typescript") {
|
|
5060
|
-
const usedKeys = /* @__PURE__ */ new Set();
|
|
5061
|
-
const enumEntries = values.map((value) => {
|
|
5062
|
-
let key = toPascalCase(value);
|
|
5063
|
-
if (usedKeys.has(key)) {
|
|
5064
|
-
let counter = 2;
|
|
5065
|
-
while (usedKeys.has(`${key}${counter}`)) {
|
|
5066
|
-
counter++;
|
|
5067
|
-
}
|
|
5068
|
-
key = `${key}${counter}`;
|
|
5069
|
-
}
|
|
5070
|
-
usedKeys.add(key);
|
|
5071
|
-
const stringValue = typeof value === "string" ? `"${value}"` : value;
|
|
5072
|
-
return ` ${key} = ${stringValue},`;
|
|
5073
|
-
}).join("\n");
|
|
5074
|
-
const enumCode = `export enum ${enumName} {
|
|
5075
|
-
${enumEntries}
|
|
5076
|
-
}`;
|
|
5077
|
-
const schemaCode2 = `export const ${schemaName} = z.nativeEnum(${enumName});`;
|
|
5078
|
-
const typeCode2 = `export type ${name} = z.infer<typeof ${schemaName}>;`;
|
|
5079
|
-
return { enumCode, schemaCode: schemaCode2, typeCode: typeCode2 };
|
|
5080
|
-
}
|
|
5081
5171
|
const enumValues = values.map((v) => `"${v}"`).join(", ");
|
|
5082
5172
|
const schemaCode = `export const ${schemaName} = z.enum([${enumValues}]);`;
|
|
5083
5173
|
const typeCode = `export type ${name} = z.infer<typeof ${schemaName}>;`;
|
|
5084
|
-
return {
|
|
5174
|
+
return { schemaCode, typeCode };
|
|
5085
5175
|
}
|
|
5086
5176
|
|
|
5087
5177
|
// src/generators/jsdoc-generator.ts
|
|
@@ -5188,6 +5278,9 @@ var LRUCache = class {
|
|
|
5188
5278
|
this.cache = /* @__PURE__ */ new Map();
|
|
5189
5279
|
this.maxSize = maxSize;
|
|
5190
5280
|
}
|
|
5281
|
+
get capacity() {
|
|
5282
|
+
return this.maxSize;
|
|
5283
|
+
}
|
|
5191
5284
|
get(key) {
|
|
5192
5285
|
if (!this.cache.has(key)) return void 0;
|
|
5193
5286
|
const value = this.cache.get(key);
|
|
@@ -5745,6 +5838,11 @@ ${properties.join(",\n")}
|
|
|
5745
5838
|
// src/validators/string-validator.ts
|
|
5746
5839
|
init_cjs_shims();
|
|
5747
5840
|
var PATTERN_CACHE = new LRUCache(1e3);
|
|
5841
|
+
function configurePatternCache(size) {
|
|
5842
|
+
if (size > 0 && size !== PATTERN_CACHE.capacity) {
|
|
5843
|
+
PATTERN_CACHE = new LRUCache(size);
|
|
5844
|
+
}
|
|
5845
|
+
}
|
|
5748
5846
|
var FORMAT_MAP = {
|
|
5749
5847
|
uuid: "z.uuid()",
|
|
5750
5848
|
email: "z.email()",
|
|
@@ -6362,14 +6460,11 @@ var OpenApiGenerator = class {
|
|
|
6362
6460
|
constructor(options) {
|
|
6363
6461
|
this.schemas = /* @__PURE__ */ new Map();
|
|
6364
6462
|
this.types = /* @__PURE__ */ new Map();
|
|
6365
|
-
this.enums = /* @__PURE__ */ new Map();
|
|
6366
|
-
this.nativeEnums = /* @__PURE__ */ new Map();
|
|
6367
6463
|
this.schemaDependencies = /* @__PURE__ */ new Map();
|
|
6368
6464
|
this.schemaUsageMap = /* @__PURE__ */ new Map();
|
|
6369
|
-
this.
|
|
6370
|
-
this.needsZodImport = false;
|
|
6465
|
+
this.needsZodImport = true;
|
|
6371
6466
|
this.filterStats = createFilterStatistics();
|
|
6372
|
-
var _a, _b, _c;
|
|
6467
|
+
var _a, _b, _c, _d, _e;
|
|
6373
6468
|
if (!options.input) {
|
|
6374
6469
|
throw new ConfigurationError("Input path is required", { providedOptions: options });
|
|
6375
6470
|
}
|
|
@@ -6378,17 +6473,21 @@ var OpenApiGenerator = class {
|
|
|
6378
6473
|
input: options.input,
|
|
6379
6474
|
output: options.output,
|
|
6380
6475
|
includeDescriptions: (_a = options.includeDescriptions) != null ? _a : true,
|
|
6381
|
-
enumType: options.enumType || "zod",
|
|
6382
6476
|
useDescribe: (_b = options.useDescribe) != null ? _b : false,
|
|
6383
6477
|
schemaType: options.schemaType || "all",
|
|
6384
6478
|
prefix: options.prefix,
|
|
6385
6479
|
suffix: options.suffix,
|
|
6386
6480
|
showStats: (_c = options.showStats) != null ? _c : true,
|
|
6387
|
-
nativeEnumType: options.nativeEnumType || "union",
|
|
6388
6481
|
request: options.request,
|
|
6389
6482
|
response: options.response,
|
|
6390
|
-
operationFilters: options.operationFilters
|
|
6483
|
+
operationFilters: options.operationFilters,
|
|
6484
|
+
ignoreHeaders: options.ignoreHeaders,
|
|
6485
|
+
cacheSize: (_d = options.cacheSize) != null ? _d : 1e3,
|
|
6486
|
+
batchSize: (_e = options.batchSize) != null ? _e : 10
|
|
6391
6487
|
};
|
|
6488
|
+
if (this.options.cacheSize) {
|
|
6489
|
+
configurePatternCache(this.options.cacheSize);
|
|
6490
|
+
}
|
|
6392
6491
|
try {
|
|
6393
6492
|
const fs = require("fs");
|
|
6394
6493
|
if (!fs.existsSync(this.options.input)) {
|
|
@@ -6444,7 +6543,6 @@ var OpenApiGenerator = class {
|
|
|
6444
6543
|
this.requestOptions = this.resolveOptionsForContext("request");
|
|
6445
6544
|
this.responseOptions = this.resolveOptionsForContext("response");
|
|
6446
6545
|
this.analyzeSchemaUsage();
|
|
6447
|
-
this.determineSchemaTypeModes();
|
|
6448
6546
|
this.propertyGenerator = new PropertyGenerator({
|
|
6449
6547
|
spec: this.spec,
|
|
6450
6548
|
schemaDependencies: this.schemaDependencies,
|
|
@@ -6452,8 +6550,6 @@ var OpenApiGenerator = class {
|
|
|
6452
6550
|
mode: this.requestOptions.mode,
|
|
6453
6551
|
includeDescriptions: this.requestOptions.includeDescriptions,
|
|
6454
6552
|
useDescribe: this.requestOptions.useDescribe,
|
|
6455
|
-
typeMode: this.requestOptions.typeMode,
|
|
6456
|
-
nativeEnumType: this.requestOptions.nativeEnumType,
|
|
6457
6553
|
namingOptions: {
|
|
6458
6554
|
prefix: this.options.prefix,
|
|
6459
6555
|
suffix: this.options.suffix
|
|
@@ -6469,25 +6565,6 @@ var OpenApiGenerator = class {
|
|
|
6469
6565
|
if (!((_a = this.spec.components) == null ? void 0 : _a.schemas)) {
|
|
6470
6566
|
throw new SpecValidationError("No schemas found in OpenAPI spec", { filePath: this.options.input });
|
|
6471
6567
|
}
|
|
6472
|
-
for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
|
|
6473
|
-
if (schema.enum) {
|
|
6474
|
-
const context = this.schemaUsageMap.get(name);
|
|
6475
|
-
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
6476
|
-
if (resolvedOptions.enumType === "typescript") {
|
|
6477
|
-
this.generateNativeEnum(name, schema);
|
|
6478
|
-
} else {
|
|
6479
|
-
const { enumCode } = generateEnum(name, schema.enum, {
|
|
6480
|
-
enumType: "zod",
|
|
6481
|
-
prefix: this.options.prefix,
|
|
6482
|
-
suffix: this.options.suffix
|
|
6483
|
-
});
|
|
6484
|
-
if (enumCode) {
|
|
6485
|
-
this.enums.set(name, enumCode);
|
|
6486
|
-
this.needsZodImport = true;
|
|
6487
|
-
}
|
|
6488
|
-
}
|
|
6489
|
-
}
|
|
6490
|
-
}
|
|
6491
6568
|
for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
|
|
6492
6569
|
this.generateComponentSchema(name, schema);
|
|
6493
6570
|
}
|
|
@@ -6504,22 +6581,11 @@ var OpenApiGenerator = class {
|
|
|
6504
6581
|
output.push('import { z } from "zod";');
|
|
6505
6582
|
output.push("");
|
|
6506
6583
|
}
|
|
6507
|
-
if (this.nativeEnums.size > 0) {
|
|
6508
|
-
output.push("// Native Enums");
|
|
6509
|
-
for (const enumCode of this.nativeEnums.values()) {
|
|
6510
|
-
output.push(enumCode);
|
|
6511
|
-
output.push("");
|
|
6512
|
-
}
|
|
6513
|
-
}
|
|
6514
6584
|
output.push("// Schemas and Types");
|
|
6515
6585
|
for (const name of orderedSchemaNames) {
|
|
6516
|
-
const enumCode = this.enums.get(name);
|
|
6517
6586
|
const schemaCode = this.schemas.get(name);
|
|
6518
6587
|
const typeCode = this.types.get(name);
|
|
6519
|
-
if (
|
|
6520
|
-
output.push(enumCode);
|
|
6521
|
-
output.push("");
|
|
6522
|
-
} else if (schemaCode) {
|
|
6588
|
+
if (schemaCode) {
|
|
6523
6589
|
output.push(schemaCode);
|
|
6524
6590
|
if (!schemaCode.includes(`export type ${name}`)) {
|
|
6525
6591
|
const schemaName = `${toCamelCase(name, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
|
|
@@ -6557,25 +6623,19 @@ var OpenApiGenerator = class {
|
|
|
6557
6623
|
const normalizedOutput = (0, import_node_path.normalize)(this.options.output);
|
|
6558
6624
|
this.ensureDirectoryExists(normalizedOutput);
|
|
6559
6625
|
(0, import_node_fs.writeFileSync)(normalizedOutput, output);
|
|
6626
|
+
console.log(` \u2713 Generated ${normalizedOutput}`);
|
|
6560
6627
|
}
|
|
6561
6628
|
/**
|
|
6562
6629
|
* Resolve options for a specific context (request or response)
|
|
6563
6630
|
* Nested options silently override root-level options
|
|
6564
|
-
* Response schemas always use 'inferred' mode (Zod schemas)
|
|
6565
6631
|
*/
|
|
6566
6632
|
resolveOptionsForContext(context) {
|
|
6567
|
-
var _a, _b, _c, _d, _e, _f
|
|
6633
|
+
var _a, _b, _c, _d, _e, _f;
|
|
6568
6634
|
const contextOptions = context === "request" ? this.options.request : this.options.response;
|
|
6569
|
-
const nativeEnumType = context === "request" ? (_c = (_b = (_a = this.options.request) == null ? void 0 : _a.nativeEnumType) != null ? _b : this.options.nativeEnumType) != null ? _c : "union" : (_d = this.options.nativeEnumType) != null ? _d : "union";
|
|
6570
6635
|
return {
|
|
6571
|
-
mode: (
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
includeDescriptions: (_l = (_k = contextOptions == null ? void 0 : contextOptions.includeDescriptions) != null ? _k : this.options.includeDescriptions) != null ? _l : true,
|
|
6575
|
-
// Response schemas always use 'inferred' mode (Zod schemas are required)
|
|
6576
|
-
// Request schemas can optionally use 'native' mode
|
|
6577
|
-
typeMode: context === "response" ? "inferred" : (_n = (_m = this.options.request) == null ? void 0 : _m.typeMode) != null ? _n : "inferred",
|
|
6578
|
-
nativeEnumType
|
|
6636
|
+
mode: (_b = (_a = contextOptions == null ? void 0 : contextOptions.mode) != null ? _a : this.options.mode) != null ? _b : "normal",
|
|
6637
|
+
useDescribe: (_d = (_c = contextOptions == null ? void 0 : contextOptions.useDescribe) != null ? _c : this.options.useDescribe) != null ? _d : false,
|
|
6638
|
+
includeDescriptions: (_f = (_e = contextOptions == null ? void 0 : contextOptions.includeDescriptions) != null ? _e : this.options.includeDescriptions) != null ? _f : true
|
|
6579
6639
|
};
|
|
6580
6640
|
}
|
|
6581
6641
|
/**
|
|
@@ -6766,28 +6826,6 @@ var OpenApiGenerator = class {
|
|
|
6766
6826
|
detectCycle(name);
|
|
6767
6827
|
}
|
|
6768
6828
|
}
|
|
6769
|
-
/**
|
|
6770
|
-
* Determine the typeMode for each schema based on its usage context
|
|
6771
|
-
* Response schemas always use 'inferred' mode
|
|
6772
|
-
*/
|
|
6773
|
-
determineSchemaTypeModes() {
|
|
6774
|
-
var _a;
|
|
6775
|
-
for (const [name] of Object.entries(((_a = this.spec.components) == null ? void 0 : _a.schemas) || {})) {
|
|
6776
|
-
const context = this.schemaUsageMap.get(name);
|
|
6777
|
-
if (context === "request") {
|
|
6778
|
-
this.schemaTypeModeMap.set(name, this.requestOptions.typeMode);
|
|
6779
|
-
} else if (context === "response") {
|
|
6780
|
-
this.schemaTypeModeMap.set(name, "inferred");
|
|
6781
|
-
} else if (context === "both") {
|
|
6782
|
-
this.schemaTypeModeMap.set(name, "inferred");
|
|
6783
|
-
} else {
|
|
6784
|
-
this.schemaTypeModeMap.set(name, "inferred");
|
|
6785
|
-
}
|
|
6786
|
-
if (this.schemaTypeModeMap.get(name) === "inferred") {
|
|
6787
|
-
this.needsZodImport = true;
|
|
6788
|
-
}
|
|
6789
|
-
}
|
|
6790
|
-
}
|
|
6791
6829
|
/**
|
|
6792
6830
|
* Validate the OpenAPI specification
|
|
6793
6831
|
*/
|
|
@@ -6863,80 +6901,54 @@ var OpenApiGenerator = class {
|
|
|
6863
6901
|
if (!this.schemaDependencies.has(name)) {
|
|
6864
6902
|
this.schemaDependencies.set(name, /* @__PURE__ */ new Set());
|
|
6865
6903
|
}
|
|
6866
|
-
const typeMode = this.schemaTypeModeMap.get(name) || "inferred";
|
|
6867
6904
|
const context = this.schemaUsageMap.get(name);
|
|
6868
6905
|
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
6869
6906
|
if (schema.enum) {
|
|
6870
|
-
const
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
});
|
|
6877
|
-
const enumSchemaCode = `${jsdoc}${schemaCode}
|
|
6878
|
-
${typeCode}`;
|
|
6879
|
-
this.schemas.set(name, enumSchemaCode);
|
|
6880
|
-
} else {
|
|
6881
|
-
const { enumCode, schemaCode, typeCode } = generateEnum(name, schema.enum, {
|
|
6882
|
-
enumType: "zod",
|
|
6883
|
-
prefix: this.options.prefix,
|
|
6884
|
-
suffix: this.options.suffix
|
|
6885
|
-
});
|
|
6886
|
-
if (enumCode) {
|
|
6887
|
-
this.enums.set(name, enumCode);
|
|
6888
|
-
}
|
|
6889
|
-
const enumSchemaCode = `${jsdoc}${schemaCode}
|
|
6907
|
+
const jsdoc2 = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
6908
|
+
const { schemaCode, typeCode } = generateEnum(name, schema.enum, {
|
|
6909
|
+
prefix: this.options.prefix,
|
|
6910
|
+
suffix: this.options.suffix
|
|
6911
|
+
});
|
|
6912
|
+
const enumSchemaCode = `${jsdoc2}${schemaCode}
|
|
6890
6913
|
${typeCode}`;
|
|
6891
|
-
|
|
6892
|
-
}
|
|
6914
|
+
this.schemas.set(name, enumSchemaCode);
|
|
6893
6915
|
return;
|
|
6894
6916
|
}
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
const
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
if (zodSchema.includes("z.discriminatedUnion(")) {
|
|
6926
|
-
const match = zodSchema.match(/z\.discriminatedUnion\([^,]+,\s*\[([^\]]+)\]/);
|
|
6927
|
-
if (match) {
|
|
6928
|
-
const refs = match[1].split(",").map((ref) => ref.trim());
|
|
6929
|
-
for (const ref of refs) {
|
|
6930
|
-
const depMatch = ref.match(/^([a-z][a-zA-Z0-9]*?)Schema$/);
|
|
6931
|
-
if (depMatch) {
|
|
6932
|
-
const depName = depMatch[1].charAt(0).toUpperCase() + depMatch[1].slice(1);
|
|
6933
|
-
(_b = this.schemaDependencies.get(name)) == null ? void 0 : _b.add(depName);
|
|
6934
|
-
}
|
|
6917
|
+
const schemaName = `${toCamelCase(name, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
|
|
6918
|
+
const jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
6919
|
+
if (schema.allOf && schema.allOf.length === 1 && schema.allOf[0].$ref) {
|
|
6920
|
+
const refName = resolveRef(schema.allOf[0].$ref);
|
|
6921
|
+
(_a = this.schemaDependencies.get(name)) == null ? void 0 : _a.add(refName);
|
|
6922
|
+
}
|
|
6923
|
+
this.propertyGenerator = new PropertyGenerator({
|
|
6924
|
+
spec: this.spec,
|
|
6925
|
+
schemaDependencies: this.schemaDependencies,
|
|
6926
|
+
schemaType: this.options.schemaType || "all",
|
|
6927
|
+
mode: resolvedOptions.mode,
|
|
6928
|
+
includeDescriptions: resolvedOptions.includeDescriptions,
|
|
6929
|
+
useDescribe: resolvedOptions.useDescribe,
|
|
6930
|
+
namingOptions: {
|
|
6931
|
+
prefix: this.options.prefix,
|
|
6932
|
+
suffix: this.options.suffix
|
|
6933
|
+
}
|
|
6934
|
+
});
|
|
6935
|
+
const isAlias = !!(schema.$ref && !schema.properties && !schema.allOf && !schema.oneOf && !schema.anyOf);
|
|
6936
|
+
const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, isAlias);
|
|
6937
|
+
const zodSchemaCode = `${jsdoc}export const ${schemaName} = ${zodSchema};`;
|
|
6938
|
+
if (zodSchema.includes("z.discriminatedUnion(")) {
|
|
6939
|
+
const match = zodSchema.match(/z\.discriminatedUnion\([^,]+,\s*\[([^\]]+)\]/);
|
|
6940
|
+
if (match) {
|
|
6941
|
+
const refs = match[1].split(",").map((ref) => ref.trim());
|
|
6942
|
+
for (const ref of refs) {
|
|
6943
|
+
const depMatch = ref.match(/^([a-z][a-zA-Z0-9]*?)Schema$/);
|
|
6944
|
+
if (depMatch) {
|
|
6945
|
+
const depName = depMatch[1].charAt(0).toUpperCase() + depMatch[1].slice(1);
|
|
6946
|
+
(_b = this.schemaDependencies.get(name)) == null ? void 0 : _b.add(depName);
|
|
6935
6947
|
}
|
|
6936
6948
|
}
|
|
6937
6949
|
}
|
|
6938
|
-
this.schemas.set(name, zodSchemaCode);
|
|
6939
6950
|
}
|
|
6951
|
+
this.schemas.set(name, zodSchemaCode);
|
|
6940
6952
|
}
|
|
6941
6953
|
/**
|
|
6942
6954
|
* Generate query parameter schemas for each operation
|
|
@@ -7022,6 +7034,24 @@ ${propsCode}
|
|
|
7022
7034
|
}
|
|
7023
7035
|
}
|
|
7024
7036
|
}
|
|
7037
|
+
/**
|
|
7038
|
+
* Check if a header should be ignored based on filter patterns
|
|
7039
|
+
* @internal
|
|
7040
|
+
*/
|
|
7041
|
+
shouldIgnoreHeader(headerName) {
|
|
7042
|
+
const ignorePatterns = this.options.ignoreHeaders;
|
|
7043
|
+
if (!ignorePatterns || ignorePatterns.length === 0) {
|
|
7044
|
+
return false;
|
|
7045
|
+
}
|
|
7046
|
+
if (ignorePatterns.includes("*")) {
|
|
7047
|
+
return true;
|
|
7048
|
+
}
|
|
7049
|
+
const headerLower = headerName.toLowerCase();
|
|
7050
|
+
return ignorePatterns.some((pattern) => {
|
|
7051
|
+
const patternLower = pattern.toLowerCase();
|
|
7052
|
+
return (0, import_minimatch2.minimatch)(headerLower, patternLower);
|
|
7053
|
+
});
|
|
7054
|
+
}
|
|
7025
7055
|
/**
|
|
7026
7056
|
* Generate header parameter schemas for each operation
|
|
7027
7057
|
* Header parameters are always string type (HTTP header semantics)
|
|
@@ -7044,7 +7074,7 @@ ${propsCode}
|
|
|
7044
7074
|
continue;
|
|
7045
7075
|
}
|
|
7046
7076
|
const headerParams = operation.parameters.filter(
|
|
7047
|
-
(param) => param && typeof param === "object" && param.in === "header"
|
|
7077
|
+
(param) => param && typeof param === "object" && param.in === "header" && !this.shouldIgnoreHeader(param.name)
|
|
7048
7078
|
);
|
|
7049
7079
|
if (headerParams.length === 0) {
|
|
7050
7080
|
continue;
|
|
@@ -7142,151 +7172,11 @@ ${propsCode}
|
|
|
7142
7172
|
}
|
|
7143
7173
|
return "z.unknown()";
|
|
7144
7174
|
}
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
const context = this.schemaUsageMap.get(name);
|
|
7151
|
-
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
7152
|
-
const jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
7153
|
-
if (resolvedOptions.nativeEnumType === "enum") {
|
|
7154
|
-
const enumName = `${name}Enum`;
|
|
7155
|
-
const members = schema.enum.map((value) => {
|
|
7156
|
-
const key = typeof value === "string" ? this.toEnumKey(value) : `N${value}`;
|
|
7157
|
-
const val = typeof value === "string" ? `"${value}"` : value;
|
|
7158
|
-
return ` ${key} = ${val}`;
|
|
7159
|
-
}).join(",\n");
|
|
7160
|
-
const enumCode = `${jsdoc}export enum ${enumName} {
|
|
7161
|
-
${members}
|
|
7162
|
-
}`;
|
|
7163
|
-
this.nativeEnums.set(name, enumCode);
|
|
7164
|
-
const typeCode = `export type ${name} = ${enumName};`;
|
|
7165
|
-
this.types.set(name, typeCode);
|
|
7166
|
-
} else {
|
|
7167
|
-
const unionType = schema.enum.map((v) => typeof v === "string" ? `"${v}"` : v).join(" | ");
|
|
7168
|
-
const typeCode = `${jsdoc}export type ${name} = ${unionType};`;
|
|
7169
|
-
this.types.set(name, typeCode);
|
|
7170
|
-
}
|
|
7171
|
-
}
|
|
7172
|
-
/**
|
|
7173
|
-
* Convert string to valid enum key
|
|
7174
|
-
*/
|
|
7175
|
-
toEnumKey(value) {
|
|
7176
|
-
const cleaned = value.replace(/[^a-zA-Z0-9]/g, "_");
|
|
7177
|
-
const pascalCase = cleaned.split("_").map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
|
|
7178
|
-
return pascalCase || "Value";
|
|
7179
|
-
}
|
|
7180
|
-
/**
|
|
7181
|
-
* Add constraint annotations to JSDoc for native types
|
|
7182
|
-
*/
|
|
7183
|
-
addConstraintsToJSDoc(jsdoc, schema, includeDescriptions) {
|
|
7184
|
-
if (!includeDescriptions) return jsdoc;
|
|
7185
|
-
const constraints = [];
|
|
7186
|
-
if (schema.minLength !== void 0) constraints.push(`@minLength ${schema.minLength}`);
|
|
7187
|
-
if (schema.maxLength !== void 0) constraints.push(`@maxLength ${schema.maxLength}`);
|
|
7188
|
-
if (schema.pattern) constraints.push(`@pattern ${schema.pattern}`);
|
|
7189
|
-
if (schema.minimum !== void 0) constraints.push(`@minimum ${schema.minimum}`);
|
|
7190
|
-
if (schema.maximum !== void 0) constraints.push(`@maximum ${schema.maximum}`);
|
|
7191
|
-
if (schema.minItems !== void 0) constraints.push(`@minItems ${schema.minItems}`);
|
|
7192
|
-
if (schema.maxItems !== void 0) constraints.push(`@maxItems ${schema.maxItems}`);
|
|
7193
|
-
if (schema.minProperties !== void 0) constraints.push(`@minProperties ${schema.minProperties}`);
|
|
7194
|
-
if (schema.maxProperties !== void 0) constraints.push(`@maxProperties ${schema.maxProperties}`);
|
|
7195
|
-
if (schema.multipleOf !== void 0) constraints.push(`@multipleOf ${schema.multipleOf}`);
|
|
7196
|
-
if (schema.format) constraints.push(`@format ${schema.format}`);
|
|
7197
|
-
if (constraints.length === 0) return jsdoc;
|
|
7198
|
-
if (jsdoc) {
|
|
7199
|
-
const lines = jsdoc.trim().split("\n");
|
|
7200
|
-
if (lines[0] === "/**" && lines[lines.length - 1] === " */") {
|
|
7201
|
-
const newLines = [...lines.slice(0, -1), ...constraints.map((c) => ` * ${c}`), " */\n"];
|
|
7202
|
-
return newLines.join("\n");
|
|
7203
|
-
}
|
|
7204
|
-
const content = jsdoc.replace("/** ", "").replace(" */\n", "");
|
|
7205
|
-
return `/**
|
|
7206
|
-
* ${content}
|
|
7207
|
-
${constraints.map((c) => ` * ${c}`).join("\n")}
|
|
7208
|
-
*/
|
|
7209
|
-
`;
|
|
7210
|
-
}
|
|
7211
|
-
return `/**
|
|
7212
|
-
${constraints.map((c) => ` * ${c}`).join("\n")}
|
|
7213
|
-
*/
|
|
7214
|
-
`;
|
|
7215
|
-
}
|
|
7216
|
-
/**
|
|
7217
|
-
* Generate native TypeScript type definition from OpenAPI schema
|
|
7218
|
-
*/
|
|
7219
|
-
generateNativeTypeDefinition(schema, _schemaName) {
|
|
7220
|
-
if (schema.$ref) {
|
|
7221
|
-
return resolveRef(schema.$ref);
|
|
7222
|
-
}
|
|
7223
|
-
if (schema.const !== void 0) {
|
|
7224
|
-
return typeof schema.const === "string" ? `"${schema.const}"` : String(schema.const);
|
|
7225
|
-
}
|
|
7226
|
-
const isNullable2 = schema.nullable || Array.isArray(schema.type) && schema.type.includes("null");
|
|
7227
|
-
const wrapNullable2 = (type) => isNullable2 ? `(${type}) | null` : type;
|
|
7228
|
-
const primaryType = Array.isArray(schema.type) ? schema.type.find((t) => t !== "null") : schema.type;
|
|
7229
|
-
switch (primaryType) {
|
|
7230
|
-
case "string":
|
|
7231
|
-
return wrapNullable2("string");
|
|
7232
|
-
case "number":
|
|
7233
|
-
case "integer":
|
|
7234
|
-
return wrapNullable2("number");
|
|
7235
|
-
case "boolean":
|
|
7236
|
-
return wrapNullable2("boolean");
|
|
7237
|
-
case "array":
|
|
7238
|
-
if (schema.items) {
|
|
7239
|
-
const itemType = this.generateNativeTypeDefinition(schema.items);
|
|
7240
|
-
return wrapNullable2(`${itemType}[]`);
|
|
7241
|
-
}
|
|
7242
|
-
return wrapNullable2("unknown[]");
|
|
7243
|
-
case "object":
|
|
7244
|
-
return wrapNullable2(this.generateObjectType(schema));
|
|
7245
|
-
default:
|
|
7246
|
-
if (schema.allOf) {
|
|
7247
|
-
const types = schema.allOf.map((s) => this.generateNativeTypeDefinition(s));
|
|
7248
|
-
return wrapNullable2(types.join(" & "));
|
|
7249
|
-
}
|
|
7250
|
-
if (schema.oneOf || schema.anyOf) {
|
|
7251
|
-
const schemas = schema.oneOf || schema.anyOf || [];
|
|
7252
|
-
const types = schemas.map((s) => this.generateNativeTypeDefinition(s));
|
|
7253
|
-
return wrapNullable2(types.join(" | "));
|
|
7254
|
-
}
|
|
7255
|
-
return wrapNullable2("unknown");
|
|
7256
|
-
}
|
|
7257
|
-
}
|
|
7258
|
-
/**
|
|
7259
|
-
* Generate TypeScript object type definition
|
|
7260
|
-
*/
|
|
7261
|
-
generateObjectType(schema) {
|
|
7262
|
-
if (!schema.properties || Object.keys(schema.properties).length === 0) {
|
|
7263
|
-
return "Record<string, unknown>";
|
|
7264
|
-
}
|
|
7265
|
-
const context = this.schemaUsageMap.get(schema.$ref ? resolveRef(schema.$ref) : "");
|
|
7266
|
-
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
7267
|
-
const required = new Set(schema.required || []);
|
|
7268
|
-
const props = [];
|
|
7269
|
-
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
7270
|
-
const propType = this.generateNativeTypeDefinition(propSchema);
|
|
7271
|
-
const optional = !required.has(propName) ? "?" : "";
|
|
7272
|
-
let propJsdoc = generateJSDoc(propSchema, propName, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
7273
|
-
if (resolvedOptions.includeDescriptions && !propJsdoc) {
|
|
7274
|
-
propJsdoc = this.addConstraintsToJSDoc("", propSchema, resolvedOptions.includeDescriptions);
|
|
7275
|
-
} else if (propJsdoc && resolvedOptions.includeDescriptions) {
|
|
7276
|
-
propJsdoc = this.addConstraintsToJSDoc(propJsdoc, propSchema, resolvedOptions.includeDescriptions);
|
|
7277
|
-
}
|
|
7278
|
-
if (propJsdoc) {
|
|
7279
|
-
const cleanJsdoc = propJsdoc.trimEnd();
|
|
7280
|
-
props.push(` ${cleanJsdoc}
|
|
7281
|
-
${propName}${optional}: ${propType};`);
|
|
7282
|
-
} else {
|
|
7283
|
-
props.push(` ${propName}${optional}: ${propType};`);
|
|
7284
|
-
}
|
|
7285
|
-
}
|
|
7286
|
-
return `{
|
|
7287
|
-
${props.join("\n")}
|
|
7288
|
-
}`;
|
|
7289
|
-
}
|
|
7175
|
+
// REMOVED: generateNativeEnum method - no longer needed as we only generate Zod schemas
|
|
7176
|
+
// REMOVED: toEnumKey method - was only used by generateNativeEnum
|
|
7177
|
+
// REMOVED: addConstraintsToJSDoc method - was only used for native TypeScript types
|
|
7178
|
+
// REMOVED: generateNativeTypeDefinition method - was only used for native TypeScript types
|
|
7179
|
+
// REMOVED: generateObjectType method - was only used for native TypeScript types
|
|
7290
7180
|
/**
|
|
7291
7181
|
* Topological sort for schema dependencies
|
|
7292
7182
|
* Returns schemas in the order they should be declared
|
|
@@ -7298,9 +7188,6 @@ ${props.join("\n")}
|
|
|
7298
7188
|
const aliases = [];
|
|
7299
7189
|
const circularDeps = /* @__PURE__ */ new Set();
|
|
7300
7190
|
const codeCache = /* @__PURE__ */ new Map();
|
|
7301
|
-
for (const [name, code] of this.enums) {
|
|
7302
|
-
codeCache.set(name, code);
|
|
7303
|
-
}
|
|
7304
7191
|
for (const [name, code] of this.schemas) {
|
|
7305
7192
|
codeCache.set(name, code);
|
|
7306
7193
|
}
|
|
@@ -7325,7 +7212,7 @@ ${props.join("\n")}
|
|
|
7325
7212
|
const deps = this.schemaDependencies.get(name);
|
|
7326
7213
|
if (deps && deps.size > 0) {
|
|
7327
7214
|
for (const dep of deps) {
|
|
7328
|
-
if (this.
|
|
7215
|
+
if (this.schemas.has(dep) || this.types.has(dep)) {
|
|
7329
7216
|
visit(dep);
|
|
7330
7217
|
}
|
|
7331
7218
|
}
|
|
@@ -7336,7 +7223,7 @@ ${props.join("\n")}
|
|
|
7336
7223
|
sorted.push(name);
|
|
7337
7224
|
}
|
|
7338
7225
|
};
|
|
7339
|
-
const allNames = /* @__PURE__ */ new Set([...this.
|
|
7226
|
+
const allNames = /* @__PURE__ */ new Set([...this.schemas.keys(), ...this.types.keys()]);
|
|
7340
7227
|
for (const name of allNames) {
|
|
7341
7228
|
visit(name);
|
|
7342
7229
|
}
|
|
@@ -7354,7 +7241,6 @@ ${props.join("\n")}
|
|
|
7354
7241
|
generateStats() {
|
|
7355
7242
|
const stats = {
|
|
7356
7243
|
totalSchemas: this.schemas.size,
|
|
7357
|
-
enums: this.enums.size,
|
|
7358
7244
|
withCircularRefs: 0,
|
|
7359
7245
|
withDiscriminators: 0,
|
|
7360
7246
|
withConstraints: 0
|
|
@@ -7369,7 +7255,6 @@ ${props.join("\n")}
|
|
|
7369
7255
|
const output = [
|
|
7370
7256
|
"// Generation Statistics:",
|
|
7371
7257
|
`// Total schemas: ${stats.totalSchemas}`,
|
|
7372
|
-
`// Enums: ${stats.enums}`,
|
|
7373
7258
|
`// Circular references: ${stats.withCircularRefs}`,
|
|
7374
7259
|
`// Discriminated unions: ${stats.withDiscriminators}`,
|
|
7375
7260
|
`// With constraints: ${stats.withConstraints}`
|
|
@@ -7386,120 +7271,18 @@ ${props.join("\n")}
|
|
|
7386
7271
|
}
|
|
7387
7272
|
};
|
|
7388
7273
|
|
|
7389
|
-
// src/batch-executor.ts
|
|
7390
|
-
async function processSpec(spec, index, total) {
|
|
7391
|
-
console.log(`Processing [${index + 1}/${total}] ${spec.input}...`);
|
|
7392
|
-
try {
|
|
7393
|
-
const generator = new OpenApiGenerator(spec);
|
|
7394
|
-
generator.generate();
|
|
7395
|
-
console.log(`\u2713 Successfully generated ${spec.output}`);
|
|
7396
|
-
return {
|
|
7397
|
-
spec,
|
|
7398
|
-
success: true
|
|
7399
|
-
};
|
|
7400
|
-
} catch (error) {
|
|
7401
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
7402
|
-
console.error(`\u2717 Failed to generate ${spec.output}: ${errorMessage}`);
|
|
7403
|
-
return {
|
|
7404
|
-
spec,
|
|
7405
|
-
success: false,
|
|
7406
|
-
error: errorMessage
|
|
7407
|
-
};
|
|
7408
|
-
}
|
|
7409
|
-
}
|
|
7410
|
-
async function executeParallel(specs) {
|
|
7411
|
-
console.log(`
|
|
7412
|
-
Executing ${specs.length} spec(s) in parallel...
|
|
7413
|
-
`);
|
|
7414
|
-
const promises = specs.map((spec, index) => processSpec(spec, index, specs.length));
|
|
7415
|
-
const results = await Promise.allSettled(promises);
|
|
7416
|
-
return results.map((result, index) => {
|
|
7417
|
-
if (result.status === "fulfilled") {
|
|
7418
|
-
return result.value;
|
|
7419
|
-
}
|
|
7420
|
-
return {
|
|
7421
|
-
spec: specs[index],
|
|
7422
|
-
success: false,
|
|
7423
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
7424
|
-
};
|
|
7425
|
-
});
|
|
7426
|
-
}
|
|
7427
|
-
async function executeSequential(specs) {
|
|
7428
|
-
console.log(`
|
|
7429
|
-
Executing ${specs.length} spec(s) sequentially...
|
|
7430
|
-
`);
|
|
7431
|
-
const results = [];
|
|
7432
|
-
for (let i = 0; i < specs.length; i++) {
|
|
7433
|
-
const result = await processSpec(specs[i], i, specs.length);
|
|
7434
|
-
results.push(result);
|
|
7435
|
-
}
|
|
7436
|
-
return results;
|
|
7437
|
-
}
|
|
7438
|
-
function printSummary(summary) {
|
|
7439
|
-
console.log(`
|
|
7440
|
-
${"=".repeat(50)}`);
|
|
7441
|
-
console.log("Batch Execution Summary");
|
|
7442
|
-
console.log("=".repeat(50));
|
|
7443
|
-
console.log(`Total specs: ${summary.total}`);
|
|
7444
|
-
console.log(`Successful: ${summary.successful}`);
|
|
7445
|
-
console.log(`Failed: ${summary.failed}`);
|
|
7446
|
-
if (summary.failed > 0) {
|
|
7447
|
-
console.log("\nFailed specs:");
|
|
7448
|
-
for (const result of summary.results) {
|
|
7449
|
-
if (!result.success) {
|
|
7450
|
-
console.error(` \u2717 ${result.spec.input}`);
|
|
7451
|
-
console.error(` Error: ${result.error}`);
|
|
7452
|
-
}
|
|
7453
|
-
}
|
|
7454
|
-
}
|
|
7455
|
-
console.log(`${"=".repeat(50)}
|
|
7456
|
-
`);
|
|
7457
|
-
}
|
|
7458
|
-
async function executeBatch(specs, executionMode = "parallel") {
|
|
7459
|
-
if (specs.length === 0) {
|
|
7460
|
-
throw new ConfigurationError("No specs provided for batch execution", { specsCount: 0, executionMode });
|
|
7461
|
-
}
|
|
7462
|
-
let results = [];
|
|
7463
|
-
try {
|
|
7464
|
-
results = executionMode === "parallel" ? await executeParallel(specs) : await executeSequential(specs);
|
|
7465
|
-
const summary = {
|
|
7466
|
-
total: results.length,
|
|
7467
|
-
successful: results.filter((r) => r.success).length,
|
|
7468
|
-
failed: results.filter((r) => !r.success).length,
|
|
7469
|
-
results
|
|
7470
|
-
};
|
|
7471
|
-
printSummary(summary);
|
|
7472
|
-
return summary;
|
|
7473
|
-
} finally {
|
|
7474
|
-
if (results.length > 10) {
|
|
7475
|
-
for (const result of results) {
|
|
7476
|
-
if (result.spec) {
|
|
7477
|
-
result.spec = null;
|
|
7478
|
-
}
|
|
7479
|
-
}
|
|
7480
|
-
if (global.gc) {
|
|
7481
|
-
global.gc();
|
|
7482
|
-
}
|
|
7483
|
-
}
|
|
7484
|
-
}
|
|
7485
|
-
}
|
|
7486
|
-
function getBatchExitCode(summary) {
|
|
7487
|
-
return summary.failed > 0 ? 1 : 0;
|
|
7488
|
-
}
|
|
7489
|
-
|
|
7490
7274
|
// src/utils/config-loader.ts
|
|
7491
7275
|
init_cjs_shims();
|
|
7492
7276
|
var import_cosmiconfig = require("cosmiconfig");
|
|
7277
|
+
var import_zod2 = require("zod");
|
|
7278
|
+
|
|
7279
|
+
// src/utils/config-schemas.ts
|
|
7280
|
+
init_cjs_shims();
|
|
7493
7281
|
var import_zod = require("zod");
|
|
7494
|
-
var TypeModeSchema = import_zod.z.enum(["inferred", "native"]);
|
|
7495
|
-
var NativeEnumTypeSchema = import_zod.z.enum(["union", "enum"]);
|
|
7496
7282
|
var RequestResponseOptionsSchema = import_zod.z.strictObject({
|
|
7497
7283
|
mode: import_zod.z.enum(["strict", "normal", "loose"]).optional(),
|
|
7498
|
-
enumType: import_zod.z.enum(["zod", "typescript"]).optional(),
|
|
7499
7284
|
useDescribe: import_zod.z.boolean().optional(),
|
|
7500
|
-
includeDescriptions: import_zod.z.boolean().optional()
|
|
7501
|
-
typeMode: TypeModeSchema.optional(),
|
|
7502
|
-
nativeEnumType: NativeEnumTypeSchema.optional()
|
|
7285
|
+
includeDescriptions: import_zod.z.boolean().optional()
|
|
7503
7286
|
});
|
|
7504
7287
|
var OperationFiltersSchema = import_zod.z.strictObject({
|
|
7505
7288
|
includeTags: import_zod.z.array(import_zod.z.string()).optional(),
|
|
@@ -7512,42 +7295,37 @@ var OperationFiltersSchema = import_zod.z.strictObject({
|
|
|
7512
7295
|
excludeOperationIds: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7513
7296
|
excludeDeprecated: import_zod.z.boolean().optional()
|
|
7514
7297
|
});
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
mode:
|
|
7535
|
-
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7544
|
-
|
|
7545
|
-
|
|
7546
|
-
}).optional(),
|
|
7547
|
-
specs: import_zod.z.array(OpenApiGeneratorOptionsSchema).min(1, "At least one spec is required"),
|
|
7548
|
-
executionMode: import_zod.z.enum(["parallel", "sequential"]).optional()
|
|
7549
|
-
});
|
|
7550
|
-
var createTypeScriptLoader = () => {
|
|
7298
|
+
|
|
7299
|
+
// src/utils/config-validation.ts
|
|
7300
|
+
init_cjs_shims();
|
|
7301
|
+
function formatConfigValidationError(error, filepath, configPath, additionalNotes) {
|
|
7302
|
+
var _a;
|
|
7303
|
+
const formattedErrors = ((_a = error.issues) == null ? void 0 : _a.map((err) => {
|
|
7304
|
+
const path = err.path.length > 0 ? err.path.join(".") : "root";
|
|
7305
|
+
return ` - ${path}: ${err.message}`;
|
|
7306
|
+
}).join("\n")) || "Unknown validation error";
|
|
7307
|
+
const configSource = filepath || configPath || "config file";
|
|
7308
|
+
const lines = [
|
|
7309
|
+
`Invalid configuration file at: ${configSource}`,
|
|
7310
|
+
"",
|
|
7311
|
+
"Validation errors:",
|
|
7312
|
+
formattedErrors,
|
|
7313
|
+
"",
|
|
7314
|
+
"Please check your configuration file and ensure:",
|
|
7315
|
+
" - All required fields are present (specs array with input/output)",
|
|
7316
|
+
" - Field names are spelled correctly (no typos)",
|
|
7317
|
+
" - Values match the expected types (e.g., mode: 'strict' | 'normal' | 'loose')",
|
|
7318
|
+
" - No unknown/extra properties are included"
|
|
7319
|
+
];
|
|
7320
|
+
if (additionalNotes && additionalNotes.length > 0) {
|
|
7321
|
+
lines.push(...additionalNotes.map((note) => ` - ${note}`));
|
|
7322
|
+
}
|
|
7323
|
+
return lines.join("\n");
|
|
7324
|
+
}
|
|
7325
|
+
|
|
7326
|
+
// src/utils/typescript-loader.ts
|
|
7327
|
+
init_cjs_shims();
|
|
7328
|
+
function createTypeScriptLoader() {
|
|
7551
7329
|
return async (filepath) => {
|
|
7552
7330
|
try {
|
|
7553
7331
|
const esbuild = await import("esbuild");
|
|
@@ -7578,9 +7356,49 @@ var createTypeScriptLoader = () => {
|
|
|
7578
7356
|
);
|
|
7579
7357
|
}
|
|
7580
7358
|
};
|
|
7581
|
-
}
|
|
7359
|
+
}
|
|
7360
|
+
|
|
7361
|
+
// src/utils/config-loader.ts
|
|
7362
|
+
var OpenApiGeneratorOptionsSchema = import_zod2.z.strictObject({
|
|
7363
|
+
mode: import_zod2.z.enum(["strict", "normal", "loose"]).optional(),
|
|
7364
|
+
input: import_zod2.z.string(),
|
|
7365
|
+
output: import_zod2.z.string(),
|
|
7366
|
+
includeDescriptions: import_zod2.z.boolean().optional(),
|
|
7367
|
+
useDescribe: import_zod2.z.boolean().optional(),
|
|
7368
|
+
schemaType: import_zod2.z.enum(["all", "request", "response"]).optional(),
|
|
7369
|
+
prefix: import_zod2.z.string().optional(),
|
|
7370
|
+
suffix: import_zod2.z.string().optional(),
|
|
7371
|
+
showStats: import_zod2.z.boolean().optional(),
|
|
7372
|
+
request: RequestResponseOptionsSchema.optional(),
|
|
7373
|
+
response: RequestResponseOptionsSchema.optional(),
|
|
7374
|
+
name: import_zod2.z.string().optional(),
|
|
7375
|
+
operationFilters: OperationFiltersSchema.optional(),
|
|
7376
|
+
cacheSize: import_zod2.z.number().positive().optional(),
|
|
7377
|
+
batchSize: import_zod2.z.number().positive().optional()
|
|
7378
|
+
});
|
|
7379
|
+
var ConfigFileSchema = import_zod2.z.strictObject({
|
|
7380
|
+
defaults: import_zod2.z.strictObject({
|
|
7381
|
+
mode: import_zod2.z.enum(["strict", "normal", "loose"]).optional(),
|
|
7382
|
+
includeDescriptions: import_zod2.z.boolean().optional(),
|
|
7383
|
+
useDescribe: import_zod2.z.boolean().optional(),
|
|
7384
|
+
schemaType: import_zod2.z.enum(["all", "request", "response"]).optional(),
|
|
7385
|
+
prefix: import_zod2.z.string().optional(),
|
|
7386
|
+
suffix: import_zod2.z.string().optional(),
|
|
7387
|
+
showStats: import_zod2.z.boolean().optional(),
|
|
7388
|
+
request: RequestResponseOptionsSchema.optional(),
|
|
7389
|
+
response: RequestResponseOptionsSchema.optional(),
|
|
7390
|
+
operationFilters: OperationFiltersSchema.optional(),
|
|
7391
|
+
cacheSize: import_zod2.z.number().positive().optional(),
|
|
7392
|
+
batchSize: import_zod2.z.number().positive().optional()
|
|
7393
|
+
}).optional(),
|
|
7394
|
+
specs: import_zod2.z.array(OpenApiGeneratorOptionsSchema).min(1, {
|
|
7395
|
+
message: "Configuration must include at least one specification. Each specification should have 'input' and 'output' paths."
|
|
7396
|
+
}).refine((specs) => specs.every((spec) => spec.input && spec.output), {
|
|
7397
|
+
message: "Each specification must have both 'input' and 'output' paths defined"
|
|
7398
|
+
}),
|
|
7399
|
+
executionMode: import_zod2.z.enum(["parallel", "sequential"]).optional()
|
|
7400
|
+
});
|
|
7582
7401
|
async function loadConfig(configPath) {
|
|
7583
|
-
var _a;
|
|
7584
7402
|
const explorer = (0, import_cosmiconfig.cosmiconfig)("openapi-to-zod", {
|
|
7585
7403
|
searchPlaces: ["openapi-to-zod.config.ts", "openapi-to-zod.config.json", "package.json"],
|
|
7586
7404
|
loaders: {
|
|
@@ -7602,24 +7420,8 @@ async function loadConfig(configPath) {
|
|
|
7602
7420
|
const validatedConfig = ConfigFileSchema.parse(result.config);
|
|
7603
7421
|
return validatedConfig;
|
|
7604
7422
|
} catch (error) {
|
|
7605
|
-
if (error instanceof
|
|
7606
|
-
const
|
|
7607
|
-
const path = err.path.length > 0 ? err.path.join(".") : "root";
|
|
7608
|
-
return ` - ${path}: ${err.message}`;
|
|
7609
|
-
}).join("\n")) || "Unknown validation error";
|
|
7610
|
-
const configSource = result.filepath || configPath || "config file";
|
|
7611
|
-
const errorMessage = [
|
|
7612
|
-
`Invalid configuration file at: ${configSource}`,
|
|
7613
|
-
"",
|
|
7614
|
-
"Validation errors:",
|
|
7615
|
-
formattedErrors,
|
|
7616
|
-
"",
|
|
7617
|
-
"Please check your configuration file and ensure:",
|
|
7618
|
-
" - All required fields are present (specs array with input/output)",
|
|
7619
|
-
" - Field names are spelled correctly (no typos)",
|
|
7620
|
-
" - Values match the expected types (e.g., mode: 'strict' | 'normal' | 'loose')",
|
|
7621
|
-
" - No unknown/extra properties are included"
|
|
7622
|
-
].join("\n");
|
|
7423
|
+
if (error instanceof import_zod2.z.ZodError) {
|
|
7424
|
+
const errorMessage = formatConfigValidationError(error, result.filepath, configPath);
|
|
7623
7425
|
throw new Error(errorMessage);
|
|
7624
7426
|
}
|
|
7625
7427
|
throw error;
|
|
@@ -7635,7 +7437,6 @@ function mergeConfigWithDefaults(config) {
|
|
|
7635
7437
|
// Apply defaults first
|
|
7636
7438
|
mode: defaults.mode,
|
|
7637
7439
|
includeDescriptions: defaults.includeDescriptions,
|
|
7638
|
-
enumType: defaults.enumType,
|
|
7639
7440
|
useDescribe: defaults.useDescribe,
|
|
7640
7441
|
schemaType: defaults.schemaType,
|
|
7641
7442
|
prefix: defaults.prefix,
|
|
@@ -7655,17 +7456,13 @@ program.name("openapi-to-zod").description("Generate Zod v4 schemas from OpenAPI
|
|
|
7655
7456
|
`
|
|
7656
7457
|
Examples:
|
|
7657
7458
|
# Create a new config file
|
|
7658
|
-
$ openapi-to-zod
|
|
7459
|
+
$ openapi-to-zod init
|
|
7659
7460
|
|
|
7660
7461
|
# Generate with auto-discovered config
|
|
7661
7462
|
$ openapi-to-zod
|
|
7662
7463
|
|
|
7663
7464
|
# Generate with custom config path
|
|
7664
7465
|
$ openapi-to-zod --config custom.config.ts
|
|
7665
|
-
|
|
7666
|
-
Breaking Changes (v2.0):
|
|
7667
|
-
CLI options removed. Use configuration file instead.
|
|
7668
|
-
Run 'openapi-to-zod --init' to create a config file.
|
|
7669
7466
|
`
|
|
7670
7467
|
).action(async (options) => {
|
|
7671
7468
|
try {
|
|
@@ -7722,17 +7519,19 @@ function findSpecFiles() {
|
|
|
7722
7519
|
return { files, totalCount };
|
|
7723
7520
|
}
|
|
7724
7521
|
async function executeConfigMode(options) {
|
|
7522
|
+
var _a, _b;
|
|
7725
7523
|
let config;
|
|
7726
7524
|
try {
|
|
7727
7525
|
config = await loadConfig(options.config);
|
|
7728
7526
|
} catch {
|
|
7729
|
-
throw new CliOptionsError("No config file found. Run 'openapi-to-zod
|
|
7527
|
+
throw new CliOptionsError("No config file found. Run 'openapi-to-zod init' to create one.", {
|
|
7730
7528
|
configPath: options.config
|
|
7731
7529
|
});
|
|
7732
7530
|
}
|
|
7733
7531
|
const specs = mergeConfigWithDefaults(config);
|
|
7734
7532
|
const executionMode = config.executionMode || "parallel";
|
|
7735
|
-
const
|
|
7533
|
+
const batchSize = (_b = (_a = specs[0]) == null ? void 0 : _a.batchSize) != null ? _b : 10;
|
|
7534
|
+
const summary = await executeBatch(specs, executionMode, (spec) => new OpenApiGenerator(spec), batchSize);
|
|
7736
7535
|
const exitCode = getBatchExitCode(summary);
|
|
7737
7536
|
if (exitCode !== 0) {
|
|
7738
7537
|
process.exit(exitCode);
|
|
@@ -7834,7 +7633,7 @@ async function initConfigFile() {
|
|
|
7834
7633
|
{
|
|
7835
7634
|
type: "confirm",
|
|
7836
7635
|
name: "includeDefaults",
|
|
7837
|
-
message: "Include commonly-used defaults?
|
|
7636
|
+
message: "Include commonly-used recommended defaults?",
|
|
7838
7637
|
initial: true
|
|
7839
7638
|
}
|
|
7840
7639
|
]);
|
|
@@ -7855,7 +7654,9 @@ export default defineConfig({
|
|
|
7855
7654
|
defaults: {
|
|
7856
7655
|
mode: 'strict',
|
|
7857
7656
|
includeDescriptions: true,
|
|
7858
|
-
|
|
7657
|
+
useDescribe: false,
|
|
7658
|
+
showStats: true,
|
|
7659
|
+
schemaType: 'all',
|
|
7859
7660
|
},
|
|
7860
7661
|
specs: [
|
|
7861
7662
|
{
|