Skip to content

Commit ad24cf7

Browse files
committed
Merge branch 'master' of github.com:samchungy/zod-openapi
2 parents 5cf6dc0 + 1efe558 commit ad24cf7

File tree

2 files changed

+112
-9
lines changed

2 files changed

+112
-9
lines changed

src/create/schema/parsers/intersection.test.ts

+94
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,98 @@ describe('createIntersectionSchema', () => {
2727

2828
expect(result).toEqual(expected);
2929
});
30+
31+
it('creates an object with an allOf', () => {
32+
const schema = z.object({
33+
a: z.string(),
34+
});
35+
36+
const andSchema = schema.and(
37+
z.object({
38+
b: z.string(),
39+
}),
40+
);
41+
42+
const result = createIntersectionSchema(andSchema, createOutputState());
43+
44+
expect(result).toEqual<Schema>({
45+
type: 'schema',
46+
schema: {
47+
allOf: [
48+
{
49+
type: 'object',
50+
properties: {
51+
a: {
52+
type: 'string',
53+
},
54+
},
55+
required: ['a'],
56+
},
57+
{
58+
type: 'object',
59+
properties: {
60+
b: {
61+
type: 'string',
62+
},
63+
},
64+
required: ['b'],
65+
},
66+
],
67+
},
68+
});
69+
});
70+
71+
it('attempts to flatten nested and usage', () => {
72+
const schema = z.object({
73+
a: z.string(),
74+
});
75+
76+
const schema2 = z.object({
77+
b: z.string(),
78+
});
79+
80+
const schema3 = z.object({
81+
c: z.string(),
82+
});
83+
84+
const result = createIntersectionSchema(
85+
schema.and(schema2).and(schema3),
86+
createOutputState(),
87+
);
88+
89+
expect(result).toEqual<Schema>({
90+
type: 'schema',
91+
schema: {
92+
allOf: [
93+
{
94+
type: 'object',
95+
properties: {
96+
a: {
97+
type: 'string',
98+
},
99+
},
100+
required: ['a'],
101+
},
102+
{
103+
type: 'object',
104+
properties: {
105+
b: {
106+
type: 'string',
107+
},
108+
},
109+
required: ['b'],
110+
},
111+
{
112+
type: 'object',
113+
properties: {
114+
c: {
115+
type: 'string',
116+
},
117+
},
118+
required: ['c'],
119+
},
120+
],
121+
},
122+
});
123+
});
30124
});
+18-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { ZodIntersection, ZodTypeAny } from 'zod';
22

3+
import { isZodType } from '../../../zodType';
34
import {
45
type Schema,
56
type SchemaState,
@@ -15,18 +16,26 @@ export const createIntersectionSchema = <
1516
zodIntersection: ZodIntersection<T, U>,
1617
state: SchemaState,
1718
): Schema => {
18-
const left = createSchemaObject(zodIntersection._def.left, state, [
19-
'intersection left',
20-
]);
21-
const right = createSchemaObject(zodIntersection._def.right, state, [
22-
'intersection right',
23-
]);
24-
19+
const schemas = flattenIntersection(zodIntersection);
20+
const allOfs = schemas.map((schema, index) =>
21+
createSchemaObject(schema, state, [`intersection ${index}`]),
22+
);
2523
return {
2624
type: 'schema',
2725
schema: {
28-
allOf: [left.schema, right.schema],
26+
allOf: allOfs.map((schema) => schema.schema),
2927
},
30-
effects: flattenEffects([left.effects, right.effects]),
28+
effects: flattenEffects(allOfs.map((schema) => schema.effects)),
3129
};
3230
};
31+
32+
export const flattenIntersection = (zodType: ZodTypeAny): ZodTypeAny[] => {
33+
if (!isZodType(zodType, 'ZodIntersection')) {
34+
return [zodType];
35+
}
36+
37+
const leftSchemas = flattenIntersection(zodType._def.left);
38+
const rightSchemas = flattenIntersection(zodType._def.right);
39+
40+
return [...leftSchemas, ...rightSchemas];
41+
};

0 commit comments

Comments
 (0)