Skip to content

Commit

Permalink
feat: add function types for ModuleEventHandler
Browse files Browse the repository at this point in the history
introduces setEvent, updates tests to include isUnconfiguredHandler
also updates eslintrc to fix a tiny oversight
  • Loading branch information
zapteryx committed Nov 10, 2023
1 parent 68576a9 commit fea324a
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 7 deletions.
10 changes: 9 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@
"yoda": "error",
"@typescript-eslint/no-shadow": ["error", { "allow": ["err", "resolve", "reject"] }],
"@typescript-eslint/explicit-function-return-type": ["error", { "allowTypedFunctionExpressions": false }],
"@typescript-eslint/consistent-type-imports": ["error"]
"@typescript-eslint/consistent-type-imports": ["error"],
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_"
}
]
}
}
3 changes: 2 additions & 1 deletion src/ModuleHandlers/ModuleBaseHandler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {
AcceptedEventTypes,
ModuleAutocompleteHandler,
ModuleButtonHandler,
ModuleCommandHandler,
Expand Down Expand Up @@ -44,7 +45,7 @@ export abstract class ModuleBaseHandler {
* Checks if this handler is an event handler.
* @returns Whether this handler is an event handler.
*/
isEventHandler(): this is ModuleEventHandler {
isEventHandler(): this is ModuleEventHandler<AcceptedEventTypes> {
return this.type === 'ModuleEventHandler';
}

Expand Down
31 changes: 28 additions & 3 deletions src/ModuleHandlers/ModuleEventHandler.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import type { ClientEvents } from 'discord.js';
import {
ModuleBaseHandler,
type GenericExecuteFunction,
} from './ModuleBaseHandler.js';

export class ModuleEventHandler extends ModuleBaseHandler {
type GenericEventExecuteFunction<K extends keyof ClientEvents> = (
...args: ClientEvents[K]
) => Promise<void> | void;

export type AcceptedEventTypes = keyof ClientEvents | string | symbol;

export class ModuleEventHandler<
E extends AcceptedEventTypes,
> extends ModuleBaseHandler {
once = false;
execute: GenericExecuteFunction;
execute: GenericEventExecuteFunction<keyof ClientEvents>;

/**
* Set whether this event handler should only be called once.
Expand All @@ -17,7 +26,23 @@ export class ModuleEventHandler extends ModuleBaseHandler {
return this;
}

setExecute(execute: GenericExecuteFunction): this {
/**
* Sets the event for this handler.
* @param _event - The event.
* @returns This instance for chaining.
*/
setEvent<K extends keyof ClientEvents>(_event: K): ModuleEventHandler<K> {
const newInstance = new ModuleEventHandler<K>();
newInstance.once = this.once;
newInstance.execute = this.execute;
return newInstance;
}

setExecute(
execute: E extends keyof ClientEvents
? GenericEventExecuteFunction<E>
: GenericExecuteFunction,
): this {
this.execute = execute;
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ describe('ModuleAutocompleteHandler class', (): void => {
);
});
test('all other typecheck methods return false', (): void => {
expect(new ModuleAutocompleteHandler().isUnconfiguredHandler()).toBe(
false,
);
expect(new ModuleAutocompleteHandler().isEventHandler()).toBe(false);
expect(new ModuleAutocompleteHandler().isButtonHandler()).toBe(false);
expect(new ModuleAutocompleteHandler().isCommandHandler()).toBe(false);
Expand Down
1 change: 1 addition & 0 deletions src/ModuleHandlers/__tests__/ModuleButtonHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ describe('ModuleButtonHandler class', (): void => {
expect(new ModuleButtonHandler().isButtonHandler()).toBe(true);
});
test('all other typecheck methods return false', (): void => {
expect(new ModuleButtonHandler().isUnconfiguredHandler()).toBe(false);
expect(new ModuleButtonHandler().isEventHandler()).toBe(false);
expect(new ModuleButtonHandler().isAutocompleteHandler()).toBe(false);
expect(new ModuleButtonHandler().isCommandHandler()).toBe(false);
Expand Down
1 change: 1 addition & 0 deletions src/ModuleHandlers/__tests__/ModuleCommandHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ describe('ModuleCommandHandler class', (): void => {
expect(new ModuleCommandHandler().isCommandHandler()).toBe(true);
});
test('all other typecheck methods return false', (): void => {
expect(new ModuleCommandHandler().isUnconfiguredHandler()).toBe(false);
expect(new ModuleCommandHandler().isEventHandler()).toBe(false);
expect(new ModuleCommandHandler().isAutocompleteHandler()).toBe(false);
expect(new ModuleCommandHandler().isButtonHandler()).toBe(false);
Expand Down
29 changes: 29 additions & 0 deletions src/ModuleHandlers/__tests__/ModuleEventHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,35 @@ describe('ModuleEventHandler class', (): void => {
expect(instance.setOnce(true)).toEqual(instance);
});
});
describe('setEvent method', (): void => {
test('is a function', (): void => {
expect(typeof ModuleEventHandler.prototype.setEvent).toEqual(
'function',
);
});
test('returns a new instance of ModuleEventHandler', (): void => {
const instance = new ModuleEventHandler();
expect(instance.setEvent('messageCreate')).toBeInstanceOf(
ModuleEventHandler,
);
});
test('returns a new instance of ModuleEventHandler with the same execute function', (): void => {
const instance = new ModuleEventHandler();
instance.setExecute((eventArgs): void => {
eventArgs;
});
expect(instance.setEvent('messageCreate').execute).toEqual(
instance.execute,
);
});
test('returns a new instance of ModuleEventHandler with the same once value', (): void => {
const instance = new ModuleEventHandler();
instance.setOnce(true);
expect(instance.setEvent('messageCreate').once).toEqual(
instance.once,
);
});
});
describe('setExecute method', (): void => {
test('is a function', (): void => {
expect(typeof ModuleEventHandler.prototype.setExecute).toEqual(
Expand Down
3 changes: 3 additions & 0 deletions src/ModuleHandlers/__tests__/ModuleMenuCommandHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ describe('ModuleMenuCommandHandler class', (): void => {
);
});
test('all other typecheck methods return false', (): void => {
expect(new ModuleMenuCommandHandler().isUnconfiguredHandler()).toBe(
false,
);
expect(new ModuleMenuCommandHandler().isEventHandler()).toBe(false);
expect(new ModuleMenuCommandHandler().isAutocompleteHandler()).toBe(
false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ describe('ModuleMessageCommandHandler class', (): void => {
).toBe(true);
});
test('all other typecheck methods return false', (): void => {
expect(new ModuleMessageCommandHandler().isUnconfiguredHandler()).toBe(
false,
);
expect(new ModuleMessageCommandHandler().isEventHandler()).toBe(false);
expect(new ModuleMessageCommandHandler().isAutocompleteHandler()).toBe(
false,
Expand Down
3 changes: 3 additions & 0 deletions src/ModuleHandlers/__tests__/ModuleModalSubmitHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ describe('ModuleModalSubmitHandler class', (): void => {
);
});
test('all other typecheck methods return false', (): void => {
expect(new ModuleModalSubmitHandler().isUnconfiguredHandler()).toBe(
false,
);
expect(new ModuleModalSubmitHandler().isEventHandler()).toBe(false);
expect(new ModuleModalSubmitHandler().isAutocompleteHandler()).toBe(
false,
Expand Down
3 changes: 3 additions & 0 deletions src/ModuleHandlers/__tests__/ModuleSelectMenuHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ describe('ModuleSelectMenuHandler class', (): void => {
expect(new ModuleSelectMenuHandler().isSelectMenuHandler()).toBe(true);
});
test('all other typecheck methods return false', (): void => {
expect(new ModuleSelectMenuHandler().isUnconfiguredHandler()).toBe(
false,
);
expect(new ModuleSelectMenuHandler().isEventHandler()).toBe(false);
expect(new ModuleSelectMenuHandler().isAutocompleteHandler()).toBe(
false,
Expand Down
9 changes: 7 additions & 2 deletions src/SkeletonClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { logger, type LoggerObject } from './Logger.js';
import type { ModuleBaseHandler } from './ModuleHandlers/ModuleBaseHandler.js';
import {
ModuleEventHandler,
type AcceptedEventTypes,
type ModuleAutocompleteHandler,
type ModuleButtonHandler,
type ModuleCommandHandler,
Expand Down Expand Up @@ -58,7 +59,10 @@ export class SkeletonClient extends Client {
/** Command data stored internally for use in deploying commands */
private commandData: SlashCommandBuilder[] = [];
// One event can have multiple handlers
protected eventHandlers = new Collection<string, ModuleEventHandler[]>();
protected eventHandlers = new Collection<
string,
ModuleEventHandler<AcceptedEventTypes>[]
>();
private verbose = process.argv
.slice(2)
.map((argv): string => argv.toLowerCase())
Expand Down Expand Up @@ -305,7 +309,8 @@ export class SkeletonClient extends Client {
camelCaseHandlerType === 'event' &&
handlerData.isEventHandler()
) {
let eventHandlers: ModuleEventHandler[] = [];
let eventHandlers: ModuleEventHandler<AcceptedEventTypes>[] =
[];
// Event already exists in the collection
if (this.eventHandlers.has(handlerName)) {
eventHandlers = this.eventHandlers.get(handlerName);
Expand Down

0 comments on commit fea324a

Please sign in to comment.