Skip to content

Commit d068f68

Browse files
timmissetTim Misset
andauthored
feat(zod): revert #1907 to not use discriminatedUnion (#2118)
* #2085 revert changes from PR1907, except for cleanup performed in that PR * #2085 formatter --------- Co-authored-by: Tim Misset <[email protected]>
1 parent 44c8cf4 commit d068f68

File tree

2 files changed

+6
-261
lines changed

2 files changed

+6
-261
lines changed

packages/zod/src/index.ts

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ export const generateZodValidationSchemaDefinition = (
351351
case 'object':
352352
default: {
353353
if (schema.allOf || schema.oneOf || schema.anyOf) {
354-
let separator = schema.allOf
354+
const separator = schema.allOf
355355
? 'allOf'
356356
: schema.oneOf
357357
? 'oneOf'
@@ -362,20 +362,10 @@ export const generateZodValidationSchemaDefinition = (
362362
| ReferenceObject
363363
)[];
364364

365-
if (
366-
(schema.oneOf || schema.anyOf) &&
367-
schema.discriminator &&
368-
schema.discriminator.propertyName
369-
) {
370-
// store the discriminator property name in the separator to be used when building the zod schema
371-
// adding discriminator property name is already handled via the deference function
372-
separator = `discriminator__${schema.discriminator.propertyName}`;
373-
}
374-
375365
functions.push([
376366
separator,
377-
schemas.map((schema) => {
378-
return generateZodValidationSchemaDefinition(
367+
schemas.map((schema) =>
368+
generateZodValidationSchemaDefinition(
379369
schema as SchemaObject,
380370
context,
381371
camel(name),
@@ -384,8 +374,8 @@ export const generateZodValidationSchemaDefinition = (
384374
{
385375
required: true,
386376
},
387-
);
388-
}),
377+
),
378+
),
389379
]);
390380
break;
391381
}
@@ -558,18 +548,7 @@ export const parseZodValidationSchemaDefinition = (
558548
'',
559549
);
560550
}
561-
if (fn.startsWith('discriminator__')) {
562-
const [, propertyName] = fn.split('discriminator__');
563-
const typeSchemas = args.map(
564-
({ functions }: { functions: [string, any][]; consts: string[] }) => {
565-
const schemaFunctions = functions.map(parseProperty).join('');
566-
return schemaFunctions;
567-
},
568-
);
569-
return `zod.discriminatedUnion('${propertyName}', [${typeSchemas.join(
570-
',',
571-
)}])`;
572-
} else if (fn === 'oneOf' || fn === 'anyOf') {
551+
if (fn === 'oneOf' || fn === 'anyOf') {
573552
return args.reduce(
574553
(
575554
acc: string,

packages/zod/src/zod.test.ts

Lines changed: 0 additions & 234 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,240 +1160,6 @@ describe('generatePartOfSchemaGenerateZod', () => {
11601160
});
11611161
});
11621162

1163-
const apiSchemaWithDiscriminator: GeneratorOptions = {
1164-
pathRoute: '/dogs',
1165-
context: {
1166-
specKey: 'dog',
1167-
specs: {
1168-
dog: {
1169-
openapi: '3.0.0',
1170-
info: {
1171-
version: '1.0.0',
1172-
title: 'Dogs',
1173-
},
1174-
paths: {
1175-
'/dogs': {
1176-
get: {
1177-
summary: 'List all dogs',
1178-
operationId: 'listDogs',
1179-
tags: ['dogs'],
1180-
responses: {
1181-
'200': {
1182-
description: 'A paged array of dogs',
1183-
content: {
1184-
'application/json': {
1185-
schema: {
1186-
$ref: '#/components/schemas/Dogs',
1187-
},
1188-
},
1189-
},
1190-
},
1191-
},
1192-
},
1193-
},
1194-
},
1195-
components: {
1196-
schemas: {
1197-
Dogs: {
1198-
type: 'array',
1199-
items: {
1200-
$ref: '#/components/schemas/Dog',
1201-
},
1202-
},
1203-
Dog: {
1204-
type: 'object',
1205-
oneOf: [
1206-
{
1207-
$ref: '#/components/schemas/Labradoodle',
1208-
},
1209-
{
1210-
$ref: '#/components/schemas/Dachshund',
1211-
},
1212-
],
1213-
required: ['type'],
1214-
properties: {
1215-
barksPerMinute: {
1216-
type: 'integer',
1217-
},
1218-
},
1219-
discriminator: {
1220-
propertyName: 'breed',
1221-
mapping: {
1222-
Labradoodle: '#/components/schemas/Labradoodle',
1223-
Dachshund: '#/components/schemas/Dachshund',
1224-
},
1225-
},
1226-
},
1227-
Labradoodle: {
1228-
type: 'object',
1229-
required: ['cuteness'],
1230-
properties: {
1231-
cuteness: {
1232-
type: 'integer',
1233-
},
1234-
// in the real runner breed is added by getApiSchemas in import-open-api.ts, inferred from the discriminator
1235-
breed: {
1236-
type: 'string',
1237-
enum: ['Labradoodle'],
1238-
},
1239-
},
1240-
},
1241-
Dachshund: {
1242-
type: 'object',
1243-
required: ['length'],
1244-
properties: {
1245-
length: {
1246-
type: 'integer',
1247-
},
1248-
// in the real runner breed is added by getApiSchemas in import-open-api.ts, inferred from the discriminator
1249-
breed: {
1250-
type: 'string',
1251-
enum: ['Labradoodle'],
1252-
},
1253-
},
1254-
},
1255-
},
1256-
},
1257-
},
1258-
},
1259-
output: {
1260-
override: {
1261-
zod: {
1262-
generateEachHttpStatus: false,
1263-
},
1264-
},
1265-
},
1266-
},
1267-
} as const;
1268-
1269-
describe('generateDiscriminatedUnionZod', () => {
1270-
it('generates a discriminatedUnion zod schema', async () => {
1271-
const result = await generateZod(
1272-
{
1273-
pathRoute: '/dogs',
1274-
verb: 'get',
1275-
operationName: 'test',
1276-
override: {
1277-
zod: {
1278-
strict: {
1279-
param: false,
1280-
body: false,
1281-
response: false,
1282-
query: false,
1283-
header: false,
1284-
},
1285-
generate: {
1286-
param: true,
1287-
body: true,
1288-
response: true,
1289-
query: true,
1290-
header: true,
1291-
},
1292-
coerce: {
1293-
param: false,
1294-
body: false,
1295-
response: false,
1296-
query: false,
1297-
header: false,
1298-
},
1299-
},
1300-
},
1301-
},
1302-
apiSchemaWithDiscriminator,
1303-
{},
1304-
);
1305-
expect(result.implementation).toBe(
1306-
`export const testResponseItem = zod.discriminatedUnion('breed', [zod.object({\n "cuteness": zod.number(),\n "breed": zod.enum(['Labradoodle']).optional()\n}),zod.object({\n "length": zod.number(),\n "breed": zod.enum(['Labradoodle']).optional()\n})])\nexport const testResponse = zod.array(testResponseItem)\n\n`,
1307-
);
1308-
expect(result.implementation).not.toContain('.or(zod.object');
1309-
});
1310-
it('generated discriminatedUnion zod schema strict setting', async () => {
1311-
const result = await generateZod(
1312-
{
1313-
pathRoute: '/dogs',
1314-
verb: 'get',
1315-
operationName: 'test',
1316-
override: {
1317-
zod: {
1318-
strict: {
1319-
param: true,
1320-
body: true,
1321-
response: true,
1322-
query: true,
1323-
header: true,
1324-
},
1325-
generate: {
1326-
param: true,
1327-
body: true,
1328-
response: true,
1329-
query: true,
1330-
header: true,
1331-
},
1332-
coerce: {
1333-
param: false,
1334-
body: false,
1335-
response: false,
1336-
query: false,
1337-
header: false,
1338-
},
1339-
},
1340-
},
1341-
},
1342-
apiSchemaWithDiscriminator,
1343-
{},
1344-
);
1345-
expect(result.implementation).toBe(
1346-
`export const testResponseItem = zod.discriminatedUnion('breed', [zod.object({\n "cuteness": zod.number(),\n "breed": zod.enum(['Labradoodle']).optional()\n}).strict(),zod.object({\n "length": zod.number(),\n "breed": zod.enum(['Labradoodle']).optional()\n}).strict()])\nexport const testResponse = zod.array(testResponseItem)\n\n`,
1347-
);
1348-
});
1349-
it('does not generate a discriminatedUnion zod schema when discriminator is absent', async () => {
1350-
const schemaWithoutDiscriminator = { ...apiSchemaWithDiscriminator };
1351-
const dogSchema = schemaWithoutDiscriminator.context.specs['dog']
1352-
.components!.schemas!['Dog'] as SchemaObject;
1353-
delete dogSchema.discriminator;
1354-
const result = await generateZod(
1355-
{
1356-
pathRoute: '/dogs',
1357-
verb: 'get',
1358-
operationName: 'test',
1359-
override: {
1360-
zod: {
1361-
strict: {
1362-
param: false,
1363-
body: false,
1364-
response: false,
1365-
query: false,
1366-
header: false,
1367-
},
1368-
generate: {
1369-
param: true,
1370-
body: true,
1371-
response: true,
1372-
query: true,
1373-
header: true,
1374-
},
1375-
coerce: {
1376-
param: false,
1377-
body: false,
1378-
response: false,
1379-
query: false,
1380-
header: false,
1381-
},
1382-
},
1383-
},
1384-
},
1385-
apiSchemaWithDiscriminator,
1386-
{},
1387-
);
1388-
expect(result.implementation).toBe(
1389-
`export const testResponseItem = zod.object({\n "cuteness": zod.number(),\n "breed": zod.enum(['Labradoodle']).optional()\n}).or(zod.object({\n "length": zod.number(),\n "breed": zod.enum(['Labradoodle']).optional()\n}))\nexport const testResponse = zod.array(testResponseItem)\n\n`,
1390-
);
1391-
expect(result.implementation).not.toContain(
1392-
"zod.discriminatedUnion('breed'",
1393-
);
1394-
});
1395-
});
1396-
13971163
describe('parsePrefixItemsArrayAsTupleZod', () => {
13981164
it('generates correctly', async () => {
13991165
const arrayWithPrefixItemsSchema: SchemaObject31 = {

0 commit comments

Comments
 (0)