diff --git a/package.json b/package.json index 60a831e14..bf9414c44 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@types/socket.io-client": "1.4.36", "browser-fs-access": "0.29.1", "clsx": "1.1.1", + "cross-env": "7.0.3", "fake-indexeddb": "3.1.7", "firebase": "8.3.3", "i18next-browser-languagedetector": "6.1.4", @@ -54,7 +55,19 @@ "roughjs": "4.5.2", "sass": "1.51.0", "socket.io-client": "2.3.1", - "typescript": "4.5.5" + "typescript": "4.5.5", + "workbox-background-sync": "^6.5.4", + "workbox-broadcast-update": "^6.5.4", + "workbox-cacheable-response": "^6.5.4", + "workbox-core": "^6.5.4", + "workbox-expiration": "^6.5.4", + "workbox-google-analytics": "^6.5.4", + "workbox-navigation-preload": "^6.5.4", + "workbox-precaching": "^6.5.4", + "workbox-range-requests": "^6.5.4", + "workbox-routing": "^6.5.4", + "workbox-strategies": "^6.5.4", + "workbox-streams": "^6.5.4" }, "devDependencies": { "@excalidraw/eslint-config": "1.0.0", @@ -67,6 +80,7 @@ "dotenv": "16.0.1", "eslint-config-prettier": "8.5.0", "eslint-plugin-prettier": "3.3.1", + "http-server": "14.1.1", "husky": "7.0.4", "jest-canvas-mock": "2.4.0", "lint-staged": "12.3.7", @@ -90,10 +104,9 @@ "scripts": { "build-node": "node ./scripts/build-node.js", "build:app:docker": "REACT_APP_DISABLE_SENTRY=true react-scripts build", - "build:app": "REACT_APP_GIT_SHA=$VERCEL_GIT_COMMIT_SHA react-scripts build", + "build:app": "cross-env REACT_APP_GIT_SHA=$VERCEL_GIT_COMMIT_SHA react-scripts build", "build:version": "node ./scripts/build-version.js", - "build:prebuild": "node ./scripts/prebuild.js", - "build": "yarn build:prebuild && yarn build:app && yarn build:version", + "build": "yarn build:app && yarn build:version", "eject": "react-scripts eject", "fix:code": "yarn test:code --fix", "fix:other": "yarn prettier --write", @@ -103,6 +116,7 @@ "prepare": "husky install", "prettier": "prettier \"**/*.{css,scss,json,md,html,yml}\" --ignore-path=.eslintignore", "start": "react-scripts start", + "start:production": "npm run build && npx http-server build -a localhost -p 5001 -o", "test:all": "yarn test:typecheck && yarn test:code && yarn test:other && yarn test:app --watchAll=false", "test:app": "react-scripts test --passWithNoTests", "test:code": "eslint --max-warnings=0 --ext .js,.ts,.tsx .", diff --git a/public/service-worker.js b/public/service-worker.js deleted file mode 100644 index cbbdb82b1..000000000 --- a/public/service-worker.js +++ /dev/null @@ -1,81 +0,0 @@ -// eslint-disable-next-line no-restricted-globals -// eslint-disable-next-line no-unused-expressions - -/* eslint-disable no-restricted-globals */ -/* global importScripts, workbox */ - -/** - * Welcome to your Workbox-powered service worker! - * - * You'll need to register this file in your web app and you should - * disable HTTP caching for this file too. - * See https://goo.gl/nhQhGp - * - * The rest of the code is auto-generated. Please don't update this file - * directly; instead, make changes to your Workbox build configuration - * and re-run your build process. - * See https://goo.gl/2aRDsh - */ - -// in dev, `process` is undefined because this file is not compiled until build -const IS_DEVELOPMENT = - typeof process === "undefined" || process.env.NODE_ENV !== "production"; - -if (IS_DEVELOPMENT) { - importScripts( - "https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js", - ); - workbox.setConfig({ - debug: true, - }); -} else { - importScripts("/workbox/workbox-sw.js"); - workbox.setConfig({ - modulePathPrefix: "/workbox/", - }); -} - -self.addEventListener("message", (event) => { - if (event.data && event.data.type === "SKIP_WAITING") { - self.skipWaiting(); - } -}); - -workbox.core.clientsClaim(); - -if (!IS_DEVELOPMENT) { - workbox.precaching.precacheAndRoute(self.__WB_MANIFEST); - - workbox.routing.registerNavigationRoute( - workbox.precaching.getCacheKeyForURL("./index.html"), - { - blacklist: [/^\/_/, /\/[^/?]+\.[^/]+$/], - }, - ); -} - -// Cache relevant font files -workbox.routing.registerRoute( - new RegExp("/(fonts.css|.+.(ttf|woff2|otf))"), - new workbox.strategies.StaleWhileRevalidate({ - cacheName: "fonts", - plugins: [new workbox.expiration.Plugin({ maxEntries: 10 })], - }), -); - -self.addEventListener("fetch", (event) => { - if ( - event.request.method === "POST" && - event.request.url.endsWith("/web-share-target") - ) { - return event.respondWith( - (async () => { - const formData = await event.request.formData(); - const file = formData.get("file"); - const webShareTargetCache = await caches.open("web-share-target"); - await webShareTargetCache.put("shared-file", new Response(file)); - return Response.redirect("/?web-share-target", 303); - })(), - ); - } -}); diff --git a/scripts/prebuild.js b/scripts/prebuild.js deleted file mode 100644 index 64b4a256b..000000000 --- a/scripts/prebuild.js +++ /dev/null @@ -1,21 +0,0 @@ -const fs = require("fs"); -const path = require("path"); - -// for development purposes we want to have the service-worker.js file -// accessible from the public folder. On build though, we need to compile it -// and CRA expects that file to be in src/ folder. -const moveServiceWorkerScript = () => { - const oldPath = path.resolve(__dirname, "../public/service-worker.js"); - const newPath = path.resolve(__dirname, "../src/service-worker.js"); - - fs.rename(oldPath, newPath, (error) => { - if (error) { - throw error; - } - console.info("public/service-worker.js moved to src/"); - }); -}; - -// ----------------------------------------------------------------------------- - -moveServiceWorkerScript(); diff --git a/src/excalidraw-app/pwa.ts b/src/excalidraw-app/pwa.ts index bdf92552f..69cb33ecb 100644 --- a/src/excalidraw-app/pwa.ts +++ b/src/excalidraw-app/pwa.ts @@ -1,4 +1,4 @@ -import { register as registerServiceWorker } from "../serviceWorker"; +import { register as registerServiceWorker } from "../serviceWorkerRegistration"; import { EVENT } from "../constants"; // On Apple mobile devices add the proprietary app icon and splashscreen markup. diff --git a/src/i18n.ts b/src/i18n.ts index efc00f20d..2d4e52f13 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -90,9 +90,14 @@ export const setLanguage = async (lang: Language) => { if (lang.code.startsWith(TEST_LANG_CODE)) { currentLangData = {}; } else { - currentLangData = await import( - /* webpackChunkName: "locales/[request]" */ `./locales/${currentLang.code}.json` - ); + try { + currentLangData = await import( + /* webpackChunkName: "locales/[request]" */ `./locales/${currentLang.code}.json` + ); + } catch (error: any) { + console.error(`Failed to load language ${lang.code}:`, error.message); + currentLangData = fallbackLangData; + } } }; diff --git a/src/service-worker.ts b/src/service-worker.ts new file mode 100644 index 000000000..3e3a4355f --- /dev/null +++ b/src/service-worker.ts @@ -0,0 +1,147 @@ +/// +/* eslint-disable no-restricted-globals */ + +// This service worker can be customized! +// See https://developers.google.com/web/tools/workbox/modules +// for the list of available Workbox modules, or add any other +// code you'd like. +// You can also remove this file if you'd prefer not to use a +// service worker, and the Workbox build step will be skipped. + +import { clientsClaim } from "workbox-core"; +import { ExpirationPlugin } from "workbox-expiration"; +import { precacheAndRoute, createHandlerBoundToURL } from "workbox-precaching"; +import { registerRoute } from "workbox-routing"; +import { CacheFirst, StaleWhileRevalidate } from "workbox-strategies"; + +declare const self: ServiceWorkerGlobalScope; + +clientsClaim(); + +// Precache assets generated by your build process. +// +// Their URLs are injected into the __WB_MANIFEST during build (by workbox). +// +// This variable must be present somewhere in your service worker file, +// even if you decide not to use precaching. See https://cra.link/PWA. +// +// We don't want to precache i18n files so we filter them out +// (normally this should be configured in a webpack workbox plugin, but we don't +// have access to it in CRA) — this is because all users will use at most +// one or two languages, so there's no point fetching all of them. (They'll +// be cached as you load them.) +const manifest = self.__WB_MANIFEST.filter((entry) => { + return !/locales\/[\w-]+json/.test( + typeof entry === "string" ? entry : entry.url, + ); +}); + +precacheAndRoute(manifest); + +// Set up App Shell-style routing, so that all navigation requests +// are fulfilled with your index.html shell. Learn more at +// https://developer.chrome.com/docs/workbox/app-shell-model/ +// +// below is copied verbatim from CRA@5 +const fileExtensionRegexp = new RegExp("/[^/?]+\\.[^/]+$"); +registerRoute( + // Return false to exempt requests from being fulfilled by index.html. + ({ request, url }: { request: Request; url: URL }) => { + // If this isn't a navigation, skip. + if (request.mode !== "navigate") { + return false; + } + + // If this is a URL that starts with /_, skip. + if (url.pathname.startsWith("/_")) { + return false; + } + + // If this looks like a URL for a resource, because it contains + // a file extension, skip. + if (url.pathname.match(fileExtensionRegexp)) { + return false; + } + + // Return true to signal that we want to use the handler. + return true; + }, + createHandlerBoundToURL(`${process.env.PUBLIC_URL}/index.html`), +); + +// Cache resources that aren't being precached +// ----------------------------------------------------------------------------- + +registerRoute( + new RegExp("/fonts.css"), + new StaleWhileRevalidate({ + cacheName: "fonts", + plugins: [ + // Ensure that once this runtime cache reaches a maximum size the + // least-recently used images are removed. + new ExpirationPlugin({ maxEntries: 50 }), + ], + }), +); + +// since we serve fonts from, don't forget to append new ?v= param when +// updating fonts (glyphs) without changing the filename +registerRoute( + new RegExp("/.+.(ttf|woff2|otf)"), + new CacheFirst({ + cacheName: "fonts", + plugins: [ + // Ensure that once this runtime cache reaches a maximum size the + // least-recently used images are removed. + new ExpirationPlugin({ + maxEntries: 50, + // 90 days + maxAgeSeconds: 7776000000, + }), + ], + }), +); + +registerRoute( + new RegExp("/locales\\/[\\w-]+json"), + // Customize this strategy as needed, e.g., by changing to CacheFirst. + new CacheFirst({ + cacheName: "locales", + plugins: [ + // Ensure that once this runtime cache reaches a maximum size the + // least-recently used images are removed. + new ExpirationPlugin({ + maxEntries: 50, + // 30 days + maxAgeSeconds: 2592000000, + }), + ], + }), +); + +// ----------------------------------------------------------------------------- + +self.addEventListener("fetch", (event) => { + if ( + event.request.method === "POST" && + event.request.url.endsWith("/web-share-target") + ) { + return event.respondWith( + (async () => { + const formData = await event.request.formData(); + const file = formData.get("file"); + const webShareTargetCache = await caches.open("web-share-target"); + await webShareTargetCache.put("shared-file", new Response(file)); + return Response.redirect("/?web-share-target", 303); + })(), + ); + } +}); + +// This allows the web app to trigger skipWaiting via +// registration.waiting.postMessage({type: 'SKIP_WAITING'}) +self.addEventListener("message", (event) => { + if (event.data && event.data.type === "SKIP_WAITING") { + self.skipWaiting(); + } +}); diff --git a/src/serviceWorker.tsx b/src/serviceWorkerRegistration.ts similarity index 100% rename from src/serviceWorker.tsx rename to src/serviceWorkerRegistration.ts diff --git a/yarn.lock b/yarn.lock index ccb509009..1e2d24b96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3407,6 +3407,13 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +async@^2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + async@^3.2.3: version "3.2.4" resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" @@ -3610,6 +3617,13 @@ base64-arraybuffer@0.1.4: resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz#9818c79e059b1355f97e0428a017c838e90ba812" integrity sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg== +basic-auth@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" + integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== + dependencies: + safe-buffer "5.1.2" + batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" @@ -4149,6 +4163,11 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +corser@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/corser/-/corser-2.0.1.tgz#8eda252ecaab5840dcd975ceb90d9370c819ff87" + integrity sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ== + cosmiconfig@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" @@ -4176,7 +4195,14 @@ crc-32@^0.3.0: resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-0.3.0.tgz#6a3d3687f5baec41f7e9b99fe1953a2e5d19775e" integrity sha512-kucVIjOmMc1f0tv53BJ/5WIX+MGLcKuoBhnGqQrgKJNqLByb/sVMWfW/Aw6hw0jgcqjJ2pi9E5y32zOIpaUlsA== -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-env@7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -5909,6 +5935,13 @@ html-encoding-sniffer@^2.0.1: dependencies: whatwg-encoding "^1.0.5" +html-encoding-sniffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" + integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== + dependencies: + whatwg-encoding "^2.0.0" + html-entities@^2.1.0, html-entities@^2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" @@ -6013,6 +6046,25 @@ http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" +http-server@14.1.1: + version "14.1.1" + resolved "https://registry.yarnpkg.com/http-server/-/http-server-14.1.1.tgz#d60fbb37d7c2fdff0f0fbff0d0ee6670bd285e2e" + integrity sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A== + dependencies: + basic-auth "^2.0.1" + chalk "^4.1.2" + corser "^2.0.1" + he "^1.2.0" + html-encoding-sniffer "^3.0.0" + http-proxy "^1.18.1" + mime "^1.6.0" + minimist "^1.2.6" + opener "^1.5.1" + portfinder "^1.0.28" + secure-compare "3.0.1" + union "~0.5.0" + url-join "^4.0.1" + https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -6045,7 +6097,7 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.6.3: +iconv-lite@0.6.3, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -7358,7 +7410,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: +lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -7499,7 +7551,7 @@ mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, dependencies: mime-db "1.52.0" -mime@1.6.0: +mime@1.6.0, mime@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== @@ -7545,7 +7597,7 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== -mkdirp@~0.5.1: +mkdirp@^0.5.6, mkdirp@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -7826,6 +7878,11 @@ open@^8.0.9, open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" +opener@^1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -8111,6 +8168,15 @@ points-on-path@^0.2.1: path-data-parser "0.1.0" points-on-curve "0.2.0" +portfinder@^1.0.28: + version "1.0.32" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" + integrity sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg== + dependencies: + async "^2.6.4" + debug "^3.2.7" + mkdirp "^0.5.6" + postcss-attribute-case-insensitive@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz#03d761b24afc04c09e757e92ff53716ae8ea2741" @@ -8830,7 +8896,7 @@ q@^1.1.2: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== -qs@6.11.0: +qs@6.11.0, qs@^6.4.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== @@ -9417,6 +9483,11 @@ schema-utils@^4.0.0: ajv-formats "^2.1.1" ajv-keywords "^5.0.0" +secure-compare@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/secure-compare/-/secure-compare-3.0.1.tgz#f1a0329b308b221fae37b9974f3d578d0ca999e3" + integrity sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw== + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -10277,6 +10348,13 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== +union@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/union/-/union-0.5.0.tgz#b2c11be84f60538537b846edb9ba266ba0090075" + integrity sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA== + dependencies: + qs "^6.4.0" + unique-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" @@ -10324,6 +10402,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + url-parse@^1.5.3: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" @@ -10563,6 +10646,13 @@ whatwg-encoding@^1.0.5: dependencies: iconv-lite "0.4.24" +whatwg-encoding@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" + integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== + dependencies: + iconv-lite "0.6.3" + whatwg-fetch@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" @@ -10648,7 +10738,7 @@ word-wrap@^1.2.3, word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -workbox-background-sync@6.5.4: +workbox-background-sync@6.5.4, workbox-background-sync@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz#3141afba3cc8aa2ae14c24d0f6811374ba8ff6a9" integrity sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g== @@ -10656,7 +10746,7 @@ workbox-background-sync@6.5.4: idb "^7.0.1" workbox-core "6.5.4" -workbox-broadcast-update@6.5.4: +workbox-broadcast-update@6.5.4, workbox-broadcast-update@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz#8441cff5417cd41f384ba7633ca960a7ffe40f66" integrity sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw== @@ -10706,19 +10796,19 @@ workbox-build@6.5.4: workbox-sw "6.5.4" workbox-window "6.5.4" -workbox-cacheable-response@6.5.4: +workbox-cacheable-response@6.5.4, workbox-cacheable-response@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz#a5c6ec0c6e2b6f037379198d4ef07d098f7cf137" integrity sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug== dependencies: workbox-core "6.5.4" -workbox-core@6.5.4: +workbox-core@6.5.4, workbox-core@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.5.4.tgz#df48bf44cd58bb1d1726c49b883fb1dffa24c9ba" integrity sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q== -workbox-expiration@6.5.4: +workbox-expiration@6.5.4, workbox-expiration@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.5.4.tgz#501056f81e87e1d296c76570bb483ce5e29b4539" integrity sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ== @@ -10726,7 +10816,7 @@ workbox-expiration@6.5.4: idb "^7.0.1" workbox-core "6.5.4" -workbox-google-analytics@6.5.4: +workbox-google-analytics@6.5.4, workbox-google-analytics@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz#c74327f80dfa4c1954cbba93cd7ea640fe7ece7d" integrity sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg== @@ -10736,14 +10826,14 @@ workbox-google-analytics@6.5.4: workbox-routing "6.5.4" workbox-strategies "6.5.4" -workbox-navigation-preload@6.5.4: +workbox-navigation-preload@6.5.4, workbox-navigation-preload@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz#ede56dd5f6fc9e860a7e45b2c1a8f87c1c793212" integrity sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng== dependencies: workbox-core "6.5.4" -workbox-precaching@6.5.4: +workbox-precaching@6.5.4, workbox-precaching@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.5.4.tgz#740e3561df92c6726ab5f7471e6aac89582cab72" integrity sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg== @@ -10752,7 +10842,7 @@ workbox-precaching@6.5.4: workbox-routing "6.5.4" workbox-strategies "6.5.4" -workbox-range-requests@6.5.4: +workbox-range-requests@6.5.4, workbox-range-requests@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz#86b3d482e090433dab38d36ae031b2bb0bd74399" integrity sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg== @@ -10771,21 +10861,21 @@ workbox-recipes@6.5.4: workbox-routing "6.5.4" workbox-strategies "6.5.4" -workbox-routing@6.5.4: +workbox-routing@6.5.4, workbox-routing@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.5.4.tgz#6a7fbbd23f4ac801038d9a0298bc907ee26fe3da" integrity sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg== dependencies: workbox-core "6.5.4" -workbox-strategies@6.5.4: +workbox-strategies@6.5.4, workbox-strategies@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.5.4.tgz#4edda035b3c010fc7f6152918370699334cd204d" integrity sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw== dependencies: workbox-core "6.5.4" -workbox-streams@6.5.4: +workbox-streams@6.5.4, workbox-streams@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-6.5.4.tgz#1cb3c168a6101df7b5269d0353c19e36668d7d69" integrity sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==