zod-prisma-types
zod-prisma-types copied to clipboard
[Feature Request] Support for Nested Composite Types and Relations in MongoDB
I'm facing an issue with zod-prisma-types when using Prisma with MongoDB. In MongoDB, nested composite types are not relational; they are part of the same schema and should be treated as such. However, zod-prisma-types currently excludes these nested composite types, as if they were relational, which is not the case.
Additionally, even when composite types have nested composite types within them, zod-prisma-types does not generate Zod schemas correctly for these nested structures.
Could support be added to handle these nested composite types properly?
Example Prisma Schema
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
generator zod {
provider = "zod-prisma-types"
createRelationValuesTypes = true
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
profile Profile
posts Post[]
}
type Profile {
firstName String
address Address
}
type Address {
street String
city String
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
title String
}
Expected output
export const UserSchema = z.object({
id: z.string(),
profile: z.lazy(() => ProfileSchema),
})
export const ProfileSchema = z.object({
firstName: z.string(),
address: z.lazy(() => AddressSchema),
})
export const AddressSchema = z.object({
street: z.string(),
city: z.string(),
})
export const PostSchema = z.object({
id: z.string(),
authorId: z.string(),
title: z.string(),
})
export const UserWithRelationsSchema: z.ZodType<UserWithRelations> = UserSchema.merge(
z.object({
posts: z.lazy(() => PostsSchema), // PostsSchema is schema for Modal not composite type
}),
)
export const PostWithRelationsSchema: z.ZodType<PostWithRelations> = PostSchema.merge(
z.object({
author: z.lazy(() => UserSchema), // UserSchema is schema for Modal not composite type
}),
)
Resulting output
export const UserSchema = z.object({
id: z.string(),
})
export type User = z.infer<typeof UserSchema>
export type UserRelations = {
profile: Profile
posts: PostWithRelations[]
}
export type UserWithRelations = z.infer<typeof UserSchema> & UserRelations
export const UserWithRelationsSchema: z.ZodType<UserWithRelations> = UserSchema.merge(
z.object({
profile: z.lazy(() => ProfileSchema),
posts: z.lazy(() => PostWithRelationsSchema).array(),
}),
)
export const PostSchema = z.object({
id: z.string(),
authorId: z.string(),
title: z.string(),
})
export type Post = z.infer<typeof PostSchema>
export type PostRelations = {
author: UserWithRelations
}
export type PostWithRelations = z.infer<typeof PostSchema> & PostRelations
export const PostWithRelationsSchema: z.ZodType<PostWithRelations> = PostSchema.merge(
z.object({
author: z.lazy(() => UserWithRelationsSchema),
}),
)
export const ProfileSchema = z.object({
firstName: z.string(),
})
export type Profile = z.infer<typeof ProfileSchema>
export type ProfileRelations = {
address: Address
}
export type ProfileWithRelations = z.infer<typeof ProfileSchema> & ProfileRelations
export const ProfileWithRelationsSchema: z.ZodType<ProfileWithRelations> = ProfileSchema.merge(
z.object({
address: z.lazy(() => AddressSchema),
}),
)
export const AddressSchema = z.object({
street: z.string(),
city: z.string(),
})
export type Address = z.infer<typeof AddressSchema>
Package versions:
- zod: 3.24.2
- prisma: 6.4.0
- zod-prisma-types: 3.2.4