zumito-framework 1.2.7 → 1.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -129,6 +129,9 @@ export class ZumitoFramework {
129
129
  */
130
130
  constructor(settings, callback) {
131
131
  this.settings = settings;
132
+ // Register this class instance to service container
133
+ ServiceContainer.addService(ZumitoFramework, [], true, this);
134
+ ServiceContainer.addService(TranslationManager, [], true, this.translations);
132
135
  this.modules = new ModuleManager(this);
133
136
  this.commands = new CommandManager(this);
134
137
  this.events = new Map();
@@ -138,9 +141,6 @@ export class ZumitoFramework {
138
141
  if (settings.logLevel) {
139
142
  console.logLevel = settings.logLevel;
140
143
  }
141
- // Register this class instance to service container
142
- ServiceContainer.addService(ZumitoFramework, [], true, this);
143
- ServiceContainer.addService(TranslationManager, [], true, this.translations);
144
144
  this.initialize()
145
145
  .then(() => {
146
146
  if (callback)
@@ -0,0 +1,7 @@
1
+ export declare type CommandLoadOptions = {
2
+ whitelist?: string[];
3
+ blacklist?: string[];
4
+ renames?: {
5
+ [key: string]: string;
6
+ };
7
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export declare enum ErrorType {
2
+ CommandInstance = 1,
3
+ CommandLoad = 2,
4
+ CommandRun = 3
5
+ }
@@ -0,0 +1,6 @@
1
+ export var ErrorType;
2
+ (function (ErrorType) {
3
+ ErrorType[ErrorType["CommandInstance"] = 1] = "CommandInstance";
4
+ ErrorType[ErrorType["CommandLoad"] = 2] = "CommandLoad";
5
+ ErrorType[ErrorType["CommandRun"] = 3] = "CommandRun";
6
+ })(ErrorType || (ErrorType = {}));
@@ -3,14 +3,16 @@ import { Command } from './commands/Command.js';
3
3
  import { FrameworkEvent } from './FrameworkEvent.js';
4
4
  import { DatabaseModel } from './DatabaseModel.js';
5
5
  import { CommandManager } from '../services/CommandManager.js';
6
+ import { ModuleParameters } from './parameters/ModuleParameters.js';
6
7
  export declare abstract class Module {
7
8
  protected path: string;
9
+ protected parameters: ModuleParameters;
8
10
  protected framework: ZumitoFramework;
9
11
  protected commands: CommandManager;
10
12
  protected events: Map<string, FrameworkEvent>;
11
13
  protected models: Array<DatabaseModel>;
12
14
  protected commandManager: CommandManager;
13
- constructor(path: any, framework: any);
15
+ constructor(path: any, parameters?: ModuleParameters);
14
16
  initialize(): Promise<void>;
15
17
  registerCommands(): Promise<void>;
16
18
  getCommands(): Map<string, Command>;
@@ -1,18 +1,22 @@
1
+ import { ZumitoFramework } from '../ZumitoFramework.js';
1
2
  import * as fs from 'fs';
2
3
  import path from 'path';
3
4
  import { ButtonInteraction, CommandInteraction, ModalSubmitInteraction, StringSelectMenuInteraction, } from 'discord.js';
4
5
  import { CommandManager } from '../services/CommandManager.js';
6
+ import { ServiceContainer } from '../services/ServiceContainer.js';
5
7
  export class Module {
6
8
  path;
9
+ parameters;
7
10
  framework;
8
11
  commands;
9
12
  events = new Map();
10
13
  models = [];
11
14
  commandManager;
12
- constructor(path, framework) {
15
+ constructor(path, parameters) {
13
16
  this.path = path;
14
- this.framework = framework;
15
- this.commands = new CommandManager(framework);
17
+ this.parameters = parameters;
18
+ this.framework = ServiceContainer.getService(ZumitoFramework);
19
+ this.commands = new CommandManager(this.framework);
16
20
  }
17
21
  async initialize() {
18
22
  await this.registerCommands();
@@ -0,0 +1,7 @@
1
+ export declare type ModuleParameters = {
2
+ commandWhitelist?: string[];
3
+ commandBlacklist?: string[];
4
+ commandRenames?: {
5
+ [key: string]: string;
6
+ };
7
+ };
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -25,4 +25,5 @@ import { ServiceContainer } from './services/ServiceContainer.js';
25
25
  import { GuildDataGetter } from './services/GuildDataGetter.js';
26
26
  import { CommandParser } from './services/CommandParser.js';
27
27
  import { SlashCommandRefresher } from './services/SlashCommandRefresher.js';
28
- export { ZumitoFramework, FrameworkSettings, Command, Module, CommandParameters, CommandArguments, FrameworkEvent, Translation, TranslationManager, ApiResponse, SelectMenuParameters, CommandType, CommandArgDefinition, CommandChoiceDefinition, ButtonPressed, ButtonPressedParams, TextFormatter, EmojiFallback, DatabaseConfigLoader, DatabaseModel, PresenceDataRule, RuledPresenceData, StatusManagerOptions, discord, EventParameters, ServiceContainer, GuildDataGetter, SlashCommandRefresher, CommandParser, };
28
+ import { ErrorHandler } from './services/ErrorHandler.js';
29
+ export { ZumitoFramework, FrameworkSettings, Command, Module, CommandParameters, CommandArguments, FrameworkEvent, Translation, TranslationManager, ApiResponse, SelectMenuParameters, CommandType, CommandArgDefinition, CommandChoiceDefinition, ButtonPressed, ButtonPressedParams, TextFormatter, EmojiFallback, DatabaseConfigLoader, DatabaseModel, PresenceDataRule, RuledPresenceData, StatusManagerOptions, discord, EventParameters, ServiceContainer, GuildDataGetter, SlashCommandRefresher, CommandParser, ErrorHandler, };
package/dist/index.js CHANGED
@@ -18,10 +18,12 @@ import { GuildDataGetter } from './services/GuildDataGetter.js';
18
18
  import { MemberPermissionChecker } from './services/MemberPermissionChecker.js';
19
19
  import { CommandParser } from './services/CommandParser.js';
20
20
  import { SlashCommandRefresher } from './services/SlashCommandRefresher.js';
21
+ import { ErrorHandler } from './services/ErrorHandler.js';
21
22
  ServiceContainer.addService(TextFormatter, []);
22
23
  ServiceContainer.addService(EmojiFallback, []);
23
24
  ServiceContainer.addService(GuildDataGetter, [ZumitoFramework.name]);
24
25
  ServiceContainer.addService(MemberPermissionChecker, []);
25
26
  ServiceContainer.addService(CommandParser, []);
26
27
  ServiceContainer.addService(SlashCommandRefresher, [ZumitoFramework.name]);
27
- export { ZumitoFramework, Command, Module, CommandArguments, FrameworkEvent, Translation, TranslationManager, ApiResponse, CommandType, ButtonPressed, TextFormatter, EmojiFallback, DatabaseConfigLoader, DatabaseModel, discord, ServiceContainer, GuildDataGetter, SlashCommandRefresher, CommandParser, };
28
+ ServiceContainer.addService(ErrorHandler, ['ZumitoFramework']);
29
+ export { ZumitoFramework, Command, Module, CommandArguments, FrameworkEvent, Translation, TranslationManager, ApiResponse, CommandType, ButtonPressed, TextFormatter, EmojiFallback, DatabaseConfigLoader, DatabaseModel, discord, ServiceContainer, GuildDataGetter, SlashCommandRefresher, CommandParser, ErrorHandler, };
@@ -1,8 +1,11 @@
1
1
  import { ZumitoFramework } from "../ZumitoFramework";
2
2
  import { Command } from "../definitions/commands/Command.js";
3
+ import { CommandLoadOptions } from "../definitions/CommandLoadOptions";
4
+ import { ErrorHandler } from "./ErrorHandler";
3
5
  export declare class CommandManager {
4
6
  protected commands: Map<string, Command>;
5
7
  protected framework: ZumitoFramework;
8
+ protected errorHandler: ErrorHandler;
6
9
  constructor(framework: any);
7
10
  set(name: string, command: Command): void;
8
11
  get(name: string): Command;
@@ -26,7 +29,7 @@ export declare class CommandManager {
26
29
  * @param folderPath - Absolute path to commands folder
27
30
  * @returns {Promise<Map<string, Command>>}
28
31
  */
29
- loadCommandsFolder(folderPath: string): Promise<Map<string, any>>;
32
+ loadCommandsFolder(folderPath: string, options?: CommandLoadOptions): Promise<Map<string, any>>;
30
33
  /**
31
34
  * Watch command files on a folder.
32
35
  * It loads command when new file is created, update command when file is modified and deletes command when file is deleted.
@@ -5,11 +5,16 @@ import boxen from "boxen";
5
5
  import fs from 'fs';
6
6
  import { REST, Routes, SlashCommandBuilder } from "discord.js";
7
7
  import { CommandType } from "../definitions/commands/CommandType.js";
8
+ import { ErrorHandler } from "./ErrorHandler";
9
+ import { ServiceContainer } from "./ServiceContainer";
10
+ import { ErrorType } from "../definitions/ErrorType";
8
11
  export class CommandManager {
9
12
  commands;
10
13
  framework;
14
+ errorHandler;
11
15
  constructor(framework) {
12
16
  this.commands = new Map;
17
+ this.errorHandler = ServiceContainer.getService(ErrorHandler);
13
18
  this.framework = framework;
14
19
  }
15
20
  set(name, command) {
@@ -45,7 +50,15 @@ export class CommandManager {
45
50
  console.log(e + '\n' + e.name + '\n' + e.stack);
46
51
  });
47
52
  command = Object.values(command)[0];
48
- command = new command();
53
+ try {
54
+ command = new command();
55
+ }
56
+ catch (error) {
57
+ this.errorHandler.handleError(error, {
58
+ type: ErrorType.CommandInstance,
59
+ command: command,
60
+ });
61
+ }
49
62
  this.framework.commands.set(command.constructor.name.toLowerCase(), command);
50
63
  console.debug('[🆕🟢 ] Command ' + chalk.blue(filePath.toString().replace(/^.*[\\\/]/, '').split('.').slice(0, -1).join('.')) + ' loaded');
51
64
  return command;
@@ -57,14 +70,19 @@ export class CommandManager {
57
70
  * @param folderPath - Absolute path to commands folder
58
71
  * @returns {Promise<Map<string, Command>>}
59
72
  */
60
- async loadCommandsFolder(folderPath) {
73
+ async loadCommandsFolder(folderPath, options) {
61
74
  const files = fs.readdirSync(folderPath);
62
75
  for (const file of files) {
63
76
  if (file.endsWith('d.ts'))
64
77
  continue;
65
78
  if (file.endsWith('.js') || file.endsWith('.ts')) {
66
79
  const command = await this.loadCommandFile(path.join(folderPath, file));
67
- this.commands.set(command.constructor.name.toLowerCase(), command);
80
+ const commandName = command.constructor.name.toLowerCase();
81
+ if (options?.blacklist && options.blacklist.includes(commandName))
82
+ continue;
83
+ if (options?.whitelist && !options.whitelist.includes(commandName))
84
+ continue;
85
+ this.commands.set(options?.renames?.[commandName] || commandName, command);
68
86
  }
69
87
  }
70
88
  return this.commands;
@@ -0,0 +1,19 @@
1
+ import { ErrorType } from "../definitions/ErrorType";
2
+ import { Command } from "../definitions/commands/Command";
3
+ import { ZumitoFramework } from "../ZumitoFramework";
4
+ declare type BaseErrorOptions = {
5
+ exit?: boolean;
6
+ type: ErrorType;
7
+ };
8
+ declare type CommandErrorOptions = BaseErrorOptions & {
9
+ type: ErrorType.CommandInstance | ErrorType.CommandLoad | ErrorType.CommandRun;
10
+ command: Command;
11
+ };
12
+ export declare class ErrorHandler {
13
+ framework: ZumitoFramework;
14
+ constructor(framework: ZumitoFramework);
15
+ handleError(error: Error, options: BaseErrorOptions | CommandErrorOptions): void;
16
+ handleCommandError(error: Error, options: CommandErrorOptions): void;
17
+ printErrorStack(error: Error): void;
18
+ }
19
+ export {};
@@ -0,0 +1,49 @@
1
+ import ErrorStackParser from "error-stack-parser";
2
+ import { ErrorType } from "../definitions/ErrorType";
3
+ import chalk from "chalk";
4
+ export class ErrorHandler {
5
+ framework;
6
+ constructor(framework) {
7
+ this.framework = framework;
8
+ }
9
+ handleError(error, options) {
10
+ if (options?.type == ErrorType.CommandInstance || options?.type == ErrorType.CommandLoad || options?.type == ErrorType.CommandRun) {
11
+ this.handleCommandError(error, options);
12
+ }
13
+ else {
14
+ console.error(error.toString());
15
+ }
16
+ this.printErrorStack(error);
17
+ if (options.exit)
18
+ process.exit(1);
19
+ }
20
+ handleCommandError(error, options) {
21
+ switch (options.type) {
22
+ case ErrorType.CommandInstance:
23
+ console.group(`[❌] Error instanciating command ${options.command.name}`);
24
+ break;
25
+ case ErrorType.CommandLoad:
26
+ console.group(`[❌] Error loading command ${options.command.name}`);
27
+ break;
28
+ case ErrorType.CommandRun:
29
+ console.group(`[❌] Error running command ${options.command.name}`);
30
+ break;
31
+ }
32
+ console.line(error.toString());
33
+ console.groupEnd();
34
+ }
35
+ printErrorStack(error) {
36
+ const stackParsedError = ErrorStackParser.parse(error);
37
+ let functionColor = 'blue';
38
+ for (let stack of stackParsedError) {
39
+ const filePath = stack.getFileName();
40
+ let functionName = stack.getFunctionName();
41
+ if (functionName == 'CommandManager.loadCommandFile') {
42
+ functionColor = 'yellow';
43
+ }
44
+ console.line(` at ${chalk.gray(filePath)}:${stack.getLineNumber()}:${stack.getColumnNumber()} ${chalk[functionColor](functionName)}`);
45
+ if (functionName == 'CommandManager.loadCommandFile' && !this.framework.settings.debug)
46
+ break;
47
+ }
48
+ }
49
+ }
@@ -61,7 +61,7 @@ export class ModuleManager {
61
61
  let moduleInstance;
62
62
  if (module.constructor) {
63
63
  try {
64
- moduleInstance = new module(rootPath, this.framework);
64
+ moduleInstance = new module(rootPath);
65
65
  await moduleInstance.initialize();
66
66
  this.modules.set(name || moduleInstance.constructor.name, moduleInstance);
67
67
  }
@@ -9,10 +9,10 @@ class ServiceContainerManager {
9
9
  });
10
10
  }
11
11
  getService(serviceClass) {
12
- const classname = typeof serviceClass === 'string' ? serviceClass : serviceClass.name;
13
- const service = this.services.get(classname);
12
+ const serviceName = typeof serviceClass == 'string' ? serviceClass : serviceClass.name;
13
+ const service = this.services.get(serviceName);
14
14
  if (!service)
15
- throw new Error(`Service ${classname} not found`);
15
+ throw new Error(`Service ${serviceName} not found`);
16
16
  if (service.singleton && service.instance)
17
17
  return service.instance;
18
18
  const dependencies = service.dependencies.map(dependency => this.getService(dependency));
@@ -22,9 +22,10 @@ class ServiceContainerManager {
22
22
  return instance;
23
23
  }
24
24
  addInstance(serviceClass, instance) {
25
- if (!this.services.has(serviceClass.name))
25
+ const serviceName = typeof serviceClass == 'string' ? serviceClass : serviceClass.name;
26
+ if (!this.services.has(serviceName))
26
27
  return;
27
- this.services.get(serviceClass.name).instance = instance;
28
+ this.services.get(serviceName).instance = instance;
28
29
  }
29
30
  }
30
31
  export const ServiceContainer = new ServiceContainerManager();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zumito-framework",
3
- "version": "1.2.7",
3
+ "version": "1.2.8",
4
4
  "description": "Discord.js bot framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",