mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
epic: getting rid of vue -- part 2
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
63de5fce3c
commit
1f26f0b3a7
@ -12,8 +12,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "concurrently -k \"yarn dev-run -C\" \"yarn dev:main\" \"yarn dev:renderer\"",
|
||||
"dev-run": "nodemon --watch out/main.* --exec \"electron --inspect .\" $@",
|
||||
"dev-test": "yarn test --watch",
|
||||
"dev-run": "env DEBUG=true nodemon --watch out/main.* --exec \"electron --inspect .\" $@",
|
||||
"dev:main": "env DEBUG=true yarn compile:main --watch $@",
|
||||
"dev:renderer": "env DEBUG=true yarn compile:renderer --watch $@",
|
||||
"compile": "concurrently \"yarn i18n:compile\" \"yarn compile:main -p\" \"yarn compile:renderer -p\"",
|
||||
@ -34,7 +33,8 @@
|
||||
"download-bins": "concurrently yarn:download:*",
|
||||
"download:kubectl": "yarn run ts-node build/download_kubectl.ts",
|
||||
"download:helm": "yarn run ts-node build/download_helm.ts",
|
||||
"lint": "eslint $@ --ext js,ts,tsx --max-warnings=0 src/"
|
||||
"lint": "eslint $@ --ext js,ts,tsx --max-warnings=0 src/",
|
||||
"rebuild": "electron-rebuild -f -w node-pty"
|
||||
},
|
||||
"config": {
|
||||
"bundledKubectlVersion": "1.17.4",
|
||||
@ -260,9 +260,10 @@
|
||||
"css-element-queries": "^1.2.3",
|
||||
"css-loader": "^3.5.3",
|
||||
"dompurify": "^2.0.11",
|
||||
"electron": "^6.1.12",
|
||||
"electron": "^7.3.2",
|
||||
"electron-builder": "^22.7.0",
|
||||
"electron-notarize": "^0.3.0",
|
||||
"electron-rebuild": "^1.11.0",
|
||||
"eslint": "^7.3.1",
|
||||
"file-loader": "^6.0.0",
|
||||
"flex.box": "^3.4.4",
|
||||
|
||||
@ -21,7 +21,7 @@ export class BaseStore<T = any> extends Singleton {
|
||||
public whenLoaded = when(() => this.isLoaded);
|
||||
|
||||
@observable isLoaded = false;
|
||||
@observable protected data = {} as T;
|
||||
@observable protected data: T;
|
||||
|
||||
protected constructor(protected params: BaseStoreParams) {
|
||||
super();
|
||||
@ -69,9 +69,9 @@ export class BaseStore<T = any> extends Singleton {
|
||||
},
|
||||
...confOptions,
|
||||
});
|
||||
const data = this.storeConfig.store;
|
||||
console.info(`[STORE]: [LOADED] ${this.storeConfig.path}`, data);
|
||||
this.fromStore(data);
|
||||
const jsonModel = this.storeConfig.store;
|
||||
console.info(`[STORE]: [LOADED] ${this.storeConfig.path}`, jsonModel);
|
||||
this.fromStore(jsonModel);
|
||||
this.isLoaded = true;
|
||||
}
|
||||
|
||||
@ -111,8 +111,8 @@ export class BaseStore<T = any> extends Singleton {
|
||||
}
|
||||
|
||||
@action
|
||||
protected fromStore(data: Partial<T> = {}) {
|
||||
Object.assign(this.data, data);
|
||||
protected fromStore(data: T) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@action
|
||||
@ -120,6 +120,7 @@ export class BaseStore<T = any> extends Singleton {
|
||||
this.data = produce(this.data, updater);
|
||||
}
|
||||
|
||||
// todo: use "serializr" ?
|
||||
toJSON(): T {
|
||||
return toJS(this.data, {
|
||||
recurseEverything: true,
|
||||
|
||||
@ -81,12 +81,11 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
|
||||
@action
|
||||
protected fromStore({ clusters = [] }: Partial<ClusterStoreModel> = {}) {
|
||||
// fixme: handle clusters update + delete
|
||||
clusters.forEach(model => {
|
||||
if (!this.clusters.has(model.id)) {
|
||||
this.clusters.set(model.id, new Cluster(model));
|
||||
}
|
||||
})
|
||||
const clustersMap = new Map<ClusterId, Cluster>();
|
||||
clusters.forEach(clusterModel => {
|
||||
clustersMap.set(clusterModel.id, new Cluster(clusterModel));
|
||||
});
|
||||
this.clusters.replace(clustersMap);
|
||||
}
|
||||
|
||||
toJSON(): ClusterStoreModel {
|
||||
|
||||
@ -9,12 +9,16 @@ export interface IpcOptions {
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
export interface IpcMessageHandler {
|
||||
(...args: any[]): any;
|
||||
}
|
||||
|
||||
export async function invokeMessage(channel: string, ...args: any[]) {
|
||||
logger.debug(`[IPC]: invoke channel "${channel}"`, { args });
|
||||
return ipcRenderer.invoke(channel, ...args);
|
||||
}
|
||||
|
||||
export function onMessage(channel: string, handler: (...args: any[]) => any, options: IpcOptions = {}) {
|
||||
export function onMessage(channel: string, handler: IpcMessageHandler, options: IpcOptions = {}) {
|
||||
const { timeout = 0 } = options;
|
||||
ipcMain.handle(channel, async (event, ...args: any[]) => {
|
||||
logger.debug(`[IPC]: handle "${channel}"`, { event, args });
|
||||
@ -37,8 +41,8 @@ export function onMessage(channel: string, handler: (...args: any[]) => any, opt
|
||||
})
|
||||
}
|
||||
|
||||
export function onMessages(messages: Record<string, Function>, options?: IpcOptions) {
|
||||
export function onMessages(messages: Record<string, IpcMessageHandler>, options?: IpcOptions) {
|
||||
Object.entries(messages).forEach(([channel, handler]) => {
|
||||
this.onMessage(channel, handler, options);
|
||||
onMessage(channel, handler, options);
|
||||
})
|
||||
}
|
||||
|
||||
17
src/common/register-protocol.ts
Normal file
17
src/common/register-protocol.ts
Normal file
@ -0,0 +1,17 @@
|
||||
// Register custom protocols
|
||||
|
||||
import path from "path";
|
||||
import { protocol } from "electron"
|
||||
import logger from "../main/logger";
|
||||
|
||||
export function registerFileProtocol(name: string, basePath: string) {
|
||||
protocol.registerFileProtocol(name, (request, callback) => {
|
||||
const filePath = request.url.replace(name + "://", "");
|
||||
const absPath = path.resolve(basePath, filePath);
|
||||
callback(absPath);
|
||||
}, (error) => {
|
||||
if (error) {
|
||||
logger.error(`Failed to register protocol "${name}"`, { basePath, error });
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
// Setup static folder for common assets
|
||||
|
||||
import path from "path";
|
||||
import { protocol } from "electron"
|
||||
import logger from "../main/logger";
|
||||
import { staticDir, staticProto, outDir } from "./vars";
|
||||
|
||||
export function registerStaticProtocol(rootFolder = staticDir) {
|
||||
const scheme = staticProto.replace("://", "");
|
||||
protocol.registerFileProtocol(scheme, (request, callback) => {
|
||||
const relativePath = request.url.replace(staticProto, "");
|
||||
const absPath = path.resolve(rootFolder, relativePath);
|
||||
callback(absPath);
|
||||
}, (error) => {
|
||||
logger.debug(`Failed to register protocol "${scheme}"`, error);
|
||||
})
|
||||
}
|
||||
|
||||
export function getStaticUrl(filePath: string) {
|
||||
return staticProto + filePath;
|
||||
}
|
||||
|
||||
export function getStaticPath(filePath: string) {
|
||||
return path.resolve(staticDir, filePath);
|
||||
}
|
||||
@ -7,8 +7,8 @@ import * as path from "path"
|
||||
// Writes kubeconfigs to "embedded" store, i.e. .../Lens/kubeconfigs/
|
||||
export function writeEmbeddedKubeConfig(clusterId: string, kubeConfig: string): string {
|
||||
// This can be called from main & renderer
|
||||
const a = (app || remote.app)
|
||||
const kubeConfigBase = path.join(a.getPath("userData"), "kubeconfigs")
|
||||
const userData = (app || remote.app).getPath("userData");
|
||||
const kubeConfigBase = path.join(userData, "kubeconfigs")
|
||||
ensureDirSync(kubeConfigBase)
|
||||
|
||||
const kubeConfigFile = path.join(kubeConfigBase, clusterId)
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
// App's common configuration for any process (main, renderer, build pipeline, etc.)
|
||||
import packageInfo from "../../package.json"
|
||||
import path from "path";
|
||||
|
||||
export const appName = "lens"
|
||||
|
||||
// Flags
|
||||
export const isMac = process.platform === "darwin"
|
||||
export const isWindows = process.platform === "win32"
|
||||
export const isDebugging = process.env.DEBUG === "true";
|
||||
@ -12,6 +10,10 @@ export const isDevelopment = isDebugging || !isProduction;
|
||||
export const buildVersion = process.env.BUILD_VERSION;
|
||||
export const isTestEnv = !!process.env.JEST_WORKER_ID;
|
||||
|
||||
export const appName = `${packageInfo.productName}${isDevelopment ? "Dev" : ""}`
|
||||
export const appProto = "lens" // app's "userData" folder (e.g. "lens://icons/logo.svg")
|
||||
export const staticProto = "static" // static content folder (e.g. "static://RELEASE_NOTES.md")
|
||||
|
||||
// Paths
|
||||
export const contextDir = process.cwd();
|
||||
export const staticDir = path.join(contextDir, "static");
|
||||
@ -22,8 +24,6 @@ export const htmlTemplate = path.resolve(rendererDir, "template.html");
|
||||
export const sassCommonVars = path.resolve(rendererDir, "components/vars.scss");
|
||||
|
||||
// Apis
|
||||
export const staticProto = "static://"
|
||||
|
||||
export const apiPrefix = {
|
||||
BASE: '/api',
|
||||
KUBE_BASE: '/api-kube', // kubernetes cluster api
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { action, computed, toJS } from "mobx";
|
||||
import { action, observable } from "mobx";
|
||||
import { BaseStore } from "./base-store";
|
||||
import { clusterStore } from "./cluster-store"
|
||||
|
||||
export type WorkspaceId = string;
|
||||
|
||||
export interface WorkspaceStoreModel {
|
||||
currentWorkspace?: WorkspaceId; // last visited/activated
|
||||
currentWorkspace?: WorkspaceId;
|
||||
workspaces: Workspace[]
|
||||
}
|
||||
|
||||
@ -18,17 +18,14 @@ export interface Workspace {
|
||||
export class WorkspaceStore extends BaseStore<WorkspaceStoreModel> {
|
||||
static readonly defaultId: WorkspaceId = "default"
|
||||
|
||||
protected data: WorkspaceStoreModel = {
|
||||
currentWorkspace: WorkspaceStore.defaultId,
|
||||
workspaces: [{
|
||||
@observable currentWorkspace = WorkspaceStore.defaultId;
|
||||
|
||||
@observable workspaces = observable.map<WorkspaceId, Workspace>({
|
||||
[WorkspaceStore.defaultId]: {
|
||||
id: WorkspaceStore.defaultId,
|
||||
name: "default"
|
||||
}]
|
||||
}
|
||||
|
||||
@computed get workspaces() {
|
||||
return toJS(this.data.workspaces);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
private constructor() {
|
||||
super({
|
||||
@ -36,40 +33,59 @@ export class WorkspaceStore extends BaseStore<WorkspaceStoreModel> {
|
||||
});
|
||||
}
|
||||
|
||||
public getById(id: WorkspaceId): Workspace {
|
||||
return this.workspaces.find(workspace => workspace.id === id);
|
||||
}
|
||||
|
||||
public getIndexById(id: WorkspaceId): number {
|
||||
return this.workspaces.findIndex(workspace => workspace.id === id);
|
||||
getById(id: WorkspaceId): Workspace {
|
||||
return this.workspaces.get(id);
|
||||
}
|
||||
|
||||
@action
|
||||
setCurrent(id: WorkspaceId) {
|
||||
this.data.currentWorkspace = id;
|
||||
if (!this.getById(id)) return;
|
||||
this.currentWorkspace = id;
|
||||
}
|
||||
|
||||
@action
|
||||
public saveWorkspace(newWorkspace: Workspace) {
|
||||
const workspace = this.getById(newWorkspace.id);
|
||||
if (workspace) {
|
||||
Object.assign(workspace, newWorkspace);
|
||||
public saveWorkspace(workspace: Workspace) {
|
||||
const id = workspace.id;
|
||||
const existingWorkspace = this.getById(id);
|
||||
if (existingWorkspace) {
|
||||
Object.assign(existingWorkspace, workspace);
|
||||
} else {
|
||||
this.data.workspaces.push(newWorkspace);
|
||||
this.workspaces.set(id, workspace);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
public removeWorkspace(workspaceOrId: Workspace | WorkspaceId) {
|
||||
const workspace = this.getById(typeof workspaceOrId == "string" ? workspaceOrId : workspaceOrId.id);
|
||||
public removeWorkspace(id: WorkspaceId) {
|
||||
const workspace = this.getById(id);
|
||||
if (!workspace) return;
|
||||
if (workspace.id === WorkspaceStore.defaultId) {
|
||||
if (id === WorkspaceStore.defaultId) {
|
||||
throw new Error("Cannot remove default workspace");
|
||||
}
|
||||
const index = this.getIndexById(workspace.id);
|
||||
if (index > -1) {
|
||||
this.data.workspaces.splice(index, 1)
|
||||
clusterStore.removeByWorkspaceId(workspace.id)
|
||||
if (id === this.currentWorkspace) {
|
||||
this.currentWorkspace = WorkspaceStore.defaultId;
|
||||
}
|
||||
this.workspaces.delete(id);
|
||||
clusterStore.removeByWorkspaceId(id)
|
||||
}
|
||||
|
||||
@action
|
||||
protected fromStore({ currentWorkspace, workspaces = [] }: WorkspaceStoreModel) {
|
||||
if (currentWorkspace) {
|
||||
this.currentWorkspace = currentWorkspace
|
||||
}
|
||||
if (workspaces.length) {
|
||||
this.workspaces.clear();
|
||||
workspaces.forEach(workspace => {
|
||||
this.workspaces.set(workspace.id, workspace)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
toJSON(): WorkspaceStoreModel {
|
||||
const { currentWorkspace, workspaces } = this;
|
||||
return {
|
||||
currentWorkspace: currentWorkspace,
|
||||
workspaces: Array.from(workspaces.values()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { autorun } from "mobx";
|
||||
import { apiPrefix } from "../common/vars";
|
||||
import { apiPrefix, appProto } from "../common/vars";
|
||||
import { app } from "electron"
|
||||
import path from "path"
|
||||
import http from "http"
|
||||
@ -26,8 +26,8 @@ export class ClusterManager {
|
||||
}
|
||||
|
||||
constructor(protected port: number) {
|
||||
ClusterManager.ipcListen(this);
|
||||
autorun(() => {
|
||||
// fixme: detect and stop removed clusters from config file ?
|
||||
clusterStore.clusters.forEach((cluster: Cluster) => {
|
||||
if (!cluster.initialized) {
|
||||
cluster.init(this.port);
|
||||
@ -35,6 +35,8 @@ export class ClusterManager {
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
ClusterManager.ipcListen(this);
|
||||
}
|
||||
|
||||
stop() {
|
||||
@ -48,6 +50,7 @@ export class ClusterManager {
|
||||
}
|
||||
|
||||
protected async addCluster(clusterModel: ClusterModel): Promise<Cluster> {
|
||||
tracker.event("cluster", "add");
|
||||
try {
|
||||
await validateConfig(clusterModel.kubeConfigPath);
|
||||
return clusterStore.addCluster({
|
||||
@ -60,7 +63,13 @@ export class ClusterManager {
|
||||
}
|
||||
}
|
||||
|
||||
protected stopCluster(clusterId: ClusterId) {
|
||||
tracker.event("cluster", "stop");
|
||||
this.getCluster(clusterId)?.stopServer();
|
||||
}
|
||||
|
||||
protected removeAllByWorkspace(workspaceId: string) {
|
||||
tracker.event("cluster", "remove-workspace");
|
||||
const clusters = clusterStore.getByWorkspaceId(workspaceId);
|
||||
clusters.forEach(cluster => {
|
||||
this.removeCluster(cluster.id);
|
||||
@ -68,6 +77,7 @@ export class ClusterManager {
|
||||
}
|
||||
|
||||
protected removeCluster(clusterId: string): Cluster {
|
||||
tracker.event("cluster", "remove");
|
||||
const cluster = this.getCluster(clusterId);
|
||||
if (cluster) {
|
||||
cluster.stopServer()
|
||||
@ -97,64 +107,70 @@ export class ClusterManager {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
protected async uploadClusterIcon(cluster: Cluster, fileName: string, src: string): Promise<string> {
|
||||
await ensureDir(ClusterManager.clusterIconDir)
|
||||
fileName = filenamify(cluster.contextName + "-" + fileName)
|
||||
const dest = path.join(ClusterManager.clusterIconDir, fileName)
|
||||
await copyFile(src, dest)
|
||||
return "store:///icons/" + fileName
|
||||
protected async uploadClusterIcon({ clusterId, name: fileName, path: src }: ClusterIconUpload): Promise<string> {
|
||||
const cluster = this.getCluster(clusterId);
|
||||
if (cluster) {
|
||||
tracker.event("cluster", "upload-icon");
|
||||
await ensureDir(ClusterManager.clusterIconDir)
|
||||
fileName = filenamify(cluster.contextName + "-" + fileName)
|
||||
const dest = path.join(ClusterManager.clusterIconDir, fileName)
|
||||
await copyFile(src, dest)
|
||||
cluster.preferences.icon = `${appProto}:///icons/${fileName}`
|
||||
return cluster.preferences.icon;
|
||||
}
|
||||
}
|
||||
|
||||
// todo: remove current icon file ?
|
||||
protected resetClusterIcon(clusterId: ClusterId) {
|
||||
const cluster = this.getCluster(clusterId);
|
||||
if (cluster) {
|
||||
tracker.event("cluster", "reset-icon")
|
||||
cluster.preferences.icon = null;
|
||||
}
|
||||
}
|
||||
|
||||
// todo: check feature failures
|
||||
protected async installFeature({ clusterId, name, config }: FeatureInstallRequest) {
|
||||
tracker.event("cluster", "install-feature")
|
||||
return this.getCluster(clusterId)?.installFeature(name, config)
|
||||
}
|
||||
|
||||
protected async upgradeFeature({ clusterId, name, config }: FeatureInstallRequest) {
|
||||
tracker.event("cluster", "upgrade-feature")
|
||||
return this.getCluster(clusterId)?.upgradeFeature(name, config)
|
||||
}
|
||||
|
||||
protected async uninstallFeature({ clusterId, name }: FeatureInstallRequest) {
|
||||
tracker.event("cluster", "uninstall-feature")
|
||||
return this.getCluster(clusterId)?.uninstallFeature(name);
|
||||
}
|
||||
|
||||
protected async refreshCluster(clusterId: ClusterId) {
|
||||
await this.getCluster(clusterId)?.refreshCluster();
|
||||
}
|
||||
|
||||
protected async getEventsCount(clusterId: ClusterId): Promise<number> {
|
||||
return await this.getCluster(clusterId)?.getEventCount() || 0;
|
||||
}
|
||||
|
||||
static ipcListen(clusterManager: ClusterManager) {
|
||||
onMessages({
|
||||
[ClusterIpcMessage.CLUSTER_ADD]: async (model: ClusterModel): Promise<boolean> => {
|
||||
tracker.event("cluster", "add");
|
||||
await clusterManager.addCluster(model);
|
||||
return true;
|
||||
},
|
||||
[ClusterIpcMessage.CLUSTER_STOP]: (clusterId: ClusterId) => {
|
||||
tracker.event("cluster", "stop");
|
||||
clusterManager.getCluster(clusterId)?.stopServer();
|
||||
},
|
||||
[ClusterIpcMessage.CLUSTER_REMOVE]: (clusterId: ClusterId) => {
|
||||
tracker.event("cluster", "remove");
|
||||
clusterManager.removeCluster(clusterId);
|
||||
},
|
||||
[ClusterIpcMessage.CLUSTER_REMOVE_WORKSPACE]: (workspaceId: ClusterId) => {
|
||||
clusterManager.removeAllByWorkspace(workspaceId);
|
||||
},
|
||||
[ClusterIpcMessage.CLUSTER_REFRESH]: (clusterId: ClusterId) => {
|
||||
clusterManager.getCluster(clusterId)?.refreshCluster();
|
||||
},
|
||||
[ClusterIpcMessage.CLUSTER_EVENTS]: async (clusterId: ClusterId): Promise<number> => {
|
||||
return await clusterManager.getCluster(clusterId)?.getEventCount() || 0;
|
||||
},
|
||||
// todo: check feature failures
|
||||
[ClusterIpcMessage.FEATURE_INSTALL]: ({ clusterId, name, config }: FeatureInstallRequest) => {
|
||||
tracker.event("cluster", "install-feature")
|
||||
return clusterManager.getCluster(clusterId)?.installFeature(name, config)
|
||||
},
|
||||
[ClusterIpcMessage.FEATURE_UPGRADE]: ({ clusterId, name, config }: FeatureInstallRequest) => {
|
||||
tracker.event("cluster", "upgrade-feature")
|
||||
return clusterManager.getCluster(clusterId)?.upgradeFeature(name, config)
|
||||
},
|
||||
[ClusterIpcMessage.FEATURE_REMOVE]: ({ clusterId, name }: FeatureInstallRequest) => {
|
||||
tracker.event("cluster", "uninstall-feature")
|
||||
return clusterManager.getCluster(clusterId)?.uninstallFeature(name);
|
||||
},
|
||||
[ClusterIpcMessage.ICON_SAVE]: async ({ clusterId, name, path }: ClusterIconUpload) => {
|
||||
tracker.event("cluster", "upload-icon");
|
||||
const cluster = clusterManager.getCluster(clusterId);
|
||||
if (!cluster) return false;
|
||||
cluster.preferences.icon = await clusterManager.uploadClusterIcon(cluster, name, path);
|
||||
},
|
||||
[ClusterIpcMessage.ICON_RESET]: async (clusterId: ClusterId) => {
|
||||
tracker.event("cluster", "reset-icon")
|
||||
const cluster = clusterManager.getCluster(clusterId);
|
||||
if (!cluster) return false;
|
||||
cluster.preferences.icon = null; // todo: remove current file-icon ?
|
||||
},
|
||||
}, {
|
||||
const handlers = {
|
||||
[ClusterIpcMessage.CLUSTER_ADD]: clusterManager.addCluster,
|
||||
[ClusterIpcMessage.CLUSTER_STOP]: clusterManager.stopCluster,
|
||||
[ClusterIpcMessage.CLUSTER_REMOVE]: clusterManager.removeCluster,
|
||||
[ClusterIpcMessage.CLUSTER_REMOVE_WORKSPACE]: clusterManager.removeAllByWorkspace,
|
||||
[ClusterIpcMessage.CLUSTER_REFRESH]: clusterManager.refreshCluster,
|
||||
[ClusterIpcMessage.CLUSTER_EVENTS]: clusterManager.getEventsCount,
|
||||
[ClusterIpcMessage.FEATURE_INSTALL]: clusterManager.installFeature,
|
||||
[ClusterIpcMessage.FEATURE_UPGRADE]: clusterManager.upgradeFeature,
|
||||
[ClusterIpcMessage.FEATURE_REMOVE]: clusterManager.uninstallFeature,
|
||||
[ClusterIpcMessage.ICON_SAVE]: clusterManager.uploadClusterIcon,
|
||||
[ClusterIpcMessage.ICON_RESET]: clusterManager.removeCluster,
|
||||
};
|
||||
Object.entries(handlers).forEach(([key, handler]) => {
|
||||
handlers[key as keyof typeof handlers] = handler.bind(clusterManager);
|
||||
})
|
||||
onMessages(handlers, {
|
||||
timeout: 2000,
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { observable } from "mobx";
|
||||
import type { ClusterId, ClusterModel, ClusterPreferences } from "../common/cluster-store"
|
||||
import type { FeatureStatusMap } from "./feature"
|
||||
import { observable, toJS } from "mobx";
|
||||
import { apiPrefix } from "../common/vars";
|
||||
import { ContextHandler } from "./context-handler"
|
||||
import { FeatureStatusMap } from "./feature"
|
||||
import { AuthorizationV1Api, CoreV1Api, KubeConfig, V1ResourceAttributes } from "@kubernetes/client-node"
|
||||
import { Kubectl } from "./kubectl";
|
||||
import { KubeconfigManager } from "./kubeconfig-manager"
|
||||
import { getNodeWarningConditions, loadConfig, podHasIssues } from "./k8s"
|
||||
import { getFeatures, installFeature, uninstallFeature, upgradeFeature } from "./feature-manager";
|
||||
import type { ClusterId, ClusterModel, ClusterPreferences } from "../common/cluster-store"
|
||||
import request from "request-promise-native"
|
||||
import logger from "./logger"
|
||||
|
||||
@ -17,30 +17,43 @@ enum ClusterStatus {
|
||||
Offline = 0
|
||||
}
|
||||
|
||||
export interface ClusterState extends ClusterModel {
|
||||
url: string;
|
||||
apiUrl: string;
|
||||
online?: boolean;
|
||||
accessible?: boolean;
|
||||
failureReason?: string;
|
||||
nodes?: number;
|
||||
eventCount?: number;
|
||||
version?: string;
|
||||
distribution?: string;
|
||||
isAdmin?: boolean;
|
||||
features?: FeatureStatusMap;
|
||||
}
|
||||
|
||||
export class Cluster implements ClusterModel {
|
||||
public contextHandler: ContextHandler;
|
||||
public kubeCtl: Kubectl
|
||||
protected kubeconfigManager: KubeconfigManager;
|
||||
|
||||
@observable initialized = false;
|
||||
@observable id: ClusterId;
|
||||
@observable workspace: string;
|
||||
@observable kubeConfigPath: string;
|
||||
@observable contextName: string;
|
||||
@observable url: string;
|
||||
@observable port: number;
|
||||
@observable apiUrl: string;
|
||||
@observable online: boolean;
|
||||
@observable accessible: boolean;
|
||||
@observable failureReason: string;
|
||||
@observable nodes: number;
|
||||
@observable version: string;
|
||||
@observable distribution: string;
|
||||
@observable isAdmin: boolean;
|
||||
@observable eventCount: number;
|
||||
@observable preferences: ClusterPreferences = {};
|
||||
|
||||
public contextHandler: ContextHandler;
|
||||
public url: string;
|
||||
public port: number;
|
||||
public apiUrl: string;
|
||||
public online: boolean;
|
||||
public accessible: boolean;
|
||||
public failureReason: string;
|
||||
public nodes: number;
|
||||
public version: string;
|
||||
public distribution: string;
|
||||
public isAdmin: boolean;
|
||||
public eventCount: number;
|
||||
public kubeCtl: Kubectl
|
||||
public features: FeatureStatusMap = {};
|
||||
|
||||
protected kubeconfigManager: KubeconfigManager;
|
||||
@observable features: FeatureStatusMap = {};
|
||||
|
||||
constructor(model: ClusterModel) {
|
||||
Object.assign(this, model)
|
||||
@ -50,7 +63,7 @@ export class Cluster implements ClusterModel {
|
||||
const { contextName } = this
|
||||
try {
|
||||
const kubeConfig = loadConfig(this.kubeConfigPath)
|
||||
kubeConfig.setCurrentContext(contextName); // fixme: is it needed at all?
|
||||
kubeConfig.setCurrentContext(contextName); // fixme: is it required, when if so?
|
||||
this.port = port;
|
||||
this.apiUrl = kubeConfig.getCurrentCluster().server
|
||||
this.contextHandler = new ContextHandler(kubeConfig, this)
|
||||
@ -238,12 +251,34 @@ export class Cluster implements ClusterModel {
|
||||
}
|
||||
|
||||
toJSON(): ClusterModel {
|
||||
return {
|
||||
return toJS({
|
||||
id: this.id,
|
||||
contextName: this.contextName,
|
||||
kubeConfigPath: this.kubeConfigPath,
|
||||
workspace: this.workspace,
|
||||
preferences: this.preferences,
|
||||
}
|
||||
}, {
|
||||
recurseEverything: true
|
||||
})
|
||||
}
|
||||
|
||||
getState(): ClusterState {
|
||||
const storeModel = this.toJSON();
|
||||
return toJS({
|
||||
...storeModel,
|
||||
url: this.url,
|
||||
apiUrl: this.apiUrl,
|
||||
online: this.online,
|
||||
accessible: this.accessible,
|
||||
failureReason: this.failureReason,
|
||||
nodes: this.nodes,
|
||||
version: this.version,
|
||||
distribution: this.distribution,
|
||||
isAdmin: this.isAdmin,
|
||||
features: this.features,
|
||||
eventCount: this.eventCount,
|
||||
}, {
|
||||
recurseEverything: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,30 +3,22 @@ import path from "path"
|
||||
import hb from "handlebars"
|
||||
import { ResourceApplier } from "./resource-applier"
|
||||
import { KubeConfig, CoreV1Api, Watch } from "@kubernetes/client-node"
|
||||
import logger from "./logger";
|
||||
import { Cluster } from "./cluster";
|
||||
import logger from "./logger";
|
||||
|
||||
export type FeatureInstallRequest = {
|
||||
export type FeatureStatusMap = Record<string, FeatureStatus>
|
||||
|
||||
export interface FeatureInstallRequest {
|
||||
clusterId: string;
|
||||
name: string;
|
||||
config?: any;
|
||||
}
|
||||
|
||||
export type FeatureInstallResponse = {
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export type FeatureStatus = {
|
||||
export interface FeatureStatus {
|
||||
currentVersion: string;
|
||||
installed: boolean;
|
||||
latestVersion: string;
|
||||
canUpgrade: boolean;
|
||||
// TODO We need bunch of other stuff too: upgradeable, latestVersion, ...
|
||||
};
|
||||
|
||||
export type FeatureStatusMap = {
|
||||
[name: string]: FeatureStatus;
|
||||
}
|
||||
|
||||
export abstract class Feature {
|
||||
@ -35,9 +27,7 @@ export abstract class Feature {
|
||||
latestVersion: string;
|
||||
|
||||
constructor(config: any) {
|
||||
if(config) {
|
||||
this.config = config;
|
||||
}
|
||||
if(config) this.config = config;
|
||||
}
|
||||
|
||||
// TODO Return types for these?
|
||||
|
||||
@ -2,12 +2,10 @@
|
||||
|
||||
import "../common/system-ca"
|
||||
import "../common/prometheus-providers"
|
||||
import { app, dialog, protocol } from "electron"
|
||||
import { appName, isDevelopment, isMac } from "../common/vars";
|
||||
import { PromiseIpc } from "electron-promise-ipc"
|
||||
import { app, dialog } from "electron"
|
||||
import { appName, appProto, isDevelopment, isMac, staticDir, staticProto } from "../common/vars";
|
||||
import path from "path"
|
||||
import { format as formatUrl } from "url"
|
||||
import logger from "./logger"
|
||||
import initMenu from "./menu"
|
||||
import * as proxy from "./proxy"
|
||||
import { WindowManager } from "./window-manager";
|
||||
@ -16,25 +14,13 @@ import AppUpdater from "./app-updater"
|
||||
import { shellSync } from "./shell-sync"
|
||||
import { getFreePort } from "./port"
|
||||
import { mangleProxyEnv } from "./proxy-env"
|
||||
import { findMainWebContents } from "./webcontents"
|
||||
import { registerStaticProtocol } from "../common/register-static";
|
||||
import { registerFileProtocol } from "../common/register-protocol";
|
||||
import { clusterStore } from "../common/cluster-store"
|
||||
import { userStore } from "../common/user-store";
|
||||
import { workspaceStore } from "../common/workspace-store";
|
||||
import { tracker } from "../common/tracker";
|
||||
import logger from "./logger"
|
||||
|
||||
if (isDevelopment) {
|
||||
const appName = "LensDev";
|
||||
const appData = app.getPath("appData");
|
||||
app.setName(appName);
|
||||
app.setPath("userData", path.join(appData, appName));
|
||||
}
|
||||
|
||||
mangleProxyEnv()
|
||||
if (app.commandLine.getSwitchValue("proxy-server") !== "") {
|
||||
process.env.HTTPS_PROXY = app.commandLine.getSwitchValue("proxy-server")
|
||||
}
|
||||
|
||||
const promiseIpc = new PromiseIpc({ timeout: 2000 })
|
||||
let windowManager: WindowManager = null;
|
||||
let clusterManager: ClusterManager = null;
|
||||
let proxyServer: proxy.LensProxy = null;
|
||||
@ -45,24 +31,30 @@ const vmURL = formatUrl({
|
||||
slashes: true,
|
||||
})
|
||||
|
||||
async function main() {
|
||||
shellSync(app.getLocale())
|
||||
mangleProxyEnv()
|
||||
if (app.commandLine.getSwitchValue("proxy-server") !== "") {
|
||||
process.env.HTTPS_PROXY = app.commandLine.getSwitchValue("proxy-server")
|
||||
}
|
||||
|
||||
async function main() {
|
||||
shellSync(app.getLocale());
|
||||
|
||||
// todo: check other usages .getPath("userData") and enable "lazy-evaluation"
|
||||
const workingDir = path.join(app.getPath("appData"), appName);
|
||||
app.setName(appName);
|
||||
app.setPath("userData", workingDir);
|
||||
logger.info(`Start app from "${workingDir}"`)
|
||||
|
||||
tracker.event("app", "start");
|
||||
const updater = new AppUpdater()
|
||||
updater.start();
|
||||
|
||||
tracker.event("app", "start");
|
||||
initMenu();
|
||||
registerFileProtocol(appProto, app.getPath("userData"));
|
||||
registerFileProtocol(staticProto, staticDir);
|
||||
|
||||
registerStaticProtocol();
|
||||
protocol.registerFileProtocol('store', (request, callback) => {
|
||||
const url = request.url.substr(8)
|
||||
callback(path.normalize(`${app.getPath("userData")}/${url}`))
|
||||
}, (error) => {
|
||||
if (error) console.error('Failed to register protocol')
|
||||
})
|
||||
|
||||
let port: number = null
|
||||
// find free port
|
||||
let port: number
|
||||
try {
|
||||
port = await getFreePort()
|
||||
} catch (error) {
|
||||
@ -71,10 +63,11 @@ async function main() {
|
||||
app.quit();
|
||||
}
|
||||
|
||||
// preload required stores
|
||||
// preload configuration from stores
|
||||
await Promise.all([
|
||||
userStore.load(),
|
||||
clusterStore.load(),
|
||||
workspaceStore.load(),
|
||||
]);
|
||||
|
||||
// create cluster manager
|
||||
@ -89,39 +82,9 @@ async function main() {
|
||||
app.quit();
|
||||
}
|
||||
|
||||
// boot windowmanager
|
||||
// manage lens windows
|
||||
windowManager = new WindowManager();
|
||||
windowManager.showMain(vmURL)
|
||||
|
||||
initMenu({
|
||||
logoutHook: async () => {
|
||||
// IPC send needs webContents as we're sending it to renderer
|
||||
promiseIpc.send('logout', findMainWebContents(), {}).then((data: any) => {
|
||||
logger.debug("logout IPC sent");
|
||||
})
|
||||
},
|
||||
showPreferencesHook: async () => {
|
||||
// IPC send needs webContents as we're sending it to renderer
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: 'preferences-page' }).then((data: any) => {
|
||||
logger.debug("navigate: preferences IPC sent");
|
||||
})
|
||||
},
|
||||
addClusterHook: async () => {
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: "add-cluster-page" }).then((data: any) => {
|
||||
logger.debug("navigate: add-cluster-page IPC sent");
|
||||
})
|
||||
},
|
||||
showWhatsNewHook: async () => {
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: "whats-new-page" }).then((data: any) => {
|
||||
logger.debug("navigate: whats-new-page IPC sent");
|
||||
})
|
||||
},
|
||||
clusterSettingsHook: async () => {
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: "cluster-settings-page" }).then((data: any) => {
|
||||
logger.debug("navigate: cluster-settings-page IPC sent");
|
||||
})
|
||||
},
|
||||
}, promiseIpc)
|
||||
}
|
||||
|
||||
app.on("ready", main)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { PromiseIpc } from "electron-promise-ipc";
|
||||
import { app, BrowserWindow, dialog, Menu, MenuItem, MenuItemConstructorOptions, shell, webContents } from "electron"
|
||||
import { isDevelopment, isMac, issuesTrackerUrl, isWindows, slackUrl } from "../common/vars";
|
||||
import { isMac, issuesTrackerUrl, isWindows, slackUrl } from "../common/vars";
|
||||
|
||||
// todo: refactor + split menu sections to separated files, e.g. menus/file.menu.ts
|
||||
|
||||
@ -38,10 +39,8 @@ function showAbout(_menuitem: MenuItem, browserWindow: BrowserWindow) {
|
||||
/**
|
||||
* Constructs the menu based on the example at: https://electronjs.org/docs/api/menu#main-process
|
||||
* Menu items are constructed piece-by-piece to have slightly better control on individual sub-menus
|
||||
*
|
||||
* @param ipc the main promiceIpc handle. Needed to be able to hook IPC sending into logout click handler.
|
||||
*/
|
||||
export default function initMenu(opts: MenuOptions, promiseIpc: any) {
|
||||
export default function initMenu(opts: Partial<MenuOptions> = {}) {
|
||||
const mt: MenuItemConstructorOptions[] = [];
|
||||
const macAppMenu: MenuItemConstructorOptions = {
|
||||
label: app.getName(),
|
||||
@ -199,6 +198,8 @@ export default function initMenu(opts: MenuOptions, promiseIpc: any) {
|
||||
const menu = Menu.buildFromTemplate(mt);
|
||||
Menu.setApplicationMenu(menu);
|
||||
|
||||
const promiseIpc = new PromiseIpc({ timeout: 2000 })
|
||||
|
||||
promiseIpc.on("enableClusterSettingsMenuItem", (clusterId: string) => {
|
||||
setClusterSettingsEnabled(true)
|
||||
});
|
||||
|
||||
@ -1,17 +1,13 @@
|
||||
import { BrowserWindow, shell } from "electron"
|
||||
import { PromiseIpc } from "electron-promise-ipc"
|
||||
import windowStateKeeper from "electron-window-state"
|
||||
import { getStaticUrl } from "../common/register-static";
|
||||
import { tracker } from "../common/tracker";
|
||||
|
||||
export class WindowManager {
|
||||
public mainWindow: BrowserWindow = null;
|
||||
public splashWindow: BrowserWindow = null;
|
||||
protected promiseIpc: any
|
||||
protected windowState: windowStateKeeper.State;
|
||||
|
||||
constructor({ showSplash = true } = {}) {
|
||||
this.promiseIpc = new PromiseIpc({ timeout: 2000 })
|
||||
// Manage main window size&position with persistence
|
||||
this.windowState = windowStateKeeper({
|
||||
defaultHeight: 900,
|
||||
@ -31,7 +27,7 @@ export class WindowManager {
|
||||
}
|
||||
})
|
||||
if (showSplash) {
|
||||
this.splashWindow.loadURL(getStaticUrl("splash.html"))
|
||||
this.splashWindow.loadURL("static://splash.html")
|
||||
this.splashWindow.show()
|
||||
}
|
||||
|
||||
|
||||
@ -29,14 +29,14 @@
|
||||
<script>
|
||||
import marked from 'marked'
|
||||
import {readFileSync} from 'fs'
|
||||
import { getStaticPath } from "../../../common/register-static"
|
||||
import { userStore } from "../../../common/user-store"
|
||||
|
||||
export default {
|
||||
name: 'WhatsNewPage',
|
||||
data() {
|
||||
let releaseNotes = getStaticPath("RELEASE_NOTES.md");
|
||||
let content = marked(readFileSync(releaseNotes, 'utf8'));
|
||||
// todo: check if "fs" can work with custom protocols
|
||||
let fileContents = readFileSync("static://RELEASE_NOTES.md", 'utf8');
|
||||
let content = marked(fileContents);
|
||||
return {
|
||||
error: "",
|
||||
content: content,
|
||||
|
||||
@ -2,14 +2,14 @@
|
||||
@import "fonts";
|
||||
|
||||
*, *:before, *:after {
|
||||
@include set-draggable(false);
|
||||
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
outline: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-user-drag: none;
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
::selection {
|
||||
@ -167,14 +167,6 @@ a {
|
||||
}
|
||||
}
|
||||
|
||||
.drag {
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
|
||||
.nodrag {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
// app's common loading indicator, displaying on the route transitions
|
||||
#loading {
|
||||
position: absolute;
|
||||
|
||||
@ -89,3 +89,13 @@
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@mixin set-draggable($isDraggable: true) {
|
||||
@if ($isDraggable) {
|
||||
-webkit-user-drag: auto;
|
||||
-webkit-app-region: drag;
|
||||
} @else {
|
||||
-webkit-user-drag: none;
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
import "../../common/system-ca"
|
||||
import { userStore } from "../common/user-store";
|
||||
import { workspaceStore } from "../common/workspace-store";
|
||||
import { clusterStore } from "../common/cluster-store";
|
||||
// import { App } from "./components/app";
|
||||
|
||||
await Promise.all([
|
||||
userStore.whenLoaded,
|
||||
workspaceStore.whenLoaded,
|
||||
clusterStore.whenLoaded,
|
||||
]);
|
||||
|
||||
// App.init();
|
||||
document.getElementById("app").innerHTML = "<p>Hello from renderer!</p>"
|
||||
19
src/renderer/index.tsx
Normal file
19
src/renderer/index.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import "../common/system-ca"
|
||||
import { userStore } from "../common/user-store";
|
||||
import { workspaceStore } from "../common/workspace-store";
|
||||
import { clusterStore } from "../common/cluster-store";
|
||||
// import { App } from "./components/app";
|
||||
|
||||
async function render() {
|
||||
await Promise.all([
|
||||
userStore.whenLoaded,
|
||||
workspaceStore.whenLoaded,
|
||||
clusterStore.whenLoaded,
|
||||
]);
|
||||
|
||||
// App.init();
|
||||
document.getElementById("app").innerHTML = "<p>Hello from renderer!</p>"
|
||||
}
|
||||
|
||||
// run
|
||||
render();
|
||||
@ -10,7 +10,7 @@ import CircularDependencyPlugin from "circular-dependency-plugin"
|
||||
export default function (): webpack.Configuration {
|
||||
return {
|
||||
context: __dirname,
|
||||
target: "web",
|
||||
target: "electron-renderer",
|
||||
devtool: "source-map", // todo: optimize in dev-mode with webpack.SourceMapDevToolPlugin
|
||||
mode: isProduction ? "production" : "development",
|
||||
cache: isDevelopment,
|
||||
@ -47,6 +47,10 @@ export default function (): webpack.Configuration {
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.node$/,
|
||||
use: "node-loader"
|
||||
},
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
exclude: /node_modules/,
|
||||
|
||||
187
yarn.lock
187
yarn.lock
@ -1914,11 +1914,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.24.tgz#c57511e3a19c4b5e9692bb2995c40a3a52167944"
|
||||
integrity sha512-5SCfvCxV74kzR3uWgTYiGxrd69TbT1I6+cMx1A5kEly/IVveJBimtAMlXiEyVFn5DvUFewQWxOOiJhlxeQwxgA==
|
||||
|
||||
"@types/node@^10.12.18":
|
||||
version "10.17.26"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.26.tgz#a8a119960bff16b823be4c617da028570779bcfd"
|
||||
integrity sha512-myMwkO2Cr82kirHY8uknNRHEVtn0wV3DTQfkrjx17jmkstDRZ24gNUdl8AHXVyVclTYI/bNjgTPTAWvWLqXqkw==
|
||||
|
||||
"@types/node@^12.0.12":
|
||||
version "12.12.44"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.44.tgz#0d400a1453adcb359b133acceae4dd8bb0e0a159"
|
||||
@ -3396,7 +3391,7 @@ caseless@~0.12.0:
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
|
||||
|
||||
chalk@2.4.2, chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
|
||||
chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
@ -3590,7 +3585,7 @@ cli-cursor@^3.1.0:
|
||||
dependencies:
|
||||
restore-cursor "^3.1.0"
|
||||
|
||||
cli-spinners@^2.2.0:
|
||||
cli-spinners@^2.0.0, cli-spinners@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.3.0.tgz#0632239a4b5aa4c958610142c34bb7a651fc8df5"
|
||||
integrity sha512-Xs2Hf2nzrvJMFKimOR7YR0QwZ8fc0u98kdtwN1eNAZzNQgH3vK2pXzff6GJtKh7S5hoJ87ECiAiZFS2fb5Ii2w==
|
||||
@ -3732,7 +3727,7 @@ colors@1.0.3:
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
|
||||
integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=
|
||||
|
||||
colors@^1.2.1:
|
||||
colors@^1.2.1, colors@^1.3.3:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
||||
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
|
||||
@ -4170,7 +4165,7 @@ debug@4.1.0:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
|
||||
debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.5.1, debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
@ -4309,6 +4304,11 @@ detect-file@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
|
||||
integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
|
||||
|
||||
detect-libc@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
|
||||
|
||||
detect-newline@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
|
||||
@ -4537,7 +4537,7 @@ electron-chromedriver@^6.0.0:
|
||||
electron-download "^4.1.1"
|
||||
extract-zip "^1.6.7"
|
||||
|
||||
electron-download@^4.1.0, electron-download@^4.1.1:
|
||||
electron-download@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8"
|
||||
integrity sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg==
|
||||
@ -4584,6 +4584,21 @@ electron-publish@22.7.0:
|
||||
lazy-val "^1.0.4"
|
||||
mime "^2.4.5"
|
||||
|
||||
electron-rebuild@^1.11.0:
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-rebuild/-/electron-rebuild-1.11.0.tgz#e384773a9ad30fe0a6a5bbb326b779d51f668b6a"
|
||||
integrity sha512-cn6AqZBQBVtaEyj5jZW1/LOezZZ22PA1HvhEP7asvYPJ8PDF4i4UFt9be4i9T7xJKiSiomXvY5Fd+dSq3FXZxA==
|
||||
dependencies:
|
||||
colors "^1.3.3"
|
||||
debug "^4.1.1"
|
||||
detect-libc "^1.0.3"
|
||||
fs-extra "^8.1.0"
|
||||
node-abi "^2.11.0"
|
||||
node-gyp "^6.0.1"
|
||||
ora "^3.4.0"
|
||||
spawn-rx "^3.0.0"
|
||||
yargs "^14.2.0"
|
||||
|
||||
electron-to-chromium@^1.3.413:
|
||||
version "1.3.464"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.464.tgz#fe13feaa08f6f865d3c89d5d72e54c194f463aa5"
|
||||
@ -4619,13 +4634,13 @@ electron@*:
|
||||
"@types/node" "^12.0.12"
|
||||
extract-zip "^1.0.3"
|
||||
|
||||
electron@^6.1.12:
|
||||
version "6.1.12"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-6.1.12.tgz#a7aee6dfa75b57f32b3645ef8e14dcef6d5f31a9"
|
||||
integrity sha512-RUPM8xJfTcm53V9EKMBhvpLu1+CQkmuvWDmVCypR5XbUG1OOrOLiKl0CqUZ9+tEDuOmC+DmzmJP2MZXScBU5IA==
|
||||
electron@^7.3.2:
|
||||
version "7.3.2"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-7.3.2.tgz#184b69fe9089693e179b3b34effa975dfc8e505d"
|
||||
integrity sha512-5uSWVfCJogiPiU0G+RKi4ECnNs0gPNjAwYVE9KR7RXaOJYcpNIC5RFejaaUnuRoBssJ5B1n/5WU6wDUxvPajWQ==
|
||||
dependencies:
|
||||
"@types/node" "^10.12.18"
|
||||
electron-download "^4.1.0"
|
||||
"@electron/get" "^1.0.1"
|
||||
"@types/node" "^12.0.12"
|
||||
extract-zip "^1.0.3"
|
||||
|
||||
elliptic@^6.0.0, elliptic@^6.5.2:
|
||||
@ -5412,6 +5427,13 @@ fs-extra@^9.0.0, fs-extra@^9.0.1:
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^1.0.0"
|
||||
|
||||
fs-minipass@^1.2.5:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
|
||||
integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
|
||||
dependencies:
|
||||
minipass "^2.6.0"
|
||||
|
||||
fs-minipass@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||
@ -5710,7 +5732,7 @@ got@^9.6.0:
|
||||
to-readable-stream "^1.0.0"
|
||||
url-parse-lax "^3.0.0"
|
||||
|
||||
graceful-fs@^4.1.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
|
||||
graceful-fs@^4.1.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
|
||||
@ -7458,6 +7480,11 @@ locate-path@^5.0.0:
|
||||
dependencies:
|
||||
p-locate "^4.1.0"
|
||||
|
||||
lodash.assign@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
|
||||
integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=
|
||||
|
||||
lodash.isequal@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||
@ -7478,6 +7505,13 @@ lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.1
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
|
||||
log-symbols@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
|
||||
integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
|
||||
dependencies:
|
||||
chalk "^2.0.1"
|
||||
|
||||
log-symbols@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4"
|
||||
@ -7855,6 +7889,14 @@ minipass-pipeline@^1.2.2:
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
|
||||
integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
|
||||
dependencies:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.0"
|
||||
|
||||
minipass@^3.0.0, minipass@^3.1.1:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
|
||||
@ -7862,6 +7904,13 @@ minipass@^3.0.0, minipass@^3.1.1:
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minizlib@^1.2.1:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
|
||||
integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
|
||||
dependencies:
|
||||
minipass "^2.9.0"
|
||||
|
||||
minizlib@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3"
|
||||
@ -8019,6 +8068,13 @@ no-case@^3.0.3:
|
||||
lower-case "^2.0.1"
|
||||
tslib "^1.10.0"
|
||||
|
||||
node-abi@^2.11.0:
|
||||
version "2.18.0"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.18.0.tgz#1f5486cfd7d38bd4f5392fa44a4ad4d9a0dffbf4"
|
||||
integrity sha512-yi05ZoiuNNEbyT/xXfSySZE+yVnQW6fxPZuFbLyS1s6b5Kw3HzV2PHOM4XR+nsjzkHxByK+2Wg+yCQbe35l8dw==
|
||||
dependencies:
|
||||
semver "^5.4.1"
|
||||
|
||||
node-forge@^0.7.5:
|
||||
version "0.7.6"
|
||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac"
|
||||
@ -8047,6 +8103,23 @@ node-gyp@^3.8.0:
|
||||
tar "^2.0.0"
|
||||
which "1"
|
||||
|
||||
node-gyp@^6.0.1:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-6.1.0.tgz#64e31c61a4695ad304c1d5b82cf6b7c79cc79f3f"
|
||||
integrity sha512-h4A2zDlOujeeaaTx06r4Vy+8MZ1679lU+wbCKDS4ZtvY2A37DESo37oejIw0mtmR3+rvNwts5B6Kpt1KrNYdNw==
|
||||
dependencies:
|
||||
env-paths "^2.2.0"
|
||||
glob "^7.1.4"
|
||||
graceful-fs "^4.2.2"
|
||||
mkdirp "^0.5.1"
|
||||
nopt "^4.0.1"
|
||||
npmlog "^4.1.2"
|
||||
request "^2.88.0"
|
||||
rimraf "^2.6.3"
|
||||
semver "^5.7.1"
|
||||
tar "^4.4.12"
|
||||
which "^1.3.1"
|
||||
|
||||
node-int64@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
||||
@ -8182,6 +8255,14 @@ nodemon@^2.0.4:
|
||||
dependencies:
|
||||
abbrev "1"
|
||||
|
||||
nopt@^4.0.1:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
|
||||
integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==
|
||||
dependencies:
|
||||
abbrev "1"
|
||||
osenv "^0.1.4"
|
||||
|
||||
nopt@~1.0.10:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
|
||||
@ -8262,7 +8343,7 @@ npm-run-path@^4.0.0:
|
||||
dependencies:
|
||||
path-key "^3.0.0"
|
||||
|
||||
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0:
|
||||
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
|
||||
@ -8485,6 +8566,18 @@ optionator@^0.9.1:
|
||||
type-check "^0.4.0"
|
||||
word-wrap "^1.2.3"
|
||||
|
||||
ora@^3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318"
|
||||
integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
cli-cursor "^2.1.0"
|
||||
cli-spinners "^2.0.0"
|
||||
log-symbols "^2.2.0"
|
||||
strip-ansi "^5.2.0"
|
||||
wcwidth "^1.0.1"
|
||||
|
||||
ora@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.4.tgz#e8da697cc5b6a47266655bf68e0fb588d29a545d"
|
||||
@ -8523,7 +8616,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
||||
|
||||
osenv@0:
|
||||
osenv@0, osenv@^0.1.4:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
|
||||
integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
|
||||
@ -9859,6 +9952,13 @@ rx-lite@*, rx-lite@^4.0.8:
|
||||
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
|
||||
integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=
|
||||
|
||||
rxjs@^6.3.1:
|
||||
version "6.6.0"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.0.tgz#af2901eedf02e3a83ffa7f886240ff9018bbec84"
|
||||
integrity sha512-3HMA8z/Oz61DUHe+SdOiQyzIf4tOx5oQHmMir7IZEu6TMqCLHT4LRcmNaUS0NwOz8VLvmmBduMsoaUvMaIiqzg==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
rxjs@^6.5.2, rxjs@^6.5.3:
|
||||
version "6.5.5"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec"
|
||||
@ -10265,6 +10365,15 @@ spawn-command@^0.0.2-1:
|
||||
resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
|
||||
integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=
|
||||
|
||||
spawn-rx@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/spawn-rx/-/spawn-rx-3.0.0.tgz#1d33511e13ec26337da51d78630e08beb57a6767"
|
||||
integrity sha512-dw4Ryg/KMNfkKa5ezAR5aZe9wNwPdKlnHEXtHOjVnyEDSPQyOpIPPRtcIiu7127SmtHhaCjw21yC43HliW0iIg==
|
||||
dependencies:
|
||||
debug "^2.5.1"
|
||||
lodash.assign "^4.2.0"
|
||||
rxjs "^6.3.1"
|
||||
|
||||
spdx-correct@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
|
||||
@ -10716,6 +10825,19 @@ tar@^2.0.0:
|
||||
fstream "^1.0.12"
|
||||
inherits "2"
|
||||
|
||||
tar@^4.4.12:
|
||||
version "4.4.13"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
|
||||
integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
|
||||
dependencies:
|
||||
chownr "^1.1.1"
|
||||
fs-minipass "^1.2.5"
|
||||
minipass "^2.8.6"
|
||||
minizlib "^1.2.1"
|
||||
mkdirp "^0.5.0"
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.3"
|
||||
|
||||
tar@^6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39"
|
||||
@ -11791,7 +11913,7 @@ yallist@^2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
|
||||
integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
|
||||
|
||||
yallist@^3.0.2:
|
||||
yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||
@ -11822,6 +11944,14 @@ yargs-parser@^13.1.0, yargs-parser@^13.1.2:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
||||
yargs-parser@^15.0.1:
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.1.tgz#54786af40b820dcb2fb8025b11b4d659d76323b3"
|
||||
integrity sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==
|
||||
dependencies:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
||||
yargs@13.2.4:
|
||||
version "13.2.4"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83"
|
||||
@ -11855,6 +11985,23 @@ yargs@^13.3.0, yargs@^13.3.2:
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^13.1.2"
|
||||
|
||||
yargs@^14.2.0:
|
||||
version "14.2.3"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414"
|
||||
integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==
|
||||
dependencies:
|
||||
cliui "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
find-up "^3.0.0"
|
||||
get-caller-file "^2.0.1"
|
||||
require-directory "^2.1.1"
|
||||
require-main-filename "^2.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
string-width "^3.0.0"
|
||||
which-module "^2.0.0"
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^15.0.1"
|
||||
|
||||
yargs@^15.3.1:
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user