slash-command-dispatch.ts
1 export type SlashCommandWithKind = { 2 kind: string 3 } 4 5 export type SlashCommandHandlerMap< 6 TCommand extends SlashCommandWithKind, 7 TResult, 8 TContext, 9 > = { 10 [Kind in TCommand['kind']]: (input: { 11 command: Extract<TCommand, { kind: Kind }> 12 context: TContext 13 }) => Promise<TResult> | TResult 14 } 15 16 export async function dispatchSlashCommand< 17 TCommand extends SlashCommandWithKind, 18 TResult, 19 TContext, 20 >(input: { 21 text: string 22 parsedCommand?: TCommand | null 23 parseCommand: (text: string) => TCommand | null 24 context: TContext 25 handlers: SlashCommandHandlerMap<TCommand, TResult, TContext> 26 onUnknownSlash: (input: { 27 rawText: string 28 context: TContext 29 }) => Promise<TResult> | TResult 30 }): Promise<TResult | null> { 31 const command = input.parsedCommand ?? input.parseCommand(input.text) 32 if (!command) { 33 if (input.text.trim().startsWith('/')) { 34 return input.onUnknownSlash({ 35 rawText: input.text, 36 context: input.context, 37 }) 38 } 39 return null 40 } 41 42 const handler = input.handlers[command.kind as TCommand['kind']] 43 44 return handler({ 45 command: command as never, 46 context: input.context, 47 }) 48 }