project restructuring and initial refactoring

This commit is contained in:
Roman committed 2020-06-09 15:14:40 +03:00
1 parent 5af12bdbbd
commit aa0eca2dc4
807 files changed
+11848 -22947

No files matched your search

View File
Whitespace-only changes.
+112
View File
@@ -0,0 +1,112 @@
import ElectronStore from "electron-store"
import { Cluster, ClusterBaseInfo } from "../main/cluster";
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",
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
}
}
export const clusterStore = ClusterStore.getInstance();
+11
View File
@@ -0,0 +1,11 @@
import { PrometheusLens } from "../main/prometheus/lens";
import { PrometheusHelm } from "../main/prometheus/helm";
import { PrometheusOperator } from "../main/prometheus/operator";
import { PrometheusProviderRegistry } from "../main/prometheus/provider-registry";
[PrometheusLens, PrometheusHelm, PrometheusOperator].forEach(providerClass => {
const provider = new providerClass()
PrometheusProviderRegistry.registerProvider(provider.id, provider)
});
export const prometheusProviders = PrometheusProviderRegistry.getProviders()
+12
View File
@@ -0,0 +1,12 @@
import 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
}
+7
View File
@@ -0,0 +1,7 @@
import "mac-ca"
import winca from "win-ca/api"
import { isWindows } from "./vars";
if (isWindows) {
winca.inject("+") // see: https://github.com/ukoloff/win-ca#caveats
}
+42
View File
@@ -0,0 +1,42 @@
import ua from "universal-analytics"
import { machineIdSync } from "node-machine-id"
import { userStore } from "../common/user-store"
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
}
}
+82
View File
@@ -0,0 +1,82 @@
import ElectronStore from "electron-store"
import * as version210Beta4 from "../migrations/user-store/2.1.0-beta.4"
export interface User {
id?: string;
}
export interface UserPreferences {
httpsProxy?: string;
colorTheme?: string;
allowUntrustedCAs?: boolean;
allowTelemetry?: boolean;
downloadMirror?: string;
}
export class UserStore {
private static instance: UserStore;
public store: ElectronStore;
private constructor() {
this.store = new ElectronStore({
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.downloadMirror) {
prefs.downloadMirror = "default"
}
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 };
+9
View File
@@ -0,0 +1,9 @@
import { app, remote } from "electron"
/**
*
* @returns app version correctly regardless of dev/prod mode and main/renderer differences
*/
export function getAppVersion(): string {
return (app || remote.app).getVersion();
}
+12
View File
@@ -0,0 +1,12 @@
// Encode/decode utf-8 base64 string
import * as Base64 from "crypto-js/enc-base64";
import * as Utf8 from "crypto-js/enc-utf8";
export const base64 = {
decode(data: string) {
return Base64.parse(data).toString(Utf8);
},
encode(data: string) {
return Utf8.parse(data).toString(Base64);
}
};
+18
View File
@@ -0,0 +1,18 @@
// Convert object's keys to camelCase format
import { camelCase, isPlainObject } from "lodash";
export function toCamelCase(obj: Record<string, any>): any {
if (Array.isArray(obj)) {
return obj.map(toCamelCase);
}
else if (isPlainObject(obj)) {
return Object.keys(obj).reduce((result, key) => {
const value = obj[key];
result[camelCase(key)] = typeof value === "object" ? toCamelCase(value) : value;
return result;
}, {} as any);
}
else {
return obj;
}
}
+5
View File
@@ -0,0 +1,5 @@
// Common utils bundle
export * from "./app-version"
export * from "./base64"
export * from "./camelCase"
+24
View File
@@ -0,0 +1,24 @@
// App's common paths/flags/etc. for any process
import packageInfo from "../package.json"
import path from "path";
const { main, renderer } = packageInfo.electronWebpack;
export const outDir = path.resolve(__dirname, "../dist");
export const mainDir = path.resolve(__dirname, "../", main.sourceDirectory);
export const rendererDir = path.resolve(__dirname, "../", renderer.sourceDirectory);
export const isMac = process.platform === "darwin"
export const isWindows = process.platform === "win32"
export const isProduction = process.env.NODE_ENV === "production"
export const isDevelopment = !isProduction;
export const buildVersion = process.env.BUILD_VERSION;
export const apiPrefix = {
BASE: '/api',
TERMINAL: '/api-terminal', // terminal api
KUBE_BASE: '/api-kube', // kubernetes cluster api
KUBE_USERS: '/api-users', // users & groups api
KUBE_HELM: '/api-helm', // helm charts api
KUBE_RESOURCE_APPLIER: "/api-resource",
};
+78
View File
@@ -0,0 +1,78 @@
import 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 {
public static defaultId = "default"
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) {
if (workspace.id === WorkspaceStore.defaultId) {
throw new Error("Cannot remove default 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().find( ws => ws.id === WorkspaceStore.defaultId)) {
workspaceStore.storeWorkspace({
id: WorkspaceStore.defaultId,
name: "default"
})
}
export { workspaceStore }