commandkit 0.1.10-dev.20231229094034 → 0.1.10-dev.20240108063947

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,50 +1,75 @@
1
- import { Client, ChatInputCommandInteraction, ContextMenuCommandInteraction, UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction, AutocompleteInteraction, PermissionsString, RESTPostAPIApplicationCommandsJSONBody, ButtonInteraction, Awaitable, Message, InteractionCollectorOptions, ButtonBuilder } from 'discord.js';
1
+ import * as discord_js from 'discord.js';
2
+ import { ChatInputCommandInteraction, ContextMenuCommandInteraction, AutocompleteInteraction, Client, UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction, PermissionsString, RESTPostAPIApplicationCommandsJSONBody, CacheType, Interaction, ButtonInteraction, Awaitable, Message, InteractionCollectorOptions, ButtonBuilder, PartialTextBasedChannelFields, TextBasedChannel, Guild, GuildMember, APIInteractionGuildMember, User } from 'discord.js';
3
+ import { AsyncLocalStorage } from 'async_hooks';
2
4
 
3
5
  /**
4
- * Options for instantiating a CommandKit handler.
6
+ * Validation handler options (validationsPath).
5
7
  */
6
- interface CommandKitOptions {
8
+ interface ValidationHandlerOptions {
9
+ validationsPath: string;
10
+ }
11
+
12
+ /**
13
+ * A handler for command validations.
14
+ */
15
+ declare class ValidationHandler {
16
+ #private;
17
+ constructor({ ...options }: ValidationHandlerOptions);
18
+ init(): Promise<void>;
19
+ get validations(): Function[];
20
+ reloadValidations(): Promise<void>;
21
+ }
22
+
23
+ /**
24
+ * Command handler options.
25
+ * Similar to CommandKit options in structure.
26
+ */
27
+ interface CommandHandlerOptions {
7
28
  /**
8
- * The Discord.js client object to use with CommandKit.
29
+ * The client created by the user.
9
30
  */
10
31
  client: Client;
11
32
  /**
12
- * The path to your commands directory.
33
+ * Path to the user's commands.
13
34
  */
14
- commandsPath?: string;
35
+ commandsPath: string;
15
36
  /**
16
- * The path to your events directory.
37
+ * An array of developer guild IDs.
17
38
  */
18
- eventsPath?: string;
39
+ devGuildIds: string[];
19
40
  /**
20
- * The path to the validations directory.
41
+ * An array of developer user IDs.
21
42
  */
22
- validationsPath?: string;
43
+ devUserIds: string[];
23
44
  /**
24
- * List of development guild IDs to restrict devOnly commands to.
45
+ * An array of developer role IDs.
25
46
  */
26
- devGuildIds?: string[];
47
+ devRoleIds: string[];
27
48
  /**
28
- * List of developer user IDs to restrict devOnly commands to.
49
+ * A validation handler instance to run validations before commands.
29
50
  */
30
- devUserIds?: string[];
51
+ validationHandler?: ValidationHandler;
31
52
  /**
32
- * List of developer role IDs to restrict devOnly commands to.
53
+ * A boolean indicating whether to skip CommandKit's built-in validations (permission checking, etc.)
33
54
  */
34
- devRoleIds?: string[];
55
+ skipBuiltInValidations: boolean;
35
56
  /**
36
- * Skip CommandKit's built-in validations (for devOnly commands).
57
+ * The CommandKit handler that instantiated this.
37
58
  */
38
- skipBuiltInValidations?: boolean;
59
+ commandkitInstance: CommandKit;
39
60
  /**
40
- * Bulk register application commands instead of one-by-one.
61
+ * A boolean indicating whether to register all commands in bulk.
41
62
  */
42
- bulkRegister?: boolean;
63
+ bulkRegister: boolean;
64
+ /**
65
+ * Whether to enable hooks context.
66
+ */
67
+ enableHooks: boolean;
43
68
  }
44
69
  /**
45
- * A reload type for commands.
70
+ * Represents a command interaction.
46
71
  */
47
- type ReloadOptions = 'dev' | 'global' | ReloadType;
72
+ type CommandKitInteraction = ChatInputCommandInteraction | ContextMenuCommandInteraction | AutocompleteInteraction;
48
73
 
49
74
  /**
50
75
  * Props for command run functions.
@@ -202,8 +227,110 @@ declare enum ReloadType {
202
227
  Global = "global"
203
228
  }
204
229
 
230
+ interface hCommandContext {
231
+ interaction: CommandKitInteraction;
232
+ command: CommandData;
233
+ }
234
+ /**
235
+ * A handler for client application commands.
236
+ */
237
+ declare class CommandHandler {
238
+ #private;
239
+ context: AsyncLocalStorage<hCommandContext> | null;
240
+ constructor({ ...options }: CommandHandlerOptions);
241
+ init(): Promise<void>;
242
+ handleCommands(): void;
243
+ get commands(): CommandFileObject[];
244
+ reloadCommands(type?: ReloadOptions): Promise<void>;
245
+ }
246
+
247
+ /**
248
+ * Options for instantiating a CommandKit handler.
249
+ */
250
+ interface CommandKitOptions {
251
+ /**
252
+ * The Discord.js client object to use with CommandKit.
253
+ */
254
+ client: Client;
255
+ /**
256
+ * The path to your commands directory.
257
+ */
258
+ commandsPath?: string;
259
+ /**
260
+ * The path to your events directory.
261
+ */
262
+ eventsPath?: string;
263
+ /**
264
+ * The path to the validations directory.
265
+ */
266
+ validationsPath?: string;
267
+ /**
268
+ * List of development guild IDs to restrict devOnly commands to.
269
+ */
270
+ devGuildIds?: string[];
271
+ /**
272
+ * List of developer user IDs to restrict devOnly commands to.
273
+ */
274
+ devUserIds?: string[];
275
+ /**
276
+ * List of developer role IDs to restrict devOnly commands to.
277
+ */
278
+ devRoleIds?: string[];
279
+ /**
280
+ * Skip CommandKit's built-in validations (for devOnly commands).
281
+ */
282
+ skipBuiltInValidations?: boolean;
283
+ /**
284
+ * Bulk register application commands instead of one-by-one.
285
+ */
286
+ bulkRegister?: boolean;
287
+ /**
288
+ * Options for experimental features.
289
+ */
290
+ experimental?: {
291
+ /**
292
+ * Enable hooks. This allows you to utilize hooks such as `useInteraction()` to access the interaction object anywhere inside the command.
293
+ */
294
+ hooks?: boolean;
295
+ };
296
+ }
297
+ /**
298
+ * Represents a command context.
299
+ */
300
+ interface CommandContext<T extends Interaction, Cached extends CacheType> {
301
+ /**
302
+ * The interaction that triggered this command.
303
+ */
304
+ interaction: Interaction<CacheType>;
305
+ /**
306
+ * The client that instantiated this command.
307
+ */
308
+ client: Client;
309
+ /**
310
+ * The command data.
311
+ */
312
+ handler: CommandKit;
313
+ }
314
+ /**
315
+ * Represents a command file.
316
+ */
317
+ interface CommandFileObject {
318
+ data: CommandData;
319
+ options?: CommandOptions;
320
+ run: <Cached extends CacheType = CacheType>(ctx: CommandContext<Interaction, Cached>) => Awaited<void>;
321
+ autocomplete?: <Cached extends CacheType = CacheType>(ctx: CommandContext<Interaction, Cached>) => Awaited<void>;
322
+ filePath: string;
323
+ category: string | null;
324
+ [key: string]: any;
325
+ }
326
+ /**
327
+ * A reload type for commands.
328
+ */
329
+ type ReloadOptions = 'dev' | 'global' | ReloadType;
330
+
205
331
  declare class CommandKit {
206
332
  #private;
333
+ static _instance: CommandKit | null;
207
334
  /**
208
335
  * Create a new command and event handler with CommandKit.
209
336
  *
@@ -211,6 +338,14 @@ declare class CommandKit {
211
338
  * @see {@link https://commandkit.js.org/docs/commandkit-setup}
212
339
  */
213
340
  constructor(options: CommandKitOptions);
341
+ /**
342
+ * Get the client attached to this CommandKit instance.
343
+ */
344
+ get client(): discord_js.Client<boolean>;
345
+ /**
346
+ * Get command handler instance.
347
+ */
348
+ get commandHandler(): CommandHandler | undefined;
214
349
  /**
215
350
  * Updates application commands with the latest from "commandsPath".
216
351
  */
@@ -376,4 +511,24 @@ declare function createSignal<T = unknown>(value?: CommandKitSignalInitializer<T
376
511
  */
377
512
  declare function createEffect(callback: CommandKitEffectCallback): void;
378
513
 
379
- export { AutocompleteProps, ButtonKit, CommandData, CommandKit, CommandKitButtonBuilderInteractionCollectorDispatch, CommandKitButtonBuilderInteractionCollectorDispatchContextData, CommandKitButtonBuilderOnEnd, CommandKitConfig, CommandKitEffectCallback, CommandKitSignal, CommandKitSignalInitializer, CommandKitSignalUpdater, CommandObject, CommandOptions, CommandProps, ContextMenuCommandProps, MessageContextMenuCommandProps, ReloadType, SlashCommandProps, UserContextMenuCommandProps, ValidationProps, createEffect, createSignal, defineConfig, getConfig };
514
+ declare function useClient(): discord_js.Client<boolean>;
515
+
516
+ declare function useCommandKit(): CommandKit;
517
+
518
+ type ChatInputReplyData = Parameters<ChatInputCommandInteraction['reply']>[0];
519
+ type MessageData = Parameters<PartialTextBasedChannelFields['send']>[0] | ChatInputReplyData;
520
+ declare function response(data: MessageData): Promise<void>;
521
+
522
+ declare function useChannel(): TextBasedChannel | null;
523
+
524
+ declare function useCommandData(): discord_js.RESTPostAPIApplicationCommandsJSONBody;
525
+
526
+ declare function useGuild(): Guild | null;
527
+
528
+ declare function useInteraction<T extends CommandKitInteraction = CommandKitInteraction>(): T;
529
+
530
+ declare function useMember(): GuildMember | APIInteractionGuildMember | null;
531
+
532
+ declare function useUser(): User;
533
+
534
+ export { AutocompleteProps, ButtonKit, CommandData, CommandKit, CommandKitButtonBuilderInteractionCollectorDispatch, CommandKitButtonBuilderInteractionCollectorDispatchContextData, CommandKitButtonBuilderOnEnd, CommandKitConfig, CommandKitEffectCallback, CommandKitSignal, CommandKitSignalInitializer, CommandKitSignalUpdater, CommandObject, CommandOptions, CommandProps, ContextMenuCommandProps, MessageContextMenuCommandProps, ReloadType, SlashCommandProps, UserContextMenuCommandProps, ValidationProps, createEffect, createSignal, defineConfig, getConfig, response, useChannel, useClient, useCommandData, useCommandKit, useGuild, useInteraction, useMember, useUser };
package/dist/index.d.ts CHANGED
@@ -1,50 +1,75 @@
1
- import { Client, ChatInputCommandInteraction, ContextMenuCommandInteraction, UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction, AutocompleteInteraction, PermissionsString, RESTPostAPIApplicationCommandsJSONBody, ButtonInteraction, Awaitable, Message, InteractionCollectorOptions, ButtonBuilder } from 'discord.js';
1
+ import * as discord_js from 'discord.js';
2
+ import { ChatInputCommandInteraction, ContextMenuCommandInteraction, AutocompleteInteraction, Client, UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction, PermissionsString, RESTPostAPIApplicationCommandsJSONBody, CacheType, Interaction, ButtonInteraction, Awaitable, Message, InteractionCollectorOptions, ButtonBuilder, PartialTextBasedChannelFields, TextBasedChannel, Guild, GuildMember, APIInteractionGuildMember, User } from 'discord.js';
3
+ import { AsyncLocalStorage } from 'async_hooks';
2
4
 
3
5
  /**
4
- * Options for instantiating a CommandKit handler.
6
+ * Validation handler options (validationsPath).
5
7
  */
6
- interface CommandKitOptions {
8
+ interface ValidationHandlerOptions {
9
+ validationsPath: string;
10
+ }
11
+
12
+ /**
13
+ * A handler for command validations.
14
+ */
15
+ declare class ValidationHandler {
16
+ #private;
17
+ constructor({ ...options }: ValidationHandlerOptions);
18
+ init(): Promise<void>;
19
+ get validations(): Function[];
20
+ reloadValidations(): Promise<void>;
21
+ }
22
+
23
+ /**
24
+ * Command handler options.
25
+ * Similar to CommandKit options in structure.
26
+ */
27
+ interface CommandHandlerOptions {
7
28
  /**
8
- * The Discord.js client object to use with CommandKit.
29
+ * The client created by the user.
9
30
  */
10
31
  client: Client;
11
32
  /**
12
- * The path to your commands directory.
33
+ * Path to the user's commands.
13
34
  */
14
- commandsPath?: string;
35
+ commandsPath: string;
15
36
  /**
16
- * The path to your events directory.
37
+ * An array of developer guild IDs.
17
38
  */
18
- eventsPath?: string;
39
+ devGuildIds: string[];
19
40
  /**
20
- * The path to the validations directory.
41
+ * An array of developer user IDs.
21
42
  */
22
- validationsPath?: string;
43
+ devUserIds: string[];
23
44
  /**
24
- * List of development guild IDs to restrict devOnly commands to.
45
+ * An array of developer role IDs.
25
46
  */
26
- devGuildIds?: string[];
47
+ devRoleIds: string[];
27
48
  /**
28
- * List of developer user IDs to restrict devOnly commands to.
49
+ * A validation handler instance to run validations before commands.
29
50
  */
30
- devUserIds?: string[];
51
+ validationHandler?: ValidationHandler;
31
52
  /**
32
- * List of developer role IDs to restrict devOnly commands to.
53
+ * A boolean indicating whether to skip CommandKit's built-in validations (permission checking, etc.)
33
54
  */
34
- devRoleIds?: string[];
55
+ skipBuiltInValidations: boolean;
35
56
  /**
36
- * Skip CommandKit's built-in validations (for devOnly commands).
57
+ * The CommandKit handler that instantiated this.
37
58
  */
38
- skipBuiltInValidations?: boolean;
59
+ commandkitInstance: CommandKit;
39
60
  /**
40
- * Bulk register application commands instead of one-by-one.
61
+ * A boolean indicating whether to register all commands in bulk.
41
62
  */
42
- bulkRegister?: boolean;
63
+ bulkRegister: boolean;
64
+ /**
65
+ * Whether to enable hooks context.
66
+ */
67
+ enableHooks: boolean;
43
68
  }
44
69
  /**
45
- * A reload type for commands.
70
+ * Represents a command interaction.
46
71
  */
47
- type ReloadOptions = 'dev' | 'global' | ReloadType;
72
+ type CommandKitInteraction = ChatInputCommandInteraction | ContextMenuCommandInteraction | AutocompleteInteraction;
48
73
 
49
74
  /**
50
75
  * Props for command run functions.
@@ -202,8 +227,110 @@ declare enum ReloadType {
202
227
  Global = "global"
203
228
  }
204
229
 
230
+ interface hCommandContext {
231
+ interaction: CommandKitInteraction;
232
+ command: CommandData;
233
+ }
234
+ /**
235
+ * A handler for client application commands.
236
+ */
237
+ declare class CommandHandler {
238
+ #private;
239
+ context: AsyncLocalStorage<hCommandContext> | null;
240
+ constructor({ ...options }: CommandHandlerOptions);
241
+ init(): Promise<void>;
242
+ handleCommands(): void;
243
+ get commands(): CommandFileObject[];
244
+ reloadCommands(type?: ReloadOptions): Promise<void>;
245
+ }
246
+
247
+ /**
248
+ * Options for instantiating a CommandKit handler.
249
+ */
250
+ interface CommandKitOptions {
251
+ /**
252
+ * The Discord.js client object to use with CommandKit.
253
+ */
254
+ client: Client;
255
+ /**
256
+ * The path to your commands directory.
257
+ */
258
+ commandsPath?: string;
259
+ /**
260
+ * The path to your events directory.
261
+ */
262
+ eventsPath?: string;
263
+ /**
264
+ * The path to the validations directory.
265
+ */
266
+ validationsPath?: string;
267
+ /**
268
+ * List of development guild IDs to restrict devOnly commands to.
269
+ */
270
+ devGuildIds?: string[];
271
+ /**
272
+ * List of developer user IDs to restrict devOnly commands to.
273
+ */
274
+ devUserIds?: string[];
275
+ /**
276
+ * List of developer role IDs to restrict devOnly commands to.
277
+ */
278
+ devRoleIds?: string[];
279
+ /**
280
+ * Skip CommandKit's built-in validations (for devOnly commands).
281
+ */
282
+ skipBuiltInValidations?: boolean;
283
+ /**
284
+ * Bulk register application commands instead of one-by-one.
285
+ */
286
+ bulkRegister?: boolean;
287
+ /**
288
+ * Options for experimental features.
289
+ */
290
+ experimental?: {
291
+ /**
292
+ * Enable hooks. This allows you to utilize hooks such as `useInteraction()` to access the interaction object anywhere inside the command.
293
+ */
294
+ hooks?: boolean;
295
+ };
296
+ }
297
+ /**
298
+ * Represents a command context.
299
+ */
300
+ interface CommandContext<T extends Interaction, Cached extends CacheType> {
301
+ /**
302
+ * The interaction that triggered this command.
303
+ */
304
+ interaction: Interaction<CacheType>;
305
+ /**
306
+ * The client that instantiated this command.
307
+ */
308
+ client: Client;
309
+ /**
310
+ * The command data.
311
+ */
312
+ handler: CommandKit;
313
+ }
314
+ /**
315
+ * Represents a command file.
316
+ */
317
+ interface CommandFileObject {
318
+ data: CommandData;
319
+ options?: CommandOptions;
320
+ run: <Cached extends CacheType = CacheType>(ctx: CommandContext<Interaction, Cached>) => Awaited<void>;
321
+ autocomplete?: <Cached extends CacheType = CacheType>(ctx: CommandContext<Interaction, Cached>) => Awaited<void>;
322
+ filePath: string;
323
+ category: string | null;
324
+ [key: string]: any;
325
+ }
326
+ /**
327
+ * A reload type for commands.
328
+ */
329
+ type ReloadOptions = 'dev' | 'global' | ReloadType;
330
+
205
331
  declare class CommandKit {
206
332
  #private;
333
+ static _instance: CommandKit | null;
207
334
  /**
208
335
  * Create a new command and event handler with CommandKit.
209
336
  *
@@ -211,6 +338,14 @@ declare class CommandKit {
211
338
  * @see {@link https://commandkit.js.org/docs/commandkit-setup}
212
339
  */
213
340
  constructor(options: CommandKitOptions);
341
+ /**
342
+ * Get the client attached to this CommandKit instance.
343
+ */
344
+ get client(): discord_js.Client<boolean>;
345
+ /**
346
+ * Get command handler instance.
347
+ */
348
+ get commandHandler(): CommandHandler | undefined;
214
349
  /**
215
350
  * Updates application commands with the latest from "commandsPath".
216
351
  */
@@ -376,4 +511,24 @@ declare function createSignal<T = unknown>(value?: CommandKitSignalInitializer<T
376
511
  */
377
512
  declare function createEffect(callback: CommandKitEffectCallback): void;
378
513
 
379
- export { AutocompleteProps, ButtonKit, CommandData, CommandKit, CommandKitButtonBuilderInteractionCollectorDispatch, CommandKitButtonBuilderInteractionCollectorDispatchContextData, CommandKitButtonBuilderOnEnd, CommandKitConfig, CommandKitEffectCallback, CommandKitSignal, CommandKitSignalInitializer, CommandKitSignalUpdater, CommandObject, CommandOptions, CommandProps, ContextMenuCommandProps, MessageContextMenuCommandProps, ReloadType, SlashCommandProps, UserContextMenuCommandProps, ValidationProps, createEffect, createSignal, defineConfig, getConfig };
514
+ declare function useClient(): discord_js.Client<boolean>;
515
+
516
+ declare function useCommandKit(): CommandKit;
517
+
518
+ type ChatInputReplyData = Parameters<ChatInputCommandInteraction['reply']>[0];
519
+ type MessageData = Parameters<PartialTextBasedChannelFields['send']>[0] | ChatInputReplyData;
520
+ declare function response(data: MessageData): Promise<void>;
521
+
522
+ declare function useChannel(): TextBasedChannel | null;
523
+
524
+ declare function useCommandData(): discord_js.RESTPostAPIApplicationCommandsJSONBody;
525
+
526
+ declare function useGuild(): Guild | null;
527
+
528
+ declare function useInteraction<T extends CommandKitInteraction = CommandKitInteraction>(): T;
529
+
530
+ declare function useMember(): GuildMember | APIInteractionGuildMember | null;
531
+
532
+ declare function useUser(): User;
533
+
534
+ export { AutocompleteProps, ButtonKit, CommandData, CommandKit, CommandKitButtonBuilderInteractionCollectorDispatch, CommandKitButtonBuilderInteractionCollectorDispatchContextData, CommandKitButtonBuilderOnEnd, CommandKitConfig, CommandKitEffectCallback, CommandKitSignal, CommandKitSignalInitializer, CommandKitSignalUpdater, CommandObject, CommandOptions, CommandProps, ContextMenuCommandProps, MessageContextMenuCommandProps, ReloadType, SlashCommandProps, UserContextMenuCommandProps, ValidationProps, createEffect, createSignal, defineConfig, getConfig, response, useChannel, useClient, useCommandData, useCommandKit, useGuild, useInteraction, useMember, useUser };
package/dist/index.js CHANGED
@@ -35,7 +35,16 @@ __export(src_exports, {
35
35
  createEffect: () => createEffect,
36
36
  createSignal: () => createSignal,
37
37
  defineConfig: () => defineConfig,
38
- getConfig: () => getConfig
38
+ getConfig: () => getConfig,
39
+ response: () => response,
40
+ useChannel: () => useChannel,
41
+ useClient: () => useClient,
42
+ useCommandData: () => useCommandData,
43
+ useCommandKit: () => useCommandKit,
44
+ useGuild: () => useGuild,
45
+ useInteraction: () => useInteraction,
46
+ useMember: () => useMember,
47
+ useUser: () => useUser
39
48
  });
40
49
  module.exports = __toCommonJS(src_exports);
41
50
 
@@ -470,8 +479,10 @@ function permissions_default({ interaction, targetCommand }) {
470
479
  var validations_default = [devOnly_default, permissions_default];
471
480
 
472
481
  // src/handlers/command-handler/CommandHandler.ts
482
+ var import_async_hooks = require("async_hooks");
473
483
  var CommandHandler = class {
474
484
  #data;
485
+ context = null;
475
486
  constructor({ ...options }) {
476
487
  this.#data = {
477
488
  ...options,
@@ -480,6 +491,9 @@ var CommandHandler = class {
480
491
  };
481
492
  }
482
493
  async init() {
494
+ if (this.#data.enableHooks && !this.context) {
495
+ this.context = new import_async_hooks.AsyncLocalStorage();
496
+ }
483
497
  await this.#buildCommands();
484
498
  this.#buildBuiltInValidations();
485
499
  const devOnlyCommands = this.#data.commands.filter((cmd) => cmd.options?.devOnly);
@@ -579,6 +593,7 @@ var CommandHandler = class {
579
593
  }
580
594
  }
581
595
  handleCommands() {
596
+ const areHooksEnabled = this.#data.enableHooks;
582
597
  this.#data.client.on("interactionCreate", async (interaction) => {
583
598
  if (!interaction.isChatInputCommand() && !interaction.isContextMenuCommand() && !interaction.isAutocomplete())
584
599
  return;
@@ -591,50 +606,65 @@ var CommandHandler = class {
591
606
  const { data, options, run, autocomplete, ...rest } = targetCommand;
592
607
  if (isAutocomplete && !autocomplete)
593
608
  return;
594
- const commandObj = {
595
- data: targetCommand.data,
596
- options: targetCommand.options,
597
- ...rest
598
- };
599
- if (this.#data.validationHandler) {
600
- let canRun2 = true;
601
- for (const validationFunction of this.#data.validationHandler.validations) {
602
- const stopValidationLoop = await validationFunction({
603
- interaction,
604
- commandObj,
605
- client: this.#data.client,
606
- handler: this.#data.commandkitInstance
607
- });
608
- if (stopValidationLoop) {
609
- canRun2 = false;
610
- break;
609
+ const executor = async () => {
610
+ const commandObj = {
611
+ data: targetCommand.data,
612
+ options: targetCommand.options,
613
+ ...rest
614
+ };
615
+ if (this.#data.validationHandler) {
616
+ let canRun2 = true;
617
+ for (const validationFunction of this.#data.validationHandler.validations) {
618
+ const stopValidationLoop = await validationFunction({
619
+ interaction,
620
+ commandObj,
621
+ client: this.#data.client,
622
+ handler: this.#data.commandkitInstance
623
+ });
624
+ if (stopValidationLoop) {
625
+ canRun2 = false;
626
+ break;
627
+ }
611
628
  }
629
+ if (!canRun2)
630
+ return;
612
631
  }
613
- if (!canRun2)
632
+ let canRun = true;
633
+ if (!this.#data.skipBuiltInValidations) {
634
+ for (const validation of this.#data.builtInValidations) {
635
+ const stopValidationLoop = validation({
636
+ targetCommand,
637
+ interaction,
638
+ handlerData: this.#data
639
+ });
640
+ if (stopValidationLoop) {
641
+ canRun = false;
642
+ break;
643
+ }
644
+ }
645
+ }
646
+ if (!canRun)
614
647
  return;
615
- }
616
- let canRun = true;
617
- if (!this.#data.skipBuiltInValidations) {
618
- for (const validation of this.#data.builtInValidations) {
619
- const stopValidationLoop = validation({
620
- targetCommand,
648
+ const command = targetCommand[isAutocomplete ? "autocomplete" : "run"];
649
+ if (!areHooksEnabled) {
650
+ const context2 = {
621
651
  interaction,
622
- handlerData: this.#data
623
- });
624
- if (stopValidationLoop) {
625
- canRun = false;
626
- break;
627
- }
652
+ client: this.#data.client,
653
+ handler: this.#data.commandkitInstance
654
+ };
655
+ return await command(context2);
628
656
  }
629
- }
630
- if (!canRun)
631
- return;
632
- const context2 = {
633
- interaction,
634
- client: this.#data.client,
635
- handler: this.#data.commandkitInstance
657
+ return command();
636
658
  };
637
- await targetCommand[isAutocomplete ? "autocomplete" : "run"](context2);
659
+ if (this.context)
660
+ return this.context.run(
661
+ {
662
+ command: targetCommand.data,
663
+ interaction
664
+ },
665
+ executor
666
+ );
667
+ return executor();
638
668
  });
639
669
  }
640
670
  get commands() {
@@ -808,8 +838,9 @@ var ValidationHandler = class {
808
838
  };
809
839
 
810
840
  // src/CommandKit.ts
811
- var CommandKit = class {
841
+ var CommandKit = class _CommandKit {
812
842
  #data;
843
+ static _instance = null;
813
844
  /**
814
845
  * Create a new command and event handler with CommandKit.
815
846
  *
@@ -826,8 +857,21 @@ var CommandKit = class {
826
857
  );
827
858
  }
828
859
  this.#data = options;
860
+ _CommandKit._instance = this;
829
861
  this.#init();
830
862
  }
863
+ /**
864
+ * Get the client attached to this CommandKit instance.
865
+ */
866
+ get client() {
867
+ return this.#data.client;
868
+ }
869
+ /**
870
+ * Get command handler instance.
871
+ */
872
+ get commandHandler() {
873
+ return this.#data.commandHandler;
874
+ }
831
875
  /**
832
876
  * (Private) Initialize CommandKit.
833
877
  */
@@ -858,7 +902,8 @@ var CommandKit = class {
858
902
  validationHandler: this.#data.validationHandler,
859
903
  skipBuiltInValidations: this.#data.skipBuiltInValidations || false,
860
904
  commandkitInstance: this,
861
- bulkRegister: this.#data.bulkRegister || false
905
+ bulkRegister: this.#data.bulkRegister || false,
906
+ enableHooks: this.#data.experimental?.hooks ?? false
862
907
  });
863
908
  await commandHandler.init();
864
909
  this.#data.commandHandler = commandHandler;
@@ -1111,6 +1156,103 @@ function createEffect(callback) {
1111
1156
  function getCurrentObserver() {
1112
1157
  return context[context.length - 1];
1113
1158
  }
1159
+
1160
+ // src/hooks/common.ts
1161
+ function getCommandKit() {
1162
+ return CommandKit._instance;
1163
+ }
1164
+ function getCommandHandler() {
1165
+ const handler = getCommandKit()?.commandHandler;
1166
+ if (!handler) {
1167
+ throw new Error("CommandKit is not initialized.");
1168
+ }
1169
+ return handler;
1170
+ }
1171
+ function getContext() {
1172
+ const info = getCommandHandler().context;
1173
+ if (!info) {
1174
+ throw new Error("Context is not available, did you forget to enable hooks?");
1175
+ }
1176
+ return info;
1177
+ }
1178
+ function prepareHookInvocationError(name) {
1179
+ return new Error(`Cannot invoke hook "${name}" outside of a command.`);
1180
+ }
1181
+
1182
+ // src/hooks/useCommandKit.ts
1183
+ function useCommandKit() {
1184
+ const kit = getCommandKit();
1185
+ if (!kit)
1186
+ throw new Error("CommandKit is not initialized.");
1187
+ return kit;
1188
+ }
1189
+
1190
+ // src/hooks/useClient.ts
1191
+ function useClient() {
1192
+ return useCommandKit().client;
1193
+ }
1194
+
1195
+ // src/hooks/useInteraction.ts
1196
+ function useInteraction() {
1197
+ const data = getContext().getStore();
1198
+ if (!data)
1199
+ throw prepareHookInvocationError("useInteraction");
1200
+ return data.interaction;
1201
+ }
1202
+
1203
+ // src/hooks/response.ts
1204
+ async function response(data) {
1205
+ const interaction = useInteraction();
1206
+ if (interaction.isAutocomplete())
1207
+ return;
1208
+ if (interaction.replied || interaction.deferred) {
1209
+ await interaction.editReply(data);
1210
+ } else if (interaction.isMessageComponent()) {
1211
+ await interaction.update(data);
1212
+ } else {
1213
+ await interaction.reply(data);
1214
+ }
1215
+ }
1216
+
1217
+ // src/hooks/useChannel.ts
1218
+ function useChannel() {
1219
+ const data = getContext().getStore();
1220
+ if (!data)
1221
+ throw prepareHookInvocationError("useChannel");
1222
+ return data.interaction.channel;
1223
+ }
1224
+
1225
+ // src/hooks/useCommandData.ts
1226
+ function useCommandData() {
1227
+ const data = getContext().getStore();
1228
+ if (!data)
1229
+ throw prepareHookInvocationError("useCommandData");
1230
+ return data.command;
1231
+ }
1232
+
1233
+ // src/hooks/useGuild.ts
1234
+ function useGuild() {
1235
+ const data = getContext().getStore();
1236
+ if (!data)
1237
+ throw prepareHookInvocationError("useGuild");
1238
+ return data.interaction.guild;
1239
+ }
1240
+
1241
+ // src/hooks/useMember.ts
1242
+ function useMember() {
1243
+ const data = getContext().getStore();
1244
+ if (!data)
1245
+ throw prepareHookInvocationError("useMember");
1246
+ return data.interaction.member;
1247
+ }
1248
+
1249
+ // src/hooks/useUser.ts
1250
+ function useUser() {
1251
+ const data = getContext().getStore();
1252
+ if (!data)
1253
+ throw prepareHookInvocationError("useUser");
1254
+ return data.interaction.user;
1255
+ }
1114
1256
  // Annotate the CommonJS export names for ESM import in node:
1115
1257
  0 && (module.exports = {
1116
1258
  ButtonKit,
@@ -1118,5 +1260,14 @@ function getCurrentObserver() {
1118
1260
  createEffect,
1119
1261
  createSignal,
1120
1262
  defineConfig,
1121
- getConfig
1263
+ getConfig,
1264
+ response,
1265
+ useChannel,
1266
+ useClient,
1267
+ useCommandData,
1268
+ useCommandKit,
1269
+ useGuild,
1270
+ useInteraction,
1271
+ useMember,
1272
+ useUser
1122
1273
  });
package/dist/index.mjs CHANGED
@@ -437,8 +437,10 @@ function permissions_default({ interaction, targetCommand }) {
437
437
  var validations_default = [devOnly_default, permissions_default];
438
438
 
439
439
  // src/handlers/command-handler/CommandHandler.ts
440
+ import { AsyncLocalStorage } from "async_hooks";
440
441
  var CommandHandler = class {
441
442
  #data;
443
+ context = null;
442
444
  constructor({ ...options }) {
443
445
  this.#data = {
444
446
  ...options,
@@ -447,6 +449,9 @@ var CommandHandler = class {
447
449
  };
448
450
  }
449
451
  async init() {
452
+ if (this.#data.enableHooks && !this.context) {
453
+ this.context = new AsyncLocalStorage();
454
+ }
450
455
  await this.#buildCommands();
451
456
  this.#buildBuiltInValidations();
452
457
  const devOnlyCommands = this.#data.commands.filter((cmd) => cmd.options?.devOnly);
@@ -546,6 +551,7 @@ var CommandHandler = class {
546
551
  }
547
552
  }
548
553
  handleCommands() {
554
+ const areHooksEnabled = this.#data.enableHooks;
549
555
  this.#data.client.on("interactionCreate", async (interaction) => {
550
556
  if (!interaction.isChatInputCommand() && !interaction.isContextMenuCommand() && !interaction.isAutocomplete())
551
557
  return;
@@ -558,50 +564,65 @@ var CommandHandler = class {
558
564
  const { data, options, run, autocomplete, ...rest } = targetCommand;
559
565
  if (isAutocomplete && !autocomplete)
560
566
  return;
561
- const commandObj = {
562
- data: targetCommand.data,
563
- options: targetCommand.options,
564
- ...rest
565
- };
566
- if (this.#data.validationHandler) {
567
- let canRun2 = true;
568
- for (const validationFunction of this.#data.validationHandler.validations) {
569
- const stopValidationLoop = await validationFunction({
570
- interaction,
571
- commandObj,
572
- client: this.#data.client,
573
- handler: this.#data.commandkitInstance
574
- });
575
- if (stopValidationLoop) {
576
- canRun2 = false;
577
- break;
567
+ const executor = async () => {
568
+ const commandObj = {
569
+ data: targetCommand.data,
570
+ options: targetCommand.options,
571
+ ...rest
572
+ };
573
+ if (this.#data.validationHandler) {
574
+ let canRun2 = true;
575
+ for (const validationFunction of this.#data.validationHandler.validations) {
576
+ const stopValidationLoop = await validationFunction({
577
+ interaction,
578
+ commandObj,
579
+ client: this.#data.client,
580
+ handler: this.#data.commandkitInstance
581
+ });
582
+ if (stopValidationLoop) {
583
+ canRun2 = false;
584
+ break;
585
+ }
578
586
  }
587
+ if (!canRun2)
588
+ return;
579
589
  }
580
- if (!canRun2)
590
+ let canRun = true;
591
+ if (!this.#data.skipBuiltInValidations) {
592
+ for (const validation of this.#data.builtInValidations) {
593
+ const stopValidationLoop = validation({
594
+ targetCommand,
595
+ interaction,
596
+ handlerData: this.#data
597
+ });
598
+ if (stopValidationLoop) {
599
+ canRun = false;
600
+ break;
601
+ }
602
+ }
603
+ }
604
+ if (!canRun)
581
605
  return;
582
- }
583
- let canRun = true;
584
- if (!this.#data.skipBuiltInValidations) {
585
- for (const validation of this.#data.builtInValidations) {
586
- const stopValidationLoop = validation({
587
- targetCommand,
606
+ const command = targetCommand[isAutocomplete ? "autocomplete" : "run"];
607
+ if (!areHooksEnabled) {
608
+ const context2 = {
588
609
  interaction,
589
- handlerData: this.#data
590
- });
591
- if (stopValidationLoop) {
592
- canRun = false;
593
- break;
594
- }
610
+ client: this.#data.client,
611
+ handler: this.#data.commandkitInstance
612
+ };
613
+ return await command(context2);
595
614
  }
596
- }
597
- if (!canRun)
598
- return;
599
- const context2 = {
600
- interaction,
601
- client: this.#data.client,
602
- handler: this.#data.commandkitInstance
615
+ return command();
603
616
  };
604
- await targetCommand[isAutocomplete ? "autocomplete" : "run"](context2);
617
+ if (this.context)
618
+ return this.context.run(
619
+ {
620
+ command: targetCommand.data,
621
+ interaction
622
+ },
623
+ executor
624
+ );
625
+ return executor();
605
626
  });
606
627
  }
607
628
  get commands() {
@@ -775,8 +796,9 @@ var ValidationHandler = class {
775
796
  };
776
797
 
777
798
  // src/CommandKit.ts
778
- var CommandKit = class {
799
+ var CommandKit = class _CommandKit {
779
800
  #data;
801
+ static _instance = null;
780
802
  /**
781
803
  * Create a new command and event handler with CommandKit.
782
804
  *
@@ -793,8 +815,21 @@ var CommandKit = class {
793
815
  );
794
816
  }
795
817
  this.#data = options;
818
+ _CommandKit._instance = this;
796
819
  this.#init();
797
820
  }
821
+ /**
822
+ * Get the client attached to this CommandKit instance.
823
+ */
824
+ get client() {
825
+ return this.#data.client;
826
+ }
827
+ /**
828
+ * Get command handler instance.
829
+ */
830
+ get commandHandler() {
831
+ return this.#data.commandHandler;
832
+ }
798
833
  /**
799
834
  * (Private) Initialize CommandKit.
800
835
  */
@@ -825,7 +860,8 @@ var CommandKit = class {
825
860
  validationHandler: this.#data.validationHandler,
826
861
  skipBuiltInValidations: this.#data.skipBuiltInValidations || false,
827
862
  commandkitInstance: this,
828
- bulkRegister: this.#data.bulkRegister || false
863
+ bulkRegister: this.#data.bulkRegister || false,
864
+ enableHooks: this.#data.experimental?.hooks ?? false
829
865
  });
830
866
  await commandHandler.init();
831
867
  this.#data.commandHandler = commandHandler;
@@ -1082,11 +1118,117 @@ function createEffect(callback) {
1082
1118
  function getCurrentObserver() {
1083
1119
  return context[context.length - 1];
1084
1120
  }
1121
+
1122
+ // src/hooks/common.ts
1123
+ function getCommandKit() {
1124
+ return CommandKit._instance;
1125
+ }
1126
+ function getCommandHandler() {
1127
+ const handler = getCommandKit()?.commandHandler;
1128
+ if (!handler) {
1129
+ throw new Error("CommandKit is not initialized.");
1130
+ }
1131
+ return handler;
1132
+ }
1133
+ function getContext() {
1134
+ const info = getCommandHandler().context;
1135
+ if (!info) {
1136
+ throw new Error("Context is not available, did you forget to enable hooks?");
1137
+ }
1138
+ return info;
1139
+ }
1140
+ function prepareHookInvocationError(name) {
1141
+ return new Error(`Cannot invoke hook "${name}" outside of a command.`);
1142
+ }
1143
+
1144
+ // src/hooks/useCommandKit.ts
1145
+ function useCommandKit() {
1146
+ const kit = getCommandKit();
1147
+ if (!kit)
1148
+ throw new Error("CommandKit is not initialized.");
1149
+ return kit;
1150
+ }
1151
+
1152
+ // src/hooks/useClient.ts
1153
+ function useClient() {
1154
+ return useCommandKit().client;
1155
+ }
1156
+
1157
+ // src/hooks/useInteraction.ts
1158
+ function useInteraction() {
1159
+ const data = getContext().getStore();
1160
+ if (!data)
1161
+ throw prepareHookInvocationError("useInteraction");
1162
+ return data.interaction;
1163
+ }
1164
+
1165
+ // src/hooks/response.ts
1166
+ async function response(data) {
1167
+ const interaction = useInteraction();
1168
+ if (interaction.isAutocomplete())
1169
+ return;
1170
+ if (interaction.replied || interaction.deferred) {
1171
+ await interaction.editReply(data);
1172
+ } else if (interaction.isMessageComponent()) {
1173
+ await interaction.update(data);
1174
+ } else {
1175
+ await interaction.reply(data);
1176
+ }
1177
+ }
1178
+
1179
+ // src/hooks/useChannel.ts
1180
+ function useChannel() {
1181
+ const data = getContext().getStore();
1182
+ if (!data)
1183
+ throw prepareHookInvocationError("useChannel");
1184
+ return data.interaction.channel;
1185
+ }
1186
+
1187
+ // src/hooks/useCommandData.ts
1188
+ function useCommandData() {
1189
+ const data = getContext().getStore();
1190
+ if (!data)
1191
+ throw prepareHookInvocationError("useCommandData");
1192
+ return data.command;
1193
+ }
1194
+
1195
+ // src/hooks/useGuild.ts
1196
+ function useGuild() {
1197
+ const data = getContext().getStore();
1198
+ if (!data)
1199
+ throw prepareHookInvocationError("useGuild");
1200
+ return data.interaction.guild;
1201
+ }
1202
+
1203
+ // src/hooks/useMember.ts
1204
+ function useMember() {
1205
+ const data = getContext().getStore();
1206
+ if (!data)
1207
+ throw prepareHookInvocationError("useMember");
1208
+ return data.interaction.member;
1209
+ }
1210
+
1211
+ // src/hooks/useUser.ts
1212
+ function useUser() {
1213
+ const data = getContext().getStore();
1214
+ if (!data)
1215
+ throw prepareHookInvocationError("useUser");
1216
+ return data.interaction.user;
1217
+ }
1085
1218
  export {
1086
1219
  ButtonKit,
1087
1220
  CommandKit,
1088
1221
  createEffect,
1089
1222
  createSignal,
1090
1223
  defineConfig,
1091
- getConfig
1224
+ getConfig,
1225
+ response,
1226
+ useChannel,
1227
+ useClient,
1228
+ useCommandData,
1229
+ useCommandKit,
1230
+ useGuild,
1231
+ useInteraction,
1232
+ useMember,
1233
+ useUser
1092
1234
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "commandkit",
3
3
  "description": "Beginner friendly command & event handler for Discord.js",
4
- "version": "0.1.10-dev.20231229094034",
4
+ "version": "0.1.10-dev.20240108063947",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.mjs",