jan/web/plugin/PluginManager.ts
Louis 96dba2690d feat: class-based plugin manager
chore: add facades

refactor: core module export

refactor: inference plugin - deprecate function registering (#537)

* refactor: revamp inference plugin as class - deprecate function registering

* refactor: monitoring plugin - deprecate service registering (#538)

refactor: revamp inference plugin as class - deprecate function registering

chore: update import

refactor: plugin revamp - model management

chore: update build steps and remove experimental plugins

refactor: remove pluggable electron

chore: add sorting for conversations

chore: build plugins for testing

chore: consistent plugin directory name

chore: docs

chore: fix CI

chore: update conversation prefix
2023-11-06 13:46:01 +07:00

151 lines
3.9 KiB
TypeScript

import { JanPlugin, PluginType } from '@janhq/core'
import Plugin from './Plugin'
/**
* Manages the registration and retrieval of plugins.
*/
export class PluginManager {
// MARK: - Plugin Manager
private plugins = new Map<PluginType, JanPlugin>()
/**
* Registers a plugin.
* @param plugin - The plugin to register.
*/
register<T extends JanPlugin>(plugin: T) {
this.plugins.set(plugin.type(), plugin)
}
/**
* Retrieves a plugin by its type.
* @param type - The type of the plugin to retrieve.
* @returns The plugin, if found.
*/
get<T extends JanPlugin>(type: PluginType): T | undefined {
return this.plugins.get(type) as T | undefined
}
/**
* Loads all registered plugins.
*/
load() {
this.listPlugins().forEach((plugin) => {
plugin.onLoad()
})
}
/**
* Unloads all registered plugins.
*/
unload() {
this.listPlugins().forEach((plugin) => {
plugin.onUnload()
})
}
/**
* Retrieves a list of all registered plugins.
* @returns An array of all registered plugins.
*/
listPlugins() {
return [...this.plugins.values()]
}
/**
* Retrieves a list of all registered plugins.
* @returns An array of all registered plugins.
*/
async getActive(): Promise<Plugin[]> {
const plgList = await window.pluggableElectronIpc?.getActive()
let plugins: Plugin[] = plgList.map(
(plugin: any) =>
new Plugin(
plugin.name,
plugin.url,
plugin.activationPoints,
plugin.active,
plugin.description,
plugin.version,
plugin.icon
)
)
return plugins
}
/**
* Register a plugin with its class.
* @param {Plugin} plugin plugin object as provided by the main process.
* @returns {void}
*/
async activatePlugin(plugin: Plugin) {
if (plugin.url)
// Import class
await import(/* webpackIgnore: true */ plugin.url).then((pluginClass) => {
// Register class if it has a default export
if (
typeof pluginClass.default === 'function' &&
pluginClass.default.prototype
) {
this.register(new pluginClass.default())
}
})
}
// MARK: - Plugin Facades
/**
* Registers all active plugins.
* @returns {void}
*/
async registerActive() {
// Get active plugins
const plugins = await this.getActive()
// Activate all
await Promise.all(
plugins.map((plugin: Plugin) => this.activatePlugin(plugin))
)
}
/**
* Install a new plugin.
* @param {Array.<installOptions | string>} plugins A list of NPM specifiers, or installation configuration objects.
* @returns {Promise.<Array.<Plugin> | false>} plugin as defined by the main process. Has property cancelled set to true if installation was cancelled in the main process.
* @alias plugins.install
*/
async install(plugins: any[]) {
if (typeof window === 'undefined') {
return
}
const plgList = await window.pluggableElectronIpc?.install(plugins)
if (plgList.cancelled) return false
return plgList.map(async (plg: any) => {
const plugin = new Plugin(
plg.name,
plg.url,
plg.activationPoints,
plg.active
)
await this.activatePlugin(plugin)
return plugin
})
}
/**
* Uninstall provided plugins
* @param {Array.<string>} plugins List of names of plugins to uninstall.
* @param {boolean} reload Whether to reload all renderers after updating the plugins.
* @returns {Promise.<boolean>} Whether uninstalling the plugins was successful.
* @alias plugins.uninstall
*/
uninstall(plugins: string[], reload = true) {
if (typeof window === 'undefined') {
return
}
return window.pluggableElectronIpc?.uninstall(plugins, reload)
}
}
/**
* The singleton instance of the PluginManager.
*/
export const pluginManager = new PluginManager()