docs(18-02): complete global items service and routes plan
- SUMMARY.md with full task/commit/deviation documentation - STATE.md updated to Phase 18, Plan 2/5 - ROADMAP.md progress updated - REQUIREMENTS.md: GLOB-01 through GLOB-05 marked complete
This commit is contained in:
@@ -41,11 +41,11 @@ Requirements for this milestone. Each maps to roadmap phases.
|
|||||||
|
|
||||||
### Global Item Database
|
### Global Item Database
|
||||||
|
|
||||||
- [ ] **GLOB-01**: A global item catalog exists with brand, model, category, manufacturer specs, and image
|
- [x] **GLOB-01**: A global item catalog exists with brand, model, category, manufacturer specs, and image
|
||||||
- [ ] **GLOB-02**: Global catalog is seeded with initial items from manufacturer data
|
- [x] **GLOB-02**: Global catalog is seeded with initial items from manufacturer data
|
||||||
- [ ] **GLOB-03**: User can search the global catalog by name or brand
|
- [x] **GLOB-03**: User can search the global catalog by name or brand
|
||||||
- [ ] **GLOB-04**: User can link a personal collection item to a global catalog entry
|
- [x] **GLOB-04**: User can link a personal collection item to a global catalog entry
|
||||||
- [ ] **GLOB-05**: Global item pages show basic info and owner count
|
- [x] **GLOB-05**: Global item pages show basic info and owner count
|
||||||
|
|
||||||
### User Profiles & Sharing
|
### User Profiles & Sharing
|
||||||
|
|
||||||
@@ -136,11 +136,11 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| IMG-02 | Phase 17 | Pending |
|
| IMG-02 | Phase 17 | Pending |
|
||||||
| IMG-03 | Phase 17 | Pending |
|
| IMG-03 | Phase 17 | Pending |
|
||||||
| IMG-04 | Phase 17 | Pending |
|
| IMG-04 | Phase 17 | Pending |
|
||||||
| GLOB-01 | Phase 18 | Pending |
|
| GLOB-01 | Phase 18 | Complete (18-02) |
|
||||||
| GLOB-02 | Phase 18 | Pending |
|
| GLOB-02 | Phase 18 | Complete (18-02) |
|
||||||
| GLOB-03 | Phase 18 | Pending |
|
| GLOB-03 | Phase 18 | Complete (18-02) |
|
||||||
| GLOB-04 | Phase 18 | Pending |
|
| GLOB-04 | Phase 18 | Complete (18-02) |
|
||||||
| GLOB-05 | Phase 18 | Pending |
|
| GLOB-05 | Phase 18 | Complete (18-02) |
|
||||||
| PROF-01 | Phase 18 | Pending |
|
| PROF-01 | Phase 18 | Pending |
|
||||||
| PROF-02 | Phase 18 | Pending |
|
| PROF-02 | Phase 18 | Pending |
|
||||||
| PROF-03 | Phase 18 | Pending |
|
| PROF-03 | Phase 18 | Pending |
|
||||||
|
|||||||
@@ -192,4 +192,4 @@ Plans:
|
|||||||
| 15. External Authentication | v2.0 | 0/? | Not started | - |
|
| 15. External Authentication | v2.0 | 0/? | Not started | - |
|
||||||
| 16. Multi-User Data Model | v2.0 | 0/? | Not started | - |
|
| 16. Multi-User Data Model | v2.0 | 0/? | Not started | - |
|
||||||
| 17. Object Storage | v2.0 | 0/? | Not started | - |
|
| 17. Object Storage | v2.0 | 0/? | Not started | - |
|
||||||
| 18. Global Items & Public Profiles | v2.0 | 0/? | Not started | - |
|
| 18. Global Items & Public Profiles | v2.0 | 2/5 | In progress | - |
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ See: .planning/PROJECT.md (updated 2026-04-03)
|
|||||||
|
|
||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 14 of 18 (PostgreSQL Migration)
|
Phase: 18 of 18 (Global Items & Public Profiles)
|
||||||
Plan: 0 of ? in current phase
|
Plan: 2 of 5 in current phase
|
||||||
Status: Ready to plan
|
Status: Executing
|
||||||
Last activity: 2026-04-03 — v2.0 roadmap created (Phases 14-18)
|
Last activity: 2026-04-05 — Completed 18-02 global items service and routes
|
||||||
|
|
||||||
Progress: [----------] 0% (v2.0 milestone)
|
Progress: [##--------] 20% (v2.0 milestone)
|
||||||
|
|
||||||
## Performance Metrics
|
## Performance Metrics
|
||||||
|
|
||||||
@@ -64,6 +64,6 @@ None active.
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-04-03
|
Last session: 2026-04-05
|
||||||
Stopped at: v2.0 roadmap created with 5 phases (14-18) covering 30 requirements
|
Stopped at: Completed 18-02-PLAN.md (global items service and routes)
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
---
|
||||||
|
phase: 18-global-items-public-profiles
|
||||||
|
plan: 02
|
||||||
|
subsystem: server
|
||||||
|
tags: [global-items, service, routes, seed, search, linking]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: 18-01
|
||||||
|
provides: "globalItems/itemGlobalLinks tables, Zod schemas, seed JSON"
|
||||||
|
provides:
|
||||||
|
- "Global item search service with case-insensitive LIKE and wildcard escaping"
|
||||||
|
- "Global item detail with owner count aggregation"
|
||||||
|
- "Item-to-global link/unlink service functions"
|
||||||
|
- "GET /api/global-items and GET /api/global-items/:id public routes"
|
||||||
|
- "POST /api/items/:id/link and DELETE /api/items/:id/link auth-protected routes"
|
||||||
|
- "Idempotent seed script integrated into startup"
|
||||||
|
affects: [18-03, 18-04, 18-05]
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns: ["LIKE search with wildcard escaping for SQLite", "Owner count via junction table aggregation"]
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- "src/server/services/global-item.service.ts"
|
||||||
|
- "src/server/routes/global-items.ts"
|
||||||
|
- "src/db/seed-global-items.ts"
|
||||||
|
- "tests/services/global-item.service.test.ts"
|
||||||
|
- "tests/routes/global-items.test.ts"
|
||||||
|
modified:
|
||||||
|
- "src/server/routes/items.ts"
|
||||||
|
- "src/server/index.ts"
|
||||||
|
- "src/db/seed.ts"
|
||||||
|
- "src/db/schema.ts"
|
||||||
|
- "src/shared/schemas.ts"
|
||||||
|
- "src/shared/types.ts"
|
||||||
|
- "src/db/global-items-seed.json"
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Used SQLite LIKE (case-insensitive for ASCII) instead of Postgres ILIKE since codebase is still SQLite"
|
||||||
|
- "Auth middleware already skips GET requests globally, no additional skip needed for /api/global-items"
|
||||||
|
- "Link/unlink endpoints placed on items routes (/api/items/:id/link) since they act on user items"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "Junction table count aggregation for owner counts"
|
||||||
|
- "Wildcard character escaping in search queries"
|
||||||
|
|
||||||
|
requirements-completed: [GLOB-01, GLOB-02, GLOB-03, GLOB-04, GLOB-05]
|
||||||
|
|
||||||
|
duration: 4min
|
||||||
|
completed: 2026-04-05
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 18 Plan 02: Global Items Service and Routes Summary
|
||||||
|
|
||||||
|
**Global item catalog backend with LIKE search, owner count aggregation, item linking, idempotent seeding, and full test coverage**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 4 min
|
||||||
|
- **Started:** 2026-04-05T11:03:16Z
|
||||||
|
- **Completed:** 2026-04-05T11:07:46Z
|
||||||
|
- **Tasks:** 2
|
||||||
|
- **Files created:** 5
|
||||||
|
- **Files modified:** 6
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- Built global-item.service.ts with 4 service functions following existing DI pattern
|
||||||
|
- Implemented case-insensitive search with wildcard escaping (%, _) for safe user input
|
||||||
|
- Added owner count aggregation via junction table count query
|
||||||
|
- Created public GET routes for global item catalog (search + detail)
|
||||||
|
- Added authenticated POST/DELETE link/unlink endpoints on item routes
|
||||||
|
- Wrote idempotent seed script that imports 18-item bikepacking catalog on startup
|
||||||
|
- Full TDD: 12 service tests + 10 route tests, all passing
|
||||||
|
- Full suite: 278 tests, 0 failures
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Global item service + seed script + tests (TDD)**
|
||||||
|
- RED: `3a6876f` - Failing tests for service and seed
|
||||||
|
- GREEN: `60dd9f4` - Implementation passing all tests
|
||||||
|
2. **Task 2: Global item routes + link/unlink + route tests** - `d97d5d9`
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `src/server/services/global-item.service.ts` - searchGlobalItems, getGlobalItemWithOwnerCount, linkItemToGlobal, unlinkItemFromGlobal
|
||||||
|
- `src/server/routes/global-items.ts` - GET / (search), GET /:id (detail with ownerCount)
|
||||||
|
- `src/db/seed-global-items.ts` - Idempotent seed function importing from JSON
|
||||||
|
- `src/db/seed.ts` - Added seedGlobalItems call to seedDefaults
|
||||||
|
- `src/server/routes/items.ts` - Added POST /:id/link and DELETE /:id/link
|
||||||
|
- `src/server/index.ts` - Registered /api/global-items route
|
||||||
|
- `src/db/schema.ts` - Added globalItems and itemGlobalLinks SQLite tables
|
||||||
|
- `src/shared/schemas.ts` - Added searchGlobalItemsSchema and linkItemSchema
|
||||||
|
- `src/shared/types.ts` - Added GlobalItem, ItemGlobalLink, SearchGlobalItems, LinkItem types
|
||||||
|
- `src/db/global-items-seed.json` - 18 bikepacking gear items across 7 categories
|
||||||
|
- `tests/services/global-item.service.test.ts` - 12 service tests
|
||||||
|
- `tests/routes/global-items.test.ts` - 10 route tests
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- Used SQLite LIKE instead of Postgres ILIKE since the codebase is still on SQLite; SQLite LIKE is already case-insensitive for ASCII characters
|
||||||
|
- Auth middleware already has a global GET skip rule, so no additional middleware change was needed for public global item access
|
||||||
|
- Link/unlink endpoints placed on /api/items/:id/link (item-centric) rather than on global-items routes
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 3 - Blocking] Applied 18-01 schema prerequisites to SQLite codebase**
|
||||||
|
- **Found during:** Pre-task setup
|
||||||
|
- **Issue:** Plan 18-01 was executed by a parallel agent on a Postgres-migrated schema, but this worktree is still on SQLite
|
||||||
|
- **Fix:** Added globalItems/itemGlobalLinks as sqliteTable definitions, Zod schemas, types, seed JSON, and migration directly in this branch
|
||||||
|
- **Files modified:** src/db/schema.ts, src/shared/schemas.ts, src/shared/types.ts, src/db/global-items-seed.json, drizzle migration
|
||||||
|
|
||||||
|
**2. [Rule 1 - Bug] Used LIKE instead of ILIKE for SQLite compatibility**
|
||||||
|
- **Found during:** Task 1
|
||||||
|
- **Issue:** Plan specified ilike (Postgres-only), but codebase uses SQLite where LIKE is already case-insensitive for ASCII
|
||||||
|
- **Fix:** Used drizzle-orm `like` operator which maps to SQLite LIKE
|
||||||
|
- **Files modified:** src/server/services/global-item.service.ts
|
||||||
|
|
||||||
|
## Known Stubs
|
||||||
|
|
||||||
|
None - all endpoints return real data from the database.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
- Global item catalog fully queryable via API
|
||||||
|
- Link/unlink API ready for client integration in Plan 18-03
|
||||||
|
- Seed data available for development and testing
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 18-global-items-public-profiles*
|
||||||
|
*Completed: 2026-04-05*
|
||||||
Reference in New Issue
Block a user