UNPKG

eslint-config-xaxa

Version:

Modern, ESLint v9+ compatible, Airbnb-based shareable config; including plugins like Import, Prettier, Unicorn, Typescript, Astro, and React.

378 lines (328 loc) 14.4 kB
import eslintJs from '@eslint/js'; import eslintConfigPrettier from 'eslint-config-prettier'; // import { configs as astroConfigs } from 'eslint-plugin-astro'; import eslintPluginImport from 'eslint-plugin-import'; import eslintPluginNoUseExtendNative from 'eslint-plugin-no-use-extend-native'; // import eslintPluginPrettier from 'eslint-plugin-prettier'; import eslintPluginPromise from 'eslint-plugin-promise'; import eslintPluginUnicorn from 'eslint-plugin-unicorn'; import globals from 'globals'; import { configs as tseslintConfigs } from 'typescript-eslint'; import airbnbBase from './airbnb-base.js'; const airbnb = airbnbBase .filter((x) => !x.name.includes('import')) // @ts-ignore .concat({ name: 'airbnb/plugin-import-rules', rules: airbnbBase?.find((x) => x.name.includes('import'))?.rules || {}, }); export default [ eslintJs.configs.recommended, eslintPluginNoUseExtendNative.configs.recommended, eslintPluginUnicorn.configs.recommended, eslintPluginImport.flatConfigs.recommended, eslintPluginImport.flatConfigs.errors, eslintPluginImport.flatConfigs.warnings, eslintPluginImport.flatConfigs.react, eslintPluginImport.flatConfigs.typescript, eslintPluginPromise.configs['flat/recommended'], tseslintConfigs.eslintRecommended, // TODO: bruh.. buggy // astroConfigs['flat/recommended'], ...airbnb, { name: 'wgw/plugin-import-overrides', rules: { 'import/no-unresolved': [ 'error', { ignore: ['^astro:*', '^bun:*', '^bun$', '^npm:*', '^jsr:*', '^cloudflare:*'], }, ], 'import/no-unassigned-import': 'off', 'import/prefer-default-export': 'off', 'import/no-relative-packages': 'off', 'import/namespace': ['error', { allowComputed: true }], 'import/no-absolute-path': 'error', 'import/no-webpack-loader-syntax': 'error', 'import/no-self-import': 'error', // Enable this sometime in the future when Node.js has ES2015 module support 'import/no-cycle': 'error', // Disabled as it doesn't work with TypeScript // 'import/newline-after-import': 'error', 'import/no-amd': 'error', 'import/no-duplicates': 'error', // Enable this sometime in the future when Node.js has ES2015 module support // 'import/unambiguous': 'error', // Enable this sometime in the future when Node.js has ES2015 module support // 'import/no-commonjs': 'error', // Looks useful, but too unstable at the moment 'import/no-deprecated': 'error', 'import/no-extraneous-dependencies': 'off', 'import/no-mutable-exports': 'error', 'import/no-named-as-default-member': 'error', // ! buggy, when you have same identifier as default and as named // like `import test from 'foo';` and `import { test } from 'foo';` 'import/no-named-as-default': 'off', // Disabled because it's buggy and it also doesn't work with TypeScript // 'import/no-unresolved': [ // 'error', { commonjs: true } // ], 'import/order': 'error', // 'import/no-unassigned-import': [ // 'error', // { // allow: ['dotenv/config', 'dotenv/import', '@babel/polyfill', '@babel/register', '*.css'], // }, // ], // Ensure more web-compat // ! note that it doesn't work in CommonJS // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md // "import/extensions": ["error", "ignorePackages"], 'import/extensions': ['off'], // ? Always use named exports. Enable? // 'import/no-default-export': 'error', // ? enable? 'import/exports-last': 'off', // TODO: Enable in future. // Ensures everything is tested (all exports should be used). // For cases when you don't want or can't test, add eslint-ignore comment! // see: https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unused-modules.md // ! maybe not // 'import/no-unused-modules': '', 'import/no-useless-path-segments': ['error', { noUselessIndex: false }], }, }, { name: 'wgw/plugin-promise-overrides', rules: { // These below are to ensure not changes // inside upstream XO and the plugin:promise/recommended configs 'promise/catch-or-return': 'off', 'promise/always-return': 'off', 'promise/no-native': 'off', 'promise/no-nesting': 'off', 'promise/no-promise-in-callback': 'off', 'promise/no-callback-in-promise': 'off', 'promise/avoid-new': 'off', 'promise/prefer-await-to-then': 'error', 'promise/prefer-await-to-callbacks': 'error', // These are the same as in XO CLI, but they are not in the eslint-config-xo 'promise/no-return-wrap': ['error', { allowReject: true }], 'promise/param-names': 'error', 'promise/no-new-statics': 'error', 'promise/no-return-in-finally': 'error', 'promise/valid-params': 'error', }, }, { name: 'wgw/plugin-unicorn-overrides', rules: { 'unicorn/no-await-expression-member': 'off', 'unicorn/consistent-destructuring ': 'off', 'unicorn/expiring-todo-comments': 'off', 'unicorn/no-useless-spread': 'off', // useless rule 'unicorn/prefer-switch': 'off', // fvck off // It is too much annoyance for me. It's a good thing, but generally // after so many years we already name things properly, // so please don't mess with me and don't correct me. 'unicorn/prevent-abbreviations': 'off', // Please don't annoy me. 'unicorn/no-null': 'off', 'unicorn/prefer-spread': 'off', 'unicorn/no-array-reduce': 'off', // These below are intentional & explicit overrides of XO and Unicorn // ! needed for `unicorn/no-unreadable-array-destructuring` // 'prefer-destructuring': ['warn', { object: true, array: false }], 'unicorn/no-unreadable-array-destructuring': 'error', // default in recommended 'unicorn/no-unused-properties': 'error', // Disallow unsafe regular expressions. // Don't allow potential catastrophic crashes, slow behaving and downtimes. // You still can disable that and do whatever you want, // but that will be explicit and visible. // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/no-unsafe-regex.md // 'unicorn/no-unsafe-regex': 'error', // Enforce importing index files with `.` instead of `./index`. (fixable) // But we should be explicit. We know it is working without that, // but at least it is good for newcomers. // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/import-index.md 'unicorn/import-index': 'off', // Enforce proper Error subclassing. (fixable) // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/custom-error-definition.md 'unicorn/custom-error-definition': 'error', // Pretty useful rule, but it depends. // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/filename-case.md 'unicorn/filename-case': 'off', // It is pretty common to name it `err`, and there is almost no reason to be any other. // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/catch-error-name.md 'unicorn/catch-error-name': ['error', { name: 'err' }], // Doesn't work well in node-land. We have `.on/.off` emitters in Nodejs. 'unicorn/prefer-add-event-listener': 'off', 'unicorn/no-process-exit': 'error', }, }, { name: 'wgw/misc', files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs'], settings: { 'import/resolver': { // You will also need to install and configure the TypeScript resolver // See also https://github.com/import-js/eslint-import-resolver-typescript#configuration typescript: { alwaysTryTypes: true, project: 'packages/*/{ts,js}config.json', bun: true, node: true, }, }, }, languageOptions: { globals: { ...globals.builtin, ...globals.browser, ...globals.node, ...globals.nodeBuiltin, ...globals['shared-node-browser'], }, ecmaVersion: 'latest', sourceType: 'module', // parser: typescriptParser, parserOptions: { ecmaVersion: 'latest', // project: ['packages/**/tsconfig.json'], // projectService: true, // lib: ['ESNext'], ecmaFeatures: { jsx: true, generators: false, }, }, }, rules: { '@typescript-eslint/triple-slash-reference': 'off', '@typescript-eslint/no-unused-vars': 'off', // fvck off, we have properly configured `no-unused-vars` '@typescript-eslint/no-explicit-any': 'off', 'no-restricted-exports': 'off', 'sort-keys': 'off', camelcase: 'off', // !NOTE: eslint-plugin-node is unmaintained and not used in April 2025 // "node/prefer-global/process": "off", // "node/file-extension-in-import": "off", // "no-param-reassign": "off", // 'no-explicit-any': 'warn', // https://eslint.org/docs/rules/function-call-argument-newline 'no-import-assign': 'error', // https://eslint.org/docs/rules/function-call-argument-newline 'function-call-argument-newline': ['error', 'consistent'], // Prefer Object.hasOwn() over Object.prototype.hasOwnProperty.call() // https://eslint.org/docs/rules/prefer-object-has-own 'prefer-object-has-own': 'error', // Off in Airbnb, until `eslint v7.15 is required` // disallow use of optional chaining in contexts where the undefined value is not allowed // https://eslint.org/docs/rules/no-unsafe-optional-chaining 'no-unsafe-optional-chaining': ['error', { disallowArithmeticOperators: true }], // https://eslint.org/docs/rules/default-param-last 'default-param-last': 'error', 'prefer-regex-literals': 'error', 'no-empty': ['error', { allowEmptyCatch: true }], 'no-extend-native': 'error', 'no-use-extend-native/no-use-extend-native': 'error', // yes, we know that it's just a convention, allow me Airbnb. 'no-underscore-dangle': 'off', // why? 'no-continue': 'warn', 'no-console': 'off', // we use es modules strict: ['off', 'global'], // we use spaces 'no-tabs': 'error', // Enforce using named functions when regular function is used, // otherwise use arrow functions 'func-names': ['error', 'always'], // Always use parens (for consistency). // https://eslint.org/docs/rules/arrow-parens 'arrow-parens': ['error', 'always', { requireForBlockBody: true }], 'prefer-arrow-callback': ['error', { allowNamedFunctions: true, allowUnboundThis: true }], // http://eslint.org/docs/rules/max-params 'max-params': ['error', { max: 6 }], // http://eslint.org/docs/rules/max-statements 'max-statements': ['error', 40, { ignoreTopLevelFunctions: true }], // http://eslint.org/docs/rules/max-statements-per-line 'max-statements-per-line': ['error', { max: 1 }], // http://eslint.org/docs/rules/max-nested-callbacks 'max-nested-callbacks': ['error', { max: 4 }], // http://eslint.org/docs/rules/max-depth 'max-depth': ['error', { max: 4 }], // enforces no braces where they can be omitted // https://eslint.org/docs/rules/arrow-body-style // Never enable for object literal. 'arrow-body-style': ['error', 'as-needed', { requireReturnForObjectLiteral: false }], // Allow functions to be use before define because: // 1) they are hoisted, // 2) because ensure read flow is from top to bottom // 3) logically order of the code. // 4) the only addition is 'typedefs' option, see overrides for TS files 'no-use-before-define': [ 'error', { functions: false, classes: true, variables: true, allowNamedExports: true, }, ], // disallow declaration of variables that are not used in the code 'no-unused-vars': [ 'error', { ignoreRestSiblings: true, // airbnb's default vars: 'all', // airbnb's default // caughtErrorsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))', varsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))', args: 'after-used', // airbnb's default argsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))', // catch blocks are handled by Unicorns caughtErrors: 'none', // caughtErrorsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))', }, ], // Default as Airbnb's except we allow for of & for await of 'no-restricted-syntax': [ 'error', { selector: 'ForInStatement', message: 'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.', }, // { // selector: 'ForOfStatement', // message: 'iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.', // }, { selector: 'LabeledStatement', message: 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.', }, { selector: 'WithStatement', message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.', }, ], // bruh 'prefer-destructuring': 'off', 'lines-between-class-members': [ 'error', { enforce: [ { blankLine: 'never', prev: 'field', next: '*' }, { blankLine: 'always', prev: 'field', next: 'method' }, { blankLine: 'always', prev: 'method', next: 'method' }, ], }, ], }, }, eslintConfigPrettier, // eslintPluginPrettier.configs.recommended, ];