-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(template)!: Improve (and add back in) the plugin system for inte…
…racting with Electron's "main" process in an easier way Refs: #1462 Refs: #1373 BREAKING-CHANGE: Plugins must now be registered in the client's `electron/plugins/index.ts` file (instead of the Telestion configuration file).
- Loading branch information
Showing
9 changed files
with
257 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
packages/telestion-client-template/template/src/electron/lifecycle-hooks/on-ready-hook.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { LifecycleHook } from '../model/lifecycle-hook'; | ||
import { Plugin } from '../model/plugin'; | ||
|
||
export class OnReadyHook implements LifecycleHook { | ||
readonly name = 'onReady'; | ||
|
||
async fn(plugins: Array<Plugin>) { | ||
await Promise.allSettled(plugins.map(this.callOnReadyHook)); | ||
} | ||
|
||
private async callOnReadyHook(plugin: Plugin) { | ||
if (!plugin.onReady || typeof plugin.onReady !== 'function') { | ||
return; | ||
} | ||
await plugin.onReady(); | ||
} | ||
} |
4 changes: 2 additions & 2 deletions
4
packages/telestion-client-template/template/src/electron/menu-builder.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 4 additions & 0 deletions
4
packages/telestion-client-template/template/src/electron/model/awaitable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/** | ||
* A value that can be awaited. | ||
*/ | ||
export type Awaitable<T> = T | Promise<T>; |
18 changes: 18 additions & 0 deletions
18
packages/telestion-client-template/template/src/electron/model/lifecycle-hook.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Plugin } from './plugin'; | ||
|
||
/** | ||
* A lifecycle hook is a function that is called when a lifecycle event occurs. | ||
*/ | ||
export interface LifecycleHook { | ||
/** | ||
* The name of the lifecycle hook. | ||
* | ||
* Used for logging purposes. | ||
*/ | ||
readonly name: string; | ||
/** | ||
* The function that is called when the lifecycle hook is executed. | ||
* @param plugins the plugins that are currently loaded | ||
*/ | ||
fn: (plugins: Plugin[]) => Promise<void> | void; | ||
} |
11 changes: 11 additions & 0 deletions
11
packages/telestion-client-template/template/src/electron/model/plugin.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/** | ||
* A plugin object containing lifecycle methods for the plugin. | ||
* | ||
* Gets managed by a {@link PluginManager}. | ||
*/ | ||
export interface Plugin { | ||
/** | ||
* A lifecycle method | ||
*/ | ||
[hook: string]: ((...args: any) => any | Promise<any>) | undefined; | ||
} |
86 changes: 86 additions & 0 deletions
86
packages/telestion-client-template/template/src/electron/plugin-manager.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { Plugin } from './model/plugin'; | ||
import { LifecycleHook } from './model/lifecycle-hook'; | ||
import { Awaitable } from './model/awaitable'; | ||
|
||
/** | ||
* The plugin manager is responsible for loading and managing plugins. | ||
* | ||
* It can be used to load plugins, and to execute lifecycle hooks. | ||
* | ||
* @see {@link LifecycleHook}, {@link Plugin} | ||
*/ | ||
export class PluginManager { | ||
/** | ||
* The plugins that are currently installed. | ||
* @private | ||
*/ | ||
private plugins: Plugin[] = []; | ||
/** | ||
* A promise that resolves when all plugins are installed. | ||
* @private | ||
*/ | ||
private _ready: Promise<any> = Promise.resolve(); | ||
|
||
/** | ||
* Creates a new plugin manager. | ||
* @param plugins the plugins to initially load | ||
*/ | ||
constructor(plugins: Awaitable<Plugin>[]) { | ||
plugins.forEach(plugin => this.installPlugin(plugin)); | ||
} | ||
|
||
/** | ||
* Installs a plugin. | ||
* | ||
* Installation is done in the background, so the plugin is not immediately available. | ||
* However, it is guaranteed that the plugin is installed before the next lifecycle hook is called. | ||
* @param plugin the plugin to install | ||
*/ | ||
installPlugin(plugin: Plugin | Promise<Plugin>): void { | ||
this._ready = Promise.allSettled([ | ||
this._ready, | ||
this.validateAndAddPlugin(plugin) | ||
]); | ||
} | ||
|
||
/** | ||
* Executes a lifecycle hook. | ||
* | ||
* This method is asynchronous and returns a promise that resolves when all plugins have executed the hook. | ||
* | ||
* Awaits any pending plugin installation completions. | ||
* @param hook the lifecycle hook to execute | ||
*/ | ||
async callHook(hook: LifecycleHook) { | ||
await this._ready; | ||
await hook.fn(this.plugins); | ||
} | ||
|
||
/** | ||
* Checks if the given object is a valid plugin. | ||
* @param plugin the object to check | ||
* @private | ||
*/ | ||
private isPlugin(plugin: unknown): plugin is Plugin { | ||
return ( | ||
typeof plugin === 'object' && | ||
plugin !== null && | ||
!Array.isArray(plugin) && | ||
!(plugin instanceof Promise) | ||
); | ||
} | ||
|
||
/** | ||
* Validates and adds a plugin to the list of installed plugins if it is a valid plugin. | ||
* Rejects the promise if the plugin is not valid. | ||
* @param plugin the plugin to validate and add | ||
* @private | ||
*/ | ||
private async validateAndAddPlugin(plugin: Plugin | Promise<Plugin>) { | ||
const pluginInstance = await plugin; | ||
if (!this.isPlugin(pluginInstance)) { | ||
throw new Error('Plugin is not a valid plugin: ' + pluginInstance); | ||
} | ||
this.plugins.push(pluginInstance); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
packages/telestion-client-template/template/src/electron/plugins/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { Plugin } from '../model/plugin'; | ||
import { Awaitable } from '../model/awaitable'; | ||
|
||
/** | ||
* The plugins that get loaded into the Electron main process. | ||
*/ | ||
export const plugins: Awaitable<Plugin>[] = [ | ||
// Add your plugins here: | ||
// require('./my-plugin'), | ||
require('./test-plugin') | ||
]; |
6 changes: 6 additions & 0 deletions
6
packages/telestion-client-template/template/src/electron/plugins/test-plugin.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export function onReady() { | ||
// Do something when the application is ready | ||
console.log('Application is ready'); | ||
} | ||
|
||
export const name = 'app'; |