eslint-config-webpack
Version:
Provides Webpack's eslint rules as an extensible shared config
361 lines (305 loc) • 7.51 kB
JavaScript
import importPlugin from "eslint-plugin-import";
import globals from "globals";
import isTypescriptInstalled from "./utils/is-typescript-installed.js";
/** @type {import("eslint").Linter.Config["rules"]} */
const commonRules = {
// No need
// "n/callback-return": "error",
// Depends on `sourceType` and enabled below only for commonjs
// "n/exports-style": "error",
// We have the `import/extensions` rule
"n/file-extension-in-import": "off",
// There is no need, as in some cases we want to load a module lazily.
// "n/global-require": "error",
// No need
// "n/handle-callback-err": "error"
// From recommended
// "n/hashbang": "error",
// No need
// "n/no-callback-literal": "error",
// From recommended
// "n/no-deprecated-api": "error",
// From recommended
// "n/no-exports-assign": "error",
// We have `import/no-extraneous-dependencies` rule
"n/no-extraneous-import": "off",
// We have `import/no-extraneous-dependencies` rule
"n/no-extraneous-require": "off",
// Deprecated
// "n/no-hide-core-modules": "error",
// We have `import/no-unresolved` rule
"n/no-missing-import": "off",
// We have `import/no-unresolved` rule
"n/no-missing-require": "off",
// No need
// "n/no-mixed-requires": "error",
// No need
// "n/no-new-require": "error",
// Depends on `sourceType` and enabled below only for commonjs
// "n/no-path-concat": "error",
// No need
// "n/no-process-env": "error",
// From recommended
// "n/no-process-exit": "error",
// No need
// "n/no-restricted-import": ["error", []],
// No need
// "n/no-restricted-require": ["error", []]
// No need
// "n/no-sync": "error",
// No need
// "n/no-top-level-await": "error",
"n/no-unpublished-bin": "error",
// From recommended
// "n/no-unpublished-import": "error",
// From recommended
// "n/no-unpublished-require": "error",
// From recommended
// "n/no-unsupported-features/es-builtins": "error",
// From recommended (override)
"n/no-unsupported-features/es-syntax": [
"error",
{
ignores: ["error-cause"],
},
],
// "n/no-unsupported-features/es-syntax": "error",
// From recommended (override to ignore test module)
"n/no-unsupported-features/node-builtins": [
"error",
{
ignores: [
"test",
"test.after",
"test.afterEach",
"test.assert",
"test.assert.register",
"test.before",
"test.beforeEach",
"test.describe",
"test.describe.only",
"test.describe.skip",
"test.describe.todo",
"test.it",
"test.it.only",
"test.it.skip",
"test.it.todo",
"test.mock",
"test.mock.fn",
"test.mock.getter",
"test.mock.method",
"test.mock.module",
"test.mock.reset",
"test.mock.restoreAll",
"test.mock.setter",
"test.mock.timers",
"test.mock.timers.enable",
"test.mock.timers.reset",
"test.mock.timers.tick",
"test.only",
"test.run",
"test.snapshot",
"test.snapshot.setDefaultSnapshotSerializers",
"test.snapshot.setResolveSnapshotPath",
"test.skip",
"test.suite",
"test.test",
"test.test.only",
"test.test.skip",
"test.test.todo",
"test.todo",
],
},
],
"n/prefer-global/buffer": ["error", "always"],
"n/prefer-global/console": ["error", "always"],
"n/prefer-global/crypto": ["error", "always"],
"n/prefer-global/process": ["error", "always"],
"n/prefer-global/text-decoder": ["error", "always"],
"n/prefer-global/text-encoder": ["error", "always"],
"n/prefer-global/timers": ["error", "always"],
"n/prefer-global/url": ["error", "always"],
"n/prefer-global/url-search-params": ["error", "always"],
"n/prefer-node-protocol": "error",
// No need
// "n/prefer-promises/dns": "error",
// No need
// "n/prefer-promises/fs": "error",
// From recommended
// "n/process-exit-as-throw": "error",
};
const ignores = ["**/*.d.ts"];
/**
* @returns {Promise<import("eslint").Linter.Config>} config
*/
async function getCommonJSConfig() {
const nodePlugin = (await import("eslint-plugin-n")).default;
const nodeConfig = nodePlugin.configs["flat/recommended-script"];
return {
...nodeConfig,
name: "node/commonjs",
ignores,
plugins: {
...nodeConfig.plugins,
import: importPlugin,
},
rules: {
...nodeConfig.rules,
...commonRules,
"n/exports-style": "error",
"n/no-path-concat": "error",
"import/extensions": [
"error",
"always",
{
ignorePackages: true,
checkTypeImports: true,
pattern: {
js: "never",
ts: "never",
},
// Allow to have `ts` extension in `require` for compatibility with Node.js built-in typescript support
pathGroupOverrides: [
{
pattern: "*.ts",
patternOptions: {
matchBase: true,
},
action: "ignore",
},
],
},
],
},
};
}
/**
* @returns {Promise<import("eslint").Linter.Config>} config
*/
async function getModuleConfig() {
const nodePlugin = (await import("eslint-plugin-n")).default;
const nodeConfig = nodePlugin.configs["flat/recommended-module"];
return {
...nodeConfig,
name: "node/module",
ignores,
plugins: {
...nodeConfig.plugins,
import: importPlugin,
},
rules: {
...nodeConfig.rules,
...commonRules,
"n/no-unsupported-features/es-syntax": [
"error",
{
ignores: ["modules", "error-cause"],
},
],
"import/extensions": [
"error",
"always",
{ ignorePackages: true, checkTypeImports: true },
],
},
};
}
const commonjsConfig = await getCommonJSConfig();
const moduleConfig = await getModuleConfig();
/**
* @returns {Promise<import("eslint").Linter.Config>} config
*/
async function getDirtyConfig() {
const nodePlugin = (await import("eslint-plugin-n")).default;
return {
name: "node/dirty",
plugins: {
n: nodePlugin,
import: importPlugin,
},
ignores: [
...new Set([
...(commonjsConfig.ignores || []),
...(moduleConfig.ignores || []),
]),
],
languageOptions: {
sourceType: "module",
parserOptions: {
ecmaFeatures: { globalReturn: true },
},
globals: {
...globals.node,
__dirname: "readonly",
__filename: "readonly",
exports: "writable",
module: "readonly",
require: "readonly",
},
},
rules: {
...commonjsConfig.rules,
...moduleConfig.rules,
// Disable for dirty modules
"import/extensions": ["off"],
},
};
}
const dirtyConfig = await getDirtyConfig();
const jsExtensions = isTypescriptInstalled()
? ["*.{js,ts}", "**/*.{js,ts}"]
: ["**/*.js"];
const cjsExtensions = isTypescriptInstalled()
? ["*.{cjs,cts}", "**/*.{cjs,cts}"]
: ["**/*.cjs"];
const mjsExtensions = isTypescriptInstalled()
? ["*.{mjs,jsx,mts,tsx}", "**/*.{mjs,jsx,mts,tsx}"]
: ["*.{mjs,jsx}", "**/*.{mjs,jsx}"];
export default {
"node/dirty": dirtyConfig,
"node/commonjs": commonjsConfig,
"node/module": moduleConfig,
"node/recommended": moduleConfig,
"node/mixed-dirty": [
{
files: jsExtensions,
...dirtyConfig,
},
{
files: cjsExtensions,
...commonjsConfig,
},
{
files: mjsExtensions,
...moduleConfig,
},
],
"node/mixed-module-and-commonjs": [
{
files: jsExtensions,
...moduleConfig,
},
{
files: cjsExtensions,
...commonjsConfig,
},
{
files: mjsExtensions,
...moduleConfig,
},
],
"node/mixed-commonjs-and-module": [
{
files: jsExtensions,
...commonjsConfig,
},
{
files: cjsExtensions,
...commonjsConfig,
},
{
files: mjsExtensions,
...moduleConfig,
},
],
};