feat: adding better typings, refactoring

This commit is contained in:
Jacob Nguyen
2022-05-29 14:30:28 -05:00
parent 475b0736d5
commit 99e2a997ed
3 changed files with 76 additions and 95 deletions

View File

@@ -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<T extends keyof ModuleDefs>(cmdType: T) {
return (src: Observable<Module | undefined>) =>
new Observable<ModuleDefs[T]>(subscriber => {
@@ -48,21 +42,3 @@ export function ignoreNonBot(prefix: string) {
});
});
}
// export function processOnEvents<T extends CommandType>(ty: T, interaction: InteractionDefs[T]) {
// return (src: Observable<ModuleDefs[T]>) =>
// new Observable<Awaitable<Result<void, void>>>(subscriber => {
// return src.subscribe({
// next(m) {
// subscriber.next(m.onEvent?.map(e => {
// return (<UnionToIntersection<typeof e>>e).execute(
// [interaction as SelectMenuInteraction], //This is just to satisfy compiler
// controller,
// );
// })) ;
// },
// error: e => subscriber.error(e),
// complete: () => subscriber.complete(),
// });
// });
// }

View File

@@ -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<void>;
@@ -31,31 +30,19 @@ type BasePlugin = Override<
}
>;
export type CommandPlugin = Override<
BasePlugin,
{
type: PluginType.Command;
execute: (
wrapper: Client,
module: Module,
controller: Controller,
) => Awaitable<Result<void, void>>;
}
>;
//TODO: rn adding the modType check a little hackish. Find better way to determine the
// module type of the event plugin
// export type EventPlugin<T extends keyof ModuleDefs> = Override<
// BasePlugin,
// {
// type: PluginType.Event;
// execute: (
// event: Parameters<ModuleDefs[T]['execute']>,
// controller: Controller,
// ) => Awaitable<Result<void, void>>;
// }
// >;
export type CommandPlugin<T extends keyof ModuleDefs = keyof ModuleDefs> = {
[K in T]: Override<
BasePlugin,
{
type: PluginType.Command;
execute: (
wrapper: Client,
module: ModuleDefs[T],
controller: Controller,
) => Awaitable<Result<void, void>>;
}
>;
}[T];
export type EventPlugin<T extends keyof ModuleDefs = keyof ModuleDefs> = {
[K in T]: Override<
BasePlugin,
@@ -69,23 +56,53 @@ export type EventPlugin<T extends keyof ModuleDefs = keyof ModuleDefs> = {
>;
}[T];
export function plugins(...plug: CommandPlugin[]): CommandPlugin[];
export function plugins<T extends keyof ModuleDefs>(...plug: EventPlugin<T>[]): EventPlugin<T>[];
export function plugins<T extends keyof ModuleDefs>(...plug: EventPlugin<T>[] | CommandPlugin[]) {
return plug;
//Syntactic sugar on hold
// export function plugins<T extends keyof ModuleDefs>(
// ...plug: (EventPlugin<T> | CommandPlugin<T>)[]
// ) {
// return plug;
// }
type ModuleNoPlugins = {
[T in keyof ModuleDefs]: Omit<ModuleDefs[T], 'plugins' | 'onEvent'>;
};
function isEventPlugin<T extends CommandType>(
e: CommandPlugin<T> | EventPlugin<T>,
): e is EventPlugin<T> {
return e.type === PluginType.Event;
}
function isCommandPlugin<T extends CommandType>(
e: CommandPlugin<T> | EventPlugin<T>,
): e is CommandPlugin<T> {
return !isEventPlugin(e);
}
type ModuleNoPlugins = ValueOf<{
[T in keyof ModuleDefs]: Omit<ModuleDefs[T], 'plugins'>;
}>;
//TODO: I WANT BETTER TYPINGS AHHHHHHHHHHHHHHH
export function sernModule(plugins: CommandPlugin[], mod: ModuleNoPlugins): Module {
export function sernModule<T extends CommandType>(
plugin: (CommandPlugin<T> | EventPlugin<T>)[],
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<CommandType.Autocomplete>[],
mod: Omit<AutocompleteCommand, 'type' | 'name' | 'description' | 'onEvent'>,
): Omit<AutocompleteCommand, 'type' | 'name' | 'description'> {
return {
onEvent,
...mod,
};
}

View File

@@ -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<CommandType.Text>[];
plugins?: CommandPlugin[];
onEvent: EventPlugin<CommandType.Text>[];
plugins: CommandPlugin[];
alias?: string[];
}
>;
@@ -45,8 +44,8 @@ export type SlashCommand = Override<
BaseModule,
{
type: CommandType.Slash;
onEvent?: EventPlugin<CommandType.Slash>[];
plugins?: CommandPlugin[];
onEvent: EventPlugin<CommandType.Slash>[];
plugins: CommandPlugin[];
options?: SernOptionsData[];
}
>;
@@ -55,8 +54,8 @@ export type BothCommand = Override<
BaseModule,
{
type: CommandType.Both;
onEvent?: EventPlugin<CommandType.Both>[];
plugins?: CommandPlugin[];
onEvent: EventPlugin<CommandType.Both>[];
plugins: CommandPlugin[];
alias?: string[];
options?: SernOptionsData[];
}
@@ -66,8 +65,8 @@ export type ContextMenuUser = Override<
BaseModule,
{
type: CommandType.MenuUser;
onEvent?: EventPlugin<CommandType.MenuUser>[];
plugins?: CommandPlugin[];
onEvent: EventPlugin<CommandType.MenuUser>[];
plugins: CommandPlugin[];
execute: (ctx: UserContextMenuCommandInteraction) => Awaitable<void>;
}
>;
@@ -76,8 +75,8 @@ export type ContextMenuMsg = Override<
BaseModule,
{
type: CommandType.MenuMsg;
onEvent?: EventPlugin<CommandType.MenuMsg>[];
plugins?: CommandPlugin[];
onEvent: EventPlugin<CommandType.MenuMsg>[];
plugins: CommandPlugin[];
execute: (ctx: MessageContextMenuCommandInteraction) => Awaitable<void>;
}
>;
@@ -86,8 +85,8 @@ export type ButtonCommand = Override<
BaseModule,
{
type: CommandType.Button;
onEvent?: EventPlugin<CommandType.Button>[];
plugins?: CommandPlugin[];
onEvent: EventPlugin<CommandType.Button>[];
plugins: CommandPlugin[];
execute: (ctx: ButtonInteraction) => Awaitable<void>;
}
>;
@@ -96,8 +95,8 @@ export type SelectMenuCommand = Override<
BaseModule,
{
type: CommandType.MenuSelect;
onEvent?: EventPlugin<CommandType.MenuSelect>[];
plugins?: CommandPlugin[];
onEvent: EventPlugin<CommandType.MenuSelect>[];
plugins: CommandPlugin[];
execute: (ctx: SelectMenuInteraction) => Awaitable<void>;
}
>;
@@ -106,8 +105,8 @@ export type ModalSubmitCommand = Override<
BaseModule,
{
type: CommandType.Modal;
onEvent?: EventPlugin<CommandType.Modal>[];
plugins?: CommandPlugin[];
onEvent: EventPlugin<CommandType.Modal>[];
plugins: CommandPlugin[];
execute: (ctx: ModalSubmitInteraction) => Awaitable<void>;
}
>;
@@ -121,7 +120,7 @@ export type AutocompleteCommand = Override<
{
type: CommandType.Autocomplete;
name: string;
onEvent?: EventPlugin<CommandType.Autocomplete>[];
onEvent: EventPlugin<CommandType.Autocomplete>[];
execute: (ctx: AutocompleteInteraction) => Awaitable<void>;
}
>;
@@ -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