diff --git a/@plotly/dash-test-components/package-lock.json b/@plotly/dash-test-components/package-lock.json
index f127880c0e..e99d73699c 100644
--- a/@plotly/dash-test-components/package-lock.json
+++ b/@plotly/dash-test-components/package-lock.json
@@ -5,9 +5,9 @@
"requires": true,
"dependencies": {
"@babel/cli": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.8.4.tgz",
- "integrity": "sha512-XXLgAm6LBbaNxaGhMAznXXaxtCWfuv6PIDJ9Alsy9JYTOh+j2jJz+L/162kkfU1j/pTSxK1xGmlwI4pdIMkoag==",
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.11.5.tgz",
+ "integrity": "sha512-0umMDxxdEZ98EMZtS9Wgnaf4NdgqBcQHaGYaMfAmP+ZicVglZ2+QZwoHNacfnUq4hCmC1V7Ap5Phq7FInpWrWg==",
"dev": true,
"requires": {
"chokidar": "^2.1.8",
@@ -15,10 +15,10 @@
"convert-source-map": "^1.1.0",
"fs-readdir-recursive": "^1.1.0",
"glob": "^7.0.0",
- "lodash": "^4.17.13",
+ "lodash": "^4.17.19",
"make-dir": "^2.1.0",
"slash": "^2.0.0",
- "source-map": "^0.5.0"
+ "source-map": "^0.6.1"
},
"dependencies": {
"commander": {
@@ -26,57 +26,51 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
}
}
},
"@babel/code-frame": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
- "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
"dev": true,
"requires": {
- "@babel/highlight": "^7.8.3"
+ "@babel/highlight": "^7.10.4"
}
},
"@babel/compat-data": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.9.0.tgz",
- "integrity": "sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g==",
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz",
+ "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==",
"dev": true,
"requires": {
- "browserslist": "^4.9.1",
+ "browserslist": "^4.12.0",
"invariant": "^2.2.4",
"semver": "^5.5.0"
}
},
"@babel/core": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz",
- "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.8.3",
- "@babel/generator": "^7.9.0",
- "@babel/helper-module-transforms": "^7.9.0",
- "@babel/helpers": "^7.9.0",
- "@babel/parser": "^7.9.0",
- "@babel/template": "^7.8.6",
- "@babel/traverse": "^7.9.0",
- "@babel/types": "^7.9.0",
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.5.tgz",
+ "integrity": "sha512-fsEANVOcZHzrsV6dMVWqpSeXClq3lNbYrfFGme6DE25FQWe7pyeYpXyx9guqUnpy466JLzZ8z4uwSr2iv60V5Q==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.5",
+ "@babel/helper-module-transforms": "^7.11.0",
+ "@babel/helpers": "^7.10.4",
+ "@babel/parser": "^7.11.5",
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.11.5",
+ "@babel/types": "^7.11.5",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.1",
"json5": "^2.1.2",
- "lodash": "^4.17.13",
+ "lodash": "^4.17.19",
"resolve": "^1.3.2",
"semver": "^5.4.1",
- "source-map": "^0.5.0"
+ "source-map": "^0.6.1"
},
"dependencies": {
"debug": {
@@ -93,385 +87,432 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
}
}
},
"@babel/generator": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.5.tgz",
- "integrity": "sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==",
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.5.tgz",
+ "integrity": "sha512-9UqHWJ4IwRTy4l0o8gq2ef8ws8UPzvtMkVKjTLAiRmza9p9V6Z+OfuNd9fB1j5Q67F+dVJtPC2sZXI8NM9br4g==",
"dev": true,
"requires": {
- "@babel/types": "^7.9.5",
+ "@babel/types": "^7.11.5",
"jsesc": "^2.5.1",
- "lodash": "^4.17.13",
- "source-map": "^0.5.0"
- },
- "dependencies": {
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- }
+ "source-map": "^0.6.1"
}
},
"@babel/helper-annotate-as-pure": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz",
- "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
+ "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
"dev": true,
"requires": {
- "@babel/types": "^7.8.3"
+ "@babel/types": "^7.10.4"
}
},
"@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz",
- "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz",
+ "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==",
"dev": true,
"requires": {
- "@babel/helper-explode-assignable-expression": "^7.8.3",
- "@babel/types": "^7.8.3"
+ "@babel/helper-explode-assignable-expression": "^7.10.4",
+ "@babel/types": "^7.10.4"
}
},
"@babel/helper-builder-react-jsx": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.9.0.tgz",
- "integrity": "sha512-weiIo4gaoGgnhff54GQ3P5wsUQmnSwpkvU0r6ZHq6TzoSzKy4JxHEgnxNytaKbov2a9z/CVNyzliuCOUPEX3Jw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz",
+ "integrity": "sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg==",
"dev": true,
"requires": {
- "@babel/helper-annotate-as-pure": "^7.8.3",
- "@babel/types": "^7.9.0"
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/types": "^7.10.4"
}
},
"@babel/helper-builder-react-jsx-experimental": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.9.5.tgz",
- "integrity": "sha512-HAagjAC93tk748jcXpZ7oYRZH485RCq/+yEv9SIWezHRPv9moZArTnkUNciUNzvwHUABmiWKlcxJvMcu59UwTg==",
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.11.5.tgz",
+ "integrity": "sha512-Vc4aPJnRZKWfzeCBsqTBnzulVNjABVdahSPhtdMD3Vs80ykx4a87jTHtF/VR+alSrDmNvat7l13yrRHauGcHVw==",
"dev": true,
"requires": {
- "@babel/helper-annotate-as-pure": "^7.8.3",
- "@babel/helper-module-imports": "^7.8.3",
- "@babel/types": "^7.9.5"
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/types": "^7.11.5"
}
},
"@babel/helper-compilation-targets": {
- "version": "7.8.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz",
- "integrity": "sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz",
+ "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==",
"dev": true,
"requires": {
- "@babel/compat-data": "^7.8.6",
- "browserslist": "^4.9.1",
+ "@babel/compat-data": "^7.10.4",
+ "browserslist": "^4.12.0",
"invariant": "^2.2.4",
"levenary": "^1.1.1",
"semver": "^5.5.0"
}
},
+ "@babel/helper-create-class-features-plugin": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz",
+ "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-member-expression-to-functions": "^7.10.5",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4"
+ }
+ },
"@babel/helper-create-regexp-features-plugin": {
- "version": "7.8.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz",
- "integrity": "sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz",
+ "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==",
"dev": true,
"requires": {
- "@babel/helper-annotate-as-pure": "^7.8.3",
- "@babel/helper-regex": "^7.8.3",
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-regex": "^7.10.4",
"regexpu-core": "^4.7.0"
}
},
"@babel/helper-define-map": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz",
- "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz",
+ "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==",
"dev": true,
"requires": {
- "@babel/helper-function-name": "^7.8.3",
- "@babel/types": "^7.8.3",
- "lodash": "^4.17.13"
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/types": "^7.10.5",
+ "lodash": "^4.17.19"
}
},
"@babel/helper-explode-assignable-expression": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz",
- "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==",
+ "version": "7.11.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz",
+ "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==",
"dev": true,
"requires": {
- "@babel/traverse": "^7.8.3",
- "@babel/types": "^7.8.3"
+ "@babel/types": "^7.10.4"
}
},
"@babel/helper-function-name": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
- "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
"dev": true,
"requires": {
- "@babel/helper-get-function-arity": "^7.8.3",
- "@babel/template": "^7.8.3",
- "@babel/types": "^7.9.5"
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
}
},
"@babel/helper-get-function-arity": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz",
- "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
"dev": true,
"requires": {
- "@babel/types": "^7.8.3"
+ "@babel/types": "^7.10.4"
}
},
"@babel/helper-hoist-variables": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz",
- "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz",
+ "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==",
"dev": true,
"requires": {
- "@babel/types": "^7.8.3"
+ "@babel/types": "^7.10.4"
}
},
"@babel/helper-member-expression-to-functions": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz",
- "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==",
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
+ "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
"dev": true,
"requires": {
- "@babel/types": "^7.8.3"
+ "@babel/types": "^7.11.0"
}
},
"@babel/helper-module-imports": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz",
- "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
+ "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
"dev": true,
"requires": {
- "@babel/types": "^7.8.3"
+ "@babel/types": "^7.10.4"
}
},
"@babel/helper-module-transforms": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz",
- "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==",
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz",
+ "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==",
"dev": true,
"requires": {
- "@babel/helper-module-imports": "^7.8.3",
- "@babel/helper-replace-supers": "^7.8.6",
- "@babel/helper-simple-access": "^7.8.3",
- "@babel/helper-split-export-declaration": "^7.8.3",
- "@babel/template": "^7.8.6",
- "@babel/types": "^7.9.0",
- "lodash": "^4.17.13"
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.11.0",
+ "lodash": "^4.17.19"
}
},
"@babel/helper-optimise-call-expression": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz",
- "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+ "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
"dev": true,
"requires": {
- "@babel/types": "^7.8.3"
+ "@babel/types": "^7.10.4"
}
},
"@babel/helper-plugin-utils": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz",
- "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
"dev": true
},
"@babel/helper-regex": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz",
- "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz",
+ "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==",
"dev": true,
"requires": {
- "lodash": "^4.17.13"
+ "lodash": "^4.17.19"
}
},
"@babel/helper-remap-async-to-generator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz",
- "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==",
+ "version": "7.11.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz",
+ "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==",
"dev": true,
"requires": {
- "@babel/helper-annotate-as-pure": "^7.8.3",
- "@babel/helper-wrap-function": "^7.8.3",
- "@babel/template": "^7.8.3",
- "@babel/traverse": "^7.8.3",
- "@babel/types": "^7.8.3"
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-wrap-function": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
}
},
"@babel/helper-replace-supers": {
- "version": "7.8.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz",
- "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
+ "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
"dev": true,
"requires": {
- "@babel/helper-member-expression-to-functions": "^7.8.3",
- "@babel/helper-optimise-call-expression": "^7.8.3",
- "@babel/traverse": "^7.8.6",
- "@babel/types": "^7.8.6"
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
}
},
"@babel/helper-simple-access": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz",
- "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz",
+ "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz",
+ "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==",
"dev": true,
"requires": {
- "@babel/template": "^7.8.3",
- "@babel/types": "^7.8.3"
+ "@babel/types": "^7.11.0"
}
},
"@babel/helper-split-export-declaration": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz",
- "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==",
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+ "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
"dev": true,
"requires": {
- "@babel/types": "^7.8.3"
+ "@babel/types": "^7.11.0"
}
},
"@babel/helper-validator-identifier": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz",
- "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
"dev": true
},
"@babel/helper-wrap-function": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz",
- "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz",
+ "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==",
"dev": true,
"requires": {
- "@babel/helper-function-name": "^7.8.3",
- "@babel/template": "^7.8.3",
- "@babel/traverse": "^7.8.3",
- "@babel/types": "^7.8.3"
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
}
},
"@babel/helpers": {
- "version": "7.9.2",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz",
- "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz",
+ "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==",
"dev": true,
"requires": {
- "@babel/template": "^7.8.3",
- "@babel/traverse": "^7.9.0",
- "@babel/types": "^7.9.0"
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
}
},
"@babel/highlight": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
- "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
"dev": true,
"requires": {
- "@babel/helper-validator-identifier": "^7.9.0",
+ "@babel/helper-validator-identifier": "^7.10.4",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
},
"@babel/parser": {
- "version": "7.9.4",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz",
- "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA=="
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q=="
},
"@babel/plugin-proposal-async-generator-functions": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz",
- "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz",
+ "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/helper-remap-async-to-generator": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-remap-async-to-generator": "^7.10.4",
"@babel/plugin-syntax-async-generators": "^7.8.0"
}
},
+ "@babel/plugin-proposal-class-properties": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz",
+ "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
"@babel/plugin-proposal-dynamic-import": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz",
- "integrity": "sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz",
+ "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-dynamic-import": "^7.8.0"
}
},
+ "@babel/plugin-proposal-export-namespace-from": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz",
+ "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ }
+ },
"@babel/plugin-proposal-json-strings": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz",
- "integrity": "sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz",
+ "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-json-strings": "^7.8.0"
}
},
+ "@babel/plugin-proposal-logical-assignment-operators": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz",
+ "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ }
+ },
"@babel/plugin-proposal-nullish-coalescing-operator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz",
- "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz",
+ "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0"
}
},
"@babel/plugin-proposal-numeric-separator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz",
- "integrity": "sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/plugin-syntax-numeric-separator": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
}
},
"@babel/plugin-proposal-object-rest-spread": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz",
- "integrity": "sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg==",
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz",
+ "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-object-rest-spread": "^7.8.0",
- "@babel/plugin-transform-parameters": "^7.9.5"
+ "@babel/plugin-transform-parameters": "^7.10.4"
}
},
"@babel/plugin-proposal-optional-catch-binding": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz",
- "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz",
+ "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.0"
}
},
"@babel/plugin-proposal-optional-chaining": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz",
- "integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==",
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz",
+ "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0",
"@babel/plugin-syntax-optional-chaining": "^7.8.0"
}
},
+ "@babel/plugin-proposal-private-methods": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz",
+ "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
"@babel/plugin-proposal-unicode-property-regex": {
- "version": "7.8.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz",
- "integrity": "sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz",
+ "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==",
"dev": true,
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.8.8",
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-syntax-async-generators": {
@@ -483,6 +524,15 @@
"@babel/helper-plugin-utils": "^7.8.0"
}
},
+ "@babel/plugin-syntax-class-properties": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz",
+ "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
"@babel/plugin-syntax-dynamic-import": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
@@ -492,6 +542,15 @@
"@babel/helper-plugin-utils": "^7.8.0"
}
},
+ "@babel/plugin-syntax-export-namespace-from": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
"@babel/plugin-syntax-json-strings": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
@@ -502,12 +561,21 @@
}
},
"@babel/plugin-syntax-jsx": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz",
- "integrity": "sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz",
+ "integrity": "sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-syntax-nullish-coalescing-operator": {
@@ -520,12 +588,12 @@
}
},
"@babel/plugin-syntax-numeric-separator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz",
- "integrity": "sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-syntax-object-rest-spread": {
@@ -556,434 +624,461 @@
}
},
"@babel/plugin-syntax-top-level-await": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz",
- "integrity": "sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz",
+ "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-arrow-functions": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz",
- "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz",
+ "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-async-to-generator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz",
- "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz",
+ "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==",
"dev": true,
"requires": {
- "@babel/helper-module-imports": "^7.8.3",
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/helper-remap-async-to-generator": "^7.8.3"
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-remap-async-to-generator": "^7.10.4"
}
},
"@babel/plugin-transform-block-scoped-functions": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz",
- "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz",
+ "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-block-scoping": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz",
- "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==",
+ "version": "7.11.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz",
+ "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
- "lodash": "^4.17.13"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-classes": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz",
- "integrity": "sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg==",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.8.3",
- "@babel/helper-define-map": "^7.8.3",
- "@babel/helper-function-name": "^7.9.5",
- "@babel/helper-optimise-call-expression": "^7.8.3",
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/helper-replace-supers": "^7.8.6",
- "@babel/helper-split-export-declaration": "^7.8.3",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz",
+ "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-define-map": "^7.10.4",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4",
"globals": "^11.1.0"
}
},
"@babel/plugin-transform-computed-properties": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz",
- "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz",
+ "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-destructuring": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz",
- "integrity": "sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz",
+ "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-dotall-regex": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz",
- "integrity": "sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz",
+ "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==",
"dev": true,
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.8.3",
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-duplicate-keys": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz",
- "integrity": "sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz",
+ "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-exponentiation-operator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz",
- "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz",
+ "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==",
"dev": true,
"requires": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3",
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-for-of": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz",
- "integrity": "sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz",
+ "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-function-name": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz",
- "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz",
+ "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==",
"dev": true,
"requires": {
- "@babel/helper-function-name": "^7.8.3",
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-literals": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz",
- "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz",
+ "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-member-expression-literals": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz",
- "integrity": "sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz",
+ "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-modules-amd": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz",
- "integrity": "sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz",
+ "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==",
"dev": true,
"requires": {
- "@babel/helper-module-transforms": "^7.9.0",
- "@babel/helper-plugin-utils": "^7.8.3",
- "babel-plugin-dynamic-import-node": "^2.3.0"
+ "@babel/helper-module-transforms": "^7.10.5",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
}
},
"@babel/plugin-transform-modules-commonjs": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz",
- "integrity": "sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz",
+ "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==",
"dev": true,
"requires": {
- "@babel/helper-module-transforms": "^7.9.0",
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/helper-simple-access": "^7.8.3",
- "babel-plugin-dynamic-import-node": "^2.3.0"
+ "@babel/helper-module-transforms": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
}
},
"@babel/plugin-transform-modules-systemjs": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz",
- "integrity": "sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz",
+ "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==",
"dev": true,
"requires": {
- "@babel/helper-hoist-variables": "^7.8.3",
- "@babel/helper-module-transforms": "^7.9.0",
- "@babel/helper-plugin-utils": "^7.8.3",
- "babel-plugin-dynamic-import-node": "^2.3.0"
+ "@babel/helper-hoist-variables": "^7.10.4",
+ "@babel/helper-module-transforms": "^7.10.5",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
}
},
"@babel/plugin-transform-modules-umd": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz",
- "integrity": "sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz",
+ "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==",
"dev": true,
"requires": {
- "@babel/helper-module-transforms": "^7.9.0",
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-module-transforms": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz",
- "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz",
+ "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==",
"dev": true,
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.8.3"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4"
}
},
"@babel/plugin-transform-new-target": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz",
- "integrity": "sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz",
+ "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-object-super": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz",
- "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz",
+ "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/helper-replace-supers": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4"
}
},
"@babel/plugin-transform-parameters": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz",
- "integrity": "sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz",
+ "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==",
"dev": true,
"requires": {
- "@babel/helper-get-function-arity": "^7.8.3",
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-property-literals": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz",
- "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz",
+ "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-react-display-name": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz",
- "integrity": "sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.4.tgz",
+ "integrity": "sha512-Zd4X54Mu9SBfPGnEcaGcOrVAYOtjT2on8QZkLKEq1S/tHexG39d9XXGZv19VfRrDjPJzFmPfTAqOQS1pfFOujw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-react-jsx": {
- "version": "7.9.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz",
- "integrity": "sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz",
+ "integrity": "sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A==",
"dev": true,
"requires": {
- "@babel/helper-builder-react-jsx": "^7.9.0",
- "@babel/helper-builder-react-jsx-experimental": "^7.9.0",
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/plugin-syntax-jsx": "^7.8.3"
+ "@babel/helper-builder-react-jsx": "^7.10.4",
+ "@babel/helper-builder-react-jsx-experimental": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-jsx": "^7.10.4"
}
},
"@babel/plugin-transform-react-jsx-development": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.9.0.tgz",
- "integrity": "sha512-tK8hWKrQncVvrhvtOiPpKrQjfNX3DtkNLSX4ObuGcpS9p0QrGetKmlySIGR07y48Zft8WVgPakqd/bk46JrMSw==",
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.11.5.tgz",
+ "integrity": "sha512-cImAmIlKJ84sDmpQzm4/0q/2xrXlDezQoixy3qoz1NJeZL/8PRon6xZtluvr4H4FzwlDGI5tCcFupMnXGtr+qw==",
"dev": true,
"requires": {
- "@babel/helper-builder-react-jsx-experimental": "^7.9.0",
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/plugin-syntax-jsx": "^7.8.3"
+ "@babel/helper-builder-react-jsx-experimental": "^7.11.5",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-jsx": "^7.10.4"
}
},
"@babel/plugin-transform-react-jsx-self": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.9.0.tgz",
- "integrity": "sha512-K2ObbWPKT7KUTAoyjCsFilOkEgMvFG+y0FqOl6Lezd0/13kMkkjHskVsZvblRPj1PHA44PrToaZANrryppzTvQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz",
+ "integrity": "sha512-yOvxY2pDiVJi0axdTWHSMi5T0DILN+H+SaeJeACHKjQLezEzhLx9nEF9xgpBLPtkZsks9cnb5P9iBEi21En3gg==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/plugin-syntax-jsx": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-jsx": "^7.10.4"
}
},
"@babel/plugin-transform-react-jsx-source": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.9.0.tgz",
- "integrity": "sha512-K6m3LlSnTSfRkM6FcRk8saNEeaeyG5k7AVkBU2bZK3+1zdkSED3qNdsWrUgQBeTVD2Tp3VMmerxVO2yM5iITmw==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.5.tgz",
+ "integrity": "sha512-wTeqHVkN1lfPLubRiZH3o73f4rfon42HpgxUSs86Nc+8QIcm/B9s8NNVXu/gwGcOyd7yDib9ikxoDLxJP0UiDA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/plugin-syntax-jsx": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-jsx": "^7.10.4"
+ }
+ },
+ "@babel/plugin-transform-react-pure-annotations": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz",
+ "integrity": "sha512-+njZkqcOuS8RaPakrnR9KvxjoG1ASJWpoIv/doyWngId88JoFlPlISenGXjrVacZUIALGUr6eodRs1vmPnF23A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-regenerator": {
- "version": "7.8.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz",
- "integrity": "sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz",
+ "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==",
"dev": true,
"requires": {
"regenerator-transform": "^0.14.2"
}
},
"@babel/plugin-transform-reserved-words": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz",
- "integrity": "sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz",
+ "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-shorthand-properties": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz",
- "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz",
+ "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-spread": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz",
- "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==",
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz",
+ "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0"
}
},
"@babel/plugin-transform-sticky-regex": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz",
- "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz",
+ "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/helper-regex": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-regex": "^7.10.4"
}
},
"@babel/plugin-transform-template-literals": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz",
- "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz",
+ "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==",
"dev": true,
"requires": {
- "@babel/helper-annotate-as-pure": "^7.8.3",
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-typeof-symbol": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz",
- "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz",
+ "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-transform-unicode-escapes": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz",
+ "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-unicode-regex": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz",
- "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz",
+ "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==",
"dev": true,
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.8.3",
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/preset-env": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.5.tgz",
- "integrity": "sha512-eWGYeADTlPJH+wq1F0wNfPbVS1w1wtmMJiYk55Td5Yu28AsdR9AsC97sZ0Qq8fHqQuslVSIYSGJMcblr345GfQ==",
- "dev": true,
- "requires": {
- "@babel/compat-data": "^7.9.0",
- "@babel/helper-compilation-targets": "^7.8.7",
- "@babel/helper-module-imports": "^7.8.3",
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/plugin-proposal-async-generator-functions": "^7.8.3",
- "@babel/plugin-proposal-dynamic-import": "^7.8.3",
- "@babel/plugin-proposal-json-strings": "^7.8.3",
- "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-proposal-numeric-separator": "^7.8.3",
- "@babel/plugin-proposal-object-rest-spread": "^7.9.5",
- "@babel/plugin-proposal-optional-catch-binding": "^7.8.3",
- "@babel/plugin-proposal-optional-chaining": "^7.9.0",
- "@babel/plugin-proposal-unicode-property-regex": "^7.8.3",
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.5.tgz",
+ "integrity": "sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.11.0",
+ "@babel/helper-compilation-targets": "^7.10.4",
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-proposal-async-generator-functions": "^7.10.4",
+ "@babel/plugin-proposal-class-properties": "^7.10.4",
+ "@babel/plugin-proposal-dynamic-import": "^7.10.4",
+ "@babel/plugin-proposal-export-namespace-from": "^7.10.4",
+ "@babel/plugin-proposal-json-strings": "^7.10.4",
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
+ "@babel/plugin-proposal-numeric-separator": "^7.10.4",
+ "@babel/plugin-proposal-object-rest-spread": "^7.11.0",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.10.4",
+ "@babel/plugin-proposal-optional-chaining": "^7.11.0",
+ "@babel/plugin-proposal-private-methods": "^7.10.4",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.10.4",
"@babel/plugin-syntax-async-generators": "^7.8.0",
+ "@babel/plugin-syntax-class-properties": "^7.10.4",
"@babel/plugin-syntax-dynamic-import": "^7.8.0",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
"@babel/plugin-syntax-json-strings": "^7.8.0",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0",
- "@babel/plugin-syntax-numeric-separator": "^7.8.0",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
"@babel/plugin-syntax-object-rest-spread": "^7.8.0",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.0",
"@babel/plugin-syntax-optional-chaining": "^7.8.0",
- "@babel/plugin-syntax-top-level-await": "^7.8.3",
- "@babel/plugin-transform-arrow-functions": "^7.8.3",
- "@babel/plugin-transform-async-to-generator": "^7.8.3",
- "@babel/plugin-transform-block-scoped-functions": "^7.8.3",
- "@babel/plugin-transform-block-scoping": "^7.8.3",
- "@babel/plugin-transform-classes": "^7.9.5",
- "@babel/plugin-transform-computed-properties": "^7.8.3",
- "@babel/plugin-transform-destructuring": "^7.9.5",
- "@babel/plugin-transform-dotall-regex": "^7.8.3",
- "@babel/plugin-transform-duplicate-keys": "^7.8.3",
- "@babel/plugin-transform-exponentiation-operator": "^7.8.3",
- "@babel/plugin-transform-for-of": "^7.9.0",
- "@babel/plugin-transform-function-name": "^7.8.3",
- "@babel/plugin-transform-literals": "^7.8.3",
- "@babel/plugin-transform-member-expression-literals": "^7.8.3",
- "@babel/plugin-transform-modules-amd": "^7.9.0",
- "@babel/plugin-transform-modules-commonjs": "^7.9.0",
- "@babel/plugin-transform-modules-systemjs": "^7.9.0",
- "@babel/plugin-transform-modules-umd": "^7.9.0",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3",
- "@babel/plugin-transform-new-target": "^7.8.3",
- "@babel/plugin-transform-object-super": "^7.8.3",
- "@babel/plugin-transform-parameters": "^7.9.5",
- "@babel/plugin-transform-property-literals": "^7.8.3",
- "@babel/plugin-transform-regenerator": "^7.8.7",
- "@babel/plugin-transform-reserved-words": "^7.8.3",
- "@babel/plugin-transform-shorthand-properties": "^7.8.3",
- "@babel/plugin-transform-spread": "^7.8.3",
- "@babel/plugin-transform-sticky-regex": "^7.8.3",
- "@babel/plugin-transform-template-literals": "^7.8.3",
- "@babel/plugin-transform-typeof-symbol": "^7.8.4",
- "@babel/plugin-transform-unicode-regex": "^7.8.3",
+ "@babel/plugin-syntax-top-level-await": "^7.10.4",
+ "@babel/plugin-transform-arrow-functions": "^7.10.4",
+ "@babel/plugin-transform-async-to-generator": "^7.10.4",
+ "@babel/plugin-transform-block-scoped-functions": "^7.10.4",
+ "@babel/plugin-transform-block-scoping": "^7.10.4",
+ "@babel/plugin-transform-classes": "^7.10.4",
+ "@babel/plugin-transform-computed-properties": "^7.10.4",
+ "@babel/plugin-transform-destructuring": "^7.10.4",
+ "@babel/plugin-transform-dotall-regex": "^7.10.4",
+ "@babel/plugin-transform-duplicate-keys": "^7.10.4",
+ "@babel/plugin-transform-exponentiation-operator": "^7.10.4",
+ "@babel/plugin-transform-for-of": "^7.10.4",
+ "@babel/plugin-transform-function-name": "^7.10.4",
+ "@babel/plugin-transform-literals": "^7.10.4",
+ "@babel/plugin-transform-member-expression-literals": "^7.10.4",
+ "@babel/plugin-transform-modules-amd": "^7.10.4",
+ "@babel/plugin-transform-modules-commonjs": "^7.10.4",
+ "@babel/plugin-transform-modules-systemjs": "^7.10.4",
+ "@babel/plugin-transform-modules-umd": "^7.10.4",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4",
+ "@babel/plugin-transform-new-target": "^7.10.4",
+ "@babel/plugin-transform-object-super": "^7.10.4",
+ "@babel/plugin-transform-parameters": "^7.10.4",
+ "@babel/plugin-transform-property-literals": "^7.10.4",
+ "@babel/plugin-transform-regenerator": "^7.10.4",
+ "@babel/plugin-transform-reserved-words": "^7.10.4",
+ "@babel/plugin-transform-shorthand-properties": "^7.10.4",
+ "@babel/plugin-transform-spread": "^7.11.0",
+ "@babel/plugin-transform-sticky-regex": "^7.10.4",
+ "@babel/plugin-transform-template-literals": "^7.10.4",
+ "@babel/plugin-transform-typeof-symbol": "^7.10.4",
+ "@babel/plugin-transform-unicode-escapes": "^7.10.4",
+ "@babel/plugin-transform-unicode-regex": "^7.10.4",
"@babel/preset-modules": "^0.1.3",
- "@babel/types": "^7.9.5",
- "browserslist": "^4.9.1",
+ "@babel/types": "^7.11.5",
+ "browserslist": "^4.12.0",
"core-js-compat": "^3.6.2",
"invariant": "^2.2.2",
"levenary": "^1.1.1",
@@ -991,9 +1086,9 @@
}
},
"@babel/preset-modules": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz",
- "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==",
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz",
+ "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
@@ -1004,53 +1099,54 @@
}
},
"@babel/preset-react": {
- "version": "7.9.4",
- "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.9.4.tgz",
- "integrity": "sha512-AxylVB3FXeOTQXNXyiuAQJSvss62FEotbX2Pzx3K/7c+MKJMdSg6Ose6QYllkdCFA8EInCJVw7M/o5QbLuA4ZQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.10.4.tgz",
+ "integrity": "sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.8.3",
- "@babel/plugin-transform-react-display-name": "^7.8.3",
- "@babel/plugin-transform-react-jsx": "^7.9.4",
- "@babel/plugin-transform-react-jsx-development": "^7.9.0",
- "@babel/plugin-transform-react-jsx-self": "^7.9.0",
- "@babel/plugin-transform-react-jsx-source": "^7.9.0"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-transform-react-display-name": "^7.10.4",
+ "@babel/plugin-transform-react-jsx": "^7.10.4",
+ "@babel/plugin-transform-react-jsx-development": "^7.10.4",
+ "@babel/plugin-transform-react-jsx-self": "^7.10.4",
+ "@babel/plugin-transform-react-jsx-source": "^7.10.4",
+ "@babel/plugin-transform-react-pure-annotations": "^7.10.4"
}
},
"@babel/runtime": {
- "version": "7.9.2",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
- "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==",
+ "version": "7.11.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz",
+ "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
},
"@babel/template": {
- "version": "7.8.6",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
- "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
"dev": true,
"requires": {
- "@babel/code-frame": "^7.8.3",
- "@babel/parser": "^7.8.6",
- "@babel/types": "^7.8.6"
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
}
},
"@babel/traverse": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz",
- "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==",
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
+ "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
"dev": true,
"requires": {
- "@babel/code-frame": "^7.8.3",
- "@babel/generator": "^7.9.5",
- "@babel/helper-function-name": "^7.9.5",
- "@babel/helper-split-export-declaration": "^7.8.3",
- "@babel/parser": "^7.9.0",
- "@babel/types": "^7.9.5",
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.5",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
"debug": "^4.1.0",
"globals": "^11.1.0",
- "lodash": "^4.17.13"
+ "lodash": "^4.17.19"
},
"dependencies": {
"debug": {
@@ -1071,13 +1167,13 @@
}
},
"@babel/types": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz",
- "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==",
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
"dev": true,
"requires": {
- "@babel/helper-validator-identifier": "^7.9.5",
- "lodash": "^4.17.13",
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
"to-fast-properties": "^2.0.0"
}
},
@@ -1274,6 +1370,12 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"dev": true
},
+ "acorn": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
+ "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
+ "dev": true
+ },
"acorn-jsx": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz",
@@ -1281,9 +1383,9 @@
"dev": true
},
"ajv": {
- "version": "6.12.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
- "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==",
+ "version": "6.12.4",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
+ "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
@@ -1299,9 +1401,9 @@
"dev": true
},
"ajv-keywords": {
- "version": "3.4.1",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
- "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
"dev": true
},
"ansi-regex": {
@@ -1372,6 +1474,26 @@
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
"dev": true
},
+ "asn1.js": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
+ "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "safer-buffer": "^2.1.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+ "dev": true
+ }
+ }
+ },
"assert": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
@@ -1445,9 +1567,9 @@
}
},
"babel-plugin-dynamic-import-node": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz",
- "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==",
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
"dev": true,
"requires": {
"object.assign": "^4.1.0"
@@ -1549,9 +1671,9 @@
"dev": true
},
"bn.js": {
- "version": "4.11.8",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
- "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
+ "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==",
"dev": true
},
"brace-expansion": {
@@ -1643,21 +1765,50 @@
"requires": {
"bn.js": "^4.1.0",
"randombytes": "^2.0.1"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+ "dev": true
+ }
}
},
"browserify-sign": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
- "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
- "dev": true,
- "requires": {
- "bn.js": "^4.1.1",
- "browserify-rsa": "^4.0.0",
- "create-hash": "^1.1.0",
- "create-hmac": "^1.1.2",
- "elliptic": "^6.0.0",
- "inherits": "^2.0.1",
- "parse-asn1": "^5.0.0"
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
+ "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^5.1.1",
+ "browserify-rsa": "^4.0.1",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "elliptic": "^6.5.3",
+ "inherits": "^2.0.4",
+ "parse-asn1": "^5.1.5",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true
+ }
}
},
"browserify-zlib": {
@@ -1670,15 +1821,15 @@
}
},
"browserslist": {
- "version": "4.11.1",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.11.1.tgz",
- "integrity": "sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g==",
+ "version": "4.14.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz",
+ "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==",
"dev": true,
"requires": {
- "caniuse-lite": "^1.0.30001038",
- "electron-to-chromium": "^1.3.390",
- "node-releases": "^1.1.53",
- "pkg-up": "^2.0.0"
+ "caniuse-lite": "^1.0.30001111",
+ "electron-to-chromium": "^1.3.523",
+ "escalade": "^3.0.2",
+ "node-releases": "^1.1.60"
}
},
"buffer": {
@@ -1757,9 +1908,9 @@
"dev": true
},
"caniuse-lite": {
- "version": "1.0.30001042",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001042.tgz",
- "integrity": "sha512-igMQ4dlqnf4tWv0xjaaE02op9AJ2oQzXKjWf4EuAHFN694Uo9/EfPVIPJcmn2WkU9RqozCxx5e2KPcVClHDbDw==",
+ "version": "1.0.30001123",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001123.tgz",
+ "integrity": "sha512-03dJDoa4YC4332jq0rqwiM+Hw6tA5RJtrnZKvOQy7ASoIUv8CinkcmGhYpCvCjedvkBQrrKnkcELxrUSW/XwNQ==",
"dev": true
},
"chalk": {
@@ -1984,13 +2135,21 @@
"dev": true
},
"create-ecdh": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
- "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
+ "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
"dev": true,
"requires": {
"bn.js": "^4.1.0",
- "elliptic": "^6.0.0"
+ "elliptic": "^6.5.3"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+ "dev": true
+ }
}
},
"create-hash": {
@@ -2154,6 +2313,14 @@
"bn.js": "^4.1.0",
"miller-rabin": "^4.0.0",
"randombytes": "^2.0.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+ "dev": true
+ }
}
},
"doctrine": {
@@ -2183,15 +2350,15 @@
}
},
"electron-to-chromium": {
- "version": "1.3.410",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.410.tgz",
- "integrity": "sha512-DbCBdwtARI0l3e3m6ZIxVaTNahb6dSsmGjuag/twiVcWuM4MSpL5IfsJsJSyqLqxosE/m0CXlZaBmxegQW/dAg==",
+ "version": "1.3.560",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.560.tgz",
+ "integrity": "sha512-0cEFfOA3sNXfSxo0FIClBhrLVSe/QO9LBiqmmYPm3N/IYyt41NRTa2EhvOMWAOKpjd91t/rq062yhnJzfVMKkQ==",
"dev": true
},
"elliptic": {
- "version": "6.5.2",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz",
- "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==",
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
+ "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==",
"dev": true,
"requires": {
"bn.js": "^4.4.0",
@@ -2201,6 +2368,14 @@
"inherits": "^2.0.1",
"minimalistic-assert": "^1.0.0",
"minimalistic-crypto-utils": "^1.0.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+ "dev": true
+ }
}
},
"emoji-regex": {
@@ -2225,9 +2400,9 @@
}
},
"enhanced-resolve": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz",
- "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz",
+ "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
@@ -2266,22 +2441,22 @@
}
},
"es-abstract": {
- "version": "1.17.5",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
- "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
+ "version": "1.17.6",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
+ "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
"dev": true,
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
- "is-callable": "^1.1.5",
- "is-regex": "^1.0.5",
+ "is-callable": "^1.2.0",
+ "is-regex": "^1.1.0",
"object-inspect": "^1.7.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.0",
- "string.prototype.trimleft": "^2.1.1",
- "string.prototype.trimright": "^2.1.1"
+ "string.prototype.trimend": "^1.0.1",
+ "string.prototype.trimstart": "^1.0.1"
}
},
"es-to-primitive": {
@@ -2293,19 +2468,14 @@
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
"is-symbol": "^1.0.2"
- },
- "dependencies": {
- "is-symbol": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
- "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.1"
- }
- }
}
},
+ "escalade": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz",
+ "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==",
+ "dev": true
+ },
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@@ -2328,12 +2498,20 @@
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
"esrecurse": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
- "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
"requires": {
- "estraverse": "^4.1.0"
+ "estraverse": "^5.2.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+ "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+ "dev": true
+ }
}
},
"estraverse": {
@@ -2348,9 +2526,9 @@
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
},
"events": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
- "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
+ "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==",
"dev": true
},
"evp_bytestokey": {
@@ -2494,9 +2672,9 @@
}
},
"fast-deep-equal": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
- "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
"fast-json-stable-stringify": {
@@ -2529,726 +2707,120 @@
"repeat-string": "^1.6.1",
"to-regex-range": "^2.1.0"
},
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "find-cache-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
- "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
- "dev": true,
- "requires": {
- "commondir": "^1.0.1",
- "make-dir": "^2.0.0",
- "pkg-dir": "^3.0.0"
- }
- },
- "find-up": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
- "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
- "dev": true,
- "requires": {
- "locate-path": "^2.0.0"
- }
- },
- "findup-sync": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz",
- "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==",
- "dev": true,
- "requires": {
- "detect-file": "^1.0.0",
- "is-glob": "^4.0.0",
- "micromatch": "^3.0.4",
- "resolve-dir": "^1.0.1"
- }
- },
- "flush-write-stream": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
- "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "readable-stream": "^2.3.6"
- }
- },
- "for-in": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
- "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
- "dev": true
- },
- "fragment-cache": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
- "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
- "dev": true,
- "requires": {
- "map-cache": "^0.2.2"
- }
- },
- "from2": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
- "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "readable-stream": "^2.0.0"
- }
- },
- "fs-readdir-recursive": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
- "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
- "dev": true
- },
- "fs-write-stream-atomic": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
- "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "iferr": "^0.1.5",
- "imurmurhash": "^0.1.4",
- "readable-stream": "1 || 2"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
- "dev": true
- },
- "fsevents": {
- "version": "1.2.12",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz",
- "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==",
- "dev": true,
- "optional": true,
- "requires": {
- "bindings": "^1.5.0",
- "nan": "^2.12.1",
- "node-pre-gyp": "*"
- },
- "dependencies": {
- "abbrev": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
- "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
- "dev": true,
- "optional": true
- },
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true,
- "optional": true
- },
- "aproba": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
- "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
- "dev": true,
- "optional": true
- },
- "are-we-there-yet": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
- "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
- "dev": true,
- "optional": true,
- "requires": {
- "delegates": "^1.0.0",
- "readable-stream": "^2.0.6"
- }
- },
- "balanced-match": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true,
- "optional": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "optional": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "dev": true,
- "optional": true
- },
- "code-point-at": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
- "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true,
- "optional": true
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true,
- "optional": true
- },
- "console-control-strings": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
- "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
- "dev": true,
- "optional": true
- },
- "core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
- "dev": true,
- "optional": true
- },
- "debug": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
- "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "dev": true,
- "optional": true
- },
- "delegates": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
- "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
- "dev": true,
- "optional": true
- },
- "detect-libc": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
- "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
- "dev": true,
- "optional": true
- },
- "fs-minipass": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
- "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
- "dev": true,
- "optional": true,
- "requires": {
- "minipass": "^2.6.0"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
- "dev": true,
- "optional": true
- },
- "gauge": {
- "version": "2.7.4",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
- "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
- "dev": true,
- "optional": true,
- "requires": {
- "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"
- }
- },
- "glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "dev": true,
- "optional": true,
- "requires": {
- "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"
- }
- },
- "has-unicode": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
- "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
- "dev": true,
- "optional": true
- },
- "iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "dev": true,
- "optional": true,
- "requires": {
- "safer-buffer": ">= 2.1.2 < 3"
- }
- },
- "ignore-walk": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
- "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
- "dev": true,
- "optional": true,
- "requires": {
- "minimatch": "^3.0.4"
- }
- },
- "inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
- "dev": true,
- "optional": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true,
- "optional": true
- },
- "ini": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
- "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
- "dev": true,
- "optional": true
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "dev": true,
- "optional": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
- "dev": true,
- "optional": true
- },
- "minimatch": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
- "dev": true,
- "optional": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
- "dev": true,
- "optional": true
- },
- "minipass": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
- "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
- "dev": true,
- "optional": true,
- "requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
- }
- },
- "minizlib": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
- "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
- "dev": true,
- "optional": true,
- "requires": {
- "minipass": "^2.9.0"
- }
- },
- "mkdirp": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz",
- "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==",
- "dev": true,
- "optional": true,
- "requires": {
- "minimist": "^1.2.5"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true,
- "optional": true
- },
- "needle": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.3.tgz",
- "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==",
- "dev": true,
- "optional": true,
- "requires": {
- "debug": "^3.2.6",
- "iconv-lite": "^0.4.4",
- "sax": "^1.2.4"
- }
- },
- "node-pre-gyp": {
- "version": "0.14.0",
- "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz",
- "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==",
- "dev": true,
- "optional": true,
- "requires": {
- "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.4.2"
- }
- },
- "nopt": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
- "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
- "dev": true,
- "optional": true,
- "requires": {
- "abbrev": "1",
- "osenv": "^0.1.4"
- }
- },
- "npm-bundled": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
- "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
- "dev": true,
- "optional": true,
- "requires": {
- "npm-normalize-package-bin": "^1.0.1"
- }
- },
- "npm-normalize-package-bin": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
- "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
- "dev": true,
- "optional": true
- },
- "npm-packlist": {
- "version": "1.4.8",
- "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
- "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
- "dev": true,
- "optional": true,
- "requires": {
- "ignore-walk": "^3.0.1",
- "npm-bundled": "^1.0.1",
- "npm-normalize-package-bin": "^1.0.1"
- }
- },
- "npmlog": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
- "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
- "dev": true,
- "optional": true,
- "requires": {
- "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": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
- "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true,
- "optional": true
- },
- "object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
- "dev": true,
- "optional": true
- },
- "once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "dev": true,
- "optional": true,
- "requires": {
- "wrappy": "1"
- }
- },
- "os-homedir": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
- "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
- "dev": true,
- "optional": true
- },
- "os-tmpdir": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
- "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
- "dev": true,
- "optional": true
- },
- "osenv": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
- "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
- "dev": true,
- "optional": true,
- "requires": {
- "os-homedir": "^1.0.0",
- "os-tmpdir": "^1.0.0"
- }
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
- "dev": true,
- "optional": true
- },
- "process-nextick-args": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "dev": true,
- "optional": true
- },
- "rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "dev": true,
- "optional": true,
- "requires": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- }
- },
- "readable-stream": {
- "version": "2.3.7",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
- "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
- "dev": true,
- "optional": true,
- "requires": {
- "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"
- }
- },
- "rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
- "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
- "dev": true,
- "optional": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true,
- "optional": true
- },
- "safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true,
- "optional": true
- },
- "sax": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
- "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
- "dev": true,
- "optional": true
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true,
- "optional": true
- },
- "set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
- "dev": true,
- "optional": true
- },
- "signal-exit": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
- "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
- "dev": true,
- "optional": true
- },
- "string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
- "dev": true,
- "optional": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "dev": true,
- "optional": true,
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "optional": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- },
- "strip-json-comments": {
+ "dependencies": {
+ "extend-shallow": {
"version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
- "dev": true,
- "optional": true
- },
- "tar": {
- "version": "4.4.13",
- "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
- "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
- "dev": true,
- "optional": true,
- "requires": {
- "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"
- }
- },
- "util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
- "dev": true,
- "optional": true
- },
- "wide-align": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
- "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
- "optional": true,
"requires": {
- "string-width": "^1.0.2 || 2"
+ "is-extendable": "^0.1.0"
}
- },
- "wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "dev": true,
- "optional": true
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true,
- "optional": true
}
}
},
+ "find-cache-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+ "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^2.0.0",
+ "pkg-dir": "^3.0.0"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "findup-sync": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz",
+ "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==",
+ "dev": true,
+ "requires": {
+ "detect-file": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "micromatch": "^3.0.4",
+ "resolve-dir": "^1.0.1"
+ }
+ },
+ "flush-write-stream": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
+ "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.3.6"
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "from2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
+ }
+ },
+ "fs-readdir-recursive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
+ "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
+ "dev": true
+ },
+ "fs-write-stream-atomic": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+ "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "iferr": "^0.1.5",
+ "imurmurhash": "^0.1.4",
+ "readable-stream": "1 || 2"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
+ },
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -3352,9 +2924,9 @@
"dev": true
},
"graceful-fs": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
- "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+ "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
"dev": true
},
"has": {
@@ -3411,13 +2983,33 @@
}
},
"hash-base": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
- "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+ "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
"dev": true,
"requires": {
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true
+ }
}
},
"hash.js": {
@@ -3518,6 +3110,12 @@
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
"dev": true
},
+ "interpret": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
+ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
+ "dev": true
+ },
"invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@@ -3570,9 +3168,9 @@
"dev": true
},
"is-callable": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
- "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
+ "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
"dev": true
},
"is-data-descriptor": {
@@ -3677,12 +3275,21 @@
}
},
"is-regex": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
- "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
+ "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "is-symbol": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
+ "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
"dev": true,
"requires": {
- "has": "^1.0.3"
+ "has-symbols": "^1.0.1"
}
},
"is-windows": {
@@ -3817,12 +3424,12 @@
}
},
"locate-path": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
- "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"requires": {
- "p-locate": "^2.0.0",
+ "p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
@@ -3929,6 +3536,14 @@
"requires": {
"bn.js": "^4.0.0",
"brorand": "^1.0.1"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+ "dev": true
+ }
}
},
"minimalistic-assert": {
@@ -4246,27 +3861,27 @@
"dev": true
},
"p-limit": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
- "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"requires": {
- "p-try": "^1.0.0"
+ "p-try": "^2.0.0"
}
},
"p-locate": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
- "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"requires": {
- "p-limit": "^1.1.0"
+ "p-limit": "^2.0.0"
}
},
"p-try": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
- "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
"pako": {
@@ -4297,20 +3912,6 @@
"evp_bytestokey": "^1.0.0",
"pbkdf2": "^3.0.3",
"safe-buffer": "^5.1.1"
- },
- "dependencies": {
- "asn1.js": {
- "version": "5.4.1",
- "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
- "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
- "dev": true,
- "requires": {
- "bn.js": "^4.0.0",
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0",
- "safer-buffer": "^2.1.0"
- }
- }
}
},
"parse-json": {
@@ -4428,60 +4029,6 @@
"dev": true,
"requires": {
"find-up": "^3.0.0"
- },
- "dependencies": {
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true
- }
- }
- },
- "pkg-up": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
- "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
- "dev": true,
- "requires": {
- "find-up": "^2.1.0"
}
},
"posix-character-classes": {
@@ -4541,6 +4088,14 @@
"parse-asn1": "^5.0.0",
"randombytes": "^2.0.1",
"safe-buffer": "^5.1.2"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+ "dev": true
+ }
}
},
"pump": {
@@ -4664,14 +4219,6 @@
"acorn": "^7.2.0",
"acorn-jsx": "^5.2.0",
"core-js": "^3.6.5"
- },
- "dependencies": {
- "acorn": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
- "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
- "dev": true
- }
}
},
"read-pkg": {
@@ -4957,26 +4504,6 @@
"@types/json-schema": "^7.0.5",
"ajv": "^6.12.4",
"ajv-keywords": "^3.5.2"
- },
- "dependencies": {
- "ajv": {
- "version": "6.12.4",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
- "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
- "dev": true,
- "requires": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
- "ajv-keywords": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
- "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true
- }
}
},
"semver": {
@@ -5360,28 +4887,6 @@
"es-abstract": "^1.17.5"
}
},
- "string.prototype.trimleft": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
- "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5",
- "string.prototype.trimstart": "^1.0.0"
- }
- },
- "string.prototype.trimright": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
- "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5",
- "string.prototype.trimend": "^1.0.0"
- }
- },
"string.prototype.trimstart": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
@@ -5922,29 +5427,6 @@
"integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
"dev": true
},
- "enhanced-resolve": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz",
- "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "memory-fs": "^0.5.0",
- "tapable": "^1.0.0"
- },
- "dependencies": {
- "memory-fs": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
- "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
- "dev": true,
- "requires": {
- "errno": "^0.1.3",
- "readable-stream": "^2.0.1"
- }
- }
- }
- },
"schema-utils": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
@@ -5977,12 +5459,6 @@
"yargs": "^13.3.2"
},
"dependencies": {
- "interpret": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
- "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
- "dev": true
- },
"supports-color": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
@@ -6079,51 +5555,6 @@
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.1.2"
- },
- "dependencies": {
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true
- }
}
},
"yargs-parser": {
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7fbc913ce2..c5a41709c6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,14 @@
All notable changes to `dash` will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).
-## [UNRELEASED]
+## [1.16.0] - 2020-09-03
+### Added
+- [#1371](https://github.com/plotly/dash/pull/1371) You can now get [CSP `script-src` hashes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src) of all added inline scripts by calling `app.csp_hashes()` (both Dash internal inline scripts, and those added with `app.clientside_callback`) .
+
+### Changed
+- [#1385](https://github.com/plotly/dash/pull/1385) Closes [#1350](https://github.com/plotly/dash/issues/1350) and fixes a previously undefined callback behavior when multiple elements are stacked on top of one another and their `n_clicks` props are used as inputs of the same callback. The callback will now trigger once with all the triggered `n_clicks` props changes.
+- [#1179](https://github.com/plotly/dash/pull/1179) New and improved callback graph in the debug menu. Now based on Cytoscape for much more interactivity, plus callback profiling including number of calls, fine-grained time information, bytes sent and received, and more. You can even add custom timing information on the server with `callback_context.record_timing(name, seconds)`
+
### Fixed
- [#1384](https://github.com/plotly/dash/pull/1384) Fixed a bug introduced by [#1180](https://github.com/plotly/dash/pull/1180) breaking use of `prevent_initial_call` as a positional arg in callback definitions
@@ -15,7 +22,6 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- [#1180](https://github.com/plotly/dash/pull/1180) and [#1375](https://github.com/plotly/dash/pull/1375) `Input`, `Output`, and `State` in callback definitions don't need to be in lists. You still need to provide `Output` items first, then `Input` items, then `State`, and the list form is still supported. In particular, if you want to return a single output item wrapped in a length-1 list, you should still wrap the `Output` in a list. This can be useful for procedurally-generated callbacks.
- [#1368](https://github.com/plotly/dash/pull/1368) Updated pytest to v6.0.1. To avoid deprecation warnings, this also updated pytest-sugar to 0.9.4 and pytest-mock to 3.2.0. The pytest-mock update only effects python >= 3.0. Pytest-mock remains pinned at 2.0.0 for python == 2.7.
-
## [1.14.0] - 2020-07-27
### Added
- [#1343](https://github.com/plotly/dash/pull/1343) Add `title` parameter to set the
diff --git a/dash-renderer/.prettierrc b/dash-renderer/.prettierrc
index dcd9342f37..570eb0943d 100644
--- a/dash-renderer/.prettierrc
+++ b/dash-renderer/.prettierrc
@@ -1,6 +1,7 @@
{
"tabWidth": 4,
"singleQuote": true,
+ "jsxSingleQuote": true,
"bracketSpacing": false,
- "trailingComma": "es5"
-}
\ No newline at end of file
+ "trailingComma": "none"
+}
diff --git a/dash-renderer/package-lock.json b/dash-renderer/package-lock.json
index 139405ae99..2b297372fa 100644
--- a/dash-renderer/package-lock.json
+++ b/dash-renderer/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "dash-renderer",
- "version": "1.7.0",
+ "version": "1.8.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -5358,6 +5358,27 @@
"babel-plugin-jest-hoist": "^25.1.0"
}
},
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "requires": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "2.6.11",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
+ "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
+ },
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+ }
+ }
+ },
"bail": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/bail/-/bail-1.0.4.tgz",
@@ -5431,6 +5452,11 @@
}
}
},
+ "base16": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
+ "integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA="
+ },
"base64-js": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
@@ -6789,6 +6815,32 @@
"integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
"dev": true
},
+ "cytoscape": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.14.1.tgz",
+ "integrity": "sha512-s8TaaDzXZ5dMkaoZXrfNRdR053L6MsF+P/Yb4AXpF8Y3VNHZXbuydMpaJTlDG/0HKqs51qHSejTUxV1fyQfU6g==",
+ "requires": {
+ "heap": "^0.2.6",
+ "lodash.debounce": "^4.0.8"
+ }
+ },
+ "cytoscape-dagre": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/cytoscape-dagre/-/cytoscape-dagre-2.2.2.tgz",
+ "integrity": "sha512-zsg36qNwua/L2stJSWkcbSDcvW3E6VZf6KRe6aLnQJxuXuz89tMqI5EVYVKEcNBgzTEzFMFv0PE3T0nD4m6VDw==",
+ "requires": {
+ "dagre": "^0.8.2"
+ }
+ },
+ "dagre": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz",
+ "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==",
+ "requires": {
+ "graphlib": "^2.1.8",
+ "lodash": "^4.17.15"
+ }
+ },
"damerau-levenshtein": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz",
@@ -9785,6 +9837,14 @@
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
"dev": true
},
+ "graphlib": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz",
+ "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==",
+ "requires": {
+ "lodash": "^4.17.15"
+ }
+ },
"growly": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
@@ -9910,6 +9970,11 @@
"minimalistic-assert": "^1.0.1"
}
},
+ "heap": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz",
+ "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw="
+ },
"hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -13044,8 +13109,7 @@
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
- "dev": true
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
},
"lodash.camelcase": {
"version": "4.3.0",
@@ -13053,12 +13117,27 @@
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
"dev": true
},
+ "lodash.curry": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
+ "integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA="
+ },
+ "lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
+ },
"lodash.difference": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
"integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=",
"dev": true
},
+ "lodash.flow": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
+ "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o="
+ },
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -16188,6 +16267,11 @@
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"dev": true
},
+ "pure-color": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz",
+ "integrity": "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4="
+ },
"q": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
@@ -16332,6 +16416,15 @@
"prop-types": "^15.6.2"
}
},
+ "react-cytoscapejs": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/react-cytoscapejs/-/react-cytoscapejs-1.2.1.tgz",
+ "integrity": "sha512-8exVCetpzyGCAKuRjXPWGjFCnb22boZ3SXUPpPB/+wQI8Q8BwkT1URN3A7J1Czvj1qAbShh5QQ514mBUp7i7kw==",
+ "requires": {
+ "cytoscape": "^3.2.19",
+ "prop-types": "^15.6.2"
+ }
+ },
"react-dom": {
"version": "16.13.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.0.tgz",
@@ -16348,6 +16441,29 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz",
"integrity": "sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw=="
},
+ "react-json-tree": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/react-json-tree/-/react-json-tree-0.11.2.tgz",
+ "integrity": "sha512-aYhUPj1y5jR3ZQ+G3N7aL8FbTyO03iLwnVvvEikLcNFqNTyabdljo9xDftZndUBFyyyL0aK3qGO9+8EilILHUw==",
+ "requires": {
+ "babel-runtime": "^6.6.1",
+ "prop-types": "^15.5.8",
+ "react-base16-styling": "^0.5.1"
+ },
+ "dependencies": {
+ "react-base16-styling": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.5.3.tgz",
+ "integrity": "sha1-OFjyTpxN2MvT9wLz901YHKKRcmk=",
+ "requires": {
+ "base16": "^1.0.0",
+ "lodash.curry": "^4.0.1",
+ "lodash.flow": "^3.3.0",
+ "pure-color": "^1.2.0"
+ }
+ }
+ }
+ },
"react-redux": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz",
@@ -19690,6 +19806,12 @@
}
}
},
+ "tslint-config-prettier": {
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz",
+ "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==",
+ "dev": true
+ },
"tsscmp": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
@@ -20285,11 +20407,6 @@
"unist-util-stringify-position": "^1.1.1"
}
},
- "viz.js": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/viz.js/-/viz.js-2.1.2.tgz",
- "integrity": "sha512-UO6CPAuEMJ8oNR0gLLNl+wUiIzQUsyUOp8SyyDKTqVRBtq7kk1VnFmIZW8QufjxGrGEuI+LVR7p/C7uEKy0LQw=="
- },
"vm-browserify": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
diff --git a/dash-renderer/package.json b/dash-renderer/package.json
index 12d43bb271..d20a4146f0 100644
--- a/dash-renderer/package.json
+++ b/dash-renderer/package.json
@@ -1,15 +1,15 @@
{
"name": "dash-renderer",
- "version": "1.7.0",
+ "version": "1.8.0",
"description": "render dash components in react",
"main": "dash_renderer/dash_renderer.min.js",
"scripts": {
"prepublishOnly": "rm -rf lib && babel src --extensions=\".ts,.tsx,.js,.jsx\" --out-dir lib --copy-files",
"private::format.js-eslint": "eslint --quiet --fix .",
- "private::format.js-prettier": "prettier --config .prettierrc --write \"src/**/*.js\"",
+ "private::format.js-prettier": "prettier --config .prettierrc --write \"src/**/*.{js,jsx,ts,tsx}\"",
"private::format.ts": "tslint --fix --project tsconfig.json --config tslint.json",
"private::lint.js-eslint": "eslint .",
- "private::lint.js-prettier": "prettier --config .prettierrc \"src/**/*.js\" --list-different",
+ "private::lint.js-prettier": "prettier --config .prettierrc \"src/**/*.{js,jsx,ts,tsx}\" --list-different",
"private::lint.ts": "tslint --project tsconfig.json --config tslint.json",
"build:js": "webpack --build release",
"build:dev": "webpack --build local",
@@ -27,18 +27,21 @@
"@babel/polyfill": "7.8.7",
"@plotly/dash-component-plugins": "^1.2.0",
"cookie": "^0.4.0",
+ "cytoscape": "^3.14.1",
+ "cytoscape-dagre": "^2.2.2",
"dependency-graph": "^0.9.0",
"fast-isnumeric": "^1.1.3",
"prop-types": "15.7.2",
"radium": "^0.26.0",
"ramda": "^0.27.0",
"react": "16.13.0",
+ "react-cytoscapejs": "^1.2.1",
"react-dom": "16.13.0",
+ "react-json-tree": "^0.11.2",
"react-redux": "^7.2.0",
"redux": "^4.0.5",
"redux-actions": "^2.6.5",
- "redux-thunk": "^2.3.0",
- "viz.js": "2.1.2"
+ "redux-thunk": "^2.3.0"
},
"devDependencies": {
"@babel/cli": "^7.10.3",
@@ -75,6 +78,7 @@
"ts-jest": "^26.0.0",
"ts-loader": "^7.0.2",
"tslint": "^6.1.2",
+ "tslint-config-prettier": "^1.18.0",
"typescript": "^3.8.3",
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11",
diff --git a/dash-renderer/src/APIController.react.js b/dash-renderer/src/APIController.react.js
index 8479b0fd07..fe939774f1 100644
--- a/dash-renderer/src/APIController.react.js
+++ b/dash-renderer/src/APIController.react.js
@@ -10,7 +10,7 @@ import {
onError,
setGraphs,
setPaths,
- setLayout,
+ setLayout
} from './actions';
import {computePaths} from './actions/paths';
import {computeGraphs} from './actions/dependencies';
@@ -20,6 +20,7 @@ import {applyPersistence} from './persistence';
import {getAppState} from './reducers/constants';
import {STATUS} from './constants/constants';
import {getLoadingState, getLoadingHash} from './utils/TreeContainer';
+import wait from './utils/wait';
export const DashContext = createContext({});
@@ -36,7 +37,7 @@ const UnconnectedContainer = props => {
error,
layoutRequest,
layout,
- loadingMap,
+ loadingMap
} = props;
const [errorLoading, setErrorLoading] = useState(false);
@@ -55,16 +56,19 @@ const UnconnectedContainer = props => {
_dashprivate_config: propsRef.current.config,
_dashprivate_dispatch: propsRef.current.dispatch,
_dashprivate_graphs: propsRef.current.graphs,
- _dashprivate_loadingMap: propsRef.current.loadingMap,
- }),
+ _dashprivate_loadingMap: propsRef.current.loadingMap
+ })
});
useEffect(storeEffect.bind(null, props, events, setErrorLoading));
useEffect(() => {
if (renderedTree.current) {
- renderedTree.current = false;
- events.current.emit('rendered');
+ (async () => {
+ renderedTree.current = false;
+ await wait(0);
+ events.current.emit('rendered');
+ })();
}
});
@@ -73,13 +77,13 @@ const UnconnectedContainer = props => {
layoutRequest.status &&
!includes(layoutRequest.status, [STATUS.OK, 'loading'])
) {
- content =
Error loading layout
;
+ content = Error loading layout
;
} else if (
errorLoading ||
(dependenciesRequest.status &&
!includes(dependenciesRequest.status, [STATUS.OK, 'loading']))
) {
- content = Error loading dependencies
;
+ content = Error loading dependencies
;
} else if (appLifecycle === getAppState('HYDRATED')) {
renderedTree.current = true;
@@ -102,7 +106,7 @@ const UnconnectedContainer = props => {
);
} else {
- content = Loading...
;
+ content = Loading...
;
}
return config && config.ui === true ? (
@@ -120,7 +124,7 @@ function storeEffect(props, events, setErrorLoading) {
error,
graphs,
layout,
- layoutRequest,
+ layoutRequest
} = props;
if (isEmpty(layoutRequest)) {
@@ -180,7 +184,7 @@ function storeEffect(props, events, setErrorLoading) {
UnconnectedContainer.propTypes = {
appLifecycle: PropTypes.oneOf([
getAppState('STARTED'),
- getAppState('HYDRATED'),
+ getAppState('HYDRATED')
]),
dispatch: PropTypes.func,
dependenciesRequest: PropTypes.object,
@@ -190,7 +194,7 @@ UnconnectedContainer.propTypes = {
loadingMap: PropTypes.any,
history: PropTypes.any,
error: PropTypes.object,
- config: PropTypes.object,
+ config: PropTypes.object
};
const Container = connect(
@@ -204,7 +208,7 @@ const Container = connect(
graphs: state.graphs,
history: state.history,
error: state.error,
- config: state.config,
+ config: state.config
}),
dispatch => ({dispatch})
)(UnconnectedContainer);
diff --git a/dash-renderer/src/AccessDenied.react.js b/dash-renderer/src/AccessDenied.react.js
index 0201563457..2d78f985a3 100644
--- a/dash-renderer/src/AccessDenied.react.js
+++ b/dash-renderer/src/AccessDenied.react.js
@@ -46,6 +46,6 @@ function AccessDenied(props) {
);
}
AccessDenied.propTypes = {
- config: PropTypes.object,
+ config: PropTypes.object
};
export default AccessDenied;
diff --git a/dash-renderer/src/AppContainer.react.js b/dash-renderer/src/AppContainer.react.js
index 0dcb5e2a65..92f4325bbf 100644
--- a/dash-renderer/src/AppContainer.react.js
+++ b/dash-renderer/src/AppContainer.react.js
@@ -2,7 +2,6 @@ import {connect} from 'react-redux';
import React from 'react';
import PropTypes from 'prop-types';
import APIController from './APIController.react';
-import DocumentTitle from './components/core/DocumentTitle.react';
import Loading from './components/core/Loading.react';
import Toolbar from './components/core/Toolbar.react';
import Reloader from './components/core/Reloader.react';
@@ -31,8 +30,8 @@ class UnconnectedAppContainer extends React.Component {
credentials: 'same-origin',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json',
- },
+ 'Content-Type': 'application/json'
+ }
};
dispatch(setConfig(config));
@@ -41,14 +40,13 @@ class UnconnectedAppContainer extends React.Component {
render() {
const {config} = this.props;
if (type(config) === 'Null') {
- return Loading...
;
+ return Loading...
;
}
const {show_undo_redo} = config;
return (
{show_undo_redo ? : null}
-
@@ -59,13 +57,13 @@ class UnconnectedAppContainer extends React.Component {
UnconnectedAppContainer.propTypes = {
hooks: PropTypes.object,
dispatch: PropTypes.func,
- config: PropTypes.object,
+ config: PropTypes.object
};
const AppContainer = connect(
state => ({
history: state.history,
- config: state.config,
+ config: state.config
}),
dispatch => ({dispatch})
)(UnconnectedAppContainer);
diff --git a/dash-renderer/src/AppProvider.react.tsx b/dash-renderer/src/AppProvider.react.tsx
index 6b534be900..4214911833 100644
--- a/dash-renderer/src/AppProvider.react.tsx
+++ b/dash-renderer/src/AppProvider.react.tsx
@@ -30,5 +30,3 @@ AppProvider.defaultProps = {
};
export default AppProvider;
-
-
diff --git a/dash-renderer/src/StoreObserver.ts b/dash-renderer/src/StoreObserver.ts
index 4bc82382f0..482ec13a08 100644
--- a/dash-renderer/src/StoreObserver.ts
+++ b/dash-renderer/src/StoreObserver.ts
@@ -1,12 +1,6 @@
-import {
- any,
- filter,
- forEach,
- map,
- path
-} from 'ramda';
+import {any, filter, forEach, map, path} from 'ramda';
-import { Store, Unsubscribe } from 'redux';
+import {Store, Unsubscribe} from 'redux';
type Observer = (store: TStore) => void;
type UnregisterObserver = () => void;
@@ -20,7 +14,8 @@ interface IStoreObserverState {
export interface IStoreObserverDefinition {
observer: Observer>;
- inputs: string[]
+ inputs: string[];
+ [key: string]: any;
}
export default class StoreObserver {
@@ -48,14 +43,14 @@ export default class StoreObserver {
this.add(observer.observer, observer.inputs);
return () => this.remove(observer.observer);
}
- }
+ };
setStore = (store: Store) => {
this.__finalize__();
this.__init__(store);
- }
+ };
- private __finalize__ = () => this._unsubscribe?.()
+ private __finalize__ = () => this._unsubscribe?.();
private __init__ = (store?: Store) => {
this._store = store;
@@ -63,18 +58,16 @@ export default class StoreObserver {
this._unsubscribe = store.subscribe(this.notify);
}
- forEach(o => o.lastState = null, this._observers);
- }
+ forEach(o => (o.lastState = null), this._observers);
+ };
- private add = (
- observer: Observer>,
- inputs: string[]
- ) => this._observers.push({
- inputPaths: map(p => p.split('.'), inputs),
- lastState: null,
- observer,
- triggered: false
- });
+ private add = (observer: Observer>, inputs: string[]) =>
+ this._observers.push({
+ inputPaths: map(p => p.split('.'), inputs),
+ lastState: null,
+ observer,
+ triggered: false
+ });
private notify = () => {
const store = this._store;
@@ -85,29 +78,27 @@ export default class StoreObserver {
const state = store.getState();
const triggered = filter(
- o => !o.triggered && any(
- i => path(i, state) !== path(i, o.lastState),
- o.inputPaths
- ),
+ o =>
+ !o.triggered &&
+ any(i => path(i, state) !== path(i, o.lastState), o.inputPaths),
this._observers
);
- forEach(o => o.triggered = true, triggered);
+ forEach(o => (o.triggered = true), triggered);
- forEach(
- o => {
- o.lastState = store.getState();
- o.observer(store);
- o.triggered = false;
- },
- triggered
- );
- }
+ forEach(o => {
+ o.lastState = store.getState();
+ o.observer(store);
+ o.triggered = false;
+ }, triggered);
+ };
- private remove = (observer: Observer>) => this._observers.splice(
- this._observers.findIndex(
- o => observer === o.observer,
- this._observers
- ), 1
- );
+ private remove = (observer: Observer>) =>
+ this._observers.splice(
+ this._observers.findIndex(
+ o => observer === o.observer,
+ this._observers
+ ),
+ 1
+ );
}
diff --git a/dash-renderer/src/TreeContainer.js b/dash-renderer/src/TreeContainer.js
index bf317ad17d..7c2ef9efbe 100644
--- a/dash-renderer/src/TreeContainer.js
+++ b/dash-renderer/src/TreeContainer.js
@@ -15,7 +15,7 @@ import {
pick,
pickBy,
propOr,
- type,
+ type
} from 'ramda';
import {notifyObservers, updateProps} from './actions';
import isSimpleComponent from './isSimpleComponent';
@@ -26,12 +26,12 @@ import {getWatchedKeys, stringifyId} from './actions/dependencies';
import {
getLoadingHash,
getLoadingState,
- validateComponent,
+ validateComponent
} from './utils/TreeContainer';
import {DashContext} from './APIController.react';
const NOT_LOADING = {
- is_loading: false,
+ is_loading: false
};
function CheckedComponent(p) {
@@ -56,7 +56,7 @@ CheckedComponent.propTypes = {
layout: PropTypes.any,
props: PropTypes.any,
extraProps: PropTypes.any,
- id: PropTypes.string,
+ id: PropTypes.string
};
function createElement(element, props, extraProps, children) {
@@ -117,7 +117,7 @@ class BaseTreeContainer extends Component {
_dashprivate_graphs,
_dashprivate_dispatch,
_dashprivate_path,
- _dashprivate_layout,
+ _dashprivate_layout
} = this.props;
const oldProps = this.getLayoutProps();
@@ -142,7 +142,7 @@ class BaseTreeContainer extends Component {
_dashprivate_dispatch(
updateProps({
props: changedProps,
- itempath: _dashprivate_path,
+ itempath: _dashprivate_path
})
);
@@ -151,7 +151,7 @@ class BaseTreeContainer extends Component {
_dashprivate_dispatch(
notifyObservers({
id,
- props: pick(watchedKeys, changedProps),
+ props: pick(watchedKeys, changedProps)
})
);
}
@@ -184,7 +184,7 @@ class BaseTreeContainer extends Component {
const {
_dashprivate_config,
_dashprivate_dispatch,
- _dashprivate_error,
+ _dashprivate_error
} = this.props;
if (isEmpty(_dashprivate_layout)) {
@@ -208,7 +208,7 @@ class BaseTreeContainer extends Component {
}
const extraProps = {
loading_state: loading_state || NOT_LOADING,
- setProps,
+ setProps
};
return (
@@ -242,7 +242,7 @@ class BaseTreeContainer extends Component {
const {
_dashprivate_layout,
_dashprivate_loadingState,
- _dashprivate_path,
+ _dashprivate_path
} = this.props;
const layoutProps = this.getLayoutProps();
@@ -266,10 +266,10 @@ TreeContainer.propTypes = {
_dashprivate_layout: PropTypes.object,
_dashprivate_loadingState: PropTypes.oneOfType([
PropTypes.object,
- PropTypes.bool,
+ PropTypes.bool
]),
_dashprivate_loadingStateHash: PropTypes.string,
- _dashprivate_path: PropTypes.string,
+ _dashprivate_path: PropTypes.string
};
BaseTreeContainer.propTypes = {
@@ -278,7 +278,7 @@ BaseTreeContainer.propTypes = {
_dashprivate_dispatch: PropTypes.func,
_dashprivate_graphs: PropTypes.any,
_dashprivate_loadingMap: PropTypes.any,
- _dashprivate_path: PropTypes.array,
+ _dashprivate_path: PropTypes.array
};
export default TreeContainer;
diff --git a/dash-renderer/src/actions/api.js b/dash-renderer/src/actions/api.js
index 8a78708d9f..a2f422aa3a 100644
--- a/dash-renderer/src/actions/api.js
+++ b/dash-renderer/src/actions/api.js
@@ -10,7 +10,7 @@ function GET(path, fetchConfig) {
path,
mergeDeepRight(fetchConfig, {
method: 'GET',
- headers: getCSRFHeader(),
+ headers: getCSRFHeader()
})
);
}
@@ -21,7 +21,7 @@ function POST(path, fetchConfig, body = {}) {
mergeDeepRight(fetchConfig, {
method: 'POST',
headers: getCSRFHeader(),
- body: body ? JSON.stringify(body) : null,
+ body: body ? JSON.stringify(body) : null
})
);
}
@@ -37,14 +37,14 @@ export default function apiThunk(endpoint, method, store, id, body) {
if (getState().error.backEndConnected !== connected) {
dispatch({
type: 'SET_CONNECTION_STATUS',
- payload: connected,
+ payload: connected
});
}
}
dispatch({
type: store,
- payload: {id, status: 'loading'},
+ payload: {id, status: 'loading'}
});
return request[method](url, config.fetch, body)
.then(
@@ -61,8 +61,8 @@ export default function apiThunk(endpoint, method, store, id, body) {
payload: {
status: res.status,
content: json,
- id,
- },
+ id
+ }
});
return json;
});
@@ -74,8 +74,8 @@ export default function apiThunk(endpoint, method, store, id, body) {
type: store,
payload: {
id,
- status: res.status,
- },
+ status: res.status
+ }
});
},
() => {
diff --git a/dash-renderer/src/actions/callbacks.ts b/dash-renderer/src/actions/callbacks.ts
index c660bcb218..7bb917f189 100644
--- a/dash-renderer/src/actions/callbacks.ts
+++ b/dash-renderer/src/actions/callbacks.ts
@@ -10,13 +10,25 @@ import {
zip
} from 'ramda';
-import { STATUS } from '../constants/constants';
-import { CallbackActionType, CallbackAggregateActionType } from '../reducers/callbacks';
-import { CallbackResult, ICallback, IExecutedCallback, IExecutingCallback, ICallbackPayload, IStoredCallback, IBlockedCallback, IPrioritizedCallback } from '../types/callbacks';
-import { isMultiValued, stringifyId, isMultiOutputProp } from './dependencies';
-import { urlBase } from './utils';
-import { getCSRFHeader } from '.';
-import { createAction, Action } from 'redux-actions';
+import {STATUS} from '../constants/constants';
+import {
+ CallbackActionType,
+ CallbackAggregateActionType
+} from '../reducers/callbacks';
+import {
+ CallbackResult,
+ ICallback,
+ IExecutedCallback,
+ IExecutingCallback,
+ ICallbackPayload,
+ IStoredCallback,
+ IBlockedCallback,
+ IPrioritizedCallback
+} from '../types/callbacks';
+import {isMultiValued, stringifyId, isMultiOutputProp} from './dependencies';
+import {urlBase} from './utils';
+import {getCSRFHeader} from '.';
+import {createAction, Action} from 'redux-actions';
export const addBlockedCallbacks = createAction(
CallbackActionType.AddBlocked
@@ -39,7 +51,9 @@ export const addRequestedCallbacks = createAction(
export const addStoredCallbacks = createAction(
CallbackActionType.AddStored
);
-export const addWatchedCallbacks = createAction(CallbackActionType.AddWatched);
+export const addWatchedCallbacks = createAction(
+ CallbackActionType.AddWatched
+);
export const removeExecutedCallbacks = createAction(
CallbackActionType.RemoveExecuted
);
@@ -61,11 +75,11 @@ export const removeStoredCallbacks = createAction(
export const removeWatchedCallbacks = createAction(
CallbackActionType.RemoveWatched
);
-export const aggregateCallbacks = createAction<(
- Action |
- Action |
- null
-)[]>(CallbackAggregateActionType.Aggregate);
+export const aggregateCallbacks = createAction<
+ (Action | Action | null)[]
+>(CallbackAggregateActionType.Aggregate);
+
+const updateResourceUsage = createAction('UPDATE_RESOURCE_USAGE');
function unwrapIfNotMulti(
paths: any,
@@ -90,13 +104,13 @@ function unwrapIfNotMulti(
(isStr
? '`' + spec.id + '`'
: JSON.stringify(spec.id) +
- (anyVals ? ' with MATCH values ' + anyVals : '')) +
+ (anyVals ? ' with MATCH values ' + anyVals : '')) +
' and the property is `' +
spec.property +
(isStr
? '`. The string ids in the current layout are: [' +
- keys(paths.strs).join(', ') +
- ']'
+ keys(paths.strs).join(', ') +
+ ']'
: '`. The wildcard ids currently available are logged above.');
} else {
msg =
@@ -129,7 +143,7 @@ function fillVals(
const inputVals = getter(paths).map((inputList: any, i: number) => {
const [inputs, inputError] = unwrapIfNotMulti(
paths,
- inputList.map(({ id, property, path: path_ }: any) => ({
+ inputList.map(({id, property, path: path_}: any) => ({
id,
property,
value: (path(path_, layout) as any).props[property]
@@ -181,78 +195,113 @@ function refErr(errors: any, paths: any) {
const getVals = (input: any) =>
Array.isArray(input) ? pluck('value', input) : input.value;
-const zipIfArray = (a: any, b: any) => (Array.isArray(a) ? zip(a, b) : [[a, b]]);
+const zipIfArray = (a: any, b: any) =>
+ Array.isArray(a) ? zip(a, b) : [[a, b]];
-function handleClientside(clientside_function: any, payload: ICallbackPayload) {
- const dc = ((window as any).dash_clientside = (window as any).dash_clientside || {});
+function handleClientside(
+ dispatch: any,
+ clientside_function: any,
+ config: any,
+ payload: ICallbackPayload
+) {
+ const dc = ((window as any).dash_clientside =
+ (window as any).dash_clientside || {});
if (!dc.no_update) {
Object.defineProperty(dc, 'no_update', {
- value: { description: 'Return to prevent updating an Output.' },
+ value: {description: 'Return to prevent updating an Output.'},
writable: false
});
Object.defineProperty(dc, 'PreventUpdate', {
- value: { description: 'Throw to prevent updating all Outputs.' },
+ value: {description: 'Throw to prevent updating all Outputs.'},
writable: false
});
}
- const { inputs, outputs, state } = payload;
+ const {inputs, outputs, state} = payload;
+ const requestTime = Date.now();
- let returnValue;
+ const inputDict = inputsToDict(inputs);
+ const stateDict = inputsToDict(state);
+ const result: any = {};
+ let status: any = STATUS.OK;
try {
- const { namespace, function_name } = clientside_function;
+ const {namespace, function_name} = clientside_function;
let args = inputs.map(getVals);
if (state) {
args = concat(args, state.map(getVals));
}
// setup callback context
- const input_dict = inputsToDict(inputs);
dc.callback_context = {};
dc.callback_context.triggered = payload.changedPropIds.map(prop_id => ({
prop_id: prop_id,
- value: input_dict[prop_id]
+ value: inputDict[prop_id]
}));
dc.callback_context.inputs_list = inputs;
- dc.callback_context.inputs = input_dict;
+ dc.callback_context.inputs = inputDict;
dc.callback_context.states_list = state;
- dc.callback_context.states = inputsToDict(state);
+ dc.callback_context.states = stateDict;
+
+ const returnValue = dc[namespace][function_name](...args);
+
+ if (typeof returnValue?.then === 'function') {
+ throw new Error(
+ 'The clientside function returned a Promise. ' +
+ 'Promises are not supported in Dash clientside ' +
+ 'right now, but may be in the future.'
+ );
+ }
- returnValue = dc[namespace][function_name](...args);
+ zipIfArray(outputs, returnValue).forEach(([outi, reti]) => {
+ zipIfArray(outi, reti).forEach(([outij, retij]) => {
+ const {id, property} = outij;
+ const idStr = stringifyId(id);
+ const dataForId = (result[idStr] = result[idStr] || {});
+ if (retij !== dc.no_update) {
+ dataForId[property] = retij;
+ }
+ });
+ });
} catch (e) {
if (e === dc.PreventUpdate) {
- return {};
+ status = STATUS.PREVENT_UPDATE;
+ } else {
+ status = STATUS.CLIENTSIDE_ERROR;
+ throw e;
}
- throw e;
} finally {
delete dc.callback_context;
- }
- if (typeof returnValue?.then === 'function') {
- throw new Error(
- 'The clientside function returned a Promise. ' +
- 'Promises are not supported in Dash clientside ' +
- 'right now, but may be in the future.'
- );
+ // Setting server = client forces network = 0
+ const totalTime = Date.now() - requestTime;
+ const resources = {
+ __dash_server: totalTime,
+ __dash_client: totalTime,
+ __dash_upload: 0,
+ __dash_download: 0
+ };
+
+ if (config.ui) {
+ dispatch(
+ updateResourceUsage({
+ id: payload.output,
+ usage: resources,
+ status,
+ result,
+ inputs,
+ state
+ })
+ );
+ }
}
- const data: any = {};
- zipIfArray(outputs, returnValue).forEach(([outi, reti]) => {
- zipIfArray(outi, reti).forEach(([outij, retij]) => {
- const { id, property } = outij;
- const idStr = stringifyId(id);
- const dataForId = (data[idStr] = data[idStr] || {});
- if (retij !== dc.no_update) {
- dataForId[property] = retij;
- }
- });
- });
- return data;
+ return result;
}
function handleServerside(
+ dispatch: any,
hooks: any,
config: any,
payload: any
@@ -261,41 +310,101 @@ function handleServerside(
hooks.request_pre(payload);
}
+ const requestTime = Date.now();
+ const body = JSON.stringify(payload);
+
return fetch(
`${urlBase(config)}_dash-update-component`,
mergeDeepRight(config.fetch, {
method: 'POST',
headers: getCSRFHeader() as any,
- body: JSON.stringify(payload)
+ body
})
- ).then((res: any) => {
- const { status } = res;
- if (status === STATUS.OK) {
- return res.json().then((data: any) => {
- const { multi, response } = data;
- if (hooks.request_post !== null) {
- hooks.request_post(payload, response);
+ ).then(
+ (res: any) => {
+ const {status} = res;
+
+ function recordProfile(result: any) {
+ if (config.ui) {
+ // Callback profiling - only relevant if we're showing the debug ui
+ const resources = {
+ __dash_server: 0,
+ __dash_client: Date.now() - requestTime,
+ __dash_upload: body.length,
+ __dash_download: Number(
+ res.headers.get('Content-Length')
+ )
+ } as any;
+
+ const timingHeaders =
+ res.headers.get('Server-Timing') || '';
+
+ timingHeaders.split(',').forEach((header: any) => {
+ const name = header.split(';')[0];
+ const dur = header.match(/;dur=[0-9\.]+/);
+
+ if (dur) {
+ resources[name] = Number(dur[0].slice(5));
+ }
+ });
+
+ dispatch(
+ updateResourceUsage({
+ id: payload.output,
+ usage: resources,
+ status,
+ result,
+ inputs: payload.inputs,
+ state: payload.state
+ })
+ );
}
+ }
- if (multi) {
- return response;
- }
+ if (status === STATUS.OK) {
+ return res.json().then((data: any) => {
+ const {multi, response} = data;
+ if (hooks.request_post !== null) {
+ hooks.request_post(payload, response);
+ }
- const { output } = payload;
- const id = output.substr(0, output.lastIndexOf('.'));
- return { [id]: response.props };
- });
- }
- if (status === STATUS.PREVENT_UPDATE) {
- return {};
+ let result;
+ if (multi) {
+ result = response;
+ } else {
+ const {output} = payload;
+ const id = output.substr(0, output.lastIndexOf('.'));
+ result = {[id]: response.props};
+ }
+
+ recordProfile(result);
+ return result;
+ });
+ }
+ if (status === STATUS.PREVENT_UPDATE) {
+ recordProfile({});
+ return {};
+ }
+ throw res;
+ },
+ () => {
+ // fetch rejection - this means the request didn't return,
+ // we don't get here from 400/500 errors, only network
+ // errors or unresponsive servers.
+ if (config.ui) {
+ dispatch(
+ updateResourceUsage({
+ id: payload.output,
+ status: STATUS.NO_RESPONSE,
+ result: {},
+ inputs: payload.inputs,
+ state: payload.state
+ })
+ );
+ }
+ throw new Error('Callback failed: the server did not respond.');
}
- throw res;
- }, () => {
- // fetch rejection - this means the request didn't return,
- // we don't get here from 400/500 errors, only network
- // errors or unresponsive servers.
- throw new Error('Callback failed: the server did not respond.');
- });
+ );
}
function inputsToDict(inputs_list: any) {
@@ -314,13 +423,13 @@ function inputsToDict(inputs_list: any) {
for (let ii = 0; ii < inputsi.length; ii++) {
const id_str = `${stringifyId(inputsi[ii].id)}.${
inputsi[ii].property
- }`;
+ }`;
inputs[id_str] = inputsi[ii].value ?? null;
}
} else {
const id_str = `${stringifyId(inputs_list[i].id)}.${
inputs_list[i].property
- }`;
+ }`;
inputs[id_str] = inputs_list[i].value ?? null;
}
}
@@ -333,9 +442,10 @@ export function executeCallback(
hooks: any,
paths: any,
layout: any,
- { allOutputs }: any
+ {allOutputs}: any,
+ dispatch: any
): IExecutingCallback {
- const { output, inputs, state, clientside_function } = cb.callback;
+ const {output, inputs, state, clientside_function} = cb.callback;
try {
const inVals = fillVals(paths, layout, cb, inputs, 'Input', true);
@@ -385,25 +495,33 @@ export function executeCallback(
outputs: isMultiOutputProp(output) ? outputs : outputs[0],
inputs: inVals,
changedPropIds: keys(cb.changedPropIds),
- state: cb.callback.state.length ?
- fillVals(paths, layout, cb, state, 'State') :
- undefined
+ state: cb.callback.state.length
+ ? fillVals(paths, layout, cb, state, 'State')
+ : undefined
};
if (clientside_function) {
try {
- resolve({ data: handleClientside(clientside_function, payload), payload });
+ resolve({
+ data: handleClientside(
+ dispatch,
+ clientside_function,
+ config,
+ payload
+ ),
+ payload
+ });
} catch (error) {
- resolve({ error, payload });
+ resolve({error, payload});
}
return null;
} else {
- handleServerside(hooks, config, payload)
- .then(data => resolve({ data, payload }))
- .catch(error => resolve({ error, payload }));
+ handleServerside(dispatch, hooks, config, payload)
+ .then(data => resolve({data, payload}))
+ .catch(error => resolve({error, payload}));
}
} catch (error) {
- resolve({ error, payload: null });
+ resolve({error, payload: null});
}
});
@@ -416,7 +534,7 @@ export function executeCallback(
} catch (error) {
return {
...cb,
- executionPromise: { error, payload: null }
+ executionPromise: {error, payload: null}
};
}
}
diff --git a/dash-renderer/src/actions/constants.js b/dash-renderer/src/actions/constants.js
index b9fba5047d..3d61debf6c 100644
--- a/dash-renderer/src/actions/constants.js
+++ b/dash-renderer/src/actions/constants.js
@@ -7,7 +7,7 @@ const actionList = {
SET_APP_LIFECYCLE: 1,
SET_CONFIG: 1,
ON_ERROR: 1,
- SET_HOOKS: 1,
+ SET_HOOKS: 1
};
export const getAction = action => {
diff --git a/dash-renderer/src/actions/dependencies.js b/dash-renderer/src/actions/dependencies.js
index 1d77086d1d..b83015dbf8 100644
--- a/dash-renderer/src/actions/dependencies.js
+++ b/dash-renderer/src/actions/dependencies.js
@@ -23,7 +23,7 @@ import {
startsWith,
values,
zip,
- zipObj,
+ zipObj
} from 'ramda';
import {
@@ -33,7 +33,7 @@ import {
INDIRECT,
mergeMax,
makeResolvedCallback,
- resolveDeps,
+ resolveDeps
} from './dependencies_ts';
import {computePaths, getPath} from './paths';
@@ -56,7 +56,7 @@ const wildcards = {ALL, MATCH, ALLSMALLER};
const allowedWildcards = {
Output: {ALL, MATCH},
Input: wildcards,
- State: wildcards,
+ State: wildcards
};
const wildcardValTypes = ['string', 'number', 'boolean'];
@@ -97,7 +97,7 @@ export function splitIdAndProp(idAndProp) {
const idStr = idAndProp.substr(0, dotPos);
return {
id: parseIfWildcard(idStr),
- property: idAndProp.substr(dotPos + 1),
+ property: idAndProp.substr(dotPos + 1)
};
}
@@ -193,7 +193,7 @@ function validateDependencies(parsedDependencies, dispatchError) {
hasOutputs = false;
dispatchError('A callback is missing Outputs', [
'Please provide an output for this callback:',
- JSON.stringify(dep, null, 2),
+ JSON.stringify(dep, null, 2)
]);
}
@@ -208,14 +208,14 @@ function validateDependencies(parsedDependencies, dispatchError) {
'Without `Input` elements, it will never get called.',
'',
'Subscribing to `Input` components will cause the',
- 'callback to be called whenever their values change.',
+ 'callback to be called whenever their values change.'
]);
}
const spec = [
[outputs, 'Output'],
[inputs, 'Input'],
- [state, 'State'],
+ [state, 'State']
];
spec.forEach(([args, cls]) => {
if (cls === 'Output' && !hasOutputs) {
@@ -230,7 +230,7 @@ function validateDependencies(parsedDependencies, dispatchError) {
head,
`For ${cls}(s) we found:`,
JSON.stringify(args),
- 'but we expected an Array.',
+ 'but we expected an Array.'
]);
}
args.forEach((idProp, i) => {
@@ -249,7 +249,7 @@ function validateArg({id, property}, head, cls, i, dispatchError) {
dispatchError('Callback property error', [
head,
`${cls}[${i}].property = ${JSON.stringify(property)}`,
- 'but we expected `property` to be a non-empty string.',
+ 'but we expected `property` to be a non-empty string.'
]);
}
@@ -258,7 +258,7 @@ function validateArg({id, property}, head, cls, i, dispatchError) {
dispatchError('Callback item missing ID', [
head,
`${cls}[${i}].id = {}`,
- 'Every item linked to a callback needs an ID',
+ 'Every item linked to a callback needs an ID'
]);
}
@@ -267,7 +267,7 @@ function validateArg({id, property}, head, cls, i, dispatchError) {
dispatchError('Callback wildcard ID error', [
head,
`${cls}[${i}].id has key "${k}"`,
- 'Keys must be non-empty strings.',
+ 'Keys must be non-empty strings.'
]);
}
@@ -277,7 +277,7 @@ function validateArg({id, property}, head, cls, i, dispatchError) {
head,
`${cls}[${i}].id["${k}"] = ${v.wild}`,
`Allowed wildcards for ${cls}s are:`,
- keys(allowedWildcards[cls]).join(', '),
+ keys(allowedWildcards[cls]).join(', ')
]);
}
} else if (!includes(typeof v, wildcardValTypes)) {
@@ -286,7 +286,7 @@ function validateArg({id, property}, head, cls, i, dispatchError) {
`${cls}[${i}].id["${k}"] = ${JSON.stringify(v)}`,
'Wildcard callback ID values must be either wildcards',
'or constants of one of these types:',
- wildcardValTypes.join(', '),
+ wildcardValTypes.join(', ')
]);
}
}, id);
@@ -295,7 +295,7 @@ function validateArg({id, property}, head, cls, i, dispatchError) {
dispatchError('Callback item missing ID', [
head,
`${cls}[${i}].id = "${id}"`,
- 'Every item linked to a callback needs an ID',
+ 'Every item linked to a callback needs an ID'
]);
}
const invalidChars = idInvalidChars.filter(c => includes(c, id));
@@ -303,14 +303,14 @@ function validateArg({id, property}, head, cls, i, dispatchError) {
dispatchError('Callback invalid ID string', [
head,
`${cls}[${i}].id = '${id}'`,
- `characters '${invalidChars.join("', '")}' are not allowed.`,
+ `characters '${invalidChars.join("', '")}' are not allowed.`
]);
}
} else {
dispatchError('Callback ID type error', [
head,
`${cls}[${i}].id = ${JSON.stringify(id)}`,
- 'IDs must be strings or wildcard-compatible objects.',
+ 'IDs must be strings or wildcard-compatible objects.'
]);
}
}
@@ -324,7 +324,7 @@ function findDuplicateOutputs(outputs, head, dispatchError, outStrs, outObjs) {
if (newOutputStrs[idProp]) {
dispatchError('Duplicate callback Outputs', [
head,
- `Output ${i} (${idProp}) is already used by this callback.`,
+ `Output ${i} (${idProp}) is already used by this callback.`
]);
} else if (outStrs[idProp]) {
dispatchError('Duplicate callback outputs', [
@@ -333,7 +333,7 @@ function findDuplicateOutputs(outputs, head, dispatchError, outStrs, outObjs) {
'Any given output can only have one callback that sets it.',
'To resolve this situation, try combining these into',
'one callback function, distinguishing the trigger',
- 'by using `dash.callback_context` if necessary.',
+ 'by using `dash.callback_context` if necessary.'
]);
} else {
newOutputStrs[idProp] = 1;
@@ -349,7 +349,7 @@ function findDuplicateOutputs(outputs, head, dispatchError, outStrs, outObjs) {
head,
`Output ${i} (${idProp})`,
`overlaps another output (${idProp2})`,
- `used in ${selfOverlap ? 'this' : 'a different'} callback.`,
+ `used in ${selfOverlap ? 'this' : 'a different'} callback.`
]);
} else {
newOutputObjs.push(idObj);
@@ -377,7 +377,7 @@ function findInOutOverlap(outputs, inputs, head, dispatchError) {
dispatchError('Same `Input` and `Output`', [
head,
`Input ${ini} (${combineIdAndProp(in_)})`,
- `matches Output ${outi} (${combineIdAndProp(out)})`,
+ `matches Output ${outi} (${combineIdAndProp(out)})`
]);
}
} else if (wildcardOverlap(in_, [out])) {
@@ -385,7 +385,7 @@ function findInOutOverlap(outputs, inputs, head, dispatchError) {
head,
`Input ${ini} (${combineIdAndProp(in_)})`,
'can match the same component(s) as',
- `Output ${outi} (${combineIdAndProp(out)})`,
+ `Output ${outi} (${combineIdAndProp(out)})`
]);
}
});
@@ -402,13 +402,13 @@ function findMismatchedWildcards(outputs, inputs, state, head, dispatchError) {
'does not have MATCH wildcards on the same keys as',
`Output 0 (${combineIdAndProp(outputs[0])}).`,
'MATCH wildcards must be on the same keys for all Outputs.',
- 'ALL wildcards need not match, only MATCH.',
+ 'ALL wildcards need not match, only MATCH.'
]);
}
});
[
[inputs, 'Input'],
- [state, 'State'],
+ [state, 'State']
].forEach(([args, cls]) => {
args.forEach((arg, i) => {
const {matchKeys, allsmallerKeys} = findWildcardKeys(arg.id);
@@ -423,7 +423,7 @@ function findMismatchedWildcards(outputs, inputs, state, head, dispatchError) {
`where Output 0 (${combineIdAndProp(outputs[0])})`,
'does not have a MATCH wildcard. Inputs and State do not',
'need every MATCH from the Output(s), but they cannot have',
- 'extras beyond the Output(s).',
+ 'extras beyond the Output(s).'
]);
}
});
@@ -492,7 +492,7 @@ export function validateCallbacksToLayout(state_, dispatchError) {
'generated by other callbacks (and therefore not in the',
'initial layout), you can suppress this exception by setting',
'`suppress_callback_exceptions=True`.',
- tail(callbacks),
+ tail(callbacks)
]);
}
@@ -519,7 +519,7 @@ export function validateCallbacksToLayout(state_, dispatchError) {
`in one of the ${cls} items of a callback.`,
`This ID is assigned to a ${namespace}.${type} component`,
'in the layout, which does not support this property.',
- tail(callbacks),
+ tail(callbacks)
]);
}
}
@@ -664,7 +664,7 @@ export function computeGraphs(dependencies, dispatchError) {
inputMap,
outputPatterns,
inputPatterns,
- callbacks: parsedDependencies,
+ callbacks: parsedDependencies
};
if (hasError) {
@@ -683,7 +683,7 @@ export function computeGraphs(dependencies, dispatchError) {
if (!wildcardPlaceholders[key]) {
wildcardPlaceholders[key] = {
exact: [],
- expand: 0,
+ expand: 0
};
}
const keyPlaceholders = wildcardPlaceholders[key];
@@ -872,7 +872,7 @@ export function idMatch(
vals,
refKeys,
refPatternVals,
- refVals,
+ refVals
})
);
}
@@ -1204,7 +1204,7 @@ export function getUnfilteredLayoutCallbacks(graphs, paths, layoutChunk, opts) {
return map(
cb => ({
...cb,
- priority: getPriority(graphs, paths, cb),
+ priority: getPriority(graphs, paths, cb)
}),
callbacks
);
diff --git a/dash-renderer/src/actions/dependencies_ts.ts b/dash-renderer/src/actions/dependencies_ts.ts
index 7fcf8cba55..a053d4ffd8 100644
--- a/dash-renderer/src/actions/dependencies_ts.ts
+++ b/dash-renderer/src/actions/dependencies_ts.ts
@@ -16,18 +16,29 @@ import {
reduce,
zipObj
} from 'ramda';
-import { ICallback, ICallbackProperty, ICallbackDefinition, ILayoutCallbackProperty, ICallbackTemplate } from '../types/callbacks';
-import { addAllResolvedFromOutputs, splitIdAndProp, stringifyId, getUnfilteredLayoutCallbacks, isMultiValued, idMatch } from './dependencies';
-import { getPath } from './paths';
+import {
+ ICallback,
+ ICallbackProperty,
+ ICallbackDefinition,
+ ILayoutCallbackProperty,
+ ICallbackTemplate
+} from '../types/callbacks';
+import {
+ addAllResolvedFromOutputs,
+ splitIdAndProp,
+ stringifyId,
+ getUnfilteredLayoutCallbacks,
+ isMultiValued,
+ idMatch
+} from './dependencies';
+import {getPath} from './paths';
export const DIRECT = 2;
export const INDIRECT = 1;
export const mergeMax = mergeWith(Math.max);
-export const combineIdAndProp = ({
- id,
- property
-}: ICallbackProperty) => `${stringifyId(id)}.${property}`;
+export const combineIdAndProp = ({id, property}: ICallbackProperty) =>
+ `${stringifyId(id)}.${property}`;
export function getCallbacksByInput(
graphs: any,
@@ -38,7 +49,7 @@ export function getCallbacksByInput(
withPriority: boolean = true
): ICallback[] {
const matches: ICallback[] = [];
- const idAndProp = combineIdAndProp({ id, property: prop });
+ const idAndProp = combineIdAndProp({id, property: prop});
if (typeof id === 'string') {
// standard id version
@@ -74,7 +85,7 @@ export function getCallbacksByInput(
matches.forEach(match => {
match.changedPropIds[idAndProp] = changeType || DIRECT;
if (withPriority) {
- match.priority = getPriority(graphs, paths, match)
+ match.priority = getPriority(graphs, paths, match);
}
});
return matches;
@@ -85,18 +96,19 @@ export function getCallbacksByInput(
* Uses the number of callbacks at each tree depth and the total depth of the tree
* to create a sortable priority hash.
*/
-export function getPriority(graphs: any, paths: any, callback: ICallback): string {
+export function getPriority(
+ graphs: any,
+ paths: any,
+ callback: ICallback
+): string {
let callbacks: ICallback[] = [callback];
- let touchedOutputs: { [key: string]: boolean } = {};
+ let touchedOutputs: {[key: string]: boolean} = {};
let priority: number[] = [];
while (callbacks.length) {
const outputs = filter(
o => !touchedOutputs[combineIdAndProp(o)],
- flatten(map(
- cb => flatten(cb.getOutputs(paths)),
- callbacks
- ))
+ flatten(map(cb => flatten(cb.getOutputs(paths)), callbacks))
);
touchedOutputs = reduce(
@@ -105,17 +117,20 @@ export function getPriority(graphs: any, paths: any, callback: ICallback): strin
outputs
);
- callbacks = flatten(map(
- ({ id, property }: any) => getCallbacksByInput(
- graphs,
- paths,
- id,
- property,
- INDIRECT,
- false
- ),
- outputs
- ));
+ callbacks = flatten(
+ map(
+ ({id, property}: any) =>
+ getCallbacksByInput(
+ graphs,
+ paths,
+ id,
+ property,
+ INDIRECT,
+ false
+ ),
+ outputs
+ )
+ );
if (callbacks.length) {
priority.push(callbacks.length);
@@ -148,18 +163,19 @@ export const getReadyCallbacks = (
);
// Make `outputs` hash table for faster access
- const outputsMap: { [key: string]: boolean } = {};
- forEach(output => outputsMap[output] = true, outputs);
+ const outputsMap: {[key: string]: boolean} = {};
+ forEach(output => (outputsMap[output] = true), outputs);
// Find `requested` callbacks that do not depend on a outstanding output (as either input or state)
return filter(
- cb => all(
- cbp => !outputsMap[combineIdAndProp(cbp)],
- flatten(cb.getInputs(paths))
- ),
+ cb =>
+ all(
+ cbp => !outputsMap[combineIdAndProp(cbp)],
+ flatten(cb.getInputs(paths))
+ ),
candidates
);
-}
+};
export const getLayoutCallbacks = (
graphs: any,
@@ -188,14 +204,15 @@ export const getLayoutCallbacks = (
*/
while (true) {
// Find callbacks for which all inputs are missing or in the exclusions
- const [included, excluded] = partition(({
- callback: { inputs },
- getInputs
- }) => all(isMultiValued, inputs) ||
- !isEmpty(difference(
- map(combineIdAndProp, flatten(getInputs(paths))),
- exclusions
- )),
+ const [included, excluded] = partition(
+ ({callback: {inputs}, getInputs}) =>
+ all(isMultiValued, inputs) ||
+ !isEmpty(
+ difference(
+ map(combineIdAndProp, flatten(getInputs(paths))),
+ exclusions
+ )
+ ),
callbacks
);
@@ -209,10 +226,10 @@ export const getLayoutCallbacks = (
// update exclusions with all additional excluded outputs
exclusions = concat(
exclusions,
- map(combineIdAndProp, flatten(map(
- ({ getOutputs }) => getOutputs(paths),
- excluded
- )))
+ map(
+ combineIdAndProp,
+ flatten(map(({getOutputs}) => getOutputs(paths), excluded))
+ )
);
}
@@ -220,35 +237,30 @@ export const getLayoutCallbacks = (
Return all callbacks with an `executionGroup` to allow group-processing
*/
const executionGroup = Math.random().toString(16);
- return map(cb => ({
- ...cb,
- executionGroup
- }), callbacks);
-}
+ return map(cb => ({...cb, executionGroup}), callbacks);
+};
export const getUniqueIdentifier = ({
anyVals,
- callback: {
- inputs,
- outputs,
- state
- }
-}: ICallback): string => concat(
- map(combineIdAndProp, [
- ...inputs,
- ...outputs,
- ...state
- ]),
- Array.isArray(anyVals) ?
- anyVals :
- anyVals === '' ? [] : [anyVals]
+ callback: {inputs, outputs, state}
+}: ICallback): string =>
+ concat(
+ map(combineIdAndProp, [...inputs, ...outputs, ...state]),
+ Array.isArray(anyVals) ? anyVals : anyVals === '' ? [] : [anyVals]
).join(',');
-export function includeObservers(id: any, properties: any, graphs: any, paths: any): ICallback[] {
- return flatten(map(
- propName => getCallbacksByInput(graphs, paths, id, propName),
- keys(properties)
- ));
+export function includeObservers(
+ id: any,
+ properties: any,
+ graphs: any,
+ paths: any
+): ICallback[] {
+ return flatten(
+ map(
+ propName => getCallbacksByInput(graphs, paths, id, propName),
+ keys(properties)
+ )
+ );
}
/*
@@ -272,25 +284,34 @@ export const makeResolvedCallback = (
initialCall: false
});
-export function pruneCallbacks(callbacks: T[], paths: any): {
- added: T[],
- removed: T[]
+export function pruneCallbacks(
+ callbacks: T[],
+ paths: any
+): {
+ added: T[];
+ removed: T[];
} {
const [, removed] = partition(
- ({ getOutputs, callback: { outputs } }) => flatten(getOutputs(paths)).length === outputs.length,
+ ({getOutputs, callback: {outputs}}) =>
+ flatten(getOutputs(paths)).length === outputs.length,
callbacks
);
const [, modified] = partition(
- ({ getOutputs }) => !flatten(getOutputs(paths)).length,
+ ({getOutputs}) => !flatten(getOutputs(paths)).length,
removed
);
const added = map(
- cb => assoc('changedPropIds', pickBy(
- (_, propId) => getPath(paths, splitIdAndProp(propId).id),
- cb.changedPropIds
- ), cb),
+ cb =>
+ assoc(
+ 'changedPropIds',
+ pickBy(
+ (_, propId) => getPath(paths, splitIdAndProp(propId).id),
+ cb.changedPropIds
+ ),
+ cb
+ ),
modified
);
@@ -300,11 +321,15 @@ export function pruneCallbacks(callbacks: T[], paths: any):
};
}
-export function resolveDeps(refKeys?: any, refVals?: any, refPatternVals?: string) {
- return (paths: any) => ({ id: idPattern, property }: ICallbackProperty) => {
+export function resolveDeps(
+ refKeys?: any,
+ refVals?: any,
+ refPatternVals?: string
+) {
+ return (paths: any) => ({id: idPattern, property}: ICallbackProperty) => {
if (typeof idPattern === 'string') {
const path = getPath(paths, idPattern);
- return path ? [{ id: idPattern, property, path }] : [];
+ return path ? [{id: idPattern, property, path}] : [];
}
const _keys = Object.keys(idPattern).sort();
const patternVals = props(_keys, idPattern);
@@ -314,7 +339,7 @@ export function resolveDeps(refKeys?: any, refVals?: any, refPatternVals?: strin
return [];
}
const result: ILayoutCallbackProperty[] = [];
- keyPaths.forEach(({ values: vals, path }: any) => {
+ keyPaths.forEach(({values: vals, path}: any) => {
if (
idMatch(
_keys,
@@ -325,7 +350,7 @@ export function resolveDeps(refKeys?: any, refVals?: any, refPatternVals?: strin
refPatternVals
)
) {
- result.push({ id: zipObj(_keys, vals), property, path });
+ result.push({id: zipObj(_keys, vals), property, path});
}
});
return result;
diff --git a/dash-renderer/src/actions/index.js b/dash-renderer/src/actions/index.js
index 7d165f41a6..13e3d74f18 100644
--- a/dash-renderer/src/actions/index.js
+++ b/dash-renderer/src/actions/index.js
@@ -22,7 +22,7 @@ export const dispatchError = dispatch => (message, lines) =>
dispatch(
onError({
type: 'backEnd',
- error: {message, html: lines.join('\n')},
+ error: {message, html: lines.join('\n')}
})
);
@@ -40,7 +40,7 @@ const logWarningOnce = once(console.warn);
export function getCSRFHeader() {
try {
return {
- 'X-CSRFToken': cookie.parse(document.cookie)._csrf_token,
+ 'X-CSRFToken': cookie.parse(document.cookie)._csrf_token
};
} catch (e) {
logWarningOnce(e);
@@ -60,8 +60,8 @@ function triggerDefaultState(dispatch, getState) {
type: 'backEnd',
error: {
message: 'Circular Dependencies',
- html: err.toString(),
- },
+ html: err.toString()
+ }
})
);
}
@@ -69,7 +69,7 @@ function triggerDefaultState(dispatch, getState) {
dispatch(
addRequestedCallbacks(
getLayoutCallbacks(graphs, paths, layout, {
- outputsOnly: true,
+ outputsOnly: true
})
)
);
@@ -92,7 +92,7 @@ function moveHistory(changeType) {
dispatch(
createAction('UNDO_PROP_CHANGE')({
itempath: getPath(paths, id),
- props,
+ props
})
);
diff --git a/dash-renderer/src/actions/isAppReady.js b/dash-renderer/src/actions/isAppReady.js
index 03465dc2f7..3d8dd69d9a 100644
--- a/dash-renderer/src/actions/isAppReady.js
+++ b/dash-renderer/src/actions/isAppReady.js
@@ -36,7 +36,7 @@ export default (layout, paths, targets) => {
ready,
rendered.then(
() => document.getElementById(stringifyId(id)) && ready
- ),
+ )
])
);
}
diff --git a/dash-renderer/src/actions/isLoading.ts b/dash-renderer/src/actions/isLoading.ts
index a501211317..5635cc7cd6 100644
--- a/dash-renderer/src/actions/isLoading.ts
+++ b/dash-renderer/src/actions/isLoading.ts
@@ -1,5 +1,7 @@
-import { createAction } from 'redux-actions';
+import {createAction} from 'redux-actions';
-import { IsLoadingActionType, IsLoadingState } from '../reducers/isLoading';
+import {IsLoadingActionType, IsLoadingState} from '../reducers/isLoading';
-export const setIsLoading = createAction(IsLoadingActionType.Set);
+export const setIsLoading = createAction(
+ IsLoadingActionType.Set
+);
diff --git a/dash-renderer/src/actions/loadingMap.ts b/dash-renderer/src/actions/loadingMap.ts
index 2e4834dbd8..60512106ce 100644
--- a/dash-renderer/src/actions/loadingMap.ts
+++ b/dash-renderer/src/actions/loadingMap.ts
@@ -1,5 +1,7 @@
-import { createAction } from 'redux-actions';
+import {createAction} from 'redux-actions';
-import { LoadingMapActionType, LoadingMapState } from '../reducers/loadingMap';
+import {LoadingMapActionType, LoadingMapState} from '../reducers/loadingMap';
-export const setLoadingMap = createAction(LoadingMapActionType.Set);
+export const setLoadingMap = createAction(
+ LoadingMapActionType.Set
+);
diff --git a/dash-renderer/src/actions/paths.js b/dash-renderer/src/actions/paths.js
index d9eca5a6be..e34bc7ea1c 100644
--- a/dash-renderer/src/actions/paths.js
+++ b/dash-renderer/src/actions/paths.js
@@ -5,7 +5,7 @@ import {
forEachObjIndexed,
path,
propEq,
- props,
+ props
} from 'ramda';
import {crawlLayout} from './utils';
diff --git a/dash-renderer/src/components/core/DocumentTitle.react.js b/dash-renderer/src/components/core/DocumentTitle.react.js
deleted file mode 100644
index bfea61831e..0000000000
--- a/dash-renderer/src/components/core/DocumentTitle.react.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import {connect} from 'react-redux';
-import {Component} from 'react';
-import PropTypes from 'prop-types';
-
-class DocumentTitle extends Component {
- constructor(props) {
- super(props);
- const {update_title} = props.config;
- this.state = {
- title: document.title,
- update_title,
- };
- }
-
- UNSAFE_componentWillReceiveProps(props) {
- if (!this.state.update_title) {
- // Let callbacks or other components have full control over title
- return;
- }
- if (props.isLoading) {
- this.setState({title: document.title});
- if (this.state.update_title) {
- document.title = this.state.update_title;
- }
- } else {
- if (document.title === this.state.update_title) {
- document.title = this.state.title;
- } else {
- this.setState({title: document.title});
- }
- }
- }
-
- shouldComponentUpdate() {
- return false;
- }
-
- render() {
- return null;
- }
-}
-
-DocumentTitle.propTypes = {
- isLoading: PropTypes.bool.isRequired,
- config: PropTypes.shape({update_title: PropTypes.string}),
-};
-
-export default connect(state => ({
- isLoading: state.isLoading,
- config: state.config,
-}))(DocumentTitle);
diff --git a/dash-renderer/src/components/core/Loading.react.js b/dash-renderer/src/components/core/Loading.react.js
index b4eb2793f5..00f5add0a5 100644
--- a/dash-renderer/src/components/core/Loading.react.js
+++ b/dash-renderer/src/components/core/Loading.react.js
@@ -4,15 +4,15 @@ import PropTypes from 'prop-types';
function Loading(props) {
if (props.isLoading) {
- return
;
+ return
;
}
return null;
}
Loading.propTypes = {
- isLoading: PropTypes.bool.isRequired,
+ isLoading: PropTypes.bool.isRequired
};
export default connect(state => ({
- isLoading: state.isLoading,
+ isLoading: state.isLoading
}))(Loading);
diff --git a/dash-renderer/src/components/core/Reloader.react.js b/dash-renderer/src/components/core/Reloader.react.js
index 0a20dd9edd..3bfa9f41eb 100644
--- a/dash-renderer/src/components/core/Reloader.react.js
+++ b/dash-renderer/src/components/core/Reloader.react.js
@@ -7,7 +7,7 @@ import {
lt,
path,
pathOr,
- sort,
+ sort
} from 'ramda';
import React from 'react';
import PropTypes from 'prop-types';
@@ -24,11 +24,11 @@ class Reloader extends React.Component {
disabled: false,
intervalId: null,
packages: null,
- max_retry,
+ max_retry
};
} else {
this.state = {
- disabled: true,
+ disabled: true
};
}
this._retry = 0;
@@ -202,13 +202,13 @@ Reloader.propTypes = {
config: PropTypes.object,
reloadRequest: PropTypes.object,
dispatch: PropTypes.func,
- interval: PropTypes.number,
+ interval: PropTypes.number
};
export default connect(
state => ({
config: state.config,
- reloadRequest: state.reloadRequest,
+ reloadRequest: state.reloadRequest
}),
dispatch => ({dispatch})
)(Reloader);
diff --git a/dash-renderer/src/components/core/Toolbar.react.js b/dash-renderer/src/components/core/Toolbar.react.js
index 7d5941658d..b30e3de018 100644
--- a/dash-renderer/src/components/core/Toolbar.react.js
+++ b/dash-renderer/src/components/core/Toolbar.react.js
@@ -12,24 +12,24 @@ function UnconnectedToolbar(props) {
display: 'inline-block',
opacity: '0.2',
':hover': {
- opacity: 1,
- },
+ opacity: 1
+ }
},
iconStyle: {
- fontSize: 20,
+ fontSize: 20
},
labelStyle: {
- fontSize: 15,
- },
+ fontSize: 15
+ }
};
const undoLink = (
{history.past.length > 0 ? undoLink : null}
@@ -99,12 +99,12 @@ function UnconnectedToolbar(props) {
UnconnectedToolbar.propTypes = {
history: PropTypes.object,
- dispatch: PropTypes.func,
+ dispatch: PropTypes.func
};
const Toolbar = connect(
state => ({
- history: state.history,
+ history: state.history
}),
dispatch => ({dispatch})
)(Radium(UnconnectedToolbar));
diff --git a/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainer.css b/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainer.css
index fb98faa56e..025e59eddc 100644
--- a/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainer.css
+++ b/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainer.css
@@ -3,8 +3,8 @@
position: fixed;
bottom: 165px;
right: 16px;
- max-width: 80vw;
- max-height: calc(100vh - 180px);
+ width: 80vw;
+ height: calc(100vh - 180px);
overflow: auto;
box-sizing: border-box;
background: #ffffff;
@@ -14,3 +14,34 @@
0px 2px 6px rgba(80, 103, 132, 0.12),
0px 0px 1px rgba(80, 103, 132, 0.32);
}
+
+.dash-callback-dag--info {
+ border-radius: 4px;
+ position: absolute;
+ padding: 8px;
+ bottom: 16px;
+ left: 16px;
+ max-width: calc(100% - 32px);
+ max-height: 50%;
+ overflow: auto;
+ box-sizing: border-box;
+ background: rgba(255,255,255,0.9);
+ border: 2px solid #ccc;
+ font-family: "Arial", sans-serif;
+}
+
+.dash-callback-dag--message {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+ line-height: 2em;
+ font-family: "Arial", sans-serif;
+}
+
+.dash-callback-dag--layoutSelector {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+}
diff --git a/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainer.react.js b/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainer.react.js
index 480e65e768..3e298154ce 100644
--- a/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainer.react.js
+++ b/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainer.react.js
@@ -1,89 +1,448 @@
-import React, {useEffect, useRef} from 'react';
+import React, {Component, useState, useMemo, useEffect, useRef} from 'react';
import PropTypes from 'prop-types';
+import {connect, useSelector} from 'react-redux';
+import Cytoscape from 'cytoscape';
+import CytoscapeComponent from 'react-cytoscapejs';
+import Dagre from 'cytoscape-dagre';
+import JSONTree from 'react-json-tree';
+import {keys, mergeRight, omit, path} from 'ramda';
+
+import {getPath} from '../../../actions/paths';
+import {stringifyId} from '../../../actions/dependencies';
+import {onError} from '../../../actions';
import './CallbackGraphContainer.css';
+import stylesheet from './CallbackGraphContainerStylesheet';
+import {
+ updateSelectedNode,
+ updateChangedProps,
+ updateCallback
+} from './CallbackGraphEffects';
-import Viz from 'viz.js';
-import {Module, render} from 'viz.js/full.render';
+Cytoscape.use(Dagre);
-import {stringifyId} from '../../../actions/dependencies';
+/*
+ * Generates all the elements (nodes, edeges) for the dependency graph.
+ */
+function generateElements(graphs, profile) {
+ const consumed = [];
+ const elements = [];
-const CallbackGraphContainer = ({graphs}) => {
- const el = useRef(null);
+ function recordNode(id, property) {
+ const idStr = stringifyId(id);
+ const idType = typeof id === 'object' ? 'wildcard' : 'component';
- const viz = useRef(null);
+ const parent = idStr;
+ const child = `${idStr}.${property}`;
- const makeViz = () => {
- viz.current = new Viz({Module, render});
- };
+ if (!consumed.includes(parent)) {
+ consumed.push(parent);
+ elements.push({
+ data: {
+ id: idStr,
+ label: idStr,
+ type: idType
+ }
+ });
+ }
- if (!viz.current) {
- makeViz();
+ if (!consumed.includes(child)) {
+ consumed.push(child);
+ elements.push({
+ data: {
+ id: child,
+ label: property,
+ parent: parent,
+ type: 'property'
+ }
+ });
+ }
+
+ return child;
}
- useEffect(() => {
- const {callbacks} = graphs;
- const elements = {};
- const callbacksOut = [];
- const links = callbacks.map(({inputs, outputs}, i) => {
- callbacksOut.push(`cb${i};`);
- function recordAndReturn({id, property}) {
- const idClean = stringifyId(id)
- .replace(/[\{\}".;\[\]()]/g, '')
- .replace(/:/g, '-')
- .replace(/,/g, '_');
- elements[idClean] = elements[idClean] || {};
- elements[idClean][property] = true;
- return `"${idClean}.${property}"`;
+ function recordEdge(source, target, type) {
+ elements.push({
+ data: {
+ source: source,
+ target: target,
+ type: type
}
- const out_nodes = outputs.map(recordAndReturn).join(', ');
- const in_nodes = inputs.map(recordAndReturn).join(', ');
- return `{${in_nodes}} -> cb${i} -> {${out_nodes}};`;
});
+ }
- const dot = `digraph G {
- overlap = false; fontname="Arial"; fontcolor="#333333";
- edge [color="#888888"];
- node [shape=box, fontname="Arial", style=filled, color="#109DFF", fontcolor=white];
- graph [penwidth=0];
- subgraph callbacks {
- node [shape=circle, width=0.3, label="", color="#00CC96"];
- ${callbacksOut.join('\n')} }
-
- ${Object.entries(elements)
- .map(
- ([id, props], i) => `
- subgraph cluster_${i} {
- bgcolor="#B9C2CE";
- ${Object.keys(props)
- .map(p => `"${id}.${p}" [label="${p}"];`)
- .join('\n')}
- label = "${id}"; }`
- )
- .join('\n')}
-
- ${links.join('\n')} }`;
-
- viz.current
- .renderSVGElement(dot)
- .then(vizEl => {
- el.current.innerHTML = '';
- el.current.appendChild(vizEl);
- })
- .catch(e => {
- // https://github.com/mdaines/viz.js/wiki/Caveats
- makeViz();
- // eslint-disable-next-line no-console
- console.error(e);
- el.current.innerHTML = 'Error creating callback graph';
- });
+ (graphs.callbacks || []).forEach((callback, i) => {
+ const cb = `__dash_callback__.${callback.output}`;
+ const cbProfile = profile.callbacks[callback.output] || {};
+ const count = cbProfile.count || 0;
+ const time = cbProfile.total || 0;
+
+ elements.push({
+ data: {
+ id: cb,
+ label: `callback.${i}`,
+ type: 'callback',
+ mode: callback.clientside_function ? 'client' : 'server',
+ count: count,
+ time: count > 0 ? Math.round(time / count) : 0,
+ loadingSet: Date.now(),
+ errorSet: Date.now()
+ }
+ });
+
+ callback.outputs.map(({id, property}) => {
+ const node = recordNode(id, property);
+ recordEdge(cb, node, 'output');
+ });
+
+ callback.inputs.map(({id, property}) => {
+ const node = recordNode(id, property);
+ recordEdge(node, cb, 'input');
+ });
+
+ callback.state.map(({id, property}) => {
+ const node = recordNode(id, property);
+ recordEdge(node, cb, 'state');
+ });
});
- return
;
+ return elements;
+}
+
+function reduceStatus(status) {
+ if (keys(status).length === 2) {
+ return status.latest;
+ }
+ return status;
+}
+
+function flattenOutputs(res) {
+ const outputs = {};
+ for (const idStr in res) {
+ for (const prop in res[idStr]) {
+ outputs[idStr + '.' + prop] = res[idStr][prop];
+ }
+ }
+ return outputs;
+}
+
+function flattenInputs(inArray, final) {
+ (inArray || []).forEach(inItem => {
+ if (Array.isArray(inItem)) {
+ flattenInputs(inItem, final);
+ } else {
+ const {id, property, value} = inItem;
+ final[stringifyId(id) + '.' + property] = value;
+ }
+ });
+ return final;
+}
+
+// len('__dash_callback__.')
+const cbPrefixLen = 18;
+
+const layouts = {
+ 'top-down': {
+ name: 'dagre',
+ padding: 10,
+ spacingFactor: 0.8
+ },
+ 'left-right': {
+ name: 'dagre',
+ padding: 10,
+ nodeSep: 0,
+ rankSep: 80,
+ rankDir: 'LR'
+ },
+ force: {
+ name: 'cose',
+ padding: 10,
+ animate: false
+ }
};
-CallbackGraphContainer.propTypes = {
- graphs: PropTypes.object,
+function CallbackGraph() {
+ // Grab items from the redux store.
+ const paths = useSelector(state => state.paths);
+ const layout = useSelector(state => state.layout);
+ const graphs = useSelector(state => state.graphs);
+ const profile = useSelector(state => state.profile);
+ const changed = useSelector(state => state.changed);
+ const lifecycleState = useSelector(state => state.appLifecycle);
+
+ // Keep track of cytoscape reference and user selected items.
+ const [selected, setSelected] = useState(null);
+ const [cytoscape, setCytoscape] = useState(null);
+
+ const {graphLayout} = profile;
+ const chosenType = graphLayout?._chosenType;
+ const layoutSelector = useRef(null);
+ const [layoutType, setLayoutType] = useState(chosenType || 'top-down');
+
+ // Generate and memoize the elements.
+ const elements = useMemo(() => generateElements(graphs, profile), [graphs]);
+
+ // Custom hook to make sure cytoscape is loaded.
+ const useCytoscapeEffect = (effect, condition) => {
+ useEffect(
+ () => (cytoscape && effect(cytoscape)) || undefined,
+ condition
+ );
+ };
+
+ function setPresetLayout({cy}) {
+ const positions = {};
+ cy.nodes().each(n => {
+ positions[n.id()] = n.position();
+ });
+ profile.graphLayout = {
+ name: 'preset',
+ fit: false,
+ positions,
+ zoom: cy.zoom(),
+ pan: cy.pan(),
+ _chosenType: layoutSelector.current?.value
+ };
+ }
+
+ // Adds callbacks once cyctoscape is intialized.
+ useCytoscapeEffect(
+ cy => {
+ cytoscape.on('tap', 'node', e => setSelected(e.target));
+ cytoscape.on('tap', e => {
+ if (e.target === cy) {
+ setSelected(null);
+ }
+ });
+ cytoscape.on('zoom', setPresetLayout);
+ cytoscape.on('pan', setPresetLayout);
+ cytoscape.nodes().on('position', setPresetLayout);
+ },
+ [cytoscape]
+ );
+
+ // Set node classes on selected.
+ useCytoscapeEffect(
+ cy => selected && updateSelectedNode(cy, selected.data().id),
+ [selected]
+ );
+
+ // Flash classes when props change. Uses changed as a trigger. Also
+ // flash all input edges originating from this node and highlight
+ // the subtree that contains the selected node.
+ useCytoscapeEffect(
+ cy => changed && updateChangedProps(cy, changed.id, changed.props),
+ [changed]
+ );
+
+ // Update callbacks from profiling information.
+ useCytoscapeEffect(
+ cy =>
+ profile.updated.forEach(cb =>
+ updateCallback(cy, cb, profile.callbacks[cb])
+ ),
+ [profile.updated]
+ );
+
+ if (lifecycleState !== 'HYDRATED') {
+ // If we get here too early - most likely during hot reloading - then
+ // we need to bail out and wait for the full state to be available
+ return (
+
+
+
Waiting for app to be ready...
+
+
+ );
+ }
+
+ // FIXME: Move to a new component?
+ // Generate the element introspection data.
+ let elementName = '';
+ let elementInfo = {};
+ let hasPatterns = false;
+
+ if (selected) {
+ function getComponent(id) {
+ // for now ignore pattern-matching IDs
+ // to do better we may need to store the *actual* IDs used for each
+ // callback invocation, since they need not match what's on the page now.
+ if (id.charAt(0) === '{') {
+ hasPatterns = true;
+ return undefined;
+ }
+ const idPath = getPath(paths, id);
+ return idPath ? path(idPath, layout) : undefined;
+ }
+
+ function getPropValue(data) {
+ const parent = getComponent(data.parent);
+ return parent ? parent.props[data.label] : undefined;
+ }
+
+ const data = selected.data();
+
+ switch (data.type) {
+ case 'component': {
+ const rest = omit(['id'], getComponent(data.id)?.props);
+ elementInfo = rest;
+ elementName = data.id;
+ break;
+ }
+
+ case 'property': {
+ elementName = data.parent;
+ elementInfo[data.label] = getPropValue(data);
+ break;
+ }
+
+ // callback
+ default: {
+ elementInfo.type = data.mode;
+
+ // Remove uid and set profile.
+ const callbackOutputId = data.id.slice(cbPrefixLen);
+ elementName = callbackOutputId.replace(/(^\.\.|\.\.$)/g, '');
+ const cbProfile = profile.callbacks[callbackOutputId];
+ if (cbProfile) {
+ const {
+ count,
+ status,
+ network,
+ resources,
+ total,
+ compute,
+ result,
+ inputs,
+ state
+ } = cbProfile;
+
+ const avg = v => Math.round(v / (count || 1));
+
+ elementInfo['call count'] = count;
+ elementInfo.status = reduceStatus(status);
+
+ const timing = (elementInfo['time (avg milliseconds)'] = {
+ total: avg(total),
+ compute: avg(compute)
+ });
+ if (data.mode === 'server') {
+ timing.network = avg(network.time);
+
+ elementInfo['data transfer (avg bytes)'] = {
+ download: avg(network.download),
+ upload: avg(network.upload)
+ };
+ }
+ for (const key in resources) {
+ timing['user: ' + key] = avg(resources[key]);
+ }
+
+ elementInfo.outputs = flattenOutputs(result);
+ elementInfo.inputs = flattenInputs(inputs, {});
+ elementInfo.state = flattenInputs(state, {});
+ } else {
+ elementInfo['call count'] = 0;
+ }
+ }
+ }
+ }
+
+ const cyLayout =
+ chosenType === layoutType
+ ? graphLayout
+ : mergeRight(layouts[layoutType], {ready: setPresetLayout});
+
+ return (
+
+
+ {selected ? (
+
+ {hasPatterns ? (
+
+ Info isn't supported for pattern-matching IDs at
+ this time
+
+ ) : null}
+
+ _keys.length === 1 ? elementName : _keys[0]
+ }
+ getItemString={(type, data, itemType) => (
+ {itemType}
+ )}
+ shouldExpandNode={(keyName, data, level) => level < 1}
+ />
+
+ ) : null}
+
setLayoutType(e.target.value)}
+ value={layoutType}
+ ref={layoutSelector}
+ >
+ {keys(layouts).map(k => (
+
+ {k}
+
+ ))}
+
+
+ );
+}
+
+CallbackGraph.propTypes = {};
+
+class UnconnectedCallbackGraphContainer extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {hasError: false};
+ }
+
+ static getDerivedStateFromError(_) {
+ return {hasError: true};
+ }
+
+ componentDidCatch(error, info) {
+ const {dispatch} = this.props;
+ dispatch(
+ onError({
+ myID: this.state.myID,
+ type: 'frontEnd',
+ error,
+ info
+ })
+ );
+ }
+
+ render() {
+ return this.state.hasError ? (
+
+
+
Oops! The callback graph threw an error.
+
Check the error list for details.
+
+
+ ) : (
+
+ );
+ }
+}
+
+UnconnectedCallbackGraphContainer.propTypes = {
+ dispatch: PropTypes.func
};
+const CallbackGraphContainer = connect(null, dispatch => ({dispatch}))(
+ UnconnectedCallbackGraphContainer
+);
+
export {CallbackGraphContainer};
diff --git a/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainerStylesheet.js b/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainerStylesheet.js
new file mode 100644
index 0000000000..60a7305b43
--- /dev/null
+++ b/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainerStylesheet.js
@@ -0,0 +1,154 @@
+const stylesheet = [
+ {
+ selector: '*',
+ style: {
+ 'font-size': 12,
+ 'font-family': '"Arial", sans-serif'
+ }
+ },
+
+ {
+ selector: 'edge',
+ style: {
+ width: 2,
+ 'line-color': '#888888',
+ 'target-arrow-color': '#888888',
+ 'target-arrow-shape': 'triangle',
+ 'target-arrow-fill': 'filled',
+ 'arrow-scale': 1,
+ 'curve-style': 'bezier',
+ 'control-point-step-size': 40,
+ 'transition-property': 'line-color, target-arrow-color',
+ 'transition-duration': '0.25s',
+ 'transition-timing-function': 'ease-in-out-sine'
+ }
+ },
+
+ {
+ selector: 'edge[type="output"]',
+ style: {
+ 'line-color': '#0080D0',
+ 'target-arrow-color': '#0080D0'
+ }
+ },
+
+ {
+ selector: 'edge[type="state"]',
+ style: {
+ 'line-style': 'dashed'
+ }
+ },
+
+ {
+ selector: 'node',
+ style: {
+ color: '#333333',
+ padding: 6,
+ 'text-valign': 'center',
+ 'text-halign': 'center',
+ 'border-width': 2,
+ 'border-opacity': 0,
+ 'border-style': 'solid',
+ 'border-color': '#888888',
+ 'transition-property': 'border-opacity',
+ 'transition-duration': '0.25s',
+ 'transition-timing-function': 'ease-in-out-sine'
+ }
+ },
+
+ {
+ selector: 'node[type="callback"]',
+ style: {
+ width: 35,
+ height: 25,
+ shape: 'round-rectangle',
+ label: e => `${e.data().count}\n${e.data().time} ms`,
+ 'text-wrap': 'wrap',
+ 'text-justification': 'center'
+ }
+ },
+
+ {
+ selector: 'node[type="callback"][mode="client"]',
+ style: {
+ color: '#323330',
+ 'background-color': '#F0DB4F'
+ }
+ },
+
+ {
+ selector: 'node[type="callback"][mode="server"]',
+ style: {
+ color: '#323330',
+ 'background-color': '#00CC96'
+ }
+ },
+
+ {
+ selector: 'node[type="component"], node[type="wildcard"]',
+ style: {
+ width: 'label',
+ // height: 'label',
+ shape: 'rectangle',
+ content: e => e.data().label.replace(/\"/g, ''),
+ 'text-valign': 'top',
+ 'background-color': '#B9C2CE'
+ }
+ },
+
+ {
+ selector: 'node[type="property"]',
+ style: {
+ width: 'label',
+ height: 20,
+ shape: 'rectangle',
+ content: 'data(label)',
+ color: 'white',
+ 'background-color': '#109DFF'
+ }
+ },
+
+ {
+ selector: '.selected-node',
+ style: {
+ ghost: 'yes',
+ 'ghost-offset-x': 2,
+ 'ghost-offset-y': 2,
+ 'ghost-opacity': 0.25,
+ 'border-opacity': 1
+ }
+ },
+
+ {
+ selector: '.prop-changed, .callback-loading',
+ style: {
+ 'border-color': '#CC43B7',
+ 'border-width': 2,
+ 'border-opacity': 1
+ }
+ },
+
+ {
+ selector: '.callback-error',
+ style: {
+ 'background-color': '#E1332E'
+ }
+ },
+
+ {
+ selector: '.triggered',
+ style: {
+ 'line-color': '#CC43B7',
+ 'target-arrow-color': '#CC43B7'
+ }
+ },
+
+ {
+ selector: '.inactive',
+ style: {
+ opacity: 0.5
+ }
+ }
+];
+
+export default stylesheet;
diff --git a/dash-renderer/src/components/error/CallbackGraph/CallbackGraphEffects.js b/dash-renderer/src/components/error/CallbackGraph/CallbackGraphEffects.js
new file mode 100644
index 0000000000..05c777f8cc
--- /dev/null
+++ b/dash-renderer/src/components/error/CallbackGraph/CallbackGraphEffects.js
@@ -0,0 +1,161 @@
+import {STATUS, STATUSMAP} from '../../../constants/constants';
+
+/**
+ * getEdgeTypes
+ *
+ * Finds all edges connected to a node and splits them by type.
+ *
+ * @param {Object} node - Cytoscape node.
+ * @returns {Object} - Object contaiing the edges, sorted by type.
+ */
+function getEdgeTypes(node) {
+ const elements = node.connectedEdges();
+ return {
+ input: elements.filter('[type = "input"]'),
+ state: elements.filter('[type = "state"]'),
+ output: elements.filter('[type = "output"]')
+ };
+}
+
+/**
+ * updateSelected
+ *
+ * Updates the classes of the selected node and recenters the viewport.
+ *
+ * @param {Object} cy - Reference to the cytoscape instance.
+ * @param {String} id - The id of the selected node.
+ * @returns {function} - cleanup function, for useEffect hook
+ */
+export function updateSelectedNode(cy, id) {
+ if (id) {
+ const node = cy.getElementById(id);
+
+ // Highlght the selected node.
+
+ node.addClass('selected-node');
+
+ // Find the subtree that the node belongs to. A subtree contains
+ // all all ancestors and descendents that are connected via Inputs
+ // or Outputs (but not State).
+
+ // WARNING: No cycle detection!
+
+ function ascend(node, collection) {
+ // FIXME: Should we include State parents but non-recursively?
+ const type = node.data().type === 'callback' ? 'input' : 'output';
+ const edges = getEdgeTypes(node)[type];
+ const parents = edges.sources();
+ collection.merge(edges);
+ collection.merge(parents);
+ if (node.data().type === 'property') {
+ collection.merge(node.ancestors());
+ }
+ parents.forEach(node => ascend(node, collection));
+ }
+
+ function descend(node, collection) {
+ const type = node.data().type === 'callback' ? 'output' : 'input';
+ const edges = getEdgeTypes(node)[type];
+ const children = edges.targets();
+ collection.merge(edges);
+ collection.merge(children);
+ if (node.data().type === 'property') {
+ collection.merge(node.ancestors());
+ }
+ children.forEach(node => descend(node, collection));
+ }
+
+ const subtree = cy.collection();
+ subtree.merge(node);
+ ascend(node, subtree);
+ descend(node, subtree);
+
+ const other = subtree.absoluteComplement();
+ other.addClass('inactive');
+
+ return () => {
+ node.removeClass('selected-node');
+ other.removeClass('inactive');
+ };
+ }
+ return undefined;
+}
+
+/**
+ * updateChangedProp
+ *
+ * Flashes property nodes that updated and any inputs they are connected to.
+ *
+ * @param {Object} cy - Reference to the cytoscape instance.
+ * @param {String} id - The component id which updated.
+ * @param {Object} props - The props that updated.
+ * @param {Number} flashTime - The time to flash classes for in ms.
+ * @returns {undefined}
+ */
+export function updateChangedProps(cy, id, props, flashTime = 500) {
+ Object.keys(props).forEach(prop => {
+ const node = cy.getElementById(`${id}.${prop}`);
+ node.flashClass('prop-changed', flashTime);
+ node.edgesTo('*')
+ .filter('[type = "input"]')
+ .flashClass('triggered', flashTime);
+ });
+}
+
+/**
+ * updateCallback
+ *
+ * Updates a callback node with profiling information (call count, avg time)
+ * and adds or removes classes as necessary. Classes are always assert for
+ * at least flashTime ms so that they can be visually observed. When callbacks
+ * resolve, all output edges are flashed.
+ *
+ * @param {Object} cy - Reference to the cytoscape instance.
+ * @param {String} id - The id of the callback (i.e., it's output identifier)
+ * @param {Object} profile - The callback profiling infomration.
+ * @param {Number} flashTime - The time to flash classes for in ms.
+ * @returns {undefined}
+ */
+export function updateCallback(cy, id, profile, flashTime = 500) {
+ const node = cy.getElementById(`__dash_callback__.${id}`);
+ const {count, total, status} = profile;
+ const {latest} = status;
+
+ // Update data.
+ const avgTime = count > 0 ? total / count : 0;
+ node.data('count', count);
+ node.data('time', Math.round(avgTime));
+
+ // Either flash the classes OR maintain it for long callbacks.
+ if (latest === 'loading') {
+ node.data('loadingSet', Date.now());
+ node.addClass('callback-loading');
+ } else if (node.hasClass('callback-loading')) {
+ const timeLeft = node.data('loadingSet') + flashTime - Date.now();
+ setTimeout(
+ () => node.removeClass('callback-loading'),
+ Math.max(timeLeft, 0)
+ );
+ }
+
+ if (
+ latest !== 'loading' &&
+ latest !== STATUSMAP[STATUS.OK] &&
+ latest !== STATUSMAP[STATUS.PREVENT_UPDATE]
+ ) {
+ node.data('errorSet', Date.now());
+ node.addClass('callback-error');
+ } else if (node.hasClass('callback-error')) {
+ const timeLeft = node.data('errorSet') + flashTime - Date.now();
+ setTimeout(
+ () => node.removeClass('callback-error'),
+ Math.max(timeLeft, 0)
+ );
+ }
+
+ // FIXME: This will flash branches that return no_update!!
+ // If the callback resolved properly, flash the outputs.
+ if (latest === STATUSMAP[STATUS.OK]) {
+ node.edgesTo('*').flashClass('triggered', flashTime);
+ }
+}
diff --git a/dash-renderer/src/components/error/ComponentErrorBoundary.react.js b/dash-renderer/src/components/error/ComponentErrorBoundary.react.js
index f62b63cbe6..dbc2171f47 100644
--- a/dash-renderer/src/components/error/ComponentErrorBoundary.react.js
+++ b/dash-renderer/src/components/error/ComponentErrorBoundary.react.js
@@ -8,7 +8,7 @@ class ComponentErrorBoundary extends Component {
this.state = {
myID: props.componentId,
oldChildren: null,
- hasError: false,
+ hasError: false
};
}
@@ -23,7 +23,7 @@ class ComponentErrorBoundary extends Component {
myID: this.state.myID,
type: 'frontEnd',
error,
- info,
+ info
})
);
dispatch(revert);
@@ -38,7 +38,7 @@ class ComponentErrorBoundary extends Component {
) {
/* eslint-disable-next-line react/no-did-update-set-state */
this.setState({
- oldChildren: prevChildren,
+ oldChildren: prevChildren
});
}
}
@@ -53,7 +53,7 @@ ComponentErrorBoundary.propTypes = {
children: PropTypes.object,
componentId: PropTypes.string,
error: PropTypes.object,
- dispatch: PropTypes.func,
+ dispatch: PropTypes.func
};
export default ComponentErrorBoundary;
diff --git a/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js b/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js
index a4cac920ea..5703add4db 100644
--- a/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js
+++ b/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js
@@ -12,7 +12,7 @@ class FrontEndError extends Component {
constructor(props) {
super(props);
this.state = {
- collapsed: this.props.isListItem,
+ collapsed: this.props.isListItem
};
}
@@ -27,20 +27,20 @@ class FrontEndError extends Component {
/* eslint-disable no-inline-comments */
const errorHeader = (
this.setState({collapsed: !collapsed})}
>
-
+
⛑️
-
+
{e.error.message || 'Error'}
-
-
+
+
{`${e.timestamp.toLocaleTimeString()}`}
-
+
{/* Special percy timestamp for visual testing.
* Hidden during regular usage.
*/}
@@ -59,7 +59,7 @@ class FrontEndError extends Component {
/* eslint-enable no-inline-comments */
return collapsed ? (
- {errorHeader}
+ {errorHeader}
) : (
{errorHeader}
@@ -73,7 +73,7 @@ const MAX_MESSAGE_LENGTH = 40;
/* eslint-disable no-inline-comments */
function UnconnectedErrorContent({error, base}) {
return (
-
+
{/*
* 40 is a rough heuristic - if longer than 40 then the
* message might overflow into ellipses in the title above &
@@ -81,16 +81,16 @@ function UnconnectedErrorContent({error, base}) {
*/}
{typeof error.message !== 'string' ||
error.message.length < MAX_MESSAGE_LENGTH ? null : (
-
-
+
)}
{typeof error.stack !== 'string' ? null : (
-
-
+
+
@@ -112,8 +112,8 @@ function UnconnectedErrorContent({error, base}) {
{typeof error.html !== 'string' ? null : error.html.indexOf(
'
-
+
+
{/* Embed werkzeug debugger in an iframe to prevent
CSS leaking - werkzeug HTML includes a bunch
of CSS on base html elements like `
`
@@ -138,14 +138,14 @@ function UnconnectedErrorContent({error, base}) {
*/
width: 'calc(600px - 67px)',
height: '75vh',
- border: 'none',
+ border: 'none'
}}
/>
) : (
-
@@ -160,12 +160,12 @@ const errorPropTypes = PropTypes.shape({
stack: PropTypes.string,
/* backend error messages */
- html: PropTypes.string,
+ html: PropTypes.string
});
UnconnectedErrorContent.propTypes = {
error: errorPropTypes,
- base: PropTypes.string,
+ base: PropTypes.string
};
const ErrorContent = connect(state => ({base: urlBase(state.config)}))(
@@ -175,15 +175,15 @@ const ErrorContent = connect(state => ({base: urlBase(state.config)}))(
FrontEndError.propTypes = {
e: PropTypes.shape({
timestamp: PropTypes.object,
- error: errorPropTypes,
+ error: errorPropTypes
}),
inAlertsTray: PropTypes.bool,
- isListItem: PropTypes.bool,
+ isListItem: PropTypes.bool
};
FrontEndError.defaultProps = {
inAlertsTray: false,
- isListItem: false,
+ isListItem: false
};
export {FrontEndError};
diff --git a/dash-renderer/src/components/error/FrontEnd/FrontEndErrorContainer.react.js b/dash-renderer/src/components/error/FrontEnd/FrontEndErrorContainer.react.js
index 794070aebb..3bdbf51cb3 100644
--- a/dash-renderer/src/components/error/FrontEnd/FrontEndErrorContainer.react.js
+++ b/dash-renderer/src/components/error/FrontEnd/FrontEndErrorContainer.react.js
@@ -26,16 +26,16 @@ class FrontEndErrorContainer extends Component {
}
return (
-
-
+
+
🛑 Errors (
-
+
{errorsLength}
){connected ? null : '\u00a0 🚫 Server Unavailable'}
-
{errorElements}
+
{errorElements}
);
}
@@ -44,11 +44,11 @@ class FrontEndErrorContainer extends Component {
FrontEndErrorContainer.propTypes = {
errors: PropTypes.array,
connected: PropTypes.bool,
- inAlertsTray: PropTypes.any,
+ inAlertsTray: PropTypes.any
};
FrontEndErrorContainer.propTypes = {
- inAlertsTray: PropTypes.any,
+ inAlertsTray: PropTypes.any
};
export {FrontEndErrorContainer};
diff --git a/dash-renderer/src/components/error/GlobalErrorContainer.react.js b/dash-renderer/src/components/error/GlobalErrorContainer.react.js
index bd9fa3887a..4ca50cfd01 100644
--- a/dash-renderer/src/components/error/GlobalErrorContainer.react.js
+++ b/dash-renderer/src/components/error/GlobalErrorContainer.react.js
@@ -10,15 +10,11 @@ class UnconnectedGlobalErrorContainer extends Component {
}
render() {
- const {config, error, graphs, children} = this.props;
+ const {config, error, children} = this.props;
return (
-
-
- {children}
+
);
@@ -28,14 +24,12 @@ class UnconnectedGlobalErrorContainer extends Component {
UnconnectedGlobalErrorContainer.propTypes = {
children: PropTypes.object,
config: PropTypes.object,
- error: PropTypes.object,
- graphs: PropTypes.object,
+ error: PropTypes.object
};
const GlobalErrorContainer = connect(state => ({
config: state.config,
- error: state.error,
- graphs: state.graphs,
+ error: state.error
}))(Radium(UnconnectedGlobalErrorContainer));
export default GlobalErrorContainer;
diff --git a/dash-renderer/src/components/error/GlobalErrorContainerPassthrough.react.js b/dash-renderer/src/components/error/GlobalErrorContainerPassthrough.react.js
index 11f4975f29..161f239257 100644
--- a/dash-renderer/src/components/error/GlobalErrorContainerPassthrough.react.js
+++ b/dash-renderer/src/components/error/GlobalErrorContainerPassthrough.react.js
@@ -6,12 +6,12 @@ class GlobalErrorContainer extends Component {
super(props);
}
render() {
- return {this.props.children}
;
+ return {this.props.children}
;
}
}
GlobalErrorContainer.propTypes = {
- children: PropTypes.object,
+ children: PropTypes.object
};
export default GlobalErrorContainer;
diff --git a/dash-renderer/src/components/error/GlobalErrorOverlay.react.js b/dash-renderer/src/components/error/GlobalErrorOverlay.react.js
index bdbc46b34d..4ad50a978c 100644
--- a/dash-renderer/src/components/error/GlobalErrorOverlay.react.js
+++ b/dash-renderer/src/components/error/GlobalErrorOverlay.react.js
@@ -27,7 +27,7 @@ export default class GlobalErrorOverlay extends Component {
return (
{this.props.children}
-
+
{frontEndErrors}
@@ -41,5 +41,5 @@ GlobalErrorOverlay.propTypes = {
children: PropTypes.object,
visible: PropTypes.bool,
error: PropTypes.object,
- errorsOpened: PropTypes.any,
+ errorsOpened: PropTypes.any
};
diff --git a/dash-renderer/src/components/error/menu/DebugMenu.react.js b/dash-renderer/src/components/error/menu/DebugMenu.react.js
index 636323eb48..47f0d5cf23 100644
--- a/dash-renderer/src/components/error/menu/DebugMenu.react.js
+++ b/dash-renderer/src/components/error/menu/DebugMenu.react.js
@@ -24,7 +24,7 @@ const buttonFactory = (
iconVariant,
label
) => (
-
+
<_Icon className={classes('dash-debug-menu__icon', iconVariant)} />
{label ? (
- {label}
+ {label}
) : null}
@@ -48,12 +48,12 @@ class DebugMenu extends Component {
this.state = {
opened: false,
callbackGraphOpened: false,
- errorsOpened: true,
+ errorsOpened: true
};
}
render() {
const {opened, errorsOpened, callbackGraphOpened} = this.state;
- const {error, graphs, hotReload} = this.props;
+ const {error, hotReload} = this.props;
const errCount = error.frontEnd.length + error.backEnd.length;
const connected = error.backEndConnected;
@@ -74,16 +74,14 @@ class DebugMenu extends Component {
: ClockIcon;
const menuContent = opened ? (
-
- {callbackGraphOpened ? (
-
- ) : null}
+
+ {callbackGraphOpened ? : null}
{buttonFactory(
callbackGraphOpened,
'callbacks',
() => {
this.setState({
- callbackGraphOpened: !callbackGraphOpened,
+ callbackGraphOpened: !callbackGraphOpened
});
},
GraphIcon,
@@ -108,20 +106,20 @@ class DebugMenu extends Component {
)}
) : (
-
+
);
const alertsLabel =
(errCount || !connected) && !opened ? (
-
-
+
+
{errCount ? (
-
+
{'🛑 ' + errCount}
) : null}
{connected ? null : (
-
🚫
+
🚫
)}
@@ -160,8 +158,7 @@ class DebugMenu extends Component {
DebugMenu.propTypes = {
children: PropTypes.object,
error: PropTypes.object,
- graphs: PropTypes.object,
- hotReload: PropTypes.bool,
+ hotReload: PropTypes.bool
};
export {DebugMenu};
diff --git a/dash-renderer/src/constants/constants.js b/dash-renderer/src/constants/constants.js
index f883eb68f8..c37b3b1f75 100644
--- a/dash-renderer/src/constants/constants.js
+++ b/dash-renderer/src/constants/constants.js
@@ -5,4 +5,10 @@ export const STATUS = {
OK: 200,
PREVENT_UPDATE: 204,
CLIENTSIDE_ERROR: 'CLIENTSIDE_ERROR',
+ NO_RESPONSE: 'NO_RESPONSE'
+};
+
+export const STATUSMAP = {
+ [STATUS.OK]: 'SUCCESS',
+ [STATUS.PREVENT_UPDATE]: 'NO_UPDATE'
};
diff --git a/dash-renderer/src/observers/documentTitle.ts b/dash-renderer/src/observers/documentTitle.ts
new file mode 100644
index 0000000000..f4d9bcf1f4
--- /dev/null
+++ b/dash-renderer/src/observers/documentTitle.ts
@@ -0,0 +1,55 @@
+import {IStoreObserverDefinition} from '../StoreObserver';
+import {IStoreState} from '../store';
+
+const updateTitle = (getState: () => IStoreState) => {
+ const {config, isLoading} = getState();
+
+ const update_title = config?.update_title;
+
+ if (!update_title) {
+ return;
+ }
+
+ if (isLoading) {
+ if (document.title !== update_title) {
+ observer.title = document.title;
+ document.title = update_title;
+ }
+ } else {
+ if (document.title === update_title) {
+ document.title = observer.title;
+ } else {
+ observer.title = document.title;
+ }
+ }
+};
+
+const observer: IStoreObserverDefinition
= {
+ inputs: ['isLoading'],
+ mutationObserver: undefined,
+ observer: ({getState}) => {
+ const {config} = getState();
+
+ if (observer.config !== config) {
+ observer.config = config;
+ observer.mutationObserver?.disconnect();
+ observer.mutationObserver = new MutationObserver(() =>
+ updateTitle(getState)
+ );
+
+ const title = document.querySelector('title');
+ if (title) {
+ observer.mutationObserver.observe(title, {
+ subtree: true,
+ childList: true,
+ attributes: true,
+ characterData: true
+ });
+ }
+ }
+
+ updateTitle(getState);
+ }
+};
+
+export default observer;
diff --git a/dash-renderer/src/observers/executedCallbacks.ts b/dash-renderer/src/observers/executedCallbacks.ts
index 90e3787dd7..9df4809b86 100644
--- a/dash-renderer/src/observers/executedCallbacks.ts
+++ b/dash-renderer/src/observers/executedCallbacks.ts
@@ -12,7 +12,7 @@ import {
toPairs
} from 'ramda';
-import { IStoreState } from '../store';
+import {IStoreState} from '../store';
import {
aggregateCallbacks,
@@ -22,7 +22,7 @@ import {
addStoredCallbacks
} from '../actions/callbacks';
-import { parseIfWildcard } from '../actions/dependencies';
+import {parseIfWildcard} from '../actions/dependencies';
import {
combineIdAndProp,
@@ -31,33 +31,22 @@ import {
includeObservers
} from '../actions/dependencies_ts';
-import {
- ICallback,
- IStoredCallback
-} from '../types/callbacks';
+import {ICallback, IStoredCallback} from '../types/callbacks';
-import { updateProps, setPaths, handleAsyncError } from '../actions';
-import { getPath, computePaths } from '../actions/paths';
+import {updateProps, setPaths, handleAsyncError} from '../actions';
+import {getPath, computePaths} from '../actions/paths';
-import {
- applyPersistence,
- prunePersistence
-} from '../persistence';
-import { IStoreObserverDefinition } from '../StoreObserver';
+import {applyPersistence, prunePersistence} from '../persistence';
+import {IStoreObserverDefinition} from '../StoreObserver';
const observer: IStoreObserverDefinition = {
- observer: ({
- dispatch,
- getState
- }) => {
+ observer: ({dispatch, getState}) => {
const {
- callbacks: {
- executed
- }
+ callbacks: {executed}
} = getState();
function applyProps(id: any, updatedProps: any) {
- const { layout, paths } = getState();
+ const {layout, paths} = getState();
const itempath = getPath(paths, id);
if (!itempath) {
return false;
@@ -74,7 +63,7 @@ const observer: IStoreObserverDefinition = {
// In case the update contains whole components, see if any of
// those components have props to update to persist user edits.
- const { props } = applyPersistence({ props: updatedProps }, dispatch);
+ const {props} = applyPersistence({props: updatedProps}, dispatch);
dispatch(
updateProps({
@@ -91,16 +80,10 @@ const observer: IStoreObserverDefinition = {
let storedCallbacks: IStoredCallback[] = [];
forEach(cb => {
- const predecessors = concat(
- cb.predecessors ?? [],
- [cb.callback]
- );
+ const predecessors = concat(cb.predecessors ?? [], [cb.callback]);
const {
- callback: {
- clientside_function,
- output
- },
+ callback: {clientside_function, output},
executionResult
} = cb;
@@ -108,12 +91,16 @@ const observer: IStoreObserverDefinition = {
return;
}
- const { data, error, payload } = executionResult;
+ const {data, error, payload} = executionResult;
if (data !== undefined) {
- forEach(([id, props]: [any, { [key: string]: any }]) => {
+ forEach(([id, props]: [any, {[key: string]: any}]) => {
const parsedId = parseIfWildcard(id);
- const { graphs, layout: oldLayout, paths: oldPaths } = getState();
+ const {
+ graphs,
+ layout: oldLayout,
+ paths: oldPaths
+ } = getState();
// Components will trigger callbacks on their own as required (eg. derived)
const appliedProps = applyProps(parsedId, props);
@@ -121,10 +108,19 @@ const observer: IStoreObserverDefinition = {
// Add callbacks for modified inputs
requestedCallbacks = concat(
requestedCallbacks,
- flatten(map(
- prop => getCallbacksByInput(graphs, oldPaths, parsedId, prop, true),
- keys(props)
- )).map(rcb => ({
+ flatten(
+ map(
+ prop =>
+ getCallbacksByInput(
+ graphs,
+ oldPaths,
+ parsedId,
+ prop,
+ true
+ ),
+ keys(props)
+ )
+ ).map(rcb => ({
...rcb,
predecessors
}))
@@ -132,12 +128,19 @@ const observer: IStoreObserverDefinition = {
// New layout - trigger callbacks for that explicitly
if (has('children', appliedProps)) {
- const { children } = appliedProps;
+ const {children} = appliedProps;
- const oldChildrenPath: string[] = concat(getPath(oldPaths, parsedId) as string[], ['props', 'children']);
+ const oldChildrenPath: string[] = concat(
+ getPath(oldPaths, parsedId) as string[],
+ ['props', 'children']
+ );
const oldChildren = path(oldChildrenPath, oldLayout);
- const paths = computePaths(children, oldChildrenPath, oldPaths);
+ const paths = computePaths(
+ children,
+ oldChildrenPath,
+ oldPaths
+ );
dispatch(setPaths(paths));
// Get callbacks for new layout (w/ execution group)
@@ -156,7 +159,9 @@ const observer: IStoreObserverDefinition = {
requestedCallbacks = concat(
requestedCallbacks,
getLayoutCallbacks(graphs, oldPaths, oldChildren, {
- removedArrayInputsOnly: true, newPaths: paths, chunkPath: oldChildrenPath
+ removedArrayInputsOnly: true,
+ newPaths: paths,
+ chunkPath: oldChildrenPath
}).map(rcb => ({
...rcb,
predecessors
@@ -172,11 +177,16 @@ const observer: IStoreObserverDefinition = {
appliedProps
);
if (!isEmpty(addedProps)) {
- const { graphs: currentGraphs, paths } = getState();
+ const {graphs: currentGraphs, paths} = getState();
requestedCallbacks = concat(
requestedCallbacks,
- includeObservers(id, addedProps, currentGraphs, paths).map(rcb => ({
+ includeObservers(
+ id,
+ addedProps,
+ currentGraphs,
+ paths
+ ).map(rcb => ({
...rcb,
predecessors
}))
@@ -190,25 +200,37 @@ const observer: IStoreObserverDefinition = {
storedCallbacks.push({
...cb,
executionMeta: {
- allProps: map(combineIdAndProp, flatten(cb.getOutputs(getState().paths))),
- updatedProps: flatten(map(
- ([id, value]) => map(
- property => combineIdAndProp({ id, property }),
- keys(value)
- ),
- toPairs(data)
- ))
+ allProps: map(
+ combineIdAndProp,
+ flatten(cb.getOutputs(getState().paths))
+ ),
+ updatedProps: flatten(
+ map(
+ ([id, value]) =>
+ map(
+ property =>
+ combineIdAndProp({id, property}),
+ keys(value)
+ ),
+ toPairs(data)
+ )
+ )
}
});
}
if (error !== undefined) {
const outputs = payload
- ? map(combineIdAndProp, flatten([payload.outputs])).join(', ')
+ ? map(combineIdAndProp, flatten([payload.outputs])).join(
+ ', '
+ )
: output;
let message = `Callback error updating ${outputs}`;
if (clientside_function) {
- const { namespace: ns, function_name: fn } = clientside_function;
+ const {
+ namespace: ns,
+ function_name: fn
+ } = clientside_function;
message += ` via clientside function ${ns}.${fn}`;
}
@@ -217,19 +239,28 @@ const observer: IStoreObserverDefinition = {
storedCallbacks.push({
...cb,
executionMeta: {
- allProps: map(combineIdAndProp, flatten(cb.getOutputs(getState().paths))),
+ allProps: map(
+ combineIdAndProp,
+ flatten(cb.getOutputs(getState().paths))
+ ),
updatedProps: []
}
});
}
}, executed);
- dispatch(aggregateCallbacks([
- executed.length ? removeExecutedCallbacks(executed) : null,
- executed.length ? addCompletedCallbacks(executed.length) : null,
- storedCallbacks.length ? addStoredCallbacks(storedCallbacks) : null,
- requestedCallbacks.length ? addRequestedCallbacks(requestedCallbacks) : null
- ]));
+ dispatch(
+ aggregateCallbacks([
+ executed.length ? removeExecutedCallbacks(executed) : null,
+ executed.length ? addCompletedCallbacks(executed.length) : null,
+ storedCallbacks.length
+ ? addStoredCallbacks(storedCallbacks)
+ : null,
+ requestedCallbacks.length
+ ? addRequestedCallbacks(requestedCallbacks)
+ : null
+ ])
+ );
},
inputs: ['callbacks.executed']
};
diff --git a/dash-renderer/src/observers/executingCallbacks.ts b/dash-renderer/src/observers/executingCallbacks.ts
index ffc92141e4..0ec1ef7908 100644
--- a/dash-renderer/src/observers/executingCallbacks.ts
+++ b/dash-renderer/src/observers/executingCallbacks.ts
@@ -1,9 +1,4 @@
-import {
- assoc,
- find,
- forEach,
- partition
-} from 'ramda';
+import {assoc, find, forEach, partition} from 'ramda';
import {
addExecutedCallbacks,
@@ -13,48 +8,68 @@ import {
removeWatchedCallbacks
} from '../actions/callbacks';
-import { IStoreObserverDefinition } from '../StoreObserver';
-import { IStoreState } from '../store';
+import {IStoreObserverDefinition} from '../StoreObserver';
+import {IStoreState} from '../store';
const observer: IStoreObserverDefinition = {
- observer: ({
- dispatch,
- getState
- }) => {
+ observer: ({dispatch, getState}) => {
const {
- callbacks: {
- executing
- }
+ callbacks: {executing}
} = getState();
- const [deferred, skippedOrReady] = partition(cb => cb.executionPromise instanceof Promise, executing);
+ const [deferred, skippedOrReady] = partition(
+ cb => cb.executionPromise instanceof Promise,
+ executing
+ );
- dispatch(aggregateCallbacks([
- executing.length ? removeExecutingCallbacks(executing) : null,
- deferred.length ? addWatchedCallbacks(deferred) : null,
- skippedOrReady.length ? addExecutedCallbacks(skippedOrReady.map(cb => assoc('executionResult', cb.executionPromise as any, cb))) : null
- ]));
+ dispatch(
+ aggregateCallbacks([
+ executing.length ? removeExecutingCallbacks(executing) : null,
+ deferred.length ? addWatchedCallbacks(deferred) : null,
+ skippedOrReady.length
+ ? addExecutedCallbacks(
+ skippedOrReady.map(cb =>
+ assoc(
+ 'executionResult',
+ cb.executionPromise as any,
+ cb
+ )
+ )
+ )
+ : null
+ ])
+ );
forEach(async cb => {
const result = await cb.executionPromise;
- const { callbacks: { watched } } = getState();
+ const {
+ callbacks: {watched}
+ } = getState();
// Check if it's been removed from the `watched` list since - on callback completion, another callback may be cancelled
// Find the callback instance or one that matches its promise (eg. could have been pruned)
- const currentCb = find(_cb => _cb === cb || _cb.executionPromise === cb.executionPromise, watched);
+ const currentCb = find(
+ _cb =>
+ _cb === cb || _cb.executionPromise === cb.executionPromise,
+ watched
+ );
if (!currentCb) {
return;
}
// Otherwise move to `executed` and remove from `watched`
- dispatch(aggregateCallbacks([
- removeWatchedCallbacks([currentCb]),
- addExecutedCallbacks([{
- ...currentCb,
- executionResult: result
- }])
- ]));
+ dispatch(
+ aggregateCallbacks([
+ removeWatchedCallbacks([currentCb]),
+ addExecutedCallbacks([
+ {
+ ...currentCb,
+ executionResult: result
+ }
+ ])
+ ])
+ );
}, deferred);
},
inputs: ['callbacks.executing']
diff --git a/dash-renderer/src/observers/isLoading.ts b/dash-renderer/src/observers/isLoading.ts
index fc625d45a9..687f607378 100644
--- a/dash-renderer/src/observers/isLoading.ts
+++ b/dash-renderer/src/observers/isLoading.ts
@@ -1,18 +1,11 @@
-import { IStoreObserverDefinition } from '../StoreObserver';
-import { IStoreState } from '../store';
-import { getPendingCallbacks } from '../utils/callbacks';
-import { setIsLoading } from '../actions/isLoading';
-
+import {IStoreObserverDefinition} from '../StoreObserver';
+import {IStoreState} from '../store';
+import {getPendingCallbacks} from '../utils/callbacks';
+import {setIsLoading} from '../actions/isLoading';
const observer: IStoreObserverDefinition = {
- observer: ({
- dispatch,
- getState
- }) => {
- const {
- callbacks,
- isLoading
- } = getState();
+ observer: ({dispatch, getState}) => {
+ const {callbacks, isLoading} = getState();
const pendingCallbacks = getPendingCallbacks(callbacks);
diff --git a/dash-renderer/src/observers/loadingMap.ts b/dash-renderer/src/observers/loadingMap.ts
index 50b300bfc1..d91e057811 100644
--- a/dash-renderer/src/observers/loadingMap.ts
+++ b/dash-renderer/src/observers/loadingMap.ts
@@ -1,27 +1,14 @@
-import {
- equals,
- flatten,
- isEmpty,
- map,
- reduce
-} from 'ramda';
+import {equals, flatten, isEmpty, map, reduce} from 'ramda';
-import { setLoadingMap } from '../actions/loadingMap';
-import { IStoreObserverDefinition } from '../StoreObserver';
-import { IStoreState } from '../store';
-import { ILayoutCallbackProperty } from '../types/callbacks';
+import {setLoadingMap} from '../actions/loadingMap';
+import {IStoreObserverDefinition} from '../StoreObserver';
+import {IStoreState} from '../store';
+import {ILayoutCallbackProperty} from '../types/callbacks';
const observer: IStoreObserverDefinition = {
- observer: ({
- dispatch,
- getState
- }) => {
+ observer: ({dispatch, getState}) => {
const {
- callbacks: {
- executing,
- watched,
- executed
- },
+ callbacks: {executing, watched, executed},
loadingMap,
paths
} = getState();
@@ -34,39 +21,48 @@ const observer: IStoreObserverDefinition = {
are impacted for this node and nested nodes.
*/
- const loadingPaths: ILayoutCallbackProperty[] = flatten(map(
- cb => cb.getOutputs(paths),
- [...executing, ...watched, ...executed]
- ));
+ const loadingPaths: ILayoutCallbackProperty[] = flatten(
+ map(cb => cb.getOutputs(paths), [
+ ...executing,
+ ...watched,
+ ...executed
+ ])
+ );
- const nextMap: any = isEmpty(loadingPaths) ?
- null :
- reduce(
- (res, {id, property, path}) => {
- let target = res;
- const idprop = {id, property};
+ const nextMap: any = isEmpty(loadingPaths)
+ ? null
+ : reduce(
+ (res, {id, property, path}) => {
+ let target = res;
+ const idprop = {id, property};
- // Assign all affected props for this path and nested paths
- target.__dashprivate__idprops__ = target.__dashprivate__idprops__ || [];
- target.__dashprivate__idprops__.push(idprop);
+ // Assign all affected props for this path and nested paths
+ target.__dashprivate__idprops__ =
+ target.__dashprivate__idprops__ || [];
+ target.__dashprivate__idprops__.push(idprop);
- path.forEach((p, i) => {
- target = (target[p] = target[p] ??
- (p === 'children' && typeof path[i + 1] === 'number' ? [] : {})
- );
+ path.forEach((p, i) => {
+ target = target[p] =
+ target[p] ??
+ (p === 'children' &&
+ typeof path[i + 1] === 'number'
+ ? []
+ : {});
- target.__dashprivate__idprops__ = target.__dashprivate__idprops__ || [];
- target.__dashprivate__idprops__.push(idprop);
- });
+ target.__dashprivate__idprops__ =
+ target.__dashprivate__idprops__ || [];
+ target.__dashprivate__idprops__.push(idprop);
+ });
- // Assign one affected prop for this path
- target.__dashprivate__idprop__ = target.__dashprivate__idprop__ || idprop;
+ // Assign one affected prop for this path
+ target.__dashprivate__idprop__ =
+ target.__dashprivate__idprop__ || idprop;
- return res;
- },
- {} as any,
- loadingPaths
- );
+ return res;
+ },
+ {} as any,
+ loadingPaths
+ );
if (!equals(nextMap, loadingMap)) {
dispatch(setLoadingMap(nextMap));
diff --git a/dash-renderer/src/observers/prioritizedCallbacks.ts b/dash-renderer/src/observers/prioritizedCallbacks.ts
index 0b6efeb2ba..dfda545878 100644
--- a/dash-renderer/src/observers/prioritizedCallbacks.ts
+++ b/dash-renderer/src/observers/prioritizedCallbacks.ts
@@ -1,15 +1,6 @@
-import {
- find,
- flatten,
- forEach,
- map,
- partition,
- pluck,
- sort,
- uniq
-} from 'ramda';
-
-import { IStoreState } from '../store';
+import {find, flatten, forEach, map, partition, pluck, sort, uniq} from 'ramda';
+
+import {IStoreState} from '../store';
import {
addBlockedCallbacks,
@@ -20,11 +11,9 @@ import {
removePrioritizedCallbacks
} from '../actions/callbacks';
-import { stringifyId } from '../actions/dependencies';
+import {stringifyId} from '../actions/dependencies';
-import {
- combineIdAndProp
-} from '../actions/dependencies_ts';
+import {combineIdAndProp} from '../actions/dependencies_ts';
import isAppReady from '../actions/isAppReady';
@@ -34,71 +23,94 @@ import {
ILayoutCallbackProperty,
IPrioritizedCallback
} from '../types/callbacks';
-import { IStoreObserverDefinition } from '../StoreObserver';
+import {IStoreObserverDefinition} from '../StoreObserver';
const sortPriority = (c1: ICallback, c2: ICallback): number => {
return (c1.priority ?? '') > (c2.priority ?? '') ? -1 : 1;
-}
+};
-const getStash = (cb: IPrioritizedCallback, paths: any): {
- allOutputs: ILayoutCallbackProperty[][],
- allPropIds: any[]
+const getStash = (
+ cb: IPrioritizedCallback,
+ paths: any
+): {
+ allOutputs: ILayoutCallbackProperty[][];
+ allPropIds: any[];
} => {
- const { getOutputs } = cb;
+ const {getOutputs} = cb;
const allOutputs = getOutputs(paths);
const flatOutputs: any[] = flatten(allOutputs);
const allPropIds: any[] = [];
const reqOut: any = {};
- flatOutputs.forEach(({ id, property }) => {
+ flatOutputs.forEach(({id, property}) => {
const idStr = stringifyId(id);
const idOut = (reqOut[idStr] = reqOut[idStr] || []);
idOut.push(property);
- allPropIds.push(combineIdAndProp({ id: idStr, property }));
+ allPropIds.push(combineIdAndProp({id: idStr, property}));
});
- return { allOutputs, allPropIds };
-}
+ return {allOutputs, allPropIds};
+};
-const getIds = (cb: ICallback, paths: any) => uniq(pluck('id', [
- ...flatten(cb.getInputs(paths)),
- ...flatten(cb.getState(paths))
-]));
+const getIds = (cb: ICallback, paths: any) =>
+ uniq(
+ pluck('id', [
+ ...flatten(cb.getInputs(paths)),
+ ...flatten(cb.getState(paths))
+ ])
+ );
const observer: IStoreObserverDefinition = {
- observer: async ({
- dispatch,
- getState
- }) => {
- const { callbacks: { executing, watched }, config, hooks, layout, paths } = getState();
- let { callbacks: { prioritized } } = getState();
-
- const available = Math.max(
- 0,
- 12 - executing.length - watched.length
- );
+ observer: async ({dispatch, getState}) => {
+ const {
+ callbacks: {executing, watched},
+ config,
+ hooks,
+ layout,
+ paths
+ } = getState();
+ let {
+ callbacks: {prioritized}
+ } = getState();
+
+ const available = Math.max(0, 12 - executing.length - watched.length);
// Order prioritized callbacks based on depth and breadth of callback chain
prioritized = sort(sortPriority, prioritized);
// Divide between sync and async
- const [syncCallbacks, asyncCallbacks] = partition(cb => isAppReady(
- layout,
- paths,
- getIds(cb, paths)
- ) === true, prioritized);
+ const [syncCallbacks, asyncCallbacks] = partition(
+ cb => isAppReady(layout, paths, getIds(cb, paths)) === true,
+ prioritized
+ );
const pickedSyncCallbacks = syncCallbacks.slice(0, available);
- const pickedAsyncCallbacks = asyncCallbacks.slice(0, available - pickedSyncCallbacks.length);
+ const pickedAsyncCallbacks = asyncCallbacks.slice(
+ 0,
+ available - pickedSyncCallbacks.length
+ );
if (pickedSyncCallbacks.length) {
- dispatch(aggregateCallbacks([
- removePrioritizedCallbacks(pickedSyncCallbacks),
- addExecutingCallbacks(map(
- cb => executeCallback(cb, config, hooks, paths, layout, getStash(cb, paths)),
- pickedSyncCallbacks
- ))
- ]));
+ dispatch(
+ aggregateCallbacks([
+ removePrioritizedCallbacks(pickedSyncCallbacks),
+ addExecutingCallbacks(
+ map(
+ cb =>
+ executeCallback(
+ cb,
+ config,
+ hooks,
+ paths,
+ layout,
+ getStash(cb, paths),
+ dispatch
+ ),
+ pickedSyncCallbacks
+ )
+ )
+ ])
+ );
}
if (pickedAsyncCallbacks.length) {
@@ -111,29 +123,48 @@ const observer: IStoreObserverDefinition = {
pickedAsyncCallbacks
);
- dispatch(aggregateCallbacks([
- removePrioritizedCallbacks(pickedAsyncCallbacks),
- addBlockedCallbacks(deffered)
- ]));
+ dispatch(
+ aggregateCallbacks([
+ removePrioritizedCallbacks(pickedAsyncCallbacks),
+ addBlockedCallbacks(deffered)
+ ])
+ );
forEach(async cb => {
await cb.isReady;
- const { callbacks: { blocked } } = getState();
-
- // Check if it's been removed from the `blocked` list since - on callback completion, another callback may be cancelled
- // Find the callback instance or one that matches its promise (eg. could have been pruned)
- const currentCb = find(_cb => _cb === cb || _cb.isReady === cb.isReady, blocked);
+ const {
+ callbacks: {blocked}
+ } = getState();
+
+ // Check if it's been removed from the `blocked` list since - on
+ // callback completion, another callback may be cancelled
+ // Find the callback instance or one that matches its promise
+ // (eg. could have been pruned)
+ const currentCb = find(
+ _cb => _cb === cb || _cb.isReady === cb.isReady,
+ blocked
+ );
if (!currentCb) {
return;
}
- const executingCallback = executeCallback(cb, config, hooks, paths, layout, cb);
-
- dispatch(aggregateCallbacks([
- removeBlockedCallbacks([cb]),
- addExecutingCallbacks([executingCallback])
- ]));
+ const executingCallback = executeCallback(
+ cb,
+ config,
+ hooks,
+ paths,
+ layout,
+ cb,
+ dispatch
+ );
+
+ dispatch(
+ aggregateCallbacks([
+ removeBlockedCallbacks([cb]),
+ addExecutingCallbacks([executingCallback])
+ ])
+ );
}, deffered);
}
},
diff --git a/dash-renderer/src/observers/requestedCallbacks.ts b/dash-renderer/src/observers/requestedCallbacks.ts
index 2d787a43a1..2b1cd1dc0e 100644
--- a/dash-renderer/src/observers/requestedCallbacks.ts
+++ b/dash-renderer/src/observers/requestedCallbacks.ts
@@ -4,32 +4,37 @@ import {
difference,
filter,
flatten,
+ forEach,
groupBy,
includes,
intersection,
isEmpty,
isNil,
map,
+ mergeLeft,
+ mergeWith,
+ pluck,
+ reduce,
values
} from 'ramda';
-import { IStoreState } from '../store';
+import {IStoreState} from '../store';
import {
aggregateCallbacks,
- removeRequestedCallbacks,
removePrioritizedCallbacks,
removeExecutingCallbacks,
removeWatchedCallbacks,
- addRequestedCallbacks,
addPrioritizedCallbacks,
addExecutingCallbacks,
addWatchedCallbacks,
removeBlockedCallbacks,
- addBlockedCallbacks
+ addBlockedCallbacks,
+ addRequestedCallbacks,
+ removeRequestedCallbacks
} from '../actions/callbacks';
-import { isMultiValued } from '../actions/dependencies';
+import {isMultiValued} from '../actions/dependencies';
import {
combineIdAndProp,
@@ -45,16 +50,25 @@ import {
IBlockedCallback
} from '../types/callbacks';
-import { getPendingCallbacks } from '../utils/callbacks';
-import { IStoreObserverDefinition } from '../StoreObserver';
+import wait from './../utils/wait';
+
+import {getPendingCallbacks} from '../utils/callbacks';
+import {IStoreObserverDefinition} from '../StoreObserver';
const observer: IStoreObserverDefinition = {
- observer: ({
- dispatch,
- getState
- }) => {
- const { callbacks, callbacks: { prioritized, blocked, executing, watched, stored }, paths } = getState();
- let { callbacks: { requested } } = getState();
+ observer: async ({dispatch, getState}) => {
+ await wait(0);
+
+ const {
+ callbacks,
+ callbacks: {prioritized, blocked, executing, watched, stored},
+ paths
+ } = getState();
+ let {
+ callbacks: {requested}
+ } = getState();
+
+ const initialRequested = requested.slice(0);
const pendingCallbacks = getPendingCallbacks(callbacks);
@@ -78,26 +92,53 @@ const observer: IStoreObserverDefinition = {
1. Remove duplicated `requested` callbacks - give precedence to newer callbacks over older ones
*/
- /*
- Extract all but the first callback from each IOS-key group
- these callbacks are duplicates.
- */
- const rDuplicates = flatten(map(
- group => group.slice(0, -1),
- values(
- groupBy(
- getUniqueIdentifier,
- requested
- )
- )
- ));
+ let rDuplicates: ICallback[] = [];
+ let rMergedDuplicates: ICallback[] = [];
+
+ forEach(group => {
+ if (group.length === 1) {
+ // keep callback if its the only one of its kind
+ rMergedDuplicates.push(group[0]);
+ } else {
+ const initial = group.find(cb => cb.initialCall);
+ if (initial) {
+ // drop the initial callback if it's not alone
+ rDuplicates.push(initial);
+ }
+
+ const groupWithoutInitial = group.filter(cb => cb !== initial);
+ if (groupWithoutInitial.length === 1) {
+ // if there's only one callback beside the initial one, keep that callback
+ rMergedDuplicates.push(groupWithoutInitial[0]);
+ } else {
+ // otherwise merge all remaining callbacks together
+ rDuplicates = concat(rDuplicates, groupWithoutInitial);
+ rMergedDuplicates.push(
+ mergeLeft(
+ {
+ changedPropIds: reduce(
+ mergeWith(Math.max),
+ {},
+ pluck('changedPropIds', groupWithoutInitial)
+ ),
+ executionGroup: filter(
+ exg => !!exg,
+ pluck('executionGroup', groupWithoutInitial)
+ ).slice(-1)[0]
+ },
+ groupWithoutInitial.slice(-1)[0]
+ ) as ICallback
+ );
+ }
+ }
+ }, values(groupBy(getUniqueIdentifier, requested)));
/*
TODO?
Clean up the `requested` list - during the dispatch phase,
duplicates will be removed for real
*/
- requested = difference(requested, rDuplicates);
+ requested = rMergedDuplicates;
/*
2. Remove duplicated `prioritized`, `executing` and `watching` callbacks
@@ -107,73 +148,94 @@ const observer: IStoreObserverDefinition = {
Extract all but the first callback from each IOS-key group
these callbacks are `prioritized` and duplicates.
*/
- const pDuplicates = flatten(map(
- group => group.slice(0, -1),
- values(
- groupBy(
- getUniqueIdentifier,
- concat(prioritized, requested)
+ const pDuplicates = flatten(
+ map(
+ group => group.slice(0, -1),
+ values(
+ groupBy(
+ getUniqueIdentifier,
+ concat(prioritized, requested)
+ )
)
)
- ));
-
- const bDuplicates = flatten(map(
- group => group.slice(0, -1),
- values(
- groupBy(
- getUniqueIdentifier,
- concat(blocked, requested)
+ );
+
+ const bDuplicates = flatten(
+ map(
+ group => group.slice(0, -1),
+ values(
+ groupBy(
+ getUniqueIdentifier,
+ concat(blocked, requested)
+ )
)
)
- )) as IBlockedCallback[];
-
- const eDuplicates = flatten(map(
- group => group.slice(0, -1),
- values(
- groupBy(
- getUniqueIdentifier,
- concat(executing, requested)
+ ) as IBlockedCallback[];
+
+ const eDuplicates = flatten(
+ map(
+ group => group.slice(0, -1),
+ values(
+ groupBy(
+ getUniqueIdentifier,
+ concat(executing, requested)
+ )
)
)
- )) as IExecutingCallback[];
-
- const wDuplicates = flatten(map(
- group => group.slice(0, -1),
- values(
- groupBy(
- getUniqueIdentifier,
- concat(watched, requested)
+ ) as IExecutingCallback[];
+
+ const wDuplicates = flatten(
+ map(
+ group => group.slice(0, -1),
+ values(
+ groupBy(
+ getUniqueIdentifier,
+ concat(watched, requested)
+ )
)
)
- )) as IExecutingCallback[];
+ ) as IExecutingCallback[];
/*
3. Modify or remove callbacks that are outputting to non-existing layout `id`.
*/
- const { added: rAdded, removed: rRemoved } = pruneCallbacks(requested, paths);
- const { added: pAdded, removed: pRemoved } = pruneCallbacks(prioritized, paths);
- const { added: bAdded, removed: bRemoved } = pruneCallbacks(blocked, paths);
- const { added: eAdded, removed: eRemoved } = pruneCallbacks(executing, paths);
- const { added: wAdded, removed: wRemoved } = pruneCallbacks(watched, paths);
+ const {added: rAdded, removed: rRemoved} = pruneCallbacks(
+ requested,
+ paths
+ );
+ const {added: pAdded, removed: pRemoved} = pruneCallbacks(
+ prioritized,
+ paths
+ );
+ const {added: bAdded, removed: bRemoved} = pruneCallbacks(
+ blocked,
+ paths
+ );
+ const {added: eAdded, removed: eRemoved} = pruneCallbacks(
+ executing,
+ paths
+ );
+ const {added: wAdded, removed: wRemoved} = pruneCallbacks(
+ watched,
+ paths
+ );
/*
TODO?
Clean up the `requested` list - during the dispatch phase,
it will be updated for real
*/
- requested = concat(
- difference(
- requested,
- rRemoved
- ),
- rAdded
- );
+ requested = concat(difference(requested, rRemoved), rAdded);
/*
4. Find `requested` callbacks that do not depend on a outstanding output (as either input or state)
*/
- let readyCallbacks = getReadyCallbacks(paths, requested, pendingCallbacks);
+ let readyCallbacks = getReadyCallbacks(
+ paths,
+ requested,
+ pendingCallbacks
+ );
let oldBlocked: ICallback[] = [];
let newBlocked: ICallback[] = [];
@@ -210,21 +272,32 @@ const observer: IStoreObserverDefinition = {
candidates = candidates.slice(1);
// Remaining candidates are not blocked by current assumptions
- candidates = getReadyCallbacks(paths, candidates, readyCallbacks);
+ candidates = getReadyCallbacks(
+ paths,
+ candidates,
+ readyCallbacks
+ );
// Blocked requests need to make sure they have the callback as a predecessor
const blockedByAssumptions = difference(candidates, candidates);
const modified = filter(
- cb => !cb.predecessors || !includes(readyCallback.callback, cb.predecessors),
+ cb =>
+ !cb.predecessors ||
+ !includes(readyCallback.callback, cb.predecessors),
blockedByAssumptions
);
oldBlocked = concat(oldBlocked, modified);
- newBlocked = concat(newBlocked, modified.map(cb => ({
- ...cb,
- predecessors: concat(cb.predecessors ?? [], [readyCallback.callback])
- })));
+ newBlocked = concat(
+ newBlocked,
+ modified.map(cb => ({
+ ...cb,
+ predecessors: concat(cb.predecessors ?? [], [
+ readyCallback.callback
+ ])
+ }))
+ );
}
}
@@ -233,13 +306,7 @@ const observer: IStoreObserverDefinition = {
Clean up the `requested` list - during the dispatch phase,
it will be updated for real
*/
- requested = concat(
- difference(
- requested,
- oldBlocked
- ),
- newBlocked
- );
+ requested = concat(difference(requested, oldBlocked), newBlocked);
/*
5. Prune callbacks that became irrelevant in their `executionGroup`
@@ -255,7 +322,11 @@ const observer: IStoreObserverDefinition = {
const dropped: ICallback[] = filter(cb => {
// If there is no `stored` callback for the group, no outputs were dropped -> `cb` is kept
- if (!cb.executionGroup || !pendingGroups[cb.executionGroup] || !pendingGroups[cb.executionGroup].length) {
+ if (
+ !cb.executionGroup ||
+ !pendingGroups[cb.executionGroup] ||
+ !pendingGroups[cb.executionGroup].length
+ ) {
return false;
}
@@ -263,84 +334,76 @@ const observer: IStoreObserverDefinition = {
const inputs = map(combineIdAndProp, flatten(cb.getInputs(paths)));
// Get all the potentially updated props for the group so far
- const allProps = flatten(map(
- gcb => gcb.executionMeta.allProps,
- pendingGroups[cb.executionGroup]
- ));
+ const allProps = flatten(
+ map(
+ gcb => gcb.executionMeta.allProps,
+ pendingGroups[cb.executionGroup]
+ )
+ );
// Get all the updated props for the group so far
- const updated = flatten(map(
- gcb => gcb.executionMeta.updatedProps,
- pendingGroups[cb.executionGroup]
- ));
+ const updated = flatten(
+ map(
+ gcb => gcb.executionMeta.updatedProps,
+ pendingGroups[cb.executionGroup]
+ )
+ );
// If there's no overlap between the updated props and the inputs,
// + there's no props that aren't covered by the potentially updated props,
// and not all inputs are multi valued
// -> drop `cb`
const res =
- isEmpty(intersection(
- inputs,
- updated
- )) &&
- isEmpty(difference(
- inputs,
- allProps
- ))
- && !all(
- isMultiValued,
- cb.callback.inputs
- );
+ isEmpty(intersection(inputs, updated)) &&
+ isEmpty(difference(inputs, allProps)) &&
+ !all(isMultiValued, cb.callback.inputs);
return res;
- },
- readyCallbacks
- );
+ }, readyCallbacks);
/*
TODO?
Clean up the `requested` list - during the dispatch phase,
it will be updated for real
*/
- requested = difference(
- requested,
- dropped
- );
-
- readyCallbacks = difference(
- readyCallbacks,
- dropped
+ requested = difference(requested, dropped);
+
+ readyCallbacks = difference(readyCallbacks, dropped);
+
+ requested = difference(requested, readyCallbacks);
+
+ const added = difference(requested, initialRequested);
+ const removed = difference(initialRequested, requested);
+
+ dispatch(
+ aggregateCallbacks([
+ // Clean up requested callbacks
+ added.length ? addRequestedCallbacks(added) : null,
+ removed.length ? removeRequestedCallbacks(removed) : null,
+ // Clean up duplicated callbacks
+ pDuplicates.length
+ ? removePrioritizedCallbacks(pDuplicates)
+ : null,
+ bDuplicates.length ? removeBlockedCallbacks(bDuplicates) : null,
+ eDuplicates.length
+ ? removeExecutingCallbacks(eDuplicates)
+ : null,
+ wDuplicates.length ? removeWatchedCallbacks(wDuplicates) : null,
+ // Prune callbacks
+ pRemoved.length ? removePrioritizedCallbacks(pRemoved) : null,
+ pAdded.length ? addPrioritizedCallbacks(pAdded) : null,
+ bRemoved.length ? removeBlockedCallbacks(bRemoved) : null,
+ bAdded.length ? addBlockedCallbacks(bAdded) : null,
+ eRemoved.length ? removeExecutingCallbacks(eRemoved) : null,
+ eAdded.length ? addExecutingCallbacks(eAdded) : null,
+ wRemoved.length ? removeWatchedCallbacks(wRemoved) : null,
+ wAdded.length ? addWatchedCallbacks(wAdded) : null,
+ // Promote callbacks
+ readyCallbacks.length
+ ? addPrioritizedCallbacks(readyCallbacks)
+ : null
+ ])
);
-
- dispatch(aggregateCallbacks([
- // Clean up duplicated callbacks
- rDuplicates.length ? removeRequestedCallbacks(rDuplicates) : null,
- pDuplicates.length ? removePrioritizedCallbacks(pDuplicates) : null,
- bDuplicates.length ? removeBlockedCallbacks(bDuplicates) : null,
- eDuplicates.length ? removeExecutingCallbacks(eDuplicates) : null,
- wDuplicates.length ? removeWatchedCallbacks(wDuplicates) : null,
- // Prune callbacks
- rRemoved.length ? removeRequestedCallbacks(rRemoved) : null,
- rAdded.length ? addRequestedCallbacks(rAdded) : null,
- pRemoved.length ? removePrioritizedCallbacks(pRemoved) : null,
- pAdded.length ? addPrioritizedCallbacks(pAdded) : null,
- bRemoved.length ? removeBlockedCallbacks(bRemoved) : null,
- bAdded.length ? addBlockedCallbacks(bAdded) : null,
- eRemoved.length ? removeExecutingCallbacks(eRemoved) : null,
- eAdded.length ? addExecutingCallbacks(eAdded) : null,
- wRemoved.length ? removeWatchedCallbacks(wRemoved) : null,
- wAdded.length ? addWatchedCallbacks(wAdded) : null,
- // Prune circular callbacks
- rCirculars.length ? removeRequestedCallbacks(rCirculars) : null,
- // Prune circular assumptions
- oldBlocked.length ? removeRequestedCallbacks(oldBlocked) : null,
- newBlocked.length ? addRequestedCallbacks(newBlocked) : null,
- // Drop non-triggered initial callbacks
- dropped.length ? removeRequestedCallbacks(dropped) : null,
- // Promote callbacks
- readyCallbacks.length ? removeRequestedCallbacks(readyCallbacks) : null,
- readyCallbacks.length ? addPrioritizedCallbacks(readyCallbacks) : null
- ]));
},
inputs: ['callbacks.requested', 'callbacks.completed']
};
diff --git a/dash-renderer/src/observers/storedCallbacks.ts b/dash-renderer/src/observers/storedCallbacks.ts
index 83b19518b9..58116a73c8 100644
--- a/dash-renderer/src/observers/storedCallbacks.ts
+++ b/dash-renderer/src/observers/storedCallbacks.ts
@@ -8,30 +8,23 @@ import {
toPairs
} from 'ramda';
-import { IStoreState } from '../store';
+import {IStoreState} from '../store';
-import {
- aggregateCallbacks,
- removeStoredCallbacks
-} from '../actions/callbacks';
+import {aggregateCallbacks, removeStoredCallbacks} from '../actions/callbacks';
-import {
- ICallback,
- IStoredCallback
-} from '../types/callbacks';
+import {ICallback, IStoredCallback} from '../types/callbacks';
-import { getPendingCallbacks } from '../utils/callbacks';
-import { IStoreObserverDefinition } from '../StoreObserver';
+import {getPendingCallbacks} from '../utils/callbacks';
+import {IStoreObserverDefinition} from '../StoreObserver';
const observer: IStoreObserverDefinition = {
- observer: ({
- dispatch,
- getState
- }) => {
- const { callbacks } = getState();
+ observer: ({dispatch, getState}) => {
+ const {callbacks} = getState();
const pendingCallbacks = getPendingCallbacks(callbacks);
- let { callbacks: { stored } } = getState();
+ let {
+ callbacks: {stored}
+ } = getState();
const [nullGroupCallbacks, groupCallbacks] = partition(
cb => isNil(cb.executionGroup),
@@ -41,27 +34,30 @@ const observer: IStoreObserverDefinition = {
const executionGroups = groupBy(
cb => cb.executionGroup as any,
groupCallbacks
- )
+ );
const pendingGroups = groupBy(
cb => cb.executionGroup as any,
filter(cb => !isNil(cb.executionGroup), pendingCallbacks)
);
- let dropped = reduce((res, [
- executionGroup,
- executionGroupCallbacks
- ]) => !pendingGroups[executionGroup] ?
- concat(res, executionGroupCallbacks) :
- res,
+ let dropped = reduce(
+ (res, [executionGroup, executionGroupCallbacks]) =>
+ !pendingGroups[executionGroup]
+ ? concat(res, executionGroupCallbacks)
+ : res,
[] as IStoredCallback[],
toPairs(executionGroups)
);
- dispatch(aggregateCallbacks([
- nullGroupCallbacks.length ? removeStoredCallbacks(nullGroupCallbacks) : null,
- dropped.length ? removeStoredCallbacks(dropped) : null
- ]));
+ dispatch(
+ aggregateCallbacks([
+ nullGroupCallbacks.length
+ ? removeStoredCallbacks(nullGroupCallbacks)
+ : null,
+ dropped.length ? removeStoredCallbacks(dropped) : null
+ ])
+ );
},
inputs: ['callbacks.stored', 'callbacks.completed']
};
diff --git a/dash-renderer/src/persistence.js b/dash-renderer/src/persistence.js
index 658b83d896..85d3b47a00 100644
--- a/dash-renderer/src/persistence.js
+++ b/dash-renderer/src/persistence.js
@@ -64,7 +64,7 @@ import {
lensPath,
mergeRight,
set,
- type,
+ type
} from 'ramda';
import {createAction} from 'redux-actions';
@@ -78,7 +78,7 @@ function err(e) {
return createAction('ON_ERROR')({
type: 'frontEnd',
- error,
+ error
});
}
@@ -208,14 +208,14 @@ function longString() {
}
export const stores = {
- memory: new MemStore(),
+ memory: new MemStore()
// Defer testing & making local/session stores until requested.
// That way if we have errors here they can show up in devtools.
};
const backEnds = {
local: 'localStorage',
- session: 'sessionStorage',
+ session: 'sessionStorage'
};
function tryGetWebStore(backEnd, dispatch) {
@@ -262,7 +262,7 @@ function getStore(type, dispatch) {
const noopTransform = {
extract: propValue => propValue,
- apply: (storedValue, _propValue) => storedValue,
+ apply: (storedValue, _propValue) => storedValue
};
const getTransform = (element, propName, propPart) => {
@@ -302,7 +302,7 @@ const getProps = layout => {
element,
persistence,
persisted_props,
- persistence_type,
+ persistence_type
};
};
@@ -314,7 +314,7 @@ export function recordUiEdit(layout, newProps, dispatch) {
element,
persistence,
persisted_props,
- persistence_type,
+ persistence_type
} = getProps(layout);
if (!canPersist || !persistence) {
return;
@@ -389,7 +389,7 @@ function persistenceMods(layout, component, path, dispatch) {
element,
persistence,
persisted_props,
- persistence_type,
+ persistence_type
} = getProps(component);
let layoutOut = layout;
@@ -455,7 +455,7 @@ export function prunePersistence(layout, newProps, dispatch) {
persistence,
persisted_props,
persistence_type,
- element,
+ element
} = getProps(layout);
const getFinal = (propName, prevVal) =>
diff --git a/dash-renderer/src/reducers/callbacks.ts b/dash-renderer/src/reducers/callbacks.ts
index 196c652938..5386960354 100644
--- a/dash-renderer/src/reducers/callbacks.ts
+++ b/dash-renderer/src/reducers/callbacks.ts
@@ -1,8 +1,4 @@
-import {
- concat,
- difference,
- reduce
-} from 'ramda';
+import {concat, difference, reduce} from 'ramda';
import {
ICallback,
@@ -37,8 +33,8 @@ export enum CallbackAggregateActionType {
}
export interface IAggregateAction {
- type: CallbackAggregateActionType.Aggregate,
- payload: (ICallbackAction | ICompletedAction | null)[]
+ type: CallbackAggregateActionType.Aggregate;
+ payload: (ICallbackAction | ICompletedAction | null)[];
}
export interface ICallbackAction {
@@ -47,14 +43,11 @@ export interface ICallbackAction {
}
export interface ICompletedAction {
- type: CallbackAggregateActionType.AddCompleted,
- payload: number
+ type: CallbackAggregateActionType.AddCompleted;
+ payload: number;
}
-type CallbackAction =
- IAggregateAction |
- ICallbackAction |
- ICompletedAction;
+type CallbackAction = IAggregateAction | ICallbackAction | ICompletedAction;
export interface ICallbacksState {
requested: ICallback[];
@@ -79,7 +72,7 @@ const DEFAULT_STATE: ICallbacksState = {
};
const transforms: {
- [key: string]: (a1: ICallback[], a2: ICallback[]) => ICallback[]
+ [key: string]: (a1: ICallback[], a2: ICallback[]) => ICallback[];
} = {
[CallbackActionType.AddBlocked]: concat,
[CallbackActionType.AddExecuted]: concat,
@@ -98,7 +91,7 @@ const transforms: {
};
const fields: {
- [key: string]: keyof Omit
+ [key: string]: keyof Omit;
} = {
[CallbackActionType.AddBlocked]: 'blocked',
[CallbackActionType.AddExecuted]: 'executed',
@@ -114,41 +107,41 @@ const fields: {
[CallbackActionType.RemoveRequested]: 'requested',
[CallbackActionType.RemoveStored]: 'stored',
[CallbackActionType.RemoveWatched]: 'watched'
-}
+};
-const mutateCompleted = (
- state: ICallbacksState,
- action: ICompletedAction
-) => ({ ...state, completed: state.completed + action.payload });
+const mutateCompleted = (state: ICallbacksState, action: ICompletedAction) => ({
+ ...state,
+ completed: state.completed + action.payload
+});
-const mutateCallbacks = (
- state: ICallbacksState,
- action: ICallbackAction
-) => {
+const mutateCallbacks = (state: ICallbacksState, action: ICallbackAction) => {
const transform = transforms[action.type];
const field = fields[action.type];
- return (!transform || !field || action.payload.length === 0) ?
- state : {
- ...state,
- [field]: transform(state[field], action.payload)
- };
-}
-
-
+ return !transform || !field || action.payload.length === 0
+ ? state
+ : {
+ ...state,
+ [field]: transform(state[field], action.payload)
+ };
+};
export default (
state: ICallbacksState = DEFAULT_STATE,
action: CallbackAction
-) => reduce((s, a) => {
- if (a === null) {
- return s;
- } else if (a.type === CallbackAggregateActionType.AddCompleted) {
- return mutateCompleted(s, a);
- } else {
- return mutateCallbacks(s, a);
- }
-}, state, action.type === CallbackAggregateActionType.Aggregate ?
- action.payload :
- [action]
-);
+) =>
+ reduce(
+ (s, a) => {
+ if (a === null) {
+ return s;
+ } else if (a.type === CallbackAggregateActionType.AddCompleted) {
+ return mutateCompleted(s, a);
+ } else {
+ return mutateCallbacks(s, a);
+ }
+ },
+ state,
+ action.type === CallbackAggregateActionType.Aggregate
+ ? action.payload
+ : [action]
+ );
diff --git a/dash-renderer/src/reducers/changed.js b/dash-renderer/src/reducers/changed.js
new file mode 100644
index 0000000000..80fb1db107
--- /dev/null
+++ b/dash-renderer/src/reducers/changed.js
@@ -0,0 +1,13 @@
+const initialChange = {
+ id: null,
+ props: {}
+};
+
+function changed(state = initialChange) {
+ // This is empty just to initialize the store. Changes
+ // are actually recorded in reducer.js so that we can
+ // resolve paths to id.
+ return state;
+}
+
+export default changed;
diff --git a/dash-renderer/src/reducers/constants.js b/dash-renderer/src/reducers/constants.js
index da4dfb20b6..e8943eac5c 100644
--- a/dash-renderer/src/reducers/constants.js
+++ b/dash-renderer/src/reducers/constants.js
@@ -1,7 +1,7 @@
export function getAppState(state) {
const stateList = {
STARTED: 'STARTED',
- HYDRATED: 'HYDRATED',
+ HYDRATED: 'HYDRATED'
};
if (stateList[state]) {
return stateList[state];
diff --git a/dash-renderer/src/reducers/error.js b/dash-renderer/src/reducers/error.js
index 4188703054..a5dbfc12a6 100644
--- a/dash-renderer/src/reducers/error.js
+++ b/dash-renderer/src/reducers/error.js
@@ -3,7 +3,7 @@ import {mergeRight} from 'ramda';
const initialError = {
frontEnd: [],
backEnd: [],
- backEndConnected: true,
+ backEndConnected: true
};
export default function error(state = initialError, action) {
@@ -19,19 +19,19 @@ export default function error(state = initialError, action) {
return {
frontEnd: [
mergeRight(action.payload, {timestamp: new Date()}),
- ...frontEnd,
+ ...frontEnd
],
backEnd,
- backEndConnected,
+ backEndConnected
};
} else if (action.payload.type === 'backEnd') {
return {
frontEnd,
backEnd: [
mergeRight(action.payload, {timestamp: new Date()}),
- ...backEnd,
+ ...backEnd
],
- backEndConnected,
+ backEndConnected
};
}
return state;
diff --git a/dash-renderer/src/reducers/history.js b/dash-renderer/src/reducers/history.js
index 091cfb3221..799ede6705 100644
--- a/dash-renderer/src/reducers/history.js
+++ b/dash-renderer/src/reducers/history.js
@@ -1,7 +1,7 @@
const initialHistory = {
past: [],
present: {},
- future: [],
+ future: []
};
function history(state = initialHistory, action) {
@@ -13,7 +13,7 @@ function history(state = initialHistory, action) {
return {
past: newPast,
present: previous,
- future: [present, ...future],
+ future: [present, ...future]
};
}
@@ -24,7 +24,7 @@ function history(state = initialHistory, action) {
return {
past: [...past, present],
present: next,
- future: newFuture,
+ future: newFuture
};
}
@@ -35,7 +35,7 @@ function history(state = initialHistory, action) {
return {
past: newPast,
present: previous,
- future: [...future],
+ future: [...future]
};
}
diff --git a/dash-renderer/src/reducers/isLoading.ts b/dash-renderer/src/reducers/isLoading.ts
index 0a25260551..8f0c84124e 100644
--- a/dash-renderer/src/reducers/isLoading.ts
+++ b/dash-renderer/src/reducers/isLoading.ts
@@ -8,15 +8,11 @@ export interface ILoadingMapAction {
}
type IsLoadingState = boolean;
-export {
- IsLoadingState
-};
+export {IsLoadingState};
const DEFAULT_STATE: IsLoadingState = true;
export default (
state: IsLoadingState = DEFAULT_STATE,
action: ILoadingMapAction
-) => action.type === IsLoadingActionType.Set ?
- action.payload :
- state;
+) => (action.type === IsLoadingActionType.Set ? action.payload : state);
diff --git a/dash-renderer/src/reducers/layout.js b/dash-renderer/src/reducers/layout.js
index d9a6b6407f..6c082f313c 100644
--- a/dash-renderer/src/reducers/layout.js
+++ b/dash-renderer/src/reducers/layout.js
@@ -9,7 +9,7 @@ const layout = (state = {}, action) => {
includes(action.type, [
'UNDO_PROP_CHANGE',
'REDO_PROP_CHANGE',
- getAction('ON_PROP_CHANGE'),
+ getAction('ON_PROP_CHANGE')
])
) {
const propPath = append('props', action.payload.itempath);
diff --git a/dash-renderer/src/reducers/loadingMap.ts b/dash-renderer/src/reducers/loadingMap.ts
index 1fb31a208d..14981e9268 100644
--- a/dash-renderer/src/reducers/loadingMap.ts
+++ b/dash-renderer/src/reducers/loadingMap.ts
@@ -8,15 +8,11 @@ export interface ILoadingMapAction {
}
type LoadingMapState = any;
-export {
- LoadingMapState
-};
+export {LoadingMapState};
const DEFAULT_STATE: LoadingMapState = {};
export default (
state: LoadingMapState = DEFAULT_STATE,
action: ILoadingMapAction
-) => action.type === LoadingMapActionType.Set ?
- action.payload :
- state;
+) => (action.type === LoadingMapActionType.Set ? action.payload : state);
diff --git a/dash-renderer/src/reducers/profile.js b/dash-renderer/src/reducers/profile.js
new file mode 100644
index 0000000000..b71a61106d
--- /dev/null
+++ b/dash-renderer/src/reducers/profile.js
@@ -0,0 +1,86 @@
+import {clone} from 'ramda';
+
+import {STATUSMAP} from '../constants/constants';
+
+const defaultProfile = {
+ count: 0,
+ total: 0,
+ compute: 0,
+ network: {
+ time: 0,
+ upload: 0,
+ download: 0
+ },
+ resources: {},
+ status: {
+ latest: null
+ },
+ result: {}
+};
+
+const defaultState = {
+ updated: [],
+ resources: {},
+ callbacks: {}
+};
+
+const profile = (state = defaultState, action) => {
+ if (action.type === 'UPDATE_RESOURCE_USAGE') {
+ // Keep a record of the most recent change. This
+ // is subtly different from history.present becasue
+ // it watches all props, not just inputs.
+ const {id, usage, status} = action.payload;
+ const statusMapped = STATUSMAP[status] || status;
+
+ // Keep track of the callback that actually changed.
+ const newState = {
+ updated: [id],
+ resources: state.resources,
+ callbacks: state.callbacks
+ };
+
+ newState.callbacks[id] =
+ newState.callbacks[id] || clone(defaultProfile);
+
+ const cb = newState.callbacks[id];
+ const cbResources = cb.resources;
+ const totalResources = newState.resources;
+
+ // Update resource usage & params.
+ cb.count += 1;
+ cb.status.latest = statusMapped;
+ cb.status[statusMapped] = (cb.status[statusMapped] || 0) + 1;
+ cb.result = action.payload.result;
+ cb.inputs = action.payload.inputs;
+ cb.state = action.payload.state;
+
+ if (usage) {
+ const {
+ __dash_client,
+ __dash_server,
+ __dash_upload,
+ __dash_download,
+ ...user
+ } = usage;
+
+ cb.total += __dash_client;
+ cb.compute += __dash_server;
+ cb.network.time += __dash_client - __dash_server;
+ cb.network.upload += __dash_upload;
+ cb.network.download += __dash_download;
+
+ for (const r in user) {
+ if (user.hasOwnProperty(r)) {
+ cbResources[r] = (cbResources[r] || 0) + user[r];
+ totalResources[r] = (totalResources[r] || 0) + user[r];
+ }
+ }
+ }
+
+ return newState;
+ }
+
+ return state;
+};
+
+export default profile;
diff --git a/dash-renderer/src/reducers/reducer.js b/dash-renderer/src/reducers/reducer.js
index d238b75225..c722119270 100644
--- a/dash-renderer/src/reducers/reducer.js
+++ b/dash-renderer/src/reducers/reducer.js
@@ -11,6 +11,8 @@ import graphs from './dependencyGraph';
import error from './error';
import history from './history';
import hooks from './hooks';
+import profile from './profile';
+import changed from './changed';
import isLoading from './isLoading';
import layout from './layout';
import loadingMap from './loadingMap';
@@ -20,7 +22,7 @@ export const apiRequests = [
'dependenciesRequest',
'layoutRequest',
'reloadRequest',
- 'loginRequest',
+ 'loginRequest'
];
function mainReducer() {
@@ -32,10 +34,12 @@ function mainReducer() {
graphs,
history,
hooks,
+ profile,
+ changed,
isLoading,
layout,
loadingMap,
- paths,
+ paths
};
forEach(r => {
parts[r] = createApiReducer(r);
@@ -44,16 +48,22 @@ function mainReducer() {
return combineReducers(parts);
}
-function getInputHistoryState(itempath, props, state) {
- const {graphs, layout, paths} = state;
- const idProps = path(itempath.concat(['props']), layout);
- const {id} = idProps || {};
+function getInputHistoryState(payload, state, recordChanges) {
+ const {graphs, paths, layout} = state;
+ const {itempath, props} = payload;
+ const refProps = path(itempath.concat(['props']), layout) || {};
+ const {id} = refProps;
+
let historyEntry;
if (id) {
+ if (recordChanges) {
+ state.changed = {id, props};
+ }
+
historyEntry = {id, props: {}};
keys(props).forEach(propKey => {
if (getCallbacksByInput(graphs, paths, id, propKey).length) {
- historyEntry.props[propKey] = idProps[propKey];
+ historyEntry.props[propKey] = refProps[propKey];
}
});
}
@@ -63,9 +73,10 @@ function getInputHistoryState(itempath, props, state) {
function recordHistory(reducer) {
return function(state, action) {
// Record initial state
- if (action.type === 'ON_PROP_CHANGE') {
- const {itempath, props} = action.payload;
- const historyEntry = getInputHistoryState(itempath, props, state);
+ const {type, payload} = action;
+ if (type === 'ON_PROP_CHANGE') {
+ // history records all prop changes that are inputs.
+ const historyEntry = getInputHistoryState(payload, state, true);
if (historyEntry && !isEmpty(historyEntry.props)) {
state.history.present = historyEntry;
}
@@ -73,25 +84,17 @@ function recordHistory(reducer) {
const nextState = reducer(state, action);
- if (
- action.type === 'ON_PROP_CHANGE' &&
- action.payload.source !== 'response'
- ) {
- const {itempath, props} = action.payload;
+ if (type === 'ON_PROP_CHANGE' && payload.source !== 'response') {
/*
* if the prop change is an input, then
* record it so that it can be played back
*/
- const historyEntry = getInputHistoryState(
- itempath,
- props,
- nextState
- );
+ const historyEntry = getInputHistoryState(payload, nextState);
if (historyEntry && !isEmpty(historyEntry.props)) {
nextState.history = {
past: [...nextState.history.past, state.history.present],
present: historyEntry,
- future: [],
+ future: []
};
}
}
diff --git a/dash-renderer/src/registry.js b/dash-renderer/src/registry.js
index 35d60e4924..00bd498cb9 100644
--- a/dash-renderer/src/registry.js
+++ b/dash-renderer/src/registry.js
@@ -13,5 +13,5 @@ export default {
}
throw new Error(`${namespace} was not found.`);
- },
+ }
};
diff --git a/dash-renderer/src/store.ts b/dash-renderer/src/store.ts
index 3b26f75a92..3639b92fa2 100644
--- a/dash-renderer/src/store.ts
+++ b/dash-renderer/src/store.ts
@@ -1,15 +1,16 @@
-import { once } from 'ramda';
-import { createStore, applyMiddleware, Store, Observer } from 'redux';
+import {once} from 'ramda';
+import {createStore, applyMiddleware, Store, Observer} from 'redux';
import thunk from 'redux-thunk';
import {createReducer} from './reducers/reducer';
import StoreObserver from './StoreObserver';
-import { ICallbacksState } from './reducers/callbacks';
-import { LoadingMapState } from './reducers/loadingMap';
-import { IsLoadingState } from './reducers/isLoading';
+import {ICallbacksState} from './reducers/callbacks';
+import {LoadingMapState} from './reducers/loadingMap';
+import {IsLoadingState} from './reducers/isLoading';
+import documentTitle from './observers/documentTitle';
import executedCallbacks from './observers/executedCallbacks';
import executingCallbacks from './observers/executingCallbacks';
-import isLoading from './observers/isLoading'
+import isLoading from './observers/isLoading';
import loadingMap from './observers/loadingMap';
import prioritizedCallbacks from './observers/prioritizedCallbacks';
import requestedCallbacks from './observers/requestedCallbacks';
@@ -33,6 +34,7 @@ const storeObserver = new StoreObserver();
const setObservers = once(() => {
const observe = storeObserver.observe;
+ observe(documentTitle);
observe(isLoading);
observe(loadingMap);
observe(requestedCallbacks);
diff --git a/dash-renderer/src/styles/styles.js b/dash-renderer/src/styles/styles.js
index 868e2ec662..9b84068224 100644
--- a/dash-renderer/src/styles/styles.js
+++ b/dash-renderer/src/styles/styles.js
@@ -16,7 +16,7 @@ export const base = {
html: {
fontFamily: "'Open Sans', Helvetica, sans-serif",
fontWeight: 400,
- color: '#2A3F5F',
+ color: '#2A3F5F'
},
h2: {
@@ -24,13 +24,13 @@ export const base = {
fontWeight: '600',
fontSize: '28px',
marginTop: '14px',
- marginBottom: '14px',
+ marginBottom: '14px'
},
h4: {
fontSize: '18px',
marginTop: '9px',
- marginBottom: '18px',
+ marginBottom: '18px'
},
button: {
@@ -46,27 +46,27 @@ export const base = {
lineHeight: '1',
cursor: 'pointer',
outline: 'none',
- margin: '0px',
+ margin: '0px'
},
a: {
color: '#119DFF',
textDecoration: 'none',
- cursor: 'pointer',
+ cursor: 'pointer'
},
caption: {
fontSize: '13px',
marginTop: '20px',
- color: '#A2B1C6',
+ color: '#A2B1C6'
},
container: {
marginLeft: 'auto',
marginRight: 'auto',
width: '90%',
- maxWidth: '300px',
- },
+ maxWidth: '300px'
+ }
};
export default base;
diff --git a/dash-renderer/src/types/callbacks.ts b/dash-renderer/src/types/callbacks.ts
index 14882607d5..e9790ff704 100644
--- a/dash-renderer/src/types/callbacks.ts
+++ b/dash-renderer/src/types/callbacks.ts
@@ -1,4 +1,4 @@
-type CallbackId = string | { [key: string]: any }
+type CallbackId = string | {[key: string]: any};
export interface ICallbackDefinition {
clientside_function?: {
@@ -40,9 +40,7 @@ export interface ICallback extends ICallbackTemplate {
}
// tslint:disable-next-line:no-empty-interface
-export interface IPrioritizedCallback extends ICallback {
-
-}
+export interface IPrioritizedCallback extends ICallback {}
export interface IBlockedCallback extends IPrioritizedCallback {
allOutputs: ILayoutCallbackProperty[][];
@@ -55,9 +53,7 @@ export interface IExecutingCallback extends IPrioritizedCallback {
}
// tslint:disable-next-line:no-empty-interface
-export interface IWatchedCallback extends IExecutingCallback {
-
-}
+export interface IWatchedCallback extends IExecutingCallback {}
export interface IExecutedCallback extends IWatchedCallback {
executionResult: CallbackResult | null;
@@ -67,7 +63,7 @@ export interface IStoredCallback extends IExecutedCallback {
executionMeta: {
allProps: string[];
updatedProps: string[];
- }
+ };
}
export interface ICallbackPayload {
@@ -82,4 +78,4 @@ export type CallbackResult = {
data?: any;
error?: Error;
payload: ICallbackPayload | null;
-}
+};
diff --git a/dash-renderer/src/utils/TreeContainer.ts b/dash-renderer/src/utils/TreeContainer.ts
index cf9df689c1..8e28555160 100644
--- a/dash-renderer/src/utils/TreeContainer.ts
+++ b/dash-renderer/src/utils/TreeContainer.ts
@@ -1,7 +1,7 @@
-import { path, type, has } from 'ramda';
+import {path, type, has} from 'ramda';
import Registry from '../registry';
-import { stringifyId } from '../actions/dependencies';
+import {stringifyId} from '../actions/dependencies';
function isLoadingComponent(layout: any) {
validateComponent(layout);
@@ -10,7 +10,11 @@ function isLoadingComponent(layout: any) {
const NULL_LOADING_STATE = false;
-export function getLoadingState(componentLayout: any, componentPath: any, loadingMap: any) {
+export function getLoadingState(
+ componentLayout: any,
+ componentPath: any,
+ loadingMap: any
+) {
if (!loadingMap) {
return NULL_LOADING_STATE;
}
@@ -43,21 +47,21 @@ export function getLoadingState(componentLayout: any, componentPath: any, loadin
return NULL_LOADING_STATE;
}
-export const getLoadingHash = (
- componentPath: any,
- loadingMap: any
-) => (
- ((loadingMap && (path(componentPath, loadingMap) as any)?.__dashprivate__idprops__) ?? []) as any[]
-).map(({ id, property }) => `${id}.${property}`).join(',');
+export const getLoadingHash = (componentPath: any, loadingMap: any) =>
+ (((loadingMap &&
+ (path(componentPath, loadingMap) as any)?.__dashprivate__idprops__) ??
+ []) as any[])
+ .map(({id, property}) => `${id}.${property}`)
+ .join(',');
export function validateComponent(componentDefinition: any) {
if (type(componentDefinition) === 'Array') {
throw new Error(
'The children property of a component is a list of lists, instead ' +
- 'of just a list. ' +
- 'Check the component that has the following contents, ' +
- 'and remove one of the levels of nesting: \n' +
- JSON.stringify(componentDefinition, null, 2)
+ 'of just a list. ' +
+ 'Check the component that has the following contents, ' +
+ 'and remove one of the levels of nesting: \n' +
+ JSON.stringify(componentDefinition, null, 2)
);
}
if (
@@ -70,9 +74,9 @@ export function validateComponent(componentDefinition: any) {
) {
throw new Error(
'An object was provided as `children` instead of a component, ' +
- 'string, or number (or list of those). ' +
- 'Check the children property that looks something like:\n' +
- JSON.stringify(componentDefinition, null, 2)
+ 'string, or number (or list of those). ' +
+ 'Check the children property that looks something like:\n' +
+ JSON.stringify(componentDefinition, null, 2)
);
}
}
diff --git a/dash-renderer/src/utils/callbacks.ts b/dash-renderer/src/utils/callbacks.ts
index 14befb6e7c..30d592ff8c 100644
--- a/dash-renderer/src/utils/callbacks.ts
+++ b/dash-renderer/src/utils/callbacks.ts
@@ -1,8 +1,7 @@
-import { omit, values } from 'ramda';
+import {omit, values} from 'ramda';
-import { ICallbacksState } from '../reducers/callbacks';
-import { ICallback } from '../types/callbacks';
+import {ICallbacksState} from '../reducers/callbacks';
+import {ICallback} from '../types/callbacks';
-export const getPendingCallbacks = (state: ICallbacksState) => Array().concat(
- ...values(omit(['stored', 'completed'], state))
-);
+export const getPendingCallbacks = (state: ICallbacksState) =>
+ Array().concat(...values(omit(['stored', 'completed'], state)));
diff --git a/dash-renderer/src/utils/wait.ts b/dash-renderer/src/utils/wait.ts
new file mode 100644
index 0000000000..3059cb2a7a
--- /dev/null
+++ b/dash-renderer/src/utils/wait.ts
@@ -0,0 +1,8 @@
+export default async (duration: number) => {
+ let _resolve: any;
+ const p = new Promise(resolve => (_resolve = resolve));
+
+ setTimeout(_resolve, duration);
+
+ return p;
+};
diff --git a/dash-renderer/tslint.json b/dash-renderer/tslint.json
index 600dce2dfc..31269d7c5d 100644
--- a/dash-renderer/tslint.json
+++ b/dash-renderer/tslint.json
@@ -1,7 +1,8 @@
{
"defaultSeverity": "error",
"extends": [
- "tslint:recommended"
+ "tslint:recommended",
+ "tslint-config-prettier"
],
"linterOptions": {
"exclude": [
@@ -44,12 +45,7 @@
"ordered-imports": false,
"prefer-const": false,
"prefer-for-of": false,
- "quotemark": [true, "single"],
"space-before-function-paren": [false, "always"],
- "trailing-comma": [true, {
- "singleline": "never",
- "multiline": "never"
- }],
"unified-signatures": false,
"variable-name": false
},
diff --git a/dash/_callback_context.py b/dash/_callback_context.py
index d4e95dfb0e..71997f11dd 100644
--- a/dash/_callback_context.py
+++ b/dash/_callback_context.py
@@ -72,5 +72,29 @@ def states_list(self):
def response(self):
return getattr(flask.g, "dash_response")
+ @staticmethod
+ @has_context
+ def record_timing(name, duration=None, description=None):
+ """Records timing information for a server resource.
+
+ :param name: The name of the resource.
+ :type name: string
+
+ :param duration: The time in seconds to report. Internally, this
+ is rounded to the nearest millisecond.
+ :type duration: float or None
+
+ :param description: A description of the resource.
+ :type description: string or None
+ """
+ timing_information = getattr(flask.g, "timing_information", {})
+
+ if name in timing_information:
+ raise KeyError('Duplicate resource name "{}" found.'.format(name))
+
+ timing_information[name] = {"dur": round(duration * 1000), "desc": description}
+
+ setattr(flask.g, "timing_information", timing_information)
+
callback_context = CallbackContext()
diff --git a/dash/dash.py b/dash/dash.py
index c17ddbe271..cb3f7aae01 100644
--- a/dash/dash.py
+++ b/dash/dash.py
@@ -9,7 +9,10 @@
import threading
import re
import logging
+import time
import mimetypes
+import hashlib
+import base64
from functools import wraps
from future.moves.urllib.parse import urlparse
@@ -1128,6 +1131,42 @@ def _serve_default_favicon():
pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon"
)
+ def csp_hashes(self, hash_algorithm="sha256"):
+ """Calculates CSP hashes (sha + base64) of all inline scripts, such that
+ one of the biggest benefits of CSP (disallowing general inline scripts)
+ can be utilized together with Dash clientside callbacks (inline scripts).
+
+ Calculate these hashes after all inline callbacks are defined,
+ and add them to your CSP headers before starting the server, for example
+ with the flask-talisman package from PyPI:
+
+ flask_talisman.Talisman(app.server, content_security_policy={
+ "default-src": "'self'",
+ "script-src": ["'self'"] + app.csp_hashes()
+ })
+
+ :param hash_algorithm: One of the recognized CSP hash algorithms ('sha256', 'sha384', 'sha512').
+ :return: List of CSP hash strings of all inline scripts.
+ """
+
+ HASH_ALGORITHMS = ["sha256", "sha384", "sha512"]
+ if hash_algorithm not in HASH_ALGORITHMS:
+ raise ValueError(
+ "Possible CSP hash algorithms: " + ", ".join(HASH_ALGORITHMS)
+ )
+
+ method = getattr(hashlib, hash_algorithm)
+
+ return [
+ "'{hash_algorithm}-{base64_hash}'".format(
+ hash_algorithm=hash_algorithm,
+ base64_hash=base64.b64encode(
+ method(script.encode("utf-8")).digest()
+ ).decode("utf-8"),
+ )
+ for script in self._inline_scripts + [self.renderer]
+ ]
+
def get_asset_url(self, path):
asset = get_asset_path(
self.config.requests_pathname_prefix,
@@ -1402,6 +1441,34 @@ def _wrap_errors(_):
break
return get_current_traceback(skip=skip).render_full(), 500
+ if debug and dev_tools.ui:
+
+ def _before_request():
+ flask.g.timing_information = {
+ "__dash_server": {"dur": time.time(), "desc": None}
+ }
+
+ def _after_request(response):
+ dash_total = flask.g.timing_information["__dash_server"]
+ dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000)
+
+ for name, info in flask.g.timing_information.items():
+
+ value = name
+ if info.get("desc") is not None:
+ value += ';desc="{}"'.format(info["desc"])
+
+ if info.get("dur") is not None:
+ value += ";dur={}".format(info["dur"])
+
+ response.headers.add("Server-Timing", value)
+
+ return response
+
+ self.server.before_request(_before_request)
+
+ self.server.after_request(_after_request)
+
if (
debug
and dev_tools.serve_dev_bundles
diff --git a/dash/testing/browser.py b/dash/testing/browser.py
index 91a09e499e..cbaac4e8fa 100644
--- a/dash/testing/browser.py
+++ b/dash/testing/browser.py
@@ -103,6 +103,7 @@ def visit_and_snapshot(
resource_path,
hook_id,
wait_for_callbacks=True,
+ convert_canvases=False,
assert_check=True,
stay_on_page=False,
):
@@ -114,7 +115,11 @@ def visit_and_snapshot(
# wait for the hook_id to present and all callbacks get fired
self.wait_for_element_by_id(hook_id)
- self.percy_snapshot(path, wait_for_callbacks=wait_for_callbacks)
+ self.percy_snapshot(
+ path,
+ wait_for_callbacks=wait_for_callbacks,
+ convert_canvases=convert_canvases,
+ )
if assert_check:
assert not self.driver.find_elements_by_css_selector(
"div.dash-debug-alert"
@@ -125,7 +130,7 @@ def visit_and_snapshot(
logger.exception("snapshot at resource %s error", path)
raise e
- def percy_snapshot(self, name="", wait_for_callbacks=False):
+ def percy_snapshot(self, name="", wait_for_callbacks=False, convert_canvases=False):
"""percy_snapshot - visual test api shortcut to `percy_runner.snapshot`.
It also combines the snapshot `name` with the Python version.
"""
@@ -148,7 +153,43 @@ def percy_snapshot(self, name="", wait_for_callbacks=False):
self.redux_state_rqs,
)
- self.percy_runner.snapshot(name=snapshot_name)
+ if convert_canvases:
+ self.driver.execute_script(
+ """
+ const stash = window._canvasStash = [];
+ Array.from(document.querySelectorAll('canvas')).forEach(c => {
+ const i = document.createElement('img');
+ i.src = c.toDataURL();
+ i.width = c.width;
+ i.height = c.height;
+ i.setAttribute('style', c.getAttribute('style'));
+ i.className = c.className;
+ i.setAttribute('data-canvasnum', stash.length);
+ stash.push(c);
+ c.parentElement.insertBefore(i, c);
+ c.parentElement.removeChild(c);
+ });
+ """
+ )
+
+ self.percy_runner.snapshot(name=snapshot_name)
+
+ self.driver.execute_script(
+ """
+ const stash = window._canvasStash;
+ Array.from(
+ document.querySelectorAll('img[data-canvasnum]')
+ ).forEach(i => {
+ const c = stash[+i.getAttribute('data-canvasnum')];
+ i.parentElement.insertBefore(c, i);
+ i.parentElement.removeChild(i);
+ });
+ delete window._canvasStash;
+ """
+ )
+
+ else:
+ self.percy_runner.snapshot(name=snapshot_name)
def take_snapshot(self, name):
"""Hook method to take snapshot when a selenium test fails. The
diff --git a/dash/version.py b/dash/version.py
index 6b0872cb2f..638c1217d2 100644
--- a/dash/version.py
+++ b/dash/version.py
@@ -1 +1 @@
-__version__ = "1.15.0"
+__version__ = "1.16.0"
diff --git a/requires-install.txt b/requires-install.txt
index a23dd78567..2c67c74890 100644
--- a/requires-install.txt
+++ b/requires-install.txt
@@ -1,8 +1,8 @@
Flask>=1.0.2
flask-compress
plotly
-dash_renderer==1.7.0
-dash-core-components==1.11.0
-dash-html-components==1.1.0
-dash-table==4.10.0
+dash_renderer==1.8.0
+dash-core-components==1.12.0
+dash-html-components==1.1.1
+dash-table==4.10.1
future
diff --git a/requires-testing.txt b/requires-testing.txt
index 1662b98057..1b14e7d6e9 100644
--- a/requires-testing.txt
+++ b/requires-testing.txt
@@ -10,3 +10,4 @@ cryptography==3.0
requests[security]==2.21.0
beautifulsoup4==4.8.2
waitress==1.4.3
+flask-talisman==0.7.0
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/assets/__init__.py b/tests/assets/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/assets/todo_app.py b/tests/assets/todo_app.py
new file mode 100644
index 0000000000..ed4971be18
--- /dev/null
+++ b/tests/assets/todo_app.py
@@ -0,0 +1,123 @@
+from multiprocessing import Value
+
+import dash
+from dash.dependencies import Input, Output, State, MATCH, ALL, ALLSMALLER
+import dash_html_components as html
+import dash_core_components as dcc
+
+
+def todo_app(content_callback=False):
+ app = dash.Dash(__name__)
+
+ content = html.Div(
+ [
+ html.Div("Dash To-Do list"),
+ dcc.Input(id="new-item"),
+ html.Button("Add", id="add"),
+ html.Button("Clear Done", id="clear-done"),
+ html.Div(id="list-container"),
+ html.Hr(),
+ html.Div(id="totals"),
+ ]
+ )
+
+ if content_callback:
+ app.layout = html.Div([html.Div(id="content"), dcc.Location(id="url")])
+
+ @app.callback(Output("content", "children"), [Input("url", "pathname")])
+ def display_content(_):
+ return content
+
+ else:
+ app.layout = content
+
+ style_todo = {"display": "inline", "margin": "10px"}
+ style_done = {"textDecoration": "line-through", "color": "#888"}
+ style_done.update(style_todo)
+
+ app.list_calls = Value("i", 0)
+ app.style_calls = Value("i", 0)
+ app.preceding_calls = Value("i", 0)
+ app.total_calls = Value("i", 0)
+
+ @app.callback(
+ Output("list-container", "children"),
+ Output("new-item", "value"),
+ Input("add", "n_clicks"),
+ Input("new-item", "n_submit"),
+ Input("clear-done", "n_clicks"),
+ State("new-item", "value"),
+ State({"item": ALL}, "children"),
+ State({"item": ALL, "action": "done"}, "value"),
+ )
+ def edit_list(add, add2, clear, new_item, items, items_done):
+ app.list_calls.value += 1
+ triggered = [t["prop_id"] for t in dash.callback_context.triggered]
+ adding = len(
+ [1 for i in triggered if i in ("add.n_clicks", "new-item.n_submit")]
+ )
+ clearing = len([1 for i in triggered if i == "clear-done.n_clicks"])
+ new_spec = [
+ (text, done)
+ for text, done in zip(items, items_done)
+ if not (clearing and done)
+ ]
+ if adding:
+ new_spec.append((new_item, []))
+ new_list = [
+ html.Div(
+ [
+ dcc.Checklist(
+ id={"item": i, "action": "done"},
+ options=[{"label": "", "value": "done"}],
+ value=done,
+ style={"display": "inline"},
+ ),
+ html.Div(
+ text, id={"item": i}, style=style_done if done else style_todo
+ ),
+ html.Div(id={"item": i, "preceding": True}, style=style_todo),
+ ],
+ style={"clear": "both"},
+ )
+ for i, (text, done) in enumerate(new_spec)
+ ]
+ return [new_list, "" if adding else new_item]
+
+ @app.callback(
+ Output({"item": MATCH}, "style"),
+ Input({"item": MATCH, "action": "done"}, "value"),
+ )
+ def mark_done(done):
+ app.style_calls.value += 1
+ return style_done if done else style_todo
+
+ @app.callback(
+ Output({"item": MATCH, "preceding": True}, "children"),
+ Input({"item": ALLSMALLER, "action": "done"}, "value"),
+ Input({"item": MATCH, "action": "done"}, "value"),
+ )
+ def show_preceding(done_before, this_done):
+ app.preceding_calls.value += 1
+ if this_done:
+ return ""
+ all_before = len(done_before)
+ done_before = len([1 for d in done_before if d])
+ out = "{} of {} preceding items are done".format(done_before, all_before)
+ if all_before == done_before:
+ out += " DO THIS NEXT!"
+ return out
+
+ @app.callback(
+ Output("totals", "children"), Input({"item": ALL, "action": "done"}, "value")
+ )
+ def show_totals(done):
+ app.total_calls.value += 1
+ count_all = len(done)
+ count_done = len([d for d in done if d])
+ result = "{} of {} items completed".format(count_done, count_all)
+ if count_all:
+ result += " - {}%".format(int(100 * count_done / count_all))
+ return result
+
+ return app
diff --git a/tests/integration/callbacks/__init__.py b/tests/integration/callbacks/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/integration/callbacks/test_basic_callback.py b/tests/integration/callbacks/test_basic_callback.py
index 13276b1899..afbd81cd97 100644
--- a/tests/integration/callbacks/test_basic_callback.py
+++ b/tests/integration/callbacks/test_basic_callback.py
@@ -1,5 +1,5 @@
import json
-from multiprocessing import Value
+from multiprocessing import Lock, Value
import pytest
@@ -9,9 +9,12 @@
import dash
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
+from dash.testing import wait
def test_cbsc001_simple_callback(dash_duo):
+ lock = Lock()
+
app = dash.Dash(__name__)
app.layout = html.Div(
[
@@ -23,8 +26,9 @@ def test_cbsc001_simple_callback(dash_duo):
@app.callback(Output("output-1", "children"), [Input("input", "value")])
def update_output(value):
- call_count.value = call_count.value + 1
- return value
+ with lock:
+ call_count.value = call_count.value + 1
+ return value
dash_duo.start_server(app)
@@ -34,9 +38,11 @@ def update_output(value):
input_ = dash_duo.find_element("#input")
dash_duo.clear_input(input_)
- input_.send_keys("hello world")
+ for key in "hello world":
+ with lock:
+ input_.send_keys(key)
- assert dash_duo.find_element("#output-1").text == "hello world"
+ wait.until(lambda: dash_duo.find_element("#output-1").text == "hello world", 2)
dash_duo.percy_snapshot(name="simple-callback-hello-world")
assert call_count.value == 2 + len("hello world"), "initial count + each key stroke"
@@ -345,6 +351,8 @@ def set_path(n):
def test_cbsc008_wildcard_prop_callbacks(dash_duo):
+ lock = Lock()
+
app = dash.Dash(__name__)
app.layout = html.Div(
[
@@ -369,8 +377,9 @@ def test_cbsc008_wildcard_prop_callbacks(dash_duo):
@app.callback(Output("output-1", "data-cb"), [Input("input", "value")])
def update_data(value):
- input_call_count.value += 1
- return value
+ with lock:
+ input_call_count.value += 1
+ return value
@app.callback(Output("output-1", "children"), [Input("output-1", "data-cb")])
def update_text(data):
@@ -382,7 +391,10 @@ def update_text(data):
input1 = dash_duo.find_element("#input")
dash_duo.clear_input(input1)
- input1.send_keys("hello world")
+
+ for key in "hello world":
+ with lock:
+ input1.send_keys(key)
dash_duo.wait_for_text_to_equal("#output-1", "hello world")
dash_duo.percy_snapshot(name="wildcard-callback-2")
diff --git a/tests/integration/callbacks/test_callback_context.py b/tests/integration/callbacks/test_callback_context.py
index f4f4552c4c..3eabe92e64 100644
--- a/tests/integration/callbacks/test_callback_context.py
+++ b/tests/integration/callbacks/test_callback_context.py
@@ -1,4 +1,5 @@
import json
+import operator
import pytest
import dash_html_components as html
@@ -9,6 +10,9 @@
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate, MissingCallbackContextException
+import dash.testing.wait as wait
+
+from selenium.webdriver.common.action_chains import ActionChains
def test_cbcx001_modified_response(dash_duo):
@@ -96,3 +100,237 @@ def report_triggered(n):
'triggered is truthy, has prop/id ["btn", "n_clicks"], and full value '
'[{"prop_id": "btn.n_clicks", "value": 1}]',
)
+
+
+@pytest.mark.DASH1350
+def test_cbcx005_grouped_clicks(dash_duo):
+ class context:
+ calls = 0
+ callback_contexts = []
+ clicks = dict()
+
+ app = Dash(__name__)
+ app.layout = html.Div(
+ [
+ html.Button("Button 0", id="btn0"),
+ html.Div(
+ [
+ html.Button("Button 1", id="btn1"),
+ html.Div(
+ [html.Div(id="div3"), html.Button("Button 2", id="btn2")],
+ id="div2",
+ style=dict(backgroundColor="yellow", padding="50px"),
+ ),
+ ],
+ id="div1",
+ style=dict(backgroundColor="blue", padding="50px"),
+ ),
+ ],
+ id="div0",
+ style=dict(backgroundColor="red", padding="50px"),
+ )
+
+ @app.callback(
+ Output("div3", "children"),
+ [
+ Input("div1", "n_clicks"),
+ Input("div2", "n_clicks"),
+ Input("btn0", "n_clicks"),
+ Input("btn1", "n_clicks"),
+ Input("btn2", "n_clicks"),
+ ],
+ prevent_initial_call=True,
+ )
+ def update(div1, div2, btn0, btn1, btn2):
+ context.calls = context.calls + 1
+ context.callback_contexts.append(callback_context.triggered)
+ context.clicks["div1"] = div1
+ context.clicks["div2"] = div2
+ context.clicks["btn0"] = btn0
+ context.clicks["btn1"] = btn1
+ context.clicks["btn2"] = btn2
+
+ def click(target):
+ ActionChains(dash_duo.driver).move_to_element_with_offset(
+ target, 5, 5
+ ).click().perform()
+
+ dash_duo.start_server(app)
+ click(dash_duo.find_element("#btn0"))
+ assert context.calls == 1
+ keys = list(map(operator.itemgetter("prop_id"), context.callback_contexts[-1:][0]))
+ assert len(keys) == 1
+ assert "btn0.n_clicks" in keys
+
+ assert context.clicks.get("btn0") == 1
+ assert context.clicks.get("btn1") is None
+ assert context.clicks.get("btn2") is None
+ assert context.clicks.get("div1") is None
+ assert context.clicks.get("div2") is None
+
+ click(dash_duo.find_element("#div1"))
+ assert context.calls == 2
+ keys = list(map(operator.itemgetter("prop_id"), context.callback_contexts[-1:][0]))
+ assert len(keys) == 1
+ assert "div1.n_clicks" in keys
+
+ assert context.clicks.get("btn0") == 1
+ assert context.clicks.get("btn1") is None
+ assert context.clicks.get("btn2") is None
+ assert context.clicks.get("div1") == 1
+ assert context.clicks.get("div2") is None
+
+ click(dash_duo.find_element("#btn1"))
+ assert context.calls == 3
+ keys = list(map(operator.itemgetter("prop_id"), context.callback_contexts[-1:][0]))
+ assert len(keys) == 2
+ assert "btn1.n_clicks" in keys
+ assert "div1.n_clicks" in keys
+
+ assert context.clicks.get("btn0") == 1
+ assert context.clicks.get("btn1") == 1
+ assert context.clicks.get("btn2") is None
+ assert context.clicks.get("div1") == 2
+ assert context.clicks.get("div2") is None
+
+ click(dash_duo.find_element("#div2"))
+ assert context.calls == 4
+ keys = list(map(operator.itemgetter("prop_id"), context.callback_contexts[-1:][0]))
+ assert len(keys) == 2
+ assert "div1.n_clicks" in keys
+ assert "div2.n_clicks" in keys
+
+ assert context.clicks.get("btn0") == 1
+ assert context.clicks.get("btn1") == 1
+ assert context.clicks.get("btn2") is None
+ assert context.clicks.get("div1") == 3
+ assert context.clicks.get("div2") == 1
+
+ click(dash_duo.find_element("#btn2"))
+ assert context.calls == 5
+ keys = list(map(operator.itemgetter("prop_id"), context.callback_contexts[-1:][0]))
+ assert len(keys) == 3
+ assert "btn2.n_clicks" in keys
+ assert "div1.n_clicks" in keys
+ assert "div2.n_clicks" in keys
+
+ assert context.clicks.get("btn0") == 1
+ assert context.clicks.get("btn1") == 1
+ assert context.clicks.get("btn2") == 1
+ assert context.clicks.get("div1") == 4
+ assert context.clicks.get("div2") == 2
+
+
+@pytest.mark.DASH1350
+def test_cbcx006_initial_callback_predecessor(dash_duo):
+ class context:
+ calls = 0
+ callback_contexts = []
+
+ app = Dash(__name__)
+ app.layout = html.Div(
+ [
+ html.Div(
+ style={"display": "block"},
+ children=[
+ html.Div(
+ [
+ html.Label("ID: input-number-1"),
+ dcc.Input(id="input-number-1", type="number", value=0),
+ ]
+ ),
+ html.Div(
+ [
+ html.Label("ID: input-number-2"),
+ dcc.Input(id="input-number-2", type="number", value=0),
+ ]
+ ),
+ html.Div(
+ [
+ html.Label("ID: sum-number"),
+ dcc.Input(
+ id="sum-number", type="number", value=0, disabled=True
+ ),
+ ]
+ ),
+ ],
+ ),
+ html.Div(id="results"),
+ ]
+ )
+
+ @app.callback(
+ Output("sum-number", "value"),
+ [Input("input-number-1", "value"), Input("input-number-2", "value")],
+ )
+ def update_sum_number(n1, n2):
+ context.calls = context.calls + 1
+ context.callback_contexts.append(callback_context.triggered)
+
+ return n1 + n2
+
+ @app.callback(
+ Output("results", "children"),
+ [
+ Input("input-number-1", "value"),
+ Input("input-number-2", "value"),
+ Input("sum-number", "value"),
+ ],
+ )
+ def update_results(n1, n2, nsum):
+ context.calls = context.calls + 1
+ context.callback_contexts.append(callback_context.triggered)
+
+ return [
+ "{} + {} = {}".format(n1, n2, nsum),
+ html.Br(),
+ "ctx.triggered={}".format(callback_context.triggered),
+ ]
+
+ dash_duo.start_server(app)
+
+ # Initial Callbacks
+ wait.until(lambda: context.calls == 2, 2)
+ wait.until(lambda: len(context.callback_contexts) == 2, 2)
+
+ keys0 = list(map(operator.itemgetter("prop_id"), context.callback_contexts[0]))
+ # Special case present for backward compatibility
+ assert len(keys0) == 1
+ assert "." in keys0
+
+ keys1 = list(map(operator.itemgetter("prop_id"), context.callback_contexts[1]))
+ assert len(keys1) == 1
+ assert "sum-number.value" in keys1
+
+ # User action & followup callbacks
+ dash_duo.find_element("#input-number-1").click()
+ dash_duo.find_element("#input-number-1").send_keys("1")
+
+ wait.until(lambda: context.calls == 4, 2)
+ wait.until(lambda: len(context.callback_contexts) == 4, 2)
+
+ keys0 = list(map(operator.itemgetter("prop_id"), context.callback_contexts[2]))
+ # Special case present for backward compatibility
+ assert len(keys0) == 1
+ assert "input-number-1.value" in keys0
+
+ keys1 = list(map(operator.itemgetter("prop_id"), context.callback_contexts[3]))
+ assert len(keys1) == 2
+ assert "sum-number.value" in keys1
+ assert "input-number-1.value" in keys1
+
+ dash_duo.find_element("#input-number-2").click()
+ dash_duo.find_element("#input-number-2").send_keys("1")
+
+ wait.until(lambda: context.calls == 6, 2)
+ wait.until(lambda: len(context.callback_contexts) == 6, 2)
+
+ keys0 = list(map(operator.itemgetter("prop_id"), context.callback_contexts[4]))
+ # Special case present for backward compatibility
+ assert len(keys0) == 1
+ assert "input-number-2.value" in keys0
+
+ keys1 = list(map(operator.itemgetter("prop_id"), context.callback_contexts[5]))
+ assert len(keys1) == 2
+ assert "sum-number.value" in keys1
+ assert "input-number-2.value" in keys1
diff --git a/tests/integration/callbacks/test_wildcards.py b/tests/integration/callbacks/test_wildcards.py
index f8916340d3..b578b0c84e 100644
--- a/tests/integration/callbacks/test_wildcards.py
+++ b/tests/integration/callbacks/test_wildcards.py
@@ -1,4 +1,3 @@
-from multiprocessing import Value
import pytest
import re
from selenium.webdriver.common.keys import Keys
@@ -9,6 +8,8 @@
from dash.testing import wait
from dash.dependencies import Input, Output, State, ALL, ALLSMALLER, MATCH
+from ...assets.todo_app import todo_app
+
def css_escape(s):
sel = re.sub("[\\{\\}\\\"\\'.:,]", lambda m: "\\" + m.group(0), s)
@@ -16,123 +17,6 @@ def css_escape(s):
return sel
-def todo_app(content_callback):
- app = dash.Dash(__name__)
-
- content = html.Div(
- [
- html.Div("Dash To-Do list"),
- dcc.Input(id="new-item"),
- html.Button("Add", id="add"),
- html.Button("Clear Done", id="clear-done"),
- html.Div(id="list-container"),
- html.Hr(),
- html.Div(id="totals"),
- ]
- )
-
- if content_callback:
- app.layout = html.Div([html.Div(id="content"), dcc.Location(id="url")])
-
- @app.callback(Output("content", "children"), [Input("url", "pathname")])
- def display_content(_):
- return content
-
- else:
- app.layout = content
-
- style_todo = {"display": "inline", "margin": "10px"}
- style_done = {"textDecoration": "line-through", "color": "#888"}
- style_done.update(style_todo)
-
- app.list_calls = Value("i", 0)
- app.style_calls = Value("i", 0)
- app.preceding_calls = Value("i", 0)
- app.total_calls = Value("i", 0)
-
- @app.callback(
- Output("list-container", "children"),
- Output("new-item", "value"),
- Input("add", "n_clicks"),
- Input("new-item", "n_submit"),
- Input("clear-done", "n_clicks"),
- State("new-item", "value"),
- State({"item": ALL}, "children"),
- State({"item": ALL, "action": "done"}, "value"),
- )
- def edit_list(add, add2, clear, new_item, items, items_done):
- app.list_calls.value += 1
- triggered = [t["prop_id"] for t in dash.callback_context.triggered]
- adding = len(
- [1 for i in triggered if i in ("add.n_clicks", "new-item.n_submit")]
- )
- clearing = len([1 for i in triggered if i == "clear-done.n_clicks"])
- new_spec = [
- (text, done)
- for text, done in zip(items, items_done)
- if not (clearing and done)
- ]
- if adding:
- new_spec.append((new_item, []))
- new_list = [
- html.Div(
- [
- dcc.Checklist(
- id={"item": i, "action": "done"},
- options=[{"label": "", "value": "done"}],
- value=done,
- style={"display": "inline"},
- ),
- html.Div(
- text, id={"item": i}, style=style_done if done else style_todo
- ),
- html.Div(id={"item": i, "preceding": True}, style=style_todo),
- ],
- style={"clear": "both"},
- )
- for i, (text, done) in enumerate(new_spec)
- ]
- return [new_list, "" if adding else new_item]
-
- @app.callback(
- Output({"item": MATCH}, "style"),
- Input({"item": MATCH, "action": "done"}, "value"),
- )
- def mark_done(done):
- app.style_calls.value += 1
- return style_done if done else style_todo
-
- @app.callback(
- Output({"item": MATCH, "preceding": True}, "children"),
- Input({"item": ALLSMALLER, "action": "done"}, "value"),
- Input({"item": MATCH, "action": "done"}, "value"),
- )
- def show_preceding(done_before, this_done):
- app.preceding_calls.value += 1
- if this_done:
- return ""
- all_before = len(done_before)
- done_before = len([1 for d in done_before if d])
- out = "{} of {} preceding items are done".format(done_before, all_before)
- if all_before == done_before:
- out += " DO THIS NEXT!"
- return out
-
- @app.callback(
- Output("totals", "children"), Input({"item": ALL, "action": "done"}, "value")
- )
- def show_totals(done):
- app.total_calls.value += 1
- count_all = len(done)
- count_done = len([d for d in done if d])
- result = "{} of {} items completed".format(count_done, count_all)
- if count_all:
- result += " - {}%".format(int(100 * count_done / count_all))
- return result
-
- return app
-
-
@pytest.mark.parametrize("content_callback", (False, True))
def test_cbwc001_todo_app(content_callback, dash_duo):
app = todo_app(content_callback)
diff --git a/tests/integration/devtools/__init__.py b/tests/integration/devtools/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/integration/devtools/test_callback_timing.py b/tests/integration/devtools/test_callback_timing.py
new file mode 100644
index 0000000000..a84b60942f
--- /dev/null
+++ b/tests/integration/devtools/test_callback_timing.py
@@ -0,0 +1,38 @@
+from time import sleep
+import requests
+
+import dash_html_components as html
+import dash
+from dash.dependencies import Output, Input
+
+
+def test_dvct001_callback_timing(dash_thread_server):
+ app = dash.Dash(__name__)
+ app.layout = html.Div()
+
+ @app.callback(Output("x", "p"), Input("y", "q"))
+ def x(y):
+ dash.callback_context.record_timing("pancakes", 1.23)
+ sleep(0.5)
+ return y
+
+ dash_thread_server(app, debug=True, use_reloader=False, use_debugger=True)
+
+ response = requests.post(
+ dash_thread_server.url + "/_dash-update-component",
+ json={
+ "output": "x.p",
+ "outputs": {"id": "x", "property": "p"},
+ "inputs": [{"id": "y", "property": "q", "value": 9}],
+ "changedPropIds": ["y.q"],
+ },
+ )
+
+ # eg 'Server-Timing': '__dash_server;dur=505, pancakes;dur=1230'
+ assert "Server-Timing" in response.headers
+ st = response.headers["Server-Timing"]
+ times = {k: int(float(v)) for k, v in [p.split(";dur=") for p in st.split(", ")]}
+ assert "__dash_server" in times
+ assert times["__dash_server"] >= 500 # 0.5 sec wait
+ assert "pancakes" in times
+ assert times["pancakes"] == 1230
diff --git a/tests/integration/devtools/test_callback_validation.py b/tests/integration/devtools/test_callback_validation.py
index a006e23eec..4f57e01254 100644
--- a/tests/integration/devtools/test_callback_validation.py
+++ b/tests/integration/devtools/test_callback_validation.py
@@ -677,7 +677,7 @@ def c2(children):
@app.callback([Output("a", "children")], [Input("c", "children")])
def c3(children):
- return children
+ return (children,)
dash_duo.start_server(app, **debugging)
diff --git a/tests/integration/devtools/test_devtools_ui.py b/tests/integration/devtools/test_devtools_ui.py
index 878e6377b7..d32facb033 100644
--- a/tests/integration/devtools/test_devtools_ui.py
+++ b/tests/integration/devtools/test_devtools_ui.py
@@ -5,6 +5,8 @@
import dash
import dash.testing.wait as wait
+from ...assets.todo_app import todo_app
+
def test_dvui001_disable_props_check_config(dash_duo):
app = dash.Dash(__name__)
@@ -62,3 +64,38 @@ def test_dvui002_disable_ui_config(dash_duo):
".dash-debug-menu"
), "the debug menu icon should NOT show up"
dash_duo.percy_snapshot("devtools - disable dev tools UI - no debug menu")
+
+
+def test_dvui003_callback_graph(dash_duo):
+ app = todo_app()
+
+ dash_duo.start_server(
+ app,
+ debug=True,
+ use_reloader=False,
+ use_debugger=True,
+ dev_tools_hot_reload=False,
+ )
+
+ dash_duo.wait_for_text_to_equal("#totals", "0 of 0 items completed")
+
+ # reset compute and network times for all profiled callbacks, so we get
+ # a consistent callback graph image
+ dash_duo.driver.execute_script(
+ """
+ const cbProfiles = window.store.getState().profile.callbacks;
+ Object.keys(cbProfiles).forEach(k => {
+ cbProfiles[k].compute = 44;
+ cbProfiles[k].network.time = 33;
+ cbProfiles[k].total = 77;
+ });
+ """
+ )
+
+ dash_duo.find_element(".dash-debug-menu").click()
+ sleep(1) # wait for debug menu opening animation
+ dash_duo.find_element(".dash-debug-menu__button--callbacks").click()
+ sleep(3) # wait for callback graph to draw
+ dash_duo.find_element('canvas[data-id="layer2-node"]')
+
+ dash_duo.percy_snapshot("devtools - callback graph", convert_canvases=True)
diff --git a/tests/integration/renderer/test_multi_output.py b/tests/integration/renderer/test_multi_output.py
index 4741471420..433301ea57 100644
--- a/tests/integration/renderer/test_multi_output.py
+++ b/tests/integration/renderer/test_multi_output.py
@@ -1,8 +1,9 @@
-from multiprocessing import Value
+from multiprocessing import Lock, Value
import dash
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
+from dash.testing import wait
import dash_core_components as dcc
import dash_html_components as html
@@ -47,6 +48,8 @@ def update_output(n_clicks):
def test_rdmo002_multi_outputs_on_single_component(dash_duo):
+ lock = Lock()
+
call_count = Value("i")
app = dash.Dash(__name__)
@@ -66,8 +69,9 @@ def test_rdmo002_multi_outputs_on_single_component(dash_duo):
[Input("input", "value")],
)
def update_output(value):
- call_count.value += 1
- return [value, {"fontFamily": value}, value]
+ with lock:
+ call_count.value += 1
+ return [value, {"fontFamily": value}, value]
dash_duo.start_server(app)
@@ -79,7 +83,9 @@ def update_output(value):
assert call_count.value == 1
- dash_duo.find_element("#input").send_keys(" hello")
+ for key in " hello":
+ with lock:
+ dash_duo.find_element("#input").send_keys(key)
dash_duo.wait_for_text_to_equal("#output-container", "dash hello")
_html = dash_duo.find_element("#output-container").get_property("innerHTML")
@@ -88,7 +94,7 @@ def update_output(value):
'style="font-family: "dash hello";">dash hello '
)
- assert call_count.value == 7
+ wait.until(lambda: call_count.value == 7, 3)
def test_rdmo003_single_output_as_multi(dash_duo):
diff --git a/tests/integration/test_csp.py b/tests/integration/test_csp.py
new file mode 100644
index 0000000000..6074ac30c8
--- /dev/null
+++ b/tests/integration/test_csp.py
@@ -0,0 +1,61 @@
+import contextlib
+
+import pytest
+import flask_talisman
+from selenium.common.exceptions import NoSuchElementException
+
+import dash
+import dash_core_components as dcc
+import dash_html_components as html
+from dash.dependencies import Input, Output
+
+
+@contextlib.contextmanager
+def does_not_raise():
+ yield
+
+
+@pytest.mark.parametrize(
+ "add_hashes, hash_algorithm, expectation",
+ [
+ (False, None, pytest.raises(NoSuchElementException)),
+ (True, "sha256", does_not_raise()),
+ (True, "sha384", does_not_raise()),
+ (True, "sha512", does_not_raise()),
+ (True, "sha999", pytest.raises(ValueError)),
+ ],
+)
+def test_incs001_csp_hashes_inline_scripts(
+ dash_duo, add_hashes, hash_algorithm, expectation
+):
+ app = dash.Dash(__name__)
+
+ app.layout = html.Div(
+ [dcc.Input(id="input_element", type="text"), html.Div(id="output_element")]
+ )
+
+ app.clientside_callback(
+ """
+ function(input) {
+ return input;
+ }
+ """,
+ Output("output_element", "children"),
+ [Input("input_element", "value")],
+ )
+
+ with expectation:
+ csp = {
+ "default-src": "'self'",
+ "script-src": ["'self'"]
+ + (app.csp_hashes(hash_algorithm) if add_hashes else []),
+ }
+
+ flask_talisman.Talisman(
+ app.server, content_security_policy=csp, force_https=False
+ )
+
+ dash_duo.start_server(app)
+
+ dash_duo.find_element("#input_element").send_keys("xyz")
+ assert dash_duo.wait_for_element("#output_element").text == "xyz"