From 4a1c2a9ece41dad3a6117e96a80da2532c80edd6 Mon Sep 17 00:00:00 2001 From: Anton Nikolaev Date: Fri, 7 Aug 2020 10:19:34 -0700 Subject: [PATCH] Custom eslint rule for disallowing cross-package references Summary: Added infra for writing and using custom eslint rules and created a rule for disallowing cross-package file imports. Such imports are anti-pattern and they also break standalone plugin bundling. We still have a bunch of places where Flipper core references code directly from plugins. I've ignored these places for now and added task T71355623 to revisit them. Reviewed By: passy Differential Revision: D22998955 fbshipit-source-id: d04cff8fc115ba1300a7e6830306ec134046e927 --- desktop/.eslintrc.js | 2 + desktop/app/src/chrome/LocationsButton.tsx | 4 + .../src/electron-requires-main.ts | 1 + desktop/eslint-plugin-flipper/LICENSE | 21 ++ desktop/eslint-plugin-flipper/jestconfig.json | 8 + desktop/eslint-plugin-flipper/package.json | 42 ++++ desktop/eslint-plugin-flipper/src/index.ts | 18 ++ .../noRelativeImportsAcrossPackages.node.ts | 56 +++++ .../rules/noRelativeImportsAcrossPackages.ts | 110 ++++++++++ .../src/utils/createEslintRule.ts | 12 ++ desktop/eslint-plugin-flipper/tsconfig.json | 9 + desktop/eslint-plugin-flipper/tslint.json | 7 + desktop/headless/index.tsx | 2 + desktop/package.json | 9 +- .../__test__/DatabaseDetailSidebar.node.tsx | 2 + desktop/tsconfig.base.json | 1 + desktop/yarn.lock | 196 +++++++++++------- 17 files changed, 428 insertions(+), 72 deletions(-) create mode 100644 desktop/eslint-plugin-flipper/LICENSE create mode 100644 desktop/eslint-plugin-flipper/jestconfig.json create mode 100644 desktop/eslint-plugin-flipper/package.json create mode 100644 desktop/eslint-plugin-flipper/src/index.ts create mode 100644 desktop/eslint-plugin-flipper/src/rules/__tests__/noRelativeImportsAcrossPackages.node.ts create mode 100644 desktop/eslint-plugin-flipper/src/rules/noRelativeImportsAcrossPackages.ts create mode 100644 desktop/eslint-plugin-flipper/src/utils/createEslintRule.ts create mode 100644 desktop/eslint-plugin-flipper/tsconfig.json create mode 100644 desktop/eslint-plugin-flipper/tslint.json diff --git a/desktop/.eslintrc.js b/desktop/.eslintrc.js index 5d7ed4d84..3501634ef 100644 --- a/desktop/.eslintrc.js +++ b/desktop/.eslintrc.js @@ -38,6 +38,7 @@ module.exports = { 'import', 'node', 'react-hooks', + 'flipper', ], rules: { // disable rules from eslint-config-fbjs @@ -69,6 +70,7 @@ module.exports = { 'import/no-unresolved': [2, {commonjs: true, amd: true}], 'node/no-extraneous-import': [2, {allowModules: builtInModules}], 'node/no-extraneous-require': [2, {allowModules: builtInModules}], + 'flipper/no-relative-imports-across-packages': [2], }, settings: { 'import/resolver': { diff --git a/desktop/app/src/chrome/LocationsButton.tsx b/desktop/app/src/chrome/LocationsButton.tsx index 3ab24e737..5e44c7731 100644 --- a/desktop/app/src/chrome/LocationsButton.tsx +++ b/desktop/app/src/chrome/LocationsButton.tsx @@ -11,10 +11,14 @@ import {Button, styled} from 'flipper'; import {connect} from 'react-redux'; import React, {Component} from 'react'; import {State as Store} from '../reducers'; +// TODO T71355623 +// eslint-disable-next-line flipper/no-relative-imports-across-packages import { readBookmarksFromDB, writeBookmarkToDB, } from '../../../plugins/navigation/util/indexedDB'; +// TODO T71355623 +// eslint-disable-next-line flipper/no-relative-imports-across-packages import {PersistedState as NavPluginState} from '../../../plugins/navigation/types'; import BaseDevice from '../devices/BaseDevice'; import {State as PluginState} from 'app/src/reducers/pluginStates'; diff --git a/desktop/babel-transformer/src/electron-requires-main.ts b/desktop/babel-transformer/src/electron-requires-main.ts index 0bf523158..31ebf853f 100644 --- a/desktop/babel-transformer/src/electron-requires-main.ts +++ b/desktop/babel-transformer/src/electron-requires-main.ts @@ -31,6 +31,7 @@ module.exports = () => ({ node.callee.type === 'MemberExpression' && node.callee.object.type === 'Identifier' && node.callee.object.name === 'require' && + node.callee.property.type === 'Identifier' && node.callee.property.name === 'resolve' && node.arguments.length === 1 && node.arguments[0].type == 'StringLiteral' diff --git a/desktop/eslint-plugin-flipper/LICENSE b/desktop/eslint-plugin-flipper/LICENSE new file mode 100644 index 000000000..b96dcb048 --- /dev/null +++ b/desktop/eslint-plugin-flipper/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/desktop/eslint-plugin-flipper/jestconfig.json b/desktop/eslint-plugin-flipper/jestconfig.json new file mode 100644 index 000000000..bab48ba29 --- /dev/null +++ b/desktop/eslint-plugin-flipper/jestconfig.json @@ -0,0 +1,8 @@ +{ + "transform": { + "^.+\\.tsx?$": "ts-jest" + }, + "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", + "testPathIgnorePatterns": ["/node_modules/", "/lib/"], + "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"] +} diff --git a/desktop/eslint-plugin-flipper/package.json b/desktop/eslint-plugin-flipper/package.json new file mode 100644 index 000000000..a2611c14d --- /dev/null +++ b/desktop/eslint-plugin-flipper/package.json @@ -0,0 +1,42 @@ +{ + "name": "eslint-plugin-flipper", + "version": "0.52.1", + "private": true, + "description": "Custom ESLint rules for Flipper", + "repository": "facebook/flipper", + "main": "lib/index.js", + "flipperBundlerEntry": "src", + "types": "lib/index.d.ts", + "license": "MIT", + "bugs": "https://github.com/facebook/flipper/issues", + "dependencies": { + "@typescript-eslint/experimental-utils": "^3.8.0", + "fs-extra": "^9.0.1" + }, + "devDependencies": { + "@types/jest": "26", + "@typescript-eslint/parser": "^3.8.0", + "flipper-test-utils": "0.52.1", + "jest": "^26", + "metro-memory-fs": "^0.61.0", + "prettier": "^2.0.0", + "rimraf": "^3.0.2", + "ts-jest": "^26.0.0", + "ts-node": "^8", + "typescript": "^3.9.5" + }, + "scripts": { + "reset": "rimraf lib *.tsbuildinfo", + "build": "tsc -b", + "prepack": "yarn reset && yarn build" + }, + "files": [ + "lib/**/*", + "src/**/*" + ], + "homepage": "https://github.com/facebook/flipper", + "keywords": [ + "Flipper" + ], + "author": "Facebook, Inc" +} diff --git a/desktop/eslint-plugin-flipper/src/index.ts b/desktop/eslint-plugin-flipper/src/index.ts new file mode 100644 index 000000000..b9ded1b70 --- /dev/null +++ b/desktop/eslint-plugin-flipper/src/index.ts @@ -0,0 +1,18 @@ +/** + * 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 + */ + +import noRelativeImportsAcrossPackages, { + RULE_NAME as noRelativeImportsAcrossPackagesRuleName, +} from './rules/noRelativeImportsAcrossPackages'; + +module.exports = { + rules: { + [noRelativeImportsAcrossPackagesRuleName]: noRelativeImportsAcrossPackages, + }, +}; diff --git a/desktop/eslint-plugin-flipper/src/rules/__tests__/noRelativeImportsAcrossPackages.node.ts b/desktop/eslint-plugin-flipper/src/rules/__tests__/noRelativeImportsAcrossPackages.node.ts new file mode 100644 index 000000000..a35ab3085 --- /dev/null +++ b/desktop/eslint-plugin-flipper/src/rules/__tests__/noRelativeImportsAcrossPackages.node.ts @@ -0,0 +1,56 @@ +/** + * 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 + */ + +import {TSESLint} from '@typescript-eslint/experimental-utils'; +import rule, {RULE_NAME} from '../noRelativeImportsAcrossPackages'; + +const tester = new TSESLint.RuleTester({ + parser: require.resolve('@typescript-eslint/parser'), + parserOptions: { + sourceType: 'module', + ecmaVersion: 2020, + }, +}); + +tester.run(RULE_NAME, rule, { + valid: [ + { + code: `import * as testUtils from 'flipper-test-utils';`, + filename: __filename, + }, + { + code: `const testUtils = require('flipper-test-utils');`, + filename: __filename, + }, + { + code: `import rule, {RULE_NAME} from '../noRelativeImportsAcrossPackages';`, + filename: __filename, + }, + { + code: `require('../noRelativeImportsAcrossPackages');`, + filename: __filename, + }, + { + code: `import m from './subdir/module';`, + filename: __filename, + }, + ], + invalid: [ + { + code: `import * as pathUtils from '../../../../test-utils/src/pathUtils';`, + filename: __filename, + errors: [{messageId: 'noRelativeImportsAcrossPackages'}], + }, + { + code: `require('../../../../test-utils/src/pathUtils');`, + filename: __filename, + errors: [{messageId: 'noRelativeImportsAcrossPackages'}], + }, + ], +}); diff --git a/desktop/eslint-plugin-flipper/src/rules/noRelativeImportsAcrossPackages.ts b/desktop/eslint-plugin-flipper/src/rules/noRelativeImportsAcrossPackages.ts new file mode 100644 index 000000000..6908ddb9e --- /dev/null +++ b/desktop/eslint-plugin-flipper/src/rules/noRelativeImportsAcrossPackages.ts @@ -0,0 +1,110 @@ +/** + * 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 + */ + +import {resolve, dirname, join} from 'path'; +import fs from 'fs-extra'; +import {TSESTree} from '@typescript-eslint/experimental-utils'; +import {createESLintRule} from '../utils/createEslintRule'; + +const rootDirs = new Map(); +function findRootDir(path: string): string { + const cachedRoot = rootDirs.get(path); + if (cachedRoot) { + return cachedRoot; + } + if (fs.pathExistsSync(join(path, 'package.json'))) { + rootDirs.set(path, path); + return path; + } + const parentRoot = findRootDir(dirname(path)); + rootDirs.set(path, parentRoot); + return parentRoot; +} + +type Options = []; + +export type MessageIds = 'noRelativeImportsAcrossPackages'; +export const RULE_NAME = 'no-relative-imports-across-packages'; + +export default createESLintRule({ + name: RULE_NAME, + meta: { + type: 'problem', + docs: { + description: `Ensure that package boundaries are respected within monorepo`, + category: 'Possible Errors', + recommended: 'error', + }, + schema: [], + messages: { + noRelativeImportsAcrossPackages: `Attempted to require "{{requiredPath}}" from file "{{filename}}" resolved to "{{resolvedPath}}" which is outside the package root dir "{{root}}".`, + }, + }, + defaultOptions: [], + create(context) { + const filename = context.getFilename(); + const dir = dirname(filename); + const root = findRootDir(dir); + return { + ImportDeclaration(node: TSESTree.ImportDeclaration) { + if (typeof node.source.value === 'string') { + const requiredPath = node.source.value; + const resolvedPath = resolve(dir, requiredPath); + if ( + // imported a file not a package + requiredPath.startsWith('.') && + // the resolved path for the imported file is outside the package root + !resolvedPath.startsWith(root) + ) { + context.report({ + node, + messageId: 'noRelativeImportsAcrossPackages', + data: { + filename, + root, + requiredPath, + resolvedPath, + }, + }); + } + } + }, + CallExpression(node: TSESTree.CallExpression) { + const args = node.arguments || []; + if ( + node.callee.type === 'Identifier' && + node.callee.name === 'require' && + args.length === 1 && + args[0].type === 'Literal' && + typeof args[0].value === 'string' + ) { + const requiredPath = args[0].value; + const resolvedPath = resolve(dir, requiredPath); + if ( + // required a file not a package + requiredPath.startsWith('.') && + // the resolved path for the required file is outside the package root + !resolvedPath.startsWith(root) + ) { + context.report({ + node, + messageId: 'noRelativeImportsAcrossPackages', + data: { + filename, + root, + requiredPath, + resolvedPath, + }, + }); + } + } + }, + }; + }, +}); diff --git a/desktop/eslint-plugin-flipper/src/utils/createEslintRule.ts b/desktop/eslint-plugin-flipper/src/utils/createEslintRule.ts new file mode 100644 index 000000000..5aab90fd7 --- /dev/null +++ b/desktop/eslint-plugin-flipper/src/utils/createEslintRule.ts @@ -0,0 +1,12 @@ +/** + * 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 + */ + +import {ESLintUtils} from '@typescript-eslint/experimental-utils'; + +export const createESLintRule = ESLintUtils.RuleCreator(() => ``); diff --git a/desktop/eslint-plugin-flipper/tsconfig.json b/desktop/eslint-plugin-flipper/tsconfig.json new file mode 100644 index 000000000..2fb289f45 --- /dev/null +++ b/desktop/eslint-plugin-flipper/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + "outDir": "lib", + "rootDir": "src" + }, + "include": ["src"], + "exclude": ["node_modules", "**/__tests__/*"] +} diff --git a/desktop/eslint-plugin-flipper/tslint.json b/desktop/eslint-plugin-flipper/tslint.json new file mode 100644 index 000000000..c98e4b003 --- /dev/null +++ b/desktop/eslint-plugin-flipper/tslint.json @@ -0,0 +1,7 @@ +{ + "extends": ["tslint:recommended", "tslint-config-prettier"], + "rules": { + "interface-name": false, + "variable-name": false + } +} diff --git a/desktop/headless/index.tsx b/desktop/headless/index.tsx index 1424b2357..821b97437 100644 --- a/desktop/headless/index.tsx +++ b/desktop/headless/index.tsx @@ -7,6 +7,8 @@ * @format */ +/* eslint-disable flipper/no-relative-imports-across-packages */ // TODO T71355623 + import path from 'path'; import {createStore, Dispatch, Middleware, MiddlewareAPI} from 'redux'; import {applyMiddleware} from 'redux'; diff --git a/desktop/package.json b/desktop/package.json index 7eeca7216..1feb69834 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -28,7 +28,8 @@ "plugins/*", "e2e", "plugin-lib", - "test-utils" + "test-utils", + "eslint-plugin-flipper" ], "nohoist": [ "flipper-plugin-kaios-big-allocations/firefox-client" @@ -108,6 +109,7 @@ }, "devDependencies": { "@babel/code-frame": "^7.10.4", + "@babel/eslint-parser": "^7.11.0", "@jest-runner/electron": "^3.0.0", "@testing-library/dom": "^7.20.2", "@testing-library/react": "^10.4.3", @@ -173,6 +175,7 @@ "eslint-config-prettier": "^6.10.1", "eslint-import-resolver-typescript": "^2.0.0", "eslint-plugin-babel": "^5.3.0", + "eslint-plugin-flipper": "0.52.1", "eslint-plugin-flowtype": "^4.7.0", "eslint-plugin-header": "^3.0.0", "eslint-plugin-import": "^2.22.0", @@ -219,7 +222,7 @@ }, "scripts": { "preinstall": "node scripts/prepare-watchman-config.js && yarn config set ignore-engines", - "postinstall": "patch-package && ./ts-node scripts/yarn-install-fb-plugins.ts && yarn build:pkg && ./ts-node scripts/generate-plugin-entry-points.ts", + "postinstall": "patch-package && ./ts-node scripts/yarn-install-fb-plugins.ts && yarn build:pkg && yarn build:eslint && ./ts-node scripts/generate-plugin-entry-points.ts", "rm-dist": "rimraf ../dist", "rm-modules": "rimraf **/*/node_modules node_modules", "rm-temp": "rimraf $TMPDIR/jest* $TMPDIR/react-native-packager*", @@ -234,6 +237,7 @@ "start:no-embedded-plugins": "yarn start --no-embedded-plugins", "build:babel-transformer": "cd babel-transformer && yarn build", "build:pkg": "cd pkg && yarn build", + "build:eslint": "cd eslint-plugin-flipper && yarn build", "prebuild": "yarn build:pkg && yarn rm-dist", "build": "cross-env NODE_ENV=production ./ts-node scripts/build-release.ts $@", "build:dev": "cross-env NODE_ENV=development ./ts-node scripts/build-release.ts $@", @@ -252,6 +256,7 @@ "test-with-device": "yarn build:pkg && USE_ELECTRON_STUBS=1 jest --testMatch=\"**/**.device\\.(js|jsx|ts|tsx)\" --detectOpenHandles", "test-e2e": "cd e2e && yarn test", "lint:tsc": "tsc --noemit", + "prelint:eslint": "yarn build:eslint", "lint:eslint": "eslint . --ext .js,.ts,.tsx", "lint:flow": "flow check", "lint": "yarn lint:eslint && yarn lint:flow && yarn lint:tsc", diff --git a/desktop/plugins/databases/__test__/DatabaseDetailSidebar.node.tsx b/desktop/plugins/databases/__test__/DatabaseDetailSidebar.node.tsx index a87e04e5c..a0a84d637 100644 --- a/desktop/plugins/databases/__test__/DatabaseDetailSidebar.node.tsx +++ b/desktop/plugins/databases/__test__/DatabaseDetailSidebar.node.tsx @@ -9,6 +9,8 @@ import {render, fireEvent} from '@testing-library/react'; import React from 'react'; +// TODO T71355623 +// eslint-disable-next-line flipper/no-relative-imports-across-packages import reducers, {Store} from '../../../app/src/reducers'; import configureStore from 'redux-mock-store'; import {Provider} from 'react-redux'; diff --git a/desktop/tsconfig.base.json b/desktop/tsconfig.base.json index fd70f3f64..726542394 100644 --- a/desktop/tsconfig.base.json +++ b/desktop/tsconfig.base.json @@ -20,6 +20,7 @@ "paths": { "flipper": ["./app/src"], "flipper-plugin": ["./flipper-plugin/src"], + "eslint-plugin-flipper": ["./eslint-plugin-flipper/src"], "flipper-*": ["./*/src"], "*": ["./*", "./types/*"] } diff --git a/desktop/yarn.lock b/desktop/yarn.lock index 806f02748..68a978970 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -195,14 +195,22 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.5.0", "@babel/generator@^7.9.0": - version "7.9.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.3.tgz#7c8b2956c6f68b3ab732bd16305916fbba521d94" - integrity sha512-RpxM252EYsz9qLUIq6F7YJyK1sv0wWDBFuztfDGWaQKzHjqDHysxSiRUpA/X9jmfqo+WzkAVKFaUily5h+gDCQ== +"@babel/eslint-parser@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.11.0.tgz#b123924edd44508782c030066c926f1b807151cd" + integrity sha512-dJDM2Pc01D9TwKL3Mmz2xgVF9X953RBHq9H4gywbN1q8MrfvXmNHfsCt06vvByBVQqm+9WxMs+doEH/R09TwWQ== dependencies: - "@babel/types" "^7.9.0" + eslint-scope "5.1.0" + eslint-visitor-keys "^1.3.0" + semver "^6.3.0" + +"@babel/generator@^7.11.0", "@babel/generator@^7.5.0", "@babel/generator@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" + integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== + dependencies: + "@babel/types" "^7.11.0" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" "@babel/helper-annotate-as-pure@^7.8.3": @@ -286,21 +294,21 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-function-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" - integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== +"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-get-function-arity@^7.10.1", "@babel/helper-get-function-arity@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz#7303390a81ba7cb59613895a192b93850e373f7d" - integrity sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw== +"@babel/helper-get-function-arity@^7.10.1", "@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" "@babel/helper-hoist-variables@^7.8.3": version "7.8.3" @@ -384,14 +392,14 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-split-export-declaration@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" - integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== +"@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.8.3": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.11.0" -"@babel/helper-validator-identifier@^7.10.1", "@babel/helper-validator-identifier@^7.10.4": +"@babel/helper-validator-identifier@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== @@ -424,10 +432,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.10.4", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0", "@babel/parser@^7.9.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64" - integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0", "@babel/parser@^7.9.4": + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.2.tgz#0882ab8a455df3065ea2dcb4c753b2460a24bead" + integrity sha512-Vuj/+7vLo6l1Vi7uuO+1ngCDNeVmNbTngcJFKCR/oEtz8tKz0CJxZEGmPt9KcIloZhOZ3Zit6xbpXT2MDlS9Vw== "@babel/plugin-external-helpers@^7.0.0": version "7.8.3" @@ -1089,37 +1097,37 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.0.0", "@babel/template@^7.3.3", "@babel/template@^7.8.3", "@babel/template@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" - integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== +"@babel/template@^7.0.0", "@babel/template@^7.10.4", "@babel/template@^7.3.3", "@babel/template@^7.8.3", "@babel/template@^7.8.6": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.6" - "@babel/types" "^7.8.6" + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892" - integrity sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" + integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.0" - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.0" - "@babel/types" "^7.9.0" + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.0" + "@babel/types" "^7.11.0" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" + lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.10.1", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.2.tgz#30283be31cad0dbf6fb00bd40641ca0ea675172d" - integrity sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" + integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== dependencies: - "@babel/helper-validator-identifier" "^7.10.1" - lodash "^4.17.13" + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": @@ -2064,16 +2072,11 @@ dependencies: "@types/lodash" "*" -"@types/lodash@*": +"@types/lodash@*", "@types/lodash@^4.14.150": version "4.14.157" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.157.tgz#fdac1c52448861dfde1a2e1515dbc46e54926dc8" integrity sha512-Ft5BNFmv2pHDgxV5JDsndOWTRJ+56zte0ZpYLowp03tW+K+t8u8YMOzAnpuqPgzX6WO1XpDIUm7u04M8vdDiVQ== -"@types/lodash@^4.14.150": - version "4.14.150" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.150.tgz#649fe44684c3f1fcb6164d943c5a61977e8cf0bd" - integrity sha512-kMNLM5JBcasgYscD9x/Gvr6lTAv2NVgsKtet/hm93qMyf/D1pt+7jeEZklKJKxMVmXjxbRVQQGfqDSfipYCO6w== - "@types/mime@*": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" @@ -2474,6 +2477,17 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" +"@typescript-eslint/experimental-utils@3.8.0", "@typescript-eslint/experimental-utils@^3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.8.0.tgz#ac1f7c88322dcfb7635ece6f0441516dd951099a" + integrity sha512-o8T1blo1lAJE0QDsW7nSyvZHbiDzQDjINJKyB44Z3sSL39qBy5L10ScI/XwDtaiunoyKGLiY9bzRk4YjsUZl8w== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/types" "3.8.0" + "@typescript-eslint/typescript-estree" "3.8.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + "@typescript-eslint/parser@^2.19.2": version "2.19.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.19.2.tgz#21f42c0694846367e7d6a907feb08ab2f89c0879" @@ -2484,6 +2498,22 @@ "@typescript-eslint/typescript-estree" "2.19.2" eslint-visitor-keys "^1.1.0" +"@typescript-eslint/parser@^3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.8.0.tgz#8e1dcd404299bf79492409c81c415fa95a7c622b" + integrity sha512-u5vjOBaCsnMVQOvkKCXAmmOhyyMmFFf5dbkM3TIbg3MZ2pyv5peE4gj81UAbTHwTOXEwf7eCQTUMKrDl/+qGnA== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "3.8.0" + "@typescript-eslint/types" "3.8.0" + "@typescript-eslint/typescript-estree" "3.8.0" + eslint-visitor-keys "^1.1.0" + +"@typescript-eslint/types@3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.8.0.tgz#58581dd863f86e0cd23353d94362bb90b4bea796" + integrity sha512-8kROmEQkv6ss9kdQ44vCN1dTrgu4Qxrd2kXr10kz2NP5T8/7JnEfYNxCpPkArbLIhhkGLZV3aVMplH1RXQRF7Q== + "@typescript-eslint/typescript-estree@2.19.2": version "2.19.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.19.2.tgz#67485b00172f400474d243c6c0be27581a579350" @@ -2510,6 +2540,27 @@ semver "^6.3.0" tsutils "^3.17.1" +"@typescript-eslint/typescript-estree@3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.8.0.tgz#0606d19f629f813dbdd5a34c7a1e895d6191cac6" + integrity sha512-MTv9nPDhlKfclwnplRNDL44mP2SY96YmPGxmMbMy6x12I+pERcxpIUht7DXZaj4mOKKtet53wYYXU0ABaiXrLw== + dependencies: + "@typescript-eslint/types" "3.8.0" + "@typescript-eslint/visitor-keys" "3.8.0" + debug "^4.1.1" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/visitor-keys@3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.8.0.tgz#ad35110249fb3fc30a36bfcbfeea93e710cfaab1" + integrity sha512-gfqQWyVPpT9NpLREXNR820AYwgz+Kr1GuF3nf1wxpHD6hdxI62tq03ToomFnDxY0m3pUB39IF7sil7D5TQexLA== + dependencies: + eslint-visitor-keys "^1.1.0" + "@yarnpkg/lockfile@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" @@ -3020,14 +3071,14 @@ babel-core@^7.0.0-bridge.0: integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== babel-eslint@^10.0.1: - version "10.0.3" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" - integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA== + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" eslint-visitor-keys "^1.0.0" resolve "^1.12.0" @@ -5108,7 +5159,7 @@ eslint-rule-composer@^0.3.0: resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== -eslint-scope@^5.0.0, eslint-scope@^5.1.0: +eslint-scope@5.1.0, eslint-scope@^5.0.0, eslint-scope@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== @@ -5123,7 +5174,7 @@ eslint-utils@^2.0.0: dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.2.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.2.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== @@ -5822,10 +5873,10 @@ fs-extra@^8.0.1, fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.0.tgz#b6afc31036e247b2466dc99c29ae797d5d4580a3" - integrity sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g== +fs-extra@^9.0.0, fs-extra@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" + integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== dependencies: at-least-node "^1.0.0" graceful-fs "^4.2.0" @@ -8352,6 +8403,11 @@ metro-inspector-proxy@0.60.0: ws "^1.1.5" yargs "^15.3.1" +metro-memory-fs@^0.61.0: + version "0.61.0" + resolved "https://registry.yarnpkg.com/metro-memory-fs/-/metro-memory-fs-0.61.0.tgz#31a2ddc9a9cadd5d8f147b57e0cc4a11a0f96203" + integrity sha512-0YN95SMYExvZALvFp6gdaK9FVyYlpQEMD6J8USNGOL3SZxRvZLlYrxhw2TMdPVP3eQg27GQYT1tc2r7dGZuUIg== + metro-minify-terser@^0.60.0: version "0.60.0" resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.60.0.tgz#743550c96edccd3bcbf6d9b83b78e89c314b4c04"