Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions codemods/pluralize-method-names/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# 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)`.

```diff
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)`.

```diff
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)`.

```diff
app.get('/', (req, res) => {
- const language = req.acceptsLanguage('en');
+ const language = req.acceptsLanguages('en');
res.json({ language });
});
```

## References

- [Migration of pluralized request methods](https://expressjs.com/en/guide/migrating-5.html#plural)
26 changes: 26 additions & 0 deletions codemods/pluralize-method-names/codemod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
schema_version: "1.0"
name: "@expressjs/pluralize-method-names"
version: "1.0.0"
description: Migrates usage of deprecated singular request methods to their pluralized versions in Express.js applications.
author: bjohansebas (Sebastian Beltran)
license: MIT
workflow: workflow.yaml
category: migration

targets:
languages:
- javascript
- typescript

keywords:
- transformation
- migration
- express
- accepts
- accepetsCharsets
- acceptsEncodings
- acceptsLanguages

registry:
access: public
visibility: public
22 changes: 22 additions & 0 deletions codemods/pluralize-method-names/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "@expressjs/pluralize-method-names",
"private": true,
"version": "1.0.0",
"description": "Migrates usage of deprecated singular request methods to their pluralized versions in Express.js applications.",
"type": "module",
"scripts": {
"test": "npx codemod jssg test -l typescript ./src/workflow.ts ./"
},
"repository": {
"type": "git",
"url": "git+https://github.com/expressjs/codemod.git",
"directory": "codemods/pluralize-method-names",
"bugs": "https://github.com/expressjs/codemod/issues"
},
"author": "bjohansebas (Sebastian Beltran)",
"license": "MIT",
"homepage": "https://github.com/expressjs/codemod/blob/main/codemods/pluralize-method-names/README.md",
"devDependencies": {
"@codemod.com/jssg-types": "^1.3.1"
}
}
38 changes: 38 additions & 0 deletions codemods/pluralize-method-names/src/workflow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type Js from '@codemod.com/jssg-types/src/langs/javascript'
import type { Edit, SgRoot } from '@codemod.com/jssg-types/src/main'

async function transform(root: SgRoot<Js>): Promise<string | null> {
const rootNode = root.root()

const nodes = rootNode.findAll({
rule: {
any: [
{ pattern: '$OBJ.$METHOD($ARG)' },
{
pattern: '$OBJ.$METHOD()',
},
],
},
constraints: {
METHOD: { regex: '^(acceptsCharset|acceptsEncoding|acceptsLanguage)$' },
},
})

const edits: Edit[] = []

for (const call of nodes) {
const method = call.getMatch('METHOD')
const obj = call.getMatch('OBJ')
if (!obj || !method) continue

const objDef = obj.definition({ resolveExternal: false })
if (!objDef) continue

edits.push(method.replace(`${method.text()}s`))
}

if (edits.length === 0) return null
return rootNode.commitEdits(edits)
}

export default transform
19 changes: 19 additions & 0 deletions codemods/pluralize-method-names/tests/expected/charset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import express from 'express'

const app = express()

app.get('/', (req, res) => {
const charset = req.acceptsCharsets();
res.json({ charset });
});


app.get('/', (req, res) => {
const charset = req.acceptsCharsets('utf-8');
res.json({ charset });
});

app.get('/', function (request, response) {
const charset = request.acceptsCharsets('utf-8');
response.json({ charset });
});
18 changes: 18 additions & 0 deletions codemods/pluralize-method-names/tests/expected/encoding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import express from 'express'

const app = express()

app.get('/', (req, res) => {
const encoding = req.acceptsEncodings();
res.json({ encoding });
});

app.get('/', (req, res) => {
const encoding = req.acceptsEncodings('gzip');
res.json({ encoding });
});

app.get('/', function (request, response) {
const encoding = request.acceptsEncodings('gzip');
response.json({ encoding });
});
18 changes: 18 additions & 0 deletions codemods/pluralize-method-names/tests/expected/language.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import express from 'express'

const app = express()

app.get('/', (req, res) => {
const encoding = req.acceptsLanguages();
res.json({ encoding });
});

app.get('/', (req, res) => {
const encoding = req.acceptsLanguages('gzip');
res.json({ encoding });
});

app.get('/', function (request, response) {
const encoding = request.acceptsLanguages('gzip');
response.json({ encoding });
});
19 changes: 19 additions & 0 deletions codemods/pluralize-method-names/tests/input/charset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import express from 'express'

const app = express()

app.get('/', (req, res) => {
const charset = req.acceptsCharset();
res.json({ charset });
});


app.get('/', (req, res) => {
const charset = req.acceptsCharset('utf-8');
res.json({ charset });
});

app.get('/', function (request, response) {
const charset = request.acceptsCharset('utf-8');
response.json({ charset });
});
18 changes: 18 additions & 0 deletions codemods/pluralize-method-names/tests/input/encoding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import express from 'express'

const app = express()

app.get('/', (req, res) => {
const encoding = req.acceptsEncoding();
res.json({ encoding });
});

app.get('/', (req, res) => {
const encoding = req.acceptsEncoding('gzip');
res.json({ encoding });
});

app.get('/', function (request, response) {
const encoding = request.acceptsEncoding('gzip');
response.json({ encoding });
});
18 changes: 18 additions & 0 deletions codemods/pluralize-method-names/tests/input/language.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import express from 'express'

const app = express()

app.get('/', (req, res) => {
const encoding = req.acceptsLanguage();
res.json({ encoding });
});

app.get('/', (req, res) => {
const encoding = req.acceptsLanguage('gzip');
res.json({ encoding });
});

app.get('/', function (request, response) {
const encoding = request.acceptsLanguage('gzip');
response.json({ encoding });
});
28 changes: 28 additions & 0 deletions codemods/pluralize-method-names/workflow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/codemod-com/codemod/refs/heads/main/schemas/workflow.json

version: "1"

nodes:
- id: apply-transforms
name: Apply AST Transformations
type: automatic
runtime:
type: direct
steps:
- name: Migrates usage of deprecated singular request methods to their pluralized versions in Express.js applications.
js-ast-grep:
js_file: src/workflow.ts
base_path: .
semantic_analysis: file
include:
- "**/*.cjs"
- "**/*.js"
- "**/*.jsx"
- "**/*.mjs"
- "**/*.cts"
- "**/*.mts"
- "**/*.ts"
- "**/*.tsx"
exclude:
- "**/node_modules/**"
language: typescript