From 8a46ecb7373d6c5e7300861169ea51a7917cd2b4 Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Tue, 5 Mar 2024 13:11:06 +0000 Subject: refactor: Extract trpc logic into its package --- packages/trpc/index.ts | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 packages/trpc/index.ts (limited to 'packages/trpc/index.ts') diff --git a/packages/trpc/index.ts b/packages/trpc/index.ts new file mode 100644 index 00000000..a32eb871 --- /dev/null +++ b/packages/trpc/index.ts @@ -0,0 +1,57 @@ +import { db } from "@hoarder/db"; +import serverConfig from "@hoarder/shared/config"; +import { TRPCError, initTRPC } from "@trpc/server"; +import superjson from "superjson"; + +type User = { + id: string; + role: "admin" | "user" | null; +}; + +export type Context = { + user: User | null; + db: typeof db; +}; + +// Avoid exporting the entire t-object +// since it's not very descriptive. +// For instance, the use of a t variable +// is common in i18n libraries. +const t = initTRPC.context().create({ + transformer: superjson, +}); +export const createCallerFactory = t.createCallerFactory; +// Base router and procedure helpers +export const router = t.router; +export const procedure = t.procedure.use(function isDemoMode(opts) { + if (serverConfig.demoMode && opts.type == "mutation") { + throw new TRPCError({ + message: "Mutations are not allowed in demo mode", + code: "FORBIDDEN", + }); + } + return opts.next(); +}); +export const publicProcedure = procedure; + +export const authedProcedure = procedure.use(function isAuthed(opts) { + const user = opts.ctx.user; + + if (!user || !user.id) { + throw new TRPCError({ code: "UNAUTHORIZED" }); + } + + return opts.next({ + ctx: { + user, + }, + }); +}); + +export const adminProcedure = authedProcedure.use(function isAdmin(opts) { + const user = opts.ctx.user; + if (user.role != "admin") { + throw new TRPCError({ code: "FORBIDDEN" }); + } + return opts.next(opts); +}); -- cgit v1.2.3-70-g09d2