From a8b5b4c678cdcfabb2e8dbcd9850ea55bc04b23a Mon Sep 17 00:00:00 2001 From: Rishikesh Kanabar Date: Sat, 3 Feb 2024 10:51:06 -0500 Subject: [PATCH 1/4] feat(trpc): create profile router --- src/server/api/root.ts | 5 +- src/server/api/routers/.gitkeep | 0 src/server/api/routers/profileRouter.ts | 78 +++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) delete mode 100644 src/server/api/routers/.gitkeep create mode 100644 src/server/api/routers/profileRouter.ts diff --git a/src/server/api/root.ts b/src/server/api/root.ts index 32643bb..dfc3e92 100644 --- a/src/server/api/root.ts +++ b/src/server/api/root.ts @@ -1,11 +1,14 @@ import { createTRPCRouter } from "~/server/api/trpc"; +import { profileRouter } from "~/server/api/routers/profileRouter"; /** * This is the primary router for your server. * * All routers added in /api/routers should be manually added here. */ -export const appRouter = createTRPCRouter({}); +export const appRouter = createTRPCRouter({ + profile: profileRouter, +}); // export type definition of API export type AppRouter = typeof appRouter; diff --git a/src/server/api/routers/.gitkeep b/src/server/api/routers/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/server/api/routers/profileRouter.ts b/src/server/api/routers/profileRouter.ts new file mode 100644 index 0000000..99f7b6d --- /dev/null +++ b/src/server/api/routers/profileRouter.ts @@ -0,0 +1,78 @@ +import { z } from "zod"; +import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc"; + +export const profileRouter = createTRPCRouter({ + list: protectedProcedure.query(async ({ ctx }) => { + return await ctx.db.profile.findMany(); + }), + getCurrentUser: protectedProcedure.query(async ({ ctx }) => { + return await ctx.db.profile.findMany({ + where: { + userId: ctx.session.user.id, + }, + }); + }), + create: protectedProcedure + .input( + z.object({ + firstName: z.string(), + lastName: z.string(), + major: z.string(), + minor: z.string().optional(), + // TODO: Update this to something more robust + graduationYear: z.number().min(2024).max(2030), + graduationMonth: z.number().min(1).max(12), + }), + ) + .mutation(async ({ ctx, input }) => { + return await ctx.db.profile.create({ + data: { + firstName: input.firstName, + lastName: input.lastName, + major: input.major, + minor: input.minor, + graduationYear: input.graduationYear, + graduationMonth: input.graduationMonth, + userId: ctx.session.user.id, + }, + }); + }), + update: protectedProcedure + .input( + z.object({ + id: z.string(), + data: z.object({ + firstName: z.string().optional(), + lastName: z.string().optional(), + major: z.string().optional(), + minor: z.string().optional(), + // TODO: Update this to something more robust + graduationYear: z.number().min(2024).max(2030).optional(), + graduationMonth: z.number().min(1).max(12).optional(), + }), + }), + ) + .mutation(async ({ ctx, input }) => { + return await ctx.db.profile.update({ + where: { + id: input.id, + }, + data: { + ...input.data, + }, + }); + }), + delete: protectedProcedure + .input( + z.object({ + id: z.string(), + }), + ) + .mutation(async ({ ctx, input }) => { + return await ctx.db.profile.delete({ + where: { + id: input.id, + }, + }); + }), +}); From 4dd7aad8226124cc5af26968cd031fd959273c0b Mon Sep 17 00:00:00 2001 From: Rishikesh Kanabar Date: Sun, 4 Feb 2024 11:08:05 -0500 Subject: [PATCH 2/4] fix(trpc): add basic error handling --- .../routers/{profileRouter.ts => profile.ts} | 73 +++++++++++++++++-- 1 file changed, 65 insertions(+), 8 deletions(-) rename src/server/api/routers/{profileRouter.ts => profile.ts} (50%) diff --git a/src/server/api/routers/profileRouter.ts b/src/server/api/routers/profile.ts similarity index 50% rename from src/server/api/routers/profileRouter.ts rename to src/server/api/routers/profile.ts index 99f7b6d..7a881e6 100644 --- a/src/server/api/routers/profileRouter.ts +++ b/src/server/api/routers/profile.ts @@ -1,10 +1,43 @@ +import { TRPCError } from "@trpc/server"; import { z } from "zod"; -import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc"; +import { + createTRPCRouter, + protectedProcedure, + publicProcedure, +} from "~/server/api/trpc"; + +const MAX_GRADUATION_LENGTH = 6; +const MONTH_LB = 1; +const MONTH_UB = 12; +const YEAR_LB = new Date().getFullYear(); +const YEAR_UB = YEAR_LB + MAX_GRADUATION_LENGTH; export const profileRouter = createTRPCRouter({ - list: protectedProcedure.query(async ({ ctx }) => { + list: publicProcedure.query(async ({ ctx }) => { return await ctx.db.profile.findMany(); }), + getById: publicProcedure + .input( + z.object({ + id: z.string(), + }), + ) + .query(async ({ ctx, input }) => { + const profile = await ctx.db.profile.findUnique({ + where: { + id: input.id, + }, + }); + + if (!profile) { + throw new TRPCError({ + code: "NOT_FOUND", + message: `Profile with ID ${input.id} not found.`, + }); + } + + return profile; + }), getCurrentUser: protectedProcedure.query(async ({ ctx }) => { return await ctx.db.profile.findMany({ where: { @@ -19,9 +52,8 @@ export const profileRouter = createTRPCRouter({ lastName: z.string(), major: z.string(), minor: z.string().optional(), - // TODO: Update this to something more robust - graduationYear: z.number().min(2024).max(2030), - graduationMonth: z.number().min(1).max(12), + graduationYear: z.number().min(YEAR_LB).max(YEAR_UB), + graduationMonth: z.number().min(MONTH_LB).max(MONTH_UB), }), ) .mutation(async ({ ctx, input }) => { @@ -46,13 +78,25 @@ export const profileRouter = createTRPCRouter({ lastName: z.string().optional(), major: z.string().optional(), minor: z.string().optional(), - // TODO: Update this to something more robust - graduationYear: z.number().min(2024).max(2030).optional(), - graduationMonth: z.number().min(1).max(12).optional(), + graduationYear: z.number().min(YEAR_LB).max(YEAR_UB).optional(), + graduationMonth: z.number().min(MONTH_LB).max(MONTH_UB).optional(), }), }), ) .mutation(async ({ ctx, input }) => { + const profile = await ctx.db.profile.findUnique({ + where: { + id: input.id, + }, + }); + + if (!profile) { + throw new TRPCError({ + code: "NOT_FOUND", + message: `Profile with ID ${input.id} not found.`, + }); + } + return await ctx.db.profile.update({ where: { id: input.id, @@ -69,6 +113,19 @@ export const profileRouter = createTRPCRouter({ }), ) .mutation(async ({ ctx, input }) => { + const profile = await ctx.db.profile.findUnique({ + where: { + id: input.id, + }, + }); + + if (!profile) { + throw new TRPCError({ + code: "NOT_FOUND", + message: `Profile with ID ${input.id} not found.`, + }); + } + return await ctx.db.profile.delete({ where: { id: input.id, From b0d978f51a3ef32c9951faeca2d023b980fd8e43 Mon Sep 17 00:00:00 2001 From: Rishikesh Kanabar Date: Sun, 4 Feb 2024 11:13:37 -0500 Subject: [PATCH 3/4] fix(trpc): fix file path in root router --- src/server/api/root.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/api/root.ts b/src/server/api/root.ts index dfc3e92..15b503e 100644 --- a/src/server/api/root.ts +++ b/src/server/api/root.ts @@ -1,5 +1,5 @@ import { createTRPCRouter } from "~/server/api/trpc"; -import { profileRouter } from "~/server/api/routers/profileRouter"; +import { profileRouter } from "~/server/api/routers/profile"; /** * This is the primary router for your server. From 46f2cccb2007c8d3824b48c6f4fe79957f6dbebe Mon Sep 17 00:00:00 2001 From: Rishikesh Kanabar Date: Sun, 4 Feb 2024 12:00:18 -0500 Subject: [PATCH 4/4] refactor(trpc): use spread operator --- src/server/api/routers/profile.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/server/api/routers/profile.ts b/src/server/api/routers/profile.ts index 7a881e6..3a62118 100644 --- a/src/server/api/routers/profile.ts +++ b/src/server/api/routers/profile.ts @@ -59,12 +59,7 @@ export const profileRouter = createTRPCRouter({ .mutation(async ({ ctx, input }) => { return await ctx.db.profile.create({ data: { - firstName: input.firstName, - lastName: input.lastName, - major: input.major, - minor: input.minor, - graduationYear: input.graduationYear, - graduationMonth: input.graduationMonth, + ...input, userId: ctx.session.user.id, }, });