@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/index.mjs
CHANGED
|
@@ -67,7 +67,7 @@ var ConfigurationError = class extends GeneratorError {
|
|
|
67
67
|
// src/openapi-generator.ts
|
|
68
68
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
69
69
|
import { dirname, normalize } from "path";
|
|
70
|
-
import { minimatch as
|
|
70
|
+
import { minimatch as minimatch3 } from "minimatch";
|
|
71
71
|
import { parse } from "yaml";
|
|
72
72
|
|
|
73
73
|
// src/utils/name-utils.ts
|
|
@@ -126,8 +126,26 @@ function resolveRef(ref) {
|
|
|
126
126
|
function generateEnum(name, values, options) {
|
|
127
127
|
const schemaName = `${toCamelCase(name, options)}Schema`;
|
|
128
128
|
const typeName = toPascalCase(name);
|
|
129
|
-
const
|
|
130
|
-
|
|
129
|
+
const allBooleans = values.every((v) => typeof v === "boolean");
|
|
130
|
+
if (allBooleans) {
|
|
131
|
+
const schemaCode2 = `export const ${schemaName} = z.boolean();`;
|
|
132
|
+
const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
|
|
133
|
+
return { schemaCode: schemaCode2, typeCode: typeCode2 };
|
|
134
|
+
}
|
|
135
|
+
const allStrings = values.every((v) => typeof v === "string");
|
|
136
|
+
if (allStrings) {
|
|
137
|
+
const enumValues = values.map((v) => `"${v}"`).join(", ");
|
|
138
|
+
const schemaCode2 = `export const ${schemaName} = z.enum([${enumValues}]);`;
|
|
139
|
+
const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
|
|
140
|
+
return { schemaCode: schemaCode2, typeCode: typeCode2 };
|
|
141
|
+
}
|
|
142
|
+
const literalValues = values.map((v) => {
|
|
143
|
+
if (typeof v === "string") {
|
|
144
|
+
return `z.literal("${v}")`;
|
|
145
|
+
}
|
|
146
|
+
return `z.literal(${v})`;
|
|
147
|
+
}).join(", ");
|
|
148
|
+
const schemaCode = `export const ${schemaName} = z.union([${literalValues}]);`;
|
|
131
149
|
const typeCode = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
|
|
132
150
|
return { schemaCode, typeCode };
|
|
133
151
|
}
|
|
@@ -137,7 +155,7 @@ function escapeDescription(str) {
|
|
|
137
155
|
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
|
|
138
156
|
}
|
|
139
157
|
function escapePattern(str) {
|
|
140
|
-
return str.replace(
|
|
158
|
+
return str.replace(/\//g, "\\/");
|
|
141
159
|
}
|
|
142
160
|
function escapeJSDoc(str) {
|
|
143
161
|
return str.replace(/\*\//g, "*\\/");
|
|
@@ -145,14 +163,17 @@ function escapeJSDoc(str) {
|
|
|
145
163
|
function wrapNullable(validation, isNullable2) {
|
|
146
164
|
return isNullable2 ? `${validation}.nullable()` : validation;
|
|
147
165
|
}
|
|
148
|
-
function isNullable(schema) {
|
|
166
|
+
function isNullable(schema, defaultNullable = false) {
|
|
149
167
|
if (schema.nullable === true) {
|
|
150
168
|
return true;
|
|
151
169
|
}
|
|
170
|
+
if (schema.nullable === false) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
152
173
|
if (Array.isArray(schema.type)) {
|
|
153
174
|
return schema.type.includes("null");
|
|
154
175
|
}
|
|
155
|
-
return
|
|
176
|
+
return defaultNullable;
|
|
156
177
|
}
|
|
157
178
|
function getPrimaryType(schema) {
|
|
158
179
|
if (Array.isArray(schema.type)) {
|
|
@@ -262,61 +283,36 @@ var LRUCache = class {
|
|
|
262
283
|
};
|
|
263
284
|
|
|
264
285
|
// src/utils/pattern-utils.ts
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
if (/\\[dDwWsS]/.test(pattern)) {
|
|
270
|
-
return true;
|
|
271
|
-
}
|
|
272
|
-
if (/\.\*|\.\+/.test(pattern)) {
|
|
273
|
-
return true;
|
|
274
|
-
}
|
|
275
|
-
if (/[[\]()]/.test(pattern)) {
|
|
276
|
-
return true;
|
|
277
|
-
}
|
|
278
|
-
if (/[^/][+?*]\{/.test(pattern)) {
|
|
286
|
+
import { minimatch } from "minimatch";
|
|
287
|
+
function isValidGlobPattern(pattern) {
|
|
288
|
+
try {
|
|
289
|
+
new minimatch.Minimatch(pattern);
|
|
279
290
|
return true;
|
|
291
|
+
} catch {
|
|
292
|
+
return false;
|
|
280
293
|
}
|
|
281
|
-
return false;
|
|
282
294
|
}
|
|
283
|
-
function
|
|
284
|
-
|
|
285
|
-
return pattern;
|
|
286
|
-
}
|
|
287
|
-
if (isRegexPattern(pattern)) {
|
|
288
|
-
try {
|
|
289
|
-
return new RegExp(pattern);
|
|
290
|
-
} catch (error) {
|
|
291
|
-
console.warn(`\u26A0\uFE0F Invalid regex pattern "${pattern}": ${error instanceof Error ? error.message : String(error)}`);
|
|
292
|
-
return null;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
return null;
|
|
295
|
+
function isGlobPattern(pattern) {
|
|
296
|
+
return /[*?[\]{}!]/.test(pattern);
|
|
296
297
|
}
|
|
297
298
|
function stripPrefix(input, pattern, ensureLeadingChar) {
|
|
298
299
|
if (!pattern) {
|
|
299
300
|
return input;
|
|
300
301
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
return `${ensureLeadingChar}${stripped}`;
|
|
312
|
-
}
|
|
302
|
+
if (isGlobPattern(pattern) && !isValidGlobPattern(pattern)) {
|
|
303
|
+
console.warn(`\u26A0\uFE0F Invalid glob pattern "${pattern}": Pattern is malformed`);
|
|
304
|
+
return input;
|
|
305
|
+
}
|
|
306
|
+
if (isGlobPattern(pattern)) {
|
|
307
|
+
let longestMatch = -1;
|
|
308
|
+
for (let i = 1; i <= input.length; i++) {
|
|
309
|
+
const testPrefix = input.substring(0, i);
|
|
310
|
+
if (minimatch(testPrefix, pattern)) {
|
|
311
|
+
longestMatch = i;
|
|
313
312
|
}
|
|
314
|
-
return stripped;
|
|
315
313
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
if (input.startsWith(stringPattern)) {
|
|
319
|
-
const stripped = input.substring(stringPattern.length);
|
|
314
|
+
if (longestMatch > 0) {
|
|
315
|
+
const stripped = input.substring(longestMatch);
|
|
320
316
|
if (ensureLeadingChar) {
|
|
321
317
|
if (stripped === "") {
|
|
322
318
|
return ensureLeadingChar;
|
|
@@ -325,11 +321,40 @@ function stripPrefix(input, pattern, ensureLeadingChar) {
|
|
|
325
321
|
return `${ensureLeadingChar}${stripped}`;
|
|
326
322
|
}
|
|
327
323
|
}
|
|
328
|
-
return stripped;
|
|
324
|
+
return stripped === "" && !ensureLeadingChar ? input : stripped;
|
|
329
325
|
}
|
|
326
|
+
return input;
|
|
327
|
+
}
|
|
328
|
+
if (input.startsWith(pattern)) {
|
|
329
|
+
const stripped = input.substring(pattern.length);
|
|
330
|
+
if (ensureLeadingChar) {
|
|
331
|
+
if (stripped === "") {
|
|
332
|
+
return ensureLeadingChar;
|
|
333
|
+
}
|
|
334
|
+
if (!stripped.startsWith(ensureLeadingChar)) {
|
|
335
|
+
return `${ensureLeadingChar}${stripped}`;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return stripped;
|
|
330
339
|
}
|
|
331
340
|
return input;
|
|
332
341
|
}
|
|
342
|
+
function stripPathPrefix(path, pattern) {
|
|
343
|
+
if (!pattern) {
|
|
344
|
+
return path;
|
|
345
|
+
}
|
|
346
|
+
if (!isGlobPattern(pattern)) {
|
|
347
|
+
let normalizedPattern = pattern.trim();
|
|
348
|
+
if (!normalizedPattern.startsWith("/")) {
|
|
349
|
+
normalizedPattern = `/${normalizedPattern}`;
|
|
350
|
+
}
|
|
351
|
+
if (normalizedPattern.endsWith("/") && normalizedPattern !== "/") {
|
|
352
|
+
normalizedPattern = normalizedPattern.slice(0, -1);
|
|
353
|
+
}
|
|
354
|
+
return stripPrefix(path, normalizedPattern, "/");
|
|
355
|
+
}
|
|
356
|
+
return stripPrefix(path, pattern, "/");
|
|
357
|
+
}
|
|
333
358
|
|
|
334
359
|
// src/validators/array-validator.ts
|
|
335
360
|
function generateArrayValidation(schema, context) {
|
|
@@ -855,7 +880,7 @@ function configurePatternCache(size) {
|
|
|
855
880
|
PATTERN_CACHE = new LRUCache(size);
|
|
856
881
|
}
|
|
857
882
|
}
|
|
858
|
-
var
|
|
883
|
+
var DEFAULT_FORMAT_MAP = {
|
|
859
884
|
uuid: "z.uuid()",
|
|
860
885
|
email: "z.email()",
|
|
861
886
|
uri: "z.url()",
|
|
@@ -865,7 +890,6 @@ var FORMAT_MAP = {
|
|
|
865
890
|
byte: "z.base64()",
|
|
866
891
|
binary: "z.string()",
|
|
867
892
|
date: "z.iso.date()",
|
|
868
|
-
"date-time": "z.iso.datetime()",
|
|
869
893
|
time: "z.iso.time()",
|
|
870
894
|
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" })',
|
|
871
895
|
ipv4: "z.ipv4()",
|
|
@@ -884,6 +908,30 @@ var FORMAT_MAP = {
|
|
|
884
908
|
"json-pointer": 'z.string().refine((val) => val === "" || /^(\\/([^~/]|~0|~1)+)+$/.test(val), { message: "Must be a valid JSON Pointer (RFC 6901)" })',
|
|
885
909
|
"relative-json-pointer": 'z.string().refine((val) => /^(0|[1-9]\\d*)(#|(\\/([^~/]|~0|~1)+)*)$/.test(val), { message: "Must be a valid relative JSON Pointer" })'
|
|
886
910
|
};
|
|
911
|
+
var FORMAT_MAP = {
|
|
912
|
+
...DEFAULT_FORMAT_MAP,
|
|
913
|
+
"date-time": "z.iso.datetime()"
|
|
914
|
+
};
|
|
915
|
+
function configureDateTimeFormat(pattern) {
|
|
916
|
+
if (!pattern) {
|
|
917
|
+
FORMAT_MAP["date-time"] = "z.iso.datetime()";
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
const patternStr = pattern instanceof RegExp ? pattern.source : pattern;
|
|
921
|
+
if (patternStr === "") {
|
|
922
|
+
FORMAT_MAP["date-time"] = "z.iso.datetime()";
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
try {
|
|
926
|
+
new RegExp(patternStr);
|
|
927
|
+
} catch (error) {
|
|
928
|
+
throw new Error(
|
|
929
|
+
`Invalid regular expression pattern for customDateTimeFormatRegex: ${patternStr}. ${error instanceof Error ? error.message : "Pattern is malformed"}`
|
|
930
|
+
);
|
|
931
|
+
}
|
|
932
|
+
const escapedPattern = escapePattern(patternStr);
|
|
933
|
+
FORMAT_MAP["date-time"] = `z.string().regex(/${escapedPattern}/)`;
|
|
934
|
+
}
|
|
887
935
|
function generateStringValidation(schema, useDescribe) {
|
|
888
936
|
let validation = FORMAT_MAP[schema.format || ""] || "z.string()";
|
|
889
937
|
if (schema.minLength !== void 0) {
|
|
@@ -1173,7 +1221,8 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1173
1221
|
if ((this.context.schemaType === "request" || this.context.schemaType === "response") && schema.properties) {
|
|
1174
1222
|
schema = this.filterNestedProperties(schema);
|
|
1175
1223
|
}
|
|
1176
|
-
const
|
|
1224
|
+
const effectiveDefaultNullable = isTopLevel ? false : this.context.defaultNullable;
|
|
1225
|
+
const nullable = isNullable(schema, effectiveDefaultNullable);
|
|
1177
1226
|
if (hasMultipleTypes(schema)) {
|
|
1178
1227
|
const union = this.generateMultiTypeUnion(schema, currentSchema);
|
|
1179
1228
|
return wrapNullable(union, nullable);
|
|
@@ -1201,9 +1250,25 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1201
1250
|
return wrapNullable(zodLiteral, nullable);
|
|
1202
1251
|
}
|
|
1203
1252
|
if (schema.enum) {
|
|
1204
|
-
const
|
|
1205
|
-
|
|
1206
|
-
|
|
1253
|
+
const allBooleans = schema.enum.every((v) => typeof v === "boolean");
|
|
1254
|
+
if (allBooleans) {
|
|
1255
|
+
const zodBoolean = "z.boolean()";
|
|
1256
|
+
return wrapNullable(zodBoolean, nullable);
|
|
1257
|
+
}
|
|
1258
|
+
const allStrings = schema.enum.every((v) => typeof v === "string");
|
|
1259
|
+
if (allStrings) {
|
|
1260
|
+
const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
|
|
1261
|
+
const zodEnum = `z.enum([${enumValues}])`;
|
|
1262
|
+
return wrapNullable(zodEnum, nullable);
|
|
1263
|
+
}
|
|
1264
|
+
const literalValues = schema.enum.map((v) => {
|
|
1265
|
+
if (typeof v === "string") {
|
|
1266
|
+
return `z.literal("${v}")`;
|
|
1267
|
+
}
|
|
1268
|
+
return `z.literal(${v})`;
|
|
1269
|
+
}).join(", ");
|
|
1270
|
+
const zodUnion = `z.union([${literalValues}])`;
|
|
1271
|
+
return wrapNullable(zodUnion, nullable);
|
|
1207
1272
|
}
|
|
1208
1273
|
if (schema.allOf) {
|
|
1209
1274
|
let composition = generateAllOf(
|
|
@@ -1334,7 +1399,7 @@ _PropertyGenerator.INCLUSION_RULES = {
|
|
|
1334
1399
|
var PropertyGenerator = _PropertyGenerator;
|
|
1335
1400
|
|
|
1336
1401
|
// src/utils/operation-filters.ts
|
|
1337
|
-
import { minimatch } from "minimatch";
|
|
1402
|
+
import { minimatch as minimatch2 } from "minimatch";
|
|
1338
1403
|
function createFilterStatistics() {
|
|
1339
1404
|
return {
|
|
1340
1405
|
totalOperations: 0,
|
|
@@ -1353,7 +1418,7 @@ function matchesAnyPattern(value, patterns) {
|
|
|
1353
1418
|
if (!value) {
|
|
1354
1419
|
return false;
|
|
1355
1420
|
}
|
|
1356
|
-
return patterns.some((pattern) =>
|
|
1421
|
+
return patterns.some((pattern) => minimatch2(value, pattern));
|
|
1357
1422
|
}
|
|
1358
1423
|
function containsAny(arr, values) {
|
|
1359
1424
|
if (!values || values.length === 0) {
|
|
@@ -1476,7 +1541,7 @@ var OpenApiGenerator = class {
|
|
|
1476
1541
|
this.schemaUsageMap = /* @__PURE__ */ new Map();
|
|
1477
1542
|
this.needsZodImport = true;
|
|
1478
1543
|
this.filterStats = createFilterStatistics();
|
|
1479
|
-
var _a, _b, _c, _d, _e;
|
|
1544
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1480
1545
|
if (!options.input) {
|
|
1481
1546
|
throw new ConfigurationError("Input path is required", { providedOptions: options });
|
|
1482
1547
|
}
|
|
@@ -1486,21 +1551,27 @@ var OpenApiGenerator = class {
|
|
|
1486
1551
|
output: options.output,
|
|
1487
1552
|
includeDescriptions: (_a = options.includeDescriptions) != null ? _a : true,
|
|
1488
1553
|
useDescribe: (_b = options.useDescribe) != null ? _b : false,
|
|
1554
|
+
defaultNullable: (_c = options.defaultNullable) != null ? _c : false,
|
|
1489
1555
|
schemaType: options.schemaType || "all",
|
|
1490
1556
|
prefix: options.prefix,
|
|
1491
1557
|
suffix: options.suffix,
|
|
1492
1558
|
stripSchemaPrefix: options.stripSchemaPrefix,
|
|
1493
|
-
|
|
1559
|
+
stripPathPrefix: options.stripPathPrefix,
|
|
1560
|
+
showStats: (_d = options.showStats) != null ? _d : true,
|
|
1494
1561
|
request: options.request,
|
|
1495
1562
|
response: options.response,
|
|
1496
1563
|
operationFilters: options.operationFilters,
|
|
1497
1564
|
ignoreHeaders: options.ignoreHeaders,
|
|
1498
|
-
cacheSize: (
|
|
1499
|
-
batchSize: (
|
|
1565
|
+
cacheSize: (_e = options.cacheSize) != null ? _e : 1e3,
|
|
1566
|
+
batchSize: (_f = options.batchSize) != null ? _f : 10,
|
|
1567
|
+
customDateTimeFormatRegex: options.customDateTimeFormatRegex
|
|
1500
1568
|
};
|
|
1501
1569
|
if (this.options.cacheSize) {
|
|
1502
1570
|
configurePatternCache(this.options.cacheSize);
|
|
1503
1571
|
}
|
|
1572
|
+
if (this.options.customDateTimeFormatRegex) {
|
|
1573
|
+
configureDateTimeFormat(this.options.customDateTimeFormatRegex);
|
|
1574
|
+
}
|
|
1504
1575
|
try {
|
|
1505
1576
|
const fs = __require("fs");
|
|
1506
1577
|
if (!fs.existsSync(this.options.input)) {
|
|
@@ -1563,6 +1634,7 @@ var OpenApiGenerator = class {
|
|
|
1563
1634
|
mode: this.requestOptions.mode,
|
|
1564
1635
|
includeDescriptions: this.requestOptions.includeDescriptions,
|
|
1565
1636
|
useDescribe: this.requestOptions.useDescribe,
|
|
1637
|
+
defaultNullable: (_g = this.options.defaultNullable) != null ? _g : false,
|
|
1566
1638
|
namingOptions: {
|
|
1567
1639
|
prefix: this.options.prefix,
|
|
1568
1640
|
suffix: this.options.suffix
|
|
@@ -1580,6 +1652,9 @@ var OpenApiGenerator = class {
|
|
|
1580
1652
|
throw new SpecValidationError("No schemas found in OpenAPI spec", { filePath: this.options.input });
|
|
1581
1653
|
}
|
|
1582
1654
|
for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
|
|
1655
|
+
if (this.options.operationFilters && this.schemaUsageMap.size > 0 && !this.schemaUsageMap.has(name)) {
|
|
1656
|
+
continue;
|
|
1657
|
+
}
|
|
1583
1658
|
this.generateComponentSchema(name, schema);
|
|
1584
1659
|
}
|
|
1585
1660
|
this.generateQueryParameterSchemas();
|
|
@@ -1913,7 +1988,7 @@ var OpenApiGenerator = class {
|
|
|
1913
1988
|
* Generate schema for a component
|
|
1914
1989
|
*/
|
|
1915
1990
|
generateComponentSchema(name, schema) {
|
|
1916
|
-
var _a, _b;
|
|
1991
|
+
var _a, _b, _c;
|
|
1917
1992
|
if (!this.schemaDependencies.has(name)) {
|
|
1918
1993
|
this.schemaDependencies.set(name, /* @__PURE__ */ new Set());
|
|
1919
1994
|
}
|
|
@@ -1945,14 +2020,14 @@ ${typeCode}`;
|
|
|
1945
2020
|
mode: resolvedOptions.mode,
|
|
1946
2021
|
includeDescriptions: resolvedOptions.includeDescriptions,
|
|
1947
2022
|
useDescribe: resolvedOptions.useDescribe,
|
|
2023
|
+
defaultNullable: (_b = this.options.defaultNullable) != null ? _b : false,
|
|
1948
2024
|
namingOptions: {
|
|
1949
2025
|
prefix: this.options.prefix,
|
|
1950
2026
|
suffix: this.options.suffix
|
|
1951
2027
|
},
|
|
1952
2028
|
stripSchemaPrefix: this.options.stripSchemaPrefix
|
|
1953
2029
|
});
|
|
1954
|
-
const
|
|
1955
|
-
const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, isAlias);
|
|
2030
|
+
const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, true);
|
|
1956
2031
|
const zodSchemaCode = `${jsdoc}export const ${schemaName} = ${zodSchema};`;
|
|
1957
2032
|
if (zodSchema.includes("z.discriminatedUnion(")) {
|
|
1958
2033
|
const match = zodSchema.match(/z\.discriminatedUnion\([^,]+,\s*\[([^\]]+)\]/);
|
|
@@ -1962,7 +2037,7 @@ ${typeCode}`;
|
|
|
1962
2037
|
const depMatch = ref.match(/^([a-z][a-zA-Z0-9]*?)Schema$/);
|
|
1963
2038
|
if (depMatch) {
|
|
1964
2039
|
const depName = depMatch[1].charAt(0).toUpperCase() + depMatch[1].slice(1);
|
|
1965
|
-
(
|
|
2040
|
+
(_c = this.schemaDependencies.get(name)) == null ? void 0 : _c.add(depName);
|
|
1966
2041
|
}
|
|
1967
2042
|
}
|
|
1968
2043
|
}
|
|
@@ -1986,7 +2061,7 @@ ${typeCode}`;
|
|
|
1986
2061
|
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
|
|
1987
2062
|
continue;
|
|
1988
2063
|
}
|
|
1989
|
-
if (!operation.
|
|
2064
|
+
if (!operation.parameters || !Array.isArray(operation.parameters)) {
|
|
1990
2065
|
continue;
|
|
1991
2066
|
}
|
|
1992
2067
|
const queryParams = operation.parameters.filter(
|
|
@@ -1995,7 +2070,13 @@ ${typeCode}`;
|
|
|
1995
2070
|
if (queryParams.length === 0) {
|
|
1996
2071
|
continue;
|
|
1997
2072
|
}
|
|
1998
|
-
|
|
2073
|
+
let pascalOperationId;
|
|
2074
|
+
if (operation.operationId) {
|
|
2075
|
+
pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
|
|
2076
|
+
} else {
|
|
2077
|
+
const strippedPath = stripPathPrefix(path, this.options.stripPathPrefix);
|
|
2078
|
+
pascalOperationId = this.generateMethodNameFromPath(method, strippedPath);
|
|
2079
|
+
}
|
|
1999
2080
|
const schemaName = `${pascalOperationId}QueryParams`;
|
|
2000
2081
|
if (!this.schemaDependencies.has(schemaName)) {
|
|
2001
2082
|
this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
|
|
@@ -2043,8 +2124,9 @@ ${propsCode}
|
|
|
2043
2124
|
const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
|
|
2044
2125
|
const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
|
|
2045
2126
|
const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}QueryParamsSchema`;
|
|
2127
|
+
const jsdocOperationName = operation.operationId || `${method.toUpperCase()} ${path}`;
|
|
2046
2128
|
const jsdoc = `/**
|
|
2047
|
-
* Query parameters for ${
|
|
2129
|
+
* Query parameters for ${jsdocOperationName}
|
|
2048
2130
|
*/
|
|
2049
2131
|
`;
|
|
2050
2132
|
const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
|
|
@@ -2053,6 +2135,35 @@ ${propsCode}
|
|
|
2053
2135
|
}
|
|
2054
2136
|
}
|
|
2055
2137
|
}
|
|
2138
|
+
/**
|
|
2139
|
+
* Generate a PascalCase method name from HTTP method and path
|
|
2140
|
+
* Used as fallback when operationId is not available
|
|
2141
|
+
* @internal
|
|
2142
|
+
*/
|
|
2143
|
+
generateMethodNameFromPath(method, path) {
|
|
2144
|
+
const segments = path.split("/").filter(Boolean).map((segment) => {
|
|
2145
|
+
if (segment.startsWith("{") && segment.endsWith("}")) {
|
|
2146
|
+
const paramName = segment.slice(1, -1);
|
|
2147
|
+
return `By${this.capitalizeSegment(paramName)}`;
|
|
2148
|
+
}
|
|
2149
|
+
return this.capitalizeSegment(segment);
|
|
2150
|
+
}).join("");
|
|
2151
|
+
const capitalizedMethod = method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
|
|
2152
|
+
return `${capitalizedMethod}${segments}`;
|
|
2153
|
+
}
|
|
2154
|
+
/**
|
|
2155
|
+
* Capitalizes a path segment, handling special characters like dashes, underscores, and dots
|
|
2156
|
+
* @internal
|
|
2157
|
+
*/
|
|
2158
|
+
capitalizeSegment(str) {
|
|
2159
|
+
if (str.includes("-") || str.includes("_") || str.includes(".")) {
|
|
2160
|
+
return str.split(/[-_.]/).map((part) => {
|
|
2161
|
+
if (!part) return "";
|
|
2162
|
+
return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
|
|
2163
|
+
}).join("");
|
|
2164
|
+
}
|
|
2165
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
2166
|
+
}
|
|
2056
2167
|
/**
|
|
2057
2168
|
* Check if a header should be ignored based on filter patterns
|
|
2058
2169
|
* @internal
|
|
@@ -2068,7 +2179,7 @@ ${propsCode}
|
|
|
2068
2179
|
const headerLower = headerName.toLowerCase();
|
|
2069
2180
|
return ignorePatterns.some((pattern) => {
|
|
2070
2181
|
const patternLower = pattern.toLowerCase();
|
|
2071
|
-
return
|
|
2182
|
+
return minimatch3(headerLower, patternLower);
|
|
2072
2183
|
});
|
|
2073
2184
|
}
|
|
2074
2185
|
/**
|
|
@@ -2089,7 +2200,7 @@ ${propsCode}
|
|
|
2089
2200
|
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
|
|
2090
2201
|
continue;
|
|
2091
2202
|
}
|
|
2092
|
-
if (!operation.
|
|
2203
|
+
if (!operation.parameters || !Array.isArray(operation.parameters)) {
|
|
2093
2204
|
continue;
|
|
2094
2205
|
}
|
|
2095
2206
|
const headerParams = operation.parameters.filter(
|
|
@@ -2098,7 +2209,13 @@ ${propsCode}
|
|
|
2098
2209
|
if (headerParams.length === 0) {
|
|
2099
2210
|
continue;
|
|
2100
2211
|
}
|
|
2101
|
-
|
|
2212
|
+
let pascalOperationId;
|
|
2213
|
+
if (operation.operationId) {
|
|
2214
|
+
pascalOperationId = operation.operationId.includes("-") ? toPascalCase(operation.operationId) : operation.operationId.charAt(0).toUpperCase() + operation.operationId.slice(1);
|
|
2215
|
+
} else {
|
|
2216
|
+
const strippedPath = stripPathPrefix(path, this.options.stripPathPrefix);
|
|
2217
|
+
pascalOperationId = this.generateMethodNameFromPath(method, strippedPath);
|
|
2218
|
+
}
|
|
2102
2219
|
const schemaName = `${pascalOperationId}HeaderParams`;
|
|
2103
2220
|
if (!this.schemaDependencies.has(schemaName)) {
|
|
2104
2221
|
this.schemaDependencies.set(schemaName, /* @__PURE__ */ new Set());
|
|
@@ -2135,8 +2252,9 @@ ${propsCode}
|
|
|
2135
2252
|
const prefixedName = this.options.prefix ? `${toPascalCase(this.options.prefix)}${operationName}` : operationName;
|
|
2136
2253
|
const suffixedName = this.options.suffix ? `${prefixedName}${toPascalCase(this.options.suffix)}` : prefixedName;
|
|
2137
2254
|
const camelCaseSchemaName = `${suffixedName.charAt(0).toLowerCase() + suffixedName.slice(1)}HeaderParamsSchema`;
|
|
2255
|
+
const jsdocOperationName = operation.operationId || `${method.toUpperCase()} ${path}`;
|
|
2138
2256
|
const jsdoc = `/**
|
|
2139
|
-
* Header parameters for ${
|
|
2257
|
+
* Header parameters for ${jsdocOperationName}
|
|
2140
2258
|
*/
|
|
2141
2259
|
`;
|
|
2142
2260
|
const fullSchemaCode = `${jsdoc}export const ${camelCaseSchemaName} = ${schemaCode};`;
|
|
@@ -2156,8 +2274,22 @@ ${propsCode}
|
|
|
2156
2274
|
return `${schemaName}Schema`;
|
|
2157
2275
|
}
|
|
2158
2276
|
if (schema.enum) {
|
|
2159
|
-
const
|
|
2160
|
-
|
|
2277
|
+
const allBooleans = schema.enum.every((v) => typeof v === "boolean");
|
|
2278
|
+
if (allBooleans) {
|
|
2279
|
+
return "z.boolean()";
|
|
2280
|
+
}
|
|
2281
|
+
const allStrings = schema.enum.every((v) => typeof v === "string");
|
|
2282
|
+
if (allStrings) {
|
|
2283
|
+
const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
|
|
2284
|
+
return `z.enum([${enumValues}])`;
|
|
2285
|
+
}
|
|
2286
|
+
const literalValues = schema.enum.map((v) => {
|
|
2287
|
+
if (typeof v === "string") {
|
|
2288
|
+
return `z.literal("${v}")`;
|
|
2289
|
+
}
|
|
2290
|
+
return `z.literal(${v})`;
|
|
2291
|
+
}).join(", ");
|
|
2292
|
+
return `z.union([${literalValues}])`;
|
|
2161
2293
|
}
|
|
2162
2294
|
const type = schema.type;
|
|
2163
2295
|
if (type === "string") {
|