UNPKG

@sern/handler

Version:

A complete, customizable, typesafe, & reactive framework for discord bots.

121 lines (120 loc) 4.88 kB
import { CommandType, PluginType } from './structures/enums'; import type { Plugin, PluginResult, CommandArgs, InitArgs } from '../types/core-plugin'; import type { Dictionary } from '../types/utility'; export declare function makePlugin<V extends unknown[]>(type: PluginType, execute: (...args: any[]) => any): Plugin<V>; /** * @since 2.5.0 */ export declare function EventInitPlugin(execute: (args: InitArgs) => PluginResult): Plugin<unknown[]>; /** * Creates an initialization plugin for command preprocessing and modification * * @since 2.5.0 * @template I - Extends CommandType to enforce type safety for command modules * * @param {function} execute - Function to execute during command initialization * @param {InitArgs<T>} execute.args - The initialization arguments * @param {T} execute.args.module - The command module being initialized * @param {string} execute.args.absPath - The absolute path to the module file * @param {Dependencies} execute.args.deps - Dependency injection container * * @returns {Plugin} A plugin that runs during command initialization * * @example * // Plugin to update command description * export const updateDescription = (description: string) => { * return CommandInitPlugin(({ deps }) => { * if(description.length > 100) { * deps.logger?.info({ message: "Invalid description" }) * return controller.stop("From updateDescription: description is invalid"); * } * module.description = description; * return controller.next(); * }); * }; * * @example * // Plugin to store registration date in module locals * export const dateRegistered = () => { * return CommandInitPlugin(({ module }) => { * module.locals.registered = Date.now() * return controller.next(); * }); * }; * * @remarks * - Init plugins can modify how commands are loaded and perform preprocessing * - The module.locals object can be used to store custom plugin-specific data * - Be careful when modifying module fields as multiple plugins may interact with them * - Use controller.next() to continue to the next plugin * - Use controller.stop(reason) to halt plugin execution */ export declare function CommandInitPlugin<I extends CommandType>(execute: (args: InitArgs) => PluginResult): Plugin; /** * Creates a control plugin for command preprocessing, filtering, and state management * * @since 2.5.0 * @template I - Extends CommandType to enforce type safety for command modules * * @param {function} execute - Function to execute during command control flow * @param {CommandArgs<I>} execute.args - The command arguments array * @param {Context} execute.args[0] - The discord context (e.g., guild, channel, user info, interaction) * @param {SDT} execute.args[1] - The State, Dependencies, Params, Module, and Type object * * @returns {Plugin} A plugin that runs during command execution flow * * @example * // Plugin to restrict command to specific guild * export const inGuild = (guildId: string) => { * return CommandControlPlugin((ctx, sdt) => { * if(ctx.guild.id !== guildId) { * return controller.stop(); * } * return controller.next(); * }); * }; * * @example * // Plugins passing state through the chain * const plugin1 = CommandControlPlugin((ctx, sdt) => { * return controller.next({ 'plugin1/data': 'from plugin1' }); * }); * * const plugin2 = CommandControlPlugin((ctx, sdt) => { * return controller.next({ 'plugin2/data': ctx.user.id }); * }); * * export default commandModule({ * type: CommandType.Slash, * plugins: [plugin1, plugin2], * execute: (ctx, sdt) => { * console.log(sdt.state); // Access accumulated state * } * }); * * @remarks * - Control plugins are executed in order when a discord.js event is emitted * - Use controller.next() to continue to next plugin or controller.stop() to halt execution * - State can be passed between plugins using controller.next({ key: value }) * - State keys should be namespaced to avoid collisions (e.g., 'plugin-name/key') * - Final accumulated state is passed to the command's execute function * - All plugins must succeed for the command to execute * - Plugins have access to dependencies through the sdt.deps object * - Useful for implementing preconditions, filters, and command preprocessing */ export declare function CommandControlPlugin<I extends CommandType>(execute: (...args: CommandArgs<I>) => PluginResult): Plugin<unknown[]>; /** * @since 1.0.0 * The object passed into every plugin to control a command's behavior */ export declare const controller: { next: (val?: Dictionary) => { readonly ok: true; readonly value: Dictionary | undefined; }; stop: (val?: string) => { readonly ok: false; readonly error: string | undefined; }; }; export type Controller = typeof controller;