Skip to content

feat: support both v4 and v5#350

Open
cesco69 wants to merge 5 commits into
dimdenGD:mainfrom
cesco69:express_v5
Open

feat: support both v4 and v5#350
cesco69 wants to merge 5 commits into
dimdenGD:mainfrom
cesco69:express_v5

Conversation

@cesco69

@cesco69 cesco69 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Adds dual Express 4/5 support through a new version option in the constructor. Default behavior remains on Express 4:

const express = require("ultimate-express");

// Express 4 behavior (default)
const app = express(); // or express({ version: 4 })

// Express 5 behavior
const app = express({ version: 5 });

Motivation

Express 5 is now the dominant version in the ecosystem:

Version Downloads (Last 7 Days) Tag
5.2.1 42,541,731 latest
4.22.2 20,748,526 latest-4

With Express 5 having more than double the weekly downloads compared to v4, it's important for ultimate-express to support both. In a future major version we may deprecate and remove v4 behavior entirely.

Full list of Express 5 changes implemented

Every behavioral divergence listed below is tested against express5 (npm:express@5) in the tests/tests/v5/ directory using the SKIP_V4 marker.

Removed APIs (throw on use)

Change Test file Behavior
app.del() removed app-del-removed.js Throws error, use app.delete()
app.param(fn) removed app-param-fn-removed.js Throws error, use app.param(name, fn)
req.param() removed req-param-removed.js Throws error, use req.params/req.body/req.query

Behavioral changes

Change Test file Behavior
Async error handling async-errors-native.js Rejected promises in handlers auto-forward to error middleware
res.status() validation res-status-validation.js Only accepts integers 100-999, throws RangeError otherwise
res.vary() validation res-vary-throws.js Throws when called without field argument
res.redirect('back') removed res-redirect-back-removed.js Treats 'back' as literal URL (no Referrer magic)
res.location('back') removed res-redirect-back-removed.js Same as above
req.query read-only req-query-readonly.js Assignment silently ignored, getter always returns parsed query
req.host includes port req-host-port.js Returns host:port instead of just host
req.params null prototype req-params-prototype.js No inherited Object methods (toString, hasOwnProperty, etc.)
res.clearCookie ignores maxAge/expires res-clearCookie.js User-provided maxAge/expires are overridden
express.urlencoded() default extended: false urlencoded-default.js Simple query parser by default (no nested objects)
express.static() dotfiles default 'ignore' static-dotfiles.js Dot-files and dot-directories return 404
app.listen() error handling app-listen-error.js Passes error to callback instead of throwing

Path route matching (new syntax)

Change Test file Behavior
Named wildcards /*splat path-matching-splat.js Wildcard must have a name, captures as array
Root-matching wildcard /{*splat} path-matching-splat.js Also matches / (splat is undefined)
Optional groups /:file{.:ext} path-matching-optional.js Braces for optional segments instead of ?
Regex chars in paths not supported - +, (), [], ? are treated as literals or throw

What's NOT yet implemented (left to do)

Express 5 feature Status Notes
res.sendFile() hidden/from options rejection N/A Options were never implemented in ultimate-express
router.param() rejects array of names Not implemented Edge case, requires a lot of changes
express.static.mime removed Not implemented Would need to remove the export
MIME type changes (.jstext/javascript) Not implemented Depends on mime-db version used
express:router debug namespace change N/A ultimate-express doesn't use debug module
res.render() enforced async Not implemented Current implementation may already be async depending on engine
Brotli decompression in body middleware Already supported Was implemented before this PR

Tests

Added 16 tests in tests/tests/v5/ with SKIP_V4 marker. Each test:

  1. Is skipped for Express 4 comparison (uses SKIP_V4 marker)
  2. Runs against native express@5 (via express5 package in devDependencies)
  3. Runs against ultimate-express with version: 5

close #83

@cesco69 cesco69 changed the title feat: support both v4 and v5 [WIP] feat: support both v4 and v5 Jul 16, 2026
@cesco69
cesco69 marked this pull request as ready for review July 16, 2026 13:28
@dimdenGD

Copy link
Copy Markdown
Owner

For this to be merged, provide full list of changes and what's left to support Express 5. Also looking at your tests, it seems that you test against express and not express5 ("express5": "npm:express@5" in package.json). Every Expess 5 divergence should be tested.

@cesco69

cesco69 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the feedback. I've updated the PR. I also fixed two behaviors I got wrong in the first iteration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat]: express v5 compatibility

2 participants