mirror of
https://github.com/sern-handler/handler
synced 2026-06-06 01:16:55 +00:00
freeze module after plugins, updateModule, and more
This commit is contained in:
@@ -14,8 +14,8 @@ import { PayloadType, PluginType } from './structures/enums';
|
||||
import assert from 'assert';
|
||||
import type { Payload } from '../types/utility';
|
||||
|
||||
export const ok = (val: unknown) => Ok(val);
|
||||
export const err = (val: string) => Err(val);
|
||||
export const ok = (val: unknown=undefined) => Ok(val);
|
||||
export const err = (val?: string) => Err(val);
|
||||
|
||||
export function partitionPlugins<T,V>
|
||||
(arr: Array<{ type: PluginType }> = []): [T[], V[]] {
|
||||
|
||||
@@ -143,7 +143,6 @@ export function createMessageHandler(
|
||||
) {
|
||||
return createGenericHandler(source, async event => {
|
||||
const [prefix] = fmt(event.content, defaultPrefix);
|
||||
console.log(prefix)
|
||||
let module= mg.get(`${prefix}_T`) ?? mg.get(`${prefix}_B`) as Module;
|
||||
if(!module) {
|
||||
return Err('Possibly undefined behavior: could not find a static id to resolve');
|
||||
|
||||
@@ -18,18 +18,26 @@ export default async function(dir: string, deps : UnpackedDependencies) {
|
||||
// https://observablehq.com/@ehouais/multiple-promises-as-an-async-generator
|
||||
// possibly optimize to concurrently import modules
|
||||
for await (const path of Files.readRecursive(dir)) {
|
||||
const { module } = await Files.importModule<Module>(path);
|
||||
let { module } = await Files.importModule<Module>(path);
|
||||
const validType = module.type >= CommandType.Text && module.type <= CommandType.ChannelSelect;
|
||||
if(!validType) {
|
||||
throw Error(`Found ${module.name} at ${module.meta.absPath}, which has an incorrect \`type\``);
|
||||
}
|
||||
for(const plugin of module.plugins) {
|
||||
const res = await plugin.execute({ module, absPath: module.meta.absPath });
|
||||
const res = await plugin.execute({
|
||||
module,
|
||||
absPath: module.meta.absPath ,
|
||||
updateModule: (partial: Partial<Module>) => {
|
||||
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()");
|
||||
}
|
||||
}
|
||||
Object.freeze(module); // no more writing!!
|
||||
commands.set(module.meta.id, module);
|
||||
sEmitter.emit('module.register', resultPayload(PayloadType.Success, module));
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ export interface ModalSubmitCommand extends Module {
|
||||
}
|
||||
|
||||
export interface AutocompleteCommand
|
||||
extends Omit<Module, 'name' | 'type' | 'plugins' | 'description'> {
|
||||
extends Omit<Module, 'name' | 'type' | 'plugins' | 'description' | 'meta'> {
|
||||
onEvent: ControlPlugin[];
|
||||
execute: (ctx: AutocompleteInteraction) => Awaitable<unknown>;
|
||||
}
|
||||
@@ -117,21 +117,21 @@ export interface DiscordEventCommand<T extends keyof ClientEvents = keyof Client
|
||||
}
|
||||
export interface TextCommand extends Module {
|
||||
type: CommandType.Text;
|
||||
execute: (ctx: Context, args: ['text', string[]]) => Awaitable<unknown>;
|
||||
execute: (ctx: Context) => Awaitable<unknown>;
|
||||
}
|
||||
|
||||
export interface SlashCommand extends Module {
|
||||
type: CommandType.Slash;
|
||||
description: string;
|
||||
options?: SernOptionsData[];
|
||||
execute: (ctx: Context, args: ['slash', SlashOptions]) => Awaitable<unknown>;
|
||||
execute: (ctx: Context) => Awaitable<unknown>;
|
||||
}
|
||||
|
||||
export interface BothCommand extends Module {
|
||||
type: CommandType.Both;
|
||||
description: string;
|
||||
options?: SernOptionsData[];
|
||||
execute: (ctx: Context, args: Args) => Awaitable<unknown>;
|
||||
execute: (ctx: Context) => Awaitable<unknown>;
|
||||
}
|
||||
|
||||
export type EventModule = DiscordEventCommand | SernEventCommand | ExternalEventCommand | CronEventCommand;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* Plugins are reminiscent of middleware in express.
|
||||
*/
|
||||
|
||||
import type { Err, Ok } from 'ts-results-es';
|
||||
import type { Err, Ok, Result } from 'ts-results-es';
|
||||
import type {
|
||||
BothCommand,
|
||||
ButtonCommand,
|
||||
@@ -33,7 +33,7 @@ import type {
|
||||
TextCommand,
|
||||
UserSelectCommand,
|
||||
} from './core-modules';
|
||||
import type { Args, Awaitable, Payload, SlashOptions, VoidResult } from './utility';
|
||||
import type { Args, Awaitable, Payload, SlashOptions } from './utility';
|
||||
import type { CommandType, EventType, PluginType } from '../core/structures/enums'
|
||||
import type { Context } from '../core/structures/context'
|
||||
import type {
|
||||
@@ -49,11 +49,12 @@ import type {
|
||||
UserSelectMenuInteraction,
|
||||
} from 'discord.js';
|
||||
|
||||
export type PluginResult = Awaitable<VoidResult>;
|
||||
export type PluginResult = Awaitable<Result<unknown, unknown>>;
|
||||
|
||||
export interface InitArgs<T extends Processed<Module>> {
|
||||
module: T;
|
||||
absPath: string;
|
||||
updateModule: (module: Partial<T>) => T
|
||||
}
|
||||
export interface Controller {
|
||||
next: () => Ok<void>;
|
||||
@@ -73,8 +74,8 @@ export interface ControlPlugin<Args extends any[] = any[]> {
|
||||
execute: (...args: Args) => PluginResult;
|
||||
}
|
||||
|
||||
export type AnyCommandPlugin = ControlPlugin | InitPlugin<[InitArgs<Processed<CommandModule>>]>;
|
||||
export type AnyEventPlugin = ControlPlugin | InitPlugin<[InitArgs<Processed<EventModule>>]>;
|
||||
export type AnyCommandPlugin = ControlPlugin | InitPlugin<[InitArgs<Processed<Module>>]>;
|
||||
export type AnyEventPlugin = ControlPlugin | InitPlugin<[InitArgs<Processed<Module>>]>;
|
||||
|
||||
export type CommandArgs<
|
||||
I extends CommandType = CommandType,
|
||||
@@ -88,51 +89,51 @@ export type EventArgs< I extends EventType = EventType,
|
||||
interface CommandArgsMatrix {
|
||||
[CommandType.Text]: {
|
||||
[PluginType.Control]: [Context, ['text', string[]]];
|
||||
[PluginType.Init]: [InitArgs<Processed<TextCommand>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
[CommandType.Slash]: {
|
||||
[PluginType.Control]: [Context, ['slash', /* library coupled */ SlashOptions]];
|
||||
[PluginType.Init]: [InitArgs<Processed<SlashCommand>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
[CommandType.Both]: {
|
||||
[PluginType.Control]: [Context, Args];
|
||||
[PluginType.Init]: [InitArgs<Processed<BothCommand>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
[CommandType.CtxMsg]: {
|
||||
[PluginType.Control]: [/* library coupled */ MessageContextMenuCommandInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<ContextMenuMsg>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
[CommandType.CtxUser]: {
|
||||
[PluginType.Control]: [/* library coupled */ UserContextMenuCommandInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<ContextMenuUser>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
[CommandType.Button]: {
|
||||
[PluginType.Control]: [/* library coupled */ ButtonInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<ButtonCommand>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
[CommandType.StringSelect]: {
|
||||
[PluginType.Control]: [/* library coupled */ StringSelectMenuInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<StringSelectCommand>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
[CommandType.RoleSelect]: {
|
||||
[PluginType.Control]: [/* library coupled */ RoleSelectMenuInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<RoleSelectCommand>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
[CommandType.ChannelSelect]: {
|
||||
[PluginType.Control]: [/* library coupled */ ChannelSelectMenuInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<ChannelSelectCommand>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
[CommandType.MentionableSelect]: {
|
||||
[PluginType.Control]: [/* library coupled */ MentionableSelectMenuInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<MentionableSelectCommand>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
[CommandType.UserSelect]: {
|
||||
[PluginType.Control]: [/* library coupled */ UserSelectMenuInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<UserSelectCommand>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
[CommandType.Modal]: {
|
||||
[PluginType.Control]: [/* library coupled */ ModalSubmitInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<ModalSubmitCommand>>];
|
||||
[PluginType.Init]: [InitArgs<Processed<Module>>];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user