Skip to content

Commit

Permalink
refactor: rm deprecations, clean up, rm indirection
Browse files Browse the repository at this point in the history
  • Loading branch information
jacoobes committed Feb 13, 2024
1 parent 45cbda7 commit ac7f47c
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 114 deletions.
8 changes: 4 additions & 4 deletions src/core/contracts/module-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
2 changes: 1 addition & 1 deletion src/core/contracts/module-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
}
11 changes: 11 additions & 0 deletions src/core/ioc/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 1 addition & 2 deletions src/core/ioc/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'])};
});
}

Expand Down
50 changes: 0 additions & 50 deletions src/core/modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
}
2 changes: 1 addition & 1 deletion src/core/structures/module-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>();
}
17 changes: 7 additions & 10 deletions src/core/structures/services/module-manager.ts
Original file line number Diff line number Diff line change
@@ -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';
/**
Expand All @@ -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 {
Expand All @@ -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);
}
}
5 changes: 1 addition & 4 deletions src/handlers/dispatchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[]) {
Expand Down
53 changes: 24 additions & 29 deletions src/handlers/event-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
MonoTypeOperatorFunction,
catchError,
finalize,
map,
} from 'rxjs';
import {
Files,
Expand Down Expand Up @@ -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 }));
});
}

Expand All @@ -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),
}
}
});
}

Expand All @@ -135,7 +130,7 @@ export function buildModules<T extends AnyModule>(
) {
return Files
.buildModuleStream<Processed<T>>(input)
.pipe(assignDefaults(moduleManager));
.pipe(assignDefaults());
}


Expand Down Expand Up @@ -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;
},
}),
);
Expand Down
19 changes: 11 additions & 8 deletions src/handlers/ready-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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));
});
}
Expand All @@ -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));
}
6 changes: 1 addition & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,8 @@ export {
commandModule,
eventModule,
discordEvent,
EventExecutable,
CommandExecutable,
} from './core/modules';

export * as Presence from './core/presences'

export {
useContainerRaw
} from './core/_internal'

0 comments on commit ac7f47c

Please sign in to comment.