112 lines
3.3 KiB
TypeScript
112 lines
3.3 KiB
TypeScript
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";
|
|
import { titleCase } from "title-case";
|
|
|
|
function conditionFromInput(input: { colorName: string }, userId: string) {
|
|
return and(eq(titleCase(colors.name), titleCase(input.colorName)), eq(colors.userId, userId));
|
|
}
|
|
|
|
async function createColor(
|
|
input: ZColor,
|
|
ctx: Context,
|
|
) {
|
|
return ctx.db.transaction(async (trx) => {
|
|
|
|
try {
|
|
const result = await trx
|
|
.insert(colors)
|
|
.values({
|
|
name: titleCase(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(),
|
|
userId: z.string(),
|
|
}),
|
|
),
|
|
}))
|
|
.query(async ({ ctx }) => {
|
|
const dbColors = await ctx.db
|
|
.select({
|
|
id: colors.id,
|
|
name: colors.name,
|
|
hexcode: colors.hexcode,
|
|
userId: colors.userId,
|
|
})
|
|
.from(colors);
|
|
|
|
return {
|
|
colors: dbColors.map(({ ...color }) => ({
|
|
...color,
|
|
})),
|
|
};
|
|
}),
|
|
create: authedProcedure
|
|
.input(zColorSchema)
|
|
.output(
|
|
z.object({
|
|
id: z.string(),
|
|
hexcode: z.string(),
|
|
name: z.string(),
|
|
}),
|
|
)
|
|
.mutation(async ({ input, ctx }) => {
|
|
return createColor(input, ctx);
|
|
}),
|
|
delete: authedProcedure
|
|
.input(
|
|
z.object({
|
|
colorName: z.string(),
|
|
}),
|
|
)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const res = await ctx.db
|
|
.delete(colors)
|
|
.where(conditionFromInput(input, ctx.user.id));
|
|
if (res.changes == 0) {
|
|
throw new TRPCError({ code: "NOT_FOUND" });
|
|
}
|
|
}),
|
|
});
|