@cerios/openapi-to-zod 1.1.0 → 1.2.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 +209 -28
- package/dist/cli.js +245 -80
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +246 -81
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +209 -77
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +209 -77
- package/dist/index.mjs.map +1 -1
- package/dist/internal.d.mts +34 -19
- package/dist/internal.d.ts +34 -19
- package/dist/internal.js +106 -50
- package/dist/internal.js.map +1 -1
- package/dist/internal.mjs +104 -50
- package/dist/internal.mjs.map +1 -1
- package/dist/{types-B7ePTDjr.d.mts → types--r0d47sd.d.mts} +86 -8
- package/dist/{types-B7ePTDjr.d.ts → types--r0d47sd.d.ts} +86 -8
- package/package.json +105 -102
package/dist/cli.js
CHANGED
|
@@ -5129,7 +5129,7 @@ function getBatchExitCode(summary) {
|
|
|
5129
5129
|
init_cjs_shims();
|
|
5130
5130
|
var import_node_fs = require("fs");
|
|
5131
5131
|
var import_node_path = require("path");
|
|
5132
|
-
var
|
|
5132
|
+
var import_minimatch3 = require("minimatch");
|
|
5133
5133
|
var import_yaml = require("yaml");
|
|
5134
5134
|
|
|
5135
5135
|
// src/generators/enum-generator.ts
|
|
@@ -5192,8 +5192,26 @@ function resolveRef(ref) {
|
|
|
5192
5192
|
function generateEnum(name, values, options) {
|
|
5193
5193
|
const schemaName = `${toCamelCase(name, options)}Schema`;
|
|
5194
5194
|
const typeName = toPascalCase(name);
|
|
5195
|
-
const
|
|
5196
|
-
|
|
5195
|
+
const allBooleans = values.every((v) => typeof v === "boolean");
|
|
5196
|
+
if (allBooleans) {
|
|
5197
|
+
const schemaCode2 = `export const ${schemaName} = z.boolean();`;
|
|
5198
|
+
const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
|
|
5199
|
+
return { schemaCode: schemaCode2, typeCode: typeCode2 };
|
|
5200
|
+
}
|
|
5201
|
+
const allStrings = values.every((v) => typeof v === "string");
|
|
5202
|
+
if (allStrings) {
|
|
5203
|
+
const enumValues = values.map((v) => `"${v}"`).join(", ");
|
|
5204
|
+
const schemaCode2 = `export const ${schemaName} = z.enum([${enumValues}]);`;
|
|
5205
|
+
const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
|
|
5206
|
+
return { schemaCode: schemaCode2, typeCode: typeCode2 };
|
|
5207
|
+
}
|
|
5208
|
+
const literalValues = values.map((v) => {
|
|
5209
|
+
if (typeof v === "string") {
|
|
5210
|
+
return `z.literal("${v}")`;
|
|
5211
|
+
}
|
|
5212
|
+
return `z.literal(${v})`;
|
|
5213
|
+
}).join(", ");
|
|
5214
|
+
const schemaCode = `export const ${schemaName} = z.union([${literalValues}]);`;
|
|
5197
5215
|
const typeCode = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
|
|
5198
5216
|
return { schemaCode, typeCode };
|
|
5199
5217
|
}
|
|
@@ -5207,7 +5225,7 @@ function escapeDescription(str) {
|
|
|
5207
5225
|
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
|
|
5208
5226
|
}
|
|
5209
5227
|
function escapePattern(str) {
|
|
5210
|
-
return str.replace(
|
|
5228
|
+
return str.replace(/\//g, "\\/");
|
|
5211
5229
|
}
|
|
5212
5230
|
function escapeJSDoc(str) {
|
|
5213
5231
|
return str.replace(/\*\//g, "*\\/");
|
|
@@ -5215,14 +5233,17 @@ function escapeJSDoc(str) {
|
|
|
5215
5233
|
function wrapNullable(validation, isNullable2) {
|
|
5216
5234
|
return isNullable2 ? `${validation}.nullable()` : validation;
|
|
5217
5235
|
}
|
|
5218
|
-
function isNullable(schema) {
|
|
5236
|
+
function isNullable(schema, defaultNullable = false) {
|
|
5219
5237
|
if (schema.nullable === true) {
|
|
5220
5238
|
return true;
|
|
5221
5239
|
}
|
|
5240
|
+
if (schema.nullable === false) {
|
|
5241
|
+
return false;
|
|
5242
|
+
}
|
|
5222
5243
|
if (Array.isArray(schema.type)) {
|
|
5223
5244
|
return schema.type.includes("null");
|
|
5224
5245
|
}
|
|
5225
|
-
return
|
|
5246
|
+
return defaultNullable;
|
|
5226
5247
|
}
|
|
5227
5248
|
function getPrimaryType(schema) {
|
|
5228
5249
|
if (Array.isArray(schema.type)) {
|
|
@@ -5337,61 +5358,36 @@ var LRUCache = class {
|
|
|
5337
5358
|
|
|
5338
5359
|
// src/utils/pattern-utils.ts
|
|
5339
5360
|
init_cjs_shims();
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
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)) {
|
|
5361
|
+
var import_minimatch = require("minimatch");
|
|
5362
|
+
function isValidGlobPattern(pattern) {
|
|
5363
|
+
try {
|
|
5364
|
+
new import_minimatch.minimatch.Minimatch(pattern);
|
|
5354
5365
|
return true;
|
|
5366
|
+
} catch {
|
|
5367
|
+
return false;
|
|
5355
5368
|
}
|
|
5356
|
-
return false;
|
|
5357
5369
|
}
|
|
5358
|
-
function
|
|
5359
|
-
|
|
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;
|
|
5370
|
+
function isGlobPattern(pattern) {
|
|
5371
|
+
return /[*?[\]{}!]/.test(pattern);
|
|
5371
5372
|
}
|
|
5372
5373
|
function stripPrefix(input, pattern, ensureLeadingChar) {
|
|
5373
5374
|
if (!pattern) {
|
|
5374
5375
|
return input;
|
|
5375
5376
|
}
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
return `${ensureLeadingChar}${stripped}`;
|
|
5387
|
-
}
|
|
5377
|
+
if (isGlobPattern(pattern) && !isValidGlobPattern(pattern)) {
|
|
5378
|
+
console.warn(`\u26A0\uFE0F Invalid glob pattern "${pattern}": Pattern is malformed`);
|
|
5379
|
+
return input;
|
|
5380
|
+
}
|
|
5381
|
+
if (isGlobPattern(pattern)) {
|
|
5382
|
+
let longestMatch = -1;
|
|
5383
|
+
for (let i = 1; i <= input.length; i++) {
|
|
5384
|
+
const testPrefix = input.substring(0, i);
|
|
5385
|
+
if ((0, import_minimatch.minimatch)(testPrefix, pattern)) {
|
|
5386
|
+
longestMatch = i;
|
|
5388
5387
|
}
|
|
5389
|
-
return stripped;
|
|
5390
5388
|
}
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
if (input.startsWith(stringPattern)) {
|
|
5394
|
-
const stripped = input.substring(stringPattern.length);
|
|
5389
|
+
if (longestMatch > 0) {
|
|
5390
|
+
const stripped = input.substring(longestMatch);
|
|
5395
5391
|
if (ensureLeadingChar) {
|
|
5396
5392
|
if (stripped === "") {
|
|
5397
5393
|
return ensureLeadingChar;
|
|
@@ -5400,11 +5396,40 @@ function stripPrefix(input, pattern, ensureLeadingChar) {
|
|
|
5400
5396
|
return `${ensureLeadingChar}${stripped}`;
|
|
5401
5397
|
}
|
|
5402
5398
|
}
|
|
5403
|
-
return stripped;
|
|
5399
|
+
return stripped === "" && !ensureLeadingChar ? input : stripped;
|
|
5400
|
+
}
|
|
5401
|
+
return input;
|
|
5402
|
+
}
|
|
5403
|
+
if (input.startsWith(pattern)) {
|
|
5404
|
+
const stripped = input.substring(pattern.length);
|
|
5405
|
+
if (ensureLeadingChar) {
|
|
5406
|
+
if (stripped === "") {
|
|
5407
|
+
return ensureLeadingChar;
|
|
5408
|
+
}
|
|
5409
|
+
if (!stripped.startsWith(ensureLeadingChar)) {
|
|
5410
|
+
return `${ensureLeadingChar}${stripped}`;
|
|
5411
|
+
}
|
|
5404
5412
|
}
|
|
5413
|
+
return stripped;
|
|
5405
5414
|
}
|
|
5406
5415
|
return input;
|
|
5407
5416
|
}
|
|
5417
|
+
function stripPathPrefix(path, pattern) {
|
|
5418
|
+
if (!pattern) {
|
|
5419
|
+
return path;
|
|
5420
|
+
}
|
|
5421
|
+
if (!isGlobPattern(pattern)) {
|
|
5422
|
+
let normalizedPattern = pattern.trim();
|
|
5423
|
+
if (!normalizedPattern.startsWith("/")) {
|
|
5424
|
+
normalizedPattern = `/${normalizedPattern}`;
|
|
5425
|
+
}
|
|
5426
|
+
if (normalizedPattern.endsWith("/") && normalizedPattern !== "/") {
|
|
5427
|
+
normalizedPattern = normalizedPattern.slice(0, -1);
|
|
5428
|
+
}
|
|
5429
|
+
return stripPrefix(path, normalizedPattern, "/");
|
|
5430
|
+
}
|
|
5431
|
+
return stripPrefix(path, pattern, "/");
|
|
5432
|
+
}
|
|
5408
5433
|
|
|
5409
5434
|
// src/validators/array-validator.ts
|
|
5410
5435
|
init_cjs_shims();
|
|
@@ -5938,7 +5963,7 @@ function configurePatternCache(size) {
|
|
|
5938
5963
|
PATTERN_CACHE = new LRUCache(size);
|
|
5939
5964
|
}
|
|
5940
5965
|
}
|
|
5941
|
-
var
|
|
5966
|
+
var DEFAULT_FORMAT_MAP = {
|
|
5942
5967
|
uuid: "z.uuid()",
|
|
5943
5968
|
email: "z.email()",
|
|
5944
5969
|
uri: "z.url()",
|
|
@@ -5948,7 +5973,6 @@ var FORMAT_MAP = {
|
|
|
5948
5973
|
byte: "z.base64()",
|
|
5949
5974
|
binary: "z.string()",
|
|
5950
5975
|
date: "z.iso.date()",
|
|
5951
|
-
"date-time": "z.iso.datetime()",
|
|
5952
5976
|
time: "z.iso.time()",
|
|
5953
5977
|
duration: 'z.string().refine((val) => /^P(?:(?:\\d+Y)?(?:\\d+M)?(?:\\d+D)?(?:T(?:\\d+H)?(?:\\d+M)?(?:\\d+(?:\\.\\d+)?S)?)?|\\d+W)$/.test(val) && !/^PT?$/.test(val), { message: "Must be a valid ISO 8601 duration" })',
|
|
5954
5978
|
ipv4: "z.ipv4()",
|
|
@@ -5967,6 +5991,30 @@ var FORMAT_MAP = {
|
|
|
5967
5991
|
"json-pointer": 'z.string().refine((val) => val === "" || /^(\\/([^~/]|~0|~1)+)+$/.test(val), { message: "Must be a valid JSON Pointer (RFC 6901)" })',
|
|
5968
5992
|
"relative-json-pointer": 'z.string().refine((val) => /^(0|[1-9]\\d*)(#|(\\/([^~/]|~0|~1)+)*)$/.test(val), { message: "Must be a valid relative JSON Pointer" })'
|
|
5969
5993
|
};
|
|
5994
|
+
var FORMAT_MAP = {
|
|
5995
|
+
...DEFAULT_FORMAT_MAP,
|
|
5996
|
+
"date-time": "z.iso.datetime()"
|
|
5997
|
+
};
|
|
5998
|
+
function configureDateTimeFormat(pattern) {
|
|
5999
|
+
if (!pattern) {
|
|
6000
|
+
FORMAT_MAP["date-time"] = "z.iso.datetime()";
|
|
6001
|
+
return;
|
|
6002
|
+
}
|
|
6003
|
+
const patternStr = pattern instanceof RegExp ? pattern.source : pattern;
|
|
6004
|
+
if (patternStr === "") {
|
|
6005
|
+
FORMAT_MAP["date-time"] = "z.iso.datetime()";
|
|
6006
|
+
return;
|
|
6007
|
+
}
|
|
6008
|
+
try {
|
|
6009
|
+
new RegExp(patternStr);
|
|
6010
|
+
} catch (error) {
|
|
6011
|
+
throw new Error(
|
|
6012
|
+
`Invalid regular expression pattern for customDateTimeFormatRegex: ${patternStr}. ${error instanceof Error ? error.message : "Pattern is malformed"}`
|
|
6013
|
+
);
|
|
6014
|
+
}
|
|
6015
|
+
const escapedPattern = escapePattern(patternStr);
|
|
6016
|
+
FORMAT_MAP["date-time"] = `z.string().regex(/${escapedPattern}/)`;
|
|
6017
|
+
}
|
|
5970
6018
|
function generateStringValidation(schema, useDescribe) {
|
|
5971
6019
|
let validation = FORMAT_MAP[schema.format || ""] || "z.string()";
|
|
5972
6020
|
if (schema.minLength !== void 0) {
|
|
@@ -6256,7 +6304,8 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
6256
6304
|
if ((this.context.schemaType === "request" || this.context.schemaType === "response") && schema.properties) {
|
|
6257
6305
|
schema = this.filterNestedProperties(schema);
|
|
6258
6306
|
}
|
|
6259
|
-
const
|
|
6307
|
+
const effectiveDefaultNullable = isTopLevel ? false : this.context.defaultNullable;
|
|
6308
|
+
const nullable = isNullable(schema, effectiveDefaultNullable);
|
|
6260
6309
|
if (hasMultipleTypes(schema)) {
|
|
6261
6310
|
const union = this.generateMultiTypeUnion(schema, currentSchema);
|
|
6262
6311
|
return wrapNullable(union, nullable);
|
|
@@ -6284,9 +6333,25 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
6284
6333
|
return wrapNullable(zodLiteral, nullable);
|
|
6285
6334
|
}
|
|
6286
6335
|
if (schema.enum) {
|
|
6287
|
-
const
|
|
6288
|
-
|
|
6289
|
-
|
|
6336
|
+
const allBooleans = schema.enum.every((v) => typeof v === "boolean");
|
|
6337
|
+
if (allBooleans) {
|
|
6338
|
+
const zodBoolean = "z.boolean()";
|
|
6339
|
+
return wrapNullable(zodBoolean, nullable);
|
|
6340
|
+
}
|
|
6341
|
+
const allStrings = schema.enum.every((v) => typeof v === "string");
|
|
6342
|
+
if (allStrings) {
|
|
6343
|
+
const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
|
|
6344
|
+
const zodEnum = `z.enum([${enumValues}])`;
|
|
6345
|
+
return wrapNullable(zodEnum, nullable);
|
|
6346
|
+
}
|
|
6347
|
+
const literalValues = schema.enum.map((v) => {
|
|
6348
|
+
if (typeof v === "string") {
|
|
6349
|
+
return `z.literal("${v}")`;
|
|
6350
|
+
}
|
|
6351
|
+
return `z.literal(${v})`;
|
|
6352
|
+
}).join(", ");
|
|
6353
|
+
const zodUnion = `z.union([${literalValues}])`;
|
|
6354
|
+
return wrapNullable(zodUnion, nullable);
|
|
6290
6355
|
}
|
|
6291
6356
|
if (schema.allOf) {
|
|
6292
6357
|
let composition = generateAllOf(
|
|
@@ -6418,7 +6483,7 @@ var PropertyGenerator = _PropertyGenerator;
|
|
|
6418
6483
|
|
|
6419
6484
|
// src/utils/operation-filters.ts
|
|
6420
6485
|
init_cjs_shims();
|
|
6421
|
-
var
|
|
6486
|
+
var import_minimatch2 = require("minimatch");
|
|
6422
6487
|
function createFilterStatistics() {
|
|
6423
6488
|
return {
|
|
6424
6489
|
totalOperations: 0,
|
|
@@ -6437,7 +6502,7 @@ function matchesAnyPattern(value, patterns) {
|
|
|
6437
6502
|
if (!value) {
|
|
6438
6503
|
return false;
|
|
6439
6504
|
}
|
|
6440
|
-
return patterns.some((pattern) => (0,
|
|
6505
|
+
return patterns.some((pattern) => (0, import_minimatch2.minimatch)(value, pattern));
|
|
6441
6506
|
}
|
|
6442
6507
|
function containsAny(arr, values) {
|
|
6443
6508
|
if (!values || values.length === 0) {
|
|
@@ -6560,7 +6625,7 @@ var OpenApiGenerator = class {
|
|
|
6560
6625
|
this.schemaUsageMap = /* @__PURE__ */ new Map();
|
|
6561
6626
|
this.needsZodImport = true;
|
|
6562
6627
|
this.filterStats = createFilterStatistics();
|
|
6563
|
-
var _a, _b, _c, _d, _e;
|
|
6628
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
6564
6629
|
if (!options.input) {
|
|
6565
6630
|
throw new ConfigurationError("Input path is required", { providedOptions: options });
|
|
6566
6631
|
}
|
|
@@ -6570,21 +6635,27 @@ var OpenApiGenerator = class {
|
|
|
6570
6635
|
output: options.output,
|
|
6571
6636
|
includeDescriptions: (_a = options.includeDescriptions) != null ? _a : true,
|
|
6572
6637
|
useDescribe: (_b = options.useDescribe) != null ? _b : false,
|
|
6638
|
+
defaultNullable: (_c = options.defaultNullable) != null ? _c : false,
|
|
6573
6639
|
schemaType: options.schemaType || "all",
|
|
6574
6640
|
prefix: options.prefix,
|
|
6575
6641
|
suffix: options.suffix,
|
|
6576
6642
|
stripSchemaPrefix: options.stripSchemaPrefix,
|
|
6577
|
-
|
|
6643
|
+
stripPathPrefix: options.stripPathPrefix,
|
|
6644
|
+
showStats: (_d = options.showStats) != null ? _d : true,
|
|
6578
6645
|
request: options.request,
|
|
6579
6646
|
response: options.response,
|
|
6580
6647
|
operationFilters: options.operationFilters,
|
|
6581
6648
|
ignoreHeaders: options.ignoreHeaders,
|
|
6582
|
-
cacheSize: (
|
|
6583
|
-
batchSize: (
|
|
6649
|
+
cacheSize: (_e = options.cacheSize) != null ? _e : 1e3,
|
|
6650
|
+
batchSize: (_f = options.batchSize) != null ? _f : 10,
|
|
6651
|
+
customDateTimeFormatRegex: options.customDateTimeFormatRegex
|
|
6584
6652
|
};
|
|
6585
6653
|
if (this.options.cacheSize) {
|
|
6586
6654
|
configurePatternCache(this.options.cacheSize);
|
|
6587
6655
|
}
|
|
6656
|
+
if (this.options.customDateTimeFormatRegex) {
|
|
6657
|
+
configureDateTimeFormat(this.options.customDateTimeFormatRegex);
|
|
6658
|
+
}
|
|
6588
6659
|
try {
|
|
6589
6660
|
const fs = require("fs");
|
|
6590
6661
|
if (!fs.existsSync(this.options.input)) {
|
|
@@ -6647,6 +6718,7 @@ var OpenApiGenerator = class {
|
|
|
6647
6718
|
mode: this.requestOptions.mode,
|
|
6648
6719
|
includeDescriptions: this.requestOptions.includeDescriptions,
|
|
6649
6720
|
useDescribe: this.requestOptions.useDescribe,
|
|
6721
|
+
defaultNullable: (_g = this.options.defaultNullable) != null ? _g : false,
|
|
6650
6722
|
namingOptions: {
|
|
6651
6723
|
prefix: this.options.prefix,
|
|
6652
6724
|
suffix: this.options.suffix
|
|
@@ -6664,6 +6736,9 @@ var OpenApiGenerator = class {
|
|
|
6664
6736
|
throw new SpecValidationError("No schemas found in OpenAPI spec", { filePath: this.options.input });
|
|
6665
6737
|
}
|
|
6666
6738
|
for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
|
|
6739
|
+
if (this.options.operationFilters && this.schemaUsageMap.size > 0 && !this.schemaUsageMap.has(name)) {
|
|
6740
|
+
continue;
|
|
6741
|
+
}
|
|
6667
6742
|
this.generateComponentSchema(name, schema);
|
|
6668
6743
|
}
|
|
6669
6744
|
this.generateQueryParameterSchemas();
|
|
@@ -6997,7 +7072,7 @@ var OpenApiGenerator = class {
|
|
|
6997
7072
|
* Generate schema for a component
|
|
6998
7073
|
*/
|
|
6999
7074
|
generateComponentSchema(name, schema) {
|
|
7000
|
-
var _a, _b;
|
|
7075
|
+
var _a, _b, _c;
|
|
7001
7076
|
if (!this.schemaDependencies.has(name)) {
|
|
7002
7077
|
this.schemaDependencies.set(name, /* @__PURE__ */ new Set());
|
|
7003
7078
|
}
|
|
@@ -7029,14 +7104,14 @@ ${typeCode}`;
|
|
|
7029
7104
|
mode: resolvedOptions.mode,
|
|
7030
7105
|
includeDescriptions: resolvedOptions.includeDescriptions,
|
|
7031
7106
|
useDescribe: resolvedOptions.useDescribe,
|
|
7107
|
+
defaultNullable: (_b = this.options.defaultNullable) != null ? _b : false,
|
|
7032
7108
|
namingOptions: {
|
|
7033
7109
|
prefix: this.options.prefix,
|
|
7034
7110
|
suffix: this.options.suffix
|
|
7035
7111
|
},
|
|
7036
7112
|
stripSchemaPrefix: this.options.stripSchemaPrefix
|
|
7037
7113
|
});
|
|
7038
|
-
const
|
|
7039
|
-
const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, isAlias);
|
|
7114
|
+
const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, true);
|
|
7040
7115
|
const zodSchemaCode = `${jsdoc}export const ${schemaName} = ${zodSchema};`;
|
|
7041
7116
|
if (zodSchema.includes("z.discriminatedUnion(")) {
|
|
7042
7117
|
const match = zodSchema.match(/z\.discriminatedUnion\([^,]+,\s*\[([^\]]+)\]/);
|
|
@@ -7046,7 +7121,7 @@ ${typeCode}`;
|
|
|
7046
7121
|
const depMatch = ref.match(/^([a-z][a-zA-Z0-9]*?)Schema$/);
|
|
7047
7122
|
if (depMatch) {
|
|
7048
7123
|
const depName = depMatch[1].charAt(0).toUpperCase() + depMatch[1].slice(1);
|
|
7049
|
-
(
|
|
7124
|
+
(_c = this.schemaDependencies.get(name)) == null ? void 0 : _c.add(depName);
|
|
7050
7125
|
}
|
|
7051
7126
|
}
|
|
7052
7127
|
}
|
|
@@ -7070,7 +7145,7 @@ ${typeCode}`;
|
|
|
7070
7145
|
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
|
|
7071
7146
|
continue;
|
|
7072
7147
|
}
|
|
7073
|
-
if (!operation.
|
|
7148
|
+
if (!operation.parameters || !Array.isArray(operation.parameters)) {
|
|
7074
7149
|
continue;
|
|
7075
7150
|
}
|
|
7076
7151
|
const queryParams = operation.parameters.filter(
|
|
@@ -7079,7 +7154,13 @@ ${typeCode}`;
|
|
|
7079
7154
|
if (queryParams.length === 0) {
|
|
7080
7155
|
continue;
|
|
7081
7156
|
}
|
|
7082
|
-
|
|
7157
|
+
let pascalOperationId;
|
|
7158
|
+
if (operation.operationId) {
|
|
7159
|
+
pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
|
|
7160
|
+
} else {
|
|
7161
|
+
const strippedPath = stripPathPrefix(path, this.options.stripPathPrefix);
|
|
7162
|
+
pascalOperationId = this.generateMethodNameFromPath(method, strippedPath);
|
|
7163
|
+
}
|
|
7083
7164
|
const schemaName = `${pascalOperationId}QueryParams`;
|
|
7084
7165
|
if (!this.schemaDependencies.has(schemaName)) {
|
|
7085
7166
|
this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
|
|
@@ -7127,8 +7208,9 @@ ${propsCode}
|
|
|
7127
7208
|
const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
|
|
7128
7209
|
const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
|
|
7129
7210
|
const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}QueryParamsSchema`;
|
|
7211
|
+
const jsdocOperationName = operation.operationId || `${method.toUpperCase()} ${path}`;
|
|
7130
7212
|
const jsdoc = `/**
|
|
7131
|
-
* Query parameters for ${
|
|
7213
|
+
* Query parameters for ${jsdocOperationName}
|
|
7132
7214
|
*/
|
|
7133
7215
|
`;
|
|
7134
7216
|
const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
|
|
@@ -7137,6 +7219,35 @@ ${propsCode}
|
|
|
7137
7219
|
}
|
|
7138
7220
|
}
|
|
7139
7221
|
}
|
|
7222
|
+
/**
|
|
7223
|
+
* Generate a PascalCase method name from HTTP method and path
|
|
7224
|
+
* Used as fallback when operationId is not available
|
|
7225
|
+
* @internal
|
|
7226
|
+
*/
|
|
7227
|
+
generateMethodNameFromPath(method, path) {
|
|
7228
|
+
const segments = path.split("/").filter(Boolean).map((segment) => {
|
|
7229
|
+
if (segment.startsWith("{") && segment.endsWith("}")) {
|
|
7230
|
+
const paramName = segment.slice(1, -1);
|
|
7231
|
+
return `By${this.capitalizeSegment(paramName)}`;
|
|
7232
|
+
}
|
|
7233
|
+
return this.capitalizeSegment(segment);
|
|
7234
|
+
}).join("");
|
|
7235
|
+
const capitalizedMethod = method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
|
|
7236
|
+
return `${capitalizedMethod}${segments}`;
|
|
7237
|
+
}
|
|
7238
|
+
/**
|
|
7239
|
+
* Capitalizes a path segment, handling special characters like dashes, underscores, and dots
|
|
7240
|
+
* @internal
|
|
7241
|
+
*/
|
|
7242
|
+
capitalizeSegment(str) {
|
|
7243
|
+
if (str.includes("-") || str.includes("_") || str.includes(".")) {
|
|
7244
|
+
return str.split(/[-_.]/).map((part) => {
|
|
7245
|
+
if (!part) return "";
|
|
7246
|
+
return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
|
|
7247
|
+
}).join("");
|
|
7248
|
+
}
|
|
7249
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
7250
|
+
}
|
|
7140
7251
|
/**
|
|
7141
7252
|
* Check if a header should be ignored based on filter patterns
|
|
7142
7253
|
* @internal
|
|
@@ -7152,7 +7263,7 @@ ${propsCode}
|
|
|
7152
7263
|
const headerLower = headerName.toLowerCase();
|
|
7153
7264
|
return ignorePatterns.some((pattern) => {
|
|
7154
7265
|
const patternLower = pattern.toLowerCase();
|
|
7155
|
-
return (0,
|
|
7266
|
+
return (0, import_minimatch3.minimatch)(headerLower, patternLower);
|
|
7156
7267
|
});
|
|
7157
7268
|
}
|
|
7158
7269
|
/**
|
|
@@ -7173,7 +7284,7 @@ ${propsCode}
|
|
|
7173
7284
|
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
|
|
7174
7285
|
continue;
|
|
7175
7286
|
}
|
|
7176
|
-
if (!operation.
|
|
7287
|
+
if (!operation.parameters || !Array.isArray(operation.parameters)) {
|
|
7177
7288
|
continue;
|
|
7178
7289
|
}
|
|
7179
7290
|
const headerParams = operation.parameters.filter(
|
|
@@ -7182,7 +7293,13 @@ ${propsCode}
|
|
|
7182
7293
|
if (headerParams.length === 0) {
|
|
7183
7294
|
continue;
|
|
7184
7295
|
}
|
|
7185
|
-
|
|
7296
|
+
let pascalOperationId;
|
|
7297
|
+
if (operation.operationId) {
|
|
7298
|
+
pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
|
|
7299
|
+
} else {
|
|
7300
|
+
const strippedPath = stripPathPrefix(path, this.options.stripPathPrefix);
|
|
7301
|
+
pascalOperationId = this.generateMethodNameFromPath(method, strippedPath);
|
|
7302
|
+
}
|
|
7186
7303
|
const schemaName = `${pascalOperationId}HeaderParams`;
|
|
7187
7304
|
if (!this.schemaDependencies.has(schemaName)) {
|
|
7188
7305
|
this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
|
|
@@ -7219,8 +7336,9 @@ ${propsCode}
|
|
|
7219
7336
|
const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
|
|
7220
7337
|
const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
|
|
7221
7338
|
const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}HeaderParamsSchema`;
|
|
7339
|
+
const jsdocOperationName = operation.operationId || `${method.toUpperCase()} ${path}`;
|
|
7222
7340
|
const jsdoc = `/**
|
|
7223
|
-
* Header parameters for ${
|
|
7341
|
+
* Header parameters for ${jsdocOperationName}
|
|
7224
7342
|
*/
|
|
7225
7343
|
`;
|
|
7226
7344
|
const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
|
|
@@ -7240,8 +7358,22 @@ ${propsCode}
|
|
|
7240
7358
|
return `${schemaName}Schema`;
|
|
7241
7359
|
}
|
|
7242
7360
|
if (schema.enum) {
|
|
7243
|
-
const
|
|
7244
|
-
|
|
7361
|
+
const allBooleans = schema.enum.every((v) => typeof v === "boolean");
|
|
7362
|
+
if (allBooleans) {
|
|
7363
|
+
return "z.boolean()";
|
|
7364
|
+
}
|
|
7365
|
+
const allStrings = schema.enum.every((v) => typeof v === "string");
|
|
7366
|
+
if (allStrings) {
|
|
7367
|
+
const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
|
|
7368
|
+
return `z.enum([${enumValues}])`;
|
|
7369
|
+
}
|
|
7370
|
+
const literalValues = schema.enum.map((v) => {
|
|
7371
|
+
if (typeof v === "string") {
|
|
7372
|
+
return `z.literal("${v}")`;
|
|
7373
|
+
}
|
|
7374
|
+
return `z.literal(${v})`;
|
|
7375
|
+
}).join(", ");
|
|
7376
|
+
return `z.union([${literalValues}])`;
|
|
7245
7377
|
}
|
|
7246
7378
|
const type = schema.type;
|
|
7247
7379
|
if (type === "string") {
|
|
@@ -7386,7 +7518,8 @@ var import_zod = require("zod");
|
|
|
7386
7518
|
var RequestResponseOptionsSchema = import_zod.z.strictObject({
|
|
7387
7519
|
mode: import_zod.z.enum(["strict", "normal", "loose"]).optional(),
|
|
7388
7520
|
useDescribe: import_zod.z.boolean().optional(),
|
|
7389
|
-
includeDescriptions: import_zod.z.boolean().optional()
|
|
7521
|
+
includeDescriptions: import_zod.z.boolean().optional(),
|
|
7522
|
+
defaultNullable: import_zod.z.boolean().optional()
|
|
7390
7523
|
});
|
|
7391
7524
|
var OperationFiltersSchema = import_zod.z.strictObject({
|
|
7392
7525
|
includeTags: import_zod.z.array(import_zod.z.string()).optional(),
|
|
@@ -7469,6 +7602,7 @@ var OpenApiGeneratorOptionsSchema = import_zod2.z.strictObject({
|
|
|
7469
7602
|
output: import_zod2.z.string(),
|
|
7470
7603
|
includeDescriptions: import_zod2.z.boolean().optional(),
|
|
7471
7604
|
useDescribe: import_zod2.z.boolean().optional(),
|
|
7605
|
+
defaultNullable: import_zod2.z.boolean().optional(),
|
|
7472
7606
|
schemaType: import_zod2.z.enum(["all", "request", "response"]).optional(),
|
|
7473
7607
|
prefix: import_zod2.z.string().optional(),
|
|
7474
7608
|
suffix: import_zod2.z.string().optional(),
|
|
@@ -7479,13 +7613,28 @@ var OpenApiGeneratorOptionsSchema = import_zod2.z.strictObject({
|
|
|
7479
7613
|
name: import_zod2.z.string().optional(),
|
|
7480
7614
|
operationFilters: OperationFiltersSchema.optional(),
|
|
7481
7615
|
cacheSize: import_zod2.z.number().positive().optional(),
|
|
7482
|
-
batchSize: import_zod2.z.number().positive().optional()
|
|
7616
|
+
batchSize: import_zod2.z.number().positive().optional(),
|
|
7617
|
+
customDateTimeFormatRegex: import_zod2.z.union([
|
|
7618
|
+
import_zod2.z.string().refine(
|
|
7619
|
+
(pattern) => {
|
|
7620
|
+
try {
|
|
7621
|
+
new RegExp(pattern);
|
|
7622
|
+
return true;
|
|
7623
|
+
} catch {
|
|
7624
|
+
return false;
|
|
7625
|
+
}
|
|
7626
|
+
},
|
|
7627
|
+
{ message: "Must be a valid regular expression pattern" }
|
|
7628
|
+
),
|
|
7629
|
+
import_zod2.z.instanceof(RegExp)
|
|
7630
|
+
]).optional()
|
|
7483
7631
|
});
|
|
7484
7632
|
var ConfigFileSchema = import_zod2.z.strictObject({
|
|
7485
7633
|
defaults: import_zod2.z.strictObject({
|
|
7486
7634
|
mode: import_zod2.z.enum(["strict", "normal", "loose"]).optional(),
|
|
7487
7635
|
includeDescriptions: import_zod2.z.boolean().optional(),
|
|
7488
7636
|
useDescribe: import_zod2.z.boolean().optional(),
|
|
7637
|
+
defaultNullable: import_zod2.z.boolean().optional(),
|
|
7489
7638
|
schemaType: import_zod2.z.enum(["all", "request", "response"]).optional(),
|
|
7490
7639
|
prefix: import_zod2.z.string().optional(),
|
|
7491
7640
|
suffix: import_zod2.z.string().optional(),
|
|
@@ -7495,7 +7644,21 @@ var ConfigFileSchema = import_zod2.z.strictObject({
|
|
|
7495
7644
|
response: RequestResponseOptionsSchema.optional(),
|
|
7496
7645
|
operationFilters: OperationFiltersSchema.optional(),
|
|
7497
7646
|
cacheSize: import_zod2.z.number().positive().optional(),
|
|
7498
|
-
batchSize: import_zod2.z.number().positive().optional()
|
|
7647
|
+
batchSize: import_zod2.z.number().positive().optional(),
|
|
7648
|
+
customDateTimeFormatRegex: import_zod2.z.union([
|
|
7649
|
+
import_zod2.z.string().refine(
|
|
7650
|
+
(pattern) => {
|
|
7651
|
+
try {
|
|
7652
|
+
new RegExp(pattern);
|
|
7653
|
+
return true;
|
|
7654
|
+
} catch {
|
|
7655
|
+
return false;
|
|
7656
|
+
}
|
|
7657
|
+
},
|
|
7658
|
+
{ message: "Must be a valid regular expression pattern" }
|
|
7659
|
+
),
|
|
7660
|
+
import_zod2.z.instanceof(RegExp)
|
|
7661
|
+
]).optional()
|
|
7499
7662
|
}).optional(),
|
|
7500
7663
|
specs: import_zod2.z.array(OpenApiGeneratorOptionsSchema).min(1, {
|
|
7501
7664
|
message: "Configuration must include at least one specification. Each specification should have 'input' and 'output' paths."
|
|
@@ -7544,10 +7707,12 @@ function mergeConfigWithDefaults(config) {
|
|
|
7544
7707
|
mode: defaults.mode,
|
|
7545
7708
|
includeDescriptions: defaults.includeDescriptions,
|
|
7546
7709
|
useDescribe: defaults.useDescribe,
|
|
7710
|
+
defaultNullable: defaults.defaultNullable,
|
|
7547
7711
|
schemaType: defaults.schemaType,
|
|
7548
7712
|
prefix: defaults.prefix,
|
|
7549
7713
|
suffix: defaults.suffix,
|
|
7550
7714
|
showStats: defaults.showStats,
|
|
7715
|
+
customDateTimeFormatRegex: defaults.customDateTimeFormatRegex,
|
|
7551
7716
|
// Override with spec-specific values (including required input/output)
|
|
7552
7717
|
...spec
|
|
7553
7718
|
};
|