From e0f6a4cd16ab5cf6fea0dbe5b9f6a88871c3cf4a Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 20 May 2024 12:21:18 -0500 Subject: [PATCH] initplugins inject deps, inconspicuos --- src/core/create-plugins.ts | 25 ++-------------- src/core/functions.ts | 44 +++++++++++++---------------- src/core/modules.ts | 10 ++----- src/core/structures/context.ts | 23 ++++++++------- src/handlers/event-utils.ts | 31 ++++++++++++-------- src/handlers/message.ts | 2 +- src/handlers/ready.ts | 16 ++--------- src/handlers/user-defined-events.ts | 20 ++----------- src/index.ts | 3 +- src/types/core-modules.ts | 6 ++-- src/types/core-plugin.ts | 17 +++-------- 11 files changed, 68 insertions(+), 129 deletions(-) diff --git a/src/core/create-plugins.ts b/src/core/create-plugins.ts index 4bcf269..3f9d759 100644 --- a/src/core/create-plugins.ts +++ b/src/core/create-plugins.ts @@ -1,6 +1,5 @@ -import { CommandType, EventType, PluginType } from './structures/enums'; -import type { Plugin, PluginResult, EventArgs, CommandArgs, InitArgs } from '../types/core-plugin'; -import type { ClientEvents } from 'discord.js'; +import { CommandType, PluginType } from './structures/enums'; +import type { Plugin, PluginResult, CommandArgs, InitArgs } from '../types/core-plugin'; import { err, ok } from './functions'; export function makePlugin( @@ -31,27 +30,7 @@ export function CommandControlPlugin( ) { return makePlugin(PluginType.Control, execute); } -/** - * @since 2.5.0 - */ -export function EventControlPlugin( - execute: (...args: EventArgs) => PluginResult, -) { - return makePlugin(PluginType.Control, execute); -} -/** - * @since 2.5.0 - * @Experimental - * A specialized function for creating control plugins with discord.js ClientEvents. - * Will probably be moved one day! - */ -export function DiscordEventControlPlugin( - name: T, - execute: (...args: ClientEvents[T]) => PluginResult, -) { - return makePlugin(PluginType.Control, execute); -} /** * @since 1.0.0 diff --git a/src/core/functions.ts b/src/core/functions.ts index 02ef466..20ccb43 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -46,37 +46,31 @@ export function treeSearch( while (_options.length > 0) { const cur = _options.pop()!; switch (cur.type) { - case ApplicationCommandOptionType.Subcommand: - { + case ApplicationCommandOptionType.Subcommand: { subcommands.add(cur.name); for (const option of cur.options ?? []) _options.push(option); - } - break; - case ApplicationCommandOptionType.SubcommandGroup: - { + } break; + case ApplicationCommandOptionType.SubcommandGroup: { for (const command of cur.options ?? []) _options.push(command); - } - break; - default: - { - if ('autocomplete' in cur && cur.autocomplete) { - const choice = iAutocomplete.options.getFocused(true); - assert( 'command' in cur, 'No `command` property found for option ' + cur.name); - if (subcommands.size > 0) { - const parent = iAutocomplete.options.getSubcommand(); - const parentAndOptionMatches = - subcommands.has(parent) && cur.name === choice.name; - if (parentAndOptionMatches) { - return { ...cur, parent }; - } - } else { - if (cur.name === choice.name) { - return { ...cur, parent: undefined }; - } + } break; + default: { + if ('autocomplete' in cur && cur.autocomplete) { + const choice = iAutocomplete.options.getFocused(true); + assert( 'command' in cur, 'No `command` property found for option ' + cur.name); + if (subcommands.size > 0) { + const parent = iAutocomplete.options.getSubcommand(); + const parentAndOptionMatches = + subcommands.has(parent) && cur.name === choice.name; + if (parentAndOptionMatches) { + return { ...cur, parent }; + } + } else { + if (cur.name === choice.name) { + return { ...cur, parent: undefined }; } } } - break; + } break; } } } diff --git a/src/core/modules.ts b/src/core/modules.ts index 3e13c67..06d1bf1 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -1,6 +1,5 @@ import type { ClientEvents } from 'discord.js'; import { EventType } from '../core/structures/enums'; -import type { AnyEventPlugin, } from '../types/core-plugin'; import type { InputCommand, InputEvent, @@ -21,18 +20,14 @@ export function commandModule(mod: InputCommand): Module { plugins, } as Module; } + /** * @since 1.0.0 * The wrapper function to define event modules for sern * @param mod */ export function eventModule(mod: InputEvent): Module { - const [onEvent, plugins] = partitionPlugins(mod.plugins); - return { - ...mod, - plugins, - onEvent, - } as Module; + return mod as Module; } /** Create event modules from discord.js client events, @@ -43,7 +38,6 @@ export function eventModule(mod: InputEvent): Module { */ export function discordEvent(mod: { name: T; - plugins?: AnyEventPlugin[]; execute: (...args: ClientEvents[T]) => Awaitable; }) { return eventModule({ type: EventType.Discord, ...mod, }); diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index f3aa159..40292df 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -24,25 +24,26 @@ function fmt(msg: string, prefix?: string): string[] { * Message and ChatInputCommandInteraction */ export class Context extends CoreContext { - prefix: string|undefined; get options() { return this.interaction.options; } - args() { - return { - message: () => { + args(type: 'message'|'interaction', parser?: Function) { + switch(type) { + case 'message': { const [, ...rest] = fmt(this.message.content, this.prefix); - return rest as T; - }, - interaction: () => this.interaction.options + return rest; + }; + case 'interaction': { + return this.interaction.options; + }; } } - protected constructor(protected ctx: Result, prefix?: string) { + protected constructor(protected ctx: Result, + public prefix?: string) { super(ctx); - this.prefix = prefix } public get id(): Snowflake { @@ -52,9 +53,7 @@ export class Context extends CoreContext { } public get channel() { - return safeUnwrap(this.ctx - .map(m => m.channel) - .mapErr(i => i.channel)); + return safeUnwrap(this.ctx.map(m => m.channel).mapErr(i => i.channel)); } public get channelId(): Snowflake { diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 34264d5..edfa9a5 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -17,7 +17,7 @@ import * as Id from '../core/id' import type { Emitter } from '../core/interfaces'; import { PayloadType, SernError } from '../core/structures/enums' import { Err, Ok, Result } from 'ts-results-es'; -import type { UnpackedDependencies, VoidResult } from '../types/utility'; +import type { UnpackedDependencies } from '../types/utility'; import type { CommandModule, Module, Processed } from '../types/core-modules'; import * as assert from 'node:assert'; import { Context } from '../core/structures/context'; @@ -36,15 +36,9 @@ interface ExecutePayload { function intoPayload(module: Module, deps: Dependencies) { return pipe(map(arrayifySource), - map(args => ({ module, args, deps }))); + map(args => ({ module, args, deps })), + map(p => p.args)); } -const createResult = (deps: Dependencies) => - createResultResolver({ - onNext: (p) => p.args, - onStop: (module) => { - //maybe do something when plugins fail? - } - }); /** * Creates an observable from { source } * @param module @@ -60,7 +54,6 @@ export function eventDispatcher(deps: Dependencies, module: Module, source: unkn //@ts-ignore return fromEvent(source, module.name!) .pipe(intoPayload(module, deps), - concatMap(createResult(deps)), execute); } @@ -218,7 +211,23 @@ export function createResultResolver(config: { } }; }; - +export async function callInitPlugins(module: Module, deps: Dependencies, sEmitter?: Emitter) { + for(const plugin of module.plugins) { + const res = await plugin.execute({ + module, + absPath: module.meta.absPath , + updateModule: (partial: Partial) => { + module = { ...module, ...partial }; + return module; + }, + deps + }); + if(res.isErr()) { + sEmitter?.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); + throw Error("Plugin failed with controller.stop()"); + } + } +} async function callPlugins({ args, module, deps }: ExecutePayload) { let state = {}; for(const plugin of module.onEvent) { diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 6863f74..2739e9d 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -17,7 +17,7 @@ function isNonBot(prefix: string) { function hasPrefix(prefix: string, content: string) { const prefixInContent = content.slice(0, prefix.length); - return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0); + return prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0; } export default function ( diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 503301c..e7cf010 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -5,6 +5,7 @@ import { PayloadType } from '..'; import { CommandType, SernError } from '../core/structures/enums'; import { Module } from '../types/core-modules'; import { UnpackedDependencies } from '../types/utility'; +import { callInitPlugins } from './event-utils'; export default async function(dir: string, deps : UnpackedDependencies) { const { '@sern/client': client, @@ -23,20 +24,7 @@ export default async function(dir: string, deps : UnpackedDependencies) { if(!validType) { throw Error(`Found ${module.name} at ${module.meta.absPath}, which has incorrect \`type\``); } - for(const plugin of module.plugins) { - const res = await plugin.execute({ - module, - absPath: module.meta.absPath , - updateModule: (partial: Partial) => { - module = { ...module, ...partial }; - return module; - } - }); - if(res.isErr()) { - sEmitter.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); - throw Error("Plugin failed with controller.stop()"); - } - } + await callInitPlugins(module, deps, sEmitter); // FREEZE! no more writing!! commands.set(module.meta.id, Object.freeze(module)); sEmitter.emit('module.register', resultPayload(PayloadType.Success, module)); diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index f6276da..fecee05 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -1,9 +1,8 @@ -import { EventType, PayloadType, SernError } from '../core/structures/enums'; -import { eventDispatcher, handleCrash } from './event-utils' +import { EventType, SernError } from '../core/structures/enums'; +import { callInitPlugins, eventDispatcher, handleCrash } from './event-utils' import { EventModule, Module } from '../types/core-modules'; import * as Files from '../core/module-loading' import type { UnpackedDependencies } from '../types/utility'; -import { resultPayload } from '../core/functions'; import { from, map, mergeAll } from 'rxjs'; const intoDispatcher = (deps: UnpackedDependencies) => @@ -29,20 +28,7 @@ export default async function(deps: UnpackedDependencies, eventDir: string) { const eventModules: EventModule[] = []; for await (const path of Files.readRecursive(eventDir)) { let { module } = await Files.importModule(path); - for(const plugin of module.plugins) { - const res = await plugin.execute({ - module, - absPath: module.meta.absPath, - updateModule: (partial: Partial) => { - module = { ...module, ...partial }; - return module; - } - }); - if(res.isErr()) { - deps['@sern/emitter'].emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); - throw Error("Plugin failed with controller.stop()"); - } - } + await callInitPlugins(module, deps) eventModules.push(module as EventModule); } from(eventModules) diff --git a/src/index.ts b/src/index.ts index 624de27..96db42d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,8 +32,7 @@ export type { InitPlugin, ControlPlugin, Plugin, - AnyEventPlugin, - AnyCommandPlugin, + AnyPlugin, } from './types/core-plugin'; diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index c09f89f..ca618ca 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -17,7 +17,7 @@ import type { } from 'discord.js'; import type { CommandType, EventType } from '../core/structures/enums'; import { Context } from '../core/structures/context' -import { AnyCommandPlugin, AnyEventPlugin, ControlPlugin, InitPlugin } from './core-plugin'; +import { AnyPlugin, ControlPlugin, InitPlugin } from './core-plugin'; import { Awaitable, SernEventsMapping } from './utility'; type ToBeDecided = { @@ -193,12 +193,12 @@ type EventModulesNoPlugins = { }; export type InputEvent = { - [T in EventType]: EventModulesNoPlugins[T] & { plugins?: AnyEventPlugin[] }; + [T in EventType]: EventModulesNoPlugins[T]; }[EventType]; export type InputCommand = { [T in CommandType]: CommandModuleNoPlugins[T] & { - plugins?: AnyCommandPlugin[]; + plugins?: AnyPlugin[]; }; }[CommandType]; diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 108d243..d0bc067 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -16,13 +16,12 @@ import type { Module, Processed, } from './core-modules'; -import type { Awaitable, Payload } from './utility'; -import type { CommandType, EventType, PluginType } from '../core/structures/enums' +import type { Awaitable } from './utility'; +import type { CommandType, PluginType } from '../core/structures/enums' import type { Context } from '../core/structures/context' import type { ButtonInteraction, ChannelSelectMenuInteraction, - ClientEvents, MentionableSelectMenuInteraction, MessageContextMenuCommandInteraction, ModalSubmitInteraction, @@ -37,6 +36,7 @@ export type PluginResult = Awaitable>; export interface InitArgs = Processed> { module: T; absPath: string; + deps: Dependencies updateModule: (module: Partial) => T } export interface Controller { @@ -57,11 +57,9 @@ export interface ControlPlugin { execute: (...args: Args) => PluginResult; } -export type AnyCommandPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; -export type AnyEventPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; +export type AnyPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; export type CommandArgs = CommandArgsMatrix[I] -export type EventArgs = EventArgsMatrix[I] interface CommandArgsMatrix { [CommandType.Text]: [Context]; @@ -77,10 +75,3 @@ interface CommandArgsMatrix { [CommandType.UserSelect]: [UserSelectMenuInteraction]; [CommandType.Modal]: [ModalSubmitInteraction]; } - -interface EventArgsMatrix { - [EventType.Discord]: ClientEvents[keyof ClientEvents]; - [EventType.Sern]: [Payload]; - [EventType.External]: unknown[]; - [EventType.Cron]: unknown[]; -}