Files
flipper/desktop/.eslintrc.js
Michel Weststrate 5df34a337c Unshare global types
Summary:
This diff adds `types` fields on the compiler config for every project. This way we can make sure that for example node types and packages are not available in flipper-ui-core. Without an explicit types field, all types would be shared between all packages, and implicitly included into the compilation of everything. For the same reason `types/index.d.ts` has been removed, we want to be intentional on which types are being used in which package.

This diff does most of the work, the next diff will fine tune the globals, and do some further cleanup.

As an alternative solution I first tried a `nohoist: **/node_modules/types/**` and make sure every package list explicitly the types used in package json, which works but is much more error prone, as for example two different react types versions in two packages will cause the most unreadable compiler error due to the types not being shared and not literally the same.

Reviewed By: lawrencelomax

Differential Revision: D33124441

fbshipit-source-id: c2b9d768f845ac28005d8331ef5fa1066c7e4cd7
2021-12-17 07:36:07 -08:00

214 lines
7.1 KiB
JavaScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const fbjs = require('eslint-config-fbjs');
const rulesDirPlugin = require('eslint-plugin-rulesdir');
rulesDirPlugin.RULES_DIR = 'eslint-rules';
// enforces copy-right header and @format directive to be present in every file
const pattern = /^\*\r?\n[\S\s]*Facebook[\S\s]* \* @format\r?\n/;
// This list should match the replacements defined in `replace-flipper-requires.ts` and `dispatcher/plugins.tsx`
const builtInModules = [
'flipper',
'flipper-plugin',
'flipper-plugin-lib',
'react',
'react-dom',
'electron',
'antd',
'immer',
'@emotion/styled',
'@ant-design/icons',
'jest',
'ts-jest',
];
const prettierConfig = require('./.prettierrc.json');
// We should forbid using "flipper" import. However, we have hundreds of plugins using it.
// So we forbid it everywhere but in "plugins" directory.
// To do that we need to keep "error" level of linting for most imports, but downlevel warning for "flipper" import to "warn".
// It is not possible OOTB by eslint.
// Instead, we create a clone of the "no-restricted-imports" rule and use it to split out restricted imports in two groups: warn and error.
// https://github.com/eslint/eslint/issues/14061#issuecomment-772490154
const restrictedImportsUniversalErrorConfig = {
paths: [
{
name: 'electron',
message:
"Direct imports from 'electron' are deprecated. Most functions can be found in getFlipperLib() from flipper-plugin package instead.",
},
],
patterns: [
{
group: ['flipper-plugin/*'],
message:
"Imports from nested flipper-plugin directories are not allowed. Import from 'flipper-plugin' module directly. If it is missing an export, add it there with corresponding documentation (https://fbflipper.com/docs/extending/flipper-plugin/).",
},
{
group: ['flipper-common/*'],
message:
"Imports from nested flipper-common directories are not allowed. Import from 'flipper-common' module directly. If it is missing an export, add it there.",
},
{
group: ['flipper-ui-core/*'],
message:
"Imports from nested flipper-ui-core directories are not allowed. Import from 'flipper-ui-core' module directly. If it is missing an export, add it there.",
},
],
};
module.exports = {
parser: 'babel-eslint',
root: true,
extends: ['fbjs', 'prettier'],
plugins: [
...fbjs.plugins,
'header',
'prettier',
'@typescript-eslint',
'import',
'node',
'react-hooks',
'flipper',
'promise',
'communist-spelling',
'rulesdir',
],
rules: {
// disable rules from eslint-config-fbjs
'flowtype/define-flow-type': 0,
'flowtype/use-flow-type': 0,
'react/react-in-jsx-scope': 0, // not needed with our metro implementation
// Disallow boolean JSX properties set to true, e.g. `grow={true}`.
'react/jsx-boolean-value': ['warn', 'never'],
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
'react/jsx-key': 'error',
'no-new': 0, // new keyword needed e.g. new Notification
'no-catch-shadow': 0, // only relevant for IE8 and below
'no-bitwise': 0, // bitwise operations needed in some places
'consistent-return': 0,
'no-var': 2,
'prefer-const': [2, {destructuring: 'all'}],
'prefer-spread': 1,
'prefer-rest-params': 1,
'no-console': 0, // we're setting window.console in App.js
'no-multi-spaces': 2,
'prefer-promise-reject-errors': 1,
'no-throw-literal': 'error',
'no-extra-boolean-cast': 2,
'no-extra-semi': 2,
'no-unsafe-negation': 2,
'no-useless-computed-key': 2,
'no-useless-rename': 2,
'no-restricted-properties': [
1,
{
object: 'electron',
property: 'remote',
},
],
'no-restricted-imports': [
'error',
{
...restrictedImportsUniversalErrorConfig,
paths: [
...restrictedImportsUniversalErrorConfig.paths,
{
name: 'flipper',
message:
"Direct imports from 'flipper' are deprecated. Import from 'flipper-plugin' instead, which can be tested and distributed stand-alone. See https://fbflipper.com/docs/extending/sandy-migration for more details.",
},
],
},
],
// additional rules for this project
'header/header': [2, 'block', {pattern}],
'prettier/prettier': [2, prettierConfig],
'import/no-unresolved': [2, {commonjs: true, amd: true}],
'node/no-extraneous-import': [2, {allowModules: builtInModules}],
'node/no-extraneous-require': [2, {allowModules: builtInModules}],
'node/no-sync': [1],
'flipper/no-relative-imports-across-packages': [2],
'flipper/no-electron-remote-imports': [1],
'flipper/no-console-error-without-context': [2],
'communist-spelling/communist-spelling': [1, {allow: ['cancelled']}],
// promise rules, see https://github.com/xjamundx/eslint-plugin-promise for details on each of them
'promise/catch-or-return': 'error',
'promise/no-nesting': 'warn',
'promise/no-promise-in-callback': 'warn',
'promise/no-callback-in-promise': 'warn',
'promise/no-return-in-finally': 'warn',
'promise/valid-params': 'error',
},
settings: {
'import/resolver': {
typescript: {
alwaysTryTypes: true,
extensions: ['.js', '.jsx', '.ts', '.tsx'],
project: '.',
},
},
},
overrides: [
{
files: ['*.tsx', '*.ts'],
parser: '@typescript-eslint/parser',
rules: {
'prettier/prettier': [2, {...prettierConfig, parser: 'typescript'}],
// following rules are disabled because TS already handles it
'no-undef': 0,
'import/no-unresolved': 0,
// following rules are disabled because they don't handle TS correctly,
// while their @typescript-eslint counterpart does
// for reference: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/README.md#extension-rules
'no-unused-vars': 0,
'no-redeclare': 0,
'no-dupe-class-members': 0,
'@typescript-eslint/no-redeclare': 1,
'@typescript-eslint/no-unused-vars': [
1,
{
ignoreRestSiblings: true,
varsIgnorePattern: '^_',
argsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],
},
},
{
files: ['plugins/**/*.ts', 'plugins/**/*.tsx'],
rules: {
'no-restricted-imports': [
'error',
restrictedImportsUniversalErrorConfig,
],
'rulesdir/no-restricted-imports-clone': [
'warn',
{
paths: [
{
name: 'flipper',
message:
"Direct imports from 'flipper' are deprecated. Import from 'flipper-plugin' instead, which can be tested and distributed stand-alone. See https://fbflipper.com/docs/extending/sandy-migration for more details.",
},
],
},
],
},
},
],
};