--- phase: 03-setups-and-dashboard plan: 01 type: tdd wave: 1 depends_on: [] files_modified: - src/db/schema.ts - src/shared/schemas.ts - src/shared/types.ts - src/server/services/setup.service.ts - src/server/routes/setups.ts - src/server/index.ts - tests/helpers/db.ts - tests/services/setup.service.test.ts - tests/routes/setups.test.ts autonomous: true requirements: - SETP-01 - SETP-02 - SETP-03 must_haves: truths: - "Setup CRUD operations work (create, read, update, delete)" - "Items can be added to and removed from a setup via junction table" - "Setup totals (weight, cost, item count) are computed correctly via SQL aggregation" - "Deleting a setup cascades to setup_items, deleting a collection item cascades from setup_items" artifacts: - path: "src/db/schema.ts" provides: "setups and setupItems table definitions" contains: "setupItems" - path: "src/shared/schemas.ts" provides: "Zod schemas for setup create/update/sync" contains: "createSetupSchema" - path: "src/shared/types.ts" provides: "Setup and SetupWithItems TypeScript types" contains: "CreateSetup" - path: "src/server/services/setup.service.ts" provides: "Setup business logic with DB injection" exports: ["getAllSetups", "getSetupWithItems", "createSetup", "updateSetup", "deleteSetup", "syncSetupItems", "removeSetupItem"] - path: "src/server/routes/setups.ts" provides: "Hono API routes for setups" contains: "setupRoutes" - path: "tests/services/setup.service.test.ts" provides: "Unit tests for setup service" min_lines: 50 - path: "tests/routes/setups.test.ts" provides: "Integration tests for setup API routes" min_lines: 30 key_links: - from: "src/server/routes/setups.ts" to: "src/server/services/setup.service.ts" via: "service function calls" pattern: "setup\\.service" - from: "src/server/index.ts" to: "src/server/routes/setups.ts" via: "route mounting" pattern: "setupRoutes" - from: "src/server/services/setup.service.ts" to: "src/db/schema.ts" via: "drizzle schema imports" pattern: "import.*schema" --- Build the complete setup backend: database schema (setups + setup_items junction table), shared Zod schemas/types, service layer with CRUD + item sync + totals aggregation, and Hono API routes. All with TDD. Purpose: Provides the data layer and API that the frontend (Plan 02) will consume. The many-to-many junction table is the only new DB pattern in this project. Output: Working API at /api/setups with full test coverage. @/home/jean-luc-makiola/.claude/get-shit-done/workflows/execute-plan.md @/home/jean-luc-makiola/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/03-setups-and-dashboard/03-RESEARCH.md @src/db/schema.ts @src/shared/schemas.ts @src/shared/types.ts @src/server/index.ts @tests/helpers/db.ts From src/server/services/thread.service.ts (pattern reference): ```typescript export function getAllThreads(db: Db = prodDb, includeResolved = false) { ... } export function getThread(db: Db = prodDb, id: number) { ... } export function createThread(db: Db = prodDb, data: CreateThread) { ... } export function deleteThread(db: Db = prodDb, id: number) { ... } ``` From src/server/routes/threads.ts (pattern reference): ```typescript const threadRoutes = new Hono<{ Variables: { db: Db } }>(); threadRoutes.get("/", (c) => { ... }); threadRoutes.post("/", zValidator("json", createThreadSchema), (c) => { ... }); ``` From tests/helpers/db.ts: ```typescript export function createTestDb() { ... } // Returns in-memory Drizzle instance ``` Setup Backend with Junction Table src/db/schema.ts, src/shared/schemas.ts, src/shared/types.ts, src/server/services/setup.service.ts, src/server/routes/setups.ts, src/server/index.ts, tests/helpers/db.ts, tests/services/setup.service.test.ts, tests/routes/setups.test.ts Service layer (setup.service.ts): - getAllSetups: returns setups with itemCount, totalWeight (grams), totalCost (cents) via SQL subqueries - getSetupWithItems: returns single setup with full item details (joined with categories), null if not found - createSetup: creates setup with name, returns created setup - updateSetup: updates setup name, returns updated setup, null if not found - deleteSetup: deletes setup (cascade deletes setup_items), returns boolean - syncSetupItems: delete-all + re-insert in transaction, accepts setupId + itemIds array - removeSetupItem: removes single item from setup by setupId + itemId API routes (setups.ts): - GET /api/setups -> list all setups with aggregated totals - GET /api/setups/:id -> single setup with items - POST /api/setups -> create setup (validates name via createSetupSchema) - PUT /api/setups/:id -> update setup name - DELETE /api/setups/:id -> delete setup - PUT /api/setups/:id/items -> sync setup items (validates itemIds via syncSetupItemsSchema) - DELETE /api/setups/:id/items/:itemId -> remove single item from setup Edge cases: - Syncing with empty itemIds array clears all items from setup - Deleting a collection item cascades removal from all setups - getAllSetups returns 0 for weight/cost when setup has no items (COALESCE) 1. Add setups and setupItems tables to src/db/schema.ts (with cascade FKs) 2. Add Zod schemas (createSetupSchema, updateSetupSchema, syncSetupItemsSchema) to src/shared/schemas.ts 3. Add types (CreateSetup, UpdateSetup, SyncSetupItems, Setup, SetupItem) to src/shared/types.ts 4. Add setups and setup_items CREATE TABLE to tests/helpers/db.ts 5. Implement setup.service.ts following thread.service.ts pattern (db as first param with prod default) 6. Implement setups.ts routes following threads.ts pattern (Hono with zValidator) 7. Mount setupRoutes in src/server/index.ts 8. Use raw SQL in Drizzle sql`` for correlated subqueries in getAllSetups (per Phase 2 decision about table.column refs) ```bash bun test tests/services/setup.service.test.ts && bun test tests/routes/setups.test.ts && bun test ``` All setup service and route tests pass. Full test suite remains green. - Setup CRUD API responds correctly at all 7 endpoints - Junction table correctly links items to setups (many-to-many) - Totals aggregation returns correct weight/cost/count via SQL - Cascade delete works both directions (setup deletion, item deletion) - All existing tests still pass After completion, create `.planning/phases/03-setups-and-dashboard/03-01-SUMMARY.md`