chore(deps): upgrade to express 5 - #232
Merged
Merged
Conversation
Bumps express 4.22.2 to 5.2.1 and @types/express to match. The HTTP contract is
unchanged: each default Express 5 alters is pinned or restored.
Query schema validation had stopped applying. Express 5 exposes req.query as a
getter with no setter that re-reads the URL on every access, so the assignment in
defineRoute threw and every route carrying a query schema answered 404. The
validated query is now installed as an own property so the schema's coercions
survive into the handler.
The default query parser moved from extended to simple, which would read a[b]=1
as the literal key "a[b]". Pinned back to extended so upgrading never silently
changes how a caller's query string parses.
A request with no body now arrives as undefined rather than {}. Bodies are
validated as {} when absent, so a body-less request still reports its missing
fields, and DELETE /admin/users answers "User not found." instead of throwing.
path-to-regexp v8 rejects a bare "*", so the SPA history fallback is now
/console/*splat.
Route params are typed through a new RouteRequest, since Express 5 widens
req.params to string | string[] for repeatable params this API does not use.
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.
Supersedes #198, which was a version bump only. Express 5 broke four things here that needed real work.
What broke, and why
Every route with a query schema returned 404. Express 5 exposes
req.queryas a getter with no setter, and one that re-parses the URL on every read, so the assignment indefineRoutethrew. That silently took out/internal/auth-events/*,/admin/auth-events, and/webauthn/register/start. The validated query is now installed as an own data property, which is also what makes the schema's coercions survive into the handler.The default query parser moved from
extendedtosimple, which would reada[b]=1as the literal keya[b]. Pinned back toextended. The dashboard sends flat repeated keys (type=x&type=y) and the React SDK usesURLSearchParams, so nothing in tree depends on the difference, but an outside integrator might, and a dependency bump is the wrong place to change how query strings parse. Moving to the narrower parser stays available as a deliberate change, and is worth considering on its own:simpleavoids theqsdeep nesting surface.A request with no body now arrives as
undefinedrather than{}. Bodies are validated as{}when absent, so a body-less request still reports its missing fields instead of one opaque "expected object, received undefined".DELETE /admin/usersdestructuredreq.bodyunguarded and threw aTypeErroron a body-less call, so it now answersUser not found.as it did before.The SPA history fallback route no longer parsed. path-to-regexp v8 rejects a bare
*, so/console/*is now the named/console/*splat. This was failing at registration time and crashing the wholeadminDashboardintegration file.Types
Route params go through a new
RouteRequest, since Express 5 widensreq.paramstostring | string[]for the repeatable params this API does not use. That covers the 26 type errors without casting at each site.Contract
No contract change. Every default Express 5 alters is pinned or restored, so no caller has to adapt and the SDKs need no coordinated release.
Verification
npm run typecheck,npm run lint,npm run format:check: cleannpm run test:run: 1194 passed, 1 skipped (the raw bump was 1144 passed / 43 failed)npm run coverage: 98.79% statements, 96.36% branches, both above thresholdNoticed but not touched
Filed separately rather than folded in here: #229 (
npm run builddoes not cleandist/), #230 (non-CORS errors answer 404 instead of 500), #231 (global rate limiters have no test coverage).