feat: ✨ add more NodeJS-specific rules
This commit is contained in:
12
.changeset/chilly-tigers-promise.md
Normal file
12
.changeset/chilly-tigers-promise.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
"@eslegant/js": minor
|
||||
---
|
||||
|
||||
Added rules for NodeJS environments, using the eslint-plugin-n and eslint-plugin-security.
|
||||
|
||||
The added configs in the `recommended` object helps preventing issues
|
||||
such as using deprecated or unsupported APIs and warns about security issues.
|
||||
Building on top of the recommended configs of the plugins.
|
||||
|
||||
In the `strict` object they helps making the code more node-explicit, such as importing
|
||||
global variables (e.g. `process` needs to be imported from `node:process`).
|
||||
@@ -3,7 +3,7 @@
|
||||
This is a list of rules that implements the same features and/or end
|
||||
up fixing the same errors.
|
||||
|
||||
- **[`@typescript/member-ordering`][ts/member-ordering], [`@typescript/sort-type-constituents`][ts/sort-type-constituents], [`import/order`][in/order]**:
|
||||
- **[`@typescript/member-ordering`][ts/member-ordering], [`@typescript/sort-type-constituents`][ts/sort-type-constituents], [`import/order`][im/order]**:
|
||||
implements the same functions from [`eslint-plugin-perfectionist`][plugin-perfectionist]
|
||||
|
||||
- **[`unicorn/no-for-loop`][un/no-for-loop] and [`@typescript/prefer-for-of`][ts/prefer-for-of]**:
|
||||
@@ -15,6 +15,14 @@ up fixing the same errors.
|
||||
- **[`@typescript/prefer-regexp-exec`][ts/prefer-regexp-exec] and [`unicorn/prefer-regexp-test`][un/prefer-regexp-test]**:
|
||||
`unicorn/prefer-regexp-exec` was used, because it reports on `RegExp#exec()` and `String#match()`
|
||||
|
||||
- **[`import/extensions`][im/extensions] and [`n/file-extension-in-import`][n/file-extension-in-import]**:
|
||||
`import/extensions` was used, as it is not a node-specific issue.
|
||||
|
||||
- **[`import/no-extraneous-dependencies`][im/no-extraneous-dependencies], [`n/no-extraneous-require`][n/no-extraneous-require] and [`n/no-extraneous-import`][n/no-extraneous-import]**:
|
||||
`import/no-extraneous-dependencies` was used, as it is not a node-specific issue.
|
||||
|
||||
- **[`import/no-unresolved`][im/no-unresolved], [`n/no-missing-require`][n/no-missing-require] and [`n/no-missing-import`][n/no-missing-import]**:
|
||||
`import/no-unresolved` was used, as it is not a node-specific issue.
|
||||
|
||||
[ts/member-ordering]: <https://typescript-eslint.io/rules/member-ordering>
|
||||
[ts/prefer-for-of]: <https://typescript-eslint.io/rules/prefer-for-of>
|
||||
@@ -22,10 +30,19 @@ up fixing the same errors.
|
||||
[ts/prefer-regexp-exec]: <https://typescript-eslint.io/rules/prefer-regexp-exec>
|
||||
[ts/sort-type-constituents]: <https://typescript-eslint.io/rules/sort-type-constituents>
|
||||
|
||||
[un/no-for-loop]: <https://github.com/sindresorhus/eslint-plugin-unicorn/blob/6d15a02d48de7ecfc38d0683a8487b2f937d83a0/docs/rules/no-for-loop.md>
|
||||
[un/prefer-includes]: <https://github.com/sindresorhus/eslint-plugin-unicorn/blob/6d15a02d48de7ecfc38d0683a8487b2f937d83a0/docs/rules/prefer-includes.md>
|
||||
[un/prefer-regexp-test]: <https://github.com/sindresorhus/eslint-plugin-unicorn/blob/6d15a02d48de7ecfc38d0683a8487b2f937d83a0/docs/rules/prefer-regexp-test.md>
|
||||
[un/no-for-loop]: <https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-for-loop.md>
|
||||
[un/prefer-includes]: <https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-includes.md>
|
||||
[un/prefer-regexp-test]: <https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-regexp-test.md>
|
||||
|
||||
[in/order]: <https://github.com/import-js/eslint-plugin-import/blob/6b95a021938139726b3f862beb37012d6e2afab2/docs/rules/order.md>
|
||||
[im/order]: <https://github.com/import-js/eslint-plugin-import/blob/maib/docs/rules/order.md>
|
||||
[im/extensions]: <https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/extensions.md>
|
||||
[im/no-extraneous-dependencies]: <https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-extraneous-dependencies.md>
|
||||
[im/no-unresolved]: <https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-unresolved.md>
|
||||
|
||||
[n/file-extension-in-import]: <https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/file-extension-in-import.md>
|
||||
[n/no-extraneous-import]: <https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-extraneous-import.md>
|
||||
[n/no-extraneous-require]: <https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-extraneous-require.md>
|
||||
[n/no-missing-import]: <https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-missing-import.md>
|
||||
[n/no-missing-require]: <https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-missing-require.md>
|
||||
|
||||
[plugin-perfectionist]: <https://eslint-plugin-perfectionist.azat.io/>
|
||||
|
||||
@@ -46,7 +46,9 @@
|
||||
"eslint-import-resolver-typescript": "^3.6.0",
|
||||
"eslint-plugin-i": "2.28.0-2",
|
||||
"eslint-plugin-jsdoc": "^46.5.0",
|
||||
"eslint-plugin-n": "^16.0.2",
|
||||
"eslint-plugin-perfectionist": "^1.5.1",
|
||||
"eslint-plugin-security": "^1.7.1",
|
||||
"eslint-plugin-unicorn": "^48.0.1",
|
||||
"globals": "^13.21.0"
|
||||
},
|
||||
|
||||
24
configs/js/src/@types/eslint-plugin-n.d.ts
vendored
Normal file
24
configs/js/src/@types/eslint-plugin-n.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @file
|
||||
* Type declaration for the `eslint-plugin-n` package in a attempt to make it
|
||||
* compatible with the new flat config.
|
||||
* @license MIT
|
||||
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
|
||||
*/
|
||||
|
||||
import type { ESLint } from 'eslint';
|
||||
|
||||
/**
|
||||
* @summary Additional ESLint's rules for Node.js.
|
||||
*
|
||||
* ---
|
||||
* **Note:** Types in this project where overridden to be compatible with
|
||||
* ESLint new flat config types. ESlint already has backwards compatibility
|
||||
* for plugins not created in the new flat config.
|
||||
* @see {@link https://www.npmjs.com/package/eslint-plugin-n npm package}
|
||||
*/
|
||||
declare module 'eslint-plugin-n' {
|
||||
declare const plugin: ESLint.Plugin;
|
||||
export default plugin;
|
||||
}
|
||||
|
||||
24
configs/js/src/@types/eslint-plugin-security.d.ts
vendored
Normal file
24
configs/js/src/@types/eslint-plugin-security.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @file
|
||||
* Type declaration for the `eslint-plugin-security` package in a attempt to make it
|
||||
* compatible with the new flat config.
|
||||
* @license MIT
|
||||
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
|
||||
*/
|
||||
|
||||
import type { ESLint } from 'eslint';
|
||||
|
||||
/**
|
||||
* @summary ESLint rules for Node Security.
|
||||
*
|
||||
* ---
|
||||
* **Note:** Types in this project where overridden to be compatible with
|
||||
* ESLint new flat config types. ESlint already has backwards compatibility
|
||||
* for plugins not created in the new flat config.
|
||||
* @see {@link https://www.npmjs.com/package/eslint-plugin-security npm package}
|
||||
*/
|
||||
declare module 'eslint-plugin-security' {
|
||||
declare const plugin: ESLint.Plugin;
|
||||
export default plugin;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
|
||||
*/
|
||||
|
||||
import process from 'node:process';
|
||||
|
||||
import tsESLint from '@typescript-eslint/eslint-plugin';
|
||||
import securityPlugin from 'eslint-plugin-security';
|
||||
import unicornPlugin from 'eslint-plugin-unicorn';
|
||||
// @ts-expect-error because the package doesn't export correct types
|
||||
import tsParser from '@typescript-eslint/parser';
|
||||
@@ -17,6 +20,7 @@ import globals from 'globals';
|
||||
// eslint-disable-next-line import/no-relative-parent-imports
|
||||
import { jsFiles, tsFiles } from '../constants.js';
|
||||
|
||||
|
||||
/** @type {import('eslint').Linter.FlatConfig} */
|
||||
const config = {
|
||||
files: [...tsFiles, ...jsFiles],
|
||||
@@ -40,6 +44,8 @@ const config = {
|
||||
'import': importPlugin,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
'jsdoc': jsdocPlugin,
|
||||
// @ts-expect-error because eslint-plugin-security doesn't export correct types
|
||||
'security': securityPlugin,
|
||||
// @ts-expect-error because eslint-plugin-unicorn doesn't export correct types
|
||||
'unicorn': unicornPlugin,
|
||||
},
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable import/no-relative-parent-imports */
|
||||
/* eslint-disable unicorn/no-useless-spread */
|
||||
/**
|
||||
* @file
|
||||
* Configuration objects for the NodeJS environment.
|
||||
@@ -6,13 +8,24 @@
|
||||
* @author Guz013 <contact.guz013@gmail.com> (https://guz.one)
|
||||
*/
|
||||
|
||||
/* eslint-disable import/no-relative-parent-imports */
|
||||
/* eslint-disable unicorn/no-useless-spread */
|
||||
import nodePlugin from 'eslint-plugin-n';
|
||||
import globals from 'globals';
|
||||
|
||||
import { createVariations } from '../../lib/rule-variations.js';
|
||||
import { jsFiles, tsFiles } from '../../constants.js';
|
||||
|
||||
const commonjs = createVariations({
|
||||
files: ['**/*.cts', '**/*.cjs'],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.nodeBuiltin,
|
||||
...globals.commonjs,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
// @ts-expect-error because types are not defined in 'eslint-plugin-n'
|
||||
n: nodePlugin,
|
||||
},
|
||||
rules: {
|
||||
...{}, // Plugin: @typescript-eslint/eslint-plugin
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
@@ -23,17 +36,52 @@ const commonjs = createVariations({
|
||||
|
||||
...{}, // Plugin: eslint-plugin-import
|
||||
'import/no-commonjs': 'off',
|
||||
|
||||
...{}, // Plugin: eslint-plugin-n
|
||||
'n/global-require': 'error',
|
||||
'n/no-exports-assign': 'error',
|
||||
|
||||
...{}, // Plugin: eslint-plugin-security
|
||||
'security/detect-non-literal-require': 'error',
|
||||
},
|
||||
});
|
||||
|
||||
const recommended = createVariations({
|
||||
files: [...tsFiles, ...jsFiles],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.nodeBuiltin,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
// @ts-expect-error because types are not defined in 'eslint-plugin-n'
|
||||
n: nodePlugin,
|
||||
},
|
||||
rules: {
|
||||
...{}, // Plugin: eslint-plugin-unicorn
|
||||
'unicorn/prefer-node-protocol': 'error',
|
||||
|
||||
...{}, // Plugin: eslint-plugin-import
|
||||
'import/no-dynamic-require': 'error',
|
||||
|
||||
...{}, // Plugin: eslint-plugin-n
|
||||
'n/no-deprecated-api': 'error',
|
||||
'n/no-process-exit': 'error',
|
||||
'n/no-unpublished-bin': 'error',
|
||||
'n/no-unpublished-import': 'error',
|
||||
'n/no-unpublished-require': 'error',
|
||||
'n/no-unsupported-features/es-builtins': 'error',
|
||||
'n/no-unsupported-features/es-syntax': 'error',
|
||||
'n/no-unsupported-features/node-builtins': 'error',
|
||||
'n/process-exit-as-throw': 'error',
|
||||
'n/shebang': 'error',
|
||||
|
||||
...{}, // Plugin: eslint-plugin-security
|
||||
'security/detect-buffer-noassert': 'warn',
|
||||
'security/detect-child-process': 'warn',
|
||||
'security/detect-new-buffer': 'warn',
|
||||
'security/detect-no-csrf-before-method-override': 'warn',
|
||||
'security/detect-non-literal-fs-filename': 'warn',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -41,6 +89,26 @@ const strict = createVariations({
|
||||
...recommended.error,
|
||||
rules: {
|
||||
...recommended.error.rules,
|
||||
|
||||
...{}, // Plugin: eslint-plugin-n
|
||||
'n/no-new-require': 'error',
|
||||
'n/no-path-concat': 'error',
|
||||
'n/prefer-global/buffer': ['error', 'never'],
|
||||
'n/prefer-global/console': ['error', 'always'],
|
||||
'n/prefer-global/process': ['error', 'never'],
|
||||
'n/prefer-global/text-decoder': ['error', 'always'],
|
||||
'n/prefer-global/text-encoder': ['error', 'always'],
|
||||
'n/prefer-global/url': ['error', 'always'],
|
||||
'n/prefer-global/url-search-params': ['error', 'always'],
|
||||
'n/prefer-promises/dns': 'error',
|
||||
'n/prefer-promises/fs': 'error',
|
||||
|
||||
...{}, // Plugin: eslint-plugin-security
|
||||
'security/detect-buffer-noassert': 'error',
|
||||
'security/detect-child-process': 'error',
|
||||
'security/detect-new-buffer': 'error',
|
||||
'security/detect-no-csrf-before-method-override': 'error',
|
||||
'security/detect-non-literal-fs-filename': 'warn',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
52
pnpm-lock.yaml
generated
52
pnpm-lock.yaml
generated
@@ -60,9 +60,15 @@ importers:
|
||||
eslint-plugin-jsdoc:
|
||||
specifier: ^46.5.0
|
||||
version: 46.5.0(eslint@8.47.0)
|
||||
eslint-plugin-n:
|
||||
specifier: ^16.0.2
|
||||
version: 16.0.2(eslint@8.47.0)
|
||||
eslint-plugin-perfectionist:
|
||||
specifier: ^1.5.1
|
||||
version: 1.5.1(eslint@8.47.0)(typescript@5.1.6)
|
||||
eslint-plugin-security:
|
||||
specifier: ^1.7.1
|
||||
version: 1.7.1
|
||||
eslint-plugin-unicorn:
|
||||
specifier: ^48.0.1
|
||||
version: 48.0.1(eslint@8.47.0)
|
||||
@@ -1496,6 +1502,12 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/builtins@5.0.1:
|
||||
resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==}
|
||||
dependencies:
|
||||
semver: 7.5.4
|
||||
dev: false
|
||||
|
||||
/busboy@1.6.0:
|
||||
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
|
||||
engines: {node: '>=10.16.0'}
|
||||
@@ -2016,6 +2028,17 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/eslint-plugin-es-x@7.2.0(eslint@8.47.0):
|
||||
resolution: {integrity: sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: '>=8'
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0)
|
||||
'@eslint-community/regexpp': 4.7.0
|
||||
eslint: 8.47.0
|
||||
dev: false
|
||||
|
||||
/eslint-plugin-i@2.28.0-2(@typescript-eslint/parser@6.4.1)(eslint-import-resolver-typescript@3.6.0)(eslint@8.47.0):
|
||||
resolution: {integrity: sha512-z48kG4qmE4TmiLcxbmvxMT5ycwvPkXaWW0XpU1L768uZaTbiDbxsHMEdV24JHlOR1xDsPpKW39BfP/pRdYIwFA==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -2094,6 +2117,23 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/eslint-plugin-n@16.0.2(eslint@8.47.0):
|
||||
resolution: {integrity: sha512-Y66uDfUNbBzypsr0kELWrIz+5skicECrLUqlWuXawNSLUq3ltGlCwu6phboYYOTSnoTdHgTLrc+5Ydo6KjzZog==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
peerDependencies:
|
||||
eslint: '>=7.0.0'
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0)
|
||||
builtins: 5.0.1
|
||||
eslint: 8.47.0
|
||||
eslint-plugin-es-x: 7.2.0(eslint@8.47.0)
|
||||
ignore: 5.2.4
|
||||
is-core-module: 2.13.0
|
||||
minimatch: 3.1.2
|
||||
resolve: 1.22.4
|
||||
semver: 7.5.4
|
||||
dev: false
|
||||
|
||||
/eslint-plugin-perfectionist@1.5.1(eslint@8.47.0)(typescript@5.1.6):
|
||||
resolution: {integrity: sha512-PiUrAfGDc/l6MKKUP8qt5RXueC7FZC6F/0j8ijXYU8o3x8o2qUi6zEEYBkId/IiKloIXM5KTD4jrH9833kDNzA==}
|
||||
peerDependencies:
|
||||
@@ -2111,6 +2151,12 @@ packages:
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
/eslint-plugin-security@1.7.1:
|
||||
resolution: {integrity: sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==}
|
||||
dependencies:
|
||||
safe-regex: 2.1.1
|
||||
dev: false
|
||||
|
||||
/eslint-plugin-svelte@2.30.0(eslint@8.44.0)(svelte@4.0.5):
|
||||
resolution: {integrity: sha512-2/qj0BJsfM0U2j4EjGb7iC/0nbUvXx1Gn78CdtyuXpi/rSomLPCPwnsZsloXMzlt6Xwe8LBlpRvZObSKEHLP5A==}
|
||||
engines: {node: ^14.17.0 || >=16.0.0}
|
||||
@@ -3600,6 +3646,12 @@ packages:
|
||||
get-intrinsic: 1.2.1
|
||||
is-regex: 1.1.4
|
||||
|
||||
/safe-regex@2.1.1:
|
||||
resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==}
|
||||
dependencies:
|
||||
regexp-tree: 0.1.27
|
||||
dev: false
|
||||
|
||||
/safer-buffer@2.1.2:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
dev: true
|
||||
|
||||
Reference in New Issue
Block a user