import debug from 'debug';
import { Command, Commander } from './commander';
import { ConfigureError } from './errors';
import { IContext } from '../types';
import { Context } from '../types';
import { UtilsCore } from './utils';
import EventListener from './utils/event-emiter';
import executeCommand from './executeCommand';
const logger = debug('commander-core:handler');
/**
* @description источники загрузок
* @interface
*/
interface ICommandsLoader {
/**
* @description директория
*/
directory?: string;
/**
* @description массив, при указании этого источника директория будет игнорироваться
*/
fromArray?: Command[];
}
/**
* @interface
*/
export interface IHandlerParams {
/**
* объект описывающий источник загрузок
* @type {ICommandsLoader}
*/
commands: ICommandsLoader;
/**
* строгий режим, гарантирующий что при загрузке будет хотя бы 1 команда иначе бросит ошибку
* @type {boolean}
* @default true
*/
strictLoader?: boolean;
/**
* настраиваемые утилиты для вашей логики, например для работы с базой данных
* @type {UtilsCore}
*/
utils: UtilsCore;
}
/**
* @description класс обработчика
* @class
* @param {IHandlerParams} data данные обработчика
* @example
*
* const { Handler, UtilsCore } = require('commander-core');
*
* class Utils extends UtilsCore {
* testMetods() {
* console.log('test')
* }
* }
*
* const handler = new Handler({
* commands: {
* directory: path.resolve(__dirname, 'commands'); //директория команд
* },
* strictLoader: true // строгая загрузка
* utils: new Utils() // Utils
* })
* @example
*
* сonst handler = new Handler({
* commands: {
* fromArray: [new Command(params)]; //массив команд
* },
* strictLoader: true // строгая загрузка
* utils: new Utils() // Utils
* })
*/
export class Handler {
/**
* @type {EventEmitter} events менеджер событий
*/
readonly events: EventListener;
readonly commander: Commander;
readonly utils: UtilsCore;
private readonly commandsDirectory: string;
private sourceCommands = '';
private strictLoader = false;
constructor(
data: IHandlerParams = {
commands: {},
strictLoader: false,
utils: new UtilsCore(),
},
) {
logger('create handler start');
this.strictLoader = data.strictLoader;
logger('strictLoader: %s', this.strictLoader);
if (!data.commands.directory && !data.commands.fromArray?.length) {
throw new ConfigureError('не указан источник загрузки команд');
}
if (
data.strictLoader &&
!data.commands.fromArray?.length &&
!data.commands.directory
) {
throw new ConfigureError('Строгий режим загрузки! команды не найдены');
}
this.utils = data.utils;
logger('handler.utils: %o', this.utils);
this.events = data.utils.events;
logger('handler.events: %o', this.events);
this.commander = data.utils.commander;
logger('handler.commander: %o', this.commander);
if (data.commands.fromArray?.length > 0) {
this.commander.commandsLoaded = true;
this.commander.setCommands(data.commands.fromArray);
}
if (data.commands.directory) {
this.commandsDirectory = data.commands.directory;
}
this.sourceCommands =
data.commands.fromArray?.length > 0 ? 'array' : 'directory';
logger('sourceCommands: %s', this.sourceCommands);
logger('create handler complited');
}
get [Symbol.toStringTag](): string {
return 'Handler';
}
/**
* @description загружает команды из директории
* @return {Promise<void>}
*/
async loadCommands(): Promise<void> {
logger('booting commands');
if (this.sourceCommands === 'array') {
throw new ConfigureError(
'нельзя загружать команды из директории если указан массив комманд!',
);
}
await this.commander.loadFromDirectory(this.commandsDirectory);
const commands: Command[] = this.commander.getCommands;
logger('commands count: %d', commands.length);
if (commands.length < 1 && this.strictLoader) {
logger('booting commands error');
throw new ConfigureError('Строгий режим загрузки! команды не найдены');
}
logger('handler.commander: %o', this.commander);
logger('booting commands complited');
}
/**
* @description обработка команды
* @param {object} context объект контекста возвращаемый из vk-io или puregram
* @return {void}
* @example
*
* execute<MessageContext>(context)
* // => void
*/
async execute<C extends Context>(context: C & IContext): Promise<void> {
return executeCommand<C>(context, this.utils);
}
}
Source