diff options
| author | MohamedBassem <me@mbassem.com> | 2024-03-05 13:11:06 +0000 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-03-05 13:11:06 +0000 |
| commit | 8a46ecb7373d6c5e7300861169ea51a7917cd2b4 (patch) | |
| tree | 4ad318c3b5fc8b7a74cba6d0e37b6ade24db829a /packages/trpc/routers/users.ts | |
| parent | 224aa38d5976523f213e2860b6addc7630d472ba (diff) | |
| download | karakeep-8a46ecb7373d6c5e7300861169ea51a7917cd2b4.tar.zst | |
refactor: Extract trpc logic into its package
Diffstat (limited to 'packages/trpc/routers/users.ts')
| -rw-r--r-- | packages/trpc/routers/users.ts | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/packages/trpc/routers/users.ts b/packages/trpc/routers/users.ts new file mode 100644 index 00000000..b5334f99 --- /dev/null +++ b/packages/trpc/routers/users.ts @@ -0,0 +1,93 @@ +import { zSignUpSchema } from "../types/users"; +import { adminProcedure, publicProcedure, router } from "../index"; +import { SqliteError } from "@hoarder/db"; +import { z } from "zod"; +import { hashPassword } from "../auth"; +import { TRPCError } from "@trpc/server"; +import { users } from "@hoarder/db/schema"; +import { count, eq } from "drizzle-orm"; + +export const usersAppRouter = router({ + create: publicProcedure + .input(zSignUpSchema) + .output( + z.object({ + id: z.string(), + name: z.string(), + email: z.string(), + role: z.enum(["user", "admin"]).nullable(), + }), + ) + .mutation(async ({ input, ctx }) => { + // TODO: This is racy, but that's probably fine. + const [{ count: userCount }] = await ctx.db + .select({ count: count() }) + .from(users); + try { + const result = await ctx.db + .insert(users) + .values({ + name: input.name, + email: input.email, + password: await hashPassword(input.password), + role: userCount == 0 ? "admin" : "user", + }) + .returning({ + id: users.id, + name: users.name, + email: users.email, + role: users.role, + }); + return result[0]; + } catch (e) { + if (e instanceof SqliteError) { + if (e.code == "SQLITE_CONSTRAINT_UNIQUE") { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Email is already taken", + }); + } + } + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: "Something went wrong", + }); + } + }), + list: adminProcedure + .output( + z.object({ + users: z.array( + z.object({ + id: z.string(), + name: z.string(), + email: z.string(), + role: z.enum(["user", "admin"]).nullable(), + }), + ), + }), + ) + .query(async ({ ctx }) => { + const users = await ctx.db.query.users.findMany({ + columns: { + id: true, + name: true, + email: true, + role: true, + }, + }); + return { users }; + }), + delete: adminProcedure + .input( + z.object({ + userId: z.string(), + }), + ) + .mutation(async ({ input, ctx }) => { + const res = await ctx.db.delete(users).where(eq(users.id, input.userId)); + if (res.changes == 0) { + throw new TRPCError({ code: "NOT_FOUND" }); + } + }), +}); |
