Files
GearBox/.planning/phases/26-discovery-landing-page/26-01-SUMMARY.md
Jean-Luc Makiola a00b90d97a docs(26-01): complete discovery service plan
- SUMMARY.md: discovery service with cursor pagination
- STATE.md: advanced to plan 2, added decisions, updated progress to 71%
- ROADMAP.md: phase 26 in progress (1/3 plans)
- REQUIREMENTS.md: DISC-02, DISC-03, DISC-04, INFR-02 marked complete
2026-04-10 14:55:15 +02:00

3.4 KiB

phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics
phase plan subsystem tags dependency_graph tech_stack key_files decisions metrics
26-discovery-landing-page 01 server/services
discovery
service-layer
cursor-pagination
tdd
drizzle
requires provides affects
discovery.service.ts
26-02
26-03
added patterns
cursor-pagination
CursorPage-response-shape
post-query-cursor-filter
created modified
src/server/services/discovery.service.ts
tests/services/discovery.service.test.ts
Composite cursor for setups: itemCount_id format, filtered post-query in JS for simplicity with grouped SQL
createdAt ISO string cursor for recent items: standard timestamp-based pagination
No cursor pagination for trending categories: bounded small list (< 50), simple limit is sufficient per RESEARCH.md open question 3
Shared CursorPage<T> generic interface for consistent cursor response shape across setups and items
duration completed_date tasks_completed tasks_total files_created files_modified
~2 min 2026-04-10 1 1 2 0

Phase 26 Plan 01: Discovery Service Summary

One-liner: Discovery service layer with cursor pagination using Drizzle ORM — getPopularSetups (itemCount_id composite cursor), getRecentGlobalItems (ISO timestamp cursor), getTrendingCategories (simple limit).

Tasks Completed

Task Name Commit Files
1 (RED) Discovery service TDD — failing tests 06b6e93 tests/services/discovery.service.test.ts
1 (GREEN) Discovery service TDD — implementation d1f8a7a src/server/services/discovery.service.ts

What Was Built

src/server/services/discovery.service.ts

Three exported async functions:

getPopularSetups(db, limit=6, cursor?)

  • JOINs setups → setupItems (count) → users (displayName)
  • WHERE isPublic=true, GROUP BY setup fields
  • ORDER BY item count DESC, id DESC
  • Cursor: itemCount_id composite string, filtered post-query in JS
  • Returns CursorPage<{ id, name, createdAt, itemCount, creatorName }>

getRecentGlobalItems(db, limit=8, cursor?)

  • SELECT * FROM globalItems WHERE createdAt < cursor (if provided)
  • ORDER BY createdAt DESC, LIMIT limit+1 for hasMore detection
  • Cursor: ISO timestamp of last item's createdAt
  • Returns CursorPage<GlobalItem>

getTrendingCategories(db, limit=12)

  • SELECT category, COUNT(id) FROM globalItems WHERE category IS NOT NULL
  • GROUP BY category, ORDER BY count DESC
  • Returns plain Array<{ name: string; itemCount: number }> (no cursor)

tests/services/discovery.service.test.ts

11 tests covering:

  • getPopularSetups: ordering by count desc, private setup exclusion, hasMore/nextCursor, second page deduplication, creatorName from users.displayName
  • getRecentGlobalItems: ordering by createdAt desc, hasMore/nextCursor, second page deduplication
  • getTrendingCategories: ordering by count desc, null category exclusion, empty state

Deviations from Plan

None — plan executed exactly as written.

The test used a dynamic import pattern for eq which was corrected to a static import (minor code quality fix before RED commit).

Verification

  • bun test tests/services/discovery.service.test.ts: 11 pass, 0 fail
  • bun test full suite: 290 tests — same pass/fail ratio as before (15 pre-existing failures from withImageUrl storage service export issue, unrelated to this plan)

Self-Check

Checked below.