@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/README.md
CHANGED
|
@@ -834,14 +834,14 @@ All errors include:
|
|
|
834
834
|
|
|
835
835
|
## API Reference
|
|
836
836
|
|
|
837
|
-
### `generateZodSchemas(options:
|
|
837
|
+
### `generateZodSchemas(options: OpenApiGeneratorOptions): void`
|
|
838
838
|
|
|
839
839
|
Main function to generate schemas.
|
|
840
840
|
|
|
841
841
|
#### Options
|
|
842
842
|
|
|
843
843
|
```typescript
|
|
844
|
-
interface
|
|
844
|
+
interface OpenApiGeneratorOptions {
|
|
845
845
|
/**
|
|
846
846
|
* Object validation mode
|
|
847
847
|
* - 'strict': Uses z.strictObject() - no additional properties allowed
|
package/dist/cli.js
CHANGED
|
@@ -4961,6 +4961,7 @@ var require_prompts3 = __commonJS({
|
|
|
4961
4961
|
// src/cli.ts
|
|
4962
4962
|
init_cjs_shims();
|
|
4963
4963
|
var import_node_fs2 = require("fs");
|
|
4964
|
+
var import_node_path2 = require("path");
|
|
4964
4965
|
var import_commander = require("commander");
|
|
4965
4966
|
var import_prompts = __toESM(require_prompts3());
|
|
4966
4967
|
|
|
@@ -5012,7 +5013,7 @@ var ConfigurationError = class extends GeneratorError {
|
|
|
5012
5013
|
}
|
|
5013
5014
|
};
|
|
5014
5015
|
|
|
5015
|
-
// src/generator.ts
|
|
5016
|
+
// src/openapi-generator.ts
|
|
5016
5017
|
init_cjs_shims();
|
|
5017
5018
|
var import_node_fs = require("fs");
|
|
5018
5019
|
var import_node_path = require("path");
|
|
@@ -6221,8 +6222,143 @@ _PropertyGenerator.INCLUSION_RULES = {
|
|
|
6221
6222
|
};
|
|
6222
6223
|
var PropertyGenerator = _PropertyGenerator;
|
|
6223
6224
|
|
|
6224
|
-
// src/
|
|
6225
|
-
|
|
6225
|
+
// src/utils/operation-filters.ts
|
|
6226
|
+
init_cjs_shims();
|
|
6227
|
+
var import_minimatch = require("minimatch");
|
|
6228
|
+
function createFilterStatistics() {
|
|
6229
|
+
return {
|
|
6230
|
+
totalOperations: 0,
|
|
6231
|
+
includedOperations: 0,
|
|
6232
|
+
filteredByTags: 0,
|
|
6233
|
+
filteredByPaths: 0,
|
|
6234
|
+
filteredByMethods: 0,
|
|
6235
|
+
filteredByOperationIds: 0,
|
|
6236
|
+
filteredByDeprecated: 0
|
|
6237
|
+
};
|
|
6238
|
+
}
|
|
6239
|
+
function matchesAnyPattern(value, patterns) {
|
|
6240
|
+
if (!patterns || patterns.length === 0) {
|
|
6241
|
+
return false;
|
|
6242
|
+
}
|
|
6243
|
+
if (!value) {
|
|
6244
|
+
return false;
|
|
6245
|
+
}
|
|
6246
|
+
return patterns.some((pattern) => (0, import_minimatch.minimatch)(value, pattern));
|
|
6247
|
+
}
|
|
6248
|
+
function containsAny(arr, values) {
|
|
6249
|
+
if (!values || values.length === 0) {
|
|
6250
|
+
return false;
|
|
6251
|
+
}
|
|
6252
|
+
if (!arr || arr.length === 0) {
|
|
6253
|
+
return false;
|
|
6254
|
+
}
|
|
6255
|
+
return values.some((value) => arr.includes(value));
|
|
6256
|
+
}
|
|
6257
|
+
function shouldIncludeOperation(operation, path, method, filters, stats) {
|
|
6258
|
+
if (!filters) {
|
|
6259
|
+
return true;
|
|
6260
|
+
}
|
|
6261
|
+
const methodLower = method.toLowerCase();
|
|
6262
|
+
const operationId = operation == null ? void 0 : operation.operationId;
|
|
6263
|
+
const tags = (operation == null ? void 0 : operation.tags) || [];
|
|
6264
|
+
const deprecated = (operation == null ? void 0 : operation.deprecated) === true;
|
|
6265
|
+
if (filters.includeTags && filters.includeTags.length > 0) {
|
|
6266
|
+
if (!containsAny(tags, filters.includeTags)) {
|
|
6267
|
+
if (stats) stats.filteredByTags++;
|
|
6268
|
+
return false;
|
|
6269
|
+
}
|
|
6270
|
+
}
|
|
6271
|
+
if (filters.includePaths && filters.includePaths.length > 0) {
|
|
6272
|
+
if (!matchesAnyPattern(path, filters.includePaths)) {
|
|
6273
|
+
if (stats) stats.filteredByPaths++;
|
|
6274
|
+
return false;
|
|
6275
|
+
}
|
|
6276
|
+
}
|
|
6277
|
+
if (filters.includeMethods && filters.includeMethods.length > 0) {
|
|
6278
|
+
const methodsLower = filters.includeMethods.map((m) => m.toLowerCase());
|
|
6279
|
+
if (!methodsLower.includes(methodLower)) {
|
|
6280
|
+
if (stats) stats.filteredByMethods++;
|
|
6281
|
+
return false;
|
|
6282
|
+
}
|
|
6283
|
+
}
|
|
6284
|
+
if (filters.includeOperationIds && filters.includeOperationIds.length > 0) {
|
|
6285
|
+
if (!matchesAnyPattern(operationId, filters.includeOperationIds)) {
|
|
6286
|
+
if (stats) stats.filteredByOperationIds++;
|
|
6287
|
+
return false;
|
|
6288
|
+
}
|
|
6289
|
+
}
|
|
6290
|
+
if (filters.excludeDeprecated === true && deprecated) {
|
|
6291
|
+
if (stats) stats.filteredByDeprecated++;
|
|
6292
|
+
return false;
|
|
6293
|
+
}
|
|
6294
|
+
if (filters.excludeTags && filters.excludeTags.length > 0) {
|
|
6295
|
+
if (containsAny(tags, filters.excludeTags)) {
|
|
6296
|
+
if (stats) stats.filteredByTags++;
|
|
6297
|
+
return false;
|
|
6298
|
+
}
|
|
6299
|
+
}
|
|
6300
|
+
if (filters.excludePaths && filters.excludePaths.length > 0) {
|
|
6301
|
+
if (matchesAnyPattern(path, filters.excludePaths)) {
|
|
6302
|
+
if (stats) stats.filteredByPaths++;
|
|
6303
|
+
return false;
|
|
6304
|
+
}
|
|
6305
|
+
}
|
|
6306
|
+
if (filters.excludeMethods && filters.excludeMethods.length > 0) {
|
|
6307
|
+
const methodsLower = filters.excludeMethods.map((m) => m.toLowerCase());
|
|
6308
|
+
if (methodsLower.includes(methodLower)) {
|
|
6309
|
+
if (stats) stats.filteredByMethods++;
|
|
6310
|
+
return false;
|
|
6311
|
+
}
|
|
6312
|
+
}
|
|
6313
|
+
if (filters.excludeOperationIds && filters.excludeOperationIds.length > 0) {
|
|
6314
|
+
if (matchesAnyPattern(operationId, filters.excludeOperationIds)) {
|
|
6315
|
+
if (stats) stats.filteredByOperationIds++;
|
|
6316
|
+
return false;
|
|
6317
|
+
}
|
|
6318
|
+
}
|
|
6319
|
+
return true;
|
|
6320
|
+
}
|
|
6321
|
+
function validateFilters(stats, filters) {
|
|
6322
|
+
if (!filters || stats.totalOperations === 0) {
|
|
6323
|
+
return;
|
|
6324
|
+
}
|
|
6325
|
+
if (stats.includedOperations === 0) {
|
|
6326
|
+
console.warn(
|
|
6327
|
+
`\u26A0\uFE0F Warning: All ${stats.totalOperations} operations were filtered out. Check your operationFilters configuration.`
|
|
6328
|
+
);
|
|
6329
|
+
const filterBreakdown = [];
|
|
6330
|
+
if (stats.filteredByTags > 0) filterBreakdown.push(`${stats.filteredByTags} by tags`);
|
|
6331
|
+
if (stats.filteredByPaths > 0) filterBreakdown.push(`${stats.filteredByPaths} by paths`);
|
|
6332
|
+
if (stats.filteredByMethods > 0) filterBreakdown.push(`${stats.filteredByMethods} by methods`);
|
|
6333
|
+
if (stats.filteredByOperationIds > 0) filterBreakdown.push(`${stats.filteredByOperationIds} by operationIds`);
|
|
6334
|
+
if (stats.filteredByDeprecated > 0) filterBreakdown.push(`${stats.filteredByDeprecated} by deprecated flag`);
|
|
6335
|
+
if (filterBreakdown.length > 0) {
|
|
6336
|
+
console.warn(` Filtered: ${filterBreakdown.join(", ")}`);
|
|
6337
|
+
}
|
|
6338
|
+
}
|
|
6339
|
+
}
|
|
6340
|
+
function formatFilterStatistics(stats) {
|
|
6341
|
+
if (stats.totalOperations === 0) {
|
|
6342
|
+
return "";
|
|
6343
|
+
}
|
|
6344
|
+
const lines = [];
|
|
6345
|
+
lines.push("Operation Filtering:");
|
|
6346
|
+
lines.push(` Total operations: ${stats.totalOperations}`);
|
|
6347
|
+
lines.push(` Included operations: ${stats.includedOperations}`);
|
|
6348
|
+
const filteredCount = stats.filteredByTags + stats.filteredByPaths + stats.filteredByMethods + stats.filteredByOperationIds + stats.filteredByDeprecated;
|
|
6349
|
+
if (filteredCount > 0) {
|
|
6350
|
+
lines.push(` Filtered operations: ${filteredCount}`);
|
|
6351
|
+
if (stats.filteredByTags > 0) lines.push(` - By tags: ${stats.filteredByTags}`);
|
|
6352
|
+
if (stats.filteredByPaths > 0) lines.push(` - By paths: ${stats.filteredByPaths}`);
|
|
6353
|
+
if (stats.filteredByMethods > 0) lines.push(` - By methods: ${stats.filteredByMethods}`);
|
|
6354
|
+
if (stats.filteredByOperationIds > 0) lines.push(` - By operationIds: ${stats.filteredByOperationIds}`);
|
|
6355
|
+
if (stats.filteredByDeprecated > 0) lines.push(` - By deprecated: ${stats.filteredByDeprecated}`);
|
|
6356
|
+
}
|
|
6357
|
+
return lines.join("\n");
|
|
6358
|
+
}
|
|
6359
|
+
|
|
6360
|
+
// src/openapi-generator.ts
|
|
6361
|
+
var OpenApiGenerator = class {
|
|
6226
6362
|
constructor(options) {
|
|
6227
6363
|
this.schemas = /* @__PURE__ */ new Map();
|
|
6228
6364
|
this.types = /* @__PURE__ */ new Map();
|
|
@@ -6232,6 +6368,7 @@ var ZodSchemaGenerator = class {
|
|
|
6232
6368
|
this.schemaUsageMap = /* @__PURE__ */ new Map();
|
|
6233
6369
|
this.schemaTypeModeMap = /* @__PURE__ */ new Map();
|
|
6234
6370
|
this.needsZodImport = false;
|
|
6371
|
+
this.filterStats = createFilterStatistics();
|
|
6235
6372
|
var _a, _b, _c;
|
|
6236
6373
|
if (!options.input) {
|
|
6237
6374
|
throw new ConfigurationError("Input path is required", { providedOptions: options });
|
|
@@ -6249,7 +6386,8 @@ var ZodSchemaGenerator = class {
|
|
|
6249
6386
|
showStats: (_c = options.showStats) != null ? _c : true,
|
|
6250
6387
|
nativeEnumType: options.nativeEnumType || "union",
|
|
6251
6388
|
request: options.request,
|
|
6252
|
-
response: options.response
|
|
6389
|
+
response: options.response,
|
|
6390
|
+
operationFilters: options.operationFilters
|
|
6253
6391
|
};
|
|
6254
6392
|
try {
|
|
6255
6393
|
const fs = require("fs");
|
|
@@ -6262,19 +6400,41 @@ var ZodSchemaGenerator = class {
|
|
|
6262
6400
|
}
|
|
6263
6401
|
}
|
|
6264
6402
|
try {
|
|
6265
|
-
const
|
|
6266
|
-
|
|
6403
|
+
const content = (0, import_node_fs.readFileSync)(this.options.input, "utf-8");
|
|
6404
|
+
try {
|
|
6405
|
+
this.spec = (0, import_yaml.parse)(content);
|
|
6406
|
+
} catch (yamlError) {
|
|
6407
|
+
try {
|
|
6408
|
+
this.spec = JSON.parse(content);
|
|
6409
|
+
} catch {
|
|
6410
|
+
if (yamlError instanceof Error) {
|
|
6411
|
+
const errorMessage = [
|
|
6412
|
+
`Failed to parse OpenAPI specification from: ${this.options.input}`,
|
|
6413
|
+
"",
|
|
6414
|
+
`Error: ${yamlError.message}`,
|
|
6415
|
+
"",
|
|
6416
|
+
"Please ensure:",
|
|
6417
|
+
" - The file exists and is readable",
|
|
6418
|
+
" - The file contains valid YAML or JSON syntax",
|
|
6419
|
+
" - The file is a valid OpenAPI 3.x specification"
|
|
6420
|
+
].join("\n");
|
|
6421
|
+
throw new SpecValidationError(errorMessage, {
|
|
6422
|
+
filePath: this.options.input,
|
|
6423
|
+
originalError: yamlError.message
|
|
6424
|
+
});
|
|
6425
|
+
}
|
|
6426
|
+
throw yamlError;
|
|
6427
|
+
}
|
|
6428
|
+
}
|
|
6267
6429
|
} catch (error) {
|
|
6430
|
+
if (error instanceof SpecValidationError) {
|
|
6431
|
+
throw error;
|
|
6432
|
+
}
|
|
6268
6433
|
if (error instanceof Error) {
|
|
6269
6434
|
const errorMessage = [
|
|
6270
|
-
`Failed to
|
|
6271
|
-
"",
|
|
6272
|
-
`Error: ${error.message}`,
|
|
6435
|
+
`Failed to read OpenAPI specification from: ${this.options.input}`,
|
|
6273
6436
|
"",
|
|
6274
|
-
|
|
6275
|
-
" - The file exists and is readable",
|
|
6276
|
-
" - The file contains valid YAML syntax",
|
|
6277
|
-
" - The file is a valid OpenAPI 3.x specification"
|
|
6437
|
+
`Error: ${error.message}`
|
|
6278
6438
|
].join("\n");
|
|
6279
6439
|
throw new SpecValidationError(errorMessage, { filePath: this.options.input, originalError: error.message });
|
|
6280
6440
|
}
|
|
@@ -6332,6 +6492,8 @@ var ZodSchemaGenerator = class {
|
|
|
6332
6492
|
this.generateComponentSchema(name, schema);
|
|
6333
6493
|
}
|
|
6334
6494
|
this.generateQueryParameterSchemas();
|
|
6495
|
+
this.generateHeaderParameterSchemas();
|
|
6496
|
+
validateFilters(this.filterStats, this.options.operationFilters);
|
|
6335
6497
|
const orderedSchemaNames = this.topologicalSort();
|
|
6336
6498
|
const output = ["// Auto-generated by @cerios/openapi-to-zod", "// Do not edit this file manually", ""];
|
|
6337
6499
|
if (this.options.showStats === true) {
|
|
@@ -6425,9 +6587,16 @@ var ZodSchemaGenerator = class {
|
|
|
6425
6587
|
const requestSchemas = /* @__PURE__ */ new Set();
|
|
6426
6588
|
const responseSchemas = /* @__PURE__ */ new Set();
|
|
6427
6589
|
if (this.spec.paths) {
|
|
6428
|
-
for (const [, pathItem] of Object.entries(this.spec.paths)) {
|
|
6429
|
-
|
|
6590
|
+
for (const [path, pathItem] of Object.entries(this.spec.paths)) {
|
|
6591
|
+
const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
6592
|
+
for (const method of methods) {
|
|
6593
|
+
const operation = pathItem[method];
|
|
6430
6594
|
if (typeof operation !== "object" || !operation) continue;
|
|
6595
|
+
this.filterStats.totalOperations++;
|
|
6596
|
+
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters, this.filterStats)) {
|
|
6597
|
+
continue;
|
|
6598
|
+
}
|
|
6599
|
+
this.filterStats.includedOperations++;
|
|
6431
6600
|
if ("requestBody" in operation && operation.requestBody && typeof operation.requestBody === "object" && "content" in operation.requestBody && operation.requestBody.content) {
|
|
6432
6601
|
for (const mediaType of Object.values(operation.requestBody.content)) {
|
|
6433
6602
|
if (mediaType && typeof mediaType === "object" && "schema" in mediaType && mediaType.schema) {
|
|
@@ -6777,12 +6946,15 @@ ${typeCode}`;
|
|
|
6777
6946
|
if (!this.spec.paths) {
|
|
6778
6947
|
return;
|
|
6779
6948
|
}
|
|
6780
|
-
for (const [
|
|
6949
|
+
for (const [path, pathItem] of Object.entries(this.spec.paths)) {
|
|
6781
6950
|
if (!pathItem || typeof pathItem !== "object") continue;
|
|
6782
6951
|
const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
6783
6952
|
for (const method of methods) {
|
|
6784
6953
|
const operation = pathItem[method];
|
|
6785
6954
|
if (!operation) continue;
|
|
6955
|
+
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
|
|
6956
|
+
continue;
|
|
6957
|
+
}
|
|
6786
6958
|
if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
|
|
6787
6959
|
continue;
|
|
6788
6960
|
}
|
|
@@ -6843,6 +7015,80 @@ ${propsCode}
|
|
|
6843
7015
|
const jsdoc = `/**
|
|
6844
7016
|
* Query parameters for ${operation.operationId}
|
|
6845
7017
|
*/
|
|
7018
|
+
`;
|
|
7019
|
+
const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
|
|
7020
|
+
this.schemas.set(schemaName, fullSchemaCode);
|
|
7021
|
+
this.needsZodImport = true;
|
|
7022
|
+
}
|
|
7023
|
+
}
|
|
7024
|
+
}
|
|
7025
|
+
/**
|
|
7026
|
+
* Generate header parameter schemas for each operation
|
|
7027
|
+
* Header parameters are always string type (HTTP header semantics)
|
|
7028
|
+
*/
|
|
7029
|
+
generateHeaderParameterSchemas() {
|
|
7030
|
+
var _a;
|
|
7031
|
+
if (!this.spec.paths) {
|
|
7032
|
+
return;
|
|
7033
|
+
}
|
|
7034
|
+
for (const [path, pathItem] of Object.entries(this.spec.paths)) {
|
|
7035
|
+
if (!pathItem || typeof pathItem !== "object") continue;
|
|
7036
|
+
const methods = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
7037
|
+
for (const method of methods) {
|
|
7038
|
+
const operation = pathItem[method];
|
|
7039
|
+
if (!operation) continue;
|
|
7040
|
+
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
|
|
7041
|
+
continue;
|
|
7042
|
+
}
|
|
7043
|
+
if (!operation.operationId || !operation.parameters || !Array.isArray(operation.parameters)) {
|
|
7044
|
+
continue;
|
|
7045
|
+
}
|
|
7046
|
+
const headerParams = operation.parameters.filter(
|
|
7047
|
+
(param) => param && typeof param === "object" && param.in === "header"
|
|
7048
|
+
);
|
|
7049
|
+
if (headerParams.length === 0) {
|
|
7050
|
+
continue;
|
|
7051
|
+
}
|
|
7052
|
+
const pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
|
|
7053
|
+
const schemaName = `${pascalOperationId}HeaderParams`;
|
|
7054
|
+
if (!this.schemaDependencies.has(schemaName)) {
|
|
7055
|
+
this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
|
|
7056
|
+
}
|
|
7057
|
+
const properties = {};
|
|
7058
|
+
for (const param of headerParams) {
|
|
7059
|
+
const paramName = param.name;
|
|
7060
|
+
const paramSchema = param.schema;
|
|
7061
|
+
if (!paramSchema) continue;
|
|
7062
|
+
let zodType = "z.string()";
|
|
7063
|
+
if (param.description && this.requestOptions.includeDescriptions) {
|
|
7064
|
+
if (this.requestOptions.useDescribe) {
|
|
7065
|
+
zodType = `${zodType}.describe(${JSON.stringify(param.description)})`;
|
|
7066
|
+
}
|
|
7067
|
+
}
|
|
7068
|
+
zodType = `${zodType}.optional()`;
|
|
7069
|
+
properties[paramName] = zodType;
|
|
7070
|
+
if (paramSchema.$ref) {
|
|
7071
|
+
const refName = resolveRef(paramSchema.$ref);
|
|
7072
|
+
(_a = this.schemaDependencies.get(schemaName)) == null ? void 0 : _a.add(refName);
|
|
7073
|
+
}
|
|
7074
|
+
}
|
|
7075
|
+
const objectMode = this.requestOptions.mode;
|
|
7076
|
+
const zodMethod = objectMode === "strict" ? "strictObject" : objectMode === "loose" ? "looseObject" : "object";
|
|
7077
|
+
const propsCode = Object.entries(properties).map(([key, value]) => {
|
|
7078
|
+
const needsQuotes = !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key);
|
|
7079
|
+
const quotedKey = needsQuotes ? `"${key}"` : key;
|
|
7080
|
+
return ` ${quotedKey}: ${value}`;
|
|
7081
|
+
}).join(",\n");
|
|
7082
|
+
const schemaCode = `z.${zodMethod}({
|
|
7083
|
+
${propsCode}
|
|
7084
|
+
})`;
|
|
7085
|
+
const operationName = pascalOperationId;
|
|
7086
|
+
const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
|
|
7087
|
+
const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
|
|
7088
|
+
const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}HeaderParamsSchema`;
|
|
7089
|
+
const jsdoc = `/**
|
|
7090
|
+
* Header parameters for ${operation.operationId}
|
|
7091
|
+
*/
|
|
6846
7092
|
`;
|
|
6847
7093
|
const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
|
|
6848
7094
|
this.schemas.set(schemaName, fullSchemaCode);
|
|
@@ -7120,15 +7366,23 @@ ${props.join("\n")}
|
|
|
7120
7366
|
stats.withConstraints++;
|
|
7121
7367
|
}
|
|
7122
7368
|
}
|
|
7123
|
-
|
|
7369
|
+
const output = [
|
|
7124
7370
|
"// Generation Statistics:",
|
|
7125
7371
|
`// Total schemas: ${stats.totalSchemas}`,
|
|
7126
7372
|
`// Enums: ${stats.enums}`,
|
|
7127
7373
|
`// Circular references: ${stats.withCircularRefs}`,
|
|
7128
7374
|
`// Discriminated unions: ${stats.withDiscriminators}`,
|
|
7129
|
-
`// With constraints: ${stats.withConstraints}
|
|
7130
|
-
`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`
|
|
7375
|
+
`// With constraints: ${stats.withConstraints}`
|
|
7131
7376
|
];
|
|
7377
|
+
if (this.options.operationFilters && this.filterStats.totalOperations > 0) {
|
|
7378
|
+
output.push("//");
|
|
7379
|
+
const filterStatsStr = formatFilterStatistics(this.filterStats);
|
|
7380
|
+
for (const line of filterStatsStr.split("\n")) {
|
|
7381
|
+
output.push(`// ${line}`);
|
|
7382
|
+
}
|
|
7383
|
+
}
|
|
7384
|
+
output.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
7385
|
+
return output;
|
|
7132
7386
|
}
|
|
7133
7387
|
};
|
|
7134
7388
|
|
|
@@ -7136,7 +7390,7 @@ ${props.join("\n")}
|
|
|
7136
7390
|
async function processSpec(spec, index, total) {
|
|
7137
7391
|
console.log(`Processing [${index + 1}/${total}] ${spec.input}...`);
|
|
7138
7392
|
try {
|
|
7139
|
-
const generator = new
|
|
7393
|
+
const generator = new OpenApiGenerator(spec);
|
|
7140
7394
|
generator.generate();
|
|
7141
7395
|
console.log(`\u2713 Successfully generated ${spec.output}`);
|
|
7142
7396
|
return {
|
|
@@ -7247,7 +7501,18 @@ var RequestResponseOptionsSchema = import_zod.z.strictObject({
|
|
|
7247
7501
|
typeMode: TypeModeSchema.optional(),
|
|
7248
7502
|
nativeEnumType: NativeEnumTypeSchema.optional()
|
|
7249
7503
|
});
|
|
7250
|
-
var
|
|
7504
|
+
var OperationFiltersSchema = import_zod.z.strictObject({
|
|
7505
|
+
includeTags: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7506
|
+
excludeTags: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7507
|
+
includePaths: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7508
|
+
excludePaths: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7509
|
+
includeMethods: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7510
|
+
excludeMethods: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7511
|
+
includeOperationIds: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7512
|
+
excludeOperationIds: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7513
|
+
excludeDeprecated: import_zod.z.boolean().optional()
|
|
7514
|
+
});
|
|
7515
|
+
var OpenApiGeneratorOptionsSchema = import_zod.z.strictObject({
|
|
7251
7516
|
mode: import_zod.z.enum(["strict", "normal", "loose"]).optional(),
|
|
7252
7517
|
input: import_zod.z.string(),
|
|
7253
7518
|
output: import_zod.z.string(),
|
|
@@ -7261,7 +7526,8 @@ var GeneratorOptionsSchema = import_zod.z.strictObject({
|
|
|
7261
7526
|
nativeEnumType: NativeEnumTypeSchema.optional(),
|
|
7262
7527
|
request: RequestResponseOptionsSchema.optional(),
|
|
7263
7528
|
response: RequestResponseOptionsSchema.optional(),
|
|
7264
|
-
name: import_zod.z.string().optional()
|
|
7529
|
+
name: import_zod.z.string().optional(),
|
|
7530
|
+
operationFilters: OperationFiltersSchema.optional()
|
|
7265
7531
|
});
|
|
7266
7532
|
var ConfigFileSchema = import_zod.z.strictObject({
|
|
7267
7533
|
defaults: import_zod.z.strictObject({
|
|
@@ -7275,9 +7541,10 @@ var ConfigFileSchema = import_zod.z.strictObject({
|
|
|
7275
7541
|
showStats: import_zod.z.boolean().optional(),
|
|
7276
7542
|
nativeEnumType: NativeEnumTypeSchema.optional(),
|
|
7277
7543
|
request: RequestResponseOptionsSchema.optional(),
|
|
7278
|
-
response: RequestResponseOptionsSchema.optional()
|
|
7544
|
+
response: RequestResponseOptionsSchema.optional(),
|
|
7545
|
+
operationFilters: OperationFiltersSchema.optional()
|
|
7279
7546
|
}).optional(),
|
|
7280
|
-
specs: import_zod.z.array(
|
|
7547
|
+
specs: import_zod.z.array(OpenApiGeneratorOptionsSchema).min(1, "At least one spec is required"),
|
|
7281
7548
|
executionMode: import_zod.z.enum(["parallel", "sequential"]).optional()
|
|
7282
7549
|
});
|
|
7283
7550
|
var createTypeScriptLoader = () => {
|
|
@@ -7424,6 +7691,36 @@ program.command("init").description("Initialize a new openapi-to-zod configurati
|
|
|
7424
7691
|
}
|
|
7425
7692
|
});
|
|
7426
7693
|
program.parse();
|
|
7694
|
+
function findSpecFiles() {
|
|
7695
|
+
const specFolders = ["spec", "specs"];
|
|
7696
|
+
const validExtensions = [".yaml", ".yml", ".json"];
|
|
7697
|
+
const excludePatterns = ["node_modules", ".git", "dist", "build", "coverage"];
|
|
7698
|
+
const allFiles = [];
|
|
7699
|
+
for (const folder of specFolders) {
|
|
7700
|
+
if (!(0, import_node_fs2.existsSync)(folder)) continue;
|
|
7701
|
+
try {
|
|
7702
|
+
const entries = (0, import_node_fs2.readdirSync)(folder, { recursive: true, encoding: "utf-8" });
|
|
7703
|
+
for (const entry of entries) {
|
|
7704
|
+
const fullPath = (0, import_node_path2.join)(folder, entry);
|
|
7705
|
+
if (excludePatterns.some((pattern) => fullPath.includes(pattern))) continue;
|
|
7706
|
+
try {
|
|
7707
|
+
const stats = (0, import_node_fs2.statSync)(fullPath);
|
|
7708
|
+
if (!stats.isFile()) continue;
|
|
7709
|
+
const hasValidExt = validExtensions.some((ext) => fullPath.endsWith(ext));
|
|
7710
|
+
if (!hasValidExt) continue;
|
|
7711
|
+
const sizeKB = (stats.size / 1024).toFixed(2);
|
|
7712
|
+
allFiles.push({ path: fullPath.replace(/\\/g, "/"), size: `${sizeKB} KB` });
|
|
7713
|
+
} catch {
|
|
7714
|
+
}
|
|
7715
|
+
}
|
|
7716
|
+
} catch {
|
|
7717
|
+
}
|
|
7718
|
+
}
|
|
7719
|
+
allFiles.sort((a, b) => a.path.localeCompare(b.path));
|
|
7720
|
+
const totalCount = allFiles.length;
|
|
7721
|
+
const files = allFiles.slice(0, 20);
|
|
7722
|
+
return { files, totalCount };
|
|
7723
|
+
}
|
|
7427
7724
|
async function executeConfigMode(options) {
|
|
7428
7725
|
let config;
|
|
7429
7726
|
try {
|
|
@@ -7457,14 +7754,66 @@ async function initConfigFile() {
|
|
|
7457
7754
|
return;
|
|
7458
7755
|
}
|
|
7459
7756
|
}
|
|
7460
|
-
const
|
|
7461
|
-
|
|
7757
|
+
const { files, totalCount } = findSpecFiles();
|
|
7758
|
+
if (totalCount > 20) {
|
|
7759
|
+
console.log(`Showing first 20 of ${totalCount} files found. Use manual entry to specify others.
|
|
7760
|
+
`);
|
|
7761
|
+
}
|
|
7762
|
+
let inputPath;
|
|
7763
|
+
if (files.length > 0) {
|
|
7764
|
+
const choices = [
|
|
7765
|
+
...files.map((f) => ({ title: `${f.path} (${f.size})`, value: f.path })),
|
|
7766
|
+
{ title: "\u2192 Enter manually...", value: "__MANUAL__" }
|
|
7767
|
+
];
|
|
7768
|
+
const inputResponse = await (0, import_prompts.default)({
|
|
7769
|
+
type: "select",
|
|
7770
|
+
name: "input",
|
|
7771
|
+
message: "Select OpenAPI spec file (YAML or JSON):",
|
|
7772
|
+
choices
|
|
7773
|
+
});
|
|
7774
|
+
if (!inputResponse.input) {
|
|
7775
|
+
console.log("\nInitialization cancelled.");
|
|
7776
|
+
return;
|
|
7777
|
+
}
|
|
7778
|
+
if (inputResponse.input === "__MANUAL__") {
|
|
7779
|
+
const manualResponse = await (0, import_prompts.default)({
|
|
7780
|
+
type: "text",
|
|
7781
|
+
name: "input",
|
|
7782
|
+
message: "Input OpenAPI file path (YAML or JSON):",
|
|
7783
|
+
initial: "openapi.{yaml,yml,json}",
|
|
7784
|
+
validate: (value) => {
|
|
7785
|
+
if (value.length === 0) return "Input path is required";
|
|
7786
|
+
if (!(0, import_node_fs2.existsSync)(value)) return "\u26A0\uFE0F File does not exist. Continue anyway?";
|
|
7787
|
+
return true;
|
|
7788
|
+
}
|
|
7789
|
+
});
|
|
7790
|
+
if (!manualResponse.input) {
|
|
7791
|
+
console.log("\nInitialization cancelled.");
|
|
7792
|
+
return;
|
|
7793
|
+
}
|
|
7794
|
+
inputPath = manualResponse.input;
|
|
7795
|
+
} else {
|
|
7796
|
+
inputPath = inputResponse.input;
|
|
7797
|
+
}
|
|
7798
|
+
} else {
|
|
7799
|
+
const manualResponse = await (0, import_prompts.default)({
|
|
7462
7800
|
type: "text",
|
|
7463
7801
|
name: "input",
|
|
7464
|
-
message: "Input OpenAPI file path:",
|
|
7465
|
-
initial: "openapi.yaml",
|
|
7466
|
-
validate: (value) =>
|
|
7467
|
-
|
|
7802
|
+
message: "Input OpenAPI file path (YAML or JSON):",
|
|
7803
|
+
initial: "openapi.{yaml,yml,json}",
|
|
7804
|
+
validate: (value) => {
|
|
7805
|
+
if (value.length === 0) return "Input path is required";
|
|
7806
|
+
if (!(0, import_node_fs2.existsSync)(value)) return "\u26A0\uFE0F File does not exist. Continue anyway?";
|
|
7807
|
+
return true;
|
|
7808
|
+
}
|
|
7809
|
+
});
|
|
7810
|
+
if (!manualResponse.input) {
|
|
7811
|
+
console.log("\nInitialization cancelled.");
|
|
7812
|
+
return;
|
|
7813
|
+
}
|
|
7814
|
+
inputPath = manualResponse.input;
|
|
7815
|
+
}
|
|
7816
|
+
const response = await (0, import_prompts.default)([
|
|
7468
7817
|
{
|
|
7469
7818
|
type: "text",
|
|
7470
7819
|
name: "output",
|
|
@@ -7489,11 +7838,12 @@ async function initConfigFile() {
|
|
|
7489
7838
|
initial: true
|
|
7490
7839
|
}
|
|
7491
7840
|
]);
|
|
7492
|
-
if (!response.
|
|
7841
|
+
if (!response.output || !response.format) {
|
|
7493
7842
|
console.log("\nInitialization cancelled.");
|
|
7494
7843
|
return;
|
|
7495
7844
|
}
|
|
7496
|
-
const {
|
|
7845
|
+
const { output, format, includeDefaults } = response;
|
|
7846
|
+
const input = inputPath;
|
|
7497
7847
|
let configContent;
|
|
7498
7848
|
let configFilename;
|
|
7499
7849
|
if (format === "ts") {
|
|
@@ -7554,6 +7904,20 @@ export default defineConfig({
|
|
|
7554
7904
|
console.log("\nNext steps:");
|
|
7555
7905
|
console.log(" 1. Review and customize your config file if needed");
|
|
7556
7906
|
console.log(" 2. Run 'openapi-to-zod' to generate schemas\n");
|
|
7557
|
-
|
|
7907
|
+
const ceriosMessages = [
|
|
7908
|
+
"Things just got Cerios!",
|
|
7909
|
+
"Getting Cerios about schemas!",
|
|
7910
|
+
"Cerios business ahead!",
|
|
7911
|
+
"Don't take it too Cerios-ly!",
|
|
7912
|
+
"Time to get Cerios!",
|
|
7913
|
+
"We're dead Cerios about types!",
|
|
7914
|
+
"This is Cerios-ly awesome!",
|
|
7915
|
+
"Cerios-ly, you're all set!",
|
|
7916
|
+
"You are Cerios right now!",
|
|
7917
|
+
"Cerios vibes only!"
|
|
7918
|
+
];
|
|
7919
|
+
const randomMessage = ceriosMessages[Math.floor(Math.random() * ceriosMessages.length)];
|
|
7920
|
+
console.log(`${randomMessage}
|
|
7921
|
+
`);
|
|
7558
7922
|
}
|
|
7559
7923
|
//# sourceMappingURL=cli.js.map
|