From 465b81c287cbdaee16fcd5591514f8d116521320 Mon Sep 17 00:00:00 2001 From: Roshan Padaki Date: Wed, 14 Sep 2022 16:46:54 -0400 Subject: [PATCH] move more browser components to monorepo (#7239) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🦋 remake the repository structure * 💿 incorporate subsequent whisthq/brave-core changes * 🏔 more fixes and upstream changes --- browser/hybrid/browser/extensions/BUILD.gn | 19 + .../extensions/whist_component_loader.cc | 22 + .../extensions/whist_component_loader.h | 22 + browser/hybrid/browser/sources.gni | 7 + browser/hybrid/browser/ui/BUILD.gn | 14 + .../ui/webui/cloud_tabs_ui/cloud_tabs_ui.cc | 80 + .../ui/webui/cloud_tabs_ui/cloud_tabs_ui.h | 19 + .../webui/whist_web_ui_controller_factory.cc | 59 + .../webui/whist_web_ui_controller_factory.h | 28 + .../cloud_tabs_extension/.eslintrc.js | 31 + .../cloud_tabs_extension/.gitignore | 6 + .../cloud_tabs_extension/package-lock.json | 9107 +++++++++++++++++ .../cloud_tabs_extension/package.json | 86 + .../cloud_tabs_extension/public/BUILD.gn | 37 + .../public/css/content.css | 26 + .../public/icons/cloud-off.png | Bin 0 -> 2415 bytes .../public/icons/cloud-on.png | Bin 0 -> 3607 bytes .../cloud_tabs_extension/public/intercom.html | 18 + .../cloud_tabs_extension/public/manifest.json | 48 + .../cloud_tabs_extension/public/popup.html | 18 + .../cloud_tabs_extension/scripts/build.js | 95 + .../scripts/execCommand.js | 25 + .../cloud_tabs_extension/scripts/helpers.js | 29 + .../cloud_tabs_extension/scripts/lint.js | 32 + .../cloud_tabs_extension/src/@core-ts/api.ts | 41 + .../cloud_tabs_extension/src/@core-ts/auth.ts | 146 + .../cloud_tabs_extension/src/@types/api.ts | 2 + .../src/@types/index.d.ts | 34 + .../src/@types/messaging.ts | 23 + .../src/@types/payload.ts | 37 + .../cloud_tabs_extension/src/constants/app.ts | 5 + .../src/constants/errors.ts | 51 + .../src/constants/host.ts | 1 + .../src/constants/location.ts | 2766 +++++ .../src/constants/storage.ts | 13 + .../src/constants/urls.ts | 20 + .../cloud_tabs_extension/src/content/index.ts | 3 + .../src/content/notifications.ts | 63 + .../src/popup/assets/cloud-off.png | Bin 0 -> 22311 bytes .../src/popup/assets/cloud-on.png | Bin 0 -> 29386 bytes .../src/popup/assets/cloud-waiting.png | Bin 0 -> 15486 bytes .../src/popup/assets/cloud-warning.png | Bin 0 -> 23704 bytes .../src/popup/assets/whist_logo.png | Bin 0 -> 10381 bytes .../src/popup/components/checkbox.tsx | 57 + .../src/popup/components/help.tsx | 14 + .../src/popup/components/host.tsx | 11 + .../src/popup/components/login.tsx | 24 + .../src/popup/components/metrics.tsx | 30 + .../src/popup/components/network.tsx | 102 + .../src/popup/components/toggle.tsx | 93 + .../src/popup/components/waitlist.tsx | 101 + .../src/popup/containers/loading.tsx | 30 + .../src/popup/containers/main.tsx | 79 + .../src/popup/containers/offline.tsx | 22 + .../cloud_tabs_extension/src/popup/index.tsx | 178 + .../src/popup/utils/messaging.ts | 17 + .../src/popup/utils/ui.ts | 11 + .../cloud_tabs_extension/src/tab/help.tsx | 46 + .../cloud_tabs_extension/src/tab/index.tsx | 14 + .../cloud_tabs_extension/src/worker/README.md | 5 + .../src/worker/effects/auth.ts | 54 + .../src/worker/effects/content.ts | 15 + .../src/worker/effects/cookies.ts | 61 + .../src/worker/effects/download.ts | 5 + .../src/worker/effects/errors.ts | 44 + .../src/worker/effects/logging.ts | 76 + .../src/worker/effects/mandelbox.ts | 69 + .../src/worker/effects/ping.ts | 13 + .../src/worker/effects/popup.ts | 218 + .../src/worker/effects/socketio.ts | 133 + .../src/worker/effects/tabs.ts | 160 + .../src/worker/effects/webRequest.ts | 32 + .../src/worker/effects/windows.ts | 12 + .../src/worker/events/auth.ts | 42 + .../src/worker/events/content.ts | 22 + .../src/worker/events/cookies.ts | 54 + .../src/worker/events/download.ts | 11 + .../src/worker/events/host.ts | 109 + .../src/worker/events/idle.ts | 10 + .../src/worker/events/mandelbox.ts | 75 + .../src/worker/events/popup.ts | 81 + .../src/worker/events/socketio.ts | 62 + .../src/worker/events/tabs.ts | 74 + .../src/worker/events/webRequest.ts | 22 + .../src/worker/events/webui.ts | 46 + .../src/worker/events/windows.ts | 11 + .../cloud_tabs_extension/src/worker/index.ts | 13 + .../src/worker/utils/auth.ts | 109 + .../src/worker/utils/encode.ts | 19 + .../src/worker/utils/errors.ts | 42 + .../src/worker/utils/host.ts | 71 + .../src/worker/utils/jsonTransport.ts | 73 + .../src/worker/utils/location.ts | 108 + .../src/worker/utils/mandelbox.ts | 64 + .../src/worker/utils/observables.ts | 9 + .../src/worker/utils/protocol.ts | 15 + .../src/worker/utils/state.ts | 45 + .../src/worker/utils/storage.ts | 46 + .../src/worker/utils/tabs.ts | 105 + .../cloud_tabs_extension/tailwind.config.js | 25 + .../cloud_tabs_extension/tsconfig.json | 12 + .../cloud_tabs_extension/webpack.config.js | 74 + .../hybrid/components/cloud_tabs_ui/BUILD.gn | 17 + .../cloud_tabs_ui/cloud_tabs_ui.html | 10 + .../cloud_tabs_ui/css/whist_cloud.css.unused | 103 + .../components/cloud_tabs_ui/resources.grd | 0 .../cloud_tabs_ui/src/controls/history.ts | 78 + .../cloud_tabs_ui/src/controls/refresh.ts | 22 + .../cloud_tabs_ui/src/controls/session.ts | 23 + .../cloud_tabs_ui/src/controls/tab.ts | 54 + .../cloud_tabs_ui/src/controls/whist.ts | 101 + .../components/cloud_tabs_ui/src/index.ts | 40 + .../cloud_tabs_ui/src/shared/state.ts | 5 + .../cloud_tabs_ui/src/ui/loading.ts | 51 + .../cloud_tabs_ui/src/ui/notifications.ts | 95 + .../components/cloud_tabs_ui/src/ui/utils.ts | 12 + .../browser/extensions/extension_service.cc | 5 + .../browser/extensions/extension_service.h | 10 + .../webui/chrome_web_ui_controller_factory.cc | 5 + 119 files changed, 16839 insertions(+) create mode 100644 browser/hybrid/browser/extensions/BUILD.gn create mode 100644 browser/hybrid/browser/extensions/whist_component_loader.cc create mode 100644 browser/hybrid/browser/extensions/whist_component_loader.h create mode 100644 browser/hybrid/browser/sources.gni create mode 100644 browser/hybrid/browser/ui/BUILD.gn create mode 100644 browser/hybrid/browser/ui/webui/cloud_tabs_ui/cloud_tabs_ui.cc create mode 100644 browser/hybrid/browser/ui/webui/cloud_tabs_ui/cloud_tabs_ui.h create mode 100644 browser/hybrid/browser/ui/webui/whist_web_ui_controller_factory.cc create mode 100644 browser/hybrid/browser/ui/webui/whist_web_ui_controller_factory.h create mode 100644 browser/hybrid/components/cloud_tabs_extension/.eslintrc.js create mode 100644 browser/hybrid/components/cloud_tabs_extension/.gitignore create mode 100644 browser/hybrid/components/cloud_tabs_extension/package-lock.json create mode 100644 browser/hybrid/components/cloud_tabs_extension/package.json create mode 100644 browser/hybrid/components/cloud_tabs_extension/public/BUILD.gn create mode 100644 browser/hybrid/components/cloud_tabs_extension/public/css/content.css create mode 100644 browser/hybrid/components/cloud_tabs_extension/public/icons/cloud-off.png create mode 100644 browser/hybrid/components/cloud_tabs_extension/public/icons/cloud-on.png create mode 100644 browser/hybrid/components/cloud_tabs_extension/public/intercom.html create mode 100644 browser/hybrid/components/cloud_tabs_extension/public/manifest.json create mode 100644 browser/hybrid/components/cloud_tabs_extension/public/popup.html create mode 100644 browser/hybrid/components/cloud_tabs_extension/scripts/build.js create mode 100644 browser/hybrid/components/cloud_tabs_extension/scripts/execCommand.js create mode 100644 browser/hybrid/components/cloud_tabs_extension/scripts/helpers.js create mode 100644 browser/hybrid/components/cloud_tabs_extension/scripts/lint.js create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/@core-ts/api.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/@core-ts/auth.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/@types/api.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/@types/index.d.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/@types/messaging.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/@types/payload.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/constants/app.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/constants/errors.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/constants/host.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/constants/location.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/constants/storage.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/constants/urls.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/content/index.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/content/notifications.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/assets/cloud-off.png create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/assets/cloud-on.png create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/assets/cloud-waiting.png create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/assets/cloud-warning.png create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/assets/whist_logo.png create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/components/checkbox.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/components/help.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/components/host.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/components/login.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/components/metrics.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/components/network.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/components/toggle.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/components/waitlist.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/containers/loading.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/containers/main.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/containers/offline.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/index.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/utils/messaging.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/popup/utils/ui.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/tab/help.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/tab/index.tsx create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/README.md create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/auth.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/content.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/cookies.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/download.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/errors.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/logging.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/mandelbox.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/ping.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/popup.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/socketio.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/tabs.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/webRequest.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/effects/windows.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/auth.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/content.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/cookies.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/download.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/host.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/idle.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/mandelbox.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/popup.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/socketio.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/tabs.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/webRequest.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/webui.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/events/windows.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/index.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/auth.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/encode.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/errors.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/host.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/jsonTransport.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/location.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/mandelbox.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/observables.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/protocol.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/state.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/storage.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/src/worker/utils/tabs.ts create mode 100644 browser/hybrid/components/cloud_tabs_extension/tailwind.config.js create mode 100644 browser/hybrid/components/cloud_tabs_extension/tsconfig.json create mode 100644 browser/hybrid/components/cloud_tabs_extension/webpack.config.js create mode 100644 browser/hybrid/components/cloud_tabs_ui/BUILD.gn create mode 100644 browser/hybrid/components/cloud_tabs_ui/cloud_tabs_ui.html create mode 100644 browser/hybrid/components/cloud_tabs_ui/css/whist_cloud.css.unused create mode 100644 browser/hybrid/components/cloud_tabs_ui/resources.grd create mode 100644 browser/hybrid/components/cloud_tabs_ui/src/controls/history.ts create mode 100644 browser/hybrid/components/cloud_tabs_ui/src/controls/refresh.ts create mode 100644 browser/hybrid/components/cloud_tabs_ui/src/controls/session.ts create mode 100644 browser/hybrid/components/cloud_tabs_ui/src/controls/tab.ts create mode 100644 browser/hybrid/components/cloud_tabs_ui/src/controls/whist.ts create mode 100644 browser/hybrid/components/cloud_tabs_ui/src/index.ts create mode 100644 browser/hybrid/components/cloud_tabs_ui/src/shared/state.ts create mode 100644 browser/hybrid/components/cloud_tabs_ui/src/ui/loading.ts create mode 100644 browser/hybrid/components/cloud_tabs_ui/src/ui/notifications.ts create mode 100644 browser/hybrid/components/cloud_tabs_ui/src/ui/utils.ts create mode 100644 browser/hybrid/src/chrome/browser/extensions/extension_service.cc create mode 100644 browser/hybrid/src/chrome/browser/extensions/extension_service.h create mode 100644 browser/hybrid/src/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc diff --git a/browser/hybrid/browser/extensions/BUILD.gn b/browser/hybrid/browser/extensions/BUILD.gn new file mode 100644 index 00000000000..5785a434ecd --- /dev/null +++ b/browser/hybrid/browser/extensions/BUILD.gn @@ -0,0 +1,19 @@ +source_set("extensions") { + sources = [ + "//whist/browser/hybrid/browser/extensions/whist_component_loader.cc", + "//whist/browser/hybrid/browser/extensions/whist_component_loader.h", + ] + + deps = [ + ":resources", + "//base", + "//brave/browser/extensions", + ] +} + +group("resources") { + deps = [ + "//brave/components/whist_extension:generated_resources", + "//brave/components/whist_extension:static_resources", + ] +} diff --git a/browser/hybrid/browser/extensions/whist_component_loader.cc b/browser/hybrid/browser/extensions/whist_component_loader.cc new file mode 100644 index 00000000000..b8654f758ac --- /dev/null +++ b/browser/hybrid/browser/extensions/whist_component_loader.cc @@ -0,0 +1,22 @@ +#include "whist_component_loader.h" + +namespace extensions { + WhistComponentLoader::WhistComponentLoader(ExtensionSystem* extension_system, + Profile* profile) + : BraveComponentLoader(extension_system, profile) {} + + WhistComponentLoader::~WhistComponentLoader() {} + + void WhistComponentLoader::AddWhistExtension() { + if (!Exists(whist_extension_id)) { + base::FilePath whist_extension_path(FILE_PATH_LITERAL("")); + whist_extension_path = whist_extension_path.Append(FILE_PATH_LITERAL("whist_extension")); + Add(IDR_WHIST_EXTENSION, whist_extension_path); + } + } + + void WhistComponentLoader::AddDefaultComponentExtensions(bool skip_session_components) { + BraveComponentLoader::AddDefaultComponentExtensions(skip_session_components); + AddWhistExtension(); + } +} // namespace extensions diff --git a/browser/hybrid/browser/extensions/whist_component_loader.h b/browser/hybrid/browser/extensions/whist_component_loader.h new file mode 100644 index 00000000000..fcfeb3549b1 --- /dev/null +++ b/browser/hybrid/browser/extensions/whist_component_loader.h @@ -0,0 +1,22 @@ +#ifndef WHIST_BROWSER_EXTENSIONS_WHIST_COMPONENT_LOADER_H +#define WHIST_BROWSER_EXTENSIONS_WHIST_COMPONENT_LOADER_H + +#include "src/brave/browser/extensions/brave_component_loader.h" +#include "brave/components/whist_extension/grit/whist_extension.h" +#include "extensions/common/constants.h" + +namespace extensions { + class WhistComponentLoader : public BraveComponentLoader { + public: + WhistComponentLoader(ExtensionSystem* extension_system, + Profile* browser_context); + WhistComponentLoader(const WhistComponentLoader&) = delete; + WhistComponentLoader& operator=(const WhistComponentLoader&) = delete; + ~WhistComponentLoader() override; + + void AddDefaultComponentExtensions(bool skip_session_components) override; + void AddWhistExtension(); + }; +} // namespace extensions + +#endif // WHIST_BROWSER_EXTENSIONS_WHIST_COMPONENT_LOADER_H diff --git a/browser/hybrid/browser/sources.gni b/browser/hybrid/browser/sources.gni new file mode 100644 index 00000000000..8d464fc62d1 --- /dev/null +++ b/browser/hybrid/browser/sources.gni @@ -0,0 +1,7 @@ +import("//extensions/buildflags/buildflags.gni") + +whist_chrome_browser_deps = [ "//whist/browser/hybrid/browser/ui" ] + +if (enable_extensions) { + whist_chrome_browser_deps += [ "//whist/browser/hybrid/browser/extensions" ] +} diff --git a/browser/hybrid/browser/ui/BUILD.gn b/browser/hybrid/browser/ui/BUILD.gn new file mode 100644 index 00000000000..a2c18b1c74b --- /dev/null +++ b/browser/hybrid/browser/ui/BUILD.gn @@ -0,0 +1,14 @@ +source_set("ui") { + sources = [ + "webui/cloud_tabs_ui/cloud_tabs_ui.cc", + "webui/cloud_tabs_ui/cloud_tabs_ui.h", + "webui/whist_web_ui_controller_factory.cc", + "webui/whist_web_ui_controller_factory.h", + ] + + deps = [ + "//base", + "//brave/browser/ui", + "//whist/browser/hybrid/components/cloud_tabs_ui:generated_resources", + ] +} diff --git a/browser/hybrid/browser/ui/webui/cloud_tabs_ui/cloud_tabs_ui.cc b/browser/hybrid/browser/ui/webui/cloud_tabs_ui/cloud_tabs_ui.cc new file mode 100644 index 00000000000..ef24c8b12d9 --- /dev/null +++ b/browser/hybrid/browser/ui/webui/cloud_tabs_ui/cloud_tabs_ui.cc @@ -0,0 +1,80 @@ +// Copyright 2022 Whist Technologies, Inc. All rights reserved. + +#include "cloud_tabs_ui.h" + +#include + +#include "base/rand_util.h" +#include "brave/common/pref_names.h" +#include "brave/browser/ui/webui/brave_webui_source.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/common/url_constants.h" +#include "components/prefs/pref_change_registrar.h" +#include "components/prefs/pref_service.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" +#include "content/public/browser/web_ui_message_handler.h" +#include "content/public/browser/web_ui_controller.h" +#include "content/public/browser/web_ui_data_source.h" +#include "content/public/common/url_constants.h" +#include "components/grit/brave_components_resources.h" + +#include "whist/browser/hybrid/components/cloud_tabs_ui/resources/grit/cloud_tabs_ui_generated_map.h" + +using content::WebUIMessageHandler; + +namespace { +class CloudUIHandler : public WebUIMessageHandler { + public: + CloudUIHandler() {} + CloudUIHandler(const CloudUIHandler&) = delete; + CloudUIHandler& operator=(const CloudUIHandler&) = delete; + + // WebUIMessageHandler implementation. + void RegisterMessages() override; + + // Added by Whist + private: + void OnWhistMandelboxInfoChanged(); + + PrefChangeRegistrar local_state_change_registrar_; + PrefChangeRegistrar profile_state_change_registrar_; +}; + +// Added by Whist +void CloudUIHandler::RegisterMessages() {} +} + +std::string RandomString() { + std::string random_string; + for (int index = 0; index < 32; ++index) { + random_string.append(1, static_cast(base::RandInt('A', 'Z'))); + } + return random_string; +} + +WhistCloudUI::WhistCloudUI(content::WebUI* web_ui, const GURL& url) + : content::WebUIController(web_ui) { + content::WebUIDataSource* source = CreateAndAddWebUIDataSource( + web_ui, content::kCloudScheme, kCloudTabsUiGenerated, kCloudTabsUiGeneratedSize, + IDR_WHIST_CLOUD_TABS_UI_HTML, + /*disable_trusted_types_csp=*/true); + + web_ui->AddMessageHandler(std::make_unique()); + + // Generate random nonce and set security policy accordingly + std::string random_nonce = RandomString(); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, + "script-src cloud: chrome://resources 'nonce-" + random_nonce + "' 'self';"); + source->AddString("whistUINonce", random_nonce); + // Required resources. + source->UseStringsJs(); + source->SetDefaultResource(IDR_WHIST_CLOUD_TABS_UI_HTML); + + Profile* profile = Profile::FromWebUI(web_ui); + content::WebUIDataSource::Add(profile, source); +} + +WhistCloudUI::~WhistCloudUI() = default; diff --git a/browser/hybrid/browser/ui/webui/cloud_tabs_ui/cloud_tabs_ui.h b/browser/hybrid/browser/ui/webui/cloud_tabs_ui/cloud_tabs_ui.h new file mode 100644 index 00000000000..a95b8f49e6d --- /dev/null +++ b/browser/hybrid/browser/ui/webui/cloud_tabs_ui/cloud_tabs_ui.h @@ -0,0 +1,19 @@ +// Copyright 2022 Whist Technologies, Inc. All rights reserved. + +#ifndef CHROME_BROWSER_UI_WEBUI_WHIST_CLOUD_WHIST_CLOUD_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_WHIST_CLOUD_WHIST_CLOUD_UI_H_ + +#include "content/public/browser/web_ui_controller.h" + +// The WebUI for cloud:*. +class WhistCloudUI : public content::WebUIController { + public: + WhistCloudUI(content::WebUI* web_ui, const GURL& url); + + WhistCloudUI(const WhistCloudUI&) = delete; + WhistCloudUI& operator=(const WhistCloudUI&) = delete; + + ~WhistCloudUI() override; +}; + +#endif // CHROME_BROWSER_UI_WEBUI_WHIST_CLOUD_WHIST_CLOUD_UI_H_ diff --git a/browser/hybrid/browser/ui/webui/whist_web_ui_controller_factory.cc b/browser/hybrid/browser/ui/webui/whist_web_ui_controller_factory.cc new file mode 100644 index 00000000000..b0fdee0b6b4 --- /dev/null +++ b/browser/hybrid/browser/ui/webui/whist_web_ui_controller_factory.cc @@ -0,0 +1,59 @@ +#include "whist_web_ui_controller_factory.h" +#include "whist/browser/hybrid/browser/ui/webui/cloud_tabs_ui/cloud_tabs_ui.h" +#include "chrome/common/url_constants.h" +#include "base/logging.h" +#include + +using content::WebUI; +using content::WebUIController; + +namespace { + typedef WebUIController* (*WebUIFactoryFunction)(WebUI* web_ui, + const GURL& url); + + WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) { + if(url.SchemeIs(content::kCloudScheme)) { + return new WhistCloudUI(web_ui, url); + } + + return nullptr; + } + + WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, const GURL& url) { + if (url.SchemeIs(content::kCloudScheme)) { + return &NewWebUI; + } + + return nullptr; + } +} // namespace + +WebUI::TypeID WhistWebUIControllerFactory::GetWebUIType( + content::BrowserContext* browser_context, + const GURL& url) { + WebUIFactoryFunction function = GetWebUIFactoryFunction(NULL, url); + if (function) { + return reinterpret_cast(function); + } + return BraveWebUIControllerFactory::GetWebUIType(browser_context, url); +} + +std::unique_ptr +WhistWebUIControllerFactory::CreateWebUIControllerForURL(WebUI* web_ui, + const GURL& url) { + WebUIFactoryFunction function = GetWebUIFactoryFunction(web_ui, url); + if (!function) { + return BraveWebUIControllerFactory::CreateWebUIControllerForURL(web_ui, + url); + } + + return base::WrapUnique((*function)(web_ui, url)); +} + +// static +WhistWebUIControllerFactory* WhistWebUIControllerFactory::GetInstance() { + return base::Singleton::get(); +} + +WhistWebUIControllerFactory::WhistWebUIControllerFactory() {} +WhistWebUIControllerFactory::~WhistWebUIControllerFactory() {} diff --git a/browser/hybrid/browser/ui/webui/whist_web_ui_controller_factory.h b/browser/hybrid/browser/ui/webui/whist_web_ui_controller_factory.h new file mode 100644 index 00000000000..ba367ad6108 --- /dev/null +++ b/browser/hybrid/browser/ui/webui/whist_web_ui_controller_factory.h @@ -0,0 +1,28 @@ +#ifndef WHIST_BROWSER_UI_WEBUI_WHIST_WEB_UI_CONTROLLER_FACTORY_H +#define WHIST_BROWSER_UI_WEBUI_WHIST_WEB_UI_CONTROLLER_FACTORY_H + +#include "base/memory/ptr_util.h" +#include "brave/browser/ui/webui/brave_web_ui_controller_factory.h" + +class WhistWebUIControllerFactory : public BraveWebUIControllerFactory { + public: + WhistWebUIControllerFactory(const WhistWebUIControllerFactory&) = delete; + WhistWebUIControllerFactory& operator=(const WhistWebUIControllerFactory&) = + delete; + + content::WebUI::TypeID GetWebUIType(content::BrowserContext* browser_context, + const GURL& url) override; + std::unique_ptr CreateWebUIControllerForURL( + content::WebUI* web_ui, + const GURL& url) override; + + static WhistWebUIControllerFactory* GetInstance(); + + protected: + friend struct base::DefaultSingletonTraits; + + WhistWebUIControllerFactory(); + ~WhistWebUIControllerFactory() override; +}; + +#endif // WHIST_BROWSER_UI_WEBUI_WHIST_WEB_UI_CONTROLLER_FACTORY_H diff --git a/browser/hybrid/components/cloud_tabs_extension/.eslintrc.js b/browser/hybrid/components/cloud_tabs_extension/.eslintrc.js new file mode 100644 index 00000000000..37c39f19f05 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/.eslintrc.js @@ -0,0 +1,31 @@ +module.exports = { + env: { + browser: true, + es2021: true, + }, + extends: [ + "plugin:react/recommended", + "standard-with-typescript", + "plugin:prettier/recommended", + ], + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 12, + sourceType: "module", + project: "./tsconfig.json", + }, + plugins: ["react", "@typescript-eslint", "prettier"], + rules: { + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/consistent-type-assertions": "off", + "prettier/prettier": "error", + }, + settings: { + react: { + version: "detect", + }, + }, + } diff --git a/browser/hybrid/components/cloud_tabs_extension/.gitignore b/browser/hybrid/components/cloud_tabs_extension/.gitignore new file mode 100644 index 00000000000..ff87cc00d05 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/.gitignore @@ -0,0 +1,6 @@ +# General +src/generated_config.json +src/config.json +public/css/tailwind.css +node_modules +build diff --git a/browser/hybrid/components/cloud_tabs_extension/package-lock.json b/browser/hybrid/components/cloud_tabs_extension/package-lock.json new file mode 100644 index 00000000000..4d45d7d3132 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/package-lock.json @@ -0,0 +1,9107 @@ +{ + "name": "cloud-tabs-extension", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "cloud-tabs-extension", + "version": "1.0.0", + "license": "UNLICENSED", + "dependencies": { + "@amplitude/analytics-browser": "^1.1.1", + "@fortawesome/fontawesome-svg-core": "^6.1.1", + "@fortawesome/free-solid-svg-icons": "^6.1.1", + "@fortawesome/react-fontawesome": "^0.1.18", + "@headlessui/react": "^1.6.5", + "buffer": "^6.0.3", + "classnames": "^2.3.1", + "file-loader": "^6.2.0", + "fuzzy-search": "^3.2.1", + "http": "^0.0.1-security", + "https-browserify": "^1.0.0", + "json-stringify-safe": "^5.0.1", + "jwt-decode": "^3.1.2", + "lodash.find": "^4.6.0", + "lodash.has": "^4.5.2", + "lodash.isempty": "^4.4.0", + "lodash.isequal": "^4.5.0", + "lodash.pick": "^4.4.0", + "lodash.remove": "^4.7.0", + "lodash.sortby": "^4.7.0", + "lodash.union": "^4.6.0", + "lodash.uniq": "^4.5.0", + "lodash.uniqby": "^4.7.0", + "on-change": "^4.0.1", + "ping.js": "^0.3.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-use-intercom": "^2.0.0", + "rxjs": "^7.5.5", + "socket.io-client": "^4.5.1", + "stream-http": "^3.2.0", + "url": "^0.11.0", + "yargs": "^17.5.0" + }, + "devDependencies": { + "@types/chrome": "^0.0.130", + "@types/fuzzy-search": "^2.1.2", + "@types/json-stringify-safe": "^5.0.0", + "@types/lodash.find": "^4.6.7", + "@types/lodash.has": "^4.5.6", + "@types/lodash.isempty": "^4.4.6", + "@types/lodash.isequal": "^4.5.6", + "@types/lodash.pick": "^4.4.7", + "@types/lodash.remove": "^4.7.7", + "@types/lodash.sortby": "^4.7.7", + "@types/lodash.union": "^4.6.7", + "@types/lodash.uniq": "^4.5.7", + "@types/lodash.uniqby": "^4.7.7", + "@types/react": "^17.0.39", + "@types/react-dom": "^17.0.11", + "@types/simple-peer": "^9.6.1", + "copy-webpack-plugin": "^7.0.0", + "css-loader": "^6.7.1", + "eslint": "<8.0.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.1.0", + "eslint-plugin-react": "^7.30.1", + "html-webpack-plugin": "^5.5.0", + "path-browserify": "^1.0.1", + "prettier": "^2.7.1", + "process": "^0.11.10", + "simple-peer": "^9.9.3", + "style-loader": "^3.3.1", + "tailwindcss": "^3.1.6", + "ts-loader": "^9.3.0", + "typescript": "^4.8.3", + "webpack": "^5.21.2", + "webpack-cli": "^4.5.0" + } + }, + "node_modules/@amplitude/analytics-browser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-browser/-/analytics-browser-1.1.1.tgz", + "integrity": "sha512-J6ftCTThmtKZ4OG6sqFu6eFIJHCP/s/GK+FMZ2mUSEwWxAUWQYWE8LLPnKo/BIDQXCT0q++sMc4+OMr8w7azPw==", + "dependencies": { + "@amplitude/analytics-core": "^0.6.4", + "@amplitude/analytics-types": "^0.6.1", + "@amplitude/ua-parser-js": "^0.7.31", + "tslib": "^2.3.1" + } + }, + "node_modules/@amplitude/analytics-core": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-core/-/analytics-core-0.6.4.tgz", + "integrity": "sha512-RuWkLGO89O/8x88J7OPMIB1sSZ+toAJQeEI+KFkZGU1uQ0znhF1nLe64UUi39mP7qLMFYtQfXVD8IfNLIJt7IQ==", + "dependencies": { + "@amplitude/analytics-types": "^0.6.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@amplitude/analytics-types": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-types/-/analytics-types-0.6.1.tgz", + "integrity": "sha512-6XWxxt0LYMkOLZHnAzLoDRwhMcOeNviXEdba6tVVjYOM9zW6ZOCLZWO3N+/s+UF6tYOvDZyLH6a1PqAlNUvHqQ==" + }, + "node_modules/@amplitude/ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@amplitude/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-+z8UGRaj13Pt5NDzOnkTBy49HE2CX64jeL0ArB86HAtilpnfkPB7oqkigN7Lf2LxscMg4QhFD7mmCfedh3rqTg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", + "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.1.tgz", + "integrity": "sha512-wVn5WJPirFTnzN6tR95abCx+ocH+3IFLXAgyavnf9hUmN0CfWoDjPT/BAWsUVwSlYYVBeCLJxaqi7ZGe4uSjBA==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.1.tgz", + "integrity": "sha512-NCg0w2YIp81f4V6cMGD9iomfsIj7GWrqmsa0ZsPh59G7PKiGN1KymZNxmF00ssuAlo/VZmpK6xazsGOwzKYUMg==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.1.1.tgz", + "integrity": "sha512-0/5exxavOhI/D4Ovm2r3vxNojGZioPwmFrKg0ZUH69Q68uFhFPs6+dhAToh6VEQBntxPRYPuT5Cg1tpNa9JUPg==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.18.tgz", + "integrity": "sha512-RwLIB4TZw0M9gvy5u+TusAA0afbwM4JQIimNH/j3ygd6aIvYPQLqXMhC9ErY26J23rDPyDZldIfPq/HpTTJ/tQ==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.x" + } + }, + "node_modules/@headlessui/react": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.6.5.tgz", + "integrity": "sha512-3VkKteDxlxf3fE0KbfO9t60KC1lM7YNpZggLpwzVNg1J/zwL+h+4N7MBlFDVpInZI3rKlZGpNx0PWsG/9c2vQg==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16 || ^17 || ^18", + "react-dom": "^16 || ^17 || ^18" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "node_modules/@types/chrome": { + "version": "0.0.130", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.130.tgz", + "integrity": "sha512-pAHbcPeOmjNCF5EoUCAZk3+5lll1yyIDP+CZRNf1Dk8LaANkNBNZ5szHqeYYVjMyEGP6yIFeaO+Y7qNpz1hVOw==", + "dev": true, + "dependencies": { + "@types/filesystem": "*", + "@types/har-format": "*" + } + }, + "node_modules/@types/eslint": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz", + "integrity": "sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw==", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz", + "integrity": "sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.46", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", + "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==" + }, + "node_modules/@types/filesystem": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.29.tgz", + "integrity": "sha512-85/1KfRedmfPGsbK8YzeaQUyV1FQAvMPMTuWFQ5EkLd2w7szhNO96bk3Rh/SKmOfd9co2rCLf0Voy4o7ECBOvw==", + "dev": true, + "dependencies": { + "@types/filewriter": "*" + } + }, + "node_modules/@types/filewriter": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.28.tgz", + "integrity": "sha1-wFTor02d11205jq8dviFFocU1LM= sha512-AR2KUJIMdSfl/SaAHpRotBAlaJpmhgHwehEeSJQOG0hS3IrjDU16xUEEUTdqcvdLa1q16ZK5MMrtOagfLvm0gw==", + "dev": true + }, + "node_modules/@types/fuzzy-search": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/fuzzy-search/-/fuzzy-search-2.1.2.tgz", + "integrity": "sha512-YOqA50Z3xcycm4Br5+MBUpSumfdOAcv34A8A8yFn62zBQPTzJSXQk11qYE5w8BWQ0KrVThXUgEQh7ZLrYI1NaQ==", + "dev": true + }, + "node_modules/@types/har-format": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.5.tgz", + "integrity": "sha512-IG8AE1m2pWtPqQ7wXhFhy6Q59bwwnLwO36v5Rit2FrbXCIp8Sk8E2PfUCreyrdo17STwFSKDAkitVuVYbpEHvQ==", + "dev": true + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==" + }, + "node_modules/@types/json-stringify-safe": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz", + "integrity": "sha512-UUA1sH0RSRROdInuDOA1yoRzbi5xVFD1RHCoOvNRPTNwR8zBkJ/84PZ6NhKVDtKp0FTeIccJCdQz1X2aJPr4uw==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.178", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz", + "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==", + "dev": true + }, + "node_modules/@types/lodash.find": { + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/@types/lodash.find/-/lodash.find-4.6.7.tgz", + "integrity": "sha512-ESwK5k3nf9ufS+M2niH06/gjrREihHobyWQLs5c5+O93uar3N9s0rNx8bBfG9zLYVaPBJEsEIk06hm5ccstF5w==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lodash.has": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@types/lodash.has/-/lodash.has-4.5.6.tgz", + "integrity": "sha512-SpUCvze0uHilQX/mt4K/cak5OQny1pVfz3pJx6H70dE3Tvw9s7EtlMK+vY6UBS+PQgETDfv6vhwoa3FPS2wrhg==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lodash.isempty": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isempty/-/lodash.isempty-4.4.6.tgz", + "integrity": "sha512-AauKrFlA4z3Usog5HLGDupKzkCP7h5KXGlfAcRGUfvTmL7guVuEzDSNI6lYJ7syO7J2RE2F47179pSLr26UHIw==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lodash.isequal": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.6.tgz", + "integrity": "sha512-Ww4UGSe3DmtvLLJm2F16hDwEQSv7U0Rr8SujLUA2wHI2D2dm8kPu6Et+/y303LfjTIwSBKXB/YTUcAKpem/XEg==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lodash.pick": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/@types/lodash.pick/-/lodash.pick-4.4.7.tgz", + "integrity": "sha512-HgdyKz7/1+oeoVzbpu1XiX/Bti9AUksHtOILH38T07aKvqoirzcdOsrO2+Yg3L51Hv/8m1MetvHZEUGeABiTiQ==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lodash.remove": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/@types/lodash.remove/-/lodash.remove-4.7.7.tgz", + "integrity": "sha512-jZrQtY6zdukkFFinY+yxikzU3hCS6SEXsTy103Ao+2YsZq2H+D/NpXuAoZpcpn7BTMBUsgr2NO7l4UYHxKXXjw==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lodash.sortby": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/@types/lodash.sortby/-/lodash.sortby-4.7.7.tgz", + "integrity": "sha512-J/4IS+jQopGBrrRetBXDCX0KnSeXJZ0rOTmGAxR9MWGV24YdHxX8IRi9LCGAU9GKWlBov9KRSfQpuup9PReqrw==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lodash.union": { + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/@types/lodash.union/-/lodash.union-4.6.7.tgz", + "integrity": "sha512-6HXM6tsnHJzKgJE0gA/LhTGf/7AbjUk759WZ1MziVm+OBNAATHhdgj+a3KVE8g76GCLAnN4ZEQQG1EGgtBIABA==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lodash.uniq": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/@types/lodash.uniq/-/lodash.uniq-4.5.7.tgz", + "integrity": "sha512-qg7DeAbdZMi6DGvCxThlJycykLLhETrJrQZ6F2KaZ+o0sNK1qRHz46lgNA+nHHjwrmA2a91DyiZTp3ey3m1rEw==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lodash.uniqby": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/@types/lodash.uniqby/-/lodash.uniqby-4.7.7.tgz", + "integrity": "sha512-sv2g6vkCIvEUsK5/Vq17haoZaisfj2EWW8mP7QWlnKi6dByoNmeuHDDXHR7sabuDqwO4gvU7ModIL22MmnOocg==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "14.14.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.27.tgz", + "integrity": "sha512-Ecfmo4YDQPwuqTCl1yBxLV5ihKfRlkBmzUEDcfIRvDxOTGQEeikr317Ln7Gcv0tjA8dVgKI3rniqW2G1OyKDng==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "17.0.39", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz", + "integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", + "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true + }, + "node_modules/@types/simple-peer": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/simple-peer/-/simple-peer-9.6.1.tgz", + "integrity": "sha512-WdXxmHW+m0NaD5XPGlp5AB7raq+NUWX/+/aQvDcoOx0qiP78QmDdk015W29uoyvGhyiJCb9dZJuI2Oi39zGRfg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", + "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", + "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", + "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", + "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", + "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", + "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", + "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", + "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", + "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", + "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", + "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/helper-wasm-section": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-opt": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "@webassemblyjs/wast-printer": "1.11.0" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", + "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", + "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", + "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", + "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.1.tgz", + "integrity": "sha512-B+4uBUYhpzDXmwuo3V9yBH6cISwxEI4J+NO5ggDaGEEHb0osY/R7MzeKc0bHURXQuZjMM4qD+bSJCKIuI3eNBQ==", + "dev": true, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x", + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.2.tgz", + "integrity": "sha512-5U9kUJHnwU+FhKH4PWGZuBC1hTEPYyxGSL5jjoBI96Gx8qcYJGOikpiIpFoTq8mmgX3im2zAo2wanv/alD74KQ==", + "dev": true, + "dependencies": { + "envinfo": "^7.7.3" + }, + "peerDependencies": { + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.0.tgz", + "integrity": "sha512-k2p2VrONcYVX1wRRrf0f3X2VGltLWcv+JzXRBDmvCxGlCeESx4OXw91TsWeKOkp784uNoVQo313vxJFHXPPwfw==", + "dev": true, + "peerDependencies": { + "webpack-cli": "4.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "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" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-includes": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", + "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", + "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24= sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001370", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001370.tgz", + "integrity": "sha512-3PDmaP56wz/qz7G508xzjx8C+MC2qEm4SYhSEzC9IBROo+dGXFWRuaXkWti0A9tuI00g+toiriVqxtWMgl350g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/chrome-trace-event/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + }, + "node_modules/clean-css": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", + "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/copy-webpack-plugin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-7.0.0.tgz", + "integrity": "sha512-SLjQNa5iE3BoCP76ESU9qYo9ZkEWtXoZxDurHoqPchAFRblJ9g96xTeC560UXBMre1Nx6ixIIUfiY3VcjpJw3g==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.4", + "glob-parent": "^5.1.1", + "globby": "^11.0.1", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-loader": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", + "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.7", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/css-select": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", + "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^5.1.0", + "domhandler": "^4.3.0", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", + "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", + "dev": true + }, + "node_modules/detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "dependencies": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", + "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.140", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.140.tgz", + "integrity": "sha512-NLz5va823QfJBYOO/hLV4AfU4Crmkl/6Hl2pH3qdJcmi0ySZ3YTWHxOlDm3uJOFBEPy3pIhu8gKQo6prQTWKKA==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/engine.io-client": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz", + "integrity": "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", + "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", + "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-module-lexer": { + "version": "0.3.26", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.3.26.tgz", + "integrity": "sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA==" + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.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", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.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.merge": "^4.6.2", + "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": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.1.0.tgz", + "integrity": "sha512-A3AXIEfTnq3D5qDFjWJdQ9c4BLhw/TqhSR+6+SVaoPJBAWciFEuJiNQh275OnjRrAi7yssZzuWBRw66VG2g6UA==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.30.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz", + "integrity": "sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.5", + "array.prototype.flatmap": "^1.3.0", + "doctrine": "^2.1.0", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.5", + "object.fromentries": "^2.0.5", + "object.hasown": "^1.1.1", + "object.values": "^1.1.5", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.3", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", + "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", + "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fuzzy-search": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/fuzzy-search/-/fuzzy-search-3.2.1.tgz", + "integrity": "sha512-vAcPiyomt1ioKAsAL2uxSABHJ4Ju/e4UeDM+g1OlR0vV4YhLGMNsdLNvZTpEDY4JCSt0E4hASCNM5t2ETtsbyg==" + }, + "node_modules/get-browser-rtc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", + "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", + "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "webpack": "^5.20.0" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/http/-/http-0.0.1-security.tgz", + "integrity": "sha512-RnDvP10Ty9FxqOtPZuxtebw1j4L/WiqNMDtuc1YMH1XQm5TgDRaR1G9u8upL6KD1bXHSp9eSXo/ED+8Q7FAr+g==" + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.1.tgz", + "integrity": "sha512-pxrjmNpeRw5wwVeWyEAk7QJu2GnBO3uzPFmHCKJJFPKK2Cy0cWL23krGtLdnMmbIi6/FjlrQpPyfQI19ByPOhQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.5", + "object.assign": "^4.1.2" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/jwt-decode": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", + "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", + "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.find": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", + "integrity": "sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E=" + }, + "node_modules/lodash.has": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", + "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI=" + }, + "node_modules/lodash.isempty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", + "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==" + }, + "node_modules/lodash.remove": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.remove/-/lodash.remove-4.7.0.tgz", + "integrity": "sha512-GnwkSsEXGXirSxh3YI+jc/qvptE2DV8ZjA4liK0NT1MJ3mNDMFhX3bY+4Wr8onlNItYuPp7/4u19Fi55mvzkTw==" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "dependencies": { + "mime-db": "1.45.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-releases": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", + "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.hasown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz", + "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-change": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/on-change/-/on-change-4.0.1.tgz", + "integrity": "sha512-Gxmr/8NsLTigoUUEPvnAIUGl7uxwfC3Mm1G+qTmODEZcT4ZGfeaFyQgfGCdbKVS2pICIFYB82RH6MUHToPcS4Q==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/on-change?sponsor=1" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ping.js": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ping.js/-/ping.js-0.3.0.tgz", + "integrity": "sha512-qisFwio7j0cwYbOcRL4BlTdxKALcpGPTkpl8ichGASgkrVqfI3sZfQDsP8wETR5rfutXZJLjlJ117aLkRnk2mA==" + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.6" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz", + "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-use-intercom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-use-intercom/-/react-use-intercom-2.0.0.tgz", + "integrity": "sha512-DSm79RtGHAQyZ4WfBFuNMWtmpyLjWt6jhrhFwfMmy/eIvvCeJ+5wMdPMGXBn2+qzLDyhV0fqo3vNsqR4EvFqHw==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", + "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", + "dev": true, + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "node_modules/simple-peer": { + "version": "9.9.3", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.9.3.tgz", + "integrity": "sha512-T3wuv0UqBpDTV0x0pJPPsz4thy0tC0fTOHE4g9+AF43RUxxT+MWeXVtdQcK5Xuzv/XTVrB2NrGzdfO1IFBqOkw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "buffer": "^6.0.2", + "debug": "^4.2.0", + "err-code": "^2.0.3", + "get-browser-rtc": "^1.0.2", + "queue-microtask": "^1.2.0", + "randombytes": "^2.1.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/socket.io-client": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz", + "integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.2.1", + "socket.io-parser": "~4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz", + "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-loader": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/table": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", + "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/tailwindcss": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.6.tgz", + "integrity": "sha512-7skAOY56erZAFQssT1xkpk+kWt2NrO45kORlxFPXUt3CiGsVPhH1smuH5XoDH6sGPXLyBv+zgCKA2HWBsgCytg==", + "dev": true, + "dependencies": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.1", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.14", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.1" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.14.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", + "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz", + "integrity": "sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==", + "dependencies": { + "jest-worker": "^26.6.2", + "p-limit": "^3.1.0", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.5.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-loader": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.0.tgz", + "integrity": "sha512-2kLLAdAD+FCKijvGKi9sS0OzoqxLCF3CxHpok7rVgCZ5UldRzH0TkbwG9XECKjBzHsAewntC5oDaI/FwKzEUog==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "node_modules/v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, + "node_modules/watchpack": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz", + "integrity": "sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.21.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.21.2.tgz", + "integrity": "sha512-xHflCenx+AM4uWKX71SWHhxml5aMXdy2tu/vdi4lClm7PADKxlyDAFFN1rEFzNV0MAoPpHtBeJnl/+K6F4QBPg==", + "dependencies": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.46", + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/wasm-edit": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "acorn": "^8.0.4", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.7.0", + "es-module-lexer": "^0.3.26", + "eslint-scope": "^5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.1", + "watchpack": "^2.0.0", + "webpack-sources": "^2.1.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.5.0.tgz", + "integrity": "sha512-wXg/ef6Ibstl2f50mnkcHblRPN/P9J4Nlod5Hg9HGFgSeF8rsqDGHJeVe4aR26q9l62TUJi6vmvC2Qz96YJw1Q==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.0.1", + "@webpack-cli/info": "^1.2.2", + "@webpack-cli/serve": "^1.3.0", + "colorette": "^1.2.1", + "commander": "^7.0.0", + "enquirer": "^2.3.6", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "v8-compile-cache": "^2.2.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/init": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.0.0.tgz", + "integrity": "sha512-ovx/7NkTrnPuIV8sqk/GjUIIM1+iUQeqA3ye2VNpq9sVoiZsooObWlQy+OPWGI17GDaEoybuAGJm6U8yC077BA==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-merge": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", + "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.2.0.tgz", + "integrity": "sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==", + "dependencies": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.5.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.0.tgz", + "integrity": "sha512-3sLxVhbAB5OC8qvVRebCLWuouhwh/rswsiDYx3WGxajUk/l4G20SKfrKKFeNIHboUFt2JFgv2yfn+5cgOr/t5A==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@amplitude/analytics-browser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-browser/-/analytics-browser-1.1.1.tgz", + "integrity": "sha512-J6ftCTThmtKZ4OG6sqFu6eFIJHCP/s/GK+FMZ2mUSEwWxAUWQYWE8LLPnKo/BIDQXCT0q++sMc4+OMr8w7azPw==", + "requires": { + "@amplitude/analytics-core": "^0.6.4", + "@amplitude/analytics-types": "^0.6.1", + "@amplitude/ua-parser-js": "^0.7.31", + "tslib": "^2.3.1" + } + }, + "@amplitude/analytics-core": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-core/-/analytics-core-0.6.4.tgz", + "integrity": "sha512-RuWkLGO89O/8x88J7OPMIB1sSZ+toAJQeEI+KFkZGU1uQ0znhF1nLe64UUi39mP7qLMFYtQfXVD8IfNLIJt7IQ==", + "requires": { + "@amplitude/analytics-types": "^0.6.1", + "tslib": "^2.3.1" + } + }, + "@amplitude/analytics-types": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-types/-/analytics-types-0.6.1.tgz", + "integrity": "sha512-6XWxxt0LYMkOLZHnAzLoDRwhMcOeNviXEdba6tVVjYOM9zW6ZOCLZWO3N+/s+UF6tYOvDZyLH6a1PqAlNUvHqQ==" + }, + "@amplitude/ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@amplitude/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-+z8UGRaj13Pt5NDzOnkTBy49HE2CX64jeL0ArB86HAtilpnfkPB7oqkigN7Lf2LxscMg4QhFD7mmCfedh3rqTg==" + }, + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@discoveryjs/json-ext": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", + "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "@fortawesome/fontawesome-common-types": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.1.tgz", + "integrity": "sha512-wVn5WJPirFTnzN6tR95abCx+ocH+3IFLXAgyavnf9hUmN0CfWoDjPT/BAWsUVwSlYYVBeCLJxaqi7ZGe4uSjBA==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.1.tgz", + "integrity": "sha512-NCg0w2YIp81f4V6cMGD9iomfsIj7GWrqmsa0ZsPh59G7PKiGN1KymZNxmF00ssuAlo/VZmpK6xazsGOwzKYUMg==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.1.1" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.1.1.tgz", + "integrity": "sha512-0/5exxavOhI/D4Ovm2r3vxNojGZioPwmFrKg0ZUH69Q68uFhFPs6+dhAToh6VEQBntxPRYPuT5Cg1tpNa9JUPg==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.1.1" + } + }, + "@fortawesome/react-fontawesome": { + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.18.tgz", + "integrity": "sha512-RwLIB4TZw0M9gvy5u+TusAA0afbwM4JQIimNH/j3ygd6aIvYPQLqXMhC9ErY26J23rDPyDZldIfPq/HpTTJ/tQ==", + "requires": { + "prop-types": "^15.8.1" + } + }, + "@headlessui/react": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.6.5.tgz", + "integrity": "sha512-3VkKteDxlxf3fE0KbfO9t60KC1lM7YNpZggLpwzVNg1J/zwL+h+4N7MBlFDVpInZI3rKlZGpNx0PWsG/9c2vQg==", + "requires": {} + }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, + "@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "@types/chrome": { + "version": "0.0.130", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.130.tgz", + "integrity": "sha512-pAHbcPeOmjNCF5EoUCAZk3+5lll1yyIDP+CZRNf1Dk8LaANkNBNZ5szHqeYYVjMyEGP6yIFeaO+Y7qNpz1hVOw==", + "dev": true, + "requires": { + "@types/filesystem": "*", + "@types/har-format": "*" + } + }, + "@types/eslint": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz", + "integrity": "sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw==", + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz", + "integrity": "sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==", + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.46", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", + "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==" + }, + "@types/filesystem": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.29.tgz", + "integrity": "sha512-85/1KfRedmfPGsbK8YzeaQUyV1FQAvMPMTuWFQ5EkLd2w7szhNO96bk3Rh/SKmOfd9co2rCLf0Voy4o7ECBOvw==", + "dev": true, + "requires": { + "@types/filewriter": "*" + } + }, + "@types/filewriter": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.28.tgz", + "integrity": "sha1-wFTor02d11205jq8dviFFocU1LM= sha512-AR2KUJIMdSfl/SaAHpRotBAlaJpmhgHwehEeSJQOG0hS3IrjDU16xUEEUTdqcvdLa1q16ZK5MMrtOagfLvm0gw==", + "dev": true + }, + "@types/fuzzy-search": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/fuzzy-search/-/fuzzy-search-2.1.2.tgz", + "integrity": "sha512-YOqA50Z3xcycm4Br5+MBUpSumfdOAcv34A8A8yFn62zBQPTzJSXQk11qYE5w8BWQ0KrVThXUgEQh7ZLrYI1NaQ==", + "dev": true + }, + "@types/har-format": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.5.tgz", + "integrity": "sha512-IG8AE1m2pWtPqQ7wXhFhy6Q59bwwnLwO36v5Rit2FrbXCIp8Sk8E2PfUCreyrdo17STwFSKDAkitVuVYbpEHvQ==", + "dev": true + }, + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==" + }, + "@types/json-stringify-safe": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz", + "integrity": "sha512-UUA1sH0RSRROdInuDOA1yoRzbi5xVFD1RHCoOvNRPTNwR8zBkJ/84PZ6NhKVDtKp0FTeIccJCdQz1X2aJPr4uw==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.178", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz", + "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==", + "dev": true + }, + "@types/lodash.find": { + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/@types/lodash.find/-/lodash.find-4.6.7.tgz", + "integrity": "sha512-ESwK5k3nf9ufS+M2niH06/gjrREihHobyWQLs5c5+O93uar3N9s0rNx8bBfG9zLYVaPBJEsEIk06hm5ccstF5w==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.has": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@types/lodash.has/-/lodash.has-4.5.6.tgz", + "integrity": "sha512-SpUCvze0uHilQX/mt4K/cak5OQny1pVfz3pJx6H70dE3Tvw9s7EtlMK+vY6UBS+PQgETDfv6vhwoa3FPS2wrhg==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.isempty": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isempty/-/lodash.isempty-4.4.6.tgz", + "integrity": "sha512-AauKrFlA4z3Usog5HLGDupKzkCP7h5KXGlfAcRGUfvTmL7guVuEzDSNI6lYJ7syO7J2RE2F47179pSLr26UHIw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.isequal": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.6.tgz", + "integrity": "sha512-Ww4UGSe3DmtvLLJm2F16hDwEQSv7U0Rr8SujLUA2wHI2D2dm8kPu6Et+/y303LfjTIwSBKXB/YTUcAKpem/XEg==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.pick": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/@types/lodash.pick/-/lodash.pick-4.4.7.tgz", + "integrity": "sha512-HgdyKz7/1+oeoVzbpu1XiX/Bti9AUksHtOILH38T07aKvqoirzcdOsrO2+Yg3L51Hv/8m1MetvHZEUGeABiTiQ==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.remove": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/@types/lodash.remove/-/lodash.remove-4.7.7.tgz", + "integrity": "sha512-jZrQtY6zdukkFFinY+yxikzU3hCS6SEXsTy103Ao+2YsZq2H+D/NpXuAoZpcpn7BTMBUsgr2NO7l4UYHxKXXjw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.sortby": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/@types/lodash.sortby/-/lodash.sortby-4.7.7.tgz", + "integrity": "sha512-J/4IS+jQopGBrrRetBXDCX0KnSeXJZ0rOTmGAxR9MWGV24YdHxX8IRi9LCGAU9GKWlBov9KRSfQpuup9PReqrw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.union": { + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/@types/lodash.union/-/lodash.union-4.6.7.tgz", + "integrity": "sha512-6HXM6tsnHJzKgJE0gA/LhTGf/7AbjUk759WZ1MziVm+OBNAATHhdgj+a3KVE8g76GCLAnN4ZEQQG1EGgtBIABA==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.uniq": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/@types/lodash.uniq/-/lodash.uniq-4.5.7.tgz", + "integrity": "sha512-qg7DeAbdZMi6DGvCxThlJycykLLhETrJrQZ6F2KaZ+o0sNK1qRHz46lgNA+nHHjwrmA2a91DyiZTp3ey3m1rEw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lodash.uniqby": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/@types/lodash.uniqby/-/lodash.uniqby-4.7.7.tgz", + "integrity": "sha512-sv2g6vkCIvEUsK5/Vq17haoZaisfj2EWW8mP7QWlnKi6dByoNmeuHDDXHR7sabuDqwO4gvU7ModIL22MmnOocg==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/node": { + "version": "14.14.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.27.tgz", + "integrity": "sha512-Ecfmo4YDQPwuqTCl1yBxLV5ihKfRlkBmzUEDcfIRvDxOTGQEeikr317Ln7Gcv0tjA8dVgKI3rniqW2G1OyKDng==" + }, + "@types/prop-types": { + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", + "dev": true + }, + "@types/react": { + "version": "17.0.39", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz", + "integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", + "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true + }, + "@types/simple-peer": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/simple-peer/-/simple-peer-9.6.1.tgz", + "integrity": "sha512-WdXxmHW+m0NaD5XPGlp5AB7raq+NUWX/+/aQvDcoOx0qiP78QmDdk015W29uoyvGhyiJCb9dZJuI2Oi39zGRfg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@webassemblyjs/ast": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", + "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", + "requires": { + "@webassemblyjs/helper-numbers": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", + "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", + "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", + "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==" + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", + "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", + "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", + "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", + "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", + "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", + "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", + "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/helper-wasm-section": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-opt": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "@webassemblyjs/wast-printer": "1.11.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", + "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", + "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", + "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", + "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/configtest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.1.tgz", + "integrity": "sha512-B+4uBUYhpzDXmwuo3V9yBH6cISwxEI4J+NO5ggDaGEEHb0osY/R7MzeKc0bHURXQuZjMM4qD+bSJCKIuI3eNBQ==", + "dev": true, + "requires": {} + }, + "@webpack-cli/info": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.2.tgz", + "integrity": "sha512-5U9kUJHnwU+FhKH4PWGZuBC1hTEPYyxGSL5jjoBI96Gx8qcYJGOikpiIpFoTq8mmgX3im2zAo2wanv/alD74KQ==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.0.tgz", + "integrity": "sha512-k2p2VrONcYVX1wRRrf0f3X2VGltLWcv+JzXRBDmvCxGlCeESx4OXw91TsWeKOkp784uNoVQo313vxJFHXPPwfw==", + "dev": true, + "requires": {} + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-includes": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", + "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "array.prototype.flatmap": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", + "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + } + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24= sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "requires": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001370", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001370.tgz", + "integrity": "sha512-3PDmaP56wz/qz7G508xzjx8C+MC2qEm4SYhSEzC9IBROo+dGXFWRuaXkWti0A9tuI00g+toiriVqxtWMgl350g==" + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + }, + "clean-css": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", + "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true + }, + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "copy-webpack-plugin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-7.0.0.tgz", + "integrity": "sha512-SLjQNa5iE3BoCP76ESU9qYo9ZkEWtXoZxDurHoqPchAFRblJ9g96xTeC560UXBMre1Nx6ixIIUfiY3VcjpJw3g==", + "dev": true, + "requires": { + "fast-glob": "^3.2.4", + "glob-parent": "^5.1.1", + "globby": "^11.0.1", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "css-loader": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", + "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.7", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.5" + } + }, + "css-select": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", + "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^5.1.0", + "domhandler": "^4.3.0", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", + "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", + "dev": true + }, + "detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "requires": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + } + }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + }, + "domhandler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", + "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "electron-to-chromium": { + "version": "1.4.140", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.140.tgz", + "integrity": "sha512-NLz5va823QfJBYOO/hLV4AfU4Crmkl/6Hl2pH3qdJcmi0ySZ3YTWHxOlDm3uJOFBEPy3pIhu8gKQo6prQTWKKA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "engine.io-client": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz", + "integrity": "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "engine.io-parser": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", + "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==" + }, + "enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + }, + "envinfo": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", + "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", + "dev": true + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-module-lexer": { + "version": "0.3.26", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.3.26.tgz", + "integrity": "sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA==" + }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.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", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.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.merge": "^4.6.2", + "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": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "requires": {} + }, + "eslint-plugin-prettier": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.1.0.tgz", + "integrity": "sha512-A3AXIEfTnq3D5qDFjWJdQ9c4BLhw/TqhSR+6+SVaoPJBAWciFEuJiNQh275OnjRrAi7yssZzuWBRw66VG2g6UA==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-plugin-react": { + "version": "7.30.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz", + "integrity": "sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==", + "dev": true, + "requires": { + "array-includes": "^3.1.5", + "array.prototype.flatmap": "^1.3.0", + "doctrine": "^2.1.0", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.5", + "object.fromentries": "^2.0.5", + "object.hasown": "^1.1.1", + "object.values": "^1.1.5", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.3", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.7" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==" + }, + "execa": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "fastq": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", + "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", + "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true + }, + "fuzzy-search": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/fuzzy-search/-/fuzzy-search-3.2.1.tgz", + "integrity": "sha512-vAcPiyomt1ioKAsAL2uxSABHJ4Ju/e4UeDM+g1OlR0vV4YhLGMNsdLNvZTpEDY4JCSt0E4hASCNM5t2ETtsbyg==" + }, + "get-browser-rtc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", + "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "dev": true + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", + "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "requires": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + } + }, + "html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "dev": true, + "requires": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "http": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/http/-/http-0.0.1-security.tgz", + "integrity": "sha512-RnDvP10Ty9FxqOtPZuxtebw1j4L/WiqNMDtuc1YMH1XQm5TgDRaR1G9u8upL6KD1bXHSp9eSXo/ED+8Q7FAr+g==" + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "requires": {} + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "jsx-ast-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.1.tgz", + "integrity": "sha512-pxrjmNpeRw5wwVeWyEAk7QJu2GnBO3uzPFmHCKJJFPKK2Cy0cWL23krGtLdnMmbIi6/FjlrQpPyfQI19ByPOhQ==", + "dev": true, + "requires": { + "array-includes": "^3.1.5", + "object.assign": "^4.1.2" + } + }, + "jwt-decode": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", + "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lilconfig": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", + "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", + "dev": true + }, + "loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==" + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.find": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", + "integrity": "sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E=" + }, + "lodash.has": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", + "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI=" + }, + "lodash.isempty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", + "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==" + }, + "lodash.remove": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.remove/-/lodash.remove-4.7.0.tgz", + "integrity": "sha512-GnwkSsEXGXirSxh3YI+jc/qvptE2DV8ZjA4liK0NT1MJ3mNDMFhX3bY+4Wr8onlNItYuPp7/4u19Fi55mvzkTw==" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==" + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" + }, + "mime-types": { + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "requires": { + "mime-db": "1.45.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node-releases": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "object.fromentries": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", + "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "object.hasown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz", + "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==", + "dev": true, + "requires": { + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "on-change": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/on-change/-/on-change-4.0.1.tgz", + "integrity": "sha512-Gxmr/8NsLTigoUUEPvnAIUGl7uxwfC3Mm1G+qTmODEZcT4ZGfeaFyQgfGCdbKVS2pICIFYB82RH6MUHToPcS4Q==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + }, + "ping.js": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ping.js/-/ping.js-0.3.0.tgz", + "integrity": "sha512-qisFwio7j0cwYbOcRL4BlTdxKALcpGPTkpl8ichGASgkrVqfI3sZfQDsP8wETR5rfutXZJLjlJ117aLkRnk2mA==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.6" + } + }, + "postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "queue-microtask": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz", + "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==", + "dev": true + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "react-use-intercom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-use-intercom/-/react-use-intercom-2.0.0.tgz", + "integrity": "sha512-DSm79RtGHAQyZ4WfBFuNMWtmpyLjWt6jhrhFwfMmy/eIvvCeJ+5wMdPMGXBn2+qzLDyhV0fqo3vNsqR4EvFqHw==", + "requires": {} + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "requires": { + "pify": "^2.3.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "rechoir": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", + "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "requires": { + "tslib": "^2.1.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "simple-peer": { + "version": "9.9.3", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.9.3.tgz", + "integrity": "sha512-T3wuv0UqBpDTV0x0pJPPsz4thy0tC0fTOHE4g9+AF43RUxxT+MWeXVtdQcK5Xuzv/XTVrB2NrGzdfO1IFBqOkw==", + "dev": true, + "requires": { + "buffer": "^6.0.2", + "debug": "^4.2.0", + "err-code": "^2.0.3", + "get-browser-rtc": "^1.0.2", + "queue-microtask": "^1.2.0", + "randombytes": "^2.1.0", + "readable-stream": "^3.6.0" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "socket.io-client": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz", + "integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.2.1", + "socket.io-parser": "~4.2.0" + } + }, + "socket.io-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz", + "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + } + }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "style-loader": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "dev": true, + "requires": {} + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "table": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", + "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "tailwindcss": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.6.tgz", + "integrity": "sha512-7skAOY56erZAFQssT1xkpk+kWt2NrO45kORlxFPXUt3CiGsVPhH1smuH5XoDH6sGPXLyBv+zgCKA2HWBsgCytg==", + "dev": true, + "requires": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.1", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.14", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.1" + }, + "dependencies": { + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + } + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, + "terser": { + "version": "5.14.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", + "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + } + } + }, + "terser-webpack-plugin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz", + "integrity": "sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==", + "requires": { + "jest-worker": "^26.6.2", + "p-limit": "^3.1.0", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.5.1" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-loader": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.0.tgz", + "integrity": "sha512-2kLLAdAD+FCKijvGKi9sS0OzoqxLCF3CxHpok7rVgCZ5UldRzH0TkbwG9XECKjBzHsAewntC5oDaI/FwKzEUog==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, + "watchpack": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz", + "integrity": "sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw==", + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "webpack": { + "version": "5.21.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.21.2.tgz", + "integrity": "sha512-xHflCenx+AM4uWKX71SWHhxml5aMXdy2tu/vdi4lClm7PADKxlyDAFFN1rEFzNV0MAoPpHtBeJnl/+K6F4QBPg==", + "requires": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.46", + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/wasm-edit": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "acorn": "^8.0.4", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.7.0", + "es-module-lexer": "^0.3.26", + "eslint-scope": "^5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.1", + "watchpack": "^2.0.0", + "webpack-sources": "^2.1.1" + } + }, + "webpack-cli": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.5.0.tgz", + "integrity": "sha512-wXg/ef6Ibstl2f50mnkcHblRPN/P9J4Nlod5Hg9HGFgSeF8rsqDGHJeVe4aR26q9l62TUJi6vmvC2Qz96YJw1Q==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.0.1", + "@webpack-cli/info": "^1.2.2", + "@webpack-cli/serve": "^1.3.0", + "colorette": "^1.2.1", + "commander": "^7.0.0", + "enquirer": "^2.3.6", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "v8-compile-cache": "^2.2.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "commander": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.0.0.tgz", + "integrity": "sha512-ovx/7NkTrnPuIV8sqk/GjUIIM1+iUQeqA3ye2VNpq9sVoiZsooObWlQy+OPWGI17GDaEoybuAGJm6U8yC077BA==", + "dev": true + } + } + }, + "webpack-merge": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", + "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.2.0.tgz", + "integrity": "sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==", + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "requires": {} + }, + "xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "yargs": { + "version": "17.5.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.0.tgz", + "integrity": "sha512-3sLxVhbAB5OC8qvVRebCLWuouhwh/rswsiDYx3WGxajUk/l4G20SKfrKKFeNIHboUFt2JFgv2yfn+5cgOr/t5A==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + } + }, + "yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==" + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + } + } +} diff --git a/browser/hybrid/components/cloud_tabs_extension/package.json b/browser/hybrid/components/cloud_tabs_extension/package.json new file mode 100644 index 00000000000..3c990308ee3 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/package.json @@ -0,0 +1,86 @@ +{ + "name": "cloud-tabs-extension", + "version": "1.0.0", + "description": "The cloud tabs extension enables creating cloud tabs.", + "repository": "https://github.com/whisthq/whist", + "author": "Whist Technologies, Inc.", + "license": "UNLICENSED", + "private": true, + "devDependencies": { + "@types/chrome": "^0.0.130", + "@types/simple-peer": "^9.6.1", + "@types/fuzzy-search": "^2.1.2", + "@types/json-stringify-safe": "^5.0.0", + "@types/lodash.find": "^4.6.7", + "@types/lodash.has": "^4.5.6", + "@types/lodash.isempty": "^4.4.6", + "@types/lodash.isequal": "^4.5.6", + "@types/lodash.pick": "^4.4.7", + "@types/lodash.remove": "^4.7.7", + "@types/lodash.sortby": "^4.7.7", + "@types/lodash.union": "^4.6.7", + "@types/lodash.uniq": "^4.5.7", + "@types/lodash.uniqby": "^4.7.7", + "@types/react": "^17.0.39", + "@types/react-dom": "^17.0.11", + "copy-webpack-plugin": "^7.0.0", + "css-loader": "^6.7.1", + "eslint": "<8.0.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.1.0", + "eslint-plugin-react": "^7.30.1", + "html-webpack-plugin": "^5.5.0", + "path-browserify": "^1.0.1", + "prettier": "^2.7.1", + "process": "^0.11.10", + "simple-peer": "^9.9.3", + "style-loader": "^3.3.1", + "tailwindcss": "^3.1.6", + "ts-loader": "^9.3.0", + "typescript": "^4.8.3", + "webpack": "^5.21.2", + "webpack-cli": "^4.5.0" + }, + "scripts": { + "build": "node ./scripts/build.js", + "format": "prettier --write .", + "format:check": "prettier --check ,", + "lint:check": "node ./scripts/lint.js --fix", + "lint:fix": "node ./scripts/lint.js --fix" + }, + "dependencies": { + "@amplitude/analytics-browser": "^1.1.1", + "@fortawesome/fontawesome-svg-core": "^6.1.1", + "@fortawesome/free-solid-svg-icons": "^6.1.1", + "@fortawesome/react-fontawesome": "^0.1.18", + "@headlessui/react": "^1.6.5", + "buffer": "^6.0.3", + "classnames": "^2.3.1", + "file-loader": "^6.2.0", + "fuzzy-search": "^3.2.1", + "http": "^0.0.1-security", + "https-browserify": "^1.0.0", + "json-stringify-safe": "^5.0.1", + "jwt-decode": "^3.1.2", + "lodash.find": "^4.6.0", + "lodash.has": "^4.5.2", + "lodash.isempty": "^4.4.0", + "lodash.isequal": "^4.5.0", + "lodash.pick": "^4.4.0", + "lodash.remove": "^4.7.0", + "lodash.sortby": "^4.7.0", + "lodash.union": "^4.6.0", + "lodash.uniq": "^4.5.0", + "lodash.uniqby": "^4.7.0", + "on-change": "^4.0.1", + "ping.js": "^0.3.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-use-intercom": "^2.0.0", + "rxjs": "^7.5.5", + "socket.io-client": "^4.5.1", + "stream-http": "^3.2.0", + "url": "^0.11.0", + "yargs": "^17.5.0" + } +} diff --git a/browser/hybrid/components/cloud_tabs_extension/public/BUILD.gn b/browser/hybrid/components/cloud_tabs_extension/public/BUILD.gn new file mode 100644 index 00000000000..71bd08cfc57 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/public/BUILD.gn @@ -0,0 +1,37 @@ +import("//brave/components/common/typescript.gni") + +transpile_web_ui("whist_extension") { + # This needs to fire re-pack if changed, nevertheless the extension + # is repacked on each 2nd build + + # Define what the output bundle is called and what the entry point file is + entry_points = [ + [ + "whist_popup", + rebase_path("popup.js"), + ], + [ + "whist_worker", + rebase_path("worker.js"), + ], + [ + "whist_content_script", + rebase_path("content.js"), + ], + [ + "whist_tab", + rebase_path("tab.js"), + ], + ] + + # The directory / pack name + resource_name = "whist_extension" + + # Must match the relative path from the static GRD to the manifest.json + # plus any other relative path we want these files to live in the extension + extra_relative_path = "/whist_extension/out" + + public_asset_path = "/out/" + + deps = [] +} diff --git a/browser/hybrid/components/cloud_tabs_extension/public/css/content.css b/browser/hybrid/components/cloud_tabs_extension/public/css/content.css new file mode 100644 index 00000000000..9f8862e2fbc --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/public/css/content.css @@ -0,0 +1,26 @@ +.whist-notification { + animation: fadeIn 1.5s; + animation-duration: 1.5s; + font-family: BlinkMacSystemFont, Arial, Helvetica; + z-index: 999999; + padding: 15px 20px; + position: fixed; + top: 10px; + right: 10px; + border-radius: 5px; + display: flex; + align-items: center; + backdrop-filter: blur(5px); + font-size: 13px; + font-weight: 500; +} + +@keyframes fadeIn { + 0% { opacity: 0; } + 100% { opacity: 1; } + } + +@keyframes fadeOut { + 0% { opacity: 1; } + 100% { opacity: 0; visibility: hidden; } +} diff --git a/browser/hybrid/components/cloud_tabs_extension/public/icons/cloud-off.png b/browser/hybrid/components/cloud_tabs_extension/public/icons/cloud-off.png new file mode 100644 index 0000000000000000000000000000000000000000..081e003d090dcfd281b37699ad9486f1833e9fd1 GIT binary patch literal 2415 zcmV-#36S=QP)*Tov39pGY<}pMpI2pGtL+~fi}^mrRhuC zC)3*KLmN%Od(f&?jHFg07VAA#jMjQVMZh~kzi;QPlgV*Vfint)850X=&LwYu2nCsteK~0u>b%=>YI90Ii0#V^C#+4F=pdO1lZ{*|Vn*06&VwV(Cx~)+AuMP8b210UMuy^m? zjR3cvz)kQ%APBt6gM6Z|=6%9JTbR0pL;*u%}6HzzM&zWfk?{CgSa1P0)pf6L-@a*;m6d2{#1Yj_i3U9Y_yYj?7lLWYt*$2-yGQ zqkk5FodxU4QeiG-=(s_H2JM+NX;P}{D1q|wa_08;P4KQ6FkK-Cy!|YZYu&naOJnf* zR5m+?1N`99~)ol8kb04r-RxXcH()lEx=0keJFeilaL!i5X!$&)AcxAKaMi@(PG z8wm2oW5Ed?r|Hk1 zKUXhayeK|=`0zR>0k}>U27lYNNQJq9i%3wmF#$`Pa`50mb@}q;Ht+T6(?_AqPyny> z*|TR_L1H~hnT$9B0Q?p-!vvowJ=&HxpSjiqn*{aj*|VywtSpYyuwldW`*bU+5P_zl z&kDgE^O;1We-CmM8+=$^m$ryq$VnYUIez@O+P-~zTtBvvMm1m)kHjWi{Y`Y;;LpIW zUAtaKhwPvf=nBrDS+Hlo^&JA+x^=7CvSo{I+XkWgkVsQglY0F4u~wN0PsZ)sxpS63 z1L*t@*FYV~EUtHL%hQJ$tcMOAQjLv`x{py_`;wB9qQRTVMA}1#4wY~J6&!@=8QUh`n0-x_ih`P=!g&`1DoF^ zt~qn&sPW^+>u+%!b6bjgBe^YnEzIJ!+>GRGT-qMLnMYqN)X_ndz|7cSFR{*Kr~>kqUK5(CPBavhic@=kt!!A zM~xXXM#m$8o9l*6fD*%iEjCb>)kWwYmo8n>(@bHTY6BN*2f0#OTAHr^37R@&$PoWM zbHOv!d@fs2rqKrbC5jL`R~1aJ2j%M&!+fkoMf5hHX^nr`8;uIrf%Ual}? z17qMP`y-|>c(~CZ39%|y(Gw?5IA==U&&$hGix)4}i;``%FmU#Ff-LWS=eHOJ_yvvU z&?MJKv60Xu%nXDbQXpaWS+Zn_nm>QO6R-^`(JYu27o`j1+Ke^qOmyztxsUOq+Vw#O zDl?85%q$DepFbZ6f;oHMym^6^b`f&TU=Vmw81=`cOP4;4dRD72ttD4irFiq^P33Yq zxyK+)FzpHb+rH;n+;7t((5~RPngDKoYY#-rOExjfi${+h#SLWUYROVESQy|icX9z2 zWjx~EcAvn41q*)0gQGSHyN;2qUf7^GoKm-M-;SI9MBr_|xBR^gcwB#2wrtr&pMW`uoF&5B;>uJuP=s99TeHzkXd^yLL^#GkNl4r}gbjV;T(BZ-Fki@j7c? z9CG~&0JgAVz$Va8k``#dJo|#wa!z<$mna|H?Hh6O!ev^p-*TR)6SAJ<@b)HTm z9=2kzkGZi9+w8bzCFs7qLt#nIEvFfzj$rk{qh0C(A4q_*aN)xL-~?fVYc&o!Mhx3e z+oy9}(YgJ!XH{m>I8xlWV#SJeK{x{mcqHD1Z+{|3AwlsF1T-v$sQj)8+&gXX&q6_@ zbk(X=MPV322~bcHzXK9$;7+V{TWzrI0qnZZK+n$3R^F+z51a~O&A9#>;MXO>myiIZ zprGJWY-YyP*Vmtr(%N+f>T)Gl8-EAWrwu$pF@bxQKZ04AzIyfQ&F#U~;d2k1X}*ON zTZF;0kU?5uy@;8KB>2oMC2d%}m8Z^F1S56;qfZ^K@2y$0=Ch9A>D0d(;4hf3!I}$T z&9|XBJl^nfcZ&x$;;rVbAR3{ik&;_MJZh&)XeHX^(6836U0bg@C|&wz56Y%Zn{q(r zO%UM<`MUmSB>sfLC>35nYXF?}d>JfWt-2sxCSVGV%ljf${saO8VbL~!lmiL=IsP2B hfmcutG^%cr-vLNK{rdvHGgbfq002ovPDHLkV1m$Dn$!RQ literal 0 HcmV?d00001 diff --git a/browser/hybrid/components/cloud_tabs_extension/public/icons/cloud-on.png b/browser/hybrid/components/cloud_tabs_extension/public/icons/cloud-on.png new file mode 100644 index 0000000000000000000000000000000000000000..40e902f1f3c7b4761c682ed3e23a8b9cab8cacdc GIT binary patch literal 3607 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 + + + + + + Whist + + + +
+ + + diff --git a/browser/hybrid/components/cloud_tabs_extension/public/manifest.json b/browser/hybrid/components/cloud_tabs_extension/public/manifest.json new file mode 100644 index 00000000000..efecdb51fc9 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/public/manifest.json @@ -0,0 +1,48 @@ +{ + "name": "Cloud Tabs", + "version": "1.0.0", + "manifest_version": 2, + "description": "The Whist Extension enables creating cloud tabs.", + "browser_action": { + "default_title": "Cloud Tabs", + "default_popup": "popup.html" + }, + "background": { + "scripts": ["out/whist_worker.bundle.js"], + "persistent": true + }, + "web_accessible_resources": ["/css/content.css"], + "content_scripts": [ + { + "matches": [""], + "js": ["out/whist_content_script.bundle.js"], + "css": ["/css/content.css"], + "run_at": "document_start", + "all_frames": true + } + ], + "permissions": [ + "browserAction", + "cookies", + "downloads", + "history", + "identity", + "idle", + "storage", + "tabs", + "webRequest", + "webRequestBlocking", + "webNavigation", + "runtime", + "*://*/*", + "*://fractal-dev.us.auth0.com/*", + "*://fractal-staging.us.auth0.com/*", + "*://auth.whist.com/*" + ], + "host_permissions": ["*://*/*"], + "icons": { + "48": "/icons/cloud-off.png" + }, + "content_security_policy": "script-src-elem 'self' https:", + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi18w/rnQgTy3EP1V7ciHpDA2ORMq/wzNCbBfrbfvem3n8eWVgfbpnnDmIIWJookv/2Ob5P4Cov2gj9R2nTn0TGoJT/btdDngd4mUOJhrdJ/gJakP7Z5aaM2dE4fQO2To8ggdyqnXjjqvkVUYvzWdi/5ozun9FrAdzyb3SqjvlmwtcbxdOSPCKujxkKh05+YS+c8FAd5sQLdNHNtvdLU0qSkSL37s9/kUr6wAzZcA/bJGAhLvzF8wjFUGbbxRzlfB+AoUArVsOs7t8ss1a974nP3mVdGRKtNCNPaBIASHLp/rcycyQcWj3QwU2w7yV9RTP0noZlB9Uen3wWxENwj70QIDAQAB" +} diff --git a/browser/hybrid/components/cloud_tabs_extension/public/popup.html b/browser/hybrid/components/cloud_tabs_extension/public/popup.html new file mode 100644 index 00000000000..a89cb000977 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/public/popup.html @@ -0,0 +1,18 @@ + + + + + + + Whist + + + +
+ + + diff --git a/browser/hybrid/components/cloud_tabs_extension/scripts/build.js b/browser/hybrid/components/cloud_tabs_extension/scripts/build.js new file mode 100644 index 00000000000..ba0d37d8600 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/scripts/build.js @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2021-2022 Whist Technologies, Inc. + * @file build.js + * @brief This file contains utility functions for building the Whist Extension. + */ + +const execCommand = require("./execCommand").execCommand +const helpers = require("./helpers") +const yargs = require("yargs") + +const build = (argv) => { + let json = { + COMMIT_SHA: argv.commit ?? "local_dev", + AUTH0_CLIENT_ID: argv.auth0_client_id, + AUTH0_DOMAIN_URL: argv.auth0_domain_url, + AUTH0_REDIRECT_URL: argv.auth0_redirect_url, + SCALING_SERVICE_URL: argv.scaling_service_url, + AMPLITUDE_KEY: argv.amplitude_key, + HOST_IP: argv.host_ip, + } + + console.log("Building Whist extension with config", json) + helpers.createConfigFileFromJSON(json) + + // Build Tailwind CSS file + helpers.buildTailwind() + + execCommand( + `webpack --config webpack.config.js ${ + argv.output_dir ? `--env targetDir=${argv.output_dir}` : "" + }` + ) +} + +if (require.main === module) { + const argv = yargs(process.argv.slice(2)) + .version(false) + .option("commit", { + description: "Set the commit hash of the current branch", + type: "string", + requiresArg: true, + demandOption: false, + }) + .option("whistVersion", { + description: "Set the commit hash of the current branch", + type: "string", + requiresArg: true, + demandOption: false, + }) + .option("auth0_client_id", { + description: "Auth0 client ID", + type: "string", + requiresArg: true, + demandOption: false, + }) + .option("auth0_domain_url", { + description: "Auth0 domain URL", + type: "string", + requiresArg: true, + demandOption: false, + }) + .option("auth0_redirect_url", { + description: "Auth0 redirect URL", + type: "string", + requiresArg: true, + demandOption: false, + }) + .option("scaling_service_url", { + description: "Scaling service URL", + type: "string", + requiresArg: true, + demandOption: false, + }) + .option("host_ip", { + description: "Set a testing host IP", + type: "string", + requiresArg: true, + demandOption: false, + }) + .option("amplitude_key", { + description: "Amplitude public key", + type: "string", + requiresArg: true, + demandOption: false, + }) + .option("output_dir", { + description: "Build output directory (defaults to `build`)", + type: "string", + requiresArg: true, + demandOption: false, + }) + .help().argv + + build(argv) +} diff --git a/browser/hybrid/components/cloud_tabs_extension/scripts/execCommand.js b/browser/hybrid/components/cloud_tabs_extension/scripts/execCommand.js new file mode 100644 index 00000000000..6cfc65271f9 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/scripts/execCommand.js @@ -0,0 +1,25 @@ + +/** + * Copyright (c) 2021-2022 Whist Technologies, Inc. + * @file execCommand.js + * @brief Execute a command in a cross-platform manner. + */ + +const execSync = require("child_process").execSync + +module.exports = { + execCommand: (command, cwd, env = {}, stdio = "inherit") => { + try { + const output = execSync(command, { + encoding: "utf-8", + cwd: cwd, + env: { ...process.env, ...env }, + stdio: stdio, + }) + return output + } catch (error) { + console.error(`Error running "${command}": ${error}`) + process.exit(-1) + } + }, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/scripts/helpers.js b/browser/hybrid/components/cloud_tabs_extension/scripts/helpers.js new file mode 100644 index 00000000000..6da29229cc5 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/scripts/helpers.js @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2021-2022 Whist Technologies, Inc. + * @file helpers.js + * @brief This file contains helpers for building the Whist Extension. + */ + +const fs = require("fs") +const execCommand = require("./execCommand").execCommand + +module.exports = { + // Creates the Tailwind CSS file + buildTailwind: () => { + process.stdout.write("\nBuilding CSS with Tailwind..."); + execCommand("tailwindcss build -o public/css/tailwind.css", ".") + process.stdout.write("\n") + }, + // Function to set the commit sha for the packaged app, which gets + // hardcoded into the electron bundle via `env_overrides.json`. + // Acceptable arguments: a git commit sha + checkCommitSha: (e) => { + if (!(e.length === 40 && /^[a-f0-9]+$/.test(e))) { + console.error(`setPackagedCommitSha passed a bad commit sha: ${e}`) + process.exit(-1) + } + }, + createConfigFileFromJSON: (json) => { + fs.writeFileSync("src/generated_config.json", JSON.stringify(json)) + }, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/scripts/lint.js b/browser/hybrid/components/cloud_tabs_extension/scripts/lint.js new file mode 100644 index 00000000000..e2b5249574d --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/scripts/lint.js @@ -0,0 +1,32 @@ +/* scripts/lint.js + * + * This script triggers lint checking and/or fixing for all of + * our source files, using ESLint. + * + * This should be invoked via: + * $ yarn lint:check + * or: + * $ yarn lint:fix + * from your command line. + * + */ + +const { execute } = require("../node_modules/eslint/lib/cli") + +// The first two arguments here are simply placeholders, as ESLint CLI expects to be called in this way + +const lint = (_env, ...args) => { + execute([ + "yarn", + "eslint", + ...args, + "--max-warnings=0", + "./src/**/*.{js,jsx,ts,tsx}", + ]).then((ret) => process.exit(ret)) +} + +module.exports = lint + +if (require.main === module) { + lint({}, ...process.argv.slice(2)) +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/@core-ts/api.ts b/browser/hybrid/components/cloud_tabs_extension/src/@core-ts/api.ts new file mode 100644 index 00000000000..19cfb7fbdce --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/@core-ts/api.ts @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2021-2022 Whist Technologies, Inc. + * @file api.ts + * @brief This file contains utility functions for HTTP requests. + */ + +import stringify from "json-stringify-safe" + +const httpConfig = + (method: string) => + async (args: { body: object; url: string; accessToken?: string }) => { + const response = await fetch(args.url, { + method, + headers: { + "Content-Type": "application/json", + ...(args.accessToken !== undefined && { + Authorization: `Bearer ${args.accessToken}`, + }), + }, + body: stringify(args.body), + }) + + try { + const json = await response.json() + + return { + status: response.status, + json, + } + } catch (err) { + return { + status: response.status, + json: {}, + } + } + } + +const post = httpConfig("POST") +const put = httpConfig("PUT") + +export { post, put } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/@core-ts/auth.ts b/browser/hybrid/components/cloud_tabs_extension/src/@core-ts/auth.ts new file mode 100644 index 00000000000..55eabc8d93a --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/@core-ts/auth.ts @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2021-2022 Whist Technologies, Inc. + * @file auth.ts + * @brief This file contains utility functions authentication. + */ + +import jwtDecode from "jwt-decode" +import { Buffer } from "buffer" + +import { post } from "@app/@core-ts/api" + +import { config } from "@app/constants/app" + +export const authInfoCallbackRequest = async ( + callbackURL: string | undefined +) => { + /* + Description: + Given a callback URL, generates an { email, accessToken, refreshToken } response + Arguments: + callbackURL (string): Callback URL + Returns: + {email, accessToken, refreshToken} + */ + + if (callbackURL === undefined) return + try { + const url = new URL(callbackURL) + const code = url.searchParams.get("code") + + const response = await post({ + url: `https://${config.AUTH0_DOMAIN_URL}/oauth/token`, + body: { + grant_type: "authorization_code", + client_id: config.AUTH0_CLIENT_ID, + code, + redirect_uri: config.AUTH0_REDIRECT_URL, + }, + }) + + return response + } catch (err) {} +} + +export const parseAuthInfo = (res: { + status: number + json: { + id_token?: string + access_token?: string + refresh_token?: string + } +}) => { + /* + Description: + Helper function that takes an Auth0 response and extracts a {email, sub, accessToken} object + Arguments: + Response (Record): Auth0 response object + Returns: + {email, sub, accessToken, subscriptionStatus} + */ + + try { + const accessToken = res?.json.access_token + const decodedAccessToken = jwtDecode(accessToken ?? "") + const decodedIdToken = jwtDecode(res?.json.id_token ?? "") + const userEmail = decodedIdToken?.email + const subscriptionStatus = + decodedAccessToken["https://api.fractal.co/subscription_status"] + + if (typeof accessToken !== "string") + return { + error: { + message: "Response does not have .json.access_token", + data: res, + }, + } + if (typeof userEmail !== "string") + return { + error: { + message: "Decoded JWT does not have property .email", + data: res, + }, + } + return { + userEmail, + accessToken, + subscriptionStatus, + refreshToken: res?.json.refresh_token, + } + } catch (err) { + return { + error: { + message: `Error while decoding JWT: ${err as string}`, + data: res, + }, + } + } +} + +export const generateRandomConfigToken = () => { + /* + Description: + Generates a config token for app config security + Returns: + string: Config token + */ + + const buffer = Buffer.from(crypto.getRandomValues(new Uint32Array(48))) + return buffer.toString("base64") +} + +export const isTokenExpired = (accessToken: string) => { + // Extract the expiry in seconds since epoch + try { + const profile: { exp: number } = jwtDecode(accessToken) + // Get current time in seconds since epoch + const currentTime = Date.now() / 1000 + // Allow for ten seconds so we don't compare the access token to the current time right + // before the expiry + const secondsBuffer = 10 + return currentTime + secondsBuffer > profile.exp + } catch (err) { + console.log(`Failed to decode access token: ${err}`) + return true + } +} + +export const requestAuthInfoRefresh = async (refreshToken: string) => { + /* + Description: + Given a valid Auth0 refresh token, generates a new {email, accessToken, refreshToken} object + Arguments: + refreshToken (string): Refresh token + Returns: + {email, accessToken, refreshToken} + */ + return await post({ + url: `https://${config.AUTH0_DOMAIN_URL}/oauth/token`, + body: { + grant_type: "refresh_token", + client_id: config.AUTH0_CLIENT_ID, + refresh_token: refreshToken, + scope: "openid profile offline_access email", + }, + }) +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/@types/api.ts b/browser/hybrid/components/cloud_tabs_extension/src/@types/api.ts new file mode 100644 index 00000000000..54c562bcdac --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/@types/api.ts @@ -0,0 +1,2 @@ +export type AsyncReturnType Promise> = + T extends (...args: any) => Promise ? R : any diff --git a/browser/hybrid/components/cloud_tabs_extension/src/@types/index.d.ts b/browser/hybrid/components/cloud_tabs_extension/src/@types/index.d.ts new file mode 100644 index 00000000000..4530fa1477b --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/@types/index.d.ts @@ -0,0 +1,34 @@ +declare module "*.svg" { + const content: any + export default content +} + +declare module "*.jpg" { + const content: string + export default content +} + +declare module "*.png" { + const content: string + export default content +} + +declare module "*.json" { + const content: string + export default content +} + +declare module "*.gif" { + const content: string + export default content +} + +declare module "*.css" { + interface IClassNames { + [className: string]: string + } + const classNames: IClassNames + export = classNames +} + +declare module "rxjs" diff --git a/browser/hybrid/components/cloud_tabs_extension/src/@types/messaging.ts b/browser/hybrid/components/cloud_tabs_extension/src/@types/messaging.ts new file mode 100644 index 00000000000..d23ec22745e --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/@types/messaging.ts @@ -0,0 +1,23 @@ +export enum ContentScriptMessageType { + INJECT_WHIST_TAG, +} + +export enum PopupMessageType { + STREAM_TAB, // Fired by the popup when the user clicks the stream tab toggle + FETCH_POPUP_DATA, // Fired by the popup to request data from the background script + SEND_POPUP_DATA, // Fired by the background script to send updated data to the popup + SAVE_URL, // Fired by the popup when the user clicks the "always stream this URL" checkbox + OPEN_LOGIN_PAGE, // Fired by the popup when the user clicks the login button + OPEN_INTERCOM, // Fired by the popup when the user clicks the help button + INVITE_CODE, // Fired by the popup when the user enters an invite code +} + +export interface ContentScriptMessage { + type: ContentScriptMessageType + value: any +} + +export interface PopupMessage { + type: PopupMessageType + value: any +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/@types/payload.ts b/browser/hybrid/components/cloud_tabs_extension/src/@types/payload.ts new file mode 100644 index 00000000000..75cc4f80402 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/@types/payload.ts @@ -0,0 +1,37 @@ +export interface AuthInfo { + userEmail?: string + accessToken?: string + refreshToken?: string + error?: { + message: string + data: { + status: number + json: { + id_token?: string + access_token?: string + refresh_token?: string + } + } + } + isFirstAuth: boolean +} + +export interface MandelboxInfo { + mandelboxIP: string + mandelboxID: string +} + +export interface HostInfo { + mandelboxSecret: string + mandelboxPorts: { + port_32261: number + port_32262: number + port_32263: number + port_32273: number + } +} + +export interface ConfigTokenInfo { + token?: string + isNew: boolean +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/constants/app.ts b/browser/hybrid/components/cloud_tabs_extension/src/constants/app.ts new file mode 100644 index 00000000000..c0642a58c9d --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/constants/app.ts @@ -0,0 +1,5 @@ +import _config from "@app/generated_config.json" + +export const config = JSON.parse(JSON.stringify(_config)) +export const sessionID = Date.now() +export const inviteCode = "94478" diff --git a/browser/hybrid/components/cloud_tabs_extension/src/constants/errors.ts b/browser/hybrid/components/cloud_tabs_extension/src/constants/errors.ts new file mode 100644 index 00000000000..1463554f791 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/constants/errors.ts @@ -0,0 +1,51 @@ +export enum PopupError { + IS_INVALID_URL = "Whoops! Due to an unexpected error, we were unable to enable this cloud tab. Opening this URL in a different tab may fix this issue.", + IS_INVALID_SCHEME = "For performance and privacy reasons, cloud tabs are only enabled for sites with http: or https: URLs.", + IS_VIDEO = "Since videos are already streamed, we don't recommend turning this site into a cloud tab; doing so may lead to worse video quality.", + IS_UNSUPPORTED_URL = "Whoops! Cloud tabs are disabled for this site because we've detected that it's not compatible with cloud streaming.", + IS_LOCALHOST = "It looks like you're running localhost! Localhost should be kept local, so we've disabled cloud tabs on this site.", + IS_VIDEO_CHAT = "Whoops! It looks like this site has video/audio conferencing. To ensure the best quality, we've disabled cloud tabs on this site.", + IS_WHIST_URL = "Whoops! It looks like you're on a Whist internal page, which cannot be streamed.", + IS_INCOGNITO = "It looks like you're incognito. For added privacy, cloud tabs have been disabled for all incognito windows.", + MULTIWINDOW_NOT_SUPPORTED = "Sorry! Whist currently only supports cloud tabs within a single window, and you have a cloud tab running in another window.", +} + +export enum CloudTabError { + UPDATE_NEEDED = "UPDATE_NEEDED", + NO_INSTANCE_ERROR = "NO_INSTANCE_ERROR", + HOST_ERROR = "HOST_ERROR", + NETWORK_ERROR = "NETWORK_ERROR", + AUTH_ERROR = "AUTH_ERROR", +} + +export const errorMessage: { + [key: string]: { + text: string + duration: number + type?: string + } +} = { + [CloudTabError.UPDATE_NEEDED]: { + text: `🎉   An update is available! Click here to download the update and access cloud tabs.`, + duration: 10000, + }, + [CloudTabError.NO_INSTANCE_ERROR]: { + text: "Cloud tabs are unavailable because Whist servers are full. Please try again in a few minutes!", + duration: 7500, + type: "warning", + }, + [CloudTabError.HOST_ERROR]: { + text: "Sorry! Cloud tabs are unavailable due to an unexpected bug. Our developers have been notified and we're working on a fix.", + duration: 7500, + type: "warning", + }, + [CloudTabError.NETWORK_ERROR]: { + text: "Cloud tabs are having trouble with your network. Please check your Internet connection and try again.", + duration: 7500, + type: "warning", + }, + [CloudTabError.AUTH_ERROR]: { + text: `We're having trouble authenticating you. Please click here to sign in!`, + duration: 10000, + }, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/constants/host.ts b/browser/hybrid/components/cloud_tabs_extension/src/constants/host.ts new file mode 100644 index 00000000000..0b82a1b1d69 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/constants/host.ts @@ -0,0 +1 @@ +export const hostServicePort = 4678 diff --git a/browser/hybrid/components/cloud_tabs_extension/src/constants/location.ts b/browser/hybrid/components/cloud_tabs_extension/src/constants/location.ts new file mode 100644 index 00000000000..bbad315062b --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/constants/location.ts @@ -0,0 +1,2766 @@ +enum AWSRegion { + US_EAST_1 = "us-east-1", + US_EAST_2 = "us-east-2", + US_WEST_1 = "us-west-1", + US_WEST_2 = "us-west-2", + CA_CENTRAL_1 = "ca-central-1", + AF_SOUTH_1 = "af-south-1", + AP_EAST_1 = "ap-east-1", + AP_SOUTHEAST_3 = "ap-southeast-3", + AP_SOUTH_1 = "ap-south-1", + AP_NORTHEAST_3 = "ap-northeast-3", + AP_NORTHEAST_2 = "ap-northeast-2", + AP_SOUTHEAST_1 = "ap-southeast-1", + AP_SOUTHEAST_2 = "ap-southeast-2", + AP_NORTHEAST_1 = "ap-northeast-1", + EU_CENTRAL_1 = "eu-central-1", + EU_WEST_1 = "eu-west-1", + EU_WEST_2 = "eu-west-2", + EU_SOUTH_1 = "eu-south-1", + EU_WEST_3 = "eu-west-3", + EU_NORTH_1 = "eu-north-1", + ME_SOUTH_1 = "me-south-1", + SA_EAST_1 = "sa-east-1", +} + +const regions = [ + { + name: AWSRegion.US_EAST_1, + enabled: true, + country: "US", + location: "Arlington, VA", + }, + { + name: AWSRegion.US_EAST_2, + enabled: true, + country: "US", + location: "Columbus, OH", + }, + { + name: AWSRegion.US_WEST_1, + enabled: true, + country: "US", + location: "San Francisco, CA", + }, + { + name: AWSRegion.US_WEST_2, + enabled: true, + country: "US", + location: "Portland, OR", + }, + { + name: AWSRegion.CA_CENTRAL_1, + enabled: true, + country: "CA", + location: "Montréal, QC", + }, + { + name: AWSRegion.AF_SOUTH_1, + enabled: true, + country: "ZA", + location: "Cape Town", + }, + { + name: AWSRegion.AP_EAST_1, + enabled: true, + country: "HK", + location: "Hong Kong", + }, + { + name: AWSRegion.AP_SOUTHEAST_3, + enabled: true, + country: "ID", + location: "Jakarta", + }, + { + name: AWSRegion.AP_SOUTH_1, + enabled: true, + country: "In", + location: "Mumbai", + }, + { + name: AWSRegion.AP_NORTHEAST_3, + enabled: true, + country: "JP", + location: "Osaka", + }, + { + name: AWSRegion.AP_NORTHEAST_2, + enabled: true, + country: "KR", + location: "Seoul", + }, + { + name: AWSRegion.AP_SOUTHEAST_1, + enabled: true, + country: "SG", + location: "Singapore", + }, + { + name: AWSRegion.AP_SOUTHEAST_2, + enabled: true, + country: "AU", + location: "Sydney", + }, + { + name: AWSRegion.AP_NORTHEAST_1, + enabled: true, + country: "JP", + location: "Tokyo", + }, + { + name: AWSRegion.EU_CENTRAL_1, + enabled: true, + country: "DE", + location: "Frankfurt", + }, + { + name: AWSRegion.EU_WEST_1, + enabled: true, + country: "IE", + location: "Dublin", + }, + { + name: AWSRegion.EU_WEST_2, + enabled: true, + country: "GB", + location: "London", + }, + { + name: AWSRegion.EU_SOUTH_1, + enabled: true, + country: "IT", + location: "Milan", + }, + { + name: AWSRegion.EU_WEST_3, + enabled: true, + country: "FR", + location: "Paris", + }, + { + name: AWSRegion.EU_NORTH_1, + enabled: true, + country: "SE", + location: "Stockholm", + }, + { + name: AWSRegion.ME_SOUTH_1, + enabled: true, + country: "BH", + location: "Manama", + }, + { + name: AWSRegion.SA_EAST_1, + enabled: true, + country: "BR", + location: "São Paulo", + }, +] + +const timezones = { + "Africa/Abidjan": { + u: 0, + c: ["CI", "BF", "GH", "GM", "GN", "ML", "MR", "SH", "SL", "SN", "TG"], + }, + "Africa/Accra": { + a: "Africa/Abidjan", + c: ["GH"], + r: 1, + }, + "Africa/Addis_Ababa": { + a: "Africa/Nairobi", + c: ["ET"], + r: 1, + }, + "Africa/Algiers": { + u: 60, + c: ["DZ"], + }, + "Africa/Asmara": { + a: "Africa/Nairobi", + c: ["ER"], + r: 1, + }, + "Africa/Asmera": { + a: "Africa/Nairobi", + c: ["ER"], + r: 1, + }, + "Africa/Bamako": { + a: "Africa/Abidjan", + c: ["ML"], + r: 1, + }, + "Africa/Bangui": { + a: "Africa/Lagos", + c: ["CF"], + r: 1, + }, + "Africa/Banjul": { + a: "Africa/Abidjan", + c: ["GM"], + r: 1, + }, + "Africa/Bissau": { + u: 0, + c: ["GW"], + }, + "Africa/Blantyre": { + a: "Africa/Maputo", + c: ["MW"], + r: 1, + }, + "Africa/Brazzaville": { + a: "Africa/Lagos", + c: ["CG"], + r: 1, + }, + "Africa/Bujumbura": { + a: "Africa/Maputo", + c: ["BI"], + r: 1, + }, + "Africa/Cairo": { + u: 120, + c: ["EG"], + }, + "Africa/Casablanca": { + u: 60, + d: 0, + c: ["MA"], + }, + "Africa/Ceuta": { + u: 60, + d: 120, + c: ["ES"], + }, + "Africa/Conakry": { + a: "Africa/Abidjan", + c: ["GN"], + r: 1, + }, + "Africa/Dakar": { + a: "Africa/Abidjan", + c: ["SN"], + r: 1, + }, + "Africa/Dar_es_Salaam": { + a: "Africa/Nairobi", + c: ["TZ"], + r: 1, + }, + "Africa/Djibouti": { + a: "Africa/Nairobi", + c: ["DJ"], + r: 1, + }, + "Africa/Douala": { + a: "Africa/Lagos", + c: ["CM"], + r: 1, + }, + "Africa/El_Aaiun": { + u: 60, + d: 0, + c: ["EH"], + }, + "Africa/Freetown": { + a: "Africa/Abidjan", + c: ["SL"], + r: 1, + }, + "Africa/Gaborone": { + a: "Africa/Maputo", + c: ["BW"], + r: 1, + }, + "Africa/Harare": { + a: "Africa/Maputo", + c: ["ZW"], + r: 1, + }, + "Africa/Johannesburg": { + u: 120, + c: ["ZA", "LS", "SZ"], + }, + "Africa/Juba": { + u: 120, + c: ["SS"], + }, + "Africa/Kampala": { + a: "Africa/Nairobi", + c: ["UG"], + r: 1, + }, + "Africa/Khartoum": { + u: 120, + c: ["SD"], + }, + "Africa/Kigali": { + a: "Africa/Maputo", + c: ["RW"], + r: 1, + }, + "Africa/Kinshasa": { + a: "Africa/Lagos", + c: ["CD"], + r: 1, + }, + "Africa/Lagos": { + u: 60, + c: ["NG", "AO", "BJ", "CD", "CF", "CG", "CM", "GA", "GQ", "NE"], + }, + "Africa/Libreville": { + a: "Africa/Lagos", + c: ["GA"], + r: 1, + }, + "Africa/Lome": { + a: "Africa/Abidjan", + c: ["TG"], + r: 1, + }, + "Africa/Luanda": { + a: "Africa/Lagos", + c: ["AO"], + r: 1, + }, + "Africa/Lubumbashi": { + a: "Africa/Maputo", + c: ["CD"], + r: 1, + }, + "Africa/Lusaka": { + a: "Africa/Maputo", + c: ["ZM"], + r: 1, + }, + "Africa/Malabo": { + a: "Africa/Lagos", + c: ["GQ"], + r: 1, + }, + "Africa/Maputo": { + u: 120, + c: ["MZ", "BI", "BW", "CD", "MW", "RW", "ZM", "ZW"], + }, + "Africa/Maseru": { + a: "Africa/Johannesburg", + c: ["LS"], + r: 1, + }, + "Africa/Mbabane": { + a: "Africa/Johannesburg", + c: ["SZ"], + r: 1, + }, + "Africa/Mogadishu": { + a: "Africa/Nairobi", + c: ["SO"], + r: 1, + }, + "Africa/Monrovia": { + u: 0, + c: ["LR"], + }, + "Africa/Nairobi": { + u: 180, + c: ["KE", "DJ", "ER", "ET", "KM", "MG", "SO", "TZ", "UG", "YT"], + }, + "Africa/Ndjamena": { + u: 60, + c: ["TD"], + }, + "Africa/Niamey": { + a: "Africa/Lagos", + c: ["NE"], + r: 1, + }, + "Africa/Nouakchott": { + a: "Africa/Abidjan", + c: ["MR"], + r: 1, + }, + "Africa/Ouagadougou": { + a: "Africa/Abidjan", + c: ["BF"], + r: 1, + }, + "Africa/Porto-Novo": { + a: "Africa/Lagos", + c: ["BJ"], + r: 1, + }, + "Africa/Sao_Tome": { + u: 0, + c: ["ST"], + }, + "Africa/Timbuktu": { + a: "Africa/Abidjan", + c: ["ML"], + r: 1, + }, + "Africa/Tripoli": { + u: 120, + c: ["LY"], + }, + "Africa/Tunis": { + u: 60, + c: ["TN"], + }, + "Africa/Windhoek": { + u: 120, + c: ["NA"], + }, + "America/Adak": { + u: -600, + d: -540, + c: ["US"], + }, + "America/Anchorage": { + u: -540, + d: -480, + c: ["US"], + }, + "America/Anguilla": { + a: "America/Puerto_Rico", + c: ["AI"], + r: 1, + }, + "America/Antigua": { + a: "America/Puerto_Rico", + c: ["AG"], + r: 1, + }, + "America/Araguaina": { + u: -180, + c: ["BR"], + }, + "America/Argentina/Buenos_Aires": { + u: -180, + c: ["AR"], + }, + "America/Argentina/Catamarca": { + u: -180, + c: ["AR"], + }, + "America/Argentina/ComodRivadavia": { + a: "America/Argentina/Catamarca", + r: 1, + }, + "America/Argentina/Cordoba": { + u: -180, + c: ["AR"], + }, + "America/Argentina/Jujuy": { + u: -180, + c: ["AR"], + }, + "America/Argentina/La_Rioja": { + u: -180, + c: ["AR"], + }, + "America/Argentina/Mendoza": { + u: -180, + c: ["AR"], + }, + "America/Argentina/Rio_Gallegos": { + u: -180, + c: ["AR"], + }, + "America/Argentina/Salta": { + u: -180, + c: ["AR"], + }, + "America/Argentina/San_Juan": { + u: -180, + c: ["AR"], + }, + "America/Argentina/San_Luis": { + u: -180, + c: ["AR"], + }, + "America/Argentina/Tucuman": { + u: -180, + c: ["AR"], + }, + "America/Argentina/Ushuaia": { + u: -180, + c: ["AR"], + }, + "America/Aruba": { + a: "America/Puerto_Rico", + c: ["AW"], + r: 1, + }, + "America/Asuncion": { + u: -240, + d: -180, + c: ["PY"], + }, + "America/Atikokan": { + a: "America/Panama", + c: ["CA"], + r: 1, + }, + "America/Atka": { + a: "America/Adak", + r: 1, + }, + "America/Bahia": { + u: -180, + c: ["BR"], + }, + "America/Bahia_Banderas": { + u: -360, + d: -300, + c: ["MX"], + }, + "America/Barbados": { + u: -240, + c: ["BB"], + }, + "America/Belem": { + u: -180, + c: ["BR"], + }, + "America/Belize": { + u: -360, + c: ["BZ"], + }, + "America/Blanc-Sablon": { + a: "America/Puerto_Rico", + c: ["CA"], + r: 1, + }, + "America/Boa_Vista": { + u: -240, + c: ["BR"], + }, + "America/Bogota": { + u: -300, + c: ["CO"], + }, + "America/Boise": { + u: -420, + d: -360, + c: ["US"], + }, + "America/Buenos_Aires": { + a: "America/Argentina/Buenos_Aires", + r: 1, + }, + "America/Cambridge_Bay": { + u: -420, + d: -360, + c: ["CA"], + }, + "America/Campo_Grande": { + u: -240, + c: ["BR"], + }, + "America/Cancun": { + u: -300, + c: ["MX"], + }, + "America/Caracas": { + u: -240, + c: ["VE"], + }, + "America/Catamarca": { + a: "America/Argentina/Catamarca", + r: 1, + }, + "America/Cayenne": { + u: -180, + c: ["GF"], + }, + "America/Cayman": { + a: "America/Panama", + c: ["KY"], + r: 1, + }, + "America/Chicago": { + u: -360, + d: -300, + c: ["US"], + }, + "America/Chihuahua": { + u: -420, + d: -360, + c: ["MX"], + }, + "America/Coral_Harbour": { + a: "America/Panama", + c: ["CA"], + r: 1, + }, + "America/Cordoba": { + a: "America/Argentina/Cordoba", + r: 1, + }, + "America/Costa_Rica": { + u: -360, + c: ["CR"], + }, + "America/Creston": { + a: "America/Phoenix", + c: ["CA"], + r: 1, + }, + "America/Cuiaba": { + u: -240, + c: ["BR"], + }, + "America/Curacao": { + a: "America/Puerto_Rico", + c: ["CW"], + r: 1, + }, + "America/Danmarkshavn": { + u: 0, + c: ["GL"], + }, + "America/Dawson": { + u: -420, + c: ["CA"], + }, + "America/Dawson_Creek": { + u: -420, + c: ["CA"], + }, + "America/Denver": { + u: -420, + d: -360, + c: ["US"], + }, + "America/Detroit": { + u: -300, + d: -240, + c: ["US"], + }, + "America/Dominica": { + a: "America/Puerto_Rico", + c: ["DM"], + r: 1, + }, + "America/Edmonton": { + u: -420, + d: -360, + c: ["CA"], + }, + "America/Eirunepe": { + u: -300, + c: ["BR"], + }, + "America/El_Salvador": { + u: -360, + c: ["SV"], + }, + "America/Ensenada": { + a: "America/Tijuana", + r: 1, + }, + "America/Fort_Nelson": { + u: -420, + c: ["CA"], + }, + "America/Fort_Wayne": { + a: "America/Indiana/Indianapolis", + r: 1, + }, + "America/Fortaleza": { + u: -180, + c: ["BR"], + }, + "America/Glace_Bay": { + u: -240, + d: -180, + c: ["CA"], + }, + "America/Godthab": { + a: "America/Nuuk", + r: 1, + }, + "America/Goose_Bay": { + u: -240, + d: -180, + c: ["CA"], + }, + "America/Grand_Turk": { + u: -300, + d: -240, + c: ["TC"], + }, + "America/Grenada": { + a: "America/Puerto_Rico", + c: ["GD"], + r: 1, + }, + "America/Guadeloupe": { + a: "America/Puerto_Rico", + c: ["GP"], + r: 1, + }, + "America/Guatemala": { + u: -360, + c: ["GT"], + }, + "America/Guayaquil": { + u: -300, + c: ["EC"], + }, + "America/Guyana": { + u: -240, + c: ["GY"], + }, + "America/Halifax": { + u: -240, + d: -180, + c: ["CA"], + }, + "America/Havana": { + u: -300, + d: -240, + c: ["CU"], + }, + "America/Hermosillo": { + u: -420, + c: ["MX"], + }, + "America/Indiana/Indianapolis": { + u: -300, + d: -240, + c: ["US"], + }, + "America/Indiana/Knox": { + u: -360, + d: -300, + c: ["US"], + }, + "America/Indiana/Marengo": { + u: -300, + d: -240, + c: ["US"], + }, + "America/Indiana/Petersburg": { + u: -300, + d: -240, + c: ["US"], + }, + "America/Indiana/Tell_City": { + u: -360, + d: -300, + c: ["US"], + }, + "America/Indiana/Vevay": { + u: -300, + d: -240, + c: ["US"], + }, + "America/Indiana/Vincennes": { + u: -300, + d: -240, + c: ["US"], + }, + "America/Indiana/Winamac": { + u: -300, + d: -240, + c: ["US"], + }, + "America/Indianapolis": { + a: "America/Indiana/Indianapolis", + r: 1, + }, + "America/Inuvik": { + u: -420, + d: -360, + c: ["CA"], + }, + "America/Iqaluit": { + u: -300, + d: -240, + c: ["CA"], + }, + "America/Jamaica": { + u: -300, + c: ["JM"], + }, + "America/Jujuy": { + a: "America/Argentina/Jujuy", + r: 1, + }, + "America/Juneau": { + u: -540, + d: -480, + c: ["US"], + }, + "America/Kentucky/Louisville": { + u: -300, + d: -240, + c: ["US"], + }, + "America/Kentucky/Monticello": { + u: -300, + d: -240, + c: ["US"], + }, + "America/Knox_IN": { + a: "America/Indiana/Knox", + r: 1, + }, + "America/Kralendijk": { + a: "America/Puerto_Rico", + c: ["BQ"], + r: 1, + }, + "America/La_Paz": { + u: -240, + c: ["BO"], + }, + "America/Lima": { + u: -300, + c: ["PE"], + }, + "America/Los_Angeles": { + u: -480, + d: -420, + c: ["US"], + }, + "America/Louisville": { + a: "America/Kentucky/Louisville", + r: 1, + }, + "America/Lower_Princes": { + a: "America/Puerto_Rico", + c: ["SX"], + r: 1, + }, + "America/Maceio": { + u: -180, + c: ["BR"], + }, + "America/Managua": { + u: -360, + c: ["NI"], + }, + "America/Manaus": { + u: -240, + c: ["BR"], + }, + "America/Marigot": { + a: "America/Puerto_Rico", + c: ["MF"], + r: 1, + }, + "America/Martinique": { + u: -240, + c: ["MQ"], + }, + "America/Matamoros": { + u: -360, + d: -300, + c: ["MX"], + }, + "America/Mazatlan": { + u: -420, + d: -360, + c: ["MX"], + }, + "America/Mendoza": { + a: "America/Argentina/Mendoza", + r: 1, + }, + "America/Menominee": { + u: -360, + d: -300, + c: ["US"], + }, + "America/Merida": { + u: -360, + d: -300, + c: ["MX"], + }, + "America/Metlakatla": { + u: -540, + d: -480, + c: ["US"], + }, + "America/Mexico_City": { + u: -360, + d: -300, + c: ["MX"], + }, + "America/Miquelon": { + u: -180, + d: -120, + c: ["PM"], + }, + "America/Moncton": { + u: -240, + d: -180, + c: ["CA"], + }, + "America/Monterrey": { + u: -360, + d: -300, + c: ["MX"], + }, + "America/Montevideo": { + u: -180, + c: ["UY"], + }, + "America/Montreal": { + a: "America/Toronto", + c: ["CA"], + r: 1, + }, + "America/Montserrat": { + a: "America/Puerto_Rico", + c: ["MS"], + r: 1, + }, + "America/Nassau": { + a: "America/Toronto", + c: ["BS"], + r: 1, + }, + "America/New_York": { + u: -300, + d: -240, + c: ["US"], + }, + "America/Nipigon": { + u: -300, + d: -240, + c: ["CA"], + }, + "America/Nome": { + u: -540, + d: -480, + c: ["US"], + }, + "America/Noronha": { + u: -120, + c: ["BR"], + }, + "America/North_Dakota/Beulah": { + u: -360, + d: -300, + c: ["US"], + }, + "America/North_Dakota/Center": { + u: -360, + d: -300, + c: ["US"], + }, + "America/North_Dakota/New_Salem": { + u: -360, + d: -300, + c: ["US"], + }, + "America/Nuuk": { + u: -180, + d: -120, + c: ["GL"], + }, + "America/Ojinaga": { + u: -420, + d: -360, + c: ["MX"], + }, + "America/Panama": { + u: -300, + c: ["PA", "CA", "KY"], + }, + "America/Pangnirtung": { + u: -300, + d: -240, + c: ["CA"], + }, + "America/Paramaribo": { + u: -180, + c: ["SR"], + }, + "America/Phoenix": { + u: -420, + c: ["US", "CA"], + }, + "America/Port-au-Prince": { + u: -300, + d: -240, + c: ["HT"], + }, + "America/Port_of_Spain": { + a: "America/Puerto_Rico", + c: ["TT"], + r: 1, + }, + "America/Porto_Acre": { + a: "America/Rio_Branco", + r: 1, + }, + "America/Porto_Velho": { + u: -240, + c: ["BR"], + }, + "America/Puerto_Rico": { + u: -240, + c: [ + "PR", + "AG", + "CA", + "AI", + "AW", + "BL", + "BQ", + "CW", + "DM", + "GD", + "GP", + "KN", + "LC", + "MF", + "MS", + "SX", + "TT", + "VC", + "VG", + "VI", + ], + }, + "America/Punta_Arenas": { + u: -180, + c: ["CL"], + }, + "America/Rainy_River": { + u: -360, + d: -300, + c: ["CA"], + }, + "America/Rankin_Inlet": { + u: -360, + d: -300, + c: ["CA"], + }, + "America/Recife": { + u: -180, + c: ["BR"], + }, + "America/Regina": { + u: -360, + c: ["CA"], + }, + "America/Resolute": { + u: -360, + d: -300, + c: ["CA"], + }, + "America/Rio_Branco": { + u: -300, + c: ["BR"], + }, + "America/Rosario": { + a: "America/Argentina/Cordoba", + r: 1, + }, + "America/Santa_Isabel": { + a: "America/Tijuana", + r: 1, + }, + "America/Santarem": { + u: -180, + c: ["BR"], + }, + "America/Santiago": { + u: -240, + d: -180, + c: ["CL"], + }, + "America/Santo_Domingo": { + u: -240, + c: ["DO"], + }, + "America/Sao_Paulo": { + u: -180, + c: ["BR"], + }, + "America/Scoresbysund": { + u: -60, + d: 0, + c: ["GL"], + }, + "America/Shiprock": { + a: "America/Denver", + r: 1, + }, + "America/Sitka": { + u: -540, + d: -480, + c: ["US"], + }, + "America/St_Barthelemy": { + a: "America/Puerto_Rico", + c: ["BL"], + r: 1, + }, + "America/St_Johns": { + u: -150, + d: -90, + c: ["CA"], + }, + "America/St_Kitts": { + a: "America/Puerto_Rico", + c: ["KN"], + r: 1, + }, + "America/St_Lucia": { + a: "America/Puerto_Rico", + c: ["LC"], + r: 1, + }, + "America/St_Thomas": { + a: "America/Puerto_Rico", + c: ["VI"], + r: 1, + }, + "America/St_Vincent": { + a: "America/Puerto_Rico", + c: ["VC"], + r: 1, + }, + "America/Swift_Current": { + u: -360, + c: ["CA"], + }, + "America/Tegucigalpa": { + u: -360, + c: ["HN"], + }, + "America/Thule": { + u: -240, + d: -180, + c: ["GL"], + }, + "America/Thunder_Bay": { + u: -300, + d: -240, + c: ["CA"], + }, + "America/Tijuana": { + u: -480, + d: -420, + c: ["MX"], + }, + "America/Toronto": { + u: -300, + d: -240, + c: ["CA", "BS"], + }, + "America/Tortola": { + a: "America/Puerto_Rico", + c: ["VG"], + r: 1, + }, + "America/Vancouver": { + u: -480, + d: -420, + c: ["CA"], + }, + "America/Virgin": { + a: "America/Puerto_Rico", + c: ["VI"], + r: 1, + }, + "America/Whitehorse": { + u: -420, + c: ["CA"], + }, + "America/Winnipeg": { + u: -360, + d: -300, + c: ["CA"], + }, + "America/Yakutat": { + u: -540, + d: -480, + c: ["US"], + }, + "America/Yellowknife": { + u: -420, + d: -360, + c: ["CA"], + }, + "Antarctica/Casey": { + u: 660, + c: ["AQ"], + }, + "Antarctica/Davis": { + u: 420, + c: ["AQ"], + }, + "Antarctica/DumontDUrville": { + a: "Pacific/Port_Moresby", + c: ["AQ"], + r: 1, + }, + "Antarctica/Macquarie": { + u: 600, + d: 660, + c: ["AU"], + }, + "Antarctica/Mawson": { + u: 300, + c: ["AQ"], + }, + "Antarctica/McMurdo": { + a: "Pacific/Auckland", + c: ["AQ"], + r: 1, + }, + "Antarctica/Palmer": { + u: -180, + c: ["AQ"], + }, + "Antarctica/Rothera": { + u: -180, + c: ["AQ"], + }, + "Antarctica/South_Pole": { + a: "Pacific/Auckland", + c: ["AQ"], + r: 1, + }, + "Antarctica/Syowa": { + a: "Asia/Riyadh", + c: ["AQ"], + r: 1, + }, + "Antarctica/Troll": { + u: 0, + d: 120, + c: ["AQ"], + }, + "Antarctica/Vostok": { + u: 360, + c: ["AQ"], + }, + "Arctic/Longyearbyen": { + a: "Europe/Oslo", + c: ["SJ"], + r: 1, + }, + "Asia/Aden": { + a: "Asia/Riyadh", + c: ["YE"], + r: 1, + }, + "Asia/Almaty": { + u: 360, + c: ["KZ"], + }, + "Asia/Amman": { + u: 120, + d: 180, + c: ["JO"], + }, + "Asia/Anadyr": { + u: 720, + c: ["RU"], + }, + "Asia/Aqtau": { + u: 300, + c: ["KZ"], + }, + "Asia/Aqtobe": { + u: 300, + c: ["KZ"], + }, + "Asia/Ashgabat": { + u: 300, + c: ["TM"], + }, + "Asia/Ashkhabad": { + a: "Asia/Ashgabat", + r: 1, + }, + "Asia/Atyrau": { + u: 300, + c: ["KZ"], + }, + "Asia/Baghdad": { + u: 180, + c: ["IQ"], + }, + "Asia/Bahrain": { + a: "Asia/Qatar", + c: ["BH"], + r: 1, + }, + "Asia/Baku": { + u: 240, + c: ["AZ"], + }, + "Asia/Bangkok": { + u: 420, + c: ["TH", "KH", "LA", "VN"], + }, + "Asia/Barnaul": { + u: 420, + c: ["RU"], + }, + "Asia/Beirut": { + u: 120, + d: 180, + c: ["LB"], + }, + "Asia/Bishkek": { + u: 360, + c: ["KG"], + }, + "Asia/Brunei": { + u: 480, + c: ["BN"], + }, + "Asia/Calcutta": { + a: "Asia/Kolkata", + r: 1, + }, + "Asia/Chita": { + u: 540, + c: ["RU"], + }, + "Asia/Choibalsan": { + u: 480, + c: ["MN"], + }, + "Asia/Chongqing": { + a: "Asia/Shanghai", + r: 1, + }, + "Asia/Chungking": { + a: "Asia/Shanghai", + r: 1, + }, + "Asia/Colombo": { + u: 330, + c: ["LK"], + }, + "Asia/Dacca": { + a: "Asia/Dhaka", + r: 1, + }, + "Asia/Damascus": { + u: 120, + d: 180, + c: ["SY"], + }, + "Asia/Dhaka": { + u: 360, + c: ["BD"], + }, + "Asia/Dili": { + u: 540, + c: ["TL"], + }, + "Asia/Dubai": { + u: 240, + c: ["AE", "OM"], + }, + "Asia/Dushanbe": { + u: 300, + c: ["TJ"], + }, + "Asia/Famagusta": { + u: 120, + d: 180, + c: ["CY"], + }, + "Asia/Gaza": { + u: 120, + d: 180, + c: ["PS"], + }, + "Asia/Harbin": { + a: "Asia/Shanghai", + r: 1, + }, + "Asia/Hebron": { + u: 120, + d: 180, + c: ["PS"], + }, + "Asia/Ho_Chi_Minh": { + u: 420, + c: ["VN"], + }, + "Asia/Hong_Kong": { + u: 480, + c: ["HK"], + }, + "Asia/Hovd": { + u: 420, + c: ["MN"], + }, + "Asia/Irkutsk": { + u: 480, + c: ["RU"], + }, + "Asia/Istanbul": { + a: "Europe/Istanbul", + r: 1, + }, + "Asia/Jakarta": { + u: 420, + c: ["ID"], + }, + "Asia/Jayapura": { + u: 540, + c: ["ID"], + }, + "Asia/Jerusalem": { + u: 120, + d: 180, + c: ["IL"], + }, + "Asia/Kabul": { + u: 270, + c: ["AF"], + }, + "Asia/Kamchatka": { + u: 720, + c: ["RU"], + }, + "Asia/Karachi": { + u: 300, + c: ["PK"], + }, + "Asia/Kashgar": { + a: "Asia/Urumqi", + r: 1, + }, + "Asia/Kathmandu": { + u: 345, + c: ["NP"], + }, + "Asia/Katmandu": { + a: "Asia/Kathmandu", + r: 1, + }, + "Asia/Khandyga": { + u: 540, + c: ["RU"], + }, + "Asia/Kolkata": { + u: 330, + c: ["IN"], + }, + "Asia/Krasnoyarsk": { + u: 420, + c: ["RU"], + }, + "Asia/Kuala_Lumpur": { + u: 480, + c: ["MY"], + }, + "Asia/Kuching": { + u: 480, + c: ["MY"], + }, + "Asia/Kuwait": { + a: "Asia/Riyadh", + c: ["KW"], + r: 1, + }, + "Asia/Macao": { + a: "Asia/Macau", + r: 1, + }, + "Asia/Macau": { + u: 480, + c: ["MO"], + }, + "Asia/Magadan": { + u: 660, + c: ["RU"], + }, + "Asia/Makassar": { + u: 480, + c: ["ID"], + }, + "Asia/Manila": { + u: 480, + c: ["PH"], + }, + "Asia/Muscat": { + a: "Asia/Dubai", + c: ["OM"], + r: 1, + }, + "Asia/Nicosia": { + u: 120, + d: 180, + c: ["CY"], + }, + "Asia/Novokuznetsk": { + u: 420, + c: ["RU"], + }, + "Asia/Novosibirsk": { + u: 420, + c: ["RU"], + }, + "Asia/Omsk": { + u: 360, + c: ["RU"], + }, + "Asia/Oral": { + u: 300, + c: ["KZ"], + }, + "Asia/Phnom_Penh": { + a: "Asia/Bangkok", + c: ["KH"], + r: 1, + }, + "Asia/Pontianak": { + u: 420, + c: ["ID"], + }, + "Asia/Pyongyang": { + u: 540, + c: ["KP"], + }, + "Asia/Qatar": { + u: 180, + c: ["QA", "BH"], + }, + "Asia/Qostanay": { + u: 360, + c: ["KZ"], + }, + "Asia/Qyzylorda": { + u: 300, + c: ["KZ"], + }, + "Asia/Rangoon": { + a: "Asia/Yangon", + r: 1, + }, + "Asia/Riyadh": { + u: 180, + c: ["SA", "AQ", "KW", "YE"], + }, + "Asia/Saigon": { + a: "Asia/Ho_Chi_Minh", + r: 1, + }, + "Asia/Sakhalin": { + u: 660, + c: ["RU"], + }, + "Asia/Samarkand": { + u: 300, + c: ["UZ"], + }, + "Asia/Seoul": { + u: 540, + c: ["KR"], + }, + "Asia/Shanghai": { + u: 480, + c: ["CN"], + }, + "Asia/Singapore": { + u: 480, + c: ["SG", "MY"], + }, + "Asia/Srednekolymsk": { + u: 660, + c: ["RU"], + }, + "Asia/Taipei": { + u: 480, + c: ["TW"], + }, + "Asia/Tashkent": { + u: 300, + c: ["UZ"], + }, + "Asia/Tbilisi": { + u: 240, + c: ["GE"], + }, + "Asia/Tehran": { + u: 210, + d: 270, + c: ["IR"], + }, + "Asia/Tel_Aviv": { + a: "Asia/Jerusalem", + r: 1, + }, + "Asia/Thimbu": { + a: "Asia/Thimphu", + r: 1, + }, + "Asia/Thimphu": { + u: 360, + c: ["BT"], + }, + "Asia/Tokyo": { + u: 540, + c: ["JP"], + }, + "Asia/Tomsk": { + u: 420, + c: ["RU"], + }, + "Asia/Ujung_Pandang": { + a: "Asia/Makassar", + r: 1, + }, + "Asia/Ulaanbaatar": { + u: 480, + c: ["MN"], + }, + "Asia/Ulan_Bator": { + a: "Asia/Ulaanbaatar", + r: 1, + }, + "Asia/Urumqi": { + u: 360, + c: ["CN"], + }, + "Asia/Ust-Nera": { + u: 600, + c: ["RU"], + }, + "Asia/Vientiane": { + a: "Asia/Bangkok", + c: ["LA"], + r: 1, + }, + "Asia/Vladivostok": { + u: 600, + c: ["RU"], + }, + "Asia/Yakutsk": { + u: 540, + c: ["RU"], + }, + "Asia/Yangon": { + u: 390, + c: ["MM"], + }, + "Asia/Yekaterinburg": { + u: 300, + c: ["RU"], + }, + "Asia/Yerevan": { + u: 240, + c: ["AM"], + }, + "Atlantic/Azores": { + u: -60, + d: 0, + c: ["PT"], + }, + "Atlantic/Bermuda": { + u: -240, + d: -180, + c: ["BM"], + }, + "Atlantic/Canary": { + u: 0, + d: 60, + c: ["ES"], + }, + "Atlantic/Cape_Verde": { + u: -60, + c: ["CV"], + }, + "Atlantic/Faeroe": { + a: "Atlantic/Faroe", + r: 1, + }, + "Atlantic/Faroe": { + u: 0, + d: 60, + c: ["FO"], + }, + "Atlantic/Jan_Mayen": { + a: "Europe/Oslo", + c: ["SJ"], + r: 1, + }, + "Atlantic/Madeira": { + u: 0, + d: 60, + c: ["PT"], + }, + "Atlantic/Reykjavik": { + u: 0, + c: ["IS"], + }, + "Atlantic/South_Georgia": { + u: -120, + c: ["GS"], + }, + "Atlantic/St_Helena": { + a: "Africa/Abidjan", + c: ["SH"], + r: 1, + }, + "Atlantic/Stanley": { + u: -180, + c: ["FK"], + }, + "Australia/ACT": { + a: "Australia/Sydney", + r: 1, + }, + "Australia/Adelaide": { + u: 570, + d: 630, + c: ["AU"], + }, + "Australia/Brisbane": { + u: 600, + c: ["AU"], + }, + "Australia/Broken_Hill": { + u: 570, + d: 630, + c: ["AU"], + }, + "Australia/Canberra": { + a: "Australia/Sydney", + r: 1, + }, + "Australia/Currie": { + a: "Australia/Hobart", + r: 1, + }, + "Australia/Darwin": { + u: 570, + c: ["AU"], + }, + "Australia/Eucla": { + u: 525, + c: ["AU"], + }, + "Australia/Hobart": { + u: 600, + d: 660, + c: ["AU"], + }, + "Australia/LHI": { + a: "Australia/Lord_Howe", + r: 1, + }, + "Australia/Lindeman": { + u: 600, + c: ["AU"], + }, + "Australia/Lord_Howe": { + u: 630, + d: 660, + c: ["AU"], + }, + "Australia/Melbourne": { + u: 600, + d: 660, + c: ["AU"], + }, + "Australia/NSW": { + a: "Australia/Sydney", + r: 1, + }, + "Australia/North": { + a: "Australia/Darwin", + r: 1, + }, + "Australia/Perth": { + u: 480, + c: ["AU"], + }, + "Australia/Queensland": { + a: "Australia/Brisbane", + r: 1, + }, + "Australia/South": { + a: "Australia/Adelaide", + r: 1, + }, + "Australia/Sydney": { + u: 600, + d: 660, + c: ["AU"], + }, + "Australia/Tasmania": { + a: "Australia/Hobart", + r: 1, + }, + "Australia/Victoria": { + a: "Australia/Melbourne", + r: 1, + }, + "Australia/West": { + a: "Australia/Perth", + r: 1, + }, + "Australia/Yancowinna": { + a: "Australia/Broken_Hill", + r: 1, + }, + "Brazil/Acre": { + a: "America/Rio_Branco", + r: 1, + }, + "Brazil/DeNoronha": { + a: "America/Noronha", + r: 1, + }, + "Brazil/East": { + a: "America/Sao_Paulo", + r: 1, + }, + "Brazil/West": { + a: "America/Manaus", + r: 1, + }, + CET: { + u: 60, + d: 120, + }, + CST6CDT: { + u: -360, + d: -300, + }, + "Canada/Atlantic": { + a: "America/Halifax", + r: 1, + }, + "Canada/Central": { + a: "America/Winnipeg", + r: 1, + }, + "Canada/Eastern": { + a: "America/Toronto", + c: ["CA"], + r: 1, + }, + "Canada/Mountain": { + a: "America/Edmonton", + r: 1, + }, + "Canada/Newfoundland": { + a: "America/St_Johns", + r: 1, + }, + "Canada/Pacific": { + a: "America/Vancouver", + r: 1, + }, + "Canada/Saskatchewan": { + a: "America/Regina", + r: 1, + }, + "Canada/Yukon": { + a: "America/Whitehorse", + r: 1, + }, + "Chile/Continental": { + a: "America/Santiago", + r: 1, + }, + "Chile/EasterIsland": { + a: "Pacific/Easter", + r: 1, + }, + Cuba: { + a: "America/Havana", + r: 1, + }, + EET: { + u: 120, + d: 180, + }, + EST: { + u: -300, + }, + EST5EDT: { + u: -300, + d: -240, + }, + Egypt: { + a: "Africa/Cairo", + r: 1, + }, + Eire: { + a: "Europe/Dublin", + r: 1, + }, + "Etc/GMT": { + u: 0, + }, + "Etc/GMT+0": { + a: "Etc/GMT", + r: 1, + }, + "Etc/GMT+1": { + u: -60, + }, + "Etc/GMT+10": { + u: -600, + }, + "Etc/GMT+11": { + u: -660, + }, + "Etc/GMT+12": { + u: -720, + }, + "Etc/GMT+2": { + u: -120, + }, + "Etc/GMT+3": { + u: -180, + }, + "Etc/GMT+4": { + u: -240, + }, + "Etc/GMT+5": { + u: -300, + }, + "Etc/GMT+6": { + u: -360, + }, + "Etc/GMT+7": { + u: -420, + }, + "Etc/GMT+8": { + u: -480, + }, + "Etc/GMT+9": { + u: -540, + }, + "Etc/GMT-0": { + a: "Etc/GMT", + r: 1, + }, + "Etc/GMT-1": { + u: 60, + }, + "Etc/GMT-10": { + u: 600, + }, + "Etc/GMT-11": { + u: 660, + }, + "Etc/GMT-12": { + u: 720, + }, + "Etc/GMT-13": { + u: 780, + }, + "Etc/GMT-14": { + u: 840, + }, + "Etc/GMT-2": { + u: 120, + }, + "Etc/GMT-3": { + u: 180, + }, + "Etc/GMT-4": { + u: 240, + }, + "Etc/GMT-5": { + u: 300, + }, + "Etc/GMT-6": { + u: 360, + }, + "Etc/GMT-7": { + u: 420, + }, + "Etc/GMT-8": { + u: 480, + }, + "Etc/GMT-9": { + u: 540, + }, + "Etc/GMT0": { + a: "Etc/GMT", + r: 1, + }, + "Etc/Greenwich": { + a: "Etc/GMT", + r: 1, + }, + "Etc/UCT": { + a: "Etc/UTC", + r: 1, + }, + "Etc/UTC": { + u: 0, + }, + "Etc/Universal": { + a: "Etc/UTC", + r: 1, + }, + "Etc/Zulu": { + a: "Etc/UTC", + r: 1, + }, + "Europe/Amsterdam": { + u: 60, + d: 120, + c: ["NL"], + }, + "Europe/Andorra": { + u: 60, + d: 120, + c: ["AD"], + }, + "Europe/Astrakhan": { + u: 240, + c: ["RU"], + }, + "Europe/Athens": { + u: 120, + d: 180, + c: ["GR"], + }, + "Europe/Belfast": { + a: "Europe/London", + c: ["GB"], + r: 1, + }, + "Europe/Belgrade": { + u: 60, + d: 120, + c: ["RS", "BA", "HR", "ME", "MK", "SI"], + }, + "Europe/Berlin": { + u: 60, + d: 120, + c: ["DE"], + }, + "Europe/Bratislava": { + a: "Europe/Prague", + c: ["SK"], + r: 1, + }, + "Europe/Brussels": { + u: 60, + d: 120, + c: ["BE"], + }, + "Europe/Bucharest": { + u: 120, + d: 180, + c: ["RO"], + }, + "Europe/Budapest": { + u: 60, + d: 120, + c: ["HU"], + }, + "Europe/Busingen": { + a: "Europe/Zurich", + c: ["DE"], + r: 1, + }, + "Europe/Chisinau": { + u: 120, + d: 180, + c: ["MD"], + }, + "Europe/Copenhagen": { + u: 60, + d: 120, + c: ["DK"], + }, + "Europe/Dublin": { + u: 60, + d: 0, + c: ["IE"], + }, + "Europe/Gibraltar": { + u: 60, + d: 120, + c: ["GI"], + }, + "Europe/Guernsey": { + a: "Europe/London", + c: ["GG"], + r: 1, + }, + "Europe/Helsinki": { + u: 120, + d: 180, + c: ["FI", "AX"], + }, + "Europe/Isle_of_Man": { + a: "Europe/London", + c: ["IM"], + r: 1, + }, + "Europe/Istanbul": { + u: 180, + c: ["TR"], + }, + "Europe/Jersey": { + a: "Europe/London", + c: ["JE"], + r: 1, + }, + "Europe/Kaliningrad": { + u: 120, + c: ["RU"], + }, + "Europe/Kiev": { + u: 120, + d: 180, + c: ["UA"], + }, + "Europe/Kirov": { + u: 180, + c: ["RU"], + }, + "Europe/Lisbon": { + u: 0, + d: 60, + c: ["PT"], + }, + "Europe/Ljubljana": { + a: "Europe/Belgrade", + c: ["SI"], + r: 1, + }, + "Europe/London": { + u: 0, + d: 60, + c: ["GB", "GG", "IM", "JE"], + }, + "Europe/Luxembourg": { + u: 60, + d: 120, + c: ["LU"], + }, + "Europe/Madrid": { + u: 60, + d: 120, + c: ["ES"], + }, + "Europe/Malta": { + u: 60, + d: 120, + c: ["MT"], + }, + "Europe/Mariehamn": { + a: "Europe/Helsinki", + c: ["AX"], + r: 1, + }, + "Europe/Minsk": { + u: 180, + c: ["BY"], + }, + "Europe/Monaco": { + u: 60, + d: 120, + c: ["MC"], + }, + "Europe/Moscow": { + u: 180, + c: ["RU"], + }, + "Europe/Nicosia": { + a: "Asia/Nicosia", + r: 1, + }, + "Europe/Oslo": { + u: 60, + d: 120, + c: ["NO", "SJ", "BV"], + }, + "Europe/Paris": { + u: 60, + d: 120, + c: ["FR"], + }, + "Europe/Podgorica": { + a: "Europe/Belgrade", + c: ["ME"], + r: 1, + }, + "Europe/Prague": { + u: 60, + d: 120, + c: ["CZ", "SK"], + }, + "Europe/Riga": { + u: 120, + d: 180, + c: ["LV"], + }, + "Europe/Rome": { + u: 60, + d: 120, + c: ["IT", "SM", "VA"], + }, + "Europe/Samara": { + u: 240, + c: ["RU"], + }, + "Europe/San_Marino": { + a: "Europe/Rome", + c: ["SM"], + r: 1, + }, + "Europe/Sarajevo": { + a: "Europe/Belgrade", + c: ["BA"], + r: 1, + }, + "Europe/Saratov": { + u: 240, + c: ["RU"], + }, + "Europe/Simferopol": { + u: 180, + c: ["RU", "UA"], + }, + "Europe/Skopje": { + a: "Europe/Belgrade", + c: ["MK"], + r: 1, + }, + "Europe/Sofia": { + u: 120, + d: 180, + c: ["BG"], + }, + "Europe/Stockholm": { + u: 60, + d: 120, + c: ["SE"], + }, + "Europe/Tallinn": { + u: 120, + d: 180, + c: ["EE"], + }, + "Europe/Tirane": { + u: 60, + d: 120, + c: ["AL"], + }, + "Europe/Tiraspol": { + a: "Europe/Chisinau", + r: 1, + }, + "Europe/Ulyanovsk": { + u: 240, + c: ["RU"], + }, + "Europe/Uzhgorod": { + u: 120, + d: 180, + c: ["UA"], + }, + "Europe/Vaduz": { + a: "Europe/Zurich", + c: ["LI"], + r: 1, + }, + "Europe/Vatican": { + a: "Europe/Rome", + c: ["VA"], + r: 1, + }, + "Europe/Vienna": { + u: 60, + d: 120, + c: ["AT"], + }, + "Europe/Vilnius": { + u: 120, + d: 180, + c: ["LT"], + }, + "Europe/Volgograd": { + u: 180, + c: ["RU"], + }, + "Europe/Warsaw": { + u: 60, + d: 120, + c: ["PL"], + }, + "Europe/Zagreb": { + a: "Europe/Belgrade", + c: ["HR"], + r: 1, + }, + "Europe/Zaporozhye": { + u: 120, + d: 180, + c: ["UA"], + }, + "Europe/Zurich": { + u: 60, + d: 120, + c: ["CH", "DE", "LI"], + }, + Factory: { + u: 0, + }, + GB: { + a: "Europe/London", + c: ["GB"], + r: 1, + }, + "GB-Eire": { + a: "Europe/London", + c: ["GB"], + r: 1, + }, + GMT: { + a: "Etc/GMT", + r: 1, + }, + "GMT+0": { + a: "Etc/GMT", + r: 1, + }, + "GMT-0": { + a: "Etc/GMT", + r: 1, + }, + GMT0: { + a: "Etc/GMT", + r: 1, + }, + Greenwich: { + a: "Etc/GMT", + r: 1, + }, + HST: { + u: -600, + }, + Hongkong: { + a: "Asia/Hong_Kong", + r: 1, + }, + Iceland: { + a: "Atlantic/Reykjavik", + r: 1, + }, + "Indian/Antananarivo": { + a: "Africa/Nairobi", + c: ["MG"], + r: 1, + }, + "Indian/Chagos": { + u: 360, + c: ["IO"], + }, + "Indian/Christmas": { + u: 420, + c: ["CX"], + }, + "Indian/Cocos": { + u: 390, + c: ["CC"], + }, + "Indian/Comoro": { + a: "Africa/Nairobi", + c: ["KM"], + r: 1, + }, + "Indian/Kerguelen": { + u: 300, + c: ["TF", "HM"], + }, + "Indian/Mahe": { + u: 240, + c: ["SC"], + }, + "Indian/Maldives": { + u: 300, + c: ["MV"], + }, + "Indian/Mauritius": { + u: 240, + c: ["MU"], + }, + "Indian/Mayotte": { + a: "Africa/Nairobi", + c: ["YT"], + r: 1, + }, + "Indian/Reunion": { + u: 240, + c: ["RE", "TF"], + }, + Iran: { + a: "Asia/Tehran", + r: 1, + }, + Israel: { + a: "Asia/Jerusalem", + r: 1, + }, + Jamaica: { + a: "America/Jamaica", + r: 1, + }, + Japan: { + a: "Asia/Tokyo", + r: 1, + }, + Kwajalein: { + a: "Pacific/Kwajalein", + r: 1, + }, + Libya: { + a: "Africa/Tripoli", + r: 1, + }, + MET: { + u: 60, + d: 120, + }, + MST: { + u: -420, + }, + MST7MDT: { + u: -420, + d: -360, + }, + "Mexico/BajaNorte": { + a: "America/Tijuana", + r: 1, + }, + "Mexico/BajaSur": { + a: "America/Mazatlan", + r: 1, + }, + "Mexico/General": { + a: "America/Mexico_City", + r: 1, + }, + NZ: { + a: "Pacific/Auckland", + c: ["NZ"], + r: 1, + }, + "NZ-CHAT": { + a: "Pacific/Chatham", + r: 1, + }, + Navajo: { + a: "America/Denver", + r: 1, + }, + PRC: { + a: "Asia/Shanghai", + r: 1, + }, + PST8PDT: { + u: -480, + d: -420, + }, + "Pacific/Apia": { + u: 780, + c: ["WS"], + }, + "Pacific/Auckland": { + u: 720, + d: 780, + c: ["NZ", "AQ"], + }, + "Pacific/Bougainville": { + u: 660, + c: ["PG"], + }, + "Pacific/Chatham": { + u: 765, + d: 825, + c: ["NZ"], + }, + "Pacific/Chuuk": { + u: 600, + c: ["FM"], + }, + "Pacific/Easter": { + u: -360, + d: -300, + c: ["CL"], + }, + "Pacific/Efate": { + u: 660, + c: ["VU"], + }, + "Pacific/Enderbury": { + a: "Pacific/Kanton", + r: 1, + }, + "Pacific/Fakaofo": { + u: 780, + c: ["TK"], + }, + "Pacific/Fiji": { + u: 720, + d: 780, + c: ["FJ"], + }, + "Pacific/Funafuti": { + u: 720, + c: ["TV"], + }, + "Pacific/Galapagos": { + u: -360, + c: ["EC"], + }, + "Pacific/Gambier": { + u: -540, + c: ["PF"], + }, + "Pacific/Guadalcanal": { + u: 660, + c: ["SB"], + }, + "Pacific/Guam": { + u: 600, + c: ["GU", "MP"], + }, + "Pacific/Honolulu": { + u: -600, + c: ["US", "UM"], + }, + "Pacific/Johnston": { + a: "Pacific/Honolulu", + c: ["UM"], + r: 1, + }, + "Pacific/Kanton": { + u: 780, + c: ["KI"], + }, + "Pacific/Kiritimati": { + u: 840, + c: ["KI"], + }, + "Pacific/Kosrae": { + u: 660, + c: ["FM"], + }, + "Pacific/Kwajalein": { + u: 720, + c: ["MH"], + }, + "Pacific/Majuro": { + u: 720, + c: ["MH"], + }, + "Pacific/Marquesas": { + u: -510, + c: ["PF"], + }, + "Pacific/Midway": { + a: "Pacific/Pago_Pago", + c: ["UM"], + r: 1, + }, + "Pacific/Nauru": { + u: 720, + c: ["NR"], + }, + "Pacific/Niue": { + u: -660, + c: ["NU"], + }, + "Pacific/Norfolk": { + u: 660, + d: 720, + c: ["NF"], + }, + "Pacific/Noumea": { + u: 660, + c: ["NC"], + }, + "Pacific/Pago_Pago": { + u: -660, + c: ["AS", "UM"], + }, + "Pacific/Palau": { + u: 540, + c: ["PW"], + }, + "Pacific/Pitcairn": { + u: -480, + c: ["PN"], + }, + "Pacific/Pohnpei": { + u: 660, + c: ["FM"], + }, + "Pacific/Ponape": { + a: "Pacific/Pohnpei", + r: 1, + }, + "Pacific/Port_Moresby": { + u: 600, + c: ["PG", "AQ"], + }, + "Pacific/Rarotonga": { + u: -600, + c: ["CK"], + }, + "Pacific/Saipan": { + a: "Pacific/Guam", + c: ["MP"], + r: 1, + }, + "Pacific/Samoa": { + a: "Pacific/Pago_Pago", + c: ["WS"], + r: 1, + }, + "Pacific/Tahiti": { + u: -600, + c: ["PF"], + }, + "Pacific/Tarawa": { + u: 720, + c: ["KI"], + }, + "Pacific/Tongatapu": { + u: 780, + c: ["TO"], + }, + "Pacific/Truk": { + a: "Pacific/Chuuk", + r: 1, + }, + "Pacific/Wake": { + u: 720, + c: ["UM"], + }, + "Pacific/Wallis": { + u: 720, + c: ["WF"], + }, + "Pacific/Yap": { + a: "Pacific/Chuuk", + r: 1, + }, + Poland: { + a: "Europe/Warsaw", + r: 1, + }, + Portugal: { + a: "Europe/Lisbon", + r: 1, + }, + ROC: { + a: "Asia/Taipei", + r: 1, + }, + ROK: { + a: "Asia/Seoul", + r: 1, + }, + Singapore: { + a: "Asia/Singapore", + c: ["SG"], + r: 1, + }, + Turkey: { + a: "Europe/Istanbul", + r: 1, + }, + UCT: { + a: "Etc/UTC", + r: 1, + }, + "US/Alaska": { + a: "America/Anchorage", + r: 1, + }, + "US/Aleutian": { + a: "America/Adak", + r: 1, + }, + "US/Arizona": { + a: "America/Phoenix", + c: ["US"], + r: 1, + }, + "US/Central": { + a: "America/Chicago", + r: 1, + }, + "US/East-Indiana": { + a: "America/Indiana/Indianapolis", + r: 1, + }, + "US/Eastern": { + a: "America/New_York", + r: 1, + }, + "US/Hawaii": { + a: "Pacific/Honolulu", + c: ["US"], + r: 1, + }, + "US/Indiana-Starke": { + a: "America/Indiana/Knox", + r: 1, + }, + "US/Michigan": { + a: "America/Detroit", + r: 1, + }, + "US/Mountain": { + a: "America/Denver", + r: 1, + }, + "US/Pacific": { + a: "America/Los_Angeles", + r: 1, + }, + "US/Samoa": { + a: "Pacific/Pago_Pago", + c: ["WS"], + r: 1, + }, + UTC: { + a: "Etc/UTC", + r: 1, + }, + Universal: { + a: "Etc/UTC", + r: 1, + }, + "W-SU": { + a: "Europe/Moscow", + r: 1, + }, + WET: { + u: 0, + d: 60, + }, + Zulu: { + a: "Etc/UTC", + r: 1, + }, +} as { [key: string]: any } + +export { regions, timezones, AWSRegion } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/constants/storage.ts b/browser/hybrid/components/cloud_tabs_extension/src/constants/storage.ts new file mode 100644 index 00000000000..7e8f1f8592f --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/constants/storage.ts @@ -0,0 +1,13 @@ +export enum Storage { + AUTH_INFO = "AUTH_INFO", + CLOSEST_AWS_REGIONS = "CLOSEST_AWS_REGIONS", + CONFIG_TOKEN_INFO = "CONFIG_TOKEN_INFO", + SAVED_CLOUD_URLS = "SAVED_CLOUD_URLS", + WAITLISTED = "WAITLISTED", +} + +export enum MandelboxState { + MANDELBOX_NONEXISTENT, + MANDELBOX_WAITING, + MANDELBOX_CONNECTED, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/constants/urls.ts b/browser/hybrid/components/cloud_tabs_extension/src/constants/urls.ts new file mode 100644 index 00000000000..7b9b051e77e --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/constants/urls.ts @@ -0,0 +1,20 @@ +import { config } from "@app/constants/app" + +export const videoUrls = [ + "youtube.com", + "tiktok.com", + "vimeo.com", + "twitch.com", + "dailymotion.com", + "netflix.com", + "hulu.com", + "hbomax.com", + "disneyplus.com", + "espn.com", + "tennistv.com", +] +export const videoChatUrls = ["meet.google.com", "gather.town", "zoom.us"] +export const unsupportedUrls = ["abercrombie.com"] +export const whistUrls = [config.AUTH0_REDIRECT_URL, config.AUTH0_DOMAIN_URL] +export const whistLoadingUrl = + "data:text/plain;charset=utf-8;base64,V2hpc3QgaXMgbG9hZGluZw==" diff --git a/browser/hybrid/components/cloud_tabs_extension/src/content/index.ts b/browser/hybrid/components/cloud_tabs_extension/src/content/index.ts new file mode 100644 index 00000000000..9d842416d2b --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/content/index.ts @@ -0,0 +1,3 @@ +import { initNotificationListener } from "./notifications" + +initNotificationListener() diff --git a/browser/hybrid/components/cloud_tabs_extension/src/content/notifications.ts b/browser/hybrid/components/cloud_tabs_extension/src/content/notifications.ts new file mode 100644 index 00000000000..799033e951b --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/content/notifications.ts @@ -0,0 +1,63 @@ +import { CloudTabError, errorMessage } from "@app/constants/errors" + +let shown = false + +const element = (html: string) => { + const template = document.createElement("template") + html = html.trim() + template.innerHTML = html + return template.content.firstChild as HTMLElement +} + +const createNotification = ({ + text, + duration, + type, +}: { + text: string + type?: string + duration?: number +}) => { + // Create the notification HTMLElement + const notification = element(`
${text}
`) + + notification.style.background = type === "warning" ? "#fee2e2" : "#bae6fd" + notification.style.color = type === "warning" ? "#c2410c" : "#1d4ed8" + + // Inject the HTMLElement into the DOM + shown = true + document.body.appendChild(notification) + // Fade out notification + duration !== undefined && + setTimeout(() => { + notification.style.animation = "fadeOut 1.5s" + notification.style.animationFillMode = "forwards" + shown = false + }, duration) + + return notification +} + +const initNotificationListener = () => { + chrome.runtime.onMessage.addListener((message: any) => { + if (shown || !Object.keys(errorMessage).includes(message.type)) return true + + const notification = createNotification(errorMessage[message.type]) + + if (message.type === CloudTabError.AUTH_ERROR) { + notification.addEventListener("click", () => { + chrome.runtime.sendMessage({ type: "SHOW_LOGIN_PAGE" }) + }) + } + + if (message.type === CloudTabError.UPDATE_NEEDED) { + notification.addEventListener("click", () => { + chrome.runtime.sendMessage({ type: "SHOW_UPDATE_PAGE" }) + }) + } + + return true + }) +} + +export { initNotificationListener } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/assets/cloud-off.png b/browser/hybrid/components/cloud_tabs_extension/src/popup/assets/cloud-off.png new file mode 100644 index 0000000000000000000000000000000000000000..b5fb239cdcd03b84d8ef3a3e38f98e8167678fba GIT binary patch literal 22311 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
6mZSXGIdr* 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 S{E?pv14?r0vQ;u>A^!)-MbAh8 literal 0 HcmV?d00001 diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/assets/cloud-waiting.png b/browser/hybrid/components/cloud_tabs_extension/src/popup/assets/cloud-waiting.png new file mode 100644 index 0000000000000000000000000000000000000000..b861f3a929465b595aa05e1e555ed61359a5358d GIT binary patch literal 15486 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 IG@N4pFHk)9X8-^I literal 0 HcmV?d00001 diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/assets/cloud-warning.png b/browser/hybrid/components/cloud_tabs_extension/src/popup/assets/cloud-warning.png new file mode 100644 index 0000000000000000000000000000000000000000..3e91acd20a591b325b7f4e7992d8e173b7536d51 GIT binary patch literal 23704 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 literal 0 HcmV?d00001 diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/assets/whist_logo.png b/browser/hybrid/components/cloud_tabs_extension/src/popup/assets/whist_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e84ffc10ed64820e7a9e807ad937eaf1b3ab7b1b GIT binary patch literal 10381 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 Uebr6(uX+%muB@Zfpa6;bKaxcfcmMzZ literal 0 HcmV?d00001 diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/components/checkbox.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/checkbox.tsx new file mode 100644 index 00000000000..141fbf7eea2 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/checkbox.tsx @@ -0,0 +1,57 @@ +import * as React from "react" +import { useState } from "react" +import classNames from "classnames" +import { Switch } from "@headlessui/react" + +const Checkbox = (props: { + label: string + default: boolean + onChange: (checked: boolean) => void +}) => { + const [checked, setChecked] = useState(props.default) + + const onChange = () => { + const _checked = !checked + setChecked(_checked) + props.onChange(_checked) + } + + return ( +
+
+ + + +
+ {props.label} +
+
+
+ + +
+
+ ) +} + +export default Checkbox diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/components/help.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/help.tsx new file mode 100644 index 00000000000..b7f2116fb57 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/help.tsx @@ -0,0 +1,14 @@ +import * as React from "react" + +const Help = (props: { onClick: () => void }) => { + return ( + + ) +} +export default Help diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/components/host.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/host.tsx new file mode 100644 index 00000000000..8a08b3784c2 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/host.tsx @@ -0,0 +1,11 @@ +import * as React from "react" + +const Host = (props: { host: string }) => ( +
+
+ {props.host} +
+
+) + +export default Host diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/components/login.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/login.tsx new file mode 100644 index 00000000000..9224c9c7c7c --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/login.tsx @@ -0,0 +1,24 @@ +import * as React from "react" + +const Login = (props: { onClick: () => void }) => { + return ( +
+
+

+ Sign in to Whist +

+

+ To unlock cloud tabs +

+ +
+
+ ) +} +export default Login diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/components/metrics.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/metrics.tsx new file mode 100644 index 00000000000..5a5a3270db9 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/metrics.tsx @@ -0,0 +1,30 @@ +import React from "react" + +const Metrics = (props: { numberCloudTabs: number }) => { + const { numberCloudTabs } = props + return ( +
+
+ + + +
+
+ {Math.min(0.6 * numberCloudTabs, 25).toFixed(1)} GB RAM saved +
+
+
+
+ ) +} + +export default Metrics diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/components/network.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/network.tsx new file mode 100644 index 00000000000..9058d29ee27 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/network.tsx @@ -0,0 +1,102 @@ +import React from "react" + +const maxPingTime = 25 + +const Network = (props: { networkInfo: any }) => { + const { networkInfo } = props + + const icon = () => { + if (networkInfo === undefined) + return ( +
+ + + + +
+ ) + + if (networkInfo.pingTime < maxPingTime) + return ( + + + + ) + + return ( + + + + ) + } + + const text = () => { + if (networkInfo === undefined) return "Detecting your network latency..." + if (networkInfo.pingTime < maxPingTime) + return ( + <> +
+ Your Internet is strong +
+
+
Ping: {networkInfo.pingTime}ms
+
+
Closest Server: {networkInfo.region}
+
+ + ) + + return ( + <> +
+ Your ping is high +
+
+
Ping: {networkInfo.pingTime}ms
+
+
Closest Server: {networkInfo.region}
+
+ + ) + } + + return ( +
+
+
{icon()}
+
{text()}
+
+
+ ) +} + +export default Network diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/components/toggle.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/toggle.tsx new file mode 100644 index 00000000000..7f401cfa9ca --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/toggle.tsx @@ -0,0 +1,93 @@ +import * as React from "react" +import classNames from "classnames" + +import { useState } from "react" +import { Switch } from "@headlessui/react" + +import CloudOff from "../assets/cloud-off.png" +import CloudOn from "../assets/cloud-on.png" +import CloudWaiting from "../assets/cloud-waiting.png" +import CloudWarning from "../assets/cloud-warning.png" + +const Toggle = (props: { + initial: boolean + isWaiting: boolean + error: string | undefined + onToggled: (enabled: boolean) => void +}) => { + const [enabled, setEnabled] = useState(props.initial || props.isWaiting) + + const onChange = () => { + const _enabled = !enabled + props.onToggled(_enabled) + setEnabled(_enabled) + } + + const text = () => { + if (props.error !== undefined) return "This page shouldn't be streamed" + if (props.isWaiting) return "Whist is connecting" + if (enabled) return `Streaming is ON for this site` + return `Streaming is OFF for this site` + } + + const icon = () => { + if (props.error !== undefined) return CloudWarning + if (props.isWaiting) return CloudWaiting + if (enabled) return CloudOn + return CloudOff + } + + const description = () => { + if (props.error !== undefined) return props.error + if (props.isWaiting) + return "This should only take a few seconds. If it takes any longer, please report it as a bug so we can fix!" + if (enabled) + return "This site is being streamed. You can disable streaming if you experience latency due to poor Internet." + return "Enable streaming to make this site faster and use much less memory." + } + + return ( +
+ + + +
{text()}
+
+
+ + +
+ +
+ {description()} +
+
+ ) +} + +export default Toggle diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/components/waitlist.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/waitlist.tsx new file mode 100644 index 00000000000..d7fe3261308 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/components/waitlist.tsx @@ -0,0 +1,101 @@ +import * as React from "react" +import classNames from "classnames" +import { useState, useEffect } from "react" + +import Logo from "../assets/whist_logo.png" + +const Waitlist = (props: { + onClick: (code: string) => void + error: boolean +}) => { + const [code, setCode] = useState("") + const [showError, setShowError] = useState(false) + + useEffect(() => { + setShowError(props.error) + }, [props.error]) + + const onChange = (e: any) => { + setCode(e.target.value) + setShowError(false) + console.log("changing to", e.target.value) + } + + const onKeyDown = (e: any) => { + console.log("key down", code) + if (e.key === "Enter") { + props.onClick(code) + setShowError(false) + } + } + + return ( + <> +
+
+ +
+
+ + +
+
+ Invalid code +
+
+
+
+ + ) +} + +export default Waitlist diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/containers/loading.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/containers/loading.tsx new file mode 100644 index 00000000000..18ee3b17e96 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/containers/loading.tsx @@ -0,0 +1,30 @@ +import * as React from "react" + +const Loading = () => { + return ( +
+
+ +
+ Whist is loading... +
+
+
+ ) +} + +export default Loading diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/containers/main.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/containers/main.tsx new file mode 100644 index 00000000000..89fb727e9f4 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/containers/main.tsx @@ -0,0 +1,79 @@ +import * as React from "react" + +import Host from "../components/host" +import Toggle from "../components/toggle" +import Checkbox from "../components/checkbox" +import Metrics from "../components/metrics" +import Help from "../components/help" +import Network from "../components/network" + +const Main = (props: { + isWaiting: boolean + isSaved: boolean + networkInfo: any + numberCloudTabs: number + error?: string + host?: string + isCloudTab?: boolean + onToggled: (toggled: boolean) => void + onSaved: (saved: boolean) => void + onHelp: () => void +}) => { + const { + host, + isCloudTab, + isWaiting, + error, + isSaved, + onToggled, + onSaved, + onHelp, + numberCloudTabs, + networkInfo, + } = props + + return ( +
+
+ {host !== undefined && ( + <> + +
+ + )} + {isCloudTab !== undefined && ( + <> + + {numberCloudTabs > 0 && host !== undefined && error === undefined && ( +
+ +
+ )} + + )} + {numberCloudTabs > 0 && ( +
+
+ +
+ )} +
+
+ +
+
+ +
+ ) +} + +export default Main diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/containers/offline.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/containers/offline.tsx new file mode 100644 index 00000000000..e9e2d3e67a8 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/containers/offline.tsx @@ -0,0 +1,22 @@ +import * as React from "react" + +import Toggle from "../components/toggle" + +const Offline = () => { + return ( +
+
+ {}} + isWaiting={false} + error={ + "Whist is having trouble finding your network. Please check your Internet to see if you're connected." + } + /> +
+
+ ) +} + +export default Offline diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/index.tsx b/browser/hybrid/components/cloud_tabs_extension/src/popup/index.tsx new file mode 100644 index 00000000000..2e95c5f0b38 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/index.tsx @@ -0,0 +1,178 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" +import { useState, useEffect } from "react" +import classNames from "classnames" + +import Login from "./components/login" +import Waitlist from "./components/waitlist" + +import Offline from "./containers/offline" +import Main from "./containers/main" +import Loading from "./containers/loading" + +import { sendMessageToBackground } from "./utils/messaging" + +import { PopupMessageType } from "@app/@types/messaging" + +const App = () => { + const [dark, setDark] = useState(true) + const [isLoggedIn, setIsLoggedIn] = useState(true) + const [host, setHost] = useState(undefined) + const [isSaved, setIsSaved] = useState(false) + const [numberCloudTabs, setNumberCloudTabs] = useState(0) + const [error, setError] = useState(undefined) + const [isCloudTab, setIsCloudTab] = useState(undefined) + const [isWaiting, setIsWaiting] = useState(false) + const [networkError, setNetworkError] = useState(false) + const [waitlisted, setWaitlisted] = useState(true) + const [inviteError, setInviteError] = useState(false) + const [loaded, setLoaded] = useState(false) + const [networkInfo, setNetworkInfo] = useState(undefined) + + const parseHost = (host: string | undefined) => { + if (host === undefined) return undefined + const isLong = host.length > 15 + return `${host?.substring(0, 15)}${isLong ? "..." : ""}` + } + + const fetchPopupData = async () => { + const sleep = async (ms: number) => + await new Promise((resolve) => setTimeout(resolve, ms)) + let attempts = 0 + let _loaded = false + while (!_loaded && attempts < 20) { + attempts += 1 + sendMessageToBackground( + PopupMessageType.FETCH_POPUP_DATA, + undefined, + ({ + error, + isCloudTab, + numberCloudTabs, + isSaved, + host, + isWaiting, + isLoggedIn, + networkError, + waitlisted, + networkInfo, + }) => { + _loaded = true + setLoaded(true) + setError(error) + setIsCloudTab(isCloudTab) + setNumberCloudTabs(numberCloudTabs) + setIsSaved(isSaved) + setHost(parseHost(host)) + setIsWaiting(isWaiting) + setIsLoggedIn(isLoggedIn) + setNetworkError(networkError) + setWaitlisted(waitlisted) + setNetworkInfo(networkInfo) + } + ) + await sleep(250) + } + } + + useEffect(() => { + void fetchPopupData() + ;(chrome as any).braveTheme.getBraveThemeType((themeType: string) => { + setDark(themeType === "Dark") + }) + }, []) + + useEffect(() => { + chrome.runtime.onMessage.addListener((message) => { + if (message.type !== PopupMessageType.SEND_POPUP_DATA) return + + if (message.value.isLoggedIn !== undefined) + setIsLoggedIn(message.value.isLoggedIn) + + if (message.value.isWaiting !== undefined) + setIsWaiting(message.value.isWaiting) + }) + }, []) + + const onToggled = (enabled: boolean) => { + sendMessageToBackground(PopupMessageType.STREAM_TAB, { enabled }, () => { + void fetchPopupData() + }) + } + + const onSaved = (saved: boolean) => { + sendMessageToBackground(PopupMessageType.SAVE_URL, { saved }, () => { + void fetchPopupData() + }) + } + + const onHelp = () => { + sendMessageToBackground(PopupMessageType.OPEN_INTERCOM) + } + + const onInviteCode = (code: string) => { + setInviteError(false) + sendMessageToBackground( + PopupMessageType.INVITE_CODE, + { code }, + ({ success }: { success: boolean }) => { + success ? setWaitlisted(false) : setInviteError(true) + } + ) + } + + if (!loaded) + return ( +
+ +
+ ) + + if (networkError) + return ( +
+ +
+ ) + + if (!isLoggedIn) + return ( +
+
+ { + sendMessageToBackground(PopupMessageType.OPEN_LOGIN_PAGE) + }} + /> +
+
+ ) + + if (waitlisted) + return ( +
+
+ +
+
+ ) + + return ( +
+
+
+ ) +} + +ReactDOM.render(, document.getElementById("root")) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/utils/messaging.ts b/browser/hybrid/components/cloud_tabs_extension/src/popup/utils/messaging.ts new file mode 100644 index 00000000000..eb7a78ee01b --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/utils/messaging.ts @@ -0,0 +1,17 @@ +import { PopupMessage, PopupMessageType } from "@app/@types/messaging" + +const sendMessageToBackground = ( + type: PopupMessageType, + value?: any, + callback?: (response: any) => void +) => { + chrome.runtime.sendMessage( + { + type, + value, + }, + callback + ) +} + +export { sendMessageToBackground } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/popup/utils/ui.ts b/browser/hybrid/components/cloud_tabs_extension/src/popup/utils/ui.ts new file mode 100644 index 00000000000..2abef075977 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/popup/utils/ui.ts @@ -0,0 +1,11 @@ +const fixAppearance = () => { + chrome.runtime.getPlatformInfo((info) => { + if (info.os === "mac") { + setTimeout(() => { + document.body.style.width = `${document.body.clientWidth + 1}px` + }, 250) + } + }) +} + +export { fixAppearance } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/tab/help.tsx b/browser/hybrid/components/cloud_tabs_extension/src/tab/help.tsx new file mode 100644 index 00000000000..16fd180282e --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/tab/help.tsx @@ -0,0 +1,46 @@ +import React, { useState, useEffect } from "react" +import { IntercomProvider, useIntercom } from "react-use-intercom" + +const Support = (props: { userEmail: string | undefined }) => { + const { show, update } = useIntercom() + const [dark, setDark] = useState(true) + + useEffect(() => { + ;(chrome as any).braveTheme.getBraveThemeType((theme: string) => + setDark(theme === "Dark") + ) + ;(chrome as any).braveTheme.onBraveThemeTypeChanged.addListener( + (theme: string) => setDark(theme === "Dark") + ) + }, []) + + useEffect(() => { + show() + }, []) + + useEffect(() => { + if (props.userEmail !== undefined) update({ email: props.userEmail }) + }, [props.userEmail]) + + return ( +
+
+
+ ) +} + +const WithInterCom = (props: { + onClose: () => void + userEmail: string | undefined +}) => ( + + + +) + +export default WithInterCom diff --git a/browser/hybrid/components/cloud_tabs_extension/src/tab/index.tsx b/browser/hybrid/components/cloud_tabs_extension/src/tab/index.tsx new file mode 100644 index 00000000000..39dafcf0513 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/tab/index.tsx @@ -0,0 +1,14 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" + +import WithInterCom from "./help" + +const App = () => { + return ( + <> + {}} userEmail={undefined} /> + + ) +} + +ReactDOM.render(, document.getElementById("root")) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/README.md b/browser/hybrid/components/cloud_tabs_extension/src/worker/README.md new file mode 100644 index 00000000000..0fb980f0bea --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/README.md @@ -0,0 +1,5 @@ +# Whist Extension Background Service Worker + +This folder is home to the background service worker, i.e. the brains of our extension. + +The primary responsibility of this folder is to handle all `chrome` extension API calls and handle all the extension's business logic. diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/auth.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/auth.ts new file mode 100644 index 00000000000..fba5ef13db3 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/auth.ts @@ -0,0 +1,54 @@ +import { take } from "rxjs/operators" + +import { initConfigTokenHandler } from "@app/worker/utils/auth" +import { authSuccess, authFailure } from "@app/worker/events/auth" +import { getStorage, setStorage } from "@app/worker/utils/storage" +import { getActiveTab, updateTabUrl } from "@app/worker/utils/tabs" +import { whistState } from "@app/worker/utils/state" + +import { PopupMessage, PopupMessageType } from "@app/@types/messaging" +import { AuthInfo } from "@app/@types/payload" +import { Storage } from "@app/constants/storage" + +void initConfigTokenHandler() + +// Tell the browser that auth succeeded and redirect to chrome://welcome +authSuccess.subscribe((auth: AuthInfo) => { + whistState.isLoggedIn = true + ;(chrome as any).whist.setWhistIsLoggedIn(true, async () => { + if (auth.isFirstAuth) { + const { id } = await getActiveTab() + updateTabUrl(id ?? -1, "chrome://welcome") + } + + chrome.runtime.sendMessage({ + type: PopupMessageType.SEND_POPUP_DATA, + value: { + isLoggedIn: true, + }, + }) + + void setStorage(Storage.AUTH_INFO, auth) + whistState.isLoggedIn = true + }) +}) + +// Tell the browser that auth failed +authFailure.subscribe(async () => { + whistState.isLoggedIn = false + ;(chrome as any).whist.setWhistIsLoggedIn(false) + chrome.runtime.sendMessage({ + type: PopupMessageType.SEND_POPUP_DATA, + value: { + isLoggedIn: false, + }, + }) +}) + +authFailure.pipe(take(1)).subscribe(async () => { + const { id } = await getActiveTab() + const authInfo = await getStorage(Storage.AUTH_INFO) + + if (authInfo?.accessToken === undefined) + updateTabUrl(id ?? -1, "chrome://welcome") +}) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/content.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/content.ts new file mode 100644 index 00000000000..3ea5f1a3d73 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/content.ts @@ -0,0 +1,15 @@ +import { showUpdatePage, showLoginPage } from "@app/worker/events/content" + +showUpdatePage.subscribe(() => { + chrome.tabs.create({ + url: "whist://settings/help", + }) +}) + +showLoginPage.subscribe(() => { + ;(chrome as any).whist.setWhistIsLoggedIn(false, () => { + chrome.tabs.create({ + url: "whist://welcome", + }) + }) +}) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/cookies.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/cookies.ts new file mode 100644 index 00000000000..c314f4c180a --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/cookies.ts @@ -0,0 +1,61 @@ +import { withLatestFrom } from "rxjs/operators" +import { Socket } from "socket.io-client" + +import { + clientCookieAdded, + clientCookieRemoved, + serverCookieAdded, +} from "@app/worker/events/cookies" +import { socketConnected } from "@app/worker/events/socketio" + +import { whistState } from "@app/worker/utils/state" + +// If a cookie is added in a local tab, add it to a cloud tab +clientCookieAdded + .pipe(withLatestFrom(socketConnected)) + .subscribe(([cookie, socket]: [chrome.cookies.Cookie, Socket]) => { + socket.emit("server-add-cookie", cookie) + }) + +// If a cookie is removed from a local tab, remove it from the cloud tab +clientCookieRemoved + .pipe(withLatestFrom(socketConnected)) + .subscribe(([cookie, socket]: [chrome.cookies.Cookie, Socket]) => { + socket.emit("server-remove-cookie", cookie) + }) + +socketConnected.subscribe((socket: Socket) => { + chrome.cookies.getAll({}, (cookies) => { + socket.emit("sync-cookies", ...cookies) + }) +}) + +// If the server adds a cookie, also add it on the client side +// We add this cookie to an "alreadyAddedCookies" list to make sure +// we don't fall into an infinite loop of adding cookies and then +// sending them back to the server to be added +serverCookieAdded.subscribe(([cookie]: [chrome.cookies.Cookie]) => { + if (cookie.domain.includes("google")) return + + const url = cookie.domain.startsWith(".") + ? `https://${cookie.domain.slice(1)}${cookie.path}` + : `https://${cookie.domain}${cookie.path}` + + // See https://developer.chrome.com/docs/extensions/reference/cookies/#method-set + // for why we construct the cookie details this way + const details = { + ...(!cookie.hostOnly && { domain: cookie.domain }), + ...(!cookie.session && { expirationDate: cookie.expirationDate }), + httpOnly: cookie.httpOnly, + name: cookie.name, + path: cookie.path, + sameSite: cookie.sameSite, + secure: cookie.secure, + storeId: cookie.storeId, + value: cookie.value, + url, + } as chrome.cookies.SetDetails + + whistState.alreadyAddedCookies.push(cookie) + chrome.cookies.set(details) +}) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/download.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/download.ts new file mode 100644 index 00000000000..f632023cacc --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/download.ts @@ -0,0 +1,5 @@ +import { downloadStarted } from "@app/worker/events/download" + +downloadStarted.subscribe(([url]: [string]) => { + chrome.downloads.download({ url }) +}) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/errors.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/errors.ts new file mode 100644 index 00000000000..a2e46274f77 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/errors.ts @@ -0,0 +1,44 @@ +import { mandelboxError } from "@app/worker/events/mandelbox" +import { hostError } from "@app/worker/events/host" +import { authNetworkError } from "@app/worker/events/auth" + +import { whistState } from "@app/worker/utils/state" +import { stripCloudUrl, updateTabUrl } from "@app/worker/utils/tabs" +import { + mandelboxCreateErrorCommitHash, + mandelboxCreateErrorUnauthorized, + mandelboxRequest, +} from "@app/worker/utils/mandelbox" + +import { AsyncReturnType } from "@app/@types/api" +import { CloudTabError } from "@app/constants/errors" + +const showPopup = (type: CloudTabError) => { + whistState.waitingCloudTabs.forEach((tab) => { + updateTabUrl(tab.id, stripCloudUrl(tab.url ?? ""), () => { + setTimeout(() => { + chrome.tabs.sendMessage(tab.id ?? 0, { type }) + }, 1000) + }) + }) + whistState.waitingCloudTabs = [] +} + +hostError.subscribe(() => { + showPopup(CloudTabError.HOST_ERROR) +}) +authNetworkError.subscribe(() => { + showPopup(CloudTabError.NETWORK_ERROR) +}) + +mandelboxError.subscribe( + (response: AsyncReturnType) => { + if (mandelboxCreateErrorCommitHash(response)) { + showPopup(CloudTabError.UPDATE_NEEDED) + } else if (mandelboxCreateErrorUnauthorized(response)) { + showPopup(CloudTabError.AUTH_ERROR) + } else { + showPopup(CloudTabError.NO_INSTANCE_ERROR) + } + } +) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/logging.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/logging.ts new file mode 100644 index 00000000000..6e1beaa6568 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/logging.ts @@ -0,0 +1,76 @@ +import { interval, merge } from "rxjs" +import { throttle } from "rxjs/operators" +import * as amplitude from "@amplitude/analytics-browser" +import { track, Identify, identify } from "@amplitude/analytics-browser" + +import { authSuccess, authFailure } from "@app/worker/events/auth" +import { + mandelboxNeeded, + mandelboxError, + mandelboxSuccess, +} from "@app/worker/events/mandelbox" +import { hostSuccess, hostError } from "@app/worker/events/host" +import { tabActivated, tabCreated, tabFocused } from "@app/worker/events/tabs" +import { + socketConnected, + socketDisconnected, +} from "@app/worker/events/socketio" +import { getStorage } from "@app/worker/utils/storage" + +import { config } from "@app/constants/app" +import { AuthInfo } from "@app/@types/payload" +import { Storage } from "@app/constants/storage" + +authSuccess.subscribe(async (auth: AuthInfo) => { + console.log("Successfully logged in") + + if (config.AMPLITUDE_KEY !== undefined) { + amplitude.init(config.AMPLITUDE_KEY, auth.userEmail) + + const event = new Identify() + const waitlisted = await getStorage(Storage.WAITLISTED) + + event.set("waitlisted", waitlisted) + identify(event) + } +}) + +merge(tabActivated, tabFocused, tabCreated) + .pipe(throttle(() => interval(1000 * 60 * 60 * 12))) + .subscribe(() => { + console.log("Usage ping") + track("Usage ping") + }) + +authFailure.subscribe((auth: AuthInfo) => { + console.log("Auth failure", auth) +}) + +mandelboxNeeded.subscribe((x: any) => { + console.log("Mandelbox needed", x) +}) + +mandelboxSuccess.subscribe((x: any) => { + console.log("Mandelbox successfully assigned", x) +}) + +hostSuccess.subscribe((x: any) => { + console.log("Host service successful", x) + track("Used cloud tab") +}) + +mandelboxError.subscribe((x: any) => { + console.log("Mandelbox assign error", x) +}) + +hostError.subscribe((x: any) => { + console.log("Host service error", x) +}) + +socketConnected.subscribe(() => { + console.log("Cloud tab successfully connected") +}) + +socketDisconnected.subscribe(() => { + console.log("Cloud tab socket disconnected") +}) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/mandelbox.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/mandelbox.ts new file mode 100644 index 00000000000..4453ea73b69 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/mandelbox.ts @@ -0,0 +1,69 @@ +import { zip, merge } from "rxjs" +import { withLatestFrom } from "rxjs/operators" + +import { + mandelboxError, + mandelboxNeeded, + mandelboxSuccess, +} from "@app/worker/events/mandelbox" +import { webuiMandelboxNeeded } from "@app/worker/events/webui" +import { hostSuccess, hostError } from "@app/worker/events/host" +import { socket, socketReconnectFailed } from "@app/worker/events/socketio" + +import { serializeProtocolArgs } from "@app/worker/utils/protocol" +import { addTabToQueue } from "@app/worker/utils/tabs" +import { whistState } from "@app/worker/utils/state" + +import { MandelboxState } from "@app/constants/storage" +import { Socket } from "socket.io-client" + +mandelboxNeeded.subscribe(() => { + whistState.mandelboxState = MandelboxState.MANDELBOX_WAITING +}) + +merge(mandelboxNeeded, socketReconnectFailed) + .pipe(withLatestFrom(socket)) + .subscribe(([, socket]: [any, Socket]) => { + socket.close() + }) + +zip(mandelboxSuccess, hostSuccess).subscribe(([mandelbox, host]: any) => { + const s = serializeProtocolArgs({ ...mandelbox, ...host }) + ;(chrome as any).whist.broadcastWhistMessage( + JSON.stringify({ + type: "MANDELBOX_INFO", + value: { + "server-ip": s.mandelboxIP, + p: s.mandelboxPorts, + k: s.mandelboxSecret, + }, + }) + ) + + whistState.mandelboxState = MandelboxState.MANDELBOX_CONNECTED + whistState.mandelboxInfo = { ...mandelbox, ...host } +}) + +webuiMandelboxNeeded.subscribe(() => { + if (whistState.mandelboxState !== MandelboxState.MANDELBOX_WAITING) { + whistState.mandelboxState = MandelboxState.MANDELBOX_NONEXISTENT + } + whistState.mandelboxInfo = undefined +}) + +merge(mandelboxError, hostError, socketReconnectFailed).subscribe(() => { + whistState.mandelboxState = MandelboxState.MANDELBOX_NONEXISTENT + whistState.mandelboxInfo = undefined +}) + +merge(webuiMandelboxNeeded, socketReconnectFailed).subscribe(() => { + whistState.activeCloudTabs = [] + + chrome.tabs.query({}, (tabs: chrome.tabs.Tab[]) => { + const cloudTabs = tabs.filter((tab) => tab.url?.startsWith("cloud:")) + + cloudTabs.forEach((tab) => { + addTabToQueue(tab) + }) + }) +}) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/ping.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/ping.ts new file mode 100644 index 00000000000..b5c3d4857e4 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/ping.ts @@ -0,0 +1,13 @@ +import { initAWSRegionPing } from "@app/worker/utils/location" +import { setStorage } from "@app/worker/utils/storage" + +import { Storage } from "@app/constants/storage" + +// Find closest AWS region +void initAWSRegionPing() + .then((regions) => { + void setStorage(Storage.CLOSEST_AWS_REGIONS, regions) + }) + .catch((err) => { + console.error("No Internet", err) + }) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/popup.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/popup.ts new file mode 100644 index 00000000000..3e1e0d63e1e --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/popup.ts @@ -0,0 +1,218 @@ +import uniq from "lodash.uniq" +import { merge, of } from "rxjs" +import { withLatestFrom, takeUntil } from "rxjs/operators" + +import { + authSuccess, + authFailure, + authNetworkError, +} from "@app/worker/events/auth" +import { tabActivated, tabFocused, tabUpdated } from "@app/worker/events/tabs" + +import { stateDidChange, whistState } from "@app/worker/utils/state" +import { getStorage, setStorage } from "@app/worker/utils/storage" +import { + convertToCloudTab, + getActiveTab, + getNumberOfCloudTabs, + isCloudTab, + removeTabFromQueue, + stripCloudUrl, + updateTabUrl, +} from "@app/worker/utils/tabs" +import { cannotStreamError } from "@app/worker/utils/errors" +import { + popupActivateCloudTab, + popupClicked, + popupDeactivateCloudTab, + popupOpened, + popupUrlSaved, + popupUrlUnsaved, + popupOpenLogin, + popupOpenIntercom, + popupInviteCode, +} from "@app/worker/events/popup" +import { Storage } from "@app/constants/storage" +import { inviteCode } from "@app/constants/app" +import { AWSRegion, regions } from "@app/constants/location" + +// If the popup is opened, send the necessary display information +popupOpened + .pipe(withLatestFrom(authSuccess)) + .subscribe(async ([event]: [any]) => { + void Promise.all([ + getNumberOfCloudTabs(), + getActiveTab(), + getStorage(Storage.WAITLISTED), + getStorage(Storage.SAVED_CLOUD_URLS), + getStorage>( + Storage.CLOSEST_AWS_REGIONS + ), + ]).then( + ([ + numberCloudTabs, + activeTab, + waitlisted, + savedCloudUrls, + sortedRegions, + ]) => { + const url = new URL(stripCloudUrl(activeTab.url ?? "")) + const host = + url?.protocol === "http:" || url?.protocol === "https:" + ? url?.hostname + : undefined + + event.sendResponse({ + isCloudTab: isCloudTab(activeTab), + isWaiting: whistState.waitingCloudTabs.some( + (tab: chrome.tabs.Tab) => activeTab.id === tab.id + ), + isSaved: (savedCloudUrls ?? []).some( + (_host: string) => _host === host + ), + error: cannotStreamError(activeTab), + numberCloudTabs, + host, + isLoggedIn: true, + waitlisted: waitlisted ?? true, + networkInfo: { + ...sortedRegions[0], + region: regions.find((r) => r.name === sortedRegions[0]?.region) + ?.location, + }, + }) + } + ) + }) + +popupOpened + .pipe(withLatestFrom(authFailure), takeUntil(authSuccess)) + .subscribe(([event]: [any]) => { + event.sendResponse({ isLoggedIn: false }) + }) + +popupOpened + .pipe(withLatestFrom(authNetworkError), takeUntil(authSuccess)) + .subscribe(([event]: [any]) => { + event.sendResponse({ networkError: true }) + }) + +merge(popupActivateCloudTab, popupClicked) + .pipe(withLatestFrom(authSuccess)) + .subscribe(() => { + void Promise.all([ + getActiveTab(), + getStorage(Storage.WAITLISTED), + ]).then(([tab, waitlisted]: [chrome.tabs.Tab, boolean | undefined]) => { + if ( + !(waitlisted ?? true) && + cannotStreamError(tab) === undefined && + !isCloudTab(tab) + ) { + convertToCloudTab(tab) + } + }) + }) + +// If the user disables a cloud tab +popupDeactivateCloudTab.subscribe((event: any) => { + void Promise.all([getStorage(Storage.SAVED_CLOUD_URLS), getActiveTab()]).then( + (args: any) => { + const [savedCloudUrls, tab] = args + const url = new URL(stripCloudUrl(tab.url)) + const host = url.hostname + + removeTabFromQueue(tab) + + void setStorage( + Storage.SAVED_CLOUD_URLS, + savedCloudUrls?.filter((h: string) => h !== host) + ).then(() => { + updateTabUrl(tab.id, stripCloudUrl(tab.url ?? "")) + event.sendResponse() + }) + } + ) +}) + +// If the user saves a URL to always be streamed +popupUrlSaved.subscribe((event: any) => { + void Promise.all([getStorage(Storage.SAVED_CLOUD_URLS), getActiveTab()]).then( + (args: any) => { + const [savedCloudUrls, tab] = args + const url = new URL(stripCloudUrl(tab.url)) + const host = url.hostname + + void setStorage( + Storage.SAVED_CLOUD_URLS, + uniq([...(savedCloudUrls ?? []), host]) + ).then(() => event.sendResponse()) + } + ) +}) + +// If the user unsaves a URL from always being streamed +popupUrlUnsaved.subscribe((event: any) => { + void Promise.all([getStorage(Storage.SAVED_CLOUD_URLS), getActiveTab()]).then( + (args: any) => { + const [savedCloudUrls, tab] = args + const url = new URL(stripCloudUrl(tab.url)) + const host = url.hostname + + void setStorage( + Storage.SAVED_CLOUD_URLS, + (savedCloudUrls ?? [])?.filter((_host: string) => _host !== host) + ).then(() => event.sendResponse) + } + ) +}) + +// If the user clicks the popup login button +popupOpenLogin.subscribe(() => { + chrome.tabs.create({ url: "chrome://welcome" }) +}) + +// If the user clicks the popup help button +popupOpenIntercom.subscribe(() => { + chrome.tabs.create({ url: chrome.runtime.getURL("intercom.html") }) +}) + +popupInviteCode.subscribe((event: any) => { + const success = event?.request?.value?.code === inviteCode + event.sendResponse({ success }) + + if (success) void setStorage(Storage.WAITLISTED, false) +}) + +merge( + tabActivated, + tabFocused, + tabUpdated, + stateDidChange("waitingCloudTabs"), + of(null) +).subscribe(async () => { + const activeTab = await getActiveTab() + const waitlisted = + (await getStorage(Storage.WAITLISTED)) ?? true + + if (isCloudTab(activeTab)) { + chrome.browserAction.setIcon({ + path: "../icons/cloud-on.png", + }) + } else { + chrome.browserAction.setIcon({ + path: "../icons/cloud-off.png", + }) + } + + if ( + waitlisted || + cannotStreamError(activeTab) !== undefined || + isCloudTab(activeTab) || + !whistState.isLoggedIn + ) { + chrome.browserAction.setPopup({ popup: "../popup.html" }) + } else { + chrome.browserAction.setPopup({ popup: "" }) + } +}) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/socketio.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/socketio.ts new file mode 100644 index 00000000000..ce3b7d8c560 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/socketio.ts @@ -0,0 +1,133 @@ +import { Socket } from "socket.io-client" +import { merge } from "rxjs" +import { withLatestFrom, filter } from "rxjs/operators" +import find from "lodash.find" + +import { + socketStatus, + socketConnected, + socketDisconnected, +} from "@app/worker/events/socketio" +import { serverCookiesSynced } from "@app/worker/events/cookies" +import { + tabActivated, + tabRemoved, + tabUpdated, + tabFocused, + tabZoomed, +} from "@app/worker/events/tabs" +import { webuiNavigate, webuiRefresh } from "@app/worker/events/webui" +import { + getActiveTab, + isCloudTab, + markActiveCloudTab, + unmarkActiveCloudTab, + getTab, +} from "@app/worker/utils/tabs" +import { stateDidChange, whistState } from "@app/worker/utils/state" +import { getStorage } from "@app/worker/utils/storage" +import { Storage } from "@app/constants/storage" + +import { PopupMessage, PopupMessageType } from "@app/@types/messaging" + +merge( + serverCookiesSynced, + stateDidChange("waitingCloudTabs").pipe( + withLatestFrom(socketStatus), + filter( + ([change, connected]) => change?.applyData?.name === "push" && connected + ) + ) +) + .pipe(withLatestFrom(socketConnected)) + .subscribe(([, socket]: [any, Socket]) => { + while (whistState.waitingCloudTabs.length > 0) { + const tab = whistState.waitingCloudTabs.pop() + + if (tab !== undefined) { + socket.emit("activate-tab", tab, true) + markActiveCloudTab(tab) + } + + void getActiveTab().then((activeTab) => { + if (activeTab.id === tab?.id) { + chrome.runtime.sendMessage({ + type: PopupMessageType.SEND_POPUP_DATA, + value: { + isWaiting: false, + }, + }) + } + }) + } + }) + +// If a tab is activated, active it on the server +merge(tabActivated, tabFocused) + .pipe(withLatestFrom(serverCookiesSynced, socketConnected)) + .subscribe(([tab, _synced, socket]: [chrome.tabs.Tab, any, Socket]) => { + if (isCloudTab(tab)) { + socket.emit("activate-tab", tab, false) + } + }) + +// If a tab is removed, remove it on the server +tabRemoved + .pipe(withLatestFrom(socketConnected)) + .subscribe(([tabId, socket]: [number, Socket]) => { + const tab = find(whistState.activeCloudTabs, (t) => t.id === tabId) + if (tab !== undefined) { + socket.emit("close-tab", tab) + unmarkActiveCloudTab(tab) + } + }) + +// If a user navigates away from a cloud tab, remove it on the server +tabUpdated + .pipe(withLatestFrom(socketConnected)) + .subscribe(async ([tab, socket]: [chrome.tabs.Tab, Socket]) => { + const savedCloudUrls = await getStorage(Storage.SAVED_CLOUD_URLS) + const url = new URL(tab?.url?.replace("cloud:", "") ?? "") + const host = url.hostname + const isSaved = (savedCloudUrls ?? []).includes(host) + + if (!isCloudTab(tab) && !isSaved) { + socket.emit("close-tab", tab) + unmarkActiveCloudTab(tab) + } + }) + +tabZoomed + .pipe(withLatestFrom(socketConnected)) + .subscribe(([zoomChangeInfo, socket]: [object, Socket]) => { + socket.emit("zoom-tab", zoomChangeInfo) + }) + +webuiNavigate + .pipe(withLatestFrom(socketConnected)) + .subscribe(async ([message, socket]: [any, Socket]) => { + const tab = await getTab(message.id) + socket.emit("activate-tab", { ...tab, url: message.url }, true) + }) + +webuiRefresh + .pipe(withLatestFrom(socketConnected)) + .subscribe(([message, socket]: [any, Socket]) => { + socket.emit("refresh-tab", message) + }) + +socketDisconnected.subscribe((socket: Socket) => { + ;(chrome as any).whist.broadcastWhistMessage( + JSON.stringify({ + type: "SOCKET_DISCONNECTED", + }) + ) +}) + +socketConnected.subscribe((socket: Socket) => { + ;(chrome as any).whist.broadcastWhistMessage( + JSON.stringify({ + type: "SOCKET_CONNECTED", + }) + ) +}) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/tabs.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/tabs.ts new file mode 100644 index 00000000000..a97cf8fee4b --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/tabs.ts @@ -0,0 +1,160 @@ +import { merge } from "rxjs" +import find from "lodash.find" + +import { authSuccess } from "@app/worker/events/auth" +import { webuiOpenSupport } from "@app/worker/events/webui" +import { + tabActivated, + tabRemoved, + tabUpdated, + tabCreated, + tabFocused, + cloudTabCreated, + cloudTabUpdated, + cloudTabActivated, +} from "@app/worker/events/tabs" +import { whistState } from "@app/worker/utils/state" +import { + addTabToQueue, + isActiveCloudTab, + isCloudTab, + removeTabFromQueue, + unmarkActiveCloudTab, + stripCloudUrl, + updateTabUrl, + getTab, +} from "@app/worker/utils/tabs" +import { toBase64 } from "@app/worker/utils/encode" +import { cannotStreamError } from "@app/worker/utils/errors" +import { serializeProtocolArgs } from "@app/worker/utils/protocol" + +// On launch, add all previously opened cloud tabs to the cloud tab queue +authSuccess.subscribe(() => { + chrome.tabs.query({}, (tabs: chrome.tabs.Tab[]) => { + // Tech debt: Change this when server-side multiwindow is supported + // Currently, because the server only has one window, if there are restored + // cloud tabs spread across multiple windows, we have no way of sending the correct + // video frames to each restored tab since only one window can be visible at a time + // on the server. So, if we detect restored tabs across multiple windows, we + // revert them to local tabs as a temporary fix. + const cloudTabs = tabs.filter((tab) => tab.url?.startsWith("cloud:")) + const sameWindow = tabs.every((tab) => tab.windowId === tabs[0].windowId) + + if (!sameWindow) { + cloudTabs.forEach((tab) => { + if (tab.url !== undefined) updateTabUrl(tab.id, stripCloudUrl(tab.url)) + }) + } else { + cloudTabs.forEach((tab) => { + if (!isActiveCloudTab(tab)) addTabToQueue(tab) + }) + } + }) +}) + +// If a tab is created or updated and it's a cloud tab, add it to the queue +merge(tabCreated, tabUpdated).subscribe((tab: chrome.tabs.Tab) => { + if (isCloudTab(tab) && !isActiveCloudTab(tab)) addTabToQueue(tab) +}) + +// If a tab is activated or changed, update its info in the cloud tab queue +merge(tabActivated, tabUpdated, tabFocused).subscribe( + async (tab: chrome.tabs.Tab) => { + whistState.waitingCloudTabs = await Promise.all( + whistState.waitingCloudTabs.map(async (tab) => await getTab(tab.id)) + ) + + if (!isCloudTab(tab)) unmarkActiveCloudTab(tab) + } +) + +// If a tab is removed, remove it from the cloud tab queue +tabRemoved.subscribe((tabId: number) => { + const tab = find(whistState.waitingCloudTabs, (t) => t.id === tabId) + if (tab !== undefined) removeTabFromQueue(tab) +}) + +tabUpdated.subscribe((tab: chrome.tabs.Tab) => { + if (isCloudTab(tab) && whistState.mandelboxInfo !== undefined) { + const s = serializeProtocolArgs(whistState.mandelboxInfo) + + ;(chrome as any).whist.broadcastWhistMessage( + JSON.stringify({ + type: "MANDELBOX_INFO", + value: { + "server-ip": s.mandelboxIP, + p: s.mandelboxPorts, + k: s.mandelboxSecret, + }, + }) + ) + } +}) + +cloudTabUpdated.subscribe( + async ([tabId, _historyLength, tab]: [number, number, chrome.tabs.Tab]) => { + if (tabId === undefined || cannotStreamError(tab) !== undefined) return + + if (tab.favIconUrl !== undefined) { + tab.favIconUrl = await toBase64(tab.favIconUrl) + ;(chrome as any).whist.broadcastWhistMessage( + JSON.stringify({ + type: "UPDATE_TAB", + value: { + id: tabId, + favIconUrl: tab?.favIconUrl, + }, + }) + ) + } + } +) + +cloudTabUpdated.subscribe( + ([tabId, historyLength, tab]: [number, number, chrome.tabs.Tab]) => { + if (tabId === undefined || cannotStreamError(tab) !== undefined) return + ;(chrome as any).whist.broadcastWhistMessage( + JSON.stringify({ + type: "UPDATE_TAB", + value: { + id: tabId, + ...(tab.url !== undefined && { + url: `cloud:${stripCloudUrl(tab.url)}`, + }), + title: tab?.title, + historyLength, + }, + }) + ) + } +) + +cloudTabUpdated.subscribe( + ([tabId, _historyLength, tab]: [number, number, chrome.tabs.Tab]) => { + if (tab.url !== undefined && cannotStreamError(tab) !== undefined) { + updateTabUrl(tabId, stripCloudUrl(tab.url)) + } + } +) + +cloudTabCreated.subscribe((tabs: chrome.tabs.Tab[]) => { + const tab = tabs[0] + + if (tab.url !== undefined) + chrome.tabs.create({ url: tab.url, active: tab.active }) +}) + +webuiOpenSupport.subscribe(() => { + chrome.tabs.create({ url: chrome.runtime.getURL("intercom.html") }) +}) + +cloudTabActivated.subscribe(([tabId]: [number]) => { + ;(chrome as any).whist.broadcastWhistMessage( + JSON.stringify({ + type: "ACTIVATE_TAB", + value: { + id: tabId, + }, + }) + ) +}) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/webRequest.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/webRequest.ts new file mode 100644 index 00000000000..9862546b701 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/webRequest.ts @@ -0,0 +1,32 @@ +import { Storage } from "@app/constants/storage" + +import { webRequest } from "@app/worker/events/webRequest" +import { getStorage } from "@app/worker/utils/storage" +import { + getTab, + updateTabUrl, + unmarkActiveCloudTab, + stripCloudUrl, +} from "@app/worker/utils/tabs" + +/* eslint-disable @typescript-eslint/strict-boolean-expressions */ +webRequest.subscribe((response: any) => { + void Promise.all([ + getStorage(Storage.SAVED_CLOUD_URLS), + getTab(response.tabId), + ]).then((args: any) => { + const [savedCloudUrls, tab] = args + const url = new URL(response.url) + const host = url.hostname + const currentHost = new URL(stripCloudUrl(tab.url)).hostname + const isSaved = (savedCloudUrls ?? []).includes(host) + const isCloudUrl = response.url.startsWith("cloud:") + + if (!isSaved && !isCloudUrl) return + + if (!isCloudUrl && host !== currentHost) { + unmarkActiveCloudTab(tab) + updateTabUrl(tab.id, `cloud:${response.url as string}`) + } + }) +}) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/windows.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/windows.ts new file mode 100644 index 00000000000..492043118d2 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/effects/windows.ts @@ -0,0 +1,12 @@ +import { serverWindowCreated } from "@app/worker/events/windows" + +serverWindowCreated.subscribe( + ([window]: [chrome.windows.Window & { url: string }]) => { + chrome.windows.create({ + url: window.url, + incognito: window.incognito, + state: window.state, + type: window.type, + } as any) + } +) diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/auth.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/auth.ts new file mode 100644 index 00000000000..7e0b90a03a1 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/auth.ts @@ -0,0 +1,42 @@ +import { merge, from, timer, interval } from "rxjs" +import { filter, share, switchMap, take, throttle } from "rxjs/operators" + +import { webpageLoaded } from "@app/worker/events/webRequest" +import { activatedFromSleep } from "@app/worker/events/idle" +import { + authSuccess as _authSuccess, + authFailure as _authFailure, + authNetworkError as _authNetworkError, + initGoogleAuthHandler, + initWhistAuth, +} from "@app/worker/utils/auth" + +import { AuthInfo } from "@app/@types/payload" + +const SEC_MS = 1000 // Number of ms in a second +const DAY_MS = 86400 * SEC_MS // Number of ms in a day + +const authInfo = merge( + merge( + webpageLoaded.pipe(take(1)), + activatedFromSleep, + timer(0, DAY_MS / 2) + ).pipe( + // We throttle by 10s so there's no race condition of two simultaneous auth refresh requests + throttle(() => interval(SEC_MS * 10)), + switchMap(() => from(initWhistAuth())) + ), + from(initGoogleAuthHandler()) +).pipe(share()) + +const authSuccess = authInfo.pipe( + filter((auth: AuthInfo) => _authSuccess(auth)) +) +const authFailure = authInfo.pipe( + filter((auth: AuthInfo) => _authFailure(auth)) +) +const authNetworkError = authInfo.pipe( + filter((auth: AuthInfo) => _authNetworkError(auth)) +) + +export { authInfo, authSuccess, authFailure, authNetworkError } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/content.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/content.ts new file mode 100644 index 00000000000..aec2bff00df --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/content.ts @@ -0,0 +1,22 @@ +import { fromEventPattern } from "rxjs" +import { filter, share } from "rxjs/operators" + +const showUpdatePage = fromEventPattern( + (handler: any) => (chrome as any).runtime.onMessage.addListener(handler), + (handler: any) => (chrome as any).runtime.onMessage.removeListener(handler), + (message: any) => message +).pipe( + filter((message: any) => message.type === "SHOW_UPDATE_PAGE"), + share() +) + +const showLoginPage = fromEventPattern( + (handler: any) => (chrome as any).runtime.onMessage.addListener(handler), + (handler: any) => (chrome as any).runtime.onMessage.removeListener(handler), + (message: any) => message +).pipe( + filter((message: any) => message.type === "SHOW_LOGIN_PAGE"), + share() +) + +export { showUpdatePage, showLoginPage } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/cookies.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/cookies.ts new file mode 100644 index 00000000000..48f7749d305 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/cookies.ts @@ -0,0 +1,54 @@ +import { fromEventPattern, fromEvent } from "rxjs" +import { filter, map, switchMap } from "rxjs/operators" +import { Socket } from "socket.io-client" +import find from "lodash.find" +import isEqual from "lodash.isequal" + +import { socketConnected } from "@app/worker/events/socketio" +import { whistState } from "@app/worker/utils/state" + +const clientCookieAdded = fromEventPattern( + (handler: any) => chrome.cookies.onChanged.addListener(handler), + (handler: any) => chrome.cookies.onChanged.removeListener(handler), + (details: any) => details +).pipe( + filter( + ({ cause, removed }: { cause: string; removed: boolean }) => + !removed && cause === "explicit" + ), + filter( + ({ cookie }) => + find(whistState.alreadyAddedCookies, (c) => isEqual(c, cookie)) === + undefined + ), + map(({ cookie }) => cookie) +) + +// We want to ignore cookies that were removed by explicit calls to chrome.cookies.remove +// and removed because they were overwritten by a new cookie +const clientCookieRemoved = fromEventPattern( + (handler: any) => chrome.cookies.onChanged.addListener(handler), + (handler: any) => chrome.cookies.onChanged.removeListener(handler), + (details: any) => details +).pipe( + filter( + ({ cause, removed }: { cause: string; removed: boolean }) => + removed && ["expired", "expired_overwrite", "evicted"].includes(cause) + ), + map(({ cookie }) => cookie) +) + +const serverCookieAdded = socketConnected.pipe( + switchMap((s: Socket) => fromEvent(s, "client-add-cookie")) +) + +const serverCookiesSynced = socketConnected.pipe( + switchMap((s: Socket) => fromEvent(s, "cookie-sync-complete")) +) + +export { + clientCookieAdded, + clientCookieRemoved, + serverCookieAdded, + serverCookiesSynced, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/download.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/download.ts new file mode 100644 index 00000000000..3f6fd28381f --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/download.ts @@ -0,0 +1,11 @@ +import { fromEvent } from "rxjs" +import { switchMap } from "rxjs/operators" +import { Socket } from "socket.io-client" + +import { socketConnected } from "@app/worker/events/socketio" + +const downloadStarted = socketConnected.pipe( + switchMap((s: Socket) => fromEvent(s, "download-started")) +) + +export { downloadStarted } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/host.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/host.ts new file mode 100644 index 00000000000..404e508f23c --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/host.ts @@ -0,0 +1,109 @@ +import { from, of } from "rxjs" +import { + switchMap, + map, + filter, + share, + timeout, + catchError, +} from "rxjs/operators" + +import { getStorage } from "@app/worker/utils/storage" +import { hostSpinUp, hostSpinUpSuccess } from "@app/worker/utils/host" +import { + timeZone, + darkMode, + userAgent, + platform, + keyboardRepeatRate, + keyboardRepeatInitialDelay, +} from "@app/worker/utils/jsonTransport" +import { mandelboxSuccess } from "@app/worker/events/mandelbox" + +import { MandelboxInfo } from "@app/@types/payload" +import { Storage } from "@app/constants/storage" +import { AsyncReturnType } from "@app/@types/api" +import { generateRandomConfigToken } from "@app/@core-ts/auth" + +const jsonTransport = async () => { + const t = timeZone() + const u = userAgent() + + const [d, p, r, i] = await Promise.all([ + darkMode(), + platform(), + keyboardRepeatRate(), + keyboardRepeatInitialDelay(), + ]) + + return { + dark_mode: d, + desired_timezone: t, + user_agent: u, + client_os: p, + client_dpi: window.devicePixelRatio * 96, + key_repeat: r, + initial_key_repeat: i, + } +} + +const hostInfo = mandelboxSuccess.pipe( + switchMap((mandelbox: MandelboxInfo) => + from( + Promise.all([ + getStorage(Storage.AUTH_INFO), + getStorage(Storage.CONFIG_TOKEN_INFO), + new Promise((resolve) => resolve(mandelbox)), + jsonTransport(), + ]) + ) + ), + switchMap(([auth, _configTokenInfo, mandelbox, jsonData]) => + from( + hostSpinUp({ + ip: mandelbox.mandelboxIP ?? "", + config_encryption_token: generateRandomConfigToken(), + is_new_config_encryption_token: true, + jwt_access_token: auth.accessToken ?? "", + mandelbox_id: mandelbox.mandelboxID, + json_data: JSON.stringify({ + kiosk_mode: true, + restore_last_session: false, + load_extension: true, + ...jsonData, + }), + importedData: undefined, + }) + ).pipe( + timeout(10000), // If nothing is emitted for 10s, we assume a timeout so that an error can be shown + catchError(() => of({})) + ) + ), + share() +) + +const hostSuccess = hostInfo.pipe( + filter((response: AsyncReturnType) => + hostSpinUpSuccess(response) + ), + map((response: AsyncReturnType) => ({ + mandelboxSecret: response.json?.result?.aes_key, + mandelboxPorts: { + port_32261: response.json?.result?.port_32261, + port_32262: response.json?.result?.port_32262, + port_32263: response.json?.result?.port_32263, + port_32273: response.json?.result?.port_32273, + }, + })), + share() +) + +const hostError = hostInfo.pipe( + filter( + (response: AsyncReturnType) => + !hostSpinUpSuccess(response) + ), + share() +) + +export { hostSuccess, hostError } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/idle.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/idle.ts new file mode 100644 index 00000000000..d132364c3aa --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/idle.ts @@ -0,0 +1,10 @@ +import { fromEventPattern } from "rxjs" +import { filter } from "rxjs/operators" + +const activatedFromSleep = fromEventPattern( + (handler: any) => chrome.idle.onStateChanged.addListener(handler), + (handler: any) => chrome.idle.onStateChanged.removeListener(handler), + (newState: chrome.idle.IdleState) => newState +).pipe(filter((newState: chrome.idle.IdleState) => newState === "active")) + +export { activatedFromSleep } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/mandelbox.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/mandelbox.ts new file mode 100644 index 00000000000..c0e85e18016 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/mandelbox.ts @@ -0,0 +1,75 @@ +import { from, of } from "rxjs" +import { switchMap, map, filter, share } from "rxjs/operators" + +import { getStorage } from "@app/worker/utils/storage" +import { + mandelboxRequest, + mandelboxCreateSuccess, +} from "@app/worker/utils/mandelbox" +import { stateDidChange, whistState } from "@app/worker/utils/state" + +import { MandelboxState, Storage } from "@app/constants/storage" +import { config } from "@app/constants/app" +import { AsyncReturnType } from "@app/@types/api" +import { AWSRegion } from "@app/constants/location" + +const mandelboxNeeded = stateDidChange("waitingCloudTabs") + .pipe(filter((change: any) => change?.applyData?.name === "push")) + .pipe( + filter( + () => whistState.mandelboxState === MandelboxState.MANDELBOX_NONEXISTENT + ), + share() + ) + +const mandelboxInfo = mandelboxNeeded.pipe( + switchMap(() => + from( + Promise.all([ + getStorage(Storage.AUTH_INFO), + getStorage(Storage.CLOSEST_AWS_REGIONS), + ]) + ) + ), + switchMap(([auth, regions]) => + config.HOST_IP === undefined + ? from( + mandelboxRequest( + auth.accessToken ?? "", + regions.map((r: { region: AWSRegion }) => r.region), + auth.userEmail ?? "", + "1.0.0" + ) + ) + : of({ + status: 200, + json: { + ip: config.HOST_IP, + mandelbox_id: (crypto as any).randomUUID(), + }, + }) + ), + share() +) + +const mandelboxSuccess = mandelboxInfo.pipe( + filter( + (response: AsyncReturnType) => + mandelboxCreateSuccess(response) || config.HOST_IP !== undefined + ), + map((response: AsyncReturnType) => ({ + mandelboxIP: response.json.ip, + mandelboxID: response.json.mandelbox_id, + })), + share() +) + +const mandelboxError = mandelboxInfo.pipe( + filter( + (response: AsyncReturnType) => + !mandelboxCreateSuccess(response) + ) +) + +// TODO: Implement mandelbox failure events +export { mandelboxNeeded, mandelboxSuccess, mandelboxError } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/popup.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/popup.ts new file mode 100644 index 00000000000..40b22b4c5cb --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/popup.ts @@ -0,0 +1,81 @@ +import { fromEventPattern } from "rxjs" +import { filter, share } from "rxjs/operators" + +import { PopupMessageType } from "@app/@types/messaging" +import { NodeEventHandler } from "rxjs/internal/observable/fromEvent" + +const popupMessage = fromEventPattern( + (handler: NodeEventHandler) => { + const wrapper = (request: any, sender: any, sendResponse: any) => { + const event = { request, sender, sendResponse } + handler(event) + return true + } + chrome.runtime.onMessage.addListener(wrapper) + return wrapper + }, + (_handler: NodeEventHandler, wrapper: any) => + chrome.runtime.onMessage.removeListener(wrapper) +).pipe(share()) + +const popupToggled = popupMessage.pipe( + filter((event: any) => event.request.type === PopupMessageType.STREAM_TAB) +) + +const popupClicked = fromEventPattern( + (handler: any) => chrome.browserAction.onClicked.addListener(handler), + (handler: any) => chrome.browserAction.onClicked.removeListener(handler), + (details: any) => details +) + +const popupOpened = popupMessage.pipe( + filter( + (event: any) => event.request.type === PopupMessageType.FETCH_POPUP_DATA + ) +) + +/* eslint-disable @typescript-eslint/strict-boolean-expressions */ +const popupActivateCloudTab = popupToggled.pipe( + filter((event: any) => event.request.value.enabled) +) + +const popupDeactivateCloudTab = popupToggled.pipe( + filter((event: any) => !event.request.value.enabled) +) + +const popupUrlSaved = popupMessage.pipe( + filter((event: any) => event.request.type === PopupMessageType.SAVE_URL), + filter((event: any) => event.request.value.saved) +) + +/* eslint-disable @typescript-eslint/strict-boolean-expressions */ +const popupUrlUnsaved = popupMessage.pipe( + filter((event: any) => event.request.type === PopupMessageType.SAVE_URL), + filter((event: any) => !event.request.value.saved) +) + +const popupOpenLogin = popupMessage.pipe( + filter( + (event: any) => event.request.type === PopupMessageType.OPEN_LOGIN_PAGE + ) +) + +const popupOpenIntercom = popupMessage.pipe( + filter((event: any) => event.request.type === PopupMessageType.OPEN_INTERCOM) +) + +const popupInviteCode = popupMessage.pipe( + filter((event: any) => event.request.type === PopupMessageType.INVITE_CODE) +) + +export { + popupClicked, + popupActivateCloudTab, + popupDeactivateCloudTab, + popupOpened, + popupUrlSaved, + popupUrlUnsaved, + popupOpenLogin, + popupOpenIntercom, + popupInviteCode, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/socketio.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/socketio.ts new file mode 100644 index 00000000000..95692103af5 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/socketio.ts @@ -0,0 +1,62 @@ +import { zip, fromEvent, of, merge } from "rxjs" +import { + map, + switchMap, + filter, + share, + startWith, + withLatestFrom, + count, + take, +} from "rxjs/operators" + +import { mandelboxSuccess } from "@app/worker/events/mandelbox" +import { hostSuccess } from "@app/worker/events/host" +import { io, Socket } from "socket.io-client" +import { MandelboxInfo, HostInfo } from "@app/@types/payload" + +const socket = zip(mandelboxSuccess, hostSuccess).pipe( + map(([mandelbox, host]: [MandelboxInfo, HostInfo]) => + io(`http://${mandelbox.mandelboxIP}:${host.mandelboxPorts.port_32261}`, { + reconnectionDelayMax: 500, + transports: ["websocket"], + }) + ), + share() +) + +const socketConnected = socket.pipe( + switchMap((s: Socket) => + fromEvent(s, "connected").pipe( + filter((clientsConnected: number) => clientsConnected === 2), + withLatestFrom(of(s)) + ) + ), + map(([, s]: [any, Socket]) => s) +) + +const socketDisconnected = socket.pipe( + switchMap((s: Socket) => + fromEvent(s, "disconnect").pipe(withLatestFrom(of(s))) + ), + map(([, s]: [any, Socket]) => s) +) + +const socketReconnectFailed = merge(socket, socketConnected).pipe( + switchMap((s: Socket) => + fromEvent(s.io, "reconnect_error").pipe(take(15), count()) + ) +) + +const socketStatus = merge( + socketConnected.pipe(map(() => true)), + socketDisconnected.pipe(map(() => false)) +).pipe(startWith(false)) + +export { + socket, + socketConnected, + socketDisconnected, + socketStatus, + socketReconnectFailed, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/tabs.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/tabs.ts new file mode 100644 index 00000000000..6e94dd14048 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/tabs.ts @@ -0,0 +1,74 @@ +import { fromEvent, fromEventPattern, from } from "rxjs" +import { switchMap, share, filter } from "rxjs/operators" +import { Socket } from "socket.io-client" + +import { getTab, getActiveTab } from "@app/worker/utils/tabs" +import { socketConnected } from "@app/worker/events/socketio" + +// All tab observables should emit a chrome.tabs.Tab +const tabCreated = fromEventPattern( + (handler: any) => chrome.tabs.onCreated.addListener(handler), + (handler: any) => chrome.tabs.onCreated.removeListener(handler), + (tab: chrome.tabs.Tab) => tab +).pipe(share()) + +const tabActivated = fromEventPattern( + (handler: any) => chrome.tabs.onActivated.addListener(handler), + (handler: any) => chrome.tabs.onActivated.removeListener(handler), + (activeInfo: { tabId: number }) => activeInfo.tabId +).pipe( + switchMap((tabId: number) => from(getTab(tabId))), + share() +) + +const tabFocused = fromEventPattern( + (handler: any) => chrome.windows.onFocusChanged.addListener(handler), + (handler: any) => chrome.windows.onFocusChanged.removeListener(handler), + (windowId: number) => windowId +).pipe( + filter((windowId: number) => windowId > -1), + switchMap((windowId: number) => from(getActiveTab(windowId))), + share() +) + +const tabRemoved = fromEventPattern( + (handler: any) => chrome.tabs.onRemoved.addListener(handler), + (handler: any) => chrome.tabs.onRemoved.removeListener(handler), + (tabId: number, _removeInfo: object) => tabId +).pipe(share()) + +const tabUpdated = fromEventPattern( + (handler: any) => chrome.tabs.onUpdated.addListener(handler), + (handler: any) => chrome.tabs.onUpdated.removeListener(handler), + (_tabId: number, _changeInfo: object, tab: chrome.tabs.Tab) => tab +).pipe(share()) + +const tabZoomed = fromEventPattern( + (handler: any) => chrome.tabs.onZoomChange.addListener(handler), + (handler: any) => chrome.tabs.onZoomChange.removeListener(handler), + (zoomChangeInfo: object) => zoomChangeInfo +).pipe(share()) + +const cloudTabCreated = socketConnected + .pipe(switchMap((s: Socket) => fromEvent(s, "tab-created"))) + .pipe(share()) + +const cloudTabUpdated = socketConnected + .pipe(switchMap((s: Socket) => fromEvent(s, "tab-updated"))) + .pipe(share()) + +const cloudTabActivated = socketConnected + .pipe(switchMap((s: Socket) => fromEvent(s, "tab-activated"))) + .pipe(share()) + +export { + tabCreated, + tabActivated, + tabRemoved, + tabUpdated, + tabZoomed, + cloudTabCreated, + cloudTabUpdated, + cloudTabActivated, + tabFocused, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/webRequest.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/webRequest.ts new file mode 100644 index 00000000000..4b4feedfbee --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/webRequest.ts @@ -0,0 +1,22 @@ +import { fromEventPattern } from "rxjs" +import { filter } from "rxjs/operators" +import { NodeEventHandler } from "rxjs/internal/observable/fromEvent" + +const webRequest = fromEventPattern( + (handler: NodeEventHandler) => + chrome.webRequest.onBeforeRequest.addListener(handler, { + urls: ["*://*/*"], + types: ["main_frame"], + }), + (handler: NodeEventHandler) => + chrome.webRequest.onBeforeRequest.removeListener(handler), + (response: any) => response +) + +const webpageLoaded = fromEventPattern( + (handler: any) => chrome.webNavigation.onCompleted.addListener(handler), + (handler: any) => chrome.webNavigation.onCompleted.removeListener(handler), + (details: any) => details +).pipe(filter((details: any) => details.url.startsWith("http"))) + +export { webRequest, webpageLoaded } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/webui.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/webui.ts new file mode 100644 index 00000000000..3dfdd109dbb --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/webui.ts @@ -0,0 +1,46 @@ +import { fromEventPattern } from "rxjs" +import { filter, map, share } from "rxjs/operators" + +const webuiNavigate = fromEventPattern( + (handler: any) => (chrome as any).whist.onMessage.addListener(handler), + (handler: any) => (chrome as any).whist.onMessage.removeListener(handler), + (message: any) => message +).pipe( + map((message: string) => JSON.parse(message)), + filter((message: any) => message.type === "NAVIGATION"), + map((message: any) => message.value), + share() +) + +const webuiOpenSupport = fromEventPattern( + (handler: any) => (chrome as any).whist.onMessage.addListener(handler), + (handler: any) => (chrome as any).whist.onMessage.removeListener(handler), + (message: any) => message +).pipe( + map((message: string) => JSON.parse(message)), + filter((message: any) => message.type === "OPEN_SUPPORT"), + share() +) + +const webuiRefresh = fromEventPattern( + (handler: any) => (chrome as any).whist.onMessage.addListener(handler), + (handler: any) => (chrome as any).whist.onMessage.removeListener(handler), + (message: any) => message +).pipe( + map((message: string) => JSON.parse(message)), + filter((message: any) => message.type === "REFRESH"), + map((message: any) => message.value), + share() +) + +const webuiMandelboxNeeded = fromEventPattern( + (handler: any) => (chrome as any).whist.onMessage.addListener(handler), + (handler: any) => (chrome as any).whist.onMessage.removeListener(handler), + (message: any) => message +).pipe( + map((message: string) => JSON.parse(message)), + filter((message: any) => message.type === "MANDELBOX_NEEDED"), + share() +) + +export { webuiNavigate, webuiOpenSupport, webuiRefresh, webuiMandelboxNeeded } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/events/windows.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/windows.ts new file mode 100644 index 00000000000..a4d03ab9a38 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/events/windows.ts @@ -0,0 +1,11 @@ +import { fromEvent } from "rxjs" +import { switchMap } from "rxjs/operators" +import { Socket } from "socket.io-client" + +import { socketConnected } from "@app/worker/events/socketio" + +const serverWindowCreated = socketConnected.pipe( + switchMap((s: Socket) => fromEvent(s, "server-window-created")) +) + +export { serverWindowCreated } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/index.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/index.ts new file mode 100644 index 00000000000..f09cd64b33a --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/index.ts @@ -0,0 +1,13 @@ +import "./effects/auth" +import "./effects/content" +import "./effects/cookies" +import "./effects/download" +import "./effects/errors" +import "./effects/logging" +import "./effects/mandelbox" +import "./effects/ping" +import "./effects/popup" +import "./effects/socketio" +import "./effects/tabs" +import "./effects/webRequest" +import "./effects/windows" diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/auth.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/auth.ts new file mode 100644 index 00000000000..86b5df6f064 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/auth.ts @@ -0,0 +1,109 @@ +import has from "lodash.has" + +import { + parseAuthInfo, + requestAuthInfoRefresh, + authInfoCallbackRequest, + generateRandomConfigToken, +} from "@app/@core-ts/auth" +import { getStorage, setStorage } from "@app/worker/utils/storage" + +import { config } from "@app/constants/app" +import { Storage } from "@app/constants/storage" +import { AuthInfo, ConfigTokenInfo } from "@app/@types/payload" + +const initWhistAuth = async () => { + /* + Description: + Checks cached auth tokens, refreshes them, and prompts the user to re-authenticate + if necessary. + */ + + const cachedAuthInfo = await getStorage(Storage.AUTH_INFO) + const refreshResponse = await requestAuthInfoRefresh( + cachedAuthInfo?.refreshToken ?? "" + ) + const refreshedAuthInfo = { + ...parseAuthInfo(refreshResponse), + isFirstAuth: false, + } + + return refreshedAuthInfo +} + +const initGoogleAuthHandler = async () => { + /* + Description: + Opens the Google auth window when requested by the user + */ + const authPromise = new Promise((resolve) => { + chrome.webRequest.onBeforeRequest.addListener( + (details: { url: string }) => { + const callbackUrl = details.url + + void authInfoCallbackRequest(callbackUrl).then((response: any) => { + const authInfo = parseAuthInfo(response) + const refreshToken = response?.json.refresh_token + resolve({ + ...authInfo, + refreshToken, + isFirstAuth: true, + }) + }) + }, + { + urls: [`${config.AUTH0_REDIRECT_URL}*`], + }, + ["blocking"] + ) + }) + + return await authPromise +} + +const initConfigTokenHandler = async () => { + const configTokenInfo = await getStorage( + Storage.CONFIG_TOKEN_INFO + ) + + if (configTokenInfo?.token === undefined) { + void setStorage(Storage.CONFIG_TOKEN_INFO, { + token: generateRandomConfigToken(), + isNew: true, + }) + } else { + void setStorage(Storage.CONFIG_TOKEN_INFO, { + ...configTokenInfo, + isNew: false, + }) + } +} + +const authSuccess = (payload: AuthInfo) => { + return payload !== undefined && !has(payload, "error") +} + +const authNetworkError = (payload: AuthInfo) => { + return ( + payload !== undefined && + has(payload, "error") && + payload.error?.data?.status === 500 + ) +} + +const authFailure = (payload: AuthInfo) => { + return ( + payload !== undefined && + has(payload, "error") && + payload.error?.data?.status !== 500 + ) +} + +export { + initWhistAuth, + initGoogleAuthHandler, + initConfigTokenHandler, + authSuccess, + authNetworkError, + authFailure, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/encode.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/encode.ts new file mode 100644 index 00000000000..47e481caad9 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/encode.ts @@ -0,0 +1,19 @@ +const toBase64 = async (url: string) => { + const promise = new Promise((resolve) => { + const xhr = new XMLHttpRequest() + xhr.onload = () => { + const reader = new FileReader() + reader.onloadend = () => { + resolve(reader.result as any) + } + reader.readAsDataURL(xhr.response) + } + xhr.open("GET", url) + xhr.responseType = "blob" + xhr.send() + }) + + return await promise +} + +export { toBase64 } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/errors.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/errors.ts new file mode 100644 index 00000000000..ef04eb32684 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/errors.ts @@ -0,0 +1,42 @@ +import { PopupError } from "@app/constants/errors" +import { + videoChatUrls, + videoUrls, + unsupportedUrls, + whistUrls, +} from "@app/constants/urls" +import { isCloudTab, stripCloudUrl } from "@app/worker/utils/tabs" + +const isInvalidScheme = (url: URL) => + url.protocol !== "http:" && url.protocol !== "https:" +const isVideoChatUrl = (url: URL) => + videoChatUrls.some((el) => url.hostname.includes(el)) +const isVideoUrl = (url: URL) => + videoUrls.some((el) => url.hostname.includes(el)) +const isUnsupportedUrl = (url: URL) => + unsupportedUrls.some((el) => url.hostname.includes(el)) +const isWhistUrl = (url: URL) => + whistUrls.some((el) => url.hostname.includes(el)) + +const cannotStreamError = (tab: chrome.tabs.Tab | undefined) => { + if (tab === undefined || tab.id === undefined || tab.url === undefined) + return PopupError.IS_INVALID_URL + + if (isCloudTab(tab)) return undefined + + if (tab.incognito) return PopupError.IS_INCOGNITO + + if (!tab.url.startsWith("http")) return PopupError.IS_INVALID_SCHEME + + const url = new URL(stripCloudUrl(tab.url)) + + if (isInvalidScheme(url)) return PopupError.IS_INVALID_SCHEME + if (isVideoChatUrl(url)) return PopupError.IS_VIDEO_CHAT + if (isVideoUrl(url)) return PopupError.IS_VIDEO + if (isUnsupportedUrl(url)) return PopupError.IS_UNSUPPORTED_URL + if (isWhistUrl(url)) return PopupError.IS_WHIST_URL + + return undefined +} + +export { cannotStreamError } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/host.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/host.ts new file mode 100644 index 00000000000..ddb76fa6737 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/host.ts @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2021-2022 Whist Technologies, Inc. + * @file host.ts + * @brief This file contains utility functions for interacting with the host service. + */ + +import { put } from "@app/@core-ts/api" + +import { config } from "@app/constants/app" +import { AsyncReturnType } from "@app/@types/api" + +// This file directly interacts with data returned from the scaling service, which +// has keys labelled in snake_case format. We want to be able to pass +// these objects through to functions that validate and parse them. We also +// want to make use of argument destruction in functions. We also don't want +// to obfuscate the server's data format by converting everything to camelCase. +// So we choose to just ignore the linter rule. +/* eslint-disable @typescript-eslint/naming-convention */ +const hostSpinUp = async ({ + ip, + config_encryption_token, + is_new_config_encryption_token, + jwt_access_token, + mandelbox_id, + json_data, + importedData, +}: { + ip: string + config_encryption_token: string + is_new_config_encryption_token: boolean + jwt_access_token: string + mandelbox_id: string + json_data: string + importedData: + | { + cookies?: string + bookmarks?: string + extensions?: string + preferences?: string + localStorage?: string + } + | undefined +}) => { + return await put({ + body: { + config_encryption_token, + is_new_config_encryption_token: is_new_config_encryption_token ?? false, + mandelbox_id, + json_data, + ip, + }, + url: `${config.SCALING_SERVICE_URL as string}/json_transport`, + accessToken: jwt_access_token, + }) +} + +type HostSpinUpResponse = AsyncReturnType + +const hostSpinUpSuccess = (res: HostSpinUpResponse) => { + const result = res.json?.result + return ( + (result?.port_32262 !== undefined && + result?.port_32263 !== undefined && + result?.port_32273 !== undefined && + result?.aes_key !== undefined && + true) ?? + false + ) +} + +export { hostSpinUp, hostSpinUpSuccess } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/jsonTransport.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/jsonTransport.ts new file mode 100644 index 00000000000..a4723c19758 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/jsonTransport.ts @@ -0,0 +1,73 @@ +const timeZone = () => Intl.DateTimeFormat().resolvedOptions().timeZone + +const darkMode = async () => { + const theme = new Promise((resolve) => { + ;(chrome as any).braveTheme.getBraveThemeType((themeType: string) => { + resolve(themeType === "Dark") + }) + }) + + return await theme +} + +const userAgent = () => navigator.userAgent + +const platform = async () => { + const info = new Promise((resolve) => { + chrome.runtime.getPlatformInfo((platformInfo) => { + switch (platformInfo.os) { + case "mac": + resolve("darwin") + break + case "win": + resolve("win32") + break + default: + resolve("linux") + break + } + }) + }) + + return await info +} + +// See https://github.com/whisthq/whist/blob/81c6c4430ea661b757a8079d86018bb1a66dca87/frontend/client-applications/src/main/utils/keyRepeat.ts +// for explanations of these magic numbers +const keyboardRepeatRate = async () => { + const os = await platform() + switch (os) { + case "darwin": + return await new Promise((resolve) => + (chrome as any).whist.getKeyboardRepeatRate((rate: number) => { + resolve(Math.round((1.0 - (rate - 2) / 128) * 29 + 1)) + }) + ) + default: + return 40 // 40 is the fastest repeat rate on Linux + } +} + +const keyboardRepeatInitialDelay = async () => { + const os = await platform() + + switch (os) { + case "darwin": + return await new Promise((resolve) => + (chrome as any).whist.getKeyboardRepeatInitialDelay((delay: number) => { + resolve(Math.round((1000 / 60) * 1.2 * delay)) + }) + ) + default: + return 27 // 27 is the lowest delay on Linux + } +} + +export { + timeZone, + darkMode, + userAgent, + platform, + keyboardRepeatRate, + keyboardRepeatInitialDelay, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/location.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/location.ts new file mode 100644 index 00000000000..1fbe6bfe70f --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/location.ts @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2021-2022 Whist Technologies, Inc. + * @file location.ts + * @brief This file contains utility functions for finding the closest AWS region. + */ + +import sortBy from "lodash.sortby" + +import { AWSRegion, regions, timezones } from "@app/constants/location" + +const whistPingTime = async (host: string, numberPings: number) => { + /* + Description: + Measures the average ping time (in ms) to ping a host (IP address or URL) + + Arguments: + url (string): IP address or URL + numberPings (number): Number of times to ping the host + Returns: + (number): Average ping time to ping host (in ms) + */ + + // Create list of Promises, where each Promise resolves to a ping time + const pingResults = [] as number[] + for (let i = 0; i < numberPings; i += 1) { + try { + const start = Date.now() + await fetch(host) + pingResults.push(Date.now() - start) + } catch (err: any) { + throw new Error(err) + } + } + + // Resolve list of Promises synchronously to get a list of ping outputs + if (pingResults.length > 0) + return pingResults.reduce((a, b) => Math.min(a, b)) + return undefined +} + +const pingLoop = (regions: AWSRegion[]) => { + // Ping each region and find the closest region by lowest ping time + const pingResultPromises = [] + /* eslint-disable no-await-in-loop */ + for (let i = 0; i < regions.length; i += 1) { + const region = regions[i] + + pingResultPromises.push( + whistPingTime(`http://ec2.${region}.amazonaws.com/ping`, 6).then( + (pingTime) => { + return { region, pingTime } + } + ) + ) + } + return pingResultPromises +} + +const getSortedAWSRegions = async (regions: AWSRegion[]) => { + /* + Description: + Pulls AWS regions from SQL and pings each region, and sorts regions + by shortest ping time + + Arguments: + (AWSRegion[]): Unsorted array of regions + Returns: + (AWSRegion[]): Sorted array of regions + */ + + try { + const pingResults = await Promise.all(pingLoop(regions)) + return sortBy(pingResults, ["pingTime"]) + } catch (err: any) { + throw new Error(err) + } +} + +const getCountry = () => { + const timezone = + Intl.DateTimeFormat()?.resolvedOptions()?.timeZone ?? undefined + + if (timezone === undefined) return undefined + + return timezones[timezone]?.c?.[0] ?? undefined +} + +const initAWSRegionPing = async () => { + const country = getCountry() + const nonUSRegionsAllowed = country !== "US" + + try { + const sortedRegions = await getSortedAWSRegions( + regions + .filter( + (region) => + region.enabled && + (nonUSRegionsAllowed ? true : region.country === "US") + ) + .map((region) => region.name) + ) + return sortedRegions + } catch (err: any) { + throw new Error(err) + } +} + +export { initAWSRegionPing } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/mandelbox.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/mandelbox.ts new file mode 100644 index 00000000000..d5498c1946f --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/mandelbox.ts @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2021-2022 Whist Technologies, Inc. + * @file mandelbox.ts + * @brief This file contains utility functions interacting with the scaling service to create mandelboxes. + */ + +import { post } from "@app/@core-ts/api" +import { AWSRegion } from "@app/constants/location" +import { config, sessionID } from "@app/constants/app" +import { AsyncReturnType } from "@app/@types/api" + +const COMMIT_SHA = config.COMMIT_SHA + +const mandelboxCreateSuccess = ( + response: AsyncReturnType +) => [200, 202].includes(response.status) + +const mandelboxCreateErrorNoAccess = ( + response: AsyncReturnType +) => response.status === 402 + +const mandelboxCreateErrorUnauthorized = ( + response: AsyncReturnType +) => response.status === 422 || response.status === 401 + +const mandelboxCreateErrorMaintenance = ( + response: AsyncReturnType +) => response.status === 512 + +const mandelboxCreateErrorUnavailable = ( + response: AsyncReturnType +) => response.status === 503 && response.json.error === "NO_INSTANCE_AVAILABLE" + +const mandelboxCreateErrorCommitHash = ( + response: AsyncReturnType +) => response.status === 503 && response.json.error === "COMMIT_HASH_MISMATCH" + +const mandelboxRequest = async ( + accessToken: string, + regions: AWSRegion[], + userEmail: string, + whistVersion: string +) => + await post({ + body: { + regions, + client_commit_hash: COMMIT_SHA, + session_id: sessionID, + user_email: userEmail, + whistVersion, + }, + url: `${config.SCALING_SERVICE_URL}/mandelbox/assign`, + accessToken, + }) + +export { + mandelboxRequest, + mandelboxCreateSuccess, + mandelboxCreateErrorNoAccess, + mandelboxCreateErrorUnauthorized, + mandelboxCreateErrorMaintenance, + mandelboxCreateErrorUnavailable, + mandelboxCreateErrorCommitHash, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/observables.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/observables.ts new file mode 100644 index 00000000000..67feae50db1 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/observables.ts @@ -0,0 +1,9 @@ +import { map, withLatestFrom } from "rxjs/operators" + +const waitFor = (obs: any, waitFor: any) => + obs.pipe( + withLatestFrom(waitFor), + map(([obs]) => obs) + ) + +export { waitFor } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/protocol.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/protocol.ts new file mode 100644 index 00000000000..f8f7a4727bc --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/protocol.ts @@ -0,0 +1,15 @@ +import { HostInfo, MandelboxInfo } from "@app/@types/payload" + +const serializePorts = (ps: { + port_32262: number + port_32263: number + port_32273: number +}) => `32262:${ps?.port_32262}.32263:${ps?.port_32263}.32273:${ps?.port_32273}` + +const serializeProtocolArgs = (info: HostInfo & MandelboxInfo) => ({ + mandelboxIP: info.mandelboxIP, + mandelboxPorts: serializePorts(info.mandelboxPorts), + mandelboxSecret: info.mandelboxSecret, +}) + +export { serializeProtocolArgs } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/state.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/state.ts new file mode 100644 index 00000000000..e5833d7779f --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/state.ts @@ -0,0 +1,45 @@ +import { ReplaySubject } from "rxjs" +import { share, filter } from "rxjs/operators" + +import { MandelboxState } from "@app/constants/storage" +import onChange from "on-change" +import { MandelboxInfo, HostInfo } from "@app/@types/payload" + +const _stateDidChange = new ReplaySubject() + +const _whistState = { + isLoggedIn: false, + waitingCloudTabs: [] as chrome.tabs.Tab[], + activeCloudTabs: [] as chrome.tabs.Tab[], + mandelboxState: MandelboxState.MANDELBOX_NONEXISTENT as MandelboxState, + mandelboxInfo: undefined as (HostInfo & MandelboxInfo) | undefined, + alreadyAddedCookies: [] as chrome.cookies.Cookie[], +} + +const whistState = onChange( + _whistState, + ( + path: string, + value: any, + previousValue: any, + applyData: { + name: string + args: any[] + } + ) => { + _stateDidChange.next({ + path, + value, + previousValue, + applyData, + }) + } +) + +const stateDidChange = (state: string) => + _stateDidChange.pipe( + filter(({ path }) => path === state), + share() + ) + +export { whistState, stateDidChange } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/storage.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/storage.ts new file mode 100644 index 00000000000..3f6eb374402 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/storage.ts @@ -0,0 +1,46 @@ +import { fromEventPattern, ReplaySubject } from "rxjs" +import { map, filter, share } from "rxjs/operators" + +import { Storage } from "@app/constants/storage" + +const setStorage = async (key: string, value: any) => { + return await new Promise((resolve) => { + chrome.storage.local.set({ [key]: value }, () => { + resolve() + }) + }) +} + +const getStorage = async (key: string) => { + const promise: Promise = new Promise((resolve) => { + chrome.storage.local.get([key], (result) => { + resolve(result[key]) + }) + }) + + return await promise +} + +const storageSubject = new ReplaySubject() + +const storageChanged = fromEventPattern( + (handler: any) => chrome.storage.onChanged.addListener(handler), + (handler: any) => chrome.storage.onChanged.removeListener(handler), + (changes: object, _areaName: string) => changes +).pipe(share()) + +storageChanged.subscribe((changes: object) => storageSubject.next(changes)) + +const storageDidChange = (key: Storage) => + storageSubject.pipe( + filter((changes: Record) => changes[key] !== undefined), + map((changes: Record) => { + const oldValue = changes[key].oldValue + const newValue = changes[key].newValue + + return { oldValue, newValue } + }), + share() + ) + +export { getStorage, setStorage, storageDidChange } diff --git a/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/tabs.ts b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/tabs.ts new file mode 100644 index 00000000000..bfb6bc2e292 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/src/worker/utils/tabs.ts @@ -0,0 +1,105 @@ +import find from "lodash.find" +import remove from "lodash.remove" + +import { whistState } from "@app/worker/utils/state" + +const getActiveTab = async (windowId?: number): Promise => { + const tabPromise = new Promise((resolve) => { + chrome.tabs.query( + { + active: true, + ...(windowId !== undefined ? { windowId } : { currentWindow: true }), + }, + (tabs) => { + resolve(tabs[0]) + } + ) + }) + + return await tabPromise +} + +const getTab = async (tabId?: number): Promise => { + if (tabId === undefined) + throw new Error(`Could not get tab with undefined ID`) + + return await new Promise((resolve) => { + chrome.tabs.get(tabId, (tab) => resolve(tab)) + }) +} + +const updateTabUrl = (tabId?: number, url?: string, callback?: () => void) => { + if (tabId === undefined) + throw new Error(`Could not update tab because ID is undefined`) + if (url === undefined) + throw new Error(`Could not update tab ${tabId} because URL is undefined`) + + return callback === undefined + ? chrome.tabs.update(tabId, { url }) + : chrome.tabs.update(tabId, { url }, callback) +} + +const queryTabs = async (queryInfo: object): Promise => { + return await new Promise((resolve) => { + chrome.tabs.query(queryInfo, (tabs) => resolve(tabs)) + }) +} + +const isCloudTab = (tab?: chrome.tabs.Tab) => + tab?.url?.startsWith("cloud:") ?? false + +const isActiveCloudTab = (tab: chrome.tabs.Tab) => { + const exists = find(whistState.activeCloudTabs, (el) => el.id === tab.id) + return exists !== undefined +} + +const stripCloudUrl = (url: string) => url.replace("cloud:", "") + +const getNumberOfCloudTabs = async () => { + const tabPromise = new Promise((resolve) => { + chrome.tabs.query({ url: "cloud:*" }, (tabs) => { + resolve(tabs.length) + }) + }) + + return await tabPromise +} + +const convertToCloudTab = (tab: chrome.tabs.Tab) => { + if (!isCloudTab(tab) && tab.url !== undefined) + updateTabUrl(tab.id, `cloud:${tab.url}`) +} + +const addTabToQueue = (tab: chrome.tabs.Tab) => { + const exists = find(whistState.waitingCloudTabs, (el) => el.id === tab.id) + if (exists === undefined) whistState.waitingCloudTabs.push(tab) +} + +const removeTabFromQueue = (tab: chrome.tabs.Tab) => { + remove(whistState.waitingCloudTabs, { id: tab.id }) +} + +const markActiveCloudTab = (tab: chrome.tabs.Tab) => { + const exists = find(whistState.activeCloudTabs, (el) => el.id === tab.id) + if (exists === undefined) whistState.activeCloudTabs.push(tab) +} + +const unmarkActiveCloudTab = (tab: chrome.tabs.Tab) => { + remove(whistState.activeCloudTabs, { id: tab.id }) +} + +export { + getActiveTab, + getTab, + updateTabUrl, + queryTabs, + isCloudTab, + isActiveCloudTab, + stripCloudUrl, + getNumberOfCloudTabs, + addTabToQueue, + removeTabFromQueue, + convertToCloudTab, + markActiveCloudTab, + unmarkActiveCloudTab, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/tailwind.config.js b/browser/hybrid/components/cloud_tabs_extension/tailwind.config.js new file mode 100644 index 00000000000..0ea63fa75d2 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/tailwind.config.js @@ -0,0 +1,25 @@ +module.exports = { + // This "content" list should reference any files that call our .css files by + // name. This includes html, and any js files that 'import' css. + // This will allow tailwind to analyze and "purge" unused css. + content: ["./src/**/*.{js,jsx,ts,tsx}", "./src/tabs/index.html"], + darkMode: "class", + // The theme section is where we define anything related to visual design. + theme: { + // The extend sections lets us add extra "variants" to utilities. We also + // override some of the default utilities. + extend: { + colors: { + blue: { + DEFAULT: "#0092FF", + light: "#71D9FF", + dark: "#0000CE", + }, + gray: { + 800: "#313341", + 900: "#1e2029" + } + }, + }, + }, +} diff --git a/browser/hybrid/components/cloud_tabs_extension/tsconfig.json b/browser/hybrid/components/cloud_tabs_extension/tsconfig.json new file mode 100644 index 00000000000..f24118d2ef3 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "strict": true, + "module": "commonjs", + "target": "es6", + "esModuleInterop": true, + "jsx": "react", + "paths": { + "@app/*": ["./src/*"] + } + } +} diff --git a/browser/hybrid/components/cloud_tabs_extension/webpack.config.js b/browser/hybrid/components/cloud_tabs_extension/webpack.config.js new file mode 100644 index 00000000000..a0b6fefe675 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_extension/webpack.config.js @@ -0,0 +1,74 @@ +const path = require("path") +const CopyPlugin = require("copy-webpack-plugin") +const { ProvidePlugin } = require("webpack") + +module.exports = (env) => { + const srcDir = path.join(__dirname, "src") + const config = { + entry: { + worker: path.join(srcDir, "worker", "index.ts"), + content: path.join(srcDir, "content", "index.ts"), + popup: path.join(srcDir, "popup", "index.tsx"), + tab: path.join(srcDir, "tab", "index.tsx"), + }, + output: { + path: env.targetDir ?? path.resolve("build"), + filename: "[name].js", + }, + module: { + rules: [ + { + test: /\.tsx?$/, + use: "ts-loader", + }, + { + test: /\.css$/i, + use: ["style-loader", "css-loader"], + }, + { + test: /\.(png|jpe?g|gif)$/i, + loader: "file-loader", + options: { + name: "[name].[ext]", + outputPath: "assets", + publicPath: "../assets", + }, + }, + ], + }, + resolve: { + extensions: [".ts", ".tsx", ".js"], + fallback: { + path: require.resolve("path-browserify"), + http: require.resolve("stream-http"), + https: require.resolve("https-browserify"), + }, + alias: { + "@app": srcDir, + }, + }, + plugins: [ + new CopyPlugin({ + patterns: [{ from: "public" }], + }), + new ProvidePlugin({ + process: "process/browser", + }), + ], + externals: { + modules: [path.join(srcDir, "node_modules")], + }, + performance: { + hints: false, + maxEntrypointSize: 512000, + maxAssetSize: 512000, + }, + } + + config.mode = env.webpackMode ?? "production" + if (env.webpackMode === "development") { + config.devtool = "inline-source-map" + } + + return config +} diff --git a/browser/hybrid/components/cloud_tabs_ui/BUILD.gn b/browser/hybrid/components/cloud_tabs_ui/BUILD.gn new file mode 100644 index 00000000000..61bc8829cd0 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/BUILD.gn @@ -0,0 +1,17 @@ +import("//brave/components/common/typescript.gni") + +transpile_web_ui("cloud_tabs_ui") { + entry_points = [ [ + "cloud_tabs_ui", + rebase_path("src/index.ts"), + ] ] + + resource_name = "cloud_tabs_ui" +} + +pack_web_resources("generated_resources") { + resource_name = "cloud_tabs_ui" + output_dir = + "$root_gen_dir/whist/browser/hybrid/components/cloud_tabs_ui/resources" + deps = [ ":cloud_tabs_ui" ] +} diff --git a/browser/hybrid/components/cloud_tabs_ui/cloud_tabs_ui.html b/browser/hybrid/components/cloud_tabs_ui/cloud_tabs_ui.html new file mode 100644 index 00000000000..f98b050d298 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/cloud_tabs_ui.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/browser/hybrid/components/cloud_tabs_ui/css/whist_cloud.css.unused b/browser/hybrid/components/cloud_tabs_ui/css/whist_cloud.css.unused new file mode 100644 index 00000000000..3386c3be7f9 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/css/whist_cloud.css.unused @@ -0,0 +1,103 @@ +body { + overscroll-behavior-x: none; + overscroll-behavior-y: none; +} + +.background { + background-color: #f3f3f3; +} + +.fullScreen { + position: absolute; + top: 0%; + left: 0%; + width: 100vw; + height: 100vh; + outline: none !important; + border: none !important; + z-index: 2; +} + +.spinner { + stroke: rgba(0,0,0,0.3); + stroke-width: 8; + stroke-linecap: round; + animation: dash 1.5s ease-in-out infinite; +} + +.spinner-dark { + stroke: rgba(0,0,0,0.3); +} + +.notification { + animation: fadeIn 1.5s; + animation-duration: 1.5s; + animation-fill-mode: both; + opacity: 0; + font-family: BlinkMacSystemFont, Helvetica, Arial; + z-index: 3; + padding: 15px 20px; + position: fixed; + top: 10px; + right: 10px; + border-radius: 5px; + background: rgba(220, 252, 231, 0.9); + color: #22c55e; + display: flex; + align-items: center; + backdrop-filter: blur(5px); + font-size: 14px; + font-weight: 500; + box-shadow: 0 25px 50px -12px rgb(0 0 0 / 25%); +} + +@media (prefers-color-scheme: dark) { + .background { + background-color: #35363a; + } + .spinner-dark { + stroke: rgba(255,255,255,0.2); + } + +} + +@keyframes rotate { + 100% { + transform: rotate(360deg); + } +} + +@keyframes dash { + 0% { + stroke-dasharray: 1, 150; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -35; + } + 100% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -124; + } +} + +@keyframes pulse { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + +@keyframes fadeIn { + 0% { opacity: 0; } + 100% { opacity: 1; } +} + +@keyframes fadeOut { + 0% {opacity: 1;} + 100% {opacity: 0;} +} diff --git a/browser/hybrid/components/cloud_tabs_ui/resources.grd b/browser/hybrid/components/cloud_tabs_ui/resources.grd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/browser/hybrid/components/cloud_tabs_ui/src/controls/history.ts b/browser/hybrid/components/cloud_tabs_ui/src/controls/history.ts new file mode 100644 index 00000000000..8544bb65f22 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/src/controls/history.ts @@ -0,0 +1,78 @@ +import { getTabId } from "./session" + +let currentHistoryIndex = 0 + +const initializePopStateHandler = () => { + window.addEventListener("popstate", () => { + ;(chrome as any).whist.broadcastWhistMessage( + JSON.stringify({ + type: "NAVIGATION", + value: { + id: getTabId(), + url: document.URL, + }, + }) + ) + + currentHistoryIndex = window.history.state.index + }) +} + +const initializeURLUpdater = () => { + let webuiJustOpened = true + let serverHistoryLength = 0 + let maxHistoryIndex = 0 + + ;(chrome as any).whist.onMessage.addListener((message: string) => { + const parsed = JSON.parse(message) + + // If it's not a tab update, ignore + if (parsed.type !== "UPDATE_TAB") return + // If there's no URL change, ignore + if (parsed?.value?.url === undefined) return + // If it's for a different cloud tab, ignore + if (parsed?.value?.id !== getTabId()) return + + // If the web UI was just opened, we know we're at history index 0 so we set the history state accordingly + if (webuiJustOpened) { + webuiJustOpened = false + window.history.replaceState( + { index: 0, urls: [parsed.value.url] }, + "", + parsed.value.url + ) + // History replaceStates can only happen if we're at the end of history. So we check to see if we're the end of + // server history; if we are and the URL is changing but the server-side history length is the same, + // then the server must be doing a replaceState. We store the new replaced URL in window.history.state. + } else if ( + parsed.value.historyLength === serverHistoryLength && + maxHistoryIndex === currentHistoryIndex && + parsed.value.url !== document.URL + ) { + window.history.replaceState( + { + index: window.history.state.index, + urls: [...(window.history.state.urls ?? []), parsed.value.url], + }, + "", + document.URL + ) + // If the new URL is not in our list of previous URLs at this history index, then the server must be doing a pushState + } else if ( + document.URL !== parsed.value.url && + !window.history.state.urls.includes(parsed.value.url) + ) { + window.history.pushState( + { index: currentHistoryIndex + 1, urls: [parsed.value.url] }, + "", + parsed.value.url + ) + maxHistoryIndex = currentHistoryIndex + 1 + currentHistoryIndex = maxHistoryIndex + } + + serverHistoryLength = parsed.value.historyLength + }) +} + +export { initializeURLUpdater, initializePopStateHandler } diff --git a/browser/hybrid/components/cloud_tabs_ui/src/controls/refresh.ts b/browser/hybrid/components/cloud_tabs_ui/src/controls/refresh.ts new file mode 100644 index 00000000000..a744218505f --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/src/controls/refresh.ts @@ -0,0 +1,22 @@ +const initializePageRefreshHandler = () => { + const refresh = + (window.performance.navigation && + window.performance.navigation.type === 1) || + window.performance + .getEntriesByType("navigation") + .map((nav: any) => nav.type) + .includes("reload") + + if (refresh) { + ;(chrome as any).whist.broadcastWhistMessage( + JSON.stringify({ + type: "REFRESH", + value: { + id: sessionStorage.getNumber("tabId"), + }, + }) + ) + } +} + +export { initializePageRefreshHandler } diff --git a/browser/hybrid/components/cloud_tabs_ui/src/controls/session.ts b/browser/hybrid/components/cloud_tabs_ui/src/controls/session.ts new file mode 100644 index 00000000000..ee137520a10 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/src/controls/session.ts @@ -0,0 +1,23 @@ +const initializeSessionStorage = () => { + Storage.prototype.setObj = (key: string, obj: object) => { + return sessionStorage.setItem(key, JSON.stringify(obj)) + } + + Storage.prototype.getObj = (key: string) => { + const value = sessionStorage.getItem(key) + return value === null ? value : JSON.parse(value) + } + + Storage.prototype.setNumber = (key: string, value: number) => { + return sessionStorage.setItem(key, value.toString()) + } + + Storage.prototype.getNumber = (key: string): number | null => { + const value = sessionStorage.getItem(key) + return value === null ? value : Number(value) + } +} + +const getTabId = () => sessionStorage.getNumber("tabId") + +export { initializeSessionStorage, getTabId } diff --git a/browser/hybrid/components/cloud_tabs_ui/src/controls/tab.ts b/browser/hybrid/components/cloud_tabs_ui/src/controls/tab.ts new file mode 100644 index 00000000000..a8f6ecb90f0 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/src/controls/tab.ts @@ -0,0 +1,54 @@ +import { getTabId } from "./session" + +const initializeGetTabId = () => { + const promise = new Promise((resolve) => { + chrome.tabs.getCurrent((tab) => { + if (tab?.id !== undefined) sessionStorage.setNumber("tabId", tab.id) + if (tab?.windowId !== undefined) sessionStorage.setNumber("windowId", tab.windowId) + resolve() + }) + }) + + return promise +} + +const initializeFaviconUpdater = () => { + ;(chrome as any).whist.onMessage.addListener((message: string) => { + const parsed = JSON.parse(message) + + if (parsed.type !== "UPDATE_TAB") return + if (parsed?.value?.favIconUrl === undefined) return + if (parsed?.value?.id !== getTabId()) return + + if (parsed?.value?.favIconUrl !== undefined) { + let link: any = document.querySelector("link[rel~='icon']") + if (!link) { + link = document.createElement("link") + link.rel = "icon" + document.getElementsByTagName("head")[0].appendChild(link) + } + link.href = parsed.value.favIconUrl + } + }) +} + +const initializeTitleUpdater = () => { + // Set the initial title + const domain = new URL(document.URL.replace("cloud:", ""))?.hostname + ?.replace("www.", "") + ?.split(".")[0] + document.title = domain.charAt(0).toUpperCase() + domain.slice(1) + + // Update the title + ;(chrome as any).whist.onMessage.addListener((message: string) => { + const parsed = JSON.parse(message) + + if (parsed.type !== "UPDATE_TAB") return + if (parsed?.value?.title === undefined) return + if (parsed?.value?.id !== getTabId()) return + + document.title = parsed.value.title + }) +} + +export { initializeGetTabId, initializeFaviconUpdater, initializeTitleUpdater } diff --git a/browser/hybrid/components/cloud_tabs_ui/src/controls/whist.ts b/browser/hybrid/components/cloud_tabs_ui/src/controls/whist.ts new file mode 100644 index 00000000000..c6eebf40a37 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/src/controls/whist.ts @@ -0,0 +1,101 @@ +import { getTabId } from "./session" +import { state } from "../shared/state" + +let whistParameters: string | null = null + +const initializeWhistTagHandler = () => { + ;(chrome as any).whist.onMessage.addListener((message: string) => { + const parsed = JSON.parse(message) + + if (parsed.type === "MANDELBOX_INFO") { + // Keep the whist element in-focus + whistParameters = JSON.stringify(parsed.value) + } + }) +} + +const initializeRequestMandelbox = () => { + const whistTag: any = document.querySelector("whist") + let mandelboxRequested = false + + setInterval(() => { + if ( + !whistTag.isWhistConnected() && + !mandelboxRequested && + state.wasConnected + ) { + mandelboxRequested = true + ;(chrome as any).whist.broadcastWhistMessage( + JSON.stringify({ + type: "MANDELBOX_NEEDED", + }) + ) + } + + if(!whistTag.isWhistConnected()) { + state.wasConnected = false + } + + if (whistTag.isWhistConnected()) { + state.wasConnected = true + mandelboxRequested = false + } + }, 100) +} + +const initializeWhistFreezeHandler = () => { + const whistTag: any = document.querySelector("whist") + + chrome.windows.onFocusChanged.addListener((windowId: number) => { + if (windowId < 0 || windowId !== sessionStorage.getNumber("windowId")) { + whistTag.freeze() + } else { + chrome.tabs.query( + { + active: true, + windowId, + }, + (tabs) => { + const tabId = tabs[0]?.id + if (tabId !== sessionStorage.getNumber("tabId")) whistTag.freeze() + } + ) + } + }) + + chrome.tabs.onActivated.addListener((activeInfo: { tabId: number }) => { + if (activeInfo.tabId !== sessionStorage.getNumber("tabId")) + whistTag.freeze() + }) +} + +const initializeWhistThawHandler = () => { + const whistTag: any = document.querySelector("whist") + + ;(chrome as any).whist.onMessage.addListener((message: string) => { + const parsed = JSON.parse(message) + + if ( + (parsed.type === "ACTIVATE_TAB" || parsed.type === "UPDATE_TAB") && + parsed.value.id === getTabId() + ) { + if (whistParameters !== null && !whistTag.isWhistConnected()) { + whistTag.focus() + whistTag.whistConnect(whistParameters) + } + // We delay by 100ms because this is the amount of time we expect the protocol to lag behind + // the socket.io message, since the protocol has extra video encode/decode latency. + // Lower values were tested and they led to flashes of other tabs being seen. + setTimeout(() => { + whistTag.thaw() + }, 100) + } + }) +} + +export { + initializeWhistTagHandler, + initializeWhistFreezeHandler, + initializeWhistThawHandler, + initializeRequestMandelbox +} diff --git a/browser/hybrid/components/cloud_tabs_ui/src/index.ts b/browser/hybrid/components/cloud_tabs_ui/src/index.ts new file mode 100644 index 00000000000..ba3be20229a --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/src/index.ts @@ -0,0 +1,40 @@ +import { initializeSessionStorage } from "./controls/session" +import { + initializeGetTabId, + initializeFaviconUpdater, + initializeTitleUpdater, +} from "./controls/tab" +import { + initializeURLUpdater, + initializePopStateHandler, +} from "./controls/history" +import { + initializeWhistTagHandler, + initializeWhistFreezeHandler, + initializeWhistThawHandler, + initializeRequestMandelbox +} from "./controls/whist" +import { initializePageRefreshHandler } from "./controls/refresh" + +import { createStartNotification, createDisconnectNotification } from "./ui/notifications" +import { initializeLoadingScreen } from "./ui/loading" + +window.onload = () => { + initializeSessionStorage() + createStartNotification() + createDisconnectNotification() + + initializeGetTabId().then(() => { + initializeURLUpdater() + initializePopStateHandler() + initializeTitleUpdater() + initializeFaviconUpdater() + initializePageRefreshHandler() + }) + + initializeLoadingScreen() + initializeWhistTagHandler() + initializeWhistFreezeHandler() + initializeWhistThawHandler() + initializeRequestMandelbox() +} diff --git a/browser/hybrid/components/cloud_tabs_ui/src/shared/state.ts b/browser/hybrid/components/cloud_tabs_ui/src/shared/state.ts new file mode 100644 index 00000000000..f47cf8885ce --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/src/shared/state.ts @@ -0,0 +1,5 @@ +let state = { + wasConnected: false +} + +export { state } diff --git a/browser/hybrid/components/cloud_tabs_ui/src/ui/loading.ts b/browser/hybrid/components/cloud_tabs_ui/src/ui/loading.ts new file mode 100644 index 00000000000..902a4b6edbf --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/src/ui/loading.ts @@ -0,0 +1,51 @@ +import { css, element } from "./utils" + +const createBackground = () => { + const body = document.querySelector("body") + let background = document.createElement("div") + background.classList.add("background") + + css(background, { + width: "100vw", + height: "100vh", + position: "absolute", + top: 0, + left: 0, + "z-index": 1, + }) + + body?.appendChild(background) + return background +} + +const createLoadingMessage = (background: HTMLElement) => { + let message = element(` +
+ +
Cloud tab is loading
+
+ `) + + if (message !== null) background.appendChild(message) +} + +const removeBackgroundListener = (background?: HTMLElement) => { + ;(chrome as any).whist.onMessage.addListener((message: string) => { + const parsed = JSON.parse(message) + if (parsed.type === "ACTIVATE_TAB" || parsed.type === "UPDATE_TAB") { + // We don't remove the loading screen immediately because sometimes it takes time + // for the handshake and the protocol to actually display + setTimeout(() => { + background?.remove() + }, 7500) + } + }) +} + +const initializeLoadingScreen = () => { + const background = createBackground() + createLoadingMessage(background) + removeBackgroundListener(background) +} + +export { initializeLoadingScreen } diff --git a/browser/hybrid/components/cloud_tabs_ui/src/ui/notifications.ts b/browser/hybrid/components/cloud_tabs_ui/src/ui/notifications.ts new file mode 100644 index 00000000000..a957347ad63 --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/src/ui/notifications.ts @@ -0,0 +1,95 @@ +import { element } from "./utils" +import { state } from "../shared/state" + +let shown = false + +const createNotification = ({ + text, + duration, + type, +}: { + text: string + duration?: number + type?: string +}) => { + // Create the notification HTMLElement + let notification = element(` +
+ ${ + type === "success" + ? '' + : '' + } +
${text}
+
+ `) + + // Inject the HTMLElement into the DOM + ;(document.body || document.documentElement).appendChild(notification) + shown = true + // Fade out notification + duration !== undefined && + setTimeout(() => { + notification.style.animation = "fadeOut 1.5s" + notification.style.animationFillMode = "forwards" + shown = false + }, duration) + + return notification +} + +export const createStartNotification = () => { + let loaded = false + + ;(chrome as any).whist.onMessage.addListener((message: string) => { + const parsed = JSON.parse(message) + + if ( + (parsed.type === "UPDATE_TAB" || parsed.type === "ACTIVATE_TAB") && + !shown && + !loaded + ) { + loaded = true + createNotification({ + text: "Cloud tab activated", + duration: 3500, + type: "success", + }) + } + }) +} + +export const createDisconnectNotification = () => { + let notification: HTMLElement | null = null + const whistTag: any = document.querySelector("whist") + + setInterval(() => { + if (!whistTag.isWhistConnected() && !shown && state.wasConnected) { + notification = createNotification({ + text: "Connecting to cloud tab", + type: "loading", + }) + } + }, 100) + ;(chrome as any).whist.onMessage.addListener((message: string) => { + const parsed = JSON.parse(message) + + if (parsed.type === "SOCKET_DISCONNECTED" && !shown) { + notification = createNotification({ + text: "Connecting to cloud tab", + type: "loading", + }) + } + + if ( + (parsed.type === "UPDATE_TAB" || + parsed.type === "ACTIVATE_TAB" || + parsed.type === "SOCKET_CONNECTED") && + notification !== null + ) { + notification.style.animation = "fadeOut 1.5s" + notification.style.animationFillMode = "forwards" + shown = false + } + }) +} diff --git a/browser/hybrid/components/cloud_tabs_ui/src/ui/utils.ts b/browser/hybrid/components/cloud_tabs_ui/src/ui/utils.ts new file mode 100644 index 00000000000..88572ba8eea --- /dev/null +++ b/browser/hybrid/components/cloud_tabs_ui/src/ui/utils.ts @@ -0,0 +1,12 @@ +const css = (element: any, style: object) => { + for (const property in style) element.style[property] = style[property] +} + +const element = (html: string) => { + let template = document.createElement("template") + html = html.trim() + template.innerHTML = html + return template.content.firstChild as HTMLElement +} + +export { css, element } diff --git a/browser/hybrid/src/chrome/browser/extensions/extension_service.cc b/browser/hybrid/src/chrome/browser/extensions/extension_service.cc new file mode 100644 index 00000000000..15d95f3b057 --- /dev/null +++ b/browser/hybrid/src/chrome/browser/extensions/extension_service.cc @@ -0,0 +1,5 @@ +#include "whist/browser/hybrid/browser/extensions/whist_component_loader.h" + +#define BraveComponentLoader WhistComponentLoader +#include "src/brave/chromium_src/chrome/browser/extensions/extension_service.cc" +#undef BraveComponentLoader diff --git a/browser/hybrid/src/chrome/browser/extensions/extension_service.h b/browser/hybrid/src/chrome/browser/extensions/extension_service.h new file mode 100644 index 00000000000..30d51d670cb --- /dev/null +++ b/browser/hybrid/src/chrome/browser/extensions/extension_service.h @@ -0,0 +1,10 @@ +#ifndef WHIST_HYBRID_SRC_CHROME_BROWSER_EXTENSIONS_EXTENSION_SERVICE_H +#define WHIST_HYBRID_SRC_CHROME_BROWSER_EXTENSIONS_EXTENSION_SERVICE_H + +#define BraveExtensionService \ + BraveExtensionService; \ + friend class WhistExtensionService; +#include "src/brave/chromium_src/chrome/browser/extensions/extension_service.h" +#undef BraveExtensionService + +#endif // WHIST_HYBRID_SRC_CHROME_BROWSER_EXTENSIONS_EXTENSION_SERVICE_H diff --git a/browser/hybrid/src/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/browser/hybrid/src/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc new file mode 100644 index 00000000000..0617a11da6b --- /dev/null +++ b/browser/hybrid/src/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc @@ -0,0 +1,5 @@ +#include "whist/browser/hybrid/browser/ui/webui/whist_web_ui_controller_factory.h" + +#define BraveWebUIControllerFactory WhistWebUIControllerFactory +#include "brave/chromium_src/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc" +#undef BraveWebUIControllerFactory