diff --git a/lib/plugins/src/_internal/decorators.ts b/lib/plugins/src/_internal/decorators.ts index c0a1317..387bcf8 100644 --- a/lib/plugins/src/_internal/decorators.ts +++ b/lib/plugins/src/_internal/decorators.ts @@ -1,32 +1,22 @@ import { getPluginDependencies, pMetadata } from '.' -import type { - InitPluginApi, - Plugin, - PluginApi, - PreInitPluginApi, -} from '../types' +import type { Plugin, PluginApiDecorator } from '../types' import type { AnyPlugin, InternalPluginMeta } from '.' -export type PluginApiDecoratorStore< - A extends PreInitPluginApi | InitPluginApi | PluginApi, -> = WeakMap[0][]> +export type PluginApiDecoratorStore = + WeakMap[]> // Set of plugins that will always decorate the API of every other plugin. export const pImplicitDeps = new Set() -export const pDecoratorsPreInit: PluginApiDecoratorStore = - new WeakMap() - -export const pDecoratorsInit: PluginApiDecoratorStore = - new WeakMap() - -export const pDecoratorsStart: PluginApiDecoratorStore = +export const pDecoratorsPreInit: PluginApiDecoratorStore<'PreInit'> = new WeakMap() +export const pDecoratorsInit: PluginApiDecoratorStore<'Init'> = new WeakMap() +export const pDecoratorsStart: PluginApiDecoratorStore<'Start'> = new WeakMap() export function addPluginApiDecorator( store: PluginApiDecoratorStore, plugin: AnyPlugin, - decorator: Parameters['decorate']>[0], + decorator: PluginApiDecorator, ) { let list = store.get(plugin) if (!list) { @@ -38,9 +28,7 @@ export function addPluginApiDecorator( } export function decoratePluginApi( - store: PluginApiDecoratorStore< - PreInitPluginApi | InitPluginApi | PluginApi - >, + store: PluginApiDecoratorStore, plugin: Plugin, meta: InternalPluginMeta, ) { diff --git a/lib/plugins/src/constants.ts b/lib/plugins/src/constants.ts index c87111f..7a2129c 100644 --- a/lib/plugins/src/constants.ts +++ b/lib/plugins/src/constants.ts @@ -1,3 +1,6 @@ +/** + * The plugin flags. + */ export const PluginFlags = { /** * The plugin is enabled. @@ -18,6 +21,9 @@ export const PluginFlags = { EnabledLate: 1 << 3, } +/** + * The plugin status. + */ export const PluginStatus = { PreIniting: 1 << 0, PreInited: 1 << 1, diff --git a/lib/plugins/src/types.ts b/lib/plugins/src/types.ts index d5028a0..6d74aa7 100644 --- a/lib/plugins/src/types.ts +++ b/lib/plugins/src/types.ts @@ -39,9 +39,62 @@ export interface UnscopedPluginApi< O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, > extends UnscopedInitPluginApi {} +/** + * A cleanup function that can be registered to be called when the plugin is stopped. + */ export type PluginCleanup = () => any +/** + * Registers cleanup functions to be called when the plugin is stopped. + * + * @example + * ```ts + * cleanup(unpatch) + * cleanup(unsub) + * ``` + */ export type PluginCleanupApi = (...fns: PluginCleanup[]) => void +/** + * Decorates the plugin API for the dependents of the plugin with a decorator function. + * @param decorator The decorator function to apply. + * + * @example + * ```ts + * // Your plugin's `init` function: + * init({ decorate }) { + * decorate((plugin, options) => { + * plugin.api.customMethod = () => { + * console.log('Custom method called!') + * } + * }) + * } + * + * // In another plugin, with your plugin as a dependency: + * init({ customMethod }) { + * customMethod() // Logs: "Custom method called!" + * } + * ``` + */ +export type PluginDecorateApi< + O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, + S extends + keyof PluginApiInLifecycleMap = keyof PluginApiInLifecycleMap, +> = (decorator: PluginApiDecorator) => void + +/** + * The decorator function that modifies the plugin API. + * + * @param plugin The plugin being decorated. + * @param options The options the plugin passed. + * + * @see {@link PluginDecorateApi} + */ +export type PluginApiDecorator< + O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, + S extends + keyof PluginApiInLifecycleMap = keyof PluginApiInLifecycleMap, +> = (plugin: Plugin, options: O) => void + /** * The plugin API (very limited). * Available in the `preInit` phase. @@ -49,9 +102,7 @@ export type PluginCleanupApi = (...fns: PluginCleanup[]) => void export interface PreInitPluginApi< O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, > { - decorate( - decorator: (plugin: Plugin, options: O) => void, - ): void + decorate: PluginDecorateApi unscoped: UnscopedPreInitPluginApi cleanup: PluginCleanupApi plugin: Plugin @@ -65,7 +116,7 @@ export interface PreInitPluginApi< export interface InitPluginApi< O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, > extends PreInitPluginApi { - decorate(decorator: (plugin: Plugin, options: O) => void): void + decorate: PluginDecorateApi unscoped: UnscopedInitPluginApi } @@ -77,7 +128,7 @@ export interface InitPluginApi< export interface PluginApi< O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, > extends InitPluginApi { - decorate(decorator: (plugin: Plugin, options: O) => void): void + decorate: PluginDecorateApi unscoped: UnscopedPluginApi } @@ -97,6 +148,9 @@ export interface PluginApi< // url: string // } +/** + * The plugin manifest. + */ export interface PluginManifest { /** * The unique identifier for the plugin. @@ -142,6 +196,9 @@ export interface PluginOptions< SettingsComponent?: PluginSettingsComponent } +/** + * The plugin lifecycles. + */ export interface PluginLifecycles< O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, > { @@ -175,29 +232,22 @@ export interface PluginLifecycles< export interface Plugin< O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, - S extends keyof PluginApiInStage = keyof PluginApiInStage, + S extends + keyof PluginApiInLifecycleMap = keyof PluginApiInLifecycleMap, > { // TODO(plugins): support plugin bundles // /** // * The plugin bundle this plugin belongs to. // */ // bundle: PluginBundle - /** - * The plugin manifest. - */ manifest: PluginManifest - /** - * The plugin lifecycles. - */ lifecycles: PluginLifecycles /** - * The plugin flags. * @see {@link PluginFlags} */ flags: number /** - * The plugin status. * @see {@link PluginStatus} */ status: number @@ -206,13 +256,11 @@ export interface Plugin< */ errors: unknown[] - /** - * The plugin settings page. - */ SettingsComponent?: PluginSettingsComponent /** - * Disable the plugin. This will also stop the plugin if it is running. + * Disable the plugin. + * This will also stop the plugin if it is running. */ disable(): Promise /** @@ -225,16 +273,24 @@ export interface Plugin< * * Not recommended to use this directly. */ - api: PluginApiInStage[S] + api: PluginApiInLifecycleMap[S] } -type PluginApiInStage = { +/** + * The plugin API in a specific stage. + */ +export type PluginApiInLifecycleMap< + O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, +> = { Register: undefined PreInit: PreInitPluginApi Init: InitPluginApi Start: PluginApi } +/** + * The component that renders the plugin settings page. + */ export interface PluginSettingsComponent< O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, > extends FunctionComponent<{ api: PluginApi }> {}