1
- import type { CommandKit } from '../../CommandKit' ;
2
1
import {
3
2
AutocompleteInteraction ,
4
3
Awaitable ,
@@ -10,18 +9,20 @@ import {
10
9
Message ,
11
10
SlashCommandBuilder ,
12
11
} 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' ;
12
+ import type { CommandKit } from '../../CommandKit' ;
18
13
import { AsyncFunction , GenericFunction } from '../../context/async-context' ;
19
14
import { Logger } from '../../logger/Logger' ;
20
- import { Command , Middleware } from '../router ' ;
21
- import { AppCommandRunner } from '../commands/AppCommandRunner ' ;
15
+ import type { CommandData } from '../../types ' ;
16
+ import colors from '../../utils/colors ' ;
22
17
import { COMMANDKIT_IS_DEV } from '../../utils/constants' ;
18
+ import { CommandKitErrorCodes , isErrorType } from '../../utils/error-codes' ;
19
+ import { toFileURL } from '../../utils/resolve-file-url' ;
23
20
import { rewriteCommandDeclaration } from '../../utils/types-package' ;
24
- import colors from '../../utils/colors' ;
21
+ import { AppCommandRunner } from '../commands/AppCommandRunner' ;
22
+ import { Context } from '../commands/Context' ;
23
+ import { MessageCommandParser } from '../commands/MessageCommandParser' ;
24
+ import { CommandRegistrar } from '../register/CommandRegistrar' ;
25
+ import { Command , Middleware } from '../router' ;
25
26
26
27
/**
27
28
* Function type for wrapping command execution with custom logic.
@@ -34,7 +35,7 @@ export type RunCommand = <T extends AsyncFunction>(fn: T) => T;
34
35
* It can be used to define slash commands, context menu commands, and message commands.
35
36
*/
36
37
export interface AppCommandNative {
37
- command : SlashCommandBuilder | Record < string , any > ;
38
+ command : CommandData | Record < string , any > ;
38
39
chatInput ?: ( ctx : Context ) => Awaitable < unknown > ;
39
40
autocomplete ?: ( ctx : Context ) => Awaitable < unknown > ;
40
41
message ?: ( ctx : Context ) => Awaitable < unknown > ;
@@ -127,6 +128,10 @@ const commandDataSchema = {
127
128
userContextMenu : ( c : unknown ) => typeof c === 'function' ,
128
129
} ;
129
130
131
+ export type CommandDataSchema = typeof commandDataSchema ;
132
+ export type CommandDataSchemaKey = keyof CommandDataSchema ;
133
+ export type CommandDataSchemaValue = CommandDataSchema [ CommandDataSchemaKey ] ;
134
+
130
135
/**
131
136
* @private
132
137
* @internal
@@ -682,21 +687,35 @@ export class AppCommandHandler {
682
687
return ;
683
688
}
684
689
685
- const data = await import ( `${ toFileURL ( command . path ) } ?t=${ Date . now ( ) } ` ) ;
690
+ const commandFileData = ( await import (
691
+ `${ toFileURL ( command . path ) } ?t=${ Date . now ( ) } `
692
+ ) ) as AppCommandNative ;
686
693
687
- if ( ! data . command ) {
694
+ if ( ! commandFileData . command ) {
688
695
throw new Error (
689
696
`Invalid export for command ${ command . name } : no command definition found` ,
690
697
) ;
691
698
}
692
699
693
700
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
- ) ;
701
+
702
+ for ( const [ key , propValidator ] of Object . entries ( commandDataSchema ) as [
703
+ CommandDataSchemaKey ,
704
+ CommandDataSchemaValue ,
705
+ ] [ ] ) {
706
+ const exportedProp = commandFileData [ key ] ;
707
+
708
+ if ( exportedProp ) {
709
+ if ( ! ( await propValidator ( exportedProp ) ) ) {
710
+ throw new Error (
711
+ `Invalid export for command ${ command . name } : ${ key } does not match expected value` ,
712
+ ) ;
713
+ }
714
+
715
+ if ( key !== 'command' ) {
716
+ // command file includes a handler function (chatInput, message, etc)
717
+ handlerCount ++ ;
718
+ }
700
719
}
701
720
}
702
721
@@ -706,7 +725,7 @@ export class AppCommandHandler {
706
725
) ;
707
726
}
708
727
709
- let lastUpdated = data . command ;
728
+ let lastUpdated = commandFileData . command ;
710
729
711
730
await this . commandkit . plugins . execute ( async ( ctx , plugin ) => {
712
731
const res = await plugin . prepareCommand ( ctx , lastUpdated ) ;
@@ -718,9 +737,9 @@ export class AppCommandHandler {
718
737
719
738
this . loadedCommands . set ( id , {
720
739
command,
721
- guilds : data . guilds ,
740
+ guilds : commandFileData . command . guilds ,
722
741
data : {
723
- ...data ,
742
+ ...commandFileData ,
724
743
command : 'toJSON' in lastUpdated ? lastUpdated . toJSON ( ) : lastUpdated ,
725
744
} ,
726
745
} ) ;
0 commit comments