1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

extensions-api -- in-progress

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2020-09-01 13:20:49 +03:00
parent e56f8f3362
commit ed123e2819
5 changed files with 64 additions and 13 deletions

View File

@ -0,0 +1,3 @@
# Lens Example Extension
*TODO*: add more info

View File

@ -1,6 +1,6 @@
import { LensExtension } from "@lens"; // todo: handle runtime import import { LensExtension } from "@lens"; // todo: handle runtime import
export class ExampleExtension extends LensExtension { export default class ExampleExtension extends LensExtension {
async init(): Promise<any> { async init(): Promise<any> {
console.log('Example extension: init') console.log('Example extension: init')
return super.init(); return super.init();

View File

@ -1,11 +1,10 @@
import path from "path"; import path from "path";
import { action, observable, toJS } from "mobx"; import fs from "fs-extra";
import { action, comparer, observable, toJS } from "mobx";
import { BaseStore } from "../common/base-store"; import { BaseStore } from "../common/base-store";
import { LensExtension } from "./extension"; import { ExtensionId, ExtensionVersion, LensExtension } from "./extension";
import { isDevelopment } from "../common/vars"; import { isDevelopment } from "../common/vars";
import logger from "../main/logger";
export type ExtensionId = string;
export type ExtensionVersion = string | number;
export interface ExtensionStoreModel { export interface ExtensionStoreModel {
version: ExtensionVersion; version: ExtensionVersion;
@ -16,6 +15,7 @@ export interface ExtensionModel {
id: ExtensionId; id: ExtensionId;
version: ExtensionVersion; version: ExtensionVersion;
name: string; name: string;
manifestPath: string;
description?: string; description?: string;
enabled?: boolean; enabled?: boolean;
updateUrl?: string; updateUrl?: string;
@ -31,6 +31,21 @@ export class ExtensionStore extends BaseStore<ExtensionStoreModel> {
@observable version: ExtensionVersion = "0.0.0"; @observable version: ExtensionVersion = "0.0.0";
@observable extensions = observable.map<ExtensionId, LensExtension>(); @observable extensions = observable.map<ExtensionId, LensExtension>();
@observable removed = observable.map<ExtensionId, LensExtension>(); @observable removed = observable.map<ExtensionId, LensExtension>();
@observable installed = observable.set<LensExtension>([], { equals: comparer.shallow });
async load() {
await this.loadExtensions();
return super.load();
}
async loadExtensions() {
const localExtensions = await fs.readdir(this.builtInExtensionsPath);
logger.info(`[EXTENSIONS]: scanning installed extensions`, { paths: localExtensions });
this.installed.replace(localExtensions as any[]);
// return localExtensions
// .filter(path => ![".", ".."].includes(path))
// .map(path => import(`${path}/package.json`));
}
get builtInExtensionsPath(): string { get builtInExtensionsPath(): string {
if (isDevelopment) { if (isDevelopment) {

View File

@ -1,5 +1,8 @@
import { observable } from "mobx"; import { readJsonSync } from "fs-extra";
import { action, observable, when } from "mobx";
import { ExtensionModel } from "./extension-store"; import { ExtensionModel } from "./extension-store";
import extensionManifest from "./example-extension/package.json"
import logger from "../main/logger";
// TODO: extensions api // TODO: extensions api
// * Lazy load/unload extension (js/ts?) (from sources: local folder, npm_modules/@lens/some_plugin, etc.) // * Lazy load/unload extension (js/ts?) (from sources: local folder, npm_modules/@lens/some_plugin, etc.)
@ -9,27 +12,41 @@ import { ExtensionModel } from "./extension-store";
export type ExtensionId = string; export type ExtensionId = string;
export type ExtensionVersion = string | number; export type ExtensionVersion = string | number;
export type ExtensionManifest = typeof extensionManifest;
export class LensExtension implements ExtensionModel { export class LensExtension implements ExtensionModel {
public id: ExtensionId; public id: ExtensionId;
public version: string | number;
public updateUrl: string; public updateUrl: string;
@observable name = ""; @observable name = "";
@observable description = ""; @observable description = "";
@observable version: ExtensionVersion = "0.0.0";
@observable manifest: ExtensionManifest;
@observable manifestPath: string;
@observable isReady = false;
@observable isEnabled = false; @observable isEnabled = false;
@observable isInstalled = false;
whenReady = when(() => this.isReady);
constructor(model: ExtensionModel) { constructor(model: ExtensionModel) {
this.importModel(model); this.importModel(model);
} }
importModel({ enabled, ...model }: ExtensionModel) { @action
Object.assign(this, model); async importModel({ enabled, manifestPath, ...model }: ExtensionModel) {
this.isEnabled = enabled; try {
this.manifest = await readJsonSync(manifestPath, { throws: true })
this.manifestPath = manifestPath;
this.isEnabled = enabled;
Object.assign(this, model);
this.isReady = true;
} catch (err) {
logger.error(`[EXTENSION]: cannot read manifest at ${manifestPath}`, { ...model, err: String(err) })
this.disable();
}
} }
async init(){ async init() {
// todo? // todo?
} }
@ -46,10 +63,24 @@ export class LensExtension implements ExtensionModel {
} }
async enable() { async enable() {
this.isEnabled = true;
// todo // todo
} }
async disable() { async disable() {
this.isEnabled = false;
// todo // todo
} }
toJSON(): ExtensionModel {
return {
id: this.id,
name: this.name,
version: this.version,
description: this.description,
manifestPath: this.manifestPath,
enabled: this.isEnabled,
updateUrl: this.updateUrl,
}
}
} }

View File

@ -4,6 +4,7 @@ import { render } from "react-dom";
import { isMac } from "../common/vars"; import { isMac } from "../common/vars";
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 { extensionStore } from "../extensions/extension-store";
import { clusterStore, getHostedClusterId } from "../common/cluster-store"; import { clusterStore, getHostedClusterId } from "../common/cluster-store";
import { i18nStore } from "./i18n"; import { i18nStore } from "./i18n";
import { themeStore } from "./theme.store"; import { themeStore } from "./theme.store";
@ -23,6 +24,7 @@ export async function bootstrap(App: AppComponent) {
userStore.load(), userStore.load(),
workspaceStore.load(), workspaceStore.load(),
clusterStore.load(), clusterStore.load(),
extensionStore.load(),
i18nStore.init(), i18nStore.init(),
themeStore.init(), themeStore.init(),
]); ]);