Built a small private link shortener: a form turns a long http/https… #1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "osf/66-shortcut-a-link-shortener-combined"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What was done
/<code>redirects (302) to the stored URL, and an unknown or differently-cased code shows a 404 page.startscript inpackage.json.vitest) over storage, validation, page rendering, and the full HTTP behaviour, plus browser tests (playwright, chromium) over the shorten, follow, and Links-page flows.CHANGELOG.mdgained an entry naming this change for the release-notes job, and the unit and browser test lanes were wired into the existing workflow.How to review
git fetch origin && git checkout osf/66-shortcut-a-link-shortener-combined, thengit diff origin/main --statto see it add the server, pages, storage, tests, and config.DATABASE_URLto a reachable Postgres before any test or the app (export DATABASE_URL=postgres://app:app@127.0.0.1:5432/app);scripts/services.mjscan boot an embedded one if you have none.npm installthennpm test— expect all to pass.npx playwright install chromiumonce, thennpm run test:e2e— expect all to pass (it starts the server itself).npm start(listens onPORT, default 3000), open/, shorten a long URL, follow the/<code>link, and view/links— expect the 6-character code with a working Copy button, a 302 to the exact stored URL, a 404 for a bogus code, and the newest-first list; to see the known gap, shorten a 2,000-character URL and open/linksto find the URL column overflowing the window.src/server.tsfor the routes andsrc/db.tsfor storage and the click count.Code review
Reviewed the full Shortcut link-shortener change (src/, unit and e2e tests, configs, CHANGELOG/README, CI surface) against its proposal, delta specs, design and tasks. Found and fixed three defects: a strict-mode tsc failure in test/link-storage.test.ts (broken
address()destructuring, fixing it restored the task 2.3/3.2 typecheck), a nondeterministic race where concurrentCREATE TABLE IF NOT EXISTSon a fresh database failednpm test(reproduced 150/150 with 8 concurrent pre-warmed sessions; fixed by re-running the no-op statement on the race's catalog-conflict codes, then 0/150 and the full suite passed), and a never-sorted expected column list in test/db.test.ts that always fails once the DDL runs. Left three minor notes unfixed as documented: the spec's wording for a bare non-URL message vs the tasks-pinned 'not a valid URL', the uncapped POST body in readBody (design explicitly excludes scale engineering), and the proposal's file list omitting files its own tasks create. All 58 unit tests pass andnpx tsc --noEmitis clean.Left for you
src/validate.ts:14: The link-shortening spec scenario 'Value that is not a URL is refused' (e.g. bareexample.com) asks for a message stating the URL 'must be http or https', but the implementation rejects with 'not a valid URL' — the mapping design decision 7 and task 2.1 explicitly pin, and which unit (test/validate.test.ts:11), HTTP (test/server.test.ts:115) and e2e (e2e/shorten.spec.ts:101) tests assert. The requirement's core (refused, inline reason, no short link) is met; reconciling the wording would contradict the tasks, so left as is (also flagged as a note by the prior review round).src/server.ts:11: readBody buffers the entire POST body before validation, so a multi-megabyte body is held in memory even though the url field itself is capped at 2,000 characters. The design's Non-Goals explicitly exclude availability/scale engineering for a one-team private app, so left as is.openspec/changes/build-shortcut-a-small-link-shortener-fo-d2hmzy/proposal.md: The proposal's What Changes/Impact file list omits files its own tasks create: CHANGELOG.md (task 3.3), thestartscript (task 1.1), tsconfig.json and vitest.config.ts (task 1.2). Documentation-only gap; the change's docs are out of scope for this code review, so left as is (also flagged as a note by the prior review round).Fixed before the commit
test/link-storage.test.ts:18:const { port } = s.address()failsnpx tsc --noEmit(TS2339:address()isstring | AddressInfo | nullin strict mode), so the commit broke the typecheck that tasks 2.3 and 3.2 require to pass. Fixed with the same narrowing pattern already used by listen() in src/server.ts:94-95.src/db.ts:31: ConcurrentcreateTablescalls on a fresh database (parallel vitest workers, CI's fresh postgres container, overlapping app starts) race in the system catalogs: the loser getsduplicate key value violates unique constraint pg_type_typname_nsp_index(23505) orrelation/type already exists(42P07/42P04), makingnpm testfail nondeterministically (observed on 2 of 4 runs; reproduced 150/150 with 8 concurrent pre-warmed sessions before the fix). Fixed: on those codes the IF NOT EXISTS statement is re-run once (safe: the conflicting creator has committed, so the re-run is a no-op); other errors are re-thrown. After the fix the repro is 0/150 and the full 58-test suite passes.test/db.test.ts:46: The expected column list['code', 'clicks', 'created_at', 'id', 'url']is not in sorted order ('clicks' < 'code'), while the received list is.sort()ed, so this assertion can never pass; it was previously masked by the createTables race failing the same test earlier. Fixed the literal to the actual sort order['clicks', 'code', 'created_at', 'id', 'url']; the column set asserted is unchanged.Tests
All 31 scenarios of
build-shortcut-a-small-link-shortener-fo-d2hmzyhave a tagged test.The test lint found, in the run's tests on the last check:
Recorded, not decided
e2e/follow.spec.ts:1B7: no relative import: this file asserts on things it constructed itself, which is the measured 'asserted on my own mock' failuree2e/links.spec.ts:1B7: no relative import: this file asserts on things it constructed itself, which is the measured 'asserted on my own mock' failuree2e/shorten.spec.ts:1B7: no relative import: this file asserts on things it constructed itself, which is the measured 'asserted on my own mock' failuretest/click-tracking.test.ts:1B7: nothing imported here looks like the module under test ('click-tracking')test/clicks.test.ts:1B7: nothing imported here looks like the module under test ('clicks')test/link-storage.test.ts:1B7: nothing imported here looks like the module under test ('link-storage')test/list.test.ts:1B7: nothing imported here looks like the module under test ('list')test/shorten.test.ts:1B7: nothing imported here looks like the module under test ('shorten')Braid run
build-shortcut-a-small-link-shortener-fo-d2hmzy(42 steps, 2 retried)a31512e208Opened by Braid.
aa602ec78aa31512e208Build "Shortcut", a small link shortener for one team, as a new…to Built a small private link shortener: a form turns a long http/https…a31512e20877b7f1e0a3