Skip to content

Commit

Permalink
Add method decorator for applying middleware to command actions
Browse files Browse the repository at this point in the history
If used alongside `Command#use()`, the decorator-specified middleware will be run after those passed via `Command#use()`
  • Loading branch information
zajrik committed Mar 16, 2017
1 parent e023c88 commit ca0becd
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export { Command } from './lib/command/Command';
export { CommandLoader } from './lib/command/CommandLoader';
export { CommandRegistry } from './lib/command/CommandRegistry';
export { CommandDispatcher } from './lib/command/CommandDispatcher';
export { CommandDecorators } from './lib/command/CommandDecorators';
export { GuildStorage } from './lib/storage/GuildStorage';
export { GuildStorageLoader } from './lib/storage/GuildStorageLoader';
export { GuildStorageRegistry } from './lib/storage/GuildStorageRegistry';
Expand Down
44 changes: 44 additions & 0 deletions src/lib/command/CommandDecorators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { MiddlewareFunction } from '../types/MiddlewareFunction';
import { Message } from '../types/Message';
import { Command } from './Command';

export class CommandDecorators
{
/**
* Apply a middleware function to the action method of a command.
* Identical to `Command#use()` but used as a method decorator
*/
public static using(func: MiddlewareFunction): MethodDecorator
{
return function(target: Command<any>, key: string, descriptor: PropertyDescriptor): PropertyDescriptor
{
if (!target) throw new Error('@using must be used as a method decorator for a Command action method.');
if (key !== 'action') throw new Error(`"${target.constructor.name}#${key}" is not a valid method target for @using.`);
if (!descriptor) descriptor = Object.getOwnPropertyDescriptor(target, key);
const original: any = descriptor.value;
descriptor.value = async function(message: Message, args: any[]): Promise<any>
{
let middlewarePassed: boolean = true;
try
{
let result: Promise<[Message, any[]]> | [Message, any[]] =
func.call(this, message, args);
if (result instanceof Promise) result = await result;
if (!(result instanceof Array))
{
if (typeof result === 'string') message.channel.send(result);
middlewarePassed = false;
}
if (middlewarePassed) [message, args] = result;
}
catch (err)
{
middlewarePassed = false;
message.channel.send(err.toString());
}
if (middlewarePassed) return await original.apply(this, [message, args]);
};
return descriptor;
};
}
}

0 comments on commit ca0becd

Please sign in to comment.