Track and save on groceries

feat(backend): implement CRUD for stores

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>

+37 -8
+37 -8
apps/backend/src/impl/stores.ts
··· 1 1 import { ORPCError } from "@orpc/contract"; 2 2 import { os } from "./base.js"; 3 3 import { storesTable } from "@cherries-app/db"; 4 - import { asc, count, gt } from "drizzle-orm"; 4 + import { asc, count, eq, gt } from "drizzle-orm"; 5 + import assert from "assert"; 5 6 6 7 export const listStores = os.stores.list.handler( 7 8 async ({ input: { query }, context: { db } }) => { ··· 25 26 }, 26 27 ); 27 28 28 - export const getStore = os.stores.get.handler(({ input }) => { 29 - throw new ORPCError("NOT_FOUND", { 30 - message: `Store ${input.params.id} not found`, 31 - }); 29 + export const getStore = os.stores.get.handler(async ({ input: { params }, context: { db } }) => { 30 + const store = await db 31 + .select() 32 + .from(storesTable) 33 + .where(eq(storesTable.id, params.id)); 34 + 35 + if (store.length < 1) { 36 + throw new ORPCError("NOT_FOUND", { 37 + message: `Store ${params.id} not found`, 38 + }); 39 + } 40 + 41 + return { 42 + status: 200, 43 + body: store[0], 44 + }; 32 45 }); 33 46 34 - export const createStore = os.stores.create.handler(() => { 35 - throw new Error(); 47 + export const createStore = os.stores.create.handler(async ({ input: { body }, context: { db } }) => { 48 + const store = await db 49 + .insert(storesTable) 50 + .values([ 51 + body 52 + ]) 53 + .returning(); 54 + 55 + assert(store.length > 0, "Inserted store was returned"); 56 + 57 + return { 58 + status: 201, 59 + body: store[0], 60 + } 36 61 }); 37 62 38 - export const deleteStore = os.stores.delete.handler(() => { 63 + export const deleteStore = os.stores.delete.handler(async ({ input: { params }, context: { db } }) => { 64 + await db 65 + .delete(storesTable) 66 + .where(eq(storesTable.id, params.id)); 67 + 39 68 return { 40 69 status: 204, 41 70 };