Skip to content

Commit e14978f

Browse files
authored
Merge pull request #248 from underctrl-io/update-command-loader
Update command loader
2 parents 6f92bfd + 5567e17 commit e14978f

File tree

3 files changed

+62
-27
lines changed

3 files changed

+62
-27
lines changed

apps/test-bot/src/app/commands/(general)/(animal)/cat.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type {
2-
CommandData,
32
ChatInputCommand,
3+
CommandData,
44
MessageCommand,
55
MessageContextMenuCommand,
66
} from 'commandkit';
@@ -12,7 +12,7 @@ import {
1212

1313
export const command: CommandData = {
1414
name: 'cat',
15-
description: 'cat command',
15+
// description: 'cat command',
1616
integration_types: [
1717
ApplicationIntegrationType.GuildInstall,
1818
ApplicationIntegrationType.UserInstall,

packages/commandkit/src/app/handlers/AppCommandHandler.ts

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { CommandKit } from '../../CommandKit';
21
import {
2+
ApplicationCommandType,
33
AutocompleteInteraction,
44
Awaitable,
55
Collection,
@@ -10,18 +10,20 @@ import {
1010
Message,
1111
SlashCommandBuilder,
1212
} from 'discord.js';
13-
import { Context } from '../commands/Context';
14-
import { toFileURL } from '../../utils/resolve-file-url';
15-
import { MessageCommandParser } from '../commands/MessageCommandParser';
16-
import { CommandKitErrorCodes, isErrorType } from '../../utils/error-codes';
17-
import { CommandRegistrar } from '../register/CommandRegistrar';
13+
import type { CommandKit } from '../../CommandKit';
1814
import { AsyncFunction, GenericFunction } from '../../context/async-context';
1915
import { Logger } from '../../logger/Logger';
20-
import { Command, Middleware } from '../router';
21-
import { AppCommandRunner } from '../commands/AppCommandRunner';
16+
import type { CommandData } from '../../types';
17+
import colors from '../../utils/colors';
2218
import { COMMANDKIT_IS_DEV } from '../../utils/constants';
19+
import { CommandKitErrorCodes, isErrorType } from '../../utils/error-codes';
20+
import { toFileURL } from '../../utils/resolve-file-url';
2321
import { rewriteCommandDeclaration } from '../../utils/types-package';
24-
import colors from '../../utils/colors';
22+
import { AppCommandRunner } from '../commands/AppCommandRunner';
23+
import { Context } from '../commands/Context';
24+
import { MessageCommandParser } from '../commands/MessageCommandParser';
25+
import { CommandRegistrar } from '../register/CommandRegistrar';
26+
import { Command, Middleware } from '../router';
2527

2628
/**
2729
* Function type for wrapping command execution with custom logic.
@@ -34,7 +36,7 @@ export type RunCommand = <T extends AsyncFunction>(fn: T) => T;
3436
* It can be used to define slash commands, context menu commands, and message commands.
3537
*/
3638
export interface AppCommandNative {
37-
command: SlashCommandBuilder | Record<string, any>;
39+
command: CommandData | Record<string, any>;
3840
chatInput?: (ctx: Context) => Awaitable<unknown>;
3941
autocomplete?: (ctx: Context) => Awaitable<unknown>;
4042
message?: (ctx: Context) => Awaitable<unknown>;
@@ -127,6 +129,10 @@ const commandDataSchema = {
127129
userContextMenu: (c: unknown) => typeof c === 'function',
128130
};
129131

132+
export type CommandDataSchema = typeof commandDataSchema;
133+
export type CommandDataSchemaKey = keyof CommandDataSchema;
134+
export type CommandDataSchemaValue = CommandDataSchema[CommandDataSchemaKey];
135+
130136
/**
131137
* @private
132138
* @internal
@@ -674,29 +680,51 @@ export class AppCommandHandler {
674680
data: {
675681
command: {
676682
name: command.name,
677-
description: `${command.name} commands`,
683+
description: `${command.name} command`,
678684
type: 1,
679685
},
680686
},
681687
});
682688
return;
683689
}
684690

685-
const data = await import(`${toFileURL(command.path)}?t=${Date.now()}`);
691+
const commandFileData = (await import(
692+
`${toFileURL(command.path)}?t=${Date.now()}`
693+
)) as AppCommandNative;
686694

687-
if (!data.command) {
695+
if (!commandFileData.command) {
688696
throw new Error(
689697
`Invalid export for command ${command.name}: no command definition found`,
690698
);
691699
}
692700

701+
if (
702+
(!commandFileData.command.type ||
703+
commandFileData.command.type === ApplicationCommandType.ChatInput) &&
704+
!commandFileData.command.description
705+
) {
706+
commandFileData.command.description = `${command.name} command`;
707+
}
708+
693709
let handlerCount = 0;
694-
for (const [key, validator] of Object.entries(commandDataSchema)) {
695-
if (key !== 'command' && data[key]) handlerCount++;
696-
if (data[key] && !(await validator(data[key]))) {
697-
throw new Error(
698-
`Invalid export for command ${command.name}: ${key} does not match expected value`,
699-
);
710+
711+
for (const [key, propValidator] of Object.entries(commandDataSchema) as [
712+
CommandDataSchemaKey,
713+
CommandDataSchemaValue,
714+
][]) {
715+
const exportedProp = commandFileData[key];
716+
717+
if (exportedProp) {
718+
if (!(await propValidator(exportedProp))) {
719+
throw new Error(
720+
`Invalid export for command ${command.name}: ${key} does not match expected value`,
721+
);
722+
}
723+
724+
if (key !== 'command') {
725+
// command file includes a handler function (chatInput, message, etc)
726+
handlerCount++;
727+
}
700728
}
701729
}
702730

@@ -706,7 +734,7 @@ export class AppCommandHandler {
706734
);
707735
}
708736

709-
let lastUpdated = data.command;
737+
let lastUpdated = commandFileData.command;
710738

711739
await this.commandkit.plugins.execute(async (ctx, plugin) => {
712740
const res = await plugin.prepareCommand(ctx, lastUpdated);
@@ -718,9 +746,9 @@ export class AppCommandHandler {
718746

719747
this.loadedCommands.set(id, {
720748
command,
721-
guilds: data.guilds,
749+
guilds: commandFileData.command.guilds,
722750
data: {
723-
...data,
751+
...commandFileData,
724752
command: 'toJSON' in lastUpdated ? lastUpdated.toJSON() : lastUpdated,
725753
},
726754
});

packages/commandkit/src/types.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import {
66
} from 'discord.js';
77
import type { CommandKit } from './CommandKit';
88

9+
type Prettify<T> = {
10+
[K in keyof T]: T[K];
11+
} & {};
12+
913
/**
1014
* Options for instantiating a CommandKit handler.
1115
*/
@@ -40,6 +44,9 @@ export interface CommandContext<
4044
/**
4145
* Represents a command that can be executed by CommandKit.
4246
*/
43-
export type CommandData = RESTPostAPIApplicationCommandsJSONBody & {
44-
guilds?: string[];
45-
};
47+
export type CommandData = Prettify<
48+
Omit<RESTPostAPIApplicationCommandsJSONBody, 'description'> & {
49+
description?: string;
50+
guilds?: string[];
51+
}
52+
>;

0 commit comments

Comments
 (0)