Skip to content
Snippets Groups Projects
.eslintrc.js 7.75 KiB
Newer Older
  • Learn to ignore specific revisions
  • /* eslint-disable rulesdir/typography */
    
    const path = require('path');
    
    const rulesDirPlugin = require('eslint-plugin-rulesdir');
    rulesDirPlugin.RULES_DIR = path.join(
      __dirname,
      'packages',
      'eslint-plugin-actual',
      'lib',
      'rules',
    );
    
    
    const ruleFCMsg =
      'Type the props argument and let TS infer or use ComponentType for a component prop';
    
    
    const restrictedImportPatterns = [
      {
        group: ['*.api', '*.web', '*.electron'],
        message: 'Don’t directly reference imports from other platforms',
      },
    
      {
        group: ['uuid'],
        importNames: ['*'],
        message: "Use `import { v4 as uuidv4 } from 'uuid'` instead",
      },
    
    const restrictedImportColors = [
      {
        group: ['**/style', '**/colors'],
        importNames: ['colors'],
        message: 'Please use themes instead of colors',
      },
    ];
    
    
    module.exports = {
    
      plugins: ['prettier', 'import', 'rulesdir', '@typescript-eslint'],
    
      extends: [
        'react-app',
        'plugin:react/recommended',
        'plugin:@typescript-eslint/recommended',
      ],
    
      parser: '@typescript-eslint/parser',
      parserOptions: { project: [path.join(__dirname, './tsconfig.json')] },
    
      reportUnusedDisableDirectives: true,
    
    
        // Note: base rule explicitly disabled in favor of the TS one
    
        'no-unused-vars': 'off',
    
        '@typescript-eslint/no-unused-vars': [
    
          {
            args: 'none',
            varsIgnorePattern: '^_',
            ignoreRestSiblings: true,
          },
        ],
    
        curly: ['warn', 'multi-line', 'consistent'],
    
        'no-restricted-globals': ['warn'].concat(
    
          require('confusing-browser-globals').filter(g => g !== 'self'),
        ),
    
    
        'react/jsx-no-useless-fragment': 'warn',
        'react/self-closing-comp': 'warn',
    
        'react/no-unstable-nested-components': [
          'warn',
          { allowAsProps: true, customValidators: ['formatter'] },
        ],
    
        'rulesdir/typography': 'warn',
        'rulesdir/prefer-if-statement': 'warn',
    
        // https://github.com/eslint/eslint/issues/16954
        // https://github.com/eslint/eslint/issues/16953
    
        'no-loop-func': 'off',
    
        // Do don't need this as we're using TypeScript
        'react/prop-types': 'off',
    
    
        // TODO: re-enable these rules
        'react-hooks/exhaustive-deps': 'off',
    
        'react/display-name': 'off',
        'react/react-in-jsx-scope': 'off',
    
        // 'react-hooks/exhaustive-deps': [
    
        //   {
        //     additionalHooks: 'useLiveQuery',
        //   },
        // ],
    
        'object-shorthand': ['warn', 'properties'],
    
        'import/extensions': [
    
          'never',
          {
            json: 'always',
          },
        ],
    
        'import/no-useless-path-segments': 'warn',
        'import/no-duplicates': ['warn', { 'prefer-inline': true }],
        'import/no-unused-modules': ['warn', { unusedExports: true }],
    
            alphabetize: {
              caseInsensitive: true,
    
            groups: [
              'builtin', // Built-in types are first
              'external',
    
            ],
            'newlines-between': 'always',
            pathGroups: [
              // Enforce that React (and react-related packages) is the first import
              { group: 'builtin', pattern: 'react?(-*)', position: 'before' },
              // Separate imports from Actual from "real" external imports
              {
                group: 'external',
                pattern: 'loot-{core,design}/**/*',
    
            pathGroupsExcludedImportTypes: ['react'],
          },
        ],
    
        'no-restricted-syntax': [
    
          {
            // forbid React.* as they are legacy https://twitter.com/dan_abramov/status/1308739731551858689
            selector:
              ":matches(MemberExpression[object.name='React'], TSQualifiedName[left.name='React'])",
            message:
              'Using default React import is discouraged, please use named exports directly instead.',
          },
    
          {
            // forbid <a> in favor of <LinkButton> or <ExternalLink>
            selector: 'JSXOpeningElement[name.name="a"]',
            message:
              'Using <a> is discouraged, please use <LinkButton> or <ExternalLink> instead.',
          },
    
        'no-restricted-imports': [
    
          { patterns: [...restrictedImportPatterns, ...restrictedImportColors] },
        ],
    
        // Rules disable during TS migration
        '@typescript-eslint/no-var-requires': 'off',
        'prefer-const': 'off',
    
        'prefer-spread': 'off',
    
        '@typescript-eslint/no-empty-function': 'off',
    
          files: ['.eslintrc.js', './**/.eslintrc.js'],
    
          parserOptions: { project: null },
    
          rules: {
            '@typescript-eslint/consistent-type-exports': 'off',
          },
    
        },
        {
          files: [
            './packages/desktop-client/**/*.{ts,tsx}',
            './packages/loot-core/src/client/**/*.{ts,tsx}',
          ],
          rules: {
            // enforce type over interface
    
            '@typescript-eslint/consistent-type-definitions': ['warn', 'type'],
    
            // enforce import type
            '@typescript-eslint/consistent-type-imports': [
    
              { prefer: 'type-imports', fixStyle: 'inline-type-imports' },
            ],
            '@typescript-eslint/ban-types': [
    
              {
                types: {
                  // forbid FC as superflous
                  FunctionComponent: { message: ruleFCMsg },
                  FC: { message: ruleFCMsg },
                },
                extendDefaults: true,
              },
            ],
          },
        },
    
        {
          files: ['./packages/loot-core/src/**/*'],
          rules: {
            'no-restricted-imports': [
    
                  ...restrictedImportPatterns,
    
                  {
                    group: ['loot-core/**'],
                    message:
                      'Please use relative imports in loot-core instead of importing from `loot-core/*`',
                  },
                ],
              },
            ],
          },
        },
    
            'packages/loot-core/src/types/**/*',
            'packages/loot-core/src/client/state-types/**/*',
            '**/icons/**/*',
            '**/{mocks,__mocks__}/**/*',
    
            // can't correctly resolve usages
            '**/*.{testing,electron,browser,web,api}.ts',
          ],
    
          rules: { 'import/no-unused-modules': 'off' },
    
    Neil's avatar
    Neil committed
            './packages/desktop-client/src/style/index.*',
            './packages/desktop-client/src/style/palette.*',
    
          ],
          rules: {
            'no-restricted-imports': ['off', { patterns: restrictedImportColors }],
          },
        },
    
        // TODO: Remove this override once we addressed all warnings and enable the rule globally.
        {
          files: [
            './packages/api/*',
            './packages/api/app/**/*',
            './packages/crdt/**/*',
            './packages/desktop-client/src/*',
    
            // './packages/desktop-client/src/components/**/*',
    
            './packages/desktop-client/src/hooks/**/*',
            './packages/desktop-client/src/icons/**/*',
            './packages/desktop-client/src/style/**/*',
            './packages/desktop-client/src/types/**/*',
            './packages/desktop-client/src/util/**/*',
            './packages/desktop-electron/**/*',
            './packages/eslint-plugin-actual/**/*',
    
            './packages/loot-core/*',
            './packages/loot-core/src/client/**/*',
            './packages/loot-core/src/mocks/**/*',
            './packages/loot-core/src/platform/**/*',
            // './packages/loot-core/src/server/**/*',
            './packages/loot-core/src/shared/**/*',
            './packages/loot-core/src/types/**/*',
            './packages/loot-core/webpack/**/*',
    
          ],
          rules: {
            'prefer-const': 'warn',
          },
        },
    
        'import/parsers': {
          '@typescript-eslint/parser': ['.ts', '.tsx'],
        },
        'import/resolver': {
          typescript: {
            alwaysTryTypes: true,
          },