mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into react-table-with-resizable-columns
This commit is contained in:
commit
d1e2f0cae1
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-18.04, macos-11, windows-2019]
|
os: [ubuntu-20.04, macos-11, windows-2019]
|
||||||
node-version: [16.x]
|
node-version: [16.x]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Release from lens
|
- name: Checkout Release from lens
|
||||||
|
|||||||
21
package.json
21
package.json
@ -227,6 +227,7 @@
|
|||||||
"@tanstack/react-table": "^8.5.11",
|
"@tanstack/react-table": "^8.5.11",
|
||||||
"@tanstack/react-virtual": "3.0.0-beta.18",
|
"@tanstack/react-virtual": "3.0.0-beta.18",
|
||||||
"@types/circular-dependency-plugin": "5.0.5",
|
"@types/circular-dependency-plugin": "5.0.5",
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
"auto-bind": "^4.0.0",
|
"auto-bind": "^4.0.0",
|
||||||
"await-lock": "^2.2.2",
|
"await-lock": "^2.2.2",
|
||||||
"byline": "^5.0.0",
|
"byline": "^5.0.0",
|
||||||
@ -300,10 +301,10 @@
|
|||||||
"@material-ui/lab": "^4.0.0-alpha.60",
|
"@material-ui/lab": "^4.0.0-alpha.60",
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
|
||||||
"@sentry/types": "^6.19.7",
|
"@sentry/types": "^6.19.7",
|
||||||
"@swc/core": "^1.2.223",
|
"@swc/core": "^1.2.242",
|
||||||
"@swc/jest": "^0.2.22",
|
"@swc/jest": "^0.2.22",
|
||||||
"@testing-library/dom": "^7.31.2",
|
"@testing-library/dom": "^7.31.2",
|
||||||
"@testing-library/jest-dom": "^5.16.4",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^12.1.5",
|
"@testing-library/react": "^12.1.5",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"@types/byline": "^4.2.33",
|
"@types/byline": "^4.2.33",
|
||||||
@ -325,12 +326,12 @@
|
|||||||
"@types/jest": "^28.1.6",
|
"@types/jest": "^28.1.6",
|
||||||
"@types/js-yaml": "^4.0.5",
|
"@types/js-yaml": "^4.0.5",
|
||||||
"@types/jsdom": "^16.2.14",
|
"@types/jsdom": "^16.2.14",
|
||||||
"@types/lodash": "^4.14.181",
|
"@types/lodash": "^4.14.184",
|
||||||
"@types/marked": "^4.0.3",
|
"@types/marked": "^4.0.3",
|
||||||
"@types/md5-file": "^4.0.2",
|
"@types/md5-file": "^4.0.2",
|
||||||
"@types/mini-css-extract-plugin": "^2.4.0",
|
"@types/mini-css-extract-plugin": "^2.4.0",
|
||||||
"@types/mock-fs": "^4.13.1",
|
"@types/mock-fs": "^4.13.1",
|
||||||
"@types/node": "^16.11.47",
|
"@types/node": "^16.11.55",
|
||||||
"@types/node-fetch": "^2.6.2",
|
"@types/node-fetch": "^2.6.2",
|
||||||
"@types/npm": "^2.0.32",
|
"@types/npm": "^2.0.32",
|
||||||
"@types/proper-lockfile": "^4.1.2",
|
"@types/proper-lockfile": "^4.1.2",
|
||||||
@ -357,9 +358,9 @@
|
|||||||
"@types/uuid": "^8.3.4",
|
"@types/uuid": "^8.3.4",
|
||||||
"@types/webpack": "^5.28.0",
|
"@types/webpack": "^5.28.0",
|
||||||
"@types/webpack-dev-server": "^4.7.2",
|
"@types/webpack-dev-server": "^4.7.2",
|
||||||
"@types/webpack-env": "^1.17.0",
|
"@types/webpack-env": "^1.18.0",
|
||||||
"@types/webpack-node-externals": "^2.5.3",
|
"@types/webpack-node-externals": "^2.5.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.32.0",
|
"@typescript-eslint/eslint-plugin": "^5.34.0",
|
||||||
"@typescript-eslint/parser": "^5.31.0",
|
"@typescript-eslint/parser": "^5.31.0",
|
||||||
"adr": "^1.4.1",
|
"adr": "^1.4.1",
|
||||||
"ansi_up": "^5.1.0",
|
"ansi_up": "^5.1.0",
|
||||||
@ -372,10 +373,10 @@
|
|||||||
"css-loader": "^6.7.1",
|
"css-loader": "^6.7.1",
|
||||||
"deepdash": "^5.3.9",
|
"deepdash": "^5.3.9",
|
||||||
"dompurify": "^2.3.10",
|
"dompurify": "^2.3.10",
|
||||||
"electron": "^19.0.4",
|
"electron": "^19.0.13",
|
||||||
"electron-builder": "^23.3.3",
|
"electron-builder": "^23.3.3",
|
||||||
"electron-notarize": "^0.3.0",
|
"electron-notarize": "^0.3.0",
|
||||||
"esbuild": "^0.14.53",
|
"esbuild": "^0.15.5",
|
||||||
"esbuild-loader": "^2.19.0",
|
"esbuild-loader": "^2.19.0",
|
||||||
"eslint": "^8.21.0",
|
"eslint": "^8.21.0",
|
||||||
"eslint-plugin-header": "^3.1.1",
|
"eslint-plugin-header": "^3.1.1",
|
||||||
@ -412,7 +413,7 @@
|
|||||||
"react-select": "^5.4.0",
|
"react-select": "^5.4.0",
|
||||||
"react-select-event": "^5.5.1",
|
"react-select-event": "^5.5.1",
|
||||||
"react-window": "^1.8.7",
|
"react-window": "^1.8.7",
|
||||||
"sass": "^1.54.2",
|
"sass": "^1.54.5",
|
||||||
"sass-loader": "^12.6.0",
|
"sass-loader": "^12.6.0",
|
||||||
"sharp": "^0.30.7",
|
"sharp": "^0.30.7",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
@ -428,7 +429,7 @@
|
|||||||
"typescript-plugin-css-modules": "^3.4.0",
|
"typescript-plugin-css-modules": "^3.4.0",
|
||||||
"webpack": "^5.74.0",
|
"webpack": "^5.74.0",
|
||||||
"webpack-cli": "^4.9.2",
|
"webpack-cli": "^4.9.2",
|
||||||
"webpack-dev-server": "^4.9.3",
|
"webpack-dev-server": "^4.10.0",
|
||||||
"webpack-node-externals": "^3.0.0",
|
"webpack-node-externals": "^3.0.0",
|
||||||
"xterm": "^4.19.0",
|
"xterm": "^4.19.0",
|
||||||
"xterm-addon-fit": "^0.5.0"
|
"xterm-addon-fit": "^0.5.0"
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { action, comparer, computed, makeObservable, observable, reaction, when } from "mobx";
|
import { action, comparer, computed, makeObservable, observable, reaction, when } from "mobx";
|
||||||
import { broadcastMessage } from "../ipc";
|
|
||||||
import type { ClusterContextHandler } from "../../main/context-handler/context-handler";
|
import type { ClusterContextHandler } from "../../main/context-handler/context-handler";
|
||||||
import type { KubeConfig } from "@kubernetes/client-node";
|
import type { KubeConfig } from "@kubernetes/client-node";
|
||||||
import { HttpError } from "@kubernetes/client-node";
|
import { HttpError } from "@kubernetes/client-node";
|
||||||
@ -25,6 +24,7 @@ import type { CanI } from "./authorization-review.injectable";
|
|||||||
import type { ListNamespaces } from "./list-namespaces.injectable";
|
import type { ListNamespaces } from "./list-namespaces.injectable";
|
||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
import type { Logger } from "../logger";
|
import type { Logger } from "../logger";
|
||||||
|
import type { BroadcastMessage } from "../ipc/broadcast-message.injectable";
|
||||||
|
|
||||||
export interface ClusterDependencies {
|
export interface ClusterDependencies {
|
||||||
readonly directoryForKubeConfigs: string;
|
readonly directoryForKubeConfigs: string;
|
||||||
@ -36,6 +36,7 @@ export interface ClusterDependencies {
|
|||||||
createAuthorizationReview: (config: KubeConfig) => CanI;
|
createAuthorizationReview: (config: KubeConfig) => CanI;
|
||||||
createListNamespaces: (config: KubeConfig) => ListNamespaces;
|
createListNamespaces: (config: KubeConfig) => ListNamespaces;
|
||||||
createVersionDetector: (cluster: Cluster) => VersionDetector;
|
createVersionDetector: (cluster: Cluster) => VersionDetector;
|
||||||
|
broadcastMessage: BroadcastMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -602,7 +603,7 @@ export class Cluster implements ClusterModel, ClusterState {
|
|||||||
*/
|
*/
|
||||||
pushState(state = this.getState()) {
|
pushState(state = this.getState()) {
|
||||||
this.dependencies.logger.silly(`[CLUSTER]: push-state`, state);
|
this.dependencies.logger.silly(`[CLUSTER]: push-state`, state);
|
||||||
broadcastMessage("cluster:state", this.id, state);
|
this.dependencies.broadcastMessage("cluster:state", this.id, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get cluster system meta, e.g. use in "logger"
|
// get cluster system meta, e.g. use in "logger"
|
||||||
@ -625,7 +626,7 @@ export class Cluster implements ClusterModel, ClusterState {
|
|||||||
const update: KubeAuthUpdate = { message, isError };
|
const update: KubeAuthUpdate = { message, isError };
|
||||||
|
|
||||||
this.dependencies.logger.debug(`[CLUSTER]: broadcasting connection update`, { ...update, meta: this.getMeta() });
|
this.dependencies.logger.debug(`[CLUSTER]: broadcasting connection update`, { ...update, meta: this.getMeta() });
|
||||||
broadcastMessage(`cluster:${this.id}:connection-update`, update);
|
this.dependencies.broadcastMessage(`cluster:${this.id}:connection-update`, update);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getAllowedNamespaces(proxyConfig: KubeConfig) {
|
protected async getAllowedNamespaces(proxyConfig: KubeConfig) {
|
||||||
@ -645,7 +646,7 @@ export class Cluster implements ClusterModel, ClusterState {
|
|||||||
const { response } = error as HttpError & { response: Response };
|
const { response } = error as HttpError & { response: Response };
|
||||||
|
|
||||||
this.dependencies.logger.info("[CLUSTER]: listing namespaces is forbidden, broadcasting", { clusterId: this.id, error: response.body });
|
this.dependencies.logger.info("[CLUSTER]: listing namespaces is forbidden, broadcasting", { clusterId: this.id, error: response.body });
|
||||||
broadcastMessage(clusterListNamespaceForbiddenChannel, this.id);
|
this.dependencies.broadcastMessage(clusterListNamespaceForbiddenChannel, this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return namespaceList;
|
return namespaceList;
|
||||||
|
|||||||
10
src/common/fs/stat/stat.global-override-for-injectable.ts
Normal file
10
src/common/fs/stat/stat.global-override-for-injectable.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import statInjectable from "./stat.injectable";
|
||||||
|
import { getGlobalOverride } from "../../test-utils/get-global-override";
|
||||||
|
|
||||||
|
export default getGlobalOverride(statInjectable, () => () => {
|
||||||
|
throw new Error("Tried to call stat without explicit override");
|
||||||
|
});
|
||||||
14
src/common/fs/stat/stat.injectable.ts
Normal file
14
src/common/fs/stat/stat.injectable.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import fsInjectable from "../fs.injectable";
|
||||||
|
|
||||||
|
const statInjectable = getInjectable({
|
||||||
|
id: "stat",
|
||||||
|
|
||||||
|
instantiate: (di) => di.inject(fsInjectable).stat,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default statInjectable;
|
||||||
76
src/common/fs/validate-directory.injectable.ts
Normal file
76
src/common/fs/validate-directory.injectable.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import type { AsyncResult } from "../utils/async-result";
|
||||||
|
import { isErrnoException } from "../utils";
|
||||||
|
import type { Stats } from "fs-extra";
|
||||||
|
import { lowerFirst } from "lodash/fp";
|
||||||
|
import statInjectable from "./stat/stat.injectable";
|
||||||
|
|
||||||
|
export type ValidateDirectory = (path: string) => Promise<AsyncResult<undefined>>;
|
||||||
|
|
||||||
|
function getUserReadableFileType(stats: Stats): string {
|
||||||
|
if (stats.isFile()) {
|
||||||
|
return "a file";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats.isFIFO()) {
|
||||||
|
return "a pipe";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats.isSocket()) {
|
||||||
|
return "a socket";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats.isBlockDevice()) {
|
||||||
|
return "a block device";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats.isCharacterDevice()) {
|
||||||
|
return "a character device";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "an unknown file type";
|
||||||
|
}
|
||||||
|
|
||||||
|
const validateDirectoryInjectable = getInjectable({
|
||||||
|
id: "validate-directory",
|
||||||
|
|
||||||
|
instantiate: (di): ValidateDirectory => {
|
||||||
|
const stat = di.inject(statInjectable);
|
||||||
|
|
||||||
|
return async (path) => {
|
||||||
|
try {
|
||||||
|
const stats = await stat(path);
|
||||||
|
|
||||||
|
if (stats.isDirectory()) {
|
||||||
|
return { callWasSuccessful: true, response: undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { callWasSuccessful: false, error: `the provided path is ${getUserReadableFileType(stats)} and not a directory.` };
|
||||||
|
} catch (error) {
|
||||||
|
if (!isErrnoException(error)) {
|
||||||
|
return { callWasSuccessful: false, error: "of an unknown error, please try again." };
|
||||||
|
}
|
||||||
|
|
||||||
|
const humanReadableErrors: Record<string, string> = {
|
||||||
|
ENOENT: "the provided path does not exist.",
|
||||||
|
EACCES: "search permissions is denied for one of the directories in the prefix of the provided path.",
|
||||||
|
ELOOP: "the provided path is a sym-link which points to a chain of sym-links that is too long to resolve. Perhaps it is cyclic.",
|
||||||
|
ENAMETOOLONG: "the pathname is too long to be used.",
|
||||||
|
ENOTDIR: "a prefix of the provided path is not a directory.",
|
||||||
|
};
|
||||||
|
|
||||||
|
const humanReadableError = error.code
|
||||||
|
? humanReadableErrors[error.code]
|
||||||
|
: lowerFirst(String(error));
|
||||||
|
|
||||||
|
return { callWasSuccessful: false, error: humanReadableError };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default validateDirectoryInjectable;
|
||||||
10
src/common/fs/watch/watch.global-override-for-injectable.ts
Normal file
10
src/common/fs/watch/watch.global-override-for-injectable.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getGlobalOverride } from "../../test-utils/get-global-override";
|
||||||
|
import watchInjectable from "./watch.injectable";
|
||||||
|
|
||||||
|
export default getGlobalOverride(watchInjectable, () => () => {
|
||||||
|
throw new Error("Tried to call file system watch without explicit override");
|
||||||
|
});
|
||||||
18
src/common/fs/watch/watch.injectable.ts
Normal file
18
src/common/fs/watch/watch.injectable.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import type { FSWatcher, WatchOptions } from "chokidar";
|
||||||
|
import { watch } from "chokidar";
|
||||||
|
|
||||||
|
export type Watch = (path: string, options?: WatchOptions) => FSWatcher;
|
||||||
|
|
||||||
|
// TODO: Introduce wrapper to allow simpler API
|
||||||
|
const watchInjectable = getInjectable({
|
||||||
|
id: "watch",
|
||||||
|
instantiate: (): Watch => watch,
|
||||||
|
causesSideEffects: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default watchInjectable;
|
||||||
@ -5,9 +5,11 @@
|
|||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { broadcastMessage } from "./ipc";
|
import { broadcastMessage } from "./ipc";
|
||||||
|
|
||||||
|
export type BroadcastMessage = (channel: string, ...args: any[]) => Promise<void>;
|
||||||
|
|
||||||
const broadcastMessageInjectable = getInjectable({
|
const broadcastMessageInjectable = getInjectable({
|
||||||
id: "broadcast-message",
|
id: "broadcast-message",
|
||||||
instantiate: () => broadcastMessage,
|
instantiate: (): BroadcastMessage => broadcastMessage,
|
||||||
causesSideEffects: true,
|
causesSideEffects: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -13,10 +13,17 @@ import logger from "../../main/logger";
|
|||||||
import type { ClusterFrameInfo } from "../cluster-frames";
|
import type { ClusterFrameInfo } from "../cluster-frames";
|
||||||
import { clusterFrameMap } from "../cluster-frames";
|
import { clusterFrameMap } from "../cluster-frames";
|
||||||
import type { Disposer } from "../utils";
|
import type { Disposer } from "../utils";
|
||||||
|
import ipcMainInjectable from "../../main/utils/channel/ipc-main/ipc-main.injectable";
|
||||||
|
import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||||
|
import ipcRendererInjectable from "../../renderer/utils/channel/ipc-renderer.injectable";
|
||||||
|
|
||||||
export const broadcastMainChannel = "ipc:broadcast-main";
|
export const broadcastMainChannel = "ipc:broadcast-main";
|
||||||
|
|
||||||
export function ipcMainHandle(channel: string, listener: (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any) {
|
export function ipcMainHandle(channel: string, listener: (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any) {
|
||||||
|
const di = getLegacyGlobalDiForExtensionApi();
|
||||||
|
|
||||||
|
const ipcMain = di.inject(ipcMainInjectable);
|
||||||
|
|
||||||
ipcMain.handle(channel, async (event, ...args) => {
|
ipcMain.handle(channel, async (event, ...args) => {
|
||||||
return sanitizePayload(await listener(event, ...args));
|
return sanitizePayload(await listener(event, ...args));
|
||||||
});
|
});
|
||||||
@ -78,12 +85,20 @@ export async function broadcastMessage(channel: string, ...args: any[]): Promise
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ipcMainOn(channel: string, listener: (event: Electron.IpcMainEvent, ...args: any[]) => any): Disposer {
|
export function ipcMainOn(channel: string, listener: (event: Electron.IpcMainEvent, ...args: any[]) => any): Disposer {
|
||||||
|
const di = getLegacyGlobalDiForExtensionApi();
|
||||||
|
|
||||||
|
const ipcMain = di.inject(ipcMainInjectable);
|
||||||
|
|
||||||
ipcMain.on(channel, listener);
|
ipcMain.on(channel, listener);
|
||||||
|
|
||||||
return () => ipcMain.off(channel, listener);
|
return () => ipcMain.off(channel, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ipcRendererOn(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer {
|
export function ipcRendererOn(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer {
|
||||||
|
const di = getLegacyGlobalDiForExtensionApi();
|
||||||
|
|
||||||
|
const ipcRenderer = di.inject(ipcRendererInjectable);
|
||||||
|
|
||||||
ipcRenderer.on(channel, listener);
|
ipcRenderer.on(channel, listener);
|
||||||
|
|
||||||
return () => ipcRenderer.off(channel, listener);
|
return () => ipcRenderer.off(channel, listener);
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { DeploymentApi, Ingress, IngressApi, Pod, PodApi } from "../endpoints";
|
|||||||
import { getDiForUnitTesting } from "../../../renderer/getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../../renderer/getDiForUnitTesting";
|
||||||
import apiManagerInjectable from "../api-manager/manager.injectable";
|
import apiManagerInjectable from "../api-manager/manager.injectable";
|
||||||
import autoRegistrationInjectable from "../api-manager/auto-registration.injectable";
|
import autoRegistrationInjectable from "../api-manager/auto-registration.injectable";
|
||||||
|
import AbortController from "abort-controller";
|
||||||
|
|
||||||
jest.mock("../api-manager");
|
jest.mock("../api-manager");
|
||||||
|
|
||||||
|
|||||||
@ -840,6 +840,10 @@ export class Pod extends KubeObject<
|
|||||||
return this.spec?.priorityClassName || "";
|
return this.spec?.priorityClassName || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getServiceAccountName() {
|
||||||
|
return this.spec?.serviceAccountName || "";
|
||||||
|
}
|
||||||
|
|
||||||
getStatus(): PodStatusPhase {
|
getStatus(): PodStatusPhase {
|
||||||
const phase = this.getStatusPhase();
|
const phase = this.getStatusPhase();
|
||||||
const reason = this.getReason();
|
const reason = this.getReason();
|
||||||
|
|||||||
@ -27,9 +27,7 @@ import type { PartialDeep } from "type-fest";
|
|||||||
import logger from "../logger";
|
import logger from "../logger";
|
||||||
import { Environments, getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
import { Environments, getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||||
import autoRegistrationEmitterInjectable from "./api-manager/auto-registration-emitter.injectable";
|
import autoRegistrationEmitterInjectable from "./api-manager/auto-registration-emitter.injectable";
|
||||||
|
import type AbortController from "abort-controller";
|
||||||
// TODO: upgrade node-fetch once we are starting to use ES modules
|
|
||||||
type LegacyAbortSignal = NonNullable<RequestInit["signal"]>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The options used for creating a `KubeApi`
|
* The options used for creating a `KubeApi`
|
||||||
@ -719,7 +717,7 @@ export class KubeApi<
|
|||||||
const requestParams = timeout ? { query: { timeoutSeconds: timeout }} : {};
|
const requestParams = timeout ? { query: { timeoutSeconds: timeout }} : {};
|
||||||
const watchUrl = this.getWatchUrl(namespace);
|
const watchUrl = this.getWatchUrl(namespace);
|
||||||
const responsePromise = this.request.getResponse(watchUrl, requestParams, {
|
const responsePromise = this.request.getResponse(watchUrl, requestParams, {
|
||||||
signal: abortController.signal as LegacyAbortSignal,
|
signal: abortController.signal,
|
||||||
timeout: 600_000,
|
timeout: 600_000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -20,9 +20,7 @@ import logger from "../logger";
|
|||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
import type { PartialDeep } from "type-fest";
|
import type { PartialDeep } from "type-fest";
|
||||||
import { entries } from "../utils/objects";
|
import { entries } from "../utils/objects";
|
||||||
|
import AbortController from "abort-controller";
|
||||||
// TODO: upgrade node-fetch once we are starting to use ES modules
|
|
||||||
type LegacyAbortSignal = NonNullable<RequestInit["signal"]>;
|
|
||||||
|
|
||||||
export type OnLoadFailure = (error: unknown) => void;
|
export type OnLoadFailure = (error: unknown) => void;
|
||||||
|
|
||||||
@ -480,7 +478,7 @@ export abstract class KubeObjectStore<
|
|||||||
});
|
});
|
||||||
|
|
||||||
// TODO: upgrade node-fetch once we are starting to use ES modules
|
// TODO: upgrade node-fetch once we are starting to use ES modules
|
||||||
const signal = abortController.signal as LegacyAbortSignal;
|
const signal = abortController.signal;
|
||||||
|
|
||||||
const callback: KubeApiWatchCallback<D> = (data, error) => {
|
const callback: KubeApiWatchCallback<D> = (data, error) => {
|
||||||
if (!this.isLoaded || error?.type === "aborted") return;
|
if (!this.isLoaded || error?.type === "aborted") return;
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import { matchPath } from "react-router";
|
|||||||
import { countBy } from "lodash";
|
import { countBy } from "lodash";
|
||||||
import { isDefined, iter } from "../utils";
|
import { isDefined, iter } from "../utils";
|
||||||
import { pathToRegexp } from "path-to-regexp";
|
import { pathToRegexp } from "path-to-regexp";
|
||||||
import logger from "../../main/logger";
|
|
||||||
import type Url from "url-parse";
|
import type Url from "url-parse";
|
||||||
import { RoutingError, RoutingErrorType } from "./error";
|
import { RoutingError, RoutingErrorType } from "./error";
|
||||||
import type { ExtensionsStore } from "../../extensions/extensions-store/extensions-store";
|
import type { ExtensionsStore } from "../../extensions/extensions-store/extensions-store";
|
||||||
@ -17,6 +16,7 @@ import type { LensExtension } from "../../extensions/lens-extension";
|
|||||||
import type { RouteHandler, RouteParams } from "../../extensions/registries/protocol-handler";
|
import type { RouteHandler, RouteParams } from "../../extensions/registries/protocol-handler";
|
||||||
import { when } from "mobx";
|
import { when } from "mobx";
|
||||||
import { ipcRenderer } from "electron";
|
import { ipcRenderer } from "electron";
|
||||||
|
import type { Logger } from "../logger";
|
||||||
|
|
||||||
// IPC channel for protocol actions. Main broadcasts the open-url events to this channel.
|
// IPC channel for protocol actions. Main broadcasts the open-url events to this channel.
|
||||||
export const ProtocolHandlerIpcPrefix = "protocol-handler";
|
export const ProtocolHandlerIpcPrefix = "protocol-handler";
|
||||||
@ -66,6 +66,7 @@ export function foldAttemptResults(mainAttempt: RouteAttempt, rendererAttempt: R
|
|||||||
export interface LensProtocolRouterDependencies {
|
export interface LensProtocolRouterDependencies {
|
||||||
readonly extensionLoader: ExtensionLoader;
|
readonly extensionLoader: ExtensionLoader;
|
||||||
readonly extensionsStore: ExtensionsStore;
|
readonly extensionsStore: ExtensionsStore;
|
||||||
|
readonly logger: Logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class LensProtocolRouter {
|
export abstract class LensProtocolRouter {
|
||||||
@ -130,7 +131,7 @@ export abstract class LensProtocolRouter {
|
|||||||
data.extensionName = extensionName;
|
data.extensionName = extensionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`${LensProtocolRouter.LoggingPrefix}: No handler found`, data);
|
this.dependencies.logger.info(`${LensProtocolRouter.LoggingPrefix}: No handler found`, data);
|
||||||
|
|
||||||
return RouteAttempt.MISSING;
|
return RouteAttempt.MISSING;
|
||||||
}
|
}
|
||||||
@ -183,7 +184,7 @@ export abstract class LensProtocolRouter {
|
|||||||
timeout: 5_000,
|
timeout: 5_000,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.info(
|
this.dependencies.logger.info(
|
||||||
`${LensProtocolRouter.LoggingPrefix}: Extension ${name} matched, but not installed (${error})`,
|
`${LensProtocolRouter.LoggingPrefix}: Extension ${name} matched, but not installed (${error})`,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -193,18 +194,18 @@ export abstract class LensProtocolRouter {
|
|||||||
const extension = extensionLoader.getInstanceByName(name);
|
const extension = extensionLoader.getInstanceByName(name);
|
||||||
|
|
||||||
if (!extension) {
|
if (!extension) {
|
||||||
logger.info(`${LensProtocolRouter.LoggingPrefix}: Extension ${name} matched, but does not have a class for ${ipcRenderer ? "renderer" : "main"}`);
|
this.dependencies.logger.info(`${LensProtocolRouter.LoggingPrefix}: Extension ${name} matched, but does not have a class for ${ipcRenderer ? "renderer" : "main"}`);
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.dependencies.extensionsStore.isEnabled(extension)) {
|
if (!this.dependencies.extensionsStore.isEnabled(extension)) {
|
||||||
logger.info(`${LensProtocolRouter.LoggingPrefix}: Extension ${name} matched, but not enabled`);
|
this.dependencies.logger.info(`${LensProtocolRouter.LoggingPrefix}: Extension ${name} matched, but not enabled`);
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`${LensProtocolRouter.LoggingPrefix}: Extension ${name} matched`);
|
this.dependencies.logger.info(`${LensProtocolRouter.LoggingPrefix}: Extension ${name} matched`);
|
||||||
|
|
||||||
return extension;
|
return extension;
|
||||||
}
|
}
|
||||||
@ -250,7 +251,7 @@ export abstract class LensProtocolRouter {
|
|||||||
*/
|
*/
|
||||||
public addInternalHandler(urlSchema: string, handler: RouteHandler): this {
|
public addInternalHandler(urlSchema: string, handler: RouteHandler): this {
|
||||||
pathToRegexp(urlSchema); // verify now that the schema is valid
|
pathToRegexp(urlSchema); // verify now that the schema is valid
|
||||||
logger.info(`${LensProtocolRouter.LoggingPrefix}: internal registering ${urlSchema}`);
|
this.dependencies.logger.info(`${LensProtocolRouter.LoggingPrefix}: internal registering ${urlSchema}`);
|
||||||
this.internalRoutes.set(urlSchema, handler);
|
this.internalRoutes.set(urlSchema, handler);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import AbortController from "abort-controller";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is like an `AbortController` but will also abort if the parent aborts,
|
* This is like an `AbortController` but will also abort if the parent aborts,
|
||||||
* but won't make the parent abort if this aborts (single direction)
|
* but won't make the parent abort if this aborts (single direction)
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type AbortController from "abort-controller";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a promise that will be resolved after at least `timeout` ms have
|
* Return a promise that will be resolved after at least `timeout` ms have
|
||||||
* passed. If `failFast` is provided then the promise is also resolved if it has
|
* passed. If `failFast` is provided then the promise is also resolved if it has
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { AbortSignal } from "abort-controller";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new promise that will be rejected when the signal rejects.
|
* Creates a new promise that will be rejected when the signal rejects.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -10,8 +10,10 @@ import extensionLoaderInjectable from "../extension-loader/extension-loader.inje
|
|||||||
import { runInAction } from "mobx";
|
import { runInAction } from "mobx";
|
||||||
import updateExtensionsStateInjectable from "../extension-loader/update-extensions-state/update-extensions-state.injectable";
|
import updateExtensionsStateInjectable from "../extension-loader/update-extensions-state/update-extensions-state.injectable";
|
||||||
import mockFs from "mock-fs";
|
import mockFs from "mock-fs";
|
||||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
|
||||||
import { delay } from "../../renderer/utils";
|
import { delay } from "../../renderer/utils";
|
||||||
|
import { getDiForUnitTesting } from "../../renderer/getDiForUnitTesting";
|
||||||
|
import ipcRendererInjectable from "../../renderer/utils/channel/ipc-renderer.injectable";
|
||||||
|
import type { IpcRenderer } from "electron";
|
||||||
|
|
||||||
console = new Console(stdout, stderr);
|
console = new Console(stdout, stderr);
|
||||||
|
|
||||||
@ -19,10 +21,14 @@ const manifestPath = "manifest/path";
|
|||||||
const manifestPath2 = "manifest/path2";
|
const manifestPath2 = "manifest/path2";
|
||||||
const manifestPath3 = "manifest/path3";
|
const manifestPath3 = "manifest/path3";
|
||||||
|
|
||||||
jest.mock(
|
describe("ExtensionLoader", () => {
|
||||||
"electron",
|
let extensionLoader: ExtensionLoader;
|
||||||
() => ({
|
let updateExtensionStateMock: jest.Mock;
|
||||||
ipcRenderer: {
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||||
|
|
||||||
|
di.override(ipcRendererInjectable, () => ({
|
||||||
invoke: jest.fn(async (channel: string) => {
|
invoke: jest.fn(async (channel: string) => {
|
||||||
if (channel === "extension-loader:main:state") {
|
if (channel === "extension-loader:main:state") {
|
||||||
return [
|
return [
|
||||||
@ -59,8 +65,8 @@ jest.mock(
|
|||||||
|
|
||||||
return [];
|
return [];
|
||||||
}),
|
}),
|
||||||
on: jest.fn(
|
|
||||||
(channel: string, listener: (event: any, ...args: any[]) => void) => {
|
on: (channel: string, listener: (event: any, ...args: any[]) => void) => {
|
||||||
if (channel === "extension-loader:main:state") {
|
if (channel === "extension-loader:main:state") {
|
||||||
// First initialize with extensions 1 and 2
|
// First initialize with extensions 1 and 2
|
||||||
// and then broadcast event to remove extension 2 and add extension number 3
|
// and then broadcast event to remove extension 2 and add extension number 3
|
||||||
@ -98,20 +104,7 @@ jest.mock(
|
|||||||
}, 10);
|
}, 10);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
}) as unknown as IpcRenderer);
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
virtual: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
describe("ExtensionLoader", () => {
|
|
||||||
let extensionLoader: ExtensionLoader;
|
|
||||||
let updateExtensionStateMock: jest.Mock;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
|
||||||
|
|
||||||
mockFs();
|
mockFs();
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,10 @@ import installExtensionInjectable from "../extension-installer/install-extension
|
|||||||
import extensionPackageRootDirectoryInjectable from "../extension-installer/extension-package-root-directory/extension-package-root-directory.injectable";
|
import extensionPackageRootDirectoryInjectable from "../extension-installer/extension-package-root-directory/extension-package-root-directory.injectable";
|
||||||
import installExtensionsInjectable from "../extension-installer/install-extensions/install-extensions.injectable";
|
import installExtensionsInjectable from "../extension-installer/install-extensions/install-extensions.injectable";
|
||||||
import staticFilesDirectoryInjectable from "../../common/vars/static-files-directory.injectable";
|
import staticFilesDirectoryInjectable from "../../common/vars/static-files-directory.injectable";
|
||||||
|
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
|
||||||
|
import loggerInjectable from "../../common/logger.injectable";
|
||||||
|
import pathExistsInjectable from "../../common/fs/path-exists.injectable";
|
||||||
|
import watchInjectable from "../../common/fs/watch/watch.injectable";
|
||||||
|
|
||||||
const extensionDiscoveryInjectable = getInjectable({
|
const extensionDiscoveryInjectable = getInjectable({
|
||||||
id: "extension-discovery",
|
id: "extension-discovery",
|
||||||
@ -40,6 +44,10 @@ const extensionDiscoveryInjectable = getInjectable({
|
|||||||
),
|
),
|
||||||
|
|
||||||
staticFilesDirectory: di.inject(staticFilesDirectoryInjectable),
|
staticFilesDirectory: di.inject(staticFilesDirectoryInjectable),
|
||||||
|
readJsonFile: di.inject(readJsonFileInjectable),
|
||||||
|
pathExists: di.inject(pathExistsInjectable),
|
||||||
|
watch: di.inject(watchInjectable),
|
||||||
|
logger: di.inject(loggerInjectable),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -4,53 +4,29 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { FSWatcher } from "chokidar";
|
import type { FSWatcher } from "chokidar";
|
||||||
import { watch } from "chokidar";
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import { Console } from "console";
|
import { Console } from "console";
|
||||||
import * as fse from "fs-extra";
|
|
||||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
||||||
import extensionDiscoveryInjectable from "../extension-discovery/extension-discovery.injectable";
|
import extensionDiscoveryInjectable from "../extension-discovery/extension-discovery.injectable";
|
||||||
import type { ExtensionDiscovery } from "../extension-discovery/extension-discovery";
|
import type { ExtensionDiscovery } from "../extension-discovery/extension-discovery";
|
||||||
import installExtensionInjectable
|
import installExtensionInjectable from "../extension-installer/install-extension/install-extension.injectable";
|
||||||
from "../extension-installer/install-extension/install-extension.injectable";
|
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||||
import directoryForUserDataInjectable
|
|
||||||
from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
|
||||||
import mockFs from "mock-fs";
|
import mockFs from "mock-fs";
|
||||||
import { delay } from "../../renderer/utils";
|
import { delay } from "../../renderer/utils";
|
||||||
import { observable, when } from "mobx";
|
import { observable, when } from "mobx";
|
||||||
import appVersionInjectable from "../../common/vars/app-version.injectable";
|
import appVersionInjectable from "../../common/vars/app-version.injectable";
|
||||||
|
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
|
||||||
jest.setTimeout(60_000);
|
import pathExistsInjectable from "../../common/fs/path-exists.injectable";
|
||||||
|
import watchInjectable from "../../common/fs/watch/watch.injectable";
|
||||||
jest.mock("../../common/ipc");
|
|
||||||
jest.mock("chokidar", () => ({
|
|
||||||
watch: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
jest.mock("fs-extra");
|
|
||||||
jest.mock("electron", () => ({
|
|
||||||
app: {
|
|
||||||
getVersion: () => "99.99.99",
|
|
||||||
getName: () => "lens",
|
|
||||||
setName: jest.fn(),
|
|
||||||
setPath: jest.fn(),
|
|
||||||
getPath: () => "tmp",
|
|
||||||
getLocale: () => "en",
|
|
||||||
setLoginItemSettings: jest.fn(),
|
|
||||||
},
|
|
||||||
ipcMain: {
|
|
||||||
on: jest.fn(),
|
|
||||||
handle: jest.fn(),
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
console = new Console(process.stdout, process.stderr); // fix mockFS
|
console = new Console(process.stdout, process.stderr); // fix mockFS
|
||||||
const mockedWatch = watch as jest.MockedFunction<typeof watch>;
|
|
||||||
const mockedFse = fse as jest.Mocked<typeof fse>;
|
|
||||||
|
|
||||||
describe("ExtensionDiscovery", () => {
|
describe("ExtensionDiscovery", () => {
|
||||||
let extensionDiscovery: ExtensionDiscovery;
|
let extensionDiscovery: ExtensionDiscovery;
|
||||||
|
let readJsonFileMock: jest.Mock;
|
||||||
|
let pathExistsMock: jest.Mock;
|
||||||
|
let watchMock: jest.Mock;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||||
@ -59,6 +35,15 @@ describe("ExtensionDiscovery", () => {
|
|||||||
di.override(installExtensionInjectable, () => () => Promise.resolve());
|
di.override(installExtensionInjectable, () => () => Promise.resolve());
|
||||||
di.override(appVersionInjectable, () => "5.0.0");
|
di.override(appVersionInjectable, () => "5.0.0");
|
||||||
|
|
||||||
|
readJsonFileMock = jest.fn();
|
||||||
|
di.override(readJsonFileInjectable, () => readJsonFileMock);
|
||||||
|
|
||||||
|
pathExistsMock = jest.fn(() => Promise.resolve(true));
|
||||||
|
di.override(pathExistsInjectable, () => pathExistsMock);
|
||||||
|
|
||||||
|
watchMock = jest.fn();
|
||||||
|
di.override(watchInjectable, () => watchMock);
|
||||||
|
|
||||||
mockFs();
|
mockFs();
|
||||||
|
|
||||||
extensionDiscovery = di.inject(extensionDiscoveryInjectable);
|
extensionDiscovery = di.inject(extensionDiscoveryInjectable);
|
||||||
@ -72,7 +57,7 @@ describe("ExtensionDiscovery", () => {
|
|||||||
const letTestFinish = observable.box(false);
|
const letTestFinish = observable.box(false);
|
||||||
let addHandler!: (filePath: string) => void;
|
let addHandler!: (filePath: string) => void;
|
||||||
|
|
||||||
mockedFse.readJson.mockImplementation((p) => {
|
readJsonFileMock.mockImplementation((p) => {
|
||||||
expect(p).toBe(path.join(os.homedir(), ".k8slens/extensions/my-extension/package.json"));
|
expect(p).toBe(path.join(os.homedir(), ".k8slens/extensions/my-extension/package.json"));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -84,8 +69,6 @@ describe("ExtensionDiscovery", () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
mockedFse.pathExists.mockImplementation(() => true);
|
|
||||||
|
|
||||||
const mockWatchInstance = {
|
const mockWatchInstance = {
|
||||||
on: jest.fn((event: string, handler: typeof addHandler) => {
|
on: jest.fn((event: string, handler: typeof addHandler) => {
|
||||||
if (event === "add") {
|
if (event === "add") {
|
||||||
@ -96,7 +79,7 @@ describe("ExtensionDiscovery", () => {
|
|||||||
}),
|
}),
|
||||||
} as unknown as FSWatcher;
|
} as unknown as FSWatcher;
|
||||||
|
|
||||||
mockedWatch.mockImplementationOnce(() => mockWatchInstance);
|
watchMock.mockImplementationOnce(() => mockWatchInstance);
|
||||||
|
|
||||||
// Need to force isLoaded to be true so that the file watching is started
|
// Need to force isLoaded to be true so that the file watching is started
|
||||||
extensionDiscovery.isLoaded = true;
|
extensionDiscovery.isLoaded = true;
|
||||||
@ -139,7 +122,7 @@ describe("ExtensionDiscovery", () => {
|
|||||||
}),
|
}),
|
||||||
} as unknown as FSWatcher;
|
} as unknown as FSWatcher;
|
||||||
|
|
||||||
mockedWatch.mockImplementationOnce(() => mockWatchInstance);
|
watchMock.mockImplementationOnce(() => mockWatchInstance);
|
||||||
|
|
||||||
// Need to force isLoaded to be true so that the file watching is started
|
// Need to force isLoaded to be true so that the file watching is started
|
||||||
extensionDiscovery.isLoaded = true;
|
extensionDiscovery.isLoaded = true;
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { watch } from "chokidar";
|
|
||||||
import { ipcRenderer } from "electron";
|
import { ipcRenderer } from "electron";
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import fse from "fs-extra";
|
import fse from "fs-extra";
|
||||||
@ -12,7 +11,6 @@ import os from "os";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import { broadcastMessage, ipcMainHandle, ipcRendererOn } from "../../common/ipc";
|
import { broadcastMessage, ipcMainHandle, ipcRendererOn } from "../../common/ipc";
|
||||||
import { isErrnoException, toJS } from "../../common/utils";
|
import { isErrnoException, toJS } from "../../common/utils";
|
||||||
import logger from "../../main/logger";
|
|
||||||
import type { ExtensionsStore } from "../extensions-store/extensions-store";
|
import type { ExtensionsStore } from "../extensions-store/extensions-store";
|
||||||
import type { ExtensionLoader } from "../extension-loader";
|
import type { ExtensionLoader } from "../extension-loader";
|
||||||
import type { LensExtensionId, LensExtensionManifest } from "../lens-extension";
|
import type { LensExtensionId, LensExtensionManifest } from "../lens-extension";
|
||||||
@ -21,6 +19,10 @@ import type { ExtensionInstallationStateStore } from "../extension-installation-
|
|||||||
import type { PackageJson } from "type-fest";
|
import type { PackageJson } from "type-fest";
|
||||||
import { extensionDiscoveryStateChannel } from "../../common/ipc/extension-handling";
|
import { extensionDiscoveryStateChannel } from "../../common/ipc/extension-handling";
|
||||||
import { requestInitialExtensionDiscovery } from "../../renderer/ipc";
|
import { requestInitialExtensionDiscovery } from "../../renderer/ipc";
|
||||||
|
import type { ReadJson } from "../../common/fs/read-json-file.injectable";
|
||||||
|
import type { Logger } from "../../common/logger";
|
||||||
|
import type { PathExists } from "../../common/fs/path-exists.injectable";
|
||||||
|
import type { Watch } from "../../common/fs/watch/watch.injectable";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
extensionLoader: ExtensionLoader;
|
extensionLoader: ExtensionLoader;
|
||||||
@ -35,6 +37,10 @@ interface Dependencies {
|
|||||||
installExtensions: (packageJsonPath: string, packagesJson: PackageJson) => Promise<void>;
|
installExtensions: (packageJsonPath: string, packagesJson: PackageJson) => Promise<void>;
|
||||||
extensionPackageRootDirectory: string;
|
extensionPackageRootDirectory: string;
|
||||||
staticFilesDirectory: string;
|
staticFilesDirectory: string;
|
||||||
|
readJsonFile: ReadJson;
|
||||||
|
pathExists: PathExists;
|
||||||
|
watch: Watch;
|
||||||
|
logger: Logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InstalledExtension {
|
export interface InstalledExtension {
|
||||||
@ -155,13 +161,12 @@ export class ExtensionDiscovery {
|
|||||||
* Dependencies are installed automatically after an extension folder is copied.
|
* Dependencies are installed automatically after an extension folder is copied.
|
||||||
*/
|
*/
|
||||||
async watchExtensions(): Promise<void> {
|
async watchExtensions(): Promise<void> {
|
||||||
logger.info(`${logModule} watching extension add/remove in ${this.localFolderPath}`);
|
this.dependencies.logger.info(`${logModule} watching extension add/remove in ${this.localFolderPath}`);
|
||||||
|
|
||||||
// Wait until .load() has been called and has been resolved
|
// Wait until .load() has been called and has been resolved
|
||||||
await this.whenLoaded;
|
await this.whenLoaded;
|
||||||
|
|
||||||
// chokidar works better than fs.watch
|
this.dependencies.watch(this.localFolderPath, {
|
||||||
watch(this.localFolderPath, {
|
|
||||||
// For adding and removing symlinks to work, the depth has to be 1.
|
// For adding and removing symlinks to work, the depth has to be 1.
|
||||||
depth: 1,
|
depth: 1,
|
||||||
ignoreInitial: true,
|
ignoreInitial: true,
|
||||||
@ -206,11 +211,11 @@ export class ExtensionDiscovery {
|
|||||||
await this.dependencies.installExtension(extension.absolutePath);
|
await this.dependencies.installExtension(extension.absolutePath);
|
||||||
|
|
||||||
this.extensions.set(extension.id, extension);
|
this.extensions.set(extension.id, extension);
|
||||||
logger.info(`${logModule} Added extension ${extension.manifest.name}`);
|
this.dependencies.logger.info(`${logModule} Added extension ${extension.manifest.name}`);
|
||||||
this.events.emit("add", extension);
|
this.events.emit("add", extension);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`${logModule}: failed to add extension: ${error}`, { error });
|
this.dependencies.logger.error(`${logModule}: failed to add extension: ${error}`, { error });
|
||||||
} finally {
|
} finally {
|
||||||
this.dependencies.extensionInstallationStateStore.clearInstallingFromMain(manifestPath);
|
this.dependencies.extensionInstallationStateStore.clearInstallingFromMain(manifestPath);
|
||||||
}
|
}
|
||||||
@ -247,13 +252,13 @@ export class ExtensionDiscovery {
|
|||||||
const lensExtensionId = extension.manifestPath;
|
const lensExtensionId = extension.manifestPath;
|
||||||
|
|
||||||
this.extensions.delete(extension.id);
|
this.extensions.delete(extension.id);
|
||||||
logger.info(`${logModule} removed extension ${extensionName}`);
|
this.dependencies.logger.info(`${logModule} removed extension ${extensionName}`);
|
||||||
this.events.emit("remove", lensExtensionId);
|
this.events.emit("remove", lensExtensionId);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.warn(`${logModule} extension ${extensionFolderName} not found, can't remove`);
|
this.dependencies.logger.warn(`${logModule} extension ${extensionFolderName} not found, can't remove`);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -275,12 +280,12 @@ export class ExtensionDiscovery {
|
|||||||
const extension = this.extensions.get(extensionId) ?? this.dependencies.extensionLoader.getExtension(extensionId);
|
const extension = this.extensions.get(extensionId) ?? this.dependencies.extensionLoader.getExtension(extensionId);
|
||||||
|
|
||||||
if (!extension) {
|
if (!extension) {
|
||||||
return void logger.warn(`${logModule} could not uninstall extension, not found`, { id: extensionId });
|
return void this.dependencies.logger.warn(`${logModule} could not uninstall extension, not found`, { id: extensionId });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { manifest, absolutePath } = extension;
|
const { manifest, absolutePath } = extension;
|
||||||
|
|
||||||
logger.info(`${logModule} Uninstalling ${manifest.name}`);
|
this.dependencies.logger.info(`${logModule} Uninstalling ${manifest.name}`);
|
||||||
|
|
||||||
await this.removeSymlinkByPackageName(manifest.name);
|
await this.removeSymlinkByPackageName(manifest.name);
|
||||||
|
|
||||||
@ -296,7 +301,7 @@ export class ExtensionDiscovery {
|
|||||||
|
|
||||||
this.loadStarted = true;
|
this.loadStarted = true;
|
||||||
|
|
||||||
logger.info(
|
this.dependencies.logger.info(
|
||||||
`${logModule} loading extensions from ${this.dependencies.extensionPackageRootDirectory}`,
|
`${logModule} loading extensions from ${this.dependencies.extensionPackageRootDirectory}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -358,12 +363,12 @@ export class ExtensionDiscovery {
|
|||||||
*/
|
*/
|
||||||
protected async getByManifest(manifestPath: string, { isBundled = false } = {}): Promise<InstalledExtension | null> {
|
protected async getByManifest(manifestPath: string, { isBundled = false } = {}): Promise<InstalledExtension | null> {
|
||||||
try {
|
try {
|
||||||
const manifest = await fse.readJson(manifestPath) as LensExtensionManifest;
|
const manifest = await this.dependencies.readJsonFile(manifestPath) as unknown as LensExtensionManifest;
|
||||||
const id = this.getInstalledManifestPath(manifest.name);
|
const id = this.getInstalledManifestPath(manifest.name);
|
||||||
const isEnabled = this.dependencies.extensionsStore.isEnabled({ id, isBundled });
|
const isEnabled = this.dependencies.extensionsStore.isEnabled({ id, isBundled });
|
||||||
const extensionDir = path.dirname(manifestPath);
|
const extensionDir = path.dirname(manifestPath);
|
||||||
const npmPackage = path.join(extensionDir, `${manifest.name}-${manifest.version}.tgz`);
|
const npmPackage = path.join(extensionDir, `${manifest.name}-${manifest.version}.tgz`);
|
||||||
const absolutePath = (isProduction && await fse.pathExists(npmPackage)) ? npmPackage : extensionDir;
|
const absolutePath = (isProduction && await this.dependencies.pathExists(npmPackage)) ? npmPackage : extensionDir;
|
||||||
const isCompatible = (isBundled && this.dependencies.isCompatibleBundledExtension(manifest)) || this.dependencies.isCompatibleExtension(manifest);
|
const isCompatible = (isBundled && this.dependencies.isCompatibleBundledExtension(manifest)) || this.dependencies.isCompatibleExtension(manifest);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -378,9 +383,9 @@ export class ExtensionDiscovery {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (isErrnoException(error) && error.code === "ENOTDIR") {
|
if (isErrnoException(error) && error.code === "ENOTDIR") {
|
||||||
// ignore this error, probably from .DS_Store file
|
// ignore this error, probably from .DS_Store file
|
||||||
logger.debug(`${logModule}: failed to load extension manifest through a not-dir-like at ${manifestPath}`);
|
this.dependencies.logger.debug(`${logModule}: failed to load extension manifest through a not-dir-like at ${manifestPath}`);
|
||||||
} else {
|
} else {
|
||||||
logger.error(`${logModule}: can't load extension manifest at ${manifestPath}: ${error}`);
|
this.dependencies.logger.error(`${logModule}: can't load extension manifest at ${manifestPath}: ${error}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -395,7 +400,7 @@ export class ExtensionDiscovery {
|
|||||||
const userExtensions = await this.loadFromFolder(this.localFolderPath, bundledExtensions.map((extension) => extension.manifest.name));
|
const userExtensions = await this.loadFromFolder(this.localFolderPath, bundledExtensions.map((extension) => extension.manifest.name));
|
||||||
|
|
||||||
for (const extension of userExtensions) {
|
for (const extension of userExtensions) {
|
||||||
if ((await fse.pathExists(extension.manifestPath)) === false) {
|
if (!(await this.dependencies.pathExists(extension.manifestPath))) {
|
||||||
try {
|
try {
|
||||||
await this.dependencies.installExtension(extension.absolutePath);
|
await this.dependencies.installExtension(extension.absolutePath);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -404,7 +409,7 @@ export class ExtensionDiscovery {
|
|||||||
: String(error || "unknown error");
|
: String(error || "unknown error");
|
||||||
const { name, version } = extension.manifest;
|
const { name, version } = extension.manifest;
|
||||||
|
|
||||||
logger.error(`${logModule}: failed to install user extension ${name}@${version}: ${message}`);
|
this.dependencies.logger.error(`${logModule}: failed to install user extension ${name}@${version}: ${message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -438,7 +443,7 @@ export class ExtensionDiscovery {
|
|||||||
extensions.push(extension);
|
extensions.push(extension);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug(`${logModule}: ${extensions.length} extensions loaded`, { folderPath, extensions });
|
this.dependencies.logger.debug(`${logModule}: ${extensions.length} extensions loaded`, { folderPath, extensions });
|
||||||
|
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
@ -473,7 +478,7 @@ export class ExtensionDiscovery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug(`${logModule}: ${extensions.length} extensions loaded`, { folderPath, extensions });
|
this.dependencies.logger.debug(`${logModule}: ${extensions.length} extensions loaded`, { folderPath, extensions });
|
||||||
|
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ipcRenderer } from "electron";
|
import { ipcMain, ipcRenderer } from "electron";
|
||||||
import { isEqual } from "lodash";
|
import { isEqual } from "lodash";
|
||||||
import type { ObservableMap } from "mobx";
|
import type { ObservableMap } from "mobx";
|
||||||
import { action, computed, makeObservable, observable, observe, reaction, when } from "mobx";
|
import { action, computed, makeObservable, observable, observe, reaction, when } from "mobx";
|
||||||
@ -127,10 +127,10 @@ export class ExtensionLoader {
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
async init() {
|
async init() {
|
||||||
if (ipcRenderer) {
|
if (ipcMain) {
|
||||||
await this.initRenderer();
|
|
||||||
} else {
|
|
||||||
await this.initMain();
|
await this.initMain();
|
||||||
|
} else {
|
||||||
|
await this.initRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([this.whenLoaded]);
|
await Promise.all([this.whenLoaded]);
|
||||||
|
|||||||
@ -2,11 +2,7 @@
|
|||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable";
|
||||||
jest.mock("../../common/ipc");
|
|
||||||
jest.mock("request");
|
|
||||||
jest.mock("request-promise-native");
|
|
||||||
|
|
||||||
import { Console } from "console";
|
import { Console } from "console";
|
||||||
import type { Cluster } from "../../common/cluster/cluster";
|
import type { Cluster } from "../../common/cluster/cluster";
|
||||||
import { Kubectl } from "../kubectl/kubectl";
|
import { Kubectl } from "../kubectl/kubectl";
|
||||||
@ -41,6 +37,7 @@ describe("create clusters", () => {
|
|||||||
di.override(kubectlBinaryNameInjectable, () => "kubectl");
|
di.override(kubectlBinaryNameInjectable, () => "kubectl");
|
||||||
di.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64");
|
di.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64");
|
||||||
di.override(normalizedPlatformInjectable, () => "darwin");
|
di.override(normalizedPlatformInjectable, () => "darwin");
|
||||||
|
di.override(broadcastMessageInjectable, () => async () => {});
|
||||||
di.override(authorizationReviewInjectable, () => () => () => Promise.resolve(true));
|
di.override(authorizationReviewInjectable, () => () => () => Promise.resolve(true));
|
||||||
di.override(listNamespacesInjectable, () => () => () => Promise.resolve([ "default" ]));
|
di.override(listNamespacesInjectable, () => () => () => Promise.resolve([ "default" ]));
|
||||||
di.override(createContextHandlerInjectable, () => (cluster) => ({
|
di.override(createContextHandlerInjectable, () => (cluster) => ({
|
||||||
|
|||||||
@ -3,45 +3,13 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
jest.mock("winston", () => ({
|
import waitUntilPortIsUsedInjectable from "../kube-auth-proxy/wait-until-port-is-used/wait-until-port-is-used.injectable";
|
||||||
format: {
|
|
||||||
colorize: jest.fn(),
|
|
||||||
combine: jest.fn(),
|
|
||||||
simple: jest.fn(),
|
|
||||||
label: jest.fn(),
|
|
||||||
timestamp: jest.fn(),
|
|
||||||
printf: jest.fn(),
|
|
||||||
padLevels: jest.fn(),
|
|
||||||
ms: jest.fn(),
|
|
||||||
splat: jest.fn(),
|
|
||||||
},
|
|
||||||
createLogger: jest.fn().mockReturnValue({
|
|
||||||
silly: jest.fn(),
|
|
||||||
debug: jest.fn(),
|
|
||||||
log: jest.fn(),
|
|
||||||
info: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
crit: jest.fn(),
|
|
||||||
}),
|
|
||||||
transports: {
|
|
||||||
Console: jest.fn(),
|
|
||||||
File: jest.fn(),
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
jest.mock("../../common/ipc");
|
|
||||||
jest.mock("child_process");
|
|
||||||
jest.mock("tcp-port-used");
|
|
||||||
|
|
||||||
import type { Cluster } from "../../common/cluster/cluster";
|
import type { Cluster } from "../../common/cluster/cluster";
|
||||||
import type { KubeAuthProxy } from "../kube-auth-proxy/kube-auth-proxy";
|
import type { KubeAuthProxy } from "../kube-auth-proxy/kube-auth-proxy";
|
||||||
import { broadcastMessage } from "../../common/ipc";
|
|
||||||
import type { ChildProcess } from "child_process";
|
import type { ChildProcess } from "child_process";
|
||||||
import { spawn } from "child_process";
|
|
||||||
import { Kubectl } from "../kubectl/kubectl";
|
import { Kubectl } from "../kubectl/kubectl";
|
||||||
import type { DeepMockProxy } from "jest-mock-extended";
|
import type { DeepMockProxy } from "jest-mock-extended";
|
||||||
import { mockDeep, mock } from "jest-mock-extended";
|
import { mockDeep, mock } from "jest-mock-extended";
|
||||||
import { waitUntilUsed } from "tcp-port-used";
|
|
||||||
import type { Readable } from "stream";
|
import type { Readable } from "stream";
|
||||||
import { EventEmitter } from "stream";
|
import { EventEmitter } from "stream";
|
||||||
import { Console } from "console";
|
import { Console } from "console";
|
||||||
@ -59,17 +27,18 @@ import directoryForTempInjectable from "../../common/app-paths/directory-for-tem
|
|||||||
import normalizedPlatformInjectable from "../../common/vars/normalized-platform.injectable";
|
import normalizedPlatformInjectable from "../../common/vars/normalized-platform.injectable";
|
||||||
import kubectlBinaryNameInjectable from "../kubectl/binary-name.injectable";
|
import kubectlBinaryNameInjectable from "../kubectl/binary-name.injectable";
|
||||||
import kubectlDownloadingNormalizedArchInjectable from "../kubectl/normalized-arch.injectable";
|
import kubectlDownloadingNormalizedArchInjectable from "../kubectl/normalized-arch.injectable";
|
||||||
|
import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable";
|
||||||
|
|
||||||
console = new Console(stdout, stderr);
|
console = new Console(stdout, stderr);
|
||||||
|
|
||||||
const mockBroadcastIpc = broadcastMessage as jest.MockedFunction<typeof broadcastMessage>;
|
|
||||||
const mockSpawn = spawn as jest.MockedFunction<typeof spawn>;
|
|
||||||
const mockWaitUntilUsed = waitUntilUsed as jest.MockedFunction<typeof waitUntilUsed>;
|
|
||||||
const clusterServerUrl = "https://192.168.64.3:8443";
|
const clusterServerUrl = "https://192.168.64.3:8443";
|
||||||
|
|
||||||
describe("kube auth proxy tests", () => {
|
describe("kube auth proxy tests", () => {
|
||||||
let createCluster: CreateCluster;
|
let createCluster: CreateCluster;
|
||||||
let createKubeAuthProxy: (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy;
|
let createKubeAuthProxy: (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy;
|
||||||
|
let spawnMock: jest.Mock;
|
||||||
|
let waitUntilPortIsUsedMock: jest.Mock;
|
||||||
|
let broadcastMessageMock: jest.Mock;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
@ -105,7 +74,15 @@ describe("kube auth proxy tests", () => {
|
|||||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||||
di.override(directoryForTempInjectable, () => "some-directory-for-temp");
|
di.override(directoryForTempInjectable, () => "some-directory-for-temp");
|
||||||
|
|
||||||
di.override(spawnInjectable, () => mockSpawn);
|
spawnMock = jest.fn();
|
||||||
|
di.override(spawnInjectable, () => spawnMock);
|
||||||
|
|
||||||
|
waitUntilPortIsUsedMock = jest.fn();
|
||||||
|
di.override(waitUntilPortIsUsedInjectable, () => waitUntilPortIsUsedMock);
|
||||||
|
|
||||||
|
broadcastMessageMock = jest.fn();
|
||||||
|
di.override(broadcastMessageInjectable, () => broadcastMessageMock);
|
||||||
|
|
||||||
di.override(kubectlBinaryNameInjectable, () => "kubectl");
|
di.override(kubectlBinaryNameInjectable, () => "kubectl");
|
||||||
di.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64");
|
di.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64");
|
||||||
di.override(normalizedPlatformInjectable, () => "darwin");
|
di.override(normalizedPlatformInjectable, () => "darwin");
|
||||||
@ -211,12 +188,12 @@ describe("kube auth proxy tests", () => {
|
|||||||
|
|
||||||
return stdout;
|
return stdout;
|
||||||
});
|
});
|
||||||
mockSpawn.mockImplementationOnce((command: string): ChildProcess => {
|
spawnMock.mockImplementationOnce((command: string): ChildProcess => {
|
||||||
expect(path.basename(command).split(".")[0]).toBe("lens-k8s-proxy");
|
expect(path.basename(command).split(".")[0]).toBe("lens-k8s-proxy");
|
||||||
|
|
||||||
return mockedCP;
|
return mockedCP;
|
||||||
});
|
});
|
||||||
mockWaitUntilUsed.mockReturnValueOnce(Promise.resolve());
|
waitUntilPortIsUsedMock.mockReturnValueOnce(Promise.resolve());
|
||||||
|
|
||||||
const cluster = createCluster({
|
const cluster = createCluster({
|
||||||
id: "foobar",
|
id: "foobar",
|
||||||
@ -233,34 +210,34 @@ describe("kube auth proxy tests", () => {
|
|||||||
await proxy.run();
|
await proxy.run();
|
||||||
listeners.emit("error", { message: "foobarbat" });
|
listeners.emit("error", { message: "foobarbat" });
|
||||||
|
|
||||||
expect(mockBroadcastIpc).toBeCalledWith("cluster:foobar:connection-update", { message: "foobarbat", isError: true });
|
expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "foobarbat", isError: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call spawn and broadcast exit", async () => {
|
it("should call spawn and broadcast exit", async () => {
|
||||||
await proxy.run();
|
await proxy.run();
|
||||||
listeners.emit("exit", 0);
|
listeners.emit("exit", 0);
|
||||||
|
|
||||||
expect(mockBroadcastIpc).toBeCalledWith("cluster:foobar:connection-update", { message: "proxy exited with code: 0", isError: false });
|
expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "proxy exited with code: 0", isError: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call spawn and broadcast errors from stderr", async () => {
|
it("should call spawn and broadcast errors from stderr", async () => {
|
||||||
await proxy.run();
|
await proxy.run();
|
||||||
listeners.emit("stderr/data", "an error");
|
listeners.emit("stderr/data", "an error");
|
||||||
|
|
||||||
expect(mockBroadcastIpc).toBeCalledWith("cluster:foobar:connection-update", { message: "an error", isError: true });
|
expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "an error", isError: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call spawn and broadcast stdout serving info", async () => {
|
it("should call spawn and broadcast stdout serving info", async () => {
|
||||||
await proxy.run();
|
await proxy.run();
|
||||||
|
|
||||||
expect(mockBroadcastIpc).toBeCalledWith("cluster:foobar:connection-update", { message: "Authentication proxy started", isError: false });
|
expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "Authentication proxy started", isError: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call spawn and broadcast stdout other info", async () => {
|
it("should call spawn and broadcast stdout other info", async () => {
|
||||||
await proxy.run();
|
await proxy.run();
|
||||||
listeners.emit("stdout/data", "some info");
|
listeners.emit("stdout/data", "some info");
|
||||||
|
|
||||||
expect(mockBroadcastIpc).toBeCalledWith("cluster:foobar:connection-update", { message: "some info", isError: false });
|
expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "some info", isError: false });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import listNamespacesInjectable from "../../common/cluster/list-namespaces.injec
|
|||||||
import loggerInjectable from "../../common/logger.injectable";
|
import loggerInjectable from "../../common/logger.injectable";
|
||||||
import detectorRegistryInjectable from "../cluster-detectors/detector-registry.injectable";
|
import detectorRegistryInjectable from "../cluster-detectors/detector-registry.injectable";
|
||||||
import createVersionDetectorInjectable from "../cluster-detectors/create-version-detector.injectable";
|
import createVersionDetectorInjectable from "../cluster-detectors/create-version-detector.injectable";
|
||||||
|
import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable";
|
||||||
|
|
||||||
const createClusterInjectable = getInjectable({
|
const createClusterInjectable = getInjectable({
|
||||||
id: "create-cluster",
|
id: "create-cluster",
|
||||||
@ -30,6 +31,7 @@ const createClusterInjectable = getInjectable({
|
|||||||
logger: di.inject(loggerInjectable),
|
logger: di.inject(loggerInjectable),
|
||||||
detectorRegistry: di.inject(detectorRegistryInjectable),
|
detectorRegistry: di.inject(detectorRegistryInjectable),
|
||||||
createVersionDetector: di.inject(createVersionDetectorInjectable),
|
createVersionDetector: di.inject(createVersionDetectorInjectable),
|
||||||
|
broadcastMessage: di.inject(broadcastMessageInjectable),
|
||||||
};
|
};
|
||||||
|
|
||||||
return (model, configData) => new Cluster(dependencies, model, configData);
|
return (model, configData) => new Cluster(dependencies, model, configData);
|
||||||
|
|||||||
@ -58,7 +58,6 @@ import type { ClusterFrameInfo } from "../common/cluster-frames";
|
|||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import waitForElectronToBeReadyInjectable from "./electron-app/features/wait-for-electron-to-be-ready.injectable";
|
import waitForElectronToBeReadyInjectable from "./electron-app/features/wait-for-electron-to-be-ready.injectable";
|
||||||
import setupListenerForCurrentClusterFrameInjectable from "./start-main-application/lens-window/current-cluster-frame/setup-listener-for-current-cluster-frame.injectable";
|
import setupListenerForCurrentClusterFrameInjectable from "./start-main-application/lens-window/current-cluster-frame/setup-listener-for-current-cluster-frame.injectable";
|
||||||
import ipcMainInjectable from "./utils/channel/ipc-main/ipc-main.injectable";
|
|
||||||
import setupRunnablesAfterWindowIsOpenedInjectable from "./electron-app/runnables/setup-runnables-after-window-is-opened.injectable";
|
import setupRunnablesAfterWindowIsOpenedInjectable from "./electron-app/runnables/setup-runnables-after-window-is-opened.injectable";
|
||||||
import broadcastMessageInjectable from "../common/ipc/broadcast-message.injectable";
|
import broadcastMessageInjectable from "../common/ipc/broadcast-message.injectable";
|
||||||
import getElectronThemeInjectable from "./electron-app/features/get-electron-theme.injectable";
|
import getElectronThemeInjectable from "./electron-app/features/get-electron-theme.injectable";
|
||||||
@ -252,7 +251,6 @@ const overrideElectronFeatures = (di: DiContainer) => {
|
|||||||
di.override(shouldStartHiddenInjectable, () => false);
|
di.override(shouldStartHiddenInjectable, () => false);
|
||||||
di.override(showMessagePopupInjectable, () => () => {});
|
di.override(showMessagePopupInjectable, () => () => {});
|
||||||
di.override(waitForElectronToBeReadyInjectable, () => () => Promise.resolve());
|
di.override(waitForElectronToBeReadyInjectable, () => () => Promise.resolve());
|
||||||
di.override(ipcMainInjectable, () => ({}));
|
|
||||||
di.override(getElectronThemeInjectable, () => () => "dark");
|
di.override(getElectronThemeInjectable, () => () => "dark");
|
||||||
di.override(syncThemeFromOperatingSystemInjectable, () => ({ start: () => {}, stop: () => {} }));
|
di.override(syncThemeFromOperatingSystemInjectable, () => ({ start: () => {}, stop: () => {} }));
|
||||||
di.override(electronQuitAndInstallUpdateInjectable, () => () => {});
|
di.override(electronQuitAndInstallUpdateInjectable, () => () => {});
|
||||||
|
|||||||
@ -1,153 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { sortCharts } from "../../../common/utils";
|
|
||||||
import type { HelmRepo } from "../../../common/helm/helm-repo";
|
|
||||||
|
|
||||||
const charts = new Map([
|
|
||||||
["stable", {
|
|
||||||
"invalid-semver": sortCharts([
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "weird-versioning",
|
|
||||||
version: "I am not semver",
|
|
||||||
repo: "stable",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "weird-versioning",
|
|
||||||
version: "v4.3.0",
|
|
||||||
repo: "stable",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "weird-versioning",
|
|
||||||
version: "I am not semver but more",
|
|
||||||
repo: "stable",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "weird-versioning",
|
|
||||||
version: "v4.4.0",
|
|
||||||
repo: "stable",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
"apm-server": sortCharts([
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "apm-server",
|
|
||||||
version: "2.1.7",
|
|
||||||
repo: "stable",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "apm-server",
|
|
||||||
version: "2.1.6",
|
|
||||||
repo: "stable",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
"redis": sortCharts([
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "apm-server",
|
|
||||||
version: "1.0.0",
|
|
||||||
repo: "stable",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "apm-server",
|
|
||||||
version: "0.0.9",
|
|
||||||
repo: "stable",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
}],
|
|
||||||
["experiment", {
|
|
||||||
"fairwind": sortCharts([
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "fairwind",
|
|
||||||
version: "0.0.1",
|
|
||||||
repo: "experiment",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "fairwind",
|
|
||||||
version: "0.0.2",
|
|
||||||
repo: "experiment",
|
|
||||||
digest: "test",
|
|
||||||
deprecated: true,
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
}],
|
|
||||||
["bitnami", {
|
|
||||||
"hotdog": sortCharts([
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "hotdog",
|
|
||||||
version: "1.0.1",
|
|
||||||
repo: "bitnami",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "hotdog",
|
|
||||||
version: "1.0.2",
|
|
||||||
repo: "bitnami",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
"pretzel": sortCharts([
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "pretzel",
|
|
||||||
version: "1.0",
|
|
||||||
repo: "bitnami",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
apiVersion: "3.0.0",
|
|
||||||
name: "pretzel",
|
|
||||||
version: "1.0.1",
|
|
||||||
repo: "bitnami",
|
|
||||||
digest: "test",
|
|
||||||
created: "now",
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
}],
|
|
||||||
]);
|
|
||||||
|
|
||||||
export class HelmChartManager {
|
|
||||||
constructor(private repo: HelmRepo){ }
|
|
||||||
|
|
||||||
static forRepo(repo: HelmRepo) {
|
|
||||||
return new this(repo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async charts(): Promise<any> {
|
|
||||||
return charts.get(this.repo.name) ?? {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -8,8 +8,8 @@ import listHelmChartsInjectable from "../helm-service/list-helm-charts.injectabl
|
|||||||
import getActiveHelmRepositoriesInjectable from "../repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
import getActiveHelmRepositoriesInjectable from "../repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||||
import type { AsyncResult } from "../../../common/utils/async-result";
|
import type { AsyncResult } from "../../../common/utils/async-result";
|
||||||
import type { HelmRepo } from "../../../common/helm/helm-repo";
|
import type { HelmRepo } from "../../../common/helm/helm-repo";
|
||||||
|
import { sortCharts } from "../../../common/utils";
|
||||||
jest.mock("../helm-chart-manager");
|
import helmChartManagerInjectable from "../helm-chart-manager.injectable";
|
||||||
|
|
||||||
describe("Helm Service tests", () => {
|
describe("Helm Service tests", () => {
|
||||||
let listHelmCharts: () => Promise<any>;
|
let listHelmCharts: () => Promise<any>;
|
||||||
@ -20,6 +20,11 @@ describe("Helm Service tests", () => {
|
|||||||
|
|
||||||
getActiveHelmRepositoriesMock = jest.fn();
|
getActiveHelmRepositoriesMock = jest.fn();
|
||||||
|
|
||||||
|
di.override(
|
||||||
|
helmChartManagerInjectable,
|
||||||
|
(di, repo) => new HelmChartManagerFake(repo) as unknown,
|
||||||
|
);
|
||||||
|
|
||||||
di.override(getActiveHelmRepositoriesInjectable, () => getActiveHelmRepositoriesMock);
|
di.override(getActiveHelmRepositoriesInjectable, () => getActiveHelmRepositoriesMock);
|
||||||
|
|
||||||
di.unoverride(listHelmChartsInjectable);
|
di.unoverride(listHelmChartsInjectable);
|
||||||
@ -195,3 +200,145 @@ describe("Helm Service tests", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const charts = new Map([
|
||||||
|
["stable", {
|
||||||
|
"invalid-semver": sortCharts([
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "weird-versioning",
|
||||||
|
version: "I am not semver",
|
||||||
|
repo: "stable",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "weird-versioning",
|
||||||
|
version: "v4.3.0",
|
||||||
|
repo: "stable",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "weird-versioning",
|
||||||
|
version: "I am not semver but more",
|
||||||
|
repo: "stable",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "weird-versioning",
|
||||||
|
version: "v4.4.0",
|
||||||
|
repo: "stable",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
"apm-server": sortCharts([
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "apm-server",
|
||||||
|
version: "2.1.7",
|
||||||
|
repo: "stable",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "apm-server",
|
||||||
|
version: "2.1.6",
|
||||||
|
repo: "stable",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
"redis": sortCharts([
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "apm-server",
|
||||||
|
version: "1.0.0",
|
||||||
|
repo: "stable",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "apm-server",
|
||||||
|
version: "0.0.9",
|
||||||
|
repo: "stable",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
}],
|
||||||
|
["experiment", {
|
||||||
|
"fairwind": sortCharts([
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "fairwind",
|
||||||
|
version: "0.0.1",
|
||||||
|
repo: "experiment",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "fairwind",
|
||||||
|
version: "0.0.2",
|
||||||
|
repo: "experiment",
|
||||||
|
digest: "test",
|
||||||
|
deprecated: true,
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
}],
|
||||||
|
["bitnami", {
|
||||||
|
"hotdog": sortCharts([
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "hotdog",
|
||||||
|
version: "1.0.1",
|
||||||
|
repo: "bitnami",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "hotdog",
|
||||||
|
version: "1.0.2",
|
||||||
|
repo: "bitnami",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
"pretzel": sortCharts([
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "pretzel",
|
||||||
|
version: "1.0",
|
||||||
|
repo: "bitnami",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
apiVersion: "3.0.0",
|
||||||
|
name: "pretzel",
|
||||||
|
version: "1.0.1",
|
||||||
|
repo: "bitnami",
|
||||||
|
digest: "test",
|
||||||
|
created: "now",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
}],
|
||||||
|
]);
|
||||||
|
|
||||||
|
class HelmChartManagerFake {
|
||||||
|
constructor(private repo: HelmRepo){ }
|
||||||
|
|
||||||
|
public async charts(): Promise<any> {
|
||||||
|
return charts.get(this.repo.name) ?? {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
19
src/main/helm/helm-chart-manager-cache.injectable.ts
Normal file
19
src/main/helm/helm-chart-manager-cache.injectable.ts
Normal file
@ -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 } from "@ogre-tools/injectable";
|
||||||
|
|
||||||
|
export interface ChartCacheEntry {
|
||||||
|
data: string; // serialized JSON
|
||||||
|
mtimeMs: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HelmChartManagerCache = Map<string, ChartCacheEntry>;
|
||||||
|
|
||||||
|
const helmChartManagerCacheInjectable = getInjectable({
|
||||||
|
id: "helm-chart-manager-cache",
|
||||||
|
instantiate: (): HelmChartManagerCache => new Map(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default helmChartManagerCacheInjectable;
|
||||||
26
src/main/helm/helm-chart-manager.injectable.ts
Normal file
26
src/main/helm/helm-chart-manager.injectable.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* 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 { HelmRepo } from "../../common/helm/helm-repo";
|
||||||
|
import { HelmChartManager } from "./helm-chart-manager";
|
||||||
|
import helmChartManagerCacheInjectable from "./helm-chart-manager-cache.injectable";
|
||||||
|
import loggerInjectable from "../../common/logger.injectable";
|
||||||
|
|
||||||
|
const helmChartManagerInjectable = getInjectable({
|
||||||
|
id: "helm-chart-manager",
|
||||||
|
|
||||||
|
instantiate: (di, repo: HelmRepo) => {
|
||||||
|
const cache = di.inject(helmChartManagerCacheInjectable);
|
||||||
|
const logger = di.inject(loggerInjectable);
|
||||||
|
|
||||||
|
return new HelmChartManager(repo, { cache, logger });
|
||||||
|
},
|
||||||
|
|
||||||
|
lifecycle: lifecycleEnum.keyedSingleton({
|
||||||
|
getInstanceKey: (di, repo: HelmRepo) => repo.name,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default helmChartManagerInjectable;
|
||||||
@ -5,39 +5,34 @@
|
|||||||
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import * as yaml from "js-yaml";
|
import * as yaml from "js-yaml";
|
||||||
import logger from "../logger";
|
|
||||||
import type { RepoHelmChartList } from "../../common/k8s-api/endpoints/helm-charts.api";
|
import type { RepoHelmChartList } from "../../common/k8s-api/endpoints/helm-charts.api";
|
||||||
import { iter, put, sortCharts } from "../../common/utils";
|
import { iter, put, sortCharts } from "../../common/utils";
|
||||||
import { execHelm } from "./exec";
|
import { execHelm } from "./exec";
|
||||||
import type { SetRequired } from "type-fest";
|
import type { SetRequired } from "type-fest";
|
||||||
import { assert } from "console";
|
import { assert } from "console";
|
||||||
import type { HelmRepo } from "../../common/helm/helm-repo";
|
import type { HelmRepo } from "../../common/helm/helm-repo";
|
||||||
|
import type { HelmChartManagerCache } from "./helm-chart-manager-cache.injectable";
|
||||||
interface ChartCacheEntry {
|
import type { Logger } from "../../common/logger";
|
||||||
data: string; // serialized JSON
|
|
||||||
mtimeMs: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HelmCacheFile {
|
export interface HelmCacheFile {
|
||||||
apiVersion: string;
|
apiVersion: string;
|
||||||
entries: RepoHelmChartList;
|
entries: RepoHelmChartList;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HelmChartManager {
|
interface Dependencies {
|
||||||
static readonly #cache = new Map<string, ChartCacheEntry>();
|
cache: HelmChartManagerCache;
|
||||||
|
logger: Logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HelmChartManager {
|
||||||
protected readonly repo: SetRequired<HelmRepo, "cacheFilePath">;
|
protected readonly repo: SetRequired<HelmRepo, "cacheFilePath">;
|
||||||
|
|
||||||
private constructor(repo: HelmRepo) {
|
constructor(repo: HelmRepo, private dependencies: Dependencies) {
|
||||||
assert(repo.cacheFilePath, "CacheFilePath must be provided on the helm repo");
|
assert(repo.cacheFilePath, "CacheFilePath must be provided on the helm repo");
|
||||||
|
|
||||||
this.repo = repo as SetRequired<HelmRepo, "cacheFilePath">;
|
this.repo = repo as SetRequired<HelmRepo, "cacheFilePath">;
|
||||||
}
|
}
|
||||||
|
|
||||||
static forRepo(repo: HelmRepo) {
|
|
||||||
return new this(repo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async chartVersions(name: string) {
|
public async chartVersions(name: string) {
|
||||||
const charts = await this.charts();
|
const charts = await this.charts();
|
||||||
|
|
||||||
@ -48,7 +43,7 @@ export class HelmChartManager {
|
|||||||
try {
|
try {
|
||||||
return await this.cachedYaml();
|
return await this.cachedYaml();
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
logger.error("HELM-CHART-MANAGER]: failed to list charts", { error });
|
this.dependencies.logger.error("HELM-CHART-MANAGER]: failed to list charts", { error });
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -84,7 +79,7 @@ export class HelmChartManager {
|
|||||||
const normalized = normalizeHelmCharts(this.repo.name, data.entries);
|
const normalized = normalizeHelmCharts(this.repo.name, data.entries);
|
||||||
|
|
||||||
return put(
|
return put(
|
||||||
HelmChartManager.#cache,
|
this.dependencies.cache,
|
||||||
this.repo.name,
|
this.repo.name,
|
||||||
{
|
{
|
||||||
data: JSON.stringify(normalized),
|
data: JSON.stringify(normalized),
|
||||||
@ -94,7 +89,7 @@ export class HelmChartManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async cachedYaml(): Promise<RepoHelmChartList> {
|
protected async cachedYaml(): Promise<RepoHelmChartList> {
|
||||||
let cacheEntry = HelmChartManager.#cache.get(this.repo.name);
|
let cacheEntry = this.dependencies.cache.get(this.repo.name);
|
||||||
|
|
||||||
if (!cacheEntry) {
|
if (!cacheEntry) {
|
||||||
cacheEntry = await this.updateYamlCache();
|
cacheEntry = await this.updateYamlCache();
|
||||||
|
|||||||
@ -3,14 +3,16 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { HelmChartManager } from "../helm-chart-manager";
|
|
||||||
import getActiveHelmRepositoryInjectable from "../repositories/get-active-helm-repository.injectable";
|
import getActiveHelmRepositoryInjectable from "../repositories/get-active-helm-repository.injectable";
|
||||||
|
import type { HelmRepo } from "../../../common/helm/helm-repo";
|
||||||
|
import helmChartManagerInjectable from "../helm-chart-manager.injectable";
|
||||||
|
|
||||||
const getHelmChartValuesInjectable = getInjectable({
|
const getHelmChartValuesInjectable = getInjectable({
|
||||||
id: "get-helm-chart-values",
|
id: "get-helm-chart-values",
|
||||||
|
|
||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const getActiveHelmRepository = di.inject(getActiveHelmRepositoryInjectable);
|
const getActiveHelmRepository = di.inject(getActiveHelmRepositoryInjectable);
|
||||||
|
const getChartManager = (repo: HelmRepo) => di.inject(helmChartManagerInjectable, repo);
|
||||||
|
|
||||||
return async (repoName: string, chartName: string, version = "") => {
|
return async (repoName: string, chartName: string, version = "") => {
|
||||||
const repo = await getActiveHelmRepository(repoName);
|
const repo = await getActiveHelmRepository(repoName);
|
||||||
@ -19,7 +21,7 @@ const getHelmChartValuesInjectable = getInjectable({
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return HelmChartManager.forRepo(repo).getValues(chartName, version);
|
return getChartManager(repo).getValues(chartName, version);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -3,14 +3,16 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { HelmChartManager } from "../helm-chart-manager";
|
|
||||||
import getActiveHelmRepositoryInjectable from "../repositories/get-active-helm-repository.injectable";
|
import getActiveHelmRepositoryInjectable from "../repositories/get-active-helm-repository.injectable";
|
||||||
|
import type { HelmRepo } from "../../../common/helm/helm-repo";
|
||||||
|
import helmChartManagerInjectable from "../helm-chart-manager.injectable";
|
||||||
|
|
||||||
const getHelmChartInjectable = getInjectable({
|
const getHelmChartInjectable = getInjectable({
|
||||||
id: "get-helm-chart",
|
id: "get-helm-chart",
|
||||||
|
|
||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const getActiveHelmRepository = di.inject(getActiveHelmRepositoryInjectable);
|
const getActiveHelmRepository = di.inject(getActiveHelmRepositoryInjectable);
|
||||||
|
const getChartManager = (repo: HelmRepo) => di.inject(helmChartManagerInjectable, repo);
|
||||||
|
|
||||||
return async (repoName: string, chartName: string, version = "") => {
|
return async (repoName: string, chartName: string, version = "") => {
|
||||||
const repo = await getActiveHelmRepository(repoName);
|
const repo = await getActiveHelmRepository(repoName);
|
||||||
@ -19,7 +21,7 @@ const getHelmChartInjectable = getInjectable({
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const chartManager = HelmChartManager.forRepo(repo);
|
const chartManager = getChartManager(repo);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
readme: await chartManager.getReadme(chartName, version),
|
readme: await chartManager.getReadme(chartName, version),
|
||||||
|
|||||||
@ -5,14 +5,16 @@
|
|||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
import { object } from "../../../common/utils";
|
import { object } from "../../../common/utils";
|
||||||
import { HelmChartManager } from "../helm-chart-manager";
|
|
||||||
import getActiveHelmRepositoriesInjectable from "../repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
import getActiveHelmRepositoriesInjectable from "../repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||||
|
import type { HelmRepo } from "../../../common/helm/helm-repo";
|
||||||
|
import helmChartManagerInjectable from "../helm-chart-manager.injectable";
|
||||||
|
|
||||||
const listHelmChartsInjectable = getInjectable({
|
const listHelmChartsInjectable = getInjectable({
|
||||||
id: "list-helm-charts",
|
id: "list-helm-charts",
|
||||||
|
|
||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const getActiveHelmRepositories = di.inject(getActiveHelmRepositoriesInjectable);
|
const getActiveHelmRepositories = di.inject(getActiveHelmRepositoriesInjectable);
|
||||||
|
const getChartManager = (repo: HelmRepo) => di.inject(helmChartManagerInjectable, repo);
|
||||||
|
|
||||||
return async () => {
|
return async () => {
|
||||||
const result = await getActiveHelmRepositories();
|
const result = await getActiveHelmRepositories();
|
||||||
@ -27,7 +29,7 @@ const listHelmChartsInjectable = getInjectable({
|
|||||||
async (repo) =>
|
async (repo) =>
|
||||||
[
|
[
|
||||||
repo.name,
|
repo.name,
|
||||||
await HelmChartManager.forRepo(repo).charts(),
|
await getChartManager(repo).charts(),
|
||||||
] as const,
|
] as const,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import spawnInjectable from "../child-process/spawn.injectable";
|
|||||||
import { getKubeAuthProxyCertificate } from "./get-kube-auth-proxy-certificate";
|
import { getKubeAuthProxyCertificate } from "./get-kube-auth-proxy-certificate";
|
||||||
import loggerInjectable from "../../common/logger.injectable";
|
import loggerInjectable from "../../common/logger.injectable";
|
||||||
import baseBundledBinariesDirectoryInjectable from "../../common/vars/base-bundled-binaries-dir.injectable";
|
import baseBundledBinariesDirectoryInjectable from "../../common/vars/base-bundled-binaries-dir.injectable";
|
||||||
|
import waitUntilPortIsUsedInjectable from "./wait-until-port-is-used/wait-until-port-is-used.injectable";
|
||||||
|
|
||||||
export type CreateKubeAuthProxy = (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy;
|
export type CreateKubeAuthProxy = (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy;
|
||||||
|
|
||||||
@ -29,6 +30,7 @@ const createKubeAuthProxyInjectable = getInjectable({
|
|||||||
proxyCert: getKubeAuthProxyCertificate(clusterUrl.hostname, selfsigned.generate),
|
proxyCert: getKubeAuthProxyCertificate(clusterUrl.hostname, selfsigned.generate),
|
||||||
spawn: di.inject(spawnInjectable),
|
spawn: di.inject(spawnInjectable),
|
||||||
logger: di.inject(loggerInjectable),
|
logger: di.inject(loggerInjectable),
|
||||||
|
waitUntilPortIsUsed: di.inject(waitUntilPortIsUsedInjectable),
|
||||||
};
|
};
|
||||||
|
|
||||||
return new KubeAuthProxy(dependencies, cluster, environmentVariables);
|
return new KubeAuthProxy(dependencies, cluster, environmentVariables);
|
||||||
|
|||||||
@ -4,10 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ChildProcess } from "child_process";
|
import type { ChildProcess } from "child_process";
|
||||||
import { waitUntilUsed } from "tcp-port-used";
|
|
||||||
import { randomBytes } from "crypto";
|
import { randomBytes } from "crypto";
|
||||||
import type { Cluster } from "../../common/cluster/cluster";
|
import type { Cluster } from "../../common/cluster/cluster";
|
||||||
import logger from "../logger";
|
|
||||||
import { getPortFrom } from "../utils/get-port";
|
import { getPortFrom } from "../utils/get-port";
|
||||||
import { makeObservable, observable, when } from "mobx";
|
import { makeObservable, observable, when } from "mobx";
|
||||||
import type { SelfSignedCert } from "selfsigned";
|
import type { SelfSignedCert } from "selfsigned";
|
||||||
@ -15,6 +13,7 @@ import assert from "assert";
|
|||||||
import { TypedRegEx } from "typed-regex";
|
import { TypedRegEx } from "typed-regex";
|
||||||
import type { Spawn } from "../child-process/spawn.injectable";
|
import type { Spawn } from "../child-process/spawn.injectable";
|
||||||
import type { Logger } from "../../common/logger";
|
import type { Logger } from "../../common/logger";
|
||||||
|
import type { WaitUntilPortIsUsed } from "./wait-until-port-is-used/wait-until-port-is-used.injectable";
|
||||||
|
|
||||||
const startingServeMatcher = "starting to serve on (?<address>.+)";
|
const startingServeMatcher = "starting to serve on (?<address>.+)";
|
||||||
const startingServeRegex = Object.assign(TypedRegEx(startingServeMatcher, "i"), {
|
const startingServeRegex = Object.assign(TypedRegEx(startingServeMatcher, "i"), {
|
||||||
@ -24,8 +23,9 @@ const startingServeRegex = Object.assign(TypedRegEx(startingServeMatcher, "i"),
|
|||||||
export interface KubeAuthProxyDependencies {
|
export interface KubeAuthProxyDependencies {
|
||||||
readonly proxyBinPath: string;
|
readonly proxyBinPath: string;
|
||||||
readonly proxyCert: SelfSignedCert;
|
readonly proxyCert: SelfSignedCert;
|
||||||
spawn: Spawn;
|
readonly spawn: Spawn;
|
||||||
readonly logger: Logger;
|
readonly logger: Logger;
|
||||||
|
readonly waitUntilPortIsUsed: WaitUntilPortIsUsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class KubeAuthProxy {
|
export class KubeAuthProxy {
|
||||||
@ -106,13 +106,13 @@ export class KubeAuthProxy {
|
|||||||
onFind: () => this.cluster.broadcastConnectUpdate("Authentication proxy started"),
|
onFind: () => this.cluster.broadcastConnectUpdate("Authentication proxy started"),
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.info(`[KUBE-AUTH-PROXY]: found port=${this._port}`);
|
this.dependencies.logger.info(`[KUBE-AUTH-PROXY]: found port=${this._port}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await waitUntilUsed(this.port, 500, 10000);
|
await this.dependencies.waitUntilPortIsUsed(this.port, 500, 10000);
|
||||||
this.ready = true;
|
this.ready = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.warn("[KUBE-AUTH-PROXY]: waitUntilUsed failed", error);
|
this.dependencies.logger.warn("[KUBE-AUTH-PROXY]: waitUntilUsed failed", error);
|
||||||
this.cluster.broadcastConnectUpdate("Proxy port failed to be used within timelimit, restarting...", true);
|
this.cluster.broadcastConnectUpdate("Proxy port failed to be used within timelimit, restarting...", true);
|
||||||
this.exit();
|
this.exit();
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ export class KubeAuthProxy {
|
|||||||
this.ready = false;
|
this.ready = false;
|
||||||
|
|
||||||
if (this.proxyProcess) {
|
if (this.proxyProcess) {
|
||||||
logger.debug("[KUBE-AUTH]: stopping local proxy", this.cluster.getMeta());
|
this.dependencies.logger.debug("[KUBE-AUTH]: stopping local proxy", this.cluster.getMeta());
|
||||||
this.proxyProcess.removeAllListeners();
|
this.proxyProcess.removeAllListeners();
|
||||||
this.proxyProcess.stderr?.removeAllListeners();
|
this.proxyProcess.stderr?.removeAllListeners();
|
||||||
this.proxyProcess.stdout?.removeAllListeners();
|
this.proxyProcess.stdout?.removeAllListeners();
|
||||||
|
|||||||
@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getGlobalOverride } from "../../../common/test-utils/get-global-override";
|
||||||
|
import waitUntilPortIsUsedInjectable from "./wait-until-port-is-used.injectable";
|
||||||
|
|
||||||
|
export default getGlobalOverride(
|
||||||
|
waitUntilPortIsUsedInjectable,
|
||||||
|
() => () => {
|
||||||
|
throw new Error(
|
||||||
|
"Tried to wait until port is used without explicit override.",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
@ -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 } from "@ogre-tools/injectable";
|
||||||
|
import { waitUntilUsed } from "tcp-port-used";
|
||||||
|
|
||||||
|
export type WaitUntilPortIsUsed = (
|
||||||
|
port: number,
|
||||||
|
retryAfterMs: number,
|
||||||
|
timeoutAfterMs: number
|
||||||
|
) => Promise<void>;
|
||||||
|
|
||||||
|
const waitUntilPortIsUsedInjectable = getInjectable({
|
||||||
|
id: "wait-until-port-is-used",
|
||||||
|
instantiate: (): WaitUntilPortIsUsed => waitUntilUsed,
|
||||||
|
causesSideEffects: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default waitUntilPortIsUsedInjectable;
|
||||||
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
import * as uuid from "uuid";
|
import * as uuid from "uuid";
|
||||||
|
|
||||||
import { broadcastMessage } from "../../../common/ipc";
|
|
||||||
import { ProtocolHandlerExtension, ProtocolHandlerInternal, ProtocolHandlerInvalid } from "../../../common/protocol-handler";
|
import { ProtocolHandlerExtension, ProtocolHandlerInternal, ProtocolHandlerInvalid } from "../../../common/protocol-handler";
|
||||||
import { delay, noop } from "../../../common/utils";
|
import { delay, noop } from "../../../common/utils";
|
||||||
import type { ExtensionsStore, IsEnabledExtensionDescriptor } from "../../../extensions/extensions-store/extensions-store";
|
import type { ExtensionsStore, IsEnabledExtensionDescriptor } from "../../../extensions/extensions-store/extensions-store";
|
||||||
@ -19,8 +18,7 @@ import type { LensExtensionId } from "../../../extensions/lens-extension";
|
|||||||
import type { ObservableMap } from "mobx";
|
import type { ObservableMap } from "mobx";
|
||||||
import extensionInstancesInjectable from "../../../extensions/extension-loader/extension-instances.injectable";
|
import extensionInstancesInjectable from "../../../extensions/extension-loader/extension-instances.injectable";
|
||||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||||
|
import broadcastMessageInjectable from "../../../common/ipc/broadcast-message.injectable";
|
||||||
jest.mock("../../../common/ipc");
|
|
||||||
|
|
||||||
function throwIfDefined(val: any): void {
|
function throwIfDefined(val: any): void {
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
@ -32,6 +30,7 @@ describe("protocol router tests", () => {
|
|||||||
let extensionInstances: ObservableMap<LensExtensionId, LensExtension>;
|
let extensionInstances: ObservableMap<LensExtensionId, LensExtension>;
|
||||||
let lpr: LensProtocolRouterMain;
|
let lpr: LensProtocolRouterMain;
|
||||||
let enabledExtensions: Set<string>;
|
let enabledExtensions: Set<string>;
|
||||||
|
let broadcastMessageMock: jest.Mock;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||||
@ -46,6 +45,9 @@ describe("protocol router tests", () => {
|
|||||||
|
|
||||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||||
|
|
||||||
|
broadcastMessageMock = jest.fn();
|
||||||
|
di.override(broadcastMessageInjectable, () => broadcastMessageMock);
|
||||||
|
|
||||||
extensionInstances = di.inject(extensionInstancesInjectable);
|
extensionInstances = di.inject(extensionInstancesInjectable);
|
||||||
lpr = di.inject(lensProtocolRouterMainInjectable);
|
lpr = di.inject(lensProtocolRouterMainInjectable);
|
||||||
|
|
||||||
@ -54,12 +56,12 @@ describe("protocol router tests", () => {
|
|||||||
|
|
||||||
it("should broadcast invalid protocol on non-lens URLs", async () => {
|
it("should broadcast invalid protocol on non-lens URLs", async () => {
|
||||||
await lpr.route("https://google.ca");
|
await lpr.route("https://google.ca");
|
||||||
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInvalid, "invalid protocol", "https://google.ca");
|
expect(broadcastMessageMock).toBeCalledWith(ProtocolHandlerInvalid, "invalid protocol", "https://google.ca");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should broadcast invalid host on non internal or non extension URLs", async () => {
|
it("should broadcast invalid host on non internal or non extension URLs", async () => {
|
||||||
await lpr.route("lens://foobar");
|
await lpr.route("lens://foobar");
|
||||||
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInvalid, "invalid host", "lens://foobar");
|
expect(broadcastMessageMock).toBeCalledWith(ProtocolHandlerInvalid, "invalid host", "lens://foobar");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not throw when has valid host", async () => {
|
it("should not throw when has valid host", async () => {
|
||||||
@ -101,8 +103,8 @@ describe("protocol router tests", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await delay(50);
|
await delay(50);
|
||||||
expect(broadcastMessage).toHaveBeenCalledWith(ProtocolHandlerInternal, "lens://app", "matched");
|
expect(broadcastMessageMock).toHaveBeenCalledWith(ProtocolHandlerInternal, "lens://app", "matched");
|
||||||
expect(broadcastMessage).toHaveBeenCalledWith(ProtocolHandlerExtension, "lens://extension/@mirantis/minikube", "matched");
|
expect(broadcastMessageMock).toHaveBeenCalledWith(ProtocolHandlerExtension, "lens://extension/@mirantis/minikube", "matched");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call handler if matches", async () => {
|
it("should call handler if matches", async () => {
|
||||||
@ -117,7 +119,7 @@ describe("protocol router tests", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(called).toBe(true);
|
expect(called).toBe(true);
|
||||||
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page", "matched");
|
expect(broadcastMessageMock).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page", "matched");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call most exact handler", async () => {
|
it("should call most exact handler", async () => {
|
||||||
@ -133,7 +135,7 @@ describe("protocol router tests", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(called).toBe("foo");
|
expect(called).toBe("foo");
|
||||||
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page/foo", "matched");
|
expect(broadcastMessageMock).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page/foo", "matched");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call most exact handler for an extension", async () => {
|
it("should call most exact handler for an extension", async () => {
|
||||||
@ -174,7 +176,7 @@ describe("protocol router tests", () => {
|
|||||||
|
|
||||||
await delay(50);
|
await delay(50);
|
||||||
expect(called).toBe("foob");
|
expect(called).toBe("foob");
|
||||||
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerExtension, "lens://extension/@foobar/icecream/page/foob", "matched");
|
expect(broadcastMessageMock).toBeCalledWith(ProtocolHandlerExtension, "lens://extension/@foobar/icecream/page/foob", "matched");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should work with non-org extensions", async () => {
|
it("should work with non-org extensions", async () => {
|
||||||
@ -244,7 +246,7 @@ describe("protocol router tests", () => {
|
|||||||
await delay(50);
|
await delay(50);
|
||||||
|
|
||||||
expect(called).toBe(1);
|
expect(called).toBe(1);
|
||||||
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerExtension, "lens://extension/icecream/page", "matched");
|
expect(broadcastMessageMock).toBeCalledWith(ProtocolHandlerExtension, "lens://extension/icecream/page", "matched");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should throw if urlSchema is invalid", () => {
|
it("should throw if urlSchema is invalid", () => {
|
||||||
@ -266,7 +268,7 @@ describe("protocol router tests", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(called).toBe(3);
|
expect(called).toBe(3);
|
||||||
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page/foo/bar/bat", "matched");
|
expect(broadcastMessageMock).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page/foo/bar/bat", "matched");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call most exact handler with 2 found handlers", async () => {
|
it("should call most exact handler with 2 found handlers", async () => {
|
||||||
@ -283,6 +285,6 @@ describe("protocol router tests", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(called).toBe(1);
|
expect(called).toBe(1);
|
||||||
expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page/foo/bar/bat", "matched");
|
expect(broadcastMessageMock).toBeCalledWith(ProtocolHandlerInternal, "lens://app/page/foo/bar/bat", "matched");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import extensionLoaderInjectable from "../../../extensions/extension-loader/exte
|
|||||||
import { LensProtocolRouterMain } from "./lens-protocol-router-main";
|
import { LensProtocolRouterMain } from "./lens-protocol-router-main";
|
||||||
import extensionsStoreInjectable from "../../../extensions/extensions-store/extensions-store.injectable";
|
import extensionsStoreInjectable from "../../../extensions/extensions-store/extensions-store.injectable";
|
||||||
import showApplicationWindowInjectable from "../../start-main-application/lens-window/show-application-window.injectable";
|
import showApplicationWindowInjectable from "../../start-main-application/lens-window/show-application-window.injectable";
|
||||||
|
import broadcastMessageInjectable from "../../../common/ipc/broadcast-message.injectable";
|
||||||
|
import loggerInjectable from "../../../common/logger.injectable";
|
||||||
|
|
||||||
const lensProtocolRouterMainInjectable = getInjectable({
|
const lensProtocolRouterMainInjectable = getInjectable({
|
||||||
id: "lens-protocol-router-main",
|
id: "lens-protocol-router-main",
|
||||||
@ -16,6 +18,8 @@ const lensProtocolRouterMainInjectable = getInjectable({
|
|||||||
extensionLoader: di.inject(extensionLoaderInjectable),
|
extensionLoader: di.inject(extensionLoaderInjectable),
|
||||||
extensionsStore: di.inject(extensionsStoreInjectable),
|
extensionsStore: di.inject(extensionsStoreInjectable),
|
||||||
showApplicationWindow: di.inject(showApplicationWindowInjectable),
|
showApplicationWindow: di.inject(showApplicationWindowInjectable),
|
||||||
|
broadcastMessage: di.inject(broadcastMessageInjectable),
|
||||||
|
logger: di.inject(loggerInjectable),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -3,15 +3,14 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import logger from "../../logger";
|
|
||||||
import * as proto from "../../../common/protocol-handler";
|
import * as proto from "../../../common/protocol-handler";
|
||||||
import URLParse from "url-parse";
|
import URLParse from "url-parse";
|
||||||
import type { LensExtension } from "../../../extensions/lens-extension";
|
import type { LensExtension } from "../../../extensions/lens-extension";
|
||||||
import { broadcastMessage } from "../../../common/ipc";
|
|
||||||
import { observable, when, makeObservable } from "mobx";
|
import { observable, when, makeObservable } from "mobx";
|
||||||
import type { LensProtocolRouterDependencies, RouteAttempt } from "../../../common/protocol-handler";
|
import type { LensProtocolRouterDependencies, RouteAttempt } from "../../../common/protocol-handler";
|
||||||
import { ProtocolHandlerInvalid } from "../../../common/protocol-handler";
|
import { ProtocolHandlerInvalid } from "../../../common/protocol-handler";
|
||||||
import { disposer, noop } from "../../../common/utils";
|
import { disposer, noop } from "../../../common/utils";
|
||||||
|
import type { BroadcastMessage } from "../../../common/ipc/broadcast-message.injectable";
|
||||||
|
|
||||||
export interface FallbackHandler {
|
export interface FallbackHandler {
|
||||||
(name: string): Promise<boolean>;
|
(name: string): Promise<boolean>;
|
||||||
@ -36,6 +35,7 @@ function checkHost<Query>(url: URLParse<Query>): boolean {
|
|||||||
|
|
||||||
export interface LensProtocolRouterMainDependencies extends LensProtocolRouterDependencies {
|
export interface LensProtocolRouterMainDependencies extends LensProtocolRouterDependencies {
|
||||||
showApplicationWindow: () => Promise<void>;
|
showApplicationWindow: () => Promise<void>;
|
||||||
|
broadcastMessage: BroadcastMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
||||||
@ -73,7 +73,7 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
|||||||
this.dependencies.showApplicationWindow().catch(noop);
|
this.dependencies.showApplicationWindow().catch(noop);
|
||||||
const routeInternally = checkHost(url);
|
const routeInternally = checkHost(url);
|
||||||
|
|
||||||
logger.info(`${proto.LensProtocolRouter.LoggingPrefix}: routing ${url.toString()}`);
|
this.dependencies.logger.info(`${proto.LensProtocolRouter.LoggingPrefix}: routing ${url.toString()}`);
|
||||||
|
|
||||||
if (routeInternally) {
|
if (routeInternally) {
|
||||||
this._routeToInternal(url);
|
this._routeToInternal(url);
|
||||||
@ -81,12 +81,12 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
|||||||
await this._routeToExtension(url);
|
await this._routeToExtension(url);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
broadcastMessage(ProtocolHandlerInvalid, error ? String(error) : "unknown error", rawUrl);
|
this.dependencies.broadcastMessage(ProtocolHandlerInvalid, error ? String(error) : "unknown error", rawUrl);
|
||||||
|
|
||||||
if (error instanceof proto.RoutingError) {
|
if (error instanceof proto.RoutingError) {
|
||||||
logger.error(`${proto.LensProtocolRouter.LoggingPrefix}: ${error}`, { url: error.url });
|
this.dependencies.logger.error(`${proto.LensProtocolRouter.LoggingPrefix}: ${error}`, { url: error.url });
|
||||||
} else {
|
} else {
|
||||||
logger.error(`${proto.LensProtocolRouter.LoggingPrefix}: ${error}`, { rawUrl });
|
this.dependencies.logger.error(`${proto.LensProtocolRouter.LoggingPrefix}: ${error}`, { rawUrl });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
|||||||
const rawUrl = url.toString(); // for sending to renderer
|
const rawUrl = url.toString(); // for sending to renderer
|
||||||
const attempt = super._routeToInternal(url);
|
const attempt = super._routeToInternal(url);
|
||||||
|
|
||||||
this.disposers.push(when(() => this.rendererLoaded, () => broadcastMessage(proto.ProtocolHandlerInternal, rawUrl, attempt)));
|
this.disposers.push(when(() => this.rendererLoaded, () => this.dependencies.broadcastMessage(proto.ProtocolHandlerInternal, rawUrl, attempt)));
|
||||||
|
|
||||||
return attempt;
|
return attempt;
|
||||||
}
|
}
|
||||||
@ -136,7 +136,7 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
|||||||
*/
|
*/
|
||||||
const attempt = await super._routeToExtension(new URLParse(url.toString(), true));
|
const attempt = await super._routeToExtension(new URLParse(url.toString(), true));
|
||||||
|
|
||||||
this.disposers.push(when(() => this.rendererLoaded, () => broadcastMessage(proto.ProtocolHandlerExtension, rawUrl, attempt)));
|
this.disposers.push(when(() => this.rendererLoaded, () => this.dependencies.broadcastMessage(proto.ProtocolHandlerExtension, rawUrl, attempt)));
|
||||||
|
|
||||||
return attempt;
|
return attempt;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import { beforeApplicationIsLoadingInjectionToken } from "./runnable-tokens/befo
|
|||||||
import { onLoadOfApplicationInjectionToken } from "./runnable-tokens/on-load-of-application-injection-token";
|
import { onLoadOfApplicationInjectionToken } from "./runnable-tokens/on-load-of-application-injection-token";
|
||||||
import { afterApplicationIsLoadedInjectionToken } from "./runnable-tokens/after-application-is-loaded-injection-token";
|
import { afterApplicationIsLoadedInjectionToken } from "./runnable-tokens/after-application-is-loaded-injection-token";
|
||||||
import splashWindowInjectable from "./lens-window/splash-window/splash-window.injectable";
|
import splashWindowInjectable from "./lens-window/splash-window/splash-window.injectable";
|
||||||
|
|
||||||
import openDeepLinkInjectable from "../protocol-handler/lens-protocol-router-main/open-deep-link-for-url/open-deep-link.injectable";
|
import openDeepLinkInjectable from "../protocol-handler/lens-protocol-router-main/open-deep-link-for-url/open-deep-link.injectable";
|
||||||
import { pipeline } from "@ogre-tools/fp";
|
import { pipeline } from "@ogre-tools/fp";
|
||||||
import { find, map, startsWith, toLower } from "lodash/fp";
|
import { find, map, startsWith, toLower } from "lodash/fp";
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import type { IpcMain } from "electron";
|
||||||
|
import { getGlobalOverride } from "../../../../common/test-utils/get-global-override";
|
||||||
|
import ipcMainInjectable from "./ipc-main.injectable";
|
||||||
|
|
||||||
|
export default getGlobalOverride(ipcMainInjectable, () => ({
|
||||||
|
handle: () => {},
|
||||||
|
on: () => {},
|
||||||
|
off: () => {},
|
||||||
|
}) as unknown as IpcMain);
|
||||||
@ -6,12 +6,14 @@ import { getInjectable } from "@ogre-tools/injectable";
|
|||||||
import catalogCategoryRegistryInjectable from "../../../../common/catalog/category-registry.injectable";
|
import catalogCategoryRegistryInjectable from "../../../../common/catalog/category-registry.injectable";
|
||||||
import navigateInjectable from "../../../navigation/navigate.injectable";
|
import navigateInjectable from "../../../navigation/navigate.injectable";
|
||||||
import { CatalogEntityRegistry } from "./registry";
|
import { CatalogEntityRegistry } from "./registry";
|
||||||
|
import loggerInjectable from "../../../../common/logger.injectable";
|
||||||
|
|
||||||
const catalogEntityRegistryInjectable = getInjectable({
|
const catalogEntityRegistryInjectable = getInjectable({
|
||||||
id: "catalog-entity-registry",
|
id: "catalog-entity-registry",
|
||||||
instantiate: (di) => new CatalogEntityRegistry({
|
instantiate: (di) => new CatalogEntityRegistry({
|
||||||
categoryRegistry: di.inject(catalogCategoryRegistryInjectable),
|
categoryRegistry: di.inject(catalogCategoryRegistryInjectable),
|
||||||
navigate: di.inject(navigateInjectable),
|
navigate: di.inject(navigateInjectable),
|
||||||
|
logger: di.inject(loggerInjectable),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -10,12 +10,12 @@ import "../../../../common/catalog-entities";
|
|||||||
import { iter } from "../../../utils";
|
import { iter } from "../../../utils";
|
||||||
import type { Disposer } from "../../../utils";
|
import type { Disposer } from "../../../utils";
|
||||||
import { once } from "lodash";
|
import { once } from "lodash";
|
||||||
import logger from "../../../../common/logger";
|
|
||||||
import { CatalogRunEvent } from "../../../../common/catalog/catalog-run-event";
|
import { CatalogRunEvent } from "../../../../common/catalog/catalog-run-event";
|
||||||
import { ipcRenderer } from "electron";
|
import { ipcRenderer } from "electron";
|
||||||
import { catalogInitChannel, catalogItemsChannel, catalogEntityRunListener } from "../../../../common/ipc/catalog";
|
import { catalogInitChannel, catalogItemsChannel, catalogEntityRunListener } from "../../../../common/ipc/catalog";
|
||||||
import { isMainFrame } from "process";
|
import { isMainFrame } from "process";
|
||||||
import type { Navigate } from "../../../navigation/navigate.injectable";
|
import type { Navigate } from "../../../navigation/navigate.injectable";
|
||||||
|
import type { Logger } from "../../../../common/logger";
|
||||||
|
|
||||||
export type EntityFilter = (entity: CatalogEntity) => any;
|
export type EntityFilter = (entity: CatalogEntity) => any;
|
||||||
export type CatalogEntityOnBeforeRun = (event: CatalogRunEvent) => void | Promise<void>;
|
export type CatalogEntityOnBeforeRun = (event: CatalogRunEvent) => void | Promise<void>;
|
||||||
@ -23,6 +23,7 @@ export type CatalogEntityOnBeforeRun = (event: CatalogRunEvent) => void | Promis
|
|||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
navigate: Navigate;
|
navigate: Navigate;
|
||||||
readonly categoryRegistry: CatalogCategoryRegistry;
|
readonly categoryRegistry: CatalogCategoryRegistry;
|
||||||
|
logger: Logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CatalogEntityRegistry {
|
export class CatalogEntityRegistry {
|
||||||
@ -219,7 +220,7 @@ export class CatalogEntityRegistry {
|
|||||||
* @returns Whether the entities `onRun` method should be executed
|
* @returns Whether the entities `onRun` method should be executed
|
||||||
*/
|
*/
|
||||||
async onBeforeRun(entity: CatalogEntity): Promise<boolean> {
|
async onBeforeRun(entity: CatalogEntity): Promise<boolean> {
|
||||||
logger.debug(`[CATALOG-ENTITY-REGISTRY]: run onBeforeRun on ${entity.getId()}`);
|
this.dependencies.logger.debug(`[CATALOG-ENTITY-REGISTRY]: run onBeforeRun on ${entity.getId()}`);
|
||||||
|
|
||||||
const runEvent = new CatalogRunEvent({ target: entity });
|
const runEvent = new CatalogRunEvent({ target: entity });
|
||||||
|
|
||||||
@ -227,7 +228,7 @@ export class CatalogEntityRegistry {
|
|||||||
try {
|
try {
|
||||||
await onBeforeRun(runEvent);
|
await onBeforeRun(runEvent);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.warn(`[CATALOG-ENTITY-REGISTRY]: entity ${entity.getId()} onBeforeRun threw an error`, error);
|
this.dependencies.logger.warn(`[CATALOG-ENTITY-REGISTRY]: entity ${entity.getId()} onBeforeRun threw an error`, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runEvent.defaultPrevented) {
|
if (runEvent.defaultPrevented) {
|
||||||
@ -253,9 +254,9 @@ export class CatalogEntityRegistry {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
logger.debug(`onBeforeRun for ${entity.getId()} returned false`);
|
this.dependencies.logger.debug(`onBeforeRun for ${entity.getId()} returned false`);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => logger.error(`[CATALOG-ENTITY-REGISTRY]: entity ${entity.getId()} onRun threw an error`, error));
|
.catch(error => this.dependencies.logger.error(`[CATALOG-ENTITY-REGISTRY]: entity ${entity.getId()} onRun threw an error`, error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,10 +7,9 @@ import React from "react";
|
|||||||
import { screen } from "@testing-library/react";
|
import { screen } from "@testing-library/react";
|
||||||
import userEvent from "@testing-library/user-event";
|
import userEvent from "@testing-library/user-event";
|
||||||
import { Catalog } from "./catalog";
|
import { Catalog } from "./catalog";
|
||||||
import { mockWindow } from "../../../../__mocks__/windowMock";
|
|
||||||
import type { CatalogEntityActionContext, CatalogEntityData } from "../../../common/catalog";
|
import type { CatalogEntityActionContext, CatalogEntityData } from "../../../common/catalog";
|
||||||
import { CatalogEntity } from "../../../common/catalog";
|
import { CatalogEntity } from "../../../common/catalog";
|
||||||
import type { CatalogEntityRegistry } from "../../api/catalog/entity/registry";
|
import type { CatalogEntityOnBeforeRun, CatalogEntityRegistry } from "../../api/catalog/entity/registry";
|
||||||
import { CatalogEntityDetailRegistry } from "../../../extensions/registries";
|
import { CatalogEntityDetailRegistry } from "../../../extensions/registries";
|
||||||
import type { CatalogEntityStore } from "./catalog-entity-store/catalog-entity.store";
|
import type { CatalogEntityStore } from "./catalog-entity-store/catalog-entity.store";
|
||||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||||
@ -19,38 +18,15 @@ import catalogEntityStoreInjectable from "./catalog-entity-store/catalog-entity-
|
|||||||
import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.injectable";
|
import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.injectable";
|
||||||
import type { DiRender } from "../test-utils/renderFor";
|
import type { DiRender } from "../test-utils/renderFor";
|
||||||
import { renderFor } from "../test-utils/renderFor";
|
import { renderFor } from "../test-utils/renderFor";
|
||||||
import mockFs from "mock-fs";
|
|
||||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||||
import getConfigurationFileModelInjectable from "../../../common/get-configuration-file-model/get-configuration-file-model.injectable";
|
import getConfigurationFileModelInjectable from "../../../common/get-configuration-file-model/get-configuration-file-model.injectable";
|
||||||
import type { AppEvent } from "../../../common/app-event-bus/event-bus";
|
import type { AppEvent } from "../../../common/app-event-bus/event-bus";
|
||||||
import appEventBusInjectable from "../../../common/app-event-bus/app-event-bus.injectable";
|
import appEventBusInjectable from "../../../common/app-event-bus/app-event-bus.injectable";
|
||||||
import { computed } from "mobx";
|
import { computed } from "mobx";
|
||||||
import broadcastMessageInjectable from "../../../common/ipc/broadcast-message.injectable";
|
import broadcastMessageInjectable from "../../../common/ipc/broadcast-message.injectable";
|
||||||
|
import type { AsyncFnMock } from "@async-fn/jest";
|
||||||
mockWindow();
|
import asyncFn from "@async-fn/jest";
|
||||||
jest.mock("electron", () => ({
|
import { flushPromises } from "../../../common/test-utils/flush-promises";
|
||||||
app: {
|
|
||||||
getVersion: () => "99.99.99",
|
|
||||||
getName: () => "lens",
|
|
||||||
setName: jest.fn(),
|
|
||||||
setPath: jest.fn(),
|
|
||||||
getPath: () => "tmp",
|
|
||||||
getLocale: () => "en",
|
|
||||||
setLoginItemSettings: jest.fn(),
|
|
||||||
},
|
|
||||||
ipcMain: {
|
|
||||||
on: jest.fn(),
|
|
||||||
handle: jest.fn(),
|
|
||||||
},
|
|
||||||
ipcRenderer: {
|
|
||||||
on: jest.fn(),
|
|
||||||
invoke: jest.fn(),
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
jest.mock("./hotbar-toggle-menu-item", () => ({
|
|
||||||
HotbarToggleMenuItem: () => <div>menu item</div>,
|
|
||||||
}));
|
|
||||||
|
|
||||||
class MockCatalogEntity extends CatalogEntity {
|
class MockCatalogEntity extends CatalogEntity {
|
||||||
public apiVersion = "api";
|
public apiVersion = "api";
|
||||||
@ -95,7 +71,6 @@ describe("<Catalog />", () => {
|
|||||||
|
|
||||||
di.permitSideEffects(getConfigurationFileModelInjectable);
|
di.permitSideEffects(getConfigurationFileModelInjectable);
|
||||||
|
|
||||||
mockFs();
|
|
||||||
CatalogEntityDetailRegistry.createInstance();
|
CatalogEntityDetailRegistry.createInstance();
|
||||||
|
|
||||||
render = renderFor(di);
|
render = renderFor(di);
|
||||||
@ -103,8 +78,6 @@ describe("<Catalog />", () => {
|
|||||||
catalogEntityItem = createMockCatalogEntity(onRun);
|
catalogEntityItem = createMockCatalogEntity(onRun);
|
||||||
catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable);
|
catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable);
|
||||||
|
|
||||||
di.override(catalogEntityRegistryInjectable, () => catalogEntityRegistry);
|
|
||||||
|
|
||||||
emitEvent = jest.fn();
|
emitEvent = jest.fn();
|
||||||
|
|
||||||
di.override(appEventBusInjectable, () => ({
|
di.override(appEventBusInjectable, () => ({
|
||||||
@ -119,60 +92,71 @@ describe("<Catalog />", () => {
|
|||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
CatalogEntityDetailRegistry.resetInstance();
|
CatalogEntityDetailRegistry.resetInstance();
|
||||||
jest.clearAllMocks();
|
|
||||||
jest.restoreAllMocks();
|
|
||||||
mockFs.restore();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("can use catalogEntityRegistry.addOnBeforeRun to add hooks for catalog entities", (done) => {
|
describe("can use catalogEntityRegistry.addOnBeforeRun to add hooks for catalog entities", () => {
|
||||||
catalogEntityRegistry.addOnBeforeRun(
|
let onBeforeRunMock: AsyncFnMock<CatalogEntityOnBeforeRun>;
|
||||||
(event) => {
|
|
||||||
expect(event.target.getId()).toBe("a_catalogEntity_uid");
|
|
||||||
expect(event.target.getName()).toBe("a catalog entity");
|
|
||||||
|
|
||||||
setTimeout(() => {
|
beforeEach(() => {
|
||||||
expect(onRun).toHaveBeenCalled();
|
onBeforeRunMock = asyncFn();
|
||||||
done();
|
|
||||||
}, 500);
|
catalogEntityRegistry.addOnBeforeRun(onBeforeRunMock);
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
render(<Catalog />);
|
render(<Catalog />);
|
||||||
|
|
||||||
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("onBeforeRun prevents event => onRun wont be triggered", (done) => {
|
it("calls on before run event", () => {
|
||||||
catalogEntityRegistry.addOnBeforeRun(
|
const target = onBeforeRunMock.mock.calls[0][0].target;
|
||||||
(e) => {
|
|
||||||
setTimeout(() => {
|
const actual = { id: target.getId(), name: target.getName() };
|
||||||
|
|
||||||
|
expect(actual).toEqual({
|
||||||
|
id: "a_catalogEntity_uid",
|
||||||
|
name: "a catalog entity",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not call onRun yet", () => {
|
||||||
expect(onRun).not.toHaveBeenCalled();
|
expect(onRun).not.toHaveBeenCalled();
|
||||||
done();
|
|
||||||
}, 500);
|
|
||||||
e.preventDefault();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
render(<Catalog />);
|
|
||||||
|
|
||||||
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("addOnBeforeRun throw an exception => onRun will be triggered", (done) => {
|
it("when before run event resolves, calls onRun", async () => {
|
||||||
catalogEntityRegistry.addOnBeforeRun(
|
await onBeforeRunMock.resolve();
|
||||||
() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
expect(onRun).toHaveBeenCalled();
|
|
||||||
done();
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
throw new Error("error!");
|
expect(onRun).toHaveBeenCalled();
|
||||||
},
|
});
|
||||||
);
|
});
|
||||||
|
|
||||||
|
it("onBeforeRun prevents event => onRun wont be triggered", async () => {
|
||||||
|
const onBeforeRunMock = jest.fn((event) => event.preventDefault());
|
||||||
|
|
||||||
|
catalogEntityRegistry.addOnBeforeRun(onBeforeRunMock);
|
||||||
|
|
||||||
render(<Catalog />);
|
render(<Catalog />);
|
||||||
|
|
||||||
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
||||||
|
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(onRun).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("addOnBeforeRun throw an exception => onRun will be triggered", async () => {
|
||||||
|
const onBeforeRunMock = jest.fn(() => {
|
||||||
|
throw new Error("some error");
|
||||||
|
});
|
||||||
|
|
||||||
|
catalogEntityRegistry.addOnBeforeRun(onBeforeRunMock);
|
||||||
|
|
||||||
|
render(<Catalog />);
|
||||||
|
|
||||||
|
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
||||||
|
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(onRun).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("addOnRunHook return a promise and does not prevent run event => onRun()", (done) => {
|
it("addOnRunHook return a promise and does not prevent run event => onRun()", (done) => {
|
||||||
@ -189,40 +173,34 @@ describe("<Catalog />", () => {
|
|||||||
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("addOnRunHook return a promise and prevents event wont be triggered", (done) => {
|
it("addOnRunHook return a promise and prevents event wont be triggered", async () => {
|
||||||
catalogEntityRegistry.addOnBeforeRun(
|
const onBeforeRunMock = asyncFn();
|
||||||
async (e) => {
|
|
||||||
expect(onRun).not.toBeCalled();
|
|
||||||
|
|
||||||
setTimeout(() => {
|
catalogEntityRegistry.addOnBeforeRun(onBeforeRunMock);
|
||||||
expect(onRun).not.toBeCalled();
|
|
||||||
done();
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
render(<Catalog />);
|
render(<Catalog />);
|
||||||
|
|
||||||
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
||||||
|
|
||||||
|
onBeforeRunMock.mock.calls[0][0].preventDefault();
|
||||||
|
|
||||||
|
await onBeforeRunMock.resolve();
|
||||||
|
|
||||||
|
expect(onRun).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("addOnRunHook return a promise and reject => onRun will be triggered", (done) => {
|
it("addOnRunHook return a promise and reject => onRun will be triggered", async () => {
|
||||||
catalogEntityRegistry.addOnBeforeRun(
|
const onBeforeRunMock = asyncFn();
|
||||||
async () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
expect(onRun).toHaveBeenCalled();
|
|
||||||
done();
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
throw new Error("rejection!");
|
catalogEntityRegistry.addOnBeforeRun(onBeforeRunMock);
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
render(<Catalog />);
|
render(<Catalog />);
|
||||||
|
|
||||||
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
||||||
|
|
||||||
|
await onBeforeRunMock.reject();
|
||||||
|
|
||||||
|
expect(onRun).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("emits catalog open AppEvent", () => {
|
it("emits catalog open AppEvent", () => {
|
||||||
|
|||||||
@ -4,17 +4,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { render } from "@testing-library/react";
|
|
||||||
import { SecretDetails } from "../secret-details";
|
import { SecretDetails } from "../secret-details";
|
||||||
import { Secret, SecretType } from "../../../../common/k8s-api/endpoints";
|
import { Secret, SecretType } from "../../../../common/k8s-api/endpoints";
|
||||||
|
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
||||||
|
import { renderFor } from "../../test-utils/renderFor";
|
||||||
|
|
||||||
jest.mock("../../kube-object-meta/kube-object-meta", () => ({
|
jest.mock("../../kube-object-meta/kube-object-meta", () => ({
|
||||||
KubeObjectMeta: () => null,
|
KubeObjectMeta: () => null,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
describe("SecretDetails tests", () => {
|
describe("SecretDetails tests", () => {
|
||||||
it("should show the visibility toggle when the secret value is ''", () => {
|
it("should show the visibility toggle when the secret value is ''", () => {
|
||||||
|
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||||
|
const render = renderFor(di);
|
||||||
|
|
||||||
const secret = new Secret({
|
const secret = new Secret({
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
kind: "secret",
|
kind: "secret",
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
margin-right: -8px;
|
margin-right: -8px;
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
|
line-height: 1.1;
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
|
|||||||
@ -4,15 +4,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { findByTestId, findByText, render } from "@testing-library/react";
|
import { findByTestId, findByText } from "@testing-library/react";
|
||||||
import { NetworkPolicy } from "../../../../common/k8s-api/endpoints";
|
import { NetworkPolicy } from "../../../../common/k8s-api/endpoints";
|
||||||
import { NetworkPolicyDetails } from "../network-policy-details";
|
import { NetworkPolicyDetails } from "../network-policy-details";
|
||||||
|
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
||||||
jest.mock("../../kube-object-meta/kube-object-meta", () => ({
|
import type { DiRender } from "../../test-utils/renderFor";
|
||||||
KubeObjectMeta: () => null,
|
import { renderFor } from "../../test-utils/renderFor";
|
||||||
}));
|
|
||||||
|
|
||||||
describe("NetworkPolicyDetails", () => {
|
describe("NetworkPolicyDetails", () => {
|
||||||
|
let render: DiRender;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||||
|
|
||||||
|
render = renderFor(di);
|
||||||
|
});
|
||||||
|
|
||||||
it("should render w/o errors", () => {
|
it("should render w/o errors", () => {
|
||||||
const policy = new NetworkPolicy({
|
const policy = new NetworkPolicy({
|
||||||
metadata: {} as never,
|
metadata: {} as never,
|
||||||
|
|||||||
@ -31,6 +31,10 @@
|
|||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.node {
|
||||||
|
flex-grow: 2;
|
||||||
|
}
|
||||||
|
|
||||||
&.namespace {
|
&.namespace {
|
||||||
flex-grow: 1.2;
|
flex-grow: 1.2;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import { showDetails } from "../kube-detail-params";
|
|||||||
|
|
||||||
enum sortBy {
|
enum sortBy {
|
||||||
name = "name",
|
name = "name",
|
||||||
|
node = "node",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
cpu = "cpu",
|
cpu = "cpu",
|
||||||
memory = "memory",
|
memory = "memory",
|
||||||
@ -124,6 +125,7 @@ export class PodDetailsList extends React.Component<PodDetailsListProps> {
|
|||||||
>
|
>
|
||||||
<TableCell className="name">{pod.getName()}</TableCell>
|
<TableCell className="name">{pod.getName()}</TableCell>
|
||||||
<TableCell className="warning"><KubeObjectStatusIcon key="icon" object={pod}/></TableCell>
|
<TableCell className="warning"><KubeObjectStatusIcon key="icon" object={pod}/></TableCell>
|
||||||
|
<TableCell className="node">{pod.getNodeName()}</TableCell>
|
||||||
<TableCell className="namespace">{pod.getNs()}</TableCell>
|
<TableCell className="namespace">{pod.getNs()}</TableCell>
|
||||||
<TableCell className="ready">
|
<TableCell className="ready">
|
||||||
{`${pod.getRunningContainers().length} / ${pod.getContainers().length}`}
|
{`${pod.getRunningContainers().length} / ${pod.getContainers().length}`}
|
||||||
@ -165,6 +167,7 @@ export class PodDetailsList extends React.Component<PodDetailsListProps> {
|
|||||||
virtualHeight={660}
|
virtualHeight={660}
|
||||||
sortable={{
|
sortable={{
|
||||||
[sortBy.name]: pod => pod.getName(),
|
[sortBy.name]: pod => pod.getName(),
|
||||||
|
[sortBy.node]: pod => pod.getNodeName(),
|
||||||
[sortBy.namespace]: pod => pod.getNs(),
|
[sortBy.namespace]: pod => pod.getNs(),
|
||||||
[sortBy.cpu]: pod => podStore.getPodKubeMetrics(pod).cpu,
|
[sortBy.cpu]: pod => podStore.getPodKubeMetrics(pod).cpu,
|
||||||
[sortBy.memory]: pod => podStore.getPodKubeMetrics(pod).memory,
|
[sortBy.memory]: pod => podStore.getPodKubeMetrics(pod).memory,
|
||||||
@ -182,6 +185,7 @@ export class PodDetailsList extends React.Component<PodDetailsListProps> {
|
|||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell className="name" sortBy={sortBy.name}>Name</TableCell>
|
<TableCell className="name" sortBy={sortBy.name}>Name</TableCell>
|
||||||
<TableCell className="warning"/>
|
<TableCell className="warning"/>
|
||||||
|
<TableCell className="node" sortBy={sortBy.node}>Node</TableCell>
|
||||||
<TableCell className="namespace" sortBy={sortBy.namespace}>Namespace</TableCell>
|
<TableCell className="namespace" sortBy={sortBy.namespace}>Namespace</TableCell>
|
||||||
<TableCell className="ready">Ready</TableCell>
|
<TableCell className="ready">Ready</TableCell>
|
||||||
<TableCell className="cpu" sortBy={sortBy.cpu}>CPU</TableCell>
|
<TableCell className="cpu" sortBy={sortBy.cpu}>CPU</TableCell>
|
||||||
|
|||||||
@ -116,6 +116,9 @@ export class PodDetails extends React.Component<PodDetailsProps> {
|
|||||||
>
|
>
|
||||||
{podIPs.map(label => <Badge key={label} label={label} />)}
|
{podIPs.map(label => <Badge key={label} label={label} />)}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Service Account">
|
||||||
|
{pod.getServiceAccountName()}
|
||||||
|
</DrawerItem>
|
||||||
<DrawerItem name="Priority Class">
|
<DrawerItem name="Priority Class">
|
||||||
{pod.getPriorityClassName()}
|
{pod.getPriorityClassName()}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|||||||
@ -104,7 +104,7 @@ class NonInjectedReplicaSetScaleDialog extends Component<ReplicaSetScaleDialogPr
|
|||||||
<Wizard
|
<Wizard
|
||||||
header={(
|
header={(
|
||||||
<h5>
|
<h5>
|
||||||
Scale Replica Set
|
{"Scale Replica Set "}
|
||||||
<span>{replicaSet.getName()}</span>
|
<span>{replicaSet.getName()}</span>
|
||||||
</h5>
|
</h5>
|
||||||
)}
|
)}
|
||||||
@ -131,16 +131,16 @@ class NonInjectedReplicaSetScaleDialog extends Component<ReplicaSetScaleDialogPr
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="plus-minus-container flex gaps">
|
<div className="plus-minus-container flex gaps">
|
||||||
<Icon
|
|
||||||
material="add_circle_outline"
|
|
||||||
onClick={this.desiredReplicasUp}
|
|
||||||
data-testid="desired-replicas-up"
|
|
||||||
/>
|
|
||||||
<Icon
|
<Icon
|
||||||
material="remove_circle_outline"
|
material="remove_circle_outline"
|
||||||
onClick={this.desiredReplicasDown}
|
onClick={this.desiredReplicasDown}
|
||||||
data-testid="desired-replicas-down"
|
data-testid="desired-replicas-down"
|
||||||
/>
|
/>
|
||||||
|
<Icon
|
||||||
|
material="add_circle_outline"
|
||||||
|
onClick={this.desiredReplicasUp}
|
||||||
|
data-testid="desired-replicas-up"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{warning && (
|
{warning && (
|
||||||
|
|||||||
@ -180,6 +180,10 @@ a {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
color-scheme: auto;
|
||||||
|
}
|
||||||
|
|
||||||
// colors
|
// colors
|
||||||
.success {
|
.success {
|
||||||
color: var(--colorSuccess);
|
color: var(--colorSuccess);
|
||||||
|
|||||||
@ -4,28 +4,38 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { render, waitFor } from "@testing-library/react";
|
import { waitFor } from "@testing-library/react";
|
||||||
import { ClusterLocalTerminalSetting } from "../cluster-local-terminal-settings";
|
import { ClusterLocalTerminalSetting } from "../cluster-local-terminal-settings";
|
||||||
import userEvent from "@testing-library/user-event";
|
import userEvent from "@testing-library/user-event";
|
||||||
import { stat } from "fs/promises";
|
|
||||||
import { Notifications } from "../../../notifications";
|
|
||||||
import type { Stats } from "fs";
|
import type { Stats } from "fs";
|
||||||
import type { Cluster } from "../../../../../common/cluster/cluster";
|
import type { Cluster } from "../../../../../common/cluster/cluster";
|
||||||
|
import { getDiForUnitTesting } from "../../../../getDiForUnitTesting";
|
||||||
const mockStat = stat as jest.MockedFunction<typeof stat>;
|
import type { DiRender } from "../../../test-utils/renderFor";
|
||||||
|
import { renderFor } from "../../../test-utils/renderFor";
|
||||||
jest.mock("fs", () => {
|
import showErrorNotificationInjectable from "../../../notifications/show-error-notification.injectable";
|
||||||
const actual = jest.requireActual("fs");
|
import statInjectable from "../../../../../common/fs/stat/stat.injectable";
|
||||||
|
|
||||||
actual.promises.stat = jest.fn();
|
|
||||||
|
|
||||||
return actual;
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.mock("../../../notifications");
|
|
||||||
|
|
||||||
describe("ClusterLocalTerminalSettings", () => {
|
describe("ClusterLocalTerminalSettings", () => {
|
||||||
|
let render: DiRender;
|
||||||
|
let showErrorNotificationMock: jest.Mock;
|
||||||
|
let statMock: jest.Mock;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||||
|
|
||||||
|
showErrorNotificationMock = jest.fn();
|
||||||
|
|
||||||
|
statMock = jest.fn();
|
||||||
|
|
||||||
|
di.override(statInjectable, () => statMock);
|
||||||
|
|
||||||
|
di.override(
|
||||||
|
showErrorNotificationInjectable,
|
||||||
|
() => showErrorNotificationMock,
|
||||||
|
);
|
||||||
|
|
||||||
|
render = renderFor(di);
|
||||||
|
|
||||||
jest.resetAllMocks();
|
jest.resetAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -89,7 +99,7 @@ describe("ClusterLocalTerminalSettings", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should save the new CWD if path is a directory", async () => {
|
it("should save the new CWD if path is a directory", async () => {
|
||||||
mockStat.mockImplementation(async (path) => {
|
statMock.mockImplementation(async (path) => {
|
||||||
expect(path).toBe("/foobar");
|
expect(path).toBe("/foobar");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -114,7 +124,7 @@ describe("ClusterLocalTerminalSettings", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not save the new CWD if path is a file", async () => {
|
it("should not save the new CWD if path is a file", async () => {
|
||||||
mockStat.mockImplementation(async (path) => {
|
statMock.mockImplementation(async (path) => {
|
||||||
expect(path).toBe("/foobar");
|
expect(path).toBe("/foobar");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -136,6 +146,6 @@ describe("ClusterLocalTerminalSettings", () => {
|
|||||||
userEvent.type(dn, "/foobar");
|
userEvent.type(dn, "/foobar");
|
||||||
userEvent.click(dom.baseElement);
|
userEvent.click(dom.baseElement);
|
||||||
|
|
||||||
await waitFor(() => expect(Notifications.error).toBeCalled());
|
await waitFor(() => expect(showErrorNotificationMock).toHaveBeenCalled());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,79 +8,25 @@ import { observer } from "mobx-react";
|
|||||||
import type { Cluster } from "../../../../common/cluster/cluster";
|
import type { Cluster } from "../../../../common/cluster/cluster";
|
||||||
import { Input } from "../../input";
|
import { Input } from "../../input";
|
||||||
import { SubTitle } from "../../layout/sub-title";
|
import { SubTitle } from "../../layout/sub-title";
|
||||||
import { stat } from "fs/promises";
|
import type { ShowNotification } from "../../notifications";
|
||||||
import { Notifications } from "../../notifications";
|
import { resolveTilde } from "../../../utils";
|
||||||
import { isErrnoException, resolveTilde } from "../../../utils";
|
|
||||||
import { Icon } from "../../icon";
|
import { Icon } from "../../icon";
|
||||||
import { PathPicker } from "../../path-picker";
|
import { PathPicker } from "../../path-picker";
|
||||||
import { isWindows } from "../../../../common/vars";
|
import { isWindows } from "../../../../common/vars";
|
||||||
import type { Stats } from "fs";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import logger from "../../../../common/logger";
|
import showErrorNotificationInjectable from "../../notifications/show-error-notification.injectable";
|
||||||
import { lowerFirst } from "lodash";
|
import type { ValidateDirectory } from "../../../../common/fs/validate-directory.injectable";
|
||||||
|
import validateDirectoryInjectable from "../../../../common/fs/validate-directory.injectable";
|
||||||
|
|
||||||
export interface ClusterLocalTerminalSettingProps {
|
export interface ClusterLocalTerminalSettingProps {
|
||||||
cluster: Cluster;
|
cluster: Cluster;
|
||||||
}
|
}
|
||||||
|
interface Dependencies {
|
||||||
function getUserReadableFileType(stats: Stats): string {
|
showErrorNotification: ShowNotification;
|
||||||
if (stats.isFile()) {
|
validateDirectory: ValidateDirectory;
|
||||||
return "a file";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats.isFIFO()) {
|
|
||||||
return "a pipe";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats.isSocket()) {
|
|
||||||
return "a socket";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats.isBlockDevice()) {
|
|
||||||
return "a block device";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats.isCharacterDevice()) {
|
|
||||||
return "a character device";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "an unknown file type";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
const NonInjectedClusterLocalTerminalSetting = observer(({ cluster, showErrorNotification, validateDirectory }: Dependencies & ClusterLocalTerminalSettingProps) => {
|
||||||
* Validate that `dir` currently points to a directory. If so return `false`.
|
|
||||||
* Otherwise, return a user readable error message string for displaying.
|
|
||||||
* @param dir The path to be validated
|
|
||||||
*/
|
|
||||||
async function validateDirectory(dir: string): Promise<string | false> {
|
|
||||||
try {
|
|
||||||
const stats = await stat(dir);
|
|
||||||
|
|
||||||
if (stats.isDirectory()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `the provided path is ${getUserReadableFileType(stats)} and not a directory.`;
|
|
||||||
} catch (error) {
|
|
||||||
switch (isErrnoException(error) ? error.code : undefined) {
|
|
||||||
case "ENOENT":
|
|
||||||
return `the provided path does not exist.`;
|
|
||||||
case "EACCES":
|
|
||||||
return `search permissions is denied for one of the directories in the prefix of the provided path.`;
|
|
||||||
case "ELOOP":
|
|
||||||
return `the provided path is a sym-link which points to a chain of sym-links that is too long to resolve. Perhaps it is cyclic.`;
|
|
||||||
case "ENAMETOOLONG":
|
|
||||||
return `the pathname is too long to be used.`;
|
|
||||||
case "ENOTDIR":
|
|
||||||
return `a prefix of the provided path is not a directory.`;
|
|
||||||
default:
|
|
||||||
logger.warn(`[CLUSTER-LOCAL-TERMINAL-SETTINGS]: unexpected error in validateDirectory for resolved path=${dir}`, error);
|
|
||||||
|
|
||||||
return error ? lowerFirst(String(error)) : "of an unknown error, please try again.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ClusterLocalTerminalSetting = observer(({ cluster }: ClusterLocalTerminalSettingProps) => {
|
|
||||||
if (!cluster) {
|
if (!cluster) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -109,15 +55,15 @@ export const ClusterLocalTerminalSetting = observer(({ cluster }: ClusterLocalTe
|
|||||||
cluster.preferences.terminalCWD = undefined;
|
cluster.preferences.terminalCWD = undefined;
|
||||||
} else {
|
} else {
|
||||||
const dir = resolveTilde(directory);
|
const dir = resolveTilde(directory);
|
||||||
const errorMessage = await validateDirectory(dir);
|
const result = await validateDirectory(dir);
|
||||||
|
|
||||||
if (errorMessage) {
|
if (!result.callWasSuccessful) {
|
||||||
Notifications.error(
|
showErrorNotification(
|
||||||
<>
|
<>
|
||||||
<b>Terminal Working Directory</b>
|
<b>Terminal Working Directory</b>
|
||||||
<p>
|
<p>
|
||||||
{"Your changes were not saved because "}
|
{"Your changes were not saved because "}
|
||||||
{errorMessage}
|
{result.error}
|
||||||
</p>
|
</p>
|
||||||
</>,
|
</>,
|
||||||
);
|
);
|
||||||
@ -166,6 +112,8 @@ export const ClusterLocalTerminalSetting = observer(({ cluster }: ClusterLocalTe
|
|||||||
material="close"
|
material="close"
|
||||||
title="Clear"
|
title="Clear"
|
||||||
onClick={() => setAndCommitDirectory("")}
|
onClick={() => setAndCommitDirectory("")}
|
||||||
|
smallest
|
||||||
|
style={{ marginRight: "var(--margin)" }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -173,6 +121,7 @@ export const ClusterLocalTerminalSetting = observer(({ cluster }: ClusterLocalTe
|
|||||||
material="folder"
|
material="folder"
|
||||||
title="Pick from filesystem"
|
title="Pick from filesystem"
|
||||||
onClick={openFilePicker}
|
onClick={openFilePicker}
|
||||||
|
smallest
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -200,3 +149,16 @@ export const ClusterLocalTerminalSetting = observer(({ cluster }: ClusterLocalTe
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const ClusterLocalTerminalSetting = withInjectables<Dependencies, ClusterLocalTerminalSettingProps>(
|
||||||
|
NonInjectedClusterLocalTerminalSetting,
|
||||||
|
|
||||||
|
{
|
||||||
|
getProps: (di, props) => ({
|
||||||
|
showErrorNotification: di.inject(showErrorNotificationInjectable),
|
||||||
|
validateDirectory: di.inject(validateDirectoryInjectable),
|
||||||
|
...props,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,6 @@ exports[`kube-object-menu given kube object renders 1`] = `
|
|||||||
<i
|
<i
|
||||||
class="Icon material interactive focusable"
|
class="Icon material interactive focusable"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
tooltip="Delete"
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="icon"
|
class="icon"
|
||||||
@ -28,6 +27,9 @@ exports[`kube-object-menu given kube object renders 1`] = `
|
|||||||
delete
|
delete
|
||||||
</span>
|
</span>
|
||||||
</i>
|
</i>
|
||||||
|
<div>
|
||||||
|
Delete
|
||||||
|
</div>
|
||||||
<span
|
<span
|
||||||
class="title"
|
class="title"
|
||||||
>
|
>
|
||||||
@ -59,7 +61,6 @@ exports[`kube-object-menu given kube object when removing kube object renders 1`
|
|||||||
<i
|
<i
|
||||||
class="Icon material interactive focusable"
|
class="Icon material interactive focusable"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
tooltip="Delete"
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="icon"
|
class="icon"
|
||||||
@ -68,6 +69,9 @@ exports[`kube-object-menu given kube object when removing kube object renders 1`
|
|||||||
delete
|
delete
|
||||||
</span>
|
</span>
|
||||||
</i>
|
</i>
|
||||||
|
<div>
|
||||||
|
Delete
|
||||||
|
</div>
|
||||||
<span
|
<span
|
||||||
class="title"
|
class="title"
|
||||||
>
|
>
|
||||||
@ -148,7 +152,6 @@ exports[`kube-object-menu given kube object when rerendered with different kube
|
|||||||
<i
|
<i
|
||||||
class="Icon material interactive focusable"
|
class="Icon material interactive focusable"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
tooltip="Delete"
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="icon"
|
class="icon"
|
||||||
@ -157,6 +160,9 @@ exports[`kube-object-menu given kube object when rerendered with different kube
|
|||||||
delete
|
delete
|
||||||
</span>
|
</span>
|
||||||
</i>
|
</i>
|
||||||
|
<div>
|
||||||
|
Delete
|
||||||
|
</div>
|
||||||
<span
|
<span
|
||||||
class="title"
|
class="title"
|
||||||
>
|
>
|
||||||
@ -185,7 +191,6 @@ exports[`kube-object-menu given kube object when rerendered with different kube
|
|||||||
<i
|
<i
|
||||||
class="Icon material interactive focusable"
|
class="Icon material interactive focusable"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
tooltip="Delete"
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="icon"
|
class="icon"
|
||||||
@ -194,6 +199,9 @@ exports[`kube-object-menu given kube object when rerendered with different kube
|
|||||||
delete
|
delete
|
||||||
</span>
|
</span>
|
||||||
</i>
|
</i>
|
||||||
|
<div>
|
||||||
|
Delete
|
||||||
|
</div>
|
||||||
<span
|
<span
|
||||||
class="title"
|
class="title"
|
||||||
>
|
>
|
||||||
@ -277,7 +285,6 @@ exports[`kube-object-menu given kube object with namespace when removing kube ob
|
|||||||
<i
|
<i
|
||||||
class="Icon material interactive focusable"
|
class="Icon material interactive focusable"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
tooltip="Delete"
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="icon"
|
class="icon"
|
||||||
@ -286,6 +293,9 @@ exports[`kube-object-menu given kube object with namespace when removing kube ob
|
|||||||
delete
|
delete
|
||||||
</span>
|
</span>
|
||||||
</i>
|
</i>
|
||||||
|
<div>
|
||||||
|
Delete
|
||||||
|
</div>
|
||||||
<span
|
<span
|
||||||
class="title"
|
class="title"
|
||||||
>
|
>
|
||||||
@ -369,7 +379,6 @@ exports[`kube-object-menu given kube object without namespace when removing kube
|
|||||||
<i
|
<i
|
||||||
class="Icon material interactive focusable"
|
class="Icon material interactive focusable"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
tooltip="Delete"
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="icon"
|
class="icon"
|
||||||
@ -378,6 +387,9 @@ exports[`kube-object-menu given kube object without namespace when removing kube
|
|||||||
delete
|
delete
|
||||||
</span>
|
</span>
|
||||||
</i>
|
</i>
|
||||||
|
<div>
|
||||||
|
Delete
|
||||||
|
</div>
|
||||||
<span
|
<span
|
||||||
class="title"
|
class="title"
|
||||||
>
|
>
|
||||||
|
|||||||
@ -26,12 +26,6 @@ import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource
|
|||||||
import hideDetailsInjectable from "../kube-detail-params/hide-details.injectable";
|
import hideDetailsInjectable from "../kube-detail-params/hide-details.injectable";
|
||||||
import { kubeObjectMenuItemInjectionToken } from "./kube-object-menu-item-injection-token";
|
import { kubeObjectMenuItemInjectionToken } from "./kube-object-menu-item-injection-token";
|
||||||
|
|
||||||
// TODO: Make tooltips free of side effects by making it deterministic
|
|
||||||
jest.mock("../tooltip/tooltip");
|
|
||||||
jest.mock("../tooltip/withTooltip", () => ({
|
|
||||||
withTooltip: (target: any) => target,
|
|
||||||
}));
|
|
||||||
|
|
||||||
// TODO: make `animated={false}` not required to make tests deterministic
|
// TODO: make `animated={false}` not required to make tests deterministic
|
||||||
describe("kube-object-menu", () => {
|
describe("kube-object-menu", () => {
|
||||||
let di: DiContainer;
|
let di: DiContainer;
|
||||||
|
|||||||
@ -49,6 +49,7 @@ html {
|
|||||||
|
|
||||||
&__single-value {
|
&__single-value {
|
||||||
color: var(--textColorSecondary);
|
color: var(--textColorSecondary);
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__indicator {
|
&__indicator {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Cluster } from "../../common/cluster/cluster";
|
|||||||
import directoryForKubeConfigsInjectable from "../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
|
import directoryForKubeConfigsInjectable from "../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
|
||||||
import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token";
|
import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token";
|
||||||
import loggerInjectable from "../../common/logger.injectable";
|
import loggerInjectable from "../../common/logger.injectable";
|
||||||
|
import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable";
|
||||||
|
|
||||||
const createClusterInjectable = getInjectable({
|
const createClusterInjectable = getInjectable({
|
||||||
id: "create-cluster",
|
id: "create-cluster",
|
||||||
@ -16,6 +17,7 @@ const createClusterInjectable = getInjectable({
|
|||||||
const dependencies: ClusterDependencies = {
|
const dependencies: ClusterDependencies = {
|
||||||
directoryForKubeConfigs: di.inject(directoryForKubeConfigsInjectable),
|
directoryForKubeConfigs: di.inject(directoryForKubeConfigsInjectable),
|
||||||
logger: di.inject(loggerInjectable),
|
logger: di.inject(loggerInjectable),
|
||||||
|
broadcastMessage: di.inject(broadcastMessageInjectable),
|
||||||
|
|
||||||
// TODO: Dismantle wrong abstraction
|
// TODO: Dismantle wrong abstraction
|
||||||
// Note: "as never" to get around strictness in unnatural scenario
|
// Note: "as never" to get around strictness in unnatural scenario
|
||||||
|
|||||||
@ -32,8 +32,6 @@ import { ApiManager } from "../common/k8s-api/api-manager";
|
|||||||
import lensResourcesDirInjectable from "../common/vars/lens-resources-dir.injectable";
|
import lensResourcesDirInjectable from "../common/vars/lens-resources-dir.injectable";
|
||||||
import broadcastMessageInjectable from "../common/ipc/broadcast-message.injectable";
|
import broadcastMessageInjectable from "../common/ipc/broadcast-message.injectable";
|
||||||
import apiManagerInjectable from "../common/k8s-api/api-manager/manager.injectable";
|
import apiManagerInjectable from "../common/k8s-api/api-manager/manager.injectable";
|
||||||
import ipcRendererInjectable from "./utils/channel/ipc-renderer.injectable";
|
|
||||||
import type { IpcRenderer } from "electron";
|
|
||||||
import setupOnApiErrorListenersInjectable from "./api/setup-on-api-errors.injectable";
|
import setupOnApiErrorListenersInjectable from "./api/setup-on-api-errors.injectable";
|
||||||
import { observable, computed } from "mobx";
|
import { observable, computed } from "mobx";
|
||||||
import defaultShellInjectable from "./components/+preferences/default-shell.injectable";
|
import defaultShellInjectable from "./components/+preferences/default-shell.injectable";
|
||||||
@ -164,11 +162,6 @@ export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {})
|
|||||||
di.override(maximizeWindowInjectable, () => () => {});
|
di.override(maximizeWindowInjectable, () => () => {});
|
||||||
di.override(toggleMaximizeWindowInjectable, () => () => {});
|
di.override(toggleMaximizeWindowInjectable, () => () => {});
|
||||||
|
|
||||||
di.override(ipcRendererInjectable, () => ({
|
|
||||||
invoke: () => {},
|
|
||||||
on: () => {},
|
|
||||||
}) as unknown as IpcRenderer);
|
|
||||||
|
|
||||||
overrideFunctionalInjectables(di, [
|
overrideFunctionalInjectables(di, [
|
||||||
broadcastMessageInjectable,
|
broadcastMessageInjectable,
|
||||||
getFilePathsInjectable,
|
getFilePathsInjectable,
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { OpenDialogOptions } from "electron";
|
import type { OpenDialogOptions } from "electron";
|
||||||
import { ipcRenderer } from "electron";
|
|
||||||
import { clusterActivateHandler, clusterClearDeletingHandler, clusterDeleteHandler, clusterDisconnectHandler, clusterKubectlApplyAllHandler, clusterKubectlDeleteAllHandler, clusterSetDeletingHandler, clusterSetFrameIdHandler, clusterStates } from "../../common/ipc/cluster";
|
import { clusterActivateHandler, clusterClearDeletingHandler, clusterDeleteHandler, clusterDisconnectHandler, clusterKubectlApplyAllHandler, clusterKubectlDeleteAllHandler, clusterSetDeletingHandler, clusterSetFrameIdHandler, clusterStates } from "../../common/ipc/cluster";
|
||||||
import type { ClusterId, ClusterState } from "../../common/cluster-types";
|
import type { ClusterId, ClusterState } from "../../common/cluster-types";
|
||||||
import { windowActionHandleChannel, windowLocationChangedChannel, windowOpenAppMenuAsContextMenuChannel, type WindowAction } from "../../common/ipc/window";
|
import { windowActionHandleChannel, windowLocationChangedChannel, windowOpenAppMenuAsContextMenuChannel, type WindowAction } from "../../common/ipc/window";
|
||||||
@ -14,12 +13,22 @@ import type { InstalledExtension } from "../../extensions/extension-discovery/ex
|
|||||||
import type { LensExtensionId } from "../../extensions/lens-extension";
|
import type { LensExtensionId } from "../../extensions/lens-extension";
|
||||||
import { toJS } from "../utils";
|
import { toJS } from "../utils";
|
||||||
import type { Location } from "history";
|
import type { Location } from "history";
|
||||||
|
import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||||
|
import ipcRendererInjectable from "../utils/channel/ipc-renderer.injectable";
|
||||||
|
|
||||||
function requestMain(channel: string, ...args: any[]) {
|
function requestMain(channel: string, ...args: any[]) {
|
||||||
|
const di = getLegacyGlobalDiForExtensionApi();
|
||||||
|
|
||||||
|
const ipcRenderer = di.inject(ipcRendererInjectable);
|
||||||
|
|
||||||
return ipcRenderer.invoke(channel, ...args.map(toJS));
|
return ipcRenderer.invoke(channel, ...args.map(toJS));
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitToMain(channel: string, ...args: any[]) {
|
function emitToMain(channel: string, ...args: any[]) {
|
||||||
|
const di = getLegacyGlobalDiForExtensionApi();
|
||||||
|
|
||||||
|
const ipcRenderer = di.inject(ipcRendererInjectable);
|
||||||
|
|
||||||
return ipcRenderer.send(channel, ...args.map(toJS));
|
return ipcRenderer.send(channel, ...args.map(toJS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,10 +9,7 @@ import { once } from "lodash";
|
|||||||
import type { ClusterFrameContext } from "../cluster-frame-context/cluster-frame-context";
|
import type { ClusterFrameContext } from "../cluster-frame-context/cluster-frame-context";
|
||||||
import logger from "../../common/logger";
|
import logger from "../../common/logger";
|
||||||
import type { KubeObjectStoreLoadAllParams, KubeObjectStoreSubscribeParams } from "../../common/k8s-api/kube-object.store";
|
import type { KubeObjectStoreLoadAllParams, KubeObjectStoreSubscribeParams } from "../../common/k8s-api/kube-object.store";
|
||||||
import type { RequestInit } from "node-fetch";
|
import AbortController from "abort-controller";
|
||||||
|
|
||||||
// TODO: upgrade node-fetch once we are starting to use ES modules
|
|
||||||
type LegacyAbortSignal = NonNullable<RequestInit["signal"]>;
|
|
||||||
|
|
||||||
// Kubernetes watch-api client
|
// Kubernetes watch-api client
|
||||||
// API: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams
|
// API: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams
|
||||||
@ -106,7 +103,7 @@ export class KubeWatchApi {
|
|||||||
|
|
||||||
const loadThenSubscribe = async (namespaces: string[] | undefined) => {
|
const loadThenSubscribe = async (namespaces: string[] | undefined) => {
|
||||||
try {
|
try {
|
||||||
await store.loadAll({ namespaces, reqInit: { signal: childController.signal as LegacyAbortSignal }, onLoadFailure });
|
await store.loadAll({ namespaces, reqInit: { signal: childController.signal }, onLoadFailure });
|
||||||
unsubscribe.push(store.subscribe({ onLoadFailure, abortController: childController }));
|
unsubscribe.push(store.subscribe({ onLoadFailure, abortController: childController }));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!(error instanceof DOMException)) {
|
if (!(error instanceof DOMException)) {
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import extensionLoaderInjectable from "../../../extensions/extension-loader/extension-loader.injectable";
|
import extensionLoaderInjectable from "../../../extensions/extension-loader/extension-loader.injectable";
|
||||||
import { LensProtocolRouterRenderer } from "./lens-protocol-router-renderer";
|
import { LensProtocolRouterRenderer } from "./lens-protocol-router-renderer";
|
||||||
import extensionsStoreInjectable
|
import extensionsStoreInjectable from "../../../extensions/extensions-store/extensions-store.injectable";
|
||||||
from "../../../extensions/extensions-store/extensions-store.injectable";
|
import loggerInjectable from "../../../common/logger.injectable";
|
||||||
|
|
||||||
const lensProtocolRouterRendererInjectable = getInjectable({
|
const lensProtocolRouterRendererInjectable = getInjectable({
|
||||||
id: "lens-protocol-router-renderer",
|
id: "lens-protocol-router-renderer",
|
||||||
@ -15,6 +15,7 @@ const lensProtocolRouterRendererInjectable = getInjectable({
|
|||||||
new LensProtocolRouterRenderer({
|
new LensProtocolRouterRenderer({
|
||||||
extensionLoader: di.inject(extensionLoaderInjectable),
|
extensionLoader: di.inject(extensionLoaderInjectable),
|
||||||
extensionsStore: di.inject(extensionsStoreInjectable),
|
extensionsStore: di.inject(extensionsStoreInjectable),
|
||||||
|
logger: di.inject(loggerInjectable),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -8,10 +8,9 @@ import { ipcRenderer } from "electron";
|
|||||||
import * as proto from "../../../common/protocol-handler";
|
import * as proto from "../../../common/protocol-handler";
|
||||||
import Url from "url-parse";
|
import Url from "url-parse";
|
||||||
import { onCorrect } from "../../../common/ipc";
|
import { onCorrect } from "../../../common/ipc";
|
||||||
|
import type { LensProtocolRouterDependencies } from "../../../common/protocol-handler";
|
||||||
import { foldAttemptResults, ProtocolHandlerInvalid, RouteAttempt } from "../../../common/protocol-handler";
|
import { foldAttemptResults, ProtocolHandlerInvalid, RouteAttempt } from "../../../common/protocol-handler";
|
||||||
import { Notifications } from "../../components/notifications";
|
import { Notifications } from "../../components/notifications";
|
||||||
import type { ExtensionLoader } from "../../../extensions/extension-loader";
|
|
||||||
import type { ExtensionsStore } from "../../../extensions/extensions-store/extensions-store";
|
|
||||||
|
|
||||||
function verifyIpcArgs(args: unknown[]): args is [string, RouteAttempt] {
|
function verifyIpcArgs(args: unknown[]): args is [string, RouteAttempt] {
|
||||||
if (args.length !== 2) {
|
if (args.length !== 2) {
|
||||||
@ -32,11 +31,7 @@ function verifyIpcArgs(args: unknown[]): args is [string, RouteAttempt] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies extends LensProtocolRouterDependencies {}
|
||||||
extensionLoader: ExtensionLoader;
|
|
||||||
extensionsStore: ExtensionsStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export class LensProtocolRouterRenderer extends proto.LensProtocolRouter {
|
export class LensProtocolRouterRenderer extends proto.LensProtocolRouter {
|
||||||
constructor(protected dependencies: Dependencies) {
|
constructor(protected dependencies: Dependencies) {
|
||||||
|
|||||||
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import type { IpcRenderer } from "electron";
|
||||||
|
import ipcRendererInjectable from "./ipc-renderer.injectable";
|
||||||
|
import { getGlobalOverride } from "../../../common/test-utils/get-global-override";
|
||||||
|
|
||||||
|
export default getGlobalOverride(ipcRendererInjectable, () => ({
|
||||||
|
invoke: () => {},
|
||||||
|
on: () => {},
|
||||||
|
}) as unknown as IpcRenderer);
|
||||||
449
yarn.lock
449
yarn.lock
@ -7,6 +7,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.1.1.tgz#9274ec7460652f9c632c59addf24efb1684ef876"
|
resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.1.1.tgz#9274ec7460652f9c632c59addf24efb1684ef876"
|
||||||
integrity sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==
|
integrity sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==
|
||||||
|
|
||||||
|
"@adobe/css-tools@^4.0.1":
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.0.1.tgz#b38b444ad3aa5fedbb15f2f746dcd934226a12dd"
|
||||||
|
integrity sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==
|
||||||
|
|
||||||
"@ampproject/remapping@^2.1.0":
|
"@ampproject/remapping@^2.1.0":
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d"
|
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d"
|
||||||
@ -598,6 +603,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.53.tgz#251b4cd6760fadb4d68a05815e6dc5e432d69cd6"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.53.tgz#251b4cd6760fadb4d68a05815e6dc5e432d69cd6"
|
||||||
integrity sha512-W2dAL6Bnyn4xa/QRSU3ilIK4EzD5wgYXKXJiS1HDF5vU3675qc2bvFyLwbUcdmssDveyndy7FbitrCoiV/eMLg==
|
integrity sha512-W2dAL6Bnyn4xa/QRSU3ilIK4EzD5wgYXKXJiS1HDF5vU3675qc2bvFyLwbUcdmssDveyndy7FbitrCoiV/eMLg==
|
||||||
|
|
||||||
|
"@esbuild/linux-loong64@0.15.5":
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.5.tgz#91aef76d332cdc7c8942b600fa2307f3387e6f82"
|
||||||
|
integrity sha512-UHkDFCfSGTuXq08oQltXxSZmH1TXyWsL+4QhZDWvvLl6mEJQqk3u7/wq1LjhrrAXYIllaTtRSzUXl4Olkf2J8A==
|
||||||
|
|
||||||
"@eslint/eslintrc@^1.3.0":
|
"@eslint/eslintrc@^1.3.0":
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
|
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
|
||||||
@ -1442,101 +1452,101 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@sinonjs/commons" "^1.7.0"
|
"@sinonjs/commons" "^1.7.0"
|
||||||
|
|
||||||
"@swc/core-android-arm-eabi@1.2.223":
|
"@swc/core-android-arm-eabi@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.2.223.tgz#5d5ae572c90eb2e19f46c1ef56aab2e3fa7101fe"
|
resolved "https://registry.yarnpkg.com/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.2.242.tgz#3ae5d8b178a0835ae0878094175d943f2d894bec"
|
||||||
integrity sha512-Hy/ya4oy80Ay70H9vhA8W0/FU9aQ/oQjvZ/on+wcNMATAiU9tk47i73LtPM01GruNiYJOwFcf2XWjlTpq5a0BQ==
|
integrity sha512-Ukx1LQAUbPRJdREF9FMgeUwIuRtWJNpPyPF7BWl4hIkw024q75mohMbp3S2wgrF1TsSsEGW37q0DkFxPJ2uJbQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@swc/wasm" "1.2.122"
|
"@swc/wasm" "1.2.122"
|
||||||
|
|
||||||
"@swc/core-android-arm64@1.2.223":
|
"@swc/core-android-arm64@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.2.223.tgz#13c1751f9af36525adbb420098a4c74765afa7c4"
|
resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.2.242.tgz#2c1885c08dd5720991a6fa7585d39a93df98e773"
|
||||||
integrity sha512-qujrIXDBMWcPcdtTG/r+RNVBU5rg2Sk9Vg+U4FybX3c34rIyX2QYu5sxwM/HIGfd6wCbt5lyFZOvgSY000MTNw==
|
integrity sha512-4E/y+reQWHVCV/0Sn174gsLQyqIKlBWKnwUfPa7MA53VBacp8HTYoPY+iwKPrngsH16gEOC7iByiTJHR/4kirg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@swc/wasm" "1.2.130"
|
"@swc/wasm" "1.2.130"
|
||||||
|
|
||||||
"@swc/core-darwin-arm64@1.2.223":
|
"@swc/core-darwin-arm64@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.223.tgz#44ee2d1fbf9350c6aeda1983a384514272a9b2b7"
|
resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.242.tgz#1b8b16a132cc354ea3b31d26c46908dae2fe41ed"
|
||||||
integrity sha512-CX32sRhAnFj3fJI6V4vdu5IUV5frEZNZM6hIPUs1UuVpxyuto9IZwd2y7/ACItB5RipA3VDL/c7jrFdSmfrgzg==
|
integrity sha512-nIqtjxdbz0Fe0gFZwCygBwUrGEXj3c4mjHjNeveidVX/6U0HE/EAj+0iXuw8zjJLof8HCMnxq8CzzvhA6gd3ZA==
|
||||||
|
|
||||||
"@swc/core-darwin-x64@1.2.223":
|
"@swc/core-darwin-x64@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.2.223.tgz#a157820e158d22c9b443821d15258bc58978e154"
|
resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.2.242.tgz#cde041d520fcfb0865f49b395bb2c76af8ec3f3a"
|
||||||
integrity sha512-5FVQgWtqMmpOtky0JLTIF4a1WiAkuDOe5mwgzpi8nZ7nCxNo/DNThBbnIDlNhrR4M/1M6wzPshn1wNivvD7MQw==
|
integrity sha512-iZKzI76vYYHD/t8wkQ/uIVuIyxN1eift2nLvUU7/jtmoa6b8DH/45ykB/C3vkuvYVNMiGA8HIjJIzw7RJz5XIQ==
|
||||||
|
|
||||||
"@swc/core-freebsd-x64@1.2.223":
|
"@swc/core-freebsd-x64@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.223.tgz#ec9b300860f378aeb183084d89ba65009910d9f9"
|
resolved "https://registry.yarnpkg.com/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.242.tgz#a95827311424dd86190fdb73bec996d24188c6d3"
|
||||||
integrity sha512-5oumS+YZyOMMKc5D3Bvf/541SF8n4b8LQ5x4WFA2CdAzD/jCgphE0IoAZ0u3bHz9S6Tl6Emu11V+/ALHE1oUew==
|
integrity sha512-6JNi5/6JDvcTQzBkndELiIlJufWowoI2ZEmXlGIJpiGoj28PEDPwy5LO7KkXa4DnY5L4CSh15idFO/DxV0rGAQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@swc/wasm" "1.2.130"
|
"@swc/wasm" "1.2.130"
|
||||||
|
|
||||||
"@swc/core-linux-arm-gnueabihf@1.2.223":
|
"@swc/core-linux-arm-gnueabihf@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.223.tgz#3403de3c9402e1eeca68b1c134ea574739c7c49c"
|
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.242.tgz#1b0bd0ba96c59a9c4b87668521ce8ba55c8c7f55"
|
||||||
integrity sha512-osYjVijq101xZjwPUKR6AUib1LZU9laaM3aEOyElAi8cHolsZEp8D9ynr7cSWFUZJuzpTlY7iuJeY3FszdWrJA==
|
integrity sha512-NGL9A3cv8PCbeQ1SvPfApNlHvFbf7Jn305sCAy3iZYsmwm+EU4JNlOWXGgRioP7ABhz2kwLhfYs8UMYCDIVq8Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@swc/wasm" "1.2.130"
|
"@swc/wasm" "1.2.130"
|
||||||
|
|
||||||
"@swc/core-linux-arm64-gnu@1.2.223":
|
"@swc/core-linux-arm64-gnu@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.223.tgz#d0a2d5dd01c5744950e57ec59aa4696bbabf02e4"
|
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.242.tgz#f97c1b655779788fff9a035f6a80180b1545423b"
|
||||||
integrity sha512-JZdPZIZzkJ6R+XB0lCnL0eD9VK/JfpZgKBqR3Gur9Fxs8Ea9p1HhZHSEAJ2T2YwV629dYjXwKqraOkLQrEMzCg==
|
integrity sha512-OJ0kAjgeoRDJlo6Rvd2GnJ92tiIndmC/8krD9gfnQEyAgpR+jajOxbKhyBN/QZPyD2q/TG2LPqxhGYZ79q5mWQ==
|
||||||
|
|
||||||
"@swc/core-linux-arm64-musl@1.2.223":
|
"@swc/core-linux-arm64-musl@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.223.tgz#667bd6583f93909736600acdd9d5cc4c6141d577"
|
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.242.tgz#ad77a5c7fc79d42d64970ca1886eb9d626388ca2"
|
||||||
integrity sha512-9BVDH5Cq+VlAuJrshCgxWgziLEGzShZ2OVZ7SEA/+md1y69x2VdMR9lMSfD/EXqb6AJAaFODRe20Irtppeqr2Q==
|
integrity sha512-VqnHSYb1a6xW5ARUx9kq88s1S3XvCw9TvQXsPcN4e5qsugrLzxWLnqIM6VnWW06prxN7pYlWo9QtrtdPfbppmA==
|
||||||
|
|
||||||
"@swc/core-linux-x64-gnu@1.2.223":
|
"@swc/core-linux-x64-gnu@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.223.tgz#c29788110fe1aa7fb86332178dcd1606368fd2c2"
|
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.242.tgz#4c7f2c483876a4b0755a263133c25413fa69df88"
|
||||||
integrity sha512-Z+KAxSpUDNEPfjOKX/tZk67StvzIyAhTc5FPWoVhx5CBlkGQaDBRl1TNmb1wdne/WF9xVkx6wz22pvNevX5fig==
|
integrity sha512-DDqVJh0KpgHb+E0563+6PqAYDzYTSwgZXF/fOULwlHC7Yt50a9+ecisTFSHkWc74zPMtq27kMTuZyyLeD3gu7A==
|
||||||
|
|
||||||
"@swc/core-linux-x64-musl@1.2.223":
|
"@swc/core-linux-x64-musl@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.223.tgz#24b7001530d4e09d7bae58c704ac79a6593bb9c1"
|
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.242.tgz#48f8769094cfde9d78dc32936666575470583b2a"
|
||||||
integrity sha512-3EkAOA0KQdm7Rw/0L5odtDKAtmzhgF7FKTL+zZb+s0ju5oMwFGN+XIIwUQdPSf11Ej3ezjHjHTFTlv0xqutfuA==
|
integrity sha512-P+9sWgd5eZ6kS1WxOJbCeSgWY7mLP742PhwAzpFrJqCq5nx8Q4FYo4L5mOVNAheYDWldsxR1nKXR1RIMK3S2Lw==
|
||||||
|
|
||||||
"@swc/core-win32-arm64-msvc@1.2.223":
|
"@swc/core-win32-arm64-msvc@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.223.tgz#8902c20d3d7ed2c9741ff0e227581d26ce8e0497"
|
resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.242.tgz#e421a5a7a49d1effa71a22fea22a65256b447108"
|
||||||
integrity sha512-n8LWkej30hvfvazrJgwS6kwBZXMFCevLiRsZmP8O4hpC9b1wfAa+KLm4nHOR+J8jwF7LEjiERdU6tbIWZz0Tnw==
|
integrity sha512-W5cevrf5aDJzdE++XeQi1BJKuigC3dlG2NaBUyt3inmep7nli6eoBJdj9Vyg5EPfFOdeI6wQiwOpFvQRoAle8Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@swc/wasm" "1.2.130"
|
"@swc/wasm" "1.2.130"
|
||||||
|
|
||||||
"@swc/core-win32-ia32-msvc@1.2.223":
|
"@swc/core-win32-ia32-msvc@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.223.tgz#591405f9fa07915e9d0b94a4174a5745621fe580"
|
resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.242.tgz#1b836f5872195fef506a094eae7734b5fd28a1b5"
|
||||||
integrity sha512-kEDGFFUC6xPqCom03QtR+76Ptwtf8RABI4FqRdvrvbasw9zj0xkuLSDCvqL72zdOZCWRciiFijQVHfndLByMAQ==
|
integrity sha512-XRQcgChvY9333hBre9F53EbiVfVu5MkSH4+XIiNMK14Jg8EqQ1nOcd+jvv2sEdEVbufCmBbWNjofUrCoQey60w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@swc/wasm" "1.2.130"
|
"@swc/wasm" "1.2.130"
|
||||||
|
|
||||||
"@swc/core-win32-x64-msvc@1.2.223":
|
"@swc/core-win32-x64-msvc@1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.223.tgz#7a4549cedb7c0e7a3d4861c2b5230224194e0f04"
|
resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.242.tgz#61a6c7d4da1dec1188b912785bd8e0bb16ff8440"
|
||||||
integrity sha512-nzL8rwzMFA9cBK2s+QBMPcNnoGSPMfgY9ypRw/nTp0hQDgdLOXHy9moGFJg8dbdQD39kC5s8yQ0BmyKvePILgg==
|
integrity sha512-Cz1hZOxcfEVgzEr2sYIW9MxT+wEEbYz7aB87ZDmTUpr7vuvBiLMwsYItm8qG847wZeJfa+J7CC+tty5GJOBOOQ==
|
||||||
|
|
||||||
"@swc/core@^1.2.223":
|
"@swc/core@^1.2.242":
|
||||||
version "1.2.223"
|
version "1.2.242"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.2.223.tgz#e44a3f6971a1f5c22d1037cf60510ef32c93d2a5"
|
resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.2.242.tgz#4392ef0012fe9667440c6eb5a419b6cc86a0a786"
|
||||||
integrity sha512-LcKX1frJ1iJDSYlY9Bg0vm0rYsXloITh6PdEYM5amT73J9mC1c2YpWLnWQiH2QpcyblyMhX1pk1eZ2JZjaynrQ==
|
integrity sha512-JQqSYVoLtHtztCNBgeCKyxmqw6AksHsC4WvVSSErLXJx6JXKaog1HFVuzd6rwx2lLCV+zBnbqJFug5OX0g2knw==
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@swc/core-android-arm-eabi" "1.2.223"
|
"@swc/core-android-arm-eabi" "1.2.242"
|
||||||
"@swc/core-android-arm64" "1.2.223"
|
"@swc/core-android-arm64" "1.2.242"
|
||||||
"@swc/core-darwin-arm64" "1.2.223"
|
"@swc/core-darwin-arm64" "1.2.242"
|
||||||
"@swc/core-darwin-x64" "1.2.223"
|
"@swc/core-darwin-x64" "1.2.242"
|
||||||
"@swc/core-freebsd-x64" "1.2.223"
|
"@swc/core-freebsd-x64" "1.2.242"
|
||||||
"@swc/core-linux-arm-gnueabihf" "1.2.223"
|
"@swc/core-linux-arm-gnueabihf" "1.2.242"
|
||||||
"@swc/core-linux-arm64-gnu" "1.2.223"
|
"@swc/core-linux-arm64-gnu" "1.2.242"
|
||||||
"@swc/core-linux-arm64-musl" "1.2.223"
|
"@swc/core-linux-arm64-musl" "1.2.242"
|
||||||
"@swc/core-linux-x64-gnu" "1.2.223"
|
"@swc/core-linux-x64-gnu" "1.2.242"
|
||||||
"@swc/core-linux-x64-musl" "1.2.223"
|
"@swc/core-linux-x64-musl" "1.2.242"
|
||||||
"@swc/core-win32-arm64-msvc" "1.2.223"
|
"@swc/core-win32-arm64-msvc" "1.2.242"
|
||||||
"@swc/core-win32-ia32-msvc" "1.2.223"
|
"@swc/core-win32-ia32-msvc" "1.2.242"
|
||||||
"@swc/core-win32-x64-msvc" "1.2.223"
|
"@swc/core-win32-x64-msvc" "1.2.242"
|
||||||
|
|
||||||
"@swc/jest@^0.2.22":
|
"@swc/jest@^0.2.22":
|
||||||
version "0.2.22"
|
version "0.2.22"
|
||||||
@ -1621,16 +1631,16 @@
|
|||||||
lz-string "^1.4.4"
|
lz-string "^1.4.4"
|
||||||
pretty-format "^26.6.2"
|
pretty-format "^26.6.2"
|
||||||
|
|
||||||
"@testing-library/jest-dom@^5.16.4":
|
"@testing-library/jest-dom@^5.16.5":
|
||||||
version "5.16.4"
|
version "5.16.5"
|
||||||
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.4.tgz#938302d7b8b483963a3ae821f1c0808f872245cd"
|
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz#3912846af19a29b2dbf32a6ae9c31ef52580074e"
|
||||||
integrity sha512-Gy+IoFutbMQcky0k+bqqumXZ1cTGswLsFqmNLzNdSKkU9KGV2u9oXhukCbbJ9/LRPKiqwxEE8VpV/+YZlfkPUA==
|
integrity sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@adobe/css-tools" "^4.0.1"
|
||||||
"@babel/runtime" "^7.9.2"
|
"@babel/runtime" "^7.9.2"
|
||||||
"@types/testing-library__jest-dom" "^5.9.1"
|
"@types/testing-library__jest-dom" "^5.9.1"
|
||||||
aria-query "^5.0.0"
|
aria-query "^5.0.0"
|
||||||
chalk "^3.0.0"
|
chalk "^3.0.0"
|
||||||
css "^3.0.0"
|
|
||||||
css.escape "^1.5.1"
|
css.escape "^1.5.1"
|
||||||
dom-accessibility-api "^0.5.6"
|
dom-accessibility-api "^0.5.6"
|
||||||
lodash "^4.17.15"
|
lodash "^4.17.15"
|
||||||
@ -2063,10 +2073,10 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/lodash@^4.14.181":
|
"@types/lodash@^4.14.184":
|
||||||
version "4.14.182"
|
version "4.14.184"
|
||||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2"
|
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.184.tgz#23f96cd2a21a28e106dc24d825d4aa966de7a9fe"
|
||||||
integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==
|
integrity sha512-RoZphVtHbxPZizt4IcILciSWiC6dcn+eZ8oX9IWEYfDMcocdd42f7NPI6fQj+6zI8y4E0L7gu2pcZKLGTRaV9Q==
|
||||||
|
|
||||||
"@types/marked@^4.0.3":
|
"@types/marked@^4.0.3":
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
@ -2139,15 +2149,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b"
|
||||||
integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==
|
integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==
|
||||||
|
|
||||||
"@types/node@^16.11.26":
|
"@types/node@^16.11.26", "@types/node@^16.11.55":
|
||||||
version "16.11.34"
|
version "16.11.55"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.34.tgz#520224e4be4448c279ecad09639ab460cc441a50"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.55.tgz#4b1e4fa4238b083cf0d0b4ad9077629123950caa"
|
||||||
integrity sha512-UrWGDyLAlQ2Z8bNOGWTsqbP9ZcBeTYBVuTRNxXTztBy5KhWUFI3BaeDWoCP/CzV/EVGgO1NTYzv9ZytBI9GAEw==
|
integrity sha512-ZZepNkqPNCBy6PlCjeOY0gI1q91v7l5MUhVc5RMAUV39OxRO8lF8fqGnhY2j8FWz8fxcN8HvAUWoccWpOzl/Ug==
|
||||||
|
|
||||||
"@types/node@^16.11.47":
|
|
||||||
version "16.11.47"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.47.tgz#efa9e3e0f72e7aa6a138055dace7437a83d9f91c"
|
|
||||||
integrity sha512-fpP+jk2zJ4VW66+wAMFoBJlx1bxmBKx4DUFf68UHgdGCOuyUTDlLWqsaNPJh7xhNDykyJ9eIzAygilP/4WoN8g==
|
|
||||||
|
|
||||||
"@types/npm@^2.0.32":
|
"@types/npm@^2.0.32":
|
||||||
version "2.0.32"
|
version "2.0.32"
|
||||||
@ -2492,10 +2497,10 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
webpack-dev-server "*"
|
webpack-dev-server "*"
|
||||||
|
|
||||||
"@types/webpack-env@^1.17.0":
|
"@types/webpack-env@^1.18.0":
|
||||||
version "1.17.0"
|
version "1.18.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.17.0.tgz#f99ce359f1bfd87da90cc4a57cab0a18f34a48d0"
|
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.18.0.tgz#ed6ecaa8e5ed5dfe8b2b3d00181702c9925f13fb"
|
||||||
integrity sha512-eHSaNYEyxRA5IAG0Ym/yCyf86niZUIF/TpWKofQI/CVfh5HsMEUyfE2kwFxha4ow0s5g0LfISQxpDKjbRDrizw==
|
integrity sha512-56/MAlX5WMsPVbOg7tAxnYvNYMMWr/QJiIp6BxVSW3JJXUVzzOn64qW8TzQyMSqSUFM2+PVI4aUHcHOzIz/1tg==
|
||||||
|
|
||||||
"@types/webpack-node-externals@^2.5.3":
|
"@types/webpack-node-externals@^2.5.3":
|
||||||
version "2.5.3"
|
version "2.5.3"
|
||||||
@ -2575,14 +2580,14 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/yargs-parser" "*"
|
"@types/yargs-parser" "*"
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin@^5.32.0":
|
"@typescript-eslint/eslint-plugin@^5.34.0":
|
||||||
version "5.32.0"
|
version "5.34.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.32.0.tgz#e27e38cffa4a61226327c874a7be965e9a861624"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.34.0.tgz#d690f60e335596f38b01792e8f4b361d9bd0cb35"
|
||||||
integrity sha512-CHLuz5Uz7bHP2WgVlvoZGhf0BvFakBJKAD/43Ty0emn4wXWv5k01ND0C0fHcl/Im8Td2y/7h44E9pca9qAu2ew==
|
integrity sha512-eRfPPcasO39iwjlUAMtjeueRGuIrW3TQ9WseIDl7i5UWuFbf83yYaU7YPs4j8+4CxUMIsj1k+4kV+E+G+6ypDQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/scope-manager" "5.32.0"
|
"@typescript-eslint/scope-manager" "5.34.0"
|
||||||
"@typescript-eslint/type-utils" "5.32.0"
|
"@typescript-eslint/type-utils" "5.34.0"
|
||||||
"@typescript-eslint/utils" "5.32.0"
|
"@typescript-eslint/utils" "5.34.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
functional-red-black-tree "^1.0.1"
|
functional-red-black-tree "^1.0.1"
|
||||||
ignore "^5.2.0"
|
ignore "^5.2.0"
|
||||||
@ -2608,20 +2613,20 @@
|
|||||||
"@typescript-eslint/types" "5.31.0"
|
"@typescript-eslint/types" "5.31.0"
|
||||||
"@typescript-eslint/visitor-keys" "5.31.0"
|
"@typescript-eslint/visitor-keys" "5.31.0"
|
||||||
|
|
||||||
"@typescript-eslint/scope-manager@5.32.0":
|
"@typescript-eslint/scope-manager@5.34.0":
|
||||||
version "5.32.0"
|
version "5.34.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.32.0.tgz#763386e963a8def470580cc36cf9228864190b95"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.34.0.tgz#14efd13dc57602937e25f188fd911f118781e527"
|
||||||
integrity sha512-KyAE+tUON0D7tNz92p1uetRqVJiiAkeluvwvZOqBmW9z2XApmk5WSMV9FrzOroAcVxJZB3GfUwVKr98Dr/OjOg==
|
integrity sha512-HNvASMQlah5RsBW6L6c7IJ0vsm+8Sope/wu5sEAf7joJYWNb1LDbJipzmdhdUOnfrDFE6LR1j57x1EYVxrY4ow==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "5.32.0"
|
"@typescript-eslint/types" "5.34.0"
|
||||||
"@typescript-eslint/visitor-keys" "5.32.0"
|
"@typescript-eslint/visitor-keys" "5.34.0"
|
||||||
|
|
||||||
"@typescript-eslint/type-utils@5.32.0":
|
"@typescript-eslint/type-utils@5.34.0":
|
||||||
version "5.32.0"
|
version "5.34.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.32.0.tgz#45a14506fe3fb908600b4cef2f70778f7b5cdc79"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.34.0.tgz#7a324ab9ddd102cd5e1beefc94eea6f3eb32d32d"
|
||||||
integrity sha512-0gSsIhFDduBz3QcHJIp3qRCvVYbqzHg8D6bHFsDMrm0rURYDj+skBK2zmYebdCp+4nrd9VWd13egvhYFJj/wZg==
|
integrity sha512-Pxlno9bjsQ7hs1pdWRUv9aJijGYPYsHpwMeCQ/Inavhym3/XaKt1ZKAA8FIw4odTBfowBdZJDMxf2aavyMDkLg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/utils" "5.32.0"
|
"@typescript-eslint/utils" "5.34.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
tsutils "^3.21.0"
|
tsutils "^3.21.0"
|
||||||
|
|
||||||
@ -2630,10 +2635,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.31.0.tgz#7aa389122b64b18e473c1672fb3b8310e5f07a9a"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.31.0.tgz#7aa389122b64b18e473c1672fb3b8310e5f07a9a"
|
||||||
integrity sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==
|
integrity sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==
|
||||||
|
|
||||||
"@typescript-eslint/types@5.32.0":
|
"@typescript-eslint/types@5.34.0":
|
||||||
version "5.32.0"
|
version "5.34.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.32.0.tgz#484273021eeeae87ddb288f39586ef5efeb6dcd8"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.34.0.tgz#217bf08049e9e7b86694d982e88a2c1566330c78"
|
||||||
integrity sha512-EBUKs68DOcT/EjGfzywp+f8wG9Zw6gj6BjWu7KV/IYllqKJFPlZlLSYw/PTvVyiRw50t6wVbgv4p9uE2h6sZrQ==
|
integrity sha512-49fm3xbbUPuzBIOcy2CDpYWqy/X7VBkxVN+DC21e0zIm3+61Z0NZi6J9mqPmSW1BDVk9FIOvuCFyUPjXz93sjA==
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree@5.31.0":
|
"@typescript-eslint/typescript-estree@5.31.0":
|
||||||
version "5.31.0"
|
version "5.31.0"
|
||||||
@ -2648,28 +2653,28 @@
|
|||||||
semver "^7.3.7"
|
semver "^7.3.7"
|
||||||
tsutils "^3.21.0"
|
tsutils "^3.21.0"
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree@5.32.0":
|
"@typescript-eslint/typescript-estree@5.34.0":
|
||||||
version "5.32.0"
|
version "5.34.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.32.0.tgz#282943f34babf07a4afa7b0ff347a8e7b6030d12"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.34.0.tgz#ba7b83f4bf8ccbabf074bbf1baca7a58de3ccb9a"
|
||||||
integrity sha512-ZVAUkvPk3ITGtCLU5J4atCw9RTxK+SRc6hXqLtllC2sGSeMFWN+YwbiJR9CFrSFJ3w4SJfcWtDwNb/DmUIHdhg==
|
integrity sha512-mXHAqapJJDVzxauEkfJI96j3D10sd567LlqroyCeJaHnu42sDbjxotGb3XFtGPYKPD9IyLjhsoULML1oI3M86A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "5.32.0"
|
"@typescript-eslint/types" "5.34.0"
|
||||||
"@typescript-eslint/visitor-keys" "5.32.0"
|
"@typescript-eslint/visitor-keys" "5.34.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
globby "^11.1.0"
|
globby "^11.1.0"
|
||||||
is-glob "^4.0.3"
|
is-glob "^4.0.3"
|
||||||
semver "^7.3.7"
|
semver "^7.3.7"
|
||||||
tsutils "^3.21.0"
|
tsutils "^3.21.0"
|
||||||
|
|
||||||
"@typescript-eslint/utils@5.32.0":
|
"@typescript-eslint/utils@5.34.0":
|
||||||
version "5.32.0"
|
version "5.34.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.32.0.tgz#eccb6b672b94516f1afc6508d05173c45924840c"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.34.0.tgz#0cae98f48d8f9e292e5caa9343611b6faf49e743"
|
||||||
integrity sha512-W7lYIAI5Zlc5K082dGR27Fczjb3Q57ECcXefKU/f0ajM5ToM0P+N9NmJWip8GmGu/g6QISNT+K6KYB+iSHjXCQ==
|
integrity sha512-kWRYybU4Rn++7lm9yu8pbuydRyQsHRoBDIo11k7eqBWTldN4xUdVUMCsHBiE7aoEkFzrUEaZy3iH477vr4xHAQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/json-schema" "^7.0.9"
|
"@types/json-schema" "^7.0.9"
|
||||||
"@typescript-eslint/scope-manager" "5.32.0"
|
"@typescript-eslint/scope-manager" "5.34.0"
|
||||||
"@typescript-eslint/types" "5.32.0"
|
"@typescript-eslint/types" "5.34.0"
|
||||||
"@typescript-eslint/typescript-estree" "5.32.0"
|
"@typescript-eslint/typescript-estree" "5.34.0"
|
||||||
eslint-scope "^5.1.1"
|
eslint-scope "^5.1.1"
|
||||||
eslint-utils "^3.0.0"
|
eslint-utils "^3.0.0"
|
||||||
|
|
||||||
@ -2681,12 +2686,12 @@
|
|||||||
"@typescript-eslint/types" "5.31.0"
|
"@typescript-eslint/types" "5.31.0"
|
||||||
eslint-visitor-keys "^3.3.0"
|
eslint-visitor-keys "^3.3.0"
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys@5.32.0":
|
"@typescript-eslint/visitor-keys@5.34.0":
|
||||||
version "5.32.0"
|
version "5.34.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.32.0.tgz#b9715d0b11fdb5dd10fd0c42ff13987470525394"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.34.0.tgz#d0fb3e31033e82ddd5de048371ad39eb342b2d40"
|
||||||
integrity sha512-S54xOHZgfThiZ38/ZGTgB2rqx51CMJ5MCfVT2IplK4Q7hgzGfe0nLzLCcenDnc/cSjP568hdeKfeDcBgqNHD/g==
|
integrity sha512-O1moYjOSrab0a2fUvFpsJe0QHtvTC+cR+ovYpgKrAVXzqQyc74mv76TgY6z+aEtjQE2vgZux3CQVtGryqdcOAw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "5.32.0"
|
"@typescript-eslint/types" "5.34.0"
|
||||||
eslint-visitor-keys "^3.3.0"
|
eslint-visitor-keys "^3.3.0"
|
||||||
|
|
||||||
"@webassemblyjs/ast@1.11.1":
|
"@webassemblyjs/ast@1.11.1":
|
||||||
@ -2855,6 +2860,13 @@ abbrev@1, abbrev@~1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||||
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
||||||
|
|
||||||
|
abort-controller@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
|
||||||
|
integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
|
||||||
|
dependencies:
|
||||||
|
event-target-shim "^5.0.0"
|
||||||
|
|
||||||
accepts@~1.3.4, accepts@~1.3.5:
|
accepts@~1.3.4, accepts@~1.3.5:
|
||||||
version "1.3.7"
|
version "1.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
||||||
@ -4695,15 +4707,6 @@ css@^2.0.0:
|
|||||||
source-map-resolve "^0.5.2"
|
source-map-resolve "^0.5.2"
|
||||||
urix "^0.1.0"
|
urix "^0.1.0"
|
||||||
|
|
||||||
css@^3.0.0:
|
|
||||||
version "3.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d"
|
|
||||||
integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==
|
|
||||||
dependencies:
|
|
||||||
inherits "^2.0.4"
|
|
||||||
source-map "^0.6.1"
|
|
||||||
source-map-resolve "^0.6.0"
|
|
||||||
|
|
||||||
cssesc@^3.0.0:
|
cssesc@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||||
@ -5348,10 +5351,10 @@ electron-window-state@^5.0.3:
|
|||||||
jsonfile "^4.0.0"
|
jsonfile "^4.0.0"
|
||||||
mkdirp "^0.5.1"
|
mkdirp "^0.5.1"
|
||||||
|
|
||||||
electron@^19.0.4:
|
electron@^19.0.13:
|
||||||
version "19.0.4"
|
version "19.0.13"
|
||||||
resolved "https://registry.yarnpkg.com/electron/-/electron-19.0.4.tgz#a88d5e542868c4abd7704228ec62c553605605a0"
|
resolved "https://registry.yarnpkg.com/electron/-/electron-19.0.13.tgz#68bcf7d94f249dbae9a3d4d1794d45a24db666dc"
|
||||||
integrity sha512-roRYr1VNAWIhjD9n8qZdmhROtrzsFpuZEXrjWAw+GqPbZlrUInmvFCviRDC2Lt+VBsTNRpTfPpfzXSlLL4reEw==
|
integrity sha512-11Ne0VJy8L1GU7sGcbJHhkAz73szR27uP4vmfUVGlppC/ipA39AUkdzqiQoPC/F1EJdjEOBvHySG8K8Xe9yETA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron/get" "^1.14.1"
|
"@electron/get" "^1.14.1"
|
||||||
"@types/node" "^16.11.26"
|
"@types/node" "^16.11.26"
|
||||||
@ -5537,71 +5540,141 @@ esbuild-android-64@0.14.53:
|
|||||||
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.53.tgz#259bc3ef1399a3cad8f4f67c40ee20779c4de675"
|
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.53.tgz#259bc3ef1399a3cad8f4f67c40ee20779c4de675"
|
||||||
integrity sha512-fIL93sOTnEU+NrTAVMIKiAw0YH22HWCAgg4N4Z6zov2t0kY9RAJ50zY9ZMCQ+RT6bnOfDt8gCTnt/RaSNA2yRA==
|
integrity sha512-fIL93sOTnEU+NrTAVMIKiAw0YH22HWCAgg4N4Z6zov2t0kY9RAJ50zY9ZMCQ+RT6bnOfDt8gCTnt/RaSNA2yRA==
|
||||||
|
|
||||||
|
esbuild-android-64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.5.tgz#3c7b2f2a59017dab3f2c0356188a8dd9cbdc91c8"
|
||||||
|
integrity sha512-dYPPkiGNskvZqmIK29OPxolyY3tp+c47+Fsc2WYSOVjEPWNCHNyqhtFqQadcXMJDQt8eN0NMDukbyQgFcHquXg==
|
||||||
|
|
||||||
esbuild-android-arm64@0.14.53:
|
esbuild-android-arm64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.53.tgz#2158253d4e8f9fdd2a081bbb4f73b8806178841e"
|
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.53.tgz#2158253d4e8f9fdd2a081bbb4f73b8806178841e"
|
||||||
integrity sha512-PC7KaF1v0h/nWpvlU1UMN7dzB54cBH8qSsm7S9mkwFA1BXpaEOufCg8hdoEI1jep0KeO/rjZVWrsH8+q28T77A==
|
integrity sha512-PC7KaF1v0h/nWpvlU1UMN7dzB54cBH8qSsm7S9mkwFA1BXpaEOufCg8hdoEI1jep0KeO/rjZVWrsH8+q28T77A==
|
||||||
|
|
||||||
|
esbuild-android-arm64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.5.tgz#e301db818c5a67b786bf3bb7320e414ac0fcf193"
|
||||||
|
integrity sha512-YyEkaQl08ze3cBzI/4Cm1S+rVh8HMOpCdq8B78JLbNFHhzi4NixVN93xDrHZLztlocEYqi45rHHCgA8kZFidFg==
|
||||||
|
|
||||||
esbuild-darwin-64@0.14.53:
|
esbuild-darwin-64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.53.tgz#b4681831fd8f8d06feb5048acbe90d742074cc2a"
|
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.53.tgz#b4681831fd8f8d06feb5048acbe90d742074cc2a"
|
||||||
integrity sha512-gE7P5wlnkX4d4PKvLBUgmhZXvL7lzGRLri17/+CmmCzfncIgq8lOBvxGMiQ4xazplhxq+72TEohyFMZLFxuWvg==
|
integrity sha512-gE7P5wlnkX4d4PKvLBUgmhZXvL7lzGRLri17/+CmmCzfncIgq8lOBvxGMiQ4xazplhxq+72TEohyFMZLFxuWvg==
|
||||||
|
|
||||||
|
esbuild-darwin-64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.5.tgz#11726de5d0bf5960b92421ef433e35871c091f8d"
|
||||||
|
integrity sha512-Cr0iIqnWKx3ZTvDUAzG0H/u9dWjLE4c2gTtRLz4pqOBGjfjqdcZSfAObFzKTInLLSmD0ZV1I/mshhPoYSBMMCQ==
|
||||||
|
|
||||||
esbuild-darwin-arm64@0.14.53:
|
esbuild-darwin-arm64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.53.tgz#d267d957852d121b261b3f76ead86e5b5463acc9"
|
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.53.tgz#d267d957852d121b261b3f76ead86e5b5463acc9"
|
||||||
integrity sha512-otJwDU3hnI15Q98PX4MJbknSZ/WSR1I45il7gcxcECXzfN4Mrpft5hBDHXNRnCh+5858uPXBXA1Vaz2jVWLaIA==
|
integrity sha512-otJwDU3hnI15Q98PX4MJbknSZ/WSR1I45il7gcxcECXzfN4Mrpft5hBDHXNRnCh+5858uPXBXA1Vaz2jVWLaIA==
|
||||||
|
|
||||||
|
esbuild-darwin-arm64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.5.tgz#ad89dafebb3613fd374f5a245bb0ce4132413997"
|
||||||
|
integrity sha512-WIfQkocGtFrz7vCu44ypY5YmiFXpsxvz2xqwe688jFfSVCnUsCn2qkEVDo7gT8EpsLOz1J/OmqjExePL1dr1Kg==
|
||||||
|
|
||||||
esbuild-freebsd-64@0.14.53:
|
esbuild-freebsd-64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.53.tgz#aca2af6d72b537fe66a38eb8f374fb66d4c98ca0"
|
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.53.tgz#aca2af6d72b537fe66a38eb8f374fb66d4c98ca0"
|
||||||
integrity sha512-WkdJa8iyrGHyKiPF4lk0MiOF87Q2SkE+i+8D4Cazq3/iqmGPJ6u49je300MFi5I2eUsQCkaOWhpCVQMTKGww2w==
|
integrity sha512-WkdJa8iyrGHyKiPF4lk0MiOF87Q2SkE+i+8D4Cazq3/iqmGPJ6u49je300MFi5I2eUsQCkaOWhpCVQMTKGww2w==
|
||||||
|
|
||||||
|
esbuild-freebsd-64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.5.tgz#6bfb52b4a0d29c965aa833e04126e95173289c8a"
|
||||||
|
integrity sha512-M5/EfzV2RsMd/wqwR18CELcenZ8+fFxQAAEO7TJKDmP3knhWSbD72ILzrXFMMwshlPAS1ShCZ90jsxkm+8FlaA==
|
||||||
|
|
||||||
esbuild-freebsd-arm64@0.14.53:
|
esbuild-freebsd-arm64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.53.tgz#76282e19312d914c34343c8a7da6cc5f051580b9"
|
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.53.tgz#76282e19312d914c34343c8a7da6cc5f051580b9"
|
||||||
integrity sha512-9T7WwCuV30NAx0SyQpw8edbKvbKELnnm1FHg7gbSYaatH+c8WJW10g/OdM7JYnv7qkimw2ZTtSA+NokOLd2ydQ==
|
integrity sha512-9T7WwCuV30NAx0SyQpw8edbKvbKELnnm1FHg7gbSYaatH+c8WJW10g/OdM7JYnv7qkimw2ZTtSA+NokOLd2ydQ==
|
||||||
|
|
||||||
|
esbuild-freebsd-arm64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.5.tgz#38a3fed8c6398072f9914856c7c3e3444f9ef4dd"
|
||||||
|
integrity sha512-2JQQ5Qs9J0440F/n/aUBNvY6lTo4XP/4lt1TwDfHuo0DY3w5++anw+jTjfouLzbJmFFiwmX7SmUhMnysocx96w==
|
||||||
|
|
||||||
esbuild-linux-32@0.14.53:
|
esbuild-linux-32@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.53.tgz#1045d34cf7c5faaf2af3b29cc1573b06580c37e5"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.53.tgz#1045d34cf7c5faaf2af3b29cc1573b06580c37e5"
|
||||||
integrity sha512-VGanLBg5en2LfGDgLEUxQko2lqsOS7MTEWUi8x91YmsHNyzJVT/WApbFFx3MQGhkf+XdimVhpyo5/G0PBY91zg==
|
integrity sha512-VGanLBg5en2LfGDgLEUxQko2lqsOS7MTEWUi8x91YmsHNyzJVT/WApbFFx3MQGhkf+XdimVhpyo5/G0PBY91zg==
|
||||||
|
|
||||||
|
esbuild-linux-32@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.5.tgz#942dc70127f0c0a7ea91111baf2806e61fc81b32"
|
||||||
|
integrity sha512-gO9vNnIN0FTUGjvTFucIXtBSr1Woymmx/aHQtuU+2OllGU6YFLs99960UD4Dib1kFovVgs59MTXwpFdVoSMZoQ==
|
||||||
|
|
||||||
esbuild-linux-64@0.14.53:
|
esbuild-linux-64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.53.tgz#ab3f2ee2ebb5a6930c72d9539cb34b428808cbe4"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.53.tgz#ab3f2ee2ebb5a6930c72d9539cb34b428808cbe4"
|
||||||
integrity sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==
|
integrity sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==
|
||||||
|
|
||||||
|
esbuild-linux-64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.5.tgz#6d748564492d5daaa7e62420862c31ac3a44aed9"
|
||||||
|
integrity sha512-ne0GFdNLsm4veXbTnYAWjbx3shpNKZJUd6XpNbKNUZaNllDZfYQt0/zRqOg0sc7O8GQ+PjSMv9IpIEULXVTVmg==
|
||||||
|
|
||||||
esbuild-linux-arm64@0.14.53:
|
esbuild-linux-arm64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.53.tgz#1f5530412f6690949e78297122350488d3266cfe"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.53.tgz#1f5530412f6690949e78297122350488d3266cfe"
|
||||||
integrity sha512-GDmWITT+PMsjCA6/lByYk7NyFssW4Q6in32iPkpjZ/ytSyH+xeEx8q7HG3AhWH6heemEYEWpTll/eui3jwlSnw==
|
integrity sha512-GDmWITT+PMsjCA6/lByYk7NyFssW4Q6in32iPkpjZ/ytSyH+xeEx8q7HG3AhWH6heemEYEWpTll/eui3jwlSnw==
|
||||||
|
|
||||||
|
esbuild-linux-arm64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.5.tgz#28cd899beb2d2b0a3870fd44f4526835089a318d"
|
||||||
|
integrity sha512-7EgFyP2zjO065XTfdCxiXVEk+f83RQ1JsryN1X/VSX2li9rnHAt2swRbpoz5Vlrl6qjHrCmq5b6yxD13z6RheA==
|
||||||
|
|
||||||
esbuild-linux-arm@0.14.53:
|
esbuild-linux-arm@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.53.tgz#a44ec9b5b42007ab6c0d65a224ccc6bbd97c54cf"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.53.tgz#a44ec9b5b42007ab6c0d65a224ccc6bbd97c54cf"
|
||||||
integrity sha512-/u81NGAVZMopbmzd21Nu/wvnKQK3pT4CrvQ8BTje1STXcQAGnfyKgQlj3m0j2BzYbvQxSy+TMck4TNV2onvoPA==
|
integrity sha512-/u81NGAVZMopbmzd21Nu/wvnKQK3pT4CrvQ8BTje1STXcQAGnfyKgQlj3m0j2BzYbvQxSy+TMck4TNV2onvoPA==
|
||||||
|
|
||||||
|
esbuild-linux-arm@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.5.tgz#6441c256225564d8794fdef5b0a69bc1a43051b5"
|
||||||
|
integrity sha512-wvAoHEN+gJ/22gnvhZnS/+2H14HyAxM07m59RSLn3iXrQsdS518jnEWRBnJz3fR6BJa+VUTo0NxYjGaNt7RA7Q==
|
||||||
|
|
||||||
esbuild-linux-mips64le@0.14.53:
|
esbuild-linux-mips64le@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.53.tgz#a4d0b6b17cfdeea4e41b0b085a5f73d99311be9f"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.53.tgz#a4d0b6b17cfdeea4e41b0b085a5f73d99311be9f"
|
||||||
integrity sha512-d6/XHIQW714gSSp6tOOX2UscedVobELvQlPMkInhx1NPz4ThZI9uNLQ4qQJHGBGKGfu+rtJsxM4NVHLhnNRdWQ==
|
integrity sha512-d6/XHIQW714gSSp6tOOX2UscedVobELvQlPMkInhx1NPz4ThZI9uNLQ4qQJHGBGKGfu+rtJsxM4NVHLhnNRdWQ==
|
||||||
|
|
||||||
|
esbuild-linux-mips64le@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.5.tgz#d4927f817290eaffc062446896b2a553f0e11981"
|
||||||
|
integrity sha512-KdnSkHxWrJ6Y40ABu+ipTZeRhFtc8dowGyFsZY5prsmMSr1ZTG9zQawguN4/tunJ0wy3+kD54GaGwdcpwWAvZQ==
|
||||||
|
|
||||||
esbuild-linux-ppc64le@0.14.53:
|
esbuild-linux-ppc64le@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.53.tgz#8c331822c85465434e086e3e6065863770c38139"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.53.tgz#8c331822c85465434e086e3e6065863770c38139"
|
||||||
integrity sha512-ndnJmniKPCB52m+r6BtHHLAOXw+xBCWIxNnedbIpuREOcbSU/AlyM/2dA3BmUQhsHdb4w3amD5U2s91TJ3MzzA==
|
integrity sha512-ndnJmniKPCB52m+r6BtHHLAOXw+xBCWIxNnedbIpuREOcbSU/AlyM/2dA3BmUQhsHdb4w3amD5U2s91TJ3MzzA==
|
||||||
|
|
||||||
|
esbuild-linux-ppc64le@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.5.tgz#b6d660dc6d5295f89ac51c675f1a2f639e2fb474"
|
||||||
|
integrity sha512-QdRHGeZ2ykl5P0KRmfGBZIHmqcwIsUKWmmpZTOq573jRWwmpfRmS7xOhmDHBj9pxv+6qRMH8tLr2fe+ZKQvCYw==
|
||||||
|
|
||||||
esbuild-linux-riscv64@0.14.53:
|
esbuild-linux-riscv64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.53.tgz#36fd75543401304bea8a2d63bf8ea18aaa508e00"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.53.tgz#36fd75543401304bea8a2d63bf8ea18aaa508e00"
|
||||||
integrity sha512-yG2sVH+QSix6ct4lIzJj329iJF3MhloLE6/vKMQAAd26UVPVkhMFqFopY+9kCgYsdeWvXdPgmyOuKa48Y7+/EQ==
|
integrity sha512-yG2sVH+QSix6ct4lIzJj329iJF3MhloLE6/vKMQAAd26UVPVkhMFqFopY+9kCgYsdeWvXdPgmyOuKa48Y7+/EQ==
|
||||||
|
|
||||||
|
esbuild-linux-riscv64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.5.tgz#2801bf18414dc3d3ad58d1ea83084f00d9d84896"
|
||||||
|
integrity sha512-p+WE6RX+jNILsf+exR29DwgV6B73khEQV0qWUbzxaycxawZ8NE0wA6HnnTxbiw5f4Gx9sJDUBemh9v49lKOORA==
|
||||||
|
|
||||||
esbuild-linux-s390x@0.14.53:
|
esbuild-linux-s390x@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.53.tgz#1622677ab6824123f48f75d3afc031cd41936129"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.53.tgz#1622677ab6824123f48f75d3afc031cd41936129"
|
||||||
integrity sha512-OCJlgdkB+XPYndHmw6uZT7jcYgzmx9K+28PVdOa/eLjdoYkeAFvH5hTwX4AXGLZLH09tpl4bVsEtvuyUldaNCg==
|
integrity sha512-OCJlgdkB+XPYndHmw6uZT7jcYgzmx9K+28PVdOa/eLjdoYkeAFvH5hTwX4AXGLZLH09tpl4bVsEtvuyUldaNCg==
|
||||||
|
|
||||||
|
esbuild-linux-s390x@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.5.tgz#12a634ae6d3384cacc2b8f4201047deafe596eae"
|
||||||
|
integrity sha512-J2ngOB4cNzmqLHh6TYMM/ips8aoZIuzxJnDdWutBw5482jGXiOzsPoEF4j2WJ2mGnm7FBCO4StGcwzOgic70JQ==
|
||||||
|
|
||||||
esbuild-loader@^2.19.0:
|
esbuild-loader@^2.19.0:
|
||||||
version "2.19.0"
|
version "2.19.0"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-loader/-/esbuild-loader-2.19.0.tgz#54f62d1da8262acfc3c5883c24da35af8324f116"
|
resolved "https://registry.yarnpkg.com/esbuild-loader/-/esbuild-loader-2.19.0.tgz#54f62d1da8262acfc3c5883c24da35af8324f116"
|
||||||
@ -5619,32 +5692,62 @@ esbuild-netbsd-64@0.14.53:
|
|||||||
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.53.tgz#e86d0efd0116658be335492ed12e66b26b4baf52"
|
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.53.tgz#e86d0efd0116658be335492ed12e66b26b4baf52"
|
||||||
integrity sha512-gp2SB+Efc7MhMdWV2+pmIs/Ja/Mi5rjw+wlDmmbIn68VGXBleNgiEZG+eV2SRS0kJEUyHNedDtwRIMzaohWedQ==
|
integrity sha512-gp2SB+Efc7MhMdWV2+pmIs/Ja/Mi5rjw+wlDmmbIn68VGXBleNgiEZG+eV2SRS0kJEUyHNedDtwRIMzaohWedQ==
|
||||||
|
|
||||||
|
esbuild-netbsd-64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.5.tgz#951bbf87600512dfcfbe3b8d9d117d684d26c1b8"
|
||||||
|
integrity sha512-MmKUYGDizYjFia0Rwt8oOgmiFH7zaYlsoQ3tIOfPxOqLssAsEgG0MUdRDm5lliqjiuoog8LyDu9srQk5YwWF3w==
|
||||||
|
|
||||||
esbuild-openbsd-64@0.14.53:
|
esbuild-openbsd-64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.53.tgz#9bcbbe6f86304872c6e91f64c8eb73fc29c3588b"
|
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.53.tgz#9bcbbe6f86304872c6e91f64c8eb73fc29c3588b"
|
||||||
integrity sha512-eKQ30ZWe+WTZmteDYg8S+YjHV5s4iTxeSGhJKJajFfQx9TLZJvsJX0/paqwP51GicOUruFpSUAs2NCc0a4ivQQ==
|
integrity sha512-eKQ30ZWe+WTZmteDYg8S+YjHV5s4iTxeSGhJKJajFfQx9TLZJvsJX0/paqwP51GicOUruFpSUAs2NCc0a4ivQQ==
|
||||||
|
|
||||||
|
esbuild-openbsd-64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.5.tgz#26705b61961d525d79a772232e8b8f211fdbb035"
|
||||||
|
integrity sha512-2mMFfkLk3oPWfopA9Plj4hyhqHNuGyp5KQyTT9Rc8hFd8wAn5ZrbJg+gNcLMo2yzf8Uiu0RT6G9B15YN9WQyMA==
|
||||||
|
|
||||||
esbuild-sunos-64@0.14.53:
|
esbuild-sunos-64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.53.tgz#f7a872f7460bfb7b131f7188a95fbce3d1c577e8"
|
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.53.tgz#f7a872f7460bfb7b131f7188a95fbce3d1c577e8"
|
||||||
integrity sha512-OWLpS7a2FrIRukQqcgQqR1XKn0jSJoOdT+RlhAxUoEQM/IpytS3FXzCJM6xjUYtpO5GMY0EdZJp+ur2pYdm39g==
|
integrity sha512-OWLpS7a2FrIRukQqcgQqR1XKn0jSJoOdT+RlhAxUoEQM/IpytS3FXzCJM6xjUYtpO5GMY0EdZJp+ur2pYdm39g==
|
||||||
|
|
||||||
|
esbuild-sunos-64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.5.tgz#d794da1ae60e6e2f6194c44d7b3c66bf66c7a141"
|
||||||
|
integrity sha512-2sIzhMUfLNoD+rdmV6AacilCHSxZIoGAU2oT7XmJ0lXcZWnCvCtObvO6D4puxX9YRE97GodciRGDLBaiC6x1SA==
|
||||||
|
|
||||||
esbuild-windows-32@0.14.53:
|
esbuild-windows-32@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.53.tgz#c5e3ca50e2d1439cc2c9fe4defa63bcd474ce709"
|
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.53.tgz#c5e3ca50e2d1439cc2c9fe4defa63bcd474ce709"
|
||||||
integrity sha512-m14XyWQP5rwGW0tbEfp95U6A0wY0DYPInWBB7D69FAXUpBpBObRoGTKRv36lf2RWOdE4YO3TNvj37zhXjVL5xg==
|
integrity sha512-m14XyWQP5rwGW0tbEfp95U6A0wY0DYPInWBB7D69FAXUpBpBObRoGTKRv36lf2RWOdE4YO3TNvj37zhXjVL5xg==
|
||||||
|
|
||||||
|
esbuild-windows-32@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.5.tgz#0670326903f421424be86bc03b7f7b3ff86a9db7"
|
||||||
|
integrity sha512-e+duNED9UBop7Vnlap6XKedA/53lIi12xv2ebeNS4gFmu7aKyTrok7DPIZyU5w/ftHD4MUDs5PJUkQPP9xJRzg==
|
||||||
|
|
||||||
esbuild-windows-64@0.14.53:
|
esbuild-windows-64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.53.tgz#ec2ab4a60c5215f092ffe1eab6d01319e88238af"
|
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.53.tgz#ec2ab4a60c5215f092ffe1eab6d01319e88238af"
|
||||||
integrity sha512-s9skQFF0I7zqnQ2K8S1xdLSfZFsPLuOGmSx57h2btSEswv0N0YodYvqLcJMrNMXh6EynOmWD7rz+0rWWbFpIHQ==
|
integrity sha512-s9skQFF0I7zqnQ2K8S1xdLSfZFsPLuOGmSx57h2btSEswv0N0YodYvqLcJMrNMXh6EynOmWD7rz+0rWWbFpIHQ==
|
||||||
|
|
||||||
|
esbuild-windows-64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.5.tgz#64f32acb7341f3f0a4d10e8ff1998c2d1ebfc0a9"
|
||||||
|
integrity sha512-v+PjvNtSASHOjPDMIai9Yi+aP+Vwox+3WVdg2JB8N9aivJ7lyhp4NVU+J0MV2OkWFPnVO8AE/7xH+72ibUUEnw==
|
||||||
|
|
||||||
esbuild-windows-arm64@0.14.53:
|
esbuild-windows-arm64@0.14.53:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.53.tgz#f71d403806bdf9f4a1f9d097db9aec949bd675c8"
|
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.53.tgz#f71d403806bdf9f4a1f9d097db9aec949bd675c8"
|
||||||
integrity sha512-E+5Gvb+ZWts+00T9II6wp2L3KG2r3iGxByqd/a1RmLmYWVsSVUjkvIxZuJ3hYTIbhLkH5PRwpldGTKYqVz0nzQ==
|
integrity sha512-E+5Gvb+ZWts+00T9II6wp2L3KG2r3iGxByqd/a1RmLmYWVsSVUjkvIxZuJ3hYTIbhLkH5PRwpldGTKYqVz0nzQ==
|
||||||
|
|
||||||
esbuild@^0.14.39, esbuild@^0.14.53:
|
esbuild-windows-arm64@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.5.tgz#4fe7f333ce22a922906b10233c62171673a3854b"
|
||||||
|
integrity sha512-Yz8w/D8CUPYstvVQujByu6mlf48lKmXkq6bkeSZZxTA626efQOJb26aDGLzmFWx6eg/FwrXgt6SZs9V8Pwy/aA==
|
||||||
|
|
||||||
|
esbuild@^0.14.39:
|
||||||
version "0.14.53"
|
version "0.14.53"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.53.tgz#20b1007f686e8584f2a01a1bec5a37aac9498ce4"
|
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.53.tgz#20b1007f686e8584f2a01a1bec5a37aac9498ce4"
|
||||||
integrity sha512-ohO33pUBQ64q6mmheX1mZ8mIXj8ivQY/L4oVuAshr+aJI+zLl+amrp3EodrUNDNYVrKJXGPfIHFGhO8slGRjuw==
|
integrity sha512-ohO33pUBQ64q6mmheX1mZ8mIXj8ivQY/L4oVuAshr+aJI+zLl+amrp3EodrUNDNYVrKJXGPfIHFGhO8slGRjuw==
|
||||||
@ -5671,6 +5774,33 @@ esbuild@^0.14.39, esbuild@^0.14.53:
|
|||||||
esbuild-windows-64 "0.14.53"
|
esbuild-windows-64 "0.14.53"
|
||||||
esbuild-windows-arm64 "0.14.53"
|
esbuild-windows-arm64 "0.14.53"
|
||||||
|
|
||||||
|
esbuild@^0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.5.tgz#5effd05666f621d4ff2fe2c76a67c198292193ff"
|
||||||
|
integrity sha512-VSf6S1QVqvxfIsSKb3UKr3VhUCis7wgDbtF4Vd9z84UJr05/Sp2fRKmzC+CSPG/dNAPPJZ0BTBLTT1Fhd6N9Gg==
|
||||||
|
optionalDependencies:
|
||||||
|
"@esbuild/linux-loong64" "0.15.5"
|
||||||
|
esbuild-android-64 "0.15.5"
|
||||||
|
esbuild-android-arm64 "0.15.5"
|
||||||
|
esbuild-darwin-64 "0.15.5"
|
||||||
|
esbuild-darwin-arm64 "0.15.5"
|
||||||
|
esbuild-freebsd-64 "0.15.5"
|
||||||
|
esbuild-freebsd-arm64 "0.15.5"
|
||||||
|
esbuild-linux-32 "0.15.5"
|
||||||
|
esbuild-linux-64 "0.15.5"
|
||||||
|
esbuild-linux-arm "0.15.5"
|
||||||
|
esbuild-linux-arm64 "0.15.5"
|
||||||
|
esbuild-linux-mips64le "0.15.5"
|
||||||
|
esbuild-linux-ppc64le "0.15.5"
|
||||||
|
esbuild-linux-riscv64 "0.15.5"
|
||||||
|
esbuild-linux-s390x "0.15.5"
|
||||||
|
esbuild-netbsd-64 "0.15.5"
|
||||||
|
esbuild-openbsd-64 "0.15.5"
|
||||||
|
esbuild-sunos-64 "0.15.5"
|
||||||
|
esbuild-windows-32 "0.15.5"
|
||||||
|
esbuild-windows-64 "0.15.5"
|
||||||
|
esbuild-windows-arm64 "0.15.5"
|
||||||
|
|
||||||
escalade@^3.1.1:
|
escalade@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||||
@ -5933,6 +6063,11 @@ etag@~1.8.1:
|
|||||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
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"
|
||||||
|
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
|
||||||
|
|
||||||
eventemitter3@^4.0.0:
|
eventemitter3@^4.0.0:
|
||||||
version "4.0.7"
|
version "4.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
||||||
@ -11961,10 +12096,10 @@ sass-loader@^12.6.0:
|
|||||||
klona "^2.0.4"
|
klona "^2.0.4"
|
||||||
neo-async "^2.6.2"
|
neo-async "^2.6.2"
|
||||||
|
|
||||||
sass@^1.32.13, sass@^1.54.2:
|
sass@^1.32.13, sass@^1.54.5:
|
||||||
version "1.54.2"
|
version "1.54.5"
|
||||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.54.2.tgz#574cad83814c930ef2475921b9cb5d8203ae8867"
|
resolved "https://registry.yarnpkg.com/sass/-/sass-1.54.5.tgz#93708f5560784f6ff2eab8542ade021a4a947b3a"
|
||||||
integrity sha512-wbVV26sejsCIbBScZZtNkvnrB/bVCQ8hSlZ01D9nzsVh9zLqCkWrlpvTb3YEb6xsuNi9cx75hncqwikHFSz7tw==
|
integrity sha512-p7DTOzxkUPa/63FU0R3KApkRHwcVZYC0PLnLm5iyZACyp15qSi32x7zVUhRdABAATmkALqgGrjCJAcWvobmhHw==
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar ">=3.0.0 <4.0.0"
|
chokidar ">=3.0.0 <4.0.0"
|
||||||
immutable "^4.0.0"
|
immutable "^4.0.0"
|
||||||
@ -12394,14 +12529,6 @@ source-map-resolve@^0.5.2:
|
|||||||
source-map-url "^0.4.0"
|
source-map-url "^0.4.0"
|
||||||
urix "^0.1.0"
|
urix "^0.1.0"
|
||||||
|
|
||||||
source-map-resolve@^0.6.0:
|
|
||||||
version "0.6.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2"
|
|
||||||
integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==
|
|
||||||
dependencies:
|
|
||||||
atob "^2.1.2"
|
|
||||||
decode-uri-component "^0.2.0"
|
|
||||||
|
|
||||||
source-map-support@0.5.13:
|
source-map-support@0.5.13:
|
||||||
version "0.5.13"
|
version "0.5.13"
|
||||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
|
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
|
||||||
@ -13835,10 +13962,10 @@ webpack-dev-middleware@^5.3.1:
|
|||||||
range-parser "^1.2.1"
|
range-parser "^1.2.1"
|
||||||
schema-utils "^4.0.0"
|
schema-utils "^4.0.0"
|
||||||
|
|
||||||
webpack-dev-server@*, webpack-dev-server@^4.9.3:
|
webpack-dev-server@*, webpack-dev-server@^4.10.0:
|
||||||
version "4.9.3"
|
version "4.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz#2360a5d6d532acb5410a668417ad549ee3b8a3c9"
|
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.10.0.tgz#de270d0009eba050546912be90116e7fd740a9ca"
|
||||||
integrity sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw==
|
integrity sha512-7dezwAs+k6yXVFZ+MaL8VnE+APobiO3zvpp3rBHe/HmWQ+avwh0Q3d0xxacOiBybZZ3syTZw9HXzpa3YNbAZDQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/bonjour" "^3.5.9"
|
"@types/bonjour" "^3.5.9"
|
||||||
"@types/connect-history-api-fallback" "^1.3.5"
|
"@types/connect-history-api-fallback" "^1.3.5"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user