How to use Prisma model type in tRPC mutation w/ Zod

I have some models defined in my schema.prisma file. Let's say they look like this:
model Art {
id String @id @default(cuid())
// Some other fields
creators Creator[]
}

model Creator {
id String @id @default(cuid())
creatorId String
artId String
art Art @relation(fields: [artId], references: [id])
}
model Art {
id String @id @default(cuid())
// Some other fields
creators Creator[]
}

model Creator {
id String @id @default(cuid())
creatorId String
artId String
art Art @relation(fields: [artId], references: [id])
}
I am using a tRPC mutation to create an "Art" in my Planetscale database. So, since I'm using Zod, I am doing something like this:
create: privateProcedure
.input(
z.object({
// Some other fields
creators: (this is where I'm confused)
})
)
.mutation(async ({ input }) => {
const artistId = ctx.userId;

const art = await ctx.prisma.art.create({
data: {
// Some other fields
creators: input.creators,
},
});

return art;
}),
create: privateProcedure
.input(
z.object({
// Some other fields
creators: (this is where I'm confused)
})
)
.mutation(async ({ input }) => {
const artistId = ctx.userId;

const art = await ctx.prisma.art.create({
data: {
// Some other fields
creators: input.creators,
},
});

return art;
}),
I know I can get the Creator type from Prisma, but I don't know how to tell Zod to expect those properties as the input so that the tRPC procedure will run. I hope I'm explaining this ok because it's kinda hard to put into words lol
4 Replies
peterkyle01
peterkyle0117mo ago
You can nest objects in zod like: .input( z.object({ art: z.object({ id:z.string(), }), creators: z.object({ id: z.string(), //...like that }) }) )
zendev
zendev17mo ago
Ok just gave this a try but TS still throwing a Type error. Here's what it's saying: Type '{ collaboratorId: string; songId: string; }[]' is not assignable to type 'CreatorUncheckedCreateNestedManyWithoutArtInput | CreatorCreateNestedManyWithoutArtInput | undefined'.ts(2322) This is making me think that there should be a way to get the type called "CreatorCreateNestedManyWithoutArtInput" and use it. Also the type itself makes it sound like it's being created without Art input, even though it is? Idk honestly very confused by it all.
ray1sx
ray1sx17mo ago
You need to define the creators object on the input and then use it when calling the mutation property as you are doing. Try for example:
creators: z.object({
creatorId: z.string(),
artId: z.string(),
})
creators: z.object({
creatorId: z.string(),
artId: z.string(),
})
If I'm not wrong that is what your Prisma Schema is expecting It is the same @peterkyle01 is saying
zendev
zendev17mo ago
Ok I think I might've figured out what was going wrong - in the mutation I wasn't using the create property. So now in the input it reads:
creators: z.object({
creatorId: z.string(),
artId: z.string(),
})
creators: z.object({
creatorId: z.string(),
artId: z.string(),
})
And in the mutation it reads:
creators: {
create: [
input.creators
]
},
creators: {
create: [
input.creators
]
},
But I'm not including the relation field from the Prisma model in any way - is that necessary? Will it fill in automatically? About to test btw so will update shortly.
Want results from more Discord servers?
Add your server