mirror of
https://github.com/sern-handler/handler
synced 2026-06-06 01:16:55 +00:00
refactor: rm deprecations, clean up, rm indirection
This commit is contained in:
@@ -16,12 +16,12 @@ interface MetadataAccess {
|
||||
* @internal - direct access to the module manager will be removed in version 4
|
||||
*/
|
||||
export interface ModuleManager extends MetadataAccess {
|
||||
get(id: string): string | undefined;
|
||||
get(id: string): Module | undefined;
|
||||
|
||||
set(id: string, path: string): void;
|
||||
getPublishableCommands(): Promise<CommandModule[]>;
|
||||
set(id: string, path: Module): void;
|
||||
getPublishableCommands(): CommandModule[];
|
||||
getByNameCommandType<T extends CommandType>(
|
||||
name: string,
|
||||
commandType: T,
|
||||
): Promise<CommandModuleDefs[T]> | undefined;
|
||||
): CommandModuleDefs[T] | undefined;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ import type { CommandMeta, Module } from '../../types/core-modules';
|
||||
* Represents a core module store that stores IDs mapped to file paths.
|
||||
*/
|
||||
export interface CoreModuleStore {
|
||||
commands: Map<string, string>;
|
||||
commands: Map<string, Module>;
|
||||
metadata: WeakMap<Module, CommandMeta>;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,17 @@ import type { Logging } from '../contracts/logging';
|
||||
//SIDE EFFECT: GLOBAL DI
|
||||
let containerSubject: CoreContainer<Partial<Dependencies>>;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Don't use this unless you know what you're doing. Destroys old containerSubject if it exists and disposes everything
|
||||
* then it will swap
|
||||
*/
|
||||
export async function __swap_container(c: CoreContainer<Partial<Dependencies>>) {
|
||||
if(containerSubject) {
|
||||
await containerSubject.disposeAll()
|
||||
}
|
||||
containerSubject = c;
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
* Returns the underlying data structure holding all dependencies.
|
||||
|
||||
@@ -27,8 +27,7 @@ export class CoreContainer<T extends Partial<Dependencies>> extends Container<T,
|
||||
'@sern/emitter': () => new EventEmitter({ captureRejections: true }),
|
||||
'@sern/store': () => new ModuleStore })
|
||||
.add(ctx => {
|
||||
return { '@sern/modules': () =>
|
||||
new DefaultServices.DefaultModuleManager(ctx['@sern/store']) };
|
||||
return { '@sern/modules': new DefaultServices.DefaultModuleManager(ctx['@sern/store'])};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -61,53 +61,3 @@ export function discordEvent<T extends keyof ClientEvents>(mod: {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
function prepareClassPlugins(c: Module) {
|
||||
const [onEvent, initPlugins] = partitionPlugins(c.plugins);
|
||||
c.plugins = initPlugins as InitPlugin[];
|
||||
c.onEvent = onEvent as ControlPlugin[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Will be removed in future
|
||||
*/
|
||||
export abstract class CommandExecutable<const Type extends CommandType = CommandType> {
|
||||
abstract type: Type;
|
||||
plugins: AnyCommandPlugin[] = [];
|
||||
private static _instance: CommandModule;
|
||||
|
||||
static getInstance() {
|
||||
if (!CommandExecutable._instance) {
|
||||
//@ts-ignore
|
||||
CommandExecutable._instance = new this();
|
||||
prepareClassPlugins(CommandExecutable._instance);
|
||||
}
|
||||
return CommandExecutable._instance;
|
||||
}
|
||||
|
||||
abstract execute(...args: CommandArgs<Type, PluginType.Control>): Awaitable<unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Will be removed in future
|
||||
*/
|
||||
export abstract class EventExecutable<Type extends EventType> {
|
||||
abstract type: Type;
|
||||
plugins: AnyEventPlugin[] = [];
|
||||
|
||||
private static _instance: EventModule;
|
||||
static getInstance() {
|
||||
if (!EventExecutable._instance) {
|
||||
//@ts-ignore
|
||||
EventExecutable._instance = new this();
|
||||
prepareClassPlugins(EventExecutable._instance);
|
||||
}
|
||||
return EventExecutable._instance;
|
||||
}
|
||||
abstract execute(...args: EventArgs<Type, PluginType.Control>): Awaitable<unknown>;
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@ import { CommandMeta, Module } from '../../types/core-modules';
|
||||
*/
|
||||
export class ModuleStore {
|
||||
metadata = new WeakMap<Module, CommandMeta>();
|
||||
commands = new Map<string, string>();
|
||||
commands = new Map<string, Module>();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import * as Id from '../../../core/id';
|
||||
import { CoreModuleStore, ModuleManager } from '../../contracts';
|
||||
import { Files } from '../../_internal';
|
||||
import { CommandMeta, CommandModule, CommandModuleDefs, Module } from '../../../types/core-modules';
|
||||
import { CommandType } from '../enums';
|
||||
/**
|
||||
@@ -13,11 +12,11 @@ export class DefaultModuleManager implements ModuleManager {
|
||||
|
||||
|
||||
getByNameCommandType<T extends CommandType>(name: string, commandType: T) {
|
||||
const id = this.get(Id.create(name, commandType));
|
||||
if (!id) {
|
||||
const module = this.get(Id.create(name, commandType));
|
||||
if (!module) {
|
||||
return undefined;
|
||||
}
|
||||
return Files.importModule<CommandModuleDefs[T]>(id);
|
||||
return module as CommandModuleDefs[T];
|
||||
}
|
||||
|
||||
setMetadata(m: Module, c: CommandMeta): void {
|
||||
@@ -35,20 +34,18 @@ export class DefaultModuleManager implements ModuleManager {
|
||||
get(id: string) {
|
||||
return this.moduleStore.commands.get(id);
|
||||
}
|
||||
set(id: string, path: string): void {
|
||||
set(id: string, path: CommandModule): void {
|
||||
this.moduleStore.commands.set(id, path);
|
||||
}
|
||||
//not tested
|
||||
getPublishableCommands(): Promise<CommandModule[]> {
|
||||
getPublishableCommands(): CommandModule[] {
|
||||
const entries = this.moduleStore.commands.entries();
|
||||
const publishable = 0b000000110;
|
||||
return Promise.all(
|
||||
Array.from(entries)
|
||||
return Array.from(entries)
|
||||
.filter(([id]) => {
|
||||
const last_entry = id.at(-1);
|
||||
return last_entry == 'B' || !(publishable & Number.parseInt(last_entry!));
|
||||
})
|
||||
.map(([, path]) => Files.importModule<CommandModule>(path)),
|
||||
);
|
||||
.map(([, path]) => path as CommandModule);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,7 @@ import type { CommandModule, Module, Processed } from '../types/core-modules';
|
||||
|
||||
//TODO: refactor dispatchers so that it implements a strategy for each different type of payload?
|
||||
export function dispatchMessage(module: Processed<CommandModule>, args: [Context, Args]) {
|
||||
return {
|
||||
module,
|
||||
args,
|
||||
};
|
||||
return { module, args };
|
||||
}
|
||||
|
||||
export function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[]) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
MonoTypeOperatorFunction,
|
||||
catchError,
|
||||
finalize,
|
||||
map,
|
||||
} from 'rxjs';
|
||||
import {
|
||||
Files,
|
||||
@@ -74,18 +75,13 @@ export function createInteractionHandler<T extends Interaction>(
|
||||
const possibleIds = Id.reconstruct(event);
|
||||
let fullPaths= possibleIds
|
||||
.map(id => mg.get(id))
|
||||
.filter((id): id is string => id !== undefined);
|
||||
.filter((id): id is Module => id !== undefined);
|
||||
|
||||
if(fullPaths.length == 0) {
|
||||
return Err.EMPTY;
|
||||
}
|
||||
const [ path ] = fullPaths;
|
||||
return Files
|
||||
.defaultModuleLoader<Processed<CommandModule>>(path)
|
||||
.then(payload => Ok(createDispatcher({
|
||||
module: payload.module,
|
||||
event,
|
||||
})));
|
||||
return Ok(createDispatcher({ module: path as Processed<CommandModule>, event }));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -103,29 +99,28 @@ export function createMessageHandler(
|
||||
return Err('Possibly undefined behavior: could not find a static id to resolve');
|
||||
}
|
||||
}
|
||||
return Files
|
||||
.defaultModuleLoader<Processed<CommandModule>>(fullPath)
|
||||
.then(payload => {
|
||||
const args = contextArgs(event, rest);
|
||||
return Ok({ args, ...payload });
|
||||
});
|
||||
return Ok({ args: contextArgs(event, rest), module: fullPath as Processed<CommandModule> })
|
||||
});
|
||||
}
|
||||
/**
|
||||
* IMPURE SIDE EFFECT
|
||||
* This function assigns remaining, incomplete data to each imported module.
|
||||
*/
|
||||
function assignDefaults<T extends Module>(
|
||||
moduleManager: ModuleManager,
|
||||
): MonoTypeOperatorFunction<ImportPayload<T>> {
|
||||
return tap(({ module, absPath }) => {
|
||||
module.name ??= Files.filename(absPath);
|
||||
module.description ??= '...';
|
||||
moduleManager.setMetadata(module, {
|
||||
isClass: module.constructor.name === 'Function',
|
||||
fullPath: absPath,
|
||||
id: Id.create(module.name, module.type),
|
||||
});
|
||||
function assignDefaults<T extends Module>() {
|
||||
return map(({ module, absPath }) => {
|
||||
const processed = {
|
||||
name: module.name ?? Files.filename(absPath),
|
||||
description: module.description ?? '...',
|
||||
...module
|
||||
}
|
||||
return {
|
||||
module: processed,
|
||||
absPath,
|
||||
metadata: {
|
||||
isClass: module.constructor.name === 'Function',
|
||||
fullPath: absPath,
|
||||
id: Id.create(processed.name, module.type),
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -135,7 +130,7 @@ export function buildModules<T extends AnyModule>(
|
||||
) {
|
||||
return Files
|
||||
.buildModuleStream<Processed<T>>(input)
|
||||
.pipe(assignDefaults(moduleManager));
|
||||
.pipe(assignDefaults());
|
||||
}
|
||||
|
||||
|
||||
@@ -219,9 +214,9 @@ export function callInitPlugins<T extends Processed<AnyModule>>(sernEmitter: Emi
|
||||
onStop: (module: T) => {
|
||||
sernEmitter.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure));
|
||||
},
|
||||
onNext: ({ module }) => {
|
||||
sernEmitter.emit('module.register', resultPayload(PayloadType.Success, module));
|
||||
return { module };
|
||||
onNext: (payload) => {
|
||||
sernEmitter.emit('module.register', resultPayload(PayloadType.Success, payload.module));
|
||||
return payload;
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { buildModules, callInitPlugins } from './_internal';
|
||||
import * as assert from 'node:assert';
|
||||
import * as util from 'node:util';
|
||||
import type { DependencyList } from '../types/ioc';
|
||||
import type { AnyModule, Processed } from '../types/core-modules';
|
||||
import type { AnyModule, CommandMeta, Processed } from '../types/core-modules';
|
||||
|
||||
export function readyHandler(
|
||||
[sEmitter, , , moduleManager, client]: DependencyList,
|
||||
@@ -17,8 +17,8 @@ export function readyHandler(
|
||||
|
||||
return concat(ready$, buildModules<AnyModule>(allPaths, moduleManager))
|
||||
.pipe(callInitPlugins(sEmitter))
|
||||
.subscribe(({ module }) => {
|
||||
register(moduleManager, module)
|
||||
.subscribe(({ module, metadata }) => {
|
||||
register(moduleManager, module, metadata)
|
||||
.expect(SernError.InvalidModuleType + ' ' + util.inspect(module));
|
||||
});
|
||||
}
|
||||
@@ -31,20 +31,23 @@ const once = () => pipe(
|
||||
function register<T extends Processed<AnyModule>>(
|
||||
manager: ModuleManager,
|
||||
module: T,
|
||||
metadata: unknown
|
||||
): Result<void, void> {
|
||||
const { id, fullPath } = manager.getMetadata(module)!;
|
||||
manager.setMetadata(module, metadata as CommandMeta)!;
|
||||
|
||||
const validModuleType = module.type >= 0 && module.type <= 1 << 10;
|
||||
assert.ok(
|
||||
validModuleType,
|
||||
`Found ${module.name} at ${fullPath}, which does not have a valid type`,
|
||||
//@ts-ignore
|
||||
`Found ${module.name} at ${metadata.fullPath}, which does not have a valid type`,
|
||||
);
|
||||
if (module.type === CommandType.Both) {
|
||||
module.alias?.forEach(a => manager.set(`${a}_B`, fullPath));
|
||||
module.alias?.forEach(a => manager.set(`${a}_B`, module));
|
||||
} else {
|
||||
if(module.type === CommandType.Text){
|
||||
module.alias?.forEach(a => manager.set(`${a}_T`, fullPath));
|
||||
module.alias?.forEach(a => manager.set(`${a}_T`, module));
|
||||
}
|
||||
}
|
||||
return Result.wrap(() => manager.set(id, fullPath));
|
||||
//@ts-ignore
|
||||
return Result.wrap(() => manager.set(metadata.id, module));
|
||||
}
|
||||
|
||||
@@ -46,12 +46,8 @@ export {
|
||||
commandModule,
|
||||
eventModule,
|
||||
discordEvent,
|
||||
EventExecutable,
|
||||
CommandExecutable,
|
||||
} from './core/modules';
|
||||
|
||||
export * as Presence from './core/presences'
|
||||
|
||||
export {
|
||||
useContainerRaw
|
||||
} from './core/_internal'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user