const project = ['./tsconfig.json', './packages/*/tsconfig.json']; module.exports = { root: true, plugins: ['@typescript-eslint'], extends: [ 'airbnb', 'airbnb-typescript', 'airbnb/hooks', 'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended-requiring-type-checking', 'plugin:jest/recommended', 'plugin:jest/style', 'plugin:prettier/recommended', 'plugin:promise/recommended', 'plugin:security/recommended', 'plugin:unicorn/recommended', ], env: { es6: true, node: true, browser: false, jest: true, }, parser: '@typescript-eslint/parser', parserOptions: { extraFileExtensions: ['.cjs'], sourceType: 'module', project, allowAutomaticSingleRunInference: false, tsconfigRootDir: __dirname, warnOnUnsupportedTypeScriptVersion: false, EXPERIMENTAL_useSourceOfProjectReferenceRedirect: false, }, settings: { 'import/parsers': { '@typescript-eslint/parser': ['.ts', '.tsx'], }, 'import/resolver': { typescript: { alwaysTryTypes: true, project, }, }, }, rules: { // `import/exteions` is buggy with ts files: // https://github.com/import-js/eslint-plugin-import/issues/2111 'import/extensions': 'off', 'import/no-unresolved': 'error', 'import/order': [ 'error', { alphabetize: { order: 'asc', }, 'newlines-between': 'always', }, ], // jest-each confuses this rule. 'jest/no-standalone-expect': 'off', // Allows files with names same as the name of their default export. 'unicorn/filename-case': [ 'error', { cases: { camelCase: true, pascalCase: true, }, }, ], // Airbnb prefers forEach. 'unicorn/no-array-for-each': 'off', // Typescript requires exlicit `undefined` arguments. 'unicorn/no-useless-undefined': [ 'error', { checkArguments: false, }, ], // Common abbreviations are known and readable. 'unicorn/prevent-abbreviations': 'off', }, overrides: [ { files: ['**/stores/**/*.ts'], rules: { // In a mobx-state-tree action, we assign to the properties of `self` to update the store. 'no-param-reassign': [ 'error', { props: false, }, ], // mobx-state-tree uses empty interfaces to speed up typechecking. '@typescript-eslint/no-empty-interface': 'off', }, }, { files: ['**/__tests__/*.{ts,tsx}', '**/*.{spec,test}.{ts,tsx}'], rules: { // If a non-null assertion fails in a test, the test will also fail anyways. '@typescript-eslint/no-non-null-assertion': 'off', // Jest mocks use unbound method references. '@typescript-eslint/unbound-method': 'off', // We can't turn this on yet, because it doesn't understand `mocked` from `jest-mock`. // 'jest/unbound-method': 'error', }, }, { files: ['**/*.cjs'], parserOptions: { sourceType: 'script', }, rules: { // We have to use `const foo = require('foo')` syntax in CommonJS files. '@typescript-eslint/no-var-requires': 'off', }, }, { files: [ '.electron-builder.config.cjs', 'config/**/*.{cjs,js}', '*.config.{cjs,js}', 'scripts/**/*.js', 'packages/*/.eslintrc.cjs', 'packages/*/*.config.{cjs,js}', ], env: { // Config files are never run in a browser (even in frontend projects). browser: false, node: true, jest: false, }, rules: { // Config files and build scripts are allowed to use devDependencies. 'import/no-extraneous-dependencies': [ 'error', { devDependencies: true, }, ], // Allow reporting progress to the console from scripts. 'no-console': 'off', }, }, { files: ['packages/*/*.config.{cjs,js}'], rules: { // Allow relative imports of config files from the root package. 'import/no-relative-packages': 'off', }, }, { files: ['scripts/**/*.js'], rules: { // Scripts are allowed to `exit` abruptly. 'unicorn/no-process-exit': 'off', }, }, ], };