import { experimental_trpcMiddleware, TRPCError } from "@trpc/server"; import { and, desc, eq, inArray, notExists } from "drizzle-orm"; import { z } from "zod"; import { SqliteError } from "@lifetracker/db"; import { colors, calcInverseColor } from "@lifetracker/db/schema"; import { zColorSchema, ZColor } from "@lifetracker/shared/types/colors"; import type { Context } from "../index"; import { authedProcedure, router } from "../index"; function conditionFromInput(input: { colorId: string }, userId: string) { return and(eq(colors.id, input.colorId), eq(colors.userId, userId)); } async function createColor( input: ZColor, ctx: Context, ) { console.log("[TRPC Router] Begin Create Color"); return ctx.db.transaction(async (trx) => { try { const result = await trx .insert(colors) .values({ name: input.name, hexcode: input.hexcode, inverse: calcInverseColor(input.hexcode), userId: ctx.user!.id, }) .returning({ id: colors.id, name: colors.name, hexcode: colors.hexcode, }); return result[0]; } catch (e) { console.log(e); if (e instanceof SqliteError) { if (e.code == "SQLITE_CONSTRAINT_UNIQUE") { throw new TRPCError({ code: "BAD_REQUEST", message: "This color already exists", }); } } throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Something went wrong", }); } }); } export const colorsAppRouter = router({ list: authedProcedure .output(z.object({ colors: z.array( z.object({ id: z.string(), name: z.string(), hexcode: z.string(), numCategories: z.number(), }), ), })) .query(async ({ ctx }) => { const dbColors = await ctx.db .select({ id: colors.id, name: colors.name, hexcode: colors.hexcode, }) .from(colors); return { colors: dbColors.map(({ ...color }) => ({ ...color, numCategories: 0, })), }; }), create: authedProcedure .input(zColorSchema) .output( z.object({ id: z.string(), hexcode: z.string(), name: z.string(), }), ) .mutation(async ({ input, ctx }) => { return createColor(input, ctx); }), });