From 99e2a997edaac1ba880e56bf782ecd1fa5e96b4c Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 29 May 2022 14:30:28 -0500 Subject: [PATCH] feat: adding better typings, refactoring --- src/handler/events/observableHandling.ts | 28 +------ src/handler/plugins/plugin.ts | 97 ++++++++++++++---------- src/handler/structures/module.ts | 46 +++++------ 3 files changed, 76 insertions(+), 95 deletions(-) diff --git a/src/handler/events/observableHandling.ts b/src/handler/events/observableHandling.ts index a5ce95c..ca74454 100644 --- a/src/handler/events/observableHandling.ts +++ b/src/handler/events/observableHandling.ts @@ -1,14 +1,8 @@ -import type { Awaitable, Message } from 'discord.js'; +import type { Message } from 'discord.js'; import { Observable, throwError } from 'rxjs'; import { SernError } from '../structures/errors'; -import type { InteractionDefs, Module, ModuleDefs } from '../structures/module'; +import type { Module, ModuleDefs } from '../structures/module'; import { correctModuleType } from '../utilities/predicates'; -import type { CommandType } from '../structures/enums'; -import type { UnionToIntersection } from '../../types/handler'; -import { controller } from '../sern'; -import type { Result } from 'ts-results'; -import type { SelectMenuInteraction } from 'discord.js'; - export function filterCorrectModule(cmdType: T) { return (src: Observable) => new Observable(subscriber => { @@ -48,21 +42,3 @@ export function ignoreNonBot(prefix: string) { }); }); } - -// export function processOnEvents(ty: T, interaction: InteractionDefs[T]) { -// return (src: Observable) => -// new Observable>>(subscriber => { -// return src.subscribe({ -// next(m) { -// subscriber.next(m.onEvent?.map(e => { -// return (>e).execute( -// [interaction as SelectMenuInteraction], //This is just to satisfy compiler -// controller, -// ); -// })) ; -// }, -// error: e => subscriber.error(e), -// complete: () => subscriber.complete(), -// }); -// }); -// } diff --git a/src/handler/plugins/plugin.ts b/src/handler/plugins/plugin.ts index ca8227d..27a815c 100644 --- a/src/handler/plugins/plugin.ts +++ b/src/handler/plugins/plugin.ts @@ -15,9 +15,8 @@ import type { Awaitable, Client } from 'discord.js'; import type { Err, Ok, Result } from 'ts-results'; import type { Module, Override } from '../..'; import { CommandType } from '../..'; -import type { BaseModule, ModuleDefs } from '../structures/module'; -import type { PluginType } from '../structures/enums'; -import type { ValueOf } from 'ts-pattern/dist/types/helpers'; +import type { AutocompleteCommand, BaseModule, ModuleDefs } from '../structures/module'; +import { PluginType } from '../structures/enums'; export interface Controller { next: () => Ok; @@ -31,31 +30,19 @@ type BasePlugin = Override< } >; -export type CommandPlugin = Override< - BasePlugin, - { - type: PluginType.Command; - execute: ( - wrapper: Client, - module: Module, - controller: Controller, - ) => Awaitable>; - } ->; - -//TODO: rn adding the modType check a little hackish. Find better way to determine the -// module type of the event plugin -// export type EventPlugin = Override< -// BasePlugin, -// { -// type: PluginType.Event; -// execute: ( -// event: Parameters, -// controller: Controller, -// ) => Awaitable>; -// } -// >; - +export type CommandPlugin = { + [K in T]: Override< + BasePlugin, + { + type: PluginType.Command; + execute: ( + wrapper: Client, + module: ModuleDefs[T], + controller: Controller, + ) => Awaitable>; + } + >; +}[T]; export type EventPlugin = { [K in T]: Override< BasePlugin, @@ -69,23 +56,53 @@ export type EventPlugin = { >; }[T]; -export function plugins(...plug: CommandPlugin[]): CommandPlugin[]; -export function plugins(...plug: EventPlugin[]): EventPlugin[]; -export function plugins(...plug: EventPlugin[] | CommandPlugin[]) { - return plug; +//Syntactic sugar on hold +// export function plugins( +// ...plug: (EventPlugin | CommandPlugin)[] +// ) { +// return plug; +// } + +type ModuleNoPlugins = { + [T in keyof ModuleDefs]: Omit; +}; + +function isEventPlugin( + e: CommandPlugin | EventPlugin, +): e is EventPlugin { + return e.type === PluginType.Event; +} +function isCommandPlugin( + e: CommandPlugin | EventPlugin, +): e is CommandPlugin { + return !isEventPlugin(e); } - -type ModuleNoPlugins = ValueOf<{ - [T in keyof ModuleDefs]: Omit; -}>; - //TODO: I WANT BETTER TYPINGS AHHHHHHHHHHHHHHH -export function sernModule(plugins: CommandPlugin[], mod: ModuleNoPlugins): Module { +export function sernModule( + plugin: (CommandPlugin | EventPlugin)[], + mod: ModuleNoPlugins[T], +): Module { + const onEvent = plugin.filter(isEventPlugin); + const plugins = plugin.filter(isCommandPlugin); if (mod.type === CommandType.Autocomplete) { - return mod; + throw new Error( + 'You cannot use this function declaration for Autocomplete Interactions! use the raw object for options or' + + 'sernAutoComplete function', + ); } else return { + onEvent, plugins, ...mod, - }; + } as Module; +} + +export function sernAutocomplete( + onEvent: EventPlugin[], + mod: Omit, +): Omit { + return { + onEvent, + ...mod, + }; } diff --git a/src/handler/structures/module.ts b/src/handler/structures/module.ts index 42b51d5..555e21a 100644 --- a/src/handler/structures/module.ts +++ b/src/handler/structures/module.ts @@ -21,7 +21,6 @@ import type Context from './context'; import { CommandType, PluginType } from './enums'; import type { AutocompleteInteraction } from 'discord.js'; import type { ApplicationCommandOptionType } from 'discord.js'; -import { ChatInputCommandInteraction, Message, User } from 'discord.js'; export interface BaseModule { type: CommandType | PluginType; @@ -35,8 +34,8 @@ export type TextCommand = Override< BaseModule, { type: CommandType.Text; - onEvent?: EventPlugin[]; - plugins?: CommandPlugin[]; + onEvent: EventPlugin[]; + plugins: CommandPlugin[]; alias?: string[]; } >; @@ -45,8 +44,8 @@ export type SlashCommand = Override< BaseModule, { type: CommandType.Slash; - onEvent?: EventPlugin[]; - plugins?: CommandPlugin[]; + onEvent: EventPlugin[]; + plugins: CommandPlugin[]; options?: SernOptionsData[]; } >; @@ -55,8 +54,8 @@ export type BothCommand = Override< BaseModule, { type: CommandType.Both; - onEvent?: EventPlugin[]; - plugins?: CommandPlugin[]; + onEvent: EventPlugin[]; + plugins: CommandPlugin[]; alias?: string[]; options?: SernOptionsData[]; } @@ -66,8 +65,8 @@ export type ContextMenuUser = Override< BaseModule, { type: CommandType.MenuUser; - onEvent?: EventPlugin[]; - plugins?: CommandPlugin[]; + onEvent: EventPlugin[]; + plugins: CommandPlugin[]; execute: (ctx: UserContextMenuCommandInteraction) => Awaitable; } >; @@ -76,8 +75,8 @@ export type ContextMenuMsg = Override< BaseModule, { type: CommandType.MenuMsg; - onEvent?: EventPlugin[]; - plugins?: CommandPlugin[]; + onEvent: EventPlugin[]; + plugins: CommandPlugin[]; execute: (ctx: MessageContextMenuCommandInteraction) => Awaitable; } >; @@ -86,8 +85,8 @@ export type ButtonCommand = Override< BaseModule, { type: CommandType.Button; - onEvent?: EventPlugin[]; - plugins?: CommandPlugin[]; + onEvent: EventPlugin[]; + plugins: CommandPlugin[]; execute: (ctx: ButtonInteraction) => Awaitable; } >; @@ -96,8 +95,8 @@ export type SelectMenuCommand = Override< BaseModule, { type: CommandType.MenuSelect; - onEvent?: EventPlugin[]; - plugins?: CommandPlugin[]; + onEvent: EventPlugin[]; + plugins: CommandPlugin[]; execute: (ctx: SelectMenuInteraction) => Awaitable; } >; @@ -106,8 +105,8 @@ export type ModalSubmitCommand = Override< BaseModule, { type: CommandType.Modal; - onEvent?: EventPlugin[]; - plugins?: CommandPlugin[]; + onEvent: EventPlugin[]; + plugins: CommandPlugin[]; execute: (ctx: ModalSubmitInteraction) => Awaitable; } >; @@ -121,7 +120,7 @@ export type AutocompleteCommand = Override< { type: CommandType.Autocomplete; name: string; - onEvent?: EventPlugin[]; + onEvent: EventPlugin[]; execute: (ctx: AutocompleteInteraction) => Awaitable; } >; @@ -150,17 +149,6 @@ export type ModuleDefs = { [CommandType.Modal]: ModalSubmitCommand; [CommandType.Autocomplete]: AutocompleteCommand; }; -export type InteractionDefs = { - [CommandType.Text]: Context; - [CommandType.Slash]: Context; - [CommandType.Both]: Context; - [CommandType.MenuMsg]: MessageContextMenuCommandInteraction; - [CommandType.MenuUser]: UserContextMenuCommandInteraction; - [CommandType.Button]: ButtonInteraction; - [CommandType.MenuSelect]: SelectMenuInteraction; - [CommandType.Modal]: ModalSubmitInteraction; - [CommandType.Autocomplete]: AutocompleteInteraction; -}; //TODO: support deeply nested Autocomplete // objective: construct union of ApplicationCommandOptionData change any Autocomplete data