refactor(server): split annotation routes via Bun routes API#170
Merged
Conversation
Replace the single-handler if/else chain in `startServer` with Bun's
declarative `Bun.serve({ routes })` API, with each route extracted to
its own file under `packages/server/src/routes/`.
- `annotation.ts` is now a thin composition layer (routes table +
lifecycle); `createAnnotationServerApp` and `AnnotationServerApp` are
removed since nothing else imported them.
- Per-route tests live colocated as `routes/<name>.test.ts` and share a
`withServer(ctx, opts?, fn)` helper that defaults html/payload/config
via Fishery factories. `annotation.test.ts` keeps smoke + lifecycle
coverage (404 fallback, resolveListenPort, the submit/close race
regression).
- Adds `annotationPayload` and `frontendConfig` factories to
`@contextbridge/shared/testFactories`.
The /submit non-negotiables (`setTimeout` + `connection: close`) are
preserved in the new `handleSubmit`.
jcarver989
approved these changes
May 19, 2026
Contributor
jcarver989
left a comment
There was a problem hiding this comment.
Looks like a nice cleanup here thanks
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.
Summary
The annotation server's
fetchhandler was a long if/else chain branching onreq.methodandurl.pathname— felt messy and didn't scale to the upcomingreviewsurface. This swaps it for Bun's declarativeBun.serve({ routes })API and splits each handler into its own file underpackages/server/src/routes/, soannotation.tsbecomes a thin composition layer (routes table + lifecycle) and new routes drop in beside the existing ones.Tests follow the split: per-route HTTP integration tests live colocated as
routes/<name>.test.tsand share awithServer(ctx, opts?, fn)helper that defaults html/payload/config via new Fishery factories.annotation.test.tskeeps smoke + lifecycle coverage (404 fallback,resolveListenPort, and the existing submit→close race regression).Review focus
/submitinvariants — thesetTimeout(() => resolveResult(...), 0)deferral andconnection: closeheader are non-negotiable (they prevent Bun from tearing down the socket before the 204 is flushed). They moved intoroutes/submit.tsverbatim and the race regression test inannotation.test.tsstill passes, but worth a second pair of eyes.app.fetch(req)in-process is gone; everything is real HTTP against a started server now. Slightly slower per test, but a stronger integration boundary and removes thecreateAnnotationServerAppfactory whose only consumer was the tests themselves.withServeroverload — opted for two signatures ((ctx, fn)vs(ctx, opts, fn)) over a required{}middle arg. The overload impl is 4 lines oftypeof optsOrFn === 'function'— let me know if you'd prefer the simpler always-3-arg shape.Commits