Repository navigation
feat: semesters list end to end - #13
Open
AskingRouge wants to merge 2 commits into
Open
AskingRouge wants to merge 2 commits into
AskingRouge wants to merge 2 commits into
Conversation
VidurShah
reviewed
Oct 22, 2026
VidurShah
left a comment
Collaborator
There was a problem hiding this comment.
Nice work Nikhil. The layering is exactly what the ticket asked for (service, thin route, shared schema, typed client). The // TODO(auth), the lazy db import so CI runs without a database, and formatting dates in UTC are all well thought out.
Please fix
- Merge conflict. #8 has merged and this now conflicts in
apps/api/src/app.ts. Rebase onmainand keep both the error handlers and the/semestersroute. - Pagination. The Lists convention in TDD 3.2 is
?page=1&pageSize=50(max 200), returning{ items, total }, wheretotalis the full count, not the page length. Validate the query withvalidate("query", ...)from #8, so a bad?pageSizecomes back as a standardVALIDATIONerror. (You mentioned you couldn't open the TDD in Notion. I'll sort out your access.) - The term enum is defined twice. It's in
SEMESTER_TERMSinpackages/sharedand again in thepgEnumindb/schema/semesters.ts. Have the schema use the shared one,pgEnum("semester_term", SEMESTER_TERMS), so they can't drift apart. - The sort order isn't tested. The route test stubs the service, so the newest-first ordering and the name tiebreak never actually run. A good fix: pull the ordering into something you can test without the database, or add a service test that runs when
DATABASE_URLis set.
Small
- The error handling already uses #8's format: an unhandled database failure comes back as
{"error":{"code":"INTERNAL",...}}with a 500. The page could show the API's error message instead of the generic text, now that responses carry one.
Re-request review when it's ready.
GET /api/v1/semesters returns { items, total }, newest first, with the
response schema in packages/shared, the query in a service, a route test,
and a /semesters page with loading, error, and empty states.
- Paginate per the TDD 3.2 Lists convention (?page, ?pageSize max 200),
validated with validate("query", ...); total is the full count
- Shared pageQuerySchema in packages/shared for later list endpoints
- semester_term pgEnum uses SEMESTER_TERMS from packages/shared
- Service test against the database (skipped without DATABASE_URL)
covering newest-first order, the name tiebreak, paging, and total
- Page shows the API's error message when there is one
AskingRouge
force-pushed
the
nikhil/semesters-list
branch
from
October 28, 2026 02:14
8c250f9 to
e459da5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ticket
Closes #6
What changed
GET /api/v1/semestersreturns{ items, total }, newest first (by start date, name as tiebreak).packages/shared/src/semesters.ts.apps/api/src/services/semesters.ts; route only handles request/response, with a// TODO(auth).apps/api/tests/semesters.test.ts) with the service stubbed, so it runs without a database like CI./semesterspage fetches through the typed client, with loading, error, and empty states.Notes:
dblazily becausesrc/db/index.tsthrows on import withoutDATABASE_URL, which would break every API test in CI.db/index.tsitself is unchanged.{ items, total }without paging matches it.app.ts) and FormRenderer, answer validation, and testing router validation #10 (shared/src/index.ts). Whichever merges second keeps both lines.Why
First end-to-end feature (DB → service → route → shared schema → typed client → page) to set the pattern for later features.
How to verify
bun run db:migrate, then add a few semesters inbun run db:studio(mark one current).bun run dev, then open http://localhost:3000/semesters: newest first, correct dates, "Current" marker.bun run test:allpasses withoutDATABASE_URL.Checklist