Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 88 additions & 74 deletions packages/core/src/commands/execution-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,103 +87,117 @@
public execute(): CommandResponse | Promise<CommandResponse> {
// 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<string, unknown>
>;
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<string, Enum>
// Create a global context object with the origin.
const globalContext = { origin: this.origin } as CommandContext<
Record<string, unknown>
>;

// 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<string, Enum>
>;

// 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) {

Check warning on line 175 in packages/core/src/commands/execution-state.ts

View workflow job for this annotation

GitHub Actions / Lint

'error' is defined but never used

Check warning on line 175 in packages/core/src/commands/execution-state.ts

View workflow job for this annotation

GitHub Actions / Lint

The catch parameter `error` should be named `reason`
// 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) {

Check warning on line 183 in packages/core/src/commands/execution-state.ts

View workflow job for this annotation

GitHub Actions / Lint

The catch parameter `e` should be named `reason`
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.",

Check warning on line 198 in packages/core/src/commands/execution-state.ts

View workflow job for this annotation

GitHub Actions / Lint

Replace `·?·"§cAn·unknown·error·occurred:·"·+·e·:·"§cAn·unknown·error·occurred.",` with `⏎··········?·"§cAn·unknown·error·occurred:·"·+·e⏎··········:·"§cAn·unknown·error·occurred."`
};
}
}

protected parse(source: string): Array<string> {
Expand Down
14 changes: 13 additions & 1 deletion packages/core/src/commands/palette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import type {
CommandCallback,
CommandContext,
CommandRegistryCallback
CommandRegistryCallback,

Check warning on line 7 in packages/core/src/commands/palette.ts

View workflow job for this annotation

GitHub Actions / Lint

Delete `,`
} from "../types";

class CommandPalette {
Expand Down Expand Up @@ -106,6 +106,18 @@
// Set the command in the commands map
this.commands.set(name, command as Command<unknown>);

for (const alias of regInstance.aliases) {
this.commands.set(
alias,
new Command<T>(
alias,
description,
regInstance,
execCallback
) as Command<unknown>
);
}

// Return the command
return command;
}
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/commands/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
*/
public permissions: Array<string> = [];

/**
* The aliases for this command.
*/
public aliases: Array<string> = [];

/**
* The will make the command appear with a `debug` flag in the available commands list.
*/
Expand Down Expand Up @@ -50,7 +55,7 @@
if (callback) {
this.overloads.set(options, callback as CommandCallback);
} else {
this.overloads.set(options, () => {});
this.overloads.set(options, () => { });

Check warning on line 58 in packages/core/src/commands/registry.ts

View workflow job for this annotation

GitHub Actions / Lint

Delete `·`
}

// Return the registry.
Expand Down
Loading