mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
refactoring & fixes
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
462386a206
commit
0446fd4e89
@ -2,7 +2,7 @@ import path from "path"
|
|||||||
import Config from "conf"
|
import Config from "conf"
|
||||||
import { Options as ConfOptions } from "conf/dist/source/types"
|
import { Options as ConfOptions } from "conf/dist/source/types"
|
||||||
import { app, ipcMain, IpcMainEvent, ipcRenderer, IpcRendererEvent, remote } from "electron"
|
import { app, ipcMain, IpcMainEvent, ipcRenderer, IpcRendererEvent, remote } from "electron"
|
||||||
import { action, observable, reaction, runInAction, toJS, when } from "mobx";
|
import { action, IReactionOptions, observable, reaction, runInAction, toJS, when } from "mobx";
|
||||||
import Singleton from "./utils/singleton";
|
import Singleton from "./utils/singleton";
|
||||||
import { getAppVersion } from "./utils/app-version";
|
import { getAppVersion } from "./utils/app-version";
|
||||||
import logger from "../main/logger";
|
import logger from "../main/logger";
|
||||||
@ -12,6 +12,7 @@ import isEqual from "lodash/isEqual";
|
|||||||
export interface BaseStoreParams<T = any> extends ConfOptions<T> {
|
export interface BaseStoreParams<T = any> extends ConfOptions<T> {
|
||||||
autoLoad?: boolean;
|
autoLoad?: boolean;
|
||||||
syncEnabled?: boolean;
|
syncEnabled?: boolean;
|
||||||
|
syncOptions?: IReactionOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BaseStore<T = any> extends Singleton {
|
export class BaseStore<T = any> extends Singleton {
|
||||||
@ -20,7 +21,7 @@ export class BaseStore<T = any> extends Singleton {
|
|||||||
|
|
||||||
whenLoaded = when(() => this.isLoaded);
|
whenLoaded = when(() => this.isLoaded);
|
||||||
@observable isLoaded = false;
|
@observable isLoaded = false;
|
||||||
@observable protected data: T;
|
@observable data = {} as T;
|
||||||
|
|
||||||
protected constructor(protected params: BaseStoreParams) {
|
protected constructor(protected params: BaseStoreParams) {
|
||||||
super();
|
super();
|
||||||
@ -36,8 +37,12 @@ export class BaseStore<T = any> extends Singleton {
|
|||||||
return path.basename(this.storeConfig.path);
|
return path.basename(this.storeConfig.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get path() {
|
||||||
|
return this.storeConfig.path;
|
||||||
|
}
|
||||||
|
|
||||||
get syncChannel() {
|
get syncChannel() {
|
||||||
return `store-sync:${this.name}`
|
return `STORE-SYNC:${this.path}`
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async init() {
|
protected async init() {
|
||||||
@ -56,19 +61,19 @@ export class BaseStore<T = any> extends Singleton {
|
|||||||
...confOptions,
|
...confOptions,
|
||||||
projectName: "lens",
|
projectName: "lens",
|
||||||
projectVersion: getAppVersion(),
|
projectVersion: getAppVersion(),
|
||||||
cwd: this.storePath(),
|
cwd: this.cwd(),
|
||||||
});
|
});
|
||||||
logger.info(`[STORE]: LOADED from ${this.storeConfig.path}`);
|
logger.info(`[STORE]: LOADED from ${this.path}`);
|
||||||
this.fromStore(this.storeConfig.store);
|
this.fromStore(this.storeConfig.store);
|
||||||
this.isLoaded = true;
|
this.isLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected storePath() {
|
protected cwd() {
|
||||||
return (app || remote.app).getPath("userData")
|
return (app || remote.app).getPath("userData")
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async saveToFile(model: T) {
|
protected async saveToFile(model: T) {
|
||||||
logger.info(`[STORE]: SAVING ${this.name}`);
|
logger.info(`[STORE]: SAVING ${this.path}`);
|
||||||
// todo: update when fixed https://github.com/sindresorhus/conf/issues/114
|
// todo: update when fixed https://github.com/sindresorhus/conf/issues/114
|
||||||
Object.entries(model).forEach(([key, value]) => {
|
Object.entries(model).forEach(([key, value]) => {
|
||||||
this.storeConfig.set(key, value);
|
this.storeConfig.set(key, value);
|
||||||
@ -77,7 +82,7 @@ export class BaseStore<T = any> extends Singleton {
|
|||||||
|
|
||||||
enableSync() {
|
enableSync() {
|
||||||
this.syncDisposers.push(
|
this.syncDisposers.push(
|
||||||
reaction(() => this.toJSON(), model => this.onModelChange(model)),
|
reaction(() => this.toJSON(), model => this.onModelChange(model), this.params.syncOptions),
|
||||||
);
|
);
|
||||||
if (ipcMain) {
|
if (ipcMain) {
|
||||||
const callback = (event: IpcMainEvent, model: T) => {
|
const callback = (event: IpcMainEvent, model: T) => {
|
||||||
@ -169,6 +174,7 @@ export class BaseStore<T = any> extends Singleton {
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
protected fromStore(data: T) {
|
protected fromStore(data: T) {
|
||||||
|
if (!data) return;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,42 +1,28 @@
|
|||||||
import type { LensExtension, LensExtensionConstructor, LensExtensionId, LensExtensionManifest, LensExtensionStoreModel } from "./lens-extension"
|
import type { LensExtension, LensExtensionConstructor, LensExtensionId } from "./lens-extension"
|
||||||
import type { LensMainExtension } from "./lens-main-extension"
|
import type { LensMainExtension } from "./lens-main-extension"
|
||||||
import type { LensRendererExtension } from "./lens-renderer-extension"
|
import type { LensRendererExtension } from "./lens-renderer-extension"
|
||||||
|
import type { InstalledExtension } from "./extension-manager";
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import { broadcastIpc } from "../common/ipc"
|
import { broadcastIpc } from "../common/ipc"
|
||||||
import { action, autorun, computed, observable, reaction, toJS } from "mobx"
|
import { computed, observable, reaction, when } from "mobx"
|
||||||
import logger from "../main/logger"
|
import logger from "../main/logger"
|
||||||
import { app, ipcRenderer, remote } from "electron"
|
import { app, ipcRenderer, remote } from "electron"
|
||||||
import { BaseStore } from "../common/base-store";
|
|
||||||
import * as registries from "./registries";
|
import * as registries from "./registries";
|
||||||
|
|
||||||
export interface ExtensionLoaderStoreModel {
|
|
||||||
extensions: LensExtensionStoreModel[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface InstalledExtension {
|
|
||||||
manifest: LensExtensionManifest;
|
|
||||||
manifestPath: string;
|
|
||||||
isBundled?: boolean; // defined in package.json
|
|
||||||
}
|
|
||||||
|
|
||||||
// lazy load so that we get correct userData
|
// lazy load so that we get correct userData
|
||||||
export function extensionPackagesRoot() {
|
export function extensionPackagesRoot() {
|
||||||
return path.join((app || remote.app).getPath("userData"))
|
return path.join((app || remote.app).getPath("userData"))
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ExtensionLoader extends BaseStore<ExtensionLoaderStoreModel> {
|
export class ExtensionLoader {
|
||||||
protected disposers = new Map<LensExtensionId, Function[]>();
|
@observable isLoaded = false;
|
||||||
|
protected extensions = observable.map<LensExtensionId, InstalledExtension>([], { deep: false });
|
||||||
@observable extensions = observable.map<LensExtensionId, InstalledExtension>([], { deep: false });
|
protected instances = observable.map<LensExtensionId, LensExtension>([], { deep: false })
|
||||||
@observable instances = observable.map<LensExtensionId, LensExtension>([], { deep: false })
|
|
||||||
@observable state = observable.map<LensExtensionId, LensExtensionStoreModel>();
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
|
||||||
configName: "lens-extensions",
|
|
||||||
});
|
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
ipcRenderer.on("extensions:loaded", (event, extensions: InstalledExtension[]) => {
|
ipcRenderer.on("extensions:loaded", (event, extensions: InstalledExtension[]) => {
|
||||||
|
this.isLoaded = true;
|
||||||
extensions.forEach((ext) => {
|
extensions.forEach((ext) => {
|
||||||
if (!this.extensions.has(ext.manifestPath)) {
|
if (!this.extensions.has(ext.manifestPath)) {
|
||||||
this.extensions.set(ext.manifestPath, ext)
|
this.extensions.set(ext.manifestPath, ext)
|
||||||
@ -50,53 +36,41 @@ export class ExtensionLoader extends BaseStore<ExtensionLoaderStoreModel> {
|
|||||||
return [...this.instances.values()].filter(ext => !ext.isBundled)
|
return [...this.instances.values()].filter(ext => !ext.isBundled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
const { extensionManager } = await import("./extension-manager");
|
||||||
|
const installedExtensions = await extensionManager.load();
|
||||||
|
this.extensions.replace(installedExtensions);
|
||||||
|
this.isLoaded = true;
|
||||||
|
this.loadOnMain();
|
||||||
|
}
|
||||||
|
|
||||||
loadOnMain() {
|
loadOnMain() {
|
||||||
logger.info('[EXTENSIONS-LOADER]: load on main')
|
logger.info('[EXTENSIONS-LOADER]: load on main')
|
||||||
this.autoInitExtensions();
|
this.autoInitExtensions((extension: LensMainExtension) => [
|
||||||
this.autoEnableExtensions((extension: LensMainExtension) => [
|
|
||||||
registries.menuRegistry.add(...extension.appMenus)
|
registries.menuRegistry.add(...extension.appMenus)
|
||||||
])
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadOnClusterManagerRenderer() {
|
loadOnClusterManagerRenderer() {
|
||||||
logger.info('[EXTENSIONS-LOADER]: load on main renderer (cluster manager)')
|
logger.info('[EXTENSIONS-LOADER]: load on main renderer (cluster manager)')
|
||||||
this.autoInitExtensions();
|
this.autoInitExtensions((extension: LensRendererExtension) => [
|
||||||
this.autoEnableExtensions((extension: LensRendererExtension) => [
|
|
||||||
registries.globalPageRegistry.add(...extension.globalPages),
|
registries.globalPageRegistry.add(...extension.globalPages),
|
||||||
registries.appPreferenceRegistry.add(...extension.appPreferences),
|
registries.appPreferenceRegistry.add(...extension.appPreferences),
|
||||||
registries.clusterFeatureRegistry.add(...extension.clusterFeatures),
|
registries.clusterFeatureRegistry.add(...extension.clusterFeatures),
|
||||||
registries.statusBarRegistry.add(...extension.statusBarItems),
|
registries.statusBarRegistry.add(...extension.statusBarItems),
|
||||||
])
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadOnClusterRenderer() {
|
loadOnClusterRenderer() {
|
||||||
logger.info('[EXTENSIONS-LOADER]: load on cluster renderer (dashboard)')
|
logger.info('[EXTENSIONS-LOADER]: load on cluster renderer (dashboard)')
|
||||||
this.autoInitExtensions();
|
this.autoInitExtensions((extension: LensRendererExtension) => [
|
||||||
this.autoEnableExtensions((extension: LensRendererExtension) => [
|
|
||||||
registries.clusterPageRegistry.add(...extension.clusterPages),
|
registries.clusterPageRegistry.add(...extension.clusterPages),
|
||||||
registries.kubeObjectMenuRegistry.add(...extension.kubeObjectMenuItems),
|
registries.kubeObjectMenuRegistry.add(...extension.kubeObjectMenuItems),
|
||||||
registries.kubeObjectDetailRegistry.add(...extension.kubeObjectDetailItems),
|
registries.kubeObjectDetailRegistry.add(...extension.kubeObjectDetailItems),
|
||||||
])
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected autoEnableExtensions(register: (ext: LensExtension) => Function[]) {
|
protected autoInitExtensions(register: (ext: LensExtension) => Function[]) {
|
||||||
return autorun(() => {
|
|
||||||
this.instances.forEach(ext => {
|
|
||||||
const extensionState = this.state.get(ext.id);
|
|
||||||
const isEnabled = !extensionState /*enabled by default*/ || extensionState.isEnabled;
|
|
||||||
const isRegistered = this.disposers.has(ext.id);
|
|
||||||
if (isEnabled && !isRegistered) {
|
|
||||||
this.disposers.set(ext.id, register(ext))
|
|
||||||
} else if (!isEnabled && isRegistered) {
|
|
||||||
this.disposers.get(ext.id).forEach(dispose => dispose())
|
|
||||||
this.disposers.delete(ext.id)
|
|
||||||
}
|
|
||||||
ext.toggle(isEnabled);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
protected autoInitExtensions() {
|
|
||||||
return reaction(() => this.extensions.toJS(), (installedExtensions) => {
|
return reaction(() => this.extensions.toJS(), (installedExtensions) => {
|
||||||
for (const [id, ext] of installedExtensions) {
|
for (const [id, ext] of installedExtensions) {
|
||||||
let instance = this.instances.get(ext.manifestPath)
|
let instance = this.instances.get(ext.manifestPath)
|
||||||
@ -108,6 +82,7 @@ export class ExtensionLoader extends BaseStore<ExtensionLoaderStoreModel> {
|
|||||||
try {
|
try {
|
||||||
const LensExtensionClass: LensExtensionConstructor = extensionModule.default;
|
const LensExtensionClass: LensExtensionConstructor = extensionModule.default;
|
||||||
instance = new LensExtensionClass(ext);
|
instance = new LensExtensionClass(ext);
|
||||||
|
instance.whenEnabled(() => register(instance));
|
||||||
this.instances.set(ext.manifestPath, instance);
|
this.instances.set(ext.manifestPath, instance);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`[EXTENSIONS-LOADER]: init extension instance error`, { ext, err })
|
logger.error(`[EXTENSIONS-LOADER]: init extension instance error`, { ext, err })
|
||||||
@ -136,7 +111,8 @@ export class ExtensionLoader extends BaseStore<ExtensionLoaderStoreModel> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
broadcastExtensions(frameId?: number) {
|
async broadcastExtensions(frameId?: number) {
|
||||||
|
await when(() => this.isLoaded);
|
||||||
broadcastIpc({
|
broadcastIpc({
|
||||||
channel: "extensions:loaded",
|
channel: "extensions:loaded",
|
||||||
frameId: frameId,
|
frameId: frameId,
|
||||||
@ -146,21 +122,6 @@ export class ExtensionLoader extends BaseStore<ExtensionLoaderStoreModel> {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
|
||||||
protected fromStore({ extensions = [] }: ExtensionLoaderStoreModel) {
|
|
||||||
extensions.forEach(ext => {
|
|
||||||
this.state.set(ext.id, ext);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(): ExtensionLoaderStoreModel {
|
|
||||||
return toJS({
|
|
||||||
extensions: this.userExtensions.map(ext => ext.toJSON())
|
|
||||||
}, {
|
|
||||||
recurseEverything: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const extensionLoader: ExtensionLoader = ExtensionLoader.getInstance();
|
export const extensionLoader = new ExtensionLoader();
|
||||||
|
|||||||
@ -1,12 +1,18 @@
|
|||||||
import type { LensExtensionManifest } from "./lens-extension"
|
import type { LensExtensionId, LensExtensionManifest } from "./lens-extension"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import os from "os"
|
import os from "os"
|
||||||
import fs from "fs-extra"
|
import fs from "fs-extra"
|
||||||
|
import child_process from "child_process";
|
||||||
import logger from "../main/logger"
|
import logger from "../main/logger"
|
||||||
import { extensionPackagesRoot, InstalledExtension } from "./extension-loader"
|
import { extensionPackagesRoot } from "./extension-loader"
|
||||||
import * as child_process from 'child_process';
|
|
||||||
import { getBundledExtensions } from "../common/utils/app-version"
|
import { getBundledExtensions } from "../common/utils/app-version"
|
||||||
|
|
||||||
|
export interface InstalledExtension {
|
||||||
|
manifest: LensExtensionManifest;
|
||||||
|
manifestPath: string;
|
||||||
|
isBundled?: boolean; // defined in package.json
|
||||||
|
}
|
||||||
|
|
||||||
type Dependencies = {
|
type Dependencies = {
|
||||||
[name: string]: string;
|
[name: string]: string;
|
||||||
}
|
}
|
||||||
@ -51,7 +57,7 @@ export class ExtensionManager {
|
|||||||
return path.join(this.extensionPackagesRoot, "package.json")
|
return path.join(this.extensionPackagesRoot, "package.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
async load(): Promise<Map<string, InstalledExtension>> {
|
async load(): Promise<Map<LensExtensionId, InstalledExtension>> {
|
||||||
logger.info("[EXTENSION-MANAGER] loading extensions from " + this.extensionPackagesRoot)
|
logger.info("[EXTENSION-MANAGER] loading extensions from " + this.extensionPackagesRoot)
|
||||||
if (fs.existsSync(path.join(this.extensionPackagesRoot, "package-lock.json"))) {
|
if (fs.existsSync(path.join(this.extensionPackagesRoot, "package-lock.json"))) {
|
||||||
await fs.remove(path.join(this.extensionPackagesRoot, "package-lock.json"))
|
await fs.remove(path.join(this.extensionPackagesRoot, "package-lock.json"))
|
||||||
@ -71,7 +77,7 @@ export class ExtensionManager {
|
|||||||
return await this.loadExtensions();
|
return await this.loadExtensions();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getByManifest(manifestPath: string): Promise<InstalledExtension> {
|
protected async getByManifest(manifestPath: string): Promise<InstalledExtension> {
|
||||||
let manifestJson: LensExtensionManifest;
|
let manifestJson: LensExtensionManifest;
|
||||||
try {
|
try {
|
||||||
fs.accessSync(manifestPath, fs.constants.F_OK); // check manifest file for existence
|
fs.accessSync(manifestPath, fs.constants.F_OK); // check manifest file for existence
|
||||||
@ -81,7 +87,7 @@ export class ExtensionManager {
|
|||||||
logger.info("[EXTENSION-MANAGER] installed extension " + manifestJson.name)
|
logger.info("[EXTENSION-MANAGER] installed extension " + manifestJson.name)
|
||||||
return {
|
return {
|
||||||
manifestPath: path.join(this.nodeModulesPath, manifestJson.name, "package.json"),
|
manifestPath: path.join(this.nodeModulesPath, manifestJson.name, "package.json"),
|
||||||
manifest: manifestJson
|
manifest: manifestJson,
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`[EXTENSION-MANAGER]: can't install extension at ${manifestPath}: ${err}`, { manifestJson });
|
logger.error(`[EXTENSION-MANAGER]: can't install extension at ${manifestPath}: ${err}`, { manifestJson });
|
||||||
|
|||||||
@ -15,7 +15,7 @@ export class ExtensionStore<T = any> extends BaseStore<T> {
|
|||||||
await super.load()
|
await super.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected storePath() {
|
protected cwd() {
|
||||||
return path.join(super.storePath(), "extension-store", this.extension.name)
|
return path.join(super.cwd(), "extension-store", this.extension.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,10 @@
|
|||||||
import { action, observable, toJS } from "mobx";
|
import type { InstalledExtension } from "./extension-manager";
|
||||||
|
import { action, reaction } from "mobx";
|
||||||
import logger from "../main/logger";
|
import logger from "../main/logger";
|
||||||
import type { InstalledExtension } from "./extension-loader";
|
import { ExtensionStore } from "./extension-store";
|
||||||
|
|
||||||
export type LensExtensionId = string; // path to manifest (package.json)
|
export type LensExtensionId = string; // path to manifest (package.json)
|
||||||
export type LensExtensionConstructor = new (init: InstalledExtension) => LensExtension;
|
export type LensExtensionConstructor = new (...args: ConstructorParameters<typeof LensExtension>) => LensExtension;
|
||||||
|
|
||||||
export interface LensExtensionStoreModel {
|
|
||||||
id: LensExtensionId;
|
|
||||||
name: string;
|
|
||||||
isEnabled?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LensExtensionManifest {
|
export interface LensExtensionManifest {
|
||||||
name: string;
|
name: string;
|
||||||
@ -19,17 +14,35 @@ export interface LensExtensionManifest {
|
|||||||
renderer?: string; // path to %ext/dist/renderer.js
|
renderer?: string; // path to %ext/dist/renderer.js
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LensExtension {
|
export interface LensExtensionStoreModel {
|
||||||
public manifest: LensExtensionManifest;
|
isEnabled: boolean;
|
||||||
public manifestPath: string;
|
}
|
||||||
public isBundled: boolean;
|
|
||||||
|
|
||||||
@observable isEnabled = false;
|
export class LensExtension<S extends ExtensionStore<LensExtensionStoreModel> = any> {
|
||||||
|
protected store: S;
|
||||||
|
readonly manifest: LensExtensionManifest;
|
||||||
|
readonly manifestPath: string;
|
||||||
|
readonly isBundled: boolean;
|
||||||
|
|
||||||
constructor({ manifest, manifestPath, isBundled }: InstalledExtension) {
|
constructor({ manifest, manifestPath, isBundled }: InstalledExtension) {
|
||||||
this.manifest = manifest
|
this.manifest = manifest
|
||||||
this.manifestPath = manifestPath
|
this.manifestPath = manifestPath
|
||||||
this.isBundled = !!isBundled
|
this.isBundled = !!isBundled
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async init(store: S = createBaseStore().getInstance()) {
|
||||||
|
this.store = store;
|
||||||
|
await this.store.loadExtension(this);
|
||||||
|
reaction(() => this.store.data.isEnabled, (isEnabled = true) => {
|
||||||
|
this.toggle(isEnabled); // handle activation & deactivation
|
||||||
|
}, {
|
||||||
|
fireImmediately: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get isEnabled() {
|
||||||
|
return !!this.store.data.isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
get id(): LensExtensionId {
|
get id(): LensExtensionId {
|
||||||
@ -51,7 +64,7 @@ export class LensExtension {
|
|||||||
@action
|
@action
|
||||||
async enable() {
|
async enable() {
|
||||||
if (this.isEnabled) return;
|
if (this.isEnabled) return;
|
||||||
this.isEnabled = true;
|
this.store.data.isEnabled = true;
|
||||||
this.onActivate();
|
this.onActivate();
|
||||||
logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`);
|
logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`);
|
||||||
}
|
}
|
||||||
@ -59,7 +72,7 @@ export class LensExtension {
|
|||||||
@action
|
@action
|
||||||
async disable() {
|
async disable() {
|
||||||
if (!this.isEnabled) return;
|
if (!this.isEnabled) return;
|
||||||
this.isEnabled = false;
|
this.store.data.isEnabled = false;
|
||||||
this.onDeactivate();
|
this.onDeactivate();
|
||||||
logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`);
|
logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`);
|
||||||
}
|
}
|
||||||
@ -72,6 +85,27 @@ export class LensExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async whenEnabled(handlers: () => Function[]) {
|
||||||
|
const disposers: Function[] = [];
|
||||||
|
const unregisterHandlers = () => {
|
||||||
|
disposers.forEach(unregister => unregister())
|
||||||
|
disposers.length = 0;
|
||||||
|
}
|
||||||
|
const cancelReaction = reaction(() => this.isEnabled, isEnabled => {
|
||||||
|
if (isEnabled) {
|
||||||
|
disposers.push(...handlers());
|
||||||
|
} else {
|
||||||
|
unregisterHandlers();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
fireImmediately: true
|
||||||
|
})
|
||||||
|
return () => {
|
||||||
|
unregisterHandlers();
|
||||||
|
cancelReaction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected onActivate() {
|
protected onActivate() {
|
||||||
// mock
|
// mock
|
||||||
}
|
}
|
||||||
@ -79,14 +113,14 @@ export class LensExtension {
|
|||||||
protected onDeactivate() {
|
protected onDeactivate() {
|
||||||
// mock
|
// mock
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
toJSON(): LensExtensionStoreModel {
|
function createBaseStore() {
|
||||||
return toJS({
|
return class extends ExtensionStore<LensExtensionStoreModel> {
|
||||||
id: this.id,
|
constructor() {
|
||||||
name: this.name,
|
super({
|
||||||
isEnabled: this.isEnabled,
|
configName: "state"
|
||||||
}, {
|
});
|
||||||
recurseEverything: true,
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,13 +15,12 @@ import { shellSync } from "./shell-sync"
|
|||||||
import { getFreePort } from "./port"
|
import { getFreePort } from "./port"
|
||||||
import { mangleProxyEnv } from "./proxy-env"
|
import { mangleProxyEnv } from "./proxy-env"
|
||||||
import { registerFileProtocol } from "../common/register-protocol";
|
import { registerFileProtocol } from "../common/register-protocol";
|
||||||
|
import logger from "./logger"
|
||||||
import { clusterStore } from "../common/cluster-store"
|
import { clusterStore } from "../common/cluster-store"
|
||||||
import { userStore } from "../common/user-store";
|
import { userStore } from "../common/user-store";
|
||||||
import { workspaceStore } from "../common/workspace-store";
|
import { workspaceStore } from "../common/workspace-store";
|
||||||
import { appEventBus } from "../common/event-bus"
|
import { appEventBus } from "../common/event-bus"
|
||||||
import { extensionManager } from "../extensions/extension-manager";
|
|
||||||
import { extensionLoader } from "../extensions/extension-loader";
|
import { extensionLoader } from "../extensions/extension-loader";
|
||||||
import logger from "./logger"
|
|
||||||
|
|
||||||
const workingDir = path.join(app.getPath("appData"), appName);
|
const workingDir = path.join(app.getPath("appData"), appName);
|
||||||
let proxyPort: number;
|
let proxyPort: number;
|
||||||
@ -48,12 +47,11 @@ app.on("ready", async () => {
|
|||||||
|
|
||||||
registerFileProtocol("static", __static);
|
registerFileProtocol("static", __static);
|
||||||
|
|
||||||
// preload isomorphic stores
|
// preload
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
userStore.load(),
|
userStore.load(),
|
||||||
clusterStore.load(),
|
clusterStore.load(),
|
||||||
workspaceStore.load(),
|
workspaceStore.load(),
|
||||||
extensionLoader.load(),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// find free port
|
// find free port
|
||||||
@ -77,12 +75,8 @@ app.on("ready", async () => {
|
|||||||
app.exit();
|
app.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
windowManager = new WindowManager(proxyPort);
|
LensExtensionsApi.windowManager = windowManager = new WindowManager(proxyPort);
|
||||||
|
extensionLoader.init(); // call after windowManager to see splash earlier
|
||||||
LensExtensionsApi.windowManager = windowManager; // expose to extensions
|
|
||||||
extensionLoader.loadOnMain()
|
|
||||||
extensionLoader.extensions.replace(await extensionManager.load())
|
|
||||||
extensionLoader.broadcastExtensions()
|
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
appEventBus.emit({ name: "app", action: "start" })
|
appEventBus.emit({ name: "app", action: "start" })
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import { i18nStore } from "./i18n";
|
|||||||
import { themeStore } from "./theme.store";
|
import { themeStore } from "./theme.store";
|
||||||
import { App } from "./components/app";
|
import { App } from "./components/app";
|
||||||
import { LensApp } from "./lens-app";
|
import { LensApp } from "./lens-app";
|
||||||
import { extensionLoader } from "../extensions/extension-loader";
|
|
||||||
|
|
||||||
type AppComponent = React.ComponentType & {
|
type AppComponent = React.ComponentType & {
|
||||||
init?(): Promise<void>;
|
init?(): Promise<void>;
|
||||||
@ -35,7 +34,6 @@ export async function bootstrap(App: AppComponent) {
|
|||||||
userStore.load(),
|
userStore.load(),
|
||||||
workspaceStore.load(),
|
workspaceStore.load(),
|
||||||
clusterStore.load(),
|
clusterStore.load(),
|
||||||
extensionLoader.load(),
|
|
||||||
i18nStore.init(),
|
i18nStore.init(),
|
||||||
themeStore.init(),
|
themeStore.init(),
|
||||||
]);
|
]);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user