@cerios/openapi-to-zod 1.2.0 → 1.3.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 +87 -30
- package/dist/cli.js +306 -52
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +312 -52
- 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 +300 -51
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +300 -51
- package/dist/index.mjs.map +1 -1
- package/dist/internal.d.mts +93 -2
- package/dist/internal.d.ts +93 -2
- package/dist/internal.js +115 -4
- package/dist/internal.js.map +1 -1
- package/dist/internal.mjs +109 -4
- package/dist/internal.mjs.map +1 -1
- package/dist/{types--r0d47sd.d.mts → types-DZ4Bw-D5.d.mts} +86 -4
- package/dist/{types--r0d47sd.d.ts → types-DZ4Bw-D5.d.ts} +86 -4
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -5151,12 +5151,12 @@ function toCamelCase(str, options) {
|
|
|
5151
5151
|
name = words[0].charAt(0).toLowerCase() + words[0].slice(1) + words.slice(1).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
5152
5152
|
}
|
|
5153
5153
|
if (options == null ? void 0 : options.prefix) {
|
|
5154
|
-
const prefix = options.prefix.toLowerCase();
|
|
5154
|
+
const prefix = options.prefix.charAt(0).toLowerCase() + options.prefix.slice(1);
|
|
5155
5155
|
name = prefix + name.charAt(0).toUpperCase() + name.slice(1);
|
|
5156
5156
|
}
|
|
5157
5157
|
if (options == null ? void 0 : options.suffix) {
|
|
5158
|
-
const suffix = options.suffix;
|
|
5159
|
-
name = name + suffix
|
|
5158
|
+
const suffix = options.suffix.charAt(0).toUpperCase() + options.suffix.slice(1);
|
|
5159
|
+
name = name + suffix;
|
|
5160
5160
|
}
|
|
5161
5161
|
return name;
|
|
5162
5162
|
}
|
|
@@ -5514,12 +5514,56 @@ var init_array_validator = __esm({
|
|
|
5514
5514
|
});
|
|
5515
5515
|
|
|
5516
5516
|
// src/validators/composition-validator.ts
|
|
5517
|
+
function isDiscriminatorRequired(schemas, discriminator, context) {
|
|
5518
|
+
const invalidSchemas = [];
|
|
5519
|
+
for (const schema of schemas) {
|
|
5520
|
+
const resolved = resolveSchema(schema, context);
|
|
5521
|
+
const required = resolved.required || [];
|
|
5522
|
+
if (!required.includes(discriminator)) {
|
|
5523
|
+
const schemaName = schema.$ref ? schema.$ref.split("/").pop() || "inline" : "inline";
|
|
5524
|
+
invalidSchemas.push(schemaName);
|
|
5525
|
+
}
|
|
5526
|
+
}
|
|
5527
|
+
return {
|
|
5528
|
+
valid: invalidSchemas.length === 0,
|
|
5529
|
+
invalidSchemas
|
|
5530
|
+
};
|
|
5531
|
+
}
|
|
5517
5532
|
function generateUnion(schemas, discriminator, isNullable2, context, options, currentSchema) {
|
|
5533
|
+
if (schemas.length === 0) {
|
|
5534
|
+
console.warn(
|
|
5535
|
+
"[openapi-to-zod] Warning: Empty oneOf/anyOf array encountered. This is likely a malformed OpenAPI spec. Generating z.never() as fallback."
|
|
5536
|
+
);
|
|
5537
|
+
return wrapNullable(
|
|
5538
|
+
'z.never().describe("Empty oneOf/anyOf in OpenAPI spec - no valid schema defined")',
|
|
5539
|
+
isNullable2
|
|
5540
|
+
);
|
|
5541
|
+
}
|
|
5542
|
+
if (schemas.length === 1) {
|
|
5543
|
+
let singleSchema = context.generatePropertySchema(schemas[0], currentSchema);
|
|
5544
|
+
if ((options == null ? void 0 : options.passthrough) && !singleSchema.includes(".catchall(")) {
|
|
5545
|
+
singleSchema = `${singleSchema}.catchall(z.unknown())`;
|
|
5546
|
+
}
|
|
5547
|
+
return wrapNullable(singleSchema, isNullable2);
|
|
5548
|
+
}
|
|
5518
5549
|
if (discriminator) {
|
|
5519
5550
|
let resolvedSchemas = schemas;
|
|
5520
5551
|
if ((options == null ? void 0 : options.discriminatorMapping) && context.resolveDiscriminatorMapping) {
|
|
5521
5552
|
resolvedSchemas = context.resolveDiscriminatorMapping(options.discriminatorMapping, schemas);
|
|
5522
5553
|
}
|
|
5554
|
+
const discriminatorCheck = isDiscriminatorRequired(resolvedSchemas, discriminator, context);
|
|
5555
|
+
if (!discriminatorCheck.valid) {
|
|
5556
|
+
console.warn(
|
|
5557
|
+
`[openapi-to-zod] Warning: Discriminator "${discriminator}" is not required in schemas: ${discriminatorCheck.invalidSchemas.join(", ")}. Falling back to z.union() instead of z.discriminatedUnion().`
|
|
5558
|
+
);
|
|
5559
|
+
let schemaStrings3 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema));
|
|
5560
|
+
if (options == null ? void 0 : options.passthrough) {
|
|
5561
|
+
schemaStrings3 = schemaStrings3.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
|
|
5562
|
+
}
|
|
5563
|
+
const fallbackDescription = `Discriminator "${discriminator}" is optional in some schemas (${discriminatorCheck.invalidSchemas.join(", ")}), using z.union() instead of z.discriminatedUnion()`;
|
|
5564
|
+
const union3 = `z.union([${schemaStrings3.join(", ")}]).describe("${fallbackDescription}")`;
|
|
5565
|
+
return wrapNullable(union3, isNullable2);
|
|
5566
|
+
}
|
|
5523
5567
|
let schemaStrings2 = resolvedSchemas.map((s) => context.generatePropertySchema(s, currentSchema));
|
|
5524
5568
|
if (options == null ? void 0 : options.passthrough) {
|
|
5525
5569
|
schemaStrings2 = schemaStrings2.map((s) => s.includes(".catchall(") ? s : `${s}.catchall(z.unknown())`);
|
|
@@ -5534,25 +5578,102 @@ function generateUnion(schemas, discriminator, isNullable2, context, options, cu
|
|
|
5534
5578
|
const union = `z.union([${schemaStrings.join(", ")}])`;
|
|
5535
5579
|
return wrapNullable(union, isNullable2);
|
|
5536
5580
|
}
|
|
5537
|
-
function
|
|
5581
|
+
function resolveSchema(schema, context) {
|
|
5582
|
+
if (schema.$ref && context.resolveSchemaRef) {
|
|
5583
|
+
const resolved = context.resolveSchemaRef(schema.$ref);
|
|
5584
|
+
if (resolved) {
|
|
5585
|
+
return resolved;
|
|
5586
|
+
}
|
|
5587
|
+
}
|
|
5588
|
+
return schema;
|
|
5589
|
+
}
|
|
5590
|
+
function collectProperties(schema, context) {
|
|
5591
|
+
const resolved = resolveSchema(schema, context);
|
|
5592
|
+
const props = /* @__PURE__ */ new Map();
|
|
5593
|
+
const sourceName = schema.$ref ? schema.$ref.split("/").pop() || "unknown" : "inline";
|
|
5594
|
+
if (resolved.properties) {
|
|
5595
|
+
for (const [key, value] of Object.entries(resolved.properties)) {
|
|
5596
|
+
props.set(key, { schema: value, source: sourceName });
|
|
5597
|
+
}
|
|
5598
|
+
}
|
|
5599
|
+
if (resolved.allOf) {
|
|
5600
|
+
for (const subSchema of resolved.allOf) {
|
|
5601
|
+
const subProps = collectProperties(subSchema, context);
|
|
5602
|
+
for (const [key, value] of subProps) {
|
|
5603
|
+
if (!props.has(key)) {
|
|
5604
|
+
props.set(key, value);
|
|
5605
|
+
}
|
|
5606
|
+
}
|
|
5607
|
+
}
|
|
5608
|
+
}
|
|
5609
|
+
return props;
|
|
5610
|
+
}
|
|
5611
|
+
function schemasMatch(a, b) {
|
|
5612
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
5613
|
+
}
|
|
5614
|
+
function detectConflictingProperties(schemas, context) {
|
|
5615
|
+
const conflicts = [];
|
|
5616
|
+
const propertyMap = /* @__PURE__ */ new Map();
|
|
5617
|
+
for (const schema of schemas) {
|
|
5618
|
+
const schemaProps = collectProperties(schema, context);
|
|
5619
|
+
for (const [propName, propInfo] of schemaProps) {
|
|
5620
|
+
const existing = propertyMap.get(propName);
|
|
5621
|
+
if (existing) {
|
|
5622
|
+
if (!schemasMatch(existing.schema, propInfo.schema)) {
|
|
5623
|
+
conflicts.push(
|
|
5624
|
+
`Property "${propName}" has conflicting definitions in ${existing.source} and ${propInfo.source}`
|
|
5625
|
+
);
|
|
5626
|
+
}
|
|
5627
|
+
} else {
|
|
5628
|
+
propertyMap.set(propName, propInfo);
|
|
5629
|
+
}
|
|
5630
|
+
}
|
|
5631
|
+
}
|
|
5632
|
+
return conflicts;
|
|
5633
|
+
}
|
|
5634
|
+
function generateAllOf(schemas, isNullable2, context, currentSchema, explicitNullableFalse = false) {
|
|
5538
5635
|
if (schemas.length === 1) {
|
|
5539
|
-
const singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false);
|
|
5636
|
+
const singleSchema = context.generatePropertySchema(schemas[0], currentSchema, false, explicitNullableFalse);
|
|
5540
5637
|
return wrapNullable(singleSchema, isNullable2);
|
|
5541
5638
|
}
|
|
5639
|
+
const conflicts = detectConflictingProperties(schemas, context);
|
|
5640
|
+
let conflictDescription = "";
|
|
5641
|
+
if (conflicts.length > 0) {
|
|
5642
|
+
for (const conflict of conflicts) {
|
|
5643
|
+
console.warn(`[openapi-to-zod] Warning: allOf composition conflict - ${conflict}`);
|
|
5644
|
+
}
|
|
5645
|
+
conflictDescription = `allOf property conflicts detected: ${conflicts.join("; ")}`;
|
|
5646
|
+
}
|
|
5542
5647
|
const allObjects = schemas.every((s) => s.type === "object" || s.properties || s.$ref || s.allOf);
|
|
5543
|
-
|
|
5648
|
+
let result;
|
|
5544
5649
|
if (allObjects) {
|
|
5545
|
-
let
|
|
5650
|
+
let merged = context.generatePropertySchema(schemas[0], currentSchema, false);
|
|
5651
|
+
for (let i = 1; i < schemas.length; i++) {
|
|
5652
|
+
const schema = schemas[i];
|
|
5653
|
+
if (schema.$ref) {
|
|
5654
|
+
const refSchema = context.generatePropertySchema(schema, currentSchema, false);
|
|
5655
|
+
merged = `${merged}.extend(${refSchema}.shape)`;
|
|
5656
|
+
} else if (context.generateInlineObjectShape && (schema.properties || schema.type === "object")) {
|
|
5657
|
+
const inlineShape = context.generateInlineObjectShape(schema, currentSchema);
|
|
5658
|
+
merged = `${merged}.extend(${inlineShape})`;
|
|
5659
|
+
} else {
|
|
5660
|
+
const schemaString = context.generatePropertySchema(schema, currentSchema, false);
|
|
5661
|
+
merged = `${merged}.extend(${schemaString}.shape)`;
|
|
5662
|
+
}
|
|
5663
|
+
}
|
|
5664
|
+
result = merged;
|
|
5665
|
+
} else {
|
|
5666
|
+
const schemaStrings = schemas.map((s) => context.generatePropertySchema(s, currentSchema, false));
|
|
5667
|
+
let merged = schemaStrings[0];
|
|
5546
5668
|
for (let i = 1; i < schemaStrings.length; i++) {
|
|
5547
|
-
|
|
5669
|
+
merged = `${merged}.and(${schemaStrings[i]})`;
|
|
5548
5670
|
}
|
|
5549
|
-
|
|
5671
|
+
result = merged;
|
|
5550
5672
|
}
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
merged = `${merged}.and(${schemaStrings[i]})`;
|
|
5673
|
+
if (conflictDescription) {
|
|
5674
|
+
result = `${result}.describe("${conflictDescription}")`;
|
|
5554
5675
|
}
|
|
5555
|
-
return wrapNullable(
|
|
5676
|
+
return wrapNullable(result, isNullable2);
|
|
5556
5677
|
}
|
|
5557
5678
|
var init_composition_validator = __esm({
|
|
5558
5679
|
"src/validators/composition-validator.ts"() {
|
|
@@ -6279,6 +6400,15 @@ var init_property_generator = __esm({
|
|
|
6279
6400
|
}
|
|
6280
6401
|
return mappedSchemas;
|
|
6281
6402
|
}
|
|
6403
|
+
/**
|
|
6404
|
+
* Resolve a $ref string to the actual schema
|
|
6405
|
+
*/
|
|
6406
|
+
resolveSchemaRef(ref) {
|
|
6407
|
+
var _a, _b;
|
|
6408
|
+
const schemaName = ref.split("/").pop();
|
|
6409
|
+
if (!schemaName) return void 0;
|
|
6410
|
+
return (_b = (_a = this.context.spec.components) == null ? void 0 : _a.schemas) == null ? void 0 : _b[schemaName];
|
|
6411
|
+
}
|
|
6282
6412
|
/**
|
|
6283
6413
|
* Resolve a schema name through any aliases to get the actual schema name
|
|
6284
6414
|
* If the schema is an alias (allOf with single $ref), return the target name
|
|
@@ -6356,7 +6486,7 @@ var init_property_generator = __esm({
|
|
|
6356
6486
|
let schemaWithCatchall = baseSchema;
|
|
6357
6487
|
if (baseSchema.includes(".union([") || baseSchema.includes(".discriminatedUnion(")) {
|
|
6358
6488
|
schemaWithCatchall = baseSchema;
|
|
6359
|
-
} else if (baseSchema.includes(".
|
|
6489
|
+
} else if (baseSchema.includes(".extend(")) {
|
|
6360
6490
|
schemaWithCatchall = `${baseSchema}.catchall(z.unknown())`;
|
|
6361
6491
|
}
|
|
6362
6492
|
if (schema.unevaluatedProperties === false) {
|
|
@@ -6369,12 +6499,21 @@ var init_property_generator = __esm({
|
|
|
6369
6499
|
}
|
|
6370
6500
|
/**
|
|
6371
6501
|
* Generate Zod schema for a property
|
|
6502
|
+
* @param schema - The OpenAPI schema to generate
|
|
6503
|
+
* @param currentSchema - The name of the current schema being processed (for circular ref detection)
|
|
6504
|
+
* @param isTopLevel - Whether this is a top-level schema definition
|
|
6505
|
+
* @param suppressDefaultNullable - When true, don't apply defaultNullable (used when outer schema has explicit nullable: false)
|
|
6372
6506
|
*/
|
|
6373
|
-
generatePropertySchema(schema, currentSchema, isTopLevel = false) {
|
|
6507
|
+
generatePropertySchema(schema, currentSchema, isTopLevel = false, suppressDefaultNullable = false) {
|
|
6374
6508
|
var _a, _b, _c, _d, _e;
|
|
6375
6509
|
const isCacheable = !schema.$ref && !schema.allOf && !schema.oneOf && !schema.anyOf && !currentSchema;
|
|
6376
6510
|
if (isCacheable) {
|
|
6377
|
-
const cacheKey = JSON.stringify({
|
|
6511
|
+
const cacheKey = JSON.stringify({
|
|
6512
|
+
schema,
|
|
6513
|
+
type: this.context.schemaType,
|
|
6514
|
+
mode: this.context.mode,
|
|
6515
|
+
suppressDefaultNullable
|
|
6516
|
+
});
|
|
6378
6517
|
const cached = this.schemaCache.get(cacheKey);
|
|
6379
6518
|
if (cached) {
|
|
6380
6519
|
return cached;
|
|
@@ -6383,7 +6522,10 @@ var init_property_generator = __esm({
|
|
|
6383
6522
|
if ((this.context.schemaType === "request" || this.context.schemaType === "response") && schema.properties) {
|
|
6384
6523
|
schema = this.filterNestedProperties(schema);
|
|
6385
6524
|
}
|
|
6386
|
-
const
|
|
6525
|
+
const isEnum = !!schema.enum;
|
|
6526
|
+
const isConst = schema.const !== void 0;
|
|
6527
|
+
const shouldApplyDefaultNullable = !isTopLevel && !isEnum && !isConst && !suppressDefaultNullable;
|
|
6528
|
+
const effectiveDefaultNullable = shouldApplyDefaultNullable ? this.context.defaultNullable : false;
|
|
6387
6529
|
const nullable = isNullable(schema, effectiveDefaultNullable);
|
|
6388
6530
|
if (hasMultipleTypes(schema)) {
|
|
6389
6531
|
const union = this.generateMultiTypeUnion(schema, currentSchema);
|
|
@@ -6433,11 +6575,17 @@ var init_property_generator = __esm({
|
|
|
6433
6575
|
return wrapNullable(zodUnion, nullable);
|
|
6434
6576
|
}
|
|
6435
6577
|
if (schema.allOf) {
|
|
6578
|
+
const explicitNullableFalse = schema.nullable === false;
|
|
6436
6579
|
let composition = generateAllOf(
|
|
6437
6580
|
schema.allOf,
|
|
6438
6581
|
nullable,
|
|
6439
|
-
{
|
|
6440
|
-
|
|
6582
|
+
{
|
|
6583
|
+
generatePropertySchema: this.generatePropertySchema.bind(this),
|
|
6584
|
+
generateInlineObjectShape: this.generateInlineObjectShape.bind(this),
|
|
6585
|
+
resolveSchemaRef: this.resolveSchemaRef.bind(this)
|
|
6586
|
+
},
|
|
6587
|
+
currentSchema,
|
|
6588
|
+
explicitNullableFalse
|
|
6441
6589
|
);
|
|
6442
6590
|
if (schema.unevaluatedProperties !== void 0) {
|
|
6443
6591
|
composition = this.applyUnevaluatedProperties(composition, schema);
|
|
@@ -6452,7 +6600,8 @@ var init_property_generator = __esm({
|
|
|
6452
6600
|
nullable,
|
|
6453
6601
|
{
|
|
6454
6602
|
generatePropertySchema: this.generatePropertySchema.bind(this),
|
|
6455
|
-
resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this)
|
|
6603
|
+
resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
|
|
6604
|
+
resolveSchemaRef: this.resolveSchemaRef.bind(this)
|
|
6456
6605
|
},
|
|
6457
6606
|
{
|
|
6458
6607
|
passthrough: needsPassthrough,
|
|
@@ -6473,7 +6622,8 @@ var init_property_generator = __esm({
|
|
|
6473
6622
|
nullable,
|
|
6474
6623
|
{
|
|
6475
6624
|
generatePropertySchema: this.generatePropertySchema.bind(this),
|
|
6476
|
-
resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this)
|
|
6625
|
+
resolveDiscriminatorMapping: this.resolveDiscriminatorMapping.bind(this),
|
|
6626
|
+
resolveSchemaRef: this.resolveSchemaRef.bind(this)
|
|
6477
6627
|
},
|
|
6478
6628
|
{
|
|
6479
6629
|
passthrough: needsPassthrough,
|
|
@@ -6536,7 +6686,17 @@ var init_property_generator = __esm({
|
|
|
6536
6686
|
);
|
|
6537
6687
|
validation = addDescription(validation, schema.description, this.context.useDescribe);
|
|
6538
6688
|
} else {
|
|
6539
|
-
|
|
6689
|
+
switch (this.context.emptyObjectBehavior) {
|
|
6690
|
+
case "strict":
|
|
6691
|
+
validation = "z.strictObject({})";
|
|
6692
|
+
break;
|
|
6693
|
+
case "loose":
|
|
6694
|
+
validation = "z.looseObject({})";
|
|
6695
|
+
break;
|
|
6696
|
+
default:
|
|
6697
|
+
validation = "z.record(z.string(), z.unknown())";
|
|
6698
|
+
break;
|
|
6699
|
+
}
|
|
6540
6700
|
validation = addDescription(validation, schema.description, this.context.useDescribe);
|
|
6541
6701
|
}
|
|
6542
6702
|
break;
|
|
@@ -6551,6 +6711,44 @@ var init_property_generator = __esm({
|
|
|
6551
6711
|
}
|
|
6552
6712
|
return result;
|
|
6553
6713
|
}
|
|
6714
|
+
/**
|
|
6715
|
+
* Generate inline object shape for use with .extend()
|
|
6716
|
+
* Returns just the shape object literal: { prop1: z.string(), prop2: z.number() }
|
|
6717
|
+
*
|
|
6718
|
+
* This method is specifically for allOf compositions where we need to pass
|
|
6719
|
+
* the shape directly to .extend() instead of using z.object({...}).shape.
|
|
6720
|
+
* This avoids the .nullable().shape bug when inline objects have nullable: true.
|
|
6721
|
+
*
|
|
6722
|
+
* According to Zod docs (https://zod.dev/api?id=extend):
|
|
6723
|
+
* - .extend() accepts an object of shape definitions
|
|
6724
|
+
* - e.g., baseSchema.extend({ prop: z.string() })
|
|
6725
|
+
*/
|
|
6726
|
+
generateInlineObjectShape(schema, currentSchema) {
|
|
6727
|
+
const required = new Set(schema.required || []);
|
|
6728
|
+
const properties = [];
|
|
6729
|
+
if (schema.properties) {
|
|
6730
|
+
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
6731
|
+
if (!this.shouldIncludeProperty(propSchema)) {
|
|
6732
|
+
continue;
|
|
6733
|
+
}
|
|
6734
|
+
const isRequired = required.has(propName);
|
|
6735
|
+
const zodSchema = this.generatePropertySchema(propSchema, currentSchema);
|
|
6736
|
+
const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
6737
|
+
const quotedPropName = validIdentifier.test(propName) ? propName : `"${propName}"`;
|
|
6738
|
+
let propertyDef = `${quotedPropName}: ${zodSchema}`;
|
|
6739
|
+
if (!isRequired) {
|
|
6740
|
+
propertyDef += ".optional()";
|
|
6741
|
+
}
|
|
6742
|
+
properties.push(propertyDef);
|
|
6743
|
+
}
|
|
6744
|
+
}
|
|
6745
|
+
if (properties.length === 0) {
|
|
6746
|
+
return "{}";
|
|
6747
|
+
}
|
|
6748
|
+
return `{
|
|
6749
|
+
${properties.map((p) => ` ${p}`).join(",\n")}
|
|
6750
|
+
}`;
|
|
6751
|
+
}
|
|
6554
6752
|
};
|
|
6555
6753
|
// Performance optimization: Lookup table for faster inclusion checks
|
|
6556
6754
|
_PropertyGenerator.INCLUSION_RULES = {
|
|
@@ -6702,6 +6900,65 @@ var init_operation_filters = __esm({
|
|
|
6702
6900
|
}
|
|
6703
6901
|
});
|
|
6704
6902
|
|
|
6903
|
+
// src/utils/ref-resolver.ts
|
|
6904
|
+
function resolveRef2(obj, spec, maxDepth = 10) {
|
|
6905
|
+
var _a, _b, _c, _d;
|
|
6906
|
+
if (!obj || typeof obj !== "object" || maxDepth <= 0) return obj;
|
|
6907
|
+
if (!obj.$ref) return obj;
|
|
6908
|
+
const ref = obj.$ref;
|
|
6909
|
+
let resolved = null;
|
|
6910
|
+
const paramMatch = ref.match(/^#\/components\/parameters\/(.+)$/);
|
|
6911
|
+
const requestBodyMatch = ref.match(/^#\/components\/requestBodies\/(.+)$/);
|
|
6912
|
+
const responseMatch = ref.match(/^#\/components\/responses\/(.+)$/);
|
|
6913
|
+
const schemaMatch = ref.match(/^#\/components\/schemas\/(.+)$/);
|
|
6914
|
+
if (paramMatch && ((_a = spec.components) == null ? void 0 : _a.parameters)) {
|
|
6915
|
+
const name = paramMatch[1];
|
|
6916
|
+
resolved = spec.components.parameters[name];
|
|
6917
|
+
} else if (requestBodyMatch && ((_b = spec.components) == null ? void 0 : _b.requestBodies)) {
|
|
6918
|
+
const name = requestBodyMatch[1];
|
|
6919
|
+
resolved = spec.components.requestBodies[name];
|
|
6920
|
+
} else if (responseMatch && ((_c = spec.components) == null ? void 0 : _c.responses)) {
|
|
6921
|
+
const name = responseMatch[1];
|
|
6922
|
+
resolved = spec.components.responses[name];
|
|
6923
|
+
} else if (schemaMatch && ((_d = spec.components) == null ? void 0 : _d.schemas)) {
|
|
6924
|
+
const name = schemaMatch[1];
|
|
6925
|
+
resolved = spec.components.schemas[name];
|
|
6926
|
+
}
|
|
6927
|
+
if (resolved) {
|
|
6928
|
+
if (resolved.$ref) {
|
|
6929
|
+
return resolveRef2(resolved, spec, maxDepth - 1);
|
|
6930
|
+
}
|
|
6931
|
+
return resolved;
|
|
6932
|
+
}
|
|
6933
|
+
return obj;
|
|
6934
|
+
}
|
|
6935
|
+
function resolveParameterRef(param, spec) {
|
|
6936
|
+
return resolveRef2(param, spec);
|
|
6937
|
+
}
|
|
6938
|
+
function mergeParameters(pathParams, operationParams, spec) {
|
|
6939
|
+
const resolvedPathParams = (pathParams || []).map((p) => resolveParameterRef(p, spec));
|
|
6940
|
+
const resolvedOperationParams = (operationParams || []).map((p) => resolveParameterRef(p, spec));
|
|
6941
|
+
const merged = [...resolvedPathParams];
|
|
6942
|
+
for (const opParam of resolvedOperationParams) {
|
|
6943
|
+
if (!opParam || typeof opParam !== "object") continue;
|
|
6944
|
+
const existingIndex = merged.findIndex(
|
|
6945
|
+
(p) => p && typeof p === "object" && p.name === opParam.name && p.in === opParam.in
|
|
6946
|
+
);
|
|
6947
|
+
if (existingIndex >= 0) {
|
|
6948
|
+
merged[existingIndex] = opParam;
|
|
6949
|
+
} else {
|
|
6950
|
+
merged.push(opParam);
|
|
6951
|
+
}
|
|
6952
|
+
}
|
|
6953
|
+
return merged;
|
|
6954
|
+
}
|
|
6955
|
+
var init_ref_resolver = __esm({
|
|
6956
|
+
"src/utils/ref-resolver.ts"() {
|
|
6957
|
+
"use strict";
|
|
6958
|
+
init_esm_shims();
|
|
6959
|
+
}
|
|
6960
|
+
});
|
|
6961
|
+
|
|
6705
6962
|
// src/openapi-generator.ts
|
|
6706
6963
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
6707
6964
|
import { dirname, normalize } from "path";
|
|
@@ -6719,6 +6976,7 @@ var init_openapi_generator = __esm({
|
|
|
6719
6976
|
init_name_utils();
|
|
6720
6977
|
init_operation_filters();
|
|
6721
6978
|
init_pattern_utils();
|
|
6979
|
+
init_ref_resolver();
|
|
6722
6980
|
init_string_validator();
|
|
6723
6981
|
OpenApiGenerator = class {
|
|
6724
6982
|
constructor(options) {
|
|
@@ -6728,7 +6986,7 @@ var init_openapi_generator = __esm({
|
|
|
6728
6986
|
this.schemaUsageMap = /* @__PURE__ */ new Map();
|
|
6729
6987
|
this.needsZodImport = true;
|
|
6730
6988
|
this.filterStats = createFilterStatistics();
|
|
6731
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
6989
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
6732
6990
|
if (!options.input) {
|
|
6733
6991
|
throw new ConfigurationError("Input path is required", { providedOptions: options });
|
|
6734
6992
|
}
|
|
@@ -6739,18 +6997,19 @@ var init_openapi_generator = __esm({
|
|
|
6739
6997
|
includeDescriptions: (_a = options.includeDescriptions) != null ? _a : true,
|
|
6740
6998
|
useDescribe: (_b = options.useDescribe) != null ? _b : false,
|
|
6741
6999
|
defaultNullable: (_c = options.defaultNullable) != null ? _c : false,
|
|
7000
|
+
emptyObjectBehavior: (_d = options.emptyObjectBehavior) != null ? _d : "loose",
|
|
6742
7001
|
schemaType: options.schemaType || "all",
|
|
6743
7002
|
prefix: options.prefix,
|
|
6744
7003
|
suffix: options.suffix,
|
|
6745
7004
|
stripSchemaPrefix: options.stripSchemaPrefix,
|
|
6746
7005
|
stripPathPrefix: options.stripPathPrefix,
|
|
6747
|
-
showStats: (
|
|
7006
|
+
showStats: (_e = options.showStats) != null ? _e : true,
|
|
6748
7007
|
request: options.request,
|
|
6749
7008
|
response: options.response,
|
|
6750
7009
|
operationFilters: options.operationFilters,
|
|
6751
7010
|
ignoreHeaders: options.ignoreHeaders,
|
|
6752
|
-
cacheSize: (
|
|
6753
|
-
batchSize: (
|
|
7011
|
+
cacheSize: (_f = options.cacheSize) != null ? _f : 1e3,
|
|
7012
|
+
batchSize: (_g = options.batchSize) != null ? _g : 10,
|
|
6754
7013
|
customDateTimeFormatRegex: options.customDateTimeFormatRegex
|
|
6755
7014
|
};
|
|
6756
7015
|
if (this.options.cacheSize) {
|
|
@@ -6821,7 +7080,8 @@ var init_openapi_generator = __esm({
|
|
|
6821
7080
|
mode: this.requestOptions.mode,
|
|
6822
7081
|
includeDescriptions: this.requestOptions.includeDescriptions,
|
|
6823
7082
|
useDescribe: this.requestOptions.useDescribe,
|
|
6824
|
-
defaultNullable: (
|
|
7083
|
+
defaultNullable: (_h = this.options.defaultNullable) != null ? _h : false,
|
|
7084
|
+
emptyObjectBehavior: (_i = this.options.emptyObjectBehavior) != null ? _i : "loose",
|
|
6825
7085
|
namingOptions: {
|
|
6826
7086
|
prefix: this.options.prefix,
|
|
6827
7087
|
suffix: this.options.suffix
|
|
@@ -6891,12 +7151,6 @@ var init_openapi_generator = __esm({
|
|
|
6891
7151
|
* Generate the complete output file
|
|
6892
7152
|
*/
|
|
6893
7153
|
generate() {
|
|
6894
|
-
if (!this.options.output) {
|
|
6895
|
-
throw new ConfigurationError(
|
|
6896
|
-
"Output path is required when calling generate(). Either provide an 'output' option or use generateString() to get the result as a string.",
|
|
6897
|
-
{ hasOutput: false }
|
|
6898
|
-
);
|
|
6899
|
-
}
|
|
6900
7154
|
const output = this.generateString();
|
|
6901
7155
|
const normalizedOutput = normalize(this.options.output);
|
|
6902
7156
|
this.ensureDirectoryExists(normalizedOutput);
|
|
@@ -7175,7 +7429,7 @@ var init_openapi_generator = __esm({
|
|
|
7175
7429
|
* Generate schema for a component
|
|
7176
7430
|
*/
|
|
7177
7431
|
generateComponentSchema(name, schema) {
|
|
7178
|
-
var _a, _b, _c;
|
|
7432
|
+
var _a, _b, _c, _d;
|
|
7179
7433
|
if (!this.schemaDependencies.has(name)) {
|
|
7180
7434
|
this.schemaDependencies.set(name, /* @__PURE__ */ new Set());
|
|
7181
7435
|
}
|
|
@@ -7208,6 +7462,7 @@ ${typeCode}`;
|
|
|
7208
7462
|
includeDescriptions: resolvedOptions.includeDescriptions,
|
|
7209
7463
|
useDescribe: resolvedOptions.useDescribe,
|
|
7210
7464
|
defaultNullable: (_b = this.options.defaultNullable) != null ? _b : false,
|
|
7465
|
+
emptyObjectBehavior: (_c = this.options.emptyObjectBehavior) != null ? _c : "loose",
|
|
7211
7466
|
namingOptions: {
|
|
7212
7467
|
prefix: this.options.prefix,
|
|
7213
7468
|
suffix: this.options.suffix
|
|
@@ -7224,7 +7479,7 @@ ${typeCode}`;
|
|
|
7224
7479
|
const depMatch = ref.match(/^([a-z][a-zA-Z0-9]*?)Schema$/);
|
|
7225
7480
|
if (depMatch) {
|
|
7226
7481
|
const depName = depMatch[1].charAt(0).toUpperCase() + depMatch[1].slice(1);
|
|
7227
|
-
(
|
|
7482
|
+
(_d = this.schemaDependencies.get(name)) == null ? void 0 : _d.add(depName);
|
|
7228
7483
|
}
|
|
7229
7484
|
}
|
|
7230
7485
|
}
|
|
@@ -7248,10 +7503,8 @@ ${typeCode}`;
|
|
|
7248
7503
|
if (!shouldIncludeOperation(operation, path2, method, this.options.operationFilters)) {
|
|
7249
7504
|
continue;
|
|
7250
7505
|
}
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
}
|
|
7254
|
-
const queryParams = operation.parameters.filter(
|
|
7506
|
+
const allParams = mergeParameters(pathItem.parameters, operation.parameters, this.spec);
|
|
7507
|
+
const queryParams = allParams.filter(
|
|
7255
7508
|
(param) => param && typeof param === "object" && param.in === "query"
|
|
7256
7509
|
);
|
|
7257
7510
|
if (queryParams.length === 0) {
|
|
@@ -7387,10 +7640,8 @@ ${propsCode}
|
|
|
7387
7640
|
if (!shouldIncludeOperation(operation, path2, method, this.options.operationFilters)) {
|
|
7388
7641
|
continue;
|
|
7389
7642
|
}
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
}
|
|
7393
|
-
const headerParams = operation.parameters.filter(
|
|
7643
|
+
const allParams = mergeParameters(pathItem.parameters, operation.parameters, this.spec);
|
|
7644
|
+
const headerParams = allParams.filter(
|
|
7394
7645
|
(param) => param && typeof param === "object" && param.in === "header" && !this.shouldIgnoreHeader(param.name)
|
|
7395
7646
|
);
|
|
7396
7647
|
if (headerParams.length === 0) {
|
|
@@ -7480,13 +7731,23 @@ ${propsCode}
|
|
|
7480
7731
|
}
|
|
7481
7732
|
const type = schema.type;
|
|
7482
7733
|
if (type === "string") {
|
|
7734
|
+
const formatMap = {
|
|
7735
|
+
email: "z.email()",
|
|
7736
|
+
uri: "z.url()",
|
|
7737
|
+
url: "z.url()",
|
|
7738
|
+
uuid: "z.uuid()"
|
|
7739
|
+
};
|
|
7740
|
+
if (schema.format && formatMap[schema.format]) {
|
|
7741
|
+
let zodType2 = formatMap[schema.format];
|
|
7742
|
+
if (schema.minLength !== void 0) zodType2 = `${zodType2}.min(${schema.minLength})`;
|
|
7743
|
+
if (schema.maxLength !== void 0) zodType2 = `${zodType2}.max(${schema.maxLength})`;
|
|
7744
|
+
if (schema.pattern) zodType2 = `${zodType2}.regex(/${schema.pattern}/)`;
|
|
7745
|
+
return zodType2;
|
|
7746
|
+
}
|
|
7483
7747
|
let zodType = "z.string()";
|
|
7484
7748
|
if (schema.minLength !== void 0) zodType = `${zodType}.min(${schema.minLength})`;
|
|
7485
7749
|
if (schema.maxLength !== void 0) zodType = `${zodType}.max(${schema.maxLength})`;
|
|
7486
7750
|
if (schema.pattern) zodType = `${zodType}.regex(/${schema.pattern}/)`;
|
|
7487
|
-
if (schema.format === "email") zodType = `${zodType}.email()`;
|
|
7488
|
-
if (schema.format === "uri" || schema.format === "url") zodType = `${zodType}.url()`;
|
|
7489
|
-
if (schema.format === "uuid") zodType = `${zodType}.uuid()`;
|
|
7490
7751
|
return zodType;
|
|
7491
7752
|
}
|
|
7492
7753
|
if (type === "number" || type === "integer") {
|
|
@@ -7511,11 +7772,6 @@ ${propsCode}
|
|
|
7511
7772
|
}
|
|
7512
7773
|
return "z.unknown()";
|
|
7513
7774
|
}
|
|
7514
|
-
// REMOVED: generateNativeEnum method - no longer needed as we only generate Zod schemas
|
|
7515
|
-
// REMOVED: toEnumKey method - was only used by generateNativeEnum
|
|
7516
|
-
// REMOVED: addConstraintsToJSDoc method - was only used for native TypeScript types
|
|
7517
|
-
// REMOVED: generateNativeTypeDefinition method - was only used for native TypeScript types
|
|
7518
|
-
// REMOVED: generateObjectType method - was only used for native TypeScript types
|
|
7519
7775
|
/**
|
|
7520
7776
|
* Topological sort for schema dependencies
|
|
7521
7777
|
* Returns schemas in the order they should be declared
|
|
@@ -7623,7 +7879,8 @@ var init_config_schemas = __esm({
|
|
|
7623
7879
|
mode: z.enum(["strict", "normal", "loose"]).optional(),
|
|
7624
7880
|
useDescribe: z.boolean().optional(),
|
|
7625
7881
|
includeDescriptions: z.boolean().optional(),
|
|
7626
|
-
defaultNullable: z.boolean().optional()
|
|
7882
|
+
defaultNullable: z.boolean().optional(),
|
|
7883
|
+
emptyObjectBehavior: z.enum(["strict", "loose", "record"]).optional()
|
|
7627
7884
|
});
|
|
7628
7885
|
OperationFiltersSchema = z.strictObject({
|
|
7629
7886
|
includeTags: z.array(z.string()).optional(),
|
|
@@ -7755,6 +8012,7 @@ function mergeConfigWithDefaults(config) {
|
|
|
7755
8012
|
includeDescriptions: defaults.includeDescriptions,
|
|
7756
8013
|
useDescribe: defaults.useDescribe,
|
|
7757
8014
|
defaultNullable: defaults.defaultNullable,
|
|
8015
|
+
emptyObjectBehavior: defaults.emptyObjectBehavior,
|
|
7758
8016
|
schemaType: defaults.schemaType,
|
|
7759
8017
|
prefix: defaults.prefix,
|
|
7760
8018
|
suffix: defaults.suffix,
|
|
@@ -7781,6 +8039,7 @@ var init_config_loader = __esm({
|
|
|
7781
8039
|
includeDescriptions: z2.boolean().optional(),
|
|
7782
8040
|
useDescribe: z2.boolean().optional(),
|
|
7783
8041
|
defaultNullable: z2.boolean().optional(),
|
|
8042
|
+
emptyObjectBehavior: z2.enum(["strict", "loose", "record"]).optional(),
|
|
7784
8043
|
schemaType: z2.enum(["all", "request", "response"]).optional(),
|
|
7785
8044
|
prefix: z2.string().optional(),
|
|
7786
8045
|
suffix: z2.string().optional(),
|
|
@@ -7813,6 +8072,7 @@ var init_config_loader = __esm({
|
|
|
7813
8072
|
includeDescriptions: z2.boolean().optional(),
|
|
7814
8073
|
useDescribe: z2.boolean().optional(),
|
|
7815
8074
|
defaultNullable: z2.boolean().optional(),
|
|
8075
|
+
emptyObjectBehavior: z2.enum(["strict", "loose", "record"]).optional(),
|
|
7816
8076
|
schemaType: z2.enum(["all", "request", "response"]).optional(),
|
|
7817
8077
|
prefix: z2.string().optional(),
|
|
7818
8078
|
suffix: z2.string().optional(),
|