fix: plugins for class modules and module loader

This commit is contained in:
Jacob Nguyen
2023-05-18 11:49:14 -05:00
parent 8f39fc0896
commit f2b53dac32
4 changed files with 29 additions and 41 deletions

View File

@@ -5,27 +5,29 @@ import { type Observable, from, mergeMap, ObservableInput } from 'rxjs';
import { readdir, stat } from 'fs/promises';
import { basename, extname, join, resolve } from 'path';
import { ImportPayload } from '../handler/types';
import * as assert from 'node:assert';
import { clazz } from '../handler/commands';
import { CommandExecutable, clazz } from '../handler/commands';
export type ModuleResult<T> = Promise<Result<ImportPayload<T>, SernError>>;
function isClassModule(m: unknown): m is typeof CommandExecutable {
return m != undefined && Reflect.has(m, clazz);
}
export async function importModule<T>(absPath: string) {
let module =
/// #if MODE === 'esm'
return import(absPath).then(i => i.default as T);
import(absPath).then(i => i.default); // eslint-disable-line
/// #elif MODE === 'cjs'
return require(absPath).default as T; // eslint-disable-line
require(absPath).default; // eslint-disable-line
/// #endif
return module.then(m => isClassModule(m) ? m.getInstance():m) as T;
}
export async function defaultModuleLoader<T extends Module>(absPath: string): ModuleResult<T> {
let module = await importModule<T>(absPath);
if (module === undefined) {
return Err(SernError.UndefinedModule);
}
if(Reflect.has(module, clazz)) {
//@ts-ignore
module = module.getInstance();
}
//todo readd class modules
return Ok({ module, absPath });
}

View File

@@ -1,3 +1,4 @@
import { clazz } from '../../../handler/commands';
import { CoreModuleStore, ModuleManager } from '../../contracts';
import { importModule } from '../../module-loading';
import { CommandMeta, CommandModule, Module } from '../../types/modules';
@@ -36,8 +37,8 @@ export class DefaultModuleManager implements ModuleManager {
const publishable = 0b000000110;
return Promise.all(
Array.from(entries)
.filter(([id]) => (Number.parseInt(id.at(-1)!) & publishable) !== 0)
.map(([, path]) => importModule<CommandModule>(path)),
.filter(([id]) => !(Number.parseInt(id.at(-1)!) & publishable))
.map(([, path]) => importModule<CommandModule>(path))
);
}
}

View File

@@ -1,7 +1,7 @@
import { ClientEvents } from 'discord.js';
import { CommandType, EventType, PluginType } from '../core/structures';
import { AnyCommandPlugin, AnyEventPlugin, CommandArgs, ControlPlugin, EventArgs } from '../core/types/plugins';
import { CommandModule, EventModule, InputCommand, InputEvent } from '../core/types/modules';
import { AnyCommandPlugin, AnyEventPlugin, CommandArgs, ControlPlugin, EventArgs, InitPlugin } from '../core/types/plugins';
import { CommandModule, EventModule, InputCommand, InputEvent, Module } from '../core/types/modules';
import { partitionPlugins } from '../core/functions';
import { Awaitable } from '../shared';
@@ -27,9 +27,9 @@ export function commandModule(mod: InputCommand): CommandModule {
export function eventModule(mod: InputEvent): EventModule {
const [onEvent, plugins] = partitionPlugins(mod.plugins);
return {
onEvent,
plugins,
...mod,
plugins,
onEvent
} as EventModule;
}
@@ -50,7 +50,11 @@ export function discordEvent<T extends keyof ClientEvents>(mod: {
});
}
function prepareClassPlugins(c: Module) {
const [onEvent, initPlugins] = partitionPlugins(c.plugins);
c.plugins = initPlugins as InitPlugin[];
c.onEvent = onEvent as ControlPlugin[];
}
//
// Class modules:
// Can be refactored.
@@ -59,27 +63,17 @@ export function discordEvent<T extends keyof ClientEvents>(mod: {
* @Experimental
* Will be refactored / changed in future
*/
export abstract class CommandExecutable<const Type extends CommandType> {
export abstract class CommandExecutable<const Type extends CommandType = CommandType> {
abstract type: Type;
plugins?: AnyCommandPlugin[];
onEvent?: ControlPlugin[]
plugins: AnyCommandPlugin[] = [];
private static _instance : CommandModule;
static readonly [clazz] = true;
constructor() {
if(this.onEvent) {
console.warn('Put control plugins in `onEvent` into the `plugins` field, as it\'s automatically handled in v3.');
} else {
const [onEvent, plugins] = partitionPlugins(this.plugins);
this.plugins = plugins as AnyCommandPlugin[];
Reflect.set(this, 'onEvent', onEvent);
}
}
static getInstance() {
if (!CommandExecutable._instance) {
//@ts-ignore
CommandExecutable._instance = new this();
prepareClassPlugins(CommandExecutable._instance);
}
return CommandExecutable._instance;
}
@@ -94,23 +88,14 @@ export abstract class CommandExecutable<const Type extends CommandType> {
*/
export abstract class EventExecutable<Type extends EventType> {
abstract type: Type;
plugins?: AnyEventPlugin[];
plugins: AnyEventPlugin[] = [];
static readonly [clazz] = true;
onEvent?: ControlPlugin[]
private static _instance : EventModule;
constructor() {
if(this.onEvent) {
console.warn('Put control plugins in `onEvent` into the `plugins` field, as it\'s automatically handled in v3.');
} else {
const [onEvent, plugins] = partitionPlugins(this.plugins);
this.plugins = plugins as AnyEventPlugin[];
Reflect.set(this, 'onEvent', onEvent);
}
}
static getInstance() {
if (!EventExecutable._instance) {
//@ts-ignore
EventExecutable._instance = new this();
prepareClassPlugins(EventExecutable._instance);
}
return EventExecutable._instance;
}

View File

@@ -30,7 +30,7 @@ export function startReadyEvent(
.subscribe(module => {
const result = registerModule(moduleManager, module);
if (result.err) {
throw Error(SernError.InvalidModuleType);
throw Error(SernError.InvalidModuleType + " " + result.val);
}
});
}
@@ -42,7 +42,7 @@ function registerModule<T extends Processed<AnyModule>>(
const { id, fullPath } = manager.getMetadata(module);
assert.ok(module.type > 0 && module.type < 1<<10, `Found ${module}, which does not have a valid type`);
assert.ok(module.type > 0 && module.type < 1<<10, `Found ${module.name} at ${fullPath}, which does not have a valid type`);
if (module.type === CommandType.Both
|| module.type === CommandType.Text
) {