Prisma types and enums with trpc + zod
is it possible to use prisma types and enums with zod, instead of having to manually construct your prisma tables in your trpc router
1 Reply
model Recipe {
id String @id @default(cuid())
openedAt DateTime @default(now())
title String
description String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
steps Step[]
ingredients Ingredient[]
@@index([userId])
}
model Step {
id String @id @default(cuid())
step String
recipeId String
recipe Recipe @relation(fields: [recipeId], references: [id], onDelete: Cascade)
@@index([recipeId])
}
model Ingredient {
id String @id @default(cuid())
name String
recipeId String
recipe Recipe @relation(fields: [recipeId], references: [id], onDelete: Cascade)
measure Measurement
ammount Int
@@index([recipeId])
}
enum Measurement {
GRAM
KILOGRAM
MILLILITER
LITER
PIECE
POUND
OUNCE
TEASPOON
TABLESPOON
CUP
PINT
SLICE
}
model Recipe {
id String @id @default(cuid())
openedAt DateTime @default(now())
title String
description String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
steps Step[]
ingredients Ingredient[]
@@index([userId])
}
model Step {
id String @id @default(cuid())
step String
recipeId String
recipe Recipe @relation(fields: [recipeId], references: [id], onDelete: Cascade)
@@index([recipeId])
}
model Ingredient {
id String @id @default(cuid())
name String
recipeId String
recipe Recipe @relation(fields: [recipeId], references: [id], onDelete: Cascade)
measure Measurement
ammount Int
@@index([recipeId])
}
enum Measurement {
GRAM
KILOGRAM
MILLILITER
LITER
PIECE
POUND
OUNCE
TEASPOON
TABLESPOON
CUP
PINT
SLICE
}
update: protectedProcedure
.input(
z.object({
recipeId: z.string(),
title: z.string(),
description: z.string(),
steps: z.array(
z.object({
step: z.string(),
recipeId: z.string(),
id: z.string(),
}),
),
}),
)
.mutation(async ({ ctx, input }) => {
const recipeUser = await ctx.db.recipe.findUnique({
where: {
id: input.recipeId,
},
});
if (!recipeUser) {
return null;
}
if (ctx.session.user.id !== recipeUser.userId) {
return null;
}
const recipe = await ctx.db.recipe.update({
where: {
id: input.recipeId,
},
include: {
steps: true,
ingredients: true,
},
data: {
title: input.title,
description: input.description,
steps: {
updateMany: input.steps.map((step) => ({
where: {
id: step.id,
},
data: {
step: step.step,
},
})),
},
},
});
return recipe;
}),
update: protectedProcedure
.input(
z.object({
recipeId: z.string(),
title: z.string(),
description: z.string(),
steps: z.array(
z.object({
step: z.string(),
recipeId: z.string(),
id: z.string(),
}),
),
}),
)
.mutation(async ({ ctx, input }) => {
const recipeUser = await ctx.db.recipe.findUnique({
where: {
id: input.recipeId,
},
});
if (!recipeUser) {
return null;
}
if (ctx.session.user.id !== recipeUser.userId) {
return null;
}
const recipe = await ctx.db.recipe.update({
where: {
id: input.recipeId,
},
include: {
steps: true,
ingredients: true,
},
data: {
title: input.title,
description: input.description,
steps: {
updateMany: input.steps.map((step) => ({
where: {
id: step.id,
},
data: {
step: step.step,
},
})),
},
},
});
return recipe;
}),