Apply cursor pagination to remaining flat-list endpoints #191

Closed
opened 2026-06-20 17:36:04 +00:00 by james · 0 comments
Owner

Apply the cursor-pagination convention from docs/api-conventions.md to the three remaining flat-list endpoints. The helpers in lib/api/pagination.ts and the reference implementation on /api/notes (#179, PR #190) apply unchanged.

These endpoints are domain-bounded today — a user has tens of educations, contacts, or tokens, not thousands — so migrating them was deferred from #179. This ticket exists so the convention is consistent across every flat-list API surface before the Expo client (#183) lands and before #178 generates the OpenAPI spec.

Scope

For each endpoint below:

  • Add listPaginatedByUserId to the repo (same shape as NotesRepository), keeping the existing listByUserId for tests + server prefetches.
  • Update the route handler to use parseCursorQuery + paginatedResponse.
  • Update the PWA hook that consumes the endpoint to read .data from the response.
  • Update the dual-engine tests to assert the new envelope and exercise pagination (limit, cursor round-trip).

Endpoints:

  • /api/educations (GET) — cursor over (start_date, id) if start_date is the current sort key, otherwise (created_at, id). Confirm against the existing route's ordering.
  • /api/profile/contacts (GET) — cursor over (display_order, id). Watch for ordering stability if the user reorders mid-page (acceptable to skip / repeat a row across pages, but document the trade-off).
  • /api/account/tokens (GET) — cursor over (created_at, id).

Update docs/api-conventions.md "Currently paginated" section to list all four endpoints once they're migrated.

Acceptance criteria

  • All three endpoints return { data, next_cursor, has_more }; tests cover the page boundary on both SQLite and Postgres.
  • Existing PWA pages still render via the updated hooks (until #184 ports them to Expo).
  • docs/api-conventions.md "Currently paginated" lists /api/notes, /api/educations, /api/profile/contacts, /api/account/tokens.
  • No new behavior — purely a shape migration.

Out of scope

  • Adding useInfiniteQuery infinite-scroll UI on the PWA. The PWA is decommissioned in #185; the Expo client (#183) does this natively.
  • Pagination for the nested-tree endpoints (/api/skill-sections, /api/jobs). They stay as flat trees by design.

Composes with

#179 (PR #190), lib/api/pagination.ts, docs/api-conventions.md, #183 (Expo client).

Part of

#176

Apply the cursor-pagination convention from `docs/api-conventions.md` to the three remaining flat-list endpoints. The helpers in `lib/api/pagination.ts` and the reference implementation on `/api/notes` (#179, PR #190) apply unchanged. These endpoints are **domain-bounded today** — a user has tens of educations, contacts, or tokens, not thousands — so migrating them was deferred from #179. This ticket exists so the convention is consistent across every flat-list API surface before the Expo client (#183) lands and before #178 generates the OpenAPI spec. ## Scope For each endpoint below: - Add `listPaginatedByUserId` to the repo (same shape as `NotesRepository`), keeping the existing `listByUserId` for tests + server prefetches. - Update the route handler to use `parseCursorQuery` + `paginatedResponse`. - Update the PWA hook that consumes the endpoint to read `.data` from the response. - Update the dual-engine tests to assert the new envelope and exercise pagination (limit, cursor round-trip). Endpoints: - **`/api/educations` (GET)** — cursor over `(start_date, id)` if start_date is the current sort key, otherwise `(created_at, id)`. Confirm against the existing route's ordering. - **`/api/profile/contacts` (GET)** — cursor over `(display_order, id)`. Watch for ordering stability if the user reorders mid-page (acceptable to skip / repeat a row across pages, but document the trade-off). - **`/api/account/tokens` (GET)** — cursor over `(created_at, id)`. Update `docs/api-conventions.md` "Currently paginated" section to list all four endpoints once they're migrated. ## Acceptance criteria - [ ] All three endpoints return `{ data, next_cursor, has_more }`; tests cover the page boundary on both SQLite and Postgres. - [ ] Existing PWA pages still render via the updated hooks (until #184 ports them to Expo). - [ ] `docs/api-conventions.md` "Currently paginated" lists `/api/notes`, `/api/educations`, `/api/profile/contacts`, `/api/account/tokens`. - [ ] No new behavior — purely a shape migration. ## Out of scope - Adding `useInfiniteQuery` infinite-scroll UI on the PWA. The PWA is decommissioned in #185; the Expo client (#183) does this natively. - Pagination for the nested-tree endpoints (`/api/skill-sections`, `/api/jobs`). They stay as flat trees by design. ## Composes with #179 (PR #190), `lib/api/pagination.ts`, `docs/api-conventions.md`, #183 (Expo client). ## Part of #176
james closed this issue 2026-06-21 12:40:39 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
james/carol#191
No description provided.