From 93341a3d4d1c06f360aa98f073920075a84fa8e2 Mon Sep 17 00:00:00 2001 From: Christopher Schinnerl Date: Tue, 1 Sep 2020 15:26:48 +0200 Subject: [PATCH 01/44] fix byte range caching (#362) --- docker/nginx/conf.d/client.conf | 18 ++---------------- .../nginx/conf.d/include/proxy-cache-downloads | 9 +++++++++ 2 files changed, 11 insertions(+), 16 deletions(-) create mode 100644 docker/nginx/conf.d/include/proxy-cache-downloads diff --git a/docker/nginx/conf.d/client.conf b/docker/nginx/conf.d/client.conf index e4f85e5b..8a68f603 100644 --- a/docker/nginx/conf.d/client.conf +++ b/docker/nginx/conf.d/client.conf @@ -174,6 +174,7 @@ server { location ~ "^/([a-zA-Z0-9-_]{46}(/.*)?)$" { include /etc/nginx/conf.d/include/cors; include /etc/nginx/conf.d/include/proxy-buffer; + include /etc/nginx/conf.d/include/proxy-cache-downloads; limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time add_header Cache-Control "public, max-age=86400"; # allow consumer to cache response @@ -186,19 +187,12 @@ server { proxy_set_header User-Agent: Sia-Agent; # proxy this call to siad /skynet/skylink/ endpoint (make sure the ip is correct) proxy_pass http://siad/skynet/skylink/$skylink$is_args$args; - - # cache frequent (> 10) downloads for 24 hours - proxy_cache skynet; - proxy_cache_key $uri; - proxy_cache_min_uses 10; - proxy_cache_valid 200 1440m; - proxy_cache_bypass $cookie_nocache $arg_nocache; # add cache bypass option - add_header X-Proxy-Cache $upstream_cache_status; } location ~ "^/file/([a-zA-Z0-9-_]{46}(/.*)?)$" { include /etc/nginx/conf.d/include/cors; include /etc/nginx/conf.d/include/proxy-buffer; + include /etc/nginx/conf.d/include/proxy-cache-downloads; limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time add_header Cache-Control "public, max-age=86400"; # allow consumer to cache response @@ -212,13 +206,5 @@ server { # proxy this call to siad /skynet/skylink/ endpoint (make sure the ip is correct) # this alias also adds attachment=true url param to force download the file proxy_pass http://siad/skynet/skylink/$skylink?attachment=true&$args; - - # cache frequent (> 10) downloads for 24 hours - proxy_cache skynet; - proxy_cache_key $uri; - proxy_cache_min_uses 10; - proxy_cache_valid 200 1440m; - proxy_cache_bypass $cookie_nocache $arg_nocache; # add cache bypass option - add_header X-Proxy-Cache $upstream_cache_status; } } diff --git a/docker/nginx/conf.d/include/proxy-cache-downloads b/docker/nginx/conf.d/include/proxy-cache-downloads new file mode 100644 index 00000000..79ae2cfe --- /dev/null +++ b/docker/nginx/conf.d/include/proxy-cache-downloads @@ -0,0 +1,9 @@ +proxy_cache skynet; +slice 1m; +proxy_http_version 1.1; # upgrade if necessary because 1.0 does not support byte-range requests +proxy_set_header Range $slice_range; # pass slice range to proxy +proxy_cache_key $uri$slice_range; # include $slice_range in the cache key +proxy_cache_min_uses 3; # cache responses after 3 requests of the same file +proxy_cache_valid 200 206 24h; # cache 200 and 206 responses for 24 hours +proxy_cache_bypass $cookie_nocache $arg_nocache; # add cache bypass option +add_header X-Proxy-Cache $upstream_cache_status; # add response header to indicate cache hits and misses From 19cc8a1402fc46164ea643621b70d5a09ae0726d Mon Sep 17 00:00:00 2001 From: Kcchouette Date: Thu, 3 Sep 2020 00:17:51 +0200 Subject: [PATCH 02/44] Fix python SDK code example --- packages/webapp/src/components/CodeExamples/Code.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/webapp/src/components/CodeExamples/Code.js b/packages/webapp/src/components/CodeExamples/Code.js index 336b5fab..33018c4a 100644 --- a/packages/webapp/src/components/CodeExamples/Code.js +++ b/packages/webapp/src/components/CodeExamples/Code.js @@ -1,11 +1,11 @@ -export const python = `from siaskynet import Skynet +export const python = `import siaskynet # upload -skylink = Skynet.upload_file("./src.jpg") +skylink = siaskynet.upload_file("./src.jpg") print("Upload successful, skylink: " + skylink) # download -Skynet.download_file("./dst.jpg", skylink) +siaskynet.download_file("./dst.jpg", skylink) print("Download successful")`; export const curl = `# upload From 746da81725f83080fcc901fd483d5bfcc53ba385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Wypch=C5=82o?= Date: Thu, 3 Sep 2020 15:08:55 +0200 Subject: [PATCH 03/44] cache hns response for 5 minutes (#366) --- packages/handshake-api/package.json | 3 ++- packages/handshake-api/src/index.js | 6 ++++++ yarn.lock | 12 ++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/handshake-api/package.json b/packages/handshake-api/package.json index 2e6850ce..fbbf3a32 100644 --- a/packages/handshake-api/package.json +++ b/packages/handshake-api/package.json @@ -6,7 +6,8 @@ "dependencies": { "express": "^4.17.1", "express-http-proxy": "^1.6.2", - "hs-client": "^0.0.9" + "hs-client": "^0.0.9", + "node-cache": "^5.1.2" }, "devDependencies": { "prettier": "^2.0.5" diff --git a/packages/handshake-api/src/index.js b/packages/handshake-api/src/index.js index 6c057ca1..fa522387 100644 --- a/packages/handshake-api/src/index.js +++ b/packages/handshake-api/src/index.js @@ -1,6 +1,7 @@ const url = require("url"); const express = require("express"); const proxy = require("express-http-proxy"); +const NodeCache = require("node-cache"); const { NodeClient } = require("hs-client"); const host = process.env.HOSTNAME || "0.0.0.0"; @@ -18,16 +19,21 @@ const clientOptions = { apiKey: hsdApiKey, }; const client = new NodeClient(clientOptions); +const cache = new NodeCache({ stdTTL: 300 }); // cache for 5 minutes // Match both `sia://HASH` and `HASH` links. const startsWithSkylinkRegExp = /^(sia:\/\/)?[a-zA-Z0-9_-]{46}/; const getDomainRecords = async (name) => { + if (cache.has(name)) return cache.get(name); + const response = await client.execute("getnameresource", [name]); const records = response?.records ?? null; console.log(`${name} => ${JSON.stringify(records)}`); + cache.set(name, records); + return records; }; diff --git a/yarn.lock b/yarn.lock index 5c958731..815f171e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3928,6 +3928,11 @@ clone-response@1.0.2, clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" +clone@2.x: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + coa@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" @@ -10238,6 +10243,13 @@ node-addon-api@^3.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.0.tgz#812446a1001a54f71663bed188314bba07e09247" integrity sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg== +node-cache@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d" + integrity sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg== + dependencies: + clone "2.x" + node-emoji@^1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da" From a911b36f569f4c74621ba710f50f4f096b0e469e Mon Sep 17 00:00:00 2001 From: Matthew Sevey Date: Thu, 3 Sep 2020 10:50:43 -0400 Subject: [PATCH 04/44] Add severe check to log checker --- setup-scripts/log-checker.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/setup-scripts/log-checker.py b/setup-scripts/log-checker.py index 6d6a32ad..95092201 100755 --- a/setup-scripts/log-checker.py +++ b/setup-scripts/log-checker.py @@ -101,16 +101,16 @@ async def check_docker_logs(): await send_msg(client, "Error(s) preview:\n{}".format(std_err), force_notify=True) return - # If there are any critical errors. upload the whole log file. - if 'Critical' in std_out or 'panic' in std_out: + # If there are any critical or severe errors. upload the whole log file. + if 'Critical' in std_out or 'Severe' in std_out or 'panic' in std_out: upload_name = "{}-{}-{}-{}-{}:{}:{}.log".format(container_name, time.year, time.month, time.day, time.hour, time.minute, time.second) - await send_msg(client, "Critical error found in log!", file=discord.File(io.BytesIO(std_out.encode()), filename=upload_name), force_notify=True) + await send_msg(client, "Critical or Severe error found in log!", file=discord.File(io.BytesIO(std_out.encode()), filename=upload_name), force_notify=True) return - # No critical errors, return a heartbeat type message + # No critical or severe errors, return a heartbeat type message pretty_before = time.strftime("%I:%M%p") pretty_now = now.strftime("%I:%M%p") - await send_msg(client, "No critical warnings in log from `{}` to `{}`".format(pretty_before, pretty_now)) + await send_msg(client, "No critical or severe warnings in log from `{}` to `{}`".format(pretty_before, pretty_now)) client.run(bot_token) From 2b360933671cb5dba9737cb7eeddca0e90bccae1 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 3 Sep 2020 19:04:29 +0200 Subject: [PATCH 05/44] update dapp example to uniswap v2 --- packages/webapp/src/components/HomeSamples/HomeSamples.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/components/HomeSamples/HomeSamples.js b/packages/webapp/src/components/HomeSamples/HomeSamples.js index 1a9efd48..d8661ad1 100644 --- a/packages/webapp/src/components/HomeSamples/HomeSamples.js +++ b/packages/webapp/src/components/HomeSamples/HomeSamples.js @@ -12,7 +12,7 @@ const samples = [ { type: "Audio", url: "/_A2zt5SKoqwnnZU4cBF8uBycSKULXMyeg1c5ZISBr2Q3dA" }, { type: "Video", url: "/CABAB_1Dt0FJsxqsu_J4TodNCbCGvtFf1Uys_3EgzOlTcg" }, { type: "JSON", url: "/AAC0uO43g64ULpyrW0zO3bjEknSFbAhm8c-RFP21EQlmSQ" }, - { type: "Dapp", url: "/EAC5HJr5Pu086EAZG4fP_r6Pnd7Ft366vt6t2AnjkoFb9Q/index.html" }, + { type: "Dapp", url: "/IAC6CkhNYuWZqMVr1gob1B6tPg4MrBGRzTaDvAIAeu9A9w/" }, ]; export default function HomeSamples() { From 559960645e747089e3ab2c74ca66ce43e3710c2c Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 3 Sep 2020 19:19:40 +0200 Subject: [PATCH 06/44] fix docker build --- docker/handshake/Dockerfile | 2 +- packages/handshake-api/Dockerfile | 2 +- packages/health-check/Dockerfile | 2 +- packages/webapp/Dockerfile | 2 +- packages/webapp/package.json | 78 +- yarn.lock | 1155 +++++++++++++++++------------ 6 files changed, 704 insertions(+), 537 deletions(-) diff --git a/docker/handshake/Dockerfile b/docker/handshake/Dockerfile index 93d57f2a..abca6616 100644 --- a/docker/handshake/Dockerfile +++ b/docker/handshake/Dockerfile @@ -1,5 +1,5 @@ # we can't use alpine image since it fails on node-gyp -FROM node:14.8.0 +FROM node:14.9.0 WORKDIR /opt/hsd diff --git a/packages/handshake-api/Dockerfile b/packages/handshake-api/Dockerfile index 44fbd068..e7b69f53 100644 --- a/packages/handshake-api/Dockerfile +++ b/packages/handshake-api/Dockerfile @@ -1,4 +1,4 @@ -FROM node:14.8.0-alpine +FROM node:14.9.0-alpine WORKDIR /usr/app diff --git a/packages/health-check/Dockerfile b/packages/health-check/Dockerfile index f83e24d9..f2ee9b61 100644 --- a/packages/health-check/Dockerfile +++ b/packages/health-check/Dockerfile @@ -1,4 +1,4 @@ -FROM node:14.8.0-alpine +FROM node:14.9.0-alpine WORKDIR /usr/app diff --git a/packages/webapp/Dockerfile b/packages/webapp/Dockerfile index d75f8cf4..d2f21447 100644 --- a/packages/webapp/Dockerfile +++ b/packages/webapp/Dockerfile @@ -1,4 +1,4 @@ -FROM node:14.8.0-alpine +FROM node:14.9.0 WORKDIR /usr/app diff --git a/packages/webapp/package.json b/packages/webapp/package.json index 18955185..401fe7cf 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -4,48 +4,48 @@ "version": "1.0.0", "author": "Nebulous", "dependencies": { - "axios": "^0.20.0", - "bytes": "^3.1.0", - "classnames": "^2.2.6", - "gatsby": "^2.24.47", - "gatsby-image": "^2.4.16", - "gatsby-plugin-manifest": "^2.4.23", - "gatsby-plugin-matomo": "^0.8.3", - "gatsby-plugin-react-helmet": "^3.3.10", - "gatsby-plugin-remove-serviceworker": "^1.0.0", - "gatsby-plugin-robots-txt": "^1.5.1", - "gatsby-plugin-sass": "^2.3.12", - "gatsby-plugin-sharp": "^2.6.27", - "gatsby-source-filesystem": "^2.3.24", - "gatsby-transformer-sharp": "^2.5.13", - "http-status-codes": "^2.1.1", - "jsonp": "^0.2.1", - "node-sass": "^4.14.0", - "path-browserify": "^1.0.1", - "prop-types": "^15.7.2", - "react": "^16.13.1", - "react-countup": "^4.3.3", - "react-dom": "^16.13.1", - "react-dropzone": "^11.0.2", - "react-helmet": "^6.1.0", - "react-mailchimp-form": "^1.0.2", - "react-mailchimp-subscribe": "^2.1.0", - "react-reveal": "^1.2.2", - "react-syntax-highlighter": "^13.5.0", - "react-visibility-sensor": "^5.1.1", + "axios": "0.20.0", + "bytes": "3.1.0", + "classnames": "2.2.6", + "gatsby": "2.24.53", + "gatsby-image": "2.4.16", + "gatsby-plugin-manifest": "2.4.27", + "gatsby-plugin-matomo": "0.8.3", + "gatsby-plugin-react-helmet": "3.3.10", + "gatsby-plugin-remove-serviceworker": "1.0.0", + "gatsby-plugin-robots-txt": "1.5.1", + "gatsby-plugin-sass": "2.3.12", + "gatsby-plugin-sharp": "2.6.31", + "gatsby-source-filesystem": "2.3.27", + "gatsby-transformer-sharp": "2.5.14", + "http-status-codes": "2.1.1", + "jsonp": "0.2.1", + "node-sass": "4.14.0", + "path-browserify": "1.0.1", + "prop-types": "15.7.2", + "react": "16.13.1", + "react-countup": "4.3.3", + "react-dom": "16.13.1", + "react-dropzone": "11.0.3", + "react-helmet": "6.1.0", + "react-mailchimp-form": "1.0.2", + "react-mailchimp-subscribe": "2.1.0", + "react-reveal": "1.2.2", + "react-syntax-highlighter": "13.5.1", + "react-visibility-sensor": "5.1.1", "skynet-js": "0.0.8", - "typeface-metropolis": "^0.0.74" + "typeface-metropolis": "0.0.74" }, "devDependencies": { - "cypress": "^5.0.0", - "cypress-file-upload": "^4.0.7", - "eslint": "^7.7.0", - "eslint-config-prettier": "^6.11.0", - "eslint-plugin-cypress": "^2.11.1", - "eslint-plugin-react": "^7.20.6", - "husky": "^4.2.5", - "lint-staged": "^10.2.11", - "prettier": "^2.0.5" + "cypress": "5.1.0", + "cypress-file-upload": "4.1.1", + "eslint": "7.8.1", + "eslint-config-prettier": "6.11.0", + "eslint-plugin-cypress": "2.11.1", + "eslint-plugin-react": "7.20.6", + "husky": "4.2.5", + "lint-staged": "10.3.0", + "prettier": "2.1.1" }, "keywords": [ "sia", diff --git a/yarn.lock b/yarn.lock index 815f171e..8454e7a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -984,6 +984,15 @@ globals "^11.1.0" lodash "^4.17.19" +"@babel/types@^7.10.3": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" + integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.4.4", "@babel/types@^7.7.0": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.5.tgz#d88ae7e2fde86bfbfe851d4d81afa70a997b5d15" @@ -1148,6 +1157,22 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== +"@eslint/eslintrc@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.1.3.tgz#7d1a2b2358552cc04834c0979bd4275362e37085" + integrity sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + "@graphql-tools/schema@^6.0.14": version "6.0.18" resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-6.0.18.tgz#243eb370e4cded00767202bbabf0893f65c3f5b9" @@ -1552,14 +1577,6 @@ resolved "https://registry.yarnpkg.com/@mikaelkristiansson/domready/-/domready-1.0.10.tgz#f6d69866c0857664e70690d7a0bfedb72143adb5" integrity sha512-6cDuZeKSCSJ1KvfEQ25Y8OXUjqDJZ+HgUs6dhASWbAX8fxVraTfPsSeRe2bN+4QJDsgUaXaMWBYfRomCr04GGg== -"@mrmlnc/readdir-enhanced@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" - integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== - dependencies: - call-me-maybe "^1.0.1" - glob-to-regexp "^0.3.0" - "@nodelib/fs.scandir@2.1.3": version "2.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" @@ -1573,11 +1590,6 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== -"@nodelib/fs.stat@^1.1.2": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" - integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== - "@nodelib/fs.walk@^1.2.3": version "1.2.4" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" @@ -1596,17 +1608,17 @@ string-width "^2.0.0" strip-ansi "^3" -"@pmmmwh/react-refresh-webpack-plugin@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.3.3.tgz#40a3d674f42a011b7f30a9609aa8fb68ec3c39c9" - integrity sha512-uc6FmPEegAZawSHjUMFQwU7EjaDn7zy1iD/KD/wBROL9F4378OES8MKMYHoRAKT61Fk7LxVKZSDR5VespMQiqw== +"@pmmmwh/react-refresh-webpack-plugin@^0.4.1": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.4.2.tgz#1f9741e0bde9790a0e13272082ed7272a083620d" + integrity sha512-Loc4UDGutcZ+Bd56hBInkm6JyjyCwWy4t2wcDXzN8EDPANgVRj0VP8Nxn0Zq2pc+WKauZwEivQgbDGg4xZO20A== dependencies: ansi-html "^0.0.7" error-stack-parser "^2.0.6" html-entities "^1.2.1" - lodash.debounce "^4.0.8" native-url "^0.2.6" schema-utils "^2.6.5" + source-map "^0.7.3" "@reach/alert@0.10.3": version "0.10.3" @@ -1784,6 +1796,11 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== +"@sindresorhus/is@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-2.1.1.tgz#ceff6a28a5b4867c2dd4a1ba513de278ccbe8bb1" + integrity sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg== + "@styled-system/css@^5.0.16": version "5.1.5" resolved "https://registry.yarnpkg.com/@styled-system/css/-/css-5.1.5.tgz#0460d5f3ff962fa649ea128ef58d9584f403bbbc" @@ -1796,7 +1813,14 @@ dependencies: defer-to-connect "^1.0.1" -"@turist/fetch@^7.1.6": +"@szmarczak/http-timer@^4.0.0": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.5.tgz#bfbd50211e9dfa51ba07da58a14cdfd333205152" + integrity sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ== + dependencies: + defer-to-connect "^2.0.0" + +"@turist/fetch@^7.1.7": version "7.1.7" resolved "https://registry.yarnpkg.com/@turist/fetch/-/fetch-7.1.7.tgz#a2b1f7ec0265e6fe0946c51eef34bad9b9efc865" integrity sha512-XP20kvfyMNlWdPVQXyuzA40LoCHbbJptikt7W+TlZ5sS+NNjk70xjXCtHBLEudp7li3JldXEFSIUzpW1a0WEhA== @@ -1808,6 +1832,16 @@ resolved "https://registry.yarnpkg.com/@turist/time/-/time-0.0.1.tgz#57637d2a7d1860adb9f9cecbdcc966ce4f551d63" integrity sha512-M2BiThcbxMxSKX8W4z5u9jKZn6datnM3+FpEU+eYw0//l31E2xhqi7vTAuJ/Sf0P3yhp66SDJgPu3bRRpvrdQQ== +"@types/cacheable-request@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976" + integrity sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "*" + "@types/node" "*" + "@types/responselike" "*" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" @@ -1872,6 +1906,11 @@ resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.7.tgz#613957d900fab9ff84c8dfb24fa3eef0c2a40896" integrity sha512-2xtoL22/3Mv6a70i4+4RB7VgbDDORoWwjcqeNysojZA0R7NK17RbY5Gof/2QiFfJgX+KkWghbwJ+d/2SB8Ndzg== +"@types/http-cache-semantics@*": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz#9140779736aa2655635ee756e2467d787cfe8a2a" + integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== + "@types/http-proxy@^1.17.4": version "1.17.4" resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.4.tgz#e7c92e3dbe3e13aa799440ff42e6d3a17a9d045b" @@ -1909,6 +1948,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= +"@types/keyv@*", "@types/keyv@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7" + integrity sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw== + dependencies: + "@types/node" "*" + "@types/lodash.sample@^4.2.6": version "4.2.6" resolved "https://registry.yarnpkg.com/@types/lodash.sample/-/lodash.sample-4.2.6.tgz#ec7f6a6dbd0401c4a1e5f5b3c85fa5a85a42a84a" @@ -2009,6 +2055,13 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/responselike@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + "@types/rimraf@^2.0.2": version "2.0.4" resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.4.tgz#403887b0b53c6100a6c35d2ab24f6ccc042fec46" @@ -2292,12 +2345,12 @@ acorn@^6.1.1, acorn@^6.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== -acorn@^7.1.1, acorn@^7.3.1: +acorn@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== -acorn@^7.2.0: +acorn@^7.2.0, acorn@^7.4.0: version "7.4.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== @@ -2345,6 +2398,16 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.3: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.12.4: + version "6.12.4" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" + integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + alphanum-sort@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" @@ -2439,11 +2502,6 @@ any-observable@^0.3.0: resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== -any-promise@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= - anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -2694,7 +2752,7 @@ async@1.5.2: resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= -async@^2.6.2, async@^2.6.3: +async@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== @@ -2759,6 +2817,13 @@ axe-core@^3.5.4: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.5.tgz#84315073b53fa3c0c51676c588d59da09a192227" integrity sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q== +axios@0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd" + integrity sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA== + dependencies: + follow-redirects "^1.10.0" + axios@^0.19.0, axios@^0.19.2: version "0.19.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" @@ -2766,13 +2831,6 @@ axios@^0.19.0, axios@^0.19.2: dependencies: follow-redirects "1.5.10" -axios@^0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd" - integrity sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA== - dependencies: - follow-redirects "^1.10.0" - axobject-query@^2.1.2: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" @@ -2896,10 +2954,10 @@ babel-plugin-transform-react-remove-prop-types@^0.4.24: resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== -babel-preset-gatsby@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/babel-preset-gatsby/-/babel-preset-gatsby-0.5.5.tgz#f8d05aa407a56514d7786f7b576c1954e0a3f425" - integrity sha512-gkBRAEv5OvSerqh15gMHCCtExiUpTuKiKwb6QBImb3nSBAuCcjr0ESHzpgk4m0eZLbxUaeooVd0uPyC6FQsCBQ== +babel-preset-gatsby@^0.5.8: + version "0.5.8" + resolved "https://registry.yarnpkg.com/babel-preset-gatsby/-/babel-preset-gatsby-0.5.8.tgz#b3c0d6524e12e92bf93cb5ef78edc9ac8e093b61" + integrity sha512-24KnbRLTNF3uE1NtKCwAhRJ32hLucUuMsNFq+6n/idzZNo68POLYMN0/8wQ4dHgG2AEvlQf3CTk62vkJvz01Qw== dependencies: "@babel/plugin-proposal-class-properties" "^7.10.1" "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.1" @@ -2913,8 +2971,8 @@ babel-preset-gatsby@^0.5.5: babel-plugin-dynamic-import-node "^2.3.3" babel-plugin-macros "^2.8.0" babel-plugin-transform-react-remove-prop-types "^0.4.24" - gatsby-core-utils "^1.3.15" - gatsby-legacy-polyfills "^0.0.2" + gatsby-core-utils "^1.3.18" + gatsby-legacy-polyfills "^0.0.4" babel-runtime@^6.26.0: version "6.26.0" @@ -3422,7 +3480,7 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= -bytes@3.1.0, bytes@^3.1.0: +bytes@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== @@ -3479,6 +3537,14 @@ cache-manager@^2.11.1: lodash.clonedeep "4.5.0" lru-cache "4.0.0" +cacheable-lookup@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-2.0.1.tgz#87be64a18b925234875e10a9bb1ebca4adce6b38" + integrity sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg== + dependencies: + "@types/keyv" "^3.1.1" + keyv "^4.0.0" + cacheable-request@^2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" @@ -3505,16 +3571,24 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" +cacheable-request@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.1.tgz#062031c2856232782ed694a257fa35da93942a58" + integrity sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^2.0.0" + cachedir@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== -call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= - caller-callsite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" @@ -3579,6 +3653,11 @@ camelcase@^2.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= + camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -3700,21 +3779,6 @@ check-more-types@^2.24.0: resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= -chokidar@3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8" - integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.4.0" - optionalDependencies: - fsevents "~2.1.2" - chokidar@^2.0.4, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -3749,6 +3813,21 @@ chokidar@^3.4.1: optionalDependencies: fsevents "~2.1.2" +chokidar@^3.4.2: + version "3.4.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" + integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.4.0" + optionalDependencies: + fsevents "~2.1.2" + chownr@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -3789,7 +3868,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.6: +classnames@2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== @@ -3850,14 +3929,6 @@ cli-table3@~0.6.0: optionalDependencies: colors "^1.1.2" -cli-truncate@2.1.0, cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" - integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== - dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" - cli-truncate@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" @@ -3866,6 +3937,14 @@ cli-truncate@^0.2.1: slice-ansi "0.0.4" string-width "^1.0.1" +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + cli-width@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" @@ -3894,6 +3973,15 @@ clipboardy@^2.3.0: execa "^1.0.0" is-wsl "^2.1.1" +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -4037,10 +4125,10 @@ commander@^4.1.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== +commander@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.1.0.tgz#f8d722b78103141006b66f4c7ba1e97315ba75bc" + integrity sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA== commander@~2.8.1: version "2.8.1" @@ -4142,18 +4230,6 @@ config-chain@^1.1.11: ini "^1.3.4" proto-list "~1.2.1" -configstore@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" - integrity sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw== - dependencies: - dot-prop "^4.1.0" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - unique-string "^1.0.0" - write-file-atomic "^2.0.0" - xdg-basedir "^3.0.0" - configstore@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" @@ -4349,6 +4425,17 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" +cosmiconfig@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3" + integrity sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + countup.js@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/countup.js/-/countup.js-1.9.3.tgz#ce3e50cd7160441e478f07da31895edcc0f1c9dd" @@ -4463,11 +4550,6 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" -crypto-random-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= - crypto-random-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" @@ -4665,17 +4747,17 @@ cyclist@^1.0.1: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= -cypress-file-upload@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-4.0.7.tgz#1136139bb3c660b9c39a69f231ac1da7785acaae" - integrity sha512-rFFmnoZ2bWyWFpSV09AhkSUgYEiVy70pcQ6nf/mGTMTrVHvKCCCIfRu3TbgVYHbgBq+0hqjfjQrtz4IbgH7qZA== +cypress-file-upload@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-4.1.1.tgz#952713c8104ab7008de99c65bd63f74b244fe4df" + integrity sha512-tX6UhuJ63rNgjdzxglpX+ZYf/bM6PDhFMtt1qCBljLtAgdearqyfD1AHqyh59rOHCjfM+bf6FA3o9b/mdaX6pw== dependencies: mime "^2.4.4" -cypress@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-5.0.0.tgz#6957e299b790af8b1cd7bea68261b8935646f72e" - integrity sha512-jhPd0PMO1dPSBNpx6pHVLkmnnaTfMy3wCoacHAKJ9LJG06y16zqUNSFri64N4BjuGe8y6mNMt8TdgKnmy9muCg== +cypress@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-5.1.0.tgz#979e9ff3e0acd792eefd365bf104046479a9643b" + integrity sha512-craPRO+Viu4268s7eBvX5VJW8aBYcAQT+EwEccQSMY+eH1ZPwnxIgyDlmMWvxLVX9SkWxOlZbEycPyzanQScBQ== dependencies: "@cypress/listr-verbose-renderer" "^0.4.1" "@cypress/request" "^2.88.5" @@ -4774,7 +4856,7 @@ decamelize-keys@^1.1.0: decamelize "^1.1.0" map-obj "^1.0.0" -decamelize@^1.1.0, decamelize@^1.1.2, decamelize@^1.2.0: +decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -4798,6 +4880,13 @@ decompress-response@^4.2.0: dependencies: mimic-response "^2.0.0" +decompress-response@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-5.0.0.tgz#7849396e80e3d1eba8cb2f75ef4930f76461cb0f" + integrity sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw== + dependencies: + mimic-response "^2.0.0" + decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -4913,6 +5002,11 @@ defer-to-connect@^1.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== +defer-to-connect@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1" + integrity sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg== + define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -5053,10 +5147,10 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" -devcert@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/devcert/-/devcert-1.1.2.tgz#5c4f816e27be540c68916e0f023cf8774f2616d6" - integrity sha512-B72N5Z2Lzu11dsPvg/KD9IwQCyNg6JgsNcHw7zJ+QQN9/rusMpc0tSSOYLczmty5D7vOs94IHITPQ0uei5D3cw== +devcert@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/devcert/-/devcert-1.1.3.tgz#ff8119efae52ebf2449531b7482ae0f7211542e9" + integrity sha512-7/nIzKdQ8y2K0imjIP7dyg2GJ2h38Ps6VOMXWZHIarNDV3p6mTXyEugKFnkmsZ2DD58JEG34ILyVb3qdOMmP9w== dependencies: "@types/configstore" "^2.1.1" "@types/debug" "^0.0.30" @@ -5069,7 +5163,6 @@ devcert@^1.1.0: "@types/tmp" "^0.0.33" application-config-path "^0.1.0" command-exists "^1.2.4" - configstore "^3.0.0" debug "^3.1.0" eol "^0.9.1" get-port "^3.2.0" @@ -5096,14 +5189,6 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -dir-glob@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" - integrity sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag== - dependencies: - arrify "^1.0.1" - path-type "^3.0.0" - dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -5211,13 +5296,6 @@ domutils@^1.5.1, domutils@^1.7.0: dom-serializer "0" domelementtype "1" -dot-prop@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== - dependencies: - is-obj "^1.0.0" - dot-prop@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" @@ -5400,7 +5478,7 @@ engine.io@~3.4.0: engine.io-parser "~2.2.0" ws "^7.1.2" -enhanced-resolve@^4.1.0: +enhanced-resolve@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== @@ -5409,7 +5487,7 @@ enhanced-resolve@^4.1.0: memory-fs "^0.5.0" tapable "^1.0.0" -enquirer@^2.3.5: +enquirer@^2.3.5, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -5431,6 +5509,11 @@ envinfo@^7.5.1: resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.2.tgz#098f97a0e902f8141f9150553c92dbb282c4cabe" integrity sha512-k3Eh5bKuQnZjm49/L7H4cHzs2FlL5QjbTB3JrPxoTI8aJG7hVMe4uKyJxSYH4ahseby2waUwk5OaKX/nAsaYgg== +envinfo@^7.7.3: + version "7.7.3" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.3.tgz#4b2d8622e3e7366afb8091b23ed95569ea0208cc" + integrity sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA== + eol@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" @@ -5508,7 +5591,7 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -eslint-config-prettier@^6.11.0: +eslint-config-prettier@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz#f6d2238c1290d01c859a8b5c1f7d352a0b0da8b1" integrity sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA== @@ -5549,7 +5632,7 @@ eslint-module-utils@^2.6.0: debug "^2.6.9" pkg-dir "^2.0.0" -eslint-plugin-cypress@^2.11.1: +eslint-plugin-cypress@2.11.1: version "2.11.1" resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.11.1.tgz#a945e2774b88211e2c706a059d431e262b5c2862" integrity sha512-MxMYoReSO5+IZMGgpBZHHSx64zYPSPTpXDwsgW7ChlJTF/sA+obqRbHplxD6sBStE+g4Mi0LCLkG4t9liu//mQ== @@ -5612,7 +5695,7 @@ eslint-plugin-react-hooks@^1.7.0: resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz#6210b6d5a37205f0b92858f895a4e827020a7d04" integrity sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA== -eslint-plugin-react@^7.20.2, eslint-plugin-react@^7.20.6: +eslint-plugin-react@7.20.6, eslint-plugin-react@^7.20.6: version "7.20.6" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.6.tgz#4d7845311a93c463493ccfa0a19c9c5d0fd69f60" integrity sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg== @@ -5664,6 +5747,49 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== +eslint@7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.8.1.tgz#e59de3573fb6a5be8ff526c791571646d124a8fa" + integrity sha512-/2rX2pfhyUG0y+A123d0ccXtMm7DV7sH1m3lk9nk2DZ2LReq39FXHueR9xZwshE5MdfSf0xunSaMWRqyIA6M1w== + dependencies: + "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.1.3" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + eslint-scope "^5.1.0" + eslint-utils "^2.1.0" + eslint-visitor-keys "^1.3.0" + espree "^7.3.0" + esquery "^1.2.0" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash "^4.17.19" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + eslint@^6.8.0: version "6.8.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" @@ -5707,48 +5833,6 @@ eslint@^6.8.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -eslint@^7.7.0: - version "7.7.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.7.0.tgz#18beba51411927c4b64da0a8ceadefe4030d6073" - integrity sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.0.1" - doctrine "^3.0.0" - enquirer "^2.3.5" - eslint-scope "^5.1.0" - eslint-utils "^2.1.0" - eslint-visitor-keys "^1.3.0" - espree "^7.2.0" - esquery "^1.2.0" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash "^4.17.19" - minimatch "^3.0.4" - natural-compare "^1.4.0" - optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.1.0" - semver "^7.2.1" - strip-ansi "^6.0.0" - strip-json-comments "^3.1.0" - table "^5.2.3" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - espree@^6.1.2: version "6.2.1" resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" @@ -5758,12 +5842,12 @@ espree@^6.1.2: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.1.0" -espree@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.2.0.tgz#1c263d5b513dbad0ac30c4991b93ac354e948d69" - integrity sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g== +espree@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" + integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== dependencies: - acorn "^7.3.1" + acorn "^7.4.0" acorn-jsx "^5.2.0" eslint-visitor-keys "^1.3.0" @@ -5853,19 +5937,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" - integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw== - dependencies: - cross-spawn "^6.0.0" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -5908,7 +5979,7 @@ execa@^3.4.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -execa@^4.0.1, execa@^4.0.2: +execa@^4.0.0, execa@^4.0.2, execa@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2" integrity sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A== @@ -6112,18 +6183,6 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^2.0.2: - version "2.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" - integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== - dependencies: - "@mrmlnc/readdir-enhanced" "^2.2.1" - "@nodelib/fs.stat" "^1.1.2" - glob-parent "^3.1.0" - is-glob "^4.0.0" - merge2 "^1.2.3" - micromatch "^3.1.10" - fast-glob@^3.0.3, fast-glob@^3.1.1: version "3.2.4" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" @@ -6250,12 +6309,7 @@ file-type@5.2.0, file-type@^5.2.0: resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" integrity sha1-LdvqfHP/42No365J3DOMBYwritY= -file-type@^10.7.0: - version "10.11.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-10.11.0.tgz#2961d09e4675b9fb9a3ee6b69e9cd23f43fd1890" - integrity sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw== - -file-type@^12.4.2: +file-type@^12.0.0, file-type@^12.4.2: version "12.4.2" resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.4.2.tgz#a344ea5664a1d01447ee7fb1b635f72feb6169d9" integrity sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg== @@ -6623,10 +6677,10 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gatsby-cli@^2.12.87: - version "2.12.87" - resolved "https://registry.yarnpkg.com/gatsby-cli/-/gatsby-cli-2.12.87.tgz#0b9a3ca313a713698a0350e39e13dc7095523a02" - integrity sha512-LB65Hh8hN/H5XSh6EnOnK1jpUiB9GqgaW9c4SeGayogenaWk2RAY4blkq7ncVunM5Nm+uKbY9bDM9TlFe+r2Bg== +gatsby-cli@^2.12.91: + version "2.12.91" + resolved "https://registry.yarnpkg.com/gatsby-cli/-/gatsby-cli-2.12.91.tgz#897e7fe7ed8e26119f95e6198a037fcfb6f41542" + integrity sha512-HmKkjY6HAvb65JRpgRM1LyVYtHim6A286BvYcbMM+gwE5Bgc27e9FTmNUHjZwYiPcQqx4AMQTb4G9uL5/UuBZA== dependencies: "@babel/code-frame" "^7.10.3" "@hapi/joi" "^15.1.1" @@ -6641,9 +6695,9 @@ gatsby-cli@^2.12.87: execa "^3.4.0" fs-exists-cached "^1.0.0" fs-extra "^8.1.0" - gatsby-core-utils "^1.3.15" - gatsby-recipes "^0.2.16" - gatsby-telemetry "^1.3.27" + gatsby-core-utils "^1.3.18" + gatsby-recipes "^0.2.20" + gatsby-telemetry "^1.3.30" hosted-git-info "^3.0.4" ink "^2.7.1" ink-spinner "^3.1.0" @@ -6664,20 +6718,21 @@ gatsby-cli@^2.12.87: stack-trace "^0.0.10" strip-ansi "^5.2.0" update-notifier "^4.1.0" - uuid "3.4.0" + uuid "^8.3.0" yargs "^15.3.1" yurnalist "^1.1.2" -gatsby-core-utils@^1.3.15: - version "1.3.15" - resolved "https://registry.yarnpkg.com/gatsby-core-utils/-/gatsby-core-utils-1.3.15.tgz#6fad76a238df514afa70fed0f94427fbb39762ca" - integrity sha512-np1tJCGejhCHtgHdFl6+y5EwVAzdrieJZ3hdvpeOrJ22bL9ktl5XVLy4K937ThgxHLp8+ElMDVdziNun5tC8eg== +gatsby-core-utils@^1.3.18: + version "1.3.18" + resolved "https://registry.yarnpkg.com/gatsby-core-utils/-/gatsby-core-utils-1.3.18.tgz#8eecb424f8709bbb3dac9653973068643b3fd66f" + integrity sha512-B7ixQb4H0e2yB0nNfM2zshOAUw3nW9MvcNsRskVFwIPJY+ngh8Srla4XWXVMJ60Fyt103+jPVZTxGq72/u5HuQ== dependencies: ci-info "2.0.0" configstore "^5.0.1" fs-extra "^8.1.0" node-object-hash "^2.0.0" proper-lockfile "^4.1.1" + tmp "^0.2.1" xdg-basedir "^4.0.0" gatsby-design-tokens@^2.0.2: @@ -6687,14 +6742,14 @@ gatsby-design-tokens@^2.0.2: dependencies: hex2rgba "^0.0.1" -gatsby-graphiql-explorer@^0.4.12: - version "0.4.12" - resolved "https://registry.yarnpkg.com/gatsby-graphiql-explorer/-/gatsby-graphiql-explorer-0.4.12.tgz#9c7a3c9c562e7bb8e3e24bf7c8ac4b319d0ce64b" - integrity sha512-kHVHzGvebZlUGeGOoAAJVdLWAXftZiYeOk6EitWFkXEZtYxpgXM5Pum9qDMCzUCJ6pzS8r9U5IBJncjMal3ScQ== +gatsby-graphiql-explorer@^0.4.13: + version "0.4.13" + resolved "https://registry.yarnpkg.com/gatsby-graphiql-explorer/-/gatsby-graphiql-explorer-0.4.13.tgz#c52b3d7516454c7a267cdfed6f073ca2f4783cb7" + integrity sha512-sxuQ5p2jQrK4irI57/BXGUvvlqQxmJlUMgLQ6M4pbxO1LP9sWsqDsAjWpifwbSlQh02VcPuMWScJxTq5xPUfng== dependencies: "@babel/runtime" "^7.10.3" -gatsby-image@^2.4.16: +gatsby-image@2.4.16: version "2.4.16" resolved "https://registry.yarnpkg.com/gatsby-image/-/gatsby-image-2.4.16.tgz#65ce1642bb6a0c8d87c74b204ed79995cd43da16" integrity sha512-N5kJ3LE8re57DgR1lAZFWP2or0nCSuNXSUKvSBvVgxwcebdcFGCxN/xTJbU4ojFfFBJ/D4gKuxJrvLvDf3jcyg== @@ -6723,10 +6778,10 @@ gatsby-interface@^0.0.166: lodash.sample "^4.2.1" theme-ui "^0.2.49" -gatsby-legacy-polyfills@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/gatsby-legacy-polyfills/-/gatsby-legacy-polyfills-0.0.2.tgz#c0e2524eccb7fd53e883161a291edcb022ff5aa8" - integrity sha512-i8LLwvtupC92AjQMivLDKDCgN51sV6FLbtoNn0CRQJdLJY31P06k+5qKcjdprGLdPjCjkCsYLTYi08pdvqAuPw== +gatsby-legacy-polyfills@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/gatsby-legacy-polyfills/-/gatsby-legacy-polyfills-0.0.4.tgz#2c11859f485b87ca6fd3331bda1951f64d114b7e" + integrity sha512-BDlY9jkhEhqpQN5yvfnJYt8wTRzBOEtIQZnWHzuE7b6tYHsngxbfIMLN3UBOs9t5ZUqcPKc1C0J0NKG6NhC4Qw== dependencies: core-js-compat "^3.6.5" @@ -6739,61 +6794,61 @@ gatsby-link@^2.4.13: "@types/reach__router" "^1.3.3" prop-types "^15.7.2" -gatsby-page-utils@^0.2.20: - version "0.2.20" - resolved "https://registry.yarnpkg.com/gatsby-page-utils/-/gatsby-page-utils-0.2.20.tgz#2d9360f274b09476224f178b23d7cb106afc961a" - integrity sha512-waq2TpDjNxH5+Q+xFnuf9of3Xt0wxBkJwb6VbCGz4LS0XQ6c9KYMgC2OCBwPJOnv2Vo/6BglpRyn4lYcJEQJdw== +gatsby-page-utils@^0.2.23: + version "0.2.23" + resolved "https://registry.yarnpkg.com/gatsby-page-utils/-/gatsby-page-utils-0.2.23.tgz#8216adb75a4f7143f6a945f2efff05c9458bf9a2" + integrity sha512-z0eiGNchTk0sWNubLVBNXOI9VLHCNHFFjNt5RweW211SLR/Bw7paQOaX9gY0Bdj1C2+NZ8JMyTHs1JF7yybaDg== dependencies: "@babel/runtime" "^7.10.3" bluebird "^3.7.2" - chokidar "3.4.0" + chokidar "^3.4.2" fs-exists-cached "^1.0.0" - gatsby-core-utils "^1.3.15" + gatsby-core-utils "^1.3.18" glob "^7.1.6" lodash "^4.17.15" micromatch "^3.1.10" -gatsby-plugin-manifest@^2.4.23: - version "2.4.23" - resolved "https://registry.yarnpkg.com/gatsby-plugin-manifest/-/gatsby-plugin-manifest-2.4.23.tgz#fb0ea242e1421c9d2d576b7cd2918da50bd9a557" - integrity sha512-1vLXRU8fAmCWjTAQ8/hbvMfHEbxJsBSUk5R5phNAlwaa5jjklaxjaBgeE/uEUzc5+vq5WvBgodRRiv779fpcnA== +gatsby-plugin-manifest@2.4.27: + version "2.4.27" + resolved "https://registry.yarnpkg.com/gatsby-plugin-manifest/-/gatsby-plugin-manifest-2.4.27.tgz#e87102137efcb1fe66ab27f913241f9c1b2f4fa7" + integrity sha512-QyU6cAXLPaGsOhmuMywLyoo4EdraoLmGOPDht64+jpJu0sJ4P7XF4Ykai8D18JWhxoxEPw76hCYs4rxNUJpNfg== dependencies: "@babel/runtime" "^7.10.3" - gatsby-core-utils "^1.3.15" + gatsby-core-utils "^1.3.18" semver "^7.3.2" - sharp "^0.25.1" + sharp "^0.25.4" -gatsby-plugin-matomo@^0.8.3: +gatsby-plugin-matomo@0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/gatsby-plugin-matomo/-/gatsby-plugin-matomo-0.8.3.tgz#e0e9cc9e60f7e4b157c9964dfc9d444d73bc46ee" integrity sha512-fv6TgD+WsxziZrtmz6sNF4m9FgSyV+8y3R1sobA5hB5OxJyhs/Y4HVo9jCPRHu5VLKQsg4i7LJhWL0ocJiqEWQ== -gatsby-plugin-page-creator@^2.3.22: - version "2.3.22" - resolved "https://registry.yarnpkg.com/gatsby-plugin-page-creator/-/gatsby-plugin-page-creator-2.3.22.tgz#8e4427b09beee321be0a1f9bf7d9f4e1b9008d06" - integrity sha512-XG3uZh/1uqsT/cpp/Oy7l15MR3yF6RqG/Mf4Vk0iYRZn6poveIh8Pw4nhPekwbrn8TGT7Fp/dv1Npkvs/E2kqw== +gatsby-plugin-page-creator@^2.3.25: + version "2.3.25" + resolved "https://registry.yarnpkg.com/gatsby-plugin-page-creator/-/gatsby-plugin-page-creator-2.3.25.tgz#74087a71e1c8ff5e072fbc5355e3cdb6ba669cd5" + integrity sha512-zpVFNKDNMpvTwe/hj6C27sc/POVxxGp0ZidoTDFd6so/f+Mc0OJQQDEIzs122oYBnuspPya+0+wWaph4QcadSQ== dependencies: "@babel/traverse" "^7.10.2" fs-exists-cached "^1.0.0" - gatsby-page-utils "^0.2.20" + gatsby-page-utils "^0.2.23" globby "^11.0.1" graphql "^14.6.0" lodash "^4.17.15" slugify "^1.4.4" -gatsby-plugin-react-helmet@^3.3.10: +gatsby-plugin-react-helmet@3.3.10: version "3.3.10" resolved "https://registry.yarnpkg.com/gatsby-plugin-react-helmet/-/gatsby-plugin-react-helmet-3.3.10.tgz#ba2f84715cc2471606b90327c7c3ba11c5287bc7" integrity sha512-AcXYwmS3r298JWs6iQ3OLNxIe8L8i5a2iSdLr/SDMpHqumYm7q/vB9kCX0et5wM7DIuZ7aPXDrdi5yDCAvU5lg== dependencies: "@babel/runtime" "^7.10.3" -gatsby-plugin-remove-serviceworker@^1.0.0: +gatsby-plugin-remove-serviceworker@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gatsby-plugin-remove-serviceworker/-/gatsby-plugin-remove-serviceworker-1.0.0.tgz#9fb433bc8bd766e14e1d3711c4ac6f051e1dff7c" integrity sha1-n7QzvIvXZuFOHTcRxKxvBR4d/3w= -gatsby-plugin-robots-txt@^1.5.1: +gatsby-plugin-robots-txt@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/gatsby-plugin-robots-txt/-/gatsby-plugin-robots-txt-1.5.1.tgz#aea69ba1298f76e907cfcb8c1dfde996e5efff79" integrity sha512-hkCmoIgoCmW49GFeql8RLNIh9RsG7RosHm+wNA//oFdJSzaYX1VVXk3OV0O1+35xspovP14Kbo+U7x39nu2emA== @@ -6801,7 +6856,7 @@ gatsby-plugin-robots-txt@^1.5.1: "@babel/runtime" "^7.10.0" generate-robotstxt "^8.0.3" -gatsby-plugin-sass@^2.3.12: +gatsby-plugin-sass@2.3.12: version "2.3.12" resolved "https://registry.yarnpkg.com/gatsby-plugin-sass/-/gatsby-plugin-sass-2.3.12.tgz#4ebdf2d541004e60a5d108eb1302a43b16ceeeaf" integrity sha512-cQHp4bvK3a0xId4Q9K9/1ejGVMMOm/1I28ry7quVoHVomSB4SwNJpMTGSgSYAKn3gjsveUyL+ceCRWeiIavkPA== @@ -6809,29 +6864,29 @@ gatsby-plugin-sass@^2.3.12: "@babel/runtime" "^7.10.3" sass-loader "^7.3.1" -gatsby-plugin-sharp@^2.6.27: - version "2.6.27" - resolved "https://registry.yarnpkg.com/gatsby-plugin-sharp/-/gatsby-plugin-sharp-2.6.27.tgz#cfc66b5c465eabce0388f6b60fd942fc0198e495" - integrity sha512-uWvzxLFAXRF4n8BIa37cIYKvc+gcTJ8CmZFYlhb5daEOd545Z0Elq/mQdOAWKL14cA7AGkEdtnsodXde2gBafA== +gatsby-plugin-sharp@2.6.31: + version "2.6.31" + resolved "https://registry.yarnpkg.com/gatsby-plugin-sharp/-/gatsby-plugin-sharp-2.6.31.tgz#4e324a694f7fc9cb4053c096552a1276c9996897" + integrity sha512-TUGFlkgGwtxcBP1UQG+QNd8ipeclefMmpEC8k3/3z4r15aV7d83/CrgByFjWLalY8esHF9DiZIyR7/kYoQ8/PQ== dependencies: "@babel/runtime" "^7.10.3" - async "^2.6.3" + async "^3.2.0" bluebird "^3.7.2" - fs-extra "^8.1.0" - gatsby-core-utils "^1.3.15" - got "^8.3.2" - imagemin "^6.1.0" - imagemin-mozjpeg "^8.0.0" - imagemin-pngquant "^6.0.1" - lodash "^4.17.15" + fs-extra "^9.0.1" + gatsby-core-utils "^1.3.18" + got "^10.7.0" + imagemin "^7.0.1" + imagemin-mozjpeg "^9.0.0" + imagemin-pngquant "^9.0.0" + lodash "^4.17.19" mini-svg-data-uri "^1.2.3" potrace "^2.1.8" - probe-image-size "^4.1.1" + probe-image-size "^5.0.0" progress "^2.0.3" semver "^7.3.2" - sharp "^0.25.1" + sharp "^0.25.4" svgo "1.3.2" - uuid "^3.4.0" + uuid "^8.3.0" gatsby-plugin-typescript@^2.4.18: version "2.4.18" @@ -6853,10 +6908,10 @@ gatsby-react-router-scroll@^3.0.12: dependencies: "@babel/runtime" "^7.10.3" -gatsby-recipes@^0.2.16: - version "0.2.16" - resolved "https://registry.yarnpkg.com/gatsby-recipes/-/gatsby-recipes-0.2.16.tgz#ad59cc82275b19fe5d9697037cfaf1a8cb19ce88" - integrity sha512-Aq3zeg0kmzKlqiQWoONMz3cf/QdP/AjUEGNdUhEKyvwgd0d7K9may99ltrzcssLfhkLtv/+aPJllhQG//RQxqQ== +gatsby-recipes@^0.2.20: + version "0.2.20" + resolved "https://registry.yarnpkg.com/gatsby-recipes/-/gatsby-recipes-0.2.20.tgz#66bd9fb0064a973b2122443367ae64419e0d3ac9" + integrity sha512-0CjII9YZU0JpLWovFAJwctBcOI/tcTi5N6AS7HYUwzwYs/Ivb3en99NqOnT61m7i50wgWJmfo+Fo4Df3+vloug== dependencies: "@babel/core" "^7.9.6" "@babel/generator" "^7.9.6" @@ -6880,7 +6935,7 @@ gatsby-recipes@^0.2.16: ansi-html "^0.0.7" babel-plugin-remove-export-keywords "^1.6.5" better-queue "^3.8.10" - chokidar "3.4.0" + chokidar "^3.4.2" concurrently "^5.0.0" contentful-management "^5.26.3" cors "^2.8.5" @@ -6893,9 +6948,9 @@ gatsby-recipes@^0.2.16: flatted "^3.0.0" formik "^2.0.8" fs-extra "^8.1.0" - gatsby-core-utils "^1.3.15" + gatsby-core-utils "^1.3.18" gatsby-interface "^0.0.166" - gatsby-telemetry "^1.3.27" + gatsby-telemetry "^1.3.30" glob "^7.1.6" graphql "^14.6.0" graphql-compose "^6.3.8" @@ -6936,24 +6991,24 @@ gatsby-recipes@^0.2.16: unist-util-remove "^2.0.0" unist-util-visit "^2.0.2" urql "^1.9.7" - uuid "^8.2.0" + uuid "^8.3.0" ws "^7.3.0" xstate "^4.9.1" yoga-layout-prebuilt "^1.9.6" yup "^0.27.0" -gatsby-source-filesystem@^2.3.24: - version "2.3.24" - resolved "https://registry.yarnpkg.com/gatsby-source-filesystem/-/gatsby-source-filesystem-2.3.24.tgz#857932fb91cba876ff1e48172103ead66cf2b0fe" - integrity sha512-TiuuV7sczagVOKW94dfx1AkW/wfe678UOdBAJrMxA2wZvuTe/gXz4Vg4F+EJIoZ8pyy8BjQbclmqXEnGX4eYKw== +gatsby-source-filesystem@2.3.27: + version "2.3.27" + resolved "https://registry.yarnpkg.com/gatsby-source-filesystem/-/gatsby-source-filesystem-2.3.27.tgz#e575b992d877a5ddc1fe6177567ab5c268374ca7" + integrity sha512-lNWRVDkaC2g6mSPTGuE9bsXawS0GkkwV/X8l8ZJnqbcMBl8p+h3zYoKXQ2u00pmQRqjwp4lvlaTarLRxD0tGDQ== dependencies: "@babel/runtime" "^7.10.3" better-queue "^3.8.10" bluebird "^3.7.2" - chokidar "3.4.0" + chokidar "^3.4.2" file-type "^12.4.2" fs-extra "^8.1.0" - gatsby-core-utils "^1.3.15" + gatsby-core-utils "^1.3.18" got "^9.6.0" md5-file "^3.2.3" mime "^2.4.6" @@ -6963,54 +7018,55 @@ gatsby-source-filesystem@^2.3.24: valid-url "^1.0.9" xstate "^4.11.0" -gatsby-telemetry@^1.3.27: - version "1.3.27" - resolved "https://registry.yarnpkg.com/gatsby-telemetry/-/gatsby-telemetry-1.3.27.tgz#8e5bfa3509bcc99b11ecd5b0ed2a89f3bdc61dbb" - integrity sha512-cX3+6dB3Tc6KYebYjVL0DGBvlnlJ43whmkVDKlcsSHyOKMkQBaCD4cKav3Im6iFa3jhmj5Z2MH20oPC26tHSTQ== +gatsby-telemetry@^1.3.30: + version "1.3.30" + resolved "https://registry.yarnpkg.com/gatsby-telemetry/-/gatsby-telemetry-1.3.30.tgz#dd169f8674017597907cad2ce95127af7a4d7465" + integrity sha512-2EJdu8f7CqLfENnShK1gSJdlxC/me6eImrbReYQDuf7Bu7l9UT5Ag07D1vC8qA58wjj+p9mhZqAL5pYCdQ04jA== dependencies: "@babel/code-frame" "^7.10.3" "@babel/runtime" "^7.10.3" - "@turist/fetch" "^7.1.6" + "@turist/fetch" "^7.1.7" "@turist/time" "^0.0.1" async-retry-ng "^2.0.1" boxen "^4.2.0" configstore "^5.0.1" - envinfo "^7.5.1" + envinfo "^7.7.3" fs-extra "^8.1.0" - gatsby-core-utils "^1.3.15" - git-up "4.0.1" - is-docker "2.0.0" + gatsby-core-utils "^1.3.18" + git-up "^4.0.2" + is-docker "^2.1.1" lodash "^4.17.15" - node-fetch "2.6.0" - uuid "3.4.0" + node-fetch "^2.6.0" + uuid "^8.3.0" -gatsby-transformer-sharp@^2.5.13: - version "2.5.13" - resolved "https://registry.yarnpkg.com/gatsby-transformer-sharp/-/gatsby-transformer-sharp-2.5.13.tgz#f323072d885c0fae54a55cb105f543d7c08d3a14" - integrity sha512-3jHVuD0SnOdG+6rk7HjUG1F1UPZZrz33196bDnbaR3YYRh8MMlLkoKH+2oZ/i9SLCxkU1jNBozMJzYMyonHZvg== +gatsby-transformer-sharp@2.5.14: + version "2.5.14" + resolved "https://registry.yarnpkg.com/gatsby-transformer-sharp/-/gatsby-transformer-sharp-2.5.14.tgz#8329d5c2fead279ff43d7a8c04fb003412b8d9be" + integrity sha512-CnbTKuxhFYgziTJEgTjW2tLr9AtYpZnhI8TsqFMRos6t1RABdBubzgi5IG0fUg5MpVpD1D6xeX6YaXQtERoPew== dependencies: "@babel/runtime" "^7.10.3" bluebird "^3.7.2" - fs-extra "^8.1.0" + fs-extra "^9.0.1" potrace "^2.1.8" - probe-image-size "^4.1.1" + probe-image-size "^5.0.0" semver "^7.3.2" - sharp "^0.25.1" + sharp "^0.25.4" -gatsby@^2.24.47: - version "2.24.47" - resolved "https://registry.yarnpkg.com/gatsby/-/gatsby-2.24.47.tgz#44f50af6304111c0e5b7f9e9b777103dc2245a93" - integrity sha512-+LLqdKqfVGpk0GyKMaWMnCqonVUyumg7a5fhODdZbDELmcNsQKtO5HShKs8ZbMm1PIIHewmU3uRlqRZygfAD6w== +gatsby@2.24.53: + version "2.24.53" + resolved "https://registry.yarnpkg.com/gatsby/-/gatsby-2.24.53.tgz#93c5e45bc188881c9adc9e44f693245e0e02ba22" + integrity sha512-RflNxycCFn+VoakexlMYQa5HmdW/iq/um5fQQVr/Ba6jhSDoD4+FSSW9Eh3w3xiG8YKcdjp20iMzREHlUtfN4g== dependencies: "@babel/code-frame" "^7.10.3" "@babel/core" "^7.10.3" "@babel/parser" "^7.10.3" "@babel/runtime" "^7.10.3" "@babel/traverse" "^7.10.3" + "@babel/types" "^7.10.3" "@hapi/joi" "^15.1.1" "@mikaelkristiansson/domready" "^1.0.10" "@pieh/friendly-errors-webpack-plugin" "1.7.0-chalk-2" - "@pmmmwh/react-refresh-webpack-plugin" "^0.3.3" + "@pmmmwh/react-refresh-webpack-plugin" "^0.4.1" "@reach/router" "^1.3.4" "@types/http-proxy" "^1.17.4" "@typescript-eslint/eslint-plugin" "^2.24.0" @@ -7024,7 +7080,7 @@ gatsby@^2.24.47: babel-plugin-add-module-exports "^0.3.3" babel-plugin-dynamic-import-node "^2.3.3" babel-plugin-remove-graphql-queries "^2.9.17" - babel-preset-gatsby "^0.5.5" + babel-preset-gatsby "^0.5.8" better-opn "1.0.0" better-queue "^3.8.10" bluebird "^3.7.2" @@ -7032,7 +7088,7 @@ gatsby@^2.24.47: cache-manager "^2.11.1" cache-manager-fs-hash "^0.0.9" chalk "^2.4.2" - chokidar "3.4.0" + chokidar "^3.4.2" common-tags "^1.8.0" compression "^1.7.4" convert-hrtime "^3.0.0" @@ -7044,7 +7100,7 @@ gatsby@^2.24.47: debug "^3.2.6" del "^5.1.0" detect-port "^1.3.0" - devcert "^1.1.0" + devcert "^1.1.3" dotenv "^8.2.0" eslint "^6.8.0" eslint-config-react-app "^5.2.1" @@ -7053,9 +7109,10 @@ gatsby@^2.24.47: eslint-plugin-graphql "^3.1.1" eslint-plugin-import "^2.22.0" eslint-plugin-jsx-a11y "^6.3.1" - eslint-plugin-react "^7.20.2" + eslint-plugin-react "^7.20.6" eslint-plugin-react-hooks "^1.7.0" event-source-polyfill "^1.0.15" + execa "^4.0.3" express "^4.17.1" express-graphql "^0.9.0" fast-levenshtein "^2.0.6" @@ -7063,15 +7120,15 @@ gatsby@^2.24.47: find-cache-dir "^3.3.1" fs-exists-cached "1.0.0" fs-extra "^8.1.0" - gatsby-cli "^2.12.87" - gatsby-core-utils "^1.3.15" - gatsby-graphiql-explorer "^0.4.12" - gatsby-legacy-polyfills "^0.0.2" + gatsby-cli "^2.12.91" + gatsby-core-utils "^1.3.18" + gatsby-graphiql-explorer "^0.4.13" + gatsby-legacy-polyfills "^0.0.4" gatsby-link "^2.4.13" - gatsby-plugin-page-creator "^2.3.22" + gatsby-plugin-page-creator "^2.3.25" gatsby-plugin-typescript "^2.4.18" gatsby-react-router-scroll "^3.0.12" - gatsby-telemetry "^1.3.27" + gatsby-telemetry "^1.3.30" glob "^7.1.6" got "8.3.2" graphql "^14.6.0" @@ -7133,9 +7190,9 @@ gatsby@^2.24.47: type-of "^2.0.1" url-loader "^1.1.2" util.promisify "^1.0.1" - uuid "^3.4.0" + uuid "^8.3.0" v8-compile-cache "^1.1.2" - webpack "~4.43.0" + webpack "^4.44.1" webpack-dev-middleware "^3.7.2" webpack-dev-server "^3.11.0" webpack-hot-middleware "^2.25.0" @@ -7183,6 +7240,11 @@ gensync@^1.0.0-beta.1: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -7274,10 +7336,10 @@ gifwrap@^0.9.2: image-q "^1.1.1" omggif "^1.0.10" -git-up@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.1.tgz#cb2ef086653640e721d2042fe3104857d89007c0" - integrity sha512-LFTZZrBlrCrGCG07/dm1aCjjpL1z9L3+5aEeI9SBhAqSc+kiA9Or1bgZhQFNppJX6h/f5McrvJt1mQXTFm6Qrw== +git-up@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.2.tgz#10c3d731051b366dc19d3df454bfca3f77913a7c" + integrity sha512-kbuvus1dWQB2sSW4cbfTeGpCMd8ge9jx9RKnhXhuJ7tnvT+NIrTVfYZxjtflZddQYcmdOTlkAcjmx7bor+15AQ== dependencies: is-ssh "^1.3.0" parse-url "^5.0.0" @@ -7302,11 +7364,6 @@ glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" -glob-to-regexp@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= - glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -7374,7 +7431,7 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -globby@^10.0.1: +globby@^10.0.0, globby@^10.0.1: version "10.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== @@ -7411,19 +7468,6 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" -globby@^8.0.1: - version "8.0.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" - integrity sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w== - dependencies: - array-union "^1.0.1" - dir-glob "2.0.0" - fast-glob "^2.0.2" - glob "^7.1.2" - ignore "^3.3.5" - pify "^3.0.0" - slash "^1.0.0" - globule@^1.0.0: version "1.3.2" resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4" @@ -7440,7 +7484,7 @@ good-listener@^1.2.2: dependencies: delegate "^3.1.2" -got@8.3.2, got@^8.3.1, got@^8.3.2: +got@8.3.2, got@^8.3.1: version "8.3.2" resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" integrity sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw== @@ -7463,6 +7507,27 @@ got@8.3.2, got@^8.3.1, got@^8.3.2: url-parse-lax "^3.0.0" url-to-options "^1.0.1" +got@^10.7.0: + version "10.7.0" + resolved "https://registry.yarnpkg.com/got/-/got-10.7.0.tgz#62889dbcd6cca32cd6a154cc2d0c6895121d091f" + integrity sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg== + dependencies: + "@sindresorhus/is" "^2.0.0" + "@szmarczak/http-timer" "^4.0.0" + "@types/cacheable-request" "^6.0.1" + cacheable-lookup "^2.0.0" + cacheable-request "^7.0.1" + decompress-response "^5.0.0" + duplexer3 "^0.1.4" + get-stream "^5.0.0" + lowercase-keys "^2.0.0" + mimic-response "^2.1.0" + p-cancelable "^2.0.0" + p-event "^4.0.0" + responselike "^2.0.0" + to-readable-stream "^2.0.0" + type-fest "^0.10.0" + got@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" @@ -8023,7 +8088,12 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -http-status-codes@^2.1.1, http-status-codes@^2.1.2: +http-status-codes@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-2.1.1.tgz#1e8fc7358055135518c1dced00362fd3c1f4f606" + integrity sha512-MPKYOEXZw8MzXml8XF8UBWzWGuO60ZKXBDCGwxPJmRZJW3eTUsLgB+O+jtlPB8ZOVSUs1vjcrxtitJghYzxtHQ== + +http-status-codes@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-2.1.2.tgz#dc5b7ccd72fb383d1d7c21adbbddc3b125f6a5b7" integrity sha512-zpZ1nBcoR0j1FLQ7xbXXBy1z/yUfAi+0a5IZBoZnmOseYkaljdzQ17ZeVXFlK23IbLxMJn6aWI0uU92DQQrG0g== @@ -8038,7 +8108,7 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -husky@^4.2.5: +husky@4.2.5: version "4.2.5" resolved "https://registry.yarnpkg.com/husky/-/husky-4.2.5.tgz#2b4f7622673a71579f901d9885ed448394b5fa36" integrity sha512-SYZ95AjKcX7goYVZtVZF2i6XiZcHknw50iXvY7b0MiGoj5RwdgRQNEHdb+gPDPCXKlzwrybjFjkL6FOj8uRhZQ== @@ -8090,11 +8160,6 @@ iferr@^0.1.5: resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= -ignore@^3.3.5: - version "3.3.10" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== - ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -8110,35 +8175,37 @@ image-q@^1.1.1: resolved "https://registry.yarnpkg.com/image-q/-/image-q-1.1.1.tgz#fc84099664460b90ca862d9300b6bfbbbfbf8056" integrity sha1-/IQJlmRGC5DKhi2TALa/u7+/gFY= -imagemin-mozjpeg@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/imagemin-mozjpeg/-/imagemin-mozjpeg-8.0.0.tgz#d2ca4e8c982c7c6eda55069af89dee4c1cebcdfd" - integrity sha512-+EciPiIjCb8JWjQNr1q8sYWYf7GDCNDxPYnkD11TNIjjWNzaV+oTg4DpOPQjl5ZX/KRCPMEgS79zLYAQzLitIA== +imagemin-mozjpeg@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/imagemin-mozjpeg/-/imagemin-mozjpeg-9.0.0.tgz#d1af26d0b43d75a41c211051c1910da59d9d2324" + integrity sha512-TwOjTzYqCFRgROTWpVSt5UTT0JeCuzF1jswPLKALDd89+PmrJ2PdMMYeDLYZ1fs9cTovI9GJd68mRSnuVt691w== dependencies: - execa "^1.0.0" + execa "^4.0.0" is-jpg "^2.0.0" - mozjpeg "^6.0.0" + mozjpeg "^7.0.0" -imagemin-pngquant@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/imagemin-pngquant/-/imagemin-pngquant-6.0.1.tgz#07b4c80e327ac60ef5246758029b1e8aecd879b9" - integrity sha512-Stk+fZCLxZznV8MFNA/T3AY/VRKevsiP9uZOLV0RCXoi0vUUFriySYuz/83IGp9D254EW8miGyyQ69zKouFr7w== +imagemin-pngquant@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/imagemin-pngquant/-/imagemin-pngquant-9.0.0.tgz#f22ba4276cde1799fb15dd475e33984f8607e871" + integrity sha512-9cqnTEaJwAHWUi+8EMTB3NUouWToCWxtL+QnoYr8bfVwuKilHvRVWKsa9lt+0c3aWaGxCAkHs++j8qINvSqomA== dependencies: - execa "^0.10.0" - is-png "^1.0.0" - is-stream "^1.1.0" - pngquant-bin "^5.0.0" + execa "^4.0.0" + is-png "^2.0.0" + is-stream "^2.0.0" + ow "^0.17.0" + pngquant-bin "^6.0.0" -imagemin@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/imagemin/-/imagemin-6.1.0.tgz#62508b465728fea36c03cdc07d915fe2d8cf9e13" - integrity sha512-8ryJBL1CN5uSHpiBMX0rJw79C9F9aJqMnjGnrd/1CafegpNuA81RBAAru/jQQEOWlOJJlpRnlcVFF6wq+Ist0A== +imagemin@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/imagemin/-/imagemin-7.0.1.tgz#f6441ca647197632e23db7d971fffbd530c87dbf" + integrity sha512-33AmZ+xjZhg2JMCe+vDf6a9mzWukE7l+wAtesjE7KyteqqKjzxv7aVQeWnul1Ve26mWvEQqyPwl0OctNBfSR9w== dependencies: - file-type "^10.7.0" - globby "^8.0.1" - make-dir "^1.0.0" - p-pipe "^1.1.0" - pify "^4.0.1" + file-type "^12.0.0" + globby "^10.0.0" + graceful-fs "^4.2.2" + junk "^3.1.0" + make-dir "^3.0.0" + p-pipe "^3.0.0" replace-ext "^1.0.0" import-cwd@^2.0.0: @@ -8156,7 +8223,7 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" -import-fresh@^3.0.0, import-fresh@^3.1.0: +import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== @@ -8375,6 +8442,11 @@ invariant@^2.2.0, invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4: dependencies: loose-envify "^1.0.0" +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -8554,11 +8626,16 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= -is-docker@2.0.0, is-docker@^2.0.0: +is-docker@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== +is-docker@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" + integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -8683,7 +8760,7 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^1.0.0, is-obj@^1.0.1: +is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= @@ -8746,10 +8823,10 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-png@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-png/-/is-png-1.1.0.tgz#d574b12bf275c0350455570b0e5b57ab062077ce" - integrity sha1-1XSxK/J1wDUEVVcLDltXqwYgd84= +is-png@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-png/-/is-png-2.0.0.tgz#ee8cbc9e9b050425cedeeb4a6fb74a649b0a4a8d" + integrity sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g== is-promise@^2.1.0: version "2.2.2" @@ -9034,6 +9111,11 @@ json-buffer@3.0.0: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-loader@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" @@ -9104,7 +9186,7 @@ jsonify@~0.0.0: resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= -jsonp@^0.2.1: +jsonp@0.2.1, jsonp@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/jsonp/-/jsonp-0.2.1.tgz#a65b4fa0f10bda719a05441ea7b94c55f3e15bae" integrity sha1-pltPoPEL2nGaBUQep7lMVfPhW64= @@ -9129,6 +9211,11 @@ jsx-ast-utils@^2.4.1: array-includes "^3.1.1" object.assign "^4.1.0" +junk@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" + integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== + keyv@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" @@ -9143,6 +9230,13 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" +keyv@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.1.tgz#9fe703cb4a94d6d11729d320af033307efd02ee6" + integrity sha512-xz6Jv6oNkbhrFCvCP7HQa8AaII8y8LRpoSm661NOKLr4uHuBwhX4epXrPQgF3+xdJnN4Esm5X0xwY4bOlALOtw== + dependencies: + json-buffer "3.0.1" + killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -9209,6 +9303,13 @@ lazy-ass@^1.6.0: resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -9242,20 +9343,20 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= -lint-staged@^10.2.11: - version "10.2.11" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.2.11.tgz#713c80877f2dc8b609b05bc59020234e766c9720" - integrity sha512-LRRrSogzbixYaZItE2APaS4l2eJMjjf5MbclRZpLJtcQJShcvUzKXsNeZgsLIZ0H0+fg2tL4B59fU9wHIHtFIA== +lint-staged@10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.3.0.tgz#388c3d440590c45c339e7163f669ea69ae90b1e0" + integrity sha512-an3VgjHqmJk0TORB/sdQl0CTkRg4E5ybYCXTTCSJ5h9jFwZbcgKIx5oVma5e7wp/uKt17s1QYFmYqT9MGVosGw== dependencies: - chalk "^4.0.0" - cli-truncate "2.1.0" - commander "^5.1.0" - cosmiconfig "^6.0.0" + chalk "^4.1.0" + cli-truncate "^2.1.0" + commander "^6.0.0" + cosmiconfig "^7.0.0" debug "^4.1.1" dedent "^0.7.0" - enquirer "^2.3.5" - execa "^4.0.1" - listr2 "^2.1.0" + enquirer "^2.3.6" + execa "^4.0.3" + listr2 "^2.6.0" log-symbols "^4.0.0" micromatch "^4.0.2" normalize-path "^3.0.0" @@ -9292,10 +9393,10 @@ listr-verbose-renderer@^0.5.0: date-fns "^1.27.2" figures "^2.0.0" -listr2@^2.1.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-2.4.1.tgz#006fc94ae77b3195403cbf3a4a563e2d6366224f" - integrity sha512-8pYsCZCztr5+KAjReLyBeGhLV0vaQ2Du/eMe/ux9QAfQl7efiWejM1IWjALh0zHIRYuIbhQ8N2KztZ4ci56pnQ== +listr2@^2.6.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-2.6.2.tgz#4912eb01e1e2dd72ec37f3895a56bf2622d6f36a" + integrity sha512-6x6pKEMs8DSIpA/tixiYY2m/GcbgMplMVmhQAaLFxEtNSKLeWTGjtmU57xvv6QCm2XcqzyNXL/cTSVf4IChCRA== dependencies: chalk "^4.1.0" cli-truncate "^2.1.0" @@ -9303,7 +9404,7 @@ listr2@^2.1.0: indent-string "^4.0.0" log-update "^4.0.0" p-map "^4.0.0" - rxjs "^6.6.0" + rxjs "^6.6.2" through "^2.3.8" listr@^0.14.3: @@ -9423,11 +9524,6 @@ lodash.clonedeep@4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - lodash.every@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.every/-/lodash.every-4.6.0.tgz#eb89984bebc4364279bb3aefbbd1ca19bfa6c6a7" @@ -9947,7 +10043,7 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== -mimic-response@^2.0.0: +mimic-response@^2.0.0, mimic-response@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== @@ -10112,10 +10208,10 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" -mozjpeg@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/mozjpeg/-/mozjpeg-6.0.1.tgz#56969dddb5741ef2bcb1af066cae21e61a91a27b" - integrity sha512-9Z59pJMi8ni+IUvSH5xQwK5tNLw7p3dwDNCZ3o1xE+of3G5Hc/yOz6Ue/YuLiBXU3ZB5oaHPURyPdqfBX/QYJA== +mozjpeg@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/mozjpeg/-/mozjpeg-7.0.0.tgz#c20f67a538fcaaa388d325875c53c0e7bc432f7d" + integrity sha512-mH7atSbIusVTO3A4H43sEdmveN3aWn54k6V0edefzCEvOsTrbjg5murY2TsNznaztWnIgaRbWxeLVp4IgKdedQ== dependencies: bin-build "^3.0.0" bin-wrapper "^4.0.0" @@ -10267,11 +10363,6 @@ node-fetch@2.1.2: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U= -node-fetch@2.6.0, node-fetch@^2.5.0, node-fetch@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" - integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== - node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -10280,6 +10371,11 @@ node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" +node-fetch@^2.5.0, node-fetch@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" + integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== + node-forge@0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" @@ -10342,10 +10438,10 @@ node-releases@^1.1.58: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== -node-sass@^4.14.0: - version "4.14.1" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5" - integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g== +node-sass@4.14.0: + version "4.14.0" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.0.tgz#a8e9d7720f8e15b4a1072719dcf04006f5648eeb" + integrity sha512-AxqU+DFpk0lEz95sI6jO0hU0Rwyw7BXVEv6o9OItoXLyeygPeaSpiV4rwQb10JiTghHaa0gZeD21sz+OsQluaw== dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -10361,7 +10457,7 @@ node-sass@^4.14.0: node-gyp "^3.8.0" npmlog "^4.0.0" request "^2.88.0" - sass-graph "2.2.5" + sass-graph "^2.2.4" stdout-stream "^1.4.0" "true-case-path" "^1.0.2" @@ -10770,6 +10866,13 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= + dependencies: + lcid "^1.0.0" + os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -10788,6 +10891,13 @@ ospath@^1.2.2: resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= +ow@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/ow/-/ow-0.17.0.tgz#4f938999fed6264c9048cd6254356e0f1e7f688c" + integrity sha512-i3keDzDQP5lWIe4oODyDFey1qVrq2hXKTuTH2VpqwpYtzPiKZt2ziRI4NBQmgW40AnV5Euz17OyWweCb+bNEQA== + dependencies: + type-fest "^0.11.0" + p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" @@ -10803,6 +10913,11 @@ p-cancelable@^1.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== +p-cancelable@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e" + integrity sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg== + p-defer@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-3.0.0.tgz#d1dceb4ee9b2b604b1d94ffec83760175d4e6f83" @@ -10822,6 +10937,13 @@ p-event@^2.1.0: dependencies: p-timeout "^2.0.1" +p-event@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" + integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== + dependencies: + p-timeout "^3.1.0" + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -10898,10 +11020,10 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -p-pipe@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9" - integrity sha1-SxoROZoRUgpneQ7loMHViB1r7+k= +p-pipe@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.1.0.tgz#48b57c922aa2e1af6a6404cb7c6bf0eb9cc8e60e" + integrity sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw== p-reduce@^1.0.0: version "1.0.0" @@ -10929,6 +11051,13 @@ p-timeout@^2.0.1: dependencies: p-finally "^1.0.0" +p-timeout@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" + integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== + dependencies: + p-finally "^1.0.0" + p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -11127,7 +11256,7 @@ path-browserify@0.0.1: resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== -path-browserify@^1.0.1: +path-browserify@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== @@ -11200,13 +11329,6 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -11322,14 +11444,14 @@ pngjs@^3.0.0, pngjs@^3.3.3: resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== -pngquant-bin@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/pngquant-bin/-/pngquant-bin-5.0.2.tgz#6f34f3e89c9722a72bbc509062b40f1b17cda460" - integrity sha512-OLdT+4JZx5BqE1CFJkrvomYV0aSsv6x2Bba+aWaVc0PMfWlE+ZByNKYAdKeIqsM4uvW1HOSEHnf8KcOnykPNxA== +pngquant-bin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/pngquant-bin/-/pngquant-bin-6.0.0.tgz#aff0d7e61095feb96ced379ad8c7294ad3dd1712" + integrity sha512-oXWAS9MQ9iiDAJRdAZ9KO1mC5UwhzKkJsmetiu0iqIjJuW7JsuLhmc4JdRm7uJkIWRzIAou/Vq2VcjfJwz30Ow== dependencies: bin-build "^3.0.0" bin-wrapper "^4.0.1" - execa "^0.10.0" + execa "^4.0.0" logalot "^2.0.0" pnp-webpack-plugin@^1.6.4: @@ -11750,6 +11872,11 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= +prettier@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.1.tgz#d9485dd5e499daa6cb547023b87a6cf51bee37d6" + integrity sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw== + prettier@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" @@ -11785,12 +11912,11 @@ prismjs@^1.21.0, prismjs@~1.21.0: optionalDependencies: clipboard "^2.0.0" -probe-image-size@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/probe-image-size/-/probe-image-size-4.1.1.tgz#c836c53154b6dd04dbcf66af2bbd50087b15e1dc" - integrity sha512-42LqKZqTLxH/UvAZ2/cKhAsR4G/Y6B7i7fI2qtQu9hRBK4YjS6gqO+QRtwTjvojUx4+/+JuOMzLoFyRecT9qRw== +probe-image-size@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/probe-image-size/-/probe-image-size-5.0.0.tgz#1b87d20340ab8fcdb4324ec77fbc8a5f53419878" + integrity sha512-V6uBYw5eBc5UVIE7MUZD6Nxg0RYuGDWLDenEn0B1WC6PcTvn1xdQ6HLDDuznefsiExC6rNrCz7mFRBo0f3Xekg== dependencies: - any-promise "^1.3.0" deepmerge "^4.0.0" inherits "^2.0.3" next-tick "^1.0.0" @@ -11830,7 +11956,7 @@ prompts@^2.3.2: kleur "^3.0.3" sisteransi "^1.0.4" -prop-types@^15.5.10, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -12090,7 +12216,7 @@ react-clientside-effect@^1.2.2: dependencies: "@babel/runtime" "^7.0.0" -react-countup@^4.3.3: +react-countup@4.3.3: version "4.3.3" resolved "https://registry.yarnpkg.com/react-countup/-/react-countup-4.3.3.tgz#143a8d854d47290b73d6915eac20a12d839153c2" integrity sha512-pWnxpwdPNRyJFha/YKKbyc4RLAw8PzmULdgCziGIgw6vxhT1VdccrvQgj38HBSoM2qF/MoLmn4M2klvDWVIdaw== @@ -12123,7 +12249,7 @@ react-dev-utils@^4.2.3: strip-ansi "3.0.1" text-table "0.2.0" -react-dom@^16.13.1: +react-dom@16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== @@ -12133,10 +12259,10 @@ react-dom@^16.13.1: prop-types "^15.6.2" scheduler "^0.19.1" -react-dropzone@^11.0.2: - version "11.0.2" - resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-11.0.2.tgz#1a4084f520c2eafbeb24026760b3ee8f3759cfd3" - integrity sha512-/Wde9Il1aJ1FtWllg3N2taIeJh4aftx6UGUG8R1TmLnZit2RnDcEjcKwEEbKwgLXTTh8QQpiZWQJq45jTy1jCA== +react-dropzone@11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-11.0.3.tgz#59c396a1482454fa78466f8565336f40ce7f7c84" + integrity sha512-+MoMOoKZfkZ9i1+qEFl2ZU29AB/c9K2bFxyACqGynguJunmqO+k2PJ2AcuiH51xVNl9R7q/x5QdBaIWb6RtoSw== dependencies: attr-accept "^2.0.0" file-selector "^0.1.12" @@ -12169,7 +12295,7 @@ react-focus-lock@^2.3.1: use-callback-ref "^1.2.1" use-sidecar "^1.0.1" -react-helmet@^6.1.0: +react-helmet@6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726" integrity sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw== @@ -12210,14 +12336,14 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== -react-mailchimp-form@^1.0.2: +react-mailchimp-form@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/react-mailchimp-form/-/react-mailchimp-form-1.0.2.tgz#e4dfdc6a36bb2fb274ea49f2b19f9d54bbdfe65f" integrity sha512-G4eONuXCIiAbWw9xN5Klj38SekUV5R+crbF5+9kClDdONaz0XLbo+Nbg9kLH5zfMthyKVPKEgdosEjn/Wux8qA== dependencies: jsonp "^0.2.1" -react-mailchimp-subscribe@^2.1.0: +react-mailchimp-subscribe@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/react-mailchimp-subscribe/-/react-mailchimp-subscribe-2.1.0.tgz#a2bb7064af4bad310ef5d308322de95491d401c3" integrity sha512-sBB2XW0DPlysv+aVGRHbGQqDi8WITxXFjMzWiN07/t7U3FH2Io68EMBEU7atOUk5Y/WtsVnSytcs06aoEaf5ow== @@ -12270,7 +12396,7 @@ react-remove-scroll@^2.3.0: use-callback-ref "^1.2.3" use-sidecar "^1.0.1" -react-reveal@^1.2.2: +react-reveal@1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/react-reveal/-/react-reveal-1.2.2.tgz#f47fbc44debc4c185ae2163a215a9e822c7adfef" integrity sha512-JCv3fAoU6Z+Lcd8U48bwzm4pMZ79qsedSXYwpwt6lJNtj/v5nKJYZZbw3yhaQPPgYePo3Y0NOCoYOq/jcsisuw== @@ -12291,10 +12417,10 @@ react-style-singleton@^2.1.0: invariant "^2.2.4" tslib "^1.0.0" -react-syntax-highlighter@^13.5.0: - version "13.5.0" - resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-13.5.0.tgz#c0f3fd826a52b2a6ce5786d4ce60c3e0665b65c0" - integrity sha512-2nKo8spFxe9shcjbdUiqxkrf/IMDqKUZLx7JVIxEJ17P+fYFGL4CRsZZC66UPeQ2o/f29eKu31CrkKGCK1RHuA== +react-syntax-highlighter@13.5.1: + version "13.5.1" + resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-13.5.1.tgz#f21737cf6d582474a0f18b06b52613f4349c0e64" + integrity sha512-VVYTnFXF55WMRGdr3QNEzAzcypFZqH45kS7rqh90+AFeNGtui8/gV5AIOIJjwTsuP2UxcO9qvEq94Jq9BYFUhw== dependencies: "@babel/runtime" "^7.3.1" highlight.js "^10.1.1" @@ -12302,14 +12428,14 @@ react-syntax-highlighter@^13.5.0: prismjs "^1.21.0" refractor "^3.1.0" -react-visibility-sensor@^5.1.1: +react-visibility-sensor@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/react-visibility-sensor/-/react-visibility-sensor-5.1.1.tgz#5238380960d3a0b2be0b7faddff38541e337f5a9" integrity sha512-cTUHqIK+zDYpeK19rzW6zF9YfT4486TIgizZW53wEZ+/GPBbK7cNS0EHyJVyHYacwFEvvHLEKfgJndbemWhB/w== dependencies: prop-types "^15.7.2" -react@^16.13.1, react@^16.8.0: +react@16.13.1, react@^16.8.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== @@ -12759,6 +12885,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" @@ -12825,6 +12956,13 @@ responselike@1.0.2, responselike@^1.0.2: dependencies: lowercase-keys "^1.0.0" +responselike@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723" + integrity sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw== + dependencies: + lowercase-keys "^2.0.0" + restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -12939,7 +13077,7 @@ rxjs@^6.3.3, rxjs@^6.6.0: dependencies: tslib "^1.9.0" -rxjs@^6.5.2: +rxjs@^6.5.2, rxjs@^6.6.2: version "6.6.2" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== @@ -12968,15 +13106,15 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sass-graph@2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8" - integrity sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag== +sass-graph@^2.2.4: + version "2.2.6" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.6.tgz#09fda0e4287480e3e4967b72a2d133ba09b8d827" + integrity sha512-MKuEYXFSGuRSi8FZ3A7imN1CeVn9Gpw0/SFJKdL1ejXJneI9a5rwlEZrKejhEFAA3O6yr3eIyl/WuvASvlT36g== dependencies: glob "^7.0.0" lodash "^4.0.0" scss-tokenizer "^0.2.3" - yargs "^13.3.2" + yargs "^7.0.0" sass-loader@^7.3.1: version "7.3.1" @@ -13226,7 +13364,7 @@ shallowequal@^1.1.0: resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== -sharp@^0.25.1: +sharp@^0.25.4: version "0.25.4" resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.25.4.tgz#1a8e542144a07ab7e9316ab89de80182b827c363" integrity sha512-umSzJJ1oBwIOfwFFt/fJ7JgCva9FvrEU2cbbm7u/3hSDZhXvkME8WE5qpaJqLIe2Har5msF5UG4CzYlEg5o3BQ== @@ -13338,11 +13476,6 @@ skynet-js@0.0.8: axios "^0.19.2" url-parse "^1.4.7" -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -13825,7 +13958,7 @@ string-similarity@^1.2.2: lodash.map "^4.6.0" lodash.maxby "^4.6.0" -string-width@^1.0.1: +string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= @@ -14003,7 +14136,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.0.1, strip-json-comments@^3.1.0: +strip-json-comments@^3.0.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -14386,6 +14519,11 @@ to-readable-stream@^1.0.0: resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== +to-readable-stream@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-2.1.0.tgz#82880316121bea662cdc226adb30addb50cb06e8" + integrity sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w== + to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" @@ -14556,6 +14694,11 @@ type-fest@0.15.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.15.1.tgz#d2c4e73d3e4a53cf1a906396dd460a1c5178ca00" integrity sha512-n+UXrN8i5ioo7kqT/nF8xsEzLaqFra7k32SEsSPwvXVGyAcRgV/FUQN/sgfptJTR1oRmmq7z4IXMFSM7im7C9A== +type-fest@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.10.0.tgz#7f06b2b9fbfc581068d1341ffabd0349ceafc642" + integrity sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw== + type-fest@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" @@ -14606,7 +14749,7 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typeface-metropolis@^0.0.74: +typeface-metropolis@0.0.74: version "0.0.74" resolved "https://registry.yarnpkg.com/typeface-metropolis/-/typeface-metropolis-0.0.74.tgz#4201ff1e3b86f55825eed53662c49dff54c461f3" integrity sha512-8qJnWwD5GkFqoNkv0t068jXziJHoIayq7dNl9a0BRy30/VznqmEgrQWkMDG8KxH2hRXXAWZfayXM9L6sZEkaaw== @@ -14712,13 +14855,6 @@ unique-slug@^2.0.0: dependencies: imurmurhash "^0.1.4" -unique-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" - integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= - dependencies: - crypto-random-string "^1.0.0" - unique-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" @@ -14995,12 +15131,12 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@3.4.0, uuid@^3.0.0, uuid@^3.0.1, uuid@^3.3.2, uuid@^3.4.0: +uuid@^3.0.0, uuid@^3.0.1, uuid@^3.3.2, uuid@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^8.2.0: +uuid@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea" integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ== @@ -15095,7 +15231,7 @@ watchpack-chokidar2@^2.0.0: dependencies: chokidar "^2.1.8" -watchpack@^1.6.1: +watchpack@^1.7.4: version "1.7.4" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== @@ -15213,10 +15349,10 @@ webpack-virtual-modules@^0.2.2: dependencies: debug "^3.0.0" -webpack@~4.43.0: - version "4.43.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6" - integrity sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g== +webpack@^4.44.1: + version "4.44.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.1.tgz#17e69fff9f321b8f117d1fda714edfc0b939cc21" + integrity sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -15226,7 +15362,7 @@ webpack@~4.43.0: ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^4.1.0" + enhanced-resolve "^4.3.0" eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" loader-runner "^2.4.0" @@ -15239,7 +15375,7 @@ webpack@~4.43.0: schema-utils "^1.0.0" tapable "^1.1.3" terser-webpack-plugin "^1.4.3" - watchpack "^1.6.1" + watchpack "^1.7.4" webpack-sources "^1.4.1" websocket-driver@0.6.5: @@ -15273,6 +15409,11 @@ whatwg-fetch@>=0.10.0: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.0.tgz#e11de14f4878f773fbebcde8871b2c0699af8b30" integrity sha512-rsum2ulz2iuZH08mJkT0Yi6JnKhwdw4oeyMjokgxd+mmqYSd9cPpOQf01TIWgjxG/U4+QR+AwKq6lSbXVxkyoQ== +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" @@ -15344,6 +15485,14 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" @@ -15375,15 +15524,6 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^2.0.0: - version "2.4.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" - integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - write-file-atomic@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" @@ -15427,11 +15567,6 @@ ws@~6.1.0: dependencies: async-limiter "~1.0.0" -xdg-basedir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" - integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= - xdg-basedir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" @@ -15488,6 +15623,11 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= + y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" @@ -15516,11 +15656,19 @@ yaml-loader@^0.6.0: loader-utils "^1.4.0" yaml "^1.8.3" -yaml@^1.7.2, yaml@^1.8.3: +yaml@^1.10.0, yaml@^1.7.2, yaml@^1.8.3: version "1.10.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== +yargs-parser@5.0.0-security.0: + version "5.0.0-security.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz#4ff7271d25f90ac15643b86076a2ab499ec9ee24" + integrity sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ== + dependencies: + camelcase "^3.0.0" + object.assign "^4.1.0" + yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" @@ -15570,6 +15718,25 @@ yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yargs@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.1.tgz#67f0ef52e228d4ee0d6311acede8850f53464df6" + integrity sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g== + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "5.0.0-security.0" + yauzl@^2.10.0, yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" From e6a553ed75dc89d83a888b859d9ec8e2c5408acf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2020 17:27:43 +0000 Subject: [PATCH 07/44] Bump http-status-codes from 2.1.1 to 2.1.2 in /packages/webapp Bumps [http-status-codes](https://github.com/prettymuchbryce/node-http-status) from 2.1.1 to 2.1.2. - [Release notes](https://github.com/prettymuchbryce/node-http-status/releases) - [Commits](https://github.com/prettymuchbryce/node-http-status/compare/2.1.1...2.1.2) Signed-off-by: dependabot[bot] --- packages/webapp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/package.json b/packages/webapp/package.json index 401fe7cf..30322735 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -18,7 +18,7 @@ "gatsby-plugin-sharp": "2.6.31", "gatsby-source-filesystem": "2.3.27", "gatsby-transformer-sharp": "2.5.14", - "http-status-codes": "2.1.1", + "http-status-codes": "2.1.2", "jsonp": "0.2.1", "node-sass": "4.14.0", "path-browserify": "1.0.1", From a05355243689fc410180e70c0cb0a8d510eb1e46 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2020 17:28:14 +0000 Subject: [PATCH 08/44] Bump node-sass from 4.14.0 to 4.14.1 in /packages/webapp Bumps [node-sass](https://github.com/sass/node-sass) from 4.14.0 to 4.14.1. - [Release notes](https://github.com/sass/node-sass/releases) - [Changelog](https://github.com/sass/node-sass/blob/master/CHANGELOG.md) - [Commits](https://github.com/sass/node-sass/compare/v4.14.0...v4.14.1) Signed-off-by: dependabot[bot] --- packages/webapp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/package.json b/packages/webapp/package.json index 401fe7cf..e2d207b6 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -20,7 +20,7 @@ "gatsby-transformer-sharp": "2.5.14", "http-status-codes": "2.1.1", "jsonp": "0.2.1", - "node-sass": "4.14.0", + "node-sass": "4.14.1", "path-browserify": "1.0.1", "prop-types": "15.7.2", "react": "16.13.1", From 59a77bfaf6f4cd6781242ef18f9aece51fb03502 Mon Sep 17 00:00:00 2001 From: Ivaylo Novakov Date: Fri, 4 Sep 2020 16:12:20 +0200 Subject: [PATCH 09/44] Add a health checker script to Gollum. --- setup-scripts/funds-checker.py | 17 ++-- setup-scripts/health-checker.py | 102 ++++++++++++++++++++ setup-scripts/setup-health-check-scripts.sh | 9 +- 3 files changed, 115 insertions(+), 13 deletions(-) create mode 100755 setup-scripts/health-checker.py diff --git a/setup-scripts/funds-checker.py b/setup-scripts/funds-checker.py index 70d710ed..22a4810d 100755 --- a/setup-scripts/funds-checker.py +++ b/setup-scripts/funds-checker.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """ -health-checker runs simple health checks on a portal node using the siad API and +funds-checker runs simple checks on a portal node using the siad API and dispatches messages to a Discord channel. """ @@ -21,23 +21,22 @@ async def exit_after(delay): async def on_ready(): await run_checks() asyncio.create_task(exit_after(3)) - await client.close() async def run_checks(): - print("Running Skynet portal health checks") + print("Running Skynet portal funds checks") try: - await check_health() + await check_funds() except: # catch all exceptions trace = traceback.format_exc() await send_msg(client, "```\n{}\n```".format(trace), force_notify=True) -# check_health checks that the wallet is unlocked, that it has at least 1 -# allowance worth of money left, and if more than hald the allowance is spent. If -# all checks pass it sends a informational message. -async def check_health(): +# check_funds checks that the wallet is unlocked, that it has at least 1 +# allowance worth of money left, and if less than half the allowance is spent. +# If all checks pass it sends an informational message. +async def check_funds(): print("\nChecking wallet/funds health...") wallet_get = siad.get_wallet() renter_get = siad.get_renter() @@ -73,7 +72,7 @@ async def check_health(): return # Send an informational heartbeat if all checks passed. - await send_msg(client, "Health checks passed:\n{} \n{}".format(balance_msg, alloc_msg)) + await send_msg(client, "Funds checks passed:\n{} \n{}".format(balance_msg, alloc_msg)) client.run(bot_token) diff --git a/setup-scripts/health-checker.py b/setup-scripts/health-checker.py new file mode 100755 index 00000000..3047564c --- /dev/null +++ b/setup-scripts/health-checker.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +import discord, requests, traceback, asyncio, os, sys, json, io +from datetime import datetime, timedelta +from bot_utils import setup, send_msg, siad, sc_precision + +""" +health-checker reads the /health-check endpoint of the portal and dispatches +messages to a Discord channel. +""" + +# The default check interval in hours. +DEFAULT_CHECK_INTERVAL = 1 + +bot_token = setup() +client = discord.Client() + + +# get_hostname reads the HOSTNAME from the .env file passed as first argument +# to the script +async def get_hostname(): + if len(sys.argv) > 1: + env_file = sys.argv[1] + with open(env_file, 'r') as file: + for line in file.read().split('\n'): + pair = line.split("=") + if pair[0] == "HOSTNAME": + return pair[1] + await send_msg(client, "HOSTNAME not found, cannot check health status", force_notify=True) + os.exit(0) + + +# exit_after kills the script if it hasn't exited on its own after `delay` seconds +async def exit_after(delay): + await asyncio.sleep(delay) + os._exit(0) + + +@client.event +async def on_ready(): + await run_checks() + asyncio.create_task(exit_after(3)) + + +async def run_checks(): + print("Running Skynet portal health checks") + try: + await check_health() + except: # catch all exceptions + trace = traceback.format_exc() + print("[DEBUG] run_checks() failed.") + if len(trace) < 1900: + await send_msg(client, "```\n{}\n```".format(trace), force_notify=False) + else: + await send_msg(client, "Failed to run the checks!", file=discord.File(io.BytesIO(trace), filename="failed_checks.log"), force_notify=True) + + +# check_health checks /health-check endpoint and reports recent issues +async def check_health(): + print("\nChecking wallet/funds health...") + + try: + hostname = await get_hostname() + res = requests.get("http://"+hostname+"/health-check") + except: # catch all exceptions + trace = traceback.format_exc() + print("[DEBUG] check_health() failed.") + if len(trace) < 1900: + await send_msg(client, "```\n{}\n```".format(trace), force_notify=False) + else: + await send_msg(client, "Failed to run the checks!", file=discord.File(io.BytesIO(trace), filename="failed_checks.log"), force_notify=True) + return + + # Get the number of hours to look back in the logs or use 1 as default. + check_hours = DEFAULT_CHECK_INTERVAL + if len(sys.argv) > 3: + check_hours = int(sys.argv[3]) + + # Check the health records. + failed_checks = [] + passed_checks_counter = 0 + time_limit = datetime.now() - timedelta(hours=check_hours) + for rec in res.json(): + time = datetime.strptime(rec['date'], '%Y-%m-%dT%H:%M:%S.%fZ') + if time < time_limit: + continue + for check in rec['checks']: + if check['up'] == False: + # We append the entire record, so we can get the full context. + failed_checks.append(rec) + break + passed_checks_counter += 1 + + if len(failed_checks) > 0: + await send_msg(client, "Found {} failed checks over the last {} hours!".format(len(failed_checks), check_hours), file=discord.File(io.BytesIO(json.dumps(failed_checks, indent=2).encode()), filename="failed_checks.log"), force_notify=True) + return + + # Send an informational heartbeat if all checks passed. + await send_msg(client, "Health checks passed: {}\n".format(passed_checks_counter)) + + +client.run(bot_token) diff --git a/setup-scripts/setup-health-check-scripts.sh b/setup-scripts/setup-health-check-scripts.sh index 314a2170..7d17b85b 100755 --- a/setup-scripts/setup-health-check-scripts.sh +++ b/setup-scripts/setup-health-check-scripts.sh @@ -5,11 +5,12 @@ set -e # exit on first error sudo apt-get update sudo apt-get -y install python3-pip -pip3 install discord.py -pip3 install python-dotenv +pip3 install discord.py python-dotenv requests fundsCheck="0 0,8,16 * * * /home/user/skynet-webportal/setup-scripts/funds-checker.py /home/user/skynet-webportal/.env" logsCheck="0 0,8,16 * * * /home/user/skynet-webportal/setup-scripts/log-checker.py /home/user/skynet-webportal/.env sia 8" +healthCheck="0 * * * * /home/user/skynet-webportal/setup-scripts/health-checker.py /home/user/skynet-webportal/.env sia 1" -(crontab -u user -l; echo "$fundsCheck" ) | crontab -u user - -(crontab -u user -l; echo "$logsCheck" ) | crontab -u user - +(crontab -u user -l; echo "$fundsCheck" ) | crontab -u user - +(crontab -u user -l; echo "$logsCheck" ) | crontab -u user - +(crontab -u user -l; echo "$healthCheck" ) | crontab -u user - From 62e27120cdc96cfbb6e156bc3aa281d25db8b9b7 Mon Sep 17 00:00:00 2001 From: Ivaylo Novakov Date: Fri, 4 Sep 2020 16:39:39 +0200 Subject: [PATCH 10/44] Use localhost. --- setup-scripts/health-checker.py | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/setup-scripts/health-checker.py b/setup-scripts/health-checker.py index 3047564c..039c9410 100755 --- a/setup-scripts/health-checker.py +++ b/setup-scripts/health-checker.py @@ -16,20 +16,6 @@ bot_token = setup() client = discord.Client() -# get_hostname reads the HOSTNAME from the .env file passed as first argument -# to the script -async def get_hostname(): - if len(sys.argv) > 1: - env_file = sys.argv[1] - with open(env_file, 'r') as file: - for line in file.read().split('\n'): - pair = line.split("=") - if pair[0] == "HOSTNAME": - return pair[1] - await send_msg(client, "HOSTNAME not found, cannot check health status", force_notify=True) - os.exit(0) - - # exit_after kills the script if it hasn't exited on its own after `delay` seconds async def exit_after(delay): await asyncio.sleep(delay) @@ -52,7 +38,7 @@ async def run_checks(): if len(trace) < 1900: await send_msg(client, "```\n{}\n```".format(trace), force_notify=False) else: - await send_msg(client, "Failed to run the checks!", file=discord.File(io.BytesIO(trace), filename="failed_checks.log"), force_notify=True) + await send_msg(client, "Failed to run the checks!", file=discord.File(io.BytesIO(trace.encode()), filename="failed_checks.log"), force_notify=True) # check_health checks /health-check endpoint and reports recent issues @@ -60,15 +46,14 @@ async def check_health(): print("\nChecking wallet/funds health...") try: - hostname = await get_hostname() - res = requests.get("http://"+hostname+"/health-check") + res = requests.get("http://localhost/health-check", verify=False) except: # catch all exceptions trace = traceback.format_exc() print("[DEBUG] check_health() failed.") if len(trace) < 1900: await send_msg(client, "```\n{}\n```".format(trace), force_notify=False) else: - await send_msg(client, "Failed to run the checks!", file=discord.File(io.BytesIO(trace), filename="failed_checks.log"), force_notify=True) + await send_msg(client, "Failed to run the checks!", file=discord.File(io.BytesIO(trace.encode()), filename="failed_checks.log"), force_notify=True) return # Get the number of hours to look back in the logs or use 1 as default. From a0a9137ae70b3718c904dba7b3513f705af2f7e9 Mon Sep 17 00:00:00 2001 From: Ivaylo Novakov Date: Fri, 4 Sep 2020 16:44:19 +0200 Subject: [PATCH 11/44] Update setup-scripts/health-checker.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Karol Wypchło --- setup-scripts/health-checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup-scripts/health-checker.py b/setup-scripts/health-checker.py index 039c9410..d5b4c75a 100755 --- a/setup-scripts/health-checker.py +++ b/setup-scripts/health-checker.py @@ -43,7 +43,7 @@ async def run_checks(): # check_health checks /health-check endpoint and reports recent issues async def check_health(): - print("\nChecking wallet/funds health...") + print("\nChecking portal health status...") try: res = requests.get("http://localhost/health-check", verify=False) From 1cc20903c635bd881738ec8b023e7fd7d459357b Mon Sep 17 00:00:00 2001 From: Ivaylo Novakov Date: Fri, 4 Sep 2020 17:07:47 +0200 Subject: [PATCH 12/44] Move max discord message len to a constant. Report critical checks failed. Formatting. --- setup-scripts/health-checker.py | 51 ++++++++++++++++++++++++--------- setup-scripts/log-checker.py | 14 +++++---- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/setup-scripts/health-checker.py b/setup-scripts/health-checker.py index d5b4c75a..b8df8b71 100755 --- a/setup-scripts/health-checker.py +++ b/setup-scripts/health-checker.py @@ -1,8 +1,16 @@ #!/usr/bin/env python3 -import discord, requests, traceback, asyncio, os, sys, json, io +import asyncio +import io +import json +import os +import sys +import traceback from datetime import datetime, timedelta -from bot_utils import setup, send_msg, siad, sc_precision + +import discord +import requests +from bot_utils import setup, send_msg """ health-checker reads the /health-check endpoint of the portal and dispatches @@ -11,6 +19,7 @@ messages to a Discord channel. # The default check interval in hours. DEFAULT_CHECK_INTERVAL = 1 +DISCORD_MAX_MESSAGE_LENGTH = 1900 bot_token = setup() client = discord.Client() @@ -32,13 +41,15 @@ async def run_checks(): print("Running Skynet portal health checks") try: await check_health() - except: # catch all exceptions + except: trace = traceback.format_exc() print("[DEBUG] run_checks() failed.") - if len(trace) < 1900: + if len(trace) < DISCORD_MAX_MESSAGE_LENGTH: await send_msg(client, "```\n{}\n```".format(trace), force_notify=False) else: - await send_msg(client, "Failed to run the checks!", file=discord.File(io.BytesIO(trace.encode()), filename="failed_checks.log"), force_notify=True) + await send_msg(client, "Failed to run the portal health checks!", + file=discord.File(io.BytesIO(trace.encode()), filename="failed_checks.log"), + force_notify=True) # check_health checks /health-check endpoint and reports recent issues @@ -47,13 +58,15 @@ async def check_health(): try: res = requests.get("http://localhost/health-check", verify=False) - except: # catch all exceptions + except: trace = traceback.format_exc() print("[DEBUG] check_health() failed.") - if len(trace) < 1900: + if len(trace) < DISCORD_MAX_MESSAGE_LENGTH: await send_msg(client, "```\n{}\n```".format(trace), force_notify=False) else: - await send_msg(client, "Failed to run the checks!", file=discord.File(io.BytesIO(trace.encode()), filename="failed_checks.log"), force_notify=True) + await send_msg(client, "Failed to run the checks!", + file=discord.File(io.BytesIO(trace.encode()), filename="failed_checks.log"), + force_notify=True) return # Get the number of hours to look back in the logs or use 1 as default. @@ -62,22 +75,32 @@ async def check_health(): check_hours = int(sys.argv[3]) # Check the health records. - failed_checks = [] + failed_records = [] + failed_checks = 0 + failed_critical = 0 passed_checks_counter = 0 time_limit = datetime.now() - timedelta(hours=check_hours) for rec in res.json(): time = datetime.strptime(rec['date'], '%Y-%m-%dT%H:%M:%S.%fZ') if time < time_limit: continue + bad = False for check in rec['checks']: if check['up'] == False: - # We append the entire record, so we can get the full context. - failed_checks.append(rec) - break + bad = True + failed_checks += 1 + if check['critical']: + failed_critical += 1 + if bad: + # We append the entire record, so we can get the full context. + failed_records.append(rec) passed_checks_counter += 1 - if len(failed_checks) > 0: - await send_msg(client, "Found {} failed checks over the last {} hours!".format(len(failed_checks), check_hours), file=discord.File(io.BytesIO(json.dumps(failed_checks, indent=2).encode()), filename="failed_checks.log"), force_notify=True) + if len(failed_records) > 0: + message = "Found {} failed checks ({} critical) over the last {} hours!".format(failed_checks, failed_critical, + check_hours) + await send_msg(client, message, file=discord.File(io.BytesIO(json.dumps(failed_records, indent=2).encode()), + filename="failed_checks.log"), force_notify=True) return # Send an informational heartbeat if all checks passed. diff --git a/setup-scripts/log-checker.py b/setup-scripts/log-checker.py index 95092201..50363e88 100755 --- a/setup-scripts/log-checker.py +++ b/setup-scripts/log-checker.py @@ -20,6 +20,9 @@ Arguments: # The default check interval in hours. DEFAULT_CHECK_INTERVAL = 1 +# Discord messages have a limit on their length set at 2000 bytes. We use +# a lower limit in order to leave some space for additional message text. +DISCORD_MAX_MESSAGE_LENGTH = 1900 bot_token = setup() client = discord.Client() @@ -92,11 +95,12 @@ async def check_docker_logs(): std_err = std_err[pos+1:] upload_name = "{}-{}-{}-{}-{}:{}:{}_err.log".format(container_name, time.year, time.month, time.day, time.hour, time.minute, time.second) await send_msg(client, "Error(s) found in log!", file=discord.File(io.BytesIO(std_err.encode()), filename=upload_name), force_notify=True) - # Send at most 1900 characters of logs, rounded down to the nearest new line. - # This is a limitation in the size of Discord messages - they can be at most - # 2000 characters long (and we send some extra characters before the error log). - if len(std_err) > 1900: - pos = std_err.find("\n", -1900) + # Send at most DISCORD_MAX_MESSAGE_LENGTH characters of logs, rounded + # down to the nearest new line. This is a limitation in the size of + # Discord messages - they can be at most 2000 characters long (and we + # send some extra characters before the error log). + if len(std_err) > DISCORD_MAX_MESSAGE_LENGTH: + pos = std_err.find("\n", -DISCORD_MAX_MESSAGE_LENGTH) std_err = std_err[pos+1:] await send_msg(client, "Error(s) preview:\n{}".format(std_err), force_notify=True) return From 5eece67b03b022067ee80e47e0fb6b44f06badc1 Mon Sep 17 00:00:00 2001 From: Ivaylo Novakov Date: Fri, 4 Sep 2020 17:13:36 +0200 Subject: [PATCH 13/44] Move parameter parsing to the top of the script. --- setup-scripts/health-checker.py | 16 ++++++++-------- setup-scripts/log-checker.py | 34 ++++++++++++++++----------------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/setup-scripts/health-checker.py b/setup-scripts/health-checker.py index b8df8b71..f28d8469 100755 --- a/setup-scripts/health-checker.py +++ b/setup-scripts/health-checker.py @@ -17,8 +17,13 @@ health-checker reads the /health-check endpoint of the portal and dispatches messages to a Discord channel. """ -# The default check interval in hours. -DEFAULT_CHECK_INTERVAL = 1 +# Get the number of hours to look back in the logs or use 1 as default. +CHECK_HOURS = 1 +if len(sys.argv) > 3: + CHECK_HOURS = int(sys.argv[3]) + +# Discord messages have a limit on their length set at 2000 bytes. We use +# a lower limit in order to leave some space for additional message text. DISCORD_MAX_MESSAGE_LENGTH = 1900 bot_token = setup() @@ -69,17 +74,12 @@ async def check_health(): force_notify=True) return - # Get the number of hours to look back in the logs or use 1 as default. - check_hours = DEFAULT_CHECK_INTERVAL - if len(sys.argv) > 3: - check_hours = int(sys.argv[3]) - # Check the health records. failed_records = [] failed_checks = 0 failed_critical = 0 passed_checks_counter = 0 - time_limit = datetime.now() - timedelta(hours=check_hours) + time_limit = datetime.now() - timedelta(hours=CHECK_HOURS) for rec in res.json(): time = datetime.strptime(rec['date'], '%Y-%m-%dT%H:%M:%S.%fZ') if time < time_limit: diff --git a/setup-scripts/log-checker.py b/setup-scripts/log-checker.py index 50363e88..029b9a07 100755 --- a/setup-scripts/log-checker.py +++ b/setup-scripts/log-checker.py @@ -18,8 +18,16 @@ Arguments: """ -# The default check interval in hours. -DEFAULT_CHECK_INTERVAL = 1 +# Get the container name as an argument or use "sia" as default. +CONTAINER_NAME = "sia" +if len(sys.argv) > 2: + CONTAINER_NAME = sys.argv[2] + +# Get the number of hours to look back in the logs or use 1 as default. +CHECK_HOURS = 1 +if len(sys.argv) > 3: + CHECK_HOURS = int(sys.argv[3]) + # Discord messages have a limit on their length set at 2000 bytes. We use # a lower limit in order to leave some space for additional message text. DISCORD_MAX_MESSAGE_LENGTH = 1900 @@ -68,23 +76,13 @@ async def check_load_average(): async def check_docker_logs(): print("\nChecking docker logs...") - # Get the container name as an argument or use "sia" as default. - container_name = "sia" - if len(sys.argv) > 2: - container_name = sys.argv[2] - - # Get the number of hours to look back in the logs or use 1 as default. - check_hours = DEFAULT_CHECK_INTERVAL - if len(sys.argv) > 3: - check_hours = int(sys.argv[3]) - now = datetime.now() - time = now - timedelta(hours=check_hours) - time_string = "{}h".format(check_hours) + time = now - timedelta(hours=CHECK_HOURS) + time_string = "{}h".format(CHECK_HOURS) # Read the logs. - print("[DEBUG] Will run `docker logs --since {} {}`".format(time_string, container_name)) - proc = Popen(["docker", "logs", "--since", time_string, container_name], stdin=PIPE, stdout=PIPE, stderr=PIPE, text=True) + print("[DEBUG] Will run `docker logs --since {} {}`".format(time_string, CONTAINER_NAME)) + proc = Popen(["docker", "logs", "--since", time_string, CONTAINER_NAME], stdin=PIPE, stdout=PIPE, stderr=PIPE, text=True) std_out, std_err = proc.communicate() if len(std_err) > 0: @@ -93,7 +91,7 @@ async def check_docker_logs(): if len(std_err) > one_mb: pos = std_err.find("\n", -one_mb) std_err = std_err[pos+1:] - upload_name = "{}-{}-{}-{}-{}:{}:{}_err.log".format(container_name, time.year, time.month, time.day, time.hour, time.minute, time.second) + upload_name = "{}-{}-{}-{}-{}:{}:{}_err.log".format(CONTAINER_NAME, time.year, time.month, time.day, time.hour, time.minute, time.second) await send_msg(client, "Error(s) found in log!", file=discord.File(io.BytesIO(std_err.encode()), filename=upload_name), force_notify=True) # Send at most DISCORD_MAX_MESSAGE_LENGTH characters of logs, rounded # down to the nearest new line. This is a limitation in the size of @@ -107,7 +105,7 @@ async def check_docker_logs(): # If there are any critical or severe errors. upload the whole log file. if 'Critical' in std_out or 'Severe' in std_out or 'panic' in std_out: - upload_name = "{}-{}-{}-{}-{}:{}:{}.log".format(container_name, time.year, time.month, time.day, time.hour, time.minute, time.second) + upload_name = "{}-{}-{}-{}-{}:{}:{}.log".format(CONTAINER_NAME, time.year, time.month, time.day, time.hour, time.minute, time.second) await send_msg(client, "Critical or Severe error found in log!", file=discord.File(io.BytesIO(std_out.encode()), filename=upload_name), force_notify=True) return From 3f4742a43668bb26ba6afec647f524b801da4559 Mon Sep 17 00:00:00 2001 From: Ivaylo Novakov Date: Fri, 4 Sep 2020 17:17:26 +0200 Subject: [PATCH 14/44] Only notify the team if critical checks have failed. --- setup-scripts/health-checker.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/setup-scripts/health-checker.py b/setup-scripts/health-checker.py index f28d8469..6322f894 100755 --- a/setup-scripts/health-checker.py +++ b/setup-scripts/health-checker.py @@ -98,9 +98,10 @@ async def check_health(): if len(failed_records) > 0: message = "Found {} failed checks ({} critical) over the last {} hours!".format(failed_checks, failed_critical, - check_hours) - await send_msg(client, message, file=discord.File(io.BytesIO(json.dumps(failed_records, indent=2).encode()), - filename="failed_checks.log"), force_notify=True) + CHECK_HOURS) + file = discord.File(io.BytesIO(json.dumps(failed_records, indent=2).encode()), filename="failed_checks.log") + notifyTeam = failed_critical > 0 + await send_msg(client, message, file=file, force_notify=notifyTeam) return # Send an informational heartbeat if all checks passed. From e16d143e530c6d559911bc3194217494db26f051 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 10:11:06 +0000 Subject: [PATCH 15/44] Bump gatsby-source-filesystem from 2.3.27 to 2.3.28 in /packages/webapp Bumps [gatsby-source-filesystem](https://github.com/gatsbyjs/gatsby/tree/HEAD/packages/gatsby-source-filesystem) from 2.3.27 to 2.3.28. - [Release notes](https://github.com/gatsbyjs/gatsby/releases) - [Changelog](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-filesystem/CHANGELOG.md) - [Commits](https://github.com/gatsbyjs/gatsby/commits/gatsby-source-filesystem@2.3.28/packages/gatsby-source-filesystem) Signed-off-by: dependabot[bot] --- packages/webapp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/package.json b/packages/webapp/package.json index f893e192..57a8fac8 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -16,7 +16,7 @@ "gatsby-plugin-robots-txt": "1.5.1", "gatsby-plugin-sass": "2.3.12", "gatsby-plugin-sharp": "2.6.31", - "gatsby-source-filesystem": "2.3.27", + "gatsby-source-filesystem": "2.3.28", "gatsby-transformer-sharp": "2.5.14", "http-status-codes": "2.1.2", "jsonp": "0.2.1", From ad52875bd7e4f5b46ef307e421df77d4a450c216 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 10:13:46 +0000 Subject: [PATCH 16/44] Bump gatsby from 2.24.53 to 2.24.54 in /packages/webapp Bumps [gatsby](https://github.com/gatsbyjs/gatsby) from 2.24.53 to 2.24.54. - [Release notes](https://github.com/gatsbyjs/gatsby/releases) - [Changelog](https://github.com/gatsbyjs/gatsby/blob/master/CHANGELOG.md) - [Commits](https://github.com/gatsbyjs/gatsby/compare/gatsby@2.24.53...gatsby@2.24.54) Signed-off-by: dependabot[bot] --- packages/webapp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/package.json b/packages/webapp/package.json index f893e192..695a7159 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -7,7 +7,7 @@ "axios": "0.20.0", "bytes": "3.1.0", "classnames": "2.2.6", - "gatsby": "2.24.53", + "gatsby": "2.24.54", "gatsby-image": "2.4.16", "gatsby-plugin-manifest": "2.4.27", "gatsby-plugin-matomo": "0.8.3", From 5cd7e7f121f0f666328b5f45c8f6894afe44166e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 10:24:11 +0000 Subject: [PATCH 17/44] Bump gatsby-plugin-manifest from 2.4.27 to 2.4.28 in /packages/webapp Bumps [gatsby-plugin-manifest](https://github.com/gatsbyjs/gatsby/tree/HEAD/packages/gatsby-plugin-manifest) from 2.4.27 to 2.4.28. - [Release notes](https://github.com/gatsbyjs/gatsby/releases) - [Changelog](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-plugin-manifest/CHANGELOG.md) - [Commits](https://github.com/gatsbyjs/gatsby/commits/gatsby-plugin-manifest@2.4.28/packages/gatsby-plugin-manifest) Signed-off-by: dependabot[bot] --- packages/webapp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/package.json b/packages/webapp/package.json index f893e192..959534c7 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -9,7 +9,7 @@ "classnames": "2.2.6", "gatsby": "2.24.53", "gatsby-image": "2.4.16", - "gatsby-plugin-manifest": "2.4.27", + "gatsby-plugin-manifest": "2.4.28", "gatsby-plugin-matomo": "0.8.3", "gatsby-plugin-react-helmet": "3.3.10", "gatsby-plugin-remove-serviceworker": "1.0.0", From 83a5b420f1520c3b14e0d13b3d925e2946f151d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 10:27:28 +0000 Subject: [PATCH 18/44] Bump husky from 4.2.5 to 4.3.0 in /packages/webapp Bumps [husky](https://github.com/typicode/husky) from 4.2.5 to 4.3.0. - [Release notes](https://github.com/typicode/husky/releases) - [Changelog](https://github.com/typicode/husky/blob/master/CHANGELOG.md) - [Commits](https://github.com/typicode/husky/compare/v4.2.5...v4.3.0) Signed-off-by: dependabot[bot] --- packages/webapp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/package.json b/packages/webapp/package.json index f893e192..586dea1b 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -43,7 +43,7 @@ "eslint-config-prettier": "6.11.0", "eslint-plugin-cypress": "2.11.1", "eslint-plugin-react": "7.20.6", - "husky": "4.2.5", + "husky": "4.3.0", "lint-staged": "10.3.0", "prettier": "2.1.1" }, From e82e382c055341224ea6ee953fe558c721196020 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 10:30:28 +0000 Subject: [PATCH 19/44] Bump react-syntax-highlighter from 13.5.1 to 13.5.3 in /packages/webapp Bumps [react-syntax-highlighter](https://github.com/react-syntax-highlighter/react-syntax-highlighter) from 13.5.1 to 13.5.3. - [Release notes](https://github.com/react-syntax-highlighter/react-syntax-highlighter/releases) - [Changelog](https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/CHANGELOG.MD) - [Commits](https://github.com/react-syntax-highlighter/react-syntax-highlighter/compare/v13.5.1...v13.5.3) Signed-off-by: dependabot[bot] --- packages/webapp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/package.json b/packages/webapp/package.json index f893e192..989f6b4d 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -31,7 +31,7 @@ "react-mailchimp-form": "1.0.2", "react-mailchimp-subscribe": "2.1.0", "react-reveal": "1.2.2", - "react-syntax-highlighter": "13.5.1", + "react-syntax-highlighter": "13.5.3", "react-visibility-sensor": "5.1.1", "skynet-js": "0.0.8", "typeface-metropolis": "0.0.74" From ab66b6ff5b0ce5e51f310efeb99bb1048fd63f48 Mon Sep 17 00:00:00 2001 From: Marcin S Date: Mon, 7 Sep 2020 17:32:25 +0200 Subject: [PATCH 20/44] Update code samples for API v2 --- .../src/components/CodeExamples/Code.js | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/packages/webapp/src/components/CodeExamples/Code.js b/packages/webapp/src/components/CodeExamples/Code.js index 33018c4a..d491a357 100644 --- a/packages/webapp/src/components/CodeExamples/Code.js +++ b/packages/webapp/src/components/CodeExamples/Code.js @@ -1,11 +1,14 @@ -export const python = `import siaskynet +export const python = `import siaskynet as skynet + +# create a client +client = skynet.SkynetClient() # upload -skylink = siaskynet.upload_file("./src.jpg") +skylink = client.upload_file("./src.jpg") print("Upload successful, skylink: " + skylink) # download -siaskynet.download_file("./dst.jpg", skylink) +client.download_file("./dst.jpg", skylink) print("Download successful")`; export const curl = `# upload @@ -14,22 +17,18 @@ curl -X POST "https://siasky.net/skynet/skyfile" -F file=@src.jpg # download curl "https://siasky.net/[skylink]" -o dst.jpg`; -export const node = `const skynet = require('@nebulous/skynet'); +export const node = `const { SkynetClient } = require('@nebulous/skynet'); + +// create a client +const client = new SkynetClient(); (async () => { // upload - const skylink = await skynet.UploadFile( - "./src.jpg", - skynet.DefaultUploadOptions - ); + const skylink = await client.UploadFile("./src.jpg"); console.log(\`Upload successful, skylink: \${skylink}\`); - + // download - await skynet.DownloadFile( - "./dst.jpg", - skylink, - skynet.DefaultDownloadOptions - ); + await client.DownloadFile("./dst.jpg", skylink); console.log('Download successful'); })()`; @@ -39,21 +38,21 @@ import ( "fmt" skynet "github.com/NebulousLabs/go-skynet" ) - + +var client = skynet.New() + func main() { // upload - skylink, err := skynet.UploadFile("./src.jpg", skynet.DefaultUploadOptions) + skylink, err := client.UploadFile("./src.jpg", skynet.DefaultUploadOptions) if err != nil { - fmt.Printf("Unable to upload: %v", err.Error()) - return + panic("Unable to upload: %v", err.Error()) } fmt.Printf("Upload successful, skylink: %v\\n", skylink) // download - err = skynet.DownloadFile("./dst.jpg", skylink, skynet.DefaultDownloadOptions) + err = client.DownloadFile("./dst.jpg", skylink, skynet.DefaultDownloadOptions) if err != nil { - fmt.Printf("Something went wrong, please try again.\\nError: %v", err.Error()) - return + panic("Something went wrong, please try again.\\nError: %v", err.Error()) } fmt.Println("Download successful") }`; From 0838e4f5e52e836c135c94ad0df4ae6d523fa4b8 Mon Sep 17 00:00:00 2001 From: Ivaylo Novakov Date: Mon, 7 Sep 2020 17:56:47 +0200 Subject: [PATCH 21/44] Add free disk space check to health-checker.py. Move load-average check to health-checker.py. --- setup-scripts/health-checker.py | 50 +++++++++++++++++++++++++++++++++ setup-scripts/log-checker.py | 17 +---------- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/setup-scripts/health-checker.py b/setup-scripts/health-checker.py index 6322f894..d2e1d2fa 100755 --- a/setup-scripts/health-checker.py +++ b/setup-scripts/health-checker.py @@ -4,6 +4,7 @@ import asyncio import io import json import os +import re import sys import traceback from datetime import datetime, timedelta @@ -26,6 +27,12 @@ if len(sys.argv) > 3: # a lower limit in order to leave some space for additional message text. DISCORD_MAX_MESSAGE_LENGTH = 1900 +GB = 1 << 20 # converts from KiB to GiB +# We are going to issue Discord warnings if the free space on a server falls +# under this threshold. +FREE_DISK_SPACE_THRESHOLD = 50 * GB # 50 GiB + + bot_token = setup() client = discord.Client() @@ -45,6 +52,8 @@ async def on_ready(): async def run_checks(): print("Running Skynet portal health checks") try: + await check_load_average() + await check_disk() await check_health() except: trace = traceback.format_exc() @@ -57,6 +66,47 @@ async def run_checks(): force_notify=True) +# check_load_average monitors the system's load average value and issues a +# warning message if it exceeds 10. +async def check_load_average(): + uptime_string = os.popen("uptime").read().strip() + if sys.platform == "Darwin": + pattern = "^.*load averages: \d*\.\d* \d*\.\d* (\d*\.\d*)$" + else: + pattern = "^.*load average: \d*\.\d*, \d*\.\d*, (\d*\.\d*)$" + load_av = re.match(pattern, uptime_string).group(1) + if float(load_av) > 10: + await send_msg(client, "High system load detected: `uptime: {}`".format(uptime_string), force_notify=True) + + +# check_disk checks the amount of free space on the /home partition and issues +# a warning message if it's under 10GB. +async def check_disk(): + df = os.popen("df --block-size=1024").read().strip() + volumes = {} + for line in df.split("\n")[1:]: + fields = list(filter(None, line.split(" "))) + # -1 is "mounted on", 3 is "available space" + volumes[fields[-1]] = fields[3] + # List of mount point, longest to shortest. We'll use that to find the best + # fit for the volume we want to check. + mount_points = sorted(volumes.keys(), key=len, reverse=True) + wd = os.popen("pwd").read().strip() + vol = "" + for mp in mount_points: + if wd.startswith(mp): + vol = mp + break + if vol == "": + msg = "Failed to check free disk space! Didn't find a suitable mount point to check.\ndf output:\n{}".format(df) + await send_msg(client, msg) + return + if int(volumes[vol]) < FREE_DISK_SPACE_THRESHOLD: + free_space_gb = "{:.2f}".format(int(volumes[vol])/ GB) + await send_msg(client, "WARNING! Low disk space: {}GiB".format(free_space_gb), force_notify=True) + return + + # check_health checks /health-check endpoint and reports recent issues async def check_health(): print("\nChecking portal health status...") diff --git a/setup-scripts/log-checker.py b/setup-scripts/log-checker.py index 029b9a07..de8a7c2c 100755 --- a/setup-scripts/log-checker.py +++ b/setup-scripts/log-checker.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -import discord, sys, traceback, io, os, asyncio, re +import discord, sys, traceback, io, os, asyncio from bot_utils import setup, send_msg from datetime import datetime, timedelta from subprocess import Popen, PIPE @@ -51,27 +51,12 @@ async def on_ready(): async def run_checks(): print("Running Skynet portal log checks") try: - await check_load_average() await check_docker_logs() - except: # catch all exceptions trace = traceback.format_exc() await send_msg(client, "```\n{}\n```".format(trace), force_notify=False) -# check_load_average monitors the system's load average value and issues a -# warning message if it exceeds 10. -async def check_load_average(): - uptime_string = os.popen("uptime").read().strip() - # pattern = "" - if sys.platform == "Darwin": - pattern = "^.*load averages: \d*\.\d* \d*\.\d* (\d*\.\d*)$" - else: - pattern = "^.*load average: \d*\.\d*, \d*\.\d*, (\d*\.\d*)$" - load_av = re.match(pattern, uptime_string).group(1) - if float(load_av) > 10: - await send_msg(client, "High system load detected: `uptime: {}`".format(uptime_string), force_notify=True) - # check_docker_logs checks the docker logs by filtering on the docker image name async def check_docker_logs(): print("\nChecking docker logs...") From 2d032dbf173819da001f3b245b563e644bb9a3fa Mon Sep 17 00:00:00 2001 From: Ivaylo Novakov Date: Mon, 7 Sep 2020 17:59:39 +0200 Subject: [PATCH 22/44] Docstrings. --- setup-scripts/health-checker.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup-scripts/health-checker.py b/setup-scripts/health-checker.py index d2e1d2fa..2dd74c20 100755 --- a/setup-scripts/health-checker.py +++ b/setup-scripts/health-checker.py @@ -80,8 +80,9 @@ async def check_load_average(): # check_disk checks the amount of free space on the /home partition and issues -# a warning message if it's under 10GB. +# a warning message if it's under FREE_DISK_SPACE_THRESHOLD GB. async def check_disk(): + # We check free disk space in 1024 byte units, so it's easy to convert. df = os.popen("df --block-size=1024").read().strip() volumes = {} for line in df.split("\n")[1:]: From e301b035ad23f29f44d97f40bfca85608d134ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Wypch=C5=82o?= Date: Tue, 8 Sep 2020 16:30:54 +0200 Subject: [PATCH 23/44] assign static ips to containers (#383) --- docker-compose.yml | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3c40ca50..b57462af 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,10 @@ version: "3.7" networks: shared: - driver: bridge + ipam: + driver: default + config: + - subnet: 192.168.0.0/24 volumes: webapp: @@ -23,7 +26,8 @@ services: volumes: - ./docker/data/sia:/sia-data networks: - - shared + shared: + ipv4_address: 192.168.0.10 expose: - 9980 @@ -38,7 +42,8 @@ services: volumes: - ./docker/data/sia-upload:/sia-data networks: - - shared + shared: + ipv4_address: 192.168.0.11 expose: - 9980 @@ -55,7 +60,8 @@ services: - ./docker/data/caddy/config:/config - ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile networks: - - shared + shared: + ipv4_address: 192.168.0.20 ports: - "80:80" - "443:443" @@ -76,7 +82,8 @@ services: - ./docker/data/sia/apipassword:/data/sia/apipassword:ro - webapp:/var/www/webportal:ro networks: - - shared + shared: + ipv4_address: 192.168.0.30 expose: - 80 depends_on: @@ -110,7 +117,8 @@ services: volumes: - ./docker/data/handshake/.hsd:/root/.hsd networks: - - shared + shared: + ipv4_address: 192.168.0.40 expose: - 12037 @@ -128,7 +136,8 @@ services: env_file: - .env networks: - - shared + shared: + ipv4_address: 192.168.0.50 expose: - 3100 depends_on: @@ -143,7 +152,8 @@ services: volumes: - ./docker/data/health-check/state:/usr/app/state networks: - - shared + shared: + ipv4_address: 192.168.0.60 environment: - HOSTNAME=0.0.0.0 - PORTAL_URL=nginx From 072b6264759bd40518d92bebe942fe6c9281aa98 Mon Sep 17 00:00:00 2001 From: Marcin S Date: Tue, 8 Sep 2020 16:53:05 +0200 Subject: [PATCH 24/44] Fix syntax error in panic calls --- packages/webapp/src/components/CodeExamples/Code.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webapp/src/components/CodeExamples/Code.js b/packages/webapp/src/components/CodeExamples/Code.js index d491a357..695a4634 100644 --- a/packages/webapp/src/components/CodeExamples/Code.js +++ b/packages/webapp/src/components/CodeExamples/Code.js @@ -45,14 +45,14 @@ func main() { // upload skylink, err := client.UploadFile("./src.jpg", skynet.DefaultUploadOptions) if err != nil { - panic("Unable to upload: %v", err.Error()) + panic("Unable to upload: " + err.Error()) } fmt.Printf("Upload successful, skylink: %v\\n", skylink) // download err = client.DownloadFile("./dst.jpg", skylink, skynet.DefaultDownloadOptions) if err != nil { - panic("Something went wrong, please try again.\\nError: %v", err.Error()) + panic("Something went wrong, please try again.\\nError: " + err.Error()) } fmt.Println("Download successful") }`; From ddf72ad850d9ce8ce659935f531bc3ef1ff7e479 Mon Sep 17 00:00:00 2001 From: Ivaylo Novakov Date: Tue, 8 Sep 2020 18:07:33 +0200 Subject: [PATCH 25/44] Make the time comparisons in the health checker timezone-aware. --- setup-scripts/health-checker.py | 32 ++++++++++++--------- setup-scripts/setup-health-check-scripts.sh | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/setup-scripts/health-checker.py b/setup-scripts/health-checker.py index 2dd74c20..a3ea7f23 100755 --- a/setup-scripts/health-checker.py +++ b/setup-scripts/health-checker.py @@ -10,8 +10,10 @@ import traceback from datetime import datetime, timedelta import discord +import pytz.reference import requests from bot_utils import setup, send_msg +from tzlocal import get_localzone """ health-checker reads the /health-check endpoint of the portal and dispatches @@ -27,11 +29,10 @@ if len(sys.argv) > 3: # a lower limit in order to leave some space for additional message text. DISCORD_MAX_MESSAGE_LENGTH = 1900 -GB = 1 << 20 # converts from KiB to GiB +GB = 1 << 30 # 1 GiB in bytes # We are going to issue Discord warnings if the free space on a server falls # under this threshold. -FREE_DISK_SPACE_THRESHOLD = 50 * GB # 50 GiB - +FREE_DISK_SPACE_THRESHOLD = 50 * GB bot_token = setup() client = discord.Client() @@ -87,8 +88,8 @@ async def check_disk(): volumes = {} for line in df.split("\n")[1:]: fields = list(filter(None, line.split(" "))) - # -1 is "mounted on", 3 is "available space" - volumes[fields[-1]] = fields[3] + # -1 is "mounted on", 3 is "available space" in KiB which we want in bytes + volumes[fields[-1]] = fields[3] * 1024 # List of mount point, longest to shortest. We'll use that to find the best # fit for the volume we want to check. mount_points = sorted(volumes.keys(), key=len, reverse=True) @@ -103,7 +104,7 @@ async def check_disk(): await send_msg(client, msg) return if int(volumes[vol]) < FREE_DISK_SPACE_THRESHOLD: - free_space_gb = "{:.2f}".format(int(volumes[vol])/ GB) + free_space_gb = "{:.2f}".format(int(volumes[vol]) / GB) await send_msg(client, "WARNING! Low disk space: {}GiB".format(free_space_gb), force_notify=True) return @@ -126,13 +127,15 @@ async def check_health(): return # Check the health records. - failed_records = [] + passed_checks = 0 failed_checks = 0 failed_critical = 0 - passed_checks_counter = 0 - time_limit = datetime.now() - timedelta(hours=CHECK_HOURS) + failed_records = [] + time_limit_unaware = datetime.now() - timedelta(hours=CHECK_HOURS) # local time + time_limit = time_limit_unaware.astimezone(get_localzone()) # time with time zone for rec in res.json(): - time = datetime.strptime(rec['date'], '%Y-%m-%dT%H:%M:%S.%fZ') + time_unaware = datetime.strptime(rec['date'], '%Y-%m-%dT%H:%M:%S.%fZ') # time in UTC + time = pytz.utc.localize(time_unaware) # time with time zone if time < time_limit: continue bad = False @@ -145,18 +148,19 @@ async def check_health(): if bad: # We append the entire record, so we can get the full context. failed_records.append(rec) - passed_checks_counter += 1 + passed_checks += 1 + checks = passed_checks + failed_checks if len(failed_records) > 0: - message = "Found {} failed checks ({} critical) over the last {} hours!".format(failed_checks, failed_critical, - CHECK_HOURS) + message = "Found {}/{} failed checks ({} critical) over the last {} hours!".format(failed_checks, checks, + failed_critical, CHECK_HOURS) file = discord.File(io.BytesIO(json.dumps(failed_records, indent=2).encode()), filename="failed_checks.log") notifyTeam = failed_critical > 0 await send_msg(client, message, file=file, force_notify=notifyTeam) return # Send an informational heartbeat if all checks passed. - await send_msg(client, "Health checks passed: {}\n".format(passed_checks_counter)) + await send_msg(client, "Health checks passed: {}/{}\n".format(passed_checks, checks)) client.run(bot_token) diff --git a/setup-scripts/setup-health-check-scripts.sh b/setup-scripts/setup-health-check-scripts.sh index 7d17b85b..fd396983 100755 --- a/setup-scripts/setup-health-check-scripts.sh +++ b/setup-scripts/setup-health-check-scripts.sh @@ -5,7 +5,7 @@ set -e # exit on first error sudo apt-get update sudo apt-get -y install python3-pip -pip3 install discord.py python-dotenv requests +pip3 install discord.py python-dotenv requests pytz tzlocal fundsCheck="0 0,8,16 * * * /home/user/skynet-webportal/setup-scripts/funds-checker.py /home/user/skynet-webportal/.env" logsCheck="0 0,8,16 * * * /home/user/skynet-webportal/setup-scripts/log-checker.py /home/user/skynet-webportal/.env sia 8" From 8235d757950bb049279f84d2b3faf9399fccbb5c Mon Sep 17 00:00:00 2001 From: Ivaylo Novakov Date: Tue, 8 Sep 2020 18:20:56 +0200 Subject: [PATCH 26/44] Only announce healthy status once a day. --- setup-scripts/health-checker.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setup-scripts/health-checker.py b/setup-scripts/health-checker.py index a3ea7f23..bdf2b9ef 100755 --- a/setup-scripts/health-checker.py +++ b/setup-scripts/health-checker.py @@ -159,8 +159,10 @@ async def check_health(): await send_msg(client, message, file=file, force_notify=notifyTeam) return - # Send an informational heartbeat if all checks passed. - await send_msg(client, "Health checks passed: {}/{}\n".format(passed_checks, checks)) + # Send an informational heartbeat if all checks passed but only if it's in + # the first CHECK_HOURS hours of the day, essentially the first call. + if datetime.now().hour < CHECK_HOURS: + await send_msg(client, "Health checks passed: {}/{}\n".format(passed_checks, checks)) client.run(bot_token) From 0593b41201590a88d78f9dbce8cfbc0d6dc8d15d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Wypch=C5=82o?= Date: Wed, 9 Sep 2020 10:17:12 +0200 Subject: [PATCH 27/44] Nginx Log Format (#356) * add filebeat * nginx.conf access.log * nginx.conf access.log * fix filebeat * add upstream data to access log * Update nginx.conf * Add content type header to access_log format * Add quotes * logs with wildcard to include gzipped ones * Remove filebeat config Co-authored-by: PJ --- docker/nginx/nginx.conf | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf index a183e620..58a8d8c8 100644 --- a/docker/nginx/nginx.conf +++ b/docker/nginx/nginx.conf @@ -35,11 +35,13 @@ http { include mime.types; default_type application/octet-stream; - #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - # '$status $body_bytes_sent "$http_referer" ' - # '"$http_user_agent" "$http_x_forwarded_for"'; + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" $upstream_response_time ' + '$upstream_bytes_sent $upstream_bytes_received ' + '"$upstream_http_content_type"'; - #access_log logs/access.log main; + access_log logs/access.log main; # See Move default writable paths to a dedicated directory (#119) # https://github.com/openresty/docker-openresty/issues/119 From b1def0392866d849c17fbaceef58d05ccb2a5d98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2020 09:37:56 +0000 Subject: [PATCH 28/44] Bump gatsby-plugin-sharp from 2.6.31 to 2.6.33 in /packages/webapp Bumps [gatsby-plugin-sharp](https://github.com/gatsbyjs/gatsby/tree/HEAD/packages/gatsby-plugin-sharp) from 2.6.31 to 2.6.33. - [Release notes](https://github.com/gatsbyjs/gatsby/releases) - [Changelog](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-plugin-sharp/CHANGELOG.md) - [Commits](https://github.com/gatsbyjs/gatsby/commits/gatsby-plugin-sharp@2.6.33/packages/gatsby-plugin-sharp) Signed-off-by: dependabot[bot] --- packages/webapp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/package.json b/packages/webapp/package.json index 8a0c0dad..45263206 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -15,7 +15,7 @@ "gatsby-plugin-remove-serviceworker": "1.0.0", "gatsby-plugin-robots-txt": "1.5.1", "gatsby-plugin-sass": "2.3.12", - "gatsby-plugin-sharp": "2.6.31", + "gatsby-plugin-sharp": "2.6.33", "gatsby-source-filesystem": "2.3.28", "gatsby-transformer-sharp": "2.5.14", "http-status-codes": "2.1.2", From 36deb916f9d5f52e70859d49574ced1c7fe82d9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2020 09:38:17 +0000 Subject: [PATCH 29/44] Bump gatsby-image from 2.4.16 to 2.4.17 in /packages/webapp Bumps [gatsby-image](https://github.com/gatsbyjs/gatsby/tree/HEAD/packages/gatsby-image) from 2.4.16 to 2.4.17. - [Release notes](https://github.com/gatsbyjs/gatsby/releases) - [Changelog](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-image/CHANGELOG.md) - [Commits](https://github.com/gatsbyjs/gatsby/commits/gatsby-image@2.4.17/packages/gatsby-image) Signed-off-by: dependabot[bot] --- packages/webapp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/package.json b/packages/webapp/package.json index 8a0c0dad..72214a2f 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -8,7 +8,7 @@ "bytes": "3.1.0", "classnames": "2.2.6", "gatsby": "2.24.54", - "gatsby-image": "2.4.16", + "gatsby-image": "2.4.17", "gatsby-plugin-manifest": "2.4.28", "gatsby-plugin-matomo": "0.8.3", "gatsby-plugin-react-helmet": "3.3.10", From ca73a2f61fe7d8b8846092fe91e9cb1a5e804217 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Wed, 9 Sep 2020 14:25:00 +0200 Subject: [PATCH 30/44] improve health checks --- packages/health-check/.gitignore | 1 + packages/health-check/Dockerfile | 3 +- packages/health-check/cli/disable | 7 ++ packages/health-check/cli/enable | 7 ++ packages/health-check/src/api/all.js | 8 ++ .../{endpointHealthCheck.js => api/index.js} | 8 +- packages/health-check/src/api/recent.js | 16 +++ packages/health-check/src/basicChecks.js | 51 -------- packages/health-check/src/checks/critical.js | 48 ++++++++ .../{verboseChecks.js => checks/verbose.js} | 112 +++++++++--------- packages/health-check/src/db.js | 5 +- packages/health-check/src/index.js | 4 +- packages/health-check/src/schedule.js | 8 +- packages/health-check/src/utils.js | 8 ++ 14 files changed, 168 insertions(+), 118 deletions(-) create mode 100644 packages/health-check/.gitignore create mode 100755 packages/health-check/cli/disable create mode 100755 packages/health-check/cli/enable create mode 100644 packages/health-check/src/api/all.js rename packages/health-check/src/{endpointHealthCheck.js => api/index.js} (91%) create mode 100644 packages/health-check/src/api/recent.js delete mode 100644 packages/health-check/src/basicChecks.js create mode 100644 packages/health-check/src/checks/critical.js rename packages/health-check/src/{verboseChecks.js => checks/verbose.js} (88%) create mode 100644 packages/health-check/src/utils.js diff --git a/packages/health-check/.gitignore b/packages/health-check/.gitignore new file mode 100644 index 00000000..dc3b76b2 --- /dev/null +++ b/packages/health-check/.gitignore @@ -0,0 +1 @@ +state/ diff --git a/packages/health-check/Dockerfile b/packages/health-check/Dockerfile index f2ee9b61..1378bca4 100644 --- a/packages/health-check/Dockerfile +++ b/packages/health-check/Dockerfile @@ -5,7 +5,8 @@ WORKDIR /usr/app COPY package.json . RUN yarn --no-lockfile COPY src/* src/ +COPY cli/* cli/ EXPOSE 3100 ENV NODE_ENV production -CMD [ "node", "src/index.js" ] +CMD [ "node", "--max-http-header-size=64000", "src/index.js" ] diff --git a/packages/health-check/cli/disable b/packages/health-check/cli/disable new file mode 100755 index 00000000..05736671 --- /dev/null +++ b/packages/health-check/cli/disable @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +process.env.NODE_ENV = process.env.NODE_ENV || "production"; + +const db = require("../src/db"); + +db.set("disabled", true).write(); diff --git a/packages/health-check/cli/enable b/packages/health-check/cli/enable new file mode 100755 index 00000000..13cc1341 --- /dev/null +++ b/packages/health-check/cli/enable @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +process.env.NODE_ENV = process.env.NODE_ENV || "production"; + +const db = require("../src/db"); + +db.set("disabled", false).write(); diff --git a/packages/health-check/src/api/all.js b/packages/health-check/src/api/all.js new file mode 100644 index 00000000..782e0e52 --- /dev/null +++ b/packages/health-check/src/api/all.js @@ -0,0 +1,8 @@ +const db = require("../db"); + +// returns all health check entries +module.exports = (req, res) => { + const entries = db.get("entries").orderBy("date", "desc").value(); + + res.send(entries); +}; diff --git a/packages/health-check/src/endpointHealthCheck.js b/packages/health-check/src/api/index.js similarity index 91% rename from packages/health-check/src/endpointHealthCheck.js rename to packages/health-check/src/api/index.js index c45d5ed5..733fb61d 100644 --- a/packages/health-check/src/endpointHealthCheck.js +++ b/packages/health-check/src/api/index.js @@ -1,9 +1,15 @@ const { StatusCodes } = require("http-status-codes"); const { sum, sumBy } = require("lodash"); -const db = require("./db"); +const db = require("../db"); // getStatus returns the server's current health check status function getStatus() { + const disabled = db.get("disabled").value(); + + if (disabled) { + return StatusCodes.SERVICE_UNAVAILABLE; + } + // Grab entry element from DB const entry = db.get("entries").orderBy("date", "desc").head().value(); diff --git a/packages/health-check/src/api/recent.js b/packages/health-check/src/api/recent.js new file mode 100644 index 00000000..600b5814 --- /dev/null +++ b/packages/health-check/src/api/recent.js @@ -0,0 +1,16 @@ +const db = require("../db"); + +// returns all health check entries that are not older than one day +module.exports = (req, res) => { + const yesterday = new Date(); + + yesterday.setDate(yesterday.getDate() - 1); + + const entries = db + .get("entries") + .orderBy("date", "desc") + .filter(({ date }) => date >= yesterday.toISOString()) + .value(); + + res.send(entries); +}; diff --git a/packages/health-check/src/basicChecks.js b/packages/health-check/src/basicChecks.js deleted file mode 100644 index ace17475..00000000 --- a/packages/health-check/src/basicChecks.js +++ /dev/null @@ -1,51 +0,0 @@ -const superagent = require("superagent"); -const { StatusCodes } = require("http-status-codes"); - -// uploadCheck returns the result of uploading a sample file -async function uploadCheck(done) { - const time = process.hrtime(); - - superagent - .post(`http://${process.env.PORTAL_URL}/skynet/skyfile`) - .attach("file", "package.json", "package.json") - .end((err, res) => { - const statusCode = (res && res.statusCode) || (err && err.statusCode) || null; - - done({ - name: "upload_file", - up: statusCode === StatusCodes.OK, - statusCode, - time: catchRequestTime(time), - critical: true, - }); - }); -} - -// downloadCheck returns the result of downloading the hard coded link -function downloadCheck(done) { - const time = process.hrtime(); - const skylink = "AACogzrAimYPG42tDOKhS3lXZD8YvlF8Q8R17afe95iV2Q"; - - superagent.get(`http://${process.env.PORTAL_URL}/${skylink}?nocache=true`).end((err, res) => { - const statusCode = (res && res.statusCode) || (err && err.statusCode) || null; - - done({ - name: "download_file", - up: statusCode === StatusCodes.OK, - statusCode, - time: catchRequestTime(time), - critical: true, - }); - }); -} - -// catchRequestTime records the time it took to resolve the request in -// milliseconds -function catchRequestTime(start) { - const diff = process.hrtime(start); - - return Math.round((diff[0] * 1e9 + diff[1]) / 1e6); // msec -} - -module.exports.basicChecks = [uploadCheck, downloadCheck]; -module.exports.catchRequestTime = catchRequestTime; diff --git a/packages/health-check/src/checks/critical.js b/packages/health-check/src/checks/critical.js new file mode 100644 index 00000000..f737995f --- /dev/null +++ b/packages/health-check/src/checks/critical.js @@ -0,0 +1,48 @@ +const superagent = require("superagent"); +const { StatusCodes } = require("http-status-codes"); +const { getTimeDiff } = require("../utils"); + +// uploadCheck returns the result of uploading a sample file +async function uploadCheck(done) { + const time = process.hrtime(); + + superagent + .post(`http://${process.env.PORTAL_URL}/skynet/skyfile`) + .attach("file", "package.json", "package.json") + .end((error, response) => { + const statusCode = (response && response.statusCode) || (error && error.statusCode) || null; + + done({ + name: "upload_file", + up: statusCode === StatusCodes.OK, + statusCode, + time: getTimeDiff(time), + critical: true, + }); + }); +} + +// downloadCheck returns the result of downloading the hard coded link +async function downloadCheck(done) { + const time = process.hrtime(); + const skylink = "AACogzrAimYPG42tDOKhS3lXZD8YvlF8Q8R17afe95iV2Q"; + let statusCode; + + try { + const response = await superagent.get(`http://${process.env.PORTAL_URL}/${skylink}?nocache=true`); + + statusCode = response.statusCode; + } catch (error) { + statusCode = error.statusCode || error.status; + } + + done({ + name: "download_file", + up: statusCode === StatusCodes.OK, + statusCode, + time: getTimeDiff(time), + critical: true, + }); +} + +module.exports.criticalChecks = [uploadCheck, downloadCheck]; diff --git a/packages/health-check/src/verboseChecks.js b/packages/health-check/src/checks/verbose.js similarity index 88% rename from packages/health-check/src/verboseChecks.js rename to packages/health-check/src/checks/verbose.js index 345cd624..26c5ab71 100644 --- a/packages/health-check/src/verboseChecks.js +++ b/packages/health-check/src/checks/verbose.js @@ -1,14 +1,14 @@ const superagent = require("superagent"); const hash = require("object-hash"); const { detailedDiff } = require("deep-object-diff"); -const { isEqual } = require("lodash"); -const checks = require("./basicChecks"); +const { isEqual, isEmpty } = require("lodash"); +const { getTimeDiff } = require("../utils"); // audioExampleCheck returns the result of trying to download the skylink // for the Example audio file on siasky.net function audioExampleCheck(done) { const linkInfo = { - description: "Audio Example", + name: "Audio Example", skylink: "_A2zt5SKoqwnnZU4cBF8uBycSKULXMyeg1c5ZISBr2Q3dA", bodyHash: "be335f5ad9bc357248f3d35c7e49df491afb6b12", metadata: { filename: "feel-good.mp3" }, @@ -21,7 +21,7 @@ function audioExampleCheck(done) { // for a known Covid19 paper function covid19PaperCheck(done) { const linkInfo = { - description: "Covid-19 Paper", + name: "Covid-19 Paper", skylink: "PAMZVmfutxWoG6Wnl5BRKuWLkDNZR42k_okRRvksJekA3A", bodyHash: "81b9fb74829a96ceafa429840d1ef0ce44376ddd", metadata: { @@ -43,7 +43,7 @@ function covid19PaperCheck(done) { // for another known Covid19 paper function covid19CoroNopePaperCheck(done) { const linkInfo = { - description: "Covid-19 CoroNope Paper", + name: "Covid-19 CoroNope Paper", skylink: "bACLKGmcmX4NCp47WwOOJf0lU666VLeT5HRWpWVtqZPjEA", bodyHash: "901f6fd65ef595f70b6bfebbb2d05942351ef2b3", metadata: { filename: "coronope.pdf" }, @@ -56,8 +56,8 @@ function covid19CoroNopePaperCheck(done) { // for the Example Dapp on siasky.net function dappExampleCheck(done) { const linkInfo = { - description: "Dapp Example (UniSwap)", - skylink: "EAC5HJr5Pu086EAZG4fP_r6Pnd7Ft366vt6t2AnjkoFb9Q/index.html", + name: "Dapp Example (UniSwap)", + skylink: "EADWpKD0myqH2tZa6xtKebg6kNnwYnI94fl4R8UKgNrmOA", bodyHash: "d6ad2506590bb45b5acc6a8a964a3da4d657354f", metadata: { filename: "/index.html", @@ -73,7 +73,7 @@ function dappExampleCheck(done) { // for the Develop Momentum Application with a trailing /index.html function developMomentumIndexFileCheck(done) { const linkInfo = { - description: "Develop Momentum Index File", + name: "Develop Momentum Index File", skylink: "EAA1fG_ip4C1Vi1Ijvsr1oyr8jpH0Bo9HXya0T3kw-elGw/index.html", bodyHash: "53b44a9d3cfa9b3d66ce5c29976f4383725d3652", metadata: { @@ -90,7 +90,7 @@ function developMomentumIndexFileCheck(done) { // for the Example HTML file on siasky.net function htmlExampleCheck(done) { const linkInfo = { - description: "HTML Example", + name: "HTML Example", skylink: "PAL0w4SdA5rFCDGEutgpeQ50Om-YkBabtXVOJAkmedslKw", bodyHash: "c932fd56f98b6db589e56be8018817f13bb29f72", metadata: { filename: "introduction – Sia API Documentation.html" }, @@ -103,7 +103,7 @@ function htmlExampleCheck(done) { // for the Example image on siasky.net function imageExampleCheck(done) { const linkInfo = { - description: "Image Example", + name: "Image Example", skylink: "IADUs8d9CQjUO34LmdaaNPK_STuZo24rpKVfYW3wPPM2uQ", bodyHash: "313207978d0a88bf2b961f098804e9ab0f82837f", metadata: { filename: "sia-lm.png" }, @@ -116,7 +116,7 @@ function imageExampleCheck(done) { // for the Example JSON file on siasky.net function jsonExampleCheck(done) { const linkInfo = { - description: "JSON Example", + name: "JSON Example", skylink: "AAC0uO43g64ULpyrW0zO3bjEknSFbAhm8c-RFP21EQlmSQ", bodyHash: "198771c3d07d5c7302aadcc0697a7298e5e8ccc3", metadata: { filename: "consensus.json" }, @@ -129,7 +129,7 @@ function jsonExampleCheck(done) { // for the Example PDF file on siasky.net function pdfExampleCheck(done) { const linkInfo = { - description: "PDF Example", + name: "PDF Example", skylink: "XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg", bodyHash: "9bd8162e1575569a9041972f7f62d65887063dc3", metadata: { filename: "sia.pdf" }, @@ -142,7 +142,7 @@ function pdfExampleCheck(done) { // a Random Image. function randomImageCheck(done) { const linkInfo = { - description: "Random Image", + name: "Random Image", skylink: "PAHx7JmsU9EFGbqm5q0LNKT2wKfoJ_mhPI8zWlNEXZ8uOQ/", bodyHash: "4c73c5a0eddd5823be677d7f93bf80cc9338ee9f", metadata: { @@ -159,7 +159,7 @@ function randomImageCheck(done) { // a Random Image with no trailing slash. function randomImageRedirectCheck(done) { const linkInfo = { - description: "Random Image Redirect", + name: "Random Image Redirect", skylink: "PAHx7JmsU9EFGbqm5q0LNKT2wKfoJ_mhPI8zWlNEXZ8uOQ", bodyHash: "4c73c5a0eddd5823be677d7f93bf80cc9338ee9f", metadata: { @@ -175,7 +175,7 @@ function randomImageRedirectCheck(done) { // skyBayCheck returns the result of trying to download the skylink for the SkyBay Application. function skyBayCheck(done) { const linkInfo = { - description: "SkyBay", + name: "SkyBay", skylink: "EABkMjXzxJRpPz0eO0Or5fy2eo-rz3prdigGwRlyNd9mwA/", bodyHash: "25d63937c9734fb08d2749c6517d1b3de8ecb856", metadata: { @@ -191,7 +191,7 @@ function skyBayCheck(done) { // for the SkyBay Application with no trailing slash. function skyBayRedirectCheck(done) { const linkInfo = { - description: "SkyBay Redirect", + name: "SkyBay Redirect", skylink: "EABkMjXzxJRpPz0eO0Or5fy2eo-rz3prdigGwRlyNd9mwA", bodyHash: "25d63937c9734fb08d2749c6517d1b3de8ecb856", metadata: { @@ -206,7 +206,7 @@ function skyBayRedirectCheck(done) { // skyBinCheck returns the result of trying to download the skylink for the SkyBin Application. function skyBinCheck(done) { const linkInfo = { - description: "SkyBin", + name: "SkyBin", skylink: "CAAVU14pB9GRIqCrejD7rlS27HltGGiiCLICzmrBV0wVtA/", bodyHash: "767ec67c417e11b97c5db7dad9ea3b6b27cb0d39", metadata: { filename: "skybin.html" }, @@ -219,7 +219,7 @@ function skyBinCheck(done) { // for the SkyBin Application with no trailing slash. function skyBinRedirectCheck(done) { const linkInfo = { - description: "SkyBin Redirect", + name: "SkyBin Redirect", skylink: "CAAVU14pB9GRIqCrejD7rlS27HltGGiiCLICzmrBV0wVtA", bodyHash: "767ec67c417e11b97c5db7dad9ea3b6b27cb0d39", metadata: { filename: "skybin.html" }, @@ -231,7 +231,7 @@ function skyBinRedirectCheck(done) { // skyGalleryCheck returns the result of trying to download the skylink for the SkyGallery Application. function skyGalleryCheck(done) { const linkInfo = { - description: "SkyGallery", + name: "SkyGallery", skylink: "AADW6GsQcetwDBaDYnGCSTbYjSKY743NtY1A5VRx5sj3Dg/", bodyHash: "077e54054748d278114f1870f8045a162eb73641", metadata: { @@ -365,7 +365,7 @@ function skyGalleryCheck(done) { // for the SkyGallery Application with a trailing /index.html function skyGalleryIndexFileCheck(done) { const linkInfo = { - description: "SkyGallery Index File", + name: "SkyGallery Index File", skylink: "AADW6GsQcetwDBaDYnGCSTbYjSKY743NtY1A5VRx5sj3Dg/index.html", bodyHash: "077e54054748d278114f1870f8045a162eb73641", metadata: { @@ -382,7 +382,7 @@ function skyGalleryIndexFileCheck(done) { // for the SkyGallery Application with no trailing slash. function skyGalleryRedirectCheck(done) { const linkInfo = { - description: "SkyGallery Redirect", + name: "SkyGallery Redirect", skylink: "AADW6GsQcetwDBaDYnGCSTbYjSKY743NtY1A5VRx5sj3Dg", bodyHash: "077e54054748d278114f1870f8045a162eb73641", metadata: { @@ -516,7 +516,7 @@ function skyGalleryRedirectCheck(done) { // for the uncensored library skylink function uncensoredLibraryCheck(done) { const linkInfo = { - description: "Uncensored Library", + name: "Uncensored Library", skylink: "AAC5glnZyNJ4Ieb4MhnYJGtID6qdMqEjl0or5EvEMt7bWQ", bodyHash: "60da6cb958699c5acd7f2a2911656ff32fca89a7", metadata: { @@ -538,7 +538,7 @@ function uncensoredLibraryCheck(done) { // for the Uniswap Application with a trailing /index.html function uniswapIndexFileCheck(done) { const linkInfo = { - description: "Uniswap Skylink Index File", + name: "Uniswap Skylink Index File", skylink: "IAC6CkhNYuWZqMVr1gob1B6tPg4MrBGRzTaDvAIAeu9A9w/index.html", bodyHash: "3965f9a7def085b3a764ddc76a528eda38d72359", metadata: { @@ -551,53 +551,47 @@ function uniswapIndexFileCheck(done) { skylinkVerification(done, linkInfo); } -// skylinkVerification verifies a skylink against known information provided in -// the linkInfo. -function skylinkVerification(done, linkInfo) { +// verifies a skylink against provided information +function skylinkVerification(done, { name, skylink, bodyHash, metadata }) { const time = process.hrtime(); // Create the query for the skylink - const query = `http://${process.env.PORTAL_URL}/${linkInfo.skylink}?nocache=true`; + const query = `http://${process.env.PORTAL_URL}/${skylink}?nocache=true`; // Get the Skylink superagent .get(query) .responseType("blob") - .end((err, res) => { - // Record the statusCode - const statusCode = (res && res.statusCode) || (err && err.statusCode) || null; - let info = null; + .then( + (response) => { + const entry = { name, up: true, statusCode: response.statusCode, time: getTimeDiff(time) }; + const info = {}; - // Determine if the skylink is up. Start with checking if there was an - // error in the request. - let up = err === null; - if (up) { - // Check if the response body is valid by checking against the known - // hash - const validBody = hash(res.body) === linkInfo.bodyHash; - // Check if the metadata is valid - const metadata = res.header["skynet-file-metadata"] ? JSON.parse(res.header["skynet-file-metadata"]) : null; - const validMetadata = isEqual(metadata, linkInfo.metadata); - // Redetermine if the Skylink is up based on the results from the body - // and metadata hash checks - up = up && validBody && validMetadata; + // Check if the response body is valid by checking against the known hash + if (hash(response.body) !== bodyHash) { + entry.up = false; + info.body = { valid: false, hash: { expected: bodyHash, current: hash(response.body) } }; + } - info = { - body: { valid: validBody }, - metadata: { valid: validMetadata, diff: detailedDiff(metadata, linkInfo.metadata) }, - }; + // Check if the metadata is valid by deep comparing expected value with response + const expectedMetadata = + response.header["skynet-file-metadata"] && JSON.parse(response.header["skynet-file-metadata"]); + if (!isEqual(expectedMetadata, metadata)) { + entry.up = false; + info.metadata = { valid: false, diff: detailedDiff(expectedMetadata, metadata) }; + } + + if (!isEmpty(info)) entry.info = info; // add info only if it exists + + done(entry); // Return the entry information + }, + (error) => { + const statusCode = error.statusCode || error.status; + const entry = { name, up: false, statusCode, time: getTimeDiff(time) }; + + done(entry); // Return the entry information } - - // Return the entry information - done({ - name: linkInfo.description, - up, - info, - statusCode, - time: checks.catchRequestTime(time), - critical: true, - }); - }); + ); } module.exports.verboseChecks = [ diff --git a/packages/health-check/src/db.js b/packages/health-check/src/db.js index 4b6ed657..48a734d6 100644 --- a/packages/health-check/src/db.js +++ b/packages/health-check/src/db.js @@ -1,10 +1,13 @@ +const fs = require("fs"); const low = require("lowdb"); const FileSync = require("lowdb/adapters/FileSync"); const Memory = require("lowdb/adapters/Memory"); +if (!fs.existsSync("state")) fs.mkdirSync("state"); + const adapter = process.env.NODE_ENV === "production" ? new FileSync("state/state.json") : new Memory(); const db = low(adapter); -db.defaults({ entries: [] }).write(); +db.defaults({ disabled: false, entries: [] }).write(); module.exports = db; diff --git a/packages/health-check/src/index.js b/packages/health-check/src/index.js index 02669ad5..f39c3308 100644 --- a/packages/health-check/src/index.js +++ b/packages/health-check/src/index.js @@ -17,7 +17,9 @@ const server = express(); server.use(bodyparser.urlencoded({ extended: false })); server.use(bodyparser.json()); -server.get("/health-check", require("./endpointHealthCheck")); +server.get("/health-check", require("./api/index")); +server.get("/health-check/recent", require("./api/recent")); +server.get("/health-check/all", require("./api/all")); server.listen(port, host, (error) => { if (error) throw error; diff --git a/packages/health-check/src/schedule.js b/packages/health-check/src/schedule.js index 252f2518..72dc321b 100644 --- a/packages/health-check/src/schedule.js +++ b/packages/health-check/src/schedule.js @@ -1,13 +1,13 @@ const schedule = require("node-schedule"); const db = require("./db"); -const { basicChecks } = require("./basicChecks"); -const { verboseChecks } = require("./verboseChecks"); +const { criticalChecks } = require("./checks/critical"); +const { verboseChecks } = require("./checks/verbose"); -// execute the basic health-check script every 5 minutes +// execute the critical health-check script every 5 minutes const basicJob = schedule.scheduleJob("*/5 * * * *", async () => { const entry = { date: new Date().toISOString(), checks: [] }; - entry.checks = await Promise.all(basicChecks.map((check) => new Promise(check))); + entry.checks = await Promise.all(criticalChecks.map((check) => new Promise(check))); db.get("entries").push(entry).write(); }); diff --git a/packages/health-check/src/utils.js b/packages/health-check/src/utils.js new file mode 100644 index 00000000..e6cc72f4 --- /dev/null +++ b/packages/health-check/src/utils.js @@ -0,0 +1,8 @@ +// return the time between start and now in milliseconds +function getTimeDiff(start) { + const diff = process.hrtime(start); + + return Math.round((diff[0] * 1e9 + diff[1]) / 1e6); // msec +} + +module.exports = { getTimeDiff }; From 19b8caf81a26721dccbf66facc116cf6ce9b8d54 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Wed, 9 Sep 2020 14:53:05 +0200 Subject: [PATCH 31/44] fixed code review issues --- packages/health-check/src/api/disabled.js | 8 ++++++++ packages/health-check/src/checks/critical.js | 6 +++--- packages/health-check/src/checks/verbose.js | 21 ++++++++++---------- packages/health-check/src/index.js | 1 + packages/health-check/src/utils.js | 4 ++-- 5 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 packages/health-check/src/api/disabled.js diff --git a/packages/health-check/src/api/disabled.js b/packages/health-check/src/api/disabled.js new file mode 100644 index 00000000..6471ad2f --- /dev/null +++ b/packages/health-check/src/api/disabled.js @@ -0,0 +1,8 @@ +const db = require("../db"); + +// returns a disabled flag status +module.exports = (req, res) => { + const disabled = db.get("disabled").value(); + + res.send({ disabled }); +}; diff --git a/packages/health-check/src/checks/critical.js b/packages/health-check/src/checks/critical.js index f737995f..d8e41251 100644 --- a/packages/health-check/src/checks/critical.js +++ b/packages/health-check/src/checks/critical.js @@ -1,6 +1,6 @@ const superagent = require("superagent"); const { StatusCodes } = require("http-status-codes"); -const { getTimeDiff } = require("../utils"); +const { calculateElapsedTime } = require("../utils"); // uploadCheck returns the result of uploading a sample file async function uploadCheck(done) { @@ -16,7 +16,7 @@ async function uploadCheck(done) { name: "upload_file", up: statusCode === StatusCodes.OK, statusCode, - time: getTimeDiff(time), + time: calculateElapsedTime(time), critical: true, }); }); @@ -40,7 +40,7 @@ async function downloadCheck(done) { name: "download_file", up: statusCode === StatusCodes.OK, statusCode, - time: getTimeDiff(time), + time: calculateElapsedTime(time), critical: true, }); } diff --git a/packages/health-check/src/checks/verbose.js b/packages/health-check/src/checks/verbose.js index 26c5ab71..3374cd0a 100644 --- a/packages/health-check/src/checks/verbose.js +++ b/packages/health-check/src/checks/verbose.js @@ -1,8 +1,8 @@ const superagent = require("superagent"); const hash = require("object-hash"); const { detailedDiff } = require("deep-object-diff"); -const { isEqual, isEmpty } = require("lodash"); -const { getTimeDiff } = require("../utils"); +const { isEqual } = require("lodash"); +const { calculateElapsedTime } = require("../utils"); // audioExampleCheck returns the result of trying to download the skylink // for the Example audio file on siasky.net @@ -564,30 +564,31 @@ function skylinkVerification(done, { name, skylink, bodyHash, metadata }) { .responseType("blob") .then( (response) => { - const entry = { name, up: true, statusCode: response.statusCode, time: getTimeDiff(time) }; + const entry = { name, up: true, statusCode: response.statusCode, time: calculateElapsedTime(time) }; const info = {}; // Check if the response body is valid by checking against the known hash - if (hash(response.body) !== bodyHash) { + const currentBodyHash = hash(response.body); + if (currentBodyHash !== bodyHash) { entry.up = false; - info.body = { valid: false, hash: { expected: bodyHash, current: hash(response.body) } }; + info.bodyHash = { expected: bodyHash, current: currentBodyHash }; } // Check if the metadata is valid by deep comparing expected value with response - const expectedMetadata = + const currentMetadata = response.header["skynet-file-metadata"] && JSON.parse(response.header["skynet-file-metadata"]); - if (!isEqual(expectedMetadata, metadata)) { + if (!isEqual(currentMetadata, metadata)) { entry.up = false; - info.metadata = { valid: false, diff: detailedDiff(expectedMetadata, metadata) }; + info.metadata = detailedDiff(currentMetadata, metadata); } - if (!isEmpty(info)) entry.info = info; // add info only if it exists + if (Object.keys(info).length) entry.info = info; // add info only if it exists done(entry); // Return the entry information }, (error) => { const statusCode = error.statusCode || error.status; - const entry = { name, up: false, statusCode, time: getTimeDiff(time) }; + const entry = { name, up: false, statusCode, time: calculateElapsedTime(time) }; done(entry); // Return the entry information } diff --git a/packages/health-check/src/index.js b/packages/health-check/src/index.js index f39c3308..28838845 100644 --- a/packages/health-check/src/index.js +++ b/packages/health-check/src/index.js @@ -20,6 +20,7 @@ server.use(bodyparser.json()); server.get("/health-check", require("./api/index")); server.get("/health-check/recent", require("./api/recent")); server.get("/health-check/all", require("./api/all")); +server.get("/health-check/disabled", require("./api/disabled")); server.listen(port, host, (error) => { if (error) throw error; diff --git a/packages/health-check/src/utils.js b/packages/health-check/src/utils.js index e6cc72f4..d95880c1 100644 --- a/packages/health-check/src/utils.js +++ b/packages/health-check/src/utils.js @@ -1,8 +1,8 @@ // return the time between start and now in milliseconds -function getTimeDiff(start) { +function calculateElapsedTime(start) { const diff = process.hrtime(start); return Math.round((diff[0] * 1e9 + diff[1]) / 1e6); // msec } -module.exports = { getTimeDiff }; +module.exports = { calculateElapsedTime }; From 64cd7b135c136782f49b0969b1bdb9fe62b28e37 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Wed, 9 Sep 2020 16:08:10 +0200 Subject: [PATCH 32/44] fix health-check dockerfile --- packages/health-check/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/health-check/Dockerfile b/packages/health-check/Dockerfile index 1378bca4..e0b1c224 100644 --- a/packages/health-check/Dockerfile +++ b/packages/health-check/Dockerfile @@ -4,8 +4,8 @@ WORKDIR /usr/app COPY package.json . RUN yarn --no-lockfile -COPY src/* src/ -COPY cli/* cli/ +COPY src src +COPY cli cli EXPOSE 3100 ENV NODE_ENV production From 307d736a69b67cfea179c61f6d415f889c809da6 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Sep 2020 12:15:54 +0200 Subject: [PATCH 33/44] restructure health-check architecture --- packages/health-check/src/api/all.js | 8 --- packages/health-check/src/api/critical.js | 8 +++ packages/health-check/src/api/index.js | 78 +++++++++++++---------- packages/health-check/src/api/recent.js | 16 ----- packages/health-check/src/api/verbose.js | 8 +++ packages/health-check/src/db.js | 4 +- packages/health-check/src/index.js | 4 +- packages/health-check/src/schedule.js | 10 +-- 8 files changed, 71 insertions(+), 65 deletions(-) delete mode 100644 packages/health-check/src/api/all.js create mode 100644 packages/health-check/src/api/critical.js delete mode 100644 packages/health-check/src/api/recent.js create mode 100644 packages/health-check/src/api/verbose.js diff --git a/packages/health-check/src/api/all.js b/packages/health-check/src/api/all.js deleted file mode 100644 index 782e0e52..00000000 --- a/packages/health-check/src/api/all.js +++ /dev/null @@ -1,8 +0,0 @@ -const db = require("../db"); - -// returns all health check entries -module.exports = (req, res) => { - const entries = db.get("entries").orderBy("date", "desc").value(); - - res.send(entries); -}; diff --git a/packages/health-check/src/api/critical.js b/packages/health-check/src/api/critical.js new file mode 100644 index 00000000..6837d17e --- /dev/null +++ b/packages/health-check/src/api/critical.js @@ -0,0 +1,8 @@ +const db = require("../db"); + +// returns all critical health check entries +module.exports = (req, res) => { + const entries = db.get("critical").orderBy("date", "desc").value(); + + res.send(entries); +}; diff --git a/packages/health-check/src/api/index.js b/packages/health-check/src/api/index.js index 733fb61d..0f70c212 100644 --- a/packages/health-check/src/api/index.js +++ b/packages/health-check/src/api/index.js @@ -2,61 +2,75 @@ const { StatusCodes } = require("http-status-codes"); const { sum, sumBy } = require("lodash"); const db = require("../db"); -// getStatus returns the server's current health check status -function getStatus() { - const disabled = db.get("disabled").value(); +/** + * Get status code that should be returned in the API response. + * - OK (200) in case everything is healthy + * - SERVICE_UNAVAILABLE (503) in case of any failures or if disabled + */ +function getStatusCode() { + // check whether the portal has been manually disabled + const disabled = getDisabled(); if (disabled) { return StatusCodes.SERVICE_UNAVAILABLE; } - // Grab entry element from DB - const entry = db.get("entries").orderBy("date", "desc").head().value(); + // grab one most recent critical entry element from DB + const entry = getCurrentCriticalEntry(); - // Check that every critical check entry is up - if (entry && entry.checks.every(({ up, critical }) => up && critical)) { + // find out whether every check in the entry is up + if (entry && entry.checks.every(({ up }) => up)) { return StatusCodes.OK; } - // At least one check failed + // in case at least one check failed return StatusCodes.SERVICE_UNAVAILABLE; } -// getTimeout returns the average time out from a sample of 10 health check -// entries. -function getTimeout() { - if (getStatus() === StatusCodes.SERVICE_UNAVAILABLE) { - return 0; - } - - // Grab 10 entries from the database as a sample to determine the average - // timeout for the server. +/** + * Get the sample of most recent critical entries and + * calculate the avarage response time of all of them + */ +function getAvarageResponseTime() { + // get most recent 10 successfull checks for the calculation const sample = db - .get("entries") + .get("critical") .orderBy("date", "desc") - .filter(({ checks }) => checks.every(({ up, critical }) => up && critical)) + .filter(({ checks }) => checks.every(({ up }) => up)) .take(10) .value(); - // Return average timeout + // calculate avarage time of response return Math.round(sum(sample.map(({ checks }) => sumBy(checks, "time"))) / sample.size); } -// getEntriesSinceYesterday gets the health check entries since yesterday -function getEntriesSinceYesterday() { - const yesterday = new Date(); +/** + * Get one, most current critical entry + */ +function getCurrentCriticalEntry() { + return db.get("critical").orderBy("date", "desc").head().value(); +} - yesterday.setDate(yesterday.getDate() - 1); - - return db - .get("entries") - .orderBy("date", "desc") - .filter(({ date }) => date >= yesterday.toISOString()) - .value(); +/** + * Get the disabled flag state (manual portal disable) + */ +function getDisabled() { + return db.get("disabled").value(); } module.exports = (req, res) => { + const statusCode = getStatusCode(); + const timeout = statusCode === StatusCodes.OK ? getAvarageResponseTime() : 0; + + // We want to delay the response for the load balancer to be able to prioritize + // servers based on the successful response time of thid endpoint. Load balancer + // will pull the server if the response is an error so there is no point in delaying + // failures, hence 0 timeout on those. setTimeout(() => { - res.status(getStatus()).send(getEntriesSinceYesterday()); - }, getTimeout()); + // include some health information in the response body + const entry = getCurrentCriticalEntry(); + const disabled = getDisabled(); + + res.status(statusCode).send({ disabled, entry }); + }, timeout); }; diff --git a/packages/health-check/src/api/recent.js b/packages/health-check/src/api/recent.js deleted file mode 100644 index 600b5814..00000000 --- a/packages/health-check/src/api/recent.js +++ /dev/null @@ -1,16 +0,0 @@ -const db = require("../db"); - -// returns all health check entries that are not older than one day -module.exports = (req, res) => { - const yesterday = new Date(); - - yesterday.setDate(yesterday.getDate() - 1); - - const entries = db - .get("entries") - .orderBy("date", "desc") - .filter(({ date }) => date >= yesterday.toISOString()) - .value(); - - res.send(entries); -}; diff --git a/packages/health-check/src/api/verbose.js b/packages/health-check/src/api/verbose.js new file mode 100644 index 00000000..01a3a666 --- /dev/null +++ b/packages/health-check/src/api/verbose.js @@ -0,0 +1,8 @@ +const db = require("../db"); + +// returns all verbose health check entries +module.exports = (req, res) => { + const entries = db.get("verbose").orderBy("date", "desc").value(); + + res.send(entries); +}; diff --git a/packages/health-check/src/db.js b/packages/health-check/src/db.js index 48a734d6..bb4e7aad 100644 --- a/packages/health-check/src/db.js +++ b/packages/health-check/src/db.js @@ -5,9 +5,9 @@ const Memory = require("lowdb/adapters/Memory"); if (!fs.existsSync("state")) fs.mkdirSync("state"); -const adapter = process.env.NODE_ENV === "production" ? new FileSync("state/state.json") : new Memory(); +const adapter = new FileSync("state/state.json"); const db = low(adapter); -db.defaults({ disabled: false, entries: [] }).write(); +db.defaults({ disabled: false, critical: [], verbose: [] }).write(); module.exports = db; diff --git a/packages/health-check/src/index.js b/packages/health-check/src/index.js index 28838845..169e005b 100644 --- a/packages/health-check/src/index.js +++ b/packages/health-check/src/index.js @@ -18,8 +18,8 @@ server.use(bodyparser.urlencoded({ extended: false })); server.use(bodyparser.json()); server.get("/health-check", require("./api/index")); -server.get("/health-check/recent", require("./api/recent")); -server.get("/health-check/all", require("./api/all")); +server.get("/health-check/critical", require("./api/critical")); +server.get("/health-check/verbose", require("./api/verbose")); server.get("/health-check/disabled", require("./api/disabled")); server.listen(port, host, (error) => { diff --git a/packages/health-check/src/schedule.js b/packages/health-check/src/schedule.js index 72dc321b..0901361d 100644 --- a/packages/health-check/src/schedule.js +++ b/packages/health-check/src/schedule.js @@ -4,12 +4,12 @@ const { criticalChecks } = require("./checks/critical"); const { verboseChecks } = require("./checks/verbose"); // execute the critical health-check script every 5 minutes -const basicJob = schedule.scheduleJob("*/5 * * * *", async () => { +const criticalJob = schedule.scheduleJob("*/5 * * * *", async () => { const entry = { date: new Date().toISOString(), checks: [] }; entry.checks = await Promise.all(criticalChecks.map((check) => new Promise(check))); - db.get("entries").push(entry).write(); + db.get("critical").push(entry).write(); }); // execute the verbose health-check script once per hour @@ -18,11 +18,11 @@ const verboseJob = schedule.scheduleJob("0 * * * *", async () => { entry.checks = await Promise.all(verboseChecks.map((check) => new Promise(check))); - db.get("entries").push(entry).write(); + db.get("verbose").push(entry).write(); }); // Launch Health check jobs setTimeout(() => { - basicJob.invoke(); + criticalJob.invoke(); verboseJob.invoke(); -}, 60 * 1000); // delay for 60s to give other services time to start up +}, 60 * 0); // delay for 60s to give other services time to start up From c08d53f6e0ec86184a5dae55e776e36437d7f923 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Sep 2020 12:42:37 +0200 Subject: [PATCH 34/44] drop critical: true from existing checks --- packages/health-check/src/checks/critical.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/health-check/src/checks/critical.js b/packages/health-check/src/checks/critical.js index d8e41251..300deab1 100644 --- a/packages/health-check/src/checks/critical.js +++ b/packages/health-check/src/checks/critical.js @@ -17,7 +17,6 @@ async function uploadCheck(done) { up: statusCode === StatusCodes.OK, statusCode, time: calculateElapsedTime(time), - critical: true, }); }); } @@ -41,7 +40,6 @@ async function downloadCheck(done) { up: statusCode === StatusCodes.OK, statusCode, time: calculateElapsedTime(time), - critical: true, }); } From ec4655f5818413671616cedd70c96aa78c907be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Wypch=C5=82o?= Date: Thu, 10 Sep 2020 13:49:26 +0200 Subject: [PATCH 35/44] Apply suggestions from code review Co-authored-by: Ivaylo Novakov --- packages/health-check/src/api/index.js | 4 ++-- packages/health-check/src/schedule.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/health-check/src/api/index.js b/packages/health-check/src/api/index.js index 0f70c212..0d1ac900 100644 --- a/packages/health-check/src/api/index.js +++ b/packages/health-check/src/api/index.js @@ -15,7 +15,7 @@ function getStatusCode() { return StatusCodes.SERVICE_UNAVAILABLE; } - // grab one most recent critical entry element from DB + // grab the most recent critical entry element from DB const entry = getCurrentCriticalEntry(); // find out whether every check in the entry is up @@ -63,7 +63,7 @@ module.exports = (req, res) => { const timeout = statusCode === StatusCodes.OK ? getAvarageResponseTime() : 0; // We want to delay the response for the load balancer to be able to prioritize - // servers based on the successful response time of thid endpoint. Load balancer + // servers based on the successful response time of this endpoint. Load balancer // will pull the server if the response is an error so there is no point in delaying // failures, hence 0 timeout on those. setTimeout(() => { diff --git a/packages/health-check/src/schedule.js b/packages/health-check/src/schedule.js index 0901361d..7a2c6957 100644 --- a/packages/health-check/src/schedule.js +++ b/packages/health-check/src/schedule.js @@ -25,4 +25,4 @@ const verboseJob = schedule.scheduleJob("0 * * * *", async () => { setTimeout(() => { criticalJob.invoke(); verboseJob.invoke(); -}, 60 * 0); // delay for 60s to give other services time to start up +}, 60 * 1000); // delay for 60s to give other services time to start up From 6e0f387cf113010133c2cf1ed8689022c9fea2fc Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Sep 2020 14:03:56 +0200 Subject: [PATCH 36/44] code review changes --- packages/health-check/src/api/critical.js | 8 +++++++- packages/health-check/src/api/index.js | 9 ++++----- packages/health-check/src/api/verbose.js | 8 +++++++- packages/health-check/src/utils.js | 17 +++++++++++++++-- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/packages/health-check/src/api/critical.js b/packages/health-check/src/api/critical.js index 6837d17e..a84b4d25 100644 --- a/packages/health-check/src/api/critical.js +++ b/packages/health-check/src/api/critical.js @@ -1,8 +1,14 @@ const db = require("../db"); +const { getYesterdayISOString } = require("../utils"); // returns all critical health check entries module.exports = (req, res) => { - const entries = db.get("critical").orderBy("date", "desc").value(); + const yesterday = getYesterdayISOString(); + const entries = db + .get("critical") + .orderBy("date", "desc") + .filter(({ date }) => date > yesterday) + .value(); res.send(entries); }; diff --git a/packages/health-check/src/api/index.js b/packages/health-check/src/api/index.js index 0d1ac900..387a1e12 100644 --- a/packages/health-check/src/api/index.js +++ b/packages/health-check/src/api/index.js @@ -18,13 +18,12 @@ function getStatusCode() { // grab the most recent critical entry element from DB const entry = getCurrentCriticalEntry(); - // find out whether every check in the entry is up - if (entry && entry.checks.every(({ up }) => up)) { - return StatusCodes.OK; + // in case there is no entry yet or at least one check failed in the most recent entry + if (!entry || entry.checks.some(({ up }) => !up)) { + return StatusCodes.SERVICE_UNAVAILABLE; } - // in case at least one check failed - return StatusCodes.SERVICE_UNAVAILABLE; + return StatusCodes.OK; } /** diff --git a/packages/health-check/src/api/verbose.js b/packages/health-check/src/api/verbose.js index 01a3a666..12acaa97 100644 --- a/packages/health-check/src/api/verbose.js +++ b/packages/health-check/src/api/verbose.js @@ -1,8 +1,14 @@ const db = require("../db"); +const { getYesterdayISOString } = require("../utils"); // returns all verbose health check entries module.exports = (req, res) => { - const entries = db.get("verbose").orderBy("date", "desc").value(); + const yesterday = getYesterdayISOString(); + const entries = db + .get("verbose") + .orderBy("date", "desc") + .filter(({ date }) => date > yesterday) + .value(); res.send(entries); }; diff --git a/packages/health-check/src/utils.js b/packages/health-check/src/utils.js index d95880c1..bd6bc79c 100644 --- a/packages/health-check/src/utils.js +++ b/packages/health-check/src/utils.js @@ -1,8 +1,21 @@ -// return the time between start and now in milliseconds +/** + * Get the time between start and now in milliseconds + */ function calculateElapsedTime(start) { const diff = process.hrtime(start); return Math.round((diff[0] * 1e9 + diff[1]) / 1e6); // msec } -module.exports = { calculateElapsedTime }; +/** + * Get the ISO string with yesterday's date set (- 24 hours) + */ +function getYesterdayISOString() { + const date = new Date(); + + date.setDate(date.getDate() - 1); + + return date.toISOString(); +} + +module.exports = { calculateElapsedTime, getYesterdayISOString }; From 70fd6b0f8fdb6a50fb9a1dac34a85c0d6b56a565 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Sep 2020 14:05:21 +0200 Subject: [PATCH 37/44] typo --- packages/health-check/src/api/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/health-check/src/api/index.js b/packages/health-check/src/api/index.js index 387a1e12..a2f3f61b 100644 --- a/packages/health-check/src/api/index.js +++ b/packages/health-check/src/api/index.js @@ -28,9 +28,9 @@ function getStatusCode() { /** * Get the sample of most recent critical entries and - * calculate the avarage response time of all of them + * calculate the average response time of all of them */ -function getAvarageResponseTime() { +function getAverageResponseTime() { // get most recent 10 successfull checks for the calculation const sample = db .get("critical") @@ -39,7 +39,7 @@ function getAvarageResponseTime() { .take(10) .value(); - // calculate avarage time of response + // calculate average time of response return Math.round(sum(sample.map(({ checks }) => sumBy(checks, "time"))) / sample.size); } @@ -59,7 +59,7 @@ function getDisabled() { module.exports = (req, res) => { const statusCode = getStatusCode(); - const timeout = statusCode === StatusCodes.OK ? getAvarageResponseTime() : 0; + const timeout = statusCode === StatusCodes.OK ? getAverageResponseTime() : 0; // We want to delay the response for the load balancer to be able to prioritize // servers based on the successful response time of this endpoint. Load balancer From 394ae44aa9dda7eae4080d5b2cf891d3447561cb Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Sep 2020 14:07:24 +0200 Subject: [PATCH 38/44] rename getCurrent -> getMostRecent --- packages/health-check/src/api/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/health-check/src/api/index.js b/packages/health-check/src/api/index.js index a2f3f61b..641b154a 100644 --- a/packages/health-check/src/api/index.js +++ b/packages/health-check/src/api/index.js @@ -16,7 +16,7 @@ function getStatusCode() { } // grab the most recent critical entry element from DB - const entry = getCurrentCriticalEntry(); + const entry = getMostRecentCriticalEntry(); // in case there is no entry yet or at least one check failed in the most recent entry if (!entry || entry.checks.some(({ up }) => !up)) { @@ -46,7 +46,7 @@ function getAverageResponseTime() { /** * Get one, most current critical entry */ -function getCurrentCriticalEntry() { +function getMostRecentCriticalEntry() { return db.get("critical").orderBy("date", "desc").head().value(); } @@ -67,7 +67,7 @@ module.exports = (req, res) => { // failures, hence 0 timeout on those. setTimeout(() => { // include some health information in the response body - const entry = getCurrentCriticalEntry(); + const entry = getMostRecentCriticalEntry(); const disabled = getDisabled(); res.status(statusCode).send({ disabled, entry }); From 2e240e2819c55acb882be09ca4410e806b9f46a3 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Sep 2020 14:13:28 +0200 Subject: [PATCH 39/44] simplify values assignment --- packages/health-check/src/schedule.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/health-check/src/schedule.js b/packages/health-check/src/schedule.js index 7a2c6957..70f4d44b 100644 --- a/packages/health-check/src/schedule.js +++ b/packages/health-check/src/schedule.js @@ -5,18 +5,20 @@ const { verboseChecks } = require("./checks/verbose"); // execute the critical health-check script every 5 minutes const criticalJob = schedule.scheduleJob("*/5 * * * *", async () => { - const entry = { date: new Date().toISOString(), checks: [] }; - - entry.checks = await Promise.all(criticalChecks.map((check) => new Promise(check))); + const entry = { + date: new Date().toISOString(), + checks: await Promise.all(criticalChecks.map((check) => new Promise(check))), + }; db.get("critical").push(entry).write(); }); // execute the verbose health-check script once per hour const verboseJob = schedule.scheduleJob("0 * * * *", async () => { - const entry = { date: new Date().toISOString(), checks: [] }; - - entry.checks = await Promise.all(verboseChecks.map((check) => new Promise(check))); + const entry = { + date: new Date().toISOString(), + checks: await Promise.all(verboseChecks.map((check) => new Promise(check))), + }; db.get("verbose").push(entry).write(); }); From 20362fe7c507f1c02f1e9eee7d0f8f036e8993c6 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Sep 2020 15:16:31 +0200 Subject: [PATCH 40/44] fix health checks --- packages/health-check/src/checks/verbose.js | 478 +++++++++++++++++++- setup-scripts/health-checker.py | 2 +- 2 files changed, 474 insertions(+), 6 deletions(-) diff --git a/packages/health-check/src/checks/verbose.js b/packages/health-check/src/checks/verbose.js index 3374cd0a..c35c291d 100644 --- a/packages/health-check/src/checks/verbose.js +++ b/packages/health-check/src/checks/verbose.js @@ -60,9 +60,477 @@ function dappExampleCheck(done) { skylink: "EADWpKD0myqH2tZa6xtKebg6kNnwYnI94fl4R8UKgNrmOA", bodyHash: "d6ad2506590bb45b5acc6a8a964a3da4d657354f", metadata: { - filename: "/index.html", - length: 4131, - subfiles: { "index.html": { filename: "index.html", contenttype: "text/html", len: 4131 } }, + filename: "build", + length: 15578459, + subfiles: { + "451.html": { + filename: "451.html", + contenttype: "text/html", + offset: 40966, + len: 200, + }, + "asset-manifest.json": { + filename: "asset-manifest.json", + contenttype: "application/json", + offset: 35832, + len: 5134, + }, + "favicon.ico": { + filename: "favicon.ico", + contenttype: "image/vnd.microsoft.icon", + len: 31701, + }, + "index.html": { + filename: "index.html", + contenttype: "text/html", + offset: 31701, + len: 4131, + }, + "locales/de.json": { + filename: "locales/de.json", + contenttype: "application/json", + offset: 15542609, + len: 4376, + }, + "locales/en.json": { + filename: "locales/en.json", + contenttype: "application/json", + offset: 15558827, + len: 4049, + }, + "locales/es-AR.json": { + filename: "locales/es-AR.json", + contenttype: "application/json", + offset: 15551984, + len: 3624, + }, + "locales/es-US.json": { + filename: "locales/es-US.json", + contenttype: "application/json", + offset: 15574829, + len: 3630, + }, + "locales/it-IT.json": { + filename: "locales/it-IT.json", + contenttype: "application/json", + offset: 15538386, + len: 4223, + }, + "locales/ro.json": { + filename: "locales/ro.json", + contenttype: "application/json", + offset: 15562876, + len: 3794, + }, + "locales/ru.json": { + filename: "locales/ru.json", + contenttype: "application/json", + offset: 15546985, + len: 4999, + }, + "locales/vi.json": { + filename: "locales/vi.json", + contenttype: "application/json", + offset: 15569928, + len: 4901, + }, + "locales/zh-CN.json": { + filename: "locales/zh-CN.json", + contenttype: "application/json", + offset: 15555608, + len: 3219, + }, + "locales/zh-TW.json": { + filename: "locales/zh-TW.json", + contenttype: "application/json", + offset: 15566670, + len: 3258, + }, + "manifest.json": { + filename: "manifest.json", + contenttype: "application/json", + offset: 41166, + len: 297, + }, + "precache-manifest.cd4677068c6058f8626d6818e2c12fd3.js": { + filename: "precache-manifest.cd4677068c6058f8626d6818e2c12fd3.js", + contenttype: "text/javascript", + offset: 41463, + len: 4721, + }, + "service-worker.js": { + filename: "service-worker.js", + contenttype: "text/javascript", + offset: 46184, + len: 1185, + }, + "static/css/0.07de6c03.chunk.css": { + filename: "static/css/0.07de6c03.chunk.css", + contenttype: "text/css", + offset: 15537249, + len: 285, + }, + "static/css/0.07de6c03.chunk.css.map": { + filename: "static/css/0.07de6c03.chunk.css.map", + contenttype: "application/octet-stream", + offset: 15537818, + len: 568, + }, + "static/css/5.d75e0ccb.chunk.css": { + filename: "static/css/5.d75e0ccb.chunk.css", + contenttype: "text/css", + offset: 15537534, + len: 284, + }, + "static/css/5.d75e0ccb.chunk.css.map": { + filename: "static/css/5.d75e0ccb.chunk.css.map", + contenttype: "application/octet-stream", + offset: 15536511, + len: 738, + }, + "static/js/0.58b0f69f.chunk.js": { + filename: "static/js/0.58b0f69f.chunk.js", + contenttype: "text/javascript", + offset: 7300150, + len: 30029, + }, + "static/js/0.58b0f69f.chunk.js.map": { + filename: "static/js/0.58b0f69f.chunk.js.map", + contenttype: "application/octet-stream", + offset: 12111459, + len: 81144, + }, + "static/js/1.19c370e0.chunk.js": { + filename: "static/js/1.19c370e0.chunk.js", + contenttype: "text/javascript", + offset: 15495781, + len: 40203, + }, + "static/js/1.19c370e0.chunk.js.map": { + filename: "static/js/1.19c370e0.chunk.js.map", + contenttype: "application/octet-stream", + offset: 7330179, + len: 104594, + }, + "static/js/10.8ea29dcd.chunk.js": { + filename: "static/js/10.8ea29dcd.chunk.js", + contenttype: "text/javascript", + offset: 15483299, + len: 12345, + }, + "static/js/10.8ea29dcd.chunk.js.map": { + filename: "static/js/10.8ea29dcd.chunk.js.map", + contenttype: "application/octet-stream", + offset: 14524416, + len: 30393, + }, + "static/js/11.764b8915.chunk.js": { + filename: "static/js/11.764b8915.chunk.js", + contenttype: "text/javascript", + offset: 12208196, + len: 7103, + }, + "static/js/11.764b8915.chunk.js.map": { + filename: "static/js/11.764b8915.chunk.js.map", + contenttype: "application/octet-stream", + offset: 12192603, + len: 15593, + }, + "static/js/12.88d4fbe5.chunk.js": { + filename: "static/js/12.88d4fbe5.chunk.js", + contenttype: "text/javascript", + offset: 12055261, + len: 16721, + }, + "static/js/12.88d4fbe5.chunk.js.map": { + filename: "static/js/12.88d4fbe5.chunk.js.map", + contenttype: "application/octet-stream", + offset: 14460215, + len: 46695, + }, + "static/js/13.ea207f69.chunk.js": { + filename: "static/js/13.ea207f69.chunk.js", + contenttype: "text/javascript", + offset: 7168280, + len: 347, + }, + "static/js/13.ea207f69.chunk.js.map": { + filename: "static/js/13.ea207f69.chunk.js.map", + contenttype: "application/octet-stream", + offset: 6928538, + len: 563, + }, + "static/js/14.d8bc0d4c.chunk.js": { + filename: "static/js/14.d8bc0d4c.chunk.js", + contenttype: "text/javascript", + offset: 12870711, + len: 336, + }, + "static/js/14.d8bc0d4c.chunk.js.map": { + filename: "static/js/14.d8bc0d4c.chunk.js.map", + contenttype: "application/octet-stream", + offset: 15535984, + len: 527, + }, + "static/js/15.e6215497.chunk.js": { + filename: "static/js/15.e6215497.chunk.js", + contenttype: "text/javascript", + offset: 15495644, + len: 137, + }, + "static/js/15.e6215497.chunk.js.map": { + filename: "static/js/15.e6215497.chunk.js.map", + contenttype: "application/octet-stream", + offset: 6928431, + len: 107, + }, + "static/js/2.f6da9598.chunk.js": { + filename: "static/js/2.f6da9598.chunk.js", + contenttype: "text/javascript", + offset: 14506910, + len: 17506, + }, + "static/js/2.f6da9598.chunk.js.map": { + filename: "static/js/2.f6da9598.chunk.js.map", + contenttype: "application/octet-stream", + offset: 12071982, + len: 39477, + }, + "static/js/5.5cc0868a.chunk.js": { + filename: "static/js/5.5cc0868a.chunk.js", + contenttype: "text/javascript", + offset: 10199338, + len: 1842002, + }, + "static/js/5.5cc0868a.chunk.js.LICENSE": { + filename: "static/js/5.5cc0868a.chunk.js.LICENSE", + contenttype: "application/octet-stream", + offset: 14554809, + len: 3119, + }, + "static/js/5.5cc0868a.chunk.js.map": { + filename: "static/js/5.5cc0868a.chunk.js.map", + contenttype: "application/octet-stream", + offset: 289328, + len: 6632626, + }, + "static/js/6.b7681521.chunk.js": { + filename: "static/js/6.b7681521.chunk.js", + contenttype: "text/javascript", + offset: 14237363, + len: 222852, + }, + "static/js/6.b7681521.chunk.js.map": { + filename: "static/js/6.b7681521.chunk.js.map", + contenttype: "application/octet-stream", + offset: 12215299, + len: 655412, + }, + "static/js/7.0614dbc4.chunk.js": { + filename: "static/js/7.0614dbc4.chunk.js", + contenttype: "text/javascript", + offset: 6921954, + len: 6477, + }, + "static/js/7.0614dbc4.chunk.js.map": { + filename: "static/js/7.0614dbc4.chunk.js.map", + contenttype: "application/octet-stream", + offset: 12041340, + len: 13921, + }, + "static/js/8.7975098c.chunk.js": { + filename: "static/js/8.7975098c.chunk.js", + contenttype: "text/javascript", + offset: 13796515, + len: 420712, + }, + "static/js/8.7975098c.chunk.js.LICENSE": { + filename: "static/js/8.7975098c.chunk.js.LICENSE", + contenttype: "application/octet-stream", + offset: 13796191, + len: 324, + }, + "static/js/8.7975098c.chunk.js.map": { + filename: "static/js/8.7975098c.chunk.js.map", + contenttype: "application/octet-stream", + offset: 12871047, + len: 925144, + }, + "static/js/9.cc860b76.chunk.js": { + filename: "static/js/9.cc860b76.chunk.js", + contenttype: "text/javascript", + offset: 14557928, + len: 920812, + }, + "static/js/9.cc860b76.chunk.js.LICENSE": { + filename: "static/js/9.cc860b76.chunk.js.LICENSE", + contenttype: "application/octet-stream", + offset: 15478740, + len: 4559, + }, + "static/js/9.cc860b76.chunk.js.map": { + filename: "static/js/9.cc860b76.chunk.js.map", + contenttype: "application/octet-stream", + offset: 7434773, + len: 2764565, + }, + "static/js/main.a7822f79.chunk.js": { + filename: "static/js/main.a7822f79.chunk.js", + contenttype: "text/javascript", + offset: 7168627, + len: 131523, + }, + "static/js/main.a7822f79.chunk.js.map": { + filename: "static/js/main.a7822f79.chunk.js.map", + contenttype: "application/octet-stream", + offset: 6929101, + len: 239179, + }, + "static/js/runtime-main.68d129c6.js": { + filename: "static/js/runtime-main.68d129c6.js", + contenttype: "text/javascript", + offset: 14217227, + len: 3546, + }, + "static/js/runtime-main.68d129c6.js.map": { + filename: "static/js/runtime-main.68d129c6.js.map", + contenttype: "application/octet-stream", + offset: 14220773, + len: 16590, + }, + "static/media/arrow-down-blue.cd061363.svg": { + filename: "static/media/arrow-down-blue.cd061363.svg", + contenttype: "image/svg+xml", + offset: 219284, + len: 326, + }, + "static/media/arrow-down-grey.c0dedd2f.svg": { + filename: "static/media/arrow-down-grey.c0dedd2f.svg", + contenttype: "image/svg+xml", + offset: 196726, + len: 326, + }, + "static/media/arrow-right-white.337ad716.png": { + filename: "static/media/arrow-right-white.337ad716.png", + contenttype: "image/png", + offset: 197052, + len: 12999, + }, + "static/media/arrow-right.d285b6cf.svg": { + filename: "static/media/arrow-right.d285b6cf.svg", + contenttype: "image/svg+xml", + offset: 289065, + len: 263, + }, + "static/media/circle-grey.ed2a1dad.svg": { + filename: "static/media/circle-grey.ed2a1dad.svg", + contenttype: "image/svg+xml", + offset: 210213, + len: 321, + }, + "static/media/circle.2d975615.svg": { + filename: "static/media/circle.2d975615.svg", + contenttype: "image/svg+xml", + offset: 210534, + len: 321, + }, + "static/media/coinbaseWalletIcon.62578f59.svg": { + filename: "static/media/coinbaseWalletIcon.62578f59.svg", + contenttype: "image/svg+xml", + offset: 220450, + len: 53626, + }, + "static/media/dropdown-blue.b20914ec.svg": { + filename: "static/media/dropdown-blue.b20914ec.svg", + contenttype: "image/svg+xml", + offset: 47369, + len: 164, + }, + "static/media/dropdown.7d32d2fa.svg": { + filename: "static/media/dropdown.7d32d2fa.svg", + contenttype: "image/svg+xml", + offset: 287941, + len: 164, + }, + "static/media/dropup-blue.b96d70e1.svg": { + filename: "static/media/dropup-blue.b96d70e1.svg", + contenttype: "image/svg+xml", + offset: 210051, + len: 162, + }, + "static/media/ethereum-logo.802c6eac.svg": { + filename: "static/media/ethereum-logo.802c6eac.svg", + contenttype: "image/svg+xml", + offset: 219610, + len: 840, + }, + "static/media/magnifying-glass.67440097.svg": { + filename: "static/media/magnifying-glass.67440097.svg", + contenttype: "image/svg+xml", + offset: 210855, + len: 8429, + }, + "static/media/metamask.023762b6.png": { + filename: "static/media/metamask.023762b6.png", + contenttype: "image/png", + offset: 61600, + len: 114217, + }, + "static/media/plus-blue.e8021e51.svg": { + filename: "static/media/plus-blue.e8021e51.svg", + contenttype: "image/svg+xml", + offset: 196237, + len: 190, + }, + "static/media/plus-grey.d8e0be7d.svg": { + filename: "static/media/plus-grey.d8e0be7d.svg", + contenttype: "image/svg+xml", + offset: 288875, + len: 190, + }, + "static/media/portisIcon.b234b2bf.png": { + filename: "static/media/portisIcon.b234b2bf.png", + contenttype: "image/png", + offset: 274076, + len: 13865, + }, + "static/media/question-mark.1ae4d9f4.svg": { + filename: "static/media/question-mark.1ae4d9f4.svg", + contenttype: "image/svg+xml", + offset: 175817, + len: 818, + }, + "static/media/question.cc0a2451.svg": { + filename: "static/media/question.cc0a2451.svg", + contenttype: "image/svg+xml", + offset: 288105, + len: 770, + }, + "static/media/spinner.be00fc4a.svg": { + filename: "static/media/spinner.be00fc4a.svg", + contenttype: "image/svg+xml", + offset: 47533, + len: 694, + }, + "static/media/trustWallet.edcc1ab5.png": { + filename: "static/media/trustWallet.edcc1ab5.png", + contenttype: "image/png", + offset: 176635, + len: 19602, + }, + "static/media/walletConnectIcon.8215855c.svg": { + filename: "static/media/walletConnectIcon.8215855c.svg", + contenttype: "image/svg+xml", + offset: 48227, + len: 13373, + }, + "static/media/x.5b8e2186.svg": { + filename: "static/media/x.5b8e2186.svg", + contenttype: "image/svg+xml", + offset: 196427, + len: 299, + }, + }, }, }; @@ -575,8 +1043,8 @@ function skylinkVerification(done, { name, skylink, bodyHash, metadata }) { } // Check if the metadata is valid by deep comparing expected value with response - const currentMetadata = - response.header["skynet-file-metadata"] && JSON.parse(response.header["skynet-file-metadata"]); + const metadataHeader = response.header["skynet-file-metadata"]; + const currentMetadata = metadataHeader && JSON.parse(metadataHeader); if (!isEqual(currentMetadata, metadata)) { entry.up = false; info.metadata = detailedDiff(currentMetadata, metadata); diff --git a/setup-scripts/health-checker.py b/setup-scripts/health-checker.py index bdf2b9ef..99aef8e9 100755 --- a/setup-scripts/health-checker.py +++ b/setup-scripts/health-checker.py @@ -55,7 +55,7 @@ async def run_checks(): try: await check_load_average() await check_disk() - await check_health() + # await check_health() # FIXME: adjust it to work with https://github.com/NebulousLabs/skynet-webportal/pull/389 except: trace = traceback.format_exc() print("[DEBUG] run_checks() failed.") From c2138f1d15fb6ad046d54183abf69ac67b3fa64f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Wypch=C5=82o?= Date: Thu, 10 Sep 2020 16:29:19 +0200 Subject: [PATCH 41/44] always use request_id path (#390) --- docker/nginx/conf.d/client.conf | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/docker/nginx/conf.d/client.conf b/docker/nginx/conf.d/client.conf index 8a68f603..933e254c 100644 --- a/docker/nginx/conf.d/client.conf +++ b/docker/nginx/conf.d/client.conf @@ -151,25 +151,6 @@ server { # proxy this call to siad endpoint (make sure the ip is correct) proxy_pass http://siad/skynet/skyfile/$dir1/$dir2/$dir3/$dir4$is_args$args; } - - location ~ "/skynet/skyfile/(.+)" { - include /etc/nginx/conf.d/include/cors; - include /etc/nginx/conf.d/include/sia-auth; - - limit_conn uploads_by_ip 10; # ddos protection: max 10 uploads at a time - client_max_body_size 1000M; # make sure to limit the size of upload to a sane value - proxy_read_timeout 600; - proxy_request_buffering off; # stream uploaded files through the proxy as it comes in - proxy_set_header Expect $http_expect; - proxy_set_header User-Agent: Sia-Agent; - - # we need to explicitly use set directive here because $1 will contain the siapath with - # decoded whitespaces and set will re-encode it for us before passing it to proxy_pass - set $siapath $1; - - # proxy this call to siad endpoint (make sure the ip is correct) - proxy_pass http://siad/skynet/skyfile/$siapath$is_args$args; - } location ~ "^/([a-zA-Z0-9-_]{46}(/.*)?)$" { include /etc/nginx/conf.d/include/cors; From 96aff331354a9112553e2b2d64612817a8d12d3d Mon Sep 17 00:00:00 2001 From: Peter-Jan Brone Date: Thu, 10 Sep 2020 17:14:43 +0200 Subject: [PATCH 42/44] Wildcard Subdomains (#329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add server rule and loation block to handle the base32 encoded skylink through the wildcard subdomain * Instead of redirecting, proxy pass * Add trailing slash * Fix regex to handle server names * Update docker/nginx/conf.d/client.conf Co-authored-by: Karol Wypchło * Implement PR remarks * Implement PR remarks Co-authored-by: Karol Wypchło --- docker/nginx/conf.d/client.conf | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docker/nginx/conf.d/client.conf b/docker/nginx/conf.d/client.conf index 933e254c..a5db3ca6 100644 --- a/docker/nginx/conf.d/client.conf +++ b/docker/nginx/conf.d/client.conf @@ -21,6 +21,10 @@ server { listen 80 default_server; listen [::]:80 default_server; + # parse subdomain (a base32 encoded Skylink) into custom variable + server_name ~^([a-z0-9]{55}).*?; + set $subdomain $1; + # ddos protection: closing slow connections client_body_timeout 5s; client_header_timeout 5s; @@ -31,6 +35,17 @@ server { client_max_body_size 128k; location / { + # The only safe thing to do inside an if in a location block is return + # or rewrite, since we need to proxy_pass we have to work our way around + # using a custom error code. + # + # See https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/ + error_page 418 = @subdomain; + recursive_error_pages on; + if ($subdomain != "") { + return 418; + } + include /etc/nginx/conf.d/include/cors; root /var/www/webportal; @@ -170,6 +185,20 @@ server { proxy_pass http://siad/skynet/skylink/$skylink$is_args$args; } + location @subdomain { + include /etc/nginx/conf.d/include/cors; + include /etc/nginx/conf.d/include/proxy-buffer; + include /etc/nginx/conf.d/include/proxy-cache-downloads; + + limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time + add_header Cache-Control "public, max-age=86400"; # allow consumer to cache response + + proxy_read_timeout 600; + proxy_set_header User-Agent: Sia-Agent; + # proxy this call to siad /skynet/skylink/ endpoint (make sure the ip is correct) + proxy_pass http://siad/skynet/skylink/$subdomain/$request_uri; + } + location ~ "^/file/([a-zA-Z0-9-_]{46}(/.*)?)$" { include /etc/nginx/conf.d/include/cors; include /etc/nginx/conf.d/include/proxy-buffer; From 41514c3660b858b7b98769ee10cb76d664b67c28 Mon Sep 17 00:00:00 2001 From: PJ Date: Fri, 11 Sep 2020 11:21:39 +0200 Subject: [PATCH 43/44] Fix servername regex --- docker/nginx/conf.d/client.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/nginx/conf.d/client.conf b/docker/nginx/conf.d/client.conf index a5db3ca6..c1a78ee8 100644 --- a/docker/nginx/conf.d/client.conf +++ b/docker/nginx/conf.d/client.conf @@ -22,7 +22,7 @@ server { listen [::]:80 default_server; # parse subdomain (a base32 encoded Skylink) into custom variable - server_name ~^([a-z0-9]{55}).*?; + server_name "~^([a-z0-9]{55})\..*$"; set $subdomain $1; # ddos protection: closing slow connections From cd051c45f2d70d331a533c2c15d87d513ead5b19 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Fri, 11 Sep 2020 11:29:08 +0200 Subject: [PATCH 44/44] reorder --- packages/health-check/src/checks/verbose.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/health-check/src/checks/verbose.js b/packages/health-check/src/checks/verbose.js index c35c291d..190b4477 100644 --- a/packages/health-check/src/checks/verbose.js +++ b/packages/health-check/src/checks/verbose.js @@ -1047,7 +1047,7 @@ function skylinkVerification(done, { name, skylink, bodyHash, metadata }) { const currentMetadata = metadataHeader && JSON.parse(metadataHeader); if (!isEqual(currentMetadata, metadata)) { entry.up = false; - info.metadata = detailedDiff(currentMetadata, metadata); + info.metadata = detailedDiff(metadata, currentMetadata); } if (Object.keys(info).length) entry.info = info; // add info only if it exists