Skip to content
This repository was archived by the owner on Nov 19, 2024. It is now read-only.

Commit 5af397a

Browse files
committed
Allow coercion when given union of coercible values
1 parent d1eab87 commit 5af397a

File tree

8 files changed

+325
-93
lines changed

8 files changed

+325
-93
lines changed

package-lock.json

+133-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"superjson": "^1.12.3",
7070
"ts-jest": "^29.1.0",
7171
"ts-node": "^10.9.1",
72-
"typescript": "^5.0.4"
72+
"typescript": "^5.0.4",
73+
"zod": "^3.22.4"
7374
}
7475
}

src/adapters/node-http/core.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { normalizePath } from '../../utils/path';
2020
import { getInputOutputParsers } from '../../utils/procedure';
2121
import {
2222
instanceofZodTypeCoercible,
23+
instanceofZodTypeKind,
2324
instanceofZodTypeLikeVoid,
2425
instanceofZodTypeObject,
2526
unwrapZodType,
@@ -118,7 +119,14 @@ export const createOpenApiNodeHttpHandler = <
118119
if (instanceofZodTypeObject(unwrappedSchema)) {
119120
Object.values(unwrappedSchema.shape).forEach((shapeSchema) => {
120121
const unwrappedShapeSchema = unwrapZodType(shapeSchema, false);
121-
if (instanceofZodTypeCoercible(unwrappedShapeSchema)) {
122+
123+
if (instanceofZodTypeKind(unwrappedShapeSchema, z.ZodFirstPartyTypeKind.ZodUnion)) {
124+
unwrappedShapeSchema.options.forEach((option) => {
125+
if (instanceofZodTypeCoercible(option)) {
126+
option._def.coerce = true;
127+
}
128+
});
129+
} else if (instanceofZodTypeCoercible(unwrappedShapeSchema)) {
122130
unwrappedShapeSchema._def.coerce = true;
123131
}
124132
});

src/generator/paths.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,11 @@ export const getOpenApiPathsObject = (
9494
) || []),
9595
],
9696
}),
97-
responses: getResponsesObject(outputParser, openapi.example?.response, openapi.responseHeaders),
97+
responses: getResponsesObject(
98+
outputParser,
99+
openapi.example?.response,
100+
openapi.responseHeaders,
101+
),
98102
...(openapi.deprecated ? { deprecated: openapi.deprecated } : {}),
99103
},
100104
};

src/generator/schema.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ export const errorResponseObject: OpenAPIV3.ResponseObject = {
189189
export const getResponsesObject = (
190190
schema: unknown,
191191
example: Record<string, any> | undefined,
192-
headers: Record<string, OpenAPIV3.HeaderObject | OpenAPIV3.ReferenceObject> | undefined
192+
headers: Record<string, OpenAPIV3.HeaderObject | OpenAPIV3.ReferenceObject> | undefined,
193193
): OpenAPIV3.ResponsesObject => {
194194
if (!instanceofZodType(schema)) {
195195
throw new TRPCError({

src/utils/zod.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export const instanceofZodType = (type: any): type is z.ZodTypeAny => {
77
export const instanceofZodTypeKind = <Z extends z.ZodFirstPartyTypeKind>(
88
type: z.ZodTypeAny,
99
zodTypeKind: Z,
10-
): type is InstanceType<typeof z[Z]> => {
10+
): type is InstanceType<(typeof z)[Z]> => {
1111
return type?._def?.typeName === zodTypeKind;
1212
};
1313

@@ -106,6 +106,13 @@ export type ZodTypeCoercible = z.ZodNumber | z.ZodBoolean | z.ZodBigInt | z.ZodD
106106

107107
export const instanceofZodTypeCoercible = (_type: z.ZodTypeAny): _type is ZodTypeCoercible => {
108108
const type = unwrapZodType(_type, false);
109+
110+
if (instanceofZodTypeKind(type, z.ZodFirstPartyTypeKind.ZodUnion)) {
111+
return type._def.options.every(
112+
(option) => instanceofZodTypeLikeString(option) || instanceofZodTypeCoercible(option),
113+
);
114+
}
115+
109116
return (
110117
instanceofZodTypeKind(type, z.ZodFirstPartyTypeKind.ZodNumber) ||
111118
instanceofZodTypeKind(type, z.ZodFirstPartyTypeKind.ZodBoolean) ||

test/adapters/standalone.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,7 @@ describe('standalone adapter', () => {
11941194
// @ts-expect-error - hack to disable zodSupportsCoerce
11951195
// eslint-disable-next-line import/namespace
11961196
zodUtils.zodSupportsCoerce = false;
1197+
11971198
{
11981199
const appRouter = t.router({
11991200
plusOne: t.procedure
@@ -1225,6 +1226,7 @@ describe('standalone adapter', () => {
12251226

12261227
close();
12271228
}
1229+
12281230
// @ts-expect-error - hack to re-enable zodSupportsCoerce
12291231
// eslint-disable-next-line import/namespace
12301232
zodUtils.zodSupportsCoerce = true;

0 commit comments

Comments
 (0)