@cerios/openapi-to-zod 1.2.0 → 1.3.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 +87 -30
- package/dist/cli.js +283 -37
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +289 -37
- 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 +282 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +282 -37
- package/dist/index.mjs.map +1 -1
- package/dist/internal.d.mts +51 -2
- package/dist/internal.d.ts +51 -2
- package/dist/internal.js +69 -0
- package/dist/internal.js.map +1 -1
- package/dist/internal.mjs +64 -0
- package/dist/internal.mjs.map +1 -1
- package/dist/{types--r0d47sd.d.mts → types-B3GgqGzM.d.mts} +72 -1
- package/dist/{types--r0d47sd.d.ts → types-B3GgqGzM.d.ts} +72 -1
- package/package.json +1 -1
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
|
|
1
|
+
import { O as OpenApiGeneratorOptions } from './types-B3GgqGzM.mjs';
|
|
2
|
+
export { C as CommonSchemaOptions, a as ConfigFile, E as ExecutionMode, b as OpenAPIParameter, c as OpenAPIRequestBody, d as OpenAPIResponse, e as OpenAPISchema, f as OpenAPISpec, g as OperationFilters, R as RequestOptions, h as ResponseOptions, i as defineConfig } from './types-B3GgqGzM.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
|
|
1
|
+
import { O as OpenApiGeneratorOptions } from './types-B3GgqGzM.js';
|
|
2
|
+
export { C as CommonSchemaOptions, a as ConfigFile, E as ExecutionMode, b as OpenAPIParameter, c as OpenAPIRequestBody, d as OpenAPIResponse, e as OpenAPISchema, f as OpenAPISpec, g as OperationFilters, R as RequestOptions, h as ResponseOptions, i as defineConfig } from './types-B3GgqGzM.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Custom error classes for better error handling and debugging
|
package/dist/index.js
CHANGED
|
@@ -430,12 +430,56 @@ function generateArrayValidation(schema, context) {
|
|
|
430
430
|
}
|
|
431
431
|
|
|
432
432
|
// src/validators/composition-validator.ts
|
|
433
|
+
function isDiscriminatorRequired(schemas, discriminator, context) {
|
|
434
|
+
const invalidSchemas = [];
|
|
435
|
+
for (const schema of schemas) {
|
|
436
|
+
const resolved = resolveSchema(schema, context);
|
|
437
|
+
const required = resolved.required || [];
|
|
438
|
+
if (!required.includes(discriminator)) {
|
|
439
|
+
const schemaName = schema.$ref ? schema.$ref.split("/").pop() || "inline" : "inline";
|
|
440
|
+
invalidSchemas.push(schemaName);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return {
|
|
444
|
+
valid: invalidSchemas.length === 0,
|
|
445
|
+
invalidSchemas
|
|
446
|
+
};
|
|
447
|
+
}
|
|
433
448
|
function generateUnion(schemas, discriminator, isNullable2, context, options, currentSchema) {
|
|
449
|
+
if (schemas.length === 0) {
|
|
450
|
+
console.warn(
|
|
451
|
+
"[openapi-to-zod] Warning: Empty oneOf/anyOf array encountered. This is likely a malformed OpenAPI spec. Generating z.never() as fallback."
|
|
452
|
+
);
|
|
453
|
+
return wrapNullable(
|
|
454
|
+
'z.never().describe("Empty oneOf/anyOf in OpenAPI spec - no valid schema defined")',
|
|
455
|
+
isNullable2
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
if (schemas.length === 1) {
|
|
459
|
+
let singleSchema = context.generatePropertySchema(schemas[0], currentSchema);
|
|
460
|
+
if ((options == null ? void 0 : options.passthrough) && !singleSchema.includes(".catchall(")) {
|
|
461
|
+
singleSchema = `${singleSchema}.catchall(z.unknown())`;
|
|
462
|
+
}
|
|
463
|
+
return wrapNullable(singleSchema, isNullable2);
|
|
464
|
+
}
|
|
434
465
|
if (discriminator) {
|
|
435
466
|
let resolvedSchemas = schemas;
|
|
436
467
|
if ((options == null ? void 0 : options.discriminatorMapping) && context.resolveDiscriminatorMapping) {
|
|
437
468
|
resolvedSchemas = context.resolveDiscriminatorMapping(options.discriminatorMapping, schemas);
|
|
438
469
|
}
|
|
470
|
+
const discriminatorCheck = isDiscriminatorRequired(resolvedSchemas, discriminator, context);
|
|
471
|
+
if (!discriminatorCheck.valid) {
|
|
472
|
+
console.warn(
|
|
473
|
+
`[openapi-to-zod] Warning: Discriminator "${discriminator}" is not required in schemas: ${discriminatorCheck.invalidSchemas.join(", ")}. Falling back to z.union() instead of z.discriminatedUnion().`
|
|
474
|
+
);
|
|
475
|
+
let schemaStrings3 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema));
|
|
476
|
+
if (options == null ? void 0 : options.passthrough) {
|
|
477
|
+
schemaStrings3 = schemaStrings3.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
|
|
478
|
+
}
|
|
479
|
+
const fallbackDescription = `Discriminator "${discriminator}" is optional in some schemas (${discriminatorCheck.invalidSchemas.join(", ")}), using z.union() instead of z.discriminatedUnion()`;
|
|
480
|
+
const union3 = `z.union([${schemaStrings3.join(", ")}]).describe("${fallbackDescription}")`;
|
|
481
|
+
return wrapNullable(union3, isNullable2);
|
|
482
|
+
}
|
|
439
483
|
let schemaStrings2 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema));
|
|
440
484
|
if (options == null ? void 0 : options.passthrough) {
|
|
441
485
|
schemaStrings2 = schemaStrings2.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
|
|
@@ -450,25 +494,102 @@ function generateUnion(schemas, discriminator, isNullable2, context, options, cu
|
|
|
450
494
|
const union = `z.union([${schemaStrings.join(", ")}])`;
|
|
451
495
|
return wrapNullable(union, isNullable2);
|
|
452
496
|
}
|
|
497
|
+
function resolveSchema(schema, context) {
|
|
498
|
+
if (schema.$ref && context.resolveSchemaRef) {
|
|
499
|
+
const resolved = context.resolveSchemaRef(schema.$ref);
|
|
500
|
+
if (resolved) {
|
|
501
|
+
return resolved;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
return schema;
|
|
505
|
+
}
|
|
506
|
+
function collectProperties(schema, context) {
|
|
507
|
+
const resolved = resolveSchema(schema, context);
|
|
508
|
+
const props = /* @__PURE__ */ new Map();
|
|
509
|
+
const sourceName = schema.$ref ? schema.$ref.split("/").pop() || "unknown" : "inline";
|
|
510
|
+
if (resolved.properties) {
|
|
511
|
+
for (const [key, value] of Object.entries(resolved.properties)) {
|
|
512
|
+
props.set(key, { schema: value, source: sourceName });
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (resolved.allOf) {
|
|
516
|
+
for (const subSchema of resolved.allOf) {
|
|
517
|
+
const subProps = collectProperties(subSchema, context);
|
|
518
|
+
for (const [key, value] of subProps) {
|
|
519
|
+
if (!props.has(key)) {
|
|
520
|
+
props.set(key, value);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
return props;
|
|
526
|
+
}
|
|
527
|
+
function schemasMatch(a, b) {
|
|
528
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
529
|
+
}
|
|
530
|
+
function detectConflictingProperties(schemas, context) {
|
|
531
|
+
const conflicts = [];
|
|
532
|
+
const propertyMap = /* @__PURE__ */ new Map();
|
|
533
|
+
for (const schema of schemas) {
|
|
534
|
+
const schemaProps = collectProperties(schema, context);
|
|
535
|
+
for (const [propName, propInfo] of schemaProps) {
|
|
536
|
+
const existing = propertyMap.get(propName);
|
|
537
|
+
if (existing) {
|
|
538
|
+
if (!schemasMatch(existing.schema, propInfo.schema)) {
|
|
539
|
+
conflicts.push(
|
|
540
|
+
`Property "${propName}" has conflicting definitions in ${existing.source} and ${propInfo.source}`
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
} else {
|
|
544
|
+
propertyMap.set(propName, propInfo);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
return conflicts;
|
|
549
|
+
}
|
|
453
550
|
function generateAllOf(schemas, isNullable2, context, currentSchema) {
|
|
454
551
|
if (schemas.length === 1) {
|
|
455
552
|
const singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false);
|
|
456
553
|
return wrapNullable(singleSchema, isNullable2);
|
|
457
554
|
}
|
|
555
|
+
const conflicts = detectConflictingProperties(schemas, context);
|
|
556
|
+
let conflictDescription = "";
|
|
557
|
+
if (conflicts.length > 0) {
|
|
558
|
+
for (const conflict of conflicts) {
|
|
559
|
+
console.warn(`[openapi-to-zod] Warning: allOf composition conflict - ${conflict}`);
|
|
560
|
+
}
|
|
561
|
+
conflictDescription = `allOf property conflicts detected: ${conflicts.join("; ")}`;
|
|
562
|
+
}
|
|
458
563
|
const allObjects = schemas.every((s) => s.type === "object" || s.properties || s.$ref || s.allOf);
|
|
459
|
-
|
|
564
|
+
let result;
|
|
460
565
|
if (allObjects) {
|
|
461
|
-
let
|
|
566
|
+
let merged = context.generatePropertySchema(schemas[0], currentSchema, false);
|
|
567
|
+
for (let i = 1; i < schemas.length; i++) {
|
|
568
|
+
const schema = schemas[i];
|
|
569
|
+
if (schema.$ref) {
|
|
570
|
+
const refSchema = context.generatePropertySchema(schema, currentSchema, false);
|
|
571
|
+
merged = `${merged}.extend(${refSchema}.shape)`;
|
|
572
|
+
} else if (context.generateInlineObjectShape && (schema.properties || schema.type === "object")) {
|
|
573
|
+
const inlineShape = context.generateInlineObjectShape(schema, currentSchema);
|
|
574
|
+
merged = `${merged}.extend(${inlineShape})`;
|
|
575
|
+
} else {
|
|
576
|
+
const schemaString = context.generatePropertySchema(schema, currentSchema, false);
|
|
577
|
+
merged = `${merged}.extend(${schemaString}.shape)`;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
result = merged;
|
|
581
|
+
} else {
|
|
582
|
+
const schemaStrings = schemas.map((s) => context.generatePropertySchema(s, currentSchema, false));
|
|
583
|
+
let merged = schemaStrings[0];
|
|
462
584
|
for (let i = 1; i < schemaStrings.length; i++) {
|
|
463
|
-
|
|
585
|
+
merged = `${merged}.and(${schemaStrings[i]})`;
|
|
464
586
|
}
|
|
465
|
-
|
|
587
|
+
result = merged;
|
|
466
588
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
merged = `${merged}.and(${schemaStrings[i]})`;
|
|
589
|
+
if (conflictDescription) {
|
|
590
|
+
result = `${result}.describe("${conflictDescription}")`;
|
|
470
591
|
}
|
|
471
|
-
return wrapNullable(
|
|
592
|
+
return wrapNullable(result, isNullable2);
|
|
472
593
|
}
|
|
473
594
|
|
|
474
595
|
// src/validators/number-validator.ts
|
|
@@ -1144,6 +1265,15 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1144
1265
|
}
|
|
1145
1266
|
return mappedSchemas;
|
|
1146
1267
|
}
|
|
1268
|
+
/**
|
|
1269
|
+
* Resolve a $ref string to the actual schema
|
|
1270
|
+
*/
|
|
1271
|
+
resolveSchemaRef(ref) {
|
|
1272
|
+
var _a, _b;
|
|
1273
|
+
const schemaName = ref.split("/").pop();
|
|
1274
|
+
if (!schemaName) return void 0;
|
|
1275
|
+
return (_b = (_a = this.context.spec.components) == null ? void 0 : _a.schemas) == null ? void 0 : _b[schemaName];
|
|
1276
|
+
}
|
|
1147
1277
|
/**
|
|
1148
1278
|
* Resolve a schema name through any aliases to get the actual schema name
|
|
1149
1279
|
* If the schema is an alias (allOf with single $ref), return the target name
|
|
@@ -1221,7 +1351,7 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1221
1351
|
let schemaWithCatchall = baseSchema;
|
|
1222
1352
|
if (baseSchema.includes(".union([") || baseSchema.includes(".discriminatedUnion(")) {
|
|
1223
1353
|
schemaWithCatchall = baseSchema;
|
|
1224
|
-
} else if (baseSchema.includes(".
|
|
1354
|
+
} else if (baseSchema.includes(".extend(")) {
|
|
1225
1355
|
schemaWithCatchall = `${baseSchema}.catchall(z.unknown())`;
|
|
1226
1356
|
}
|
|
1227
1357
|
if (schema.unevaluatedProperties === false) {
|
|
@@ -1248,7 +1378,11 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1248
1378
|
if ((this.context.schemaType === "request" || this.context.schemaType === "response") && schema.properties) {
|
|
1249
1379
|
schema = this.filterNestedProperties(schema);
|
|
1250
1380
|
}
|
|
1251
|
-
const
|
|
1381
|
+
const isSchemaRef = !!schema.$ref;
|
|
1382
|
+
const isEnum = !!schema.enum;
|
|
1383
|
+
const isConst = schema.const !== void 0;
|
|
1384
|
+
const shouldApplyDefaultNullable = !isTopLevel && !isSchemaRef && !isEnum && !isConst;
|
|
1385
|
+
const effectiveDefaultNullable = shouldApplyDefaultNullable ? this.context.defaultNullable : false;
|
|
1252
1386
|
const nullable = isNullable(schema, effectiveDefaultNullable);
|
|
1253
1387
|
if (hasMultipleTypes(schema)) {
|
|
1254
1388
|
const union = this.generateMultiTypeUnion(schema, currentSchema);
|
|
@@ -1301,7 +1435,11 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1301
1435
|
let composition = generateAllOf(
|
|
1302
1436
|
schema.allOf,
|
|
1303
1437
|
nullable,
|
|
1304
|
-
{
|
|
1438
|
+
{
|
|
1439
|
+
generatePropertySchema: this.generatePropertySchema.bind(this),
|
|
1440
|
+
generateInlineObjectShape: this.generateInlineObjectShape.bind(this),
|
|
1441
|
+
resolveSchemaRef: this.resolveSchemaRef.bind(this)
|
|
1442
|
+
},
|
|
1305
1443
|
currentSchema
|
|
1306
1444
|
);
|
|
1307
1445
|
if (schema.unevaluatedProperties !== void 0) {
|
|
@@ -1317,7 +1455,8 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1317
1455
|
nullable,
|
|
1318
1456
|
{
|
|
1319
1457
|
generatePropertySchema: this.generatePropertySchema.bind(this),
|
|
1320
|
-
resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this)
|
|
1458
|
+
resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
|
|
1459
|
+
resolveSchemaRef: this.resolveSchemaRef.bind(this)
|
|
1321
1460
|
},
|
|
1322
1461
|
{
|
|
1323
1462
|
passthrough: needsPassthrough,
|
|
@@ -1338,7 +1477,8 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1338
1477
|
nullable,
|
|
1339
1478
|
{
|
|
1340
1479
|
generatePropertySchema: this.generatePropertySchema.bind(this),
|
|
1341
|
-
resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this)
|
|
1480
|
+
resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
|
|
1481
|
+
resolveSchemaRef: this.resolveSchemaRef.bind(this)
|
|
1342
1482
|
},
|
|
1343
1483
|
{
|
|
1344
1484
|
passthrough: needsPassthrough,
|
|
@@ -1401,7 +1541,17 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1401
1541
|
);
|
|
1402
1542
|
validation = addDescription(validation, schema.description, this.context.useDescribe);
|
|
1403
1543
|
} else {
|
|
1404
|
-
|
|
1544
|
+
switch (this.context.emptyObjectBehavior) {
|
|
1545
|
+
case "strict":
|
|
1546
|
+
validation = "z.strictObject({})";
|
|
1547
|
+
break;
|
|
1548
|
+
case "loose":
|
|
1549
|
+
validation = "z.looseObject({})";
|
|
1550
|
+
break;
|
|
1551
|
+
default:
|
|
1552
|
+
validation = "z.record(z.string(), z.unknown())";
|
|
1553
|
+
break;
|
|
1554
|
+
}
|
|
1405
1555
|
validation = addDescription(validation, schema.description, this.context.useDescribe);
|
|
1406
1556
|
}
|
|
1407
1557
|
break;
|
|
@@ -1416,6 +1566,44 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1416
1566
|
}
|
|
1417
1567
|
return result;
|
|
1418
1568
|
}
|
|
1569
|
+
/**
|
|
1570
|
+
* Generate inline object shape for use with .extend()
|
|
1571
|
+
* Returns just the shape object literal: { prop1: z.string(), prop2: z.number() }
|
|
1572
|
+
*
|
|
1573
|
+
* This method is specifically for allOf compositions where we need to pass
|
|
1574
|
+
* the shape directly to .extend() instead of using z.object({...}).shape.
|
|
1575
|
+
* This avoids the .nullable().shape bug when inline objects have nullable: true.
|
|
1576
|
+
*
|
|
1577
|
+
* According to Zod docs (https://zod.dev/api?id=extend):
|
|
1578
|
+
* - .extend() accepts an object of shape definitions
|
|
1579
|
+
* - e.g., baseSchema.extend({ prop: z.string() })
|
|
1580
|
+
*/
|
|
1581
|
+
generateInlineObjectShape(schema, currentSchema) {
|
|
1582
|
+
const required = new Set(schema.required || []);
|
|
1583
|
+
const properties = [];
|
|
1584
|
+
if (schema.properties) {
|
|
1585
|
+
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
1586
|
+
if (!this.shouldIncludeProperty(propSchema)) {
|
|
1587
|
+
continue;
|
|
1588
|
+
}
|
|
1589
|
+
const isRequired = required.has(propName);
|
|
1590
|
+
const zodSchema = this.generatePropertySchema(propSchema, currentSchema);
|
|
1591
|
+
const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
1592
|
+
const quotedPropName = validIdentifier.test(propName) ? propName : `"${propName}"`;
|
|
1593
|
+
let propertyDef = `${quotedPropName}: ${zodSchema}`;
|
|
1594
|
+
if (!isRequired) {
|
|
1595
|
+
propertyDef += ".optional()";
|
|
1596
|
+
}
|
|
1597
|
+
properties.push(propertyDef);
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
if (properties.length === 0) {
|
|
1601
|
+
return "{}";
|
|
1602
|
+
}
|
|
1603
|
+
return `{
|
|
1604
|
+
${properties.map((p) => ` ${p}`).join(",\n")}
|
|
1605
|
+
}`;
|
|
1606
|
+
}
|
|
1419
1607
|
};
|
|
1420
1608
|
// Performance optimization: Lookup table for faster inclusion checks
|
|
1421
1609
|
_PropertyGenerator.INCLUSION_RULES = {
|
|
@@ -1559,6 +1747,59 @@ function formatFilterStatistics(stats) {
|
|
|
1559
1747
|
return lines.join("\n");
|
|
1560
1748
|
}
|
|
1561
1749
|
|
|
1750
|
+
// src/utils/ref-resolver.ts
|
|
1751
|
+
function resolveRef2(obj, spec, maxDepth = 10) {
|
|
1752
|
+
var _a, _b, _c, _d;
|
|
1753
|
+
if (!obj || typeof obj !== "object" || maxDepth <= 0) return obj;
|
|
1754
|
+
if (!obj.$ref) return obj;
|
|
1755
|
+
const ref = obj.$ref;
|
|
1756
|
+
let resolved = null;
|
|
1757
|
+
const paramMatch = ref.match(/^#\/components\/parameters\/(.+)$/);
|
|
1758
|
+
const requestBodyMatch = ref.match(/^#\/components\/requestBodies\/(.+)$/);
|
|
1759
|
+
const responseMatch = ref.match(/^#\/components\/responses\/(.+)$/);
|
|
1760
|
+
const schemaMatch = ref.match(/^#\/components\/schemas\/(.+)$/);
|
|
1761
|
+
if (paramMatch && ((_a = spec.components) == null ? void 0 : _a.parameters)) {
|
|
1762
|
+
const name = paramMatch[1];
|
|
1763
|
+
resolved = spec.components.parameters[name];
|
|
1764
|
+
} else if (requestBodyMatch && ((_b = spec.components) == null ? void 0 : _b.requestBodies)) {
|
|
1765
|
+
const name = requestBodyMatch[1];
|
|
1766
|
+
resolved = spec.components.requestBodies[name];
|
|
1767
|
+
} else if (responseMatch && ((_c = spec.components) == null ? void 0 : _c.responses)) {
|
|
1768
|
+
const name = responseMatch[1];
|
|
1769
|
+
resolved = spec.components.responses[name];
|
|
1770
|
+
} else if (schemaMatch && ((_d = spec.components) == null ? void 0 : _d.schemas)) {
|
|
1771
|
+
const name = schemaMatch[1];
|
|
1772
|
+
resolved = spec.components.schemas[name];
|
|
1773
|
+
}
|
|
1774
|
+
if (resolved) {
|
|
1775
|
+
if (resolved.$ref) {
|
|
1776
|
+
return resolveRef2(resolved, spec, maxDepth - 1);
|
|
1777
|
+
}
|
|
1778
|
+
return resolved;
|
|
1779
|
+
}
|
|
1780
|
+
return obj;
|
|
1781
|
+
}
|
|
1782
|
+
function resolveParameterRef(param, spec) {
|
|
1783
|
+
return resolveRef2(param, spec);
|
|
1784
|
+
}
|
|
1785
|
+
function mergeParameters(pathParams, operationParams, spec) {
|
|
1786
|
+
const resolvedPathParams = (pathParams || []).map((p) => resolveParameterRef(p, spec));
|
|
1787
|
+
const resolvedOperationParams = (operationParams || []).map((p) => resolveParameterRef(p, spec));
|
|
1788
|
+
const merged = [...resolvedPathParams];
|
|
1789
|
+
for (const opParam of resolvedOperationParams) {
|
|
1790
|
+
if (!opParam || typeof opParam !== "object") continue;
|
|
1791
|
+
const existingIndex = merged.findIndex(
|
|
1792
|
+
(p) => p && typeof p === "object" && p.name === opParam.name && p.in === opParam.in
|
|
1793
|
+
);
|
|
1794
|
+
if (existingIndex >= 0) {
|
|
1795
|
+
merged[existingIndex] = opParam;
|
|
1796
|
+
} else {
|
|
1797
|
+
merged.push(opParam);
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
return merged;
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1562
1803
|
// src/openapi-generator.ts
|
|
1563
1804
|
var OpenApiGenerator = class {
|
|
1564
1805
|
constructor(options) {
|
|
@@ -1568,7 +1809,7 @@ var OpenApiGenerator = class {
|
|
|
1568
1809
|
this.schemaUsageMap = /* @__PURE__ */ new Map();
|
|
1569
1810
|
this.needsZodImport = true;
|
|
1570
1811
|
this.filterStats = createFilterStatistics();
|
|
1571
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
1812
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1572
1813
|
if (!options.input) {
|
|
1573
1814
|
throw new ConfigurationError("Input path is required", { providedOptions: options });
|
|
1574
1815
|
}
|
|
@@ -1579,18 +1820,19 @@ var OpenApiGenerator = class {
|
|
|
1579
1820
|
includeDescriptions: (_a = options.includeDescriptions) != null ? _a : true,
|
|
1580
1821
|
useDescribe: (_b = options.useDescribe) != null ? _b : false,
|
|
1581
1822
|
defaultNullable: (_c = options.defaultNullable) != null ? _c : false,
|
|
1823
|
+
emptyObjectBehavior: (_d = options.emptyObjectBehavior) != null ? _d : "loose",
|
|
1582
1824
|
schemaType: options.schemaType || "all",
|
|
1583
1825
|
prefix: options.prefix,
|
|
1584
1826
|
suffix: options.suffix,
|
|
1585
1827
|
stripSchemaPrefix: options.stripSchemaPrefix,
|
|
1586
1828
|
stripPathPrefix: options.stripPathPrefix,
|
|
1587
|
-
showStats: (
|
|
1829
|
+
showStats: (_e = options.showStats) != null ? _e : true,
|
|
1588
1830
|
request: options.request,
|
|
1589
1831
|
response: options.response,
|
|
1590
1832
|
operationFilters: options.operationFilters,
|
|
1591
1833
|
ignoreHeaders: options.ignoreHeaders,
|
|
1592
|
-
cacheSize: (
|
|
1593
|
-
batchSize: (
|
|
1834
|
+
cacheSize: (_f = options.cacheSize) != null ? _f : 1e3,
|
|
1835
|
+
batchSize: (_g = options.batchSize) != null ? _g : 10,
|
|
1594
1836
|
customDateTimeFormatRegex: options.customDateTimeFormatRegex
|
|
1595
1837
|
};
|
|
1596
1838
|
if (this.options.cacheSize) {
|
|
@@ -1661,7 +1903,8 @@ var OpenApiGenerator = class {
|
|
|
1661
1903
|
mode: this.requestOptions.mode,
|
|
1662
1904
|
includeDescriptions: this.requestOptions.includeDescriptions,
|
|
1663
1905
|
useDescribe: this.requestOptions.useDescribe,
|
|
1664
|
-
defaultNullable: (
|
|
1906
|
+
defaultNullable: (_h = this.options.defaultNullable) != null ? _h : false,
|
|
1907
|
+
emptyObjectBehavior: (_i = this.options.emptyObjectBehavior) != null ? _i : "loose",
|
|
1665
1908
|
namingOptions: {
|
|
1666
1909
|
prefix: this.options.prefix,
|
|
1667
1910
|
suffix: this.options.suffix
|
|
@@ -2015,7 +2258,7 @@ var OpenApiGenerator = class {
|
|
|
2015
2258
|
* Generate schema for a component
|
|
2016
2259
|
*/
|
|
2017
2260
|
generateComponentSchema(name, schema) {
|
|
2018
|
-
var _a, _b, _c;
|
|
2261
|
+
var _a, _b, _c, _d;
|
|
2019
2262
|
if (!this.schemaDependencies.has(name)) {
|
|
2020
2263
|
this.schemaDependencies.set(name, /* @__PURE__ */ new Set());
|
|
2021
2264
|
}
|
|
@@ -2048,6 +2291,7 @@ ${typeCode}`;
|
|
|
2048
2291
|
includeDescriptions: resolvedOptions.includeDescriptions,
|
|
2049
2292
|
useDescribe: resolvedOptions.useDescribe,
|
|
2050
2293
|
defaultNullable: (_b = this.options.defaultNullable) != null ? _b : false,
|
|
2294
|
+
emptyObjectBehavior: (_c = this.options.emptyObjectBehavior) != null ? _c : "loose",
|
|
2051
2295
|
namingOptions: {
|
|
2052
2296
|
prefix: this.options.prefix,
|
|
2053
2297
|
suffix: this.options.suffix
|
|
@@ -2064,7 +2308,7 @@ ${typeCode}`;
|
|
|
2064
2308
|
const depMatch = ref.match(/^([a-z][a-zA-Z0-9]*?)Schema$/);
|
|
2065
2309
|
if (depMatch) {
|
|
2066
2310
|
const depName = depMatch[1].charAt(0).toUpperCase() + depMatch[1].slice(1);
|
|
2067
|
-
(
|
|
2311
|
+
(_d = this.schemaDependencies.get(name)) == null ? void 0 : _d.add(depName);
|
|
2068
2312
|
}
|
|
2069
2313
|
}
|
|
2070
2314
|
}
|
|
@@ -2088,10 +2332,8 @@ ${typeCode}`;
|
|
|
2088
2332
|
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
|
|
2089
2333
|
continue;
|
|
2090
2334
|
}
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
}
|
|
2094
|
-
const queryParams = operation.parameters.filter(
|
|
2335
|
+
const allParams = mergeParameters(pathItem.parameters, operation.parameters, this.spec);
|
|
2336
|
+
const queryParams = allParams.filter(
|
|
2095
2337
|
(param) => param && typeof param === "object" && param.in === "query"
|
|
2096
2338
|
);
|
|
2097
2339
|
if (queryParams.length === 0) {
|
|
@@ -2227,10 +2469,8 @@ ${propsCode}
|
|
|
2227
2469
|
if (!shouldIncludeOperation(operation, path, method, this.options.operationFilters)) {
|
|
2228
2470
|
continue;
|
|
2229
2471
|
}
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
}
|
|
2233
|
-
const headerParams = operation.parameters.filter(
|
|
2472
|
+
const allParams = mergeParameters(pathItem.parameters, operation.parameters, this.spec);
|
|
2473
|
+
const headerParams = allParams.filter(
|
|
2234
2474
|
(param) => param && typeof param === "object" && param.in === "header" && !this.shouldIgnoreHeader(param.name)
|
|
2235
2475
|
);
|
|
2236
2476
|
if (headerParams.length === 0) {
|
|
@@ -2320,13 +2560,23 @@ ${propsCode}
|
|
|
2320
2560
|
}
|
|
2321
2561
|
const type = schema.type;
|
|
2322
2562
|
if (type === "string") {
|
|
2563
|
+
const formatMap = {
|
|
2564
|
+
email: "z.email()",
|
|
2565
|
+
uri: "z.url()",
|
|
2566
|
+
url: "z.url()",
|
|
2567
|
+
uuid: "z.uuid()"
|
|
2568
|
+
};
|
|
2569
|
+
if (schema.format && formatMap[schema.format]) {
|
|
2570
|
+
let zodType2 = formatMap[schema.format];
|
|
2571
|
+
if (schema.minLength !== void 0) zodType2 = `${zodType2}.min(${schema.minLength})`;
|
|
2572
|
+
if (schema.maxLength !== void 0) zodType2 = `${zodType2}.max(${schema.maxLength})`;
|
|
2573
|
+
if (schema.pattern) zodType2 = `${zodType2}.regex(/${schema.pattern}/)`;
|
|
2574
|
+
return zodType2;
|
|
2575
|
+
}
|
|
2323
2576
|
let zodType = "z.string()";
|
|
2324
2577
|
if (schema.minLength !== void 0) zodType = `${zodType}.min(${schema.minLength})`;
|
|
2325
2578
|
if (schema.maxLength !== void 0) zodType = `${zodType}.max(${schema.maxLength})`;
|
|
2326
2579
|
if (schema.pattern) zodType = `${zodType}.regex(/${schema.pattern}/)`;
|
|
2327
|
-
if (schema.format === "email") zodType = `${zodType}.email()`;
|
|
2328
|
-
if (schema.format === "uri" || schema.format === "url") zodType = `${zodType}.url()`;
|
|
2329
|
-
if (schema.format === "uuid") zodType = `${zodType}.uuid()`;
|
|
2330
2580
|
return zodType;
|
|
2331
2581
|
}
|
|
2332
2582
|
if (type === "number" || type === "integer") {
|
|
@@ -2351,11 +2601,6 @@ ${propsCode}
|
|
|
2351
2601
|
}
|
|
2352
2602
|
return "z.unknown()";
|
|
2353
2603
|
}
|
|
2354
|
-
// REMOVED: generateNativeEnum method - no longer needed as we only generate Zod schemas
|
|
2355
|
-
// REMOVED: toEnumKey method - was only used by generateNativeEnum
|
|
2356
|
-
// REMOVED: addConstraintsToJSDoc method - was only used for native TypeScript types
|
|
2357
|
-
// REMOVED: generateNativeTypeDefinition method - was only used for native TypeScript types
|
|
2358
|
-
// REMOVED: generateObjectType method - was only used for native TypeScript types
|
|
2359
2604
|
/**
|
|
2360
2605
|
* Topological sort for schema dependencies
|
|
2361
2606
|
* Returns schemas in the order they should be declared
|