diff --git a/src/handler/plugins/plugin.ts b/src/handler/plugins/plugin.ts index 6c8b641..ad2034d 100644 --- a/src/handler/plugins/plugin.ts +++ b/src/handler/plugins/plugin.ts @@ -11,21 +11,18 @@ * Plugins are reminiscent of middleware in express. */ -import type { Awaitable, Client } from 'discord.js'; +import type { AutocompleteInteraction, Awaitable, Client, ClientEvents } from 'discord.js'; import type { Err, Ok, Result } from 'ts-results'; -import type { DefinitelyDefined, Module, Override } from '../..'; -import type { CommandType } from '../..'; -import type { - BaseModule, - EventModule, - CommandModuleDefs, - CommandModule, -} from '../structures/module'; -import { PluginType } from '../structures/enums'; +import type { CommandType, DefinitelyDefined, Override, SernEventsMapping } from '../..'; +import { EventType, PluginType } from '../..'; +import type { BaseModule, CommandModuleDefs, EventModuleDefs } from '../structures/module'; import type { EventEmitter } from 'events'; -import type { ExternalEventCommand, SernEventCommand } from '../structures/events'; +import type { + DiscordEventCommand, + ExternalEventCommand, + SernEventCommand, +} from '../structures/events'; import type SernEmitter from '../sernEmitter'; -import type { AutocompleteInteraction } from 'discord.js'; export interface Controller { next: () => Ok; @@ -53,6 +50,17 @@ export type CommandPlugin; }[T]; +export type DiscordEmitterPlugin = Override< + BasePlugin, + { + type: PluginType.Command; + execute: ( + wrapper: Client, + module: DefinitelyDefined, + controller: Controller, + ) => Awaitable>; + } +>; export type ExternalEmitterPlugin = Override< BasePlugin, { @@ -84,7 +92,7 @@ export type AutocompletePlugin = Override< execute: ( autocmp: AutocompleteInteraction, controlller: Controller, - ) => Awaitable; + ) => Awaitable>; } >; @@ -101,77 +109,74 @@ export type EventPlugin; }[T]; -// Syntactic sugar on hold -// export function plugins( -// ...plug: (EventPlugin | CommandPlugin)[] -// ) { -// return plug; -// } +export type SernEventPlugin = Override< + BasePlugin, + { + name?: T; + type: PluginType.Event; + execute: ( + args: SernEventsMapping[T], + controller: Controller, + ) => Awaitable>; + } +>; -export type ModuleNoPlugins = { - [T in keyof CommandModuleDefs]: Omit; +export type ExternalEventPlugin = Override< + BasePlugin, + { + type: PluginType.Event; + execute: (args: unknown[], controller: Controller) => Awaitable>; + } +>; + +export type DiscordEventPlugin = Override< + BasePlugin, + { + name?: T; + type: PluginType.Event; + execute: (args: ClientEvents[T], controller: Controller) => Awaitable>; + } +>; + +export type CommandModuleNoPlugins = { + [T in CommandType]: Omit; +}; +export type EventModulesNoPlugins = { + [T in EventType]: Omit; +}; +/** + * Event Module Event Plugins + */ +export type EventModuleEventPluginDefs = { + [EventType.Discord]: DiscordEventPlugin; + [EventType.Sern]: SernEventPlugin; + [EventType.External]: ExternalEventPlugin; }; -function isEventPlugin( - e: CommandPlugin | EventPlugin, -): e is EventPlugin { - return e.type === PluginType.Event; -} -function isCommandPlugin( - e: CommandPlugin | EventPlugin, -): e is CommandPlugin { - return !isEventPlugin(e); -} +/** + * Event Module Command Plugins + */ +export type EventModuleCommandPluginDefs = { + [EventType.Discord]: DiscordEmitterPlugin; + [EventType.Sern]: SernEmitterPlugin; + [EventType.External]: ExternalEmitterPlugin; +}; + +export type EventModulePlugin = + | EventModuleEventPluginDefs[T] + | EventModuleCommandPluginDefs[T]; + +export type CommandModulePlugin = EventPlugin | CommandPlugin; //TODO: I WANT BETTER TYPINGS AHHHHHHHHHHHHHHH // Maybe add overlaods -export function sernModule( - plugin: (CommandPlugin | EventPlugin)[], - mod: ModuleNoPlugins[CommandType.Slash], -): Module; -export function sernModule( - plugin: (CommandPlugin | EventPlugin)[], - mod: ModuleNoPlugins[CommandType.Text], -): Module; -export function sernModule( - plugin: (CommandPlugin | EventPlugin)[], - mod: ModuleNoPlugins[CommandType.Button], -): Module; -export function sernModule( - plugin: (CommandPlugin | EventPlugin)[], - mod: ModuleNoPlugins[CommandType.Both], -): Module; -export function sernModule( - plugin: (CommandPlugin | EventPlugin)[], - mod: ModuleNoPlugins[CommandType.MenuMsg], -): Module; -export function sernModule( - plugin: (CommandPlugin | EventPlugin)[], - mod: ModuleNoPlugins[CommandType.MenuSelect], -): Module; +/** + * User inputs this type. Sern processes behind the scenes for better usage + */ +export type InputCommandModule = { + [T in CommandType]: CommandModuleNoPlugins[T] & { plugins?: CommandModulePlugin[] }; +}[CommandType]; -export function sernModule( - plugin: (CommandPlugin | EventPlugin)[], - mod: ModuleNoPlugins[CommandType.Modal], -): Module; - -export function sernModule( - plugin: (CommandPlugin | EventPlugin)[], - mod: ModuleNoPlugins[CommandType.MenuUser], -): Module; -export function sernModule( - plugin: (CommandPlugin | EventPlugin)[], - mod: ModuleNoPlugins[T], -): CommandModule { - const onEvent = plugin.filter(isEventPlugin); - const plugins = plugin.filter(isCommandPlugin); - return { - onEvent, - plugins, - ...mod, - } as CommandModule; -} - -export function eventModule(): EventModule { - return {} as EventModule; -} +export type InputEventModule = { + [T in EventType]: EventModulesNoPlugins[T] & { plugins?: EventModulePlugin[] }; +}[EventType]; diff --git a/src/handler/sern.ts b/src/handler/sern.ts index 443a045..feaa609 100644 --- a/src/handler/sern.ts +++ b/src/handler/sern.ts @@ -6,6 +6,16 @@ import { Err, Ok } from 'ts-results'; import { ExternalEventEmitters } from './utilities/readFile'; import type { EventEmitter } from 'events'; import { processEvents } from './events/userDefinedEventsHandling'; +import type { CommandModule, EventModule } from './structures/module'; +import { EventType, PluginType } from './structures/enums'; +import type { + CommandPlugin, + EventModuleCommandPluginDefs, + EventModuleEventPluginDefs, + EventPlugin, + InputCommandModule, + InputEventModule, +} from './plugins/plugin'; /** * @@ -27,7 +37,7 @@ export function init(wrapper: Wrapper) { * @param emitter Any external event emitter. * The object will be stored in a map, and then fetched by the name of the emitter provided. * As there are infinite possibilities to adding external event emitters, - * Most types arent provided and are as narrow as possibly can. + * Most types aren't provided and are as narrow as possibly can. */ export function addExternal(emitter: T) { if (ExternalEventEmitters.has(emitter.constructor.name)) { @@ -40,3 +50,38 @@ export const controller = { next: () => Ok.EMPTY, stop: () => Err.EMPTY, }; + +export function commandModule(mod: InputCommandModule): CommandModule { + const onEvent: EventPlugin[] = []; + const plugins: CommandPlugin[] = []; + for (const pl of mod.plugins ?? []) { + if (pl.type === PluginType.Event) { + onEvent.push(pl); + } else { + plugins.push(pl as CommandPlugin); + } + } + + return { + ...mod, + onEvent, + plugins, + } as CommandModule; +} +export function eventModule(mod: InputEventModule): EventModule { + const onEvent: EventModuleEventPluginDefs[EventType][] = []; + const plugins: EventModuleCommandPluginDefs[EventType][] = []; + for (const pl of mod.plugins ?? []) { + if (pl.type === PluginType.Event) { + onEvent.push(pl); + } else { + plugins.push(pl); + } + } + + return { + ...mod, + onEvent, + plugins, + } as EventModule; +} diff --git a/src/handler/structures/events.ts b/src/handler/structures/events.ts index 590d958..dd562ab 100644 --- a/src/handler/structures/events.ts +++ b/src/handler/structures/events.ts @@ -1,7 +1,8 @@ import type { Override, SernEventsMapping } from '../../types/handler'; -import type { BaseModule, EventModuleDefs } from './module'; +import type { BaseModule } from './module'; import type { DiscordEmitterPlugin, + DiscordEventPlugin, ExternalEmitterPlugin, ExternalEventPlugin, SernEmitterPlugin, @@ -26,7 +27,7 @@ export type DiscordEventCommand; } diff --git a/src/handler/utilities/predicates.ts b/src/handler/utilities/predicates.ts index 7809902..16de674 100644 --- a/src/handler/utilities/predicates.ts +++ b/src/handler/utilities/predicates.ts @@ -88,6 +88,13 @@ export function isExternalEvent(el: EventModule): el is ExternalEventCommand { return !isDiscordEvent(el) && !isSernEvent(el); } -export function isEventModule(module: Module): module is EventModule { - return [EventType.Sern, EventType.Discord, EventType.External].includes(module.type); -} +// export function isEventPlugin( +// e: CommandModulePlugin, +// ): e is EventPlugin { +// return e.type === PluginType.Event; +// } +// export function isCommandPlugin( +// e: CommandModulePlugin, +// ): e is CommandPlugin { +// return !isEventPlugin(e); +// } diff --git a/src/index.ts b/src/index.ts index 53c36d8..8adcc3a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ import SernEmitter from './handler/sernEmitter'; +export { eventModule, commandModule } from './handler/sern'; export * as Sern from './handler/sern'; export * from './types/handler'; export * from './handler/structures/structxports';