1
- import type { CommandKit } from '../../CommandKit' ;
2
1
import {
2
+ ApplicationCommandType ,
3
3
AutocompleteInteraction ,
4
4
Awaitable ,
5
5
Collection ,
@@ -10,18 +10,20 @@ import {
10
10
Message ,
11
11
SlashCommandBuilder ,
12
12
} 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' ;
18
14
import { AsyncFunction , GenericFunction } from '../../context/async-context' ;
19
15
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 ' ;
22
18
import { COMMANDKIT_IS_DEV } from '../../utils/constants' ;
19
+ import { CommandKitErrorCodes , isErrorType } from '../../utils/error-codes' ;
20
+ import { toFileURL } from '../../utils/resolve-file-url' ;
23
21
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' ;
25
27
26
28
/**
27
29
* Function type for wrapping command execution with custom logic.
@@ -34,7 +36,7 @@ export type RunCommand = <T extends AsyncFunction>(fn: T) => T;
34
36
* It can be used to define slash commands, context menu commands, and message commands.
35
37
*/
36
38
export interface AppCommandNative {
37
- command : SlashCommandBuilder | Record < string , any > ;
39
+ command : CommandData | Record < string , any > ;
38
40
chatInput ?: ( ctx : Context ) => Awaitable < unknown > ;
39
41
autocomplete ?: ( ctx : Context ) => Awaitable < unknown > ;
40
42
message ?: ( ctx : Context ) => Awaitable < unknown > ;
@@ -127,6 +129,10 @@ const commandDataSchema = {
127
129
userContextMenu : ( c : unknown ) => typeof c === 'function' ,
128
130
} ;
129
131
132
+ export type CommandDataSchema = typeof commandDataSchema ;
133
+ export type CommandDataSchemaKey = keyof CommandDataSchema ;
134
+ export type CommandDataSchemaValue = CommandDataSchema [ CommandDataSchemaKey ] ;
135
+
130
136
/**
131
137
* @private
132
138
* @internal
@@ -674,29 +680,51 @@ export class AppCommandHandler {
674
680
data : {
675
681
command : {
676
682
name : command . name ,
677
- description : `${ command . name } commands ` ,
683
+ description : `${ command . name } command ` ,
678
684
type : 1 ,
679
685
} ,
680
686
} ,
681
687
} ) ;
682
688
return ;
683
689
}
684
690
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 ;
686
694
687
- if ( ! data . command ) {
695
+ if ( ! commandFileData . command ) {
688
696
throw new Error (
689
697
`Invalid export for command ${ command . name } : no command definition found` ,
690
698
) ;
691
699
}
692
700
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
+
693
709
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
+ }
700
728
}
701
729
}
702
730
@@ -706,7 +734,7 @@ export class AppCommandHandler {
706
734
) ;
707
735
}
708
736
709
- let lastUpdated = data . command ;
737
+ let lastUpdated = commandFileData . command ;
710
738
711
739
await this . commandkit . plugins . execute ( async ( ctx , plugin ) => {
712
740
const res = await plugin . prepareCommand ( ctx , lastUpdated ) ;
@@ -718,9 +746,9 @@ export class AppCommandHandler {
718
746
719
747
this . loadedCommands . set ( id , {
720
748
command,
721
- guilds : data . guilds ,
749
+ guilds : commandFileData . command . guilds ,
722
750
data : {
723
- ...data ,
751
+ ...commandFileData ,
724
752
command : 'toJSON' in lastUpdated ? lastUpdated . toJSON ( ) : lastUpdated ,
725
753
} ,
726
754
} ) ;
0 commit comments