From 84ddad279188616a556ec1b601b651fb8ac0b2e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Caetano?= Date: Mon, 30 Sep 2019 18:28:02 -0300 Subject: [PATCH 1/4] feat(ESLint): add ESLint rule to parse hooks --- .eslintrc.js | 29 + eslint-plugin/.babelrc | 3 + eslint-plugin/.gitignore | 1 + eslint-plugin/README.md | 51 + eslint-plugin/package.json | 27 + .../ESLintRuleExhaustiveDeps-test.js | 5066 +++++++++++++++++ eslint-plugin/src/index.js | 11 + eslint-plugin/src/rules/ExaustiveDeps.js | 1257 ++++ eslint-plugin/yarn.lock | 2953 ++++++++++ jest.config.js | 10 +- package.json | 8 +- src/__tests__/useEffectUpdate.ts | 13 +- src/index.tsx | 14 +- yarn.lock | 636 ++- 14 files changed, 10043 insertions(+), 36 deletions(-) create mode 100644 .eslintrc.js create mode 100644 eslint-plugin/.babelrc create mode 100644 eslint-plugin/.gitignore create mode 100644 eslint-plugin/README.md create mode 100644 eslint-plugin/package.json create mode 100644 eslint-plugin/src/__tests__/ESLintRuleExhaustiveDeps-test.js create mode 100644 eslint-plugin/src/index.js create mode 100644 eslint-plugin/src/rules/ExaustiveDeps.js create mode 100644 eslint-plugin/yarn.lock diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..4d17014 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,29 @@ +module.exports = { + env: { + browser: true, + es6: true, + }, + globals: { + Atomics: 'readonly', + SharedArrayBuffer: 'readonly', + }, + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 2018, + sourceType: 'module', + }, + plugins: [ + 'react', + '@typescript-eslint', + 'react-hooks', + '@react-hook-utilities', + ], + rules: { + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'warn', + '@react-hook-utilities/exhaustive-deps': 'warn', + }, +}; diff --git a/eslint-plugin/.babelrc b/eslint-plugin/.babelrc new file mode 100644 index 0000000..8aa924d --- /dev/null +++ b/eslint-plugin/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/preset-env"] +} \ No newline at end of file diff --git a/eslint-plugin/.gitignore b/eslint-plugin/.gitignore new file mode 100644 index 0000000..f1ff06d --- /dev/null +++ b/eslint-plugin/.gitignore @@ -0,0 +1 @@ +lib/ \ No newline at end of file diff --git a/eslint-plugin/README.md b/eslint-plugin/README.md new file mode 100644 index 0000000..c73482f --- /dev/null +++ b/eslint-plugin/README.md @@ -0,0 +1,51 @@ +# @react-hook-utilities/eslint-plugin + +ESLint rules for hook utils + +## Installation + +You'll first need to install [ESLint](http://eslint.org): + +``` +$ npm i eslint --save-dev +``` + +Next, install `@react-hook-utilities/eslint-plugin`: + +``` +$ npm install @react-hook-utilities/eslint-plugin --save-dev +``` + +**Note:** If you installed ESLint globally (using the `-g` flag) then you must also install `@react-hook-utilities/eslint-plugin` globally. + +## Usage + +Add `@react-hook-utilities` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix: + +```json +{ + "plugins": [ + "@react-hook-utilities" + ] +} +``` + + +Then configure the rules you want to use under the rules section. + +```json +{ + "rules": { + "@react-hook-utilities/exhaustive-deps": 2 + } +} +``` + +## Supported Rules + +* Fill in provided rules here + + + + + diff --git a/eslint-plugin/package.json b/eslint-plugin/package.json new file mode 100644 index 0000000..1bba449 --- /dev/null +++ b/eslint-plugin/package.json @@ -0,0 +1,27 @@ +{ + "name": "@react-hook-utilities/eslint-plugin", + "version": "1.0.0", + "description": "ESLint rules for hook react-hook-utilities", + "keywords": [ + "eslint", + "eslintplugin", + "eslint-plugin" + ], + "author": "Flávio Caetano", + "main": "lib/index.js", + "scripts": { + "test": "mocha tests --recursive src/__tests__/**/*", + "babel": "rm -rf lib && babel src/ -d ./lib" + }, + "devDependencies": { + "@babel/cli": "^7.6.2", + "@babel/preset-env": "^7.6.2", + "babel-eslint": "^10.0.3", + "eslint": "~3.9.1", + "mocha": "^3.1.2" + }, + "engines": { + "node": ">=0.10.0" + }, + "license": "ISC" +} diff --git a/eslint-plugin/src/__tests__/ESLintRuleExhaustiveDeps-test.js b/eslint-plugin/src/__tests__/ESLintRuleExhaustiveDeps-test.js new file mode 100644 index 0000000..cd50089 --- /dev/null +++ b/eslint-plugin/src/__tests__/ESLintRuleExhaustiveDeps-test.js @@ -0,0 +1,5066 @@ +/** + * 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. + * + * Original Source: https://github.com/facebook/react/blob/9e64bf18e11828d6b4c0363bff5ed2eca1ccd838/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js + */ + +'use strict'; + +const ESLintTester = require('eslint').RuleTester; +const ReactHooksESLintPlugin = require('@react-hook-utilities/eslint-plugin'); +const ReactHooksESLintRule = ReactHooksESLintPlugin.rules['exhaustive-deps']; + +ESLintTester.setDefaultConfig({ + parser: require.resolve('babel-eslint'), + parserOptions: { + ecmaVersion: 6, + sourceType: 'module', + }, +}); + +// *************************************************** +// For easier local testing, you can add to any case: +// { +// skip: true, +// --or-- +// only: true, +// ... +// } +// *************************************************** + +const tests = { + valid: [ + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }); + } + `, + }, + { + code: ` + function MyComponent() { + const local = {}; + useDidMount(() => { + console.log(local); + }); + } + `, + }, + { + code: ` + function MyComponent() { + const local = {}; + useDidMount(() => { + return history.listen(); + }); + } + `, + }, + { + code: ` + function MyComponent() { + const local = {}; + useDidMount(async () => { + console.log(local); + }); + } + `, + }, + { + code: ` + function MyComponent() { + const local = {}; + useDidUnmount(() => { + console.log(local); + }); + } + `, + }, + { + code: ` + function MyComponent() { + const local = {}; + useDidUnmount(async () => { + console.log(local); + }); + } + `, + }, + { + code: ` + function MyComponent() { + useAsyncEffect(async () => { + const local = {}; + console.log(local); + }, []); + } + `, + }, + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [local]); + } + `, + }, + { + // OK because `props` wasn't defined. + // We don't technically know if `props` is supposed + // to be an import that hasn't been added yet, or + // a component-level variable. Ignore it until it + // gets defined (a different rule would flag it anyway). + code: ` + function MyComponent() { + useAsyncEffect(async () => { + console.log(props.foo); + }, []); + } + `, + }, + { + code: ` + function MyComponent() { + const local1 = {}; + { + const local2 = {}; + useAsyncEffect(async () => { + console.log(local1); + console.log(local2); + }); + } + } + `, + }, + { + code: ` + function MyComponent() { + const local1 = {}; + { + const local2 = {}; + useWorker(async () => { + console.log(local1); + console.log(local2); + }, [local1, local2]); + } + } + `, + }, + { + code: ` + function MyComponent() { + const local1 = {}; + function MyNestedComponent() { + const local2 = {}; + useWorker(async () => { + console.log(local1); + console.log(local2); + }, [local2]); + } + } + `, + }, + { + code: ` + function MyComponent() { + const local1 = {}; + { + const local2 = {}; + useWorkerLoad(async () => { + console.log(local1); + console.log(local2); + }, [local1, local2]); + } + } + `, + }, + { + code: ` + function MyComponent() { + const local1 = {}; + function MyNestedComponent() { + const local2 = {}; + useWorkerLoad(async () => { + console.log(local1); + console.log(local2); + }, [local2]); + } + } + `, + }, + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + console.log(local); + }, [local]); + } + `, + }, + { + code: ` + function MyComponent() { + useAsyncEffect(async () => { + console.log(unresolved); + }, []); + } + `, + }, + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [,,,local,,,]); + } + `, + }, + { + // Regression test + code: ` + function MyComponent({ foo }) { + useAsyncEffect(async () => { + console.log(foo.length); + }, [foo]); + } + `, + }, + { + // Regression test + code: ` + function MyComponent({ foo }) { + useAsyncEffect(async () => { + console.log(foo.length); + console.log(foo.slice(0)); + }, [foo]); + } + `, + }, + { + // Regression test + code: ` + function MyComponent({ history }) { + useAsyncEffect(async () => { + return history.listen(); + }, [history]); + } + `, + }, + { + // Valid because they have meaning without deps. + code: ` + function MyComponent(props) { + useAsyncEffect(async () => {}); + useAsyncLayoutEffect(async () => {}); + useConditionalEffect(props.innerRef, () => {}); + } + `, + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo); + }, [props.foo]); + } + `, + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo); + console.log(props.bar); + }, [props.bar, props.foo]); + } + `, + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo); + console.log(props.bar); + }, [props.foo, props.bar]); + } + `, + }, + { + code: ` + function MyComponent(props) { + const local = {}; + useAsyncEffect(async () => { + console.log(props.foo); + console.log(props.bar); + console.log(local); + }, [props.foo, props.bar, local]); + } + `, + }, + { + // [props, props.foo] is technically unnecessary ('props' covers 'props.foo'). + // However, it's valid for effects to over-specify their deps. + // So we don't warn about this. We *would* warn about useEffectUpdate/useWorker. + code: ` + function MyComponent(props) { + const local = {}; + useAsyncEffect(async () => { + console.log(props.foo); + console.log(props.bar); + }, [props, props.foo]); + + let color = {} + useAsyncEffect(async () => { + console.log(props.foo.bar.baz); + console.log(color); + }, [props.foo, props.foo.bar.baz, color]); + } + `, + }, + { + // Valid because we don't care about hooks outside of components. + code: ` + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, []); + `, + }, + { + // Valid because we don't care about hooks outside of components. + code: ` + const local1 = {}; + { + const local2 = {}; + useAsyncEffect(async () => { + console.log(local1); + console.log(local2); + }, []); + } + `, + }, + { + code: ` + function MyComponent() { + const ref = useRef(); + useAsyncEffect(async () => { + console.log(ref.current); + }, [ref]); + } + `, + }, + { + code: ` + function MyComponent() { + const ref = useRef(); + useAsyncEffect(async () => { + console.log(ref.current); + }, []); + } + `, + }, + { + code: ` + function MyComponent({ maybeRef2, foo }) { + const definitelyRef1 = useRef(); + const definitelyRef2 = useRef(); + const maybeRef1 = useSomeOtherRefyThing(); + const [state1, setState1] = useState(); + const [state2, setState2] = React.useState(); + const [state3, dispatch1] = useReducer(); + const [state4, dispatch2] = React.useReducer(); + const [state5, maybeSetState] = useFunnyState(); + const [state6, maybeDispatch] = useFunnyReducer(); + const mySetState = useWorker(async () => {}, []); + let myDispatch = useWorker(async () => {}, []); + + useAsyncEffect(async () => { + // Known to be static + console.log(definitelyRef1.current); + console.log(definitelyRef2.current); + console.log(maybeRef1.current); + console.log(maybeRef2.current); + setState1(); + setState2(); + dispatch1(); + dispatch2(); + + // Dynamic + console.log(state1); + console.log(state2); + console.log(state3); + console.log(state4); + console.log(state5); + console.log(state6); + mySetState(); + myDispatch(); + + // Not sure; assume dynamic + maybeSetState(); + maybeDispatch(); + }, [ + // Dynamic + state1, state2, state3, state4, state5, state6, + maybeRef1, maybeRef2, + + // Not sure; assume dynamic + mySetState, myDispatch, + maybeSetState, maybeDispatch + + // In this test, we don't specify static deps. + // That should be okay. + ]); + } + `, + }, + { + code: ` + function MyComponent({ maybeRef2 }) { + const definitelyRef1 = useRef(); + const definitelyRef2 = useRef(); + const maybeRef1 = useSomeOtherRefyThing(); + + const [state1, setState1] = useState(); + const [state2, setState2] = React.useState(); + const [state3, dispatch1] = useReducer(); + const [state4, dispatch2] = React.useReducer(); + + const [state5, maybeSetState] = useFunnyState(); + const [state6, maybeDispatch] = useFunnyReducer(); + + const mySetState = useWorker(async () => {}, []); + let myDispatch = useWorker(async () => {}, []); + + useAsyncEffect(async () => { + // Known to be static + console.log(definitelyRef1.current); + console.log(definitelyRef2.current); + console.log(maybeRef1.current); + console.log(maybeRef2.current); + setState1(); + setState2(); + dispatch1(); + dispatch2(); + + // Dynamic + console.log(state1); + console.log(state2); + console.log(state3); + console.log(state4); + console.log(state5); + console.log(state6); + mySetState(); + myDispatch(); + + // Not sure; assume dynamic + maybeSetState(); + maybeDispatch(); + }, [ + // Dynamic + state1, state2, state3, state4, state5, state6, + maybeRef1, maybeRef2, + + // Not sure; assume dynamic + mySetState, myDispatch, + maybeSetState, maybeDispatch, + + // In this test, we specify static deps. + // That should be okay too! + definitelyRef1, definitelyRef2, setState1, setState2, dispatch1, dispatch2 + ]); + } + `, + }, + { + code: ` + function MyComponent({ maybeRef2, foo }) { + const definitelyRef1 = useRef(); + const definitelyRef2 = useRef(); + const maybeRef1 = useSomeOtherRefyThing(); + const [state1, setState1] = useState(); + const [state2, setState2] = React.useState(); + const [state3, dispatch1] = useReducer(); + const [state4, dispatch2] = React.useReducer(); + const [state5, maybeSetState] = useFunnyState(); + const [state6, maybeDispatch] = useFunnyReducer(); + const mySetState = useWorkerLoad(async () => {}, []); + let myDispatch = useWorkerLoad(async () => {}, []); + + useAsyncEffect(async () => { + // Known to be static + console.log(definitelyRef1.current); + console.log(definitelyRef2.current); + console.log(maybeRef1.current); + console.log(maybeRef2.current); + setState1(); + setState2(); + dispatch1(); + dispatch2(); + + // Dynamic + console.log(state1); + console.log(state2); + console.log(state3); + console.log(state4); + console.log(state5); + console.log(state6); + mySetState(); + myDispatch(); + + // Not sure; assume dynamic + maybeSetState(); + maybeDispatch(); + }, [ + // Dynamic + state1, state2, state3, state4, state5, state6, + maybeRef1, maybeRef2, + + // Not sure; assume dynamic + mySetState, myDispatch, + maybeSetState, maybeDispatch + + // In this test, we don't specify static deps. + // That should be okay. + ]); + } + `, + }, + { + code: ` + function MyComponent({ maybeRef2 }) { + const definitelyRef1 = useRef(); + const definitelyRef2 = useRef(); + const maybeRef1 = useSomeOtherRefyThing(); + + const [state1, setState1] = useState(); + const [state2, setState2] = React.useState(); + const [state3, dispatch1] = useReducer(); + const [state4, dispatch2] = React.useReducer(); + + const [state5, maybeSetState] = useFunnyState(); + const [state6, maybeDispatch] = useFunnyReducer(); + + const mySetState = useWorkerLoad(async () => {}, []); + let myDispatch = useWorkerLoad(async () => {}, []); + + useAsyncEffect(async () => { + // Known to be static + console.log(definitelyRef1.current); + console.log(definitelyRef2.current); + console.log(maybeRef1.current); + console.log(maybeRef2.current); + setState1(); + setState2(); + dispatch1(); + dispatch2(); + + // Dynamic + console.log(state1); + console.log(state2); + console.log(state3); + console.log(state4); + console.log(state5); + console.log(state6); + mySetState(); + myDispatch(); + + // Not sure; assume dynamic + maybeSetState(); + maybeDispatch(); + }, [ + // Dynamic + state1, state2, state3, state4, state5, state6, + maybeRef1, maybeRef2, + + // Not sure; assume dynamic + mySetState, myDispatch, + maybeSetState, maybeDispatch, + + // In this test, we specify static deps. + // That should be okay too! + definitelyRef1, definitelyRef2, setState1, setState2, dispatch1, dispatch2 + ]); + } + `, + }, + { + code: ` + const MyComponent = forwardRef((props, ref) => { + useConditionalEffect(ref, () => ({ + focus() { + alert(props.hello); + } + })) + }); + `, + }, + { + code: ` + const MyComponent = forwardRef((props, ref) => { + useConditionalEffect(ref, () => ({ + focus() { + alert(props.hello); + } + }), [props.hello]) + }); + `, + }, + { + // This is not ideal but warning would likely create + // too many false positives. We do, however, prevent + // direct assignments. + code: ` + function MyComponent(props) { + let obj = {}; + useAsyncEffect(async () => { + obj.foo = true; + }, [obj]); + } + `, + }, + { + // Valid because we assign ref.current + // ourselves. Therefore it's likely not + // a ref managed by React. + code: ` + function MyComponent() { + const myRef = useRef(); + useAsyncEffect(async () => { + const handleMove = () => {}; + myRef.current = {}; + return () => { + console.log(myRef.current.toString()) + }; + }, []); + return
; + } + `, + }, + { + // Valid because we assign ref.current + // ourselves. Therefore it's likely not + // a ref managed by React. + code: ` + function useMyThing(myRef) { + useAsyncEffect(async () => { + const handleMove = () => {}; + myRef.current = {}; + return () => { + console.log(myRef.current.toString()) + }; + }, [myRef]); + } + `, + }, + { + // Valid because the ref is captured. + code: ` + function MyComponent() { + const myRef = useRef(); + useAsyncEffect(async () => { + const handleMove = () => {}; + const node = myRef.current; + node.addEventListener('mousemove', handleMove); + return () => node.removeEventListener('mousemove', handleMove); + }, []); + return
; + } + `, + }, + { + // Valid because the ref is captured. + code: ` + function useMyThing(myRef) { + useAsyncEffect(async () => { + const handleMove = () => {}; + const node = myRef.current; + node.addEventListener('mousemove', handleMove); + return () => node.removeEventListener('mousemove', handleMove); + }, [myRef]); + return
; + } + `, + }, + { + // Valid because it's not an effect. + code: ` + function useMyThing(myRef) { + useWorker(async () => { + const handleMouse = () => {}; + myRef.current.addEventListener('mousemove', handleMouse); + myRef.current.addEventListener('mousein', handleMouse); + return function() { + setTimeout(() => { + myRef.current.removeEventListener('mousemove', handleMouse); + myRef.current.removeEventListener('mousein', handleMouse); + }); + } + }, [myRef]); + } + `, + }, + { + // Valid because it's not an effect. + code: ` + function useMyThing(myRef) { + useWorkerLoad(async () => { + const handleMouse = () => {}; + myRef.current.addEventListener('mousemove', handleMouse); + myRef.current.addEventListener('mousein', handleMouse); + return function() { + setTimeout(() => { + myRef.current.removeEventListener('mousemove', handleMouse); + myRef.current.removeEventListener('mousein', handleMouse); + }); + } + }, [myRef]); + } + `, + }, + { + // Valid because we read ref.current in a function that isn't cleanup. + code: ` + function useMyThing() { + const myRef = useRef(); + useAsyncEffect(async () => { + const handleMove = () => { + console.log(myRef.current) + }; + window.addEventListener('mousemove', handleMove); + return () => window.removeEventListener('mousemove', handleMove); + }, []); + return
; + } + `, + }, + { + // Valid because we read ref.current in a function that isn't cleanup. + code: ` + function useMyThing() { + const myRef = useRef(); + useAsyncEffect(async () => { + const handleMove = () => { + return () => window.removeEventListener('mousemove', handleMove); + }; + window.addEventListener('mousemove', handleMove); + return () => {}; + }, []); + return
; + } + `, + }, + { + // Valid because it's a primitive constant. + code: ` + function MyComponent() { + const local1 = 42; + const local2 = '42'; + const local3 = null; + useAsyncEffect(async () => { + console.log(local1); + console.log(local2); + console.log(local3); + }, []); + } + `, + }, + { + // It's not a mistake to specify constant values though. + code: ` + function MyComponent() { + const local1 = 42; + const local2 = '42'; + const local3 = null; + useAsyncEffect(async () => { + console.log(local1); + console.log(local2); + console.log(local3); + }, [local1, local2, local3]); + } + `, + }, + { + // It is valid for effects to over-specify their deps. + code: ` + function MyComponent(props) { + const local = props.local; + useAsyncEffect(async () => {}, [local]); + } + `, + }, + { + // Valid even though activeTab is "unused". + // We allow over-specifying deps for effects, but not callbacks or memo. + code: ` + function Foo({ activeTab }) { + useAsyncEffect(async () => { + window.scrollTo(0, 0); + }, [activeTab]); + } + `, + }, + { + // It is valid to specify broader effect deps than strictly necessary. + // Don't warn for this. + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo.bar.baz); + }, [props]); + useAsyncEffect(async () => { + console.log(props.foo.bar.baz); + }, [props.foo]); + useAsyncEffect(async () => { + console.log(props.foo.bar.baz); + }, [props.foo.bar]); + useAsyncEffect(async () => { + console.log(props.foo.bar.baz); + }, [props.foo.bar.baz]); + } + `, + }, + { + // It is *also* valid to specify broader memo/callback deps than strictly necessary. + // Don't warn for this either. + code: ` + function MyComponent(props) { + const fn = useWorker(async () => { + console.log(props.foo.bar.baz); + }, [props]); + const fn2 = useWorker(async () => { + console.log(props.foo.bar.baz); + }, [props.foo]); + const fn3 = useEffectUpdate(() => { + console.log(props.foo.bar.baz); + }, [props.foo.bar]); + const fn4 = useEffectUpdate(() => { + console.log(props.foo.bar.baz); + }, [props.foo.bar.baz]); + } + `, + }, + { + // It is *also* valid to specify broader memo/callback deps than strictly necessary. + // Don't warn for this either. + code: ` + function MyComponent(props) { + const fn = useWorkerLoad(async () => { + console.log(props.foo.bar.baz); + }, [props]); + const fn2 = useWorkerLoad(async () => { + console.log(props.foo.bar.baz); + }, [props.foo]); + const fn3 = useEffectUpdate(() => { + console.log(props.foo.bar.baz); + }, [props.foo.bar]); + const fn4 = useEffectUpdate(() => { + console.log(props.foo.bar.baz); + }, [props.foo.bar.baz]); + } + `, + }, + { + // Declaring handleNext is optional because + // it doesn't use anything in the function scope. + code: ` + function MyComponent(props) { + function handleNext1() { + console.log('hello'); + } + const handleNext2 = () => { + console.log('hello'); + }; + let handleNext3 = function() { + console.log('hello'); + }; + useAsyncEffect(async () => { + return Store.subscribe(handleNext1); + }, []); + useAsyncLayoutEffect(async () => { + return Store.subscribe(handleNext2); + }, []); + useEffectUpdate(() => { + return Store.subscribe(handleNext3); + }, []); + } + `, + }, + { + // Declaring handleNext is optional because + // it doesn't use anything in the function scope. + code: ` + function MyComponent(props) { + function handleNext() { + console.log('hello'); + } + useAsyncEffect(async () => { + return Store.subscribe(handleNext); + }, []); + useAsyncLayoutEffect(async () => { + return Store.subscribe(handleNext); + }, []); + useEffectUpdate(() => { + return Store.subscribe(handleNext); + }, []); + } + `, + }, + { + // Declaring handleNext is optional because + // everything they use is fully static. + code: ` + function MyComponent(props) { + let [, setState] = useState(); + let [, dispatch] = React.useReducer(); + + function handleNext1(value) { + let value2 = value * 100; + setState(value2); + console.log('hello'); + } + const handleNext2 = (value) => { + setState(foo(value)); + console.log('hello'); + }; + let handleNext3 = function(value) { + console.log(value); + dispatch({ type: 'x', value }); + }; + useAsyncEffect(async () => { + return Store.subscribe(handleNext1); + }, []); + useAsyncLayoutEffect(async () => { + return Store.subscribe(handleNext2); + }, []); + useEffectUpdate(() => { + return Store.subscribe(handleNext3); + }, []); + } + `, + }, + { + code: ` + function useInterval(callback, delay) { + const savedCallback = useRef(); + useAsyncEffect(async () => { + savedCallback.current = callback; + }); + useAsyncEffect(async () => { + function tick() { + savedCallback.current(); + } + if (delay !== null) { + let id = setInterval(tick, delay); + return () => clearInterval(id); + } + }, [delay]); + } + `, + }, + { + code: ` + function Counter() { + const [count, setCount] = useState(0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(c => c + 1); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + }, + { + code: ` + function Counter() { + const [count, setCount] = useState(0); + + function tick() { + setCount(c => c + 1); + } + + useAsyncEffect(async () => { + let id = setInterval(() => { + tick(); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + }, + { + code: ` + function Counter() { + const [count, dispatch] = useReducer((state, action) => { + if (action === 'inc') { + return state + 1; + } + }, 0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + dispatch('inc'); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + }, + { + code: ` + function Counter() { + const [count, dispatch] = useReducer((state, action) => { + if (action === 'inc') { + return state + 1; + } + }, 0); + + const tick = () => { + dispatch('inc'); + }; + + useAsyncEffect(async () => { + let id = setInterval(tick, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + }, + { + // Regression test for a crash + code: ` + function Podcasts() { + useAsyncEffect(async () => { + setPodcasts([]); + }, []); + let [podcasts, setPodcasts] = useState(null); + } + `, + }, + { + code: ` + function withFetch(fetchPodcasts) { + return function Podcasts({ id }) { + let [podcasts, setPodcasts] = useState(null); + useAsyncEffect(async () => { + fetchPodcasts(id).then(setPodcasts); + }, [id]); + } + } + `, + }, + { + code: ` + function Podcasts({ id }) { + let [podcasts, setPodcasts] = useState(null); + useAsyncEffect(async () => { + function doFetch({ fetchPodcasts }) { + fetchPodcasts(id).then(setPodcasts); + } + doFetch({ fetchPodcasts: API.fetchPodcasts }); + }, [id]); + } + `, + }, + { + code: ` + function Counter() { + let [count, setCount] = useState(0); + + function increment(x) { + return x + 1; + } + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(increment); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + }, + { + code: ` + function Counter() { + let [count, setCount] = useState(0); + + function increment(x) { + return x + 1; + } + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count => increment(count)); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + }, + { + code: ` + import increment from './increment'; + function Counter() { + let [count, setCount] = useState(0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count => count + increment); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + }, + { + code: ` + function withStuff(increment) { + return function Counter() { + let [count, setCount] = useState(0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count => count + increment); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + } + `, + }, + { + code: ` + function App() { + const [query, setQuery] = useState('react'); + const [state, setState] = useState(null); + useAsyncEffect(async () => { + let ignore = false; + fetchSomething(); + async function fetchSomething() { + const result = await (await fetch('http://hn.algolia.com/api/v1/search?query=' + query)).json(); + if (!ignore) setState(result); + } + return () => { ignore = true; }; + }, [query]); + return ( + <> + setQuery(e.target.value)} /> + {JSON.stringify(state)} + + ); + } + `, + }, + { + code: ` + function Example() { + const foo = useWorker(async () => { + foo(); + }, []); + } + `, + }, + { + code: ` + function Example({ prop }) { + const foo = useWorker(async () => { + if (prop) { + foo(); + } + }, [prop]); + } + `, + }, + { + code: ` + function Example() { + const foo = useWorkerLoad(async () => { + foo(); + }, []); + } + `, + }, + { + code: ` + function Example({ prop }) { + const foo = useWorkerLoad(async () => { + if (prop) { + foo(); + } + }, [prop]); + } + `, + }, + { + code: ` + function Hello() { + const [state, setState] = useState(0); + useAsyncEffect(async () => { + const handleResize = () => setState(window.innerWidth); + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }); + } + `, + }, + // Ignore Generic Type Variables for arrow functions + { + code: ` + function Example({ prop }) { + const bar = useAsyncEffect((a: T): Hello => { + prop(); + }, [prop]); + } + `, + }, + // Ignore arguments keyword for arrow functions. + { + code: ` + function Example() { + useAsyncEffect(async () => { + arguments + }, []) + } + `, + }, + { + code: ` + function Example() { + useAsyncEffect(async () => { + const bar = () => { + arguments; + }; + bar(); + }, []) + } + `, + }, + ], + invalid: [ + { + code: ` + function MyComponent() { + const ref = useLazyRef(); + const [state, setState] = useState(); + useAsyncEffect(async () => { + ref.current = {}; + setState(state + 1); + }, []); + } + `, + output: ` + function MyComponent() { + const ref = useLazyRef(); + const [state, setState] = useState(); + useAsyncEffect(async () => { + ref.current = {}; + setState(state + 1); + }, [state]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'state'. " + + 'Either include it or remove the dependency array. ' + + `You can also do a functional update 'setState(s => ...)' ` + + `if you only need 'state' in the 'setState' call.`, + ], + }, + { + code: ` + function MyComponent() { + const ref = useLazyRef(); + const [state, setState] = useState(); + useAsyncEffect(() => { + ref.current = {}; + setState(state + 1); + }, [ref]); + } + `, + // We don't ask to remove static deps but don't add them either. + // Don't suggest removing "ref" (it's fine either way) + // but *do* add "state". *Don't* add "setState" ourselves. + output: ` + function MyComponent() { + const ref = useLazyRef(); + const [state, setState] = useState(); + useAsyncEffect(() => { + ref.current = {}; + setState(state + 1); + }, [ref, state]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'state'. " + + 'Either include it or remove the dependency array. ' + + `You can also do a functional update 'setState(s => ...)' ` + + `if you only need 'state' in the 'setState' call.`, + ], + }, + { + code: ` + function MyComponent(props) { + const ref1 = useLazyRef(); + const ref2 = useLazyRef(); + useAsyncEffect(() => { + ref1.current.focus(); + console.log(ref2.current.textContent); + alert(props.someOtherRefs.current.innerHTML); + fetch(props.color); + }, []); + } + `, + output: ` + function MyComponent(props) { + const ref1 = useLazyRef(); + const ref2 = useLazyRef(); + useAsyncEffect(() => { + ref1.current.focus(); + console.log(ref2.current.textContent); + alert(props.someOtherRefs.current.innerHTML); + fetch(props.color); + }, [props.color, props.someOtherRefs]); + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'props.color' and 'props.someOtherRefs'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + const ref1 = useLazyRef(); + const ref2 = useLazyRef(); + useAsyncEffect(() => { + ref1.current.focus(); + console.log(ref2.current.textContent); + alert(props.someOtherRefs.current.innerHTML); + fetch(props.color); + }, [ref1.current, ref2.current, props.someOtherRefs, props.color]); + } + `, + output: ` + function MyComponent(props) { + const ref1 = useLazyRef(); + const ref2 = useLazyRef(); + useAsyncEffect(() => { + ref1.current.focus(); + console.log(ref2.current.textContent); + alert(props.someOtherRefs.current.innerHTML); + fetch(props.color); + }, [props.someOtherRefs, props.color]); + } + `, + errors: [ + "React Hook useAsyncEffect has unnecessary dependencies: 'ref1.current' and 'ref2.current'. " + + 'Either exclude them or remove the dependency array. ' + + "Mutable values like 'ref1.current' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent() { + const ref = useLazyRef(); + useAsyncEffect(() => { + console.log(ref.current); + }, [ref.current]); + } + `, + output: ` + function MyComponent() { + const ref = useLazyRef(); + useAsyncEffect(() => { + console.log(ref.current); + }, []); + } + `, + errors: [ + "React Hook useAsyncEffect has an unnecessary dependency: 'ref.current'. " + + 'Either exclude it or remove the dependency array. ' + + "Mutable values like 'ref.current' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent({ activeTab }) { + const ref1 = useLazyRef(); + const ref2 = useLazyRef(); + useAsyncEffect(() => { + ref1.current.scrollTop = 0; + ref2.current.scrollTop = 0; + }, [ref1.current, ref2.current, activeTab]); + } + `, + output: ` + function MyComponent({ activeTab }) { + const ref1 = useLazyRef(); + const ref2 = useLazyRef(); + useAsyncEffect(() => { + ref1.current.scrollTop = 0; + ref2.current.scrollTop = 0; + }, [activeTab]); + } + `, + errors: [ + "React Hook useAsyncEffect has unnecessary dependencies: 'ref1.current' and 'ref2.current'. " + + 'Either exclude them or remove the dependency array. ' + + "Mutable values like 'ref1.current' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent({ activeTab, initY }) { + const ref1 = useLazyRef(); + const ref2 = useLazyRef(); + const fn = useWorker(() => { + ref1.current.scrollTop = initY; + ref2.current.scrollTop = initY; + }, [ref1.current, ref2.current, activeTab, initY]); + } + `, + output: ` + function MyComponent({ activeTab, initY }) { + const ref1 = useLazyRef(); + const ref2 = useLazyRef(); + const fn = useWorker(() => { + ref1.current.scrollTop = initY; + ref2.current.scrollTop = initY; + }, [initY]); + } + `, + errors: [ + "React Hook useWorker has unnecessary dependencies: 'activeTab', 'ref1.current', and 'ref2.current'. " + + 'Either exclude them or remove the dependency array. ' + + "Mutable values like 'ref1.current' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent() { + const ref = useLazyRef(); + useAsyncEffect(() => { + console.log(ref.current); + }, [ref.current, ref]); + } + `, + output: ` + function MyComponent() { + const ref = useLazyRef(); + useAsyncEffect(() => { + console.log(ref.current); + }, [ref]); + } + `, + errors: [ + "React Hook useAsyncEffect has an unnecessary dependency: 'ref.current'. " + + 'Either exclude it or remove the dependency array. ' + + "Mutable values like 'ref.current' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, []); + } + `, + output: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Note: we *could* detect it's a primitive and never assigned + // even though it's not a constant -- but we currently don't. + // So this is an error. + code: ` + function MyComponent() { + let local = 42; + useAsyncEffect(async () => { + console.log(local); + }, []); + } + `, + output: ` + function MyComponent() { + let local = 42; + useAsyncEffect(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Regexes are literals but potentially stateful. + code: ` + function MyComponent() { + const local = /foo/; + useAsyncEffect(async () => { + console.log(local); + }, []); + } + `, + output: ` + function MyComponent() { + const local = /foo/; + useAsyncEffect(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Regression test + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + if (true) { + console.log(local); + } + }, []); + } + `, + output: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + if (true) { + console.log(local); + } + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Regression test + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + try { + console.log(local); + } finally {} + }, []); + } + `, + output: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + try { + console.log(local); + } finally {} + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Regression test + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + function inner() { + console.log(local); + } + inner(); + }, []); + } + `, + output: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + function inner() { + console.log(local); + } + inner(); + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + const local1 = {}; + { + const local2 = {}; + useAsyncEffect(async () => { + console.log(local1); + console.log(local2); + }, []); + } + } + `, + output: ` + function MyComponent() { + const local1 = {}; + { + const local2 = {}; + useAsyncEffect(async () => { + console.log(local1); + console.log(local2); + }, [local1, local2]); + } + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'local1' and 'local2'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + const local1 = {}; + const local2 = {}; + useAsyncEffect(async () => { + console.log(local1); + console.log(local2); + }, [local1]); + } + `, + output: ` + function MyComponent() { + const local1 = {}; + const local2 = {}; + useAsyncEffect(async () => { + console.log(local1); + console.log(local2); + }, [local1, local2]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local2'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + const local1 = {}; + function MyNestedComponent() { + const local2 = {}; + useWorker(async () => { + console.log(local1); + console.log(local2); + }, [local1]); + } + } + `, + output: ` + function MyComponent() { + const local1 = {}; + function MyNestedComponent() { + const local2 = {}; + useWorker(async () => { + console.log(local1); + console.log(local2); + }, [local2]); + } + } + `, + errors: [ + "React Hook useWorker has a missing dependency: 'local2'. " + + 'Either include it or remove the dependency array. ' + + "Outer scope values like 'local1' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent() { + const local1 = {}; + function MyNestedComponent() { + const local2 = {}; + useWorkerLoad(async () => { + console.log(local1); + console.log(local2); + }, [local1]); + } + } + `, + output: ` + function MyComponent() { + const local1 = {}; + function MyNestedComponent() { + const local2 = {}; + useWorkerLoad(async () => { + console.log(local1); + console.log(local2); + }, [local2]); + } + } + `, + errors: [ + "React Hook useWorkerLoad has a missing dependency: 'local2'. " + + 'Either include it or remove the dependency array. ' + + "Outer scope values like 'local1' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + console.log(local); + }, []); + } + `, + output: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + console.log(local); + }, [local, local]); + } + `, + output: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a duplicate dependency: 'local'. " + + 'Either omit it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + useWorker(async () => {}, [window]); + } + `, + output: ` + function MyComponent() { + useWorker(async () => {}, []); + } + `, + errors: [ + "React Hook useWorker has an unnecessary dependency: 'window'. " + + 'Either exclude it or remove the dependency array. ' + + "Outer scope values like 'window' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent() { + useWorkerLoad(async () => {}, [window]); + } + `, + output: ` + function MyComponent() { + useWorkerLoad(async () => {}, []); + } + `, + errors: [ + "React Hook useWorkerLoad has an unnecessary dependency: 'window'. " + + 'Either exclude it or remove the dependency array. ' + + "Outer scope values like 'window' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + // It is not valid for useWorker to specify extraneous deps + // because it doesn't serve as a side effect trigger unlike useAsyncEffect. + code: ` + function MyComponent(props) { + let local = props.foo; + useWorker(async () => {}, [local]); + } + `, + output: ` + function MyComponent(props) { + let local = props.foo; + useWorker(async () => {}, []); + } + `, + errors: [ + "React Hook useWorker has an unnecessary dependency: 'local'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + // It is not valid for useWorkerLoad to specify extraneous deps + // because it doesn't serve as a side effect trigger unlike useAsyncEffect. + code: ` + function MyComponent(props) { + let local = props.foo; + useWorkerLoad(async () => {}, [local]); + } + `, + output: ` + function MyComponent(props) { + let local = props.foo; + useWorkerLoad(async () => {}, []); + } + `, + errors: [ + "React Hook useWorkerLoad has an unnecessary dependency: 'local'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent({ history }) { + useAsyncEffect(async () => { + return history.listen(); + }, []); + } + `, + output: ` + function MyComponent({ history }) { + useAsyncEffect(async () => { + return history.listen(); + }, [history]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'history'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent({ history }) { + useAsyncEffect(async () => { + return [ + history.foo.bar[2].dobedo.listen(), + history.foo.bar().dobedo.listen[2] + ]; + }, []); + } + `, + output: ` + function MyComponent({ history }) { + useAsyncEffect(async () => { + return [ + history.foo.bar[2].dobedo.listen(), + history.foo.bar().dobedo.listen[2] + ]; + }, [history.foo]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'history.foo'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + useAsyncEffect(async () => {}, ['foo']); + } + `, + // TODO: we could autofix this. + output: ` + function MyComponent() { + useAsyncEffect(async () => {}, ['foo']); + } + `, + errors: [ + // Don't assume user meant `foo` because it's not used in the effect. + "The 'foo' literal is not a valid dependency because it never changes. " + + 'You can safely remove it.', + ], + }, + { + code: ` + function MyComponent({ foo, bar, baz }) { + useAsyncEffect(async () => { + console.log(foo, bar, baz); + }, ['foo', 'bar']); + } + `, + output: ` + function MyComponent({ foo, bar, baz }) { + useAsyncEffect(async () => { + console.log(foo, bar, baz); + }, [bar, baz, foo]); + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'bar', 'baz', and 'foo'. " + + 'Either include them or remove the dependency array.', + "The 'foo' literal is not a valid dependency because it never changes. " + + 'Did you mean to include foo in the array instead?', + "The 'bar' literal is not a valid dependency because it never changes. " + + 'Did you mean to include bar in the array instead?', + ], + }, + { + code: ` + function MyComponent({ foo, bar, baz }) { + useAsyncEffect(async () => { + console.log(foo, bar, baz); + }, [42, false, null]); + } + `, + output: ` + function MyComponent({ foo, bar, baz }) { + useAsyncEffect(async () => { + console.log(foo, bar, baz); + }, [bar, baz, foo]); + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'bar', 'baz', and 'foo'. " + + 'Either include them or remove the dependency array.', + 'The 42 literal is not a valid dependency because it never changes. You can safely remove it.', + 'The false literal is not a valid dependency because it never changes. You can safely remove it.', + 'The null literal is not a valid dependency because it never changes. You can safely remove it.', + ], + }, + { + code: ` + function MyComponent() { + const dependencies = []; + useAsyncEffect(async () => {}, dependencies); + } + `, + output: ` + function MyComponent() { + const dependencies = []; + useAsyncEffect(async () => {}, dependencies); + } + `, + errors: [ + 'React Hook useAsyncEffect was passed a dependency list that is not an ' + + "array literal. This means we can't statically verify whether you've " + + 'passed the correct dependencies.', + ], + }, + { + code: ` + function MyComponent() { + const local = {}; + const dependencies = [local]; + useAsyncEffect(async () => { + console.log(local); + }, dependencies); + } + `, + // TODO: should this autofix or bail out? + output: ` + function MyComponent() { + const local = {}; + const dependencies = [local]; + useAsyncEffect(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + 'React Hook useAsyncEffect was passed a dependency list that is not an ' + + "array literal. This means we can't statically verify whether you've " + + 'passed the correct dependencies.', + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + const local = {}; + const dependencies = [local]; + useAsyncEffect(async () => { + console.log(local); + }, [...dependencies]); + } + `, + // TODO: should this autofix or bail out? + output: ` + function MyComponent() { + const local = {}; + const dependencies = [local]; + useAsyncEffect(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + 'React Hook useAsyncEffect has a spread element in its dependency array. ' + + "This means we can't statically verify whether you've passed the " + + 'correct dependencies.', + ], + }, + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [local, ...dependencies]); + } + `, + output: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [local, ...dependencies]); + } + `, + errors: [ + 'React Hook useAsyncEffect has a spread element in its dependency array. ' + + "This means we can't statically verify whether you've passed the " + + 'correct dependencies.', + ], + }, + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [computeCacheKey(local)]); + } + `, + // TODO: I'm not sure this is a good idea. + // Maybe bail out? + output: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + 'React Hook useAsyncEffect has a complex expression in the dependency array. ' + + 'Extract it to a separate variable so it can be statically checked.', + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.items[0]); + }, [props.items[0]]); + } + `, + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.items[0]); + }, [props.items]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'props.items'. " + + 'Either include it or remove the dependency array.', + 'React Hook useAsyncEffect has a complex expression in the dependency array. ' + + 'Extract it to a separate variable so it can be statically checked.', + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.items[0]); + }, [props.items, props.items[0]]); + } + `, + // TODO: ideally autofix would remove the bad expression? + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.items[0]); + }, [props.items, props.items[0]]); + } + `, + errors: [ + 'React Hook useAsyncEffect has a complex expression in the dependency array. ' + + 'Extract it to a separate variable so it can be statically checked.', + ], + }, + { + code: ` + function MyComponent({ items }) { + useAsyncEffect(async () => { + console.log(items[0]); + }, [items[0]]); + } + `, + output: ` + function MyComponent({ items }) { + useAsyncEffect(async () => { + console.log(items[0]); + }, [items]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'items'. " + + 'Either include it or remove the dependency array.', + 'React Hook useAsyncEffect has a complex expression in the dependency array. ' + + 'Extract it to a separate variable so it can be statically checked.', + ], + }, + { + code: ` + function MyComponent({ items }) { + useAsyncEffect(async () => { + console.log(items[0]); + }, [items, items[0]]); + } + `, + // TODO: ideally autofix would remove the bad expression? + output: ` + function MyComponent({ items }) { + useAsyncEffect(async () => { + console.log(items[0]); + }, [items, items[0]]); + } + `, + errors: [ + 'React Hook useAsyncEffect has a complex expression in the dependency array. ' + + 'Extract it to a separate variable so it can be statically checked.', + ], + }, + { + // It is not valid for useWorker to specify extraneous deps + // because it doesn't serve as a side effect trigger unlike useAsyncEffect. + // However, we generally allow specifying *broader* deps as escape hatch. + // So while [props, props.foo] is unnecessary, 'props' wins here as the + // broader one, and this is why 'props.foo' is reported as unnecessary. + code: ` + function MyComponent(props) { + const local = {}; + useWorker(async () => { + console.log(props.foo); + console.log(props.bar); + }, [props, props.foo]); + } + `, + output: ` + function MyComponent(props) { + const local = {}; + useWorker(async () => { + console.log(props.foo); + console.log(props.bar); + }, [props]); + } + `, + errors: [ + "React Hook useWorker has an unnecessary dependency: 'props.foo'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + // Since we don't have 'props' in the list, we'll suggest narrow dependencies. + code: ` + function MyComponent(props) { + const local = {}; + useWorker(async () => { + console.log(props.foo); + console.log(props.bar); + }, []); + } + `, + output: ` + function MyComponent(props) { + const local = {}; + useWorker(async () => { + console.log(props.foo); + console.log(props.bar); + }, [props.bar, props.foo]); + } + `, + errors: [ + "React Hook useWorker has missing dependencies: 'props.bar' and 'props.foo'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + // It is not valid for useWorkerLoad to specify extraneous deps + // because it doesn't serve as a side effect trigger unlike useAsyncEffect. + // However, we generally allow specifying *broader* deps as escape hatch. + // So while [props, props.foo] is unnecessary, 'props' wins here as the + // broader one, and this is why 'props.foo' is reported as unnecessary. + code: ` + function MyComponent(props) { + const local = {}; + useWorkerLoad(async () => { + console.log(props.foo); + console.log(props.bar); + }, [props, props.foo]); + } + `, + output: ` + function MyComponent(props) { + const local = {}; + useWorkerLoad(async () => { + console.log(props.foo); + console.log(props.bar); + }, [props]); + } + `, + errors: [ + "React Hook useWorkerLoad has an unnecessary dependency: 'props.foo'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + // Since we don't have 'props' in the list, we'll suggest narrow dependencies. + code: ` + function MyComponent(props) { + const local = {}; + useWorkerLoad(async () => { + console.log(props.foo); + console.log(props.bar); + }, []); + } + `, + output: ` + function MyComponent(props) { + const local = {}; + useWorkerLoad(async () => { + console.log(props.foo); + console.log(props.bar); + }, [props.bar, props.foo]); + } + `, + errors: [ + "React Hook useWorkerLoad has missing dependencies: 'props.bar' and 'props.foo'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + // Effects are allowed to over-specify deps. We'll complain about missing + // 'local', but we won't remove the already-specified 'local.id' from your list. + code: ` + function MyComponent() { + const local = {id: 42}; + useAsyncEffect(async () => { + console.log(local); + }, [local.id]); + } + `, + output: ` + function MyComponent() { + const local = {id: 42}; + useAsyncEffect(async () => { + console.log(local); + }, [local, local.id]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Callbacks are not allowed to over-specify deps. So we'll complain about missing + // 'local' and we will also *remove* 'local.id' from your list. + code: ` + function MyComponent() { + const local = {id: 42}; + const fn = useWorker(async () => { + console.log(local); + }, [local.id]); + } + `, + output: ` + function MyComponent() { + const local = {id: 42}; + const fn = useWorker(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useWorker has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Callbacks are not allowed to over-specify deps. So we'll complain about + // the unnecessary 'local.id'. + code: ` + function MyComponent() { + const local = {id: 42}; + const fn = useWorker(async () => { + console.log(local); + }, [local.id, local]); + } + `, + output: ` + function MyComponent() { + const local = {id: 42}; + const fn = useWorker(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useWorker has an unnecessary dependency: 'local.id'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + const fn = useWorker(async () => { + console.log(props.foo.bar.baz); + }, []); + } + `, + output: ` + function MyComponent(props) { + const fn = useWorker(async () => { + console.log(props.foo.bar.baz); + }, [props.foo.bar.baz]); + } + `, + errors: [ + "React Hook useWorker has a missing dependency: 'props.foo.bar.baz'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + let color = {} + const fn = useWorker(async () => { + console.log(props.foo.bar.baz); + console.log(color); + }, [props.foo, props.foo.bar.baz]); + } + `, + output: ` + function MyComponent(props) { + let color = {} + const fn = useWorker(async () => { + console.log(props.foo.bar.baz); + console.log(color); + }, [color, props.foo.bar.baz]); + } + `, + errors: [ + "React Hook useWorker has a missing dependency: 'color'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Callbacks are not allowed to over-specify deps. So one of these is extra. + // However, it *is* allowed to specify broader deps then strictly necessary. + // So in this case we ask you to remove 'props.foo.bar.baz' because 'props.foo' + // already covers it, and having both is unnecessary. + // TODO: maybe consider suggesting a narrower one by default in these cases. + code: ` + function MyComponent(props) { + const fn = useWorker(async () => { + console.log(props.foo.bar.baz); + }, [props.foo.bar.baz, props.foo]); + } + `, + output: ` + function MyComponent(props) { + const fn = useWorker(async () => { + console.log(props.foo.bar.baz); + }, [props.foo]); + } + `, + errors: [ + "React Hook useWorker has an unnecessary dependency: 'props.foo.bar.baz'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + const fn = useWorker(async () => { + console.log(props.foo.bar.baz); + console.log(props.foo.fizz.bizz); + }, []); + } + `, + output: ` + function MyComponent(props) { + const fn = useWorker(async () => { + console.log(props.foo.bar.baz); + console.log(props.foo.fizz.bizz); + }, [props.foo.bar.baz, props.foo.fizz.bizz]); + } + `, + errors: [ + "React Hook useWorker has missing dependencies: 'props.foo.bar.baz' and 'props.foo.fizz.bizz'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + // Normally we allow specifying deps too broadly. + // So we'd be okay if 'props.foo.bar' was there rather than 'props.foo.bar.baz'. + // However, 'props.foo.bar.baz' is missing. So we know there is a mistake. + // When we're sure there is a mistake, for callbacks we will rebuild the list + // from scratch. This will set the user on a better path by default. + // This is why we end up with just 'props.foo.bar', and not them both. + code: ` + function MyComponent(props) { + const fn = useWorker(async () => { + console.log(props.foo.bar); + }, [props.foo.bar.baz]); + } + `, + output: ` + function MyComponent(props) { + const fn = useWorker(async () => { + console.log(props.foo.bar); + }, [props.foo.bar]); + } + `, + errors: [ + "React Hook useWorker has a missing dependency: 'props.foo.bar'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + const fn = useWorker(async () => { + console.log(props); + console.log(props.hello); + }, [props.foo.bar.baz]); + } + `, + output: ` + function MyComponent(props) { + const fn = useWorker(async () => { + console.log(props); + console.log(props.hello); + }, [props]); + } + `, + errors: [ + "React Hook useWorker has a missing dependency: 'props'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Callbacks are not allowed to over-specify deps. So we'll complain about missing + // 'local' and we will also *remove* 'local.id' from your list. + code: ` + function MyComponent() { + const local = {id: 42}; + const fn = useWorkerLoad(async () => { + console.log(local); + }, [local.id]); + } + `, + output: ` + function MyComponent() { + const local = {id: 42}; + const fn = useWorkerLoad(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useWorkerLoad has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Callbacks are not allowed to over-specify deps. So we'll complain about + // the unnecessary 'local.id'. + code: ` + function MyComponent() { + const local = {id: 42}; + const fn = useWorkerLoad(async () => { + console.log(local); + }, [local.id, local]); + } + `, + output: ` + function MyComponent() { + const local = {id: 42}; + const fn = useWorkerLoad(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useWorkerLoad has an unnecessary dependency: 'local.id'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + const fn = useWorkerLoad(async () => { + console.log(props.foo.bar.baz); + }, []); + } + `, + output: ` + function MyComponent(props) { + const fn = useWorkerLoad(async () => { + console.log(props.foo.bar.baz); + }, [props.foo.bar.baz]); + } + `, + errors: [ + "React Hook useWorkerLoad has a missing dependency: 'props.foo.bar.baz'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + let color = {} + const fn = useWorkerLoad(async () => { + console.log(props.foo.bar.baz); + console.log(color); + }, [props.foo, props.foo.bar.baz]); + } + `, + output: ` + function MyComponent(props) { + let color = {} + const fn = useWorkerLoad(async () => { + console.log(props.foo.bar.baz); + console.log(color); + }, [color, props.foo.bar.baz]); + } + `, + errors: [ + "React Hook useWorkerLoad has a missing dependency: 'color'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Callbacks are not allowed to over-specify deps. So one of these is extra. + // However, it *is* allowed to specify broader deps then strictly necessary. + // So in this case we ask you to remove 'props.foo.bar.baz' because 'props.foo' + // already covers it, and having both is unnecessary. + // TODO: maybe consider suggesting a narrower one by default in these cases. + code: ` + function MyComponent(props) { + const fn = useWorkerLoad(async () => { + console.log(props.foo.bar.baz); + }, [props.foo.bar.baz, props.foo]); + } + `, + output: ` + function MyComponent(props) { + const fn = useWorkerLoad(async () => { + console.log(props.foo.bar.baz); + }, [props.foo]); + } + `, + errors: [ + "React Hook useWorkerLoad has an unnecessary dependency: 'props.foo.bar.baz'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + const fn = useWorkerLoad(async () => { + console.log(props.foo.bar.baz); + console.log(props.foo.fizz.bizz); + }, []); + } + `, + output: ` + function MyComponent(props) { + const fn = useWorkerLoad(async () => { + console.log(props.foo.bar.baz); + console.log(props.foo.fizz.bizz); + }, [props.foo.bar.baz, props.foo.fizz.bizz]); + } + `, + errors: [ + "React Hook useWorkerLoad has missing dependencies: 'props.foo.bar.baz' and 'props.foo.fizz.bizz'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + // Normally we allow specifying deps too broadly. + // So we'd be okay if 'props.foo.bar' was there rather than 'props.foo.bar.baz'. + // However, 'props.foo.bar.baz' is missing. So we know there is a mistake. + // When we're sure there is a mistake, for callbacks we will rebuild the list + // from scratch. This will set the user on a better path by default. + // This is why we end up with just 'props.foo.bar', and not them both. + code: ` + function MyComponent(props) { + const fn = useWorkerLoad(async () => { + console.log(props.foo.bar); + }, [props.foo.bar.baz]); + } + `, + output: ` + function MyComponent(props) { + const fn = useWorkerLoad(async () => { + console.log(props.foo.bar); + }, [props.foo.bar]); + } + `, + errors: [ + "React Hook useWorkerLoad has a missing dependency: 'props.foo.bar'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + const fn = useWorkerLoad(async () => { + console.log(props); + console.log(props.hello); + }, [props.foo.bar.baz]); + } + `, + output: ` + function MyComponent(props) { + const fn = useWorkerLoad(async () => { + console.log(props); + console.log(props.hello); + }, [props]); + } + `, + errors: [ + "React Hook useWorkerLoad has a missing dependency: 'props'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [local, local]); + } + `, + output: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a duplicate dependency: 'local'. " + + 'Either omit it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + const local1 = {}; + useWorker(async () => { + const local1 = {}; + console.log(local1); + }, [local1]); + } + `, + output: ` + function MyComponent() { + const local1 = {}; + useWorker(async () => { + const local1 = {}; + console.log(local1); + }, []); + } + `, + errors: [ + "React Hook useWorker has an unnecessary dependency: 'local1'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + const local1 = {}; + useWorker(async () => {}, [local1]); + } + `, + output: ` + function MyComponent() { + const local1 = {}; + useWorker(async () => {}, []); + } + `, + errors: [ + "React Hook useWorker has an unnecessary dependency: 'local1'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + const local1 = {}; + useWorkerLoad(async () => { + const local1 = {}; + console.log(local1); + }, [local1]); + } + `, + output: ` + function MyComponent() { + const local1 = {}; + useWorkerLoad(async () => { + const local1 = {}; + console.log(local1); + }, []); + } + `, + errors: [ + "React Hook useWorkerLoad has an unnecessary dependency: 'local1'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + const local1 = {}; + useWorkerLoad(async () => {}, [local1]); + } + `, + output: ` + function MyComponent() { + const local1 = {}; + useWorkerLoad(async () => {}, []); + } + `, + errors: [ + "React Hook useWorkerLoad has an unnecessary dependency: 'local1'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo); + }, []); + } + `, + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo); + }, [props.foo]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo); + console.log(props.bar); + }, []); + } + `, + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo); + console.log(props.bar); + }, [props.bar, props.foo]); + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'props.bar' and 'props.foo'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + let a, b, c, d, e, f, g; + useAsyncEffect(async () => { + console.log(b, e, d, c, a, g, f); + }, [c, a, g]); + } + `, + // Don't alphabetize if it wasn't alphabetized in the first place. + output: ` + function MyComponent(props) { + let a, b, c, d, e, f, g; + useAsyncEffect(async () => { + console.log(b, e, d, c, a, g, f); + }, [c, a, g, b, e, d, f]); + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'b', 'd', 'e', and 'f'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + let a, b, c, d, e, f, g; + useAsyncEffect(async () => { + console.log(b, e, d, c, a, g, f); + }, [a, c, g]); + } + `, + // Alphabetize if it was alphabetized. + output: ` + function MyComponent(props) { + let a, b, c, d, e, f, g; + useAsyncEffect(async () => { + console.log(b, e, d, c, a, g, f); + }, [a, b, c, d, e, f, g]); + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'b', 'd', 'e', and 'f'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + let a, b, c, d, e, f, g; + useAsyncEffect(async () => { + console.log(b, e, d, c, a, g, f); + }, []); + } + `, + // Alphabetize if it was empty. + output: ` + function MyComponent(props) { + let a, b, c, d, e, f, g; + useAsyncEffect(async () => { + console.log(b, e, d, c, a, g, f); + }, [a, b, c, d, e, f, g]); + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'a', 'b', 'c', 'd', 'e', 'f', and 'g'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + const local = {}; + useAsyncEffect(async () => { + console.log(props.foo); + console.log(props.bar); + console.log(local); + }, []); + } + `, + output: ` + function MyComponent(props) { + const local = {}; + useAsyncEffect(async () => { + console.log(props.foo); + console.log(props.bar); + console.log(local); + }, [local, props.bar, props.foo]); + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'local', 'props.bar', and 'props.foo'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + const local = {}; + useAsyncEffect(async () => { + console.log(props.foo); + console.log(props.bar); + console.log(local); + }, [props]); + } + `, + output: ` + function MyComponent(props) { + const local = {}; + useAsyncEffect(async () => { + console.log(props.foo); + console.log(props.bar); + console.log(local); + }, [local, props]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo); + }, []); + useWorker(async () => { + console.log(props.foo); + }, []); + useEffectUpdate(() => { + console.log(props.foo); + }, []); + React.useAsyncEffect(async () => { + console.log(props.foo); + }, []); + React.useWorker(async () => { + console.log(props.foo); + }, []); + React.useEffectUpdate(() => { + console.log(props.foo); + }, []); + React.notReactiveHook(() => { + console.log(props.foo); + }, []); + } + `, + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo); + }, [props.foo]); + useWorker(async () => { + console.log(props.foo); + }, [props.foo]); + useEffectUpdate(() => { + console.log(props.foo); + }, [props.foo]); + React.useAsyncEffect(async () => { + console.log(props.foo); + }, [props.foo]); + React.useWorker(async () => { + console.log(props.foo); + }, [props.foo]); + React.useEffectUpdate(() => { + console.log(props.foo); + }, [props.foo]); + React.notReactiveHook(() => { + console.log(props.foo); + }, []); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + "React Hook useWorker has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + "React Hook useEffectUpdate has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + "React Hook React.useAsyncEffect has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + "React Hook React.useWorker has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + "React Hook React.useEffectUpdate has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo); + }, []); + useWorkerLoad(async () => { + console.log(props.foo); + }, []); + useEffectUpdate(() => { + console.log(props.foo); + }, []); + React.useAsyncEffect(async () => { + console.log(props.foo); + }, []); + React.useWorkerLoad(async () => { + console.log(props.foo); + }, []); + React.useEffectUpdate(() => { + console.log(props.foo); + }, []); + React.notReactiveHook(() => { + console.log(props.foo); + }, []); + } + `, + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + console.log(props.foo); + }, [props.foo]); + useWorkerLoad(async () => { + console.log(props.foo); + }, [props.foo]); + useEffectUpdate(() => { + console.log(props.foo); + }, [props.foo]); + React.useAsyncEffect(async () => { + console.log(props.foo); + }, [props.foo]); + React.useWorkerLoad(async () => { + console.log(props.foo); + }, [props.foo]); + React.useEffectUpdate(() => { + console.log(props.foo); + }, [props.foo]); + React.notReactiveHook(() => { + console.log(props.foo); + }, []); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + "React Hook useWorkerLoad has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + "React Hook useEffectUpdate has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + "React Hook React.useAsyncEffect has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + "React Hook React.useWorkerLoad has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + "React Hook React.useEffectUpdate has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [a ? local : b]); + } + `, + // TODO: should we bail out instead? + output: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + 'React Hook useAsyncEffect has a complex expression in the dependency array. ' + + 'Extract it to a separate variable so it can be statically checked.', + ], + }, + { + code: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [a && local]); + } + `, + // TODO: should we bail out instead? + output: ` + function MyComponent() { + const local = {}; + useAsyncEffect(async () => { + console.log(local); + }, [local]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local'. " + + 'Either include it or remove the dependency array.', + 'React Hook useAsyncEffect has a complex expression in the dependency array. ' + + 'Extract it to a separate variable so it can be statically checked.', + ], + }, + { + code: ` + function MyComponent() { + const ref = useRef(); + const [state, setState] = useState(); + useAsyncEffect(async () => { + ref.current = {}; + setState(state + 1); + }, []); + } + `, + output: ` + function MyComponent() { + const ref = useRef(); + const [state, setState] = useState(); + useAsyncEffect(async () => { + ref.current = {}; + setState(state + 1); + }, [state]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'state'. " + + 'Either include it or remove the dependency array. ' + + `You can also do a functional update 'setState(s => ...)' ` + + `if you only need 'state' in the 'setState' call.`, + ], + }, + { + code: ` + function MyComponent() { + const ref = useRef(); + const [state, setState] = useState(); + useAsyncEffect(async () => { + ref.current = {}; + setState(state + 1); + }, [ref]); + } + `, + // We don't ask to remove static deps but don't add them either. + // Don't suggest removing "ref" (it's fine either way) + // but *do* add "state". *Don't* add "setState" ourselves. + output: ` + function MyComponent() { + const ref = useRef(); + const [state, setState] = useState(); + useAsyncEffect(async () => { + ref.current = {}; + setState(state + 1); + }, [ref, state]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'state'. " + + 'Either include it or remove the dependency array. ' + + `You can also do a functional update 'setState(s => ...)' ` + + `if you only need 'state' in the 'setState' call.`, + ], + }, + { + code: ` + function MyComponent(props) { + const ref1 = useRef(); + const ref2 = useRef(); + useAsyncEffect(async () => { + ref1.current.focus(); + console.log(ref2.current.textContent); + alert(props.someOtherRefs.current.innerHTML); + fetch(props.color); + }, []); + } + `, + output: ` + function MyComponent(props) { + const ref1 = useRef(); + const ref2 = useRef(); + useAsyncEffect(async () => { + ref1.current.focus(); + console.log(ref2.current.textContent); + alert(props.someOtherRefs.current.innerHTML); + fetch(props.color); + }, [props.color, props.someOtherRefs]); + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'props.color' and 'props.someOtherRefs'. " + + 'Either include them or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + const ref1 = useRef(); + const ref2 = useRef(); + useAsyncEffect(async () => { + ref1.current.focus(); + console.log(ref2.current.textContent); + alert(props.someOtherRefs.current.innerHTML); + fetch(props.color); + }, [ref1.current, ref2.current, props.someOtherRefs, props.color]); + } + `, + output: ` + function MyComponent(props) { + const ref1 = useRef(); + const ref2 = useRef(); + useAsyncEffect(async () => { + ref1.current.focus(); + console.log(ref2.current.textContent); + alert(props.someOtherRefs.current.innerHTML); + fetch(props.color); + }, [props.someOtherRefs, props.color]); + } + `, + errors: [ + "React Hook useAsyncEffect has unnecessary dependencies: 'ref1.current' and 'ref2.current'. " + + 'Either exclude them or remove the dependency array. ' + + "Mutable values like 'ref1.current' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent() { + const ref = useRef(); + useAsyncEffect(async () => { + console.log(ref.current); + }, [ref.current]); + } + `, + output: ` + function MyComponent() { + const ref = useRef(); + useAsyncEffect(async () => { + console.log(ref.current); + }, []); + } + `, + errors: [ + "React Hook useAsyncEffect has an unnecessary dependency: 'ref.current'. " + + 'Either exclude it or remove the dependency array. ' + + "Mutable values like 'ref.current' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent({ activeTab }) { + const ref1 = useRef(); + const ref2 = useRef(); + useAsyncEffect(async () => { + ref1.current.scrollTop = 0; + ref2.current.scrollTop = 0; + }, [ref1.current, ref2.current, activeTab]); + } + `, + output: ` + function MyComponent({ activeTab }) { + const ref1 = useRef(); + const ref2 = useRef(); + useAsyncEffect(async () => { + ref1.current.scrollTop = 0; + ref2.current.scrollTop = 0; + }, [activeTab]); + } + `, + errors: [ + "React Hook useAsyncEffect has unnecessary dependencies: 'ref1.current' and 'ref2.current'. " + + 'Either exclude them or remove the dependency array. ' + + "Mutable values like 'ref1.current' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent({ activeTab, initY }) { + const ref1 = useRef(); + const ref2 = useRef(); + const fn = useWorker(async () => { + ref1.current.scrollTop = initY; + ref2.current.scrollTop = initY; + }, [ref1.current, ref2.current, activeTab, initY]); + } + `, + output: ` + function MyComponent({ activeTab, initY }) { + const ref1 = useRef(); + const ref2 = useRef(); + const fn = useWorker(async () => { + ref1.current.scrollTop = initY; + ref2.current.scrollTop = initY; + }, [initY]); + } + `, + errors: [ + "React Hook useWorker has unnecessary dependencies: 'activeTab', 'ref1.current', and 'ref2.current'. " + + 'Either exclude them or remove the dependency array. ' + + "Mutable values like 'ref1.current' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent({ activeTab, initY }) { + const ref1 = useRef(); + const ref2 = useRef(); + const fn = useWorkerLoad(async () => { + ref1.current.scrollTop = initY; + ref2.current.scrollTop = initY; + }, [ref1.current, ref2.current, activeTab, initY]); + } + `, + output: ` + function MyComponent({ activeTab, initY }) { + const ref1 = useRef(); + const ref2 = useRef(); + const fn = useWorkerLoad(async () => { + ref1.current.scrollTop = initY; + ref2.current.scrollTop = initY; + }, [initY]); + } + `, + errors: [ + "React Hook useWorkerLoad has unnecessary dependencies: 'activeTab', 'ref1.current', and 'ref2.current'. " + + 'Either exclude them or remove the dependency array. ' + + "Mutable values like 'ref1.current' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + function MyComponent() { + const ref = useRef(); + useAsyncEffect(async () => { + console.log(ref.current); + }, [ref.current, ref]); + } + `, + output: ` + function MyComponent() { + const ref = useRef(); + useAsyncEffect(async () => { + console.log(ref.current); + }, [ref]); + } + `, + errors: [ + "React Hook useAsyncEffect has an unnecessary dependency: 'ref.current'. " + + 'Either exclude it or remove the dependency array. ' + + "Mutable values like 'ref.current' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + const MyComponent = forwardRef((props, ref) => { + useConditionalEffect(ref, () => ({ + focus() { + alert(props.hello); + } + }), []) + }); + `, + output: ` + const MyComponent = forwardRef((props, ref) => { + useConditionalEffect(ref, () => ({ + focus() { + alert(props.hello); + } + }), [props.hello]) + }); + `, + errors: [ + "React Hook useConditionalEffect has a missing dependency: 'props.hello'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + if (props.onChange) { + props.onChange(); + } + }, []); + } + `, + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + if (props.onChange) { + props.onChange(); + } + }, [props]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'props'. " + + 'Either include it or remove the dependency array. ' + + `However, 'props' will change when *any* prop changes, so the ` + + `preferred fix is to destructure the 'props' object outside ` + + `of the useAsyncEffect call and refer to those specific ` + + `props inside useAsyncEffect.`, + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + function play() { + props.onPlay(); + } + function pause() { + props.onPause(); + } + }, []); + } + `, + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + function play() { + props.onPlay(); + } + function pause() { + props.onPause(); + } + }, [props]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'props'. " + + 'Either include it or remove the dependency array. ' + + `However, 'props' will change when *any* prop changes, so the ` + + `preferred fix is to destructure the 'props' object outside ` + + `of the useAsyncEffect call and refer to those specific ` + + `props inside useAsyncEffect.`, + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + if (props.foo.onChange) { + props.foo.onChange(); + } + }, []); + } + `, + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + if (props.foo.onChange) { + props.foo.onChange(); + } + }, [props.foo]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + props.onChange(); + if (props.foo.onChange) { + props.foo.onChange(); + } + }, []); + } + `, + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + props.onChange(); + if (props.foo.onChange) { + props.foo.onChange(); + } + }, [props]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'props'. " + + 'Either include it or remove the dependency array. ' + + `However, 'props' will change when *any* prop changes, so the ` + + `preferred fix is to destructure the 'props' object outside ` + + `of the useAsyncEffect call and refer to those specific ` + + `props inside useAsyncEffect.`, + ], + }, + { + code: ` + function MyComponent(props) { + const [skillsCount] = useState(); + useAsyncEffect(async () => { + if (skillsCount === 0 && !props.isEditMode) { + props.toggleEditMode(); + } + }, [skillsCount, props.isEditMode, props.toggleEditMode]); + } + `, + output: ` + function MyComponent(props) { + const [skillsCount] = useState(); + useAsyncEffect(async () => { + if (skillsCount === 0 && !props.isEditMode) { + props.toggleEditMode(); + } + }, [skillsCount, props.isEditMode, props.toggleEditMode, props]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'props'. " + + 'Either include it or remove the dependency array. ' + + `However, 'props' will change when *any* prop changes, so the ` + + `preferred fix is to destructure the 'props' object outside ` + + `of the useAsyncEffect call and refer to those specific ` + + `props inside useAsyncEffect.`, + ], + }, + { + code: ` + function MyComponent(props) { + const [skillsCount] = useState(); + useAsyncEffect(async () => { + if (skillsCount === 0 && !props.isEditMode) { + props.toggleEditMode(); + } + }, []); + } + `, + output: ` + function MyComponent(props) { + const [skillsCount] = useState(); + useAsyncEffect(async () => { + if (skillsCount === 0 && !props.isEditMode) { + props.toggleEditMode(); + } + }, [props, skillsCount]); + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'props' and 'skillsCount'. " + + 'Either include them or remove the dependency array. ' + + `However, 'props' will change when *any* prop changes, so the ` + + `preferred fix is to destructure the 'props' object outside ` + + `of the useAsyncEffect call and refer to those specific ` + + `props inside useAsyncEffect.`, + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + externalCall(props); + props.onChange(); + }, []); + } + `, + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + externalCall(props); + props.onChange(); + }, [props]); + } + `, + // Don't suggest to destructure props here since you can't. + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'props'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + useAsyncEffect(async () => { + props.onChange(); + externalCall(props); + }, []); + } + `, + output: ` + function MyComponent(props) { + useAsyncEffect(async () => { + props.onChange(); + externalCall(props); + }, [props]); + } + `, + // Don't suggest to destructure props here since you can't. + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'props'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent(props) { + let value; + let value2; + let value3; + let value4; + let asyncValue; + useAsyncEffect(async () => { + if (value4) { + value = {}; + } + value2 = 100; + value = 43; + value4 = true; + console.log(value2); + console.log(value3); + setTimeout(() => { + asyncValue = 100; + }); + }, []); + } + `, + // This is a separate warning unrelated to others. + // We could've made a separate rule for it but it's rare enough to name it. + // No autofix suggestion because the intent isn't clear. + output: ` + function MyComponent(props) { + let value; + let value2; + let value3; + let value4; + let asyncValue; + useAsyncEffect(async () => { + if (value4) { + value = {}; + } + value2 = 100; + value = 43; + value4 = true; + console.log(value2); + console.log(value3); + setTimeout(() => { + asyncValue = 100; + }); + }, []); + } + `, + errors: [ + // value2 + `Assignments to the 'value2' variable from inside React Hook useAsyncEffect ` + + `will be lost after each render. To preserve the value over time, ` + + `store it in a useRef or useLazyRef Hook and keep the mutable value in the '.current' property. ` + + `Otherwise, you can move this variable directly inside useAsyncEffect.`, // value + `Assignments to the 'value' variable from inside React Hook useAsyncEffect ` + + `will be lost after each render. To preserve the value over time, ` + + `store it in a useRef or useLazyRef Hook and keep the mutable value in the '.current' property. ` + + `Otherwise, you can move this variable directly inside useAsyncEffect.`, // value4 + `Assignments to the 'value4' variable from inside React Hook useAsyncEffect ` + + `will be lost after each render. To preserve the value over time, ` + + `store it in a useRef or useLazyRef Hook and keep the mutable value in the '.current' property. ` + + `Otherwise, you can move this variable directly inside useAsyncEffect.`, // asyncValue + `Assignments to the 'asyncValue' variable from inside React Hook useAsyncEffect ` + + `will be lost after each render. To preserve the value over time, ` + + `store it in a useRef or useLazyRef Hook and keep the mutable value in the '.current' property. ` + + `Otherwise, you can move this variable directly inside useAsyncEffect.`, + ], + }, + { + code: ` + function MyComponent(props) { + let value; + let value2; + let value3; + let asyncValue; + useAsyncEffect(async () => { + value = {}; + value2 = 100; + value = 43; + console.log(value2); + console.log(value3); + setTimeout(() => { + asyncValue = 100; + }); + }, [value, value2, value3]); + } + `, + // This is a separate warning unrelated to others. + // We could've made a separate rule for it but it's rare enough to name it. + // No autofix suggestion because the intent isn't clear. + output: ` + function MyComponent(props) { + let value; + let value2; + let value3; + let asyncValue; + useAsyncEffect(async () => { + value = {}; + value2 = 100; + value = 43; + console.log(value2); + console.log(value3); + setTimeout(() => { + asyncValue = 100; + }); + }, [value, value2, value3]); + } + `, + errors: [ + // value + `Assignments to the 'value' variable from inside React Hook useAsyncEffect ` + + `will be lost after each render. To preserve the value over time, ` + + `store it in a useRef or useLazyRef Hook and keep the mutable value in the '.current' property. ` + + `Otherwise, you can move this variable directly inside useAsyncEffect.`, // value2 + `Assignments to the 'value2' variable from inside React Hook useAsyncEffect ` + + `will be lost after each render. To preserve the value over time, ` + + `store it in a useRef or useLazyRef Hook and keep the mutable value in the '.current' property. ` + + `Otherwise, you can move this variable directly inside useAsyncEffect.`, // asyncValue + `Assignments to the 'asyncValue' variable from inside React Hook useAsyncEffect ` + + `will be lost after each render. To preserve the value over time, ` + + `store it in a useRef or useLazyRef Hook and keep the mutable value in the '.current' property. ` + + `Otherwise, you can move this variable directly inside useAsyncEffect.`, + ], + }, + { + code: ` + function MyComponent() { + const myRef = useRef(); + useAsyncEffect(async () => { + const handleMove = () => {}; + myRef.current.addEventListener('mousemove', handleMove); + return () => myRef.current.removeEventListener('mousemove', handleMove); + }, []); + return
; + } + `, + output: ` + function MyComponent() { + const myRef = useRef(); + useAsyncEffect(async () => { + const handleMove = () => {}; + myRef.current.addEventListener('mousemove', handleMove); + return () => myRef.current.removeEventListener('mousemove', handleMove); + }, []); + return
; + } + `, + errors: [ + `The ref value 'myRef.current' will likely have changed by the time ` + + `this effect cleanup function runs. If this ref points to a node ` + + `rendered by React, copy 'myRef.current' to a variable inside the effect, ` + + `and use that variable in the cleanup function.`, + ], + }, + { + code: ` + function MyComponent() { + const myRef = useRef(); + useAsyncEffect(async () => { + const handleMove = () => {}; + myRef.current.addEventListener('mousemove', handleMove); + return () => myRef.current.removeEventListener('mousemove', handleMove); + }); + return
; + } + `, + output: ` + function MyComponent() { + const myRef = useRef(); + useAsyncEffect(async () => { + const handleMove = () => {}; + myRef.current.addEventListener('mousemove', handleMove); + return () => myRef.current.removeEventListener('mousemove', handleMove); + }); + return
; + } + `, + errors: [ + `The ref value 'myRef.current' will likely have changed by the time ` + + `this effect cleanup function runs. If this ref points to a node ` + + `rendered by React, copy 'myRef.current' to a variable inside the effect, ` + + `and use that variable in the cleanup function.`, + ], + }, + { + code: ` + function useMyThing(myRef) { + useAsyncEffect(async () => { + const handleMove = () => {}; + myRef.current.addEventListener('mousemove', handleMove); + return () => myRef.current.removeEventListener('mousemove', handleMove); + }, [myRef]); + } + `, + output: ` + function useMyThing(myRef) { + useAsyncEffect(async () => { + const handleMove = () => {}; + myRef.current.addEventListener('mousemove', handleMove); + return () => myRef.current.removeEventListener('mousemove', handleMove); + }, [myRef]); + } + `, + errors: [ + `The ref value 'myRef.current' will likely have changed by the time ` + + `this effect cleanup function runs. If this ref points to a node ` + + `rendered by React, copy 'myRef.current' to a variable inside the effect, ` + + `and use that variable in the cleanup function.`, + ], + }, + { + code: ` + function useMyThing(myRef) { + useAsyncEffect(async () => { + const handleMouse = () => {}; + myRef.current.addEventListener('mousemove', handleMouse); + myRef.current.addEventListener('mousein', handleMouse); + return function() { + setTimeout(() => { + myRef.current.removeEventListener('mousemove', handleMouse); + myRef.current.removeEventListener('mousein', handleMouse); + }); + } + }, [myRef]); + } + `, + output: ` + function useMyThing(myRef) { + useAsyncEffect(async () => { + const handleMouse = () => {}; + myRef.current.addEventListener('mousemove', handleMouse); + myRef.current.addEventListener('mousein', handleMouse); + return function() { + setTimeout(() => { + myRef.current.removeEventListener('mousemove', handleMouse); + myRef.current.removeEventListener('mousein', handleMouse); + }); + } + }, [myRef]); + } + `, + errors: [ + `The ref value 'myRef.current' will likely have changed by the time ` + + `this effect cleanup function runs. If this ref points to a node ` + + `rendered by React, copy 'myRef.current' to a variable inside the effect, ` + + `and use that variable in the cleanup function.`, + ], + }, + { + code: ` + function useMyThing(myRef, active) { + useAsyncEffect(async () => { + const handleMove = () => {}; + if (active) { + myRef.current.addEventListener('mousemove', handleMove); + return function() { + setTimeout(() => { + myRef.current.removeEventListener('mousemove', handleMove); + }); + } + } + }, [myRef, active]); + } + `, + output: ` + function useMyThing(myRef, active) { + useAsyncEffect(async () => { + const handleMove = () => {}; + if (active) { + myRef.current.addEventListener('mousemove', handleMove); + return function() { + setTimeout(() => { + myRef.current.removeEventListener('mousemove', handleMove); + }); + } + } + }, [myRef, active]); + } + `, + errors: [ + `The ref value 'myRef.current' will likely have changed by the time ` + + `this effect cleanup function runs. If this ref points to a node ` + + `rendered by React, copy 'myRef.current' to a variable inside the effect, ` + + `and use that variable in the cleanup function.`, + ], + }, + { + // Autofix ignores constant primitives (leaving the ones that are there). + code: ` + function MyComponent() { + const local1 = 42; + const local2 = '42'; + const local3 = null; + const local4 = {}; + useAsyncEffect(async () => { + console.log(local1); + console.log(local2); + console.log(local3); + console.log(local4); + }, [local1, local3]); + } + `, + output: ` + function MyComponent() { + const local1 = 42; + const local2 = '42'; + const local3 = null; + const local4 = {}; + useAsyncEffect(async () => { + console.log(local1); + console.log(local2); + console.log(local3); + console.log(local4); + }, [local1, local3, local4]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'local4'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function MyComponent() { + useAsyncEffect(async () => { + window.scrollTo(0, 0); + }, [window]); + } + `, + errors: [ + "React Hook useAsyncEffect has an unnecessary dependency: 'window'. " + + 'Either exclude it or remove the dependency array. ' + + "Outer scope values like 'window' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + import MutableStore from 'store'; + + function MyComponent() { + useAsyncEffect(async () => { + console.log(MutableStore.hello); + }, [MutableStore.hello]); + } + `, + output: ` + import MutableStore from 'store'; + + function MyComponent() { + useAsyncEffect(async () => { + console.log(MutableStore.hello); + }, []); + } + `, + errors: [ + "React Hook useAsyncEffect has an unnecessary dependency: 'MutableStore.hello'. " + + 'Either exclude it or remove the dependency array. ' + + "Outer scope values like 'MutableStore.hello' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + import MutableStore from 'store'; + let z = {}; + + function MyComponent(props) { + let x = props.foo; + { + let y = props.bar; + useAsyncEffect(async () => { + console.log(MutableStore.hello.world, props.foo, x, y, z, global.stuff); + }, [MutableStore.hello.world, props.foo, x, y, z, global.stuff]); + } + } + `, + output: ` + import MutableStore from 'store'; + let z = {}; + + function MyComponent(props) { + let x = props.foo; + { + let y = props.bar; + useAsyncEffect(async () => { + console.log(MutableStore.hello.world, props.foo, x, y, z, global.stuff); + }, [props.foo, x, y]); + } + } + `, + errors: [ + 'React Hook useAsyncEffect has unnecessary dependencies: ' + + "'MutableStore.hello.world', 'global.stuff', and 'z'. " + + 'Either exclude them or remove the dependency array. ' + + "Outer scope values like 'MutableStore.hello.world' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + import MutableStore from 'store'; + let z = {}; + + function MyComponent(props) { + let x = props.foo; + { + let y = props.bar; + useAsyncEffect(async () => { + // nothing + }, [MutableStore.hello.world, props.foo, x, y, z, global.stuff]); + } + } + `, + // The output should contain the ones that are inside a component + // since there are legit reasons to over-specify them for effects. + output: ` + import MutableStore from 'store'; + let z = {}; + + function MyComponent(props) { + let x = props.foo; + { + let y = props.bar; + useAsyncEffect(async () => { + // nothing + }, [props.foo, x, y]); + } + } + `, + errors: [ + 'React Hook useAsyncEffect has unnecessary dependencies: ' + + "'MutableStore.hello.world', 'global.stuff', and 'z'. " + + 'Either exclude them or remove the dependency array. ' + + "Outer scope values like 'MutableStore.hello.world' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + import MutableStore from 'store'; + let z = {}; + + function MyComponent(props) { + let x = props.foo; + { + let y = props.bar; + const fn = useWorker(async () => { + // nothing + }, [MutableStore.hello.world, props.foo, x, y, z, global.stuff]); + } + } + `, + output: ` + import MutableStore from 'store'; + let z = {}; + + function MyComponent(props) { + let x = props.foo; + { + let y = props.bar; + const fn = useWorker(async () => { + // nothing + }, []); + } + } + `, + errors: [ + 'React Hook useWorker has unnecessary dependencies: ' + + "'MutableStore.hello.world', 'global.stuff', 'props.foo', 'x', 'y', and 'z'. " + + 'Either exclude them or remove the dependency array. ' + + "Outer scope values like 'MutableStore.hello.world' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + code: ` + import MutableStore from 'store'; + let z = {}; + + function MyComponent(props) { + let x = props.foo; + { + let y = props.bar; + const fn = useWorkerLoad(async () => { + // nothing + }, [MutableStore.hello.world, props.foo, x, y, z, global.stuff]); + } + } + `, + output: ` + import MutableStore from 'store'; + let z = {}; + + function MyComponent(props) { + let x = props.foo; + { + let y = props.bar; + const fn = useWorkerLoad(async () => { + // nothing + }, []); + } + } + `, + errors: [ + 'React Hook useWorkerLoad has unnecessary dependencies: ' + + "'MutableStore.hello.world', 'global.stuff', 'props.foo', 'x', 'y', and 'z'. " + + 'Either exclude them or remove the dependency array. ' + + "Outer scope values like 'MutableStore.hello.world' aren't valid dependencies " + + "because mutating them doesn't re-render the component.", + ], + }, + { + // Every almost-static function is tainted by a dynamic value. + code: ` + function MyComponent(props) { + let [, setState] = useState(); + let [, dispatch] = React.useReducer(); + let taint = props.foo; + + function handleNext1(value) { + let value2 = value * taint; + setState(value2); + console.log('hello'); + } + const handleNext2 = (value) => { + setState(taint(value)); + console.log('hello'); + }; + let handleNext3 = function(value) { + setTimeout(() => console.log(taint)); + dispatch({ type: 'x', value }); + }; + useAsyncEffect(async () => { + return Store.subscribe(handleNext1); + }, []); + useAsyncLayoutEffect(async () => { + return Store.subscribe(handleNext2); + }, []); + useEffectUpdate(() => { + return Store.subscribe(handleNext3); + }, []); + } + `, + output: ` + function MyComponent(props) { + let [, setState] = useState(); + let [, dispatch] = React.useReducer(); + let taint = props.foo; + + function handleNext1(value) { + let value2 = value * taint; + setState(value2); + console.log('hello'); + } + const handleNext2 = (value) => { + setState(taint(value)); + console.log('hello'); + }; + let handleNext3 = function(value) { + setTimeout(() => console.log(taint)); + dispatch({ type: 'x', value }); + }; + useAsyncEffect(async () => { + return Store.subscribe(handleNext1); + }, [handleNext1]); + useAsyncLayoutEffect(async () => { + return Store.subscribe(handleNext2); + }, [handleNext2]); + useEffectUpdate(() => { + return Store.subscribe(handleNext3); + }, [handleNext3]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'handleNext1'. " + + 'Either include it or remove the dependency array.', + "React Hook useAsyncLayoutEffect has a missing dependency: 'handleNext2'. " + + 'Either include it or remove the dependency array.', + "React Hook useEffectUpdate has a missing dependency: 'handleNext3'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Regression test + code: ` + function MyComponent(props) { + let [, setState] = useState(); + let [, dispatch] = React.useReducer(); + let taint = props.foo; + + // Shouldn't affect anything + function handleChange() {} + + function handleNext1(value) { + let value2 = value * taint; + setState(value2); + console.log('hello'); + } + const handleNext2 = (value) => { + setState(taint(value)); + console.log('hello'); + }; + let handleNext3 = function(value) { + console.log(taint); + dispatch({ type: 'x', value }); + }; + useAsyncEffect(async () => { + return Store.subscribe(handleNext1); + }, []); + useAsyncLayoutEffect(async () => { + return Store.subscribe(handleNext2); + }, []); + useEffectUpdate(() => { + return Store.subscribe(handleNext3); + }, []); + } + `, + output: ` + function MyComponent(props) { + let [, setState] = useState(); + let [, dispatch] = React.useReducer(); + let taint = props.foo; + + // Shouldn't affect anything + function handleChange() {} + + function handleNext1(value) { + let value2 = value * taint; + setState(value2); + console.log('hello'); + } + const handleNext2 = (value) => { + setState(taint(value)); + console.log('hello'); + }; + let handleNext3 = function(value) { + console.log(taint); + dispatch({ type: 'x', value }); + }; + useAsyncEffect(async () => { + return Store.subscribe(handleNext1); + }, [handleNext1]); + useAsyncLayoutEffect(async () => { + return Store.subscribe(handleNext2); + }, [handleNext2]); + useEffectUpdate(() => { + return Store.subscribe(handleNext3); + }, [handleNext3]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'handleNext1'. " + + 'Either include it or remove the dependency array.', + "React Hook useAsyncLayoutEffect has a missing dependency: 'handleNext2'. " + + 'Either include it or remove the dependency array.', + "React Hook useEffectUpdate has a missing dependency: 'handleNext3'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Regression test + code: ` + function MyComponent(props) { + let [, setState] = useState(); + let [, dispatch] = React.useReducer(); + let taint = props.foo; + + // Shouldn't affect anything + const handleChange = () => {}; + + function handleNext1(value) { + let value2 = value * taint; + setState(value2); + console.log('hello'); + } + const handleNext2 = (value) => { + setState(taint(value)); + console.log('hello'); + }; + let handleNext3 = function(value) { + console.log(taint); + dispatch({ type: 'x', value }); + }; + useAsyncEffect(async () => { + return Store.subscribe(handleNext1); + }, []); + useAsyncLayoutEffect(async () => { + return Store.subscribe(handleNext2); + }, []); + useEffectUpdate(() => { + return Store.subscribe(handleNext3); + }, []); + } + `, + output: ` + function MyComponent(props) { + let [, setState] = useState(); + let [, dispatch] = React.useReducer(); + let taint = props.foo; + + // Shouldn't affect anything + const handleChange = () => {}; + + function handleNext1(value) { + let value2 = value * taint; + setState(value2); + console.log('hello'); + } + const handleNext2 = (value) => { + setState(taint(value)); + console.log('hello'); + }; + let handleNext3 = function(value) { + console.log(taint); + dispatch({ type: 'x', value }); + }; + useAsyncEffect(async () => { + return Store.subscribe(handleNext1); + }, [handleNext1]); + useAsyncLayoutEffect(async () => { + return Store.subscribe(handleNext2); + }, [handleNext2]); + useEffectUpdate(() => { + return Store.subscribe(handleNext3); + }, [handleNext3]); + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'handleNext1'. " + + 'Either include it or remove the dependency array.', + "React Hook useAsyncLayoutEffect has a missing dependency: 'handleNext2'. " + + 'Either include it or remove the dependency array.', + "React Hook useEffectUpdate has a missing dependency: 'handleNext3'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function Counter() { + let [count, setCount] = useState(0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count + 1); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + output: ` + function Counter() { + let [count, setCount] = useState(0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count + 1); + }, 1000); + return () => clearInterval(id); + }, [count]); + + return

{count}

; + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'count'. " + + 'Either include it or remove the dependency array. ' + + `You can also do a functional update 'setCount(c => ...)' if you ` + + `only need 'count' in the 'setCount' call.`, + ], + }, + { + code: ` + function Counter() { + let [count, setCount] = useState(0); + let [increment, setIncrement] = useState(0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count + increment); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + output: ` + function Counter() { + let [count, setCount] = useState(0); + let [increment, setIncrement] = useState(0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count + increment); + }, 1000); + return () => clearInterval(id); + }, [count, increment]); + + return

{count}

; + } + `, + errors: [ + "React Hook useAsyncEffect has missing dependencies: 'count' and 'increment'. " + + 'Either include them or remove the dependency array. ' + + `You can also do a functional update 'setCount(c => ...)' if you ` + + `only need 'count' in the 'setCount' call.`, + ], + }, + { + code: ` + function Counter() { + let [count, setCount] = useState(0); + let [increment, setIncrement] = useState(0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count => count + increment); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + output: ` + function Counter() { + let [count, setCount] = useState(0); + let [increment, setIncrement] = useState(0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count => count + increment); + }, 1000); + return () => clearInterval(id); + }, [increment]); + + return

{count}

; + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'increment'. " + + 'Either include it or remove the dependency array. ' + + `You can also replace multiple useState variables with useReducer ` + + `if 'setCount' needs the current value of 'increment'.`, + ], + }, + { + code: ` + function Counter() { + let [count, setCount] = useState(0); + let increment = useCustomHook(); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count => count + increment); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + output: ` + function Counter() { + let [count, setCount] = useState(0); + let increment = useCustomHook(); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count => count + increment); + }, 1000); + return () => clearInterval(id); + }, [increment]); + + return

{count}

; + } + `, + // This intentionally doesn't show the reducer message + // because we don't know if it's safe for it to close over a value. + // We only show it for state variables (and possibly props). + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'increment'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function Counter({ step }) { + let [count, setCount] = useState(0); + + function increment(x) { + return x + step; + } + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count => increment(count)); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + output: ` + function Counter({ step }) { + let [count, setCount] = useState(0); + + function increment(x) { + return x + step; + } + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count => increment(count)); + }, 1000); + return () => clearInterval(id); + }, [increment]); + + return

{count}

; + } + `, + // This intentionally doesn't show the reducer message + // because we don't know if it's safe for it to close over a value. + // We only show it for state variables (and possibly props). + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'increment'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function Counter({ increment }) { + let [count, setCount] = useState(0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count => count + increment); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + output: ` + function Counter({ increment }) { + let [count, setCount] = useState(0); + + useAsyncEffect(async () => { + let id = setInterval(() => { + setCount(count => count + increment); + }, 1000); + return () => clearInterval(id); + }, [increment]); + + return

{count}

; + } + `, + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'increment'. " + + 'Either include it or remove the dependency array. ' + + `If 'setCount' needs the current value of 'increment', ` + + `you can also switch to useReducer instead of useState and read 'increment' in the reducer.`, + ], + }, + { + code: ` + function Counter() { + const [count, setCount] = useState(0); + + function tick() { + setCount(count + 1); + } + + useAsyncEffect(async () => { + let id = setInterval(() => { + tick(); + }, 1000); + return () => clearInterval(id); + }, []); + + return

{count}

; + } + `, + output: ` + function Counter() { + const [count, setCount] = useState(0); + + function tick() { + setCount(count + 1); + } + + useAsyncEffect(async () => { + let id = setInterval(() => { + tick(); + }, 1000); + return () => clearInterval(id); + }, [tick]); + + return

{count}

; + } + `, + // TODO: ideally this should suggest useState updater form + // since this code doesn't actually work. The autofix could + // at least avoid suggesting 'tick' since it's obviously + // always different, and thus useless. + errors: [ + "React Hook useAsyncEffect has a missing dependency: 'tick'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + // Regression test for a crash + code: ` + function Podcasts() { + useAsyncEffect(async () => { + alert(podcasts); + }, []); + let [podcasts, setPodcasts] = useState(null); + } + `, + // Note: this autofix is shady because + // the variable is used before declaration. + // TODO: Maybe we can catch those fixes and not autofix. + output: ` + function Podcasts() { + useAsyncEffect(async () => { + alert(podcasts); + }, [podcasts]); + let [podcasts, setPodcasts] = useState(null); + } + `, + errors: [ + `React Hook useAsyncEffect has a missing dependency: 'podcasts'. ` + + `Either include it or remove the dependency array.`, + ], + }, + { + code: ` + function Podcasts({ fetchPodcasts, id }) { + let [podcasts, setPodcasts] = useState(null); + useAsyncEffect(async () => { + fetchPodcasts(id).then(setPodcasts); + }, [id]); + } + `, + output: ` + function Podcasts({ fetchPodcasts, id }) { + let [podcasts, setPodcasts] = useState(null); + useAsyncEffect(async () => { + fetchPodcasts(id).then(setPodcasts); + }, [fetchPodcasts, id]); + } + `, + errors: [ + `React Hook useAsyncEffect has a missing dependency: 'fetchPodcasts'. ` + + `Either include it or remove the dependency array. ` + + `If 'fetchPodcasts' changes too often, ` + + `find the parent component that defines it and wrap that definition in useWorker.`, + ], + }, + { + code: ` + function Podcasts({ api: { fetchPodcasts }, id }) { + let [podcasts, setPodcasts] = useState(null); + useAsyncEffect(async () => { + fetchPodcasts(id).then(setPodcasts); + }, [id]); + } + `, + output: ` + function Podcasts({ api: { fetchPodcasts }, id }) { + let [podcasts, setPodcasts] = useState(null); + useAsyncEffect(async () => { + fetchPodcasts(id).then(setPodcasts); + }, [fetchPodcasts, id]); + } + `, + errors: [ + `React Hook useAsyncEffect has a missing dependency: 'fetchPodcasts'. ` + + `Either include it or remove the dependency array. ` + + `If 'fetchPodcasts' changes too often, ` + + `find the parent component that defines it and wrap that definition in useWorker.`, + ], + }, + { + code: ` + function Podcasts({ fetchPodcasts, fetchPodcasts2, id }) { + let [podcasts, setPodcasts] = useState(null); + useAsyncEffect(async () => { + setTimeout(() => { + console.log(id); + fetchPodcasts(id).then(setPodcasts); + fetchPodcasts2(id).then(setPodcasts); + }); + }, [id]); + } + `, + output: ` + function Podcasts({ fetchPodcasts, fetchPodcasts2, id }) { + let [podcasts, setPodcasts] = useState(null); + useAsyncEffect(async () => { + setTimeout(() => { + console.log(id); + fetchPodcasts(id).then(setPodcasts); + fetchPodcasts2(id).then(setPodcasts); + }); + }, [fetchPodcasts, fetchPodcasts2, id]); + } + `, + errors: [ + `React Hook useAsyncEffect has missing dependencies: 'fetchPodcasts' and 'fetchPodcasts2'. ` + + `Either include them or remove the dependency array. ` + + `If 'fetchPodcasts' changes too often, ` + + `find the parent component that defines it and wrap that definition in useWorker.`, + ], + }, + { + code: ` + function Podcasts({ fetchPodcasts, id }) { + let [podcasts, setPodcasts] = useState(null); + useAsyncEffect(async () => { + console.log(fetchPodcasts); + fetchPodcasts(id).then(setPodcasts); + }, [id]); + } + `, + output: ` + function Podcasts({ fetchPodcasts, id }) { + let [podcasts, setPodcasts] = useState(null); + useAsyncEffect(async () => { + console.log(fetchPodcasts); + fetchPodcasts(id).then(setPodcasts); + }, [fetchPodcasts, id]); + } + `, + errors: [ + `React Hook useAsyncEffect has a missing dependency: 'fetchPodcasts'. ` + + `Either include it or remove the dependency array. ` + + `If 'fetchPodcasts' changes too often, ` + + `find the parent component that defines it and wrap that definition in useWorker.`, + ], + }, + { + // The mistake here is that it was moved inside the effect + // so it can't be referenced in the deps array. + code: ` + function Thing() { + useAsyncEffect(async () => { + const fetchData = async () => {}; + fetchData(); + }, [fetchData]); + } + `, + output: ` + function Thing() { + useAsyncEffect(async () => { + const fetchData = async () => {}; + fetchData(); + }, []); + } + `, + errors: [ + `React Hook useAsyncEffect has an unnecessary dependency: 'fetchData'. ` + + `Either exclude it or remove the dependency array.`, + ], + }, + { + code: ` + function Hello() { + const [state, setState] = useState(0); + useAsyncEffect(async () => { + setState({}); + }); + } + `, + output: ` + function Hello() { + const [state, setState] = useState(0); + useAsyncEffect(async () => { + setState({}); + }, []); + } + `, + errors: [ + `React Hook useAsyncEffect contains a call to 'setState'. ` + + `Without a list of dependencies, this can lead to an infinite chain of updates. ` + + `To fix this, pass [] as a second argument to the useAsyncEffect Hook.`, + ], + }, + { + code: ` + function Hello() { + const [data, setData] = useState(0); + useAsyncEffect(async () => { + fetchData.then(setData); + }); + } + `, + output: ` + function Hello() { + const [data, setData] = useState(0); + useAsyncEffect(async () => { + fetchData.then(setData); + }, []); + } + `, + errors: [ + `React Hook useAsyncEffect contains a call to 'setData'. ` + + `Without a list of dependencies, this can lead to an infinite chain of updates. ` + + `To fix this, pass [] as a second argument to the useAsyncEffect Hook.`, + ], + }, + { + code: ` + function Hello({ country }) { + const [data, setData] = useState(0); + useAsyncEffect(async () => { + fetchData(country).then(setData); + }); + } + `, + output: ` + function Hello({ country }) { + const [data, setData] = useState(0); + useAsyncEffect(async () => { + fetchData(country).then(setData); + }, [country]); + } + `, + errors: [ + `React Hook useAsyncEffect contains a call to 'setData'. ` + + `Without a list of dependencies, this can lead to an infinite chain of updates. ` + + `To fix this, pass [country] as a second argument to the useAsyncEffect Hook.`, + ], + }, + { + code: ` + function Hello({ prop1, prop2 }) { + const [state, setState] = useState(0); + useAsyncEffect(async () => { + if (prop1) { + setState(prop2); + } + }); + } + `, + output: ` + function Hello({ prop1, prop2 }) { + const [state, setState] = useState(0); + useAsyncEffect(async () => { + if (prop1) { + setState(prop2); + } + }, [prop1, prop2]); + } + `, + errors: [ + `React Hook useAsyncEffect contains a call to 'setState'. ` + + `Without a list of dependencies, this can lead to an infinite chain of updates. ` + + `To fix this, pass [prop1, prop2] as a second argument to the useAsyncEffect Hook.`, + ], + }, + { + code: ` + function Example() { + const foo = useWorker(async () => { + foo(); + }, [foo]); + } + `, + output: ` + function Example() { + const foo = useWorker(async () => { + foo(); + }, []); + } + `, + errors: [ + "React Hook useWorker has an unnecessary dependency: 'foo'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function Example({ prop }) { + const foo = useWorker(async () => { + prop.hello(foo); + }, [foo]); + const bar = useWorker(async () => { + foo(); + }, [foo]); + } + `, + output: ` + function Example({ prop }) { + const foo = useWorker(async () => { + prop.hello(foo); + }, [prop]); + const bar = useWorker(async () => { + foo(); + }, [foo]); + } + `, + errors: [ + "React Hook useWorker has a missing dependency: 'prop'. " + + 'Either include it or remove the dependency array.', + ], + }, + { + code: ` + function Example() { + const foo = useWorkerLoad(async () => { + foo(); + }, [foo]); + } + `, + output: ` + function Example() { + const foo = useWorkerLoad(async () => { + foo(); + }, []); + } + `, + errors: [ + "React Hook useWorkerLoad has an unnecessary dependency: 'foo'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function Example({ prop }) { + const foo = useWorkerLoad(async () => { + prop.hello(foo); + }, [foo]); + const bar = useWorkerLoad(async () => { + foo(); + }, [foo]); + } + `, + output: ` + function Example({ prop }) { + const foo = useWorkerLoad(async () => { + prop.hello(foo); + }, [prop]); + const bar = useWorkerLoad(async () => { + foo(); + }, [foo]); + } + `, + errors: [ + "React Hook useWorkerLoad has a missing dependency: 'prop'. " + + 'Either include it or remove the dependency array.', + ], + }, + ], +}; + +// For easier local testing +if (!process.env.CI) { + let only = []; + let skipped = []; + [...tests.valid, ...tests.invalid].forEach(t => { + if (t.skip) { + delete t.skip; + skipped.push(t); + } + if (t.only) { + delete t.only; + only.push(t); + } + // if (!t.options) { + // t.options = [{ additionalHooks: 'useAsyncLayoutEffect' }]; + // } + }); + const predicate = t => { + if (only.length > 0) { + return only.indexOf(t) !== -1; + } + if (skipped.length > 0) { + return skipped.indexOf(t) === -1; + } + return true; + }; + tests.valid = tests.valid.filter(predicate); + tests.invalid = tests.invalid.filter(predicate); +} + +const eslintTester = new ESLintTester(); +eslintTester.run( + '@react-hook-utilities/eslint-plugin', + ReactHooksESLintRule, + tests, +); diff --git a/eslint-plugin/src/index.js b/eslint-plugin/src/index.js new file mode 100644 index 0000000..3bbc31c --- /dev/null +++ b/eslint-plugin/src/index.js @@ -0,0 +1,11 @@ +/** + * @fileoverview ESLint rules for hook react-hook-utilities + * @author Flávio Caetano + */ +'use strict'; + +import ExhaustiveDeps from './rules/ExaustiveDeps'; + +export const rules = { + 'exhaustive-deps': ExhaustiveDeps, +}; diff --git a/eslint-plugin/src/rules/ExaustiveDeps.js b/eslint-plugin/src/rules/ExaustiveDeps.js new file mode 100644 index 0000000..01fcde9 --- /dev/null +++ b/eslint-plugin/src/rules/ExaustiveDeps.js @@ -0,0 +1,1257 @@ +/** + * 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. + * + * Original source: https://github.com/facebook/react/blob/9e64bf18e11828d6b4c0363bff5ed2eca1ccd838/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js + */ + +/* eslint-disable no-for-of-loops/no-for-of-loops */ + +'use strict'; + +export default { + meta: { + fixable: 'code', + schema: [ + { + type: 'object', + additionalProperties: false, + }, + ], + }, + create(context) { + // Should be shared between visitors. + let setStateCallSites = new WeakMap(); + let stateVariables = new WeakSet(); + let staticKnownValueCache = new WeakMap(); + let functionWithoutCapturedValueCache = new WeakMap(); + function memoizeWithWeakMap(fn, map) { + return function(arg) { + if (map.has(arg)) { + // to verify cache hits: + // console.log(arg.name) + return map.get(arg); + } + const result = fn(arg); + map.set(arg, result); + return result; + }; + } + + return { + FunctionExpression: visitFunctionExpression, + ArrowFunctionExpression: visitFunctionExpression, + }; + + /** + * Visitor for both function expressions and arrow function expressions. + */ + function visitFunctionExpression(node) { + // We only want to lint nodes which are reactive hook callbacks. + if ( + (node.type !== 'FunctionExpression' && + node.type !== 'ArrowFunctionExpression') || + node.parent.type !== 'CallExpression' + ) { + return; + } + + const callbackIndex = getReactiveHookCallbackIndex(node.parent.callee); + if (node.parent.arguments[callbackIndex] !== node) { + return; + } + + // Get the reactive hook node. + const reactiveHook = node.parent.callee; + const reactiveHookName = getNodeWithoutReactNamespace(reactiveHook).name; + const isEffect = reactiveHookName.endsWith('Effect'); + + // Get the declared dependencies for this reactive hook. If there is no + // second argument then the reactive callback will re-run on every render. + // So no need to check for dependency inclusion. + const depsIndex = callbackIndex + 1; + const declaredDependenciesNode = node.parent.arguments[depsIndex]; + + // Get the current scope. + const scope = context.getScope(); + + // Find all our "pure scopes". On every re-render of a component these + // pure scopes may have changes to the variables declared within. So all + // variables used in our reactive hook callback but declared in a pure + // scope need to be listed as dependencies of our reactive hook callback. + // + // According to the rules of React you can't read a mutable value in pure + // scope. We can't enforce this in a lint so we trust that all variables + // declared outside of pure scope are indeed frozen. + const pureScopes = new Set(); + let componentScope = null; + { + let currentScope = scope.upper; + while (currentScope) { + pureScopes.add(currentScope); + if (currentScope.type === 'function') { + break; + } + currentScope = currentScope.upper; + } + // If there is no parent function scope then there are no pure scopes. + // The ones we've collected so far are incorrect. So don't continue with + // the lint. + if (!currentScope) { + return; + } + componentScope = currentScope; + } + + // Next we'll define a few helpers that helps us + // tell if some values don't have to be declared as deps. + + // Some are known to be static based on Hook calls. + // const [state, setState] = useState() / React.useState() + // ^^^ true for this reference + // const [state, dispatch] = useReducer() / React.useReducer() + // ^^^ true for this reference + // const ref = useRef() + // ^^^ true for this reference + // False for everything else. + function isStaticKnownHookValue(resolved) { + if (!Array.isArray(resolved.defs)) { + return false; + } + const def = resolved.defs[0]; + if (def == null) { + return false; + } + // Look for `let stuff = ...` + if (def.node.type !== 'VariableDeclarator') { + return false; + } + const init = def.node.init; + if (init == null) { + return false; + } + // Detect primitive constants + // const foo = 42 + let declaration = def.node.parent; + if (declaration == null) { + // This might happen if variable is declared after the callback. + // In that case ESLint won't set up .parent refs. + // So we'll set them up manually. + fastFindReferenceWithParent(componentScope.block, def.node.id); + declaration = def.node.parent; + if (declaration == null) { + return false; + } + } + if ( + declaration.kind === 'const' && + init.type === 'Literal' && + (typeof init.value === 'string' || + typeof init.value === 'number' || + init.value === null) + ) { + // Definitely static + return true; + } + // Detect known Hook calls + // const [_, setState] = useState() + if (init.type !== 'CallExpression') { + return false; + } + let callee = init.callee; + // Step into `= React.something` initializer. + if ( + callee.type === 'MemberExpression' && + callee.object.name === 'React' && + callee.property != null && + !callee.computed + ) { + callee = callee.property; + } + if (callee.type !== 'Identifier') { + return false; + } + const id = def.node.id; + const { name } = callee; + + if ( + (name === 'useRef' || name === 'useLazyRef') && + id.type === 'Identifier' + ) { + // useRef() return value is static. + return true; + } else if (name === 'useState' || name === 'useReducer') { + // Only consider second value in initializing tuple static. + if ( + id.type === 'ArrayPattern' && + id.elements.length === 2 && + Array.isArray(resolved.identifiers) + ) { + // Is second tuple value the same reference we're checking? + if (id.elements[1] === resolved.identifiers[0]) { + if (name === 'useState') { + const references = resolved.references; + for (let i = 0; i < references.length; i++) { + setStateCallSites.set( + references[i].identifier, + id.elements[0], + ); + } + } + // Setter is static. + return true; + } else if (id.elements[0] === resolved.identifiers[0]) { + if (name === 'useState') { + const references = resolved.references; + for (let i = 0; i < references.length; i++) { + stateVariables.add(references[i].identifier); + } + } + // State variable itself is dynamic. + return false; + } + } + } + // By default assume it's dynamic. + return false; + } + + // Some are just functions that don't reference anything dynamic. + function isFunctionWithoutCapturedValues(resolved) { + if (!Array.isArray(resolved.defs)) { + return false; + } + const def = resolved.defs[0]; + if (def == null) { + return false; + } + if (def.node == null || def.node.id == null) { + return false; + } + // Search the direct component subscopes for + // top-level function definitions matching this reference. + const fnNode = def.node; + let childScopes = componentScope.childScopes; + let fnScope = null; + let i; + for (i = 0; i < childScopes.length; i++) { + let childScope = childScopes[i]; + let childScopeBlock = childScope.block; + if ( + // function handleChange() {} + (fnNode.type === 'FunctionDeclaration' && + childScopeBlock === fnNode) || + // const handleChange = () => {} + // const handleChange = function() {} + (fnNode.type === 'VariableDeclarator' && + childScopeBlock.parent === fnNode) + ) { + // Found it! + fnScope = childScope; + break; + } + } + if (fnScope == null) { + return false; + } + // Does this function capture any values + // that are in pure scopes (aka render)? + for (i = 0; i < fnScope.through.length; i++) { + const ref = fnScope.through[i]; + if (ref.resolved == null) { + continue; + } + if ( + pureScopes.has(ref.resolved.scope) && + // Static values are fine though, + // although we won't check functions deeper. + !memoizedIsStaticKnownHookValue(ref.resolved) + ) { + return false; + } + } + // If we got here, this function doesn't capture anything + // from render--or everything it captures is known static. + return true; + } + + // Remember such values. Avoid re-running extra checks on them. + const memoizedIsStaticKnownHookValue = memoizeWithWeakMap( + isStaticKnownHookValue, + staticKnownValueCache, + ); + const memoizedIsFunctionWithoutCapturedValues = memoizeWithWeakMap( + isFunctionWithoutCapturedValues, + functionWithoutCapturedValueCache, + ); + + // These are usually mistaken. Collect them. + const currentRefsInEffectCleanup = new Map(); + + // Is this reference inside a cleanup function for this effect node? + // We can check by traversing scopes upwards from the reference, and checking + // if the last "return () => " we encounter is located directly inside the effect. + function isInsideEffectCleanup(reference) { + let curScope = reference.from; + let isInReturnedFunction = false; + while (curScope.block !== node) { + if (curScope.type === 'function') { + isInReturnedFunction = + curScope.block.parent != null && + curScope.block.parent.type === 'ReturnStatement'; + } + curScope = curScope.upper; + } + return isInReturnedFunction; + } + + // Get dependencies from all our resolved references in pure scopes. + // Key is dependency string, value is whether it's static. + const dependencies = new Map(); + gatherDependenciesRecursively(scope); + + function gatherDependenciesRecursively(currentScope) { + for (const reference of currentScope.references) { + // If this reference is not resolved or it is not declared in a pure + // scope then we don't care about this reference. + if (!reference.resolved) { + continue; + } + if (!pureScopes.has(reference.resolved.scope)) { + continue; + } + + // Narrow the scope of a dependency if it is, say, a member expression. + // Then normalize the narrowed dependency. + const referenceNode = fastFindReferenceWithParent( + node, + reference.identifier, + ); + const dependencyNode = getDependency(referenceNode); + const dependency = toPropertyAccessString(dependencyNode); + + // Accessing ref.current inside effect cleanup is bad. + if ( + // We're in an effect... + isEffect && + // ... and this look like accessing .current... + dependencyNode.type === 'Identifier' && + dependencyNode.parent.type === 'MemberExpression' && + !dependencyNode.parent.computed && + dependencyNode.parent.property.type === 'Identifier' && + dependencyNode.parent.property.name === 'current' && + // ...in a cleanup function or below... + isInsideEffectCleanup(reference) + ) { + currentRefsInEffectCleanup.set(dependency, { + reference, + dependencyNode, + }); + } + + const def = reference.resolved.defs[0]; + + if (def == null) { + continue; + } + + // Ignore references to the function itself as it's not defined yet. + if (def.node != null && def.node.init === node.parent) { + continue; + } + + // Ignore Flow type parameters + if (def.type === 'TypeParameter') { + continue; + } + + // Add the dependency to a map so we can make sure it is referenced + // again in our dependencies array. Remember whether it's static. + if (!dependencies.has(dependency)) { + const resolved = reference.resolved; + const isStatic = + memoizedIsStaticKnownHookValue(resolved) || + memoizedIsFunctionWithoutCapturedValues(resolved); + dependencies.set(dependency, { + isStatic, + references: [reference], + }); + } else { + dependencies.get(dependency).references.push(reference); + } + } + for (const childScope of currentScope.childScopes) { + gatherDependenciesRecursively(childScope); + } + } + + // Warn about accessing .current in cleanup effects. + currentRefsInEffectCleanup.forEach( + ({ reference, dependencyNode }, dependency) => { + const references = reference.resolved.references; + // Is React managing this ref or us? + // Let's see if we can find a .current assignment. + let foundCurrentAssignment = false; + for (let i = 0; i < references.length; i++) { + const { identifier } = references[i]; + const { parent } = identifier; + if ( + parent != null && + // ref.current + parent.type === 'MemberExpression' && + !parent.computed && + parent.property.type === 'Identifier' && + parent.property.name === 'current' && + // ref.current = + parent.parent.type === 'AssignmentExpression' && + parent.parent.left === parent + ) { + foundCurrentAssignment = true; + break; + } + } + // We only want to warn about React-managed refs. + if (foundCurrentAssignment) { + return; + } + context.report({ + node: dependencyNode.parent.property, + message: + `The ref value '${dependency}.current' will likely have ` + + `changed by the time this effect cleanup function runs. If ` + + `this ref points to a node rendered by React, copy ` + + `'${dependency}.current' to a variable inside the effect, and ` + + `use that variable in the cleanup function.`, + }); + }, + ); + + // Warn about assigning to variables in the outer scope. + // Those are usually bugs. + let staleAssignments = new Set(); + function reportStaleAssignment(writeExpr, key) { + if (staleAssignments.has(key)) { + return; + } + staleAssignments.add(key); + context.report({ + node: writeExpr, + message: + `Assignments to the '${key}' variable from inside React Hook ` + + `${context.getSource(reactiveHook)} will be lost after each ` + + `render. To preserve the value over time, store it in a useRef or useLazyRef ` + + `Hook and keep the mutable value in the '.current' property. ` + + `Otherwise, you can move this variable directly inside ` + + `${context.getSource(reactiveHook)}.`, + }); + } + + // Remember which deps are optional and report bad usage first. + const optionalDependencies = new Set(); + dependencies.forEach(({ isStatic, references }, key) => { + if (isStatic) { + optionalDependencies.add(key); + } + references.forEach(reference => { + if (reference.writeExpr) { + reportStaleAssignment(reference.writeExpr, key); + } + }); + }); + + if (staleAssignments.size > 0) { + // The intent isn't clear so we'll wait until you fix those first. + return; + } + + if (!declaredDependenciesNode) { + // Check if there are any top-level setState() calls. + // Those tend to lead to infinite loops. + let setStateInsideEffectWithoutDeps = null; + dependencies.forEach(({ isStatic, references }, key) => { + if (setStateInsideEffectWithoutDeps) { + return; + } + references.forEach(reference => { + if (setStateInsideEffectWithoutDeps) { + return; + } + + const id = reference.identifier; + const isSetState = setStateCallSites.has(id); + if (!isSetState) { + return; + } + + let fnScope = reference.from; + while (fnScope.type !== 'function') { + fnScope = fnScope.upper; + } + const isDirectlyInsideEffect = fnScope.block === node; + if (isDirectlyInsideEffect) { + // TODO: we could potentially ignore early returns. + setStateInsideEffectWithoutDeps = key; + } + }); + }); + if (setStateInsideEffectWithoutDeps) { + let { suggestedDependencies } = collectRecommendations({ + dependencies, + declaredDependencies: [], + optionalDependencies, + externalDependencies: new Set(), + isEffect: true, + }); + context.report({ + node: node.parent.callee, + message: + `React Hook ${reactiveHookName} contains a call to '${setStateInsideEffectWithoutDeps}'. ` + + `Without a list of dependencies, this can lead to an infinite chain of updates. ` + + `To fix this, pass [` + + suggestedDependencies.join(', ') + + `] as a second argument to the ${reactiveHookName} Hook.`, + fix(fixer) { + return fixer.insertTextAfter( + node, + `, [${suggestedDependencies.join(', ')}]`, + ); + }, + }); + } + return; + } + + const declaredDependencies = []; + const externalDependencies = new Set(); + if (declaredDependenciesNode.type !== 'ArrayExpression') { + // If the declared dependencies are not an array expression then we + // can't verify that the user provided the correct dependencies. Tell + // the user this in an error. + context.report({ + node: declaredDependenciesNode, + message: + `React Hook ${context.getSource(reactiveHook)} was passed a ` + + 'dependency list that is not an array literal. This means we ' + + "can't statically verify whether you've passed the correct " + + 'dependencies.', + }); + } else { + declaredDependenciesNode.elements.forEach(declaredDependencyNode => { + // Skip elided elements. + if (declaredDependencyNode === null) { + return; + } + // If we see a spread element then add a special warning. + if (declaredDependencyNode.type === 'SpreadElement') { + context.report({ + node: declaredDependencyNode, + message: + `React Hook ${context.getSource(reactiveHook)} has a spread ` + + "element in its dependency array. This means we can't " + + "statically verify whether you've passed the " + + 'correct dependencies.', + }); + return; + } + // Try to normalize the declared dependency. If we can't then an error + // will be thrown. We will catch that error and report an error. + let declaredDependency; + try { + declaredDependency = toPropertyAccessString(declaredDependencyNode); + } catch (error) { + if (/Unsupported node type/.test(error.message)) { + if (declaredDependencyNode.type === 'Literal') { + if (dependencies.has(declaredDependencyNode.value)) { + context.report({ + node: declaredDependencyNode, + message: + `The ${declaredDependencyNode.raw} literal is not a valid dependency ` + + `because it never changes. ` + + `Did you mean to include ${declaredDependencyNode.value} in the array instead?`, + }); + } else { + context.report({ + node: declaredDependencyNode, + message: + `The ${declaredDependencyNode.raw} literal is not a valid dependency ` + + 'because it never changes. You can safely remove it.', + }); + } + } else { + context.report({ + node: declaredDependencyNode, + message: + `React Hook ${context.getSource(reactiveHook)} has a ` + + `complex expression in the dependency array. ` + + 'Extract it to a separate variable so it can be statically checked.', + }); + } + + return; + } else { + throw error; + } + } + + let maybeID = declaredDependencyNode; + while (maybeID.type === 'MemberExpression') { + maybeID = maybeID.object; + } + const isDeclaredInComponent = !componentScope.through.some( + ref => ref.identifier === maybeID, + ); + + // Add the dependency to our declared dependency map. + declaredDependencies.push({ + key: declaredDependency, + node: declaredDependencyNode, + }); + + if (!isDeclaredInComponent) { + externalDependencies.add(declaredDependency); + } + }); + } + + let { + suggestedDependencies, + unnecessaryDependencies, + missingDependencies, + duplicateDependencies, + } = collectRecommendations({ + dependencies, + declaredDependencies, + optionalDependencies, + externalDependencies, + isEffect, + }); + + const problemCount = + duplicateDependencies.size + + missingDependencies.size + + unnecessaryDependencies.size; + + // If we're going to report a missing dependency, + // we might as well recalculate the list ignoring + // the currently specified deps. This can result + // in some extra deduplication. We can't do this + // for effects though because those have legit + // use cases for over-specifying deps. + if (!isEffect && missingDependencies.size > 0) { + suggestedDependencies = collectRecommendations({ + dependencies, + declaredDependencies: [], // Pretend we don't know + optionalDependencies, + externalDependencies, + isEffect, + }).suggestedDependencies; + } + + // Alphabetize the suggestions, but only if deps were already alphabetized. + function areDeclaredDepsAlphabetized() { + if (declaredDependencies.length === 0) { + return true; + } + const declaredDepKeys = declaredDependencies.map(dep => dep.key); + const sortedDeclaredDepKeys = declaredDepKeys.slice().sort(); + return declaredDepKeys.join(',') === sortedDeclaredDepKeys.join(','); + } + if (areDeclaredDepsAlphabetized()) { + suggestedDependencies.sort(); + } + + function getWarningMessage(deps, singlePrefix, label, fixVerb) { + if (deps.size === 0) { + return null; + } + return ( + (deps.size > 1 ? '' : singlePrefix + ' ') + + label + + ' ' + + (deps.size > 1 ? 'dependencies' : 'dependency') + + ': ' + + joinEnglish( + Array.from(deps) + .sort() + .map(name => "'" + name + "'"), + ) + + `. Either ${fixVerb} ${ + deps.size > 1 ? 'them' : 'it' + } or remove the dependency array.` + ); + } + + let extraWarning = ''; + if (unnecessaryDependencies.size > 0) { + let badRef = null; + Array.from(unnecessaryDependencies.keys()).forEach(key => { + if (badRef !== null) { + return; + } + if (key.endsWith('.current')) { + badRef = key; + } + }); + if (badRef !== null) { + extraWarning = + ` Mutable values like '${badRef}' aren't valid dependencies ` + + "because mutating them doesn't re-render the component."; + } else if (externalDependencies.size > 0) { + const dep = Array.from(externalDependencies)[0]; + // Don't show this warning for things that likely just got moved *inside* the callback + // because in that case they're clearly not referring to globals. + if (!scope.set.has(dep)) { + extraWarning = + ` Outer scope values like '${dep}' aren't valid dependencies ` + + `because mutating them doesn't re-render the component.`; + } + } + } + + // `props.foo()` marks `props` as a dependency because it has + // a `this` value. This warning can be confusing. + // So if we're going to show it, append a clarification. + if (!extraWarning && missingDependencies.has('props')) { + let propDep = dependencies.get('props'); + if (propDep == null) { + return; + } + const refs = propDep.references; + if (!Array.isArray(refs)) { + return; + } + let isPropsOnlyUsedInMembers = true; + for (let i = 0; i < refs.length; i++) { + const ref = refs[i]; + const id = fastFindReferenceWithParent( + componentScope.block, + ref.identifier, + ); + if (!id) { + isPropsOnlyUsedInMembers = false; + break; + } + const parent = id.parent; + if (parent == null) { + isPropsOnlyUsedInMembers = false; + break; + } + if (parent.type !== 'MemberExpression') { + isPropsOnlyUsedInMembers = false; + break; + } + } + if (isPropsOnlyUsedInMembers) { + extraWarning = + ` However, 'props' will change when *any* prop changes, so the ` + + `preferred fix is to destructure the 'props' object outside of ` + + `the ${reactiveHookName} call and refer to those specific props ` + + `inside ${context.getSource(reactiveHook)}.`; + } + } + + if (!extraWarning && missingDependencies.size > 0) { + // See if the user is trying to avoid specifying a callable prop. + // This usually means they're unaware of useWorker. + let missingCallbackDep = null; + missingDependencies.forEach(missingDep => { + if (missingCallbackDep) { + return; + } + // Is this a variable from top scope? + const topScopeRef = componentScope.set.get(missingDep); + const usedDep = dependencies.get(missingDep); + if (usedDep.references[0].resolved !== topScopeRef) { + return; + } + // Is this a destructured prop? + const def = topScopeRef.defs[0]; + if (def == null || def.name == null || def.type !== 'Parameter') { + return; + } + // Was it called in at least one case? Then it's a function. + let isFunctionCall = false; + let id; + for (let i = 0; i < usedDep.references.length; i++) { + id = usedDep.references[i].identifier; + if ( + id != null && + id.parent != null && + id.parent.type === 'CallExpression' && + id.parent.callee === id + ) { + isFunctionCall = true; + break; + } + } + if (!isFunctionCall) { + return; + } + // If it's missing (i.e. in component scope) *and* it's a parameter + // then it is definitely coming from props destructuring. + // (It could also be props itself but we wouldn't be calling it then.) + missingCallbackDep = missingDep; + }); + if (missingCallbackDep !== null) { + extraWarning = + ` If '${missingCallbackDep}' changes too often, ` + + `find the parent component that defines it ` + + `and wrap that definition in useWorker.`; + } + } + + if (!extraWarning && missingDependencies.size > 0) { + let setStateRecommendation = null; + missingDependencies.forEach(missingDep => { + if (setStateRecommendation !== null) { + return; + } + const usedDep = dependencies.get(missingDep); + const references = usedDep.references; + let id; + let maybeCall; + for (let i = 0; i < references.length; i++) { + id = references[i].identifier; + maybeCall = id.parent; + // Try to see if we have setState(someExpr(missingDep)). + while (maybeCall != null && maybeCall !== componentScope.block) { + if (maybeCall.type === 'CallExpression') { + const correspondingStateVariable = setStateCallSites.get( + maybeCall.callee, + ); + if (correspondingStateVariable != null) { + if (correspondingStateVariable.name === missingDep) { + // setCount(count + 1) + setStateRecommendation = { + missingDep, + setter: maybeCall.callee.name, + form: 'updater', + }; + } else if (stateVariables.has(id)) { + // setCount(count + increment) + setStateRecommendation = { + missingDep, + setter: maybeCall.callee.name, + form: 'reducer', + }; + } else { + const resolved = references[i].resolved; + if (resolved != null) { + // If it's a parameter *and* a missing dep, + // it must be a prop or something inside a prop. + // Therefore, recommend an inline reducer. + const def = resolved.defs[0]; + if (def != null && def.type === 'Parameter') { + setStateRecommendation = { + missingDep, + setter: maybeCall.callee.name, + form: 'inlineReducer', + }; + } + } + } + break; + } + } + maybeCall = maybeCall.parent; + } + if (setStateRecommendation !== null) { + break; + } + } + }); + if (setStateRecommendation !== null) { + switch (setStateRecommendation.form) { + case 'reducer': + extraWarning = + ` You can also replace multiple useState variables with useReducer ` + + `if '${setStateRecommendation.setter}' needs the ` + + `current value of '${setStateRecommendation.missingDep}'.`; + break; + case 'inlineReducer': + extraWarning = + ` If '${setStateRecommendation.setter}' needs the ` + + `current value of '${setStateRecommendation.missingDep}', ` + + `you can also switch to useReducer instead of useState and ` + + `read '${setStateRecommendation.missingDep}' in the reducer.`; + break; + case 'updater': + extraWarning = + ` You can also do a functional update '${ + setStateRecommendation.setter + }(${setStateRecommendation.missingDep.substring( + 0, + 1, + )} => ...)' if you only need '${ + setStateRecommendation.missingDep + }'` + ` in the '${setStateRecommendation.setter}' call.`; + break; + default: + throw new Error('Unknown case.'); + } + } + } + + if (problemCount !== 0) { + context.report({ + node: declaredDependenciesNode, + message: + `React Hook ${context.getSource(reactiveHook)} has ` + + // To avoid a long message, show the next actionable item. + (getWarningMessage( + missingDependencies, + 'a', + 'missing', + 'include', + ) || + getWarningMessage( + unnecessaryDependencies, + 'an', + 'unnecessary', + 'exclude', + ) || + getWarningMessage( + duplicateDependencies, + 'a', + 'duplicate', + 'omit', + )) + + extraWarning, + fix(fixer) { + // TODO: consider preserving the comments or formatting? + return fixer.replaceText( + declaredDependenciesNode, + `[${suggestedDependencies.join(', ')}]`, + ); + }, + }); + } + } + }, +}; + +// The meat of the logic. +function collectRecommendations({ + dependencies, + declaredDependencies, + optionalDependencies, + externalDependencies, + isEffect, +}) { + // Our primary data structure. + // It is a logical representation of property chains: + // `props` -> `props.foo` -> `props.foo.bar` -> `props.foo.bar.baz` + // -> `props.lol` + // -> `props.huh` -> `props.huh.okay` + // -> `props.wow` + // We'll use it to mark nodes that are *used* by the programmer, + // and the nodes that were *declared* as deps. Then we will + // traverse it to learn which deps are missing or unnecessary. + const depTree = createDepTree(); + function createDepTree() { + return { + isRequired: false, // True if used in code + isSatisfiedRecursively: false, // True if specified in deps + hasRequiredNodesBelow: false, // True if something deeper is used by code + children: new Map(), // Nodes for properties + }; + } + + // Mark all required nodes first. + // Imagine exclamation marks next to each used deep property. + dependencies.forEach((_, key) => { + const node = getOrCreateNodeByPath(depTree, key); + node.isRequired = true; + markAllParentsByPath(depTree, key, parent => { + parent.hasRequiredNodesBelow = true; + }); + }); + + // Mark all satisfied nodes. + // Imagine checkmarks next to each declared dependency. + declaredDependencies.forEach(({ key }) => { + const node = getOrCreateNodeByPath(depTree, key); + node.isSatisfiedRecursively = true; + }); + optionalDependencies.forEach(key => { + const node = getOrCreateNodeByPath(depTree, key); + node.isSatisfiedRecursively = true; + }); + + // Tree manipulation helpers. + function getOrCreateNodeByPath(rootNode, path) { + let keys = path.split('.'); + let node = rootNode; + for (let key of keys) { + let child = node.children.get(key); + if (!child) { + child = createDepTree(); + node.children.set(key, child); + } + node = child; + } + return node; + } + function markAllParentsByPath(rootNode, path, fn) { + let keys = path.split('.'); + let node = rootNode; + for (let key of keys) { + let child = node.children.get(key); + if (!child) { + return; + } + fn(child); + node = child; + } + } + + // Now we can learn which dependencies are missing or necessary. + let missingDependencies = new Set(); + let satisfyingDependencies = new Set(); + scanTreeRecursively( + depTree, + missingDependencies, + satisfyingDependencies, + key => key, + ); + function scanTreeRecursively(node, missingPaths, satisfyingPaths, keyToPath) { + node.children.forEach((child, key) => { + const path = keyToPath(key); + if (child.isSatisfiedRecursively) { + if (child.hasRequiredNodesBelow) { + // Remember this dep actually satisfied something. + satisfyingPaths.add(path); + } + // It doesn't matter if there's something deeper. + // It would be transitively satisfied since we assume immutability. + // `props.foo` is enough if you read `props.foo.id`. + return; + } + if (child.isRequired) { + // Remember that no declared deps satisfied this node. + missingPaths.add(path); + // If we got here, nothing in its subtree was satisfied. + // No need to search further. + return; + } + scanTreeRecursively( + child, + missingPaths, + satisfyingPaths, + childKey => path + '.' + childKey, + ); + }); + } + + // Collect suggestions in the order they were originally specified. + let suggestedDependencies = []; + let unnecessaryDependencies = new Set(); + let duplicateDependencies = new Set(); + declaredDependencies.forEach(({ key }) => { + // Does this declared dep satisfy a real need? + if (satisfyingDependencies.has(key)) { + if (suggestedDependencies.indexOf(key) === -1) { + // Good one. + suggestedDependencies.push(key); + } else { + // Duplicate. + duplicateDependencies.add(key); + } + } else { + if ( + isEffect && + !key.endsWith('.current') && + !externalDependencies.has(key) + ) { + // Effects are allowed extra "unnecessary" deps. + // Such as resetting scroll when ID changes. + // Consider them legit. + // The exception is ref.current which is always wrong. + if (suggestedDependencies.indexOf(key) === -1) { + suggestedDependencies.push(key); + } + } else { + // It's definitely not needed. + unnecessaryDependencies.add(key); + } + } + }); + + // Then add the missing ones at the end. + missingDependencies.forEach(key => { + suggestedDependencies.push(key); + }); + + return { + suggestedDependencies, + unnecessaryDependencies, + duplicateDependencies, + missingDependencies, + }; +} + +/** + * Assuming () means the passed/returned node: + * (props) => (props) + * props.(foo) => (props.foo) + * props.foo.(bar) => (props).foo.bar + * props.foo.bar.(baz) => (props).foo.bar.baz + */ +function getDependency(node) { + if ( + node.parent.type === 'MemberExpression' && + node.parent.object === node && + node.parent.property.name !== 'current' && + !node.parent.computed && + !( + node.parent.parent != null && + node.parent.parent.type === 'CallExpression' && + node.parent.parent.callee === node.parent + ) + ) { + return getDependency(node.parent); + } else { + return node; + } +} + +/** + * Assuming () means the passed node. + * (foo) -> 'foo' + * foo.(bar) -> 'foo.bar' + * foo.bar.(baz) -> 'foo.bar.baz' + * Otherwise throw. + */ +function toPropertyAccessString(node) { + if (node.type === 'Identifier') { + return node.name; + } else if (node.type === 'MemberExpression' && !node.computed) { + const object = toPropertyAccessString(node.object); + const property = toPropertyAccessString(node.property); + return `${object}.${property}`; + } else { + throw new Error(`Unsupported node type: ${node.type}`); + } +} + +function getNodeWithoutReactNamespace(node) { + if ( + node.type === 'MemberExpression' && + node.object.type === 'Identifier' && + node.object.name === 'React' && + node.property.type === 'Identifier' && + !node.computed + ) { + return node.property; + } + return node; +} + +// What's the index of callback that needs to be analyzed for a given Hook? +// -1 if it's not a Hook we care about (e.g. useState). +// 0 for useEffect/useMemo/useCallback(fn). +// 1 for useImperativeHandle(ref, fn). +// For additionally configured Hooks, assume that they're like useEffect (0). +function getReactiveHookCallbackIndex(calleeNode) { + let node = getNodeWithoutReactNamespace(calleeNode); + if (node.type !== 'Identifier') { + return null; + } + switch (node.name) { + case 'useAsyncEffect': + case 'useAsyncLayoutEffect': + case 'useWorker': + case 'useWorkerLoad': + case 'useEffectUpdate': + return 0; + case 'useConditionalEffect': + return 1; + default: + return -1; + } +} + +/** + * ESLint won't assign node.parent to references from context.getScope() + * + * So instead we search for the node from an ancestor assigning node.parent + * as we go. This mutates the AST. + * + * This traversal is: + * - optimized by only searching nodes with a range surrounding our target node + * - agnostic to AST node types, it looks for `{ type: string, ... }` + */ +function fastFindReferenceWithParent(start, target) { + let queue = [start]; + let item = null; + + while (queue.length) { + item = queue.shift(); + + if (isSameIdentifier(item, target)) { + return item; + } + + if (!isAncestorNodeOf(item, target)) { + continue; + } + + for (let [key, value] of Object.entries(item)) { + if (key === 'parent') { + continue; + } + if (isNodeLike(value)) { + value.parent = item; + queue.push(value); + } else if (Array.isArray(value)) { + value.forEach(val => { + if (isNodeLike(val)) { + val.parent = item; + queue.push(val); + } + }); + } + } + } + + return null; +} + +function joinEnglish(arr) { + let s = ''; + for (let i = 0; i < arr.length; i++) { + s += arr[i]; + if (i === 0 && arr.length === 2) { + s += ' and '; + } else if (i === arr.length - 2 && arr.length > 2) { + s += ', and '; + } else if (i < arr.length - 1) { + s += ', '; + } + } + return s; +} + +function isNodeLike(val) { + return ( + typeof val === 'object' && + val !== null && + !Array.isArray(val) && + typeof val.type === 'string' + ); +} + +function isSameIdentifier(a, b) { + return ( + a.type === 'Identifier' && + a.name === b.name && + a.range[0] === b.range[0] && + a.range[1] === b.range[1] + ); +} + +function isAncestorNodeOf(a, b) { + return a.range[0] <= b.range[0] && a.range[1] >= b.range[1]; +} diff --git a/eslint-plugin/yarn.lock b/eslint-plugin/yarn.lock new file mode 100644 index 0000000..e0fcf90 --- /dev/null +++ b/eslint-plugin/yarn.lock @@ -0,0 +1,2953 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/cli@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.6.2.tgz#4ce8b5b4b2e4b4c1b7bd841cec62085e2dfc4465" + integrity sha512-JDZ+T/br9pPfT2lmAMJypJDTTTHM9ePD/ED10TRjRzJVdEVy+JB3iRlhzYmTt5YkNgHvxWGlUVnLtdv6ruiDrQ== + dependencies: + commander "^2.8.1" + convert-source-map "^1.1.0" + fs-readdir-recursive "^1.1.0" + glob "^7.0.0" + lodash "^4.17.13" + mkdirp "^0.5.1" + output-file-sync "^2.0.0" + slash "^2.0.0" + source-map "^0.5.0" + optionalDependencies: + chokidar "^2.1.8" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/generator@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.2.tgz#dac8a3c2df118334c2a29ff3446da1636a8f8c03" + integrity sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ== + dependencies: + "@babel/types" "^7.6.0" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" + integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" + integrity sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-call-delegate@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz#87c1f8ca19ad552a736a7a27b1c1fcf8b1ff1f43" + integrity sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ== + dependencies: + "@babel/helper-hoist-variables" "^7.4.4" + "@babel/traverse" "^7.4.4" + "@babel/types" "^7.4.4" + +"@babel/helper-define-map@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" + integrity sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg== + dependencies: + "@babel/helper-function-name" "^7.1.0" + "@babel/types" "^7.5.5" + lodash "^4.17.13" + +"@babel/helper-explode-assignable-expression@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" + integrity sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA== + dependencies: + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-function-name@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" + integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== + dependencies: + "@babel/helper-get-function-arity" "^7.0.0" + "@babel/template" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-get-function-arity@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" + integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-hoist-variables@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" + integrity sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w== + dependencies: + "@babel/types" "^7.4.4" + +"@babel/helper-member-expression-to-functions@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" + integrity sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA== + dependencies: + "@babel/types" "^7.5.5" + +"@babel/helper-module-imports@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" + integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" + integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-simple-access" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/template" "^7.4.4" + "@babel/types" "^7.5.5" + lodash "^4.17.13" + +"@babel/helper-optimise-call-expression@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" + integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-plugin-utils@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" + integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== + +"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" + integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== + dependencies: + lodash "^4.17.13" + +"@babel/helper-remap-async-to-generator@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" + integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-wrap-function" "^7.1.0" + "@babel/template" "^7.1.0" + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-replace-supers@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" + integrity sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.5.5" + "@babel/helper-optimise-call-expression" "^7.0.0" + "@babel/traverse" "^7.5.5" + "@babel/types" "^7.5.5" + +"@babel/helper-simple-access@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" + integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== + dependencies: + "@babel/template" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-split-export-declaration@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" + integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== + dependencies: + "@babel/types" "^7.4.4" + +"@babel/helper-wrap-function@^7.1.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" + integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ== + dependencies: + "@babel/helper-function-name" "^7.1.0" + "@babel/template" "^7.1.0" + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.2.0" + +"@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.0.0", "@babel/parser@^7.6.0", "@babel/parser@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1" + integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg== + +"@babel/plugin-proposal-async-generator-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" + integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.1.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + +"@babel/plugin-proposal-dynamic-import@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz#e532202db4838723691b10a67b8ce509e397c506" + integrity sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-dynamic-import" "^7.2.0" + +"@babel/plugin-proposal-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" + integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + +"@babel/plugin-proposal-object-rest-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz#8ffccc8f3a6545e9f78988b6bf4fe881b88e8096" + integrity sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + +"@babel/plugin-proposal-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" + integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + +"@babel/plugin-proposal-unicode-property-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz#05413762894f41bfe42b9a5e80919bd575dcc802" + integrity sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + +"@babel/plugin-syntax-async-generators@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" + integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-dynamic-import@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" + integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" + integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-object-rest-spread@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" + integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" + integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-arrow-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" + integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-async-to-generator@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz#89a3848a0166623b5bc481164b5936ab947e887e" + integrity sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.1.0" + +"@babel/plugin-transform-block-scoped-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" + integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-block-scoping@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.2.tgz#96c33ab97a9ae500cc6f5b19e04a7e6553360a79" + integrity sha512-zZT8ivau9LOQQaOGC7bQLQOT4XPkPXgN2ERfUgk1X8ql+mVkLc4E8eKk+FO3o0154kxzqenWCorfmEXpEZcrSQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + lodash "^4.17.13" + +"@babel/plugin-transform-classes@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz#d094299d9bd680a14a2a0edae38305ad60fb4de9" + integrity sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-define-map" "^7.5.5" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-optimise-call-expression" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.5.5" + "@babel/helper-split-export-declaration" "^7.4.4" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" + integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-destructuring@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6" + integrity sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-dotall-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz#44abb948b88f0199a627024e1508acaf8dc9b2f9" + integrity sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + +"@babel/plugin-transform-duplicate-keys@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" + integrity sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-exponentiation-operator@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" + integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-for-of@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" + integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-function-name@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" + integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA== + dependencies: + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" + integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-member-expression-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" + integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-modules-amd@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" + integrity sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg== + dependencies: + "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-commonjs@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz#39dfe957de4420445f1fcf88b68a2e4aa4515486" + integrity sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g== + dependencies: + "@babel/helper-module-transforms" "^7.4.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-simple-access" "^7.1.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-systemjs@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz#e75266a13ef94202db2a0620977756f51d52d249" + integrity sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg== + dependencies: + "@babel/helper-hoist-variables" "^7.4.4" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-umd@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" + integrity sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw== + dependencies: + "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.2.tgz#c1ca0bb84b94f385ca302c3932e870b0fb0e522b" + integrity sha512-xBdB+XOs+lgbZc2/4F5BVDVcDNS4tcSKQc96KmlqLEAwz6tpYPEvPdmDfvVG0Ssn8lAhronaRs6Z6KSexIpK5g== + dependencies: + regexpu-core "^4.6.0" + +"@babel/plugin-transform-new-target@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" + integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-object-super@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" + integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.5.5" + +"@babel/plugin-transform-parameters@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" + integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== + dependencies: + "@babel/helper-call-delegate" "^7.4.4" + "@babel/helper-get-function-arity" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-property-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" + integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-regenerator@^7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" + integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== + dependencies: + regenerator-transform "^0.14.0" + +"@babel/plugin-transform-reserved-words@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634" + integrity sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-shorthand-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" + integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz#fc77cf798b24b10c46e1b51b1b88c2bf661bb8dd" + integrity sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-sticky-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" + integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.0.0" + +"@babel/plugin-transform-template-literals@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" + integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-typeof-symbol@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" + integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-unicode-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz#b692aad888a7e8d8b1b214be6b9dc03d5031f698" + integrity sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + +"@babel/preset-env@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.2.tgz#abbb3ed785c7fe4220d4c82a53621d71fc0c75d3" + integrity sha512-Ru7+mfzy9M1/YTEtlDS8CD45jd22ngb9tXnn64DvQK3ooyqSw9K4K9DUWmYknTTVk4TqygL9dqCrZgm1HMea/Q== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-async-generator-functions" "^7.2.0" + "@babel/plugin-proposal-dynamic-import" "^7.5.0" + "@babel/plugin-proposal-json-strings" "^7.2.0" + "@babel/plugin-proposal-object-rest-spread" "^7.6.2" + "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.6.2" + "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-dynamic-import" "^7.2.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/plugin-transform-arrow-functions" "^7.2.0" + "@babel/plugin-transform-async-to-generator" "^7.5.0" + "@babel/plugin-transform-block-scoped-functions" "^7.2.0" + "@babel/plugin-transform-block-scoping" "^7.6.2" + "@babel/plugin-transform-classes" "^7.5.5" + "@babel/plugin-transform-computed-properties" "^7.2.0" + "@babel/plugin-transform-destructuring" "^7.6.0" + "@babel/plugin-transform-dotall-regex" "^7.6.2" + "@babel/plugin-transform-duplicate-keys" "^7.5.0" + "@babel/plugin-transform-exponentiation-operator" "^7.2.0" + "@babel/plugin-transform-for-of" "^7.4.4" + "@babel/plugin-transform-function-name" "^7.4.4" + "@babel/plugin-transform-literals" "^7.2.0" + "@babel/plugin-transform-member-expression-literals" "^7.2.0" + "@babel/plugin-transform-modules-amd" "^7.5.0" + "@babel/plugin-transform-modules-commonjs" "^7.6.0" + "@babel/plugin-transform-modules-systemjs" "^7.5.0" + "@babel/plugin-transform-modules-umd" "^7.2.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.6.2" + "@babel/plugin-transform-new-target" "^7.4.4" + "@babel/plugin-transform-object-super" "^7.5.5" + "@babel/plugin-transform-parameters" "^7.4.4" + "@babel/plugin-transform-property-literals" "^7.2.0" + "@babel/plugin-transform-regenerator" "^7.4.5" + "@babel/plugin-transform-reserved-words" "^7.2.0" + "@babel/plugin-transform-shorthand-properties" "^7.2.0" + "@babel/plugin-transform-spread" "^7.6.2" + "@babel/plugin-transform-sticky-regex" "^7.2.0" + "@babel/plugin-transform-template-literals" "^7.4.4" + "@babel/plugin-transform-typeof-symbol" "^7.2.0" + "@babel/plugin-transform-unicode-regex" "^7.6.2" + "@babel/types" "^7.6.0" + browserslist "^4.6.0" + core-js-compat "^3.1.1" + invariant "^2.2.2" + js-levenshtein "^1.1.3" + semver "^5.5.0" + +"@babel/template@^7.1.0", "@babel/template@^7.4.4": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" + integrity sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.6.0" + "@babel/types" "^7.6.0" + +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c" + integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.6.2" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/parser" "^7.6.2" + "@babel/types" "^7.6.0" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0": + version "7.6.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648" + integrity sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= + dependencies: + acorn "^3.0.4" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= + +acorn@^5.5.0: + version "5.7.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" + integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= + +ajv@^4.7.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +babel-code-frame@^6.16.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-eslint@^10.0.3: + 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== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + +babel-plugin-dynamic-import-node@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" + integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== + dependencies: + object.assign "^4.1.0" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= + +browserslist@^4.6.0, browserslist@^4.6.6: + version "4.7.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.0.tgz#9ee89225ffc07db03409f2fee524dc8227458a17" + integrity sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA== + dependencies: + caniuse-lite "^1.0.30000989" + electron-to-chromium "^1.3.247" + node-releases "^1.1.29" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= + +caniuse-lite@^1.0.30000989: + version "1.0.30000997" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000997.tgz#ba44a606804f8680894b7042612c2c7f65685b7e" + integrity sha512-BQLFPIdj2ntgBNWp9Q64LGUIEmvhKkzzHhUHR3CD5A9Lb7ZKF20/+sgadhFap69lk5XmK1fTUleDclaRFvgVUA== + +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + optionalDependencies: + fsevents "^1.2.7" + +chownr@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" + integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= + dependencies: + restore-cursor "^1.0.1" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= + dependencies: + graceful-readlink ">= 1.0.0" + +commander@^2.8.1: + version "2.20.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.1.tgz#3863ce3ca92d0831dcf2a102f5fb4b5926afd0f9" + integrity sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.4.6: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +convert-source-map@^1.1.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" + integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== + dependencies: + safe-buffer "~5.1.1" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js-compat@^3.1.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.2.1.tgz#0cbdbc2e386e8e00d3b85dc81c848effec5b8150" + integrity sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A== + dependencies: + browserslist "^4.6.6" + semver "^6.3.0" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +debug@2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw= + dependencies: + ms "2.0.0" + +debug@^2.1.1, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +define-properties@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +diff@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" + integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k= + +doctrine@^1.2.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +electron-to-chromium@^1.3.247: + version "1.3.269" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.269.tgz#3e00cc9266a0123fc2e7b4f290899e257200e6e3" + integrity sha512-t2ZTfo07HxkxTOUbIwMmqHBSnJsC9heqJUm7LwQu2iSk0wNhG4H5cMREtb8XxeCrQABDZ6IqQKY3yZq+NfAqwg== + +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.51, es5-ext@~0.10.14: + version "0.10.51" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.51.tgz#ed2d7d9d48a12df86e0299287e93a09ff478842f" + integrity sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.1" + next-tick "^1.0.0" + +es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-map@^0.1.3: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" + integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-set "~0.1.5" + es6-symbol "~3.1.1" + event-emitter "~0.3.5" + +es6-set@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" + integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-symbol "3.1.1" + event-emitter "~0.3.5" + +es6-symbol@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.2.tgz#859fdd34f32e905ff06d752e7171ddd4444a7ed1" + integrity sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.51" + +es6-weak-map@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-visitor-keys@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + +eslint@~3.9.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.9.1.tgz#5a8597706fc6048bc6061ac754d4a211d28f4f5b" + integrity sha1-WoWXcG/GBIvGBhrHVNSiEdKPT1s= + dependencies: + babel-code-frame "^6.16.0" + chalk "^1.1.3" + concat-stream "^1.4.6" + debug "^2.1.1" + doctrine "^1.2.2" + escope "^3.6.0" + espree "^3.3.1" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.0.3" + globals "^9.2.0" + ignore "^3.1.5" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + levn "^0.3.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.7.5" + strip-bom "^3.0.0" + strip-json-comments "~1.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + +espree@^3.3.1: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" + integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== + dependencies: + acorn "^5.5.0" + acorn-jsx "^3.0.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +event-emitter@~0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= + dependencies: + d "1" + es5-ext "~0.10.14" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +flat-cache@^1.2.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" + integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== + dependencies: + circular-json "^0.3.1" + graceful-fs "^4.1.2" + rimraf "~2.6.2" + write "^0.2.1" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fs-minipass@^1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs-readdir-recursive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.7: + version "1.2.9" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" + integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== + dependencies: + nan "^2.12.1" + node-pre-gyp "^0.12.0" + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +generate-function@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" + integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== + dependencies: + is-property "^1.0.2" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= + dependencies: + is-property "^1.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg= + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.1.3: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^9.2.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +graceful-fs@^4.1.11, graceful-fs@^4.1.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" + integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8= + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + +iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore-walk@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.2.tgz#99d83a246c196ea5c93ef9315ad7b0819c35069b" + integrity sha512-EXyErtpHbn75ZTsOADsfx6J/FPo6/5cjev46PXrcTpd8z3BoRkXgYu9/JVqrI7tusjmwCZutGeRJeU0Wo1e4Cw== + dependencies: + minimatch "^3.0.4" + +ignore@^3.1.5: + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +inquirer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + integrity sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34= + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + figures "^1.3.5" + lodash "^4.3.0" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + +interpret@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" + integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-my-ip-valid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" + integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ== + +is-my-json-valid@^2.10.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz#1345a6fca3e8daefc10d0fa77067f54cedafd59a" + integrity sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA== + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + is-my-ip-valid "^1.0.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-property@^1.0.0, is-property@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +js-levenshtein@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" + integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + +js-yaml@^3.5.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + dependencies: + jsonify "~0.0.0" + +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + integrity sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4= + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= + +lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" + integrity sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE= + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= + +lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" + integrity sha1-1/KEnw29p+BGgruM1yqwIkYd6+c= + dependencies: + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash@^4.0.0, lodash@^4.17.13, lodash@^4.3.0: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +minipass@^2.6.0, minipass@^2.8.6: + version "2.8.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.8.6.tgz#620d889ace26356391d010ecb9458749df9b6db5" + integrity sha512-lFG7d6g3+/UaFDCOtqPiKAC9zngWWsQZl1g5q6gaONqrjq61SX2xFqXMleQiFVyDpYwa018E9hmlAFY22PCb+A== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.2.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.2.tgz#5d24764998f98112586f7e566bd4c0999769dad4" + integrity sha512-lsNFqSHdJ21EwKzCp12HHJGxSMtHkCW1EMA9cceG3MkMNARjuWotZnMe3NKNshAvFXpm4loZqmYsCmRwhS2JMw== + dependencies: + minipass "^2.9.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mocha@^3.1.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" + integrity sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg== + dependencies: + browser-stdout "1.3.0" + commander "2.9.0" + debug "2.6.8" + diff "3.2.0" + escape-string-regexp "1.0.5" + glob "7.1.1" + growl "1.9.2" + he "1.1.1" + json3 "3.3.2" + lodash.create "3.1.1" + mkdirp "0.5.1" + supports-color "3.1.2" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +mute-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" + integrity sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA= + +nan@^2.12.1: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +needle@^2.2.1: + version "2.4.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" + integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + +next-tick@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +node-pre-gyp@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" + integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +node-releases@^1.1.29: + version "1.1.33" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.33.tgz#349f10291234624574f44cf32b7de259bf028303" + integrity sha512-I0V30bWQEoHb+10W8oedVoUrdjW5wIkYm0w7vvcrPO95pZY738m1k77GF5sO0vKg5eXYg9oGtrMAETbgZGm11A== + dependencies: + semver "^5.3.0" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-bundled@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" + integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + +npm-packlist@^1.1.6: + version "1.4.4" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" + integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +object-assign@^4.0.1, object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-keys@^1.0.11, object-keys@^1.0.12: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +output-file-sync@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-2.0.1.tgz#f53118282f5f553c2799541792b723a4c71430c0" + integrity sha512-mDho4qm7WgIXIGf4eYU1RHN2UU5tPfVYVSRwDJw0uTmj35DQUt/eNp19N7v6T3SrR0ESTEf2up2CGO73qI35zQ== + dependencies: + graceful-fs "^4.1.11" + is-plain-obj "^1.1.0" + mkdirp "^0.5.1" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +pluralize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU= + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +private@^0.1.6: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +progress@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +readline2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + integrity sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + mute-stream "0.0.5" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + dependencies: + resolve "^1.1.6" + +regenerate-unicode-properties@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" + integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + +regenerator-transform@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" + integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== + dependencies: + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.1.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + +regjsgen@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" + integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA== + +regjsparser@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" + integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== + dependencies: + jsesc "~0.5.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +require-uncached@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.1.6, resolve@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + dependencies: + path-parse "^1.0.6" + +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +rimraf@^2.6.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +run-async@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + integrity sha1-yK1KXhEGYeQCp9IbUw4AnyX444k= + dependencies: + once "^1.3.0" + +rx-lite@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" + integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI= + +safe-buffer@^5.1.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +semver@^5.3.0, semver@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +shelljs@^0.7.5: + version "0.7.8" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" + integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.0, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-json-comments@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" + integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E= + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + integrity sha1-cqJiiU2dQIuVbKBf83su2KbiotU= + dependencies: + has-flag "^1.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +table@^3.7.8: + version "3.8.3" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + integrity sha1-K7xULw/amGGnVdOUf+/Ys/UThV8= + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + +tar@^4: + version "4.4.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.8.6" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" + integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" + integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +user-home@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" + integrity sha1-nHC/2Babwdy/SGBODwS4tJzenp8= + dependencies: + os-homedir "^1.0.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= + dependencies: + mkdirp "^0.5.1" + +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +yallist@^3.0.0, yallist@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.0.tgz#906cc2100972dc2625ae78f566a2577230a1d6f7" + integrity sha512-6gpP93MR+VOOehKbCPchro3wFZNSNmek8A2kbkOAZLIZAYx1KP/zAqwO0sOHi3xJEb+UBz8NaYt/17UNit1Q9w== diff --git a/jest.config.js b/jest.config.js index 749c55a..7b9239f 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,8 +1,6 @@ module.exports = { - roots: [ - "/src" - ], + roots: ['/src'], transform: { - "^.+\\.tsx?$": "ts-jest" - } -} \ No newline at end of file + '^.+\\.tsx?$': 'ts-jest', + }, +}; diff --git a/package.json b/package.json index 441345e..d64a107 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "scripts": { "build": "tsc && prettier --check 'dist/**/*' --write", "test": "jest --coverage", - "lint": "prettier --check 'src/**/*'", + "lint": "eslint --ext=.ts,.tsx --max-warnings=0 src/ && prettier --check 'src/**/*'", "docs": "typedoc --out docs/$npm_package_version && scripts/gen-docs-index.sh $npm_package_version", "version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md" }, @@ -35,11 +35,17 @@ "react": "^16" }, "devDependencies": { + "@react-hook-utilities/eslint-plugin": "./eslint-plugin", "@testing-library/react-hooks": "^2.0.1", "@types/jest": "^24.0.18", "@types/react": "^16.9.2", + "@typescript-eslint/eslint-plugin": "^2.3.1", + "@typescript-eslint/parser": "^2.3.1", "commitlint": "^8.2.0", "conventional-changelog-cli": "^2.0.25", + "eslint": "^6.5.0", + "eslint-plugin-react": "^7.14.3", + "eslint-plugin-react-hooks": "^2.1.1", "husky": "^3.0.5", "jest": "^24.9.0", "prettier": "^1.19.1", diff --git a/src/__tests__/useEffectUpdate.ts b/src/__tests__/useEffectUpdate.ts index c00df4a..6304dc5 100644 --- a/src/__tests__/useEffectUpdate.ts +++ b/src/__tests__/useEffectUpdate.ts @@ -4,12 +4,15 @@ import { useEffectUpdate } from '..'; const deps = [1, 2, 3]; -const hook = async ({ dependencies, cleanup }: any) => +const hook = async ({ dependencies = [], cleanup }: any) => new Promise(resolve => { - useEffectUpdate(oldState => { - resolve(oldState); - return cleanup; - }, dependencies); + useEffectUpdate( + oldState => { + resolve(oldState); + return cleanup; + }, + dependencies, // eslint-disable-line @react-hook-utilities/exhaustive-deps + ); }); it('receives empty array as old state', () => { diff --git a/src/index.tsx b/src/index.tsx index da9ea48..a73623e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -55,11 +55,11 @@ export interface ValuablePromise extends Promise { */ export const useAsyncEffect = ( effect: () => Promise, - dependencies?: readonly any[], + dependencies: readonly any[] = [], ) => { useEffect(() => { effect(); - }, dependencies); + }, [...dependencies, effect]); }; /** @@ -73,11 +73,11 @@ export const useAsyncEffect = ( */ export const useAsyncLayoutEffect = ( effect: () => Promise, - dependencies?: readonly any[], + dependencies: readonly any[] = [], ) => { useLayoutEffect(() => { effect(); - }, dependencies); + }, [...dependencies, effect]); }; /** @@ -280,7 +280,7 @@ export function useEffectUpdate( } finally { oldState.current = dependencies; } - }, dependencies); + }, [...dependencies, effect, oldState.current]); } /** @@ -448,7 +448,7 @@ export function useConditionalEffect( */ export function useConditionalEffect( evalCondition: (oldState: Dependencies) => boolean, - effect: () => (() => void) | void, + effect: () => void | (() => void), dependencies: Dependencies, ): void; export function useConditionalEffect( @@ -458,7 +458,7 @@ export function useConditionalEffect( ): void { useEffectUpdate( oldState => (evalCondition(oldState) ? effect() : undefined), - dependencies, + dependencies, // eslint-disable-line @react-hook-utilities/exhaustive-deps,react-hooks/exhaustive-deps ); } diff --git a/yarn.lock b/yarn.lock index 3ce89dd..40f182d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -428,6 +428,9 @@ mkdirp "^0.5.1" rimraf "^2.5.2" +"@react-hook-utilities/eslint-plugin@./eslint-plugin": + version "1.0.0" + "@testing-library/react-hooks@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-2.0.1.tgz#1c3ec40882d0830df3078ddae0056fdf7366c81d" @@ -470,6 +473,11 @@ dependencies: "@babel/types" "^7.3.0" +"@types/eslint-visitor-keys@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" + integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" @@ -502,6 +510,11 @@ dependencies: "@types/jest-diff" "*" +"@types/json-schema@^7.0.3": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" + integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== + "@types/minimatch@3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -559,6 +572,49 @@ dependencies: "@types/yargs-parser" "*" +"@typescript-eslint/eslint-plugin@^2.3.1": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.10.0.tgz#c4cb103275e555e8a7e9b3d14c5951eb6d431e70" + integrity sha512-rT51fNLW0u3fnDGnAHVC5nu+Das+y2CpW10yqvf6/j5xbuUV3FxA3mBaIbM24CXODXjbgUznNb4Kg9XZOUxKAw== + dependencies: + "@typescript-eslint/experimental-utils" "2.10.0" + eslint-utils "^1.4.3" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@2.10.0": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.10.0.tgz#8db1656cdfd3d9dcbdbf360b8274dea76f0b2c2c" + integrity sha512-FZhWq6hWWZBP76aZ7bkrfzTMP31CCefVIImrwP3giPLcoXocmLTmr92NLZxuIcTL4GTEOE33jQMWy9PwelL+yQ== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.10.0" + eslint-scope "^5.0.0" + +"@typescript-eslint/parser@^2.3.1": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.10.0.tgz#24b2e48384ab6d5a6121e4c4faf8892c79657ad3" + integrity sha512-wQNiBokcP5ZsTuB+i4BlmVWq6o+oAhd8en2eSm/EE9m7BgZUIfEeYFd6z3S+T7bgNuloeiHA1/cevvbBDLr98g== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "2.10.0" + "@typescript-eslint/typescript-estree" "2.10.0" + eslint-visitor-keys "^1.1.0" + +"@typescript-eslint/typescript-estree@2.10.0": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.10.0.tgz#89cdabd5e8c774e9d590588cb42fb9afd14dcbd9" + integrity sha512-oOYnplddQNm/LGVkqbkAwx4TIBuuZ36cAQq9v3nFIU9FmhemHuVzAesMSXNQDdAzCa5bFgCrfD3JWhYVKlRN2g== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash.unescape "4.0.1" + semver "^6.3.0" + tsutils "^3.17.1" + JSONStream@^1.0.4: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -585,6 +641,11 @@ acorn-globals@^4.1.0: acorn "^6.0.1" acorn-walk "^6.0.1" +acorn-jsx@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" + integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== + acorn-walk@^6.0.1: version "6.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" @@ -600,12 +661,17 @@ acorn@^6.0.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== +acorn@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" + integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== + add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" integrity sha1-anmQQ3ynNtXhKI25K9MmbV9csqo= -ajv@^6.5.5: +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: version "6.10.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== @@ -620,6 +686,13 @@ ansi-escapes@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== +ansi-escapes@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" + integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== + dependencies: + type-fest "^0.8.1" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -635,6 +708,11 @@ ansi-regex@^4.0.0, ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -700,6 +778,14 @@ array-ify@^1.0.0: resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= +array-includes@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" + integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -982,7 +1068,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -991,6 +1077,11 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + chownr@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" @@ -1011,6 +1102,18 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -1303,7 +1406,7 @@ cosmiconfig@^5.2.0, cosmiconfig@^5.2.1: js-yaml "^3.13.1" parse-json "^4.0.0" -cross-spawn@^6.0.0: +cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -1380,7 +1483,7 @@ debug@^3.2.6: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1: +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -1469,6 +1572,20 @@ diff-sequences@^24.9.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + domexception@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" @@ -1496,6 +1613,11 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" @@ -1510,6 +1632,22 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +es-abstract@^1.12.0, es-abstract@^1.15.0, es-abstract@^1.7.0: + version "1.16.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.2.tgz#4e874331645e9925edef141e74fc4bd144669d34" + integrity sha512-jYo/J8XU2emLXl3OLwfwtuFfuF2w6DYPs+xy9ZfVyPkDcrauu6LYrw/q2TyCtrbc/KUdCiC5e9UajRhgNkVopA== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.7.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.1.0" + string.prototype.trimright "^2.1.0" + es-abstract@^1.5.1: version "1.14.2" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.14.2.tgz#7ce108fad83068c8783c3cdf62e504e084d8c497" @@ -1535,6 +1673,15 @@ es-to-primitive@^1.2.0: is-date-object "^1.0.1" is-symbol "^1.0.2" +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1552,6 +1699,104 @@ escodegen@^1.9.1: optionalDependencies: source-map "~0.6.1" +eslint-plugin-eslint-plugin@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-2.1.0.tgz#a7a00f15a886957d855feacaafee264f039e62d5" + integrity sha512-kT3A/ZJftt28gbl/Cv04qezb/NQ1dwYIbi8lyf806XMxkus7DvOVCLIfTXMrorp322Pnoez7+zabXH29tADIDg== + +eslint-plugin-react-hooks@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.3.0.tgz#53e073961f1f5ccf8dd19558036c1fac8c29d99a" + integrity sha512-gLKCa52G4ee7uXzdLiorca7JIQZPPXRAQDXV83J4bUEeUuc5pIEyZYAZ45Xnxe5IuupxEqHS+hUhSLIimK1EMw== + +eslint-plugin-react@^7.14.3: + version "7.17.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.17.0.tgz#a31b3e134b76046abe3cd278e7482bd35a1d12d7" + integrity sha512-ODB7yg6lxhBVMeiH1c7E95FLD4E/TwmFjltiU+ethv7KPdCwgiFuOZg9zNRHyufStTDLl/dEFqI2Q1VPmCd78A== + dependencies: + array-includes "^3.0.3" + doctrine "^2.1.0" + eslint-plugin-eslint-plugin "^2.1.0" + has "^1.0.3" + jsx-ast-utils "^2.2.3" + object.entries "^1.1.0" + object.fromentries "^2.0.1" + object.values "^1.1.0" + prop-types "^15.7.2" + resolve "^1.13.1" + +eslint-scope@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" + integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + +eslint@^6.5.0: + version "6.7.2" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1" + integrity sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.3" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" + integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== + dependencies: + acorn "^7.1.0" + acorn-jsx "^5.1.0" + eslint-visitor-keys "^1.1.0" + esprima@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -1562,7 +1807,21 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -estraverse@^4.2.0: +esquery@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== @@ -1640,6 +1899,15 @@ extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -1674,7 +1942,7 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= -fast-levenshtein@~2.0.4: +fast-levenshtein@~2.0.4, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= @@ -1686,6 +1954,20 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" +figures@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" + integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -1726,6 +2008,20 @@ find-up@^4.0.0: locate-path "^5.0.0" path-exists "^4.0.0" +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -1786,6 +2082,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -1890,6 +2191,13 @@ gitconfiglocal@^1.0.0: dependencies: ini "^1.3.2" +glob-parent@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + dependencies: + is-glob "^4.0.1" + glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: version "7.1.4" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" @@ -1902,6 +2210,18 @@ glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-dirs@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" @@ -1914,6 +2234,13 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +globals@^12.1.0: + version "12.3.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" + integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw== + dependencies: + type-fest "^0.8.1" + graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.2" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" @@ -1980,6 +2307,11 @@ has-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= +has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -2066,7 +2398,7 @@ husky@^3.0.5: run-node "^1.0.0" slash "^3.0.0" -iconv-lite@0.4.24, iconv-lite@^0.4.4: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -2080,6 +2412,11 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" @@ -2139,6 +2476,25 @@ ini@^1.3.2, ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== +inquirer@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.0.tgz#9e2b032dde77da1db5db804758b8fea3a970519a" + integrity sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ== + dependencies: + ansi-escapes "^4.2.1" + chalk "^2.4.2" + cli-cursor "^3.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^4.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + interpret@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" @@ -2241,6 +2597,11 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" @@ -2260,11 +2621,23 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-generator-fn@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -2289,6 +2662,11 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" @@ -2843,6 +3221,11 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -2877,6 +3260,14 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jsx-ast-utils@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz#8a9364e402448a3ce7f14d357738310d9248054f" + integrity sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA== + dependencies: + array-includes "^3.0.3" + object.assign "^4.1.0" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -2916,7 +3307,7 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@~0.3.0: +levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= @@ -3008,12 +3399,17 @@ lodash.templatesettings@^4.0.0: dependencies: lodash._reinterpolate "^3.0.0" +lodash.unescape@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" + integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= + lodash@4.17.14: version "4.17.14" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== -lodash@^4.14.14, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.2.1: +lodash@^4.14.14, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -3167,6 +3563,11 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "1.40.0" +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + minimatch@^3.0.0, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -3242,6 +3643,11 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + nan@^2.12.1: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" @@ -3414,7 +3820,12 @@ object-inspect@^1.6.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== -object-keys@^1.0.12, object-keys@^1.1.1: +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -3426,6 +3837,36 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.entries@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519" + integrity sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.12.0" + function-bind "^1.1.1" + has "^1.0.3" + +object.fromentries@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.1.tgz#050f077855c7af8ae6649f45c80b16ee2d31e704" + integrity sha512-PUQv8Hbg3j2QX0IQYv3iAGCbGcu4yY4KQ92/dhA4sFSixBmSmp13UpDLs6jGK8rBtbmhNNIK99LD2k293jpiGA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.15.0" + function-bind "^1.1.1" + has "^1.0.3" + object.getownpropertydescriptors@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" @@ -3441,6 +3882,16 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" +object.values@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" + integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.12.0" + function-bind "^1.1.1" + has "^1.0.3" + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -3448,6 +3899,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + opencollective-postinstall@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" @@ -3473,12 +3931,24 @@ optionator@^0.8.1: type-check "~0.3.2" wordwrap "~1.0.0" +optionator@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-tmpdir@^1.0.0: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= @@ -3743,7 +4213,7 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -progress@^2.0.3: +progress@^2.0.0, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -3756,7 +4226,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.3" -prop-types@^15.6.2: +prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -3969,6 +4439,16 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + +regexpp@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.0.0.tgz#dd63982ee3300e67b41c1956f850aa680d9d330e" + integrity sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g== + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -4096,11 +4576,33 @@ resolve@1.x, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2: dependencies: path-parse "^1.0.6" +resolve@^1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16" + integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w== + dependencies: + path-parse "^1.0.6" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -4113,11 +4615,25 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= + dependencies: + is-promise "^2.1.0" + run-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e" integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A== +rxjs@^6.4.0: + version "6.5.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" + integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== + dependencies: + tslib "^1.9.0" + safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" @@ -4183,7 +4699,7 @@ semver@6.2.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db" integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A== -semver@^6.0.0, semver@^6.2.0: +semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -4249,6 +4765,15 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -4432,7 +4957,16 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string.prototype.trimleft@^2.0.0: +string-width@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string.prototype.trimleft@^2.0.0, string.prototype.trimleft@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== @@ -4440,7 +4974,7 @@ string.prototype.trimleft@^2.0.0: define-properties "^1.1.3" function-bind "^1.1.1" -string.prototype.trimright@^2.0.0: +string.prototype.trimright@^2.0.0, string.prototype.trimright@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== @@ -4483,6 +5017,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -4512,6 +5053,11 @@ strip-indent@^2.0.0: resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= +strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -4536,6 +5082,16 @@ symbol-tree@^3.2.2: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + tar@^4: version "4.4.11" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.11.tgz#7ac09801445a3cf74445ed27499136b5240ffb73" @@ -4582,6 +5138,11 @@ text-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-2.0.0.tgz#43eabd1b495482fae4a2bf65e5f56c29f69220f6" integrity sha512-F91ZqLgvi1E0PdvmxMgp+gcf6q8fMH7mhdwWfzXnl1k+GbpQDmi8l7DzLC5JTASKbwpY3TfxajAUzAXcv2NmsQ== +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + throat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" @@ -4602,11 +5163,18 @@ through2@^3.0.0: dependencies: readable-stream "2 || 3" -through@2, "through@>=2.2.7 <3": +through@2, "through@>=2.2.7 <3", through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -4701,6 +5269,18 @@ ts-jest@^24.1.0: semver "^5.5" yargs-parser "10.x" +tslib@^1.8.1, tslib@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + dependencies: + tslib "^1.8.1" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -4725,6 +5305,11 @@ type-fest@^0.6.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + typedoc-default-themes@^0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.7.2.tgz#1e9896f920b58e6da0bba9d7e643738d02405a5a" @@ -4833,6 +5418,11 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== +v8-compile-cache@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -4918,6 +5508,11 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" +word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" @@ -4951,6 +5546,13 @@ write-file-atomic@2.4.1: imurmurhash "^0.1.4" signal-exit "^3.0.2" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + ws@^5.2.0: version "5.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" From 039e3f562a305df11bdebf4230bfbd46ef27d60f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Caetano?= Date: Tue, 1 Oct 2019 15:38:53 -0300 Subject: [PATCH 2/4] chore(ESLint): configure project to work as a monorepo --- eslint-plugin/.babelrc | 3 - eslint-plugin/.gitignore | 1 - .../ESLintRuleExhaustiveDeps-test.js | 179 +- eslint-plugin/{src => lib}/index.js | 5 +- .../{src => lib}/rules/ExaustiveDeps.js | 366 ++- eslint-plugin/package.json | 6 +- eslint-plugin/yarn.lock | 2746 +---------------- jest.config.js | 2 +- package.json | 4 +- src/__tests__/useDidUnmount.ts | 16 +- src/__tests__/useLazyRef.ts | 8 +- src/__tests__/usePromisedState.ts | 18 +- src/__tests__/useWorkerState.ts | 4 +- src/index.tsx | 84 +- yarn.lock | 61 +- 15 files changed, 450 insertions(+), 3053 deletions(-) delete mode 100644 eslint-plugin/.babelrc delete mode 100644 eslint-plugin/.gitignore rename eslint-plugin/{src => lib}/__tests__/ESLintRuleExhaustiveDeps-test.js (96%) rename eslint-plugin/{src => lib}/index.js (66%) rename eslint-plugin/{src => lib}/rules/ExaustiveDeps.js (88%) diff --git a/eslint-plugin/.babelrc b/eslint-plugin/.babelrc deleted file mode 100644 index 8aa924d..0000000 --- a/eslint-plugin/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/preset-env"] -} \ No newline at end of file diff --git a/eslint-plugin/.gitignore b/eslint-plugin/.gitignore deleted file mode 100644 index f1ff06d..0000000 --- a/eslint-plugin/.gitignore +++ /dev/null @@ -1 +0,0 @@ -lib/ \ No newline at end of file diff --git a/eslint-plugin/src/__tests__/ESLintRuleExhaustiveDeps-test.js b/eslint-plugin/lib/__tests__/ESLintRuleExhaustiveDeps-test.js similarity index 96% rename from eslint-plugin/src/__tests__/ESLintRuleExhaustiveDeps-test.js rename to eslint-plugin/lib/__tests__/ESLintRuleExhaustiveDeps-test.js index cd50089..be2e969 100644 --- a/eslint-plugin/src/__tests__/ESLintRuleExhaustiveDeps-test.js +++ b/eslint-plugin/lib/__tests__/ESLintRuleExhaustiveDeps-test.js @@ -6,13 +6,13 @@ * * Original Source: https://github.com/facebook/react/blob/9e64bf18e11828d6b4c0363bff5ed2eca1ccd838/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js */ - 'use strict'; const ESLintTester = require('eslint').RuleTester; -const ReactHooksESLintPlugin = require('@react-hook-utilities/eslint-plugin'); -const ReactHooksESLintRule = ReactHooksESLintPlugin.rules['exhaustive-deps']; +const ReactHooksESLintPlugin = require('..'); + +const ReactHooksESLintRule = ReactHooksESLintPlugin.rules['exhaustive-deps']; ESLintTester.setDefaultConfig({ parser: require.resolve('babel-eslint'), parserOptions: { @@ -175,7 +175,7 @@ const tests = { const local1 = {}; { const local2 = {}; - useWorkerLoad(async () => { + useWorkerState(async () => { console.log(local1); console.log(local2); }, [local1, local2]); @@ -189,7 +189,7 @@ const tests = { const local1 = {}; function MyNestedComponent() { const local2 = {}; - useWorkerLoad(async () => { + useWorkerState(async () => { console.log(local1); console.log(local2); }, [local2]); @@ -495,8 +495,8 @@ const tests = { const [state4, dispatch2] = React.useReducer(); const [state5, maybeSetState] = useFunnyState(); const [state6, maybeDispatch] = useFunnyReducer(); - const mySetState = useWorkerLoad(async () => {}, []); - let myDispatch = useWorkerLoad(async () => {}, []); + const mySetState = useWorkerState(async () => {}, []); + let myDispatch = useWorkerState(async () => {}, []); useAsyncEffect(async () => { // Known to be static @@ -552,8 +552,8 @@ const tests = { const [state5, maybeSetState] = useFunnyState(); const [state6, maybeDispatch] = useFunnyReducer(); - const mySetState = useWorkerLoad(async () => {}, []); - let myDispatch = useWorkerLoad(async () => {}, []); + const mySetState = useWorkerState(async () => {}, []); + let myDispatch = useWorkerState(async () => {}, []); useAsyncEffect(async () => { // Known to be static @@ -715,7 +715,7 @@ const tests = { // Valid because it's not an effect. code: ` function useMyThing(myRef) { - useWorkerLoad(async () => { + useWorkerState(async () => { const handleMouse = () => {}; myRef.current.addEventListener('mousemove', handleMouse); myRef.current.addEventListener('mousein', handleMouse); @@ -856,10 +856,10 @@ const tests = { // Don't warn for this either. code: ` function MyComponent(props) { - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props.foo.bar.baz); }, [props]); - const fn2 = useWorkerLoad(async () => { + const fn2 = useWorkerState(async () => { console.log(props.foo.bar.baz); }, [props.foo]); const fn3 = useEffectUpdate(() => { @@ -1204,7 +1204,7 @@ const tests = { { code: ` function Example() { - const foo = useWorkerLoad(async () => { + const foo = useWorkerState(async () => { foo(); }, []); } @@ -1213,7 +1213,7 @@ const tests = { { code: ` function Example({ prop }) { - const foo = useWorkerLoad(async () => { + const foo = useWorkerState(async () => { if (prop) { foo(); } @@ -1232,8 +1232,7 @@ const tests = { }); } `, - }, - // Ignore Generic Type Variables for arrow functions + }, // Ignore Generic Type Variables for arrow functions { code: ` function Example({ prop }) { @@ -1242,8 +1241,7 @@ const tests = { }, [prop]); } `, - }, - // Ignore arguments keyword for arrow functions. + }, // Ignore arguments keyword for arrow functions. { code: ` function Example() { @@ -1739,7 +1737,7 @@ const tests = { const local1 = {}; function MyNestedComponent() { const local2 = {}; - useWorkerLoad(async () => { + useWorkerState(async () => { console.log(local1); console.log(local2); }, [local1]); @@ -1751,7 +1749,7 @@ const tests = { const local1 = {}; function MyNestedComponent() { const local2 = {}; - useWorkerLoad(async () => { + useWorkerState(async () => { console.log(local1); console.log(local2); }, [local2]); @@ -1759,7 +1757,7 @@ const tests = { } `, errors: [ - "React Hook useWorkerLoad has a missing dependency: 'local2'. " + + "React Hook useWorkerState has a missing dependency: 'local2'. " + 'Either include it or remove the dependency array. ' + "Outer scope values like 'local1' aren't valid dependencies " + "because mutating them doesn't re-render the component.", @@ -1834,16 +1832,16 @@ const tests = { { code: ` function MyComponent() { - useWorkerLoad(async () => {}, [window]); + useWorkerState(async () => {}, [window]); } `, output: ` function MyComponent() { - useWorkerLoad(async () => {}, []); + useWorkerState(async () => {}, []); } `, errors: [ - "React Hook useWorkerLoad has an unnecessary dependency: 'window'. " + + "React Hook useWorkerState has an unnecessary dependency: 'window'. " + 'Either exclude it or remove the dependency array. ' + "Outer scope values like 'window' aren't valid dependencies " + "because mutating them doesn't re-render the component.", @@ -1870,22 +1868,22 @@ const tests = { ], }, { - // It is not valid for useWorkerLoad to specify extraneous deps + // It is not valid for useWorkerState to specify extraneous deps // because it doesn't serve as a side effect trigger unlike useAsyncEffect. code: ` function MyComponent(props) { let local = props.foo; - useWorkerLoad(async () => {}, [local]); + useWorkerState(async () => {}, [local]); } `, output: ` function MyComponent(props) { let local = props.foo; - useWorkerLoad(async () => {}, []); + useWorkerState(async () => {}, []); } `, errors: [ - "React Hook useWorkerLoad has an unnecessary dependency: 'local'. " + + "React Hook useWorkerState has an unnecessary dependency: 'local'. " + 'Either exclude it or remove the dependency array.', ], }, @@ -2265,7 +2263,7 @@ const tests = { ], }, { - // It is not valid for useWorkerLoad to specify extraneous deps + // It is not valid for useWorkerState to specify extraneous deps // because it doesn't serve as a side effect trigger unlike useAsyncEffect. // However, we generally allow specifying *broader* deps as escape hatch. // So while [props, props.foo] is unnecessary, 'props' wins here as the @@ -2273,7 +2271,7 @@ const tests = { code: ` function MyComponent(props) { const local = {}; - useWorkerLoad(async () => { + useWorkerState(async () => { console.log(props.foo); console.log(props.bar); }, [props, props.foo]); @@ -2282,14 +2280,14 @@ const tests = { output: ` function MyComponent(props) { const local = {}; - useWorkerLoad(async () => { + useWorkerState(async () => { console.log(props.foo); console.log(props.bar); }, [props]); } `, errors: [ - "React Hook useWorkerLoad has an unnecessary dependency: 'props.foo'. " + + "React Hook useWorkerState has an unnecessary dependency: 'props.foo'. " + 'Either exclude it or remove the dependency array.', ], }, @@ -2298,7 +2296,7 @@ const tests = { code: ` function MyComponent(props) { const local = {}; - useWorkerLoad(async () => { + useWorkerState(async () => { console.log(props.foo); console.log(props.bar); }, []); @@ -2307,14 +2305,14 @@ const tests = { output: ` function MyComponent(props) { const local = {}; - useWorkerLoad(async () => { + useWorkerState(async () => { console.log(props.foo); console.log(props.bar); }, [props.bar, props.foo]); } `, errors: [ - "React Hook useWorkerLoad has missing dependencies: 'props.bar' and 'props.foo'. " + + "React Hook useWorkerState has missing dependencies: 'props.bar' and 'props.foo'. " + 'Either include them or remove the dependency array.', ], }, @@ -2535,7 +2533,7 @@ const tests = { code: ` function MyComponent() { const local = {id: 42}; - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(local); }, [local.id]); } @@ -2543,13 +2541,13 @@ const tests = { output: ` function MyComponent() { const local = {id: 42}; - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(local); }, [local]); } `, errors: [ - "React Hook useWorkerLoad has a missing dependency: 'local'. " + + "React Hook useWorkerState has a missing dependency: 'local'. " + 'Either include it or remove the dependency array.', ], }, @@ -2559,7 +2557,7 @@ const tests = { code: ` function MyComponent() { const local = {id: 42}; - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(local); }, [local.id, local]); } @@ -2567,33 +2565,33 @@ const tests = { output: ` function MyComponent() { const local = {id: 42}; - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(local); }, [local]); } `, errors: [ - "React Hook useWorkerLoad has an unnecessary dependency: 'local.id'. " + + "React Hook useWorkerState has an unnecessary dependency: 'local.id'. " + 'Either exclude it or remove the dependency array.', ], }, { code: ` function MyComponent(props) { - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props.foo.bar.baz); }, []); } `, output: ` function MyComponent(props) { - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props.foo.bar.baz); }, [props.foo.bar.baz]); } `, errors: [ - "React Hook useWorkerLoad has a missing dependency: 'props.foo.bar.baz'. " + + "React Hook useWorkerState has a missing dependency: 'props.foo.bar.baz'. " + 'Either include it or remove the dependency array.', ], }, @@ -2601,7 +2599,7 @@ const tests = { code: ` function MyComponent(props) { let color = {} - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props.foo.bar.baz); console.log(color); }, [props.foo, props.foo.bar.baz]); @@ -2610,14 +2608,14 @@ const tests = { output: ` function MyComponent(props) { let color = {} - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props.foo.bar.baz); console.log(color); }, [color, props.foo.bar.baz]); } `, errors: [ - "React Hook useWorkerLoad has a missing dependency: 'color'. " + + "React Hook useWorkerState has a missing dependency: 'color'. " + 'Either include it or remove the dependency array.', ], }, @@ -2629,27 +2627,27 @@ const tests = { // TODO: maybe consider suggesting a narrower one by default in these cases. code: ` function MyComponent(props) { - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props.foo.bar.baz); }, [props.foo.bar.baz, props.foo]); } `, output: ` function MyComponent(props) { - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props.foo.bar.baz); }, [props.foo]); } `, errors: [ - "React Hook useWorkerLoad has an unnecessary dependency: 'props.foo.bar.baz'. " + + "React Hook useWorkerState has an unnecessary dependency: 'props.foo.bar.baz'. " + 'Either exclude it or remove the dependency array.', ], }, { code: ` function MyComponent(props) { - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props.foo.bar.baz); console.log(props.foo.fizz.bizz); }, []); @@ -2657,14 +2655,14 @@ const tests = { `, output: ` function MyComponent(props) { - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props.foo.bar.baz); console.log(props.foo.fizz.bizz); }, [props.foo.bar.baz, props.foo.fizz.bizz]); } `, errors: [ - "React Hook useWorkerLoad has missing dependencies: 'props.foo.bar.baz' and 'props.foo.fizz.bizz'. " + + "React Hook useWorkerState has missing dependencies: 'props.foo.bar.baz' and 'props.foo.fizz.bizz'. " + 'Either include them or remove the dependency array.', ], }, @@ -2677,27 +2675,27 @@ const tests = { // This is why we end up with just 'props.foo.bar', and not them both. code: ` function MyComponent(props) { - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props.foo.bar); }, [props.foo.bar.baz]); } `, output: ` function MyComponent(props) { - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props.foo.bar); }, [props.foo.bar]); } `, errors: [ - "React Hook useWorkerLoad has a missing dependency: 'props.foo.bar'. " + + "React Hook useWorkerState has a missing dependency: 'props.foo.bar'. " + 'Either include it or remove the dependency array.', ], }, { code: ` function MyComponent(props) { - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props); console.log(props.hello); }, [props.foo.bar.baz]); @@ -2705,14 +2703,14 @@ const tests = { `, output: ` function MyComponent(props) { - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { console.log(props); console.log(props.hello); }, [props]); } `, errors: [ - "React Hook useWorkerLoad has a missing dependency: 'props'. " + + "React Hook useWorkerState has a missing dependency: 'props'. " + 'Either include it or remove the dependency array.', ], }, @@ -2784,7 +2782,7 @@ const tests = { code: ` function MyComponent() { const local1 = {}; - useWorkerLoad(async () => { + useWorkerState(async () => { const local1 = {}; console.log(local1); }, [local1]); @@ -2793,14 +2791,14 @@ const tests = { output: ` function MyComponent() { const local1 = {}; - useWorkerLoad(async () => { + useWorkerState(async () => { const local1 = {}; console.log(local1); }, []); } `, errors: [ - "React Hook useWorkerLoad has an unnecessary dependency: 'local1'. " + + "React Hook useWorkerState has an unnecessary dependency: 'local1'. " + 'Either exclude it or remove the dependency array.', ], }, @@ -2808,17 +2806,17 @@ const tests = { code: ` function MyComponent() { const local1 = {}; - useWorkerLoad(async () => {}, [local1]); + useWorkerState(async () => {}, [local1]); } `, output: ` function MyComponent() { const local1 = {}; - useWorkerLoad(async () => {}, []); + useWorkerState(async () => {}, []); } `, errors: [ - "React Hook useWorkerLoad has an unnecessary dependency: 'local1'. " + + "React Hook useWorkerState has an unnecessary dependency: 'local1'. " + 'Either exclude it or remove the dependency array.', ], }, @@ -3057,7 +3055,7 @@ const tests = { useAsyncEffect(async () => { console.log(props.foo); }, []); - useWorkerLoad(async () => { + useWorkerState(async () => { console.log(props.foo); }, []); useEffectUpdate(() => { @@ -3066,7 +3064,7 @@ const tests = { React.useAsyncEffect(async () => { console.log(props.foo); }, []); - React.useWorkerLoad(async () => { + React.useWorkerState(async () => { console.log(props.foo); }, []); React.useEffectUpdate(() => { @@ -3082,7 +3080,7 @@ const tests = { useAsyncEffect(async () => { console.log(props.foo); }, [props.foo]); - useWorkerLoad(async () => { + useWorkerState(async () => { console.log(props.foo); }, [props.foo]); useEffectUpdate(() => { @@ -3091,7 +3089,7 @@ const tests = { React.useAsyncEffect(async () => { console.log(props.foo); }, [props.foo]); - React.useWorkerLoad(async () => { + React.useWorkerState(async () => { console.log(props.foo); }, [props.foo]); React.useEffectUpdate(() => { @@ -3105,13 +3103,13 @@ const tests = { errors: [ "React Hook useAsyncEffect has a missing dependency: 'props.foo'. " + 'Either include it or remove the dependency array.', - "React Hook useWorkerLoad has a missing dependency: 'props.foo'. " + + "React Hook useWorkerState has a missing dependency: 'props.foo'. " + 'Either include it or remove the dependency array.', "React Hook useEffectUpdate has a missing dependency: 'props.foo'. " + 'Either include it or remove the dependency array.', "React Hook React.useAsyncEffect has a missing dependency: 'props.foo'. " + 'Either include it or remove the dependency array.', - "React Hook React.useWorkerLoad has a missing dependency: 'props.foo'. " + + "React Hook React.useWorkerState has a missing dependency: 'props.foo'. " + 'Either include it or remove the dependency array.', "React Hook React.useEffectUpdate has a missing dependency: 'props.foo'. " + 'Either include it or remove the dependency array.', @@ -3373,7 +3371,7 @@ const tests = { function MyComponent({ activeTab, initY }) { const ref1 = useRef(); const ref2 = useRef(); - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { ref1.current.scrollTop = initY; ref2.current.scrollTop = initY; }, [ref1.current, ref2.current, activeTab, initY]); @@ -3383,14 +3381,14 @@ const tests = { function MyComponent({ activeTab, initY }) { const ref1 = useRef(); const ref2 = useRef(); - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { ref1.current.scrollTop = initY; ref2.current.scrollTop = initY; }, [initY]); } `, errors: [ - "React Hook useWorkerLoad has unnecessary dependencies: 'activeTab', 'ref1.current', and 'ref2.current'. " + + "React Hook useWorkerState has unnecessary dependencies: 'activeTab', 'ref1.current', and 'ref2.current'. " + 'Either exclude them or remove the dependency array. ' + "Mutable values like 'ref1.current' aren't valid dependencies " + "because mutating them doesn't re-render the component.", @@ -4150,7 +4148,7 @@ const tests = { let x = props.foo; { let y = props.bar; - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { // nothing }, [MutableStore.hello.world, props.foo, x, y, z, global.stuff]); } @@ -4164,14 +4162,14 @@ const tests = { let x = props.foo; { let y = props.bar; - const fn = useWorkerLoad(async () => { + const fn = useWorkerState(async () => { // nothing }, []); } } `, errors: [ - 'React Hook useWorkerLoad has unnecessary dependencies: ' + + 'React Hook useWorkerState has unnecessary dependencies: ' + "'MutableStore.hello.world', 'global.stuff', 'props.foo', 'x', 'y', and 'z'. " + 'Either exclude them or remove the dependency array. ' + "Outer scope values like 'MutableStore.hello.world' aren't valid dependencies " + @@ -4982,53 +4980,52 @@ const tests = { { code: ` function Example() { - const foo = useWorkerLoad(async () => { + const foo = useWorkerState(async () => { foo(); }, [foo]); } `, output: ` function Example() { - const foo = useWorkerLoad(async () => { + const foo = useWorkerState(async () => { foo(); }, []); } `, errors: [ - "React Hook useWorkerLoad has an unnecessary dependency: 'foo'. " + + "React Hook useWorkerState has an unnecessary dependency: 'foo'. " + 'Either exclude it or remove the dependency array.', ], }, { code: ` function Example({ prop }) { - const foo = useWorkerLoad(async () => { + const foo = useWorkerState(async () => { prop.hello(foo); }, [foo]); - const bar = useWorkerLoad(async () => { + const bar = useWorkerState(async () => { foo(); }, [foo]); } `, output: ` function Example({ prop }) { - const foo = useWorkerLoad(async () => { + const foo = useWorkerState(async () => { prop.hello(foo); }, [prop]); - const bar = useWorkerLoad(async () => { + const bar = useWorkerState(async () => { foo(); }, [foo]); } `, errors: [ - "React Hook useWorkerLoad has a missing dependency: 'prop'. " + + "React Hook useWorkerState has a missing dependency: 'prop'. " + 'Either include it or remove the dependency array.', ], }, ], -}; +}; // For easier local testing -// For easier local testing if (!process.env.CI) { let only = []; let skipped = []; @@ -5037,23 +5034,27 @@ if (!process.env.CI) { delete t.skip; skipped.push(t); } + if (t.only) { delete t.only; only.push(t); - } - // if (!t.options) { + } // if (!t.options) { // t.options = [{ additionalHooks: 'useAsyncLayoutEffect' }]; // } }); + const predicate = t => { if (only.length > 0) { return only.indexOf(t) !== -1; } + if (skipped.length > 0) { return skipped.indexOf(t) === -1; } + return true; }; + tests.valid = tests.valid.filter(predicate); tests.invalid = tests.invalid.filter(predicate); } diff --git a/eslint-plugin/src/index.js b/eslint-plugin/lib/index.js similarity index 66% rename from eslint-plugin/src/index.js rename to eslint-plugin/lib/index.js index 3bbc31c..196d98c 100644 --- a/eslint-plugin/src/index.js +++ b/eslint-plugin/lib/index.js @@ -4,8 +4,7 @@ */ 'use strict'; -import ExhaustiveDeps from './rules/ExaustiveDeps'; - -export const rules = { +const ExhaustiveDeps = require('./rules/ExaustiveDeps'); +exports.rules = { 'exhaustive-deps': ExhaustiveDeps, }; diff --git a/eslint-plugin/src/rules/ExaustiveDeps.js b/eslint-plugin/lib/rules/ExaustiveDeps.js similarity index 88% rename from eslint-plugin/src/rules/ExaustiveDeps.js rename to eslint-plugin/lib/rules/ExaustiveDeps.js index 01fcde9..97036db 100644 --- a/eslint-plugin/src/rules/ExaustiveDeps.js +++ b/eslint-plugin/lib/rules/ExaustiveDeps.js @@ -7,11 +7,9 @@ * Original source: https://github.com/facebook/react/blob/9e64bf18e11828d6b4c0363bff5ed2eca1ccd838/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js */ -/* eslint-disable no-for-of-loops/no-for-of-loops */ - 'use strict'; -export default { +module.exports = { meta: { fixable: 'code', schema: [ @@ -21,12 +19,14 @@ export default { }, ], }, + create(context) { // Should be shared between visitors. let setStateCallSites = new WeakMap(); let stateVariables = new WeakSet(); let staticKnownValueCache = new WeakMap(); let functionWithoutCapturedValueCache = new WeakMap(); + function memoizeWithWeakMap(fn, map) { return function(arg) { if (map.has(arg)) { @@ -34,6 +34,7 @@ export default { // console.log(arg.name) return map.get(arg); } + const result = fn(arg); map.set(arg, result); return result; @@ -44,10 +45,10 @@ export default { FunctionExpression: visitFunctionExpression, ArrowFunctionExpression: visitFunctionExpression, }; - /** * Visitor for both function expressions and arrow function expressions. */ + function visitFunctionExpression(node) { // We only want to lint nodes which are reactive hook callbacks. if ( @@ -59,25 +60,21 @@ export default { } const callbackIndex = getReactiveHookCallbackIndex(node.parent.callee); + if (node.parent.arguments[callbackIndex] !== node) { return; - } + } // Get the reactive hook node. - // Get the reactive hook node. const reactiveHook = node.parent.callee; const reactiveHookName = getNodeWithoutReactNamespace(reactiveHook).name; - const isEffect = reactiveHookName.endsWith('Effect'); - - // Get the declared dependencies for this reactive hook. If there is no + const isEffect = reactiveHookName.endsWith('Effect'); // Get the declared dependencies for this reactive hook. If there is no // second argument then the reactive callback will re-run on every render. // So no need to check for dependency inclusion. - const depsIndex = callbackIndex + 1; - const declaredDependenciesNode = node.parent.arguments[depsIndex]; - // Get the current scope. - const scope = context.getScope(); + const depsIndex = callbackIndex + 1; + const declaredDependenciesNode = node.parent.arguments[depsIndex]; // Get the current scope. - // Find all our "pure scopes". On every re-render of a component these + const scope = context.getScope(); // Find all our "pure scopes". On every re-render of a component these // pure scopes may have changes to the variables declared within. So all // variables used in our reactive hook callback but declared in a pure // scope need to be listed as dependencies of our reactive hook callback. @@ -85,29 +82,31 @@ export default { // According to the rules of React you can't read a mutable value in pure // scope. We can't enforce this in a lint so we trust that all variables // declared outside of pure scope are indeed frozen. + const pureScopes = new Set(); let componentScope = null; { let currentScope = scope.upper; + while (currentScope) { pureScopes.add(currentScope); + if (currentScope.type === 'function') { break; } + currentScope = currentScope.upper; - } - // If there is no parent function scope then there are no pure scopes. + } // If there is no parent function scope then there are no pure scopes. // The ones we've collected so far are incorrect. So don't continue with // the lint. + if (!currentScope) { return; } - componentScope = currentScope; - } - // Next we'll define a few helpers that helps us + componentScope = currentScope; + } // Next we'll define a few helpers that helps us // tell if some values don't have to be declared as deps. - // Some are known to be static based on Hook calls. // const [state, setState] = useState() / React.useState() // ^^^ true for this reference @@ -116,35 +115,43 @@ export default { // const ref = useRef() // ^^^ true for this reference // False for everything else. + function isStaticKnownHookValue(resolved) { if (!Array.isArray(resolved.defs)) { return false; } + const def = resolved.defs[0]; + if (def == null) { return false; - } - // Look for `let stuff = ...` + } // Look for `let stuff = ...` + if (def.node.type !== 'VariableDeclarator') { return false; } + const init = def.node.init; + if (init == null) { return false; - } - // Detect primitive constants + } // Detect primitive constants // const foo = 42 + let declaration = def.node.parent; + if (declaration == null) { // This might happen if variable is declared after the callback. // In that case ESLint won't set up .parent refs. // So we'll set them up manually. fastFindReferenceWithParent(componentScope.block, def.node.id); declaration = def.node.parent; + if (declaration == null) { return false; } } + if ( declaration.kind === 'const' && init.type === 'Literal' && @@ -154,14 +161,15 @@ export default { ) { // Definitely static return true; - } - // Detect known Hook calls + } // Detect known Hook calls // const [_, setState] = useState() + if (init.type !== 'CallExpression') { return false; } - let callee = init.callee; - // Step into `= React.something` initializer. + + let callee = init.callee; // Step into `= React.something` initializer. + if ( callee.type === 'MemberExpression' && callee.object.name === 'React' && @@ -170,9 +178,11 @@ export default { ) { callee = callee.property; } + if (callee.type !== 'Identifier') { return false; } + const id = def.node.id; const { name } = callee; @@ -193,57 +203,62 @@ export default { if (id.elements[1] === resolved.identifiers[0]) { if (name === 'useState') { const references = resolved.references; + for (let i = 0; i < references.length; i++) { setStateCallSites.set( references[i].identifier, id.elements[0], ); } - } - // Setter is static. + } // Setter is static. + return true; } else if (id.elements[0] === resolved.identifiers[0]) { if (name === 'useState') { const references = resolved.references; + for (let i = 0; i < references.length; i++) { stateVariables.add(references[i].identifier); } - } - // State variable itself is dynamic. + } // State variable itself is dynamic. + return false; } } - } - // By default assume it's dynamic. + } // By default assume it's dynamic. + return false; - } + } // Some are just functions that don't reference anything dynamic. - // Some are just functions that don't reference anything dynamic. function isFunctionWithoutCapturedValues(resolved) { if (!Array.isArray(resolved.defs)) { return false; } + const def = resolved.defs[0]; + if (def == null) { return false; } + if (def.node == null || def.node.id == null) { return false; - } - // Search the direct component subscopes for + } // Search the direct component subscopes for // top-level function definitions matching this reference. + const fnNode = def.node; let childScopes = componentScope.childScopes; let fnScope = null; let i; + for (i = 0; i < childScopes.length; i++) { let childScope = childScopes[i]; let childScopeBlock = childScope.block; + if ( // function handleChange() {} (fnNode.type === 'FunctionDeclaration' && - childScopeBlock === fnNode) || - // const handleChange = () => {} + childScopeBlock === fnNode) || // const handleChange = () => {} // const handleChange = function() {} (fnNode.type === 'VariableDeclarator' && childScopeBlock.parent === fnNode) @@ -253,31 +268,32 @@ export default { break; } } + if (fnScope == null) { return false; - } - // Does this function capture any values + } // Does this function capture any values // that are in pure scopes (aka render)? + for (i = 0; i < fnScope.through.length; i++) { const ref = fnScope.through[i]; + if (ref.resolved == null) { continue; } + if ( - pureScopes.has(ref.resolved.scope) && - // Static values are fine though, + pureScopes.has(ref.resolved.scope) && // Static values are fine though, // although we won't check functions deeper. !memoizedIsStaticKnownHookValue(ref.resolved) ) { return false; } - } - // If we got here, this function doesn't capture anything + } // If we got here, this function doesn't capture anything // from render--or everything it captures is known static. + return true; - } + } // Remember such values. Avoid re-running extra checks on them. - // Remember such values. Avoid re-running extra checks on them. const memoizedIsStaticKnownHookValue = memoizeWithWeakMap( isStaticKnownHookValue, staticKnownValueCache, @@ -285,30 +301,30 @@ export default { const memoizedIsFunctionWithoutCapturedValues = memoizeWithWeakMap( isFunctionWithoutCapturedValues, functionWithoutCapturedValueCache, - ); - - // These are usually mistaken. Collect them. - const currentRefsInEffectCleanup = new Map(); + ); // These are usually mistaken. Collect them. - // Is this reference inside a cleanup function for this effect node? + const currentRefsInEffectCleanup = new Map(); // Is this reference inside a cleanup function for this effect node? // We can check by traversing scopes upwards from the reference, and checking // if the last "return () => " we encounter is located directly inside the effect. + function isInsideEffectCleanup(reference) { let curScope = reference.from; let isInReturnedFunction = false; + while (curScope.block !== node) { if (curScope.type === 'function') { isInReturnedFunction = curScope.block.parent != null && curScope.block.parent.type === 'ReturnStatement'; } + curScope = curScope.upper; } - return isInReturnedFunction; - } - // Get dependencies from all our resolved references in pure scopes. + return isInReturnedFunction; + } // Get dependencies from all our resolved references in pure scopes. // Key is dependency string, value is whether it's static. + const dependencies = new Map(); gatherDependenciesRecursively(scope); @@ -319,30 +335,27 @@ export default { if (!reference.resolved) { continue; } + if (!pureScopes.has(reference.resolved.scope)) { continue; - } - - // Narrow the scope of a dependency if it is, say, a member expression. + } // Narrow the scope of a dependency if it is, say, a member expression. // Then normalize the narrowed dependency. + const referenceNode = fastFindReferenceWithParent( node, reference.identifier, ); const dependencyNode = getDependency(referenceNode); - const dependency = toPropertyAccessString(dependencyNode); + const dependency = toPropertyAccessString(dependencyNode); // Accessing ref.current inside effect cleanup is bad. - // Accessing ref.current inside effect cleanup is bad. if ( // We're in an effect... - isEffect && - // ... and this look like accessing .current... + isEffect && // ... and this look like accessing .current... dependencyNode.type === 'Identifier' && dependencyNode.parent.type === 'MemberExpression' && !dependencyNode.parent.computed && dependencyNode.parent.property.type === 'Identifier' && - dependencyNode.parent.property.name === 'current' && - // ...in a cleanup function or below... + dependencyNode.parent.property.name === 'current' && // ...in a cleanup function or below... isInsideEffectCleanup(reference) ) { currentRefsInEffectCleanup.set(dependency, { @@ -355,20 +368,17 @@ export default { if (def == null) { continue; - } + } // Ignore references to the function itself as it's not defined yet. - // Ignore references to the function itself as it's not defined yet. if (def.node != null && def.node.init === node.parent) { continue; - } + } // Ignore Flow type parameters - // Ignore Flow type parameters if (def.type === 'TypeParameter') { continue; - } - - // Add the dependency to a map so we can make sure it is referenced + } // Add the dependency to a map so we can make sure it is referenced // again in our dependencies array. Remember whether it's static. + if (!dependencies.has(dependency)) { const resolved = reference.resolved; const isStatic = @@ -382,40 +392,41 @@ export default { dependencies.get(dependency).references.push(reference); } } + for (const childScope of currentScope.childScopes) { gatherDependenciesRecursively(childScope); } - } + } // Warn about accessing .current in cleanup effects. - // Warn about accessing .current in cleanup effects. currentRefsInEffectCleanup.forEach( ({ reference, dependencyNode }, dependency) => { - const references = reference.resolved.references; - // Is React managing this ref or us? + const references = reference.resolved.references; // Is React managing this ref or us? // Let's see if we can find a .current assignment. + let foundCurrentAssignment = false; + for (let i = 0; i < references.length; i++) { const { identifier } = references[i]; const { parent } = identifier; + if ( - parent != null && - // ref.current + parent != null && // ref.current parent.type === 'MemberExpression' && !parent.computed && parent.property.type === 'Identifier' && - parent.property.name === 'current' && - // ref.current = + parent.property.name === 'current' && // ref.current = parent.parent.type === 'AssignmentExpression' && parent.parent.left === parent ) { foundCurrentAssignment = true; break; } - } - // We only want to warn about React-managed refs. + } // We only want to warn about React-managed refs. + if (foundCurrentAssignment) { return; } + context.report({ node: dependencyNode.parent.property, message: @@ -426,15 +437,16 @@ export default { `use that variable in the cleanup function.`, }); }, - ); - - // Warn about assigning to variables in the outer scope. + ); // Warn about assigning to variables in the outer scope. // Those are usually bugs. + let staleAssignments = new Set(); + function reportStaleAssignment(writeExpr, key) { if (staleAssignments.has(key)) { return; } + staleAssignments.add(key); context.report({ node: writeExpr, @@ -446,14 +458,14 @@ export default { `Otherwise, you can move this variable directly inside ` + `${context.getSource(reactiveHook)}.`, }); - } + } // Remember which deps are optional and report bad usage first. - // Remember which deps are optional and report bad usage first. const optionalDependencies = new Set(); dependencies.forEach(({ isStatic, references }, key) => { if (isStatic) { optionalDependencies.add(key); } + references.forEach(reference => { if (reference.writeExpr) { reportStaleAssignment(reference.writeExpr, key); @@ -474,6 +486,7 @@ export default { if (setStateInsideEffectWithoutDeps) { return; } + references.forEach(reference => { if (setStateInsideEffectWithoutDeps) { return; @@ -481,21 +494,26 @@ export default { const id = reference.identifier; const isSetState = setStateCallSites.has(id); + if (!isSetState) { return; } let fnScope = reference.from; + while (fnScope.type !== 'function') { fnScope = fnScope.upper; } + const isDirectlyInsideEffect = fnScope.block === node; + if (isDirectlyInsideEffect) { // TODO: we could potentially ignore early returns. setStateInsideEffectWithoutDeps = key; } }); }); + if (setStateInsideEffectWithoutDeps) { let { suggestedDependencies } = collectRecommendations({ dependencies, @@ -512,6 +530,7 @@ export default { `To fix this, pass [` + suggestedDependencies.join(', ') + `] as a second argument to the ${reactiveHookName} Hook.`, + fix(fixer) { return fixer.insertTextAfter( node, @@ -520,11 +539,13 @@ export default { }, }); } + return; } const declaredDependencies = []; const externalDependencies = new Set(); + if (declaredDependenciesNode.type !== 'ArrayExpression') { // If the declared dependencies are not an array expression then we // can't verify that the user provided the correct dependencies. Tell @@ -542,8 +563,8 @@ export default { // Skip elided elements. if (declaredDependencyNode === null) { return; - } - // If we see a spread element then add a special warning. + } // If we see a spread element then add a special warning. + if (declaredDependencyNode.type === 'SpreadElement') { context.report({ node: declaredDependencyNode, @@ -554,10 +575,11 @@ export default { 'correct dependencies.', }); return; - } - // Try to normalize the declared dependency. If we can't then an error + } // Try to normalize the declared dependency. If we can't then an error // will be thrown. We will catch that error and report an error. + let declaredDependency; + try { declaredDependency = toPropertyAccessString(declaredDependencyNode); } catch (error) { @@ -596,14 +618,15 @@ export default { } let maybeID = declaredDependencyNode; + while (maybeID.type === 'MemberExpression') { maybeID = maybeID.object; } + const isDeclaredInComponent = !componentScope.through.some( ref => ref.identifier === maybeID, - ); + ); // Add the dependency to our declared dependency map. - // Add the dependency to our declared dependency map. declaredDependencies.push({ key: declaredDependency, node: declaredDependencyNode, @@ -627,37 +650,37 @@ export default { externalDependencies, isEffect, }); - const problemCount = duplicateDependencies.size + missingDependencies.size + - unnecessaryDependencies.size; - - // If we're going to report a missing dependency, + unnecessaryDependencies.size; // If we're going to report a missing dependency, // we might as well recalculate the list ignoring // the currently specified deps. This can result // in some extra deduplication. We can't do this // for effects though because those have legit // use cases for over-specifying deps. + if (!isEffect && missingDependencies.size > 0) { suggestedDependencies = collectRecommendations({ dependencies, - declaredDependencies: [], // Pretend we don't know + declaredDependencies: [], + // Pretend we don't know optionalDependencies, externalDependencies, isEffect, }).suggestedDependencies; - } + } // Alphabetize the suggestions, but only if deps were already alphabetized. - // Alphabetize the suggestions, but only if deps were already alphabetized. function areDeclaredDepsAlphabetized() { if (declaredDependencies.length === 0) { return true; } + const declaredDepKeys = declaredDependencies.map(dep => dep.key); const sortedDeclaredDepKeys = declaredDepKeys.slice().sort(); return declaredDepKeys.join(',') === sortedDeclaredDepKeys.join(','); } + if (areDeclaredDepsAlphabetized()) { suggestedDependencies.sort(); } @@ -666,6 +689,7 @@ export default { if (deps.size === 0) { return null; } + return ( (deps.size > 1 ? '' : singlePrefix + ' ') + label + @@ -684,65 +708,77 @@ export default { } let extraWarning = ''; + if (unnecessaryDependencies.size > 0) { let badRef = null; Array.from(unnecessaryDependencies.keys()).forEach(key => { if (badRef !== null) { return; } + if (key.endsWith('.current')) { badRef = key; } }); + if (badRef !== null) { extraWarning = ` Mutable values like '${badRef}' aren't valid dependencies ` + "because mutating them doesn't re-render the component."; } else if (externalDependencies.size > 0) { - const dep = Array.from(externalDependencies)[0]; - // Don't show this warning for things that likely just got moved *inside* the callback + const dep = Array.from(externalDependencies)[0]; // Don't show this warning for things that likely just got moved *inside* the callback // because in that case they're clearly not referring to globals. + if (!scope.set.has(dep)) { extraWarning = ` Outer scope values like '${dep}' aren't valid dependencies ` + `because mutating them doesn't re-render the component.`; } } - } - - // `props.foo()` marks `props` as a dependency because it has + } // `props.foo()` marks `props` as a dependency because it has // a `this` value. This warning can be confusing. // So if we're going to show it, append a clarification. + if (!extraWarning && missingDependencies.has('props')) { let propDep = dependencies.get('props'); + if (propDep == null) { return; } + const refs = propDep.references; + if (!Array.isArray(refs)) { return; } + let isPropsOnlyUsedInMembers = true; + for (let i = 0; i < refs.length; i++) { const ref = refs[i]; const id = fastFindReferenceWithParent( componentScope.block, ref.identifier, ); + if (!id) { isPropsOnlyUsedInMembers = false; break; } + const parent = id.parent; + if (parent == null) { isPropsOnlyUsedInMembers = false; break; } + if (parent.type !== 'MemberExpression') { isPropsOnlyUsedInMembers = false; break; } } + if (isPropsOnlyUsedInMembers) { extraWarning = ` However, 'props' will change when *any* prop changes, so the ` + @@ -759,23 +795,27 @@ export default { missingDependencies.forEach(missingDep => { if (missingCallbackDep) { return; - } - // Is this a variable from top scope? + } // Is this a variable from top scope? + const topScopeRef = componentScope.set.get(missingDep); const usedDep = dependencies.get(missingDep); + if (usedDep.references[0].resolved !== topScopeRef) { return; - } - // Is this a destructured prop? + } // Is this a destructured prop? + const def = topScopeRef.defs[0]; + if (def == null || def.name == null || def.type !== 'Parameter') { return; - } - // Was it called in at least one case? Then it's a function. + } // Was it called in at least one case? Then it's a function. + let isFunctionCall = false; let id; + for (let i = 0; i < usedDep.references.length; i++) { id = usedDep.references[i].identifier; + if ( id != null && id.parent != null && @@ -786,14 +826,16 @@ export default { break; } } + if (!isFunctionCall) { return; - } - // If it's missing (i.e. in component scope) *and* it's a parameter + } // If it's missing (i.e. in component scope) *and* it's a parameter // then it is definitely coming from props destructuring. // (It could also be props itself but we wouldn't be calling it then.) + missingCallbackDep = missingDep; }); + if (missingCallbackDep !== null) { extraWarning = ` If '${missingCallbackDep}' changes too often, ` + @@ -808,19 +850,22 @@ export default { if (setStateRecommendation !== null) { return; } + const usedDep = dependencies.get(missingDep); const references = usedDep.references; let id; let maybeCall; + for (let i = 0; i < references.length; i++) { id = references[i].identifier; - maybeCall = id.parent; - // Try to see if we have setState(someExpr(missingDep)). + maybeCall = id.parent; // Try to see if we have setState(someExpr(missingDep)). + while (maybeCall != null && maybeCall !== componentScope.block) { if (maybeCall.type === 'CallExpression') { const correspondingStateVariable = setStateCallSites.get( maybeCall.callee, ); + if (correspondingStateVariable != null) { if (correspondingStateVariable.name === missingDep) { // setCount(count + 1) @@ -838,11 +883,13 @@ export default { }; } else { const resolved = references[i].resolved; + if (resolved != null) { // If it's a parameter *and* a missing dep, // it must be a prop or something inside a prop. // Therefore, recommend an inline reducer. const def = resolved.defs[0]; + if (def != null && def.type === 'Parameter') { setStateRecommendation = { missingDep, @@ -852,16 +899,20 @@ export default { } } } + break; } } + maybeCall = maybeCall.parent; } + if (setStateRecommendation !== null) { break; } } }); + if (setStateRecommendation !== null) { switch (setStateRecommendation.form) { case 'reducer': @@ -870,6 +921,7 @@ export default { `if '${setStateRecommendation.setter}' needs the ` + `current value of '${setStateRecommendation.missingDep}'.`; break; + case 'inlineReducer': extraWarning = ` If '${setStateRecommendation.setter}' needs the ` + @@ -877,6 +929,7 @@ export default { `you can also switch to useReducer instead of useState and ` + `read '${setStateRecommendation.missingDep}' in the reducer.`; break; + case 'updater': extraWarning = ` You can also do a functional update '${ @@ -888,6 +941,7 @@ export default { setStateRecommendation.missingDep }'` + ` in the '${setStateRecommendation.setter}' call.`; break; + default: throw new Error('Unknown case.'); } @@ -898,8 +952,7 @@ export default { context.report({ node: declaredDependenciesNode, message: - `React Hook ${context.getSource(reactiveHook)} has ` + - // To avoid a long message, show the next actionable item. + `React Hook ${context.getSource(reactiveHook)} has ` + // To avoid a long message, show the next actionable item. (getWarningMessage( missingDependencies, 'a', @@ -919,6 +972,7 @@ export default { 'omit', )) + extraWarning, + fix(fixer) { // TODO: consider preserving the comments or formatting? return fixer.replaceText( @@ -930,9 +984,8 @@ export default { } } }, -}; +}; // The meat of the logic. -// The meat of the logic. function collectRecommendations({ dependencies, declaredDependencies, @@ -950,27 +1003,29 @@ function collectRecommendations({ // and the nodes that were *declared* as deps. Then we will // traverse it to learn which deps are missing or unnecessary. const depTree = createDepTree(); + function createDepTree() { return { - isRequired: false, // True if used in code - isSatisfiedRecursively: false, // True if specified in deps - hasRequiredNodesBelow: false, // True if something deeper is used by code + isRequired: false, + // True if used in code + isSatisfiedRecursively: false, + // True if specified in deps + hasRequiredNodesBelow: false, + // True if something deeper is used by code children: new Map(), // Nodes for properties }; - } - - // Mark all required nodes first. + } // Mark all required nodes first. // Imagine exclamation marks next to each used deep property. + dependencies.forEach((_, key) => { const node = getOrCreateNodeByPath(depTree, key); node.isRequired = true; markAllParentsByPath(depTree, key, parent => { parent.hasRequiredNodesBelow = true; }); - }); - - // Mark all satisfied nodes. + }); // Mark all satisfied nodes. // Imagine checkmarks next to each declared dependency. + declaredDependencies.forEach(({ key }) => { const node = getOrCreateNodeByPath(depTree, key); node.isSatisfiedRecursively = true; @@ -978,36 +1033,42 @@ function collectRecommendations({ optionalDependencies.forEach(key => { const node = getOrCreateNodeByPath(depTree, key); node.isSatisfiedRecursively = true; - }); + }); // Tree manipulation helpers. - // Tree manipulation helpers. function getOrCreateNodeByPath(rootNode, path) { let keys = path.split('.'); let node = rootNode; + for (let key of keys) { let child = node.children.get(key); + if (!child) { child = createDepTree(); node.children.set(key, child); } + node = child; } + return node; } + function markAllParentsByPath(rootNode, path, fn) { let keys = path.split('.'); let node = rootNode; + for (let key of keys) { let child = node.children.get(key); + if (!child) { return; } + fn(child); node = child; } - } + } // Now we can learn which dependencies are missing or necessary. - // Now we can learn which dependencies are missing or necessary. let missingDependencies = new Set(); let satisfyingDependencies = new Set(); scanTreeRecursively( @@ -1016,26 +1077,30 @@ function collectRecommendations({ satisfyingDependencies, key => key, ); + function scanTreeRecursively(node, missingPaths, satisfyingPaths, keyToPath) { node.children.forEach((child, key) => { const path = keyToPath(key); + if (child.isSatisfiedRecursively) { if (child.hasRequiredNodesBelow) { // Remember this dep actually satisfied something. satisfyingPaths.add(path); - } - // It doesn't matter if there's something deeper. + } // It doesn't matter if there's something deeper. // It would be transitively satisfied since we assume immutability. // `props.foo` is enough if you read `props.foo.id`. + return; } + if (child.isRequired) { // Remember that no declared deps satisfied this node. - missingPaths.add(path); - // If we got here, nothing in its subtree was satisfied. + missingPaths.add(path); // If we got here, nothing in its subtree was satisfied. // No need to search further. + return; } + scanTreeRecursively( child, missingPaths, @@ -1043,9 +1108,8 @@ function collectRecommendations({ childKey => path + '.' + childKey, ); }); - } + } // Collect suggestions in the order they were originally specified. - // Collect suggestions in the order they were originally specified. let suggestedDependencies = []; let unnecessaryDependencies = new Set(); let duplicateDependencies = new Set(); @@ -1077,13 +1141,11 @@ function collectRecommendations({ unnecessaryDependencies.add(key); } } - }); + }); // Then add the missing ones at the end. - // Then add the missing ones at the end. missingDependencies.forEach(key => { suggestedDependencies.push(key); }); - return { suggestedDependencies, unnecessaryDependencies, @@ -1091,7 +1153,6 @@ function collectRecommendations({ missingDependencies, }; } - /** * Assuming () means the passed/returned node: * (props) => (props) @@ -1099,6 +1160,7 @@ function collectRecommendations({ * props.foo.(bar) => (props).foo.bar * props.foo.bar.(baz) => (props).foo.bar.baz */ + function getDependency(node) { if ( node.parent.type === 'MemberExpression' && @@ -1116,7 +1178,6 @@ function getDependency(node) { return node; } } - /** * Assuming () means the passed node. * (foo) -> 'foo' @@ -1124,6 +1185,7 @@ function getDependency(node) { * foo.bar.(baz) -> 'foo.bar.baz' * Otherwise throw. */ + function toPropertyAccessString(node) { if (node.type === 'Identifier') { return node.name; @@ -1146,33 +1208,36 @@ function getNodeWithoutReactNamespace(node) { ) { return node.property; } - return node; -} -// What's the index of callback that needs to be analyzed for a given Hook? + return node; +} // What's the index of callback that needs to be analyzed for a given Hook? // -1 if it's not a Hook we care about (e.g. useState). // 0 for useEffect/useMemo/useCallback(fn). // 1 for useImperativeHandle(ref, fn). // For additionally configured Hooks, assume that they're like useEffect (0). + function getReactiveHookCallbackIndex(calleeNode) { let node = getNodeWithoutReactNamespace(calleeNode); + if (node.type !== 'Identifier') { return null; } + switch (node.name) { case 'useAsyncEffect': case 'useAsyncLayoutEffect': case 'useWorker': - case 'useWorkerLoad': + case 'useWorkerState': case 'useEffectUpdate': return 0; + case 'useConditionalEffect': return 1; + default: return -1; } } - /** * ESLint won't assign node.parent to references from context.getScope() * @@ -1183,6 +1248,7 @@ function getReactiveHookCallbackIndex(calleeNode) { * - optimized by only searching nodes with a range surrounding our target node * - agnostic to AST node types, it looks for `{ type: string, ... }` */ + function fastFindReferenceWithParent(start, target) { let queue = [start]; let item = null; @@ -1202,6 +1268,7 @@ function fastFindReferenceWithParent(start, target) { if (key === 'parent') { continue; } + if (isNodeLike(value)) { value.parent = item; queue.push(value); @@ -1221,8 +1288,10 @@ function fastFindReferenceWithParent(start, target) { function joinEnglish(arr) { let s = ''; + for (let i = 0; i < arr.length; i++) { s += arr[i]; + if (i === 0 && arr.length === 2) { s += ' and '; } else if (i === arr.length - 2 && arr.length > 2) { @@ -1231,6 +1300,7 @@ function joinEnglish(arr) { s += ', '; } } + return s; } diff --git a/eslint-plugin/package.json b/eslint-plugin/package.json index 1bba449..e48bbf4 100644 --- a/eslint-plugin/package.json +++ b/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@react-hook-utilities/eslint-plugin", - "version": "1.0.0", + "version": "0.1.0", "description": "ESLint rules for hook react-hook-utilities", "keywords": [ "eslint", @@ -14,10 +14,6 @@ "babel": "rm -rf lib && babel src/ -d ./lib" }, "devDependencies": { - "@babel/cli": "^7.6.2", - "@babel/preset-env": "^7.6.2", - "babel-eslint": "^10.0.3", - "eslint": "~3.9.1", "mocha": "^3.1.2" }, "engines": { diff --git a/eslint-plugin/yarn.lock b/eslint-plugin/yarn.lock index e0fcf90..cdcf854 100644 --- a/eslint-plugin/yarn.lock +++ b/eslint-plugin/yarn.lock @@ -2,805 +2,11 @@ # yarn lockfile v1 -"@babel/cli@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.6.2.tgz#4ce8b5b4b2e4b4c1b7bd841cec62085e2dfc4465" - integrity sha512-JDZ+T/br9pPfT2lmAMJypJDTTTHM9ePD/ED10TRjRzJVdEVy+JB3iRlhzYmTt5YkNgHvxWGlUVnLtdv6ruiDrQ== - dependencies: - commander "^2.8.1" - convert-source-map "^1.1.0" - fs-readdir-recursive "^1.1.0" - glob "^7.0.0" - lodash "^4.17.13" - mkdirp "^0.5.1" - output-file-sync "^2.0.0" - slash "^2.0.0" - source-map "^0.5.0" - optionalDependencies: - chokidar "^2.1.8" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== - dependencies: - "@babel/highlight" "^7.0.0" - -"@babel/generator@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.2.tgz#dac8a3c2df118334c2a29ff3446da1636a8f8c03" - integrity sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ== - dependencies: - "@babel/types" "^7.6.0" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - -"@babel/helper-annotate-as-pure@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" - integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" - integrity sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-call-delegate@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz#87c1f8ca19ad552a736a7a27b1c1fcf8b1ff1f43" - integrity sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ== - dependencies: - "@babel/helper-hoist-variables" "^7.4.4" - "@babel/traverse" "^7.4.4" - "@babel/types" "^7.4.4" - -"@babel/helper-define-map@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" - integrity sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/types" "^7.5.5" - lodash "^4.17.13" - -"@babel/helper-explode-assignable-expression@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" - integrity sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA== - dependencies: - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== - dependencies: - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-get-function-arity@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-hoist-variables@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" - integrity sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w== - dependencies: - "@babel/types" "^7.4.4" - -"@babel/helper-member-expression-to-functions@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" - integrity sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA== - dependencies: - "@babel/types" "^7.5.5" - -"@babel/helper-module-imports@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" - integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" - integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/template" "^7.4.4" - "@babel/types" "^7.5.5" - lodash "^4.17.13" - -"@babel/helper-optimise-call-expression@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" - integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== - -"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" - integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== - dependencies: - lodash "^4.17.13" - -"@babel/helper-remap-async-to-generator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" - integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-wrap-function" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-replace-supers@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" - integrity sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.5.5" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - -"@babel/helper-simple-access@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" - integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== - dependencies: - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-split-export-declaration@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" - integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== - dependencies: - "@babel/types" "^7.4.4" - -"@babel/helper-wrap-function@^7.1.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" - integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.2.0" - -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.0.0", "@babel/parser@^7.6.0", "@babel/parser@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1" - integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg== - -"@babel/plugin-proposal-async-generator-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" - integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" - -"@babel/plugin-proposal-dynamic-import@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz#e532202db4838723691b10a67b8ce509e397c506" - integrity sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-dynamic-import" "^7.2.0" - -"@babel/plugin-proposal-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" - integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" - -"@babel/plugin-proposal-object-rest-spread@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz#8ffccc8f3a6545e9f78988b6bf4fe881b88e8096" - integrity sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - -"@babel/plugin-proposal-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" - integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" - -"@babel/plugin-proposal-unicode-property-regex@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz#05413762894f41bfe42b9a5e80919bd575dcc802" - integrity sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.6.0" - -"@babel/plugin-syntax-async-generators@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" - integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-dynamic-import@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" - integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" - integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-object-rest-spread@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" - integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" - integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-arrow-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" - integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-async-to-generator@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz#89a3848a0166623b5bc481164b5936ab947e887e" - integrity sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" - -"@babel/plugin-transform-block-scoped-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" - integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-block-scoping@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.2.tgz#96c33ab97a9ae500cc6f5b19e04a7e6553360a79" - integrity sha512-zZT8ivau9LOQQaOGC7bQLQOT4XPkPXgN2ERfUgk1X8ql+mVkLc4E8eKk+FO3o0154kxzqenWCorfmEXpEZcrSQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - lodash "^4.17.13" - -"@babel/plugin-transform-classes@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz#d094299d9bd680a14a2a0edae38305ad60fb4de9" - integrity sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.5.5" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" - "@babel/helper-split-export-declaration" "^7.4.4" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" - integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-destructuring@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6" - integrity sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-dotall-regex@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz#44abb948b88f0199a627024e1508acaf8dc9b2f9" - integrity sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.6.0" - -"@babel/plugin-transform-duplicate-keys@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" - integrity sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-exponentiation-operator@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" - integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-for-of@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" - integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-function-name@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" - integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" - integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-member-expression-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" - integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-modules-amd@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" - integrity sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg== - dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-commonjs@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz#39dfe957de4420445f1fcf88b68a2e4aa4515486" - integrity sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g== - dependencies: - "@babel/helper-module-transforms" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-systemjs@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz#e75266a13ef94202db2a0620977756f51d52d249" - integrity sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg== - dependencies: - "@babel/helper-hoist-variables" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-umd@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" - integrity sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw== - dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.2.tgz#c1ca0bb84b94f385ca302c3932e870b0fb0e522b" - integrity sha512-xBdB+XOs+lgbZc2/4F5BVDVcDNS4tcSKQc96KmlqLEAwz6tpYPEvPdmDfvVG0Ssn8lAhronaRs6Z6KSexIpK5g== - dependencies: - regexpu-core "^4.6.0" - -"@babel/plugin-transform-new-target@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" - integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-object-super@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" - integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" - -"@babel/plugin-transform-parameters@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" - integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== - dependencies: - "@babel/helper-call-delegate" "^7.4.4" - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-property-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" - integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-regenerator@^7.4.5": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" - integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== - dependencies: - regenerator-transform "^0.14.0" - -"@babel/plugin-transform-reserved-words@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634" - integrity sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-shorthand-properties@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" - integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-spread@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz#fc77cf798b24b10c46e1b51b1b88c2bf661bb8dd" - integrity sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-sticky-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" - integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - -"@babel/plugin-transform-template-literals@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" - integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-typeof-symbol@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" - integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-unicode-regex@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz#b692aad888a7e8d8b1b214be6b9dc03d5031f698" - integrity sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.6.0" - -"@babel/preset-env@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.2.tgz#abbb3ed785c7fe4220d4c82a53621d71fc0c75d3" - integrity sha512-Ru7+mfzy9M1/YTEtlDS8CD45jd22ngb9tXnn64DvQK3ooyqSw9K4K9DUWmYknTTVk4TqygL9dqCrZgm1HMea/Q== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-async-generator-functions" "^7.2.0" - "@babel/plugin-proposal-dynamic-import" "^7.5.0" - "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.6.2" - "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.6.2" - "@babel/plugin-syntax-async-generators" "^7.2.0" - "@babel/plugin-syntax-dynamic-import" "^7.2.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" - "@babel/plugin-transform-arrow-functions" "^7.2.0" - "@babel/plugin-transform-async-to-generator" "^7.5.0" - "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.6.2" - "@babel/plugin-transform-classes" "^7.5.5" - "@babel/plugin-transform-computed-properties" "^7.2.0" - "@babel/plugin-transform-destructuring" "^7.6.0" - "@babel/plugin-transform-dotall-regex" "^7.6.2" - "@babel/plugin-transform-duplicate-keys" "^7.5.0" - "@babel/plugin-transform-exponentiation-operator" "^7.2.0" - "@babel/plugin-transform-for-of" "^7.4.4" - "@babel/plugin-transform-function-name" "^7.4.4" - "@babel/plugin-transform-literals" "^7.2.0" - "@babel/plugin-transform-member-expression-literals" "^7.2.0" - "@babel/plugin-transform-modules-amd" "^7.5.0" - "@babel/plugin-transform-modules-commonjs" "^7.6.0" - "@babel/plugin-transform-modules-systemjs" "^7.5.0" - "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.6.2" - "@babel/plugin-transform-new-target" "^7.4.4" - "@babel/plugin-transform-object-super" "^7.5.5" - "@babel/plugin-transform-parameters" "^7.4.4" - "@babel/plugin-transform-property-literals" "^7.2.0" - "@babel/plugin-transform-regenerator" "^7.4.5" - "@babel/plugin-transform-reserved-words" "^7.2.0" - "@babel/plugin-transform-shorthand-properties" "^7.2.0" - "@babel/plugin-transform-spread" "^7.6.2" - "@babel/plugin-transform-sticky-regex" "^7.2.0" - "@babel/plugin-transform-template-literals" "^7.4.4" - "@babel/plugin-transform-typeof-symbol" "^7.2.0" - "@babel/plugin-transform-unicode-regex" "^7.6.2" - "@babel/types" "^7.6.0" - browserslist "^4.6.0" - core-js-compat "^3.1.1" - invariant "^2.2.2" - js-levenshtein "^1.1.3" - semver "^5.5.0" - -"@babel/template@^7.1.0", "@babel/template@^7.4.4": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" - integrity sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.6.0" - "@babel/types" "^7.6.0" - -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c" - integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.2" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.6.2" - "@babel/types" "^7.6.0" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0": - version "7.6.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648" - integrity sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= - dependencies: - acorn "^3.0.4" - -acorn@^3.0.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= - -acorn@^5.5.0: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== - -ajv-keywords@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" - integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= - -ajv@^4.7.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -ansi-escapes@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -atob@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -babel-code-frame@^6.16.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-eslint@^10.0.3: - 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== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - -babel-plugin-dynamic-import-node@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== - dependencies: - object.assign "^4.1.0" - balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -809,174 +15,11 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= -browserslist@^4.6.0, browserslist@^4.6.6: - version "4.7.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.0.tgz#9ee89225ffc07db03409f2fee524dc8227458a17" - integrity sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA== - dependencies: - caniuse-lite "^1.0.30000989" - electron-to-chromium "^1.3.247" - node-releases "^1.1.29" - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= - dependencies: - callsites "^0.2.0" - -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= - -caniuse-lite@^1.0.30000989: - version "1.0.30000997" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000997.tgz#ba44a606804f8680894b7042612c2c7f65685b7e" - integrity sha512-BQLFPIdj2ntgBNWp9Q64LGUIEmvhKkzzHhUHR3CD5A9Lb7ZKF20/+sgadhFap69lk5XmK1fTUleDclaRFvgVUA== - -chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -chownr@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" - integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== - -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -cli-cursor@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" - integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= - dependencies: - restore-cursor "^1.0.1" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - commander@2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" @@ -984,69 +27,11 @@ commander@2.9.0: dependencies: graceful-readlink ">= 1.0.0" -commander@^2.8.1: - version "2.20.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.1.tgz#3863ce3ca92d0831dcf2a102f5fb4b5926afd0f9" - integrity sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg== - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.4.6: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -convert-source-map@^1.1.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== - dependencies: - safe-buffer "~5.1.1" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -core-js-compat@^3.1.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.2.1.tgz#0cbdbc2e386e8e00d3b85dc81c848effec5b8150" - integrity sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A== - dependencies: - browserslist "^4.6.6" - semver "^6.3.0" - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - debug@2.6.8: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" @@ -1054,435 +39,21 @@ debug@2.6.8: dependencies: ms "2.0.0" -debug@^2.1.1, debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -debug@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -define-properties@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - diff@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k= -doctrine@^1.2.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - -electron-to-chromium@^1.3.247: - version "1.3.269" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.269.tgz#3e00cc9266a0123fc2e7b4f290899e257200e6e3" - integrity sha512-t2ZTfo07HxkxTOUbIwMmqHBSnJsC9heqJUm7LwQu2iSk0wNhG4H5cMREtb8XxeCrQABDZ6IqQKY3yZq+NfAqwg== - -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.51, es5-ext@~0.10.14: - version "0.10.51" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.51.tgz#ed2d7d9d48a12df86e0299287e93a09ff478842f" - integrity sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.1" - next-tick "^1.0.0" - -es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-map@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-set "~0.1.5" - es6-symbol "~3.1.1" - event-emitter "~0.3.5" - -es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= - dependencies: - d "1" - es5-ext "~0.10.14" - -es6-symbol@^3.1.1, es6-symbol@~3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.2.tgz#859fdd34f32e905ff06d752e7171ddd4444a7ed1" - integrity sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ== - dependencies: - d "^1.0.1" - es5-ext "^0.10.51" - -es6-weak-map@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" - integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== - dependencies: - d "1" - es5-ext "^0.10.46" - es6-iterator "^2.0.3" - es6-symbol "^3.1.1" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= - dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-visitor-keys@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== - -eslint@~3.9.1: - version "3.9.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.9.1.tgz#5a8597706fc6048bc6061ac754d4a211d28f4f5b" - integrity sha1-WoWXcG/GBIvGBhrHVNSiEdKPT1s= - dependencies: - babel-code-frame "^6.16.0" - chalk "^1.1.3" - concat-stream "^1.4.6" - debug "^2.1.1" - doctrine "^1.2.2" - escope "^3.6.0" - espree "^3.3.1" - estraverse "^4.2.0" - esutils "^2.0.2" - file-entry-cache "^2.0.0" - glob "^7.0.3" - globals "^9.2.0" - ignore "^3.1.5" - imurmurhash "^0.1.4" - inquirer "^0.12.0" - is-my-json-valid "^2.10.0" - is-resolvable "^1.0.0" - js-yaml "^3.5.1" - json-stable-stringify "^1.0.0" - levn "^0.3.0" - lodash "^4.0.0" - mkdirp "^0.5.0" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.1" - pluralize "^1.2.1" - progress "^1.1.8" - require-uncached "^1.0.2" - shelljs "^0.7.5" - strip-bom "^3.0.0" - strip-json-comments "~1.0.1" - table "^3.7.8" - text-table "~0.2.0" - user-home "^2.0.0" - -espree@^3.3.1: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== - dependencies: - acorn "^5.5.0" - acorn-jsx "^3.0.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== - dependencies: - estraverse "^4.1.0" - -estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -event-emitter@~0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= - dependencies: - d "1" - es5-ext "~0.10.14" - -exit-hook@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" - integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -fast-levenshtein@~2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -figures@^1.3.5: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - -file-entry-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= - dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -flat-cache@^1.2.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" - integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== - dependencies: - circular-json "^0.3.1" - graceful-fs "^4.1.2" - rimraf "~2.6.2" - write "^0.2.1" - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - -fs-readdir-recursive@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" - integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.7: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== - dependencies: - nan "^2.12.1" - node-pre-gyp "^0.12.0" - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -generate-function@^2.0.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" - integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== - dependencies: - is-property "^1.0.2" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= - dependencies: - is-property "^1.0.0" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - glob@7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" @@ -1495,33 +66,6 @@ glob@7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.3: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^9.2.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - -graceful-fs@^4.1.11, graceful-fs@^4.1.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" - integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== - "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" @@ -1532,397 +76,34 @@ growl@1.9.2: resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8= -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - he@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= -iconv-lite@^0.4.4: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ignore-walk@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.2.tgz#99d83a246c196ea5c93ef9315ad7b0819c35069b" - integrity sha512-EXyErtpHbn75ZTsOADsfx6J/FPo6/5cjev46PXrcTpd8z3BoRkXgYu9/JVqrI7tusjmwCZutGeRJeU0Wo1e4Cw== - dependencies: - minimatch "^3.0.4" - -ignore@^3.1.5: - version "3.3.10" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.3, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -inquirer@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" - integrity sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34= - dependencies: - ansi-escapes "^1.1.0" - ansi-regex "^2.0.0" - chalk "^1.0.0" - cli-cursor "^1.0.1" - cli-width "^2.0.0" - figures "^1.3.5" - lodash "^4.3.0" - readline2 "^1.0.1" - run-async "^0.1.0" - rx-lite "^3.1.2" - string-width "^1.0.1" - strip-ansi "^3.0.0" - through "^2.3.6" - -interpret@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== - -invariant@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-my-ip-valid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" - integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ== - -is-my-json-valid@^2.10.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz#1345a6fca3e8daefc10d0fa77067f54cedafd59a" - integrity sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA== - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-property@^1.0.0, is-property@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= - -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -js-levenshtein@^1.1.3: - version "1.1.6" - resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" - integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= - -js-yaml@^3.5.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + once "^1.3.0" + wrappy "1" -json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== json3@3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - lodash._baseassign@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" @@ -1979,50 +160,7 @@ lodash.keys@^3.0.0: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" -lodash@^4.0.0, lodash@^4.17.13, lodash@^4.3.0: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -2034,43 +172,7 @@ minimist@0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minipass@^2.6.0, minipass@^2.8.6: - version "2.8.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.8.6.tgz#620d889ace26356391d010ecb9458749df9b6db5" - integrity sha512-lFG7d6g3+/UaFDCOtqPiKAC9zngWWsQZl1g5q6gaONqrjq61SX2xFqXMleQiFVyDpYwa018E9hmlAFY22PCb+A== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.2.tgz#5d24764998f98112586f7e566bd4c0999769dad4" - integrity sha512-lsNFqSHdJ21EwKzCp12HHJGxSMtHkCW1EMA9cceG3MkMNARjuWotZnMe3NKNshAvFXpm4loZqmYsCmRwhS2JMw== - dependencies: - minipass "^2.9.0" - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -2100,171 +202,6 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -mute-stream@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" - integrity sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA= - -nan@^2.12.1: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - -next-tick@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -node-releases@^1.1.29: - version "1.1.33" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.33.tgz#349f10291234624574f44cf32b7de259bf028303" - integrity sha512-I0V30bWQEoHb+10W8oedVoUrdjW5wIkYm0w7vvcrPO95pZY738m1k77GF5sO0vKg5eXYg9oGtrMAETbgZGm11A== - dependencies: - semver "^5.3.0" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== - -npm-packlist@^1.1.6: - version "1.4.4" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" - integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -object-assign@^4.0.1, object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-keys@^1.0.11, object-keys@^1.0.12: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -2272,483 +209,11 @@ once@^1.3.0: dependencies: wrappy "1" -onetime@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" - integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= - -optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-tmpdir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -output-file-sync@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-2.0.1.tgz#f53118282f5f553c2799541792b723a4c71430c0" - integrity sha512-mDho4qm7WgIXIGf4eYU1RHN2UU5tPfVYVSRwDJw0uTmj35DQUt/eNp19N7v6T3SrR0ESTEf2up2CGO73qI35zQ== - dependencies: - graceful-fs "^4.1.11" - is-plain-obj "^1.1.0" - mkdirp "^0.5.1" - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -pluralize@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" - integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU= - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -private@^0.1.6: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -progress@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" - integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= - -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -readline2@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" - integrity sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - mute-stream "0.0.5" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - -regenerate-unicode-properties@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" - integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== - dependencies: - regenerate "^1.4.0" - -regenerate@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== - -regenerator-transform@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" - integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== - dependencies: - private "^0.1.6" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexpu-core@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" - integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.1.0" - regjsgen "^0.5.0" - regjsparser "^0.6.0" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.1.0" - -regjsgen@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" - integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA== - -regjsparser@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" - integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== - dependencies: - jsesc "~0.5.0" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -require-uncached@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@^1.1.6, resolve@^1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" - integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== - dependencies: - path-parse "^1.0.6" - -restore-cursor@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" - integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= - dependencies: - exit-hook "^1.0.0" - onetime "^1.0.0" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -rimraf@^2.6.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@~2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -run-async@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" - integrity sha1-yK1KXhEGYeQCp9IbUw4AnyX444k= - dependencies: - once "^1.3.0" - -rx-lite@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" - integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI= - -safe-buffer@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -semver@^5.3.0, semver@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -shelljs@^0.7.5: - version "0.7.8" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -signal-exit@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@^0.5.0, source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2", string-width@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -strip-json-comments@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" - integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E= - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - supports-color@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" @@ -2756,198 +221,7 @@ supports-color@3.1.2: dependencies: has-flag "^1.0.0" -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -table@^3.7.8: - version "3.8.3" - resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" - integrity sha1-K7xULw/amGGnVdOUf+/Ys/UThV8= - dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.0.0" - -tar@^4: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - -text-table@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== - -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== - dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" - -unicode-match-property-value-ecmascript@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" - integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" - integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -user-home@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" - integrity sha1-nHC/2Babwdy/SGBODwS4tJzenp8= - dependencies: - os-homedir "^1.0.0" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= - dependencies: - mkdirp "^0.5.1" - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -yallist@^3.0.0, yallist@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.0.tgz#906cc2100972dc2625ae78f566a2577230a1d6f7" - integrity sha512-6gpP93MR+VOOehKbCPchro3wFZNSNmek8A2kbkOAZLIZAYx1KP/zAqwO0sOHi3xJEb+UBz8NaYt/17UNit1Q9w== diff --git a/jest.config.js b/jest.config.js index 7b9239f..2fbe9b0 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,5 @@ module.exports = { - roots: ['/src'], + roots: ['/src', '/eslint-plugin/lib'], transform: { '^.+\\.tsx?$': 'ts-jest', }, diff --git a/package.json b/package.json index d64a107..bd91e4d 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "types": "dist/index.d.ts", "files": [ "dist/index.js", - "dist/index.d.ts" + "dist/index.d.ts", + "eslint-plugin/!(*/__tests__|yarn*)" ], "dependencies": { "react": "^16" @@ -41,6 +42,7 @@ "@types/react": "^16.9.2", "@typescript-eslint/eslint-plugin": "^2.3.1", "@typescript-eslint/parser": "^2.3.1", + "babel-eslint": "^10.0.3", "commitlint": "^8.2.0", "conventional-changelog-cli": "^2.0.25", "eslint": "^6.5.0", diff --git a/src/__tests__/useDidUnmount.ts b/src/__tests__/useDidUnmount.ts index e96ae7c..65b8634 100644 --- a/src/__tests__/useDidUnmount.ts +++ b/src/__tests__/useDidUnmount.ts @@ -3,23 +3,23 @@ import { renderHook } from '@testing-library/react-hooks'; import { useDidUnmount } from '..'; let cleanup: jest.Mock; -let hook: any; +let useHook: any; beforeEach(() => { cleanup = jest.fn(); - hook = ({ func = cleanup, deps }: any = {}) => { + useHook = ({ func = cleanup, deps }: any = {}) => { useDidUnmount(func, deps); }; }); it('does not call the effect if the component is mounted', () => { - renderHook(hook); + renderHook(useHook); expect(cleanup).not.toHaveBeenCalled(); }); it('calls the effect when the component gets unmounted', () => { - const { unmount } = renderHook(hook); + const { unmount } = renderHook(useHook); expect(cleanup).not.toHaveBeenCalled(); unmount(); @@ -28,7 +28,7 @@ it('calls the effect when the component gets unmounted', () => { }); it('calls the effect only once', () => { - const { unmount } = renderHook(hook); + const { unmount } = renderHook(useHook); expect(cleanup).not.toHaveBeenCalled(); unmount(); @@ -50,7 +50,7 @@ it('runs an async funciton', async () => { finished = true; }); - const { unmount } = renderHook(hook); + const { unmount } = renderHook(useHook); unmount(); @@ -64,7 +64,7 @@ it('runs an async funciton', async () => { it('calls the effect with updated dependencies', () => { const secondCleanup = jest.fn(); - const { unmount, rerender } = renderHook(hook, { + const { unmount, rerender } = renderHook(useHook, { initialProps: { func: cleanup, deps: [cleanup] }, }); @@ -78,7 +78,7 @@ it('calls the effect with updated dependencies', () => { it('does not update the effect when the dependencies have not been updated', () => { const secondCleanup = jest.fn(); - const { unmount, rerender } = renderHook(hook, { + const { unmount, rerender } = renderHook(useHook, { initialProps: { func: cleanup, deps: [cleanup] }, }); diff --git a/src/__tests__/useLazyRef.ts b/src/__tests__/useLazyRef.ts index d793201..b30eea4 100644 --- a/src/__tests__/useLazyRef.ts +++ b/src/__tests__/useLazyRef.ts @@ -3,18 +3,18 @@ import { renderHook } from '@testing-library/react-hooks'; import { useLazyRef } from '..'; const callbackFn = jest.fn(); -const mockHook = () => useLazyRef(callbackFn); +const useMockHook = () => useLazyRef(callbackFn); beforeEach(callbackFn.mockRestore); it('calls factory on first call', () => { - renderHook(mockHook); + renderHook(useMockHook); expect(callbackFn.mock.calls.length).toEqual(1); }); it('does not call factory when value is unset', () => { - const { result, rerender } = renderHook(mockHook); + const { result, rerender } = renderHook(useMockHook); expect(callbackFn.mock.calls.length).toEqual(1); // act @@ -28,7 +28,7 @@ describe('change in current value', () => { const assertChangeCurrentValue = () => { // initial value callbackFn.mockReturnValue(0); - const { result } = renderHook(mockHook); + const { result } = renderHook(useMockHook); expect(result.current.current).toEqual(0); diff --git a/src/__tests__/usePromisedState.ts b/src/__tests__/usePromisedState.ts index eaf7abf..1dca33a 100644 --- a/src/__tests__/usePromisedState.ts +++ b/src/__tests__/usePromisedState.ts @@ -3,7 +3,7 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { usePromisedState } from '..'; describe('non-nullable, non-undefined state type', () => { - const hookHelper = () => usePromisedState(); + const useHookHelper = () => usePromisedState(); it("does not resolve promise if set isn't called", () => { let resolved = false; @@ -11,7 +11,7 @@ describe('non-nullable, non-undefined state type', () => { result: { current: [promise], }, - } = renderHook(hookHelper); + } = renderHook(useHookHelper); promise.then(() => { resolved = true; @@ -27,7 +27,7 @@ describe('non-nullable, non-undefined state type', () => { result: { current: [promise, set], }, - } = renderHook(hookHelper); + } = renderHook(useHookHelper); promise.then(() => { resolved = true; @@ -48,7 +48,7 @@ describe('non-nullable, non-undefined state type', () => { it('resolves a new promise when the state is set', async () => { let resolved = false; - const { result } = renderHook(hookHelper); + const { result } = renderHook(useHookHelper); result.current[0].then(() => { resolved = true; @@ -69,7 +69,7 @@ describe('non-nullable, non-undefined state type', () => { }); describe('nullable state type', () => { - const hookHelper = () => usePromisedState(); + const useHookHelper = () => usePromisedState(); it("does not resolve promise if set isn't called", () => { let resolved = false; @@ -77,7 +77,7 @@ describe('nullable state type', () => { result: { current: [promise], }, - } = renderHook(hookHelper); + } = renderHook(useHookHelper); promise.then(() => { resolved = true; @@ -93,7 +93,7 @@ describe('nullable state type', () => { result: { current: [promise, set], }, - } = renderHook(hookHelper); + } = renderHook(useHookHelper); promise.then(() => { resolved = true; @@ -108,7 +108,7 @@ describe('nullable state type', () => { }); it('waits on a new state after setting undefined', async () => { - const { result } = renderHook(hookHelper); + const { result } = renderHook(useHookHelper); act(() => { result.current[1](0); @@ -126,7 +126,7 @@ describe('nullable state type', () => { it('resolves a new promise when the state is set', async () => { let resolved = false; - const { result } = renderHook(hookHelper); + const { result } = renderHook(useHookHelper); result.current[0].then(() => { resolved = true; diff --git a/src/__tests__/useWorkerState.ts b/src/__tests__/useWorkerState.ts index 946d493..f3ede35 100644 --- a/src/__tests__/useWorkerState.ts +++ b/src/__tests__/useWorkerState.ts @@ -210,7 +210,7 @@ describe('callback', () => { }); it('updates the scope of the callback', async () => { - const hook = () => { + const useHook = () => { const [state, setState] = useState(0); const worker = useWorkerState(async () => { callbackFn(state); @@ -218,7 +218,7 @@ describe('callback', () => { return { state, setState, ...worker }; }; - const { result, waitForNextUpdate } = renderHook(hook); + const { result, waitForNextUpdate } = renderHook(useHook); expect(callbackFn.mock.calls[0][0]).toBe(0); diff --git a/src/index.tsx b/src/index.tsx index a73623e..e807b53 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,6 +4,7 @@ import { useCallback, useState, useRef, + useMemo, MutableRefObject, } from 'react'; @@ -59,7 +60,7 @@ export const useAsyncEffect = ( ) => { useEffect(() => { effect(); - }, [...dependencies, effect]); + }, [...dependencies, effect]); // eslint-disable-line react-hooks/exhaustive-deps }; /** @@ -77,7 +78,7 @@ export const useAsyncLayoutEffect = ( ) => { useLayoutEffect(() => { effect(); - }, [...dependencies, effect]); + }, [...dependencies, effect]); // eslint-disable-line react-hooks/exhaustive-deps }; /** @@ -114,19 +115,20 @@ export const useWorker = ( setState(s => ({ ...s, isLoading })); }, []); - const callback = useCallback(async (...args: TArgs): Promise< - TRet | undefined - > => { - try { - setIsLoading(true); - const result = await worker(...args); - setState({ isLoading: false, error: undefined }); + const callback = useCallback( + async (...args: TArgs): Promise => { + try { + setIsLoading(true); + const result = await worker(...args); + setState({ isLoading: false, error: undefined }); - return result; - } catch (error) { - setState({ isLoading: false, error }); - } - }, dependencies); + return result; + } catch (error) { + setState({ isLoading: false, error }); + } + }, + [...dependencies, worker], // eslint-disable-line react-hooks/exhaustive-deps + ); return { callback, error, isLoading, setError, setIsLoading }; }; @@ -280,7 +282,7 @@ export function useEffectUpdate( } finally { oldState.current = dependencies; } - }, [...dependencies, effect, oldState.current]); + }, [...dependencies, effect]); // eslint-disable-line react-hooks/exhaustive-deps } /** @@ -458,7 +460,7 @@ export function useConditionalEffect( ): void { useEffectUpdate( oldState => (evalCondition(oldState) ? effect() : undefined), - dependencies, // eslint-disable-line @react-hook-utilities/exhaustive-deps,react-hooks/exhaustive-deps + dependencies, // eslint-disable-line @react-hook-utilities/exhaustive-deps ); } @@ -476,7 +478,7 @@ export const useDidMount = ( if (typeof result === 'function') { return result; } - }, []); + }, []); // eslint-disable-line react-hooks/exhaustive-deps }; /** @@ -508,7 +510,7 @@ export const useDidUnmount = ( effect(); } }, - dependencies || [], + dependencies || [], // eslint-disable-line react-hooks/exhaustive-deps ); }; @@ -574,7 +576,7 @@ export function useWorkerState( async () => { setData(await worker()); }, - dependencies, + dependencies, // eslint-disable-line @react-hook-utilities/exhaustive-deps ); // start loading immediately @@ -612,28 +614,34 @@ export const usePromisedState = (): [ ValuablePromise, (_: T) => void, ] => { - let resolve: (v: T) => void; - const createPromise = (value?: T) => { - const result: ValuablePromise = new Promise(r => { - resolve = r; - if (value) { - r(value); - } - }); - result.value = value; - return result; - }; + let resolve = useRef<(v: T) => void>(); + const createPromise = useMemo( + () => (value?: T) => { + const result: ValuablePromise = new Promise(r => { + resolve.current = r; + if (value) { + r(value); + } + }); + result.value = value; + return result; + }, + [], + ); const [state, setState] = useState(createPromise); return [ state, - useCallback((newValue: T) => { - if (!!newValue) { - resolve(newValue); - state.value = newValue; - } - - setState(createPromise(newValue)); - }, []), + useCallback( + (newValue: T) => { + if (!!newValue) { + resolve.current!(newValue); + state.value = newValue; + } + + setState(createPromise(newValue)); + }, + [createPromise, state.value], + ), // eslint-disable-line @react-hook-utilities/exhaustive-deps ]; }; diff --git a/yarn.lock b/yarn.lock index 40f182d..2e324c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -40,6 +40,16 @@ source-map "^0.5.0" trim-right "^1.0.1" +"@babel/generator@^7.6.2": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369" + integrity sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg== + dependencies: + "@babel/types" "^7.7.4" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/helper-function-name@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" @@ -86,7 +96,12 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.6.0": +"@babel/parser@^7.0.0", "@babel/parser@^7.6.0", "@babel/parser@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1" + integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg== + +"@babel/parser@^7.1.0", "@babel/parser@^7.4.3": version "7.6.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.0.tgz#3e05d0647432a8326cb28d0de03895ae5a57f39b" integrity sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ== @@ -114,7 +129,22 @@ "@babel/parser" "^7.6.0" "@babel/types" "^7.6.0" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.6.0": +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c" + integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.6.2" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/parser" "^7.6.2" + "@babel/types" "^7.6.0" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/traverse@^7.4.3", "@babel/traverse@^7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.0.tgz#389391d510f79be7ce2ddd6717be66d3fed4b516" integrity sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ== @@ -138,6 +168,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" + integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@cnakazawa/watch@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" @@ -429,7 +468,7 @@ rimraf "^2.5.2" "@react-hook-utilities/eslint-plugin@./eslint-plugin": - version "1.0.0" + version "0.1.0" "@testing-library/react-hooks@^2.0.1": version "2.0.1" @@ -843,6 +882,18 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== +babel-eslint@^10.0.3: + 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== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + babel-jest@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54" @@ -1740,7 +1791,7 @@ eslint-utils@^1.4.3: dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.1.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== @@ -4569,7 +4620,7 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@1.x, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2: +resolve@1.x, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.3.2: version "1.12.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== From 2e7a9f696b2dd7bed90da409b30b5b14d9e76ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Caetano?= Date: Tue, 1 Oct 2019 16:32:26 -0300 Subject: [PATCH 3/4] docs(README): add ESLint plugin instructions --- README.md | 16 +++++++++++++++- eslint-plugin/README.md | 14 +++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 70ef41d..a7a0da7 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,21 @@ A state that only resolves after setting truthy values. # Typescript -react-hook-utilities sees Typescript is a first-class citizen. The library is built for and around Typescript and you'll get bonus points for using it. Nonetheless, pure JavaScript files are also available if you're _that_ guy. +**react-hook-utilities** sees Typescript is a first-class citizen. The library is built for and around Typescript and you'll get bonus points for using it. Nonetheless, pure JavaScript files are also available if you're _that_ guy. + +# ESLint + +If you're using ESLint and don't want to lose your errors and warnings regarding dependencies, **react-hook-utilities** comes packaged with an [ESLint plugin](eslint-plugin/README.md) to lint it's own hooks. It is recommended to install the plugin as a local dependency: + +```sh +$ yarn add -D ./node_modules/react-hook-utilities/eslint-plugin +``` + +We recommend you read the [full documentation](eslint-plugin/README.md) on how to use the ESLint plugin + +# Documentation + +The documentation is available at: https://fjcaetano.github.com/react-hook-utilities # [Full Documentation](https://fjcaetano.github.com/react-hook-utilities) diff --git a/eslint-plugin/README.md b/eslint-plugin/README.md index c73482f..a1cea19 100644 --- a/eslint-plugin/README.md +++ b/eslint-plugin/README.md @@ -1,22 +1,22 @@ # @react-hook-utilities/eslint-plugin -ESLint rules for hook utils +ESLint rules for hook react-hook-utilities ## Installation -You'll first need to install [ESLint](http://eslint.org): +You'll first need to install [ESLint](http://eslint.org) and [react-hook-utilities](https://www.npmjs.com/package/react-hook-utilities) ``` -$ npm i eslint --save-dev +$ npm i eslint react-hook-utilities --save-dev ``` -Next, install `@react-hook-utilities/eslint-plugin`: +Next, install `@react-hook-utilities/eslint-plugin` directly from the host dependency: ``` -$ npm install @react-hook-utilities/eslint-plugin --save-dev +$ npm install ./node_modules/react-hook-utilities/eslint-plugin --save-dev ``` -**Note:** If you installed ESLint globally (using the `-g` flag) then you must also install `@react-hook-utilities/eslint-plugin` globally. +**Note:** If you installed ESLint globally (using the `-g` flag) then you must also install `react-hook-utilities` globally. ## Usage @@ -43,7 +43,7 @@ Then configure the rules you want to use under the rules section. ## Supported Rules -* Fill in provided rules here +* exhaustive-deps: Ensures all hooks external references have been declared as dependencies. From b28dfc23d297d6ef05f888fb038d68503a35201e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Caetano?= Date: Tue, 1 Oct 2019 17:17:08 -0300 Subject: [PATCH 4/4] docs(ESLint): gen docs with ESLint plugin reference --- .gitignore | 3 ++- package.json | 5 +++-- scripts/gen-docs-index.sh | 5 ----- scripts/gen-docs.sh | 11 +++++++++++ tsconfig.json | 4 +++- yarn.lock | 5 +++++ 6 files changed, 24 insertions(+), 9 deletions(-) delete mode 100755 scripts/gen-docs-index.sh create mode 100755 scripts/gen-docs.sh diff --git a/.gitignore b/.gitignore index a5107aa..242f43b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules/ dist/ *.log coverage/ -docs/ \ No newline at end of file +docs/ +pageDocs/ \ No newline at end of file diff --git a/package.json b/package.json index bd91e4d..2fc0f89 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "build": "tsc && prettier --check 'dist/**/*' --write", "test": "jest --coverage", "lint": "eslint --ext=.ts,.tsx --max-warnings=0 src/ && prettier --check 'src/**/*'", - "docs": "typedoc --out docs/$npm_package_version && scripts/gen-docs-index.sh $npm_package_version", + "docs": "scripts/gen-docs.sh $npm_package_version", "version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md" }, "main": "dist/index.js", @@ -54,6 +54,7 @@ "react-test-renderer": "^16.9.0", "ts-jest": "^24.1.0", "typedoc": "^0.16.9", - "typescript": "^3.7" + "typescript": "^3.7", + "typedoc-plugin-markdown-pages": "^0.3.0" } } diff --git a/scripts/gen-docs-index.sh b/scripts/gen-docs-index.sh deleted file mode 100755 index 6c643e2..0000000 --- a/scripts/gen-docs-index.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -PKG_VERSION=$1 - -echo ";" > docs/index.html \ No newline at end of file diff --git a/scripts/gen-docs.sh b/scripts/gen-docs.sh new file mode 100755 index 0000000..7786187 --- /dev/null +++ b/scripts/gen-docs.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +PKG_VERSION=$1 + +mkdir pageDocs && ln -sf ../eslint-plugin/README.md pageDocs/EslintPlugin.md + +yarn run typedoc --out "docs/${PKG_VERSION}" + +echo ";" > docs/index.html + +rm -rf pageDocs \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index cdbdbeb..fce9ac4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,8 @@ }, "typedocOptions": { "exclude": "src/__tests__/**/*", - "out": "docs" + "out": "docs", + "mdPagesSourcePath": "pageDocs", + "theme": "markdown-pages" } } diff --git a/yarn.lock b/yarn.lock index 2e324c2..6a26720 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5371,6 +5371,11 @@ typedoc-default-themes@^0.7.2: lunr "^2.3.8" underscore "^1.9.1" +typedoc-plugin-markdown-pages@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown-pages/-/typedoc-plugin-markdown-pages-0.3.0.tgz#17f0f9ff3aa312e9ed142eb15ea216ea95d5fb5f" + integrity sha512-QVWs6eL0BEOiRgJm6wRRgE8kESFv85HlefLv14ZbMM2VQ1HqErVeT9ukbhkYMznsD/juAsX3Xc5M+Ju7/ZDq4Q== + typedoc@^0.16.9: version "0.16.9" resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.16.9.tgz#d6f46f4dea7d3362029927a92981efdf896f435b"