mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Lens app source code (#119)
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
1 parent
936cbd53d4
commit
1d0815abd2
797 files changed
+73714
-215
No files matched your search
Whitespace-only changes.
@@ -0,0 +1,14 @@
|
||||
import { app, remote } from "electron"
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns app version correctly regardless of dev/prod mode and main/renderer differences
|
||||
*/
|
||||
export function getAppVersion(): string {
|
||||
// app is undefined when running in renderer
|
||||
let version = (app || remote.app).getVersion()
|
||||
if(process.env.NODE_ENV === 'development') {
|
||||
version = require("../../package.json").version
|
||||
}
|
||||
return version;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
import * as ElectronStore from "electron-store"
|
||||
import { Cluster, ClusterBaseInfo } from "../main/cluster";
|
||||
import { getAppVersion } from "./app-utils"
|
||||
import * as version200Beta2 from "./migrations/cluster-store/2.0.0-beta.2"
|
||||
import * as version241 from "./migrations/cluster-store/2.4.1"
|
||||
import * as version260Beta2 from "./migrations/cluster-store/2.6.0-beta.2"
|
||||
import * as version260Beta3 from "./migrations/cluster-store/2.6.0-beta.3"
|
||||
import * as version270Beta0 from "./migrations/cluster-store/2.7.0-beta.0"
|
||||
import * as version270Beta1 from "./migrations/cluster-store/2.7.0-beta.1"
|
||||
|
||||
export class ClusterStore {
|
||||
private static instance: ClusterStore;
|
||||
public store: ElectronStore;
|
||||
|
||||
private constructor() {
|
||||
this.store = new ElectronStore({
|
||||
name: "lens-cluster-store",
|
||||
projectVersion: getAppVersion(),
|
||||
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
|
||||
migrations: {
|
||||
"2.0.0-beta.2": version200Beta2.migration,
|
||||
"2.4.1": version241.migration,
|
||||
"2.6.0-beta.2": version260Beta2.migration,
|
||||
"2.6.0-beta.3": version260Beta3.migration,
|
||||
"2.7.0-beta.0": version270Beta0.migration,
|
||||
"2.7.0-beta.1": version270Beta1.migration
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public getAllClusterObjects(): Array<Cluster> {
|
||||
return this.store.get("clusters", []).map((clusterInfo: ClusterBaseInfo) => {
|
||||
return new Cluster(clusterInfo)
|
||||
})
|
||||
}
|
||||
|
||||
public getAllClusters(): Array<ClusterBaseInfo> {
|
||||
return this.store.get("clusters", [])
|
||||
}
|
||||
|
||||
public removeCluster(id: string): void {
|
||||
this.store.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)
|
||||
}
|
||||
}
|
||||
|
||||
public removeClustersByWorkspace(workspace: string) {
|
||||
this.getAllClusters().forEach((cluster) => {
|
||||
if (cluster.workspace === workspace) {
|
||||
this.removeCluster(cluster.id)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public getCluster(id: string): Cluster {
|
||||
const cluster = this.getAllClusterObjects().find((cluster) => cluster.id === id)
|
||||
if (cluster) { return cluster}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
public storeCluster(cluster: ClusterBaseInfo) {
|
||||
const clusters = this.getAllClusters();
|
||||
const index = clusters.findIndex((cl) => cl.id === cluster.id)
|
||||
const storable = {
|
||||
id: cluster.id,
|
||||
kubeConfig: cluster.kubeConfig,
|
||||
preferences: cluster.preferences,
|
||||
workspace: cluster.workspace
|
||||
}
|
||||
if (index === -1) {
|
||||
clusters.push(storable)
|
||||
} else {
|
||||
clusters[index] = storable
|
||||
}
|
||||
this.store.set("clusters", clusters)
|
||||
}
|
||||
|
||||
public storeClusters(clusters: ClusterBaseInfo[]) {
|
||||
clusters.forEach((cluster: ClusterBaseInfo) => {
|
||||
this.removeCluster(cluster.id)
|
||||
this.storeCluster(cluster)
|
||||
})
|
||||
}
|
||||
|
||||
public reloadCluster(cluster: ClusterBaseInfo): void {
|
||||
const storedCluster = this.getCluster(cluster.id);
|
||||
if (storedCluster) {
|
||||
cluster.kubeConfig = storedCluster.kubeConfig
|
||||
cluster.preferences = storedCluster.preferences
|
||||
cluster.workspace = storedCluster.workspace
|
||||
}
|
||||
}
|
||||
|
||||
static getInstance(): ClusterStore {
|
||||
if(!ClusterStore.instance) {
|
||||
ClusterStore.instance = new ClusterStore();
|
||||
}
|
||||
return ClusterStore.instance;
|
||||
}
|
||||
|
||||
static resetInstance() {
|
||||
ClusterStore.instance = null
|
||||
}
|
||||
}
|
||||
|
||||
const clusterStore: ClusterStore = ClusterStore.getInstance();
|
||||
|
||||
export { clusterStore };
|
||||
@@ -0,0 +1,13 @@
|
||||
/* Early store format had the kubeconfig directly under context name, this moves
|
||||
it under the kubeConfig key */
|
||||
|
||||
export function migration(store: any) {
|
||||
console.log("CLUSTER STORE, MIGRATION: 2.0.0-beta.2");
|
||||
for (const value of store) {
|
||||
const contextName = value[0];
|
||||
// Looping all the keys gives out the store internal stuff too...
|
||||
if(contextName === "__internal__" || value[1].hasOwnProperty('kubeConfig')) continue;
|
||||
|
||||
store.set(contextName, { kubeConfig: value[1] });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Cleans up a store that had the state related data stored
|
||||
export function migration(store: any) {
|
||||
console.log("CLUSTER STORE, MIGRATION: 2.4.1");
|
||||
for (const value of store) {
|
||||
const contextName = value[0];
|
||||
if(contextName === "__internal__") continue;
|
||||
const cluster = value[1];
|
||||
|
||||
store.set(contextName, { kubeConfig: cluster.kubeConfig, icon: cluster.icon || null, preferences: cluster.preferences || {} });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Move cluster icon from root to preferences
|
||||
export function migration(store: any) {
|
||||
console.log("CLUSTER STORE, MIGRATION: 2.6.0-beta.2");
|
||||
for (const value of store) {
|
||||
const clusterKey = value[0];
|
||||
if(clusterKey === "__internal__") continue
|
||||
const cluster = value[1];
|
||||
if(!cluster.preferences) cluster.preferences = {};
|
||||
if(cluster.icon) {
|
||||
cluster.preferences.icon = cluster.icon;
|
||||
delete(cluster["icon"]);
|
||||
}
|
||||
store.set(clusterKey, { contextName: clusterKey, kubeConfig: value[1].kubeConfig, preferences: value[1].preferences });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import * as yaml from "js-yaml"
|
||||
|
||||
// Convert access token and expiry from arrays into strings
|
||||
export function migration(store: any) {
|
||||
console.log("CLUSTER STORE, MIGRATION: 2.6.0-beta.3");
|
||||
for (const value of store) {
|
||||
const clusterKey = value[0];
|
||||
if(clusterKey === "__internal__") continue
|
||||
const cluster = value[1];
|
||||
if(!cluster.kubeConfig) continue
|
||||
const kubeConfig = yaml.safeLoad(cluster.kubeConfig)
|
||||
if(!kubeConfig.hasOwnProperty('users')) continue
|
||||
const userObj = kubeConfig.users[0]
|
||||
if (userObj) {
|
||||
const user = userObj.user
|
||||
if (user["auth-provider"] && user["auth-provider"].config) {
|
||||
const authConfig = user["auth-provider"].config
|
||||
if (authConfig["access-token"]) {
|
||||
authConfig["access-token"] = `${authConfig["access-token"]}`
|
||||
}
|
||||
if (authConfig.expiry) {
|
||||
authConfig.expiry = `${authConfig.expiry}`
|
||||
}
|
||||
console.log(authConfig)
|
||||
user["auth-provider"].config = authConfig
|
||||
kubeConfig.users = [{
|
||||
name: userObj.name,
|
||||
user: user
|
||||
}]
|
||||
cluster.kubeConfig = yaml.safeDump(kubeConfig)
|
||||
store.set(clusterKey, cluster)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Add existing clusters to "default" workspace
|
||||
export function migration(store: any) {
|
||||
console.log("CLUSTER STORE, MIGRATION: 2.7.0-beta.0");
|
||||
for (const value of store) {
|
||||
const clusterKey = value[0];
|
||||
if(clusterKey === "__internal__") continue
|
||||
const cluster = value[1];
|
||||
cluster.workspace = "default"
|
||||
store.set(clusterKey, cluster)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// add id for clusters and store them to array
|
||||
import { v4 as uuid } from "uuid"
|
||||
|
||||
export function migration(store: any) {
|
||||
console.log("CLUSTER STORE, MIGRATION: 2.7.0-beta.1");
|
||||
const clusters: any[] = []
|
||||
for (const value of store) {
|
||||
const clusterKey = value[0];
|
||||
if(clusterKey === "__internal__") continue
|
||||
if(clusterKey === "clusters") continue
|
||||
const cluster = value[1];
|
||||
cluster.id = uuid()
|
||||
if (!cluster.preferences.clusterName) {
|
||||
cluster.preferences.clusterName = clusterKey
|
||||
}
|
||||
clusters.push(cluster)
|
||||
store.delete(clusterKey)
|
||||
}
|
||||
if (clusters.length > 0) {
|
||||
store.set("clusters", clusters)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Add / reset "lastSeenAppVersion"
|
||||
export function migration(store: any) {
|
||||
store.set("lastSeenAppVersion", "0.0.0");
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import * as request from "request"
|
||||
import { userStore } from "../common/user-store"
|
||||
|
||||
export function globalRequestOpts(requestOpts: request.Options ) {
|
||||
const userPrefs = userStore.getPreferences()
|
||||
if (userPrefs.httpsProxy) {
|
||||
requestOpts.proxy = userPrefs.httpsProxy
|
||||
}
|
||||
requestOpts.rejectUnauthorized = !userPrefs.allowUntrustedCAs;
|
||||
|
||||
return requestOpts
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import * as winca from "win-ca/api"
|
||||
import "mac-ca"
|
||||
|
||||
if (process.platform === "win32") {
|
||||
winca.inject("+") // see: https://github.com/ukoloff/win-ca#caveats
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { machineIdSync } from 'node-machine-id'
|
||||
import { userStore } from "../common/user-store"
|
||||
import * as ua from "universal-analytics"
|
||||
|
||||
const GA_ID = "UA-159377374-1"
|
||||
|
||||
export class Tracker {
|
||||
protected visitor: ua.Visitor
|
||||
protected machineId: string = null;
|
||||
protected ip: string = null;
|
||||
protected appVersion: string;
|
||||
protected locale: string;
|
||||
protected electronUA: string;
|
||||
|
||||
constructor(app: Electron.App) {
|
||||
try {
|
||||
this.visitor = ua(GA_ID, machineIdSync(), {strictCidFormat: false})
|
||||
} catch (error) {
|
||||
this.visitor = ua(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
|
||||
}
|
||||
this.visitor.event({
|
||||
ec: eventCategory,
|
||||
ea: eventAction
|
||||
}).send()
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
protected telemetryAllowed() {
|
||||
const userPrefs = userStore.getPreferences()
|
||||
return !!userPrefs.allowTelemetry
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import * as ElectronStore from "electron-store"
|
||||
import * as appUtil from "./app-utils"
|
||||
import * as version210Beta4 from "./migrations/user-store/2.1.0-beta.4"
|
||||
|
||||
export interface User {
|
||||
id?: string;
|
||||
bio?: string;
|
||||
company?: string;
|
||||
email?: string;
|
||||
'first-name'?: string;
|
||||
'is-customer'?: boolean;
|
||||
'is-partner'?: boolean;
|
||||
'last-name'?: string;
|
||||
'lens-invitation-used'?: boolean;
|
||||
location?: string;
|
||||
//notifications?: array;
|
||||
url?: string;
|
||||
'user-avatar-src'?: string;
|
||||
username: string;
|
||||
verified?: boolean;
|
||||
}
|
||||
|
||||
export interface UserPreferences {
|
||||
httpsProxy?: string;
|
||||
colorTheme?: string;
|
||||
allowUntrustedCAs?: boolean;
|
||||
allowTelemetry?: boolean;
|
||||
}
|
||||
|
||||
export class UserStore {
|
||||
private static instance: UserStore;
|
||||
public store: ElectronStore;
|
||||
|
||||
private constructor() {
|
||||
this.store = new ElectronStore({
|
||||
projectVersion: appUtil.getAppVersion(),
|
||||
migrations: {
|
||||
"2.1.0-beta.4": version210Beta4.migration,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public lastSeenAppVersion() {
|
||||
return this.store.get('lastSeenAppVersion', "0.0.0")
|
||||
}
|
||||
|
||||
public setLastSeenAppVersion(version: string) {
|
||||
this.store.set('lastSeenAppVersion', version)
|
||||
}
|
||||
|
||||
public getSeenContexts(): Array<string> {
|
||||
return this.store.get("seenContexts", [])
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
public setPreferences(preferences: UserPreferences) {
|
||||
this.store.set('preferences', preferences)
|
||||
}
|
||||
|
||||
public getPreferences(): UserPreferences {
|
||||
const prefs = this.store.get("preferences", {})
|
||||
if (!prefs.colorTheme) {
|
||||
prefs.colorTheme = "dark"
|
||||
}
|
||||
if (prefs.allowTelemetry === undefined) {
|
||||
prefs.allowTelemetry = true
|
||||
}
|
||||
|
||||
return prefs
|
||||
}
|
||||
|
||||
static getInstance(): UserStore {
|
||||
if(!UserStore.instance) {
|
||||
UserStore.instance = new UserStore();
|
||||
}
|
||||
return UserStore.instance;
|
||||
}
|
||||
|
||||
static resetInstance() {
|
||||
UserStore.instance = null
|
||||
}
|
||||
}
|
||||
|
||||
const userStore: UserStore = UserStore.getInstance();
|
||||
|
||||
export { userStore };
|
||||
@@ -0,0 +1,74 @@
|
||||
import * as ElectronStore from "electron-store"
|
||||
import { clusterStore } from "./cluster-store"
|
||||
|
||||
export interface WorkspaceData {
|
||||
id: string;
|
||||
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 {
|
||||
private static instance: WorkspaceStore;
|
||||
public store: ElectronStore;
|
||||
|
||||
private constructor() {
|
||||
this.store = new ElectronStore({
|
||||
name: "lens-workspace-store"
|
||||
})
|
||||
}
|
||||
|
||||
public storeWorkspace(workspace: WorkspaceData) {
|
||||
const workspaces = this.getAllWorkspaces()
|
||||
const index = workspaces.findIndex((w) => w.id === workspace.id)
|
||||
if (index !== -1) {
|
||||
workspaces[index] = workspace
|
||||
} else {
|
||||
workspaces.push(workspace)
|
||||
}
|
||||
this.store.set("workspaces", workspaces)
|
||||
}
|
||||
|
||||
public removeWorkspace(workspace: Workspace) {
|
||||
const workspaces = this.getAllWorkspaces()
|
||||
const index = workspaces.findIndex((w) => w.id === workspace.id)
|
||||
if (index !== -1) {
|
||||
clusterStore.removeClustersByWorkspace(workspace.id)
|
||||
workspaces.splice(index, 1)
|
||||
this.store.set("workspaces", workspaces)
|
||||
}
|
||||
}
|
||||
|
||||
public getAllWorkspaces(): Array<Workspace> {
|
||||
const workspacesData: WorkspaceData[] = this.store.get("workspaces", [])
|
||||
|
||||
return workspacesData.map((wsd) => new Workspace(wsd))
|
||||
}
|
||||
|
||||
static getInstance(): WorkspaceStore {
|
||||
if (!WorkspaceStore.instance) {
|
||||
WorkspaceStore.instance = new WorkspaceStore()
|
||||
}
|
||||
return WorkspaceStore.instance
|
||||
}
|
||||
}
|
||||
|
||||
const workspaceStore: WorkspaceStore = WorkspaceStore.getInstance()
|
||||
|
||||
if (workspaceStore.getAllWorkspaces().length === 0) {
|
||||
workspaceStore.storeWorkspace({
|
||||
id: "default",
|
||||
name: "default"
|
||||
})
|
||||
}
|
||||
|
||||
export { workspaceStore }
|
||||
Reference in new issue
Block a user