Releases: expressjs/codemod
Release list
v1.1.0@v5-migration-recipe: feat: update package.json in v5 migration recipe (#143)
Migrate recipes for Express.js v5
This codemod migration recipe helps you update your Express.js v4 applications to be compatible with Express.js v5 by addressing deprecated APIs.
Included transformations:
- Package JSON Dependencies: Updates existing package entries in
package.jsonthat match Express.js v5 direct dependencies and related Express type packages. - Back Redirect Deprecated: This transformation updates instances of
res.redirect('back')andres.location('back')to use the recommended alternatives. Registry entry: https://app.codemod.com/registry/@expressjs/back-redirect-deprecated. - Explicit Request Params: Migrates usage of the legacy API
req.param(name)to the current recommended alternatives. Registry entry: https://app.codemod.com/registry/@expressjs/explicit-request-params. - Pluralize Method Names: Migrates deprecated singular request methods to their pluralized counterparts where applicable. Registry entry: https://app.codemod.com/registry/@expressjs/pluralize-method-names.
- Status Send Order: Migrates usages of
res.send(status),res.send(obj, status),res.json(obj, status), andres.jsonp(obj, status)to the recommended argument ordering. Registry entry: https://app.codemod.com/registry/@expressjs/status-send-order. - Redirect Arg Order: Converts
res.redirect(url, status)calls to the recommendedres.redirect(status, url)ordering. Registry entry: https://app.codemod.com/registry/@expressjs/redirect-arg-order. - Camelcase Sendfile: Replaces legacy
res.sendfile(file)usages with the camel-casedres.sendFile(file)API. Registry entry: https://app.codemod.com/registry/@expressjs/camelcase-sendfile. - Route Del to Delete: Migrates usage of the legacy APIs
app.del()toapp.delete(). Registry entry: https://app.codemod.com/registry/@expressjs/route-del-to-delete. - Static Dotfiles: Adds an explicit
dotfilesoption toexpress.static()calls and renames the removedhiddenandfromoptions to preserve Express 4 behavior. Registry entry: https://app.codemod.com/registry/@expressjs/static-dotfiles. - Static Mime: Migrates
express.static.mime(removed in Express 5) to themime-typespackage. Registry entry: https://app.codemod.com/registry/@expressjs/static-mime. - Sendfile Options: Adds an explicit
dotfilesoption tores.sendFile()calls and renames the removedhiddenandfromoptions to preserve Express 4 behavior. Registry entry: https://app.codemod.com/registry/@expressjs/sendfile-options.
References
v1.0.0@static-mime
Migrate express.static.mime
In Express 5, mime is no longer an exported property of express.static. The
mime-types package should be used to
work with MIME type values instead.
This codemod rewrites every express.static.mime reference to use a mime-types
binding and adds the corresponding import/require to the file:
- Replaces
express.static.mimewith amime-typeslocal binding (default namemime). - Adds the import once per file, matching how
expressis imported
(import mime from 'mime-types'for ESM,const mime = require('mime-types')for CommonJS). - Reuses an existing
mime-typesimport when the file already has one, and falls
back to a non-colliding name (mimeTypes) whenmimeis already taken.
The object Express 4 exposed as express.static.mime was a mime@1.x
instance, whose API is not identical to mime-types. The codemod rewrites
each member accordingly:
express.static.mime (mime@1.x) |
mime-types |
Handled by |
|---|---|---|
.lookup(path) |
.lookup(path) |
rename of the binding |
.extension(type) |
.extension(type) |
rename of the binding |
.types / .extensions |
.types / .extensions |
rename of the binding |
.charsets.lookup(type) |
.charset(type) |
method rewrite |
.define(map) |
no equivalent | flagged with a TODO comment |
.load(path) |
no equivalent | flagged with a TODO comment |
.default_type |
no equivalent | flagged with a TODO comment |
Example
import express from 'express'
+ import mime from 'mime-types'
- const type = express.static.mime.lookup('json')
+ const type = mime.lookup('json')Renamed method
- const charset = express.static.mime.charsets.lookup('text/html')
+ const charset = mime.charset('text/html')Methods without a mime-types equivalent
define, load, and default_type cannot be migrated automatically, so the
codemod points them at the new binding and flags them for manual review:
- express.static.mime.define({ 'text/x-custom': ['cstm'] })
+ mime.define({ 'text/x-custom': ['cstm'] }) /* TODO: 'mime-types' has no define(); migrate manually */CommonJS
const express = require('express')
+ const mime = require('mime-types')
- express.static.mime.lookup('json')
+ mime.lookup('json')package.json
For projects that depend on express, the codemod also adds mime-types to the
same dependency section, so the newly referenced package is declared:
"dependencies": {
- "express": "^5.0.0"
+ "express": "^5.0.0",
+ "mime-types": "^3.0.0"
}An existing mime-types entry is left untouched, and package.json files without
express are not modified.
Notes
- Behavior differs slightly even for the shared methods:
mime-typesreturns
falsefor unknown input, whereasmime@1.xlookup()fell back to
default_type(application/octet-stream). Review code that relied on that
fallback. - Members flagged with a
TODOcomment (define,load,default_type) have no
mime-typesequivalent and must be migrated by hand. - Run
npm installafter the migration so the addedmime-typesdependency is installed.
References
v1.0.0@sendfile-options: feat: add codemod to migrate res.sendFile() options for Express 5 (#149)
Migrate res.sendFile options
Express 5 changes several res.sendFile options, mirroring the express.static
changes:
- The
dotfilesoption now also applies to hidden directories in the path, not
just hidden files. In Express 4 a hidden directory in the path was served by
default; Express 5 returns a 404 Not Found unless you opt in with
dotfiles: 'allow'. - The
hiddenoption is removed and replaced bydotfiles. - The
fromoption (an undocumented alias forroot) is removed and replaced byroot.
This codemod updates res.sendFile() calls to preserve the Express 4 behavior:
- Adds an explicit
dotfiles: 'allow'option to calls that don't already specify adotfiles(orhidden) option. - Renames
hiddentodotfiles(hidden: true→dotfiles: 'allow',hidden: false→dotfiles: 'ignore'). - Renames
fromtoroot.
Only calls whose receiver is a response object (a route/middleware handler
parameter, e.g. the res in (req, res) => res.sendFile(...)) are rewritten.
Example
app.get('/build', (req, res) => {
- res.sendFile('/var/www/app/.cache/index.html')
+ res.sendFile('/var/www/app/.cache/index.html', { dotfiles: 'allow' /* Express 5: preserve v4 behavior */ })
})With existing options
- res.sendFile('index.html', { maxAge: '1d' })
+ res.sendFile('index.html', { maxAge: '1d', dotfiles: 'allow' /* Express 5: preserve v4 behavior */ })Removed hidden / from options
- res.sendFile(req.params.name, { hidden: true, from: '/uploads' })
+ res.sendFile(req.params.name, { dotfiles: 'allow', root: '/uploads' })With a trailing callback
The options object is inserted before the callback:
- res.sendFile('index.html', (err) => next(err))
+ res.sendFile('index.html', { dotfiles: 'allow' /* Express 5: preserve v4 behavior */ }, (err) => next(err))Security Consideration
After running this codemod, review each res.sendFile() call to determine if
serving dotfiles is actually necessary for your application. If you don't need to
serve dotfiles, you can:
- Remove the
dotfiles: 'allow'option to use the new Express 5 default ("ignore") - Or explicitly set
dotfiles: 'deny'to return a 403 Forbidden for dotfile requests
Note that passing a root option scopes the dotfiles check to the part of the
path relative to root, so a hidden directory in root itself is unaffected.
References
static-dotfiles@v1.0.0
Migrate express.static options
Express 5 changes several express.static options:
- The
dotfilesoption now defaults to"ignore"(Express 4 served dotfiles by default). Files inside a directory that starts with a dot (.), such as.well-known, will no longer be accessible and will return a 404 Not Found error. - The
hiddenoption is removed and replaced bydotfiles. - The
fromoption (an undocumented alias forroot) is removed and replaced byroot.
This codemod updates express.static() calls to preserve the Express 4 behavior:
- Adds an explicit
dotfiles: 'allow'option to calls that don't already specify adotfiles(orhidden) option. - Renames
hiddentodotfiles(hidden: true→dotfiles: 'allow',hidden: false→dotfiles: 'ignore'). - Renames
fromtoroot.
Example
- app.use(express.static('public'))
+ app.use(express.static('public', { dotfiles: 'allow' /* Express 5: preserve v4 behavior */ }))With existing options
- app.use(express.static('public', { maxAge: '1d' }))
+ app.use(express.static('public', { maxAge: '1d', dotfiles: 'allow' /* Express 5: preserve v4 behavior */ }))Removed hidden option
- app.use(express.static('public', { hidden: true }))
+ app.use(express.static('public', { dotfiles: 'allow' }))Removed from option
- app.use(express.static('uploads', { from: '/uploads' }))
+ app.use(express.static('uploads', { root: '/uploads', dotfiles: 'allow' /* Express 5: preserve v4 behavior */ }))Security Consideration
After running this codemod, review each express.static() call to determine if serving dotfiles is actually necessary for your application. If you don't need to serve dotfiles, you can:
- Remove the
dotfiles: 'allow'option to use the new Express 5 default ("ignore") - Or explicitly set
dotfiles: 'deny'to return a 403 Forbidden for dotfile requests
For directories like .well-known that need to be served (e.g., for Android App Links or Apple Universal Links), consider serving them explicitly:
app.use('/.well-known', express.static('public/.well-known', { dotfiles: 'allow' }))
app.use(express.static('public'))References
v5-migration-recipe@1.0.0
Migrate recipes for Express.js v5
This codemod migration recipe helps you update your Express.js v4 applications to be compatible with Express.js v5 by addressing deprecated APIs.
Included transformations:
- Back Redirect Deprecated: This transformation updates instances of
res.redirect('back')andres.location('back')to use the recommended alternatives. Registry entry: https://app.codemod.com/registry/@expressjs/back-redirect-deprecated. - Explicit Request Params: Migrates usage of the legacy API
req.param(name)to the current recommended alternatives. Registry entry: https://app.codemod.com/registry/@expressjs/explicit-request-params. - Pluralize Method Names: Migrates deprecated singular request methods to their pluralized counterparts where applicable. Registry entry: https://app.codemod.com/registry/@expressjs/pluralize-method-names.
- Status Send Order: Migrates usages of
res.send(status),res.send(obj, status),res.json(obj, status), andres.jsonp(obj, status)to the recommended argument ordering. Registry entry: https://app.codemod.com/registry/@expressjs/status-send-order. - Redirect Arg Order: Converts
res.redirect(url, status)calls to the recommendedres.redirect(status, url)ordering. Registry entry: https://app.codemod.com/registry/@expressjs/redirect-arg-order. - Camelcase Sendfile: Replaces legacy
res.sendfile(file)usages with the camel-casedres.sendFile(file)API. Registry entry: https://app.codemod.com/registry/@expressjs/camelcase-sendfile. - Route Del to Delete: Migrates usage of the legacy APIs
app.del()toapp.delete(). Registry entry: https://app.codemod.com/registry/@expressjs/route-del-to-delete.
References
route-del-to-delete@1.0.0
Migrate legacy app.del() to app.delete()
Migrates usage of the legacy APIs app.del() to app.delete().
Initially, del was used instead of delete, because delete is a reserved keyword in JavaScript. However, as of ECMAScript 6, delete and other reserved keywords can legally be used as property names. The app.del() method was deprecated in Express 4 and removed in Express 5.
Example
Migrating app.del()
The migration involves replacing instances of app.del() with app.delete().
- app.del('/some-route', (req, res) => {
+ app.delete('/some-route', (req, res) => {
// Some logic here
});References
redirect-arg-order@1.0.0
Migrate legacy res.redirect(url, status)
Migrates usage of the legacy APIs res.redirect(url, status) to the new signature
res.redirect(status, url). This usage was deprecated in Express 4, in Express 5 you must use the new signature res.redirect(status, url).
Example
Migrating res.redirect(url, status)
The migration involves replacing instances of res.redirect(url, status) with res.redirect(status, url).
app.get('/some-route', (req, res) => {
// Some logic here
- res.redirect(url, status);
+ res.redirect(status, url);
});References
explicit-request-params@1.0.0
Migrate legacy req.param(name)
The req.param(name) helper that used to magically look up values from multiple places has been removed. This potentially confusing and dangerous method of retrieving form data has been removed. You will now need to specifically look for the submitted parameter name in the req.params, req.body, or req.query object.
Examples
Replacing req.param('body') and req.param('query')
Replace req.param('body') with req.body and
req.param('query') with req.query.
app.get('/', (req, res) => {
// Before
- const reqBody = req.param('body');
- const reqQuery = req.param('query');
// After
+ const reqBody = req.body;
+ const reqQuery = req.query;
});Replacing req.param('paramName')
Replace req.param('paramName') with req.params.paramName.
app.get('/user/:id', (req, res) => {
// Before
- const userId = req.param('id');
// After
+ const userId = req.params.id;
});References
status-send-order@1.0.0
Migrate legacy res.send(obj, status), res.send(status), res.json(obj, status) and res.jsonp(obj, status)
Migrates usage of the legacy APIs res.send(obj, status), res.json(obj, status), and res.jsonp(obj, status) to use the recommended approach of specifying the status code
using the res.status(status).send(obj), res.status(status).json(obj), and
res.status(status).jsonp(obj) methods respectively. The older APIs that allowed
specifying the status code as a second argument have been deprecated.
Example
Migrating res.send(obj, status)
The migration involves replacing instances of res.send(obj, status) with res.status(status).send(obj).
app.get('/some-route', (req, res) => {
// Some logic here
- res.send(obj, status);
+ res.status(status).send(obj);
});Migrating res.json(obj, status)
The migration involves replacing instances of res.json(obj, status) with res.status(status).json(obj).
app.get('/some-route', (req, res) => {
// Some logic here
- res.json(obj, status);
+ res.status(status).json(obj);
});Migrating res.jsonp(obj, status)
The migration involves replacing instances of res.jsonp(obj, status) with res.status(status).jsonp(obj).
app.get('/some-route', (req, res) => {
// Some logic here
- res.jsonp(obj, status);
+ res.status(status).jsonp(obj);
});Migrating res.send(status)
The migration involves replacing instances of res.send(status) with res.sendStatus(status).
app.get('/some-route', (req, res) => {
// Some logic here
- res.send(status);
+ res.sendStatus(status);
});References
pluralize-method-names@1.0.0
Migrate pluralized request methods
Migrates deprecated request methods to their pluralized versions that were deprecated in Express 4 and removed in Express 5.
Example
Migrating req.acceptsCharset(charset)
The migration involves replacing instances of req.acceptsCharset(charset) with req.acceptsCharsets(charset).
app.get('/', (req, res) => {
- const charset = req.acceptsCharset('utf-8');
+ const charset = req.acceptsCharsets('utf-8');
res.json({ charset });
});Migrating `req.acceptsEncoding(encoding)
The migration involves replacing instances of req.acceptsEncoding(encoding) with req.acceptsEncodings(encoding).
app.get('/', (req, res) => {
- const encoding = req.acceptsEncoding('gzip');
+ const encoding = req.acceptsEncodings('gzip');
res.json({ encoding });
});Migrating req.acceptsLanguage(language)
The migration involves replacing instances of req.acceptsLanguage(language) with req.acceptsLanguages(language).
app.get('/', (req, res) => {
- const language = req.acceptsLanguage('en');
+ const language = req.acceptsLanguages('en');
res.json({ language });
});