FinnF
tRPC2y ago
7 replies
Finn

How to properly handle Prima selects/includes with tRPC?

Hello,
my understanding of optimizing procedures to be the most efficient would be to enable one procedure to handle different use-cases. So I'd like a procedure like getById to take a list that allows all possible attributes from the prisma models and optionally a list of models to include.

Currently, I define a list of all attributes on a global level for each router, that includes all includable Fields (I'd then do the same for the selectable fields). But that - even with just the includable fields - ends in this madness:

const includableFields = z.enum([
    "comments",
    "readingProgress",
    "novelInsights",
    "author",
    "userLists",
    // ...
]);

export const novelRouter = createTRPCRouter({
    getById: privateProcedure
        .input(
            z.object({
                id: z.string(),
                include: z.array(includableFields).optional(),
            })
        )
        .query(async ({ ctx, input }) => {
            return await ctx.db.novel.findUnique({
                where: {
                    id: input.id,
                },
                include: {
                    comments: input.include?.includes("comments") ?? false,
                    readingProgress:
                        input.include?.includes("readingProgress") ?? false,
                    novelInsights:
                        input.include?.includes("novelInsights") ?? false,
                    author: input.include?.includes("author") ?? false,
                    userLists: input.include?.includes("userLists") ?? false,
                    chapters: input.include?.includes("chapters") ?? false,
                    genre: input.include?.includes("genre") ?? false,
                    customInsights:
                        input.include?.includes("customInsights") ?? false,
                },
            });
        }),
});


The problem I have with this, is that it looks horrendous and needs to be manually adjusted everytime the schema changes
Solution
const includableFields = z.enum([
    "comments",
    "readingProgress",
    "novelInsights",
    "author",
    "userLists",
    // ...
]);

export const novelRouter = createTRPCRouter({
    getById: privateProcedure
        .input(
            z.object({
                id: z.string(),
                include: z.record(includableFields, z.boolean()).default({}),
            })
        )
        .query(async ({ ctx, input }) => {
            return await ctx.db.novel.findUnique({
                where: {
                    id: input.id,
                },
                include: input.include,
            });
        }),
});
Was this page helpful?