mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
tracker / user-store refactoring, part 1
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
c9fb015bcf
commit
4270ec4240
@ -170,9 +170,9 @@
|
||||
"@types/node": "^12.12.45",
|
||||
"@types/proper-lockfile": "^4.1.1",
|
||||
"@types/tar": "^4.0.3",
|
||||
"conf": "^7.0.1",
|
||||
"crypto-js": "^4.0.0",
|
||||
"electron-promise-ipc": "^2.1.0",
|
||||
"electron-store": "^5.2.0",
|
||||
"electron-updater": "^4.3.1",
|
||||
"electron-window-state": "^5.0.3",
|
||||
"filenamify": "^4.1.0",
|
||||
@ -193,6 +193,7 @@
|
||||
"request": "^2.88.2",
|
||||
"request-promise-native": "^1.0.8",
|
||||
"semver": "^7.3.2",
|
||||
"serializr": "^2.0.3",
|
||||
"shell-env": "^3.0.0",
|
||||
"tar": "^6.0.2",
|
||||
"tcp-port-used": "^1.0.1",
|
||||
|
||||
@ -1,32 +1,32 @@
|
||||
import ElectronStore from "electron-store"
|
||||
import { Singleton } from "./utils/singleton";
|
||||
import Config from "conf"
|
||||
import Singleton from "./utils/singleton";
|
||||
import migrations from "../migrations/cluster-store"
|
||||
import { Cluster, ClusterBaseInfo } from "../main/cluster";
|
||||
|
||||
export class ClusterStore extends Singleton {
|
||||
private store = new ElectronStore({
|
||||
name: "lens-cluster-store",
|
||||
private storeConfig = new Config({
|
||||
configName: "lens-cluster-store",
|
||||
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
|
||||
migrations: migrations,
|
||||
})
|
||||
|
||||
public getAllClusterObjects(): Cluster[] {
|
||||
return this.store.get("clusters", []).map((clusterInfo: ClusterBaseInfo) => {
|
||||
return this.storeConfig.get("clusters", []).map((clusterInfo: ClusterBaseInfo) => {
|
||||
return new Cluster(clusterInfo)
|
||||
})
|
||||
}
|
||||
|
||||
public getAllClusters(): ClusterBaseInfo[] {
|
||||
return this.store.get("clusters", [])
|
||||
return this.storeConfig.get("clusters", [])
|
||||
}
|
||||
|
||||
public removeCluster(id: string): void {
|
||||
this.store.delete(id);
|
||||
this.storeConfig.delete(id);
|
||||
const clusterBaseInfos = this.getAllClusters()
|
||||
const index = clusterBaseInfos.findIndex((cbi) => cbi.id === id)
|
||||
if (index !== -1) {
|
||||
clusterBaseInfos.splice(index, 1)
|
||||
this.store.set("clusters", clusterBaseInfos)
|
||||
this.storeConfig.set("clusters", clusterBaseInfos)
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ export class ClusterStore extends Singleton {
|
||||
} else {
|
||||
clusters[index] = storable
|
||||
}
|
||||
this.store.set("clusters", clusters)
|
||||
this.storeConfig.set("clusters", clusters)
|
||||
}
|
||||
|
||||
public storeClusters(clusters: ClusterBaseInfo[]) {
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import request from "request"
|
||||
import { userStore } from "./user-store"
|
||||
|
||||
export function globalRequestOpts(requestOpts: request.Options ) {
|
||||
const userPrefs = userStore.getPreferences()
|
||||
if (userPrefs.httpsProxy) {
|
||||
requestOpts.proxy = userPrefs.httpsProxy
|
||||
export function globalRequestOpts(requestOpts: request.Options) {
|
||||
const { httpsProxy, allowUntrustedCAs } = userStore.preferences
|
||||
if (httpsProxy) {
|
||||
requestOpts.proxy = httpsProxy
|
||||
}
|
||||
requestOpts.rejectUnauthorized = !userPrefs.allowUntrustedCAs;
|
||||
|
||||
requestOpts.rejectUnauthorized = !allowUntrustedCAs;
|
||||
return requestOpts
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { app, App, remote } from "electron"
|
||||
import ua from "universal-analytics"
|
||||
import { machineIdSync } from "node-machine-id"
|
||||
import Singleton from "./utils/singleton";
|
||||
import { userStore } from "./user-store"
|
||||
|
||||
const GA_ID = "UA-159377374-1"
|
||||
export class Tracker extends Singleton {
|
||||
static readonly GA_ID = "UA-159377374-1"
|
||||
|
||||
export class Tracker {
|
||||
protected visitor: ua.Visitor
|
||||
protected machineId: string = null;
|
||||
protected ip: string = null;
|
||||
@ -12,31 +14,35 @@ export class Tracker {
|
||||
protected locale: string;
|
||||
protected electronUA: string;
|
||||
|
||||
constructor(app: Electron.App) {
|
||||
private constructor(app: App) {
|
||||
super();
|
||||
try {
|
||||
this.visitor = ua(GA_ID, machineIdSync(), {strictCidFormat: false})
|
||||
this.visitor = ua(Tracker.GA_ID, machineIdSync(), { strictCidFormat: false })
|
||||
} catch (error) {
|
||||
this.visitor = ua(GA_ID)
|
||||
this.visitor = ua(Tracker.GA_ID)
|
||||
}
|
||||
this.visitor.set("dl", "https://lensapptelemetry.lakendlabs.com")
|
||||
}
|
||||
|
||||
public async event(eventCategory: string, eventAction: string) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (!this.telemetryAllowed()) {
|
||||
resolve()
|
||||
return
|
||||
protected async isTelemetryAllowed(): Promise<boolean> {
|
||||
return userStore.preferences.allowTelemetry;
|
||||
}
|
||||
|
||||
async event(eventCategory: string, eventAction: string, otherParams = {}) {
|
||||
try {
|
||||
const allowed = await this.isTelemetryAllowed();
|
||||
if (!allowed) {
|
||||
return;
|
||||
}
|
||||
this.visitor.event({
|
||||
ec: eventCategory,
|
||||
ea: eventAction
|
||||
ea: eventAction,
|
||||
...otherParams,
|
||||
}).send()
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
protected telemetryAllowed() {
|
||||
const userPrefs = userStore.getPreferences()
|
||||
return !!userPrefs.allowTelemetry
|
||||
} catch (err) {
|
||||
console.error(`Failed to track "${eventCategory}:${eventAction}"`, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const tracker: Tracker = Tracker.getInstance(app || remote.app);
|
||||
|
||||
@ -1,59 +1,105 @@
|
||||
import ElectronStore from "electron-store"
|
||||
import { app, remote } from "electron"
|
||||
import { computed, observable, reaction, toJS } from "mobx";
|
||||
import Config from "conf"
|
||||
import semver from "semver"
|
||||
import migrations from "../migrations/user-store"
|
||||
import { Singleton } from "./utils/singleton";
|
||||
import Singleton from "./utils/singleton";
|
||||
import { getAppVersion } from "./utils/app-version";
|
||||
import { tracker } from "./tracker";
|
||||
|
||||
export interface UserStoreModel {
|
||||
lastSeenAppVersion: string;
|
||||
seenContexts: string[];
|
||||
preferences: UserPreferences;
|
||||
}
|
||||
|
||||
export interface UserPreferences {
|
||||
httpsProxy?: string;
|
||||
colorTheme?: string;
|
||||
colorTheme?: string | "dark";
|
||||
allowUntrustedCAs?: boolean;
|
||||
allowTelemetry?: boolean;
|
||||
downloadMirror?: string;
|
||||
downloadMirror?: string | "default";
|
||||
}
|
||||
|
||||
export class UserStore extends Singleton {
|
||||
protected store = new ElectronStore({
|
||||
name: "lens-user-store",
|
||||
migrations: migrations,
|
||||
});
|
||||
private storeConfig: Config<UserStoreModel>;
|
||||
|
||||
public lastSeenAppVersion() {
|
||||
return this.store.get('lastSeenAppVersion', "0.0.0")
|
||||
@observable isReady = false;
|
||||
@observable lastSeenAppVersion = "0.0.0"
|
||||
@observable seenContexts = observable.set();
|
||||
|
||||
@observable preferences: UserPreferences = {
|
||||
allowTelemetry: true,
|
||||
colorTheme: "dark",
|
||||
downloadMirror: "default",
|
||||
};
|
||||
|
||||
@computed get hasNewAppVersion() {
|
||||
return semver.gt(getAppVersion(), this.lastSeenAppVersion);
|
||||
}
|
||||
|
||||
public setLastSeenAppVersion(version: string) {
|
||||
this.store.set('lastSeenAppVersion', version)
|
||||
private constructor() {
|
||||
super();
|
||||
this.init();
|
||||
}
|
||||
|
||||
public getSeenContexts(): Array<string> {
|
||||
return this.store.get("seenContexts", [])
|
||||
async init() {
|
||||
/*await*/ this.load();
|
||||
this.bindEvents();
|
||||
this.isReady = true;
|
||||
}
|
||||
|
||||
public storeSeenContext(newContexts: string[]) {
|
||||
const seenContexts = this.getSeenContexts().concat(newContexts)
|
||||
// store unique contexts by casting array to set first
|
||||
const newContextSet = new Set(seenContexts)
|
||||
const allContexts = [...newContextSet]
|
||||
this.store.set("seenContexts", allContexts)
|
||||
return allContexts
|
||||
saveLastSeenAppVersion() {
|
||||
this.lastSeenAppVersion = getAppVersion();
|
||||
}
|
||||
|
||||
public setPreferences(preferences: UserPreferences) {
|
||||
this.store.set('preferences', preferences)
|
||||
// todo: use "conf" as pseudo-async for more future-proof usages
|
||||
protected async load() {
|
||||
this.storeConfig = new Config<UserStoreModel>({
|
||||
configName: "lens-user-store",
|
||||
migrations: migrations,
|
||||
cwd: (app || remote.app).getPath("userData"),
|
||||
});
|
||||
this.fromStore(this.storeConfig.store);
|
||||
}
|
||||
|
||||
public getPreferences(): UserPreferences {
|
||||
const prefs = this.store.get("preferences", {})
|
||||
if (!prefs.colorTheme) {
|
||||
prefs.colorTheme = "dark"
|
||||
protected bindEvents() {
|
||||
// refresh from file-system updates
|
||||
this.storeConfig.onDidAnyChange((data, oldValue) => {
|
||||
this.fromStore(data);
|
||||
});
|
||||
|
||||
// refresh config file from runtime
|
||||
reaction(() => this.toJSON(), model => {
|
||||
this.storeConfig.store = model;
|
||||
});
|
||||
|
||||
// track telemetry availability
|
||||
reaction(() => this.preferences.allowTelemetry, allowed => {
|
||||
tracker.event("telemetry", allowed ? "enabled" : "disabled");
|
||||
});
|
||||
}
|
||||
|
||||
// todo: use "serializr" ?
|
||||
protected fromStore(data: Partial<UserStoreModel> = {}) {
|
||||
const { lastSeenAppVersion, seenContexts, preferences } = data
|
||||
if (lastSeenAppVersion) {
|
||||
this.lastSeenAppVersion = lastSeenAppVersion;
|
||||
}
|
||||
if (!prefs.downloadMirror) {
|
||||
prefs.downloadMirror = "default"
|
||||
if (seenContexts) {
|
||||
this.seenContexts = observable.set(seenContexts)
|
||||
}
|
||||
if (prefs.allowTelemetry === undefined) {
|
||||
prefs.allowTelemetry = true
|
||||
if (preferences) {
|
||||
Object.assign(this.preferences, preferences);
|
||||
}
|
||||
}
|
||||
|
||||
return prefs
|
||||
protected toJSON(): UserStoreModel {
|
||||
return toJS({
|
||||
lastSeenAppVersion: this.lastSeenAppVersion,
|
||||
seenContexts: Array.from(this.seenContexts),
|
||||
preferences: this.preferences,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
* const usersStore: UsersStore = UsersStore.getInstance();
|
||||
*/
|
||||
|
||||
export class Singleton {
|
||||
// todo: maybe convert to @decorator
|
||||
class Singleton {
|
||||
private static instances = new WeakMap<object, Singleton>();
|
||||
|
||||
// todo: figure out how to infer child class + arguments types
|
||||
@ -21,3 +22,6 @@ export class Singleton {
|
||||
Singleton.instances.delete(this);
|
||||
}
|
||||
}
|
||||
|
||||
export { Singleton }
|
||||
export default Singleton;
|
||||
@ -1,30 +1,26 @@
|
||||
import ElectronStore from "electron-store"
|
||||
import { Singleton } from "./utils/singleton";
|
||||
import Config from "conf"
|
||||
import Singleton from "./utils/singleton";
|
||||
import { clusterStore } from "./cluster-store"
|
||||
import { getAppVersion } from "./utils/app-version";
|
||||
|
||||
export type WorkspaceId = string;
|
||||
|
||||
export interface WorkspaceData {
|
||||
export interface WorkspaceStoreModel {
|
||||
workspaces: Workspace[]
|
||||
}
|
||||
|
||||
export interface Workspace {
|
||||
id: WorkspaceId;
|
||||
name: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export class Workspace implements WorkspaceData {
|
||||
public id: string
|
||||
public name: string
|
||||
public description?: string
|
||||
|
||||
public constructor(data: WorkspaceData) {
|
||||
Object.assign(this, data)
|
||||
}
|
||||
}
|
||||
|
||||
export class WorkspaceStore extends Singleton {
|
||||
static defaultId = "default"
|
||||
static readonly defaultId = "default"
|
||||
|
||||
private store = new ElectronStore({
|
||||
name: "lens-workspace-store"
|
||||
private storeConfig = new Config<WorkspaceStoreModel>({
|
||||
configName: "lens-workspace-store",
|
||||
projectVersion: getAppVersion(),
|
||||
});
|
||||
|
||||
private constructor() {
|
||||
@ -46,11 +42,10 @@ export class WorkspaceStore extends Singleton {
|
||||
}
|
||||
|
||||
public getAllWorkspaces(): Workspace[] {
|
||||
const workspacesData: WorkspaceData[] = this.store.get("workspaces", [])
|
||||
return workspacesData.map((wsd) => new Workspace(wsd))
|
||||
return this.storeConfig.get("workspaces", [])
|
||||
}
|
||||
|
||||
public saveWorkspace(workspace: WorkspaceData) {
|
||||
public saveWorkspace(workspace: Workspace) {
|
||||
const workspaces = this.getAllWorkspaces()
|
||||
const index = workspaces.findIndex((w) => w.id === workspace.id)
|
||||
if (index !== -1) {
|
||||
@ -58,7 +53,7 @@ export class WorkspaceStore extends Singleton {
|
||||
} else {
|
||||
workspaces.push(workspace)
|
||||
}
|
||||
this.store.set("workspaces", workspaces)
|
||||
this.storeConfig.set("workspaces", workspaces)
|
||||
}
|
||||
|
||||
public removeWorkspace(workspace: Workspace) {
|
||||
@ -70,7 +65,7 @@ export class WorkspaceStore extends Singleton {
|
||||
if (index !== -1) {
|
||||
clusterStore.removeClustersByWorkspace(workspace.id)
|
||||
workspaces.splice(index, 1)
|
||||
this.store.set("workspaces", workspaces)
|
||||
this.storeConfig.set("workspaces", workspaces)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,6 @@ import initMenu from "./menu"
|
||||
import * as proxy from "./proxy"
|
||||
import { WindowManager } from "./window-manager";
|
||||
import { clusterStore } from "../common/cluster-store"
|
||||
import { tracker } from "./tracker"
|
||||
import { ClusterManager } from "./cluster-manager";
|
||||
import AppUpdater from "./app-updater"
|
||||
import { shellSync } from "./shell-sync"
|
||||
@ -26,6 +25,7 @@ import { getFreePort } from "./port"
|
||||
import { mangleProxyEnv } from "./proxy-env"
|
||||
import { findMainWebContents } from "./webcontents"
|
||||
import { registerStaticProtocol } from "../common/register-static";
|
||||
import { tracker } from "../common/tracker";
|
||||
|
||||
mangleProxyEnv()
|
||||
if (app.commandLine.getSwitchValue("proxy-server") !== "") {
|
||||
|
||||
@ -285,7 +285,7 @@ export class Kubectl {
|
||||
}
|
||||
|
||||
protected getDownloadMirror() {
|
||||
const mirror = packageMirrors.get(userStore.getPreferences().downloadMirror)
|
||||
const mirror = packageMirrors.get(userStore.preferences.downloadMirror)
|
||||
if (mirror) {
|
||||
return mirror
|
||||
}
|
||||
|
||||
@ -1,19 +1,7 @@
|
||||
import packageInfo from "../../package.json"
|
||||
import { bundledKubectl, Kubectl } from "../../src/main/kubectl";
|
||||
import { UserStore } from "../common/user-store";
|
||||
|
||||
jest.mock("../common/user-store", () => {
|
||||
const userStoreMock: Partial<UserStore> = {
|
||||
getPreferences() {
|
||||
return {
|
||||
downloadMirror: "default"
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
userStore: userStoreMock,
|
||||
}
|
||||
})
|
||||
jest.mock("../common/user-store");
|
||||
|
||||
describe("kubectlVersion", () => {
|
||||
it("returns bundled version if exactly same version used", async () => {
|
||||
|
||||
@ -3,10 +3,10 @@ import * as pty from "node-pty"
|
||||
import { ShellSession } from "./shell-session";
|
||||
import { v4 as uuid } from "uuid"
|
||||
import * as k8s from "@kubernetes/client-node"
|
||||
import { KubeConfig } from "@kubernetes/client-node"
|
||||
import { Cluster } from "./cluster"
|
||||
import logger from "./logger";
|
||||
import { KubeConfig, V1Pod } from "@kubernetes/client-node";
|
||||
import { tracker } from "./tracker"
|
||||
import { Cluster, ClusterPreferences } from "./cluster"
|
||||
import { tracker } from "../common/tracker";
|
||||
|
||||
export class NodeShellSession extends ShellSession {
|
||||
protected nodeName: string;
|
||||
@ -107,7 +107,7 @@ export class NodeShellSession extends ShellSession {
|
||||
const watch = new k8s.Watch(kc);
|
||||
|
||||
const req = await watch.watch(`/api/v1/namespaces/kube-system/pods`, {},
|
||||
// callback is called for each received object.
|
||||
// callback is called for each received object.
|
||||
(_type, obj) => {
|
||||
if (obj.metadata.name == podId && obj.status.phase === "Running") {
|
||||
resolve(true)
|
||||
@ -119,9 +119,13 @@ export class NodeShellSession extends ShellSession {
|
||||
reject(false)
|
||||
}
|
||||
);
|
||||
setTimeout(() => { req.abort(); reject(false); }, 120 * 1000);
|
||||
setTimeout(() => {
|
||||
req.abort();
|
||||
reject(false);
|
||||
}, 120 * 1000);
|
||||
})
|
||||
}
|
||||
|
||||
protected deleteNodeShellPod() {
|
||||
const kc = this.getKubeConfig();
|
||||
const k8sApi = kc.makeApiClient(k8s.CoreV1Api);
|
||||
@ -130,12 +134,11 @@ export class NodeShellSession extends ShellSession {
|
||||
}
|
||||
|
||||
export async function open(socket: WebSocket, pathToKubeconfig: string, cluster: Cluster, nodeName?: string): Promise<ShellSession> {
|
||||
return new Promise(async(resolve, reject) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let shell = null
|
||||
if (nodeName) {
|
||||
shell = new NodeShellSession(socket, pathToKubeconfig, cluster, nodeName)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
shell = new ShellSession(socket, pathToKubeconfig, cluster)
|
||||
}
|
||||
shell.open()
|
||||
|
||||
@ -5,7 +5,7 @@ import path from "path";
|
||||
import * as tempy from "tempy";
|
||||
import logger from "./logger"
|
||||
import { Cluster } from "./cluster";
|
||||
import { tracker } from "./tracker";
|
||||
import { tracker } from "../common/tracker";
|
||||
|
||||
type KubeObject = {
|
||||
status: {};
|
||||
|
||||
@ -94,7 +94,7 @@ class ConfigRoute extends LensApi {
|
||||
const data: IConfigRoutePayload = {
|
||||
clusterName: cluster.contextName,
|
||||
lensVersion: app.getVersion(),
|
||||
lensTheme: `kontena-${userStore.getPreferences().colorTheme}`,
|
||||
lensTheme: `kontena-${userStore.preferences.colorTheme}`,
|
||||
kubeVersion: cluster.version,
|
||||
chartsEnabled: true,
|
||||
isClusterAdmin: cluster.isAdmin,
|
||||
|
||||
@ -5,10 +5,10 @@ import path from "path"
|
||||
import shellEnv from "shell-env"
|
||||
import { app } from "electron"
|
||||
import { Kubectl } from "./kubectl"
|
||||
import { tracker } from "./tracker"
|
||||
import { Cluster, ClusterPreferences } from "./cluster"
|
||||
import { helmCli } from "./helm-cli"
|
||||
import { isWindows } from "../common/vars";
|
||||
import { tracker } from "../common/tracker";
|
||||
|
||||
export class ShellSession extends EventEmitter {
|
||||
static shellEnvs: Map<string, any> = new Map()
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
import { Tracker } from "../common/tracker"
|
||||
import { app, remote } from "electron"
|
||||
|
||||
export const tracker = new Tracker(app || remote.app);
|
||||
@ -1,8 +1,8 @@
|
||||
import { BrowserWindow, shell } from "electron"
|
||||
import { PromiseIpc } from "electron-promise-ipc"
|
||||
import windowStateKeeper from "electron-window-state"
|
||||
import { tracker } from "./tracker";
|
||||
import { getStaticUrl } from "../common/register-static";
|
||||
import { tracker } from "../common/tracker";
|
||||
|
||||
export class WindowManager {
|
||||
public mainWindow: BrowserWindow = null;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import path from "path";
|
||||
import ElectronStore from "electron-store";
|
||||
import Config from "conf";
|
||||
import { isTestEnv } from "../common/vars";
|
||||
|
||||
export interface MigrationOpts {
|
||||
version: string;
|
||||
run(store: ElectronStore, log: (...args: any[]) => void): void;
|
||||
run(storeConfig: Config<any>, log: (...args: any[]) => void): void;
|
||||
}
|
||||
|
||||
function infoLog(...args: any[]) {
|
||||
@ -12,12 +12,12 @@ function infoLog(...args: any[]) {
|
||||
console.log(...args);
|
||||
}
|
||||
|
||||
export function migration({ version, run }: MigrationOpts) {
|
||||
export function migration<S = any>({ version, run }: MigrationOpts) {
|
||||
return {
|
||||
[version]: (store: ElectronStore) => {
|
||||
const storeName = path.dirname(store.path);
|
||||
infoLog(`STORE MIGRATION (${storeName}): ${version}`, );
|
||||
run(store, infoLog);
|
||||
[version]: (storeConfig: Config<S>) => {
|
||||
const storeName = path.dirname(storeConfig.path);
|
||||
infoLog(`STORE MIGRATION (${storeName}): ${version}`,);
|
||||
run(storeConfig, infoLog);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -27,6 +27,8 @@
|
||||
|
||||
<script>
|
||||
import CubeSpinner from "@/_vue/components/CubeSpinner";
|
||||
import { tracker } from "../../../common/tracker"
|
||||
|
||||
export default {
|
||||
name: "ClusterPage",
|
||||
components: {
|
||||
@ -112,7 +114,7 @@ export default {
|
||||
this.lens.webview = webview;
|
||||
}
|
||||
this.$store.dispatch("attachWebview", this.lens);
|
||||
this.$tracker.event("cluster", "open");
|
||||
tracker.event("cluster", "open");
|
||||
},
|
||||
hideLens: function() {
|
||||
this.$store.dispatch("hideWebviews");
|
||||
@ -131,7 +133,7 @@ export default {
|
||||
"accessible": function(newStatus, oldStatus) {
|
||||
console.log("accessible watch, vals:", newStatus, oldStatus);
|
||||
if(newStatus === false) { // accessble == false
|
||||
this.$tracker.event("cluster", "open-failed");
|
||||
tracker.event("cluster", "open-failed");
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@ -2,17 +2,14 @@ import "../../common/system-ca"
|
||||
import "./assets/css/app.scss"
|
||||
import "prismjs";
|
||||
import "prismjs/components/prism-yaml"
|
||||
import { remote } from "electron"
|
||||
import { PromiseIpc } from 'electron-promise-ipc'
|
||||
import Vue from 'vue'
|
||||
import VueElectron from 'vue-electron'
|
||||
import BootstrapVue from 'bootstrap-vue'
|
||||
import { PromiseIpc } from 'electron-promise-ipc'
|
||||
import { Tracker } from "../../common/tracker"
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
|
||||
const tracker = new Tracker(remote.app);
|
||||
const promiseIpc = new PromiseIpc({maxTimeoutMs: 6000});
|
||||
|
||||
promiseIpc.on('navigate', async (view) => {
|
||||
@ -26,7 +23,6 @@ Vue.use(BootstrapVue)
|
||||
Vue.mixin({
|
||||
created: function () {
|
||||
this.$promiseIpc = promiseIpc;
|
||||
this.$tracker = tracker;
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@ -7,18 +7,13 @@ import KubeContexts from './modules/kube-contexts'
|
||||
import Clusters from './modules/clusters'
|
||||
import HelmRepos from './modules/helm-repos'
|
||||
import Workspaces from './modules/workspaces'
|
||||
|
||||
// promise ipc
|
||||
import { tracker } from "../../../common/tracker"
|
||||
import { PromiseIpc } from 'electron-promise-ipc'
|
||||
const promiseIpc = new PromiseIpc( { maxTimeoutMs: 120000 } );
|
||||
|
||||
// tracker
|
||||
import { Tracker } from "../../../common/tracker"
|
||||
import { remote } from "electron"
|
||||
const tracker = new Tracker(remote.app);
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
const promiseIpc = new PromiseIpc( { maxTimeoutMs: 120000 } );
|
||||
|
||||
export default new Vuex.Store({
|
||||
modules: {
|
||||
Clusters,
|
||||
@ -31,29 +26,24 @@ export default new Vuex.Store({
|
||||
hud: {
|
||||
isMenuVisible: true,
|
||||
},
|
||||
seenContexts: userStore.getSeenContexts(),
|
||||
lastSeenAppVersion: userStore.lastSeenAppVersion(),
|
||||
seenContexts: userStore.seenContexts,
|
||||
lastSeenAppVersion: userStore.lastSeenAppVersion,
|
||||
},
|
||||
mutations: {
|
||||
storeSeenContexts(state, context) {
|
||||
const seenContexts = userStore.storeSeenContext(context);
|
||||
state.seenContexts = seenContexts
|
||||
userStore.seenContexts.add(context);
|
||||
state.seenContexts = Array.from(userStore.seenContexts);
|
||||
},
|
||||
updateLastSeenAppVersion(state, appVersion) {
|
||||
state.lastSeenAppVersion = appVersion;
|
||||
userStore.setLastSeenAppVersion(appVersion)
|
||||
userStore.lastSeenAppVersion = appVersion
|
||||
},
|
||||
loadPreferences(state) {
|
||||
this.commit("savePreferences", userStore.getPreferences());
|
||||
this.commit("savePreferences", userStore.preferences);
|
||||
},
|
||||
savePreferences(state, prefs) {
|
||||
if (prefs.allowTelemetry) {
|
||||
tracker.event("telemetry", "enabled")
|
||||
} else {
|
||||
tracker.event("telemetry", "disabled")
|
||||
}
|
||||
state.preferences = prefs;
|
||||
userStore.setPreferences(prefs);
|
||||
userStore.preferences = prefs;
|
||||
this.dispatch("destroyWebviews")
|
||||
promiseIpc.send("preferencesSaved")
|
||||
},
|
||||
@ -67,9 +57,7 @@ export default new Vuex.Store({
|
||||
actions: {
|
||||
async init({commit, getters}) {
|
||||
commit("loadPreferences");
|
||||
|
||||
await this.dispatch('refreshClusters', getters.currentWorkspace);
|
||||
|
||||
return true;
|
||||
},
|
||||
async addSeenContexts({commit}, data){
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
import Vue from "vue"
|
||||
import { ClusterInfo } from "../../../../main/cluster"
|
||||
import { MutationTree, ActionTree, GetterTree } from "vuex"
|
||||
import { ActionTree, GetterTree, MutationTree } from "vuex"
|
||||
import { PromiseIpc } from 'electron-promise-ipc'
|
||||
import { Tracker } from "../../../../common/tracker"
|
||||
import { remote } from "electron"
|
||||
import { clusterStore } from "../../../../common/cluster-store"
|
||||
import { Workspace } from "../../../../common/workspace-store"
|
||||
import { tracker } from "../../../../common/tracker";
|
||||
|
||||
const promiseIpc = new PromiseIpc( { maxTimeoutMs: 120000 } );
|
||||
const tracker = new Tracker(remote.app);
|
||||
const promiseIpc = new PromiseIpc({ maxTimeoutMs: 120000 });
|
||||
|
||||
export interface LensWebview {
|
||||
id: string;
|
||||
@ -26,12 +24,12 @@ const state: ClusterState = {
|
||||
clusters: []
|
||||
}
|
||||
|
||||
const actions: ActionTree<ClusterState, any> = {
|
||||
async refreshClusters({commit}, currentWorkspace: Workspace) {
|
||||
const actions: ActionTree<ClusterState, any> = {
|
||||
async refreshClusters({ commit }, currentWorkspace: Workspace) {
|
||||
const clusters: ClusterInfo[] = await promiseIpc.send('getClusters', currentWorkspace.id).catch((error: Error) => {
|
||||
return false;
|
||||
})
|
||||
if(!clusters) return false;
|
||||
if (!clusters) return false;
|
||||
commit('updateClusters', clusters);
|
||||
clusters.forEach((cluster: ClusterInfo) => {
|
||||
const lens: LensWebview = {
|
||||
@ -43,29 +41,29 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
})
|
||||
return true;
|
||||
},
|
||||
async getCluster({commit, getters}, id: string) {
|
||||
async getCluster({ commit, getters }, id: string) {
|
||||
const cluster: ClusterInfo = getters.clusters.find((c: ClusterInfo) => c.id === id)
|
||||
if(!cluster) return null;
|
||||
if (!cluster) return null;
|
||||
|
||||
const remoteCluster = await promiseIpc.send("getCluster", cluster.id)
|
||||
if(!remoteCluster) return null;
|
||||
if (!remoteCluster) return null;
|
||||
|
||||
Object.assign(cluster, remoteCluster)
|
||||
commit('updateCluster', cluster);
|
||||
|
||||
return cluster;
|
||||
},
|
||||
async refineCluster({commit}, id: string) {
|
||||
async refineCluster({ commit }, id: string) {
|
||||
console.log("VUEX: ACTION: REFINE CLUSTER", id);
|
||||
|
||||
const remoteCluster = await promiseIpc.send("getCluster", id)
|
||||
if(!remoteCluster) return null;
|
||||
if (!remoteCluster) return null;
|
||||
|
||||
commit('updateCluster', remoteCluster);
|
||||
|
||||
return remoteCluster;
|
||||
},
|
||||
async stopCluster({dispatch, getters}, id: string) {
|
||||
async stopCluster({ dispatch, getters }, id: string) {
|
||||
const cluster: ClusterInfo = getters.clusters.find((c: ClusterInfo) => c.id === id)
|
||||
if (!cluster) return;
|
||||
|
||||
@ -76,7 +74,7 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
tracker.event("cluster", "stop")
|
||||
}
|
||||
},
|
||||
async removeCluster({getters, dispatch}, id: string) {
|
||||
async removeCluster({ getters, dispatch }, id: string) {
|
||||
const cluster: ClusterInfo = getters.clusters.find((c: ClusterInfo) => c.id === id)
|
||||
if (!cluster) {
|
||||
return
|
||||
@ -92,16 +90,16 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
await dispatch("refreshClusters", getters.currentWorkspace)
|
||||
return true;
|
||||
},
|
||||
async addCluster({commit, getters, dispatch}, data) {
|
||||
async addCluster({ commit, getters, dispatch }, data) {
|
||||
const res = await promiseIpc.send("addCluster", data)
|
||||
if(!res) return null;
|
||||
if (!res) return null;
|
||||
|
||||
tracker.event("cluster", "add");
|
||||
commit('updateClusters', res.allClusters);
|
||||
await dispatch("refreshClusters", getters.currentWorkspace);
|
||||
return res.addedCluster;
|
||||
},
|
||||
async clearClusters({commit, getters, dispatch}){
|
||||
async clearClusters({ commit, getters, dispatch }) {
|
||||
// todo: clean from main process as well?
|
||||
getters.lenses.forEach((lens: LensWebview) => {
|
||||
if (lens.webview) {
|
||||
@ -113,14 +111,14 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
return true;
|
||||
},
|
||||
|
||||
async uploadClusterIcon({commit}, data) {
|
||||
async uploadClusterIcon({ commit }, data) {
|
||||
const res = await promiseIpc.send("saveClusterIcon", data)
|
||||
tracker.event("cluster", "upload-icon")
|
||||
if (res.cluster) commit("updateCluster", res.cluster)
|
||||
return res
|
||||
},
|
||||
|
||||
async resetClusterIcon({commit}, data) {
|
||||
async resetClusterIcon({ commit }, data) {
|
||||
const res = await promiseIpc.send("resetClusterIcon", data.clusterId)
|
||||
tracker.event("cluster", "reset-icon")
|
||||
if (res.cluster) commit("updateCluster", res.cluster)
|
||||
@ -128,7 +126,7 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
},
|
||||
|
||||
// For data structure see: cluster-manager.ts / FeatureInstallRequest
|
||||
async installClusterFeature({commit}, data) {
|
||||
async installClusterFeature({ commit }, data) {
|
||||
// Custom no timeout IPC as install can take very variable time
|
||||
const ipc = new PromiseIpc();
|
||||
const response = await ipc.send('installFeature', data)
|
||||
@ -140,20 +138,19 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
return response
|
||||
},
|
||||
// For data structure see: cluster-manager.ts / FeatureInstallRequest
|
||||
async upgradeClusterFeature({commit}, data) {
|
||||
async upgradeClusterFeature({ commit }, data) {
|
||||
// Custom no timeout IPC as install can take very variable time
|
||||
const ipc = new PromiseIpc();
|
||||
const response = await ipc.send('upgradeFeature', data)
|
||||
console.log("upgrade result:", response);
|
||||
const cluster = await ipc.send('refreshCluster', data.clusterId)
|
||||
|
||||
|
||||
tracker.event("cluster", "upgrade-feature")
|
||||
commit("updateCluster", cluster)
|
||||
return response
|
||||
},
|
||||
// For data structure see: cluster-manager.ts / FeatureInstallRequest
|
||||
async uninstallClusterFeature({commit}, data) {
|
||||
async uninstallClusterFeature({ commit }, data) {
|
||||
// Custom no timeout IPC as uninstall can take very variable time
|
||||
const ipc = new PromiseIpc();
|
||||
const response = await ipc.send('uninstallFeature', data)
|
||||
@ -165,7 +162,7 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
return response
|
||||
},
|
||||
|
||||
attachWebview({commit}, lens: LensWebview) {
|
||||
attachWebview({ commit }, lens: LensWebview) {
|
||||
const container: any = document.getElementById("lens-container");
|
||||
if (!container || !lens.webview) {
|
||||
return
|
||||
@ -189,9 +186,11 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
})
|
||||
promiseIpc.send("enableClusterSettingsMenuItem", lens.id)
|
||||
},
|
||||
detachWebview({commit}, lens: LensWebview) {
|
||||
detachWebview({ commit }, lens: LensWebview) {
|
||||
const container: any = document.getElementById("lens-container");
|
||||
if (!container) { return }
|
||||
if (!container) {
|
||||
return
|
||||
}
|
||||
container.childNodes.forEach((child: any) => {
|
||||
if (child === lens.webview) {
|
||||
container.removeChild(lens.webview)
|
||||
@ -202,21 +201,23 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
})
|
||||
promiseIpc.send("disableClusterSettingsMenuItem")
|
||||
},
|
||||
hideWebviews({commit}) {
|
||||
hideWebviews({ commit }) {
|
||||
const container: any = document.getElementById("lens-container");
|
||||
if (!container) { return }
|
||||
if (!container) {
|
||||
return
|
||||
}
|
||||
container.style = "display: none;"
|
||||
container.childNodes.forEach((child: any) => {
|
||||
child.style = "display: none;"
|
||||
})
|
||||
promiseIpc.send("disableClusterSettingsMenuItem")
|
||||
},
|
||||
destroyWebviews({commit}) {
|
||||
destroyWebviews({ commit }) {
|
||||
state.lenses.forEach((lens) => {
|
||||
this.dispatch("detachWebview", lens)
|
||||
})
|
||||
},
|
||||
storeCluster({commit}, cluster: ClusterInfo) {
|
||||
storeCluster({ commit }, cluster: ClusterInfo) {
|
||||
clusterStore.saveCluster(cluster);
|
||||
commit("updateCluster", cluster)
|
||||
promiseIpc.send("clusterStored", cluster.id)
|
||||
@ -250,7 +251,7 @@ const mutations: MutationTree<ClusterState> = {
|
||||
},
|
||||
updateCluster(state, cluster) {
|
||||
state.clusters.forEach((c, index) => {
|
||||
if(c.id === cluster.id) {
|
||||
if (c.id === cluster.id) {
|
||||
Vue.set(state.clusters, index, cluster)
|
||||
}
|
||||
})
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { MutationTree, ActionTree, GetterTree } from "vuex"
|
||||
import { workspaceStore, Workspace, WorkspaceData } from "../../../../common/workspace-store"
|
||||
import { workspaceStore, Workspace } from "../../../../common/workspace-store"
|
||||
|
||||
export interface WorkspaceState {
|
||||
workspaces: Array<Workspace>;
|
||||
@ -26,11 +26,11 @@ const mutations: MutationTree<WorkspaceState> = {
|
||||
setCurrentWorkspace(state, workspace: Workspace) {
|
||||
state.currentWorkspace = workspace
|
||||
},
|
||||
addWorkspace(state, workspace: WorkspaceData) {
|
||||
addWorkspace(state, workspace: Workspace) {
|
||||
workspaceStore.saveWorkspace(workspace)
|
||||
state.workspaces = workspaceStore.getAllWorkspaces()
|
||||
},
|
||||
updateWorkspace(state, workspace: WorkspaceData) {
|
||||
updateWorkspace(state, workspace: Workspace) {
|
||||
workspaceStore.saveWorkspace(workspace)
|
||||
state.workspaces = workspaceStore.getAllWorkspaces()
|
||||
},
|
||||
|
||||
67
yarn.lock
67
yarn.lock
@ -3877,21 +3877,21 @@ concurrently@^5.2.0:
|
||||
tree-kill "^1.2.2"
|
||||
yargs "^13.3.0"
|
||||
|
||||
conf@^6.2.1:
|
||||
version "6.2.4"
|
||||
resolved "https://registry.yarnpkg.com/conf/-/conf-6.2.4.tgz#49d23c4e21ef2ac2860f7b5ed25b7b7e484f769f"
|
||||
integrity sha512-GjgyPRLo1qK1LR9RWAdUagqo+DP18f5HWCFk4va7GS+wpxQTOzfuKTwKOvGW2c01/YXNicAyyoyuSddmdkBzZQ==
|
||||
conf@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/conf/-/conf-7.0.1.tgz#a3ddd860db0357219b9ccdf92fd618e161fe6848"
|
||||
integrity sha512-UFA9EPFKK+tedCjz4JKQSxAN0/0r0rjURdq9N805JXWOhFzmr7fTLmG1cnsHCvyYYd65wRjf0KB8zg+WPelkvA==
|
||||
dependencies:
|
||||
ajv "^6.10.2"
|
||||
debounce-fn "^3.0.1"
|
||||
dot-prop "^5.0.0"
|
||||
ajv "^6.12.2"
|
||||
debounce-fn "^4.0.0"
|
||||
dot-prop "^5.2.0"
|
||||
env-paths "^2.2.0"
|
||||
json-schema-typed "^7.0.1"
|
||||
make-dir "^3.0.0"
|
||||
json-schema-typed "^7.0.3"
|
||||
make-dir "^3.1.0"
|
||||
onetime "^5.1.0"
|
||||
pkg-up "^3.0.1"
|
||||
semver "^6.2.0"
|
||||
write-file-atomic "^3.0.0"
|
||||
pkg-up "^3.1.0"
|
||||
semver "^7.3.2"
|
||||
write-file-atomic "^3.0.3"
|
||||
|
||||
config-chain@^1.1.11:
|
||||
version "1.1.12"
|
||||
@ -4233,12 +4233,12 @@ de-indent@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
|
||||
integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=
|
||||
|
||||
debounce-fn@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/debounce-fn/-/debounce-fn-3.0.1.tgz#034afe8b904d985d1ec1aa589cd15f388741d680"
|
||||
integrity sha512-aBoJh5AhpqlRoHZjHmOzZlRx+wz2xVwGL9rjs+Kj0EWUrL4/h4K7OD176thl2Tdoqui/AaA4xhHrNArGLAaI3Q==
|
||||
debounce-fn@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/debounce-fn/-/debounce-fn-4.0.0.tgz#ed76d206d8a50e60de0dd66d494d82835ffe61c7"
|
||||
integrity sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==
|
||||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
mimic-fn "^3.0.0"
|
||||
|
||||
debug@4.1.0:
|
||||
version "4.1.0"
|
||||
@ -4547,7 +4547,7 @@ dot-case@^3.0.3:
|
||||
no-case "^3.0.3"
|
||||
tslib "^1.10.0"
|
||||
|
||||
dot-prop@^5.0.0, dot-prop@^5.2.0:
|
||||
dot-prop@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb"
|
||||
integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==
|
||||
@ -4674,14 +4674,6 @@ electron-publish@22.7.0:
|
||||
lazy-val "^1.0.4"
|
||||
mime "^2.4.5"
|
||||
|
||||
electron-store@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-5.2.0.tgz#a15718fc1fa21acfd07af55f9b94f9fa6a536665"
|
||||
integrity sha512-iU3WDqEDAYNYR9XV7p0tJajq/zs9z7Nrn0sAoR5nDyn8h/9dr9kusKbTxD8NtVEBD1TB1pkGMqcbIt/y6knDwQ==
|
||||
dependencies:
|
||||
conf "^6.2.1"
|
||||
type-fest "^0.7.1"
|
||||
|
||||
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"
|
||||
@ -7260,7 +7252,7 @@ json-schema-traverse@^0.4.1:
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
|
||||
|
||||
json-schema-typed@^7.0.1:
|
||||
json-schema-typed@^7.0.3:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-7.0.3.tgz#23ff481b8b4eebcd2ca123b4fa0409e66469a2d9"
|
||||
integrity sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==
|
||||
@ -7703,7 +7695,7 @@ make-dir@^2.0.0:
|
||||
pify "^4.0.1"
|
||||
semver "^5.6.0"
|
||||
|
||||
make-dir@^3.0.0, make-dir@^3.0.2:
|
||||
make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
||||
integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
|
||||
@ -7914,6 +7906,11 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
mimic-fn@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.0.0.tgz#76044cfa8818bbf6999c5c9acadf2d3649b14b4b"
|
||||
integrity sha512-PiVO95TKvhiwgSwg1IdLYlCTdul38yZxZMIcnDSFIBUm4BNZha2qpQ4GpJ++15bHoKDtrW2D69lMfFwdFYtNZQ==
|
||||
|
||||
mimic-response@^1.0.0, mimic-response@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
||||
@ -9071,7 +9068,7 @@ pkg-up@^2.0.0:
|
||||
dependencies:
|
||||
find-up "^2.1.0"
|
||||
|
||||
pkg-up@^3.0.1:
|
||||
pkg-up@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5"
|
||||
integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==
|
||||
@ -10197,6 +10194,11 @@ serialize-javascript@^3.1.0:
|
||||
dependencies:
|
||||
randombytes "^2.1.0"
|
||||
|
||||
serializr@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/serializr/-/serializr-2.0.3.tgz#f163b2b39938e1313beaf8457133713df2a936bb"
|
||||
integrity sha512-YHDTg+QE//5vESifXc7vvncxIAiUiX04FAy1RmSgACkwhvJ9DivljDEjqs5WJzg5KLokI3x3jh30KEfXq5nDJA==
|
||||
|
||||
set-blocking@^2.0.0, set-blocking@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
@ -11292,11 +11294,6 @@ type-fest@^0.6.0:
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
|
||||
integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
|
||||
|
||||
type-fest@^0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48"
|
||||
integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==
|
||||
|
||||
type-fest@^0.8.0, type-fest@^0.8.1:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||
@ -11984,7 +11981,7 @@ wrappy@1:
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
write-file-atomic@^3.0.0:
|
||||
write-file-atomic@^3.0.0, write-file-atomic@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
|
||||
integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
|
||||
|
||||
Loading…
Reference in New Issue
Block a user