Last active
June 14, 2024 10:13
-
-
Save itsRems/49e470905e9a989c873c0b9403a01d57 to your computer and use it in GitHub Desktop.
Transforms zod objects into prisma-compatible `select` objects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { z } from "zod"; | |
export type ZodPrismaSelectInnerMapper<T extends z.ZodTypeAny> = | |
T extends z.ZodObject<infer Shape> | |
? { | |
select: { | |
[K in keyof Shape]: ZodPrismaSelectInnerMapper<Shape[K]>; | |
}; | |
} | |
: T extends z.ZodArray<infer Item> | |
? ZodPrismaSelectInnerMapper<Item> | |
: true; | |
export type ZodPrismaSelectMapper<T extends z.ZodTypeAny> = | |
T extends z.ZodObject<infer Shape> | |
? { | |
[K in keyof Shape]: ZodPrismaSelectInnerMapper<Shape[K]>; | |
} | |
: T extends z.ZodArray<infer Item> | |
? ZodPrismaSelectInnerMapper<Item> | |
: true; | |
// Deeply extracts the inner type of a ZodOptional or ZodNullable | |
function extractInnerType(type: z.ZodTypeAny): z.ZodTypeAny { | |
if ( | |
type instanceof z.ZodOptional || | |
type instanceof z.ZodNullable || | |
type._def.typeName === "ZodOptional" || | |
type._def.typeName === "ZodNullable" | |
) { | |
return extractInnerType(type._def.innerType); | |
} | |
return type; | |
} | |
// Takes a zod schema and transforms all its fields to a prisma-compatible `select` | |
export function zodToPrismaSelect<T extends z.ZodType<any, any>>( | |
schema: T, | |
): ZodPrismaSelectMapper<T> { | |
const fields = schema._def.shape(); | |
const result: any = {}; | |
for (const key in fields) { | |
// Extract the inner type of the field (in case it's wrapped in a ZodOptional or ZodNullable) | |
const field = extractInnerType(fields[key]); | |
if ( | |
field._def.typeName === "ZodArray" && | |
field._def.type._def.typeName === "ZodObject" | |
) { | |
// We've hit an array of objects | |
result[key] = { | |
select: zodToPrismaSelect(field._def.type), | |
}; | |
} else if (field._def.typeName === "ZodObject") { | |
// We've hit an object | |
result[key] = { | |
select: zodToPrismaSelect(field), | |
}; | |
} else { | |
// We've hit a field | |
result[key] = true; | |
} | |
} | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment