diff --git a/packages/core/src/commands/execution-state.ts b/packages/core/src/commands/execution-state.ts index 311d1ba11..612e40085 100644 --- a/packages/core/src/commands/execution-state.ts +++ b/packages/core/src/commands/execution-state.ts @@ -87,103 +87,117 @@ class CommandExecutionState { public execute(): CommandResponse | Promise { // Check if the command is undefined. // If it is, we will throw an error. - if (!this.command) { - throw new TypeError( - `Unknown command executed. Please make sure the command exists, and that you have permission to use it.` - ); - } - - // Create a global context object with the origin. - const globalContext = { origin: this.origin } as CommandContext< - Record - >; + try { + if (!this.command) { + throw new TypeError( + `Unknown command executed. Please make sure the command exists, and that you have permission to use it.` + ); + } - // Iterate through the overloads and extract the arguments. - for (const [overload, callback] of this.command.registry.overloads) { - // Create a new context object with the origin. - const context = { origin: this.origin } as CommandContext< - Record + // Create a global context object with the origin. + const globalContext = { origin: this.origin } as CommandContext< + Record >; - // Create a new state object with the split array. - const state = new CommandArgumentPointer(this, this.split); + // Iterate through the overloads and find a match. + for (const [overload, callback] of this.command.registry.overloads) { + // Create a new context object with the origin. + const context = { origin: this.origin } as CommandContext< + Record + >; - // Iterate through the overload keys and extract the arguments. - for (const key in overload) { - // Get the value of the key - const value = overload[key]; + // Create a new state object with the split array. + const state = new CommandArgumentPointer(this, this.split); - // Check if the value is null or undefined, if it is then we will continue to the next overload - if (!value) continue; + try { + // Iterate through the overload keys and extract the arguments. + for (const key in overload) { + const value = overload[key]; - // Check if the value is an array, if it is then we will check if the argument is required. - if (Array.isArray(value)) { - // Get the enum and optional flag from the value. - const [type, optional] = value; + // If value is null or undefined, i quit. + if (!value) continue; - // Check if the argument is optional and if there are any arguments left. - if (!optional && state.offset >= state.arguments.length) { - throw new TypeError(`Argument ${key} is required.`); - } + // Check for array. + if (Array.isArray(value)) { + // Get the enum and optional flag. + const [type, optional] = value; - // Extract the argument from the split array. - // We will pass the execution state to the extract method. - // This allows customs enums to extract the argument in various ways. - const value_ = type.extract(state as CommandArgumentPointer); + // Check if the argument is optional and if there are any arguments left. + if (!optional && state.offset >= state.arguments.length) { + throw new TypeError(`Argument ${key} is required.`); + } - // Declare if the value is optional. - if (value_) value_.optional = optional; + // Extract the argument from the split array. + const value_ = type.extract(state as CommandArgumentPointer); - // Add the value to the context object. - context[key] = value_ ?? type.default; - } else { - // Extract the argument from the split array. - // We will pass the execution state to the extract method. - // This allows customs enums to extract the argument in various ways. - const value_ = value.extract(state as CommandArgumentPointer); + // Declare if the value is optional. + if (value_) value_.optional = optional; - // Declare that the enum value is not optional. - if (value_) value_.optional = false; + context[key] = value_ ?? type.default; + } else { + // Extract the argument from the split array. + const value_ = value.extract(state as CommandArgumentPointer); - // Add the value to the context object. - context[key] = value_ ?? value.default; - } - } + // Declare that the enum value is not optional. + if (value_) value_.optional = false; + + context[key] = value_ ?? value.default; + } + } - // Add the context object to the global context object. - Object.assign(globalContext, context); + // Add the context object to the global context object. + Object.assign(globalContext, context); - // Check if there are any arguments left in the split array. - // If there are, we will continue to the next overload. - if (state.offset < state.arguments.length) continue; + // Check if there are any arguments left in the split array. + // If there are, we will continue to the next overload. + if (state.offset < state.arguments.length) continue; - // Check that the length of the context object is the same as the overload object. - // We need to add 1 to compensate for the origin property. - if (Object.keys(context).length !== Object.keys(overload).length + 1) - continue; + // Check that the length of the context object is the same as the overload object. + if (Object.keys(context).length !== Object.keys(overload).length + 1) + continue; - // Iterate through the context object and try to validate the arguments. - for (const [_, value] of Object.entries(context)) { - // Check if the value is an instance of Enum. - if (!(value instanceof Enum)) continue; + // Iterate through the context object and try to validate. + for (const [_, value] of Object.entries(context)) { + if (!(value instanceof Enum)) continue; - // Get the result from the value. - const result = value.result; + const result = value.result; - // Check if the value is optional and if it is not valid. - if (value.optional && (result === null || result === undefined)) + // Check if the value is optional and if it is not valid. + if (value.optional && (result === null || result === undefined)) + continue; + + // Validate the value. + value.validate(true); + } + + // Overload is a match. + return (callback(context) ?? {}) as CommandResponse; + } catch (error) { + // If there is an error, we will continue to the next overload. continue; + } + } - // Validate the value. - value.validate(true); + // Call the global callback with the global context object. + return (this.command.callback(globalContext) ?? {}) as CommandResponse; + } catch (e) { + if (e instanceof TypeError) { + return { + message: `§c${e.message}` + }; } - // Get the response from the callback. - return (callback(context) ?? {}) as CommandResponse; - } + if (e instanceof Error) { + return { + message: `§c${e.message}` + }; + } - // Call the global callback with the global context object. - return (this.command.callback(globalContext) ?? {}) as CommandResponse; + // Catches unknown errors. + return { + message: e ? "§cAn unknown error occurred: " + e : "§cAn unknown error occurred.", + }; + } } protected parse(source: string): Array { diff --git a/packages/core/src/commands/palette.ts b/packages/core/src/commands/palette.ts index cae083cd9..57b7daf65 100644 --- a/packages/core/src/commands/palette.ts +++ b/packages/core/src/commands/palette.ts @@ -4,7 +4,7 @@ import { CommandRegistry } from "./registry"; import type { CommandCallback, CommandContext, - CommandRegistryCallback + CommandRegistryCallback, } from "../types"; class CommandPalette { @@ -106,6 +106,18 @@ class CommandPalette { // Set the command in the commands map this.commands.set(name, command as Command); + for (const alias of regInstance.aliases) { + this.commands.set( + alias, + new Command( + alias, + description, + regInstance, + execCallback + ) as Command + ); + } + // Return the command return command; } diff --git a/packages/core/src/commands/registry.ts b/packages/core/src/commands/registry.ts index e80218dd6..af7591bd2 100644 --- a/packages/core/src/commands/registry.ts +++ b/packages/core/src/commands/registry.ts @@ -17,6 +17,11 @@ class CommandRegistry { */ public permissions: Array = []; + /** + * The aliases for this command. + */ + public aliases: Array = []; + /** * The will make the command appear with a `debug` flag in the available commands list. */ @@ -50,7 +55,7 @@ class CommandRegistry { if (callback) { this.overloads.set(options, callback as CommandCallback); } else { - this.overloads.set(options, () => {}); + this.overloads.set(options, () => { }); } // Return the registry.