@cerios/openapi-to-zod 1.0.0 → 1.1.1
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 +238 -4
- package/dist/cli.js +173 -35
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +180 -35
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +168 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +168 -26
- package/dist/index.mjs.map +1 -1
- package/dist/internal.d.mts +53 -2
- package/dist/internal.d.ts +53 -2
- package/dist/internal.js +117 -2
- package/dist/internal.js.map +1 -1
- package/dist/internal.mjs +114 -2
- package/dist/internal.mjs.map +1 -1
- package/dist/{types-BjoP91vk.d.mts → types-CI48CjiU.d.mts} +43 -1
- package/dist/{types-BjoP91vk.d.ts → types-CI48CjiU.d.ts} +43 -1
- package/package.json +6 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { O as OpenApiGeneratorOptions } from './types-
|
|
2
|
-
export { C as CommonSchemaOptions, a as ConfigFile, E as ExecutionMode, b as OpenAPISchema, c as OpenAPISpec, d as OperationFilters, R as RequestOptions, e as ResponseOptions, f as defineConfig } from './types-
|
|
1
|
+
import { O as OpenApiGeneratorOptions } from './types-CI48CjiU.mjs';
|
|
2
|
+
export { C as CommonSchemaOptions, a as ConfigFile, E as ExecutionMode, b as OpenAPISchema, c as OpenAPISpec, d as OperationFilters, R as RequestOptions, e as ResponseOptions, f as defineConfig } from './types-CI48CjiU.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Custom error classes for better error handling and debugging
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { O as OpenApiGeneratorOptions } from './types-
|
|
2
|
-
export { C as CommonSchemaOptions, a as ConfigFile, E as ExecutionMode, b as OpenAPISchema, c as OpenAPISpec, d as OperationFilters, R as RequestOptions, e as ResponseOptions, f as defineConfig } from './types-
|
|
1
|
+
import { O as OpenApiGeneratorOptions } from './types-CI48CjiU.js';
|
|
2
|
+
export { C as CommonSchemaOptions, a as ConfigFile, E as ExecutionMode, b as OpenAPISchema, c as OpenAPISpec, d as OperationFilters, R as RequestOptions, e as ResponseOptions, f as defineConfig } from './types-CI48CjiU.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Custom error classes for better error handling and debugging
|
package/dist/index.js
CHANGED
|
@@ -94,12 +94,24 @@ var ConfigurationError = class extends GeneratorError {
|
|
|
94
94
|
// src/openapi-generator.ts
|
|
95
95
|
var import_node_fs = require("fs");
|
|
96
96
|
var import_node_path = require("path");
|
|
97
|
-
var
|
|
97
|
+
var import_minimatch3 = require("minimatch");
|
|
98
98
|
var import_yaml = require("yaml");
|
|
99
99
|
|
|
100
100
|
// src/utils/name-utils.ts
|
|
101
|
+
function sanitizeIdentifier(str) {
|
|
102
|
+
return str.replace(/[^a-zA-Z0-9._\-\s]+/g, "_");
|
|
103
|
+
}
|
|
101
104
|
function toCamelCase(str, options) {
|
|
102
|
-
|
|
105
|
+
const sanitized = sanitizeIdentifier(str);
|
|
106
|
+
const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
|
|
107
|
+
let name;
|
|
108
|
+
if (words.length === 0) {
|
|
109
|
+
name = str.charAt(0).toLowerCase() + str.slice(1);
|
|
110
|
+
} else if (words.length === 1) {
|
|
111
|
+
name = words[0].charAt(0).toLowerCase() + words[0].slice(1);
|
|
112
|
+
} else {
|
|
113
|
+
name = words[0].charAt(0).toLowerCase() + words[0].slice(1) + words.slice(1).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
114
|
+
}
|
|
103
115
|
if (options == null ? void 0 : options.prefix) {
|
|
104
116
|
const prefix = options.prefix.toLowerCase();
|
|
105
117
|
name = prefix + name.charAt(0).toUpperCase() + name.slice(1);
|
|
@@ -112,12 +124,23 @@ function toCamelCase(str, options) {
|
|
|
112
124
|
}
|
|
113
125
|
function toPascalCase(str) {
|
|
114
126
|
const stringValue = String(str);
|
|
115
|
-
|
|
127
|
+
const isAlreadyValidCase = /^[a-zA-Z][a-zA-Z0-9]*$/.test(stringValue);
|
|
128
|
+
if (isAlreadyValidCase) {
|
|
129
|
+
return stringValue.charAt(0).toUpperCase() + stringValue.slice(1);
|
|
130
|
+
}
|
|
131
|
+
const sanitized = sanitizeIdentifier(stringValue);
|
|
132
|
+
const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
|
|
133
|
+
let result;
|
|
134
|
+
if (words.length === 0) {
|
|
135
|
+
result = "Value";
|
|
136
|
+
} else {
|
|
137
|
+
result = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
138
|
+
}
|
|
116
139
|
if (/^\d/.test(result)) {
|
|
117
140
|
result = `N${result}`;
|
|
118
141
|
}
|
|
119
142
|
if (!result || /^_+$/.test(result)) {
|
|
120
|
-
|
|
143
|
+
return "Value";
|
|
121
144
|
}
|
|
122
145
|
return result;
|
|
123
146
|
}
|
|
@@ -129,9 +152,28 @@ function resolveRef(ref) {
|
|
|
129
152
|
// src/generators/enum-generator.ts
|
|
130
153
|
function generateEnum(name, values, options) {
|
|
131
154
|
const schemaName = `${toCamelCase(name, options)}Schema`;
|
|
132
|
-
const
|
|
133
|
-
const
|
|
134
|
-
|
|
155
|
+
const typeName = toPascalCase(name);
|
|
156
|
+
const allBooleans = values.every((v) => typeof v === "boolean");
|
|
157
|
+
if (allBooleans) {
|
|
158
|
+
const schemaCode2 = `export const ${schemaName} = z.boolean();`;
|
|
159
|
+
const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
|
|
160
|
+
return { schemaCode: schemaCode2, typeCode: typeCode2 };
|
|
161
|
+
}
|
|
162
|
+
const allStrings = values.every((v) => typeof v === "string");
|
|
163
|
+
if (allStrings) {
|
|
164
|
+
const enumValues = values.map((v) => `"${v}"`).join(", ");
|
|
165
|
+
const schemaCode2 = `export const ${schemaName} = z.enum([${enumValues}]);`;
|
|
166
|
+
const typeCode2 = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
|
|
167
|
+
return { schemaCode: schemaCode2, typeCode: typeCode2 };
|
|
168
|
+
}
|
|
169
|
+
const literalValues = values.map((v) => {
|
|
170
|
+
if (typeof v === "string") {
|
|
171
|
+
return `z.literal("${v}")`;
|
|
172
|
+
}
|
|
173
|
+
return `z.literal(${v})`;
|
|
174
|
+
}).join(", ");
|
|
175
|
+
const schemaCode = `export const ${schemaName} = z.union([${literalValues}]);`;
|
|
176
|
+
const typeCode = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
|
|
135
177
|
return { schemaCode, typeCode };
|
|
136
178
|
}
|
|
137
179
|
|
|
@@ -140,7 +182,7 @@ function escapeDescription(str) {
|
|
|
140
182
|
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
|
|
141
183
|
}
|
|
142
184
|
function escapePattern(str) {
|
|
143
|
-
return str.replace(
|
|
185
|
+
return str.replace(/\//g, "\\/");
|
|
144
186
|
}
|
|
145
187
|
function escapeJSDoc(str) {
|
|
146
188
|
return str.replace(/\*\//g, "*\\/");
|
|
@@ -264,6 +306,64 @@ var LRUCache = class {
|
|
|
264
306
|
}
|
|
265
307
|
};
|
|
266
308
|
|
|
309
|
+
// src/utils/pattern-utils.ts
|
|
310
|
+
var import_minimatch = require("minimatch");
|
|
311
|
+
function isValidGlobPattern(pattern) {
|
|
312
|
+
try {
|
|
313
|
+
new import_minimatch.minimatch.Minimatch(pattern);
|
|
314
|
+
return true;
|
|
315
|
+
} catch {
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function isGlobPattern(pattern) {
|
|
320
|
+
return /[*?[\]{}!]/.test(pattern);
|
|
321
|
+
}
|
|
322
|
+
function stripPrefix(input, pattern, ensureLeadingChar) {
|
|
323
|
+
if (!pattern) {
|
|
324
|
+
return input;
|
|
325
|
+
}
|
|
326
|
+
if (isGlobPattern(pattern) && !isValidGlobPattern(pattern)) {
|
|
327
|
+
console.warn(`\u26A0\uFE0F Invalid glob pattern "${pattern}": Pattern is malformed`);
|
|
328
|
+
return input;
|
|
329
|
+
}
|
|
330
|
+
if (isGlobPattern(pattern)) {
|
|
331
|
+
let longestMatch = -1;
|
|
332
|
+
for (let i = 1; i <= input.length; i++) {
|
|
333
|
+
const testPrefix = input.substring(0, i);
|
|
334
|
+
if ((0, import_minimatch.minimatch)(testPrefix, pattern)) {
|
|
335
|
+
longestMatch = i;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if (longestMatch > 0) {
|
|
339
|
+
const stripped = input.substring(longestMatch);
|
|
340
|
+
if (ensureLeadingChar) {
|
|
341
|
+
if (stripped === "") {
|
|
342
|
+
return ensureLeadingChar;
|
|
343
|
+
}
|
|
344
|
+
if (!stripped.startsWith(ensureLeadingChar)) {
|
|
345
|
+
return `${ensureLeadingChar}${stripped}`;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return stripped === "" && !ensureLeadingChar ? input : stripped;
|
|
349
|
+
}
|
|
350
|
+
return input;
|
|
351
|
+
}
|
|
352
|
+
if (input.startsWith(pattern)) {
|
|
353
|
+
const stripped = input.substring(pattern.length);
|
|
354
|
+
if (ensureLeadingChar) {
|
|
355
|
+
if (stripped === "") {
|
|
356
|
+
return ensureLeadingChar;
|
|
357
|
+
}
|
|
358
|
+
if (!stripped.startsWith(ensureLeadingChar)) {
|
|
359
|
+
return `${ensureLeadingChar}${stripped}`;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return stripped;
|
|
363
|
+
}
|
|
364
|
+
return input;
|
|
365
|
+
}
|
|
366
|
+
|
|
267
367
|
// src/validators/array-validator.ts
|
|
268
368
|
function generateArrayValidation(schema, context) {
|
|
269
369
|
var _a;
|
|
@@ -1120,8 +1220,9 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1120
1220
|
}
|
|
1121
1221
|
(_a = this.context.schemaDependencies.get(currentSchema)) == null ? void 0 : _a.add(refName);
|
|
1122
1222
|
}
|
|
1123
|
-
const
|
|
1124
|
-
|
|
1223
|
+
const strippedRefName = stripPrefix(resolvedRefName, this.context.stripSchemaPrefix);
|
|
1224
|
+
const schemaName = `${toCamelCase(strippedRefName, this.context.namingOptions)}Schema`;
|
|
1225
|
+
if (currentSchema && (refName === currentSchema || this.isCircularThroughAlias(currentSchema, refName))) {
|
|
1125
1226
|
const lazySchema = `z.lazy((): z.ZodTypeAny => ${schemaName})`;
|
|
1126
1227
|
return wrapNullable(lazySchema, nullable);
|
|
1127
1228
|
}
|
|
@@ -1133,9 +1234,25 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1133
1234
|
return wrapNullable(zodLiteral, nullable);
|
|
1134
1235
|
}
|
|
1135
1236
|
if (schema.enum) {
|
|
1136
|
-
const
|
|
1137
|
-
|
|
1138
|
-
|
|
1237
|
+
const allBooleans = schema.enum.every((v) => typeof v === "boolean");
|
|
1238
|
+
if (allBooleans) {
|
|
1239
|
+
const zodBoolean = "z.boolean()";
|
|
1240
|
+
return wrapNullable(zodBoolean, nullable);
|
|
1241
|
+
}
|
|
1242
|
+
const allStrings = schema.enum.every((v) => typeof v === "string");
|
|
1243
|
+
if (allStrings) {
|
|
1244
|
+
const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
|
|
1245
|
+
const zodEnum = `z.enum([${enumValues}])`;
|
|
1246
|
+
return wrapNullable(zodEnum, nullable);
|
|
1247
|
+
}
|
|
1248
|
+
const literalValues = schema.enum.map((v) => {
|
|
1249
|
+
if (typeof v === "string") {
|
|
1250
|
+
return `z.literal("${v}")`;
|
|
1251
|
+
}
|
|
1252
|
+
return `z.literal(${v})`;
|
|
1253
|
+
}).join(", ");
|
|
1254
|
+
const zodUnion = `z.union([${literalValues}])`;
|
|
1255
|
+
return wrapNullable(zodUnion, nullable);
|
|
1139
1256
|
}
|
|
1140
1257
|
if (schema.allOf) {
|
|
1141
1258
|
let composition = generateAllOf(
|
|
@@ -1266,7 +1383,7 @@ _PropertyGenerator.INCLUSION_RULES = {
|
|
|
1266
1383
|
var PropertyGenerator = _PropertyGenerator;
|
|
1267
1384
|
|
|
1268
1385
|
// src/utils/operation-filters.ts
|
|
1269
|
-
var
|
|
1386
|
+
var import_minimatch2 = require("minimatch");
|
|
1270
1387
|
function createFilterStatistics() {
|
|
1271
1388
|
return {
|
|
1272
1389
|
totalOperations: 0,
|
|
@@ -1285,7 +1402,7 @@ function matchesAnyPattern(value, patterns) {
|
|
|
1285
1402
|
if (!value) {
|
|
1286
1403
|
return false;
|
|
1287
1404
|
}
|
|
1288
|
-
return patterns.some((pattern) => (0,
|
|
1405
|
+
return patterns.some((pattern) => (0, import_minimatch2.minimatch)(value, pattern));
|
|
1289
1406
|
}
|
|
1290
1407
|
function containsAny(arr, values) {
|
|
1291
1408
|
if (!values || values.length === 0) {
|
|
@@ -1421,6 +1538,7 @@ var OpenApiGenerator = class {
|
|
|
1421
1538
|
schemaType: options.schemaType || "all",
|
|
1422
1539
|
prefix: options.prefix,
|
|
1423
1540
|
suffix: options.suffix,
|
|
1541
|
+
stripSchemaPrefix: options.stripSchemaPrefix,
|
|
1424
1542
|
showStats: (_c = options.showStats) != null ? _c : true,
|
|
1425
1543
|
request: options.request,
|
|
1426
1544
|
response: options.response,
|
|
@@ -1497,7 +1615,8 @@ var OpenApiGenerator = class {
|
|
|
1497
1615
|
namingOptions: {
|
|
1498
1616
|
prefix: this.options.prefix,
|
|
1499
1617
|
suffix: this.options.suffix
|
|
1500
|
-
}
|
|
1618
|
+
},
|
|
1619
|
+
stripSchemaPrefix: this.options.stripSchemaPrefix
|
|
1501
1620
|
});
|
|
1502
1621
|
}
|
|
1503
1622
|
/**
|
|
@@ -1510,6 +1629,9 @@ var OpenApiGenerator = class {
|
|
|
1510
1629
|
throw new SpecValidationError("No schemas found in OpenAPI spec", { filePath: this.options.input });
|
|
1511
1630
|
}
|
|
1512
1631
|
for (const [name, schema] of Object.entries(this.spec.components.schemas)) {
|
|
1632
|
+
if (this.options.operationFilters && this.schemaUsageMap.size > 0 && !this.schemaUsageMap.has(name)) {
|
|
1633
|
+
continue;
|
|
1634
|
+
}
|
|
1513
1635
|
this.generateComponentSchema(name, schema);
|
|
1514
1636
|
}
|
|
1515
1637
|
this.generateQueryParameterSchemas();
|
|
@@ -1531,9 +1653,11 @@ var OpenApiGenerator = class {
|
|
|
1531
1653
|
const typeCode = this.types.get(name);
|
|
1532
1654
|
if (schemaCode) {
|
|
1533
1655
|
output.push(schemaCode);
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1656
|
+
const strippedName = stripPrefix(name, this.options.stripSchemaPrefix);
|
|
1657
|
+
const typeName = toPascalCase(strippedName);
|
|
1658
|
+
if (!schemaCode.includes(`export type ${typeName}`)) {
|
|
1659
|
+
const schemaName = `${toCamelCase(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
|
|
1660
|
+
output.push(`export type ${typeName} = z.infer<typeof ${schemaName}>;`);
|
|
1537
1661
|
}
|
|
1538
1662
|
output.push("");
|
|
1539
1663
|
} else if (typeCode) {
|
|
@@ -1849,7 +1973,8 @@ var OpenApiGenerator = class {
|
|
|
1849
1973
|
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
1850
1974
|
if (schema.enum) {
|
|
1851
1975
|
const jsdoc2 = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
1852
|
-
const
|
|
1976
|
+
const strippedName2 = stripPrefix(name, this.options.stripSchemaPrefix);
|
|
1977
|
+
const { schemaCode, typeCode } = generateEnum(strippedName2, schema.enum, {
|
|
1853
1978
|
prefix: this.options.prefix,
|
|
1854
1979
|
suffix: this.options.suffix
|
|
1855
1980
|
});
|
|
@@ -1858,7 +1983,8 @@ ${typeCode}`;
|
|
|
1858
1983
|
this.schemas.set(name, enumSchemaCode);
|
|
1859
1984
|
return;
|
|
1860
1985
|
}
|
|
1861
|
-
const
|
|
1986
|
+
const strippedName = stripPrefix(name, this.options.stripSchemaPrefix);
|
|
1987
|
+
const schemaName = `${toCamelCase(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
|
|
1862
1988
|
const jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
1863
1989
|
if (schema.allOf && schema.allOf.length === 1 && schema.allOf[0].$ref) {
|
|
1864
1990
|
const refName = resolveRef(schema.allOf[0].$ref);
|
|
@@ -1874,7 +2000,8 @@ ${typeCode}`;
|
|
|
1874
2000
|
namingOptions: {
|
|
1875
2001
|
prefix: this.options.prefix,
|
|
1876
2002
|
suffix: this.options.suffix
|
|
1877
|
-
}
|
|
2003
|
+
},
|
|
2004
|
+
stripSchemaPrefix: this.options.stripSchemaPrefix
|
|
1878
2005
|
});
|
|
1879
2006
|
const isAlias = !!(schema.$ref && !schema.properties && !schema.allOf && !schema.oneOf && !schema.anyOf);
|
|
1880
2007
|
const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, isAlias);
|
|
@@ -1993,7 +2120,7 @@ ${propsCode}
|
|
|
1993
2120
|
const headerLower = headerName.toLowerCase();
|
|
1994
2121
|
return ignorePatterns.some((pattern) => {
|
|
1995
2122
|
const patternLower = pattern.toLowerCase();
|
|
1996
|
-
return (0,
|
|
2123
|
+
return (0, import_minimatch3.minimatch)(headerLower, patternLower);
|
|
1997
2124
|
});
|
|
1998
2125
|
}
|
|
1999
2126
|
/**
|
|
@@ -2076,12 +2203,27 @@ ${propsCode}
|
|
|
2076
2203
|
generateQueryParamType(schema, param) {
|
|
2077
2204
|
if (schema.$ref) {
|
|
2078
2205
|
const refName = resolveRef(schema.$ref);
|
|
2079
|
-
const
|
|
2206
|
+
const strippedRefName = stripPrefix(refName, this.options.stripSchemaPrefix);
|
|
2207
|
+
const schemaName = toCamelCase(strippedRefName, { prefix: this.options.prefix, suffix: this.options.suffix });
|
|
2080
2208
|
return `${schemaName}Schema`;
|
|
2081
2209
|
}
|
|
2082
2210
|
if (schema.enum) {
|
|
2083
|
-
const
|
|
2084
|
-
|
|
2211
|
+
const allBooleans = schema.enum.every((v) => typeof v === "boolean");
|
|
2212
|
+
if (allBooleans) {
|
|
2213
|
+
return "z.boolean()";
|
|
2214
|
+
}
|
|
2215
|
+
const allStrings = schema.enum.every((v) => typeof v === "string");
|
|
2216
|
+
if (allStrings) {
|
|
2217
|
+
const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
|
|
2218
|
+
return `z.enum([${enumValues}])`;
|
|
2219
|
+
}
|
|
2220
|
+
const literalValues = schema.enum.map((v) => {
|
|
2221
|
+
if (typeof v === "string") {
|
|
2222
|
+
return `z.literal("${v}")`;
|
|
2223
|
+
}
|
|
2224
|
+
return `z.literal(${v})`;
|
|
2225
|
+
}).join(", ");
|
|
2226
|
+
return `z.union([${literalValues}])`;
|
|
2085
2227
|
}
|
|
2086
2228
|
const type = schema.type;
|
|
2087
2229
|
if (type === "string") {
|