Skip to content

Commit

Permalink
prefer-node-protocol: Add checkRequire option (#1206)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
fisker and sindresorhus committed Apr 23, 2021
1 parent f1f30c3 commit 8d8411b
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 2 deletions.
18 changes: 18 additions & 0 deletions docs/rules/prefer-node-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,21 @@ import _ from 'lodash';
```js
import fs from './fs.js';
```

## Options

Type: `object`

### `checkRequire`

Type: `boolean`\
Default: `false`

Currently, `require(…)` with the `node:` protocol is only available on Node.js 16. If you don't care about old versions, you can set this to `true`.

We'll remove this option and check `require(…)` by default once this feature get backported to v12.

```js
// eslint unicorn/prefer-node-protocol: ["error", {"checkRequire": true}]
const fs = require('fs'); // Fails
```
35 changes: 33 additions & 2 deletions rules/prefer-node-protocol.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,32 @@ const messages = {
[MESSAGE_ID]: 'Prefer `node:{{moduleName}}` over `{{moduleName}}`.'
};

const selector = [
const importExportSelector = [
':matches(ImportDeclaration, ExportNamedDeclaration, ImportExpression)',
' > ',
'Literal.source'
].join('');

const requireSelector = [
'CallExpression',
'[optional!=true]',
'[callee.type="Identifier"]',
'[callee.name="require"]',
'[arguments.length=1]',
' > ',
'Literal.arguments'
].join('');

/** @param {import('eslint').Rule.RuleContext} context */
const create = context => {
const {checkRequire} = {
checkRequire: false,
...context.options[0]
};
const selector = checkRequire ?
`:matches(${importExportSelector}, ${requireSelector})` :
importExportSelector;

return {
[selector](node) {
const {value} = node;
Expand All @@ -38,6 +56,19 @@ const create = context => {
};
};

const schema = [
{
type: 'object',
properties: {
checkRequire: {
type: 'boolean',
default: false
}
},
additionalProperties: false
}
];

module.exports = {
create,
meta: {
Expand All @@ -47,7 +78,7 @@ module.exports = {
url: getDocumentationUrl(__filename)
},
fixable: 'code',
schema: [],
schema,
messages
}
};
23 changes: 23 additions & 0 deletions test/prefer-node-protocol.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,29 @@ test.snapshot({
]
});

// `options`
const checkRequireOptions = [{checkRequire: true}];
test.snapshot({
valid: [
'const fs = require("node:fs");',
'const fs = require("node:fs/promises");',
'const fs = require(fs);',
'const fs = notRequire("fs");',
'const fs = foo.require("fs");',
'const fs = require.resolve("fs");',
'const fs = require(`fs`);',
'const fs = require?.("fs");',
'const fs = require("fs", extra);',
'const fs = require();',
'const fs = require(...["fs"]);',
'const fs = require("unicorn");'
].map(code => ({code, options: checkRequireOptions})),
invalid: [
'const {promises} = require("fs")',
'const fs = require(\'fs/promises\')'
].map(code => ({code, options: checkRequireOptions}))
});

test.babel({
valid: [
'export fs from "node:fs";'
Expand Down
52 changes: 52 additions & 0 deletions test/snapshots/prefer-node-protocol.mjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,55 @@ Generated by [AVA](https://avajs.dev).
> 1 | import "timers/promises";␊
| ^^^^^^^^^^^^^^^^^ Prefer \`node:timers/promises\` over \`timers/promises\`.␊
`

## Invalid #1
1 | const {promises} = require("fs")

> Options
`␊
[␊
{␊
"checkRequire": true␊
}␊
]␊
`

> Output
`␊
1 | const {promises} = require("node:fs")␊
`

> Error 1/1
`␊
> 1 | const {promises} = require("fs")␊
| ^^^^ Prefer \`node:fs\` over \`fs\`.␊
`

## Invalid #2
1 | const fs = require('fs/promises')

> Options
`␊
[␊
{␊
"checkRequire": true␊
}␊
]␊
`

> Output
`␊
1 | const fs = require('node:fs/promises')␊
`

> Error 1/1
`␊
> 1 | const fs = require('fs/promises')␊
| ^^^^^^^^^^^^^ Prefer \`node:fs/promises\` over \`fs/promises\`.␊
`
Binary file modified test/snapshots/prefer-node-protocol.mjs.snap
Binary file not shown.

0 comments on commit 8d8411b

Please sign in to comment.