diff --git a/.eslintrc.js b/.eslintrc.js index 3fda195286..cd50650709 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -11,17 +11,12 @@ module.exports = { "**/dist/**/*", "**/static/**/*", "**/site/**/*", + "extensions/*/*.tgz", ], settings: { react: { version: packageJson.devDependencies.react || "detect", }, - // the package eslint-import-resolver-typescript is required for this line which fixes errors when using .d.ts files - "import/resolver": { - "typescript": { - "alwaysTryTypes": true, - }, - }, }, overrides: [ { @@ -95,95 +90,9 @@ module.exports = { { files: [ "**/*.ts", - ], - parser: "@typescript-eslint/parser", - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:import/recommended", - "plugin:import/typescript", - ], - plugins: [ - "header", - "unused-imports", - ], - parserOptions: { - ecmaVersion: 2018, - sourceType: "module", - }, - rules: { - "no-constant-condition": ["error", { "checkLoops": false }], - "header/header": [2, "./license-header"], - "no-invalid-this": "off", - "@typescript-eslint/no-invalid-this": ["error"], - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/ban-types": "off", - "@typescript-eslint/ban-ts-comment": "off", - "@typescript-eslint/no-empty-interface": "off", - "@typescript-eslint/no-unused-vars": "off", - "space-before-function-paren": "off", - "@typescript-eslint/space-before-function-paren": ["error", { - "anonymous": "always", - "named": "never", - "asyncArrow": "always", - }], - "unused-imports/no-unused-imports-ts": process.env.PROD === "true" ? "error" : "warn", - "unused-imports/no-unused-vars-ts": [ - "warn", { - "vars": "all", - "args": "after-used", - "ignoreRestSiblings": true, - }, - ], - "comman-dangle": "off", - "@typescript-eslint/comma-dangle": ["error", "always-multiline"], - "comma-spacing": "off", - "@typescript-eslint/comma-spacing": "error", - "indent": ["error", 2, { - "SwitchCase": 1, - }], - "quotes": ["error", "double", { - "avoidEscape": true, - "allowTemplateLiterals": true, - }], - "object-curly-spacing": "off", - "@typescript-eslint/object-curly-spacing": ["error", "always", { - "objectsInObjects": false, - "arraysInObjects": true, - }], - "react/prop-types": "off", - "semi": "off", - "@typescript-eslint/semi": ["error"], - "linebreak-style": ["error", "unix"], - "eol-last": ["error", "always"], - "object-shorthand": "error", - "prefer-template": "error", - "template-curly-spacing": "error", - "no-unused-expressions": "off", - "@typescript-eslint/no-unused-expressions": "error", - "padding-line-between-statements": [ - "error", - { "blankLine": "always", "prev": "*", "next": "return" }, - { "blankLine": "always", "prev": "*", "next": "block-like" }, - { "blankLine": "always", "prev": "*", "next": "function" }, - { "blankLine": "always", "prev": "*", "next": "class" }, - { "blankLine": "always", "prev": ["const", "let", "var"], "next": "*" }, - { "blankLine": "any", "prev": ["const", "let", "var"], "next": ["const", "let", "var"] }, - ], - "no-template-curly-in-string": "error", - }, - }, - { - files: [ "**/*.tsx", ], parser: "@typescript-eslint/parser", - plugins: [ - "header", - "unused-imports", - ], extends: [ "eslint:recommended", "plugin:@typescript-eslint/recommended", @@ -191,13 +100,19 @@ module.exports = { "plugin:import/recommended", "plugin:import/typescript", ], + plugins: [ + "header", + "unused-imports", + "react-hooks", + ], parserOptions: { ecmaVersion: 2018, sourceType: "module", - jsx: true, }, rules: { - "no-constant-condition": ["error", { "checkLoops": false }], + "no-constant-condition": ["error", { + "checkLoops": false, + }], "header/header": [2, "./license-header"], "react/prop-types": "off", "no-invalid-this": "off", @@ -211,9 +126,10 @@ module.exports = { "@typescript-eslint/ban-ts-ignore": "off", "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/ban-types": "off", + "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/no-empty-function": "off", - "react/display-name": "off", "@typescript-eslint/no-unused-vars": "off", + "react/display-name": "off", "space-before-function-paren": "off", "@typescript-eslint/space-before-function-paren": ["error", { "anonymous": "always", diff --git a/src/renderer/components/dock/edit-resource.scss b/__mocks__/monaco-editor.ts similarity index 88% rename from src/renderer/components/dock/edit-resource.scss rename to __mocks__/monaco-editor.ts index 2ae07cdd07..cbe02cb296 100644 --- a/src/renderer/components/dock/edit-resource.scss +++ b/__mocks__/monaco-editor.ts @@ -2,6 +2,4 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ - -.EditResource { -} +export default {}; diff --git a/integration/__tests__/cluster-pages.tests.ts b/integration/__tests__/cluster-pages.tests.ts index 6dc89020e3..375321aaaf 100644 --- a/integration/__tests__/cluster-pages.tests.ts +++ b/integration/__tests__/cluster-pages.tests.ts @@ -354,8 +354,7 @@ utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => { } }, 10*60*1000); - // TODO: Make re-rendering of KubeObjectListLayout not cause namespaceSelector to be closed - xit("show logs and highlight the log search entries", async () => { + it("show logs and highlight the log search entries", async () => { await frame.click(`a[href="/workloads"]`); await frame.click(`a[href="/pods"]`); @@ -400,8 +399,7 @@ utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => { await frame.waitForSelector("div.TableCell >> text='kube-system'"); }, 10*60*1000); - // TODO: Make re-rendering of KubeObjectListLayout not cause namespaceSelector to be closed - xit(`should create the ${TEST_NAMESPACE} and a pod in the namespace`, async () => { + it(`should create the ${TEST_NAMESPACE} and a pod in the namespace`, async () => { await frame.click('a[href="/namespaces"]'); await frame.click("button.add-button"); await frame.waitForSelector("div.AddNamespaceDialog >> text='Create Namespace'"); diff --git a/package.json b/package.json index 29774ca6ba..84d542583a 100644 --- a/package.json +++ b/package.json @@ -320,8 +320,8 @@ "@types/webpack": "^5.28.0", "@types/webpack-env": "^1.16.3", "@types/webpack-node-externals": "^2.5.3", - "@typescript-eslint/eslint-plugin": "^5.7.0", - "@typescript-eslint/parser": "^5.7.0", + "@typescript-eslint/eslint-plugin": "^5.10.1", + "@typescript-eslint/parser": "^5.10.1", "ansi_up": "^5.1.0", "chart.js": "^2.9.4", "circular-dependency-plugin": "^5.2.2", @@ -335,17 +335,17 @@ "electron-notarize": "^0.3.0", "esbuild": "^0.13.15", "esbuild-loader": "^2.18.0", - "eslint": "^7.32.0", - "eslint-import-resolver-typescript": "^2.5.0", + "eslint": "^8.7.0", "eslint-plugin-header": "^3.1.1", - "eslint-plugin-import": "^2.25.3", - "eslint-plugin-react": "^7.27.1", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", - "eslint-plugin-unused-imports": "^1.1.5", + "eslint-plugin-unused-imports": "^2.0.0", "flex.box": "^3.4.4", "fork-ts-checker-webpack-plugin": "^6.5.0", "hoist-non-react-statics": "^3.3.2", "html-webpack-plugin": "^5.5.0", + "ignore-loader": "^0.1.2", "include-media": "^1.4.9", "jest": "26.6.3", "jest-canvas-mock": "^2.3.1", diff --git a/src/renderer/components/dock/logs/update-tab-name.injectable.ts b/src/common/fs/read-dir.injectable.ts similarity index 54% rename from src/renderer/components/dock/logs/update-tab-name.injectable.ts rename to src/common/fs/read-dir.injectable.ts index 24074e4cb6..501ecc1cdd 100644 --- a/src/renderer/components/dock/logs/update-tab-name.injectable.ts +++ b/src/common/fs/read-dir.injectable.ts @@ -3,11 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import logTabStoreInjectable from "./tab-store.injectable"; +import fsInjectable from "./fs.injectable"; -const updateTabNameInjectable = getInjectable({ - instantiate: (di) => di.inject(logTabStoreInjectable).updateTabName, +const readDirInjectable = getInjectable({ + instantiate: (di) => di.inject(fsInjectable).readdir, lifecycle: lifecycleEnum.singleton, }); -export default updateTabNameInjectable; +export default readDirInjectable; diff --git a/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-registry.injectable.ts b/src/common/fs/read-file.injectable.ts similarity index 51% rename from src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-registry.injectable.ts rename to src/common/fs/read-file.injectable.ts index 1bbcc031ae..5e2871a03d 100644 --- a/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-registry.injectable.ts +++ b/src/common/fs/read-file.injectable.ts @@ -2,12 +2,12 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { KubeObjectMenuRegistry } from "../../../../../extensions/registries"; import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import fsInjectable from "./fs.injectable"; -const kubeObjectMenuRegistryInjectable = getInjectable({ - instantiate: () => KubeObjectMenuRegistry.getInstance(), +const readFileInjectable = getInjectable({ + instantiate: (di) => di.inject(fsInjectable).readFile, lifecycle: lifecycleEnum.singleton, }); -export default kubeObjectMenuRegistryInjectable; +export default readFileInjectable; diff --git a/src/common/fs/read-json-file/read-json-file.injectable.ts b/src/common/fs/read-json-file.injectable.ts similarity index 66% rename from src/common/fs/read-json-file/read-json-file.injectable.ts rename to src/common/fs/read-json-file.injectable.ts index b94c904885..b944decadc 100644 --- a/src/common/fs/read-json-file/read-json-file.injectable.ts +++ b/src/common/fs/read-json-file.injectable.ts @@ -2,15 +2,11 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { readJsonFile } from "./read-json-file"; import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import fsInjectable from "../fs.injectable"; +import fsInjectable from "./fs.injectable"; const readJsonFileInjectable = getInjectable({ - instantiate: (di) => readJsonFile({ - fs: di.inject(fsInjectable), - }), - + instantiate: (di) => di.inject(fsInjectable).readJson, lifecycle: lifecycleEnum.singleton, }); diff --git a/src/common/fs/read-json-file/read-json-file.ts b/src/common/fs/read-json-file/read-json-file.ts deleted file mode 100644 index cb22e78ad3..0000000000 --- a/src/common/fs/read-json-file/read-json-file.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { JsonObject } from "type-fest"; - -interface Dependencies { - fs: { - readJson: (filePath: string) => Promise; - }; -} - -export const readJsonFile = - ({ fs }: Dependencies) => - (filePath: string) => - fs.readJson(filePath); diff --git a/src/common/fs/write-json-file.injectable.ts b/src/common/fs/write-json-file.injectable.ts new file mode 100644 index 0000000000..7bef449444 --- /dev/null +++ b/src/common/fs/write-json-file.injectable.ts @@ -0,0 +1,38 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { EnsureOptions, WriteOptions } from "fs-extra"; +import path from "path"; +import type { JsonValue } from "type-fest"; +import fsInjectable from "./fs.injectable"; + +interface Dependencies { + writeJson: (file: string, object: any, options?: WriteOptions | BufferEncoding | string) => Promise; + ensureDir: (dir: string, options?: EnsureOptions | number) => Promise; +} + +const writeJsonFile = ({ writeJson, ensureDir }: Dependencies) => async (filePath: string, content: JsonValue) => { + await ensureDir(path.dirname(filePath), { mode: 0o755 }); + + await writeJson(filePath, content, { + encoding: "utf-8", + spaces: 2, + }); +}; + +const writeJsonFileInjectable = getInjectable({ + instantiate: (di) => { + const { writeJson, ensureDir } = di.inject(fsInjectable); + + return writeJsonFile({ + writeJson, + ensureDir, + }); + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default writeJsonFileInjectable; diff --git a/src/common/fs/write-json-file/write-json-file.ts b/src/common/fs/write-json-file/write-json-file.ts deleted file mode 100644 index 8db664593e..0000000000 --- a/src/common/fs/write-json-file/write-json-file.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import path from "path"; -import type { JsonObject } from "type-fest"; - -interface Dependencies { - fs: { - ensureDir: ( - directoryName: string, - options: { mode: number } - ) => Promise; - - writeJson: ( - filePath: string, - contentObject: JsonObject, - options: { spaces: number } - ) => Promise; - }; -} - -export const writeJsonFile = - ({ fs }: Dependencies) => - async (filePath: string, contentObject: JsonObject) => { - const directoryName = path.dirname(filePath); - - await fs.ensureDir(directoryName, { mode: 0o755 }); - - await fs.writeJson(filePath, contentObject, { spaces: 2 }); - }; diff --git a/src/common/ipc-channel/channel.d.ts b/src/common/ipc-channel/channel.ts similarity index 100% rename from src/common/ipc-channel/channel.d.ts rename to src/common/ipc-channel/channel.ts diff --git a/src/common/item.store.ts b/src/common/item.store.ts index c2296a7515..fee402491b 100644 --- a/src/common/item.store.ts +++ b/src/common/item.store.ts @@ -111,7 +111,7 @@ export abstract class ItemStore { } } - protected async loadItem(...args: any[]): Promise + protected async loadItem(...args: any[]): Promise; @action protected async loadItem(request: () => Promise, sortItems = true) { const item = await Promise.resolve(request()).catch(() => null); diff --git a/src/common/k8s-api/kube-watch-event.d.ts b/src/common/k8s-api/kube-watch-event.ts similarity index 100% rename from src/common/k8s-api/kube-watch-event.d.ts rename to src/common/k8s-api/kube-watch-event.ts diff --git a/src/common/user-store/preferences-helpers.ts b/src/common/user-store/preferences-helpers.ts index 228b754387..39d1e0938e 100644 --- a/src/common/user-store/preferences-helpers.ts +++ b/src/common/user-store/preferences-helpers.ts @@ -6,7 +6,7 @@ import moment from "moment-timezone"; import path from "path"; import os from "os"; -import { getAppVersion, ObservableToggleSet } from "../utils"; +import { getAppVersion } from "../utils"; import type { editor } from "monaco-editor"; import merge from "lodash/merge"; import { SemVer } from "semver"; @@ -236,10 +236,10 @@ const terminalCopyOnSelect: PreferenceDescription = { }, }; -const hiddenTableColumns: PreferenceDescription<[string, string[]][], Map>> = { +const hiddenTableColumns: PreferenceDescription<[string, string[]][], Map>> = { fromStore(val) { return new Map( - (val ?? []).map(([tableId, columnIds]) => [tableId, new ObservableToggleSet(columnIds)]), + (val ?? []).map(([tableId, columnIds]) => [tableId, new Set(columnIds)]), ); }, toStore(val) { diff --git a/src/common/user-store/user-store.ts b/src/common/user-store/user-store.ts index a1ffe65d66..9d16b2c419 100644 --- a/src/common/user-store/user-store.ts +++ b/src/common/user-store/user-store.ts @@ -11,7 +11,7 @@ import migrations, { fileNameMigration } from "../../migrations/user-store"; import { getAppVersion } from "../utils/app-version"; import { kubeConfigDefaultPath } from "../kube-helpers"; import { appEventBus } from "../app-event-bus/event-bus"; -import { ObservableToggleSet, toJS } from "../../renderer/utils"; +import { getOrInsertSet, toggle, toJS } from "../../renderer/utils"; import { DESCRIPTORS, EditorConfiguration, ExtensionRegistry, KubeconfigSyncValue, UserPreferencesModel, TerminalConfig } from "./preferences-helpers"; import logger from "../../main/logger"; @@ -71,7 +71,7 @@ export class UserStore extends BaseStore /* implements UserStore * The column IDs under each configurable table ID that have been configured * to not be shown */ - hiddenTableColumns = observable.map>(); + hiddenTableColumns = observable.map>(); /** * Monaco editor configs @@ -133,16 +133,11 @@ export class UserStore extends BaseStore /* implements UserStore return columnIds.some(columnId => config.has(columnId)); } - @action /** * Toggles the hidden configuration of a table's column */ toggleTableColumnVisibility(tableId: string, columnId: string) { - if (!this.hiddenTableColumns.get(tableId)) { - this.hiddenTableColumns.set(tableId, new ObservableToggleSet()); - } - - this.hiddenTableColumns.get(tableId).toggle(columnId); + toggle(getOrInsertSet(this.hiddenTableColumns, tableId), columnId); } @action diff --git a/src/common/utils/__tests__/bind.test.ts b/src/common/utils/__tests__/bind.test.ts deleted file mode 100644 index 77850a88d9..0000000000 --- a/src/common/utils/__tests__/bind.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { bind } from "../index"; - -describe("bind", () => { - it("should work correctly", () => { - function foobar(bound: number, nonBound: number): number { - expect(typeof bound).toBe("number"); - expect(typeof nonBound).toBe("number"); - - return bound + nonBound; - } - const foobarBound = bind(foobar, null, 5); - - expect(foobarBound(10)).toBe(15); - }); -}); diff --git a/src/common/utils/collection-functions.ts b/src/common/utils/collection-functions.ts index 0d18a41e8a..267668ce81 100644 --- a/src/common/utils/collection-functions.ts +++ b/src/common/utils/collection-functions.ts @@ -3,6 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ +import { runInAction } from "mobx"; + /** * Get the value behind `key`. If it was not present, first insert `value` * @param map The map to interact with @@ -26,6 +28,14 @@ export function getOrInsertMap(map: Map>, key: K): Map return getOrInsert(map, key, new Map()); } +/** + * Like `getOrInsert` but specifically for when `V` is `Set` so that + * the typings are inferred. + */ +export function getOrInsertSet(map: Map>, key: K): Set { + return getOrInsert(map, key, new Set()); +} + /** * Like `getOrInsert` but with delayed creation of the item */ @@ -36,3 +46,17 @@ export function getOrInsertWith(map: Map, key: K, value: () => V): V return map.get(key); } + +/** + * If `key` is in `set`, remove it otherwise add it. + * @param set The set to manipulate + * @param key The key to toggle the "is in"-ness of + */ +export function toggle(set: Set, key: K): void { + runInAction(() => { + // Returns true if value was already in Set; otherwise false. + if (!set.delete(key)) { + set.add(key); + } + }); +} diff --git a/src/common/utils/extended-map.ts b/src/common/utils/extended-map.ts index fe8520e31d..5db6bffec1 100644 --- a/src/common/utils/extended-map.ts +++ b/src/common/utils/extended-map.ts @@ -3,12 +3,14 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { action, ObservableMap } from "mobx"; +import { action, ObservableMap, runInAction } from "mobx"; export function multiSet(map: Map, newEntries: [T, V][]): void { - for (const [key, val] of newEntries) { - map.set(key, val); - } + runInAction(() => { + for (const [key, val] of newEntries) { + map.set(key, val); + } + }); } export class ExtendedMap extends Map { diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts index 1400608aab..d8a07f31f6 100644 --- a/src/common/utils/index.ts +++ b/src/common/utils/index.ts @@ -10,13 +10,6 @@ export function noop(...args: T): void { return void args; } -/** - * A typecorrect version of .bind() - */ -export function bind(fn: (...args: [...BoundArgs, ...NonBoundArgs]) => ReturnType, thisArg: any, ...boundArgs: BoundArgs): (...args: NonBoundArgs) => ReturnType { - return fn.bind(thisArg, ...boundArgs); -} - export * from "./app-version"; export * from "./autobind"; export * from "./camelCase"; @@ -45,10 +38,10 @@ export * from "./singleton"; export * from "./sort-compare"; export * from "./splitArray"; export * from "./tar"; -export * from "./toggle-set"; export * from "./toJS"; export * from "./type-narrowing"; export * from "./types"; +export * from "./wait-for-path"; import * as iter from "./iter"; import * as array from "./array"; diff --git a/src/common/utils/toggle-set.ts b/src/common/utils/toggle-set.ts deleted file mode 100644 index 3b3c226f9b..0000000000 --- a/src/common/utils/toggle-set.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { ObservableSet } from "mobx"; - -export class ToggleSet extends Set { - public toggle(value: T): void { - if (!this.delete(value)) { - // Set.prototype.delete returns false if `value` was not in the set - this.add(value); - } - } -} - -export class ObservableToggleSet extends ObservableSet { - public toggle(value: T): void { - if (!this.delete(value)) { - // Set.prototype.delete returns false if `value` was not in the set - this.add(value); - } - } -} diff --git a/src/common/utils/wait-for-path.ts b/src/common/utils/wait-for-path.ts new file mode 100644 index 0000000000..f5a068075b --- /dev/null +++ b/src/common/utils/wait-for-path.ts @@ -0,0 +1,55 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { FSWatcher } from "chokidar"; +import path from "path"; + +/** + * Wait for `filePath` and all parent directories to exist. + * @param pathname The file path to wait until it exists + * + * NOTE: There is technically a race condition in this function of the form + * "time-of-check to time-of-use" because we have to wait for each parent + * directory to exist first. + */ +export async function waitForPath(pathname: string): Promise { + const dirOfPath = path.dirname(pathname); + + if (dirOfPath === pathname) { + // The root of this filesystem, assume it exists + return; + } else { + await waitForPath(dirOfPath); + } + + return new Promise((resolve, reject) => { + const watcher = new FSWatcher({ + depth: 0, + disableGlobbing: true, + }); + const onAddOrAddDir = (filePath: string) => { + if (filePath === pathname) { + watcher.unwatch(dirOfPath); + watcher + .close() + .then(() => resolve()) + .catch(reject); + } + }; + const onError = (error: any) => { + watcher.unwatch(dirOfPath); + watcher + .close() + .then(() => reject(error)) + .catch(() => reject(error)); + }; + + watcher + .on("add", onAddOrAddDir) + .on("addDir", onAddOrAddDir) + .on("error", onError) + .add(dirOfPath); + }); +} diff --git a/src/common/fs/write-json-file/write-json-file.injectable.ts b/src/common/vars/is-linux.injectable.ts similarity index 50% rename from src/common/fs/write-json-file/write-json-file.injectable.ts rename to src/common/vars/is-linux.injectable.ts index 5ff6cbaec3..a603f01951 100644 --- a/src/common/fs/write-json-file/write-json-file.injectable.ts +++ b/src/common/vars/is-linux.injectable.ts @@ -3,12 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import { writeJsonFile } from "./write-json-file"; -import fsInjectable from "../fs.injectable"; +import { isLinux } from "../vars"; -const writeJsonFileInjectable = getInjectable({ - instantiate: (di) => writeJsonFile({ fs: di.inject(fsInjectable) }), +const isLinuxInjectable = getInjectable({ + instantiate: () => isLinux, lifecycle: lifecycleEnum.singleton, }); -export default writeJsonFileInjectable; +export default isLinuxInjectable; diff --git a/src/common/vars/is-windows.injectable.ts b/src/common/vars/is-windows.injectable.ts new file mode 100644 index 0000000000..76a08a4af2 --- /dev/null +++ b/src/common/vars/is-windows.injectable.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { isWindows } from "../vars"; + +const isWindowsInjectable = getInjectable({ + instantiate: () => isWindows, + lifecycle: lifecycleEnum.singleton, +}); + +export default isWindowsInjectable; diff --git a/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications.ts b/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications.ts new file mode 100644 index 0000000000..8961ea8424 --- /dev/null +++ b/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications.ts @@ -0,0 +1,47 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { Injectable } from "@ogre-tools/injectable"; +import { getLegacyGlobalDiForExtensionApi } from "./legacy-global-di-for-extension-api"; + +type TentativeTuple = T extends object ? [T] : [undefined?]; + +type MapInjectables = { + [Key in keyof T]: T[Key] extends () => infer Res ? Res : never; +}; + +export const asLegacyGlobalObjectForExtensionApiWithModifications = < + TInjectable extends Injectable, + TInstantiationParameter, + OtherFields extends Record any>, +>( + injectableKey: TInjectable, + otherFields: OtherFields, + ...instantiationParameter: TentativeTuple + ) => + new Proxy( + {}, + { + get(target, propertyName) { + if (propertyName === "$$typeof") { + return undefined; + } + + const instance: any = getLegacyGlobalDiForExtensionApi().inject( + injectableKey, + ...instantiationParameter, + ); + + const propertyValue = instance[propertyName] ?? otherFields[propertyName as any](); + + if (typeof propertyValue === "function") { + return function (...args: any[]) { + return propertyValue.apply(instance, args); + }; + } + + return propertyValue; + }, + }, + ) as ReturnType & MapInjectables; diff --git a/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-singleton-for-extension-api.ts b/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-singleton-for-extension-api.ts deleted file mode 100644 index 4e77961ca8..0000000000 --- a/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-singleton-for-extension-api.ts +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { Injectable } from "@ogre-tools/injectable"; -import { getLegacyGlobalDiForExtensionApi } from "./legacy-global-di-for-extension-api"; - -type TentativeTuple = T extends object ? [T] : [undefined?]; - -export const asLegacyGlobalSingletonForExtensionApi = < - TClass extends abstract new (...args: any[]) => any, - TInjectable extends Injectable, - TInstantiationParameter, ->( - Class: TClass, - injectableKey: TInjectable, - ...instantiationParameter: TentativeTuple - ) => - new Proxy(Class, { - construct: () => { - throw new Error("A legacy singleton class must be created by createInstance()"); - }, - - get: (target: any, propertyName) => { - if (propertyName === "getInstance" || propertyName === "createInstance") { - return () => - getLegacyGlobalDiForExtensionApi().inject( - injectableKey, - ...instantiationParameter, - ); - } - - if (propertyName === "resetInstance") { - return () => getLegacyGlobalDiForExtensionApi().purge(injectableKey); - } - - return target[propertyName]; - }, - }) as InstanceType & { - getInstance: () => InstanceType; - createInstance: () => InstanceType; - resetInstance: () => void; - }; diff --git a/src/extensions/common-api/registrations.ts b/src/extensions/common-api/registrations.ts index 20512afb22..be3e8d87cd 100644 --- a/src/extensions/common-api/registrations.ts +++ b/src/extensions/common-api/registrations.ts @@ -2,13 +2,12 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ - +export type { StatusBarRegistration } from "../../renderer/components/cluster-manager/status-bar-registration"; +export type { KubeObjectMenuRegistration, KubeObjectMenuComponents } from "../../renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-registration"; export type { AppPreferenceRegistration, AppPreferenceComponents } from "../../renderer/components/+preferences/app-preferences/app-preference-registration"; export type { KubeObjectDetailRegistration, KubeObjectDetailComponents } from "../registries/kube-object-detail-registry"; -export type { KubeObjectMenuRegistration, KubeObjectMenuComponents } from "../registries/kube-object-menu-registry"; export type { KubeObjectStatusRegistration } from "../registries/kube-object-status-registry"; export type { PageRegistration, RegisteredPage, PageParams, PageComponentProps, PageComponents, PageTarget } from "../registries/page-registry"; export type { ClusterPageMenuRegistration, ClusterPageMenuComponents } from "../registries/page-menu-registry"; -export type { StatusBarRegistration } from "../registries/status-bar-registry"; export type { ProtocolHandlerRegistration, RouteParams as ProtocolRouteParams, RouteHandler as ProtocolRouteHandler } from "../registries/protocol-handler"; export type { CustomCategoryViewProps, CustomCategoryViewComponents, CustomCategoryViewRegistration } from "../../renderer/components/+catalog/custom-views"; diff --git a/src/extensions/extension-loader/extension-loader.ts b/src/extensions/extension-loader/extension-loader.ts index 04b552884c..e954a1f460 100644 --- a/src/extensions/extension-loader/extension-loader.ts +++ b/src/extensions/extension-loader/extension-loader.ts @@ -249,7 +249,6 @@ export class ExtensionLoader { const removeItems = [ registries.GlobalPageRegistry.getInstance().add(extension.globalPages, extension), registries.EntitySettingRegistry.getInstance().add(extension.entitySettings), - registries.StatusBarRegistry.getInstance().add(extension.statusBarItems), registries.CatalogEntityDetailRegistry.getInstance().add(extension.catalogEntityDetailItems), ]; @@ -277,7 +276,6 @@ export class ExtensionLoader { const removeItems = [ registries.ClusterPageRegistry.getInstance().add(extension.clusterPages, extension), registries.ClusterPageMenuRegistry.getInstance().add(extension.clusterPageMenus, extension), - registries.KubeObjectMenuRegistry.getInstance().add(extension.kubeObjectMenuItems), registries.KubeObjectDetailRegistry.getInstance().add(extension.kubeObjectDetailItems), registries.KubeObjectStatusRegistry.getInstance().add(extension.kubeObjectStatusTexts), registries.WorkloadsOverviewDetailRegistry.getInstance().add(extension.kubeWorkloadsOverviewItems), diff --git a/src/extensions/extensions-store/extensions-store.ts b/src/extensions/extensions-store/extensions-store.ts index 682a5a25cb..e019071836 100644 --- a/src/extensions/extensions-store/extensions-store.ts +++ b/src/extensions/extensions-store/extensions-store.ts @@ -42,10 +42,9 @@ export class ExtensionsStore extends BaseStore { return isBundled || Boolean(this.state.get(id)?.enabled); } - @action - mergeState = (extensionsState: Record) => { + mergeState = action((extensionsState: Record) => { this.state.merge(extensionsState); - }; + }); @action protected fromStore({ extensions }: LensExtensionsStoreModel) { diff --git a/src/extensions/lens-renderer-extension.ts b/src/extensions/lens-renderer-extension.ts index 7d511c5504..9d69b4485a 100644 --- a/src/extensions/lens-renderer-extension.ts +++ b/src/extensions/lens-renderer-extension.ts @@ -18,6 +18,8 @@ import type { CommandRegistration } from "../renderer/components/command-palette import type { AppPreferenceRegistration } from "../renderer/components/+preferences/app-preferences/app-preference-registration"; import type { AdditionalCategoryColumnRegistration } from "../renderer/components/+catalog/custom-category-columns"; import type { CustomCategoryViewRegistration } from "../renderer/components/+catalog/custom-views"; +import type { StatusBarRegistration } from "../renderer/components/cluster-manager/status-bar-registration"; +import type { KubeObjectMenuRegistration } from "../renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-registration"; export class LensRendererExtension extends LensExtension { globalPages: registries.PageRegistration[] = []; @@ -26,9 +28,9 @@ export class LensRendererExtension extends LensExtension { kubeObjectStatusTexts: registries.KubeObjectStatusRegistration[] = []; appPreferences: AppPreferenceRegistration[] = []; entitySettings: registries.EntitySettingRegistration[] = []; - statusBarItems: registries.StatusBarRegistration[] = []; + statusBarItems: StatusBarRegistration[] = []; kubeObjectDetailItems: registries.KubeObjectDetailRegistration[] = []; - kubeObjectMenuItems: registries.KubeObjectMenuRegistration[] = []; + kubeObjectMenuItems: KubeObjectMenuRegistration[] = []; kubeWorkloadsOverviewItems: registries.WorkloadsOverviewDetailRegistration[] = []; commands: CommandRegistration[] = []; welcomeMenus: WelcomeMenuRegistration[] = []; diff --git a/src/extensions/registries/index.ts b/src/extensions/registries/index.ts index 477f406b2c..0713e3eede 100644 --- a/src/extensions/registries/index.ts +++ b/src/extensions/registries/index.ts @@ -7,9 +7,7 @@ export * from "./page-registry"; export * from "./page-menu-registry"; -export * from "./status-bar-registry"; export * from "./kube-object-detail-registry"; -export * from "./kube-object-menu-registry"; export * from "./kube-object-status-registry"; export * from "./entity-setting-registry"; export * from "./catalog-entity-detail-registry"; diff --git a/src/extensions/renderer-api/components.ts b/src/extensions/renderer-api/components.ts index 54a0f2d2d1..8e6df41fa1 100644 --- a/src/extensions/renderer-api/components.ts +++ b/src/extensions/renderer-api/components.ts @@ -3,14 +3,18 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { asLegacyGlobalFunctionForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api"; -import createTerminalTabInjectable from "../../renderer/components/dock/create-terminal-tab/create-terminal-tab.injectable"; -import terminalStoreInjectable from "../../renderer/components/dock/terminal-store/terminal-store.injectable"; +import createTerminalTabInjectable from "../../renderer/components/dock/terminal/create-terminal-tab.injectable"; +import terminalStoreInjectable from "../../renderer/components/dock/terminal/store.injectable"; import { asLegacyGlobalObjectForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; import logTabStoreInjectable from "../../renderer/components/dock/logs/tab-store.injectable"; -import { asLegacyGlobalSingletonForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-singleton-for-extension-api"; -import { TerminalStore as TerminalStoreClass } from "../../renderer/components/dock/terminal-store/terminal.store"; import commandOverlayInjectable from "../../renderer/components/command-palette/command-overlay.injectable"; +import { asLegacyGlobalObjectForExtensionApiWithModifications } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications"; +import createPodLogsTabInjectable from "../../renderer/components/dock/logs/create-pod-logs-tab.injectable"; +import createWorkloadLogsTabInjectable from "../../renderer/components/dock/logs/create-workload-logs-tab.injectable"; +import sendCommandInjectable from "../../renderer/components/dock/terminal/send-command.injectable"; +import { podsStore } from "../../renderer/components/+workloads-pods/pods.store"; +import renameTabInjectable from "../../renderer/components/dock/dock/rename-tab.injectable"; // layouts export * from "../../renderer/components/layout/main-layout"; @@ -71,7 +75,30 @@ export * from "../../renderer/components/+events/kube-event-details"; export * from "../../renderer/components/status-brick"; export const createTerminalTab = asLegacyGlobalFunctionForExtensionApi(createTerminalTabInjectable); -export const TerminalStore = asLegacyGlobalSingletonForExtensionApi(TerminalStoreClass, terminalStoreInjectable); -export const terminalStore = asLegacyGlobalObjectForExtensionApi(terminalStoreInjectable); -export const logTabStore = asLegacyGlobalObjectForExtensionApi(logTabStoreInjectable); +export const terminalStore = asLegacyGlobalObjectForExtensionApiWithModifications(terminalStoreInjectable, { + sendCommand: () => asLegacyGlobalFunctionForExtensionApi(sendCommandInjectable), +}); +export const logTabStore = asLegacyGlobalObjectForExtensionApiWithModifications(logTabStoreInjectable, { + createPodTab: () => asLegacyGlobalFunctionForExtensionApi(createPodLogsTabInjectable), + createWorkloadTab: () => asLegacyGlobalFunctionForExtensionApi(createWorkloadLogsTabInjectable), + renameTab: () => (tabId: string): void => { + const renameTab = asLegacyGlobalFunctionForExtensionApi(renameTabInjectable); + const tabData = logTabStore.getData(tabId); + const pod = podsStore.getById(tabData.selectedPodId); + renameTab(tabId, `Pod ${pod.getName()}`); + }, + tabs: () => undefined, +}); + +export class TerminalStore { + static getInstance() { + return terminalStore; + } + static createInstance() { + return terminalStore; + } + static resetInstance() { + console.warn("TerminalStore.resetInstance() does nothing"); + } +} diff --git a/src/main/getDiForUnitTesting.ts b/src/main/getDiForUnitTesting.ts index 54db181333..ae71fb9618 100644 --- a/src/main/getDiForUnitTesting.ts +++ b/src/main/getDiForUnitTesting.ts @@ -12,8 +12,8 @@ import getElectronAppPathInjectable from "./app-paths/get-electron-app-path/get- import setElectronAppPathInjectable from "./app-paths/set-electron-app-path/set-electron-app-path.injectable"; import appNameInjectable from "./app-paths/app-name/app-name.injectable"; import registerChannelInjectable from "./app-paths/register-channel/register-channel.injectable"; -import writeJsonFileInjectable from "../common/fs/write-json-file/write-json-file.injectable"; -import readJsonFileInjectable from "../common/fs/read-json-file/read-json-file.injectable"; +import writeJsonFileInjectable from "../common/fs/write-json-file.injectable"; +import readJsonFileInjectable from "../common/fs/read-json-file.injectable"; export const getDiForUnitTesting = ( { doGeneralOverrides } = { doGeneralOverrides: false }, diff --git a/src/main/menu/menu-registration.d.ts b/src/main/menu/menu-registration.ts similarity index 100% rename from src/main/menu/menu-registration.d.ts rename to src/main/menu/menu-registration.ts diff --git a/src/main/tray/tray-menu-registration.d.ts b/src/main/tray/tray-menu-registration.ts similarity index 100% rename from src/main/tray/tray-menu-registration.d.ts rename to src/main/tray/tray-menu-registration.ts diff --git a/src/main/window-manager.ts b/src/main/window-manager.ts index 903c9d8525..9985f39597 100644 --- a/src/main/window-manager.ts +++ b/src/main/window-manager.ts @@ -74,7 +74,7 @@ export class WindowManager extends Singleton { nodeIntegrationInSubFrames: true, webviewTag: true, contextIsolation: false, - nativeWindowOpen: true, + nativeWindowOpen: false, }, }); this.windowState.manage(this.mainWindow); diff --git a/src/renderer/bootstrap.tsx b/src/renderer/bootstrap.tsx index 9be509ab61..5593134586 100644 --- a/src/renderer/bootstrap.tsx +++ b/src/renderer/bootstrap.tsx @@ -73,9 +73,6 @@ export async function bootstrap(di: DependencyInjectionContainer) { logger.info(`${logPrefix} initializing EntitySettingsRegistry`); initializers.initEntitySettingsRegistry(); - logger.info(`${logPrefix} initializing KubeObjectMenuRegistry`); - initializers.initKubeObjectMenuRegistry(); - logger.info(`${logPrefix} initializing KubeObjectDetailRegistry`); initializers.initKubeObjectDetailRegistry(); diff --git a/src/renderer/components/+add-cluster/add-cluster.tsx b/src/renderer/components/+add-cluster/add-cluster.tsx index ba06039d4c..ed69819cfd 100644 --- a/src/renderer/components/+add-cluster/add-cluster.tsx +++ b/src/renderer/components/+add-cluster/add-cluster.tsx @@ -70,8 +70,7 @@ class NonInjectedAddCluster extends React.Component { ].filter(Boolean); } - @action - refreshContexts = debounce(() => { + readonly refreshContexts = debounce(action(() => { const { config, error } = loadConfigFromString(this.customConfig.trim() || "{}"); this.kubeContexts.replace(getContexts(config)); @@ -83,10 +82,9 @@ class NonInjectedAddCluster extends React.Component { if (config.contexts.length === 0) { this.errors.push('No contexts defined, either missing the "contexts" field, or it is empty.'); } - }, 500); + }), 500); - @action - addClusters = async () => { + addClusters = action(async () => { this.isWaiting = true; appEventBus.emit({ name: "cluster-add", action: "click" }); @@ -102,7 +100,7 @@ class NonInjectedAddCluster extends React.Component { } catch (error) { Notifications.error(`Failed to add clusters: ${error}`); } - }; + }); render() { return ( diff --git a/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx b/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx index ea31f628d7..ff7d929e8f 100644 --- a/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx +++ b/src/renderer/components/+apps-helm-charts/helm-chart-details.tsx @@ -18,8 +18,7 @@ import { Select, SelectOption } from "../select"; import { Badge } from "../badge"; import { Tooltip, withStyles } from "@material-ui/core"; import { withInjectables } from "@ogre-tools/injectable-react"; -import createInstallChartTabInjectable - from "../dock/create-install-chart-tab/create-install-chart-tab.injectable"; +import createInstallChartTabInjectable from "../dock/install-chart/create-install-chart-tab.injectable"; interface Props { chart: HelmChart; diff --git a/src/renderer/components/+apps-helm-charts/helm-charts.tsx b/src/renderer/components/+apps-helm-charts/helm-charts.tsx index 36b84d5267..49f885a093 100644 --- a/src/renderer/components/+apps-helm-charts/helm-charts.tsx +++ b/src/renderer/components/+apps-helm-charts/helm-charts.tsx @@ -12,7 +12,7 @@ import { helmChartStore } from "./helm-chart.store"; import type { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; import { HelmChartDetails } from "./helm-chart-details"; import { navigation } from "../../navigation"; -import { ItemListLayout } from "../item-object-list/item-list-layout"; +import { ItemListLayout } from "../item-object-list/list-layout"; import { helmChartsURL } from "../../../common/routes"; import type { HelmChartsRouteParams } from "../../../common/routes"; diff --git a/src/renderer/components/+apps-releases/release-details/release-details.tsx b/src/renderer/components/+apps-releases/release-details/release-details.tsx index 77f6ab2d87..30d34e1857 100644 --- a/src/renderer/components/+apps-releases/release-details/release-details.tsx +++ b/src/renderer/components/+apps-releases/release-details/release-details.tsx @@ -27,7 +27,7 @@ import { getDetailsUrl } from "../../kube-detail-params"; import { Checkbox } from "../../checkbox"; import { MonacoEditor } from "../../monaco-editor"; import { IAsyncComputed, withInjectables } from "@ogre-tools/injectable-react"; -import createUpgradeChartTabInjectable from "../../dock/create-upgrade-chart-tab/create-upgrade-chart-tab.injectable"; +import createUpgradeChartTabInjectable from "../../dock/upgrade-chart/create-upgrade-chart-tab.injectable"; import updateReleaseInjectable from "../update-release/update-release.injectable"; import releaseInjectable from "./release.injectable"; import releaseDetailsInjectable from "./release-details.injectable"; diff --git a/src/renderer/components/+apps-releases/release-menu.tsx b/src/renderer/components/+apps-releases/release-menu.tsx index a1dc263806..30824dba15 100644 --- a/src/renderer/components/+apps-releases/release-menu.tsx +++ b/src/renderer/components/+apps-releases/release-menu.tsx @@ -10,7 +10,7 @@ import { MenuActions, MenuActionsProps } from "../menu/menu-actions"; import { MenuItem } from "../menu"; import { Icon } from "../icon"; import { withInjectables } from "@ogre-tools/injectable-react"; -import createUpgradeChartTabInjectable from "../dock/create-upgrade-chart-tab/create-upgrade-chart-tab.injectable"; +import createUpgradeChartTabInjectable from "../dock/upgrade-chart/create-upgrade-chart-tab.injectable"; import releaseRollbackDialogModelInjectable from "./release-rollback-dialog-model/release-rollback-dialog-model.injectable"; import deleteReleaseInjectable from "./delete-release/delete-release.injectable"; diff --git a/src/renderer/components/+apps-releases/releases.tsx b/src/renderer/components/+apps-releases/releases.tsx index a71cc8e7a1..34f9798783 100644 --- a/src/renderer/components/+apps-releases/releases.tsx +++ b/src/renderer/components/+apps-releases/releases.tsx @@ -23,10 +23,8 @@ import { ReleaseRollbackDialog } from "./release-rollback-dialog"; import { ReleaseDetails } from "./release-details/release-details"; import removableReleasesInjectable from "./removable-releases.injectable"; import type { RemovableHelmRelease } from "./removable-releases"; -import { observer } from "mobx-react"; import type { IComputedValue } from "mobx"; import releasesInjectable from "./releases.injectable"; -import { Spinner } from "../spinner"; enum columnId { name = "name", @@ -48,7 +46,6 @@ interface Dependencies { selectNamespace: (namespace: string) => void } -@observer class NonInjectedHelmReleases extends Component { componentDidMount() { const { match: { params: { namespace }}} = this.props; @@ -89,12 +86,8 @@ class NonInjectedHelmReleases extends Component { } render() { - if (this.props.releasesArePending.get()) { - // TODO: Make Spinner "center" work properly - return
; - } - const releases = this.props.releases; + const releasesArePending = this.props.releasesArePending; // TODO: Implement ItemListLayout without stateful stores const legacyReleaseStore = { @@ -103,7 +96,11 @@ class NonInjectedHelmReleases extends Component { }, loadAll: () => Promise.resolve(), - isLoaded: true, + + get isLoaded() { + return !releasesArePending.get(); + }, + failedLoading: false, getTotalCount: () => releases.get().length, diff --git a/src/renderer/components/+catalog/catalog-add-button.tsx b/src/renderer/components/+catalog/catalog-add-button.tsx index b20f361fb4..e9f3a0743f 100644 --- a/src/renderer/components/+catalog/catalog-add-button.tsx +++ b/src/renderer/components/+catalog/catalog-add-button.tsx @@ -57,8 +57,7 @@ export class CatalogAddButton extends React.Component { } } - @action - updateCategoryItems = (category: CatalogCategory) => { + updateCategoryItems = action((category: CatalogCategory) => { if (category instanceof EventEmitter) { const menuItems: CatalogEntityAddMenu[] = []; const context: CatalogEntityAddMenuContext = { @@ -69,7 +68,7 @@ export class CatalogAddButton extends React.Component { category.emit("catalogAddMenu", context); this.menuItems.set(category.getId(), menuItems); } - }; + }); getCategoryFilteredItems = (category: CatalogCategory) => { return category.filteredItems(this.menuItems.get(category.getId()) || []); diff --git a/src/renderer/components/+catalog/catalog-tree.module.scss b/src/renderer/components/+catalog/catalog-tree.module.scss index 284b04083f..f190d04417 100644 --- a/src/renderer/components/+catalog/catalog-tree.module.scss +++ b/src/renderer/components/+catalog/catalog-tree.module.scss @@ -22,6 +22,8 @@ .content { min-height: 26px; + line-height: 1.3; + padding: 2px var(--padding) 2px 0; &:hover { background-color: var(--sidebarItemHoverBackground); @@ -39,6 +41,8 @@ .iconContainer { margin-left: 28px; + margin-top: 2px; + align-self: flex-start; } } diff --git a/src/renderer/components/+catalog/catalog.module.scss b/src/renderer/components/+catalog/catalog.module.scss index 25d564eba8..5948d64a62 100644 --- a/src/renderer/components/+catalog/catalog.module.scss +++ b/src/renderer/components/+catalog/catalog.module.scss @@ -20,6 +20,7 @@ padding: 0 var(--padding); padding-bottom: 0; padding-right: 24px; // + reserved space for .pinIcon + flex-grow: 2.5!important; > span { overflow: hidden; diff --git a/src/renderer/components/+catalog/catalog.tsx b/src/renderer/components/+catalog/catalog.tsx index 3edca9ea92..c99c24bf6b 100644 --- a/src/renderer/components/+catalog/catalog.tsx +++ b/src/renderer/components/+catalog/catalog.tsx @@ -143,8 +143,7 @@ class NonInjectedCatalog extends React.Component { return catalogCategoryRegistry.items; } - @action - onTabChange = (tabId: string | null) => { + onTabChange = action((tabId: string | null) => { const activeCategory = this.categories.find(category => category.getId() === tabId); if (activeCategory) { @@ -152,7 +151,7 @@ class NonInjectedCatalog extends React.Component { } else { navigate(catalogURL({ params: { group: browseCatalogTab }})); } - }; + }); renderNavigation() { return ( diff --git a/src/renderer/components/+catalog/get-category-columns.injectable.ts b/src/renderer/components/+catalog/get-category-columns.injectable.ts index 66fe0cddee..080fde7e29 100644 --- a/src/renderer/components/+catalog/get-category-columns.injectable.ts +++ b/src/renderer/components/+catalog/get-category-columns.injectable.ts @@ -6,7 +6,6 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import { orderBy } from "lodash"; import type { IComputedValue } from "mobx"; import type { CatalogCategory, CatalogEntity } from "../../../common/catalog"; -import { bind } from "../../utils"; import type { ItemListLayoutProps } from "../item-object-list"; import type { RegisteredAdditionalCategoryColumn } from "./custom-category-columns"; import categoryColumnsInjectable from "./custom-category-columns.injectable"; @@ -50,7 +49,7 @@ function getBrowseAllColumns(): RegisteredAdditionalCategoryColumn[] { ]; } -function getCategoryColumns({ extensionColumns }: Dependencies, { activeCategory }: GetCategoryColumnsParams): CategoryColumns { +const getCategoryColumns = ({ extensionColumns }: Dependencies) => ({ activeCategory }: GetCategoryColumnsParams): CategoryColumns => { const allRegistrations = orderBy( activeCategory ? getSpecificCategoryColumns(activeCategory, extensionColumns) @@ -83,12 +82,13 @@ function getCategoryColumns({ extensionColumns }: Dependencies, { activeCategory renderTableContents: entity => tableRowRenderers.map(fn => fn(entity)), searchFilters, }; -} +}; const getCategoryColumnsInjectable = getInjectable({ - instantiate: (di) => bind(getCategoryColumns, null, { + instantiate: (di) => getCategoryColumns({ extensionColumns: di.inject(categoryColumnsInjectable), }), + lifecycle: lifecycleEnum.singleton, }); diff --git a/src/renderer/components/+config-secrets/secret-details.tsx b/src/renderer/components/+config-secrets/secret-details.tsx index 55e6d605f5..fce67d0abc 100644 --- a/src/renderer/components/+config-secrets/secret-details.tsx +++ b/src/renderer/components/+config-secrets/secret-details.tsx @@ -12,7 +12,7 @@ import { DrawerItem, DrawerTitle } from "../drawer"; import { Input } from "../input"; import { Button } from "../button"; import { Notifications } from "../notifications"; -import { base64, ObservableToggleSet } from "../../utils"; +import { base64, toggle } from "../../utils"; import { Icon } from "../icon"; import { secretsStore } from "./secrets.store"; import type { KubeObjectDetailsProps } from "../kube-object-details"; @@ -27,7 +27,7 @@ interface Props extends KubeObjectDetailsProps { export class SecretDetails extends React.Component { @observable isSaving = false; @observable data: { [name: string]: string } = {}; - revealSecret = new ObservableToggleSet(); + revealSecret = new Set(); constructor(props: Props) { super(props); @@ -99,7 +99,7 @@ export class SecretDetails extends React.Component { this.revealSecret.toggle(name)} + onClick={() => toggle(this.revealSecret, name)} /> )} diff --git a/src/renderer/components/+extensions/attempt-install/install-request.d.ts b/src/renderer/components/+extensions/attempt-install/install-request.ts similarity index 100% rename from src/renderer/components/+extensions/attempt-install/install-request.d.ts rename to src/renderer/components/+extensions/attempt-install/install-request.ts diff --git a/src/renderer/components/+extensions/install-from-select-file-dialog.injectable.ts b/src/renderer/components/+extensions/install-from-select-file-dialog.injectable.ts index 5cf51733d1..eb1597f61f 100644 --- a/src/renderer/components/+extensions/install-from-select-file-dialog.injectable.ts +++ b/src/renderer/components/+extensions/install-from-select-file-dialog.injectable.ts @@ -7,14 +7,13 @@ import { requestOpenFilePickingDialog } from "../../ipc"; import { supportedExtensionFormats } from "./supported-extension-formats"; import attemptInstallsInjectable from "./attempt-installs/attempt-installs.injectable"; import directoryForDownloadsInjectable from "../../../common/app-paths/directory-for-downloads/directory-for-downloads.injectable"; -import { bind } from "../../utils"; interface Dependencies { attemptInstalls: (filePaths: string[]) => Promise directoryForDownloads: string } -async function installFromSelectFileDialog({ attemptInstalls, directoryForDownloads }: Dependencies) { +const installFromSelectFileDialog = ({ attemptInstalls, directoryForDownloads }: Dependencies) => async () => { const { canceled, filePaths } = await requestOpenFilePickingDialog({ defaultPath: directoryForDownloads, properties: ["openFile", "multiSelections"], @@ -26,13 +25,14 @@ async function installFromSelectFileDialog({ attemptInstalls, directoryForDownlo if (!canceled) { await attemptInstalls(filePaths); } -} +}; const installFromSelectFileDialogInjectable = getInjectable({ - instantiate: (di) => bind(installFromSelectFileDialog, null, { + instantiate: (di) => installFromSelectFileDialog({ attemptInstalls: di.inject(attemptInstallsInjectable), directoryForDownloads: di.inject(directoryForDownloadsInjectable), }), + lifecycle: lifecycleEnum.singleton, }); diff --git a/src/renderer/components/+namespaces/namespace-store/namespace.store.ts b/src/renderer/components/+namespaces/namespace-store/namespace.store.ts index 00cfd6748a..4066070cc3 100644 --- a/src/renderer/components/+namespaces/namespace-store/namespace.store.ts +++ b/src/renderer/components/+namespaces/namespace-store/namespace.store.ts @@ -4,7 +4,7 @@ */ import { action, comparer, computed, IReactionDisposer, makeObservable, reaction } from "mobx"; -import { autoBind, noop, StorageHelper, ToggleSet } from "../../../utils"; +import { autoBind, noop, StorageHelper, toggle } from "../../../utils"; import { KubeObjectStore, KubeObjectStoreLoadingParams } from "../../../../common/k8s-api/kube-object.store"; import { Namespace, namespacesApi } from "../../../../common/k8s-api/endpoints/namespaces.api"; @@ -175,10 +175,10 @@ export class NamespaceStore extends KubeObjectStore { */ @action toggleContext(namespaces: string | string[]) { - const nextState = new ToggleSet(this.contextNamespaces); + const nextState = new Set(this.contextNamespaces); for (const namespace of [namespaces].flat()) { - nextState.toggle(namespace); + toggle(nextState, namespace); } this.dependencies.storage.set([...nextState]); @@ -191,9 +191,9 @@ export class NamespaceStore extends KubeObjectStore { * @param namespace The name of a namespace */ toggleSingle(namespace: string) { - const nextState = new ToggleSet(this.contextNamespaces); + const nextState = new Set(this.contextNamespaces); - nextState.toggle(namespace); + toggle(nextState, namespace); this.dependencies.storage.set([...nextState]); } diff --git a/src/renderer/components/+network-port-forwards/port-forwards.tsx b/src/renderer/components/+network-port-forwards/port-forwards.tsx index b3e7e4c1f3..9ceeadba38 100644 --- a/src/renderer/components/+network-port-forwards/port-forwards.tsx +++ b/src/renderer/components/+network-port-forwards/port-forwards.tsx @@ -8,7 +8,7 @@ import "./port-forwards.scss"; import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; import type { RouteComponentProps } from "react-router-dom"; -import { ItemListLayout } from "../item-object-list/item-list-layout"; +import { ItemListLayout } from "../item-object-list/list-layout"; import type { PortForwardItem, PortForwardStore } from "../../port-forward"; import { PortForwardMenu } from "./port-forward-menu"; import { PortForwardsRouteParams, portForwardsURL } from "../../../common/routes"; diff --git a/src/renderer/components/+preferences/app-preferences/app-preference-registration.d.ts b/src/renderer/components/+preferences/app-preferences/app-preference-registration.ts similarity index 100% rename from src/renderer/components/+preferences/app-preferences/app-preference-registration.d.ts rename to src/renderer/components/+preferences/app-preferences/app-preference-registration.ts diff --git a/src/renderer/components/+preferences/kubeconfig-syncs.tsx b/src/renderer/components/+preferences/kubeconfig-syncs.tsx index 0594ea4de9..bbe4438226 100644 --- a/src/renderer/components/+preferences/kubeconfig-syncs.tsx +++ b/src/renderer/components/+preferences/kubeconfig-syncs.tsx @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import fse from "fs-extra"; -import { action, computed, makeObservable, observable, reaction } from "mobx"; +import { computed, makeObservable, observable, reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import React from "react"; import { Notice } from "../+extensions/notice"; @@ -93,7 +93,6 @@ export class KubeconfigSyncs extends React.Component { return Array.from(this.syncs.entries(), ([filePath, value]) => ({ filePath, ...value })); } - @action onPick = async (filePaths: string[]) => multiSet(this.syncs, await getAllEntries(filePaths)); getIconName(entry: Entry) { diff --git a/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx b/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx index ed11dfd800..3823b2213e 100644 --- a/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx +++ b/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx @@ -115,8 +115,7 @@ export class ClusterRoleBindingDialog extends React.Component { return this.serviceAccountOptions.filter(({ value }) => this.selectedAccounts.has(value)); } - @action - onOpen = () => { + onOpen = action(() => { const binding = this.clusterRoleBinding; if (!binding) { @@ -137,16 +136,15 @@ export class ClusterRoleBindingDialog extends React.Component { ); this.selectedUsers.replace(uSubjects.map(user => user.name)); this.selectedGroups.replace(gSubjects.map(group => group.name)); - }; + }); - @action - reset = () => { + reset = action(() => { this.selectedRoleRef = undefined; this.bindingName = ""; this.selectedAccounts.clear(); this.selectedUsers.clear(); this.selectedGroups.clear(); - }; + }); createBindings = async () => { const { selectedRoleRef, selectedBindings, bindingName } = this; diff --git a/src/renderer/components/+user-management/+role-bindings/dialog.tsx b/src/renderer/components/+user-management/+role-bindings/dialog.tsx index 8cb4d893d9..29cb771432 100644 --- a/src/renderer/components/+user-management/+role-bindings/dialog.tsx +++ b/src/renderer/components/+user-management/+role-bindings/dialog.tsx @@ -116,8 +116,7 @@ export class RoleBindingDialog extends React.Component { return this.serviceAccountOptions.filter(({ value }) => this.selectedAccounts.has(value)); } - @action - onOpen = () => { + onOpen = action(() => { const binding = this.roleBinding; if (!binding) { @@ -140,17 +139,16 @@ export class RoleBindingDialog extends React.Component { ); this.selectedUsers.replace(uSubjects.map(user => user.name)); this.selectedGroups.replace(gSubjects.map(group => group.name)); - }; + }); - @action - reset = () => { + reset = action(() => { this.selectedRoleRef = undefined; this.bindingName = ""; this.bindingNamespace = ""; this.selectedAccounts.clear(); this.selectedUsers.clear(); this.selectedGroups.clear(); - }; + }); createBindings = async () => { const { selectedRoleRef, bindingNamespace: namespace, selectedBindings } = this; diff --git a/src/renderer/components/+user-management/+service-accounts/details.tsx b/src/renderer/components/+user-management/+service-accounts/details.tsx index 081d44aa81..dec10fa678 100644 --- a/src/renderer/components/+user-management/+service-accounts/details.tsx +++ b/src/renderer/components/+user-management/+service-accounts/details.tsx @@ -28,27 +28,30 @@ export class ServiceAccountsDetails extends React.Component { @observable secrets: Secret[]; @observable imagePullSecrets: Secret[]; - @disposeOnUnmount - loadSecrets = autorun(async () => { - this.secrets = null; - this.imagePullSecrets = null; - const { object: serviceAccount } = this.props; + componentDidMount(): void { + disposeOnUnmount(this, [ + autorun(async () => { + this.secrets = null; + this.imagePullSecrets = null; + const { object: serviceAccount } = this.props; - if (!serviceAccount) { - return; - } - const namespace = serviceAccount.getNs(); - const secrets = serviceAccount.getSecrets().map(({ name }) => { - return secretsStore.load({ name, namespace }); - }); + if (!serviceAccount) { + return; + } + const namespace = serviceAccount.getNs(); + const secrets = serviceAccount.getSecrets().map(({ name }) => { + return secretsStore.load({ name, namespace }); + }); - this.secrets = await Promise.all(secrets); - const imagePullSecrets = serviceAccount.getImagePullSecrets().map(async ({ name }) => { - return secretsStore.load({ name, namespace }).catch(() => this.generateDummySecretObject(name)); - }); + this.secrets = await Promise.all(secrets); + const imagePullSecrets = serviceAccount.getImagePullSecrets().map(async ({ name }) => { + return secretsStore.load({ name, namespace }).catch(() => this.generateDummySecretObject(name)); + }); - this.imagePullSecrets = await Promise.all(imagePullSecrets); - }); + this.imagePullSecrets = await Promise.all(imagePullSecrets); + }), + ]); + } constructor(props: Props) { super(props); diff --git a/src/renderer/components/+user-management/+service-accounts/service-account-menu.tsx b/src/renderer/components/+user-management/+service-accounts/service-account-menu.tsx new file mode 100644 index 0000000000..6fc180a2e9 --- /dev/null +++ b/src/renderer/components/+user-management/+service-accounts/service-account-menu.tsx @@ -0,0 +1,22 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; + +import type { KubeObjectMenuProps } from "../../kube-object-menu"; +import type { ServiceAccount } from "../../../../common/k8s-api/endpoints"; +import { MenuItem } from "../../menu"; +import { openServiceAccountKubeConfig } from "../../kubeconfig-dialog"; +import { Icon } from "../../icon"; + +export function ServiceAccountMenu(props: KubeObjectMenuProps) { + const { object, toolbar } = props; + + return ( + openServiceAccountKubeConfig(object)}> + + Kubeconfig + + ); +} diff --git a/src/renderer/components/+user-management/+service-accounts/view.tsx b/src/renderer/components/+user-management/+service-accounts/view.tsx index 84721fe8d5..94c7370639 100644 --- a/src/renderer/components/+user-management/+service-accounts/view.tsx +++ b/src/renderer/components/+user-management/+service-accounts/view.tsx @@ -8,13 +8,8 @@ import "./view.scss"; import { observer } from "mobx-react"; import React from "react"; import type { RouteComponentProps } from "react-router"; -import type { ServiceAccount } from "../../../../common/k8s-api/endpoints/service-accounts.api"; -import { Icon } from "../../icon"; import { KubeObjectListLayout } from "../../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../../kube-object-status-icon"; -import type { KubeObjectMenuProps } from "../../kube-object-menu"; -import { openServiceAccountKubeConfig } from "../../kubeconfig-dialog"; -import { MenuItem } from "../../menu"; import { CreateServiceAccountDialog } from "./create-dialog"; import { serviceAccountsStore } from "./store"; import type { ServiceAccountsRouteParams } from "../../../../common/routes"; @@ -58,9 +53,6 @@ export class ServiceAccounts extends React.Component { account.getNs(), account.getAge(), ]} - renderItemMenu={(item: ServiceAccount) => { - return ; - }} addRemoveButtons={{ onAdd: () => CreateServiceAccountDialog.open(), addTooltip: "Create new Service Account", @@ -72,13 +64,3 @@ export class ServiceAccounts extends React.Component { } } -export function ServiceAccountMenu(props: KubeObjectMenuProps) { - const { object, toolbar } = props; - - return ( - openServiceAccountKubeConfig(object)}> - - Kubeconfig - - ); -} diff --git a/src/renderer/components/+welcome/welcome-banner-items/welcome-banner-registration.d.ts b/src/renderer/components/+welcome/welcome-banner-items/welcome-banner-registration.ts similarity index 100% rename from src/renderer/components/+welcome/welcome-banner-items/welcome-banner-registration.d.ts rename to src/renderer/components/+welcome/welcome-banner-items/welcome-banner-registration.ts diff --git a/src/renderer/components/+welcome/welcome-menu-items/welcome-menu-registration.d.ts b/src/renderer/components/+welcome/welcome-menu-items/welcome-menu-registration.ts similarity index 100% rename from src/renderer/components/+welcome/welcome-menu-items/welcome-menu-registration.d.ts rename to src/renderer/components/+welcome/welcome-menu-items/welcome-menu-registration.ts diff --git a/src/renderer/components/+workloads-cronjobs/cron-job-menu.tsx b/src/renderer/components/+workloads-cronjobs/cron-job-menu.tsx new file mode 100644 index 0000000000..b7f6184519 --- /dev/null +++ b/src/renderer/components/+workloads-cronjobs/cron-job-menu.tsx @@ -0,0 +1,63 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import type { KubeObjectMenuProps } from "../kube-object-menu"; +import { CronJob, cronJobApi } from "../../../common/k8s-api/endpoints"; +import { MenuItem } from "../menu"; +import { CronJobTriggerDialog } from "./cronjob-trigger-dialog"; +import { Icon } from "../icon"; +import { ConfirmDialog } from "../confirm-dialog"; +import { Notifications } from "../notifications"; + +export function CronJobMenu(props: KubeObjectMenuProps) { + const { object, toolbar } = props; + + return ( + <> + CronJobTriggerDialog.open(object)}> + + Trigger + + + {object.isSuspend() ? + ConfirmDialog.open({ + ok: async () => { + try { + await cronJobApi.resume({ namespace: object.getNs(), name: object.getName() }); + } catch (err) { + Notifications.error(err); + } + }, + labelOk: `Resume`, + message: ( +

+ Resume CronJob {object.getName()}? +

), + })}> + + Resume +
+ + : ConfirmDialog.open({ + ok: async () => { + try { + await cronJobApi.suspend({ namespace: object.getNs(), name: object.getName() }); + } catch (err) { + Notifications.error(err); + } + }, + labelOk: `Suspend`, + message: ( +

+ Suspend CronJob {object.getName()}? +

), + })}> + + Suspend +
+ } + + ); +} diff --git a/src/renderer/components/+workloads-cronjobs/cronjobs.tsx b/src/renderer/components/+workloads-cronjobs/cronjobs.tsx index 2bb2de3277..30e476502e 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjobs.tsx +++ b/src/renderer/components/+workloads-cronjobs/cronjobs.tsx @@ -8,18 +8,11 @@ import "./cronjobs.scss"; import React from "react"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router"; -import { CronJob, cronJobApi } from "../../../common/k8s-api/endpoints/cron-job.api"; -import { MenuItem } from "../menu"; -import { Icon } from "../icon"; import { cronJobStore } from "./cronjob.store"; import { jobStore } from "../+workloads-jobs/job.store"; import { eventStore } from "../+events/event.store"; -import type { KubeObjectMenuProps } from "../kube-object-menu"; import { KubeObjectListLayout } from "../kube-object-list-layout"; -import { CronJobTriggerDialog } from "./cronjob-trigger-dialog"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; -import { ConfirmDialog } from "../confirm-dialog/confirm-dialog"; -import { Notifications } from "../notifications/notifications"; import type { CronJobsRouteParams } from "../../../common/routes"; import moment from "moment"; @@ -82,61 +75,8 @@ export class CronJobs extends React.Component { cronJob.getLastScheduleTime(), cronJob.getAge(), ]} - renderItemMenu={(item: CronJob) => { - return ; - }} /> ); } } -export function CronJobMenu(props: KubeObjectMenuProps) { - const { object, toolbar } = props; - - return ( - <> - CronJobTriggerDialog.open(object)}> - - Trigger - - - {object.isSuspend() ? - ConfirmDialog.open({ - ok: async () => { - try { - await cronJobApi.resume({ namespace: object.getNs(), name: object.getName() }); - } catch (err) { - Notifications.error(err); - } - }, - labelOk: `Resume`, - message: ( -

- Resume CronJob {object.getName()}? -

), - })}> - - Resume -
- - : ConfirmDialog.open({ - ok: async () => { - try { - await cronJobApi.suspend({ namespace: object.getNs(), name: object.getName() }); - } catch (err) { - Notifications.error(err); - } - }, - labelOk: `Suspend`, - message: ( -

- Suspend CronJob {object.getName()}? -

), - })}> - - Suspend -
- } - - ); -} diff --git a/src/renderer/components/+workloads-deployments/deployment-menu.tsx b/src/renderer/components/+workloads-deployments/deployment-menu.tsx new file mode 100644 index 0000000000..9c7544a1c4 --- /dev/null +++ b/src/renderer/components/+workloads-deployments/deployment-menu.tsx @@ -0,0 +1,47 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import type { KubeObjectMenuProps } from "../kube-object-menu"; +import { Deployment, deploymentApi } from "../../../common/k8s-api/endpoints"; +import { MenuItem } from "../menu"; +import { DeploymentScaleDialog } from "./deployment-scale-dialog"; +import { Icon } from "../icon"; +import { ConfirmDialog } from "../confirm-dialog"; +import { Notifications } from "../notifications"; + +export function DeploymentMenu(props: KubeObjectMenuProps) { + const { object, toolbar } = props; + + return ( + <> + DeploymentScaleDialog.open(object)}> + + Scale + + ConfirmDialog.open({ + ok: async () => + { + try { + await deploymentApi.restart({ + namespace: object.getNs(), + name: object.getName(), + }); + } catch (err) { + Notifications.error(err); + } + }, + labelOk: `Restart`, + message: ( +

+ Are you sure you want to restart deployment {object.getName()}? +

+ ), + })}> + + Restart +
+ + ); +} diff --git a/src/renderer/components/+workloads-deployments/deployments.tsx b/src/renderer/components/+workloads-deployments/deployments.tsx index 09c7c676f4..3506db0486 100644 --- a/src/renderer/components/+workloads-deployments/deployments.tsx +++ b/src/renderer/components/+workloads-deployments/deployments.tsx @@ -8,12 +8,7 @@ import "./deployments.scss"; import React from "react"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router"; -import { Deployment, deploymentApi } from "../../../common/k8s-api/endpoints"; -import type { KubeObjectMenuProps } from "../kube-object-menu"; -import { MenuItem } from "../menu"; -import { Icon } from "../icon"; -import { DeploymentScaleDialog } from "./deployment-scale-dialog"; -import { ConfirmDialog } from "../confirm-dialog"; +import type { Deployment } from "../../../common/k8s-api/endpoints"; import { deploymentStore } from "./deployments.store"; import { eventStore } from "../+events/event.store"; import { KubeObjectListLayout } from "../kube-object-list-layout"; @@ -21,7 +16,6 @@ import { cssNames } from "../../utils"; import kebabCase from "lodash/kebabCase"; import orderBy from "lodash/orderBy"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; -import { Notifications } from "../notifications"; import type { DeploymentsRouteParams } from "../../../common/routes"; enum columnId { @@ -91,43 +85,7 @@ export class Deployments extends React.Component { deployment.getAge(), this.renderConditions(deployment), ]} - renderItemMenu={item => } /> ); } } - -export function DeploymentMenu(props: KubeObjectMenuProps) { - const { object, toolbar } = props; - - return ( - <> - DeploymentScaleDialog.open(object)}> - - Scale - - ConfirmDialog.open({ - ok: async () => - { - try { - await deploymentApi.restart({ - namespace: object.getNs(), - name: object.getName(), - }); - } catch (err) { - Notifications.error(err); - } - }, - labelOk: `Restart`, - message: ( -

- Are you sure you want to restart deployment {object.getName()}? -

- ), - })}> - - Restart -
- - ); -} diff --git a/src/renderer/components/+workloads-pods/pod-details-secrets.tsx b/src/renderer/components/+workloads-pods/pod-details-secrets.tsx index 1c354b227f..86896ce934 100644 --- a/src/renderer/components/+workloads-pods/pod-details-secrets.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-secrets.tsx @@ -20,19 +20,22 @@ interface Props { export class PodDetailsSecrets extends Component { @observable secrets: Map = observable.map(); - @disposeOnUnmount - secretsLoader = autorun(async () => { - const { pod } = this.props; + componentDidMount(): void { + disposeOnUnmount(this, [ + autorun(async () => { + const { pod } = this.props; - const secrets = await Promise.all( - pod.getSecrets().map(secretName => secretsApi.get({ - name: secretName, - namespace: pod.getNs(), - })), - ); + const secrets = await Promise.all( + pod.getSecrets().map(secretName => secretsApi.get({ + name: secretName, + namespace: pod.getNs(), + })), + ); - secrets.forEach(secret => secret && this.secrets.set(secret.getName(), secret)); - }); + secrets.forEach(secret => secret && this.secrets.set(secret.getName(), secret)); + }), + ]); + } constructor(props: Props) { super(props); diff --git a/src/renderer/components/+workloads-replicasets/replica-set-menu.tsx b/src/renderer/components/+workloads-replicasets/replica-set-menu.tsx new file mode 100644 index 0000000000..deab2193cd --- /dev/null +++ b/src/renderer/components/+workloads-replicasets/replica-set-menu.tsx @@ -0,0 +1,23 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import type { KubeObjectMenuProps } from "../kube-object-menu"; +import type { ReplicaSet } from "../../../common/k8s-api/endpoints"; +import { MenuItem } from "../menu"; +import { ReplicaSetScaleDialog } from "./replicaset-scale-dialog"; +import { Icon } from "../icon"; + +export function ReplicaSetMenu(props: KubeObjectMenuProps) { + const { object, toolbar } = props; + + return ( + <> + ReplicaSetScaleDialog.open(object)}> + + Scale + + + ); +} diff --git a/src/renderer/components/+workloads-replicasets/replicasets.tsx b/src/renderer/components/+workloads-replicasets/replicasets.tsx index c76f11131d..be21604719 100644 --- a/src/renderer/components/+workloads-replicasets/replicasets.tsx +++ b/src/renderer/components/+workloads-replicasets/replicasets.tsx @@ -7,15 +7,10 @@ import "./replicasets.scss"; import React from "react"; import { observer } from "mobx-react"; -import type { ReplicaSet } from "../../../common/k8s-api/endpoints"; -import type { KubeObjectMenuProps } from "../kube-object-menu"; import { replicaSetStore } from "./replicasets.store"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { RouteComponentProps } from "react-router"; import { KubeObjectListLayout } from "../kube-object-list-layout"; -import { MenuItem } from "../menu/menu"; -import { Icon } from "../icon/icon"; -import { ReplicaSetScaleDialog } from "./replicaset-scale-dialog"; import type { ReplicaSetsRouteParams } from "../../../common/routes"; import { eventStore } from "../+events/event.store"; @@ -70,23 +65,8 @@ export class ReplicaSets extends React.Component { replicaSet.getReady(), replicaSet.getAge(), ]} - renderItemMenu={(item: ReplicaSet) => { - return ; - }} /> ); } } -export function ReplicaSetMenu(props: KubeObjectMenuProps) { - const { object, toolbar } = props; - - return ( - <> - ReplicaSetScaleDialog.open(object)}> - - Scale - - - ); -} diff --git a/src/renderer/components/+workloads-statefulsets/stateful-set-menu.tsx b/src/renderer/components/+workloads-statefulsets/stateful-set-menu.tsx new file mode 100644 index 0000000000..b9725f6e13 --- /dev/null +++ b/src/renderer/components/+workloads-statefulsets/stateful-set-menu.tsx @@ -0,0 +1,23 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import type { KubeObjectMenuProps } from "../kube-object-menu"; +import type { StatefulSet } from "../../../common/k8s-api/endpoints"; +import { MenuItem } from "../menu"; +import { StatefulSetScaleDialog } from "./statefulset-scale-dialog"; +import { Icon } from "../icon"; + +export function StatefulSetMenu(props: KubeObjectMenuProps) { + const { object, toolbar } = props; + + return ( + <> + StatefulSetScaleDialog.open(object)}> + + Scale + + + ); +} diff --git a/src/renderer/components/+workloads-statefulsets/statefulsets.tsx b/src/renderer/components/+workloads-statefulsets/statefulsets.tsx index 1b4a967282..d7aa9e847f 100644 --- a/src/renderer/components/+workloads-statefulsets/statefulsets.tsx +++ b/src/renderer/components/+workloads-statefulsets/statefulsets.tsx @@ -12,12 +12,8 @@ import type { StatefulSet } from "../../../common/k8s-api/endpoints"; import { podsStore } from "../+workloads-pods/pods.store"; import { statefulSetStore } from "./statefulset.store"; import { eventStore } from "../+events/event.store"; -import type { KubeObjectMenuProps } from "../kube-object-menu"; import { KubeObjectListLayout } from "../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; -import { StatefulSetScaleDialog } from "./statefulset-scale-dialog"; -import { MenuItem } from "../menu/menu"; -import { Icon } from "../icon/icon"; import type { StatefulSetsRouteParams } from "../../../common/routes"; enum columnId { @@ -72,21 +68,7 @@ export class StatefulSets extends React.Component { , statefulSet.getAge(), ]} - renderItemMenu={item => } /> ); } } - -export function StatefulSetMenu(props: KubeObjectMenuProps) { - const { object, toolbar } = props; - - return ( - <> - StatefulSetScaleDialog.open(object)}> - - Scale - - - ); -} diff --git a/src/renderer/components/cluster-manager/bottom-bar-items.injectable.ts b/src/renderer/components/cluster-manager/bottom-bar-items.injectable.ts new file mode 100644 index 0000000000..9f32831ca6 --- /dev/null +++ b/src/renderer/components/cluster-manager/bottom-bar-items.injectable.ts @@ -0,0 +1,28 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { computed } from "mobx"; +import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable"; +import type { StatusBarRegistration } from "./status-bar-registration"; + +const bottomBarItemsInjectable = getInjectable({ + instantiate: (di) => { + const extensions = di.inject(rendererExtensionsInjectable); + + return computed(() => + extensions + .get() + .flatMap((extension) => extension.statusBarItems) + .sort(leftItemsBeforeRight), + ); + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default bottomBarItemsInjectable; + +const leftItemsBeforeRight = (firstItem: StatusBarRegistration, secondItem: StatusBarRegistration) => + firstItem.components?.position?.localeCompare(secondItem.components?.position); diff --git a/src/renderer/components/cluster-manager/bottom-bar.test.tsx b/src/renderer/components/cluster-manager/bottom-bar.test.tsx index 97539f0ea3..523500629c 100644 --- a/src/renderer/components/cluster-manager/bottom-bar.test.tsx +++ b/src/renderer/components/cluster-manager/bottom-bar.test.tsx @@ -4,10 +4,15 @@ */ import React from "react"; -import { render } from "@testing-library/react"; import "@testing-library/jest-dom/extend-expect"; import { BottomBar } from "./bottom-bar"; -import { StatusBarRegistry } from "../../../extensions/registries"; +import { getDiForUnitTesting } from "../../getDiForUnitTesting"; +import type { DiRender } from "../test-utils/renderFor"; +import { renderFor } from "../test-utils/renderFor"; +import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; +import { LensRendererExtension } from "../../../extensions/lens-renderer-extension"; +import { computed, IObservableArray, observable, runInAction } from "mobx"; +import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable"; jest.mock("electron", () => ({ app: { @@ -15,13 +20,43 @@ jest.mock("electron", () => ({ }, })); -describe("", () => { - beforeEach(() => { - StatusBarRegistry.createInstance(); - }); +class SomeTestExtension extends LensRendererExtension { + constructor(statusBarItems: IObservableArray) { + super({ + id: "some-id", + absolutePath: "irrelevant", + isBundled: false, + isCompatible: false, + isEnabled: false, + manifest: { name: "some-id", version: "some-version" }, + manifestPath: "irrelevant", + }); - afterEach(() => { - StatusBarRegistry.resetInstance(); + this.statusBarItems = statusBarItems; + } +} + +describe("", () => { + let render: DiRender; + let statusBarItems: IObservableArray; + + beforeEach(async () => { + + statusBarItems = observable.array([]); + + const someTestExtension = new SomeTestExtension(statusBarItems); + + const di = getDiForUnitTesting({ doGeneralOverrides: true }); + + di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data"); + + di.override(rendererExtensionsInjectable, () => { + return computed(() => [someTestExtension]); + }); + + render = renderFor(di); + + await di.runSetups(); }); it("renders w/o errors", () => { @@ -30,6 +65,7 @@ describe("", () => { expect(container).toBeInstanceOf(HTMLElement); }); + it.each([ undefined, "hello", @@ -39,7 +75,10 @@ describe("", () => { [{}], {}, ])("renders w/o errors when .getItems() returns not type compliant (%p)", val => { - StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => val); + runInAction(() => { + statusBarItems.replace([val]); + }); + expect(() => render()).not.toThrow(); }); @@ -47,9 +86,12 @@ describe("", () => { const testId = "testId"; const text = "heee"; - StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [ - { item: {text} }, - ]); + runInAction(() => { + statusBarItems.replace([ + { item: {text} }, + ]); + }); + const { getByTestId } = render(); expect(getByTestId(testId)).toHaveTextContent(text); @@ -59,9 +101,12 @@ describe("", () => { const testId = "testId"; const text = "heee"; - StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [ - { item: () => {text} }, - ]); + runInAction(() => { + statusBarItems.replace([ + { item: () => {text} }, + ]); + }); + const { getByTestId } = render(); expect(getByTestId(testId)).toHaveTextContent(text); @@ -69,31 +114,33 @@ describe("", () => { it("sort positioned items properly", () => { - StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [ - { - components: { - Item: () =>
right
, + runInAction(() => { + statusBarItems.replace([ + { + components: { + Item: () =>
right
, + }, }, - }, - { - components: { - Item: () =>
right
, - position: "right", + { + components: { + Item: () =>
right
, + position: "right", + }, }, - }, - { - components: { - Item: () =>
left
, - position: "left", + { + components: { + Item: () =>
left
, + position: "left", + }, }, - }, - { - components: { - Item: () =>
left
, - position: "left", + { + components: { + Item: () =>
left
, + position: "left", + }, }, - }, - ]); + ]); + }); const { getAllByTestId } = render(); const elems = getAllByTestId("sortedElem"); diff --git a/src/renderer/components/cluster-manager/bottom-bar.tsx b/src/renderer/components/cluster-manager/bottom-bar.tsx index 84e0f7bbc8..ecbb1634cc 100644 --- a/src/renderer/components/cluster-manager/bottom-bar.tsx +++ b/src/renderer/components/cluster-manager/bottom-bar.tsx @@ -7,11 +7,18 @@ import styles from "./bottom-bar.module.scss"; import React from "react"; import { observer } from "mobx-react"; -import { StatusBarRegistration, StatusBarRegistry } from "../../../extensions/registries"; import { cssNames } from "../../utils"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import bottomBarItemsInjectable from "./bottom-bar-items.injectable"; +import type { IComputedValue } from "mobx"; +import type { StatusBarRegistration } from "./status-bar-registration"; + +interface Dependencies { + items: IComputedValue +} @observer -export class BottomBar extends React.Component { +class NonInjectedBottomBar extends React.Component { renderRegisteredItem(registration: StatusBarRegistration) { const { item } = registration; @@ -23,19 +30,9 @@ export class BottomBar extends React.Component { } renderRegisteredItems() { - const items = StatusBarRegistry.getInstance().getItems(); - - if (!Array.isArray(items)) { - return null; - } - - items.sort(function sortLeftPositionFirst(a, b) { - return a.components?.position?.localeCompare(b.components?.position); - }); - return ( <> - {items.map((registration, index) => { + {this.props.items.get().map((registration, index) => { if (!registration?.item && !registration?.components?.Item) { return null; } @@ -64,3 +61,14 @@ export class BottomBar extends React.Component { ); } } + +export const BottomBar = withInjectables( + NonInjectedBottomBar, + + { + getProps: (di, props) => ({ + items: di.inject(bottomBarItemsInjectable), + ...props, + }), + }, +); diff --git a/src/extensions/registries/status-bar-registry.ts b/src/renderer/components/cluster-manager/status-bar-registration.ts similarity index 74% rename from src/extensions/registries/status-bar-registry.ts rename to src/renderer/components/cluster-manager/status-bar-registration.ts index e8d4661abc..2faea55cc5 100644 --- a/src/extensions/registries/status-bar-registry.ts +++ b/src/renderer/components/cluster-manager/status-bar-registration.ts @@ -2,12 +2,6 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ - -// Extensions API -> Status bar customizations - -import type React from "react"; -import { BaseRegistry } from "./base-registry"; - interface StatusBarComponents { Item?: React.ComponentType; /** @@ -28,6 +22,3 @@ export interface StatusBarRegistration extends StatusBarRegistrationV2 { */ item?: React.ReactNode; } - -export class StatusBarRegistry extends BaseRegistry { -} diff --git a/src/renderer/components/command-palette/registered-commands/commands.d.ts b/src/renderer/components/command-palette/registered-commands/commands.ts similarity index 100% rename from src/renderer/components/command-palette/registered-commands/commands.d.ts rename to src/renderer/components/command-palette/registered-commands/commands.ts diff --git a/src/renderer/components/command-palette/registered-commands/internal-commands.injectable.tsx b/src/renderer/components/command-palette/registered-commands/internal-commands.injectable.tsx index e1a3d7c46d..76e8ed7743 100644 --- a/src/renderer/components/command-palette/registered-commands/internal-commands.injectable.tsx +++ b/src/renderer/components/command-palette/registered-commands/internal-commands.injectable.tsx @@ -14,9 +14,8 @@ import { ActivateEntityCommand } from "../../activate-entity-command"; import type { CommandContext, CommandRegistration } from "./commands"; import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import commandOverlayInjectable from "../command-overlay.injectable"; -import createTerminalTabInjectable - from "../../dock/create-terminal-tab/create-terminal-tab.injectable"; -import type { DockTabCreate } from "../../dock/dock-store/dock.store"; +import createTerminalTabInjectable from "../../dock/terminal/create-terminal-tab.injectable"; +import type { DockTabCreate } from "../../dock/dock/store"; export function isKubernetesClusterActive(context: CommandContext): boolean { return context.entity?.kind === "KubernetesCluster"; diff --git a/src/renderer/components/dialog/dialog.tsx b/src/renderer/components/dialog/dialog.tsx index f339ec973e..f40f1ee91d 100644 --- a/src/renderer/components/dialog/dialog.tsx +++ b/src/renderer/components/dialog/dialog.tsx @@ -48,9 +48,6 @@ export class Dialog extends React.PureComponent { pinned: false, }; - @disposeOnUnmount - closeOnNavigate = reaction(() => navigation.toString(), () => this.close()); - public state: DialogState = { isOpen: this.props.isOpen, }; @@ -64,7 +61,13 @@ export class Dialog extends React.PureComponent { } componentDidMount() { - if (this.isOpen) this.onOpen(); + if (this.isOpen) { + this.onOpen(); + } + + disposeOnUnmount(this, [ + reaction(() => navigation.toString(), () => this.close()), + ]); } componentDidUpdate(prevProps: DialogProps) { diff --git a/src/renderer/components/dock/__test__/dock-tabs.test.tsx b/src/renderer/components/dock/__test__/dock-tabs.test.tsx index 705680317f..4be169bf7f 100644 --- a/src/renderer/components/dock/__test__/dock-tabs.test.tsx +++ b/src/renderer/components/dock/__test__/dock-tabs.test.tsx @@ -8,12 +8,12 @@ import { fireEvent } from "@testing-library/react"; import "@testing-library/jest-dom/extend-expect"; import fse from "fs-extra"; import { DockTabs } from "../dock-tabs"; -import { DockStore, DockTab, TabKind } from "../dock-store/dock.store"; +import { DockStore, DockTab, TabKind } from "../dock/store"; import { noop } from "../../../utils"; import { ThemeStore } from "../../../theme.store"; import { UserStore } from "../../../../common/user-store"; import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; +import dockStoreInjectable from "../dock/store.injectable"; import type { DiRender } from "../../test-utils/renderFor"; import { renderFor } from "../../test-utils/renderFor"; import directoryForUserDataInjectable diff --git a/src/renderer/components/dock/create-install-chart-tab/create-install-chart-tab.injectable.ts b/src/renderer/components/dock/create-install-chart-tab/create-install-chart-tab.injectable.ts deleted file mode 100644 index 8544cff719..0000000000 --- a/src/renderer/components/dock/create-install-chart-tab/create-install-chart-tab.injectable.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { createInstallChartTab } from "./create-install-chart-tab"; -import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import installChartStoreInjectable from "../install-chart-store/install-chart-store.injectable"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; - -const createInstallChartTabInjectable = getInjectable({ - instantiate: (di) => createInstallChartTab({ - installChartStore: di.inject(installChartStoreInjectable), - createDockTab: di.inject(dockStoreInjectable).createTab, - }), - - lifecycle: lifecycleEnum.singleton, -}); - -export default createInstallChartTabInjectable; diff --git a/src/renderer/components/dock/create-install-chart-tab/create-install-chart-tab.ts b/src/renderer/components/dock/create-install-chart-tab/create-install-chart-tab.ts deleted file mode 100644 index d4f6aba833..0000000000 --- a/src/renderer/components/dock/create-install-chart-tab/create-install-chart-tab.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { HelmChart } from "../../../../common/k8s-api/endpoints/helm-charts.api"; -import { - DockTab, - DockTabCreate, - DockTabCreateSpecific, - TabKind, -} from "../dock-store/dock.store"; - -import type { InstallChartStore } from "../install-chart-store/install-chart.store"; - -interface Dependencies { - createDockTab: (rawTab: DockTabCreate, addNumber: boolean) => DockTab; - installChartStore: InstallChartStore; -} - -export const createInstallChartTab = - ({ createDockTab, installChartStore }: Dependencies) => - (chart: HelmChart, tabParams: DockTabCreateSpecific = {}) => { - const { name, repo, version } = chart; - - const tab = createDockTab( - { - title: `Helm Install: ${repo}/${name}`, - ...tabParams, - kind: TabKind.INSTALL_CHART, - }, - false, - ); - - installChartStore.setData(tab.id, { - name, - repo, - version, - namespace: "default", - releaseName: "", - description: "", - }); - - return tab; - }; diff --git a/src/renderer/components/dock/create-resource-store/create-resource.store.ts b/src/renderer/components/dock/create-resource-store/create-resource.store.ts deleted file mode 100644 index 7c0c62f30b..0000000000 --- a/src/renderer/components/dock/create-resource-store/create-resource.store.ts +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import fs from "fs-extra"; -import path from "path"; -import os from "os"; -import groupBy from "lodash/groupBy"; -import filehound from "filehound"; -import { watch } from "chokidar"; -import { autoBind, StorageHelper } from "../../../utils"; -import { DockTabStorageState, DockTabStore } from "../dock-tab-store/dock-tab.store"; -import type { DockStore } from "../dock-store/dock.store"; - -interface Dependencies { - dockStore: DockStore, - createStorage: (storageKey: string, options: DockTabStorageState) => StorageHelper> -} - -export class CreateResourceStore extends DockTabStore { - constructor(protected dependencies: Dependencies) { - super(dependencies, { - storageKey: "create_resource", - }); - - autoBind(this); - fs.ensureDirSync(this.userTemplatesFolder); - } - - get lensTemplatesFolder():string { - return path.resolve(__static, "../templates/create-resource"); - } - - get userTemplatesFolder():string { - return path.join(os.homedir(), ".k8slens", "templates"); - } - - async getTemplates(templatesPath: string, defaultGroup: string) { - const templates = await filehound.create().path(templatesPath).ext(["yaml", "json"]).depth(1).find(); - - return templates ? this.groupTemplates(templates, templatesPath, defaultGroup) : {}; - } - - groupTemplates(templates: string[], templatesPath: string, defaultGroup: string) { - return groupBy(templates, (v:string) => - path.relative(templatesPath, v).split(path.sep).length>1 - ? path.parse(path.relative(templatesPath, v)).dir - : defaultGroup); - } - - async getMergedTemplates() { - const userTemplates = await this.getTemplates(this.userTemplatesFolder, "ungrouped"); - const lensTemplates = await this.getTemplates(this.lensTemplatesFolder, "lens"); - - return { ...userTemplates, ...lensTemplates }; - } - - async watchUserTemplates(callback: ()=> void){ - watch(this.userTemplatesFolder, { - depth: 1, - ignoreInitial: true, - awaitWriteFinish: { - stabilityThreshold: 500, - }, - }).on("all", () => { - callback(); - }); - } -} diff --git a/src/renderer/components/dock/create-resource-tab/create-resource-tab.injectable.ts b/src/renderer/components/dock/create-resource-tab/create-resource-tab.injectable.ts deleted file mode 100644 index daacd34c33..0000000000 --- a/src/renderer/components/dock/create-resource-tab/create-resource-tab.injectable.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { createResourceTab } from "./create-resource-tab"; -import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; - -const createResourceTabInjectable = getInjectable({ - instantiate: (di) => createResourceTab({ - dockStore: di.inject(dockStoreInjectable), - }), - - lifecycle: lifecycleEnum.singleton, -}); - -export default createResourceTabInjectable; diff --git a/src/renderer/components/dock/create-resource-tab/create-resource-tab.ts b/src/renderer/components/dock/create-resource-tab/create-resource-tab.ts deleted file mode 100644 index bea9dc05aa..0000000000 --- a/src/renderer/components/dock/create-resource-tab/create-resource-tab.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { DockStore, DockTabCreateSpecific, TabKind } from "../dock-store/dock.store"; - -interface Dependencies { - dockStore: DockStore -} - -export const createResourceTab = - ({ dockStore }: Dependencies) => - (tabParams: DockTabCreateSpecific = {}) => - dockStore.createTab({ - title: "Create resource", - ...tabParams, - kind: TabKind.CREATE_RESOURCE, - }); diff --git a/src/renderer/components/dock/create-resource.scss b/src/renderer/components/dock/create-resource.scss deleted file mode 100644 index 7191de3134..0000000000 --- a/src/renderer/components/dock/create-resource.scss +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -.CreateResource { -} diff --git a/src/renderer/components/dock/create-resource.tsx b/src/renderer/components/dock/create-resource.tsx deleted file mode 100644 index 2b6728ede6..0000000000 --- a/src/renderer/components/dock/create-resource.tsx +++ /dev/null @@ -1,184 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import "./create-resource.scss"; - -import React from "react"; -import path from "path"; -import fs from "fs-extra"; -import { GroupSelectOption, Select, SelectOption } from "../select"; -import yaml from "js-yaml"; -import { makeObservable, observable } from "mobx"; -import { observer } from "mobx-react"; -import type { CreateResourceStore } from "./create-resource-store/create-resource.store"; -import type { DockTab } from "./dock-store/dock.store"; -import { EditorPanel } from "./editor-panel"; -import { InfoPanel } from "./info-panel"; -import * as resourceApplierApi from "../../../common/k8s-api/endpoints/resource-applier.api"; -import { Notifications } from "../notifications"; -import logger from "../../../common/logger"; -import type { KubeJsonApiData } from "../../../common/k8s-api/kube-json-api"; -import { getDetailsUrl } from "../kube-detail-params"; -import { apiManager } from "../../../common/k8s-api/api-manager"; -import { prevDefault } from "../../utils"; -import { navigate } from "../../navigation"; -import { withInjectables } from "@ogre-tools/injectable-react"; -import createResourceStoreInjectable - from "./create-resource-store/create-resource-store.injectable"; - -interface Props { - tab: DockTab; -} - -interface Dependencies { - createResourceStore: CreateResourceStore -} - -@observer -class NonInjectedCreateResource extends React.Component { - @observable currentTemplates: Map = new Map(); - @observable error = ""; - @observable templates: GroupSelectOption[] = []; - - constructor(props: Props & Dependencies) { - super(props); - makeObservable(this); - } - - componentDidMount() { - this.props.createResourceStore.getMergedTemplates().then(v => this.updateGroupSelectOptions(v)); - this.props.createResourceStore.watchUserTemplates(() => this.props.createResourceStore.getMergedTemplates().then(v => this.updateGroupSelectOptions(v))); - } - - updateGroupSelectOptions(templates: Record) { - this.templates = Object.entries(templates) - .map(([name, grouping]) => this.convertToGroup(name, grouping)); - } - - convertToGroup(group: string, items: string[]): GroupSelectOption { - const options = items.map(v => ({ label: path.parse(v).name, value: v })); - - return { label: group, options }; - } - - get tabId() { - return this.props.tab.id; - } - - get data() { - return this.props.createResourceStore.getData(this.tabId); - } - - get currentTemplate() { - return this.currentTemplates.get(this.tabId) ?? null; - } - - onChange = (value: string) => { - this.error = ""; // reset first, validation goes later - this.props.createResourceStore.setData(this.tabId, value); - }; - - onError = (error: Error | string) => { - this.error = error.toString(); - }; - - onSelectTemplate = (item: SelectOption) => { - this.currentTemplates.set(this.tabId, item); - fs.readFile(item.value, "utf8").then(v => { - this.props.createResourceStore.setData(this.tabId, v); - }); - }; - - create = async (): Promise => { - if (this.error || !this.data.trim()) { - // do not save when field is empty or there is an error - return null; - } - - // skip empty documents - const resources = yaml.loadAll(this.data).filter(Boolean); - - if (resources.length === 0) { - return void logger.info("Nothing to create"); - } - - const creatingResources = resources.map(async (resource: string) => { - try { - const data: KubeJsonApiData = await resourceApplierApi.update(resource); - const { kind, apiVersion, metadata: { name, namespace }} = data; - const resourceLink = apiManager.lookupApiLink({ kind, apiVersion, name, namespace }); - - const showDetails = () => { - navigate(getDetailsUrl(resourceLink)); - close(); - }; - - const close = Notifications.ok( -

- {kind} {name} successfully created. -

, - ); - } catch (error) { - Notifications.error(error?.toString() ?? "Unknown error occured"); - } - }); - - await Promise.allSettled(creatingResources); - - return undefined; - }; - - renderControls() { - return ( -
- +
+ ); + } + + render() { + const { tabId, data, error } = this; + + return ( +
+ + +
+ ); + } +} + +export const CreateResource = withInjectables(NonInjectedCreateResource, { + getPlaceholder: () => , + + getProps: async (di, props) => ({ + createResourceTabStore: di.inject(createResourceTabStoreInjectable), + createResourceTemplates: await di.inject(createResourceTemplatesInjectable), + ...props, + }), +}); diff --git a/src/renderer/components/dock/create-terminal-tab/create-terminal-tab.injectable.ts b/src/renderer/components/dock/create-terminal-tab/create-terminal-tab.injectable.ts deleted file mode 100644 index e22ceaf273..0000000000 --- a/src/renderer/components/dock/create-terminal-tab/create-terminal-tab.injectable.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { createTerminalTab } from "./create-terminal-tab"; -import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; - -const createTerminalTabInjectable = getInjectable({ - instantiate: (di) => createTerminalTab({ - dockStore: di.inject(dockStoreInjectable), - }), - - lifecycle: lifecycleEnum.singleton, -}); - -export default createTerminalTabInjectable; diff --git a/src/renderer/components/dock/create-terminal-tab/create-terminal-tab.ts b/src/renderer/components/dock/create-terminal-tab/create-terminal-tab.ts deleted file mode 100644 index cd3c501158..0000000000 --- a/src/renderer/components/dock/create-terminal-tab/create-terminal-tab.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { - DockStore, - DockTabCreateSpecific, - TabKind, -} from "../dock-store/dock.store"; - -interface Dependencies { - dockStore: DockStore; -} - -export const createTerminalTab = - ({ dockStore }: Dependencies) => - (tabParams: DockTabCreateSpecific = {}) => - dockStore.createTab({ - title: `Terminal`, - ...tabParams, - kind: TabKind.TERMINAL, - }); diff --git a/src/renderer/components/dock/create-upgrade-chart-tab/create-upgrade-chart-tab.injectable.ts b/src/renderer/components/dock/create-upgrade-chart-tab/create-upgrade-chart-tab.injectable.ts deleted file mode 100644 index 0ba73c3abe..0000000000 --- a/src/renderer/components/dock/create-upgrade-chart-tab/create-upgrade-chart-tab.injectable.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import { createUpgradeChartTab } from "./create-upgrade-chart-tab"; -import upgradeChartStoreInjectable from "../upgrade-chart-store/upgrade-chart-store.injectable"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; - -const createUpgradeChartTabInjectable = getInjectable({ - instantiate: (di) => createUpgradeChartTab({ - upgradeChartStore: di.inject(upgradeChartStoreInjectable), - dockStore: di.inject(dockStoreInjectable), - }), - - lifecycle: lifecycleEnum.singleton, -}); - -export default createUpgradeChartTabInjectable; diff --git a/src/renderer/components/dock/create-upgrade-chart-tab/create-upgrade-chart-tab.ts b/src/renderer/components/dock/create-upgrade-chart-tab/create-upgrade-chart-tab.ts deleted file mode 100644 index 17c94c6741..0000000000 --- a/src/renderer/components/dock/create-upgrade-chart-tab/create-upgrade-chart-tab.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import { DockStore, DockTabCreateSpecific, TabKind } from "../dock-store/dock.store"; -import type { UpgradeChartStore } from "../upgrade-chart-store/upgrade-chart.store"; - -interface Dependencies { - upgradeChartStore: UpgradeChartStore; - dockStore: DockStore -} - -export const createUpgradeChartTab = - ({ upgradeChartStore, dockStore }: Dependencies) => - (release: HelmRelease, tabParams: DockTabCreateSpecific = {}) => { - let tab = upgradeChartStore.getTabByRelease(release.getName()); - - if (tab) { - dockStore.open(); - dockStore.selectTab(tab.id); - } - - if (!tab) { - tab = dockStore.createTab( - { - title: `Helm Upgrade: ${release.getName()}`, - ...tabParams, - kind: TabKind.UPGRADE_CHART, - }, - false, - ); - - upgradeChartStore.setData(tab.id, { - releaseName: release.getName(), - releaseNamespace: release.getNs(), - }); - } - - return tab; - }; diff --git a/src/renderer/components/dock/dock-store/dock-store.injectable.ts b/src/renderer/components/dock/dock-store/dock-store.injectable.ts deleted file mode 100644 index 19a47dead6..0000000000 --- a/src/renderer/components/dock/dock-store/dock-store.injectable.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import { DockStore } from "./dock.store"; -import dockStorageInjectable from "./dock-storage/dock-storage.injectable"; - -const dockStoreInjectable = getInjectable({ - instantiate: (di) => - new DockStore({ - storage: di.inject(dockStorageInjectable), - }), - - lifecycle: lifecycleEnum.singleton, -}); - -export default dockStoreInjectable; diff --git a/src/renderer/components/dock/dock-tab-store/create-dock-tab-store.injectable.ts b/src/renderer/components/dock/dock-tab-store/create-dock-tab-store.injectable.ts index 19b5af4084..ed76d8d9a6 100644 --- a/src/renderer/components/dock/dock-tab-store/create-dock-tab-store.injectable.ts +++ b/src/renderer/components/dock/dock-tab-store/create-dock-tab-store.injectable.ts @@ -4,13 +4,11 @@ */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import { DockTabStore, DockTabStoreOptions } from "./dock-tab.store"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; const createDockTabStoreInjectable = getInjectable({ instantiate: (di) => { const dependencies = { - dockStore: di.inject(dockStoreInjectable), createStorage: di.inject(createStorageInjectable), }; diff --git a/src/renderer/components/dock/dock-tab-store/dock-tab.store.ts b/src/renderer/components/dock/dock-tab-store/dock-tab.store.ts index 5bfcdd504c..ab8d4b2940 100644 --- a/src/renderer/components/dock/dock-tab-store/dock-tab.store.ts +++ b/src/renderer/components/dock/dock-tab-store/dock-tab.store.ts @@ -3,9 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { autorun, observable, reaction } from "mobx"; +import { action, observable, reaction } from "mobx"; import { autoBind, StorageHelper, toJS } from "../../../utils"; -import type { DockStore, TabId } from "../dock-store/dock.store"; +import type { TabId } from "../dock/store"; export interface DockTabStoreOptions { autoInit?: boolean; // load data from storage when `storageKey` is provided and bind events, default: true @@ -14,16 +14,15 @@ export interface DockTabStoreOptions { export type DockTabStorageState = Record; -interface Dependencies { - dockStore: DockStore +interface DockTabStoreDependencies { createStorage: (storageKey: string, options: DockTabStorageState) => StorageHelper> } export class DockTabStore { protected storage?: StorageHelper>; - protected data = observable.map(); + private data = observable.map(); - constructor(protected dependencies: Dependencies, protected options: DockTabStoreOptions) { + constructor(protected dependencies: DockTabStoreDependencies, protected options: DockTabStoreOptions) { autoBind(this); this.options = { @@ -48,17 +47,6 @@ export class DockTabStore { reaction(() => this.toJSON(), data => this.storage.set(data)); }); } - - // clear data for closed tabs - autorun(() => { - const currentTabs = this.dependencies.dockStore.tabs.map(tab => tab.id); - - Array.from(this.data.keys()).forEach(tabId => { - if (!currentTabs.includes(tabId)) { - this.clearData(tabId); - } - }); - }); } protected finalizeDataForSave(data: T): T { @@ -75,8 +63,22 @@ export class DockTabStore { return Object.fromEntries(deepCopy); } + protected getAllData() { + return this.data.toJSON(); + } + + findTabIdFromData(inspecter: (val: T) => any): TabId | undefined { + for (const [tabId, data] of this.data) { + if (inspecter(data)) { + return tabId; + } + } + + return undefined; + } + isReady(tabId: TabId): boolean { - return Boolean(this.getData(tabId) !== undefined); + return this.getData(tabId) !== undefined; } getData(tabId: TabId) { @@ -91,8 +93,11 @@ export class DockTabStore { this.data.delete(tabId); } + @action reset() { - this.data.clear(); + for (const tabId of this.data.keys()) { + this.clearData(tabId); + } this.storage?.reset(); } } diff --git a/src/renderer/components/dock/dock-tab.tsx b/src/renderer/components/dock/dock-tab.tsx index f5d7be54c2..4b91c609ba 100644 --- a/src/renderer/components/dock/dock-tab.tsx +++ b/src/renderer/components/dock/dock-tab.tsx @@ -8,14 +8,14 @@ import "./dock-tab.scss"; import React from "react"; import { observer } from "mobx-react"; import { boundMethod, cssNames, prevDefault, isMiddleClick } from "../../utils"; -import type { DockStore, DockTab as DockTabModel } from "./dock-store/dock.store"; +import type { DockStore, DockTab as DockTabModel } from "./dock/store"; import { Tab, TabProps } from "../tabs"; import { Icon } from "../icon"; import { Menu, MenuItem } from "../menu"; import { observable, makeObservable } from "mobx"; import { isMac } from "../../../common/vars"; import { withInjectables } from "@ogre-tools/injectable-react"; -import dockStoreInjectable from "./dock-store/dock-store.injectable"; +import dockStoreInjectable from "./dock/store.injectable"; export interface DockTabProps extends TabProps { moreActions?: React.ReactNode; diff --git a/src/renderer/components/dock/dock-tabs.tsx b/src/renderer/components/dock/dock-tabs.tsx index 8902fe439a..d4443cf6c0 100644 --- a/src/renderer/components/dock/dock-tabs.tsx +++ b/src/renderer/components/dock/dock-tabs.tsx @@ -8,9 +8,9 @@ import React, { Fragment } from "react"; import { Icon } from "../icon"; import { Tabs } from "../tabs/tabs"; import { DockTab } from "./dock-tab"; -import type { DockTab as DockTabModel } from "./dock-store/dock.store"; -import { TabKind } from "./dock-store/dock.store"; -import { TerminalTab } from "./terminal-tab"; +import type { DockTab as DockTabModel } from "./dock/store"; +import { TabKind } from "./dock/store"; +import { TerminalTab } from "./terminal/dock-tab"; interface Props { tabs: DockTabModel[] diff --git a/src/renderer/components/dock/dock.tsx b/src/renderer/components/dock/dock.tsx index dcc655c60d..d067931762 100644 --- a/src/renderer/components/dock/dock.tsx +++ b/src/renderer/components/dock/dock.tsx @@ -13,18 +13,19 @@ import { Icon } from "../icon"; import { MenuItem } from "../menu"; import { MenuActions } from "../menu/menu-actions"; import { ResizeDirection, ResizingAnchor } from "../resizing-anchor"; -import { CreateResource } from "./create-resource"; +import { CreateResource } from "./create-resource/view"; import { DockTabs } from "./dock-tabs"; -import { DockStore, DockTab, TabKind } from "./dock-store/dock.store"; -import { EditResource } from "./edit-resource"; -import { InstallChart } from "./install-chart"; -import { LogsDockTab } from "./logs/dock-tab"; -import { TerminalWindow } from "./terminal-window"; -import { UpgradeChart } from "./upgrade-chart"; +import { DockStore, DockTab, TabKind } from "./dock/store"; +import { EditResource } from "./edit-resource/view"; +import { InstallChart } from "./install-chart/view"; +import { LogsDockTab } from "./logs/view"; +import { TerminalWindow } from "./terminal/view"; +import { UpgradeChart } from "./upgrade-chart/view"; import { withInjectables } from "@ogre-tools/injectable-react"; -import createResourceTabInjectable from "./create-resource-tab/create-resource-tab.injectable"; -import dockStoreInjectable from "./dock-store/dock-store.injectable"; -import createTerminalTabInjectable from "./create-terminal-tab/create-terminal-tab.injectable"; +import createResourceTabInjectable from "./create-resource/create-resource-tab.injectable"; +import dockStoreInjectable from "./dock/store.injectable"; +import createTerminalTabInjectable from "./terminal/create-terminal-tab.injectable"; +import { ErrorBoundary } from "../error-boundary"; interface Props { className?: string; @@ -160,7 +161,9 @@ class NonInjectedDock extends React.Component { )} - {this.renderTabContent()} + + {this.renderTabContent()} + ); } diff --git a/src/renderer/components/dock/dock/close-dock-tab.injectable.ts b/src/renderer/components/dock/dock/close-dock-tab.injectable.ts new file mode 100644 index 0000000000..8d44637cd7 --- /dev/null +++ b/src/renderer/components/dock/dock/close-dock-tab.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { TabId } from "./store"; +import dockStoreInjectable from "./store.injectable"; + +const closeDockTabInjectable = getInjectable({ + instantiate: (di) => { + const dockStore = di.inject(dockStoreInjectable); + + return (tabId: TabId): void => { + dockStore.closeTab(tabId); + }; + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default closeDockTabInjectable; diff --git a/src/renderer/components/dock/dock/create-dock-tab.injectable.ts b/src/renderer/components/dock/dock/create-dock-tab.injectable.ts new file mode 100644 index 0000000000..1469b2e31b --- /dev/null +++ b/src/renderer/components/dock/dock/create-dock-tab.injectable.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import dockStoreInjectable from "./store.injectable"; +import type { DockTab, DockTabCreate } from "./store"; + +const createDockTabInjectable = getInjectable({ + instantiate: (di) => { + const dockStore = di.inject(dockStoreInjectable); + + return (rawTabDesc: DockTabCreate, addNumber?: boolean): DockTab => + dockStore.createTab(rawTabDesc, addNumber); + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default createDockTabInjectable; diff --git a/src/renderer/components/dock/dock-store/dock-storage/dock-storage.injectable.ts b/src/renderer/components/dock/dock/dock-storage.injectable.ts similarity index 81% rename from src/renderer/components/dock/dock-store/dock-storage/dock-storage.injectable.ts rename to src/renderer/components/dock/dock/dock-storage.injectable.ts index 56e6edd37e..e58127761f 100644 --- a/src/renderer/components/dock/dock-store/dock-storage/dock-storage.injectable.ts +++ b/src/renderer/components/dock/dock/dock-storage.injectable.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import createStorageInjectable from "../../../../utils/create-storage/create-storage.injectable"; -import { DockStorageState, TabKind } from "../dock.store"; +import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; +import { DockStorageState, TabKind } from "./store"; const dockStorageInjectable = getInjectable({ instantiate: (di) => { diff --git a/src/renderer/components/dock/dock/rename-tab.injectable.ts b/src/renderer/components/dock/dock/rename-tab.injectable.ts new file mode 100644 index 0000000000..38ceb4dcbe --- /dev/null +++ b/src/renderer/components/dock/dock/rename-tab.injectable.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import dockStoreInjectable from "./store.injectable"; +import type { TabId } from "./store"; + +const renameTabInjectable = getInjectable({ + + instantiate: (di) => { + const dockStore = di.inject(dockStoreInjectable); + + return (tabId: TabId, title: string): void => { + dockStore.renameTab(tabId, title); + }; + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default renameTabInjectable; diff --git a/src/renderer/components/dock/dock/select-dock-tab.injectable.ts b/src/renderer/components/dock/dock/select-dock-tab.injectable.ts new file mode 100644 index 0000000000..39830db90c --- /dev/null +++ b/src/renderer/components/dock/dock/select-dock-tab.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { TabId } from "./store"; +import dockStoreInjectable from "./store.injectable"; + +const selectDockTabInjectable = getInjectable({ + instantiate: (di) => { + const dockStore = di.inject(dockStoreInjectable); + + return (tabId: TabId): void => { + dockStore.selectTab(tabId); + }; + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default selectDockTabInjectable; diff --git a/src/renderer/components/dock/dock/store.injectable.ts b/src/renderer/components/dock/dock/store.injectable.ts new file mode 100644 index 0000000000..b61450ea54 --- /dev/null +++ b/src/renderer/components/dock/dock/store.injectable.ts @@ -0,0 +1,35 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { DockStore, TabKind } from "./store"; +import dockStorageInjectable from "./dock-storage.injectable"; +import clearLogTabDataInjectable from "../logs/clear-log-tab-data.injectable"; +import clearUpgradeChartTabDataInjectable from "../upgrade-chart/clear-upgrade-chart-tab-data.injectable"; +import clearCreateResourceTabDataInjectable from "../create-resource/clear-create-resource-tab-data.injectable"; +import clearEditResourceTabDataInjectable from "../edit-resource/clear-edit-resource-tab-data.injectable"; +import clearTerminalTabDataInjectable from "../terminal/clear-terminal-tab-data.injectable"; +import clearInstallChartTabDataInjectable from "../install-chart/clear-install-chart-tab-data.injectable"; +import isLogsTabDataValidInjectable from "../logs/is-logs-tab-data-valid.injectable"; + +const dockStoreInjectable = getInjectable({ + instantiate: (di) => new DockStore({ + storage: di.inject(dockStorageInjectable), + tabDataClearers: { + [TabKind.POD_LOGS]: di.inject(clearLogTabDataInjectable), + [TabKind.UPGRADE_CHART]: di.inject(clearUpgradeChartTabDataInjectable), + [TabKind.CREATE_RESOURCE]: di.inject(clearCreateResourceTabDataInjectable), + [TabKind.EDIT_RESOURCE]: di.inject(clearEditResourceTabDataInjectable), + [TabKind.INSTALL_CHART]: di.inject(clearInstallChartTabDataInjectable), + [TabKind.TERMINAL]: di.inject(clearTerminalTabDataInjectable), + }, + tabDataValidator: { + [TabKind.POD_LOGS]: di.inject(isLogsTabDataValidInjectable), + }, + }), + + lifecycle: lifecycleEnum.singleton, +}); + +export default dockStoreInjectable; diff --git a/src/renderer/components/dock/dock-store/dock.store.ts b/src/renderer/components/dock/dock/store.ts similarity index 92% rename from src/renderer/components/dock/dock-store/dock.store.ts rename to src/renderer/components/dock/dock/store.ts index b551496e7e..3cbe3c03aa 100644 --- a/src/renderer/components/dock/dock-store/dock.store.ts +++ b/src/renderer/components/dock/dock/store.ts @@ -98,11 +98,13 @@ export interface DockTabCloseEvent { } interface Dependencies { - storage: StorageHelper + readonly storage: StorageHelper + readonly tabDataClearers: Record void>; + readonly tabDataValidator: Partial boolean>>; } export class DockStore implements DockStorageState { - constructor(private dependencies: Dependencies) { + constructor(private readonly dependencies: Dependencies) { makeObservable(this); autoBind(this); this.init(); @@ -167,6 +169,16 @@ export class DockStore implements DockStorageState { private init() { // adjust terminal height if window size changes window.addEventListener("resize", throttle(this.adjustHeight, 250)); + + this.whenReady.then(action(() => { + for (const tab of this.tabs) { + const validator = this.dependencies.tabDataValidator[tab.kind]; + + if (validator && !validator(tab.id)) { + this.closeTab(tab.id); + } + } + })); } get maxHeight() { @@ -276,8 +288,7 @@ export class DockStore implements DockStorageState { } } - @action - createTab = (rawTabDesc: DockTabCreate, addNumber = true): DockTab => { + createTab = action((rawTabDesc: DockTabCreate, addNumber = true): DockTab => { const { id = uuid.v4(), kind, @@ -307,7 +318,7 @@ export class DockStore implements DockStorageState { this.open(); return tab; - }; + }); @action closeTab(tabId: TabId) { @@ -318,6 +329,7 @@ export class DockStore implements DockStorageState { } this.tabs = this.tabs.filter(tab => tab.id !== tabId); + this.dependencies.tabDataClearers[tab.kind](tab.id); if (this.selectedTabId === tab.id) { if (this.tabs.length) { @@ -331,6 +343,7 @@ export class DockStore implements DockStorageState { } } + @action closeTabs(tabs: DockTab[]) { tabs.forEach(tab => this.closeTab(tab.id)); } diff --git a/src/renderer/components/dock/edit-resource-store/edit-resource-store.injectable.ts b/src/renderer/components/dock/edit-resource-store/edit-resource-store.injectable.ts deleted file mode 100644 index 393bfa560b..0000000000 --- a/src/renderer/components/dock/edit-resource-store/edit-resource-store.injectable.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; -import { EditResourceStore } from "./edit-resource.store"; -import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; - -const editResourceStoreInjectable = getInjectable({ - instantiate: (di) => - new EditResourceStore({ - dockStore: di.inject(dockStoreInjectable), - createStorage: di.inject(createStorageInjectable), - }), - - lifecycle: lifecycleEnum.singleton, -}); - -export default editResourceStoreInjectable; diff --git a/src/renderer/components/dock/edit-resource-store/edit-resource.store.ts b/src/renderer/components/dock/edit-resource-store/edit-resource.store.ts deleted file mode 100644 index 92982cb52d..0000000000 --- a/src/renderer/components/dock/edit-resource-store/edit-resource.store.ts +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { autoBind, noop, StorageHelper } from "../../../utils"; -import { DockTabStorageState, DockTabStore } from "../dock-tab-store/dock-tab.store"; -import { autorun, IReactionDisposer } from "mobx"; -import type { DockStore, DockTab, TabId } from "../dock-store/dock.store"; -import type { KubeObject } from "../../../../common/k8s-api/kube-object"; -import { apiManager } from "../../../../common/k8s-api/api-manager"; -import type { KubeObjectStore } from "../../../../common/k8s-api/kube-object.store"; - -export interface EditingResource { - resource: string; // resource path, e.g. /api/v1/namespaces/default - draft?: string; // edited draft in yaml - firstDraft?: string; -} - -interface Dependencies { - dockStore: DockStore - createStorage: (storageKey: string, options: DockTabStorageState) => StorageHelper> -} - -export class EditResourceStore extends DockTabStore { - private watchers = new Map(); - - constructor(protected dependencies: Dependencies) { - super(dependencies, { - storageKey: "edit_resource_store", - }); - - autoBind(this); - } - - protected async init() { - super.init(); - await this.storage.whenReady; - - autorun(() => { - Array.from(this.data).forEach(([tabId, { resource }]) => { - if (this.watchers.get(tabId)) { - return; - } - this.watchers.set(tabId, autorun(() => { - const store = apiManager.getStore(resource); - - if (store) { - const isActiveTab = this.dependencies.dockStore.isOpen && this.dependencies.dockStore.selectedTabId === tabId; - const obj = store.getByPath(resource); - - // preload resource for editing - if (!obj && !store.isLoaded && !store.isLoading && isActiveTab) { - store.loadFromPath(resource).catch(noop); - } - // auto-close tab when resource removed from store - else if (!obj && store.isLoaded) { - this.dependencies.dockStore.closeTab(tabId); - } - } - }, { - delay: 100, // make sure all kube-object stores are initialized - })); - }); - }); - } - - protected finalizeDataForSave({ draft, ...data }: EditingResource): EditingResource { - return data; // skip saving draft to local-storage - } - - isReady(tabId: TabId) { - const tabDataReady = super.isReady(tabId); - - return Boolean(tabDataReady && this.getResource(tabId)); // ready to edit resource - } - - getStore(tabId: TabId): KubeObjectStore | undefined { - return apiManager.getStore(this.getResourcePath(tabId)); - } - - getResource(tabId: TabId): KubeObject | undefined { - return this.getStore(tabId)?.getByPath(this.getResourcePath(tabId)); - } - - getResourcePath(tabId: TabId): string | undefined { - return this.getData(tabId)?.resource; - } - - getTabByResource(object: KubeObject): DockTab { - const [tabId] = Array.from(this.data).find(([, { resource }]) => { - return object.selfLink === resource; - }) || []; - - return this.dependencies.dockStore.getTabById(tabId); - } - - clearInitialDraft(tabId: TabId): void { - delete this.getData(tabId)?.firstDraft; - } - - reset() { - super.reset(); - Array.from(this.watchers).forEach(([tabId, dispose]) => { - this.watchers.delete(tabId); - dispose(); - }); - } -} diff --git a/src/renderer/components/dock/edit-resource-tab/edit-resource-tab.injectable.ts b/src/renderer/components/dock/edit-resource-tab/edit-resource-tab.injectable.ts deleted file mode 100644 index ba94e51376..0000000000 --- a/src/renderer/components/dock/edit-resource-tab/edit-resource-tab.injectable.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import { editResourceTab } from "./edit-resource-tab"; -import editResourceStoreInjectable from "../edit-resource-store/edit-resource-store.injectable"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; - -const editResourceTabInjectable = getInjectable({ - instantiate: (di) => editResourceTab({ - dockStore: di.inject(dockStoreInjectable), - editResourceStore: di.inject(editResourceStoreInjectable), - }), - - lifecycle: lifecycleEnum.singleton, -}); - -export default editResourceTabInjectable; diff --git a/src/renderer/components/dock/edit-resource-tab/edit-resource-tab.ts b/src/renderer/components/dock/edit-resource-tab/edit-resource-tab.ts deleted file mode 100644 index e42004ef69..0000000000 --- a/src/renderer/components/dock/edit-resource-tab/edit-resource-tab.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { KubeObject } from "../../../../common/k8s-api/kube-object"; -import { DockStore, DockTabCreateSpecific, TabKind } from "../dock-store/dock.store"; -import type { EditResourceStore } from "../edit-resource-store/edit-resource.store"; - -interface Dependencies { - dockStore: DockStore; - editResourceStore: EditResourceStore; -} - -export const editResourceTab = - ({ dockStore, editResourceStore }: Dependencies) => - (object: KubeObject, tabParams: DockTabCreateSpecific = {}) => { - // use existing tab if already opened - let tab = editResourceStore.getTabByResource(object); - - if (tab) { - dockStore.open(); - dockStore.selectTab(tab.id); - } - - // or create new tab - if (!tab) { - tab = dockStore.createTab( - { - title: `${object.kind}: ${object.getName()}`, - ...tabParams, - kind: TabKind.EDIT_RESOURCE, - }, - false, - ); - editResourceStore.setData(tab.id, { - resource: object.selfLink, - }); - } - - return tab; - }; diff --git a/src/renderer/components/dock/edit-resource/clear-edit-resource-tab-data.injectable.ts b/src/renderer/components/dock/edit-resource/clear-edit-resource-tab-data.injectable.ts new file mode 100644 index 0000000000..3b73991af8 --- /dev/null +++ b/src/renderer/components/dock/edit-resource/clear-edit-resource-tab-data.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { TabId } from "../dock/store"; +import editResourceTabStoreInjectable from "./store.injectable"; + +const clearEditResourceTabDataInjectable = getInjectable({ + instantiate: (di) => { + const editResourceTabStore = di.inject(editResourceTabStoreInjectable); + + return (tabId: TabId) => { + editResourceTabStore.clearData(tabId); + }; + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default clearEditResourceTabDataInjectable; diff --git a/src/renderer/components/dock/edit-resource/edit-resource-tab.injectable.ts b/src/renderer/components/dock/edit-resource/edit-resource-tab.injectable.ts new file mode 100644 index 0000000000..a68639e12b --- /dev/null +++ b/src/renderer/components/dock/edit-resource/edit-resource-tab.injectable.ts @@ -0,0 +1,56 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import editResourceTabStoreInjectable from "./store.injectable"; +import dockStoreInjectable from "../dock/store.injectable"; +import type { KubeObject } from "../../../../common/k8s-api/kube-object"; +import { DockStore, DockTabCreateSpecific, TabId, TabKind } from "../dock/store"; +import type { EditResourceTabStore } from "./store"; +import { runInAction } from "mobx"; + +interface Dependencies { + dockStore: DockStore; + editResourceStore: EditResourceTabStore; +} + +const createEditResourceTab = ({ dockStore, editResourceStore }: Dependencies) => (object: KubeObject, tabParams: DockTabCreateSpecific = {}): TabId => { + // use existing tab if already opened + const tabId = editResourceStore.getTabIdByResource(object); + + if (tabId) { + dockStore.open(); + dockStore.selectTab(tabId); + + return tabId; + } + + return runInAction(() => { + const tab = dockStore.createTab( + { + title: `${object.kind}: ${object.getName()}`, + ...tabParams, + kind: TabKind.EDIT_RESOURCE, + }, + false, + ); + + editResourceStore.setData(tab.id, { + resource: object.selfLink, + }); + + return tab.id; + }); +}; + +const createEditResourceTabInjectable = getInjectable({ + instantiate: (di) => createEditResourceTab({ + dockStore: di.inject(dockStoreInjectable), + editResourceStore: di.inject(editResourceTabStoreInjectable), + }), + + lifecycle: lifecycleEnum.singleton, +}); + +export default createEditResourceTabInjectable; diff --git a/src/renderer/components/dock/edit-resource/store.injectable.ts b/src/renderer/components/dock/edit-resource/store.injectable.ts new file mode 100644 index 0000000000..ae2f462262 --- /dev/null +++ b/src/renderer/components/dock/edit-resource/store.injectable.ts @@ -0,0 +1,17 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { EditResourceTabStore } from "./store"; +import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; + +const editResourceTabStoreInjectable = getInjectable({ + instantiate: (di) => new EditResourceTabStore({ + createStorage: di.inject(createStorageInjectable), + }), + + lifecycle: lifecycleEnum.singleton, +}); + +export default editResourceTabStoreInjectable; diff --git a/src/renderer/components/dock/edit-resource/store.ts b/src/renderer/components/dock/edit-resource/store.ts new file mode 100644 index 0000000000..5b8794d758 --- /dev/null +++ b/src/renderer/components/dock/edit-resource/store.ts @@ -0,0 +1,57 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { StorageHelper } from "../../../utils"; +import { DockTabStorageState, DockTabStore } from "../dock-tab-store/dock-tab.store"; +import type { TabId } from "../dock/store"; +import type { KubeObject } from "../../../../common/k8s-api/kube-object"; +import { apiManager } from "../../../../common/k8s-api/api-manager"; +import type { KubeObjectStore } from "../../../../common/k8s-api/kube-object.store"; + +export interface EditingResource { + resource: string; // resource path, e.g. /api/v1/namespaces/default + draft?: string; // edited draft in yaml + firstDraft?: string; +} + +interface Dependencies { + createStorage: (storageKey: string, options: DockTabStorageState) => StorageHelper> +} + +export class EditResourceTabStore extends DockTabStore { + constructor(protected dependencies: Dependencies) { + super(dependencies, { + storageKey: "edit_resource_store", + }); + } + + protected finalizeDataForSave({ draft, ...data }: EditingResource): EditingResource { + return data; // skip saving draft to local-storage + } + + isReady(tabId: TabId) { + return super.isReady(tabId) && Boolean(this.getResource(tabId)); // ready to edit resource + } + + getStore(tabId: TabId): KubeObjectStore | undefined { + return apiManager.getStore(this.getResourcePath(tabId)); + } + + getResource(tabId: TabId): KubeObject | undefined { + return this.getStore(tabId)?.getByPath(this.getResourcePath(tabId)); + } + + getResourcePath(tabId: TabId): string | undefined { + return this.getData(tabId)?.resource; + } + + getTabIdByResource(object: KubeObject): TabId { + return this.findTabIdFromData(({ resource }) => object.selfLink === resource); + } + + clearInitialDraft(tabId: TabId): void { + delete this.getData(tabId)?.firstDraft; + } +} diff --git a/src/renderer/components/dock/edit-resource.tsx b/src/renderer/components/dock/edit-resource/view.tsx similarity index 67% rename from src/renderer/components/dock/edit-resource.tsx rename to src/renderer/components/dock/edit-resource/view.tsx index ec15e27ab5..aa23af9cea 100644 --- a/src/renderer/components/dock/edit-resource.tsx +++ b/src/renderer/components/dock/edit-resource/view.tsx @@ -3,29 +3,30 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import "./edit-resource.scss"; - import React from "react"; -import { computed, makeObservable, observable } from "mobx"; -import { observer } from "mobx-react"; +import { autorun, computed, makeObservable, observable } from "mobx"; +import { disposeOnUnmount, observer } from "mobx-react"; import yaml from "js-yaml"; -import type { DockTab } from "./dock-store/dock.store"; -import type { EditResourceStore } from "./edit-resource-store/edit-resource.store"; -import { InfoPanel } from "./info-panel"; -import { Badge } from "../badge"; -import { EditorPanel } from "./editor-panel"; -import { Spinner } from "../spinner"; -import type { KubeObject } from "../../../common/k8s-api/kube-object"; +import type { DockTab, TabId } from "../dock/store"; +import type { EditResourceTabStore } from "./store"; +import { InfoPanel } from "../info-panel"; +import { Badge } from "../../badge"; +import { EditorPanel } from "../editor-panel"; +import { Spinner } from "../../spinner"; +import type { KubeObject } from "../../../../common/k8s-api/kube-object"; import { createPatch } from "rfc6902"; import { withInjectables } from "@ogre-tools/injectable-react"; -import editResourceStoreInjectable from "./edit-resource-store/edit-resource-store.injectable"; +import editResourceTabStoreInjectable from "./store.injectable"; +import { noop } from "../../../utils"; +import closeDockTabInjectable from "../dock/close-dock-tab.injectable"; interface Props { tab: DockTab; } interface Dependencies { - editResourceStore: EditResourceStore + editResourceStore: EditResourceTabStore; + closeTab: (tabId: TabId) => void; } @observer @@ -37,6 +38,26 @@ class NonInjectedEditResource extends React.Component { makeObservable(this); } + componentDidMount(): void { + disposeOnUnmount(this, [ + autorun(() => { + const store = this.props.editResourceStore.getStore(this.props.tab.id); + const tabData = this.props.editResourceStore.getData(this.props.tab.id); + const obj = this.resource; + + if (!obj) { + if (store.isLoaded) { + // auto-close tab when resource removed from store + this.props.closeTab(this.props.tab.id); + } else if (!store.isLoading) { + // preload resource for editing + store.loadFromPath(tabData.resource).catch(noop); + } + } + }), + ]); + } + get tabId() { return this.props.tab.id; } @@ -132,13 +153,10 @@ class NonInjectedEditResource extends React.Component { } } -export const EditResource = withInjectables( - NonInjectedEditResource, - - { - getProps: (di, props) => ({ - editResourceStore: di.inject(editResourceStoreInjectable), - ...props, - }), - }, -); +export const EditResource = withInjectables(NonInjectedEditResource, { + getProps: (di, props) => ({ + editResourceStore: di.inject(editResourceTabStoreInjectable), + closeTab: di.inject(closeDockTabInjectable), + ...props, + }), +}); diff --git a/src/renderer/components/dock/editor-panel.tsx b/src/renderer/components/dock/editor-panel.tsx index e2500a7513..90e47b1c7f 100644 --- a/src/renderer/components/dock/editor-panel.tsx +++ b/src/renderer/components/dock/editor-panel.tsx @@ -8,11 +8,11 @@ import throttle from "lodash/throttle"; import React from "react"; import { makeObservable, observable, reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; -import type { DockStore, TabId } from "./dock-store/dock.store"; +import type { DockStore, TabId } from "./dock/store"; import { cssNames } from "../../utils"; import { MonacoEditor, MonacoEditorProps } from "../monaco-editor"; import { withInjectables } from "@ogre-tools/injectable-react"; -import dockStoreInjectable from "./dock-store/dock-store.injectable"; +import dockStoreInjectable from "./dock/store.injectable"; export interface EditorPanelProps { tabId: TabId; diff --git a/src/renderer/components/dock/info-panel.tsx b/src/renderer/components/dock/info-panel.tsx index 0d534b3a6f..91a6d329f8 100644 --- a/src/renderer/components/dock/info-panel.tsx +++ b/src/renderer/components/dock/info-panel.tsx @@ -12,14 +12,14 @@ import { cssNames } from "../../utils"; import { Button } from "../button"; import { Icon } from "../icon"; import { Spinner } from "../spinner"; -import type { DockStore, TabId } from "./dock-store/dock.store"; +import type { DockStore, TabId } from "./dock/store"; import { Notifications } from "../notifications"; import { withInjectables } from "@ogre-tools/injectable-react"; -import dockStoreInjectable from "./dock-store/dock-store.injectable"; +import dockStoreInjectable from "./dock/store.injectable"; interface Props extends OptionalProps { tabId: TabId; - submit?: () => Promise; + submit?: () => Promise; } interface OptionalProps { @@ -80,7 +80,7 @@ class NonInjectedInfoPanel extends Component { try { const result = await this.props.submit(); - if (showNotifications) Notifications.ok(result); + if (showNotifications && result) Notifications.ok(result); } catch (error) { if (showNotifications) Notifications.error(error.toString()); } finally { diff --git a/src/renderer/components/dock/install-chart/clear-install-chart-tab-data.injectable.ts b/src/renderer/components/dock/install-chart/clear-install-chart-tab-data.injectable.ts new file mode 100644 index 0000000000..0221d5dc38 --- /dev/null +++ b/src/renderer/components/dock/install-chart/clear-install-chart-tab-data.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { TabId } from "../dock/store"; +import installChartTabStoreInjectable from "./store.injectable"; + +const clearInstallChartTabDataInjectable = getInjectable({ + instantiate: (di) => { + const installChartTabStore = di.inject(installChartTabStoreInjectable); + + return (tabId: TabId) => { + installChartTabStore.clearData(tabId); + }; + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default clearInstallChartTabDataInjectable; diff --git a/src/renderer/components/dock/install-chart/create-install-chart-tab.injectable.ts b/src/renderer/components/dock/install-chart/create-install-chart-tab.injectable.ts new file mode 100644 index 0000000000..2e9920c310 --- /dev/null +++ b/src/renderer/components/dock/install-chart/create-install-chart-tab.injectable.ts @@ -0,0 +1,55 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import installChartTabStoreInjectable from "./store.injectable"; +import type { HelmChart } from "../../../../common/k8s-api/endpoints/helm-charts.api"; +import { + DockTab, + DockTabCreate, + DockTabCreateSpecific, + TabKind, +} from "../dock/store"; +import type { InstallChartTabStore } from "./store"; +import createDockTabInjectable from "../dock/create-dock-tab.injectable"; + +interface Dependencies { + createDockTab: (rawTab: DockTabCreate, addNumber: boolean) => DockTab; + installChartStore: InstallChartTabStore; +} + +const createInstallChartTab = ({ createDockTab, installChartStore }: Dependencies) => (chart: HelmChart, tabParams: DockTabCreateSpecific = {}) => { + const { name, repo, version } = chart; + + const tab = createDockTab( + { + title: `Helm Install: ${repo}/${name}`, + ...tabParams, + kind: TabKind.INSTALL_CHART, + }, + false, + ); + + installChartStore.setData(tab.id, { + name, + repo, + version, + namespace: "default", + releaseName: "", + description: "", + }); + + return tab; +}; + +const createInstallChartTabInjectable = getInjectable({ + instantiate: (di) => createInstallChartTab({ + installChartStore: di.inject(installChartTabStoreInjectable), + createDockTab: di.inject(createDockTabInjectable), + }), + + lifecycle: lifecycleEnum.singleton, +}); + +export default createInstallChartTabInjectable; diff --git a/src/renderer/components/dock/install-chart.scss b/src/renderer/components/dock/install-chart/install-chart.scss similarity index 100% rename from src/renderer/components/dock/install-chart.scss rename to src/renderer/components/dock/install-chart/install-chart.scss diff --git a/src/renderer/components/dock/install-chart-store/install-chart-store.injectable.ts b/src/renderer/components/dock/install-chart/store.injectable.ts similarity index 73% rename from src/renderer/components/dock/install-chart-store/install-chart-store.injectable.ts rename to src/renderer/components/dock/install-chart/store.injectable.ts index d0fdb731a0..f1d38d744a 100644 --- a/src/renderer/components/dock/install-chart-store/install-chart-store.injectable.ts +++ b/src/renderer/components/dock/install-chart/store.injectable.ts @@ -3,18 +3,16 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import { InstallChartStore } from "./install-chart.store"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; +import { InstallChartTabStore } from "./store"; import createDockTabStoreInjectable from "../dock-tab-store/create-dock-tab-store.injectable"; import type { IReleaseUpdateDetails } from "../../../../common/k8s-api/endpoints/helm-releases.api"; import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; -const installChartStoreInjectable = getInjectable({ +const installChartTabStoreInjectable = getInjectable({ instantiate: (di) => { const createDockTabStore = di.inject(createDockTabStoreInjectable); - return new InstallChartStore({ - dockStore: di.inject(dockStoreInjectable), + return new InstallChartTabStore({ createStorage: di.inject(createStorageInjectable), versionsStore: createDockTabStore(), detailsStore: createDockTabStore(), @@ -23,4 +21,4 @@ const installChartStoreInjectable = getInjectable({ lifecycle: lifecycleEnum.singleton, }); -export default installChartStoreInjectable; +export default installChartTabStoreInjectable; diff --git a/src/renderer/components/dock/install-chart-store/install-chart.store.ts b/src/renderer/components/dock/install-chart/store.ts similarity index 72% rename from src/renderer/components/dock/install-chart-store/install-chart.store.ts rename to src/renderer/components/dock/install-chart/store.ts index 9e8a9d4c32..e322a0ec78 100644 --- a/src/renderer/components/dock/install-chart-store/install-chart.store.ts +++ b/src/renderer/components/dock/install-chart/store.ts @@ -3,12 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { action, autorun, makeObservable } from "mobx"; -import { DockStore, TabId, TabKind } from "../dock-store/dock.store"; +import { action, makeObservable, when } from "mobx"; +import type { TabId } from "../dock/store"; import { DockTabStorageState, DockTabStore } from "../dock-tab-store/dock-tab.store"; import { getChartDetails, getChartValues } from "../../../../common/k8s-api/endpoints/helm-charts.api"; import type { IReleaseUpdateDetails } from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import { Notifications } from "../../notifications"; import type { StorageHelper } from "../../../utils"; export interface IChartInstallData { @@ -23,29 +22,18 @@ export interface IChartInstallData { } interface Dependencies { - dockStore: DockStore, - createStorage: (storageKey: string, options: DockTabStorageState) => StorageHelper> - - versionsStore: DockTabStore, - detailsStore: DockTabStore + createStorage: (storageKey: string, options: DockTabStorageState) => StorageHelper>; + versionsStore: DockTabStore; + detailsStore: DockTabStore; } -export class InstallChartStore extends DockTabStore { +export class InstallChartTabStore extends DockTabStore { constructor(protected dependencies: Dependencies) { super( dependencies, { storageKey: "install_charts" }, ); - makeObservable(this); - autorun(() => { - const { selectedTab, isOpen } = dependencies.dockStore; - - if (selectedTab?.kind === TabKind.INSTALL_CHART && isOpen) { - this.loadData(selectedTab.id) - .catch(err => Notifications.error(String(err))); - } - }, { delay: 250 }); } get versions() { @@ -60,6 +48,8 @@ export class InstallChartStore extends DockTabStore { async loadData(tabId: string) { const promises = []; + await when(() => this.isReady(tabId)); + if (!this.getData(tabId).values) { promises.push(this.loadValues(tabId)); } @@ -94,8 +84,4 @@ export class InstallChartStore extends DockTabStore { return this.loadValues(tabId, attempt + 1); } } - - setData(tabId: TabId, data: IChartInstallData){ - super.setData(tabId, data); - } } diff --git a/src/renderer/components/dock/install-chart.tsx b/src/renderer/components/dock/install-chart/view.tsx similarity index 77% rename from src/renderer/components/dock/install-chart.tsx rename to src/renderer/components/dock/install-chart/view.tsx index d159a8df08..f162ae13a3 100644 --- a/src/renderer/components/dock/install-chart.tsx +++ b/src/renderer/components/dock/install-chart/view.tsx @@ -8,29 +8,27 @@ import "./install-chart.scss"; import React, { Component } from "react"; import { action, makeObservable, observable } from "mobx"; import { observer } from "mobx-react"; -import type { DockStore, DockTab } from "./dock-store/dock.store"; -import { InfoPanel } from "./info-panel"; -import { Badge } from "../badge"; -import { NamespaceSelect } from "../+namespaces/namespace-select"; -import { prevDefault } from "../../utils"; -import type { IChartInstallData, InstallChartStore } from "./install-chart-store/install-chart.store"; -import { Spinner } from "../spinner"; -import { Icon } from "../icon"; -import { Button } from "../button"; -import { LogsDialog } from "../dialog/logs-dialog"; -import { Select, SelectOption } from "../select"; -import { Input } from "../input"; -import { EditorPanel } from "./editor-panel"; -import { navigate } from "../../navigation"; -import { releaseURL } from "../../../common/routes"; -import type { - IReleaseCreatePayload, - IReleaseUpdateDetails, -} from "../../../common/k8s-api/endpoints/helm-releases.api"; +import type { DockStore, DockTab } from "../dock/store"; +import { InfoPanel } from "../info-panel"; +import { Badge } from "../../badge"; +import { NamespaceSelect } from "../../+namespaces/namespace-select"; +import { prevDefault } from "../../../utils"; +import type { IChartInstallData, InstallChartTabStore } from "./store"; +import { Spinner } from "../../spinner"; +import { Icon } from "../../icon"; +import { Button } from "../../button"; +import { LogsDialog } from "../../dialog/logs-dialog"; +import { Select, SelectOption } from "../../select"; +import { Input } from "../../input"; +import { EditorPanel } from "../editor-panel"; +import { navigate } from "../../../navigation"; +import { releaseURL } from "../../../../common/routes"; +import type { IReleaseCreatePayload, IReleaseUpdateDetails } from "../../../../common/k8s-api/endpoints/helm-releases.api"; import { withInjectables } from "@ogre-tools/injectable-react"; -import installChartStoreInjectable from "./install-chart-store/install-chart-store.injectable"; -import dockStoreInjectable from "./dock-store/dock-store.injectable"; -import createReleaseInjectable from "../+apps-releases/create-release/create-release.injectable"; +import installChartTabStoreInjectable from "./store.injectable"; +import dockStoreInjectable from "../dock/store.injectable"; +import createReleaseInjectable from "../../+apps-releases/create-release/create-release.injectable"; +import { Notifications } from "../../notifications"; interface Props { tab: DockTab; @@ -38,7 +36,7 @@ interface Props { interface Dependencies { createRelease: (payload: IReleaseCreatePayload) => Promise - installChartStore: InstallChartStore + installChartStore: InstallChartTabStore dockStore: DockStore } @@ -52,6 +50,11 @@ class NonInjectedInstallChart extends Component { makeObservable(this); } + componentDidMount(): void { + this.props.installChartStore.loadData(this.tabId) + .catch(err => Notifications.error(String(err))); + } + get chartData() { return this.props.installChartStore.getData(this.tabId); } @@ -93,16 +96,14 @@ class NonInjectedInstallChart extends Component { this.props.installChartStore.loadValues(this.tabId); }; - @action - onChange = (values: string) => { + onChange = action((values: string) => { this.error = ""; this.save({ values }); - }; + }); - @action - onError = (error: Error | string) => { + onError = action((error: Error | string) => { this.error = error.toString(); - }; + }); onNamespaceChange = (opt: SelectOption) => { this.save({ namespace: opt.value }); @@ -223,7 +224,7 @@ export const InstallChart = withInjectables( { getProps: (di, props) => ({ createRelease: di.inject(createReleaseInjectable), - installChartStore: di.inject(installChartStoreInjectable), + installChartStore: di.inject(installChartTabStoreInjectable), dockStore: di.inject(dockStoreInjectable), ...props, }), diff --git a/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx b/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx index 9858827f86..b5923b98a0 100644 --- a/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx +++ b/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx @@ -8,7 +8,7 @@ import "@testing-library/jest-dom/extend-expect"; import * as selectEvent from "react-select-event"; import { Pod } from "../../../../../common/k8s-api/endpoints"; import { LogResourceSelector } from "../resource-selector"; -import { dockerPod, deploymentPod1 } from "./pod.mock"; +import { dockerPod, deploymentPod1, deploymentPod2 } from "./pod.mock"; import { ThemeStore } from "../../../../theme.store"; import { UserStore } from "../../../../../common/user-store"; import mockFs from "mock-fs"; @@ -18,7 +18,9 @@ import { renderFor } from "../../../test-utils/renderFor"; import directoryForUserDataInjectable from "../../../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import callForLogsInjectable from "../call-for-logs.injectable"; import { LogTabViewModel, LogTabViewModelDependencies } from "../logs-view-model"; -import type { TabId } from "../../dock-store/dock.store"; +import type { TabId } from "../../dock/store"; +import userEvent from "@testing-library/user-event"; +import { SearchStore } from "../../../../search-store/search-store"; jest.mock("electron", () => ({ app: { @@ -36,10 +38,6 @@ jest.mock("electron", () => ({ }, })); -const getComponent = (model: LogTabViewModel) => ( - -); - function mockLogTabViewModel(tabId: TabId, deps: Partial): LogTabViewModel { return new LogTabViewModel(tabId, { getLogs: jest.fn(), @@ -49,34 +47,74 @@ function mockLogTabViewModel(tabId: TabId, deps: Partial { +const getOnePodViewModel = (tabId: TabId, deps: Partial = {}): LogTabViewModel => { const selectedPod = new Pod(dockerPod); return mockLogTabViewModel(tabId, { getLogTabData: () => ({ - pods: [selectedPod], - selectedPod, - selectedContainer: selectedPod.getContainers()[0], + selectedPodId: selectedPod.getId(), + selectedContainer: selectedPod.getContainers()[0].name, + namespace: selectedPod.getNs(), + showPrevious: false, + showTimestamps: false, }), + getPodById: (id) => { + if (id === selectedPod.getId()) { + return selectedPod; + } + + return undefined; + }, + ...deps, }); }; -const getFewPodsTabData = (tabId: TabId): LogTabViewModel => { +const getFewPodsTabData = (tabId: TabId, deps: Partial = {}): LogTabViewModel => { const selectedPod = new Pod(deploymentPod1); - const anotherPod = new Pod(dockerPod); + const anotherPod = new Pod(deploymentPod2); return mockLogTabViewModel(tabId, { getLogTabData: () => ({ - pods: [selectedPod, anotherPod], - selectedPod, - selectedContainer: selectedPod.getContainers()[0], + owner: { + uid: "uuid", + kind: "Deployment", + name: "super-deployment", + }, + selectedPodId: selectedPod.getId(), + selectedContainer: selectedPod.getContainers()[0].name, + namespace: selectedPod.getNs(), + showPrevious: false, + showTimestamps: false, }), + getPodById: (id) => { + if (id === selectedPod.getId()) { + return selectedPod; + } + + if (id === anotherPod.getId()) { + return anotherPod; + } + + return undefined; + }, + getPodsByOwnerId: (id) => { + if (id === "uuid") { + return [selectedPod, anotherPod]; + } + + return []; + }, + ...deps, }); }; @@ -109,14 +147,14 @@ describe("", () => { it("renders w/o errors", () => { const model = getOnePodViewModel("foobar"); - const { container } = render(getComponent(model)); + const { container } = render(); expect(container).toBeInstanceOf(HTMLElement); }); it("renders proper namespace", async () => { const model = getOnePodViewModel("foobar"); - const { findByTestId } = render(getComponent(model)); + const { findByTestId } = render(); const ns = await findByTestId("namespace-badge"); expect(ns).toHaveTextContent("default"); @@ -124,7 +162,7 @@ describe("", () => { it("renders proper selected items within dropdowns", async () => { const model = getOnePodViewModel("foobar"); - const { findByText } = render(getComponent(model)); + const { findByText } = render(); expect(await findByText("dockerExporter")).toBeInTheDocument(); expect(await findByText("docker-exporter")).toBeInTheDocument(); @@ -132,33 +170,40 @@ describe("", () => { it("renders sibling pods in dropdown", async () => { const model = getFewPodsTabData("foobar"); - const { container, findByText } = render(getComponent(model)); + const { container, findByText } = render(); selectEvent.openMenu(container.querySelector(".pod-selector")); - - expect(await findByText("dockerExporter", { selector: ".pod-selector-menu .Select__option" })).toBeInTheDocument(); + expect(await findByText("deploymentPod2", { selector: ".pod-selector-menu .Select__option" })).toBeInTheDocument(); expect(await findByText("deploymentPod1", { selector: ".pod-selector-menu .Select__option" })).toBeInTheDocument(); }); it("renders sibling containers in dropdown", async () => { const model = getFewPodsTabData("foobar"); - const { findByText, container } = render(getComponent(model)); - const containerSelector: HTMLElement = container.querySelector(".container-selector"); - - selectEvent.openMenu(containerSelector); + const { findByText, container } = render(); + selectEvent.openMenu(container.querySelector(".container-selector")); expect(await findByText("node-exporter-1")).toBeInTheDocument(); expect(await findByText("init-node-exporter")).toBeInTheDocument(); expect(await findByText("init-node-exporter-1")).toBeInTheDocument(); }); - it("renders pod owner as dropdown title", async () => { + it("renders pod owner as badge", async () => { const model = getFewPodsTabData("foobar"); - const { findByText, container } = render(getComponent(model)); - const podSelector: HTMLElement = container.querySelector(".pod-selector"); + const { findByText } = render(); - selectEvent.openMenu(podSelector); + expect(await findByText("super-deployment", { + exact: false, + })).toBeInTheDocument(); + }); - expect(await findByText("super-deployment")).toBeInTheDocument(); + it("updates tab name if selected pod changes", async () => { + const renameTab = jest.fn(); + const model = getFewPodsTabData("foobar", { renameTab }); + const { findByText, container } = render(); + + selectEvent.openMenu(container.querySelector(".pod-selector")); + + userEvent.click(await findByText("deploymentPod2", { selector: ".pod-selector-menu .Select__option" })); + expect(renameTab).toBeCalledWith("foobar", "Pod deploymentPod2"); }); }); diff --git a/src/renderer/components/dock/logs/__test__/log-search.test.tsx b/src/renderer/components/dock/logs/__test__/log-search.test.tsx new file mode 100644 index 0000000000..24c2001eec --- /dev/null +++ b/src/renderer/components/dock/logs/__test__/log-search.test.tsx @@ -0,0 +1,147 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { screen } from "@testing-library/react"; +import { Pod } from "../../../../../common/k8s-api/endpoints"; +import { dockerPod } from "./pod.mock"; +import { getDiForUnitTesting } from "../../../../getDiForUnitTesting"; +import type { DiRender } from "../../../test-utils/renderFor"; +import { renderFor } from "../../../test-utils/renderFor"; +import { LogTabViewModel, LogTabViewModelDependencies } from "../logs-view-model"; +import type { TabId } from "../../dock/store"; +import { LogSearch } from "../search"; +import userEvent from "@testing-library/user-event"; +import { SearchStore } from "../../../../search-store/search-store"; + +function mockLogTabViewModel(tabId: TabId, deps: Partial): LogTabViewModel { + return new LogTabViewModel(tabId, { + getLogs: jest.fn(), + getLogsWithoutTimestamps: jest.fn(), + getTimestampSplitLogs: jest.fn(), + getLogTabData: jest.fn(), + setLogTabData: jest.fn(), + loadLogs: jest.fn(), + reloadLogs: jest.fn(), + renameTab: jest.fn(), + stopLoadingLogs: jest.fn(), + getPodById: jest.fn(), + getPodsByOwnerId: jest.fn(), + areLogsPresent: jest.fn(), + searchStore: new SearchStore(), + ...deps, + }); +} + +const getOnePodViewModel = (tabId: TabId, deps: Partial = {}): LogTabViewModel => { + const selectedPod = new Pod(dockerPod); + + return mockLogTabViewModel(tabId, { + getLogTabData: () => ({ + selectedPodId: selectedPod.getId(), + selectedContainer: selectedPod.getContainers()[0].name, + namespace: selectedPod.getNs(), + showPrevious: false, + showTimestamps: false, + }), + getPodById: (id) => { + if (id === selectedPod.getId()) { + return selectedPod; + } + + return undefined; + }, + ...deps, + }); +}; + +describe("LogSearch tests", () => { + let render: DiRender; + + beforeEach(async () => { + const di = getDiForUnitTesting({ doGeneralOverrides: true }); + + render = renderFor(di); + + await di.runSetups(); + }); + + it("renders w/o errors", () => { + const model = getOnePodViewModel("foobar"); + const { container } = render( + , + ); + + expect(container).toBeInstanceOf(HTMLElement); + }); + + it("should scroll to new active overlay when clicking the previous button", async () => { + const scrollToOverlay = jest.fn(); + const model = getOnePodViewModel("foobar", { + getLogsWithoutTimestamps: () => [ + "hello", + "world", + ], + }); + + render( + , + ); + + userEvent.click(await screen.findByPlaceholderText("Search...")); + userEvent.keyboard("o"); + userEvent.click(await screen.findByText("keyboard_arrow_up")); + expect(scrollToOverlay).toBeCalled(); + }); + + it("should scroll to new active overlay when clicking the next button", async () => { + const scrollToOverlay = jest.fn(); + const model = getOnePodViewModel("foobar", { + getLogsWithoutTimestamps: () => [ + "hello", + "world", + ], + }); + + render( + , + ); + + userEvent.click(await screen.findByPlaceholderText("Search...")); + userEvent.keyboard("o"); + userEvent.click(await screen.findByText("keyboard_arrow_down")); + expect(scrollToOverlay).toBeCalled(); + }); + + it("next and previous should be disabled initially", async () => { + const scrollToOverlay = jest.fn(); + const model = getOnePodViewModel("foobar", { + getLogsWithoutTimestamps: () => [ + "hello", + "world", + ], + }); + + render( + , + ); + + userEvent.click(await screen.findByText("keyboard_arrow_down")); + userEvent.click(await screen.findByText("keyboard_arrow_up")); + expect(scrollToOverlay).not.toBeCalled(); + }); +}); diff --git a/src/renderer/components/dock/logs/__test__/log-tab.store.test.ts b/src/renderer/components/dock/logs/__test__/log-tab.store.test.ts deleted file mode 100644 index b98b46daf9..0000000000 --- a/src/renderer/components/dock/logs/__test__/log-tab.store.test.ts +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { podsStore } from "../../../+workloads-pods/pods.store"; -import { UserStore } from "../../../../../common/user-store"; -import { Pod } from "../../../../../common/k8s-api/endpoints"; -import { ThemeStore } from "../../../../theme.store"; -import { deploymentPod1, deploymentPod2, deploymentPod3, dockerPod } from "./pod.mock"; -import { mockWindow } from "../../../../../../__mocks__/windowMock"; -import { getDiForUnitTesting } from "../../../../getDiForUnitTesting"; -import logTabStoreInjectable from "../tab-store.injectable"; -import type { LogTabStore } from "../tab.store"; -import dockStoreInjectable from "../../dock-store/dock-store.injectable"; -import type { DockStore } from "../../dock-store/dock.store"; -import directoryForUserDataInjectable - from "../../../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; -import mockFs from "mock-fs"; - -mockWindow(); - -podsStore.items.push(new Pod(dockerPod)); -podsStore.items.push(new Pod(deploymentPod1)); -podsStore.items.push(new Pod(deploymentPod2)); - -describe("log tab store", () => { - let logTabStore: LogTabStore; - let dockStore: DockStore; - - beforeEach(async () => { - const di = getDiForUnitTesting({ doGeneralOverrides: true }); - - mockFs(); - - di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data"); - - await di.runSetups(); - - dockStore = di.inject(dockStoreInjectable); - logTabStore = di.inject(logTabStoreInjectable); - - UserStore.createInstance(); - ThemeStore.createInstance(); - }); - - afterEach(() => { - UserStore.resetInstance(); - ThemeStore.resetInstance(); - mockFs.restore(); - }); - - it("creates log tab without sibling pods", () => { - const selectedPod = new Pod(dockerPod); - const selectedContainer = selectedPod.getAllContainers()[0]; - - logTabStore.createPodTab({ - selectedPod, - selectedContainer, - }); - - expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({ - pods: [selectedPod], - selectedPod, - selectedContainer, - showTimestamps: false, - previous: false, - }); - }); - - it("creates log tab with sibling pods", () => { - const selectedPod = new Pod(deploymentPod1); - const siblingPod = new Pod(deploymentPod2); - const selectedContainer = selectedPod.getInitContainers()[0]; - - logTabStore.createPodTab({ - selectedPod, - selectedContainer, - }); - - expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({ - pods: [selectedPod, siblingPod], - selectedPod, - selectedContainer, - showTimestamps: false, - previous: false, - }); - }); - - it("removes item from pods list if pod deleted from store", () => { - const selectedPod = new Pod(deploymentPod1); - const selectedContainer = selectedPod.getInitContainers()[0]; - - logTabStore.createPodTab({ - selectedPod, - selectedContainer, - }); - - podsStore.items.pop(); - - expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({ - pods: [selectedPod], - selectedPod, - selectedContainer, - showTimestamps: false, - previous: false, - }); - }); - - it("adds item into pods list if new sibling pod added to store", () => { - const selectedPod = new Pod(deploymentPod1); - const selectedContainer = selectedPod.getInitContainers()[0]; - - logTabStore.createPodTab({ - selectedPod, - selectedContainer, - }); - - podsStore.items.push(new Pod(deploymentPod3)); - - expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({ - pods: [selectedPod, deploymentPod3], - selectedPod, - selectedContainer, - showTimestamps: false, - previous: false, - }); - }); - - // FIXME: this is failed when it's not .only == depends on something above - it.only("closes tab if no pods left in store", async () => { - const selectedPod = new Pod(deploymentPod1); - const selectedContainer = selectedPod.getInitContainers()[0]; - - const id = logTabStore.createPodTab({ - selectedPod, - selectedContainer, - }); - - podsStore.items.clear(); - - expect(logTabStore.getData(dockStore.selectedTabId)).toBeUndefined(); - expect(logTabStore.getData(id)).toBeUndefined(); - expect(dockStore.getTabById(id)).toBeUndefined(); - }); -}); diff --git a/src/renderer/components/dock/logs/are-logs-present.injectable.ts b/src/renderer/components/dock/logs/are-logs-present.injectable.ts new file mode 100644 index 0000000000..f4644c8229 --- /dev/null +++ b/src/renderer/components/dock/logs/are-logs-present.injectable.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { TabId } from "../dock/store"; +import logStoreInjectable from "./store.injectable"; + +const areLogsPresentInjectable = getInjectable({ + instantiate: (di) => { + const logStore = di.inject(logStoreInjectable); + + return (tabId: TabId) => logStore.areLogsPresent(tabId); + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default areLogsPresentInjectable; diff --git a/src/renderer/components/dock/logs/clear-log-tab-data.injectable.ts b/src/renderer/components/dock/logs/clear-log-tab-data.injectable.ts new file mode 100644 index 0000000000..0bc007bdf4 --- /dev/null +++ b/src/renderer/components/dock/logs/clear-log-tab-data.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { TabId } from "../dock/store"; +import logTabStoreInjectable from "./tab-store.injectable"; + +const clearLogTabDataInjectable = getInjectable({ + instantiate: (di) => { + const logTabStore = di.inject(logTabStoreInjectable); + + return (tabId: TabId): void => { + logTabStore.clearData(tabId); + }; + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default clearLogTabDataInjectable; diff --git a/src/renderer/components/dock/logs/controls.tsx b/src/renderer/components/dock/logs/controls.tsx index 954ccb8478..59aead384b 100644 --- a/src/renderer/components/dock/logs/controls.tsx +++ b/src/renderer/components/dock/logs/controls.tsx @@ -8,17 +8,22 @@ import "./controls.scss"; import React from "react"; import { observer } from "mobx-react"; -import { Pod } from "../../../../common/k8s-api/endpoints"; -import { cssNames, saveFileDialog } from "../../../utils"; +import { cssNames } from "../../../utils"; import { Checkbox } from "../../checkbox"; import { Icon } from "../../icon"; import type { LogTabViewModel } from "./logs-view-model"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import openSaveFileDialogInjectable from "../../../utils/save-file.injectable"; export interface LogControlsProps { model: LogTabViewModel; } -export const LogControls = observer(({ model }: LogControlsProps) => { +interface Dependencies { + openSaveFileDialog: (filename: string, contents: BlobPart | BlobPart[], type: string) => void; +} + +const NonInjectedLogControls = observer(({ openSaveFileDialog, model }: Dependencies & LogControlsProps) => { const tabData = model.logTabData.get(); if (!tabData) { @@ -26,26 +31,25 @@ export const LogControls = observer(({ model }: LogControlsProps) => { } const logs = model.timestampSplitLogs.get(); - const { showTimestamps, previous } = tabData; + const { showTimestamps, showPrevious: previous } = tabData; const since = logs.length ? logs[0][0] : null; - const pod = new Pod(tabData.selectedPod); const toggleTimestamps = () => { model.updateLogTabData({ showTimestamps: !showTimestamps }); }; const togglePrevious = () => { - model.updateLogTabData({ previous: !previous }); + model.updateLogTabData({ showPrevious: !previous }); model.reloadLogs(); }; const downloadLogs = () => { - const fileName = pod.getName(); + const fileName = model.pod.get().getName(); const logsToDownload: string[] = showTimestamps ? model.logs.get() : model.logsWithoutTimestamps.get(); - saveFileDialog(`${fileName}.log`, logsToDownload.join("\n"), "text/plain"); + openSaveFileDialog(`${fileName}.log`, logsToDownload.join("\n"), "text/plain"); }; return ( @@ -81,3 +85,10 @@ export const LogControls = observer(({ model }: LogControlsProps) => { ); }); + +export const LogControls = withInjectables(NonInjectedLogControls, { + getProps: (di, props) => ({ + openSaveFileDialog: di.inject(openSaveFileDialogInjectable), + ...props, + }), +}); diff --git a/src/renderer/components/dock/logs/create-logs-tab.injectable.ts b/src/renderer/components/dock/logs/create-logs-tab.injectable.ts new file mode 100644 index 0000000000..ddef5c16d7 --- /dev/null +++ b/src/renderer/components/dock/logs/create-logs-tab.injectable.ts @@ -0,0 +1,48 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { DockTabCreate, DockTab, TabKind, TabId } from "../dock/store"; +import type { LogTabData } from "./tab-store"; +import * as uuid from "uuid"; +import { runInAction } from "mobx"; +import createDockTabInjectable from "../dock/create-dock-tab.injectable"; +import setLogTabDataInjectable from "./set-log-tab-data.injectable"; + +export type CreateLogsTabData = Pick & Omit, "owner" | "selectedPodId" | "selectedContainer" | "namespace">; + +interface Dependencies { + createDockTab: (rawTabDesc: DockTabCreate, addNumber?: boolean) => DockTab; + setLogTabData: (tabId: string, data: LogTabData) => void; +} + +const createLogsTab = ({ createDockTab, setLogTabData }: Dependencies) => (title: string, data: CreateLogsTabData): TabId => { + const id = `log-tab-${uuid.v4()}`; + + runInAction(() => { + createDockTab({ + id, + title, + kind: TabKind.POD_LOGS, + }, false); + setLogTabData(id, { + showTimestamps: false, + showPrevious: false, + ...data, + }); + }); + + return id; +}; + +const createLogsTabInjectable = getInjectable({ + instantiate: (di) => createLogsTab({ + createDockTab: di.inject(createDockTabInjectable), + setLogTabData: di.inject(setLogTabDataInjectable), + }), + + lifecycle: lifecycleEnum.singleton, +}); + +export default createLogsTabInjectable; diff --git a/src/renderer/components/dock/logs/create-pod-logs-tab.injectable.ts b/src/renderer/components/dock/logs/create-pod-logs-tab.injectable.ts new file mode 100644 index 0000000000..2d9c3f981d --- /dev/null +++ b/src/renderer/components/dock/logs/create-pod-logs-tab.injectable.ts @@ -0,0 +1,31 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { IPodContainer, Pod } from "../../../../common/k8s-api/endpoints"; +import type { TabId } from "../dock/store"; +import createLogsTabInjectable from "./create-logs-tab.injectable"; + +export interface PodLogsTabData { + selectedPod: Pod; + selectedContainer: IPodContainer; +} + +const createPodLogsTabInjectable = getInjectable({ + instantiate: (di) => { + const createLogsTab = di.inject(createLogsTabInjectable); + + return ({ selectedPod, selectedContainer }: PodLogsTabData): TabId => + createLogsTab(`Pod ${selectedPod.getName()}`, { + owner: selectedPod.getOwnerRefs()[0], + namespace: selectedPod.getNs(), + selectedContainer: selectedContainer.name, + selectedPodId: selectedPod.getId(), + }); + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default createPodLogsTabInjectable; diff --git a/src/renderer/components/dock/logs/create-workload-logs-tab.injectable.ts b/src/renderer/components/dock/logs/create-workload-logs-tab.injectable.ts new file mode 100644 index 0000000000..e8e2eb41ed --- /dev/null +++ b/src/renderer/components/dock/logs/create-workload-logs-tab.injectable.ts @@ -0,0 +1,48 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { podsStore } from "../../+workloads-pods/pods.store"; +import type { WorkloadKubeObject } from "../../../../common/k8s-api/workload-kube-object"; +import type { TabId } from "../dock/store"; +import createLogsTabInjectable, { CreateLogsTabData } from "./create-logs-tab.injectable"; + +export interface WorkloadLogsTabData { + workload: WorkloadKubeObject +} + +interface Dependencies { + createLogsTab: (title: string, data: CreateLogsTabData) => TabId; +} + +const createWorkloadLogsTab = ({ createLogsTab }: Dependencies) => ({ workload }: WorkloadLogsTabData): TabId | undefined => { + const pods = podsStore.getPodsByOwnerId(workload.getId()); + + if (pods.length === 0) { + return undefined; + } + + const selectedPod = pods[0]; + + return createLogsTab(`${workload.kind} ${selectedPod.getName()}`, { + selectedContainer: selectedPod.getAllContainers()[0].name, + selectedPodId: selectedPod.getId(), + namespace: selectedPod.getNs(), + owner: { + kind: workload.kind, + name: workload.getName(), + uid: workload.getId(), + }, + }); +}; + +const createWorkloadLogsTabInjectable = getInjectable({ + instantiate: (di) => createWorkloadLogsTab({ + createLogsTab: di.inject(createLogsTabInjectable), + }), + + lifecycle: lifecycleEnum.singleton, +}); + +export default createWorkloadLogsTabInjectable; diff --git a/src/renderer/components/dock/logs/dock-tab.tsx b/src/renderer/components/dock/logs/dock-tab.tsx deleted file mode 100644 index 1ae62b4fe6..0000000000 --- a/src/renderer/components/dock/logs/dock-tab.tsx +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import React from "react"; -import { observer } from "mobx-react"; -import { boundMethod } from "../../../utils"; -import { InfoPanel } from "../info-panel"; -import { LogResourceSelector } from "./resource-selector"; -import { LogList } from "./list"; -import { LogSearch } from "./search"; -import { LogControls } from "./controls"; -import { withInjectables } from "@ogre-tools/injectable-react"; -import logsViewModelInjectable from "./logs-view-model.injectable"; -import type { LogTabViewModel } from "./logs-view-model"; -import type { DockTab } from "../dock-store/dock.store"; - -export interface LogsDockTabProps { - className?: string; - tab: DockTab; -} - -interface Dependencies { - model: LogTabViewModel; -} - -@observer -class NonInjectedLogsDockTab extends React.Component { - private logListElement = React.createRef(); // A reference for VirtualList component - - componentDidMount(): void { - this.props.model.reloadLogs(); - } - - componentWillUnmount(): void { - this.props.model.stopLoadingLogs(); - } - - /** - * Scrolling to active overlay (search word highlight) - */ - @boundMethod - scrollToOverlay() { - const { activeOverlayLine } = this.props.model.searchStore; - - if (!this.logListElement.current || activeOverlayLine === undefined) return; - // Scroll vertically - this.logListElement.current.scrollToItem(activeOverlayLine, "center"); - // Scroll horizontally in timeout since virtual list need some time to prepare its contents - setTimeout(() => { - const overlay = document.querySelector(".PodLogs .list span.active"); - - if (!overlay) return; - overlay.scrollIntoViewIfNeeded(); - }, 100); - } - - render() { - const { model, tab } = this.props; - const { logTabData } = model; - const data = logTabData.get(); - - if (!data) { - return null; - } - - return ( -
- - - -
- )} - showSubmitClose={false} - showButtons={false} - showStatusPanel={false} - /> - - - - ); - } -} - -export const LogsDockTab = withInjectables(NonInjectedLogsDockTab, { - getProps: (di, props) => ({ - model: di.inject(logsViewModelInjectable, { - tabId: props.tab.id, - }), - ...props, - }), -}); diff --git a/src/renderer/components/dock/logs/get-log-tab-data.injectable.ts b/src/renderer/components/dock/logs/get-log-tab-data.injectable.ts index e706fdaafb..35fecebb3a 100644 --- a/src/renderer/components/dock/logs/get-log-tab-data.injectable.ts +++ b/src/renderer/components/dock/logs/get-log-tab-data.injectable.ts @@ -3,10 +3,16 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { LogTabData } from "./tab-store"; import logTabStoreInjectable from "./tab-store.injectable"; const getLogTabDataInjectable = getInjectable({ - instantiate: (di) => di.inject(logTabStoreInjectable).getData, + instantiate: (di) => { + const logTabStore = di.inject(logTabStoreInjectable); + + return (tabId: string): LogTabData => logTabStore.getData(tabId); + }, + lifecycle: lifecycleEnum.singleton, }); diff --git a/src/renderer/components/dock/logs/get-logs-without-timestamps.injectable.ts b/src/renderer/components/dock/logs/get-logs-without-timestamps.injectable.ts index 1be01ff443..250039d7e1 100644 --- a/src/renderer/components/dock/logs/get-logs-without-timestamps.injectable.ts +++ b/src/renderer/components/dock/logs/get-logs-without-timestamps.injectable.ts @@ -6,7 +6,13 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import logStoreInjectable from "./store.injectable"; const getLogsWithoutTimestampsInjectable = getInjectable({ - instantiate: (di) => di.inject(logStoreInjectable).getLogsWithoutTimestampsByTabId, + instantiate: (di) => { + const logStore = di.inject(logStoreInjectable); + + return (tabId: string): string[] => + logStore.getLogsWithoutTimestamps(tabId); + }, + lifecycle: lifecycleEnum.singleton, }); diff --git a/src/renderer/components/dock/logs/get-logs.injectable.ts b/src/renderer/components/dock/logs/get-logs.injectable.ts index 659a87c46f..acd6d10137 100644 --- a/src/renderer/components/dock/logs/get-logs.injectable.ts +++ b/src/renderer/components/dock/logs/get-logs.injectable.ts @@ -6,7 +6,12 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import logStoreInjectable from "./store.injectable"; const getLogsInjectable = getInjectable({ - instantiate: (di) => di.inject(logStoreInjectable).getLogsByTabId, + instantiate: (di) => { + const logStore = di.inject(logStoreInjectable); + + return (tabId: string): string[] => logStore.getLogs(tabId); + }, + lifecycle: lifecycleEnum.singleton, }); diff --git a/src/renderer/components/dock/logs/get-timestamp-split-logs.injectable.ts b/src/renderer/components/dock/logs/get-timestamp-split-logs.injectable.ts index 7cdac68327..4d2189d27e 100644 --- a/src/renderer/components/dock/logs/get-timestamp-split-logs.injectable.ts +++ b/src/renderer/components/dock/logs/get-timestamp-split-logs.injectable.ts @@ -6,7 +6,13 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import logStoreInjectable from "./store.injectable"; const getTimestampSplitLogsInjectable = getInjectable({ - instantiate: (di) => di.inject(logStoreInjectable).getTimestampSplitLogsByTabId, + instantiate: (di) => { + const logStore = di.inject(logStoreInjectable); + + return (tabId: string): [string, string][] => + logStore.getTimestampSplitLogs(tabId); + }, + lifecycle: lifecycleEnum.singleton, }); diff --git a/src/renderer/components/dock/logs/is-logs-tab-data-valid.injectable.ts b/src/renderer/components/dock/logs/is-logs-tab-data-valid.injectable.ts new file mode 100644 index 0000000000..03062ecaae --- /dev/null +++ b/src/renderer/components/dock/logs/is-logs-tab-data-valid.injectable.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { TabId } from "../dock/store"; +import logTabStoreInjectable from "./tab-store.injectable"; + +const isLogsTabDataValidInjectable = getInjectable({ + instantiate: (di) => { + const logTabStore = di.inject(logTabStoreInjectable); + + return (tabId: TabId) => logTabStore.isDataValid(tabId); + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default isLogsTabDataValidInjectable; diff --git a/src/renderer/components/dock/logs/list.tsx b/src/renderer/components/dock/logs/list.tsx index 358889f2f3..273a6ee32f 100644 --- a/src/renderer/components/dock/logs/list.tsx +++ b/src/renderer/components/dock/logs/list.tsx @@ -19,6 +19,7 @@ import { array, boundMethod, cssNames } from "../../../utils"; import { VirtualList } from "../../virtual-list"; import { ToBottom } from "./to-bottom"; import type { LogTabViewModel } from "../logs/logs-view-model"; +import { Spinner } from "../../spinner"; export interface LogListProps { model: LogTabViewModel; @@ -103,8 +104,7 @@ export class LogList extends React.Component { * Checks if JumpToBottom button should be visible and sets its observable * @param props Scrolling props from virtual list core */ - @action - setButtonVisibility = (props: ListOnScrollProps) => { + setButtonVisibility = action((props: ListOnScrollProps) => { const offset = 100 * this.lineHeight; const { scrollHeight } = this.virtualListDiv.current; const { scrollOffset } = props; @@ -114,19 +114,18 @@ export class LogList extends React.Component { } else { this.isJumpButtonVisible = true; } - }; + }); /** * Checks if last log line considered visible to user, setting its observable * @param props Scrolling props from virtual list core */ - @action - setLastLineVisibility = (props: ListOnScrollProps) => { + setLastLineVisibility = action((props: ListOnScrollProps) => { const { scrollHeight, clientHeight } = this.virtualListDiv.current; const { scrollOffset } = props; this.isLastLineVisible = (clientHeight + scrollOffset) === scrollHeight; - }; + }); /** * Check if user scrolled to top and new logs should be loaded @@ -212,12 +211,18 @@ export class LogList extends React.Component { }; render() { - const rowHeights = array.filled(this.logs.length, this.lineHeight); + if (this.props.model.isLoading.get()) { + return ( +
+ +
+ ); + } if (!this.logs.length) { return (
- There are no logs available for container + There are no logs available for container {this.props.model.logTabData.get()?.selectedContainer}
); } @@ -226,7 +231,7 @@ export class LogList extends React.Component {
di.inject(logStoreInjectable).load, + instantiate: (di) => { + const logStore = di.inject(logStoreInjectable); + + return ( + tabId: string, + pod: IComputedValue, + logTabData: IComputedValue, + ): Promise => logStore.load(tabId, pod, logTabData); + }, + lifecycle: lifecycleEnum.singleton, }); diff --git a/src/renderer/components/dock/logs/log-tab-data.validator.ts b/src/renderer/components/dock/logs/log-tab-data.validator.ts new file mode 100644 index 0000000000..32baf38fbb --- /dev/null +++ b/src/renderer/components/dock/logs/log-tab-data.validator.ts @@ -0,0 +1,38 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import Joi from "joi"; +import type { LogTabData, LogTabOwnerRef } from "./tab-store"; + +export const logTabDataValidator = Joi.object({ + owner: Joi + .object({ + uid: Joi + .string() + .required(), + name: Joi + .string() + .required(), + kind: Joi + .string() + .required(), + }) + .unknown(true) + .optional(), + selectedPodId: Joi + .string() + .required(), + namespace: Joi + .string() + .required(), + selectedContainer: Joi + .string() + .optional(), + showTimestamps: Joi + .boolean() + .required(), + showPrevious: Joi + .boolean() + .required(), +}); diff --git a/src/renderer/components/dock/logs/logs-view-model.injectable.ts b/src/renderer/components/dock/logs/logs-view-model.injectable.ts index 7516e47124..d26a34d583 100644 --- a/src/renderer/components/dock/logs/logs-view-model.injectable.ts +++ b/src/renderer/components/dock/logs/logs-view-model.injectable.ts @@ -4,16 +4,19 @@ */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import { LogTabViewModel } from "./logs-view-model"; -import type { TabId } from "../dock-store/dock.store"; +import type { TabId } from "../dock/store"; import getLogsInjectable from "./get-logs.injectable"; import getLogsWithoutTimestampsInjectable from "./get-logs-without-timestamps.injectable"; import getTimestampSplitLogsInjectable from "./get-timestamp-split-logs.injectable"; -import reloadLoadsInjectable from "./reload-logs.injectable"; +import reloadLogsInjectable from "./reload-logs.injectable"; import getLogTabDataInjectable from "./get-log-tab-data.injectable"; import loadLogsInjectable from "./load-logs.injectable"; import setLogTabDataInjectable from "./set-log-tab-data.injectable"; -import updateTabNameInjectable from "./update-tab-name.injectable"; import stopLoadingLogsInjectable from "./stop-loading-logs.injectable"; +import { podsStore } from "../../+workloads-pods/pods.store"; +import renameTabInjectable from "../dock/rename-tab.injectable"; +import areLogsPresentInjectable from "./are-logs-present.injectable"; +import searchStoreInjectable from "../../../search-store/search-store.injectable"; export interface InstantiateArgs { tabId: TabId; @@ -24,12 +27,16 @@ const logsViewModelInjectable = getInjectable({ getLogs: di.inject(getLogsInjectable), getLogsWithoutTimestamps: di.inject(getLogsWithoutTimestampsInjectable), getTimestampSplitLogs: di.inject(getTimestampSplitLogsInjectable), - reloadLogs: di.inject(reloadLoadsInjectable), + reloadLogs: di.inject(reloadLogsInjectable), getLogTabData: di.inject(getLogTabDataInjectable), setLogTabData: di.inject(setLogTabDataInjectable), loadLogs: di.inject(loadLogsInjectable), - updateTabName: di.inject(updateTabNameInjectable), + renameTab: di.inject(renameTabInjectable), stopLoadingLogs: di.inject(stopLoadingLogsInjectable), + areLogsPresent: di.inject(areLogsPresentInjectable), + getPodById: id => podsStore.getById(id), + getPodsByOwnerId: id => podsStore.getPodsByOwnerId(id), + searchStore: di.inject(searchStoreInjectable), }), lifecycle: lifecycleEnum.transient, }); diff --git a/src/renderer/components/dock/logs/logs-view-model.ts b/src/renderer/components/dock/logs/logs-view-model.ts index 6c2f182355..73ed0c770f 100644 --- a/src/renderer/components/dock/logs/logs-view-model.ts +++ b/src/renderer/components/dock/logs/logs-view-model.ts @@ -2,10 +2,11 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { LogTabData } from "./tab.store"; +import type { LogTabData } from "./tab-store"; import { computed, IComputedValue } from "mobx"; -import type { TabId } from "../dock-store/dock.store"; -import { SearchStore } from "../../../search-store/search-store"; +import type { TabId } from "../dock/store"; +import type { SearchStore } from "../../../search-store/search-store"; +import type { Pod } from "../../../../common/k8s-api/endpoints"; export interface LogTabViewModelDependencies { getLogs: (tabId: TabId) => string[]; @@ -13,27 +14,57 @@ export interface LogTabViewModelDependencies { getTimestampSplitLogs: (tabId: TabId) => [string, string][]; getLogTabData: (tabId: TabId) => LogTabData; setLogTabData: (tabId: TabId, data: LogTabData) => void; - loadLogs: (tabId: TabId, logTabData: IComputedValue) => Promise; - reloadLogs: (tabId: TabId, logTabData: IComputedValue) => Promise; - updateTabName: (tabId: TabId) => void; + loadLogs: (tabId: TabId, pod: IComputedValue, logTabData: IComputedValue) => Promise; + reloadLogs: (tabId: TabId, pod: IComputedValue, logTabData: IComputedValue) => Promise; + renameTab: (tabId: TabId, title: string) => void; stopLoadingLogs: (tabId: TabId) => void; + getPodById: (id: string) => Pod | undefined; + getPodsByOwnerId: (id: string) => Pod[]; + areLogsPresent: (tabId: TabId) => boolean; + searchStore: SearchStore; } export class LogTabViewModel { constructor(protected readonly tabId: TabId, private readonly dependencies: LogTabViewModelDependencies) {} + get searchStore() { + return this.dependencies.searchStore; + } + + readonly isLoading = computed(() => this.dependencies.areLogsPresent(this.tabId)); readonly logs = computed(() => this.dependencies.getLogs(this.tabId)); readonly logsWithoutTimestamps = computed(() => this.dependencies.getLogsWithoutTimestamps(this.tabId)); readonly timestampSplitLogs = computed(() => this.dependencies.getTimestampSplitLogs(this.tabId)); readonly logTabData = computed(() => this.dependencies.getLogTabData(this.tabId)); - readonly searchStore = new SearchStore(); + readonly pods = computed(() => { + const data = this.logTabData.get(); + + if (!data) { + return []; + } + + if (typeof data.owner?.uid === "string") { + return this.dependencies.getPodsByOwnerId(data.owner.uid); + } + + return [this.dependencies.getPodById(data.selectedPodId)]; + }); + readonly pod = computed(() => { + const data = this.logTabData.get(); + + if (!data) { + return undefined; + } + + return this.dependencies.getPodById(data.selectedPodId); + }); updateLogTabData = (partialData: Partial) => { this.dependencies.setLogTabData(this.tabId, { ...this.logTabData.get(), ...partialData }); }; - loadLogs = () => this.dependencies.loadLogs(this.tabId, this.logTabData); - reloadLogs = () => this.dependencies.reloadLogs(this.tabId, this.logTabData); - updateTabName = () => this.dependencies.updateTabName(this.tabId); + loadLogs = () => this.dependencies.loadLogs(this.tabId, this.pod, this.logTabData); + reloadLogs = () => this.dependencies.reloadLogs(this.tabId, this.pod, this.logTabData); + renameTab = (title: string) => this.dependencies.renameTab(this.tabId, title); stopLoadingLogs = () => this.dependencies.stopLoadingLogs(this.tabId); } diff --git a/src/renderer/components/dock/logs/reload-logs.injectable.ts b/src/renderer/components/dock/logs/reload-logs.injectable.ts index 9fa917bf4b..4ba55c4b58 100644 --- a/src/renderer/components/dock/logs/reload-logs.injectable.ts +++ b/src/renderer/components/dock/logs/reload-logs.injectable.ts @@ -3,11 +3,23 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { IComputedValue } from "mobx"; +import type { Pod } from "../../../../common/k8s-api/endpoints"; import logStoreInjectable from "./store.injectable"; +import type { LogTabData } from "./tab-store"; + +const reloadLogsInjectable = getInjectable({ + instantiate: (di) => { + const logStore = di.inject(logStoreInjectable); + + return ( + tabId: string, + pod: IComputedValue, + logTabData: IComputedValue, + ): Promise => logStore.reload(tabId, pod, logTabData); + }, -const reloadLoadsInjectable = getInjectable({ - instantiate: (di) => di.inject(logStoreInjectable).reload, lifecycle: lifecycleEnum.singleton, }); -export default reloadLoadsInjectable; +export default reloadLogsInjectable; diff --git a/src/renderer/components/dock/logs/resource-selector.tsx b/src/renderer/components/dock/logs/resource-selector.tsx index bca2c30f45..459069fd61 100644 --- a/src/renderer/components/dock/logs/resource-selector.tsx +++ b/src/renderer/components/dock/logs/resource-selector.tsx @@ -5,19 +5,25 @@ import "./resource-selector.scss"; -import React, { useEffect } from "react"; +import React from "react"; import { observer } from "mobx-react"; -import { Pod } from "../../../../common/k8s-api/endpoints"; import { Badge } from "../../badge"; import { Select, SelectOption } from "../../select"; -import { podsStore } from "../../+workloads-pods/pods.store"; import type { LogTabViewModel } from "./logs-view-model"; +import type { IPodContainer, Pod } from "../../../../common/k8s-api/endpoints"; export interface LogResourceSelectorProps { model: LogTabViewModel; } +function getSelectOptions(containers: IPodContainer[]): SelectOption[] { + return containers.map(container => ({ + value: container.name, + label: container.name, + })); +} + export const LogResourceSelector = observer(({ model }: LogResourceSelectorProps) => { const tabData = model.logTabData.get(); @@ -25,66 +31,61 @@ export const LogResourceSelector = observer(({ model }: LogResourceSelectorProps return null; } - const { selectedPod, selectedContainer, pods } = tabData; - const pod = new Pod(selectedPod); - const containers = pod.getContainers(); - const initContainers = pod.getInitContainers(); + const { selectedContainer, owner } = tabData; + const pods = model.pods.get(); + const pod = model.pod.get(); - const onContainerChange = (option: SelectOption) => { + if (!pod) { + return null; + } + + const onContainerChange = (option: SelectOption) => { model.updateLogTabData({ - selectedContainer: containers - .concat(initContainers) - .find(container => container.name === option.value), + selectedContainer: option.value, }); - model.reloadLogs(); }; - const onPodChange = (option: SelectOption) => { - const selectedPod = podsStore.getByName(option.value, pod.getNs()); - - model.updateLogTabData({ selectedPod }); - model.updateTabName(); - }; - - const getSelectOptions = (items: string[]) => { - return items.map(item => { - return { - value: item, - label: item, - }; + const onPodChange = ({ value }: SelectOption) => { + model.updateLogTabData({ + selectedPodId: value.getId(), + selectedContainer: value.getAllContainers()[0]?.name, }); + model.renameTab(`Pod ${value.getName()}`); + model.reloadLogs(); }; const containerSelectOptions = [ { - label: `Containers`, - options: getSelectOptions(containers.map(container => container.name)), + label: "Containers", + options: getSelectOptions(pod.getContainers()), }, { - label: `Init Containers`, - options: getSelectOptions(initContainers.map(container => container.name)), + label: "Init Containers", + options: getSelectOptions(pod.getInitContainers()), }, ]; - const podSelectOptions = [ - { - label: pod.getOwnerRefs()[0]?.name, - options: getSelectOptions(pods.map(pod => pod.metadata.name)), - }, - ]; - - useEffect(() => { - model.reloadLogs(); - }, [selectedPod]); + const podSelectOptions = pods.map(pod => ({ + label: pod.getName(), + value: pod, + })); return (
Namespace + { + owner && ( + <> + Owner + + ) + } Pod void; - toPrevOverlay: () => void; - toNextOverlay: () => void; + onSearch?: (query: string) => void; + scrollToOverlay: (lineNumber: number | undefined) => void; model: LogTabViewModel; } - -export const LogSearch = observer(({ onSearch, toPrevOverlay, toNextOverlay, model }: PodLogSearchProps) => { - const tabData = model.logTabData.get(); +export const LogSearch = observer(({ onSearch, scrollToOverlay, model: { logTabData, searchStore, ...model }}: PodLogSearchProps) => { + const tabData = logTabData.get(); if (!tabData) { return null; @@ -29,27 +27,23 @@ export const LogSearch = observer(({ onSearch, toPrevOverlay, toNextOverlay, mod const logs = tabData.showTimestamps ? model.logs.get() : model.logsWithoutTimestamps.get(); - const { setNextOverlayActive, setPrevOverlayActive, searchQuery, occurrences, activeFind, totalFinds } = model.searchStore; + const { setNextOverlayActive, setPrevOverlayActive, searchQuery, occurrences, activeFind, totalFinds } = searchStore; const jumpDisabled = !searchQuery || !occurrences.length; - const findCounts = ( -
- {activeFind}/{totalFinds} -
- ); const setSearch = (query: string) => { - model.searchStore.onSearch(logs, query); - onSearch(query); + searchStore.onSearch(logs, query); + onSearch?.(query); + scrollToOverlay(searchStore.activeOverlayLine); }; const onPrevOverlay = () => { setPrevOverlayActive(); - toPrevOverlay(); + scrollToOverlay(searchStore.activeOverlayLine); }; const onNextOverlay = () => { setNextOverlayActive(); - toNextOverlay(); + scrollToOverlay(searchStore.activeOverlayLine); }; const onClear = () => { @@ -58,13 +52,17 @@ export const LogSearch = observer(({ onSearch, toPrevOverlay, toNextOverlay, mod const onKeyDown = (evt: React.KeyboardEvent) => { if (evt.key === "Enter") { - onNextOverlay(); + if (evt.shiftKey) { + onPrevOverlay(); + } else { + onNextOverlay(); + } } }; useEffect(() => { // Refresh search when logs changed - model.searchStore.onSearch(logs); + searchStore.onSearch(logs); }, [logs]); return ( @@ -73,7 +71,11 @@ export const LogSearch = observer(({ onSearch, toPrevOverlay, toNextOverlay, mod value={searchQuery} onChange={setSearch} showClearIcon={true} - contentRight={totalFinds > 0 && findCounts} + contentRight={totalFinds > 0 && ( +
+ {activeFind}/{totalFinds} +
+ )} onClear={onClear} onKeyDown={onKeyDown} /> diff --git a/src/renderer/components/dock/logs/set-log-tab-data.injectable.ts b/src/renderer/components/dock/logs/set-log-tab-data.injectable.ts index ac783dfcc7..db84635bf1 100644 --- a/src/renderer/components/dock/logs/set-log-tab-data.injectable.ts +++ b/src/renderer/components/dock/logs/set-log-tab-data.injectable.ts @@ -3,10 +3,16 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { LogTabData } from "./tab-store"; import logTabStoreInjectable from "./tab-store.injectable"; const setLogTabDataInjectable = getInjectable({ - instantiate: (di) => di.inject(logTabStoreInjectable).setData, + instantiate: (di) => { + const logTabStore = di.inject(logTabStoreInjectable); + + return (tabId: string, data: LogTabData): void => logTabStore.setData(tabId, data); + }, + lifecycle: lifecycleEnum.singleton, }); diff --git a/src/renderer/components/dock/logs/stop-loading-logs.injectable.ts b/src/renderer/components/dock/logs/stop-loading-logs.injectable.ts index afe2542083..db0df464cf 100644 --- a/src/renderer/components/dock/logs/stop-loading-logs.injectable.ts +++ b/src/renderer/components/dock/logs/stop-loading-logs.injectable.ts @@ -6,7 +6,12 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import logStoreInjectable from "./store.injectable"; const stopLoadingLogsInjectable = getInjectable({ - instantiate: (di) => di.inject(logStoreInjectable).stopLoadingLogs, + instantiate: (di) => { + const logStore = di.inject(logStoreInjectable); + + return (tabId: string): void => logStore.stopLoadingLogs(tabId); + }, + lifecycle: lifecycleEnum.singleton, }); diff --git a/src/renderer/components/dock/logs/store.ts b/src/renderer/components/dock/logs/store.ts index 7c0116252f..fb0c446119 100644 --- a/src/renderer/components/dock/logs/store.ts +++ b/src/renderer/components/dock/logs/store.ts @@ -3,12 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { computed, observable, makeObservable, IComputedValue } from "mobx"; - -import { IPodLogsQuery, Pod } from "../../../../common/k8s-api/endpoints"; -import { autoBind, getOrInsertWith, interval, IntervalFn } from "../../../utils"; -import type { TabId } from "../dock-store/dock.store"; -import type { LogTabData } from "./tab.store"; +import { observable, IComputedValue, when } from "mobx"; +import type { IPodLogsQuery, Pod } from "../../../../common/k8s-api/endpoints"; +import { getOrInsertWith, interval, IntervalFn } from "../../../utils"; +import type { TabId } from "../dock/store"; +import type { LogTabData } from "./tab-store"; type PodLogLine = string; @@ -19,15 +18,12 @@ interface Dependencies { } export class LogStore { - @observable protected podLogs = observable.map(); + protected podLogs = observable.map(); protected refreshers = new Map(); - constructor(private dependencies: Dependencies) { - makeObservable(this); - autoBind(this); - } + constructor(private dependencies: Dependencies) {} - handlerError(tabId: TabId, error: any): void { + protected handlerError(tabId: TabId, error: any): void { if (error.error && !(error.message || error.reason || error.code)) { error = error.error; } @@ -47,24 +43,24 @@ export class LogStore { * Also, it handles loading errors, rewriting whole logs with error * messages */ - load = async (tabId: TabId, logTabData: IComputedValue) => { + public async load(tabId: TabId, computedPod: IComputedValue, logTabData: IComputedValue): Promise { try { - const logs = await this.loadLogs(logTabData, { - tailLines: this.getLinesByTabId(tabId) + logLinesToLoad, + const logs = await this.loadLogs(computedPod, logTabData, { + tailLines: this.getLogLines(tabId) + logLinesToLoad, }); - this.getRefresher(tabId, logTabData).start(); + this.getRefresher(tabId, computedPod, logTabData).start(); this.podLogs.set(tabId, logs); } catch (error) { this.handlerError(tabId, error); } - }; + } - private getRefresher(tabId: TabId, logTabData: IComputedValue): IntervalFn { + private getRefresher(tabId: TabId, computedPod: IComputedValue, logTabData: IComputedValue): IntervalFn { return getOrInsertWith(this.refreshers, tabId, () => ( interval(10, () => { if (this.podLogs.has(tabId)) { - this.loadMore(tabId, logTabData); + this.loadMore(tabId, computedPod, logTabData); } }) )); @@ -84,14 +80,14 @@ export class LogStore { * starting from last line received. * @param tabId */ - loadMore = async (tabId: TabId, logTabData: IComputedValue) => { + public async loadMore(tabId: TabId, computedPod: IComputedValue, logTabData: IComputedValue): Promise { if (!this.podLogs.get(tabId).length) { return; } try { const oldLogs = this.podLogs.get(tabId); - const logs = await this.loadLogs(logTabData, { + const logs = await this.loadLogs(computedPod, logTabData, { sinceTime: this.getLastSinceTime(tabId), }); @@ -100,7 +96,7 @@ export class LogStore { } catch (error) { this.handlerError(tabId, error); } - }; + } /** * Main logs loading function adds necessary data to payload and makes @@ -109,17 +105,19 @@ export class LogStore { * @param params request parameters described in IPodLogsQuery interface * @returns A fetch request promise */ - private async loadLogs(logTabData: IComputedValue, params: Partial): Promise { - const { selectedContainer, previous, selectedPod } = logTabData.get(); - const pod = new Pod(selectedPod); + private async loadLogs(computedPod: IComputedValue, logTabData: IComputedValue, params: Partial): Promise { + await when(() => Boolean(computedPod.get() && logTabData.get()), { timeout: 5_000 }); + + const { selectedContainer, showPrevious } = logTabData.get(); + const pod = computedPod.get(); const namespace = pod.getNs(); const name = pod.getName(); const result = await this.dependencies.callForLogs({ namespace, name }, { ...params, timestamps: true, // Always setting timestamp to separate old logs from new ones - container: selectedContainer.name, - previous, + container: selectedContainer, + previous: showPrevious, }); return result.trimEnd().split("\n"); @@ -130,26 +128,29 @@ export class LogStore { * Converts logs into a string array * @returns Length of log lines */ - @computed get lines(): number { return this.logs.length; } - public getLinesByTabId = (tabId: TabId): number => { - return this.getLogsByTabId(tabId).length; - }; + getLogLines(tabId: TabId): number{ + return this.getLogs(tabId).length; + } - public getLogsByTabId = (tabId: TabId): string[] => { + areLogsPresent(tabId: TabId): boolean { + return !this.podLogs.has(tabId); + } + + getLogs(tabId: TabId): string[]{ return this.podLogs.get(tabId) ?? []; - }; + } - public getLogsWithoutTimestampsByTabId = (tabId: TabId): string[] => { - return this.getLogsByTabId(tabId).map(this.removeTimestamps); - }; + getLogsWithoutTimestamps(tabId: TabId): string[]{ + return this.getLogs(tabId).map(this.removeTimestamps); + } - public getTimestampSplitLogsByTabId = (tabId: TabId): [string, string][] => { - return this.getLogsByTabId(tabId).map(this.splitOutTimestamp); - }; + getTimestampSplitLogs(tabId: TabId): [string, string][]{ + return this.getLogs(tabId).map(this.splitOutTimestamp); + } /** * @deprecated This now only returns the empty array @@ -173,7 +174,7 @@ export class LogStore { * (this allows to avoid getting the last stamp in the selection) * @param tabId */ - getLastSinceTime(tabId: TabId) { + getLastSinceTime(tabId: TabId): string { const logs = this.podLogs.get(tabId); const timestamps = this.getTimestamps(logs[logs.length - 1]); const stamp = new Date(timestamps ? timestamps[0] : null); @@ -183,7 +184,7 @@ export class LogStore { return stamp.toISOString(); } - splitOutTimestamp = (logs: string): [string, string] => { + splitOutTimestamp(logs: string): [string, string] { const extraction = /^(\d+\S+)(.*)/m.exec(logs); if (!extraction || extraction.length < 3) { @@ -191,23 +192,23 @@ export class LogStore { } return [extraction[1], extraction[2]]; - }; + } - getTimestamps(logs: string) { + getTimestamps(logs: string): RegExpMatchArray { return logs.match(/^\d+\S+/gm); } - removeTimestamps = (logs: string) => { + removeTimestamps(logs: string): string { return logs.replace(/^\d+.*?\s/gm, ""); - }; + } - clearLogs(tabId: TabId) { + clearLogs(tabId: TabId): void { this.podLogs.delete(tabId); } - reload = (tabId: TabId, logTabData: IComputedValue) => { + reload(tabId: TabId, computedPod: IComputedValue, logTabData: IComputedValue): Promise { this.clearLogs(tabId); - return this.load(tabId, logTabData); - }; + return this.load(tabId, computedPod, logTabData); + } } diff --git a/src/renderer/components/dock/logs/tab-store.injectable.ts b/src/renderer/components/dock/logs/tab-store.injectable.ts index 2ccc2067dc..61d4667f55 100644 --- a/src/renderer/components/dock/logs/tab-store.injectable.ts +++ b/src/renderer/components/dock/logs/tab-store.injectable.ts @@ -3,13 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import { LogTabStore } from "./tab.store"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; +import { LogTabStore } from "./tab-store"; import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; const logTabStoreInjectable = getInjectable({ instantiate: (di) => new LogTabStore({ - dockStore: di.inject(dockStoreInjectable), createStorage: di.inject(createStorageInjectable), }), diff --git a/src/renderer/components/dock/logs/tab-store.ts b/src/renderer/components/dock/logs/tab-store.ts new file mode 100644 index 0000000000..b2649472e0 --- /dev/null +++ b/src/renderer/components/dock/logs/tab-store.ts @@ -0,0 +1,81 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { DockTabStorageState, DockTabStore } from "../dock-tab-store/dock-tab.store"; +import type { StorageHelper } from "../../../utils"; +import type { TabId } from "../dock/store"; +import { logTabDataValidator } from "./log-tab-data.validator"; + +export interface LogTabOwnerRef { + /** + * The uid of the owner + */ + uid: string; + /** + * The name of the owner + */ + name: string; + /** + * The kind of the owner + */ + kind: string; +} + +export interface LogTabData { + /** + * The owning workload for this logging tab + */ + owner?: LogTabOwnerRef; + + /** + * The uid of the currently selected pod + */ + selectedPodId: string; + + /** + * The namespace of the pods/workload + */ + namespace: string; + + /** + * The name of the currently selected container within the currently selected + * pod + */ + selectedContainer: string; + + /** + * Whether to show timestamps in the logs + */ + showTimestamps: boolean; + + /** + * Whether to show the logs of the previous container instance + */ + showPrevious: boolean; +} + +interface Dependencies { + createStorage: (storageKey: string, options: DockTabStorageState) => StorageHelper> +} + +export class LogTabStore extends DockTabStore { + constructor(protected dependencies: Dependencies) { + super(dependencies, { + storageKey: "pod_logs", + }); + } + + /** + * Returns true if the data for `tabId` is valid + */ + isDataValid(tabId: TabId): boolean { + if (!this.getData(tabId)) { + return true; + } + + return !logTabDataValidator.validate(this.getData(tabId)).error; + } +} + diff --git a/src/renderer/components/dock/logs/tab.store.ts b/src/renderer/components/dock/logs/tab.store.ts deleted file mode 100644 index 83310f740e..0000000000 --- a/src/renderer/components/dock/logs/tab.store.ts +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import uniqueId from "lodash/uniqueId"; -import { reaction } from "mobx"; -import { podsStore } from "../../+workloads-pods/pods.store"; - -import { IPodContainer, Pod } from "../../../../common/k8s-api/endpoints"; -import type { WorkloadKubeObject } from "../../../../common/k8s-api/workload-kube-object"; -import logger from "../../../../common/logger"; -import { DockTabStorageState, DockTabStore } from "../dock-tab-store/dock-tab.store"; -import { DockStore, DockTabCreateSpecific, TabKind } from "../dock-store/dock.store"; -import type { StorageHelper } from "../../../utils"; - -export interface LogTabData { - pods: Pod[]; - selectedPod: Pod; - selectedContainer: IPodContainer - showTimestamps?: boolean - previous?: boolean -} - -interface PodLogsTabData { - selectedPod: Pod - selectedContainer: IPodContainer -} - -interface WorkloadLogsTabData { - workload: WorkloadKubeObject -} - -interface Dependencies { - dockStore: DockStore - createStorage: (storageKey: string, options: DockTabStorageState) => StorageHelper> -} - -export class LogTabStore extends DockTabStore { - constructor(protected dependencies: Dependencies) { - super(dependencies, { - storageKey: "pod_logs", - }); - - reaction(() => podsStore.items.length, () => this.updateTabsData()); - } - - createPodTab({ selectedPod, selectedContainer }: PodLogsTabData): string { - const podOwner = selectedPod.getOwnerRefs()[0]; - const pods = podsStore.getPodsByOwnerId(podOwner?.uid); - const title = `Pod ${selectedPod.getName()}`; - - return this.createLogsTab(title, { - pods: pods.length ? pods : [selectedPod], - selectedPod, - selectedContainer, - }); - } - - createWorkloadTab({ workload }: WorkloadLogsTabData): void { - const pods = podsStore.getPodsByOwnerId(workload.getId()); - - if (!pods.length) return; - - const selectedPod = pods[0]; - const selectedContainer = selectedPod.getAllContainers()[0]; - const title = `${workload.kind} ${selectedPod.getName()}`; - - this.createLogsTab(title, { - pods, - selectedPod, - selectedContainer, - }); - } - - updateTabName(tabId: string) { - const { selectedPod } = this.getData(tabId); - - this.dependencies.dockStore.renameTab(tabId, `Pod ${selectedPod.metadata.name}`); - } - - private createDockTab(tabParams: DockTabCreateSpecific) { - this.dependencies.dockStore.createTab({ - ...tabParams, - kind: TabKind.POD_LOGS, - }, false); - } - - private createLogsTab(title: string, data: LogTabData): string { - const id = uniqueId("log-tab-"); - - this.createDockTab({ id, title }); - this.setData(id, { - ...data, - showTimestamps: false, - previous: false, - }); - - return id; - } - - private updateTabsData() { - for (const [tabId, tabData] of this.data) { - try { - if (!tabData.selectedPod) { - tabData.selectedPod = tabData.pods[0]; - } - - const pod = new Pod(tabData.selectedPod); - const pods = podsStore.getPodsByOwnerId(pod.getOwnerRefs()[0]?.uid); - const isSelectedPodInList = pods.find(item => item.getId() == pod.getId()); - const selectedPod = isSelectedPodInList ? pod : pods[0]; - const selectedContainer = isSelectedPodInList ? tabData.selectedContainer : pod.getAllContainers()[0]; - - if (pods.length > 0) { - this.setData(tabId, { - ...tabData, - selectedPod, - selectedContainer, - pods, - }); - - this.updateTabName(tabId); - } else { - this.closeTab(tabId); - } - } catch (error) { - logger.error(`[LOG-TAB-STORE]: failed to set data for tabId=${tabId} deleting`, error); - this.data.delete(tabId); - } - } - } - - private closeTab(tabId: string) { - this.clearData(tabId); - this.dependencies.dockStore.closeTab(tabId); - } -} - diff --git a/src/renderer/components/dock/logs/view.tsx b/src/renderer/components/dock/logs/view.tsx new file mode 100644 index 0000000000..c73933b12f --- /dev/null +++ b/src/renderer/components/dock/logs/view.tsx @@ -0,0 +1,101 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React, { createRef, useEffect } from "react"; +import { observer } from "mobx-react"; +import { InfoPanel } from "../info-panel"; +import { LogResourceSelector } from "./resource-selector"; +import { LogList } from "./list"; +import { LogSearch } from "./search"; +import { LogControls } from "./controls"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import logsViewModelInjectable from "./logs-view-model.injectable"; +import type { LogTabViewModel } from "./logs-view-model"; +import type { DockTab } from "../dock/store"; +import { cssNames, Disposer } from "../../../utils"; +import type { KubeWatchSubscribeStoreOptions } from "../../../kube-watch-api/kube-watch-api"; +import subscribeStoresInjectable from "../../../kube-watch-api/subscribe-stores.injectable"; +import type { KubeObjectStore } from "../../../../common/k8s-api/kube-object.store"; +import type { KubeObject } from "../../../../common/k8s-api/kube-object"; +import { podsStore } from "../../+workloads-pods/pods.store"; + +export interface LogsDockTabProps { + className?: string; + tab: DockTab; +} + +interface Dependencies { + model: LogTabViewModel; + subscribeStores: (stores: KubeObjectStore[], opts?: KubeWatchSubscribeStoreOptions) => Disposer; +} + +const NonInjectedLogsDockTab = observer(({ className, tab, model, subscribeStores }: Dependencies & LogsDockTabProps) => { + const logListElement = createRef(); + const data = model.logTabData.get(); + + useEffect(() => { + model.reloadLogs(); + + return model.stopLoadingLogs; + }, []); + useEffect(() => subscribeStores([ + podsStore, + ], { + namespaces: data ? [data.namespace] : [], + }), [data?.namespace]); + + const scrollToOverlay = (overlayLine: number | undefined) => { + if (!logListElement.current || overlayLine === undefined) { + return; + } + + // Scroll vertically + logListElement.current.scrollToItem(overlayLine, "center"); + // Scroll horizontally in timeout since virtual list need some time to prepare its contents + setTimeout(() => { + const overlay = document.querySelector(".PodLogs .list span.active"); + + if (!overlay) return; + overlay.scrollIntoViewIfNeeded(); + }, 100); + }; + + if (!data) { + return null; + } + + return ( +
+ + + +
+ )} + showSubmitClose={false} + showButtons={false} + showStatusPanel={false} + /> + + +
+ ); +}); + + +export const LogsDockTab = withInjectables(NonInjectedLogsDockTab, { + getProps: (di, props) => ({ + model: di.inject(logsViewModelInjectable, { + tabId: props.tab.id, + }), + subscribeStores: di.inject(subscribeStoresInjectable), + ...props, + }), +}); diff --git a/src/renderer/components/dock/terminal-store/terminal.store.ts b/src/renderer/components/dock/terminal-store/terminal.store.ts deleted file mode 100644 index 9203edb87b..0000000000 --- a/src/renderer/components/dock/terminal-store/terminal.store.ts +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { autorun, observable, when } from "mobx"; -import { autoBind, noop } from "../../../utils"; -import type { Terminal } from "../terminal/terminal"; -import { TerminalApi, TerminalChannels } from "../../../api/terminal-api"; -import { - DockStore, - DockTab, - DockTabCreate, - TabId, - TabKind, -} from "../dock-store/dock.store"; -import { WebSocketApiState } from "../../../api/websocket-api"; -import { Notifications } from "../../notifications"; - -export interface ITerminalTab extends DockTab { - node?: string; // activate node shell mode -} - -interface Dependencies { - createTerminalTab: () => DockTabCreate - dockStore: DockStore - createTerminal: (tabId: TabId, api: TerminalApi) => Terminal -} - -export class TerminalStore { - protected terminals = new Map(); - protected connections = observable.map(); - - constructor(private dependencies: Dependencies) { - autoBind(this); - - // connect active tab - autorun(() => { - const { selectedTab, isOpen } = dependencies.dockStore; - - if (selectedTab?.kind === TabKind.TERMINAL && isOpen) { - this.connect(selectedTab.id); - } - }); - // disconnect closed tabs - autorun(() => { - const currentTabs = dependencies.dockStore.tabs.map(tab => tab.id); - - for (const [tabId] of this.connections) { - if (!currentTabs.includes(tabId)) this.disconnect(tabId); - } - }); - } - - connect(tabId: TabId) { - if (this.isConnected(tabId)) { - return; - } - const tab: ITerminalTab = this.dependencies.dockStore.getTabById(tabId); - const api = new TerminalApi({ - id: tabId, - node: tab.node, - }); - const terminal = this.dependencies.createTerminal(tabId, api); - - this.connections.set(tabId, api); - this.terminals.set(tabId, terminal); - - api.connect(); - } - - disconnect(tabId: TabId) { - if (!this.isConnected(tabId)) { - return; - } - const terminal = this.terminals.get(tabId); - const terminalApi = this.connections.get(tabId); - - terminal.destroy(); - terminalApi.destroy(); - this.connections.delete(tabId); - this.terminals.delete(tabId); - } - - reconnect(tabId: TabId) { - this.connections.get(tabId)?.connect(); - } - - isConnected(tabId: TabId) { - return Boolean(this.connections.get(tabId)); - } - - isDisconnected(tabId: TabId) { - return this.connections.get(tabId)?.readyState === WebSocketApiState.CLOSED; - } - - async sendCommand(command: string, options: { enter?: boolean; newTab?: boolean; tabId?: TabId } = {}) { - const { enter, newTab, tabId } = options; - - if (tabId) { - this.dependencies.dockStore.selectTab(tabId); - } - - if (newTab) { - const tab = this.dependencies.createTerminalTab(); - - await when(() => this.connections.has(tab.id)); - - const shellIsReady = when(() => this.connections.get(tab.id).isReady); - const notifyVeryLong = setTimeout(() => { - shellIsReady.cancel(); - Notifications.info( - "If terminal shell is not ready please check your shell init files, if applicable.", - { - timeout: 4_000, - }, - ); - }, 10_000); - - await shellIsReady.catch(noop); - clearTimeout(notifyVeryLong); - } - - const terminalApi = this.connections.get(this.dependencies.dockStore.selectedTabId); - - if (terminalApi) { - if (enter) { - command += "\r"; - } - - terminalApi.sendMessage({ - type: TerminalChannels.STDIN, - data: command, - }); - } else { - console.warn( - "The selected tab is does not have a connection. Cannot send command.", - { tabId: this.dependencies.dockStore.selectedTabId, command }, - ); - } - } - - getTerminal(tabId: TabId) { - return this.terminals.get(tabId); - } - - reset() { - [...this.connections].forEach(([tabId]) => { - this.disconnect(tabId); - }); - } -} diff --git a/src/renderer/components/dock/terminal-tab.scss b/src/renderer/components/dock/terminal-tab.scss deleted file mode 100644 index faa0f5a7f3..0000000000 --- a/src/renderer/components/dock/terminal-tab.scss +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -.TerminalTab { - -} diff --git a/src/renderer/components/dock/terminal-window.tsx b/src/renderer/components/dock/terminal-window.tsx deleted file mode 100644 index 5d76f69543..0000000000 --- a/src/renderer/components/dock/terminal-window.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import "./terminal-window.scss"; - -import React from "react"; -import { disposeOnUnmount, observer } from "mobx-react"; -import { cssNames } from "../../utils"; -import type { Terminal } from "./terminal/terminal"; -import type { TerminalStore } from "./terminal-store/terminal.store"; -import { ThemeStore } from "../../theme.store"; -import { DockTab, TabKind, TabId, DockStore } from "./dock-store/dock.store"; -import { withInjectables } from "@ogre-tools/injectable-react"; -import dockStoreInjectable from "./dock-store/dock-store.injectable"; -import terminalStoreInjectable from "./terminal-store/terminal-store.injectable"; - -interface Props { - tab: DockTab; -} - -interface Dependencies { - dockStore: DockStore - terminalStore: TerminalStore -} - -@observer -class NonInjectedTerminalWindow extends React.Component { - public elem: HTMLElement; - public terminal: Terminal; - - componentDidMount() { - disposeOnUnmount(this, [ - this.props.dockStore.onTabChange(({ tabId }) => this.activate(tabId), { - tabKind: TabKind.TERMINAL, - fireImmediately: true, - }), - - // refresh terminal available space (cols/rows) when resized - this.props.dockStore.onResize(() => this.terminal?.fitLazy(), { - fireImmediately: true, - }), - ]); - } - - activate(tabId: TabId) { - this.terminal?.detach(); // detach previous - this.terminal = this.props.terminalStore.getTerminal(tabId); - this.terminal.attachTo(this.elem); - } - - render() { - return ( -
this.elem = elem} - /> - ); - } -} - -export const TerminalWindow = withInjectables( - NonInjectedTerminalWindow, - - { - getProps: (di, props) => ({ - dockStore: di.inject(dockStoreInjectable), - terminalStore: di.inject(terminalStoreInjectable), - ...props, - }), - }, -); - diff --git a/src/renderer/components/dock/terminal/clear-terminal-tab-data.injectable.ts b/src/renderer/components/dock/terminal/clear-terminal-tab-data.injectable.ts new file mode 100644 index 0000000000..4396e3ee20 --- /dev/null +++ b/src/renderer/components/dock/terminal/clear-terminal-tab-data.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { TabId } from "../dock/store"; +import terminalStoreInjectable from "./store.injectable"; + +const clearTerminalTabDataInjectable = getInjectable({ + instantiate: (di) => { + const terminalStore = di.inject(terminalStoreInjectable); + + return (tabId: TabId): void => { + terminalStore.destroy(tabId); + }; + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default clearTerminalTabDataInjectable; diff --git a/src/renderer/components/dock/terminal/create-terminal-tab.injectable.ts b/src/renderer/components/dock/terminal/create-terminal-tab.injectable.ts new file mode 100644 index 0000000000..9348bd49ef --- /dev/null +++ b/src/renderer/components/dock/terminal/create-terminal-tab.injectable.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import dockStoreInjectable from "../dock/store.injectable"; +import { DockTabCreateSpecific, TabKind } from "../dock/store"; + +const createTerminalTabInjectable = getInjectable({ + instantiate: (di) => { + const dockStore = di.inject(dockStoreInjectable); + + return (tabParams: DockTabCreateSpecific = {}) => + dockStore.createTab({ + title: `Terminal`, + ...tabParams, + kind: TabKind.TERMINAL, + }); + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default createTerminalTabInjectable; diff --git a/src/renderer/components/dock/terminal/create-terminal.injectable.ts b/src/renderer/components/dock/terminal/create-terminal.injectable.ts index b52b24d13f..2dc6f04941 100644 --- a/src/renderer/components/dock/terminal/create-terminal.injectable.ts +++ b/src/renderer/components/dock/terminal/create-terminal.injectable.ts @@ -4,20 +4,11 @@ */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import { Terminal } from "./terminal"; -import type { TabId } from "../dock-store/dock.store"; +import type { TabId } from "../dock/store"; import type { TerminalApi } from "../../../api/terminal-api"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; const createTerminalInjectable = getInjectable({ - instantiate: (di) => { - const dependencies = { - dockStore: di.inject(dockStoreInjectable), - }; - - return (tabId: TabId, api: TerminalApi) => - new Terminal(dependencies, tabId, api); - }, - + instantiate: () => (tabId: TabId, api: TerminalApi) => new Terminal(tabId, api), lifecycle: lifecycleEnum.singleton, }); diff --git a/src/renderer/components/dock/terminal-tab.tsx b/src/renderer/components/dock/terminal/dock-tab.tsx similarity index 70% rename from src/renderer/components/dock/terminal-tab.tsx rename to src/renderer/components/dock/terminal/dock-tab.tsx index a633ffb062..2fc9d436d2 100644 --- a/src/renderer/components/dock/terminal-tab.tsx +++ b/src/renderer/components/dock/terminal/dock-tab.tsx @@ -3,19 +3,17 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import "./terminal-tab.scss"; - import React from "react"; import { observer } from "mobx-react"; -import { boundMethod, cssNames } from "../../utils"; -import { DockTab, DockTabProps } from "./dock-tab"; -import { Icon } from "../icon"; -import type { TerminalStore } from "./terminal-store/terminal.store"; -import type { DockStore } from "./dock-store/dock.store"; +import { boundMethod, cssNames } from "../../../utils"; +import { DockTab, DockTabProps } from "../dock-tab"; +import { Icon } from "../../icon"; +import type { TerminalStore } from "./store"; +import type { DockStore } from "../dock/store"; import { reaction } from "mobx"; import { withInjectables } from "@ogre-tools/injectable-react"; -import dockStoreInjectable from "./dock-store/dock-store.injectable"; -import terminalStoreInjectable from "./terminal-store/terminal-store.injectable"; +import dockStoreInjectable from "../dock/store.injectable"; +import terminalStoreInjectable from "./store.injectable"; interface Props extends DockTabProps { } @@ -73,15 +71,11 @@ class NonInjectedTerminalTab extends React.Component { } } -export const TerminalTab = withInjectables( - NonInjectedTerminalTab, - - { - getProps: (di, props) => ({ - dockStore: di.inject(dockStoreInjectable), - terminalStore: di.inject(terminalStoreInjectable), - ...props, - }), - }, -); +export const TerminalTab = withInjectables(NonInjectedTerminalTab, { + getProps: (di, props) => ({ + dockStore: di.inject(dockStoreInjectable), + terminalStore: di.inject(terminalStoreInjectable), + ...props, + }), +}); diff --git a/src/renderer/components/dock/terminal/get-terminal-api.injectable.ts b/src/renderer/components/dock/terminal/get-terminal-api.injectable.ts new file mode 100644 index 0000000000..7724380c50 --- /dev/null +++ b/src/renderer/components/dock/terminal/get-terminal-api.injectable.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { TerminalApi } from "../../../api/terminal-api"; +import type { TabId } from "../dock/store"; +import terminalStoreInjectable from "./store.injectable"; + +const getTerminalApiInjectable = getInjectable({ + instantiate: (di) => { + const terminalStore = di.inject(terminalStoreInjectable); + + return (tabId: TabId): TerminalApi => terminalStore.getTerminalApi(tabId); + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default getTerminalApiInjectable; diff --git a/src/renderer/components/dock/terminal/send-command.injectable.ts b/src/renderer/components/dock/terminal/send-command.injectable.ts new file mode 100644 index 0000000000..6e6b970b21 --- /dev/null +++ b/src/renderer/components/dock/terminal/send-command.injectable.ts @@ -0,0 +1,91 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { when } from "mobx"; +import { TerminalApi, TerminalChannels } from "../../../api/terminal-api"; +import { noop } from "../../../utils"; +import { Notifications } from "../../notifications"; +import selectDockTabInjectable from "../dock/select-dock-tab.injectable"; +import type { DockTab, TabId } from "../dock/store"; +import createTerminalTabInjectable from "./create-terminal-tab.injectable"; +import getTerminalApiInjectable from "./get-terminal-api.injectable"; + +interface Dependencies { + selectTab: (tabId: TabId) => void; + createTerminalTab: () => DockTab; + getTerminalApi: (tabId: TabId) => TerminalApi; +} + +export interface SendCommandOptions { + /** + * Emit an enter after the command + */ + enter?: boolean; + + /** + * @deprecated This option is ignored and infered to be `true` if `tabId` is not provided + */ + newTab?: any; + + /** + * Specify a specific terminal tab to send this command to + */ + tabId?: TabId; +} + +const sendCommand = ({ selectTab, createTerminalTab, getTerminalApi }: Dependencies) => async (command: string, options: SendCommandOptions = {}): Promise => { + let { tabId } = options; + + if (tabId) { + selectTab(tabId); + } else { + tabId = createTerminalTab().id; + } + + await when(() => Boolean(getTerminalApi(tabId))); + + const terminalApi = getTerminalApi(tabId); + const shellIsReady = when(() =>terminalApi.isReady); + const notifyVeryLong = setTimeout(() => { + shellIsReady.cancel(); + Notifications.info( + "If terminal shell is not ready please check your shell init files, if applicable.", + { + timeout: 4_000, + }, + ); + }, 10_000); + + await shellIsReady.catch(noop); + clearTimeout(notifyVeryLong); + + if (terminalApi) { + if (options.enter) { + command += "\r"; + } + + terminalApi.sendMessage({ + type: TerminalChannels.STDIN, + data: command, + }); + } else { + console.warn( + "The selected tab is does not have a connection. Cannot send command.", + { tabId, command }, + ); + } +}; + +const sendCommandInjectable = getInjectable({ + instantiate: (di) => sendCommand({ + createTerminalTab: di.inject(createTerminalTabInjectable), + selectTab: di.inject(selectDockTabInjectable), + getTerminalApi: di.inject(getTerminalApiInjectable), + }), + + lifecycle: lifecycleEnum.singleton, +}); + +export default sendCommandInjectable; diff --git a/src/renderer/components/dock/terminal-store/terminal-store.injectable.ts b/src/renderer/components/dock/terminal/store.injectable.ts similarity index 52% rename from src/renderer/components/dock/terminal-store/terminal-store.injectable.ts rename to src/renderer/components/dock/terminal/store.injectable.ts index 6e0990b31e..06c4c4d7f4 100644 --- a/src/renderer/components/dock/terminal-store/terminal-store.injectable.ts +++ b/src/renderer/components/dock/terminal/store.injectable.ts @@ -3,15 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import { TerminalStore } from "./terminal.store"; -import createTerminalTabInjectable from "../create-terminal-tab/create-terminal-tab.injectable"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; -import createTerminalInjectable from "../terminal/create-terminal.injectable"; +import { TerminalStore } from "./store"; +import createTerminalInjectable from "./create-terminal.injectable"; const terminalStoreInjectable = getInjectable({ instantiate: (di) => new TerminalStore({ - createTerminalTab: di.inject(createTerminalTabInjectable), - dockStore: di.inject(dockStoreInjectable), createTerminal: di.inject(createTerminalInjectable), }), diff --git a/src/renderer/components/dock/terminal/store.ts b/src/renderer/components/dock/terminal/store.ts new file mode 100644 index 0000000000..a54dccb820 --- /dev/null +++ b/src/renderer/components/dock/terminal/store.ts @@ -0,0 +1,87 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { action, observable } from "mobx"; +import type { Terminal } from "./terminal"; +import { TerminalApi } from "../../../api/terminal-api"; +import type { DockTab, TabId } from "../dock/store"; +import { WebSocketApiState } from "../../../api/websocket-api"; + +export interface ITerminalTab extends DockTab { + node?: string; // activate node shell mode +} + +interface Dependencies { + createTerminal: (tabId: TabId, api: TerminalApi) => Terminal; +} + +export class TerminalStore { + protected terminals = new Map(); + protected connections = observable.map(); + + constructor(private dependencies: Dependencies) { + } + + @action + connect(tab: ITerminalTab) { + if (this.isConnected(tab.id)) { + return; + } + const api = new TerminalApi({ + id: tab.id, + node: tab.node, + }); + const terminal = this.dependencies.createTerminal(tab.id, api); + + this.connections.set(tab.id, api); + this.terminals.set(tab.id, terminal); + + api.connect(); + } + + @action + destroy(tabId: TabId) { + const terminal = this.terminals.get(tabId); + const terminalApi = this.connections.get(tabId); + + terminal?.destroy(); + terminalApi?.destroy(); + this.connections.delete(tabId); + this.terminals.delete(tabId); + } + + /** + * @deprecated use `this.destroy()` instead + */ + disconnect(tabId: TabId) { + this.destroy(tabId); + } + + reconnect(tabId: TabId) { + this.connections.get(tabId)?.connect(); + } + + isConnected(tabId: TabId) { + return Boolean(this.connections.get(tabId)); + } + + isDisconnected(tabId: TabId) { + return this.connections.get(tabId)?.readyState === WebSocketApiState.CLOSED; + } + + getTerminal(tabId: TabId) { + return this.terminals.get(tabId); + } + + getTerminalApi(tabId: TabId) { + return this.connections.get(tabId); + } + + reset() { + [...this.connections].forEach(([tabId]) => { + this.destroy(tabId); + }); + } +} diff --git a/src/renderer/components/dock/terminal-window.scss b/src/renderer/components/dock/terminal/terminal-window.scss similarity index 100% rename from src/renderer/components/dock/terminal-window.scss rename to src/renderer/components/dock/terminal/terminal-window.scss diff --git a/src/renderer/components/dock/terminal/terminal.ts b/src/renderer/components/dock/terminal/terminal.ts index 718c855b97..022f71f8aa 100644 --- a/src/renderer/components/dock/terminal/terminal.ts +++ b/src/renderer/components/dock/terminal/terminal.ts @@ -7,7 +7,7 @@ import debounce from "lodash/debounce"; import { reaction } from "mobx"; import { Terminal as XTerm } from "xterm"; import { FitAddon } from "xterm-addon-fit"; -import type { DockStore, TabId } from "../dock-store/dock.store"; +import type { TabId } from "../dock/store"; import { TerminalApi, TerminalChannels } from "../../../api/terminal-api"; import { ThemeStore } from "../../../theme.store"; import { disposer } from "../../../utils"; @@ -18,12 +18,7 @@ import { clipboard } from "electron"; import logger from "../../../../common/logger"; import type { TerminalConfig } from "../../../../common/user-store/preferences-helpers"; -interface Dependencies { - dockStore: DockStore -} - export class Terminal { - private terminalConfig: TerminalConfig = UserStore.getInstance().terminalConfig; public static get spawningPool() { @@ -56,12 +51,6 @@ export class Terminal { return this.xterm.element.querySelector(".xterm-viewport"); } - get isActive() { - const { isOpen, selectedTabId } = this.dependencies.dockStore; - - return isOpen && selectedTabId === this.tabId; - } - attachTo(parentElem: HTMLElement) { parentElem.appendChild(this.elem); this.onActivate(); @@ -75,7 +64,7 @@ export class Terminal { } } - constructor(private dependencies: Dependencies, public tabId: TabId, protected api: TerminalApi) { + constructor(public tabId: TabId, protected api: TerminalApi) { // enable terminal addons this.xterm.loadAddon(this.fitAddon); @@ -107,7 +96,6 @@ export class Terminal { reaction(() => UserStore.getInstance().terminalConfig.fontFamily, this.setFontFamily, { fireImmediately: true, }), - dependencies.dockStore.onResize(this.onResize), () => onDataHandler.dispose(), () => this.fitAddon.dispose(), () => this.api.removeAllListeners(), @@ -126,7 +114,7 @@ export class Terminal { fit = () => { // Since this function is debounced we need to read this value as late as possible - if (!this.isActive || !this.xterm) { + if (!this.xterm) { return; } diff --git a/src/renderer/components/dock/terminal/view.tsx b/src/renderer/components/dock/terminal/view.tsx new file mode 100644 index 0000000000..f1e0279539 --- /dev/null +++ b/src/renderer/components/dock/terminal/view.tsx @@ -0,0 +1,74 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import "./terminal-window.scss"; + +import React from "react"; +import { disposeOnUnmount, observer } from "mobx-react"; +import { cssNames } from "../../../utils"; +import type { Terminal } from "./terminal"; +import type { TerminalStore } from "./store"; +import { ThemeStore } from "../../../theme.store"; +import type { DockTab, DockStore } from "../dock/store"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import dockStoreInjectable from "../dock/store.injectable"; +import terminalStoreInjectable from "./store.injectable"; + +interface Props { + tab: DockTab; +} + +interface Dependencies { + dockStore: DockStore; + terminalStore: TerminalStore; +} + +@observer +class NonInjectedTerminalWindow extends React.Component { + public elem: HTMLElement; + public terminal: Terminal; + + componentDidMount() { + this.props.terminalStore.connect(this.props.tab); + this.terminal = this.props.terminalStore.getTerminal(this.props.tab.id); + this.terminal.attachTo(this.elem); + + disposeOnUnmount(this, [ + // refresh terminal available space (cols/rows) when resized + this.props.dockStore.onResize(() => this.terminal.onResize(), { + fireImmediately: true, + }), + ]); + } + + componentDidUpdate(): void { + this.terminal.detach(); + this.props.terminalStore.connect(this.props.tab); + this.terminal = this.props.terminalStore.getTerminal(this.props.tab.id); + this.terminal.attachTo(this.elem); + } + + componentWillUnmount(): void { + this.terminal.detach(); + } + + render() { + return ( +
this.elem = elem} + /> + ); + } +} + +export const TerminalWindow = withInjectables(NonInjectedTerminalWindow, { + getProps: (di, props) => ({ + dockStore: di.inject(dockStoreInjectable), + terminalStore: di.inject(terminalStoreInjectable), + ...props, + }), +}); + diff --git a/src/renderer/components/dock/upgrade-chart-store/upgrade-chart.store.ts b/src/renderer/components/dock/upgrade-chart-store/upgrade-chart.store.ts deleted file mode 100644 index f6e6a2dde2..0000000000 --- a/src/renderer/components/dock/upgrade-chart-store/upgrade-chart.store.ts +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { - action, - autorun, - computed, - IReactionDisposer, - reaction, - makeObservable, -} from "mobx"; -import { DockStore, DockTab, TabId, TabKind } from "../dock-store/dock.store"; -import { DockTabStorageState, DockTabStore } from "../dock-tab-store/dock-tab.store"; -import { - getReleaseValues, - HelmRelease, -} from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import { iter, StorageHelper } from "../../../utils"; -import type { IAsyncComputed } from "@ogre-tools/injectable-react"; - -export interface IChartUpgradeData { - releaseName: string; - releaseNamespace: string; -} - -interface Dependencies { - releases: IAsyncComputed - valuesStore: DockTabStore - dockStore: DockStore - createStorage: (storageKey: string, options: DockTabStorageState) => StorageHelper> -} - -export class UpgradeChartStore extends DockTabStore { - private watchers = new Map(); - - @computed private get releaseNameReverseLookup(): Map { - return new Map(iter.map(this.data, ([id, { releaseName }]) => [releaseName, id])); - } - - get values() { - return this.dependencies.valuesStore; - } - - constructor(protected dependencies : Dependencies) { - super(dependencies, { - storageKey: "chart_releases", - }); - - makeObservable(this); - - autorun(() => { - const { selectedTab, isOpen } = dependencies.dockStore; - - if (selectedTab?.kind === TabKind.UPGRADE_CHART && isOpen) { - this.loadData(selectedTab.id); - } - }, { delay: 250 }); - - autorun(() => { - const objects = [...this.data.values()]; - - objects.forEach(({ releaseName }) => this.createReleaseWatcher(releaseName)); - }); - } - - private createReleaseWatcher(releaseName: string) { - if (this.watchers.get(releaseName)) { - return; - } - const dispose = reaction(() => { - const release = this.dependencies.releases.value.get().find(release => release.getName() === releaseName); - - return release?.getRevision(); // watch changes only by revision - }, - release => { - const releaseTab = this.getTabByRelease(releaseName); - - if (!releaseTab) { - return; - } - - // auto-reload values if was loaded before - if (release) { - if (this.dependencies.dockStore.selectedTab === releaseTab && this.values.getData(releaseTab.id)) { - this.loadValues(releaseTab.id); - } - } - // clean up watcher, close tab if release not exists / was removed - else { - dispose(); - this.watchers.delete(releaseName); - this.dependencies.dockStore.closeTab(releaseTab.id); - } - }); - - this.watchers.set(releaseName, dispose); - } - - isLoading(tabId = this.dependencies.dockStore.selectedTabId) { - const values = this.values.getData(tabId); - - return values === undefined; - } - - @action - async loadData(tabId: TabId) { - const values = this.values.getData(tabId); - - await Promise.all([ - !values && this.loadValues(tabId), - ]); - } - - @action - async loadValues(tabId: TabId) { - this.values.clearData(tabId); // reset - const { releaseName, releaseNamespace } = this.getData(tabId); - const values = await getReleaseValues(releaseName, releaseNamespace, true); - - this.values.setData(tabId, values); - } - - getTabByRelease(releaseName: string): DockTab { - return this.dependencies.dockStore.getTabById(this.releaseNameReverseLookup.get(releaseName)); - } -} diff --git a/src/renderer/components/dock/upgrade-chart/clear-upgrade-chart-tab-data.injectable.ts b/src/renderer/components/dock/upgrade-chart/clear-upgrade-chart-tab-data.injectable.ts new file mode 100644 index 0000000000..e6515a4749 --- /dev/null +++ b/src/renderer/components/dock/upgrade-chart/clear-upgrade-chart-tab-data.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { TabId } from "../dock/store"; +import upgradeChartTabStoreInjectable from "./store.injectable"; + +const clearUpgradeChartTabDataInjectable = getInjectable({ + instantiate: (di) => { + const upgradeChartTabStore = di.inject(upgradeChartTabStoreInjectable); + + return (tabId: TabId) => { + upgradeChartTabStore.clearData(tabId); + }; + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default clearUpgradeChartTabDataInjectable; diff --git a/src/renderer/components/dock/upgrade-chart/create-upgrade-chart-tab.injectable.ts b/src/renderer/components/dock/upgrade-chart/create-upgrade-chart-tab.injectable.ts new file mode 100644 index 0000000000..0d3de6158a --- /dev/null +++ b/src/renderer/components/dock/upgrade-chart/create-upgrade-chart-tab.injectable.ts @@ -0,0 +1,56 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import upgradeChartTabStoreInjectable from "./store.injectable"; +import dockStoreInjectable from "../dock/store.injectable"; +import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; +import { DockStore, DockTabCreateSpecific, TabId, TabKind } from "../dock/store"; +import type { UpgradeChartTabStore } from "./store"; +import { runInAction } from "mobx"; + +interface Dependencies { + upgradeChartStore: UpgradeChartTabStore; + dockStore: DockStore +} + +const createUpgradeChartTab = ({ upgradeChartStore, dockStore }: Dependencies) => (release: HelmRelease, tabParams: DockTabCreateSpecific = {}): TabId => { + const tabId = upgradeChartStore.getTabIdByRelease(release.getName()); + + if (tabId) { + dockStore.open(); + dockStore.selectTab(tabId); + + return tabId; + } + + return runInAction(() => { + const tab = dockStore.createTab( + { + title: `Helm Upgrade: ${release.getName()}`, + ...tabParams, + kind: TabKind.UPGRADE_CHART, + }, + false, + ); + + upgradeChartStore.setData(tab.id, { + releaseName: release.getName(), + releaseNamespace: release.getNs(), + }); + + return tab.id; + }); +}; + +const createUpgradeChartTabInjectable = getInjectable({ + instantiate: (di) => createUpgradeChartTab({ + upgradeChartStore: di.inject(upgradeChartTabStoreInjectable), + dockStore: di.inject(dockStoreInjectable), + }), + + lifecycle: lifecycleEnum.singleton, +}); + +export default createUpgradeChartTabInjectable; diff --git a/src/renderer/components/dock/upgrade-chart-store/upgrade-chart-store.injectable.ts b/src/renderer/components/dock/upgrade-chart/store.injectable.ts similarity index 55% rename from src/renderer/components/dock/upgrade-chart-store/upgrade-chart-store.injectable.ts rename to src/renderer/components/dock/upgrade-chart/store.injectable.ts index d0732e7fdb..13e69e9b10 100644 --- a/src/renderer/components/dock/upgrade-chart-store/upgrade-chart-store.injectable.ts +++ b/src/renderer/components/dock/upgrade-chart/store.injectable.ts @@ -3,27 +3,21 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import { UpgradeChartStore } from "./upgrade-chart.store"; -import dockStoreInjectable from "../dock-store/dock-store.injectable"; +import { UpgradeChartTabStore } from "./store"; import createDockTabStoreInjectable from "../dock-tab-store/create-dock-tab-store.injectable"; import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; -import releasesInjectable from "../../+apps-releases/releases.injectable"; -const upgradeChartStoreInjectable = getInjectable({ +const upgradeChartTabStoreInjectable = getInjectable({ instantiate: (di) => { const createDockTabStore = di.inject(createDockTabStoreInjectable); - const valuesStore = createDockTabStore(); - - return new UpgradeChartStore({ - releases: di.inject(releasesInjectable), - dockStore: di.inject(dockStoreInjectable), + return new UpgradeChartTabStore({ createStorage: di.inject(createStorageInjectable), - valuesStore, + valuesStore: createDockTabStore(), }); }, lifecycle: lifecycleEnum.singleton, }); -export default upgradeChartStoreInjectable; +export default upgradeChartTabStoreInjectable; diff --git a/src/renderer/components/dock/upgrade-chart/store.ts b/src/renderer/components/dock/upgrade-chart/store.ts new file mode 100644 index 0000000000..ddc1a78188 --- /dev/null +++ b/src/renderer/components/dock/upgrade-chart/store.ts @@ -0,0 +1,51 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { action, computed, makeObservable } from "mobx"; +import type { TabId } from "../dock/store"; +import { DockTabStorageState, DockTabStore } from "../dock-tab-store/dock-tab.store"; +import { getReleaseValues } from "../../../../common/k8s-api/endpoints/helm-releases.api"; +import type { StorageHelper } from "../../../utils"; + +export interface IChartUpgradeData { + releaseName: string; + releaseNamespace: string; +} + +interface Dependencies { + valuesStore: DockTabStore; + createStorage: (storageKey: string, options: DockTabStorageState) => StorageHelper>; +} + +export class UpgradeChartTabStore extends DockTabStore { + @computed private get releaseNameReverseLookup(): Map { + return new Map(this.getAllData().map(([id, { releaseName }]) => [releaseName, id])); + } + + get values() { + return this.dependencies.valuesStore; + } + + constructor(protected dependencies : Dependencies) { + super(dependencies, { + storageKey: "chart_releases", + }); + + makeObservable(this); + } + + @action + async reloadValues(tabId: TabId) { + this.values.clearData(tabId); // reset + const { releaseName, releaseNamespace } = this.getData(tabId); + const values = await getReleaseValues(releaseName, releaseNamespace, true); + + this.values.setData(tabId, values); + } + + getTabIdByRelease(releaseName: string): TabId { + return this.releaseNameReverseLookup.get(releaseName); + } +} diff --git a/src/renderer/components/dock/upgrade-chart.scss b/src/renderer/components/dock/upgrade-chart/upgrade-chart.scss similarity index 100% rename from src/renderer/components/dock/upgrade-chart.scss rename to src/renderer/components/dock/upgrade-chart/upgrade-chart.scss diff --git a/src/renderer/components/dock/upgrade-chart.tsx b/src/renderer/components/dock/upgrade-chart/view.tsx similarity index 62% rename from src/renderer/components/dock/upgrade-chart.tsx rename to src/renderer/components/dock/upgrade-chart/view.tsx index 270656e9f4..bff0491610 100644 --- a/src/renderer/components/dock/upgrade-chart.tsx +++ b/src/renderer/components/dock/upgrade-chart/view.tsx @@ -8,27 +8,20 @@ import "./upgrade-chart.scss"; import React from "react"; import { action, makeObservable, observable, reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; -import { cssNames } from "../../utils"; -import type { DockTab } from "./dock-store/dock.store"; -import { InfoPanel } from "./info-panel"; -import type { UpgradeChartStore } from "./upgrade-chart-store/upgrade-chart.store"; -import { Spinner } from "../spinner"; -import { Badge } from "../badge"; -import { EditorPanel } from "./editor-panel"; -import { - helmChartStore, - IChartVersion, -} from "../+apps-helm-charts/helm-chart.store"; -import type { - HelmRelease, - IReleaseUpdateDetails, - IReleaseUpdatePayload, -} from "../../../common/k8s-api/endpoints/helm-releases.api"; -import { Select, SelectOption } from "../select"; +import { cssNames } from "../../../utils"; +import type { DockTab } from "../dock/store"; +import { InfoPanel } from "../info-panel"; +import type { UpgradeChartTabStore } from "./store"; +import { Spinner } from "../../spinner"; +import { Badge } from "../../badge"; +import { EditorPanel } from "../editor-panel"; +import { helmChartStore, IChartVersion } from "../../+apps-helm-charts/helm-chart.store"; +import type { HelmRelease, IReleaseUpdateDetails, IReleaseUpdatePayload } from "../../../../common/k8s-api/endpoints/helm-releases.api"; +import { Select, SelectOption } from "../../select"; import { IAsyncComputed, withInjectables } from "@ogre-tools/injectable-react"; -import upgradeChartStoreInjectable from "./upgrade-chart-store/upgrade-chart-store.injectable"; -import updateReleaseInjectable from "../+apps-releases/update-release/update-release.injectable"; -import releasesInjectable from "../+apps-releases/releases.injectable"; +import upgradeChartTabStoreInjectable from "./store.injectable"; +import updateReleaseInjectable from "../../+apps-releases/update-release/update-release.injectable"; +import releasesInjectable from "../../+apps-releases/releases.injectable"; interface Props { className?: string; @@ -36,9 +29,9 @@ interface Props { } interface Dependencies { - releases: IAsyncComputed - upgradeChartStore: UpgradeChartStore - updateRelease: (name: string, namespace: string, payload: IReleaseUpdatePayload) => Promise + releases: IAsyncComputed; + upgradeChartTabStore: UpgradeChartTabStore; + updateRelease: (name: string, namespace: string, payload: IReleaseUpdatePayload) => Promise; } @observer @@ -53,10 +46,21 @@ export class NonInjectedUpgradeChart extends React.Component this.release, () => this.loadVersions()), + reaction( + () => this.release, + release => this.reloadVersions(release), + { + fireImmediately: true, + }, + ), + reaction( + () => this.release?.getRevision(), + () => this.reloadValues(), + { + fireImmediately: true, + }, + ), ]); } @@ -65,7 +69,7 @@ export class NonInjectedUpgradeChart extends React.Component { + onChange = action((value: string) => { this.error = ""; - this.props.upgradeChartStore.values.setData(this.tabId, value); - }; + this.props.upgradeChartTabStore.values.setData(this.tabId, value); + }); - @action - onError = (error: Error | string) => { + onError = action((error: Error | string) => { this.error = error.toString(); - }; + }); upgrade = async () => { if (this.error) return null; @@ -127,7 +136,7 @@ export class NonInjectedUpgradeChart extends React.Component; } const currentVersion = release.getVersion(); @@ -170,15 +179,11 @@ export class NonInjectedUpgradeChart extends React.Component( - NonInjectedUpgradeChart, - - { - getProps: (di, props) => ({ - releases: di.inject(releasesInjectable), - updateRelease: di.inject(updateReleaseInjectable), - upgradeChartStore: di.inject(upgradeChartStoreInjectable), - ...props, - }), - }, -); +export const UpgradeChart = withInjectables(NonInjectedUpgradeChart, { + getProps: (di, props) => ({ + releases: di.inject(releasesInjectable), + updateRelease: di.inject(updateReleaseInjectable), + upgradeChartTabStore: di.inject(upgradeChartTabStoreInjectable), + ...props, + }), +}); diff --git a/src/renderer/components/icon/icon.tsx b/src/renderer/components/icon/icon.tsx index f480a3cd11..dc10de5fc2 100644 --- a/src/renderer/components/icon/icon.tsx +++ b/src/renderer/components/icon/icon.tsx @@ -5,8 +5,7 @@ import "./icon.scss"; -import React, { ReactNode } from "react"; -import { findDOMNode } from "react-dom"; +import React, { createRef, ReactNode } from "react"; import { NavLink } from "react-router-dom"; import type { LocationDescriptor } from "history"; import { boundMethod, cssNames } from "../../utils"; @@ -31,6 +30,8 @@ export interface IconProps extends React.HTMLAttributes, TooltipDecoratorPr @withTooltip export class Icon extends React.PureComponent { + private readonly ref = createRef(); + static defaultProps: IconProps = { focusable: true, }; @@ -59,10 +60,7 @@ export class Icon extends React.PureComponent { // fallthrough case "Enter": { - // eslint-disable-next-line react/no-find-dom-node - const icon = findDOMNode(this) as HTMLElement; - - setTimeout(() => icon.click()); + this.ref.current?.click(); evt.preventDefault(); break; } @@ -123,16 +121,16 @@ export class Icon extends React.PureComponent { const { className, children } = iconProps; return ( - + {children} ); } if (href) { - return ; + return ; } - return ; + return ; } } diff --git a/src/renderer/components/input/search-input-url.tsx b/src/renderer/components/input/search-input-url.tsx index 74c57b0849..9ee4c8a5bb 100644 --- a/src/renderer/components/input/search-input-url.tsx +++ b/src/renderer/components/input/search-input-url.tsx @@ -24,10 +24,14 @@ export interface SearchInputUrlProps extends InputProps { export class SearchInputUrl extends React.Component { @observable inputVal = ""; // fix: use empty string on init to avoid react warnings - @disposeOnUnmount - updateInput = autorun(() => this.inputVal = searchUrlParam.get()); updateUrl = debounce((val: string) => searchUrlParam.set(val), 250); + componentDidMount(): void { + disposeOnUnmount(this, [ + autorun(() => this.inputVal = searchUrlParam.get()), + ]); + } + setValue = (value: string) => { this.inputVal = value; this.updateUrl(value); diff --git a/src/renderer/components/input/search-input.tsx b/src/renderer/components/input/search-input.tsx index a004041e9d..36bcc135c4 100644 --- a/src/renderer/components/input/search-input.tsx +++ b/src/renderer/components/input/search-input.tsx @@ -50,13 +50,9 @@ export class SearchInput extends React.Component { @boundMethod onKeyDown(evt: React.KeyboardEvent) { - if (this.props.onKeyDown) { - this.props.onKeyDown(evt); - } - // clear on escape-key - const escapeKey = evt.nativeEvent.code === "Escape"; + this.props.onKeyDown?.(evt); - if (escapeKey) { + if (evt.nativeEvent.code === "Escape") { this.clear(); evt.stopPropagation(); } @@ -87,6 +83,7 @@ export class SearchInput extends React.Component { onKeyDown={this.onKeyDown} iconRight={rightIcon} ref={this.inputRef} + blurOnEnter={false} /> ); } diff --git a/src/renderer/components/item-object-list/content.tsx b/src/renderer/components/item-object-list/content.tsx new file mode 100644 index 0000000000..ccfdddd7d3 --- /dev/null +++ b/src/renderer/components/item-object-list/content.tsx @@ -0,0 +1,271 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import "./item-list-layout.scss"; + +import React, { ReactNode } from "react"; +import { computed, makeObservable } from "mobx"; +import { observer } from "mobx-react"; +import { ConfirmDialog, ConfirmDialogParams } from "../confirm-dialog"; +import { Table, TableCell, TableCellProps, TableHead, TableProps, TableRow, TableRowProps, TableSortCallbacks } from "../table"; +import { boundMethod, cssNames, IClassName, isReactNode, prevDefault, stopPropagation } from "../../utils"; +import { AddRemoveButtons, AddRemoveButtonsProps } from "../add-remove-buttons"; +import { NoItems } from "../no-items"; +import { Spinner } from "../spinner"; +import type { ItemObject, ItemStore } from "../../../common/item.store"; +import { Filter, pageFilters } from "./page-filters.store"; +import { ThemeStore } from "../../theme.store"; +import { MenuActions } from "../menu/menu-actions"; +import { MenuItem } from "../menu"; +import { Checkbox } from "../checkbox"; +import { UserStore } from "../../../common/user-store"; + +interface ItemListLayoutContentProps { + getFilters: () => Filter[] + tableId?: string; + className: IClassName; + getItems: () => I[]; + store: ItemStore; + getIsReady: () => boolean; // show loading indicator while not ready + isSelectable?: boolean; // show checkbox in rows for selecting items + isConfigurable?: boolean; + copyClassNameFromHeadCells?: boolean; + sortingCallbacks?: TableSortCallbacks; + tableProps?: Partial>; // low-level table configuration + renderTableHeader: TableCellProps[] | null; + renderTableContents: (item: I) => (ReactNode | TableCellProps)[]; + renderItemMenu?: (item: I, store: ItemStore) => ReactNode; + customizeTableRowProps?: (item: I) => Partial; + addRemoveButtons?: Partial; + virtual?: boolean; + + // item details view + hasDetailsView?: boolean; + detailsItem?: I; + onDetails?: (item: I) => void; + + // other + customizeRemoveDialog?: (selectedItems: I[]) => Partial; + + /** + * Message to display when a store failed to load + * + * @default "Failed to load items" + */ + failedToLoadMessage?: React.ReactNode; +} + +@observer +export class ItemListLayoutContent extends React.Component> { + constructor(props: ItemListLayoutContentProps) { + super(props); + makeObservable(this); + } + + @computed get failedToLoad() { + return this.props.store.failedLoading; + } + + @boundMethod + getRow(uid: string) { + const { + isSelectable, renderTableHeader, renderTableContents, renderItemMenu, + store, hasDetailsView, onDetails, + copyClassNameFromHeadCells, customizeTableRowProps, detailsItem, + } = this.props; + const { isSelected } = store; + const item = this.props.getItems().find(item => item.getId() == uid); + + if (!item) return null; + const itemId = item.getId(); + + return ( + onDetails(item)) : undefined} + {...customizeTableRowProps(item)} + > + {isSelectable && ( + store.toggleSelection(item))} + /> + )} + { + renderTableContents(item).map((content, index) => { + const cellProps: TableCellProps = isReactNode(content) ? { children: content } : content; + const headCell = renderTableHeader?.[index]; + + if (copyClassNameFromHeadCells && headCell) { + cellProps.className = cssNames(cellProps.className, headCell.className); + } + + if (!headCell || this.showColumn(headCell)) { + return ; + } + + return null; + }) + } + {renderItemMenu && ( + +
+ {renderItemMenu(item, store)} +
+
+ )} +
+ ); + } + + @boundMethod + removeItemsDialog() { + const { customizeRemoveDialog, store } = this.props; + const { selectedItems, removeSelectedItems } = store; + const visibleMaxNamesCount = 5; + const selectedNames = selectedItems.map(ns => ns.getName()).slice(0, visibleMaxNamesCount).join(", "); + const dialogCustomProps = customizeRemoveDialog ? customizeRemoveDialog(selectedItems) : {}; + const selectedCount = selectedItems.length; + const tailCount = selectedCount > visibleMaxNamesCount ? selectedCount - visibleMaxNamesCount : 0; + const tail = tailCount > 0 ? <>, and {tailCount} more : null; + const message = selectedCount <= 1 ?

Remove item {selectedNames}?

:

Remove {selectedCount} items {selectedNames}{tail}?

; + + ConfirmDialog.open({ + ok: removeSelectedItems, + labelOk: "Remove", + message, + ...dialogCustomProps, + }); + } + + renderNoItems() { + if (this.failedToLoad) { + return {this.props.failedToLoadMessage}; + } + + if (!this.props.getIsReady()) { + return ; + } + + if (this.props.getFilters().length > 0) { + return ( + + No items found. +

+ pageFilters.reset()} className="contrast"> + Reset filters? + +

+ + ); + } + + return ; + } + + renderItems() { + if (this.props.virtual) { + return null; + } + + return this.props.getItems().map(item => this.getRow(item.getId())); + } + + renderTableHeader() { + const { customizeTableRowProps, renderTableHeader, isSelectable, isConfigurable, store } = this.props; + + if (!renderTableHeader) { + return null; + } + + const enabledItems = this.props.getItems().filter(item => !customizeTableRowProps(item).disabled); + + return ( + + {isSelectable && ( + store.toggleSelectionAll(enabledItems))} + /> + )} + {renderTableHeader.map((cellProps, index) => ( + this.showColumn(cellProps) && ( + + ) + ))} + + {isConfigurable && this.renderColumnVisibilityMenu()} + + + ); + } + + render() { + const { + store, hasDetailsView, addRemoveButtons = {}, virtual, sortingCallbacks, + detailsItem, className, tableProps = {}, tableId, + } = this.props; + const { selectedItems } = store; + const selectedItemId = detailsItem && detailsItem.getId(); + const classNames = cssNames(className, "box", "grow", ThemeStore.getInstance().activeTheme.type); + + return ( +
+ + {this.renderTableHeader()} + {this.renderItems()} +
+ +
+ ); + } + + showColumn({ id: columnId, showWithColumn }: TableCellProps): boolean { + const { tableId, isConfigurable } = this.props; + + return !isConfigurable || !UserStore.getInstance().isTableColumnHidden(tableId, columnId, showWithColumn); + } + + renderColumnVisibilityMenu() { + const { renderTableHeader, tableId } = this.props; + + return ( + + {renderTableHeader.map((cellProps, index) => ( + !cellProps.showWithColumn && ( + + `} + value={this.showColumn(cellProps)} + onChange={() => UserStore.getInstance().toggleTableColumnVisibility(tableId, cellProps.id)} + /> + + ) + ))} + + ); + } +} diff --git a/src/renderer/components/item-object-list/filters.tsx b/src/renderer/components/item-object-list/filters.tsx new file mode 100644 index 0000000000..5dd3c13dc2 --- /dev/null +++ b/src/renderer/components/item-object-list/filters.tsx @@ -0,0 +1,29 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import "./item-list-layout.scss"; + +import React from "react"; +import { PageFiltersList } from "./page-filters-list"; +import { observer } from "mobx-react"; +import type { Filter } from "./page-filters.store"; + +export interface ItemListLayoutFilterProps { + getIsReady: () => boolean + getFilters: () => Filter[] + getFiltersAreShown: () => boolean + hideFilters: boolean +} + +export const ItemListLayoutFilters = observer(({ getFilters, getFiltersAreShown, getIsReady, hideFilters }: ItemListLayoutFilterProps) => { + const filters = getFilters(); + + if (!getIsReady() || !filters.length || hideFilters || !getFiltersAreShown()) { + return null; + } + + return ; +}); + diff --git a/src/renderer/components/item-object-list/header.tsx b/src/renderer/components/item-object-list/header.tsx new file mode 100644 index 0000000000..ce5f19fd05 --- /dev/null +++ b/src/renderer/components/item-object-list/header.tsx @@ -0,0 +1,105 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import "./item-list-layout.scss"; + +import React, { ReactNode } from "react"; +import { observer } from "mobx-react"; +import { cssNames, IClassName } from "../../utils"; +import type { ItemObject, ItemStore } from "../../../common/item.store"; +import type { Filter } from "./page-filters.store"; +import type { HeaderCustomizer, HeaderPlaceholders, SearchFilter } from "./list-layout"; +import { SearchInputUrl } from "../input"; + +export interface ItemListLayoutHeaderProps { + getItems: () => I[]; + getFilters: () => Filter[]; + toggleFilters: () => void; + + store: ItemStore; + searchFilters?: SearchFilter[]; + + // header (title, filtering, searching, etc.) + showHeader?: boolean; + headerClassName?: IClassName; + renderHeaderTitle?: + | ReactNode + | ((parent: ItemListLayoutHeader) => ReactNode); + customizeHeader?: HeaderCustomizer | HeaderCustomizer[]; +} + +@observer +export class ItemListLayoutHeader extends React.Component< + ItemListLayoutHeaderProps +> { + render() { + const { + showHeader, + customizeHeader, + renderHeaderTitle, + headerClassName, + searchFilters, + getItems, + store, + getFilters, + toggleFilters, + } = this.props; + + if (!showHeader) { + return null; + } + + const renderInfo = () => { + const allItemsCount = store.getTotalCount(); + const itemsCount = getItems().length; + + if (getFilters().length > 0) { + return ( + <> + Filtered: {itemsCount} / {allItemsCount} + + ); + } + + return allItemsCount === 1 + ? `${allItemsCount} item` + : `${allItemsCount} items`; + }; + + const customizeHeaderFunctions = [customizeHeader].flat().filter(Boolean); + const renderedTitle = typeof renderHeaderTitle === "function" + ? renderHeaderTitle(this) + : renderHeaderTitle; + + const { + filters, + info, + searchProps, + title, + } = customizeHeaderFunctions.reduce( + (prevPlaceholders, customizer) => customizer(prevPlaceholders), + { + title:
{renderedTitle}
, + info: renderInfo(), + searchProps: {}, + }, + ); + + return ( +
+ {title} + { + info && ( +
+ {info} +
+ ) + } + {filters} + {searchFilters.length > 0 && searchProps && } +
+ ); + } +} diff --git a/src/renderer/components/item-object-list/index.tsx b/src/renderer/components/item-object-list/index.tsx index 6861509d03..bb05729496 100644 --- a/src/renderer/components/item-object-list/index.tsx +++ b/src/renderer/components/item-object-list/index.tsx @@ -3,4 +3,4 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -export * from "./item-list-layout"; +export * from "./list-layout"; diff --git a/src/renderer/components/item-object-list/item-list-layout.tsx b/src/renderer/components/item-object-list/item-list-layout.tsx deleted file mode 100644 index 2d6a91fe70..0000000000 --- a/src/renderer/components/item-object-list/item-list-layout.tsx +++ /dev/null @@ -1,549 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import "./item-list-layout.scss"; -import groupBy from "lodash/groupBy"; - -import React, { ReactNode } from "react"; -import { computed, makeObservable } from "mobx"; -import { observer } from "mobx-react"; -import { ConfirmDialog, ConfirmDialogParams } from "../confirm-dialog"; -import { Table, TableCell, TableCellProps, TableHead, TableProps, TableRow, TableRowProps, TableSortCallbacks } from "../table"; -import { - boundMethod, - cssNames, - IClassName, - isReactNode, - noop, - ObservableToggleSet, - prevDefault, - stopPropagation, - StorageHelper, -} from "../../utils"; -import { AddRemoveButtons, AddRemoveButtonsProps } from "../add-remove-buttons"; -import { NoItems } from "../no-items"; -import { Spinner } from "../spinner"; -import type { ItemObject, ItemStore } from "../../../common/item.store"; -import { SearchInputUrlProps, SearchInputUrl } from "../input"; -import { Filter, FilterType, pageFilters } from "./page-filters.store"; -import { PageFiltersList } from "./page-filters-list"; -import { ThemeStore } from "../../theme.store"; -import { MenuActions } from "../menu/menu-actions"; -import { MenuItem } from "../menu"; -import { Checkbox } from "../checkbox"; -import { UserStore } from "../../../common/user-store"; -import type { NamespaceStore } from "../+namespaces/namespace-store/namespace.store"; -import namespaceStoreInjectable from "../+namespaces/namespace-store/namespace-store.injectable"; -import { withInjectables } from "@ogre-tools/injectable-react"; -import itemListLayoutStorageInjectable - from "./item-list-layout-storage/item-list-layout-storage.injectable"; - - -export type SearchFilter = (item: I) => string | number | (string | number)[]; -export type SearchFilters = Record>; -export type ItemsFilter = (items: I[]) => I[]; -export type ItemsFilters = Record>; - -export interface HeaderPlaceholders { - title?: ReactNode; - searchProps?: SearchInputUrlProps; - filters?: ReactNode; - info?: ReactNode; -} - -export type HeaderCustomizer = (placeholders: HeaderPlaceholders) => HeaderPlaceholders; -export interface ItemListLayoutProps { - tableId?: string; - className: IClassName; - items?: I[]; - store: ItemStore; - dependentStores?: ItemStore[]; - preloadStores?: boolean; - hideFilters?: boolean; - searchFilters?: SearchFilter[]; - /** @deprecated */ - filterItems?: ItemsFilter[]; - - // header (title, filtering, searching, etc.) - showHeader?: boolean; - headerClassName?: IClassName; - renderHeaderTitle?: ReactNode | ((parent: NonInjectedItemListLayout) => ReactNode); - customizeHeader?: HeaderCustomizer | HeaderCustomizer[]; - - // items list configuration - isReady?: boolean; // show loading indicator while not ready - isSelectable?: boolean; // show checkbox in rows for selecting items - isConfigurable?: boolean; - copyClassNameFromHeadCells?: boolean; - sortingCallbacks?: TableSortCallbacks; - tableProps?: Partial>; // low-level table configuration - renderTableHeader: TableCellProps[] | null; - renderTableContents: (item: I) => (ReactNode | TableCellProps)[]; - renderItemMenu?: (item: I, store: ItemStore) => ReactNode; - customizeTableRowProps?: (item: I) => Partial; - addRemoveButtons?: Partial; - virtual?: boolean; - - // item details view - hasDetailsView?: boolean; - detailsItem?: I; - onDetails?: (item: I) => void; - - // other - customizeRemoveDialog?: (selectedItems: I[]) => Partial; - renderFooter?: (parent: NonInjectedItemListLayout) => React.ReactNode; - - /** - * Message to display when a store failed to load - * - * @default "Failed to load items" - */ - failedToLoadMessage?: React.ReactNode; - - filterCallbacks?: ItemsFilters; -} - -const defaultProps: Partial> = { - showHeader: true, - isSelectable: true, - isConfigurable: false, - copyClassNameFromHeadCells: true, - preloadStores: true, - dependentStores: [], - searchFilters: [], - customizeHeader: [], - filterItems: [], - hasDetailsView: true, - onDetails: noop, - virtual: true, - customizeTableRowProps: () => ({}), - failedToLoadMessage: "Failed to load items", -}; - -interface Dependencies { - namespaceStore: NamespaceStore; - itemListLayoutStorage: StorageHelper<{ showFilters: boolean }>; -} - -@observer -class NonInjectedItemListLayout extends React.Component & Dependencies> { - static defaultProps = defaultProps as object; - - constructor(props: ItemListLayoutProps & Dependencies) { - super(props); - makeObservable(this); - } - - get showFilters(): boolean { - return this.props.itemListLayoutStorage.get().showFilters; - } - - set showFilters(showFilters: boolean) { - this.props.itemListLayoutStorage.merge({ showFilters }); - } - - async componentDidMount() { - const { isConfigurable, tableId, preloadStores } = this.props; - - if (isConfigurable && !tableId) { - throw new Error("[ItemListLayout]: configurable list require props.tableId to be specified"); - } - - if (isConfigurable && !UserStore.getInstance().hiddenTableColumns.has(tableId)) { - UserStore.getInstance().hiddenTableColumns.set(tableId, new ObservableToggleSet()); - } - - if (preloadStores) { - this.loadStores(); - } - } - - private loadStores() { - const { store, dependentStores } = this.props; - const stores = Array.from(new Set([store, ...dependentStores])); - - stores.forEach(store => store.loadAll(this.props.namespaceStore.contextNamespaces)); - } - - private filterCallbacks: ItemsFilters = { - [FilterType.SEARCH]: items => { - const { searchFilters } = this.props; - const search = pageFilters.getValues(FilterType.SEARCH)[0] || ""; - - if (search && searchFilters.length) { - const normalizeText = (text: string) => String(text).toLowerCase(); - const searchTexts = [search].map(normalizeText); - - return items.filter(item => { - return searchFilters.some(getTexts => { - const sourceTexts: string[] = [getTexts(item)].flat().map(normalizeText); - - return sourceTexts.some(source => searchTexts.some(search => source.includes(search))); - }); - }); - } - - return items; - }, - }; - - @computed get isReady() { - return this.props.isReady ?? this.props.store.isLoaded; - } - - @computed get failedToLoad() { - return this.props.store.failedLoading; - } - - @computed get filters() { - let { activeFilters } = pageFilters; - const { searchFilters } = this.props; - - if (searchFilters.length === 0) { - activeFilters = activeFilters.filter(({ type }) => type !== FilterType.SEARCH); - } - - return activeFilters; - } - - applyFilters(filters: ItemsFilter[], items: I[]): I[] { - if (!filters || !filters.length) return items; - - return filters.reduce((items, filter) => filter(items), items); - } - - @computed get items() { - const { filters, filterCallbacks, props } = this; - const filterGroups = groupBy(filters, ({ type }) => type); - - const filterItems: ItemsFilter[] = []; - - Object.entries(filterGroups).forEach(([type, filtersGroup]) => { - const filterCallback = filterCallbacks[type] ?? props.filterCallbacks?.[type]; - - if (filterCallback && filtersGroup.length > 0) { - filterItems.push(filterCallback); - } - }); - - const items = this.props.items ?? this.props.store.items; - - return this.applyFilters(filterItems.concat(this.props.filterItems), items); - } - - @boundMethod - getRow(uid: string) { - const { - isSelectable, renderTableHeader, renderTableContents, renderItemMenu, - store, hasDetailsView, onDetails, - copyClassNameFromHeadCells, customizeTableRowProps, detailsItem, - } = this.props; - const { isSelected } = store; - const item = this.items.find(item => item.getId() == uid); - - if (!item) return null; - const itemId = item.getId(); - - return ( - onDetails(item)) : undefined} - {...customizeTableRowProps(item)} - > - {isSelectable && ( - store.toggleSelection(item))} - /> - )} - { - renderTableContents(item).map((content, index) => { - const cellProps: TableCellProps = isReactNode(content) ? { children: content } : content; - const headCell = renderTableHeader?.[index]; - - if (copyClassNameFromHeadCells && headCell) { - cellProps.className = cssNames(cellProps.className, headCell.className); - } - - if (!headCell || this.showColumn(headCell)) { - return ; - } - - return null; - }) - } - {renderItemMenu && ( - -
- {renderItemMenu(item, store)} -
-
- )} -
- ); - } - - @boundMethod - removeItemsDialog() { - const { customizeRemoveDialog, store } = this.props; - const { selectedItems, removeSelectedItems } = store; - const visibleMaxNamesCount = 5; - const selectedNames = selectedItems.map(ns => ns.getName()).slice(0, visibleMaxNamesCount).join(", "); - const dialogCustomProps = customizeRemoveDialog ? customizeRemoveDialog(selectedItems) : {}; - const selectedCount = selectedItems.length; - const tailCount = selectedCount > visibleMaxNamesCount ? selectedCount - visibleMaxNamesCount : 0; - const tail = tailCount > 0 ? <>, and {tailCount} more : null; - const message = selectedCount <= 1 ?

Remove item {selectedNames}?

:

Remove {selectedCount} items {selectedNames}{tail}?

; - - ConfirmDialog.open({ - ok: removeSelectedItems, - labelOk: "Remove", - message, - ...dialogCustomProps, - }); - } - - @boundMethod - toggleFilters() { - this.showFilters = !this.showFilters; - } - - renderFilters() { - const { hideFilters } = this.props; - const { isReady, filters } = this; - - if (!isReady || !filters.length || hideFilters || !this.showFilters) { - return null; - } - - return ; - } - - renderNoItems() { - if (this.failedToLoad) { - return {this.props.failedToLoadMessage}; - } - - if (!this.isReady) { - return ; - } - - if (this.filters.length > 0) { - return ( - - No items found. -

- pageFilters.reset()} className="contrast"> - Reset filters? - -

-
- ); - } - - return ; - } - - renderItems() { - if (this.props.virtual) { - return null; - } - - return this.items.map(item => this.getRow(item.getId())); - } - - renderHeaderContent(placeholders: HeaderPlaceholders): ReactNode { - const { searchFilters } = this.props; - const { title, filters, searchProps, info } = placeholders; - - return ( - <> - {title} - { - info && ( -
- {info} -
- ) - } - {filters} - {searchFilters.length > 0 && searchProps && } - - ); - } - - renderInfo() { - const { items, filters } = this; - const allItemsCount = this.props.store.getTotalCount(); - const itemsCount = items.length; - - if (filters.length > 0) { - return ( - <>Filtered: {itemsCount} / {allItemsCount} - ); - } - - return allItemsCount === 1 ? `${allItemsCount} item` : `${allItemsCount} items`; - } - - renderHeader() { - const { showHeader, customizeHeader, renderHeaderTitle, headerClassName } = this.props; - - if (!showHeader) { - return null; - } - - const title = typeof renderHeaderTitle === "function" ? renderHeaderTitle(this) : renderHeaderTitle; - const customizeHeaders = [customizeHeader].flat().filter(Boolean); - const initialPlaceholders: HeaderPlaceholders = { - title:
{title}
, - info: this.renderInfo(), - searchProps: {}, - }; - const headerPlaceholders = customizeHeaders.reduce((prevPlaceholders, customizer) => customizer(prevPlaceholders), initialPlaceholders); - const header = this.renderHeaderContent(headerPlaceholders); - - return ( -
- {header} -
- ); - } - - renderTableHeader() { - const { customizeTableRowProps, renderTableHeader, isSelectable, isConfigurable, store } = this.props; - - if (!renderTableHeader) { - return null; - } - - const enabledItems = this.items.filter(item => !customizeTableRowProps(item).disabled); - - return ( - - {isSelectable && ( - store.toggleSelectionAll(enabledItems))} - /> - )} - {renderTableHeader.map((cellProps, index) => ( - this.showColumn(cellProps) && ( - - ) - ))} - - {isConfigurable && this.renderColumnVisibilityMenu()} - - - ); - } - - renderList() { - const { - store, hasDetailsView, addRemoveButtons = {}, virtual, sortingCallbacks, - detailsItem, className, tableProps = {}, tableId, - } = this.props; - const { removeItemsDialog, items } = this; - const { selectedItems } = store; - const selectedItemId = detailsItem && detailsItem.getId(); - const classNames = cssNames(className, "box", "grow", ThemeStore.getInstance().activeTheme.type); - - return ( -
- - {this.renderTableHeader()} - {this.renderItems()} -
- -
- ); - } - - showColumn({ id: columnId, showWithColumn }: TableCellProps): boolean { - const { tableId, isConfigurable } = this.props; - - return !isConfigurable || !UserStore.getInstance().isTableColumnHidden(tableId, columnId, showWithColumn); - } - - renderColumnVisibilityMenu() { - const { renderTableHeader, tableId } = this.props; - - return ( - - {renderTableHeader.map((cellProps, index) => ( - !cellProps.showWithColumn && ( - - `} - value={this.showColumn(cellProps)} - onChange={() => UserStore.getInstance().toggleTableColumnVisibility(tableId, cellProps.id)} - /> - - ) - ))} - - ); - } - - renderFooter() { - return this.props.renderFooter?.(this); - } - - render() { - const { className } = this.props; - - return ( -
- {this.renderHeader()} - {this.renderFilters()} - {this.renderList()} - {this.renderFooter()} -
- ); - } -} - -export function ItemListLayout( - props: ItemListLayoutProps, -) { - const InjectedItemListLayout = withInjectables< - Dependencies, - ItemListLayoutProps - >( - NonInjectedItemListLayout, - - { - getProps: (di, props) => ({ - namespaceStore: di.inject(namespaceStoreInjectable), - itemListLayoutStorage: di.inject(itemListLayoutStorageInjectable), - ...props, - }), - }, - ); - - return ; -} diff --git a/src/renderer/components/item-object-list/list-layout.tsx b/src/renderer/components/item-object-list/list-layout.tsx new file mode 100644 index 0000000000..959f814bce --- /dev/null +++ b/src/renderer/components/item-object-list/list-layout.tsx @@ -0,0 +1,295 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import "./item-list-layout.scss"; + +import React, { ReactNode } from "react"; +import { computed, makeObservable, untracked } from "mobx"; +import type { ConfirmDialogParams } from "../confirm-dialog"; +import type { TableCellProps, TableProps, TableRowProps, TableSortCallbacks } from "../table"; +import { boundMethod, cssNames, IClassName, noop, StorageHelper } from "../../utils"; +import type { AddRemoveButtonsProps } from "../add-remove-buttons"; +import type { ItemObject, ItemStore } from "../../../common/item.store"; +import type { SearchInputUrlProps } from "../input"; +import { Filter, FilterType, pageFilters } from "./page-filters.store"; +import { PageFiltersList } from "./page-filters-list"; +import type { NamespaceStore } from "../+namespaces/namespace-store/namespace.store"; +import namespaceStoreInjectable from "../+namespaces/namespace-store/namespace-store.injectable"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import itemListLayoutStorageInjectable from "./storage.injectable"; +import { ItemListLayoutContent } from "./content"; +import { ItemListLayoutHeader } from "./header"; +import groupBy from "lodash/groupBy"; +import { ItemListLayoutFilters } from "./filters"; +import { observer } from "mobx-react"; + +export type SearchFilter = (item: I) => string | number | (string | number)[]; +export type SearchFilters = Record>; +export type ItemsFilter = (items: I[]) => I[]; +export type ItemsFilters = Record>; + +export interface HeaderPlaceholders { + title?: ReactNode; + searchProps?: SearchInputUrlProps; + filters?: ReactNode; + info?: ReactNode; +} + +export type HeaderCustomizer = (placeholders: HeaderPlaceholders) => HeaderPlaceholders; +export interface ItemListLayoutProps { + tableId?: string; + className: IClassName; + items?: I[]; + getItems?: () => I[]; + store: ItemStore; + dependentStores?: ItemStore[]; + preloadStores?: boolean; + hideFilters?: boolean; + searchFilters?: SearchFilter[]; + /** @deprecated */ + filterItems?: ItemsFilter[]; + + // header (title, filtering, searching, etc.) + showHeader?: boolean; + headerClassName?: IClassName; + renderHeaderTitle?: ReactNode | ((parent: NonInjectedItemListLayout) => ReactNode); + customizeHeader?: HeaderCustomizer | HeaderCustomizer[]; + + // items list configuration + isReady?: boolean; // show loading indicator while not ready + isSelectable?: boolean; // show checkbox in rows for selecting items + isConfigurable?: boolean; + copyClassNameFromHeadCells?: boolean; + sortingCallbacks?: TableSortCallbacks; + tableProps?: Partial>; // low-level table configuration + renderTableHeader: TableCellProps[] | null; + renderTableContents: (item: I) => (ReactNode | TableCellProps)[]; + renderItemMenu?: (item: I, store: ItemStore) => ReactNode; + customizeTableRowProps?: (item: I) => Partial; + addRemoveButtons?: Partial; + virtual?: boolean; + + // item details view + hasDetailsView?: boolean; + detailsItem?: I; + onDetails?: (item: I) => void; + + // other + customizeRemoveDialog?: (selectedItems: I[]) => Partial; + renderFooter?: (parent: NonInjectedItemListLayout) => React.ReactNode; + + /** + * Message to display when a store failed to load + * + * @default "Failed to load items" + */ + failedToLoadMessage?: React.ReactNode; + + filterCallbacks?: ItemsFilters; +} + +const defaultProps: Partial> = { + showHeader: true, + isSelectable: true, + isConfigurable: false, + copyClassNameFromHeadCells: true, + preloadStores: true, + dependentStores: [], + searchFilters: [], + customizeHeader: [], + filterItems: [], + hasDetailsView: true, + onDetails: noop, + virtual: true, + customizeTableRowProps: () => ({}), + failedToLoadMessage: "Failed to load items", +}; + +interface Dependencies { + namespaceStore: NamespaceStore; + itemListLayoutStorage: StorageHelper<{ showFilters: boolean }>; +} + +@observer +class NonInjectedItemListLayout extends React.Component & Dependencies> { + static defaultProps = defaultProps as object; + + constructor(props: ItemListLayoutProps & Dependencies) { + super(props); + makeObservable(this); + } + + async componentDidMount() { + const { isConfigurable, tableId, preloadStores } = this.props; + + if (isConfigurable && !tableId) { + throw new Error("[ItemListLayout]: configurable list require props.tableId to be specified"); + } + + if (preloadStores) { + this.loadStores(); + } + } + + private loadStores() { + const { store, dependentStores } = this.props; + const stores = Array.from(new Set([store, ...dependentStores])); + + stores.forEach(store => store.loadAll(this.props.namespaceStore.contextNamespaces)); + } + + get showFilters(): boolean { + return this.props.itemListLayoutStorage.get().showFilters; + } + + set showFilters(showFilters: boolean) { + this.props.itemListLayoutStorage.merge({ showFilters }); + } + + @computed get filters() { + let { activeFilters } = pageFilters; + const { searchFilters } = this.props; + + if (searchFilters.length === 0) { + activeFilters = activeFilters.filter(({ type }) => type !== FilterType.SEARCH); + } + + return activeFilters; + } + + @boundMethod + toggleFilters() { + this.showFilters = !this.showFilters; + } + + @computed get isReady() { + return this.props.isReady ?? this.props.store.isLoaded; + } + + renderFilters() { + const { hideFilters } = this.props; + const { isReady, filters } = this; + + if (!isReady || !filters.length || hideFilters || !this.showFilters) { + return null; + } + + return ; + } + + private filterCallbacks: ItemsFilters = { + [FilterType.SEARCH]: items => { + const { searchFilters } = this.props; + const search = pageFilters.getValues(FilterType.SEARCH)[0] || ""; + + if (search && searchFilters.length) { + const normalizeText = (text: string) => String(text).toLowerCase(); + const searchTexts = [search].map(normalizeText); + + return items.filter(item => { + return searchFilters.some(getTexts => { + const sourceTexts: string[] = [getTexts(item)].flat().map(normalizeText); + + return sourceTexts.some(source => searchTexts.some(search => source.includes(search))); + }); + }); + } + + return items; + }, + }; + + @computed get items() { + const filterGroups = groupBy(this.filters, ({ type }) => type); + + const filterItems: ItemsFilter[] = []; + + Object.entries(filterGroups).forEach(([type, filtersGroup]) => { + const filterCallback = this.filterCallbacks[type] ?? this.props.filterCallbacks?.[type]; + + if (filterCallback && filtersGroup.length > 0) { + filterItems.push(filterCallback); + } + }); + + const items = this.props.getItems ? this.props.getItems() : (this.props.items ?? this.props.store.items); + + return applyFilters(filterItems.concat(this.props.filterItems), items); + } + + render() { + return untracked(() => ( +
+ this.items} + getFilters={() => this.filters} + toggleFilters={this.toggleFilters} + store={this.props.store} + searchFilters={this.props.searchFilters} + showHeader={this.props.showHeader} + headerClassName={this.props.headerClassName} + renderHeaderTitle={this.props.renderHeaderTitle} + customizeHeader={this.props.customizeHeader} + /> + + this.isReady} + getFilters={() => this.filters} + getFiltersAreShown={() => this.showFilters} + hideFilters={this.props.hideFilters} + /> + + this.items} + getFilters={() => this.filters} + tableId={this.props.tableId} + className={this.props.className} + store={this.props.store} + getIsReady={() => this.isReady} + isSelectable={this.props.isSelectable} + isConfigurable={this.props.isConfigurable} + copyClassNameFromHeadCells={this.props.copyClassNameFromHeadCells} + sortingCallbacks={this.props.sortingCallbacks} + tableProps={this.props.tableProps} + renderTableHeader={this.props.renderTableHeader} + renderTableContents={this.props.renderTableContents} + renderItemMenu={this.props.renderItemMenu} + customizeTableRowProps={this.props.customizeTableRowProps} + addRemoveButtons={this.props.addRemoveButtons} + virtual={this.props.virtual} + hasDetailsView={this.props.hasDetailsView} + detailsItem={this.props.detailsItem} + onDetails={this.props.onDetails} + customizeRemoveDialog={this.props.customizeRemoveDialog} + failedToLoadMessage={this.props.failedToLoadMessage} + /> + + {this.props.renderFooter?.(this)} +
+ )); + } +} + +const InjectedItemListLayout = withInjectables>(NonInjectedItemListLayout, { + getProps: (di, props) => ({ + namespaceStore: di.inject(namespaceStoreInjectable), + itemListLayoutStorage: di.inject(itemListLayoutStorageInjectable), + ...props, + }), +}); + +export function ItemListLayout(props: ItemListLayoutProps) { + return ; +} + +function applyFilters(filters: ItemsFilter[], items: I[]): I[] { + if (!filters || !filters.length) { + return items; + } + + return filters.reduce((items, filter) => filter(items), items); +} diff --git a/src/renderer/components/item-object-list/item-list-layout-storage/item-list-layout-storage.injectable.ts b/src/renderer/components/item-object-list/storage.injectable.ts similarity index 85% rename from src/renderer/components/item-object-list/item-list-layout-storage/item-list-layout-storage.injectable.ts rename to src/renderer/components/item-object-list/storage.injectable.ts index 9033e5fdfe..a105d35472 100644 --- a/src/renderer/components/item-object-list/item-list-layout-storage/item-list-layout-storage.injectable.ts +++ b/src/renderer/components/item-object-list/storage.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; +import createStorageInjectable from "../../utils/create-storage/create-storage.injectable"; const itemListLayoutStorageInjectable = getInjectable({ instantiate: (di) => { diff --git a/src/renderer/components/kube-object-details/kube-object-details.tsx b/src/renderer/components/kube-object-details/kube-object-details.tsx index 0301302714..68b7199ced 100644 --- a/src/renderer/components/kube-object-details/kube-object-details.tsx +++ b/src/renderer/components/kube-object-details/kube-object-details.tsx @@ -51,31 +51,34 @@ export class KubeObjectDetails extends React.Component { } } - @disposeOnUnmount - loader = reaction(() => [ - this.path, - this.object, // resource might be updated via watch-event or from already opened details - crdStore.items.length, // crd stores initialized after loading - ], async () => { - this.loadingError = ""; - const { path, object } = this; + componentDidMount(): void { + disposeOnUnmount(this, [ + reaction(() => [ + this.path, + this.object, // resource might be updated via watch-event or from already opened details + crdStore.items.length, // crd stores initialized after loading + ], async () => { + this.loadingError = ""; + const { path, object } = this; - if (!object) { - const store = apiManager.getStore(path); + if (!object) { + const store = apiManager.getStore(path); - if (store) { - this.isLoading = true; + if (store) { + this.isLoading = true; - try { - await store.loadFromPath(path); - } catch (err) { - this.loadingError = <>Resource loading has failed: {err.toString()}; - } finally { - this.isLoading = false; + try { + await store.loadFromPath(path); + } catch (err) { + this.loadingError = <>Resource loading has failed: {err.toString()}; + } finally { + this.isLoading = false; + } + } } - } - } - }); + }), + ]); + } render() { const { object, isLoading, loadingError } = this; diff --git a/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx b/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx index 304694da0f..de1253fd65 100644 --- a/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx +++ b/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx @@ -10,7 +10,7 @@ import { computed, makeObservable, observable, reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { cssNames, Disposer } from "../../utils"; import type { KubeObject } from "../../../common/k8s-api/kube-object"; -import { ItemListLayout, ItemListLayoutProps } from "../item-object-list/item-list-layout"; +import { ItemListLayout, ItemListLayoutProps } from "../item-object-list/list-layout"; import type { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; import { KubeObjectMenu } from "../kube-object-menu"; import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter"; @@ -99,14 +99,14 @@ class NonInjectedKubeObjectListLayout extends React.Compon } render() { - const { className, customizeHeader, store, items = store.contextItems, ...layoutProps } = this.props; + const { className, customizeHeader, store, items, ...layoutProps } = this.props; const placeholderString = ResourceNames[ResourceKindMap[store.api.kind]] || store.api.kind; return ( this.props.items || store.contextItems} preloadStores={false} // loading handled in kubeWatchApi.subscribeStores() detailsItem={this.selectedItem} customizeHeader={[ diff --git a/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/get-kube-object-menu-items.ts b/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/get-kube-object-menu-items.ts index 0e8baf98e6..7091a7c242 100644 --- a/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/get-kube-object-menu-items.ts +++ b/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/get-kube-object-menu-items.ts @@ -2,21 +2,36 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { KubeObjectMenuRegistry } from "../../../../../extensions/registries"; +import { conforms, includes, eq } from "lodash/fp"; import type { KubeObject } from "../../../../../common/k8s-api/kube-object"; +import type { LensRendererExtension } from "../../../../../extensions/lens-renderer-extension"; +import { staticKubeObjectMenuItems as staticMenuItems } from "./static-kube-object-menu-items"; + +interface Dependencies { + extensions: LensRendererExtension[]; + kubeObject: KubeObject; +} export const getKubeObjectMenuItems = ({ - kubeObjectMenuRegistry, + extensions, kubeObject, -}: { - kubeObjectMenuRegistry: KubeObjectMenuRegistry; - kubeObject: KubeObject; -}) => { +}: Dependencies) => { if (!kubeObject) { return []; } - return kubeObjectMenuRegistry - .getItemsForKind(kubeObject.kind, kubeObject.apiVersion) + const extensionMenuItems = extensions.flatMap( + (extension) => extension.kubeObjectMenuItems, + ); + + return [...staticMenuItems, ...extensionMenuItems] + .filter( + conforms({ + kind: eq(kubeObject.kind), + apiVersions: includes(kubeObject.apiVersion), + }), + ) + .map((item) => item.components.MenuItem); }; + diff --git a/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-items.injectable.ts b/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-items.injectable.ts index 3d8f16de8e..703374ab2d 100644 --- a/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-items.injectable.ts +++ b/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-items.injectable.ts @@ -3,15 +3,15 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import kubeObjectMenuRegistryInjectable from "./kube-object-menu-registry.injectable"; import { getKubeObjectMenuItems } from "./get-kube-object-menu-items"; import type { KubeObject } from "../../../../../common/k8s-api/kube-object"; +import rendererExtensionsInjectable from "../../../../../extensions/renderer-extensions.injectable"; const kubeObjectMenuItemsInjectable = getInjectable({ instantiate: (di, { kubeObject }: { kubeObject: KubeObject }) => getKubeObjectMenuItems({ - kubeObjectMenuRegistry: di.inject(kubeObjectMenuRegistryInjectable), + extensions: di.inject(rendererExtensionsInjectable).get(), kubeObject, }), diff --git a/src/extensions/registries/kube-object-menu-registry.ts b/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-registration.ts similarity index 50% rename from src/extensions/registries/kube-object-menu-registry.ts rename to src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-registration.ts index a1db08e26d..b3a0904634 100644 --- a/src/extensions/registries/kube-object-menu-registry.ts +++ b/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-registration.ts @@ -4,10 +4,15 @@ */ import type React from "react"; -import { BaseRegistry } from "./base-registry"; +import type { KubeObject } from "../../../../../common/k8s-api/kube-object"; + +export interface KubeObjectMenuItemProps { + object: KubeObject; + toolbar?: boolean; +} export interface KubeObjectMenuComponents { - MenuItem: React.ComponentType; + MenuItem: React.ComponentType; } export interface KubeObjectMenuRegistration { @@ -15,11 +20,3 @@ export interface KubeObjectMenuRegistration { apiVersions: string[]; components: KubeObjectMenuComponents; } - -export class KubeObjectMenuRegistry extends BaseRegistry { - getItemsForKind(kind: string, apiVersion: string) { - return this.getItems().filter((item) => { - return item.kind === kind && item.apiVersions.includes(apiVersion); - }); - } -} diff --git a/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/static-kube-object-menu-items.ts b/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/static-kube-object-menu-items.ts new file mode 100644 index 0000000000..0368fbb241 --- /dev/null +++ b/src/renderer/components/kube-object-menu/dependencies/kube-object-menu-items/static-kube-object-menu-items.ts @@ -0,0 +1,47 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { ServiceAccountMenu } from "../../../+user-management/+service-accounts/service-account-menu"; +import { CronJobMenu } from "../../../+workloads-cronjobs/cron-job-menu"; +import { DeploymentMenu } from "../../../+workloads-deployments/deployment-menu"; +import { ReplicaSetMenu } from "../../../+workloads-replicasets/replica-set-menu"; +import { StatefulSetMenu } from "../../../+workloads-statefulsets/stateful-set-menu"; + +export const staticKubeObjectMenuItems = [ + { + kind: "ServiceAccount", + apiVersions: ["v1"], + components: { + MenuItem: ServiceAccountMenu, + }, + }, + { + kind: "CronJob", + apiVersions: ["batch/v1beta1"], + components: { + MenuItem: CronJobMenu, + }, + }, + { + kind: "Deployment", + apiVersions: ["apps/v1"], + components: { + MenuItem: DeploymentMenu, + }, + }, + { + kind: "ReplicaSet", + apiVersions: ["apps/v1"], + components: { + MenuItem: ReplicaSetMenu, + }, + }, + { + kind: "StatefulSet", + apiVersions: ["apps/v1"], + components: { + MenuItem: StatefulSetMenu, + }, + }, +]; diff --git a/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx b/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx index 935c4b9208..ac6b55f36f 100644 --- a/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx +++ b/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx @@ -2,82 +2,108 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ - import React from "react"; import { screen } from "@testing-library/react"; import "@testing-library/jest-dom/extend-expect"; import { KubeObject } from "../../../common/k8s-api/kube-object"; import userEvent from "@testing-library/user-event"; import type { ConfigurableDependencyInjectionContainer } from "@ogre-tools/injectable"; -import type { KubeObjectMenuRegistration } from "../../../extensions/registries"; -import { KubeObjectMenuRegistry } from "../../../extensions/registries"; import { ConfirmDialog } from "../confirm-dialog"; import asyncFn, { AsyncFnMock } from "@async-fn/jest"; import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import clusterInjectable from "./dependencies/cluster.injectable"; import hideDetailsInjectable from "./dependencies/hide-details.injectable"; -import editResourceTabInjectable from "../dock/edit-resource-tab/edit-resource-tab.injectable"; -import { TabKind } from "../dock/dock-store/dock.store"; -import kubeObjectMenuRegistryInjectable from "./dependencies/kube-object-menu-items/kube-object-menu-registry.injectable"; import { DiRender, renderFor } from "../test-utils/renderFor"; import type { Cluster } from "../../../common/cluster/cluster"; import type { ApiManager } from "../../../common/k8s-api/api-manager"; import apiManagerInjectable from "./dependencies/api-manager.injectable"; import { KubeObjectMenu } from "./index"; +import type { KubeObjectMenuRegistration } from "./dependencies/kube-object-menu-items/kube-object-menu-registration"; +import { computed } from "mobx"; +import { LensRendererExtension } from "../../../extensions/lens-renderer-extension"; +import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable"; +import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource-tab.injectable"; // TODO: Make tooltips free of side effects by making it deterministic jest.mock("../tooltip"); +class SomeTestExtension extends LensRendererExtension { + constructor( + kubeObjectMenuItems: KubeObjectMenuRegistration[], + ) { + super({ + id: "some-id", + absolutePath: "irrelevant", + isBundled: false, + isCompatible: false, + isEnabled: false, + manifest: { name: "some-id", version: "some-version" }, + manifestPath: "irrelevant", + }); + + this.kubeObjectMenuItems = kubeObjectMenuItems; + } +} + describe("kube-object-menu", () => { let di: ConfigurableDependencyInjectionContainer; let render: DiRender; beforeEach(async () => { + const MenuItemComponent: React.FC = () =>
  • Some menu item
  • ; + + const kubeObjectMenuItems = [ + { + apiVersions: ["some-api-version"], + kind: "some-kind", + components: { MenuItem: MenuItemComponent }, + }, + + { + apiVersions: ["some-unrelated-api-version"], + kind: "some-kind", + components: { MenuItem: MenuItemComponent }, + }, + + { + apiVersions: ["some-api-version"], + kind: "some-unrelated-kind", + components: { MenuItem: MenuItemComponent }, + }, + ]; + + const someTestExtension = new SomeTestExtension(kubeObjectMenuItems); + di = getDiForUnitTesting({ doGeneralOverrides: true }); - await di.runSetups(); - - // TODO: Remove global shared state - KubeObjectMenuRegistry.resetInstance(); - KubeObjectMenuRegistry.createInstance(); - render = renderFor(di); - di.override(clusterInjectable, () => ({ - name: "Some name", - }) as Cluster); + di.override(rendererExtensionsInjectable, () => + computed(() => [someTestExtension]), + ); - di.override(apiManagerInjectable, () => ({ - getStore: api => void api, - }) as ApiManager); + await di.runSetups(); + + di.override( + clusterInjectable, + () => + ({ + name: "Some name", + } as Cluster), + ); + + di.override( + apiManagerInjectable, + () => + ({ + getStore: (api) => void api, + } as ApiManager), + ); di.override(hideDetailsInjectable, () => () => {}); - di.override(editResourceTabInjectable, () => () => ({ - id: "irrelevant", - kind: TabKind.TERMINAL, - pinned: false, - title: "irrelevant", - })); - - addDynamicMenuItem({ - di, - apiVersions: ["some-api-version"], - kind: "some-kind", - }); - - addDynamicMenuItem({ - di, - apiVersions: ["some-unrelated-api-version"], - kind: "some-kind", - }); - - addDynamicMenuItem({ - di, - apiVersions: ["some-api-version"], - kind: "some-unrelated-kind", - }); + di.override(createEditResourceTabInjectable, () => () => "irrelevant"); }); it("given no cluster, does not crash", () => { @@ -248,25 +274,3 @@ describe("kube-object-menu", () => { }); }); }); - -const addDynamicMenuItem = ({ - di, - apiVersions, - kind, -}: { - di: ConfigurableDependencyInjectionContainer; - apiVersions: string[]; - kind: string; -}) => { - const MenuItemComponent: React.FC = () =>
  • Some menu item
  • ; - - const dynamicMenuItemStub: KubeObjectMenuRegistration = { - apiVersions, - kind, - components: { MenuItem: MenuItemComponent }, - }; - - const kubeObjectMenuRegistry = di.inject(kubeObjectMenuRegistryInjectable); - - kubeObjectMenuRegistry.add([dynamicMenuItemStub]); -}; diff --git a/src/renderer/components/kube-object-menu/kube-object-menu.tsx b/src/renderer/components/kube-object-menu/kube-object-menu.tsx index f4f3a81b58..6d425ab9c3 100644 --- a/src/renderer/components/kube-object-menu/kube-object-menu.tsx +++ b/src/renderer/components/kube-object-menu/kube-object-menu.tsx @@ -11,7 +11,7 @@ import identity from "lodash/identity"; import type { ApiManager } from "../../../common/k8s-api/api-manager"; import { withInjectables } from "@ogre-tools/injectable-react"; import clusterNameInjectable from "./dependencies/cluster-name.injectable"; -import editResourceTabInjectable from "../dock/edit-resource-tab/edit-resource-tab.injectable"; +import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource-tab.injectable"; import hideDetailsInjectable from "./dependencies/hide-details.injectable"; import kubeObjectMenuItemsInjectable from "./dependencies/kube-object-menu-items/kube-object-menu-items.injectable"; import apiManagerInjectable from "./dependencies/api-manager.injectable"; @@ -27,7 +27,7 @@ interface Dependencies { kubeObjectMenuItems: React.ElementType[]; clusterName: string; hideDetails: () => void; - editResourceTab: (kubeObject: KubeObject) => void; + createEditResourceTab: (kubeObject: KubeObject) => void; } class NonInjectedKubeObjectMenu extends React.Component & Dependencies> { @@ -51,7 +51,7 @@ class NonInjectedKubeObjectMenu extends React.Co @boundMethod async update() { this.props.hideDetails(); - this.props.editResourceTab(this.props.object); + this.props.createEditResourceTab(this.props.object); } @boundMethod @@ -117,7 +117,7 @@ export function KubeObjectMenu( getProps: (di, props) => ({ clusterName: di.inject(clusterNameInjectable), apiManager: di.inject(apiManagerInjectable), - editResourceTab: di.inject(editResourceTabInjectable), + createEditResourceTab: di.inject(createEditResourceTabInjectable), hideDetails: di.inject(hideDetailsInjectable), kubeObjectMenuItems: di.inject(kubeObjectMenuItemsInjectable, { diff --git a/src/renderer/components/layout/top-bar/top-bar-registration.d.ts b/src/renderer/components/layout/top-bar/top-bar-registration.ts similarity index 100% rename from src/renderer/components/layout/top-bar/top-bar-registration.d.ts rename to src/renderer/components/layout/top-bar/top-bar-registration.ts diff --git a/src/renderer/components/layout/top-bar/top-bar-win-linux.test.tsx b/src/renderer/components/layout/top-bar/top-bar-win-linux.test.tsx index 0190adcc71..9b557a2f6c 100644 --- a/src/renderer/components/layout/top-bar/top-bar-win-linux.test.tsx +++ b/src/renderer/components/layout/top-bar/top-bar-win-linux.test.tsx @@ -20,15 +20,14 @@ jest.mock("../../../../common/ipc"); jest.mock("../../../ipc"); jest.mock("../../../../common/vars", () => { - const SemVer = require("semver").SemVer; - - const versionStub = new SemVer("1.0.0"); + const { SemVer } = require("semver"); return { + ...jest.requireActual<{}>("../../../../common/vars"), __esModule: true, isWindows: null, isLinux: null, - appSemVer: versionStub, + appSemVer: new SemVer("1.0.0"), }; }); diff --git a/src/renderer/components/layout/top-bar/top-bar.test.tsx b/src/renderer/components/layout/top-bar/top-bar.test.tsx index e5d491401c..db61d3e8d0 100644 --- a/src/renderer/components/layout/top-bar/top-bar.test.tsx +++ b/src/renderer/components/layout/top-bar/top-bar.test.tsx @@ -14,15 +14,15 @@ import topBarItemsInjectable from "./top-bar-items/top-bar-items.injectable"; import { computed } from "mobx"; import directoryForUserDataInjectable from "../../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import mockFs from "mock-fs"; +import isLinuxInjectable from "../../../../common/vars/is-linux.injectable"; +import isWindowsInjectable from "../../../../common/vars/is-windows.injectable"; jest.mock("../../../../common/vars", () => { - const SemVer = require("semver").SemVer; - - const versionStub = new SemVer("1.0.0"); + const { SemVer } = require("semver"); return { - isMac: true, - appSemVer: versionStub, + ...jest.requireActual<{}>("../../../../common/vars"), + appSemVer: new SemVer("1.0.0"), }; }); @@ -98,30 +98,30 @@ describe("", () => { }); it("renders home button", async () => { - const { getByTestId } = render(); + const { findByTestId } = render(); - expect(await getByTestId("home-button")).toBeInTheDocument(); + expect(await findByTestId("home-button")).toBeInTheDocument(); }); it("renders history arrows", async () => { - const { getByTestId } = render(); + const { findByTestId } = render(); - expect(await getByTestId("history-back")).toBeInTheDocument(); - expect(await getByTestId("history-forward")).toBeInTheDocument(); + expect(await findByTestId("history-back")).toBeInTheDocument(); + expect(await findByTestId("history-forward")).toBeInTheDocument(); }); it("enables arrow by ipc event", async () => { - const { getByTestId } = render(); + const { findByTestId } = render(); - expect(await getByTestId("history-back")).not.toHaveClass("disabled"); - expect(await getByTestId("history-forward")).not.toHaveClass("disabled"); + expect(await findByTestId("history-back")).not.toHaveClass("disabled"); + expect(await findByTestId("history-forward")).not.toHaveClass("disabled"); }); it("triggers browser history back and forward", async () => { - const { getByTestId } = render(); + const { findByTestId } = render(); - const prevButton = await getByTestId("history-back"); - const nextButton = await getByTestId("history-forward"); + const prevButton = await findByTestId("history-back"); + const nextButton = await findByTestId("history-forward"); fireEvent.click(prevButton); @@ -144,12 +144,15 @@ describe("", () => { }, ])); - const { getByTestId } = render(); + const { findByTestId } = render(); - expect(await getByTestId(testId)).toHaveTextContent(text); + expect(await findByTestId(testId)).toHaveTextContent(text); }); - it("doesn't show windows title buttons", () => { + it("doesn't show windows title buttons on macos", () => { + di.override(isLinuxInjectable, () => false); + di.override(isWindowsInjectable, () => false); + const { queryByTestId } = render(); expect(queryByTestId("window-menu")).not.toBeInTheDocument(); @@ -157,4 +160,16 @@ describe("", () => { expect(queryByTestId("window-maximize")).not.toBeInTheDocument(); expect(queryByTestId("window-close")).not.toBeInTheDocument(); }); + + it("does show windows title buttons on linux", () => { + di.override(isLinuxInjectable, () => true); + di.override(isWindowsInjectable, () => false); + + const { queryByTestId } = render(); + + expect(queryByTestId("window-menu")).toBeInTheDocument(); + expect(queryByTestId("window-minimize")).toBeInTheDocument(); + expect(queryByTestId("window-maximize")).toBeInTheDocument(); + expect(queryByTestId("window-close")).toBeInTheDocument(); + }); }); diff --git a/src/renderer/components/layout/top-bar/top-bar.tsx b/src/renderer/components/layout/top-bar/top-bar.tsx index dc801a5424..3030cbad57 100644 --- a/src/renderer/components/layout/top-bar/top-bar.tsx +++ b/src/renderer/components/layout/top-bar/top-bar.tsx @@ -13,18 +13,21 @@ import { ipcRendererOn } from "../../../../common/ipc"; import { watchHistoryState } from "../../../remote-helpers/history-updater"; import { isActiveRoute, navigate } from "../../../navigation"; import { catalogRoute, catalogURL } from "../../../../common/routes"; -import { isLinux, isWindows } from "../../../../common/vars"; import { cssNames } from "../../../utils"; import topBarItemsInjectable from "./top-bar-items/top-bar-items.injectable"; import { withInjectables } from "@ogre-tools/injectable-react"; import type { TopBarRegistration } from "./top-bar-registration"; import { emitOpenAppMenuAsContextMenu, requestWindowAction } from "../../../ipc"; import { WindowAction } from "../../../../common/ipc/window"; +import isLinuxInjectable from "../../../../common/vars/is-linux.injectable"; +import isWindowsInjectable from "../../../../common/vars/is-windows.injectable"; -interface Props extends React.HTMLAttributes {} +export interface TopBarProps extends React.HTMLAttributes {} interface Dependencies { items: IComputedValue; + isWindows: boolean; + isLinux: boolean; } const prevEnabled = observable.box(false); @@ -38,7 +41,7 @@ ipcRendererOn("history:can-go-forward", (event, state: boolean) => { nextEnabled.set(state); }); -const NonInjectedTopBar = (({ items, children, ...rest }: Props & Dependencies) => { +const NonInjectedTopBar = observer(({ items, children, isWindows, isLinux, ...rest }: TopBarProps & Dependencies) => { const elem = useRef(); const openAppContextMenu = () => { @@ -161,9 +164,11 @@ const renderRegisteredItems = (items: TopBarRegistration[]) => ( -export const TopBar = withInjectables(observer(NonInjectedTopBar), { +export const TopBar = withInjectables(NonInjectedTopBar, { getProps: (di, props) => ({ items: di.inject(topBarItemsInjectable), + isLinux: di.inject(isLinuxInjectable), + isWindows: di.inject(isWindowsInjectable), ...props, }), }); diff --git a/src/renderer/components/monaco-editor/monaco-editor.tsx b/src/renderer/components/monaco-editor/monaco-editor.tsx index 788d6d941e..b5f7a57364 100644 --- a/src/renderer/components/monaco-editor/monaco-editor.tsx +++ b/src/renderer/components/monaco-editor/monaco-editor.tsx @@ -249,8 +249,7 @@ export class MonacoEditor extends React.Component { this.editor?.focus(); } - @action - validate = (value = this.getValue()) => { + validate = action((value = this.getValue()) => { const validators: MonacoValidator[] = [ monacoValidators[this.props.language], // parsing syntax check ].filter(Boolean); @@ -262,7 +261,7 @@ export class MonacoEditor extends React.Component { this.props.onError?.(error); // emit error outside } } - }; + }); // avoid excessive validations during typing validateLazy = debounce(this.validate, 250); diff --git a/src/renderer/components/resizing-anchor/resizing-anchor.tsx b/src/renderer/components/resizing-anchor/resizing-anchor.tsx index 4842dff719..7629b6610f 100644 --- a/src/renderer/components/resizing-anchor/resizing-anchor.tsx +++ b/src/renderer/components/resizing-anchor/resizing-anchor.tsx @@ -194,8 +194,7 @@ export class ResizingAnchor extends React.PureComponent { document.removeEventListener("mouseup", this.onDragEnd); } - @action - onDragInit = (event: React.MouseEvent) => { + onDragInit = action((event: React.MouseEvent) => { const { onStart, onlyButtons } = this.props; if (typeof onlyButtons === "number" && onlyButtons !== event.buttons) { @@ -209,7 +208,7 @@ export class ResizingAnchor extends React.PureComponent { this.lastMouseEvent = undefined; onStart(); - }; + }); calculateDelta(from: Position, to: Position): number | false { const node = this.ref.current; @@ -285,8 +284,7 @@ export class ResizingAnchor extends React.PureComponent { } }, 100); - @action - onDragEnd = () => { + onDragEnd = action(() => { this.props.onEnd(); document.removeEventListener("mousemove", this.onDrag); document.removeEventListener("mouseup", this.onDragEnd); @@ -295,7 +293,7 @@ export class ResizingAnchor extends React.PureComponent { this.wasDragging = true; setTimeout(() => this.wasDragging = false, 200); - }; + }); render() { const { disabled, direction, placement, onDoubleClick } = this.props; diff --git a/src/renderer/components/table/table-head.scss b/src/renderer/components/table/table-head.scss index 03e64b4add..381fb68b9c 100644 --- a/src/renderer/components/table/table-head.scss +++ b/src/renderer/components/table/table-head.scss @@ -4,7 +4,7 @@ */ .TableHead { - $border: 1px solid var(--layoutBackground); + $border: 1px solid var(--tableHeaderBorderColor); background-color: var(--tableHeaderBackground); border-bottom-width: var(--tableHeaderBorderWidth); diff --git a/src/renderer/getDiForUnitTesting.tsx b/src/renderer/getDiForUnitTesting.tsx index 901b7edbf8..c353008371 100644 --- a/src/renderer/getDiForUnitTesting.tsx +++ b/src/renderer/getDiForUnitTesting.tsx @@ -8,8 +8,10 @@ import { memoize } from "lodash/fp"; import { createContainer } from "@ogre-tools/injectable"; import { setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import getValueFromRegisteredChannelInjectable from "./app-paths/get-value-from-registered-channel/get-value-from-registered-channel.injectable"; -import writeJsonFileInjectable from "../common/fs/write-json-file/write-json-file.injectable"; -import readJsonFileInjectable from "../common/fs/read-json-file/read-json-file.injectable"; +import writeJsonFileInjectable from "../common/fs/write-json-file.injectable"; +import readJsonFileInjectable from "../common/fs/read-json-file.injectable"; +import readDirInjectable from "../common/fs/read-dir.injectable"; +import readFileInjectable from "../common/fs/read-file.injectable"; export const getDiForUnitTesting = ({ doGeneralOverrides } = { doGeneralOverrides: false }) => { const di = createContainer(); @@ -31,6 +33,14 @@ export const getDiForUnitTesting = ({ doGeneralOverrides } = { doGeneralOverride if (doGeneralOverrides) { di.override(getValueFromRegisteredChannelInjectable, () => () => undefined); + di.override(readDirInjectable, () => () => { + throw new Error("Tried to read contents of a directory from file system without specifying explicit override."); + }); + + di.override(readFileInjectable, () => () => { + throw new Error("Tried to read a file from file system without specifying explicit override."); + }); + di.override(writeJsonFileInjectable, () => () => { throw new Error("Tried to write JSON file to file system without specifying explicit override."); }); diff --git a/src/renderer/initializers/index.ts b/src/renderer/initializers/index.ts index 3965d45fcf..11c318090c 100644 --- a/src/renderer/initializers/index.ts +++ b/src/renderer/initializers/index.ts @@ -8,7 +8,6 @@ export * from "./catalog"; export * from "./entity-settings-registry"; export * from "./ipc"; export * from "./kube-object-detail-registry"; -export * from "./kube-object-menu-registry"; export * from "./registries"; export * from "./workloads-overview-detail-registry"; export * from "./catalog-category-registry"; diff --git a/src/renderer/initializers/kube-object-menu-registry.ts b/src/renderer/initializers/kube-object-menu-registry.ts deleted file mode 100644 index d25ef0aaf7..0000000000 --- a/src/renderer/initializers/kube-object-menu-registry.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { KubeObjectMenuRegistry } from "../../extensions/registries"; -import { ServiceAccountMenu } from "../components/+user-management/+service-accounts"; -import { CronJobMenu } from "../components/+workloads-cronjobs"; -import { DeploymentMenu } from "../components/+workloads-deployments"; -import { ReplicaSetMenu } from "../components/+workloads-replicasets"; -import { StatefulSetMenu } from "../components/+workloads-statefulsets"; - -export function initKubeObjectMenuRegistry() { - KubeObjectMenuRegistry.getInstance() - .add([ - { - kind: "ServiceAccount", - apiVersions: ["v1"], - components: { - MenuItem: ServiceAccountMenu, - }, - }, - { - kind: "CronJob", - apiVersions: ["batch/v1beta1"], - components: { - MenuItem: CronJobMenu, - }, - }, - { - kind: "Deployment", - apiVersions: ["apps/v1"], - components: { - MenuItem: DeploymentMenu, - }, - }, - { - kind: "ReplicaSet", - apiVersions: ["apps/v1"], - components: { - MenuItem: ReplicaSetMenu, - }, - }, - { - kind: "StatefulSet", - apiVersions: ["apps/v1"], - components: { - MenuItem: StatefulSetMenu, - }, - }, - ]); -} diff --git a/src/renderer/initializers/registries.ts b/src/renderer/initializers/registries.ts index 93caeee51e..374e114b7c 100644 --- a/src/renderer/initializers/registries.ts +++ b/src/renderer/initializers/registries.ts @@ -12,8 +12,6 @@ export function initRegistries() { registries.EntitySettingRegistry.createInstance(); registries.GlobalPageRegistry.createInstance(); registries.KubeObjectDetailRegistry.createInstance(); - registries.KubeObjectMenuRegistry.createInstance(); registries.KubeObjectStatusRegistry.createInstance(); - registries.StatusBarRegistry.createInstance(); registries.WorkloadsOverviewDetailRegistry.createInstance(); } diff --git a/src/renderer/kube-watch-api/kube-watch-api.ts b/src/renderer/kube-watch-api/kube-watch-api.ts index 4b9a802723..f38ffcec1c 100644 --- a/src/renderer/kube-watch-api/kube-watch-api.ts +++ b/src/renderer/kube-watch-api/kube-watch-api.ts @@ -27,7 +27,6 @@ class WrappedAbortController extends AbortController { interface SubscribeStoreParams { store: KubeObjectStore; parent: AbortController; - watchChanges: boolean; namespaces: string[]; onLoadFailure?: (err: any) => void; } @@ -75,7 +74,7 @@ export interface KubeWatchSubscribeStoreOptions { /** * A function that is called when listing fails. If set then blocks errors - * being rejected with + * from rejecting promises */ onLoadFailure?: (err: any) => void; } @@ -89,12 +88,16 @@ export class KubeWatchApi { constructor(private dependencies: Dependencies) {} - private subscribeStore({ store, parent, watchChanges, namespaces, onLoadFailure }: SubscribeStoreParams): Disposer { - if (this.#watch.inc(store) > 1) { + private subscribeStore({ store, parent, namespaces, onLoadFailure }: SubscribeStoreParams): Disposer { + const isNamespaceFilterWatch = !namespaces; + + if (isNamespaceFilterWatch && this.#watch.inc(store) > 1) { // don't load or subscribe to a store more than once return () => this.#watch.dec(store); } + namespaces ??= this.dependencies.clusterFrameContext?.contextNamespaces ?? []; + let childController = new WrappedAbortController(parent); const unsubscribe = disposer(); @@ -117,7 +120,7 @@ export class KubeWatchApi { */ loadThenSubscribe(namespaces).catch(noop); - const cancelReloading = watchChanges + const cancelReloading = isNamespaceFilterWatch && store.api.isNamespaced ? reaction( // Note: must slice because reaction won't fire if it isn't there () => [this.dependencies.clusterFrameContext.contextNamespaces.slice(), this.dependencies.clusterFrameContext.hasSelectedAll] as const, @@ -141,7 +144,7 @@ export class KubeWatchApi { : noop; // don't watch namespaces if namespaces were provided return () => { - if (this.#watch.dec(store) === 0) { + if (isNamespaceFilterWatch && this.#watch.dec(store) === 0) { // only stop the subcribe if this is the last one cancelReloading(); childController.abort(); @@ -156,8 +159,7 @@ export class KubeWatchApi { ...stores.map(store => this.subscribeStore({ store, parent, - watchChanges: !namespaces && store.api.isNamespaced, - namespaces: namespaces ?? this.dependencies.clusterFrameContext?.contextNamespaces ?? [], + namespaces, onLoadFailure, })), ); diff --git a/src/renderer/kube-watch-api/subscribe-stores.injectable.ts b/src/renderer/kube-watch-api/subscribe-stores.injectable.ts new file mode 100644 index 0000000000..35eb3a722e --- /dev/null +++ b/src/renderer/kube-watch-api/subscribe-stores.injectable.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import kubeWatchApiInjectable from "./kube-watch-api.injectable"; + +const subscribeStoresInjectable = getInjectable({ + instantiate: (di) => di.inject(kubeWatchApiInjectable).subscribeStores, + lifecycle: lifecycleEnum.singleton, +}); + +export default subscribeStoresInjectable; diff --git a/src/renderer/search-store/search-store.injectable.ts b/src/renderer/search-store/search-store.injectable.ts new file mode 100644 index 0000000000..3d5d08f484 --- /dev/null +++ b/src/renderer/search-store/search-store.injectable.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { SearchStore } from "./search-store"; + +const searchStoreInjectable = getInjectable({ + instantiate: () => new SearchStore(), + lifecycle: lifecycleEnum.transient, +}); + +export default searchStoreInjectable; diff --git a/src/renderer/search-store/search-store.test.ts b/src/renderer/search-store/search-store.test.ts index fa8623274c..f3fc9a4289 100644 --- a/src/renderer/search-store/search-store.test.ts +++ b/src/renderer/search-store/search-store.test.ts @@ -9,6 +9,7 @@ import { stdout, stderr } from "process"; import { getDiForUnitTesting } from "../getDiForUnitTesting"; import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; +import searchStoreInjectable from "./search-store.injectable"; jest.mock("electron", () => ({ app: { @@ -34,7 +35,7 @@ describe("search store tests", () => { await di.runSetups(); - searchStore = new SearchStore(); + searchStore = di.inject(searchStoreInjectable); }); it("does nothing with empty search query", () => { diff --git a/src/renderer/utils/create-storage/create-storage.injectable.ts b/src/renderer/utils/create-storage/create-storage.injectable.ts index 1f665bd002..729123a3ad 100644 --- a/src/renderer/utils/create-storage/create-storage.injectable.ts +++ b/src/renderer/utils/create-storage/create-storage.injectable.ts @@ -5,8 +5,8 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; import { createStorage } from "./create-storage"; -import readJsonFileInjectable from "../../../common/fs/read-json-file/read-json-file.injectable"; -import writeJsonFileInjectable from "../../../common/fs/write-json-file/write-json-file.injectable"; +import readJsonFileInjectable from "../../../common/fs/read-json-file.injectable"; +import writeJsonFileInjectable from "../../../common/fs/write-json-file.injectable"; const createStorageInjectable = getInjectable({ instantiate: (di) => diff --git a/src/renderer/utils/save-file.injectable.ts b/src/renderer/utils/save-file.injectable.ts new file mode 100644 index 0000000000..593c6955dc --- /dev/null +++ b/src/renderer/utils/save-file.injectable.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { saveFileDialog } from "./saveFile"; + +const openSaveFileDialogInjectable = getInjectable({ + instantiate: () => saveFileDialog, + lifecycle: lifecycleEnum.singleton, +}); + +export default openSaveFileDialogInjectable; diff --git a/webpack.extensions.ts b/webpack.extensions.ts index 32bba8f8a5..1cfae4963f 100644 --- a/webpack.extensions.ts +++ b/webpack.extensions.ts @@ -40,6 +40,10 @@ export default function generateExtensionTypes(): webpack.Configuration { stats: "errors-warnings", module: { rules: [ + { + test: /\.node$/, + loader: "ignore-loader", + }, { test: /\.tsx?$/, loader: "ts-loader", diff --git a/yarn.lock b/yarn.lock index 23ba83d9c3..226a290633 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,21 +12,7 @@ resolved "https://registry.yarnpkg.com/@async-fn/jest/-/jest-1.5.3.tgz#42be6c0e8ba5ccd737e006ca600e7e319fe2a591" integrity sha512-iQ9gAPZFW5U6TNcFS99ffwYYsB9LNecTnvG73BaDc/zAD0qOWctY1imEACC1pLymmm/xaf/OUq9I9QenfkatTA== -"@babel/code-frame@7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" - integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== - dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/code-frame@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/code-frame@^7.10.1", "@babel/code-frame@^7.10.4": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.1", "@babel/code-frame@^7.10.4": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== @@ -157,26 +143,16 @@ dependencies: "@babel/types" "^7.10.1" -"@babel/helper-validator-identifier@^7.10.1": +"@babel/helper-validator-identifier@^7.10.1", "@babel/helper-validator-identifier@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8" integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg== -"@babel/helper-validator-identifier@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" - integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== - "@babel/helper-validator-identifier@^7.15.7": version "7.15.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - "@babel/helpers@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.1.tgz#a6827b7cb975c9d9cef5fd61d919f60d8844a973" @@ -186,21 +162,12 @@ "@babel/traverse" "^7.10.1" "@babel/types" "^7.10.1" -"@babel/highlight@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" - integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== +"@babel/highlight@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" + integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.14.5", "@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" + "@babel/helper-validator-identifier" "^7.14.5" chalk "^2.0.0" js-tokens "^4.0.0" @@ -392,11 +359,6 @@ ajv "^6.12.0" ajv-keywords "^3.4.1" -"@discoveryjs/json-ext@^0.5.0": - version "0.5.6" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f" - integrity sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA== - "@electron/get@^1.0.1": version "1.12.2" resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.12.2.tgz#6442066afb99be08cefb9a281e4b4692b33764f3" @@ -501,18 +463,18 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== -"@eslint/eslintrc@^0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" - integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== +"@eslint/eslintrc@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318" + integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ== dependencies: ajv "^6.12.4" - debug "^4.1.1" - espree "^7.3.0" + debug "^4.3.2" + espree "^9.2.0" globals "^13.9.0" ignore "^4.0.6" import-fresh "^3.2.1" - js-yaml "^3.13.1" + js-yaml "^4.1.0" minimatch "^3.0.4" strip-json-comments "^3.1.1" @@ -615,19 +577,19 @@ "@hapi/bourne" "2.x.x" "@hapi/hoek" "9.x.x" -"@humanwhocodes/config-array@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" - integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== +"@humanwhocodes/config-array@^0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.2.tgz#68be55c737023009dfc5fe245d51181bb6476914" + integrity sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA== dependencies: - "@humanwhocodes/object-schema" "^1.2.0" + "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" minimatch "^3.0.4" -"@humanwhocodes/object-schema@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" - integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== "@iarna/cli@^1.2.0": version "1.2.0" @@ -1013,6 +975,18 @@ resolved "https://registry.yarnpkg.com/@panva/asn1.js/-/asn1.js-1.0.0.tgz#dd55ae7b8129e02049f009408b97c61ccf9032f6" integrity sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw== +"@pmmmwh/react-refresh-webpack-plugin@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.4.3.tgz#1eec460596d200c0236bf195b078a5d1df89b766" + integrity sha512-br5Qwvh8D2OQqSXpd1g/xqXKnK0r+Jz6qVKBbWmpUcrbGOxUrf39V5oZ1876084CGn18uMdR5uvPqBv9UqtBjQ== + dependencies: + ansi-html "^0.0.7" + error-stack-parser "^2.0.6" + html-entities "^1.2.1" + native-url "^0.2.6" + schema-utils "^2.6.5" + source-map "^0.7.3" + "@sentry/browser@6.7.1": version "6.7.1" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.7.1.tgz#e01144a08984a486ecc91d7922cc457e9c9bd6b7" @@ -1321,6 +1295,14 @@ dependencies: "@babel/types" "^7.3.0" +"@types/body-parser@*": + version "1.19.0" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" + integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ== + dependencies: + "@types/connect" "*" + "@types/node" "*" + "@types/byline@^4.2.33": version "4.2.33" resolved "https://registry.yarnpkg.com/@types/byline/-/byline-4.2.33.tgz#001f504f4353b84c503e74da0ed9bdf291484af2" @@ -1383,6 +1365,21 @@ dependencies: "@types/color-convert" "*" +"@types/connect-history-api-fallback@*": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.3.tgz#4772b79b8b53185f0f4c9deab09236baf76ee3b4" + integrity sha512-7SxFCd+FLlxCfwVwbyPxbR4khL9aNikJhrorw8nUIOqeuooc9gifBuDQOJw5kzN7i6i3vLn9G8Wde/4QDihpYw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.33" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546" + integrity sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A== + dependencies: + "@types/node" "*" + "@types/crypto-js@^3.1.47": version "3.1.47" resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-3.1.47.tgz#36e549dd3f1322742a3a738e7c113ebe48221860" @@ -1407,26 +1404,24 @@ resolved "https://registry.yarnpkg.com/@types/electron-devtools-installer/-/electron-devtools-installer-2.2.0.tgz#32ee4ebbe99b3daf9847a6d2097dc00b5de94f10" integrity sha512-HJNxpaOXuykCK4rQ6FOMxAA0NLFYsf7FiPFGmab0iQmtVBHSAfxzy3MRFpLTTDDWbV0yD2YsHOQvdu8yCqtCfw== -"@types/eslint-scope@^3.7.0": - version "3.7.3" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" - integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== +"@types/express-serve-static-core@*": + version "4.17.13" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz#d9af025e925fc8b089be37423b8d1eac781be084" + integrity sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA== dependencies: - "@types/eslint" "*" - "@types/estree" "*" + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" -"@types/eslint@*": - version "8.4.0" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.0.tgz#95712d5b32fd99a0d9493c31c6197ea7471c3ba6" - integrity sha512-JUYa/5JwoqikCy7O7jKtuNe9Z4ZZt615G+1EKfaDGSNEpzaA2OwbV/G1v08Oa7fd1XzlFoSCvt9ePl9/6FyAug== +"@types/express@*": + version "4.17.8" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.8.tgz#3df4293293317e61c60137d273a2e96cd8d5f27a" + integrity sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ== dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*", "@types/estree@^0.0.50": - version "0.0.50" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" - integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/qs" "*" + "@types/serve-static" "*" "@types/fs-extra@^9.0.11", "@types/fs-extra@^9.0.13": version "9.0.13" @@ -1468,10 +1463,10 @@ "@types/react" "*" hoist-non-react-statics "^3.3.0" -"@types/html-minifier-terser@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" - integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== +"@types/html-minifier-terser@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.0.tgz#551a4589b6ee2cc9c1dff08056128aec29b94880" + integrity sha512-iYCgjm1dGPRuo12+BStjd1HiVQqhlRhWDOQigNxn023HcjnhsiFz9pc6CzJj4HwDCSQca9bxTL4PxJDbkdm3PA== "@types/html-minifier@*": version "3.5.3" @@ -1496,7 +1491,7 @@ resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz#9140779736aa2655635ee756e2467d787cfe8a2a" integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== -"@types/http-proxy@^1.17.7": +"@types/http-proxy@^1.17.5", "@types/http-proxy@^1.17.7": version "1.17.7" resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.7.tgz#30ea85cc2c868368352a37f0d0d3581e24834c6f" integrity sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w== @@ -1544,12 +1539,12 @@ "@types/parse5" "*" "@types/tough-cookie" "*" -"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@^7.0.4", "@types/json-schema@^7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== -"@types/json-schema@^7.0.5": +"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": version "7.0.7" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== @@ -1586,12 +1581,17 @@ resolved "https://registry.yarnpkg.com/@types/md5-file/-/md5-file-4.0.2.tgz#c7241e88f4aa17218c774befb0fc34f33f21fe36" integrity sha512-8gacRfEqLrmZ6KofpFfxyjsm/LYepeWUWUJGaf5A9W9J5B2/dRZMdkDqFDL6YDa9IweH12IO76jO7mpsK2B3wg== -"@types/mini-css-extract-plugin@^2.4.0": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.1.tgz#c2ab735b353864019a148251e699b7038443bc77" - integrity sha512-evjjtJttaUexgg3au9ZJFy76tV9mySwX3a4Jl82BuormBYluWLRt0xk2urWrhOdPgDWzulRFyotwYOJTmkSgKw== +"@types/mime@*": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.3.tgz#c893b73721db73699943bfc3653b1deb7faa4a3a" + integrity sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q== + +"@types/mini-css-extract-plugin@^0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.1.tgz#d4bdde5197326fca039d418f4bdda03dc74dc451" + integrity sha512-+mN04Oszdz9tGjUP/c1ReVwJXxSniLd7lF++sv+8dkABxVNthg6uccei+4ssKxRHGoMmPxdn7uBdJWONSJGTGQ== dependencies: - mini-css-extract-plugin "*" + "@types/webpack" "*" "@types/minimatch@*": version "3.0.3" @@ -1670,6 +1670,21 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.1.tgz#b6e98083f13faa1e5231bfa3bdb1b0feff536b6d" integrity sha512-boy4xPNEtiw6N3abRhBi/e7hNvy3Tt8E9ZRAQrwAGzoCGZS/1wjo9KY7JHhnfnEsG5wSjDbymCozUM9a3ea7OQ== +"@types/progress-bar-webpack-plugin@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@types/progress-bar-webpack-plugin/-/progress-bar-webpack-plugin-2.1.2.tgz#1097946f06efcc087fb2563b153ee61240d9e1dd" + integrity sha512-zSmm7M96PAwwD/YZp7ML9KOtfaRRC2HcU8mrddySWLlSpIGQPynVoc7V97lS0U4tIxlXl02FDQbLSzZq52BEAg== + dependencies: + "@types/progress" "*" + "@types/webpack" "^4" + +"@types/progress@*": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/progress/-/progress-2.0.3.tgz#7ccbd9c6d4d601319126c469e73b5bb90dfc8ccc" + integrity sha512-bPOsfCZ4tsTlKiBjBhKnM8jpY5nmIll166IPD58D92hR7G7kZDfx5iB9wGF4NfZrdKolebjeAr3GouYkSGoJ/A== + dependencies: + "@types/node" "*" + "@types/prop-types@*": version "15.7.3" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" @@ -1682,11 +1697,21 @@ dependencies: "@types/retry" "*" +"@types/qs@*": + version "6.9.5" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b" + integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ== + "@types/randomcolor@^0.5.6": version "0.5.6" resolved "https://registry.yarnpkg.com/@types/randomcolor/-/randomcolor-0.5.6.tgz#c1085077c4ae0f6af60e0ad229d14721b9b3b58c" integrity sha512-lKkW8DGUQpZldTrwa+HM5rY+7eTyaHOMTsnj9ewt7AAwXuMPwBmkLlfh8+SXdgOhBW9iNI4x4zRjQ/TQZkdycQ== +"@types/range-parser@*": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" + integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== + "@types/react-beautiful-dnd@^13.1.2": version "13.1.2" resolved "https://registry.yarnpkg.com/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz#510405abb09f493afdfd898bf83995dc6385c130" @@ -1835,6 +1860,14 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.9.tgz#152c6c20a7688c30b967ec1841d31ace569863fc" integrity sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ== +"@types/serve-static@*": + version "1.13.6" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.6.tgz#866b1b8dec41c36e28c7be40ac725b88be43c5c1" + integrity sha512-nuRJmv7jW7VmCVTn+IgYDkkbbDGyIINOeu/G0d74X3lm6E5KfMeQPJhxIt1ayQeQB3cSxvYs1RA/wipYoFB4EA== + dependencies: + "@types/mime" "*" + "@types/node" "*" + "@types/sharp@^0.29.4": version "0.29.4" resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.29.4.tgz#e47d8677befc9944d4b9d76ed837452814166de0" @@ -1866,7 +1899,7 @@ dependencies: "@types/node" "*" -"@types/tapable@^1": +"@types/tapable@^1", "@types/tapable@^1.0.5": version "1.0.8" resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.8.tgz#b94a4391c85666c7b73299fd3ad79d4faa435310" integrity sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ== @@ -1940,18 +1973,28 @@ resolved "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.4.tgz#805c0612b3a0c124cf99f517364142946b74ba3b" integrity sha512-OjJdqx6QlbyZw9LShPwRW+Kmiegeg3eWNI41MQQKaG3vjdU2L9SRElntM51HmHBY1cu7izxQJ1lMYioQh3XMBg== +"@types/webpack-dev-server@^3.11.6": + version "3.11.6" + resolved "https://registry.yarnpkg.com/@types/webpack-dev-server/-/webpack-dev-server-3.11.6.tgz#d8888cfd2f0630203e13d3ed7833a4d11b8a34dc" + integrity sha512-XCph0RiiqFGetukCTC3KVnY1jwLcZ84illFRMbyFzCcWl90B/76ew0tSqF46oBhnLC4obNDG7dMO0JfTN0MgMQ== + dependencies: + "@types/connect-history-api-fallback" "*" + "@types/express" "*" + "@types/serve-static" "*" + "@types/webpack" "^4" + http-proxy-middleware "^1.0.0" + "@types/webpack-env@^1.16.3": version "1.16.3" resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.16.3.tgz#b776327a73e561b71e7881d0cd6d34a1424db86a" integrity sha512-9gtOPPkfyNoEqCQgx4qJKkuNm/x0R2hKR7fdl7zvTJyHnIisuE/LfvXOsYWL0o3qq6uiBnKZNNNzi3l0y/X+xw== -"@types/webpack-node-externals@^2.5.3": - version "2.5.3" - resolved "https://registry.yarnpkg.com/@types/webpack-node-externals/-/webpack-node-externals-2.5.3.tgz#921783aadda1fe686db0a70e20e4b9548b5a3cef" - integrity sha512-A9JxaR8QXoYT95egET4AmCFuChyTlP8d18ZAnmSHuIMsFdS7QlCQQ8pmN/+FHgLIkm+ViE/VngltT5avLACY9A== +"@types/webpack-node-externals@^1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@types/webpack-node-externals/-/webpack-node-externals-1.7.1.tgz#73d0d7ae0e98cfbd69b7443388302cd69217494a" + integrity sha512-kbO2gYPKvMb5j1KOgnIuUH52CKul9Ud4b10J5n+JX8oHmgu86hYpBVfrV4bMDe5lhCaO64h8QrKz7WnRZzqkbA== dependencies: - "@types/node" "*" - webpack "^5" + "@types/webpack" "*" "@types/webpack-sources@*": version "1.4.0" @@ -1962,7 +2005,7 @@ "@types/source-list-map" "*" source-map "^0.7.3" -"@types/webpack@^4": +"@types/webpack@*", "@types/webpack@^4", "@types/webpack@^4.41.32", "@types/webpack@^4.41.8": version "4.41.32" resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.32.tgz#a7bab03b72904070162b2f169415492209e94212" integrity sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg== @@ -1974,15 +2017,6 @@ anymatch "^3.0.0" source-map "^0.6.0" -"@types/webpack@^5.28.0": - version "5.28.0" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-5.28.0.tgz#78dde06212f038d77e54116cfe69e88ae9ed2c03" - integrity sha512-8cP0CzcxUiFuA9xGJkfeVpqmWTk9nx6CWwamRGCj95ph1SmlRRk9KlCZ6avhCbZd4L68LvYT6l1kpdEnQXrF8w== - dependencies: - "@types/node" "*" - tapable "^2.2.0" - webpack "^5" - "@types/ws@^6.0.1": version "6.0.4" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-6.0.4.tgz#7797707c8acce8f76d8c34b370d4645b70421ff1" @@ -2023,13 +2057,14 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.7.0.tgz#12d54709f8ea1da99a01d8a992cd0474ad0f0aa9" - integrity sha512-8RTGBpNn5a9M628wBPrCbJ+v3YTEOE2qeZb7TDkGKTDXSj36KGRg92SpFFaR/0S3rSXQxM0Og/kV9EyadsYSBg== +"@typescript-eslint/eslint-plugin@^5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.1.tgz#870195d0f2146b36d11fc71131b75aba52354c69" + integrity sha512-xN3CYqFlyE/qOcy978/L0xLR2HlcAGIyIK5sMOasxaaAPfQRj/MmMV6OC3I7NZO84oEUdWCOju34Z9W8E0pFDQ== dependencies: - "@typescript-eslint/experimental-utils" "5.7.0" - "@typescript-eslint/scope-manager" "5.7.0" + "@typescript-eslint/scope-manager" "5.10.1" + "@typescript-eslint/type-utils" "5.10.1" + "@typescript-eslint/utils" "5.10.1" debug "^4.3.2" functional-red-black-tree "^1.0.1" ignore "^5.1.8" @@ -2037,199 +2072,215 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.7.0.tgz#2b1633e6613c3238036156f70c32634843ad034f" - integrity sha512-u57eZ5FbEpzN5kSjmVrSesovWslH2ZyNPnaXQMXWgH57d5+EVHEt76W75vVuI9qKZ5BMDKNfRN+pxcPEjQjb2A== +"@typescript-eslint/parser@^5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.10.1.tgz#4ce9633cc33fc70bc13786cb793c1a76fe5ad6bd" + integrity sha512-GReo3tjNBwR5RnRO0K2wDIDN31cM3MmDtgyQ85oAxAmC5K3j/g85IjP+cDfcqDsDDBf1HNKQAD0WqOYL8jXqUA== dependencies: - "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.7.0" - "@typescript-eslint/types" "5.7.0" - "@typescript-eslint/typescript-estree" "5.7.0" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - -"@typescript-eslint/parser@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.7.0.tgz#4dca6de463d86f02d252e681136a67888ea3b181" - integrity sha512-m/gWCCcS4jXw6vkrPQ1BjZ1vomP01PArgzvauBqzsoZ3urLbsRChexB8/YV8z9HwE3qlJM35FxfKZ1nfP/4x8g== - dependencies: - "@typescript-eslint/scope-manager" "5.7.0" - "@typescript-eslint/types" "5.7.0" - "@typescript-eslint/typescript-estree" "5.7.0" + "@typescript-eslint/scope-manager" "5.10.1" + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/typescript-estree" "5.10.1" debug "^4.3.2" -"@typescript-eslint/scope-manager@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.7.0.tgz#70adf960e5a58994ad50438ba60d98ecadd79452" - integrity sha512-7mxR520DGq5F7sSSgM0HSSMJ+TFUymOeFRMfUfGFAVBv8BR+Jv1vHgAouYUvWRZeszVBJlLcc9fDdktxb5kmxA== +"@typescript-eslint/scope-manager@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.10.1.tgz#f0539c73804d2423506db2475352a4dec36cd809" + integrity sha512-Lyvi559Gvpn94k7+ElXNMEnXu/iundV5uFmCUNnftbFrUbAJ1WBoaGgkbOBm07jVZa682oaBU37ao/NGGX4ZDg== dependencies: - "@typescript-eslint/types" "5.7.0" - "@typescript-eslint/visitor-keys" "5.7.0" + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/visitor-keys" "5.10.1" -"@typescript-eslint/types@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.7.0.tgz#2d4cae0105ba7d08bffa69698197a762483ebcbe" - integrity sha512-5AeYIF5p2kAneIpnLFve8g50VyAjq7udM7ApZZ9JYjdPjkz0LvODfuSHIDUVnIuUoxafoWzpFyU7Sqbxgi79mA== - -"@typescript-eslint/typescript-estree@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.7.0.tgz#968fad899050ccce4f08a40cd5fabc0798525006" - integrity sha512-aO1Ql+izMrTnPj5aFFlEJkpD4jRqC4Gwhygu2oHK2wfVQpmOPbyDSveJ+r/NQo+PWV43M6uEAeLVbTi09dFLhg== +"@typescript-eslint/type-utils@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.10.1.tgz#5e526c00142585e40ab1503e83f1ff608c367405" + integrity sha512-AfVJkV8uck/UIoDqhu+ptEdBoQATON9GXnhOpPLzkQRJcSChkvD//qsz9JVffl2goxX+ybs5klvacE9vmrQyCw== dependencies: - "@typescript-eslint/types" "5.7.0" - "@typescript-eslint/visitor-keys" "5.7.0" + "@typescript-eslint/utils" "5.10.1" + debug "^4.3.2" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.10.1.tgz#dca9bd4cb8c067fc85304a31f38ec4766ba2d1ea" + integrity sha512-ZvxQ2QMy49bIIBpTqFiOenucqUyjTQ0WNLhBM6X1fh1NNlYAC6Kxsx8bRTY3jdYsYg44a0Z/uEgQkohbR0H87Q== + +"@typescript-eslint/typescript-estree@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.1.tgz#b268e67be0553f8790ba3fe87113282977adda15" + integrity sha512-PwIGnH7jIueXv4opcwEbVGDATjGPO1dx9RkUl5LlHDSe+FXxPwFL5W/qYd5/NHr7f6lo/vvTrAzd0KlQtRusJQ== + dependencies: + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/visitor-keys" "5.10.1" debug "^4.3.2" globby "^11.0.4" is-glob "^4.0.3" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/visitor-keys@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.7.0.tgz#e05164239eb7cb8aa9fa06c516ede480ce260178" - integrity sha512-hdohahZ4lTFcglZSJ3DGdzxQHBSxsLVqHzkiOmKi7xVAWC4y2c1bIMKmPJSrA4aOEoRUPOKQ87Y/taC7yVHpFg== +"@typescript-eslint/utils@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.10.1.tgz#fa682a33af47080ba2c4368ee0ad2128213a1196" + integrity sha512-RRmlITiUbLuTRtn/gcPRi4202niF+q7ylFLCKu4c+O/PcpRvZ/nAUwQ2G00bZgpWkhrNLNnvhZLbDn8Ml0qsQw== dependencies: - "@typescript-eslint/types" "5.7.0" + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.10.1" + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/typescript-estree" "5.10.1" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.1.tgz#29102de692f59d7d34ecc457ed59ab5fc558010b" + integrity sha512-NjQ0Xinhy9IL979tpoTRuLKxMc0zJC7QVSdeerXs2/QvOy2yRkzX5dRb10X5woNUdJgU8G3nYRDlI33sq1K4YQ== + dependencies: + "@typescript-eslint/types" "5.10.1" eslint-visitor-keys "^3.0.0" -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@xtuc/long" "4.2.2" + "@webassemblyjs/wast-printer" "1.9.0" -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/ast" "1.9.0" -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== + +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== dependencies: - "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" "@xtuc/long" "4.2.2" -"@webpack-cli/configtest@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.1.0.tgz#8342bef0badfb7dfd3b576f2574ab80c725be043" - integrity sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg== - -"@webpack-cli/info@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.4.0.tgz#b9179c3227ab09cbbb149aa733475fcf99430223" - integrity sha512-F6b+Man0rwE4n0409FyAJHStYA5OIZERxmnUfLVwv0mc0V1wLad3V7jqRlMkgKBeAq07jUvglacNaa6g9lOpuw== +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== dependencies: - envinfo "^7.7.3" - -"@webpack-cli/serve@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.6.0.tgz#2c275aa05c895eccebbfc34cfb223c6e8bd591a2" - integrity sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA== + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": version "1.2.0" @@ -2266,6 +2317,14 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + acorn-globals@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" @@ -2274,11 +2333,6 @@ acorn-globals@^6.0.0: acorn "^7.1.1" acorn-walk "^7.1.1" -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== - acorn-jsx@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -2303,7 +2357,12 @@ acorn-walk@^8.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0: +acorn@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" + integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== + +acorn@^7.0.0, acorn@^7.1.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== @@ -2313,6 +2372,11 @@ acorn@^8.2.4, acorn@^8.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2" integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q== +acorn@^8.7.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + agent-base@4, agent-base@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" @@ -2349,26 +2413,17 @@ aggregate-error@^3.0.0, aggregate-error@^3.1.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== -ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv-keywords@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" - integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== - dependencies: - fast-deep-equal "^3.1.3" - -ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.5.5: +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.5.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2378,26 +2433,6 @@ ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.8.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.9.0.tgz#738019146638824dea25edcf299dcba1b0e7eb18" - integrity sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -ajv@^8.0.1: - version "8.6.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.3.tgz#11a66527761dc3e9a3845ea775d2d3c0414e8764" - integrity sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - ansi-align@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" @@ -2412,7 +2447,7 @@ ansi-align@^3.0.0: dependencies: string-width "^3.0.0" -ansi-colors@^3.2.1: +ansi-colors@^3.0.0: version "3.2.4" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== @@ -2424,6 +2459,16 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.11.0" +ansi-html-community@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + +ansi-html@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" + integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -2456,7 +2501,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== @@ -2464,13 +2509,6 @@ ansi-styles@^4.0.0: "@types/color-name" "^1.1.1" color-convert "^2.0.1" -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - ansi-styles@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" @@ -2616,6 +2654,16 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-flatten@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + array-includes@^3.1.1, array-includes@^3.1.4: version "3.1.4" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" @@ -2627,11 +2675,23 @@ array-includes@^3.1.1, array-includes@^3.1.4: get-intrinsic "^1.1.1" is-string "^1.0.7" +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= + dependencies: + array-uniq "^1.0.1" + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -2672,6 +2732,15 @@ asar@^3.0.3: optionalDependencies: "@types/glob" "^7.1.1" +asn1.js@^4.0.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -2684,26 +2753,46 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== async-exit-hook@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3" integrity sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw== +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + async@0.9.x: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= +async@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + async@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" @@ -2880,6 +2969,11 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= + bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -2909,11 +3003,23 @@ bin-links@^1.1.2, bin-links@^1.1.8: npm-normalize-package-bin "^1.0.0" write-file-atomic "^2.3.0" +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + binary-extensions@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + bl@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" @@ -2935,7 +3041,45 @@ bluebird@^3.4.7, bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3. resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -boolbase@^1.0.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.2.tgz#c9686902d3c9a27729f43ab10f9d79c2004da7b0" + integrity sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA== + +body-parser@1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + bytes "3.1.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.7.2" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" + +bonjour@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" + integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= + dependencies: + array-flatten "^2.1.0" + deep-equal "^1.0.1" + dns-equal "^1.0.0" + dns-txt "^2.0.2" + multicast-dns "^6.0.1" + multicast-dns-service-types "^1.1.0" + +boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= @@ -2980,7 +3124,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1: +braces@^2.3.1, braces@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== @@ -3003,21 +3147,76 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + browser-process-hrtime@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserslist@^4.14.5: - version "4.19.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" - integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: - caniuse-lite "^1.0.30001286" - electron-to-chromium "^1.4.17" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.0.tgz#545d0b1b07e6b2c99211082bf1b12cce7a0b0e11" + integrity sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.2" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" bs-logger@0.x: version "0.2.6" @@ -3066,6 +3265,25 @@ buffer-from@1.x, buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +buffer-indexof@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" + integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^4.3.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + buffer@^5.1.0, buffer@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" @@ -3103,6 +3321,11 @@ builder-util@22.14.5: stat-mode "^1.0.0" temp-file "^3.4.0" +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" @@ -3118,6 +3341,16 @@ byte-size@^5.0.1: resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-5.0.1.tgz#4b651039a5ecd96767e71a3d7ed380e48bed4191" integrity sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw== +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + cacache@^12.0.0, cacache@^12.0.2, cacache@^12.0.3: version "12.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" @@ -3211,13 +3444,13 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camel-case@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" - integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== +camel-case@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547" + integrity sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q== dependencies: - pascal-case "^3.1.2" - tslib "^2.0.3" + pascal-case "^3.1.1" + tslib "^1.10.0" camelcase-css@^2.0.1: version "2.0.1" @@ -3244,11 +3477,6 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== -caniuse-lite@^1.0.30001286: - version "1.0.30001300" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001300.tgz#11ab6c57d3eb6f964cba950401fd00a146786468" - integrity sha512-cVjiJHWGcNlJi8TZVKNMnvMid3Z3TTdDHmLDzlOdIiZq138Exvo0G+G0wTdVYolxKb4AYwC+38pxodiInVtJSA== - capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -3266,7 +3494,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3319,7 +3547,7 @@ chartjs-color@^2.1.0: chartjs-color-string "^0.6.0" color-convert "^1.9.3" -"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.3, chokidar@^3.5.2: +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.1, chokidar@^3.4.3, chokidar@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== @@ -3334,20 +3562,24 @@ chartjs-color@^2.1.0: optionalDependencies: fsevents "~2.3.2" -chokidar@^3.4.2: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== +chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== dependencies: - anymatch "~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" + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" optionalDependencies: - fsevents "~2.3.2" + fsevents "^1.2.7" chownr@^1.1.1, chownr@^1.1.2, chownr@^1.1.4: version "1.1.4" @@ -3393,6 +3625,14 @@ cidr-regex@^2.0.10: dependencies: ip-regex "^2.1.0" +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + circular-dependency-plugin@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/circular-dependency-plugin/-/circular-dependency-plugin-5.2.2.tgz#39e836079db1d3cf2f988dc48c5188a44058b600" @@ -3413,10 +3653,10 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -clean-css@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.2.tgz#d3a7c6ee2511011e051719838bdcf8314dc4548d" - integrity sha512-/eR8ru5zyxKzpBLv9YZvMXgTSSQn7AdkMItMYynsFgGwTveCRVam9IUPFloE85B4vAIj05IuKmmEoV7/AQjT0w== +clean-css@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" + integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== dependencies: source-map "~0.6.0" @@ -3497,15 +3737,6 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" @@ -3610,11 +3841,6 @@ color@^4.0.1: color-convert "^2.0.1" color-string "^1.6.0" -colorette@^2.0.14: - version "2.0.16" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" - integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== - colors@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" @@ -3660,21 +3886,26 @@ commander@^2.20.0, commander@~2.20.3: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + commander@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== -commander@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commander@^8.2.0, commander@^8.3.0: +commander@^8.2.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + compare-version@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/compare-version/-/compare-version-0.1.2.tgz#0162ec2d9351f5ddd59a9202cba935366a725080" @@ -3685,6 +3916,26 @@ component-emitter@^1.2.1: resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -3763,11 +4014,38 @@ configstore@^5.0.1: write-file-atomic "^3.0.0" xdg-basedir "^4.0.0" +connect-history-api-fallback@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" + integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +content-disposition@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" @@ -3775,6 +4053,16 @@ convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, dependencies: safe-buffer "~5.1.1" +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + cookie@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" @@ -3853,6 +4141,14 @@ crc@^3.8.0: dependencies: buffer "^5.1.0" +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + create-error-class@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" @@ -3860,6 +4156,29 @@ create-error-class@^3.0.0: dependencies: capture-stack-trace "^1.0.0" +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -3881,7 +4200,7 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.0: +cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -3901,6 +4220,23 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + crypto-js@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" @@ -3923,18 +4259,20 @@ css-box-model@^1.2.0: dependencies: tiny-invariant "^1.0.6" -css-loader@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.5.1.tgz#0c43d4fbe0d97f699c91e9818cb585759091d1b1" - integrity sha512-gEy2w9AnJNnD9Kuo4XAP9VflW/ujKoS9c/syO+uWMlm5igc7LysKzPXaDoR2vroROkSwsTS2tGr1yGGEbZOYZQ== +css-loader@^5.2.7: + version "5.2.7" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.7.tgz#9b9f111edf6fb2be5dc62525644cbc9c232064ae" + integrity sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg== dependencies: icss-utils "^5.1.0" + loader-utils "^2.0.0" postcss "^8.2.15" 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.1.0" + schema-utils "^3.0.0" semver "^7.3.5" css-parse@~2.0.0: @@ -3944,16 +4282,15 @@ css-parse@~2.0.0: dependencies: css "^2.0.0" -css-select@^4.1.3: - version "4.2.1" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" - integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== +css-select@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= dependencies: - boolbase "^1.0.0" - css-what "^5.1.0" - domhandler "^4.3.0" - domutils "^2.8.0" - nth-check "^2.0.1" + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" css-selector-tokenizer@^0.7.0: version "0.7.3" @@ -3971,10 +4308,10 @@ css-vendor@^2.0.8: "@babel/runtime" "^7.8.3" is-in-browser "^1.0.2" -css-what@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== +css-what@2.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== css.escape@^1.5.1: version "1.5.1" @@ -4070,6 +4407,13 @@ debounce-fn@^4.0.0: dependencies: mimic-fn "^3.0.0" +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + debug@3.1.0, debug@~3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -4077,7 +4421,7 @@ debug@3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== @@ -4091,14 +4435,7 @@ debug@4.3.1: dependencies: ms "2.1.2" -debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: +debug@^3.1.0, debug@^3.1.1, debug@^3.2.6, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -4139,6 +4476,18 @@ decompress-response@^6.0.0: dependencies: mimic-response "^3.1.0" +deep-equal@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -4162,6 +4511,14 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +default-gateway@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" + integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== + dependencies: + execa "^1.0.0" + ip-regex "^2.1.0" + default-shell@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/default-shell/-/default-shell-1.0.1.tgz#752304bddc6174f49eb29cb988feea0b8813c8bc" @@ -4218,6 +4575,19 @@ defined@^1.0.0: resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= +del@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" + integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== + dependencies: + "@types/glob" "^7.1.1" + globby "^6.1.0" + is-path-cwd "^2.0.0" + is-path-in-cwd "^2.0.0" + p-map "^2.0.0" + pify "^4.0.1" + rimraf "^2.6.3" + del@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" @@ -4242,6 +4612,29 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + detect-indent@~5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" @@ -4299,6 +4692,15 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + dir-compare@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-2.4.0.tgz#785c41dc5f645b34343a4eafc50b79bac7f11631" @@ -4350,6 +4752,26 @@ dmg-license@^1.0.9: smart-buffer "^4.0.2" verror "^1.10.0" +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= + +dns-packet@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" + integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== + dependencies: + ip "^1.1.0" + safe-buffer "^5.0.1" + +dns-txt@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" + integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= + dependencies: + buffer-indexof "^1.0.0" + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -4369,7 +4791,7 @@ dom-accessibility-api@^0.5.4, dom-accessibility-api@^0.5.6: resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.9.tgz#915f8531ba29a50e5c29389dbfb87a9642fef0d6" integrity sha512-+KPF4o71fl6NrdnqIrJc6m44NA+Rhf1h7In2MRznejSQasWkjqmHOBUlk+pXJ77cVOSYyZeNHFwn/sjotB6+Sw== -dom-converter@^0.2.0: +dom-converter@^0.2: version "0.2.0" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== @@ -4384,25 +4806,29 @@ dom-helpers@^5.0.1: "@babel/runtime" "^7.8.7" csstype "^2.6.7" -dom-serializer@^1.0.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== +dom-serializer@0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== dependencies: domelementtype "^2.0.1" - domhandler "^4.2.0" entities "^2.0.0" +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +domelementtype@1, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + domelementtype@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== -domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - domexception@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" @@ -4410,34 +4836,41 @@ domexception@^2.0.1: dependencies: webidl-conversions "^5.0.0" -domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" - integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== dependencies: - domelementtype "^2.2.0" + domelementtype "1" dompurify@^2.3.4: version "2.3.4" resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.4.tgz#1cf5cf0105ccb4debdf6db162525bd41e6ddacc6" integrity sha512-6BVcgOAVFXjI0JTjEvZy901Rghm+7fDQOrNIcxB4+gdhj6Kwp6T9VBhBY/AbagKHJocRkDYGd6wvI+p4/10xtQ== -domutils@^2.5.2, domutils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== +domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" + dom-serializer "0" + domelementtype "1" -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== +domutils@^1.5.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== dependencies: - no-case "^3.0.4" - tslib "^2.0.3" + dom-serializer "0" + domelementtype "1" + +dot-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa" + integrity sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA== + dependencies: + no-case "^3.0.3" + tslib "^1.10.0" dot-prop@^4.2.1: version "4.2.1" @@ -4501,6 +4934,11 @@ editor@~1.0.0: resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742" integrity sha1-YMf4e9YrzGqJT6jM1q+3gjok90I= +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + ejs@^3.1.6: version "3.1.6" resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a" @@ -4569,11 +5007,6 @@ electron-publish@22.14.5: lazy-val "^1.0.5" mime "^2.5.2" -electron-to-chromium@^1.4.17: - version "1.4.49" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.49.tgz#5b6a3dc032590beef4be485a4b0b3fe7d0e3dfd7" - integrity sha512-k/0t1TRfonHIp8TJKfjBu2cKj8MqYTiEpOhci+q7CVEE5xnCQnx1pTa+V8b/sdhe4S3PR4p4iceEQWhGrKQORQ== - electron-updater@^4.6.1: version "4.6.1" resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.6.1.tgz#80ca805c4f51b2e682aac29d18fed75d6a533d32" @@ -4605,6 +5038,19 @@ electron@^14.2.4: "@types/node" "^14.6.2" extract-zip "^1.0.3" +elliptic@^6.0.0, elliptic@^6.5.2: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + emittery@^0.7.1: version "0.7.2" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.2.tgz#25595908e13af0f5674ab419396e2fb394cdfa82" @@ -4635,7 +5081,7 @@ enabled@2.0.x: resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== -encodeurl@^1.0.2: +encodeurl@^1.0.2, encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= @@ -4654,20 +5100,19 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enhanced-resolve@^5.0.0, enhanced-resolve@^5.8.3: - version "5.8.3" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" - integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== +enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.1, enhanced-resolve@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" + integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" -enquirer@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.5.tgz#3ab2b838df0a9d8ab9e7dff235b0e8712ef92381" - integrity sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA== - dependencies: - ansi-colors "^3.2.1" +entities@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== entities@^2.0.0: version "2.0.3" @@ -4679,11 +5124,6 @@ env-paths@^2.2.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== -envinfo@^7.7.3: - version "7.8.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" - integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== - err-code@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" @@ -4696,7 +5136,7 @@ errno@^0.1.1: dependencies: prr "~1.0.1" -errno@~0.1.7: +errno@^0.1.3, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== @@ -4710,6 +5150,13 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error-stack-parser@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" + integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ== + dependencies: + stackframe "^1.1.1" + es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: version "1.17.5" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" @@ -4727,6 +5174,24 @@ es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: string.prototype.trimleft "^2.1.1" string.prototype.trimright "^2.1.1" +es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + es-abstract@^1.19.0, es-abstract@^1.19.1: version "1.19.1" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" @@ -4753,11 +5218,6 @@ es-abstract@^1.19.0, es-abstract@^1.19.1: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== - es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -4789,126 +5249,67 @@ esbuild-android-arm64@0.13.15: resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.15.tgz#3fc3ff0bab76fe35dd237476b5d2b32bb20a3d44" integrity sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg== -esbuild-android-arm64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.14.tgz#3705f32f209deeb11c275af47c298c8783dd5f0c" - integrity sha512-be/Uw6DdpQiPfula1J4bdmA+wtZ6T3BRCZsDMFB5X+k0Gp8TIh9UvmAcqvKNnbRAafSaXG3jPCeXxDKqnc8hFQ== - esbuild-darwin-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.15.tgz#8e9169c16baf444eacec60d09b24d11b255a8e72" integrity sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ== -esbuild-darwin-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.14.tgz#c07e4eae6d938300a2d330ea82494c55bcea84e5" - integrity sha512-BEexYmjWafcISK8cT6O98E3TfcLuZL8DKuubry6G54n2+bD4GkoRD6HYUOnCkfl2p7jodA+s4369IjSFSWjtHg== - esbuild-darwin-arm64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.15.tgz#1b07f893b632114f805e188ddfca41b2b778229a" integrity sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ== -esbuild-darwin-arm64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.14.tgz#a8631e13a51a6f784fb0906e2a64c6ab53988755" - integrity sha512-tnBKm41pDOB1GtZ8q/w26gZlLLRzVmP8fdsduYjvM+yFD7E2DLG4KbPAqFMWm4Md9B+DitBglP57FY7AznxbTg== - esbuild-freebsd-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.15.tgz#0b8b7eca1690c8ec94c75680c38c07269c1f4a85" integrity sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA== -esbuild-freebsd-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.14.tgz#c280c2b944746b27ee6c6487c2691865c90bed2e" - integrity sha512-Q9Rx6sgArOHalQtNwAaIzJ6dnQ8A+I7f/RsQsdkS3JrdzmnlFo8JEVofTmwVQLoIop7OKUqIVOGP4PoQcwfVMA== - esbuild-freebsd-arm64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.15.tgz#2e1a6c696bfdcd20a99578b76350b41db1934e52" integrity sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ== -esbuild-freebsd-arm64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.14.tgz#aa4e21276efcf20e5ab2487e91ca1d789573189b" - integrity sha512-TJvq0OpLM7BkTczlyPIphcvnwrQwQDG1HqxzoYePWn26SMUAlt6wrLnEvxdbXAvNvDLVzG83kA+JimjK7aRNBA== - esbuild-linux-32@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.15.tgz#6fd39f36fc66dd45b6b5f515728c7bbebc342a69" integrity sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g== -esbuild-linux-32@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.14.tgz#3db4d929239203ce38a9060d5419ac6a6d28846c" - integrity sha512-h/CrK9Baimt5VRbu8gqibWV7e1P9l+mkanQgyOgv0Ng3jHT1NVFC9e6rb1zbDdaJVmuhWX5xVliUA5bDDCcJeg== - esbuild-linux-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.15.tgz#9cb8e4bcd7574e67946e4ee5f1f1e12386bb6dd3" integrity sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA== -esbuild-linux-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.14.tgz#f880026254c1f565a7a10fdebb7cff9b083a127d" - integrity sha512-IC+wAiIg/egp5OhQp4W44D9PcBOH1b621iRn1OXmlLzij9a/6BGr9NMIL4CRwz4j2kp3WNZu5sT473tYdynOuQ== - esbuild-linux-arm64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.15.tgz#3891aa3704ec579a1b92d2a586122e5b6a2bfba1" integrity sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA== -esbuild-linux-arm64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.14.tgz#a34bc3076e50b109c3b8c8bad9c146e35942322b" - integrity sha512-6QVul3RI4M5/VxVIRF/I5F+7BaxzR3DfNGoqEVSCZqUbgzHExPn+LXr5ly1C7af2Kw4AHpo+wDqx8A4ziP9avw== - esbuild-linux-arm@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.15.tgz#8a00e99e6a0c6c9a6b7f334841364d8a2b4aecfe" integrity sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA== -esbuild-linux-arm@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.14.tgz#231ffd12fef69ee06365d4c94b69850e4830e927" - integrity sha512-gxpOaHOPwp7zSmcKYsHrtxabScMqaTzfSQioAMUaB047YiMuDBzqVcKBG8OuESrYkGrL9DDljXr/mQNg7pbdaQ== - esbuild-linux-mips64le@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.15.tgz#36b07cc47c3d21e48db3bb1f4d9ef8f46aead4f7" integrity sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg== -esbuild-linux-mips64le@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.14.tgz#bd00570e3a30422224b732c7a5f262146c357403" - integrity sha512-4Jl5/+xoINKbA4cesH3f4R+q0vltAztZ6Jm8YycS8lNhN1pgZJBDxWfI6HUMIAdkKlIpR1PIkA9aXQgZ8sxFAg== - esbuild-linux-ppc64le@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.15.tgz#f7e6bba40b9a11eb9dcae5b01550ea04670edad2" integrity sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ== -esbuild-linux-ppc64le@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.14.tgz#430609413fd9e04d9def4e3f06726b031b23d825" - integrity sha512-BitW37GxeebKxqYNl4SVuSdnIJAzH830Lr6Mkq3pBHXtzQay0vK+IeOR/Ele1GtNVJ+/f8wYM53tcThkv5SC5w== - -esbuild-linux-s390x@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.14.tgz#2f0d8cbfe53cf3cb97f6372549a41a8051dbd689" - integrity sha512-vLj6p76HOZG3wfuTr5MyO3qW5iu8YdhUNxuY+tx846rPo7GcKtYSPMusQjeVEfZlJpSYoR+yrNBBxq+qVF9zrw== - -esbuild-loader@^2.18.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/esbuild-loader/-/esbuild-loader-2.18.0.tgz#7b9548578ab954574fd94655693d22aa5ec74120" - integrity sha512-AKqxM3bI+gvGPV8o6NAhR+cBxVO8+dh+O0OXBHIXXwuSGumckbPWHzZ17subjBGI2YEGyJ1STH7Haj8aCrwL/w== +esbuild-loader@^2.16.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/esbuild-loader/-/esbuild-loader-2.16.0.tgz#a44a57a77ed2810d6b278579271f77d739aa7bc9" + integrity sha512-LCJEwkf+nMJbNmVYNgg/0PaIZDdr5OcHw1qbWAZLkrmBRX+KwHY/yAS6ia98UBtwzk/WhsftUBNB6tfPHgFIxw== dependencies: - esbuild "^0.14.6" + esbuild "^0.13.4" joycon "^3.0.1" json5 "^2.2.0" loader-utils "^2.0.0" tapable "^2.2.0" + type-fest "^1.4.0" webpack-sources "^2.2.0" esbuild-netbsd-64@0.13.15: @@ -4916,62 +5317,32 @@ esbuild-netbsd-64@0.13.15: resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.15.tgz#a2fedc549c2b629d580a732d840712b08d440038" integrity sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w== -esbuild-netbsd-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.14.tgz#3e44de35e1add7e9582f3c0d2558d86aafbc813b" - integrity sha512-fn8looXPQhpVqUyCBWUuPjesH+yGIyfbIQrLKG05rr1Kgm3rZD/gaYrd3Wpmf5syVZx70pKZPvdHp8OTA+y7cQ== - esbuild-openbsd-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.15.tgz#b22c0e5806d3a1fbf0325872037f885306b05cd7" integrity sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g== -esbuild-openbsd-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.14.tgz#04710ef1d01cd9f15d54f50d20b5a3778f8306a2" - integrity sha512-HdAnJ399pPff3SKbd8g+P4o5znseni5u5n5rJ6Z7ouqOdgbOwHe2ofZbMow17WMdNtz1IyOZk2Wo9Ve6/lZ4Rg== - esbuild-sunos-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.15.tgz#d0b6454a88375ee8d3964daeff55c85c91c7cef4" integrity sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw== -esbuild-sunos-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.14.tgz#8e583dd92c5c7ac4303ddc37f588e44211e04e19" - integrity sha512-bmDHa99ulsGnYlh/xjBEfxoGuC8CEG5OWvlgD+pF7bKKiVTbtxqVCvOGEZeoDXB+ja6AvHIbPxrEE32J+m5nqQ== - esbuild-windows-32@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.15.tgz#c96d0b9bbb52f3303322582ef8e4847c5ad375a7" integrity sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw== -esbuild-windows-32@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.14.tgz#6d293ddfb71229f21cc13d85d5d2f43e8131693b" - integrity sha512-6tVooQcxJCNenPp5GHZBs/RLu31q4B+BuF4MEoRxswT+Eq2JGF0ZWDRQwNKB8QVIo3t6Svc5wNGez+CwKNQjBg== - esbuild-windows-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.15.tgz#1f79cb9b1e1bb02fb25cd414cb90d4ea2892c294" integrity sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ== -esbuild-windows-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.14.tgz#08a36844b69542f8ec1cb33a5ddcea02b9d0b2e8" - integrity sha512-kl3BdPXh0/RD/dad41dtzj2itMUR4C6nQbXQCyYHHo4zoUoeIXhpCrSl7BAW1nv5EFL8stT1V+TQVXGZca5A2A== - esbuild-windows-arm64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.15.tgz#482173070810df22a752c686509c370c3be3b3c3" integrity sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA== -esbuild-windows-arm64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.14.tgz#ca747ce4066d5b8a79dbe48fe6ecd92d202e5366" - integrity sha512-dCm1wTOm6HIisLanmybvRKvaXZZo4yEVrHh1dY0v582GThXJOzuXGja1HIQgV09RpSHYRL3m4KoUBL00l6SWEg== - -esbuild@^0.13.15: +esbuild@^0.13.15, esbuild@^0.13.4: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.13.15.tgz#db56a88166ee373f87dbb2d8798ff449e0450cdf" integrity sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw== @@ -4994,30 +5365,6 @@ esbuild@^0.13.15: esbuild-windows-64 "0.13.15" esbuild-windows-arm64 "0.13.15" -esbuild@^0.14.6: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.14.tgz#3b99f20d628013c3e2ae90e67687e03f1d6eb071" - integrity sha512-aiK4ddv+uui0k52OqSHu4xxu+SzOim7Rlz4i25pMEiC8rlnGU0HJ9r+ZMfdWL5bzifg+nhnn7x4NSWTeehYblg== - optionalDependencies: - esbuild-android-arm64 "0.14.14" - esbuild-darwin-64 "0.14.14" - esbuild-darwin-arm64 "0.14.14" - esbuild-freebsd-64 "0.14.14" - esbuild-freebsd-arm64 "0.14.14" - esbuild-linux-32 "0.14.14" - esbuild-linux-64 "0.14.14" - esbuild-linux-arm "0.14.14" - esbuild-linux-arm64 "0.14.14" - esbuild-linux-mips64le "0.14.14" - esbuild-linux-ppc64le "0.14.14" - esbuild-linux-s390x "0.14.14" - esbuild-netbsd-64 "0.14.14" - esbuild-openbsd-64 "0.14.14" - esbuild-sunos-64 "0.14.14" - esbuild-windows-32 "0.14.14" - esbuild-windows-64 "0.14.14" - esbuild-windows-arm64 "0.14.14" - escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -5028,6 +5375,11 @@ escape-goat@^2.0.0: resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -5075,59 +5427,47 @@ eslint-import-resolver-node@^0.3.6: debug "^3.2.7" resolve "^1.20.0" -eslint-import-resolver-typescript@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.5.0.tgz#07661966b272d14ba97f597b51e1a588f9722f0a" - integrity sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ== - dependencies: - debug "^4.3.1" - glob "^7.1.7" - is-glob "^4.0.1" - resolve "^1.20.0" - tsconfig-paths "^3.9.0" - -eslint-module-utils@^2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz#b435001c9f8dd4ab7f6d0efcae4b9696d4c24b7c" - integrity sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ== +eslint-module-utils@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.2.tgz#1d0aa455dcf41052339b63cada8ab5fd57577129" + integrity sha512-zquepFnWCY2ISMFwD/DqzaM++H+7PDzOpUvotJWm/y1BAFt5R4oeULgdrTejKqLkz7MA/tgstsUMNYc7wNdTrg== dependencies: debug "^3.2.7" find-up "^2.1.0" - pkg-dir "^2.0.0" eslint-plugin-header@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz#6ce512432d57675265fac47292b50d1eff11acd6" integrity sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg== -eslint-plugin-import@^2.25.3: - version "2.25.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz#a554b5f66e08fb4f6dc99221866e57cfff824766" - integrity sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg== +eslint-plugin-import@^2.25.4: + version "2.25.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1" + integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA== dependencies: array-includes "^3.1.4" array.prototype.flat "^1.2.5" debug "^2.6.9" doctrine "^2.1.0" eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.7.1" + eslint-module-utils "^2.7.2" has "^1.0.3" is-core-module "^2.8.0" is-glob "^4.0.3" minimatch "^3.0.4" object.values "^1.1.5" resolve "^1.20.0" - tsconfig-paths "^3.11.0" + tsconfig-paths "^3.12.0" eslint-plugin-react-hooks@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172" integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA== -eslint-plugin-react@^7.27.1: - version "7.27.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.27.1.tgz#469202442506616f77a854d91babaae1ec174b45" - integrity sha512-meyunDjMMYeWr/4EBLTV1op3iSG3mjT/pz5gti38UzfM4OPpNc2m0t2xvKCOMU5D6FSdd34BIMFOvQbW+i8GAA== +eslint-plugin-react@^7.28.0: + version "7.28.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.28.0.tgz#8f3ff450677571a659ce76efc6d80b6a525adbdf" + integrity sha512-IOlFIRHzWfEQQKcAD4iyYDndHwTQiCMcJVJjxempf203jnNLUnW34AXLrV33+nEXoifJE2ZEGmcjKPL8957eSw== dependencies: array-includes "^3.1.4" array.prototype.flatmap "^1.2.5" @@ -5144,10 +5484,10 @@ eslint-plugin-react@^7.27.1: semver "^6.3.0" string.prototype.matchall "^4.0.6" -eslint-plugin-unused-imports@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-1.1.5.tgz#a2b992ef0faf6c6c75c3815cc47bde76739513c2" - integrity sha512-TeV8l8zkLQrq9LBeYFCQmYVIXMjfHgdRQLw7dEZp4ZB3PeR10Y5Uif11heCsHRmhdRIYMoewr1d9ouUHLbLHew== +eslint-plugin-unused-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz#d8db8c4d0cfa0637a8b51ce3fd7d1b6bc3f08520" + integrity sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A== dependencies: eslint-rule-composer "^0.3.0" @@ -5156,7 +5496,15 @@ eslint-rule-composer@^0.3.0: resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== -eslint-scope@5.1.1, eslint-scope@^5.1.1: +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -5164,12 +5512,13 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== +eslint-scope@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153" + integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg== dependencies: - eslint-visitor-keys "^1.1.0" + esrecurse "^4.3.0" + estraverse "^5.2.0" eslint-utils@^3.0.0: version "3.0.0" @@ -5178,11 +5527,6 @@ eslint-utils@^3.0.0: dependencies: eslint-visitor-keys "^2.0.0" -eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - eslint-visitor-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" @@ -5193,60 +5537,60 @@ eslint-visitor-keys@^3.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz#eee4acea891814cda67a7d8812d9647dd0179af2" integrity sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA== -eslint@^7.32.0: - version "7.32.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" - integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== +eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz#6fbb166a6798ee5991358bc2daa1ba76cc1254a1" + integrity sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ== + +eslint@^8.7.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.7.0.tgz#22e036842ee5b7cf87b03fe237731675b4d3633c" + integrity sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w== dependencies: - "@babel/code-frame" "7.12.11" - "@eslint/eslintrc" "^0.4.3" - "@humanwhocodes/config-array" "^0.5.0" + "@eslint/eslintrc" "^1.0.5" + "@humanwhocodes/config-array" "^0.9.2" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" - debug "^4.0.1" + debug "^4.3.2" 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" + eslint-scope "^7.1.0" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.2.0" + espree "^9.3.0" 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" + glob-parent "^6.0.1" globals "^13.6.0" - ignore "^4.0.6" + ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - js-yaml "^3.13.1" + js-yaml "^4.1.0" 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" + regexpp "^3.2.0" + strip-ansi "^6.0.1" strip-json-comments "^3.1.0" - table "^6.0.9" text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^7.3.0, espree@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" - integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== +espree@^9.2.0, espree@^9.3.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.0.tgz#c1240d79183b72aaee6ccfa5a90bc9111df085a8" + integrity sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ== dependencies: - acorn "^7.4.0" + acorn "^8.7.0" acorn-jsx "^5.3.1" - eslint-visitor-keys "^1.3.0" + eslint-visitor-keys "^3.1.0" esprima@1.2.2: version "1.2.2" @@ -5265,6 +5609,13 @@ esquery@^1.4.0: dependencies: estraverse "^5.1.0" +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" @@ -5272,7 +5623,7 @@ esrecurse@^4.3.0: dependencies: estraverse "^5.2.0" -estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== @@ -5287,6 +5638,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + event-target-shim@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" @@ -5297,10 +5653,25 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +events@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" + integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== + +eventsource@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0" + integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ== + dependencies: + original "^1.0.0" + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" exec-sh@^0.3.2: version "0.3.4" @@ -5363,21 +5734,6 @@ execa@^4.0.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - 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" - exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -5401,6 +5757,13 @@ expand-template@^2.0.3: resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + expect@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" @@ -5413,6 +5776,42 @@ expect@^26.6.2: jest-message-util "^26.6.2" jest-regex-util "^26.0.0" +express@^4.17.1: + version "4.17.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + dependencies: + accepts "~1.3.7" + array-flatten "1.1.1" + body-parser "1.19.0" + content-disposition "0.5.3" + content-type "~1.0.4" + cookie "0.4.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "~1.1.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.5" + qs "6.7.0" + range-parser "~1.2.1" + safe-buffer "5.1.2" + send "0.17.1" + serve-static "1.14.1" + setprototypeof "1.1.1" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -5509,11 +5908,6 @@ fast-safe-stringify@^2.0.4: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== -fastest-levenshtein@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" - integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== - fastparse@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" @@ -5526,6 +5920,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + fb-watchman@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" @@ -5566,6 +5967,19 @@ file-js@0.3.0: minimatch "^3.0.3" proper-lockfile "^1.2.0" +file-loader@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + filehound@^1.17.5: version "1.17.5" resolved "https://registry.yarnpkg.com/filehound/-/filehound-1.17.5.tgz#c1c7e8d14b94d536994d820dce6c3f9ca828fd9a" @@ -5607,6 +6021,28 @@ filter-obj@^1.1.0: resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs= +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-cache-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + find-npm-prefix@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz#8d8ce2c78b3b4b9e66c8acc6a37c231eb841cfdf" @@ -5639,6 +6075,16 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +findup-sync@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" + integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== + dependencies: + detect-file "^1.0.0" + is-glob "^4.0.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -5685,19 +6131,17 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -fork-ts-checker-webpack-plugin@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e" - integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw== +fork-ts-checker-webpack-plugin@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.2.1.tgz#79326d869797906fa8b24e2abcf9421fc805450d" + integrity sha512-SVi+ZAQOGbtAsUWrZvGzz38ga2YqjWvca1pXQFUArIVXqli0lLoDQ8uS0wg0kSpcwpZmaW5jVCZXQebkyUQSsw== dependencies: "@babel/code-frame" "^7.8.3" "@types/json-schema" "^7.0.5" chalk "^4.1.0" - chokidar "^3.4.2" cosmiconfig "^6.0.0" deepmerge "^4.2.2" fs-extra "^9.0.0" - glob "^7.1.6" memfs "^3.1.2" minimatch "^3.0.4" schema-utils "2.7.0" @@ -5740,6 +6184,11 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= + fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -5747,6 +6196,11 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + from2@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-1.3.0.tgz#88413baaa5f9a597cfde9221d86986cd3c061dfd" @@ -5839,6 +6293,14 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= +fsevents@^1.2.7: + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + fsevents@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" @@ -5989,6 +6451,14 @@ github-from-package@0.0.0: resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -5996,7 +6466,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob-parent@^6.0.2: +glob-parent@^6.0.1, glob-parent@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== @@ -6008,7 +6478,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7, glob@^7.2.0: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -6047,6 +6517,42 @@ global-dirs@^3.0.0: dependencies: ini "2.0.0" +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + global-tunnel-ng@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz#d03b5102dfde3a69914f5ee7d86761ca35d57d8f" @@ -6088,6 +6594,17 @@ globby@^11.0.1, globby@^11.0.4: merge2 "^1.3.0" slash "^3.0.0" +globby@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= + dependencies: + array-union "^1.0.1" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + got@^11.8.0, got@^11.8.3: version "11.8.3" resolved "https://registry.yarnpkg.com/got/-/got-11.8.3.tgz#f496c8fdda5d729a90b4905d2b07dbd148170770" @@ -6139,16 +6656,11 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4: version "4.2.8" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== -graceful-fs@^4.2.4, graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" @@ -6274,6 +6786,23 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -6291,6 +6820,15 @@ history@^4.10.1, history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -6298,6 +6836,13 @@ hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react- dependencies: react-is "^16.7.0" +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + hosted-git-info@^2.1.4, hosted-git-info@^2.7.1, hosted-git-info@^2.8.9: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -6327,44 +6872,55 @@ html-encoding-sniffer@^2.0.1: dependencies: whatwg-encoding "^1.0.5" +html-entities@^1.2.1, html-entities@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.3.1.tgz#fb9a1a4b5b14c5daba82d3e34c6ae4fe701a0e44" + integrity sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -html-minifier-terser@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" - integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== +html-minifier-terser@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" + integrity sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg== dependencies: - camel-case "^4.1.2" - clean-css "^5.2.2" - commander "^8.3.0" + camel-case "^4.1.1" + clean-css "^4.2.3" + commander "^4.1.1" he "^1.2.0" - param-case "^3.0.4" + param-case "^3.0.3" relateurl "^0.2.7" - terser "^5.10.0" + terser "^4.6.3" -html-webpack-plugin@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" - integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== +html-webpack-plugin@^4.5.2: + version "4.5.2" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz#76fc83fa1a0f12dd5f7da0404a54e2699666bc12" + integrity sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A== 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" + "@types/html-minifier-terser" "^5.0.0" + "@types/tapable" "^1.0.5" + "@types/webpack" "^4.41.8" + html-minifier-terser "^5.0.1" + loader-utils "^1.2.3" + lodash "^4.17.20" + pretty-error "^2.1.1" + tapable "^1.1.3" + util.promisify "1.0.0" -htmlparser2@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" - integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== +htmlparser2@^3.3.0: + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== dependencies: - domelementtype "^2.0.1" - domhandler "^4.0.0" - domutils "^2.5.2" - entities "^2.0.0" + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" http-cache-semantics@^3.8.1: version "3.8.1" @@ -6381,6 +6937,43 @@ http-deceiver@^1.2.7: resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= +http-errors@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-parser-js@>=0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.2.tgz#da2e31d237b393aae72ace43882dd7e270a8ff77" + integrity sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ== + http-proxy-agent@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" @@ -6398,7 +6991,28 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" -http-proxy@^1.18.1: +http-proxy-middleware@0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" + integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== + dependencies: + http-proxy "^1.17.0" + is-glob "^4.0.0" + lodash "^4.17.11" + micromatch "^3.1.10" + +http-proxy-middleware@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz#43700d6d9eecb7419bf086a128d0f7205d9eb665" + integrity sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg== + dependencies: + "@types/http-proxy" "^1.17.5" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + +http-proxy@^1.17.0, http-proxy@^1.18.1: version "1.18.1" resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== @@ -6424,6 +7038,11 @@ http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + https-proxy-agent@^2.2.3: version "2.2.4" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" @@ -6516,6 +7135,11 @@ ignore-by-default@^1.0.1: resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= +ignore-loader@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463" + integrity sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM= + ignore-walk@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" @@ -6533,6 +7157,11 @@ ignore@^5.1.4, ignore@^5.1.8: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== +ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + image-size@~0.5.0: version "0.5.5" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" @@ -6580,6 +7209,14 @@ import-lazy@^2.1.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= +import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" + resolve-cwd "^2.0.0" + import-local@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" @@ -6623,11 +7260,21 @@ inflight@^1.0.4, inflight@~1.0.6: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + ini@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" @@ -6652,6 +7299,14 @@ init-package-json@^1.10.3: validate-npm-package-license "^3.0.1" validate-npm-package-name "^3.0.0" +internal-ip@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" + integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== + dependencies: + default-gateway "^4.2.0" + ipaddr.js "^1.9.0" + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -6661,16 +7316,11 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" -interpret@^1.0.0: +interpret@^1.0.0, interpret@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -interpret@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" - integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== - invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" @@ -6686,11 +7336,21 @@ ip-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== -ip@1.1.5, ip@^1.1.5: +ip@1.1.5, ip@^1.1.0, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= +ipaddr.js@1.9.1, ipaddr.js@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-absolute-url@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -6705,6 +7365,11 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-arguments@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" + integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -6720,6 +7385,13 @@ is-bigint@^1.0.1: resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.2.tgz#ffb381442503235ad245ea89e45b3dbff040ee5a" integrity sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA== +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -6744,6 +7416,11 @@ is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== +is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== + is-callable@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" @@ -6850,7 +7527,7 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^2.1.1: +is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= @@ -6877,6 +7554,13 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -6905,6 +7589,11 @@ is-installed-globally@^0.4.0: global-dirs "^3.0.0" is-path-inside "^3.0.2" +is-negative-zero@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" + integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= + is-negative-zero@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" @@ -6947,11 +7636,18 @@ is-obj@^2.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== -is-path-cwd@^2.2.0: +is-path-cwd@^2.0.0, is-path-cwd@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== +is-path-in-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" + integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== + dependencies: + is-path-inside "^2.1.0" + is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" @@ -6959,11 +7655,23 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-path-inside@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" + integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== + dependencies: + path-is-inside "^1.0.2" + is-path-inside@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -6981,6 +7689,13 @@ is-redirect@^1.0.0: resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= +is-regex@^1.0.4, is-regex@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== + dependencies: + has-symbols "^1.0.1" + is-regex@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" @@ -7064,11 +7779,16 @@ is-what@^3.12.0: resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA== -is-windows@^1.0.2: +is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -7095,7 +7815,7 @@ isarray@0.0.1: resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= -isarray@1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -7577,15 +8297,6 @@ jest-worker@^26.6.2: merge-stream "^2.0.0" supports-color "^7.0.0" -jest-worker@^27.4.1: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.4.6.tgz#5d2d93db419566cb680752ca0792780e71b3273e" - integrity sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - jest@26.6.3: version "26.6.3" resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef" @@ -7614,9 +8325,9 @@ jose@^2.0.5: "@panva/asn1.js" "^1.0.0" joycon@^3.0.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" - integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + version "3.0.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.0.1.tgz#9074c9b08ccf37a6726ff74a18485f85efcaddaf" + integrity sha512-SJcJNBg32dGgxhPtM0wQqxqV0ax9k/9TaUskGDSJkSFSQOEWWvQ3zzWdGQRIUry2j1zA5+ReH13t0Mf3StuVZA== jpeg-js@^0.4.2: version "0.4.3" @@ -7711,11 +8422,6 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - json-schema-typed@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-7.0.3.tgz#23ff481b8b4eebcd2ca123b4fa0409e66469a2d9" @@ -7736,6 +8442,11 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json3@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" + integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== + json5@2.x, json5@^2.1.2, json5@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" @@ -7908,6 +8619,11 @@ keyv@^4.0.0: dependencies: json-buffer "3.0.1" +killable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" + integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -7937,7 +8653,7 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -klona@^2.0.4, klona@^2.0.5: +klona@^2.0.4: version "2.0.5" resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== @@ -8170,9 +8886,9 @@ lilconfig@^2.0.3: integrity sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg== lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= load-json-file@^2.0.0: version "2.0.0" @@ -8184,10 +8900,10 @@ load-json-file@^2.0.0: pify "^2.0.0" strip-bom "^3.0.0" -loader-runner@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" - integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== +loader-runner@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== loader-utils@^0.2.16: version "0.2.17" @@ -8199,10 +8915,19 @@ loader-utils@^0.2.16: json5 "^0.5.0" object-assign "^4.0.1" +loader-utils@^1.0.2, loader-utils@^1.2.3, loader-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + loader-utils@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" - integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== + version "2.0.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" @@ -8302,11 +9027,6 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.truncate@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" - integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= - lodash.union@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" @@ -8322,7 +9042,7 @@ lodash.without@~4.4.0: resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= -lodash@4.x, lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: +lodash@4.x, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -8338,6 +9058,11 @@ logform@^2.2.0: ms "^2.1.1" triple-beam "^1.3.0" +loglevel@^1.6.8: + version "1.7.0" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.0.tgz#728166855a740d59d38db01cf46f042caa041bb0" + integrity sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ== + loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -8345,12 +9070,12 @@ loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4 dependencies: js-tokens "^3.0.0 || ^4.0.0" -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== +lower-case@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7" + integrity sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ== dependencies: - tslib "^2.0.3" + tslib "^1.10.0" lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" @@ -8413,7 +9138,7 @@ make-dir@^1.0.0, make-dir@^1.3.0: dependencies: pify "^3.0.0" -make-dir@^2.1.0: +make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== @@ -8496,11 +9221,25 @@ md5-file@^5.0.0: resolved "https://registry.yarnpkg.com/md5-file/-/md5-file-5.0.0.tgz#e519f631feca9c39e7f9ea1780b63c4745012e20" integrity sha512-xbEFXCYVWrSx/gEKS1VPlg84h/4L20znVIulKw6kMfmBUAZNAnF00eczz9ICMl+/hjQGo5KSXRxbL/47X3rmMw== +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + meant@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.3.tgz#67769af9de1d158773e928ae82c456114903554c" integrity sha512-88ZRGcNxAq4EH38cQ4D85PM57pikCwS8Z99EWHODxN7KBY+UuPiqzRTtZzS8KTXO/ywSWbdjjJST2Hly/EQxLw== +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" @@ -8520,6 +9259,27 @@ memfs@^3.1.2: resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0" integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA== +memory-fs@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -8530,7 +9290,12 @@ merge2@^1.3.0: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^3.1.4: +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -8549,15 +9314,7 @@ micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.0, micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -micromatch@^4.0.2: +micromatch@^4.0.0, micromatch@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== @@ -8565,36 +9322,45 @@ micromatch@^4.0.2: braces "^3.0.1" picomatch "^2.0.5" +micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + mime-db@1.48.0: version "1.48.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ== -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== +"mime-db@>= 1.43.0 < 2": + version "1.45.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" + integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== -mime-types@^2.1.12, mime-types@~2.1.19: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.31" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b" integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg== dependencies: mime-db "1.48.0" -mime-types@^2.1.27: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" - -mime@^1.4.1: +mime@1.6.0, mime@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.4.6, mime@^2.5.2: +mime@^2.4.4, mime@^2.4.6, mime@^2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== @@ -8637,18 +9403,25 @@ mini-create-react-context@^0.4.0: "@babel/runtime" "^7.5.5" tiny-warning "^1.0.3" -mini-css-extract-plugin@*, mini-css-extract-plugin@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.2.tgz#b3b9b98320c2c054d92c16f6a94ddfdbbba13755" - integrity sha512-Lwgq9qLNyBK6yNLgzssXnq4r2+mB9Mz3cJWlM8kseysHIvTicFhDNimFgY94jjqlwhNzLPsq8wv4X+vOHtMdYA== +mini-css-extract-plugin@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz#83172b4fd812f8fc4a09d6f6d16f924f53990ca8" + integrity sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q== dependencies: - schema-utils "^4.0.0" + loader-utils "^2.0.0" + schema-utils "^3.0.0" + webpack-sources "^1.1.0" -minimalistic-assert@^1.0.0: +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + minimatch@3.0.4, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -8725,7 +9498,7 @@ mkdirp@1.x, mkdirp@^1.0.3, mkdirp@~1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdirp@~0.5.0: +mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdirp@~0.5.0: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -8816,25 +9589,43 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + ms@2.1.2, ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +multicast-dns-service-types@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" + integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= + +multicast-dns@^6.0.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" + integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== + dependencies: + dns-packet "^1.3.1" + thunky "^1.0.2" + mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.14.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== +nan@^2.12.1, nan@^2.14.0: + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" + integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== nanoid@^3.1.30: - version "3.2.0" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" - integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== + version "3.1.30" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" + integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== nanomatch@^1.2.9: version "1.2.13" @@ -8858,6 +9649,13 @@ napi-build-utils@^1.0.1: resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== +native-url@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/native-url/-/native-url-0.2.6.tgz#ca1258f5ace169c716ff44eccbddb674e10399ae" + integrity sha512-k4bDC87WtgrdD362gZz6zoiXQrl40kYlBmpfmSjwRO1VU0V5ccwJTlxuE72F6m3V0vc1xOf6n3UCP9QyerRqmA== + dependencies: + querystring "^0.2.0" + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -8872,7 +9670,12 @@ needle@^2.5.2: iconv-lite "^0.4.4" sax "^1.2.4" -neo-async@^2.6.0: +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + +neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== @@ -8887,13 +9690,13 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== +no-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8" + integrity sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw== dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" + lower-case "^2.0.1" + tslib "^1.10.0" node-abi@^3.3.0: version "3.5.0" @@ -8975,12 +9778,42 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= -node-loader@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/node-loader/-/node-loader-2.0.0.tgz#9109a6d828703fd3e0aa03c1baec12a798071562" - integrity sha512-I5VN34NO4/5UYJaUBtkrODPWxbobrE4hgDqPrjB25yPkonFhCmZ146vTH+Zg417E9Iwoh1l/MbRs1apc5J295Q== +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.1" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "^1.0.1" + +node-loader@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/node-loader/-/node-loader-1.0.3.tgz#ed8f4a8a75928575a5a2dab0e73c9f6386b2353e" + integrity sha512-8c9ef5q24F0AjrPxUjdX7qdTlsU1zZCPeqYvSBCH1TJko3QW4qu1uA1C9KbOPdaRQwREDdbSYZgltBAlbV7l5g== dependencies: loader-utils "^2.0.0" + schema-utils "^3.0.0" node-modules-regexp@^1.0.0: version "1.0.0" @@ -9006,11 +9839,6 @@ node-pty@^0.10.1: dependencies: nan "^2.14.0" -node-releases@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" - integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== - nodemon@^2.0.15: version "2.0.15" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.15.tgz#504516ce3b43d9dc9a955ccd9ec57550a31a8d4e" @@ -9340,12 +10168,12 @@ npmlog@^4.0.1, npmlog@^4.1.2, npmlog@~4.1.2: gauge "~2.7.3" set-blocking "~2.0.0" -nth-check@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" - integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== +nth-check@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== dependencies: - boolbase "^1.0.0" + boolbase "~1.0.0" number-is-nan@^1.0.0: version "1.0.1" @@ -9391,11 +10219,24 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== +object-inspect@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" + integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== + object-inspect@^1.9.0: version "1.10.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369" integrity sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw== +object-is@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.3.tgz#2e3b9e65560137455ee3bd62aec4d90a2ea1cc81" + integrity sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -9488,6 +10329,18 @@ oidc-token-hash@^5.0.1: resolved "https://registry.yarnpkg.com/oidc-token-hash/-/oidc-token-hash-5.0.1.tgz#ae6beec3ec20f0fd885e5400d175191d6e2f10c6" integrity sha512-EvoOtz6FIEBzE+9q253HsLCVRiK/0doEJ2HCvvqMQb3dHZrP3WlJKYtJ55CRTw4jmYomzH4wkPuCj/I3ZvpKxQ== +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + once@^1.3.0, once@^1.3.1, once@^1.4.0, once@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -9534,6 +10387,13 @@ openid-client@^4.1.1: object-hash "^2.0.1" oidc-token-hash "^5.0.1" +opn@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" + integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== + dependencies: + is-wsl "^1.1.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -9558,6 +10418,18 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +original@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" + integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== + dependencies: + url-parse "^1.4.3" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -9647,6 +10519,11 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -9654,6 +10531,13 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" +p-retry@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" + integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== + dependencies: + retry "^0.12.0" + p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -9720,7 +10604,7 @@ pacote@^9.1.0, pacote@^9.5.12, pacote@^9.5.3: unique-filename "^1.1.1" which "^1.3.1" -pako@~1.0.2: +pako@~1.0.2, pako@~1.0.5: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== @@ -9734,13 +10618,13 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -param-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" - integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== +param-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238" + integrity sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA== dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" + dot-case "^3.0.3" + tslib "^1.10.0" parent-module@^1.0.0: version "1.0.1" @@ -9749,6 +10633,18 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" @@ -9779,24 +10675,44 @@ parse-node-version@^1.0.1: resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + parse5@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== -pascal-case@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" - integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascal-case@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f" + integrity sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA== dependencies: - no-case "^3.0.4" - tslib "^2.0.3" + no-case "^3.0.3" + tslib "^1.10.0" pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -9832,6 +10748,11 @@ path-parse@^1.0.6, path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + path-to-regexp@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" @@ -9856,6 +10777,17 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pbkdf2@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" + integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" @@ -9871,15 +10803,15 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== -picomatch@^2.0.5, picomatch@^2.2.3: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +picomatch@^2.2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== pify@^2.0.0: version "2.3.0" @@ -9896,6 +10828,18 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" @@ -9903,12 +10847,12 @@ pirates@^4.0.1: dependencies: node-modules-regexp "^1.0.0" -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== dependencies: - find-up "^2.1.0" + find-up "^3.0.0" pkg-dir@^4.2.0: version "4.2.0" @@ -9972,6 +10916,15 @@ popper.js@1.16.1-lts: resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" integrity sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA== +portfinder@^1.0.26: + version "1.0.28" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" + integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== + dependencies: + async "^2.6.2" + debug "^3.1.1" + mkdirp "^0.5.5" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -10021,14 +10974,16 @@ postcss-load-config@^3.0.1, postcss-load-config@^3.1.0: lilconfig "^2.0.3" yaml "^1.10.2" -postcss-loader@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef" - integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q== +postcss-loader@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-4.3.0.tgz#2c4de9657cd4f07af5ab42bd60a673004da1b8cc" + integrity sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q== dependencies: cosmiconfig "^7.0.0" - klona "^2.0.5" - semver "^7.3.5" + klona "^2.0.4" + loader-utils "^2.0.0" + schema-utils "^3.0.0" + semver "^7.3.4" postcss-modules-extract-imports@^3.0.0: version "3.0.0" @@ -10065,15 +11020,7 @@ postcss-nested@5.0.6: dependencies: postcss-selector-parser "^6.0.6" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: - version "6.0.9" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" - integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-selector-parser@^6.0.6: +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.6: version "6.0.6" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea" integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg== @@ -10094,7 +11041,12 @@ postcss-value-parser@^3.3.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: +postcss-value-parser@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== + +postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== @@ -10156,13 +11108,13 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= -pretty-error@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" - integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== +pretty-error@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" + integrity sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM= dependencies: - lodash "^4.17.20" - renderkid "^3.0.0" + renderkid "^2.0.1" + utila "~0.4" pretty-format@^26.0.0, pretty-format@^26.6.2: version "26.6.2" @@ -10189,7 +11141,20 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -progress@^2.0.0, progress@^2.0.3: +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +progress-bar-webpack-plugin@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/progress-bar-webpack-plugin/-/progress-bar-webpack-plugin-2.1.0.tgz#f7f8c8c461f40b87a8ff168443f494289b07ee65" + integrity sha512-UtlZbnxpYk1wufEWfhIjRn2U52zlY38uvnzFhs8rRxJxC1hSqw88JNR2Mbpqq9Kix8L1nGb3uQ+/1BiUWbigAg== + dependencies: + chalk "^3.0.0" + progress "^2.0.3" + +progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -10267,6 +11232,14 @@ protoduck@^5.0.1: dependencies: genfun "^5.0.0" +proxy-addr@~2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" + integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.9.1" + proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -10292,6 +11265,18 @@ pstree.remy@^1.1.8: resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + pump@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" @@ -10317,6 +11302,16 @@ pumpify@^1.3.3: inherits "^2.0.3" pump "^2.0.0" +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -10334,6 +11329,11 @@ qrcode-terminal@^0.12.0: resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== +qs@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -10349,6 +11349,16 @@ query-string@^6.8.2: split-on-first "^1.0.0" strict-uri-encode "^2.0.0" +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0, querystring@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + querystringify@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" @@ -10369,7 +11379,7 @@ raf-schd@^4.0.2: resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.2.tgz#bd44c708188f2e84c810bf55fcea9231bcaed8a0" integrity sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ== -randombytes@^2.1.0: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== @@ -10381,6 +11391,37 @@ randomcolor@^0.6.2: resolved "https://registry.yarnpkg.com/randomcolor/-/randomcolor-0.6.2.tgz#7a57362ae1a1278439aeed2c15e5deb8ea33f56d" integrity sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A== +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + unpipe "1.0.0" + +raw-loader@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6" + integrity sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + rc@^1.0.1, rc@^1.1.6, rc@^1.2.7, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -10450,6 +11491,11 @@ react-redux@^7.2.0: prop-types "^15.7.2" react-is "^16.13.1" +react-refresh@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.9.0.tgz#71863337adc3e5c2f8a6bfddd12ae3bfe32aafbf" + integrity sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ== + react-router-dom@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.0.tgz#da1bfb535a0e89a712a93b97dd76f47ad1f32363" @@ -10644,7 +11690,7 @@ read@1, read@~1.0.1, read@~1.0.7: dependencies: mute-stream "~0.0.4" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -10686,6 +11732,15 @@ readdir-scoped-modules@^1.0.0, readdir-scoped-modules@^1.1.0: graceful-fs "^4.1.2" once "^1.3.0" +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -10700,13 +11755,6 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" -rechoir@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" - integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== - dependencies: - resolve "^1.9.0" - redent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" @@ -10736,6 +11784,14 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp.prototype.flags@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" + integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + regexp.prototype.flags@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" @@ -10744,11 +11800,6 @@ regexp.prototype.flags@^1.3.1: call-bind "^1.0.2" define-properties "^1.1.3" -regexpp@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== - regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" @@ -10793,16 +11844,16 @@ remove-trailing-separator@^1.0.1: resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= -renderkid@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" - integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== +renderkid@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.3.tgz#380179c2ff5ae1365c522bf2fcfcff01c5b74149" + integrity sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA== dependencies: - css-select "^4.1.3" - dom-converter "^0.2.0" - htmlparser2 "^6.1.0" - lodash "^4.17.21" - strip-ansi "^6.0.1" + css-select "^1.1.0" + dom-converter "^0.2" + htmlparser2 "^3.3.0" + strip-ansi "^3.0.0" + utila "^0.4.0" repeat-element@^1.1.2: version "1.1.3" @@ -10861,11 +11912,6 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" @@ -10891,6 +11937,13 @@ resolve-alpn@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.1.2.tgz#30b60cfbb0c0b8dc897940fe13fe255afcdd4d28" integrity sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA== +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= + dependencies: + resolve-from "^3.0.0" + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -10898,6 +11951,19 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -10918,7 +11984,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.9.0: +resolve@^1.1.6: version "1.21.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.21.0.tgz#b51adc97f3472e6a5cf4444d34bc9d6b9037591f" integrity sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA== @@ -11001,6 +12067,14 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + roarr@^2.15.3: version "2.15.3" resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.3.tgz#65248a291a15af3ebfd767cbf7e44cb402d1d836" @@ -11037,12 +12111,12 @@ rxjs@^6.5.2: dependencies: tslib "^1.9.0" -safe-buffer@*, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: +safe-buffer@*, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -11081,13 +12155,16 @@ sanitize-filename@^1.6.2, sanitize-filename@^1.6.3: dependencies: truncate-utf8-bytes "^1.0.0" -sass-loader@^12.4.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.4.0.tgz#260b0d51a8a373bb8e88efc11f6ba5583fea0bcf" - integrity sha512-7xN+8khDIzym1oL9XyS6zP6Ges+Bo2B2xbPrjdMHEYyV3AQYhd/wXeru++3ODHF0zMjYmVadblSKrPrjEkL8mg== +sass-loader@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.2.0.tgz#3d64c1590f911013b3fa48a0b22a83d5e1494716" + integrity sha512-kUceLzC1gIHz0zNJPpqRsJyisWatGYNFRmv2CKZK2/ngMJgLqxTbXwe/hJ85luyvZkgqU3VlJ33UVF2T/0g6mw== dependencies: klona "^2.0.4" + loader-utils "^2.0.0" neo-async "^2.6.2" + schema-utils "^3.0.0" + semver "^7.3.2" sass@^1.32.13: version "1.44.0" @@ -11135,30 +12212,45 @@ schema-utils@2.7.0: ajv "^6.12.2" ajv-keywords "^3.4.1" -schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + +schema-utils@^2.6.5: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== + dependencies: + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" - integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== +schema-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" + integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== dependencies: - "@types/json-schema" "^7.0.9" - ajv "^8.8.0" - ajv-formats "^2.1.1" - ajv-keywords "^5.0.0" + "@types/json-schema" "^7.0.6" + ajv "^6.12.5" + ajv-keywords "^3.5.2" select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= +selfsigned@^1.10.8: + version "1.10.11" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.11.tgz#24929cd906fe0f44b6d01fb23999a739537acbe9" + integrity sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA== + dependencies: + node-forge "^0.10.0" + semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -11195,6 +12287,25 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + serialize-error@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18" @@ -11202,13 +12313,36 @@ serialize-error@^7.0.1: dependencies: type-fest "^0.13.1" -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== +serialize-javascript@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea" + integrity sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg== dependencies: randombytes "^2.1.0" +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.1" + set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -11229,6 +12363,29 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + sha@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/sha/-/sha-3.0.0.tgz#b2f2f90af690c16a3a839a6a6c680ea51fedd1ae" @@ -11236,13 +12393,6 @@ sha@^3.0.0: dependencies: graceful-fs "^4.1.2" -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - sharp@^0.29.3: version "0.29.3" resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.29.3.tgz#0da183d626094c974516a48fab9b3e4ba92eb5c2" @@ -11365,15 +12515,6 @@ slice-ansi@^1.0.0: dependencies: is-fullwidth-code-point "^2.0.0" -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - slide@^1.1.6, slide@~1.1.3, slide@~1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -11414,6 +12555,27 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +sockjs-client@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.1.tgz#256908f6d5adfb94dabbdbd02c66362cca0f9ea6" + integrity sha512-VnVAb663fosipI/m6pqRXakEOw7nvd7TUgdr3PlR/8V2I95QIdwT8L4nMxhyU8SmDBHYXU1TOElaKOmKLfYzeQ== + dependencies: + debug "^3.2.6" + eventsource "^1.0.7" + faye-websocket "^0.11.3" + inherits "^2.0.4" + json3 "^3.3.3" + url-parse "^1.5.1" + +sockjs@^0.3.21: + version "0.3.21" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" + integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== + dependencies: + faye-websocket "^0.11.3" + uuid "^3.4.0" + websocket-driver "^0.7.4" + socks-proxy-agent@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386" @@ -11460,21 +12622,16 @@ sorted-union-stream@~2.1.3: from2 "^1.3.0" stream-iterate "^1.1.0" -source-list-map@^2.0.1: +source-list-map@^2.0.0, source-list-map@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -"source-map-js@>=0.6.2 <2.0.0": +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf" integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA== -source-map-js@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -11494,7 +12651,7 @@ source-map-resolve@^0.6.0: atob "^2.1.2" decode-uri-component "^0.2.0" -source-map-support@^0.5.19, source-map-support@^0.5.6: +source-map-support@^0.5.19, source-map-support@^0.5.6, source-map-support@~0.5.12: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== @@ -11502,14 +12659,6 @@ source-map-support@^0.5.19, source-map-support@^0.5.6: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" @@ -11525,7 +12674,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.7.3, source-map@~0.7.2: +source-map@^0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== @@ -11647,6 +12796,11 @@ stack-utils@^2.0.2, stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +stackframe@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" + integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA== + stat-mode@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465" @@ -11667,11 +12821,24 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + stream-buffers@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-3.0.2.tgz#5249005a8d5c2d00b3a32e6e0a6ea209dc4f3521" @@ -11685,6 +12852,17 @@ stream-each@^1.1.0: end-of-stream "^1.1.0" stream-shift "^1.0.0" +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + stream-iterate@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/stream-iterate/-/stream-iterate-1.2.0.tgz#2bd7c77296c1702a46488b8ad41f79865eecd4e1" @@ -11746,15 +12924,6 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - 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" - string.prototype.matchall@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" @@ -11777,6 +12946,14 @@ string.prototype.trimend@^1.0.0: define-properties "^1.1.3" es-abstract "^1.17.5" +string.prototype.trimend@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" + integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + string.prototype.trimend@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" @@ -11811,6 +12988,14 @@ string.prototype.trimstart@^1.0.0: define-properties "^1.1.3" es-abstract "^1.17.5" +string.prototype.trimstart@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7" + integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + string.prototype.trimstart@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" @@ -11819,7 +13004,7 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" -string_decoder@^1.1.1: +string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -11908,10 +13093,13 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -style-loader@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" - integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== +style-loader@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c" + integrity sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" stylus@^0.54.8: version "0.54.8" @@ -11948,27 +13136,13 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" -supports-color@^7.0.0: +supports-color@^7.0.0, supports-color@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== dependencies: has-flag "^4.0.0" -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - supports-hyperlinks@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47" @@ -11992,18 +13166,6 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -table@^6.0.9: - version "6.7.2" - resolved "https://registry.yarnpkg.com/table/-/table-6.7.2.tgz#a8d39b9f5966693ca8b0feba270a78722cbaf3b0" - integrity sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g== - dependencies: - ajv "^8.0.1" - lodash.clonedeep "^4.5.0" - lodash.truncate "^4.4.2" - slice-ansi "^4.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - tailwindcss@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.7.tgz#15936881f042a7eb8d6f2b6a454bac9f51181bbd" @@ -12031,15 +13193,15 @@ tailwindcss@^3.0.7: resolve "^1.20.0" tmp "^0.2.1" -tapable@^1.0.0: +tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tapable@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b" + integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw== tar-fs@^2.0.0, tar-fs@^2.1.1: version "2.1.1" @@ -12145,25 +13307,29 @@ terminal-link@^2.0.0: ansi-escapes "^4.2.1" supports-hyperlinks "^2.0.0" -terser-webpack-plugin@^5.1.3: - version "5.3.0" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.0.tgz#21641326486ecf91d8054161c816e464435bae9f" - integrity sha512-LPIisi3Ol4chwAaPP8toUJ3L4qCM1G0wao7L3qNv57Drezxj6+VEyySpPw4B1HSO2Eg/hDY/MNF5XihCAoqnsQ== +terser-webpack-plugin@^1.4.3: + version "1.4.4" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz#2c63544347324baafa9a56baaddf1634c8abfc2f" + integrity sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA== dependencies: - jest-worker "^27.4.1" - schema-utils "^3.1.1" - serialize-javascript "^6.0.0" + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^3.1.0" source-map "^0.6.1" - terser "^5.7.2" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" -terser@^5.10.0, terser@^5.7.2: - version "5.10.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" - integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== +terser@^4.1.2, terser@^4.6.3: + version "4.7.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.7.0.tgz#15852cf1a08e3256a80428e865a2fa893ffba006" + integrity sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw== dependencies: commander "^2.20.0" - source-map "~0.7.2" - source-map-support "~0.5.20" + source-map "~0.6.1" + source-map-support "~0.5.12" test-exclude@^6.0.0: version "6.0.0" @@ -12202,11 +13368,23 @@ through@2, "through@>=2.2.7 <3": resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + timed-out@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= +timers-browserify@^2.0.4: + version "2.0.11" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" + integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== + dependencies: + setimmediate "^1.0.4" + tiny-invariant@^1.0.2, tiny-invariant@^1.0.6: version "1.1.0" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" @@ -12241,6 +13419,11 @@ tmpl@1.0.x: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -12283,6 +13466,11 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + touch@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" @@ -12357,15 +13545,16 @@ ts-jest@26.5.6: semver "7.x" yargs-parser "20.x" -ts-loader@^9.2.6: - version "9.2.6" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74" - integrity sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw== +ts-loader@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-7.0.5.tgz#789338fb01cb5dc0a33c54e50558b34a73c9c4c5" + integrity sha512-zXypEIT6k3oTc+OZNx/cqElrsbBtYqDknf48OZos0NQ3RTt045fBIU8RRSu+suObBzYB355aIPGOe/3kj9h7Ig== dependencies: - chalk "^4.1.0" - enhanced-resolve "^5.0.0" + chalk "^2.3.0" + enhanced-resolve "^4.0.0" + loader-utils "^1.0.2" micromatch "^4.0.0" - semver "^7.3.4" + semver "^6.0.0" ts-node@^10.4.0: version "10.4.0" @@ -12385,7 +13574,7 @@ ts-node@^10.4.0: make-error "^1.1.1" yn "3.1.1" -tsconfig-paths@^3.11.0: +tsconfig-paths@^3.12.0: version "3.12.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b" integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg== @@ -12410,11 +13599,6 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - tslib@^2.1.0, tslib@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" @@ -12427,6 +13611,11 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -12498,6 +13687,19 @@ type-fest@^1.0.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.0.2.tgz#3f9c39982859f385c77c38b7e5f1432b8a3661c6" integrity sha512-a720oz3Kjbp3ll0zkeN9qjRhO7I34MKMhPGQiQJAmaZQZQ1lo+NWThK322f7sXV+kTg9B1Ybt16KgBXWgteT8w== +type-fest@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" + integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== + +type-is@~1.6.17, type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + typed-emitter@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/typed-emitter/-/typed-emitter-1.4.0.tgz#38c6bf1224e764906bb20cb0b458fa914100607c" @@ -12515,10 +13717,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typedoc-plugin-markdown@^3.11.12: - version "3.11.12" - resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.11.12.tgz#04f4740534d19728696a5c0ccc35f319bcb93b31" - integrity sha512-gb/RuzgZ1zCnRUOqUg6firIqU7xDs9s7hq0vlU/gAsFfVCnpl3NTM9vPyPON75nnpfVFCxr/hmKQ01k1CYY/Qg== +typedoc-plugin-markdown@^3.11.3: + version "3.11.3" + resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.11.3.tgz#be340b905903f1ce552fa2fa7d677db408ab1041" + integrity sha512-rWiHbEIe0oZetDIsBR24XJVxGOJ91kDcHoj2KhFKxCLoJGX659EKBQkHne9QJ4W2stGhu1fRgFyQaouSBnxukA== dependencies: handlebars "^4.7.7" @@ -12654,7 +13856,7 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== -unpipe@~1.0.0: +unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= @@ -12681,6 +13883,11 @@ unzip-response@^2.0.1: resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + update-notifier@^2.2.0, update-notifier@^2.3.0, update-notifier@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" @@ -12729,6 +13936,15 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= +url-loader@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" + integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== + dependencies: + loader-utils "^2.0.0" + mime-types "^2.1.27" + schema-utils "^3.0.0" + url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" @@ -12743,6 +13959,14 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" +url-parse@^1.4.3, url-parse@^1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.2.tgz#a4eff6fd5ff9fe6ab98ac1f79641819d13247cda" + integrity sha512-6bTUPERy1muxxYClbzoRo5qtQuyoGEbzbQvi0SW4/8U8UyVkAQhWFBlnigqJkRm4su4x1zDQfNbEzWkt+vchcg== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + url-parse@^1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862" @@ -12751,6 +13975,14 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + use-memo-one@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.1.tgz#39e6f08fe27e422a7d7b234b5f9056af313bd22c" @@ -12783,12 +14015,39 @@ util-promisify@^2.1.0: dependencies: object.getownpropertydescriptors "^2.0.3" -utila@~0.4: +util.promisify@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +utila@^0.4.0, utila@~0.4: version "0.4.0" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= -uuid@^3.3.2, uuid@^3.3.3: +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@^3.3.2, uuid@^3.3.3, uuid@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -12798,7 +14057,7 @@ uuid@^8.3.0, uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -v8-compile-cache@^2.0.3: +v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== @@ -12832,6 +14091,11 @@ value-equal@^1.0.1: resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + verror@1.10.0, verror@^1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -12841,6 +14105,11 @@ verror@1.10.0, verror@^1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + vscode-textmate@5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" @@ -12867,13 +14136,23 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -watchpack@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" - integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== +watchpack-chokidar2@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" + integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" + integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== dependencies: - glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" + neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.1" + watchpack-chokidar2 "^2.0.0" wbuf@^1.1.0, wbuf@^1.7.3: version "1.7.3" @@ -12904,109 +14183,144 @@ webidl-conversions@^6.1.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== -webpack-cli@^4.9.1: - version "4.9.1" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.1.tgz#b64be825e2d1b130f285c314caa3b1ba9a4632b3" - integrity sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ== +webpack-cli@^3.3.12: + version "3.3.12" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" + integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag== dependencies: - "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^1.1.0" - "@webpack-cli/info" "^1.4.0" - "@webpack-cli/serve" "^1.6.0" - colorette "^2.0.14" - commander "^7.0.0" - execa "^5.0.0" - fastest-levenshtein "^1.0.12" - import-local "^3.0.2" - interpret "^2.2.0" - rechoir "^0.7.0" - webpack-merge "^5.7.3" + chalk "^2.4.2" + cross-spawn "^6.0.5" + enhanced-resolve "^4.1.1" + findup-sync "^3.0.0" + global-modules "^2.0.0" + import-local "^2.0.0" + interpret "^1.4.0" + loader-utils "^1.4.0" + supports-color "^6.1.0" + v8-compile-cache "^2.1.1" + yargs "^13.3.2" -webpack-merge@^5.7.3: - version "5.8.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" - integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== +webpack-dev-middleware@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3" + integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw== dependencies: - clone-deep "^4.0.1" - wildcard "^2.0.0" + memory-fs "^0.4.1" + mime "^2.4.4" + mkdirp "^0.5.1" + range-parser "^1.2.1" + webpack-log "^2.0.0" -webpack-node-externals@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz#1a3407c158d547a9feb4229a9e3385b7b60c9917" - integrity sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ== +webpack-dev-server@^3.11.3: + version "3.11.3" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz#8c86b9d2812bf135d3c9bce6f07b718e30f7c3d3" + integrity sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA== + dependencies: + ansi-html-community "0.0.8" + bonjour "^3.5.0" + chokidar "^2.1.8" + compression "^1.7.4" + connect-history-api-fallback "^1.6.0" + debug "^4.1.1" + del "^4.1.1" + express "^4.17.1" + html-entities "^1.3.1" + http-proxy-middleware "0.19.1" + import-local "^2.0.0" + internal-ip "^4.3.0" + ip "^1.1.5" + is-absolute-url "^3.0.3" + killable "^1.0.1" + loglevel "^1.6.8" + opn "^5.5.0" + p-retry "^3.0.1" + portfinder "^1.0.26" + schema-utils "^1.0.0" + selfsigned "^1.10.8" + semver "^6.3.0" + serve-index "^1.9.1" + sockjs "^0.3.21" + sockjs-client "^1.5.0" + spdy "^4.0.2" + strip-ansi "^3.0.1" + supports-color "^6.1.0" + url "^0.11.0" + webpack-dev-middleware "^3.7.2" + webpack-log "^2.0.0" + ws "^6.2.1" + yargs "^13.3.2" + +webpack-log@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" + integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== + dependencies: + ansi-colors "^3.0.0" + uuid "^3.3.2" + +webpack-node-externals@^1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.7.2.tgz#6e1ee79ac67c070402ba700ef033a9b8d52ac4e3" + integrity sha512-ajerHZ+BJKeCLviLUUmnyd5B4RavLF76uv3cs6KNuO8W+HuQaEs0y0L7o40NQxdPy5w0pcv8Ew7yPUAQG0UdCg== + +webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" webpack-sources@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd" - integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.0.tgz#9ed2de69b25143a4c18847586ad9eccb19278cfa" + integrity sha512-WyOdtwSvOML1kbgtXbTDnEW0jkJ7hZr/bDByIwszhWd/4XX1A3XMkrbFMsuH4+/MfLlZCUzlAdg4r7jaGKEIgQ== dependencies: source-list-map "^2.0.1" source-map "^0.6.1" -webpack-sources@^3.2.2, webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5: - version "5.66.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.66.0.tgz#789bf36287f407fc92b3e2d6f978ddff1bfc2dbb" - integrity sha512-NJNtGT7IKpGzdW7Iwpn/09OXz9inIkeIQ/ibY6B+MdV1x6+uReqz/5z1L89ezWnpPDWpXF0TY5PCYKQdWVn8Vg== +webpack@^4.46.0: + version "4.46.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" + integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== dependencies: - "@types/eslint-scope" "^3.7.0" - "@types/estree" "^0.0.50" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.4.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.3" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" + enhanced-resolve "^4.5.0" + eslint-scope "^4.0.3" 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.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.3.1" - webpack-sources "^3.2.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.3" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.7.4" + webpack-sources "^1.4.1" -webpack@^5.67.0: - version "5.67.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.67.0.tgz#cb43ca2aad5f7cc81c4cd36b626e6b819805dbfd" - integrity sha512-LjFbfMh89xBDpUMgA1W9Ur6Rn/gnr2Cq1jjHFPo4v6a79/ypznSYbAyPgGhwsxBtMIaEmDD1oJoA7BEYw/Fbrw== +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== dependencies: - "@types/eslint-scope" "^3.7.0" - "@types/estree" "^0.0.50" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.4.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.3" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - 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.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.3.1" - webpack-sources "^3.2.3" + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== whatwg-encoding@^1.0.5: version "1.0.5" @@ -13053,7 +14367,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.9, which@^1.3.0, which@^1.3.1: +which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -13088,11 +14402,6 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== - win-ca@^3.4.5: version "3.4.5" resolved "https://registry.yarnpkg.com/win-ca/-/win-ca-3.4.5.tgz#634f5603e3b1c57e273da2334cf849f6c53a61d1" @@ -13219,6 +14528,13 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +ws@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" + ws@^7.3.1, ws@^7.4.6, ws@^7.5.5: version "7.5.5" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" @@ -13259,7 +14575,7 @@ xmldom@^0.5.0: resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.5.0.tgz#193cb96b84aa3486127ea6272c4596354cb4962e" integrity sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA== -xtend@^4.0.2, xtend@~4.0.1: +xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== @@ -13350,7 +14666,7 @@ yargs-parser@^7.0.0: dependencies: camelcase "^4.1.0" -yargs@^13.3.0: +yargs@^13.3.0, yargs@^13.3.2: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==