Files
factorio-clusterio/packages/ctl/src/BaseCtlPlugin.ts
T
7122cbccf8 Add typed hook system for plugins
Replace invokeHook and the per plugin on* methods with AsyncHook
collections on the controller, host, instance, clusterioctl and web
control objects. Plugin entrypoints export a default function that
receives a load context and attaches handlers to the hooks it needs.
Class exports still load through fromContext with a deprecation
warning. The create templates and docs use the entrypoint function.

This is clusterio/clusterio#921 recreated on top of master after the
ESM migration and the PluginDeclaration permissions change.

Closes #730

Co-Authored-By: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 22:49:09 +00:00

70 lines
1.8 KiB
TypeScript

import * as lib from "@clusterio/lib";
export type CtlPluginContext = lib.PluginLoadContext<{
hooks: CtlHooks
}>;
/**
* Collection of clusterioctl plugin hooks
*/
export class CtlHooks extends lib.AsyncHookCollection {
constructor(logger: lib.Logger) {
super(logger);
this.addCommands = this.newHook();
}
/**
* Called to add commands to the command line interface.
*
* Invoked by clusterioctl to let plugins add commands. `rootCommand` is
* the top level command node which the plugin should add its own {@link
* CommandTree} to.
*
* @param rootCommand -
* Root of the clusterioctl command tree.
*/
readonly addCommands: lib.AsyncHook<[rootCommand: lib.CommandTree]>;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
export interface BaseCtlPlugin {
addCommands?(rootCommand: lib.CommandTree): Promise<void>;
}
/**
* Base class for clusterioctl plugins
*
* Ctl plugins are subclasses of this class which get instantiated by
* clusterioctl in order to extend its functionallity. To be discovered the
* class must be exported under the name `CtlPlugin` in the module
* specified by the `ctlEntrypoint` in the plugin's `plugin` export.
*/
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
export class BaseCtlPlugin {
constructor(
/**
* The plugin's own info module
*/
public info: lib.PluginNodeEnvInfo,
public logger: lib.Logger,
private hooks: CtlHooks,
) {
if (this.addCommands) {
hooks.addCommands.attach(info.name, this.addCommands.bind(this));
}
}
static fromContext(context: CtlPluginContext) {
return new this(context.plugin, context.logger, context.hooks);
}
detachHooks() {
this.hooks.detachAll(this.info.name);
}
/**
* Called immediately after the class is instantiated
*/
async init() {}
}