refactor: close the structural findings from the architecture review - #86
Merged
Merged
Conversation
Four of the five that were left open in #81. The fifth is comment density, which is a house-style question and does not belong in the same commit as a set of mechanical moves. The e2e suite could run against somebody else's application. It listened on 5173 — the port every Vite project takes by default — and `reuseExistingServer` adopted whatever was already there without checking whose it was. That is how seventeen tests once failed against a stranger's HTML, pointing at robots.txt and security headers rather than at anything real; the dangerous direction is the other one, where a reused server running stale code reports green. It now has a port nothing else defaults to, and `--strictPort` so Vite cannot answer a busy port by quietly moving to another one. Six exports were only ever used inside their own module and are now private. Each was checked against its spec first: several siblings are public precisely so they can be unit-tested, and those stay. Two components were typed against the database schema. The import was type-only, so nothing ever shipped to the browser, but it pointed presentation at the persistence shape — adding a column changed the type a card saw. They now take `SavedTitle`, which the domain owns: what the rules need, plus the three things only a rendering cares about. The database row satisfies it structurally, so nothing converts anything, and the card's own test fixture lost `userId`, `overview` and `addedAt` — three fields it never used and should never have been asked for. `watchlistActions` was one 485-line object with four reasons to change. Split into the titles, the links that publish them, and the account's own settings, spread back into one action map so the route contract is untouched: every one of the 55 action tests passes unedited. `tmdb.ts` was 612 lines and six endpoint families whose only genuinely shared parts are the fetch and two raw response shapes. Those are now `client`, and search, seasons, details, recommendations, trending and people each have their own file behind an index that re-exports the same public surface. No import anywhere else changed.
The file carried two thirteen-line essays in its markup. Both record something worth keeping — a measurement, and a pair of CSS mechanics that are not guessable — and both said it at four times the necessary length. They are now five and six lines. Nothing factual is lost: the blur block still carries the numbers that justify the ban (794ms -> 392ms over 300 frames, 154 compositing layers on a grid of 77) and the clamp block still names both reasons the clamp cannot move to the button. Four prop docs and two inline notes got the same treatment. The LCP figures stay; the retelling around them does not.
36 tasks
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.
Closes the rest of #81 — F2, F3 (remainder), F5, F6, F7 — and reaches a different conclusion on F9 than the review did.
F2 · The e2e suite could run against another application
It listened on 5173, the port every Vite project takes by default, and
reuseExistingServeradopted whatever was already there without checking whose it was. That is how seventeen tests once failed against a stranger's HTML, pointing atrobots.txtand security headers rather than at anything real. The dangerous direction is the other one: a reused server running stale code reporting green.Now a port nothing else defaults to, plus
--strictPort— without it Vite answers a busy port by quietly moving to the next one, which would leave the suite pointed at nothing.F3 · Six exports made private
Each checked against its spec first, because several siblings are public precisely so they can be unit-tested and those must stay:
DELETION_WARNING_DAYS,watchableSeasons,MAX_SEEDS,MAX_RAILS,MAX_RAIL_ITEMS,SHARE_SCOPES,CALLBACK_PATH.F5 · Components no longer type against the database schema
WatchlistCardandContinueWatchingtookWatchlistItemfrom$lib/server/db/schema. Type-only, so nothing ever shipped to the browser — but presentation depended on the persistence shape, and adding a column changed the type a card saw.They now take
SavedTitle, owned by the domain: what the rules need, plus the three things only a rendering cares about. The database row satisfies it structurally, so nothing converts anything. The proof it was real coupling: the card's own fixture lostuserId,overviewandaddedAt— three fields it never used and should never have been asked for.F6 ·
watchlistActionssplit485 lines and four reasons to change → the titles (
list.ts), the links that publish them (sharing.ts), the account's own settings (settings.ts), spread back into one map inindex.ts.The route contract is untouched: all 55 action tests pass unedited, and the spec's
import('./actions')resolves to the new index on its own.F7 ·
tmdb.tssplit612 lines and six endpoint families whose only genuinely shared parts are the fetch and two raw response shapes. Those are
client.ts; search, seasons, details, recommendations, trending and people each have their own file behind an index that re-exports the same public surface. No import anywhere else changed.F9 · The review's number was wrong, and so was its conclusion
I have to correct this rather than act on it. The 46% figure came from a counter with a bug: entering an HTML comment
<!-- … -->it only looked for*/to exit, so it swallowed the rest of every Svelte file as comment. The "82% files" were an artifact of that.Measured correctly:
MediaCard.svelte82%domain/filmography.ts65%And the real top files are not components — they are
filmography.ts,db/schema.ts,title-url.ts,domain/share.ts: files that document why a tuning constant is the value it is (why five credits, why twenty, why eight people). That is the kind worth keeping, and a sweep would have destroyed it.A targeted hunt for comments that merely restate their code found essentially nothing beyond SvelteKit's own scaffolding in
app.d.ts.So no sweep. What was genuinely bloated was prose in markup, and
MediaCardhad two thirteen-line essays. Both are now five and six lines with every fact intact — the blur ban still carries its measurement (794ms → 392ms over 300 frames, 154 compositing layers), the clamp note still names both reasons it cannot move to the button. 32 comment lines removed, and the file is the better for it; the codebase moved 36% → 35%, which is the honest size of this.Verified
npm run check— 0 errors, 0 warnings;npm run lintclean