Archive roadmap, requirements, and phase directories to milestones/. Evolve PROJECT.md with validated requirements and key decisions. Reorganize ROADMAP.md with milestone grouping. Delete REQUIREMENTS.md (fresh for next milestone).
177 lines
6.9 KiB
Markdown
177 lines
6.9 KiB
Markdown
---
|
|
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"
|
|
---
|
|
|
|
<objective>
|
|
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.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/home/jean-luc-makiola/.claude/get-shit-done/workflows/execute-plan.md
|
|
@/home/jean-luc-makiola/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.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
|
|
|
|
<interfaces>
|
|
<!-- Existing patterns to follow exactly -->
|
|
|
|
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
|
|
```
|
|
</interfaces>
|
|
</context>
|
|
|
|
<feature>
|
|
<name>Setup Backend with Junction Table</name>
|
|
<files>
|
|
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
|
|
</files>
|
|
<behavior>
|
|
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)
|
|
</behavior>
|
|
<implementation>
|
|
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)
|
|
</implementation>
|
|
</feature>
|
|
|
|
<verification>
|
|
```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.
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- 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
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/03-setups-and-dashboard/03-01-SUMMARY.md`
|
|
</output>
|