1- import type { CommandKit } from '../../CommandKit' ;
21import {
32 AutocompleteInteraction ,
43 Awaitable ,
@@ -10,18 +9,20 @@ import {
109 Message ,
1110 SlashCommandBuilder ,
1211} 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' ;
1813import { AsyncFunction , GenericFunction } from '../../context/async-context' ;
1914import { 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 ' ;
2217import { COMMANDKIT_IS_DEV } from '../../utils/constants' ;
18+ import { CommandKitErrorCodes , isErrorType } from '../../utils/error-codes' ;
19+ import { toFileURL } from '../../utils/resolve-file-url' ;
2320import { 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' ;
2526
2627/**
2728 * Function type for wrapping command execution with custom logic.
@@ -34,7 +35,7 @@ export type RunCommand = <T extends AsyncFunction>(fn: T) => T;
3435 * It can be used to define slash commands, context menu commands, and message commands.
3536 */
3637export interface AppCommandNative {
37- command : SlashCommandBuilder | Record < string , any > ;
38+ command : CommandData | Record < string , any > ;
3839 chatInput ?: ( ctx : Context ) => Awaitable < unknown > ;
3940 autocomplete ?: ( ctx : Context ) => Awaitable < unknown > ;
4041 message ?: ( ctx : Context ) => Awaitable < unknown > ;
@@ -127,6 +128,10 @@ const commandDataSchema = {
127128 userContextMenu : ( c : unknown ) => typeof c === 'function' ,
128129} ;
129130
131+ export type CommandDataSchema = typeof commandDataSchema ;
132+ export type CommandDataSchemaKey = keyof CommandDataSchema ;
133+ export type CommandDataSchemaValue = CommandDataSchema [ CommandDataSchemaKey ] ;
134+
130135/**
131136 * @private
132137 * @internal
@@ -682,21 +687,35 @@ export class AppCommandHandler {
682687 return ;
683688 }
684689
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 ;
686693
687- if ( ! data . command ) {
694+ if ( ! commandFileData . command ) {
688695 throw new Error (
689696 `Invalid export for command ${ command . name } : no command definition found` ,
690697 ) ;
691698 }
692699
693700 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+ }
700719 }
701720 }
702721
@@ -706,7 +725,7 @@ export class AppCommandHandler {
706725 ) ;
707726 }
708727
709- let lastUpdated = data . command ;
728+ let lastUpdated = commandFileData . command ;
710729
711730 await this . commandkit . plugins . execute ( async ( ctx , plugin ) => {
712731 const res = await plugin . prepareCommand ( ctx , lastUpdated ) ;
@@ -718,9 +737,9 @@ export class AppCommandHandler {
718737
719738 this . loadedCommands . set ( id , {
720739 command,
721- guilds : data . guilds ,
740+ guilds : commandFileData . command . guilds ,
722741 data : {
723- ...data ,
742+ ...commandFileData ,
724743 command : 'toJSON' in lastUpdated ? lastUpdated . toJSON ( ) : lastUpdated ,
725744 } ,
726745 } ) ;
0 commit comments