commandkit 0.1.1 → 0.1.3-dev.20231002185336

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.js CHANGED
@@ -31,7 +31,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  CommandKit: () => CommandKit,
34
- CommandType: () => CommandType
34
+ CommandType: () => CommandType,
35
+ ReloadType: () => ReloadType
35
36
  });
36
37
  module.exports = __toCommonJS(src_exports);
37
38
 
@@ -75,7 +76,286 @@ function getFolderPaths(directory, nesting) {
75
76
  var import_path2 = __toESM(require("path"));
76
77
  function toFileURL(filePath) {
77
78
  const resolvedPath = import_path2.default.resolve(filePath);
78
- return "file://" + resolvedPath.replace(/\\/g, "/");
79
+ return "file://" + resolvedPath.replace(/\\\\|\\/g, "/");
80
+ }
81
+
82
+ // src/utils/colors.ts
83
+ var resetColor = "\x1B[0m";
84
+ var colors_default = {
85
+ reset: (text) => `${text}${resetColor}`,
86
+ bright: (text) => `\x1B[1m${text}${resetColor}`,
87
+ dim: (text) => `\x1B[2m${text}${resetColor}`,
88
+ underscore: (text) => `\x1B[4m${text}${resetColor}`,
89
+ blink: (text) => `\x1B[5m${text}${resetColor}`,
90
+ reverse: (text) => `\x1B[7m${text}${resetColor}`,
91
+ hidden: (text) => `\x1B[8m${text}${resetColor}`,
92
+ black: (text) => `\x1B[30m${text}${resetColor}`,
93
+ red: (text) => `\x1B[31m${text}${resetColor}`,
94
+ green: (text) => `\x1B[32m${text}${resetColor}`,
95
+ yellow: (text) => `\x1B[33m${text}${resetColor}`,
96
+ blue: (text) => `\x1B[34m${text}${resetColor}`,
97
+ magenta: (text) => `\x1B[35m${text}${resetColor}`,
98
+ cyan: (text) => `\x1B[36m${text}${resetColor}`,
99
+ white: (text) => `\x1B[37m${text}${resetColor}`,
100
+ bgBlack: (text) => `\x1B[40m${text}${resetColor}`,
101
+ bgRed: (text) => `\x1B[41m${text}${resetColor}`,
102
+ bgGreen: (text) => `\x1B[42m${text}${resetColor}`,
103
+ bgYellow: (text) => `\x1B[43m${text}${resetColor}`,
104
+ bgBlue: (text) => `\x1B[44m${text}${resetColor}`,
105
+ bgMagenta: (text) => `\x1B[45m${text}${resetColor}`,
106
+ bgCyan: (text) => `\x1B[46m${text}${resetColor}`,
107
+ bgWhite: (text) => `\x1B[47m${text}${resetColor}`
108
+ };
109
+
110
+ // src/handlers/command-handler/functions/loadCommandsWithRest.ts
111
+ async function loadCommandsWithRest(props) {
112
+ if (props.reloading) {
113
+ if (props.client.isReady()) {
114
+ await handleLoading(
115
+ props.client,
116
+ props.commands,
117
+ props.devGuildIds,
118
+ props.reloading,
119
+ props.type
120
+ );
121
+ } else {
122
+ throw new Error(colors_default.red(`\u274C Cannot reload commands when client is not ready.`));
123
+ }
124
+ } else {
125
+ props.client.once("ready", async (c) => {
126
+ await handleLoading(c, props.commands, props.devGuildIds, props.reloading, props.type);
127
+ });
128
+ }
129
+ }
130
+ async function handleLoading(client, commands, devGuildIds, reloading, type) {
131
+ const devOnlyCommands = commands.filter((cmd) => cmd.options?.devOnly);
132
+ const globalCommands = commands.filter((cmd) => !cmd.options?.devOnly);
133
+ if (type === "dev") {
134
+ await loadDevCommands(client, devOnlyCommands, devGuildIds, reloading);
135
+ } else if (type === "global") {
136
+ await loadGlobalCommands(client, globalCommands, reloading);
137
+ } else {
138
+ await loadDevCommands(client, devOnlyCommands, devGuildIds, reloading);
139
+ await loadGlobalCommands(client, globalCommands, reloading);
140
+ }
141
+ }
142
+ async function loadGlobalCommands(client, commands, reloading) {
143
+ const requestBody = commands.map((cmd) => cmd.data);
144
+ await client.application.commands.set(requestBody).catch((error) => {
145
+ console.log(
146
+ colors_default.red(
147
+ `\u274C Error ${reloading ? "reloading" : "loading"} global application commands.
148
+ `
149
+ )
150
+ );
151
+ throw new Error(error);
152
+ });
153
+ console.log(
154
+ colors_default.green(
155
+ `\u2705 ${reloading ? "Reloaded" : "Loaded"} ${requestBody.length} global commands.`
156
+ )
157
+ );
158
+ }
159
+ async function loadDevCommands(client, commands, guildIds, reloading) {
160
+ const requestBody = commands.map((cmd) => cmd.data);
161
+ for (const guildId of guildIds) {
162
+ const targetGuild = client.guilds.cache.get(guildId) || await client.guilds.fetch(guildId);
163
+ if (!targetGuild) {
164
+ console.log(
165
+ `Couldn't ${reloading ? "reloading" : "loading"} commands in guild "${targetGuild}" - guild doesn't exist or client isn't part of the guild.`
166
+ );
167
+ continue;
168
+ }
169
+ await targetGuild.commands.set(requestBody).catch((error) => {
170
+ console.log(
171
+ colors_default.red(
172
+ `\u274C Error ${reloading ? "reloading" : "loading"} developer application commands in guild "${targetGuild?.name || guildId}".
173
+ `
174
+ )
175
+ );
176
+ throw new Error(error);
177
+ });
178
+ console.log(
179
+ colors_default.green(
180
+ `\u2705 ${reloading ? "Reloaded" : "Loaded"} ${requestBody.length} developer commands in guild "${targetGuild.name}".`
181
+ )
182
+ );
183
+ }
184
+ }
185
+
186
+ // src/handlers/command-handler/utils/areSlashCommandsDifferent.ts
187
+ function areSlashCommandsDifferent(appCommand, localCommand) {
188
+ if (!appCommand.options)
189
+ appCommand.options = [];
190
+ if (!localCommand.options)
191
+ localCommand.options = [];
192
+ if (!appCommand.description)
193
+ appCommand.description = "";
194
+ if (!localCommand.description)
195
+ localCommand.description = "";
196
+ if (localCommand.description !== appCommand.description || localCommand.options.length !== appCommand.options.length) {
197
+ return true;
198
+ }
199
+ }
200
+
201
+ // src/handlers/command-handler/functions/registerCommands.ts
202
+ async function registerCommands(props) {
203
+ if (props.reloading) {
204
+ if (props.client.isReady()) {
205
+ await handleRegistration(props.client, props.commands, props.devGuildIds, props.type);
206
+ } else {
207
+ throw new Error(colors_default.red(`\u274C Cannot reload commands when client is not ready.`));
208
+ }
209
+ } else {
210
+ props.client.once("ready", async (c) => {
211
+ await handleRegistration(c, props.commands, props.devGuildIds, props.type);
212
+ });
213
+ }
214
+ }
215
+ async function handleRegistration(client, commands, devGuildIds, type) {
216
+ const devOnlyCommands = commands.filter((cmd) => cmd.options?.devOnly);
217
+ const globalCommands = commands.filter((cmd) => !cmd.options?.devOnly);
218
+ if (type === "dev") {
219
+ await registerDevCommands(client, devOnlyCommands, devGuildIds);
220
+ } else if (type === "global") {
221
+ await registerGlobalCommands(client, globalCommands);
222
+ } else {
223
+ await registerDevCommands(client, devOnlyCommands, devGuildIds);
224
+ await registerGlobalCommands(client, globalCommands);
225
+ }
226
+ }
227
+ async function registerGlobalCommands(client, commands) {
228
+ const appCommandsManager = client.application.commands;
229
+ await appCommandsManager.fetch();
230
+ for (const command of commands) {
231
+ const targetCommand = appCommandsManager.cache.find(
232
+ (cmd) => cmd.name === command.data.name
233
+ );
234
+ if (command.options?.deleted) {
235
+ if (!targetCommand) {
236
+ console.log(
237
+ colors_default.yellow(
238
+ `\u23E9 Ignoring: Command "${command.data.name}" is globally marked as deleted.`
239
+ )
240
+ );
241
+ } else {
242
+ targetCommand.delete().then(() => {
243
+ console.log(
244
+ colors_default.green(`\u{1F6AE} Deleted command "${command.data.name}" globally.`)
245
+ );
246
+ });
247
+ }
248
+ continue;
249
+ }
250
+ if (targetCommand) {
251
+ const commandsAreDifferent = areSlashCommandsDifferent(targetCommand, command.data);
252
+ if (commandsAreDifferent) {
253
+ targetCommand.edit(command.data).then(() => {
254
+ console.log(
255
+ colors_default.green(`\u2705 Edited command "${command.data.name}" globally.`)
256
+ );
257
+ }).catch((error) => {
258
+ console.log(
259
+ colors_default.red(
260
+ `\u274C Failed to edit command "${command.data.name}" globally.`
261
+ )
262
+ );
263
+ console.error(error);
264
+ });
265
+ continue;
266
+ }
267
+ }
268
+ if (targetCommand)
269
+ continue;
270
+ appCommandsManager.create(command.data).then(() => {
271
+ console.log(colors_default.green(`\u2705 Registered command "${command.data.name}" globally.`));
272
+ }).catch((error) => {
273
+ console.log(
274
+ colors_default.red(`\u274C Failed to register command "${command.data.name}" globally.`)
275
+ );
276
+ console.error(error);
277
+ });
278
+ }
279
+ }
280
+ async function registerDevCommands(client, commands, guildIds) {
281
+ const devGuilds = [];
282
+ for (const guildId of guildIds) {
283
+ const guild = client.guilds.cache.get(guildId) || await client.guilds.fetch(guildId);
284
+ if (!guild) {
285
+ console.log(
286
+ colors_default.yellow(
287
+ `\u23E9 Ignoring: Guild ${guildId} does not exist or client isn't in this guild.`
288
+ )
289
+ );
290
+ continue;
291
+ }
292
+ devGuilds.push(guild);
293
+ }
294
+ const guildCommandsManagers = [];
295
+ for (const guild of devGuilds) {
296
+ const guildCommandsManager = guild.commands;
297
+ await guildCommandsManager.fetch();
298
+ guildCommandsManagers.push(guildCommandsManager);
299
+ }
300
+ for (const command of commands) {
301
+ for (const guildCommands of guildCommandsManagers) {
302
+ const targetCommand = guildCommands.cache.find((cmd) => cmd.name === command.data.name);
303
+ if (command.options?.deleted) {
304
+ if (!targetCommand) {
305
+ console.log(
306
+ colors_default.yellow(
307
+ `\u23E9 Ignoring: Command "${command.data.name}" is marked as deleted for ${guildCommands.guild.name}.`
308
+ )
309
+ );
310
+ } else {
311
+ targetCommand.delete().then(() => {
312
+ console.log(
313
+ colors_default.green(
314
+ `\u{1F6AE} Deleted command "${command.data.name}" in ${guildCommands.guild.name}.`
315
+ )
316
+ );
317
+ });
318
+ }
319
+ continue;
320
+ }
321
+ if (targetCommand) {
322
+ const commandsAreDifferent = areSlashCommandsDifferent(targetCommand, command.data);
323
+ if (commandsAreDifferent) {
324
+ targetCommand.edit(command.data).then(() => {
325
+ console.log(
326
+ colors_default.green(
327
+ `\u2705 Edited command "${command.data.name}" in ${guildCommands.guild.name}.`
328
+ )
329
+ );
330
+ }).catch((error) => {
331
+ console.log(
332
+ colors_default.red(
333
+ `\u274C Failed to edit command "${command.data.name}" in ${guildCommands.guild.name}.`
334
+ )
335
+ );
336
+ console.error(error);
337
+ });
338
+ continue;
339
+ }
340
+ }
341
+ if (targetCommand)
342
+ continue;
343
+ guildCommands.create(command.data).then(() => {
344
+ console.log(
345
+ colors_default.green(
346
+ `\u2705 Registered command "${command.data.name}" in ${guildCommands.guild.name}.`
347
+ )
348
+ );
349
+ }).catch((error) => {
350
+ console.log(
351
+ colors_default.red(
352
+ `\u274C Failed to register command "${command.data.name}" in ${guildCommands.guild.name}.`
353
+ )
354
+ );
355
+ console.error(error);
356
+ });
357
+ }
358
+ }
79
359
  }
80
360
 
81
361
  // src/handlers/command-handler/validations/botPermissions.ts
@@ -119,7 +399,7 @@ function devOnly_default({ interaction, targetCommand, handlerData }) {
119
399
  const memberRoles = guildMember?.roles.cache;
120
400
  let hasDevRole = false;
121
401
  memberRoles?.forEach((role) => {
122
- if (handlerData.devRoleIds?.includes(role.id)) {
402
+ if (handlerData.devRoleIds.includes(role.id)) {
123
403
  hasDevRole = true;
124
404
  }
125
405
  });
@@ -175,254 +455,13 @@ function userPermissions_default({ interaction, targetCommand }) {
175
455
  // src/handlers/command-handler/validations/index.ts
176
456
  var validations_default = [botPermissions_default, devOnly_default, guildOnly_default, userPermissions_default];
177
457
 
178
- // src/handlers/command-handler/utils/areSlashCommandsDifferent.ts
179
- function areSlashCommandsDifferent(appCommand, localCommand) {
180
- if (!appCommand.options)
181
- appCommand.options = [];
182
- if (!localCommand.options)
183
- localCommand.options = [];
184
- if (!appCommand.description)
185
- appCommand.description = "";
186
- if (!localCommand.description)
187
- localCommand.description = "";
188
- if (localCommand.description !== appCommand.description || localCommand.options.length !== appCommand.options.length) {
189
- return true;
190
- }
191
- }
192
-
193
- // src/handlers/command-handler/functions/registerCommands.ts
194
- var import_safe = __toESM(require("colors/safe"));
195
- async function registerCommands(commandHandler) {
196
- const client = commandHandler._data.client;
197
- const devGuildIds = commandHandler._data.devGuildIds;
198
- const commands = commandHandler._data.commands;
199
- client.once("ready", async () => {
200
- const devGuilds = [];
201
- for (const devGuildId of devGuildIds) {
202
- const guild = client.guilds.cache.get(devGuildId);
203
- if (!guild) {
204
- console.log(
205
- import_safe.default.yellow(
206
- `\u23E9 Ignoring: Guild ${devGuildId} does not exist or client isn't in this guild.`
207
- )
208
- );
209
- continue;
210
- }
211
- devGuilds.push(guild);
212
- }
213
- const appCommands = client.application?.commands;
214
- await appCommands?.fetch();
215
- const devGuildCommands = [];
216
- for (const guild of devGuilds) {
217
- const guildCommands = guild.commands;
218
- await guildCommands?.fetch();
219
- devGuildCommands.push(guildCommands);
220
- }
221
- for (const command of commands) {
222
- let commandData = command.data;
223
- if (command.options?.deleted) {
224
- const targetCommand = appCommands?.cache.find(
225
- (cmd) => cmd.name === commandData.name
226
- );
227
- if (!targetCommand) {
228
- console.log(
229
- import_safe.default.yellow(
230
- `\u23E9 Ignoring: Command "${commandData.name}" is globally marked as deleted.`
231
- )
232
- );
233
- } else {
234
- targetCommand.delete().then(() => {
235
- console.log(
236
- import_safe.default.green(`\u{1F6AE} Deleted command "${commandData.name}" globally.`)
237
- );
238
- });
239
- }
240
- for (const guildCommands of devGuildCommands) {
241
- const targetCommand2 = guildCommands.cache.find(
242
- (cmd) => cmd.name === commandData.name
243
- );
244
- if (!targetCommand2) {
245
- console.log(
246
- import_safe.default.yellow(
247
- `\u23E9 Ignoring: Command "${commandData.name}" is marked as deleted for ${guildCommands.guild.name}.`
248
- )
249
- );
250
- } else {
251
- targetCommand2.delete().then(() => {
252
- console.log(
253
- import_safe.default.green(
254
- `\u{1F6AE} Deleted command "${commandData.name}" in ${guildCommands.guild.name}.`
255
- )
256
- );
257
- });
258
- }
259
- }
260
- continue;
261
- }
262
- let editedCommand = false;
263
- const appGlobalCommand = appCommands?.cache.find(
264
- (cmd) => cmd.name === commandData.name
265
- );
266
- if (appGlobalCommand) {
267
- const commandsAreDifferent = areSlashCommandsDifferent(
268
- appGlobalCommand,
269
- commandData
270
- );
271
- if (commandsAreDifferent) {
272
- appGlobalCommand.edit(commandData).then(() => {
273
- console.log(
274
- import_safe.default.green(`\u2705 Edited command "${commandData.name}" globally.`)
275
- );
276
- }).catch((error) => {
277
- console.log(
278
- import_safe.default.red(
279
- `\u274C Failed to edit command "${commandData.name}" globally.`
280
- )
281
- );
282
- console.error(error);
283
- });
284
- editedCommand = true;
285
- }
286
- }
287
- for (const guildCommands of devGuildCommands) {
288
- const appGuildCommand = guildCommands.cache.find(
289
- (cmd) => cmd.name === commandData.name
290
- );
291
- if (appGuildCommand) {
292
- const commandsAreDifferent = areSlashCommandsDifferent(
293
- appGuildCommand,
294
- commandData
295
- );
296
- if (commandsAreDifferent) {
297
- appGuildCommand.edit(commandData).then(() => {
298
- console.log(
299
- import_safe.default.green(
300
- `\u2705 Edited command "${commandData.name}" in ${guildCommands.guild.name}.`
301
- )
302
- );
303
- }).catch((error) => {
304
- console.log(
305
- import_safe.default.red(
306
- `\u274C Failed to edit command "${commandData.name}" in ${guildCommands.guild.name}.`
307
- )
308
- );
309
- console.error(error);
310
- });
311
- editedCommand = true;
312
- }
313
- }
314
- }
315
- if (editedCommand)
316
- continue;
317
- if (command.options?.devOnly) {
318
- if (!devGuilds.length) {
319
- console.log(
320
- import_safe.default.yellow(
321
- `\u23E9 Ignoring: Cannot register command "${commandData.name}" as no valid "devGuildIds" were provided.`
322
- )
323
- );
324
- continue;
325
- }
326
- for (const guild of devGuilds) {
327
- const cmdExists = guild.commands.cache.some(
328
- (cmd) => cmd.name === commandData.name
329
- );
330
- if (cmdExists)
331
- continue;
332
- guild?.commands.create(commandData).then(() => {
333
- console.log(
334
- import_safe.default.green(
335
- `\u2705 Registered command "${commandData.name}" in ${guild.name}.`
336
- )
337
- );
338
- }).catch((error) => {
339
- console.log(
340
- import_safe.default.red(
341
- `\u274C Failed to register command "${commandData.name}" in ${guild.name}.`
342
- )
343
- );
344
- console.error(error);
345
- });
346
- }
347
- } else {
348
- const cmdExists = appCommands?.cache.some((cmd) => cmd.name === commandData.name);
349
- if (cmdExists)
350
- continue;
351
- appCommands?.create(commandData).then(() => {
352
- console.log(
353
- import_safe.default.green(`\u2705 Registered command "${commandData.name}" globally.`)
354
- );
355
- }).catch((error) => {
356
- console.log(
357
- import_safe.default.red(
358
- `\u274C Failed to register command "${commandData.name}" globally.`
359
- )
360
- );
361
- console.error(error);
362
- });
363
- }
364
- }
365
- });
366
- }
367
-
368
- // src/handlers/command-handler/functions/handleCommands.ts
369
- function handleCommands(commandHandler) {
370
- const client = commandHandler._data.client;
371
- const handler = commandHandler._data.commandKitInstance;
372
- client.on("interactionCreate", async (interaction) => {
373
- if (!interaction.isChatInputCommand() && !interaction.isContextMenuCommand())
374
- return;
375
- const targetCommand = commandHandler._data.commands.find(
376
- (cmd) => cmd.data.name === interaction.commandName
377
- );
378
- if (!targetCommand)
379
- return;
380
- const { data, options, run, ...rest } = targetCommand;
381
- const commandObj = {
382
- data: targetCommand.data,
383
- options: targetCommand.options,
384
- ...rest
385
- };
386
- let canRun = true;
387
- for (const validationFunction of commandHandler._data.customValidations) {
388
- const stopValidationLoop = await validationFunction({
389
- interaction,
390
- client,
391
- commandObj,
392
- handler
393
- });
394
- if (stopValidationLoop) {
395
- canRun = false;
396
- break;
397
- }
398
- }
399
- if (!canRun)
400
- return;
401
- if (!commandHandler._data.skipBuiltInValidations) {
402
- for (const validation of commandHandler._data.builtInValidations) {
403
- const stopValidationLoop = validation({
404
- targetCommand,
405
- interaction,
406
- handlerData: commandHandler._data
407
- });
408
- if (stopValidationLoop) {
409
- canRun = false;
410
- break;
411
- }
412
- }
413
- }
414
- if (!canRun)
415
- return;
416
- targetCommand.run({ interaction, client, handler });
417
- });
418
- }
419
-
420
458
  // src/handlers/command-handler/CommandHandler.ts
421
- var import_safe2 = __toESM(require("colors/safe"));
459
+ var import_rfdc = __toESM(require("rfdc"));
460
+ var clone = (0, import_rfdc.default)();
422
461
  var CommandHandler = class {
423
- _data;
462
+ #data;
424
463
  constructor({ ...options }) {
425
- this._data = {
464
+ this.#data = {
426
465
  ...options,
427
466
  builtInValidations: [],
428
467
  commands: []
@@ -431,54 +470,177 @@ var CommandHandler = class {
431
470
  async init() {
432
471
  await this.#buildCommands();
433
472
  this.#buildValidations();
434
- await this.#registerCommands();
473
+ const devOnlyCommands = this.#data.commands.filter((cmd) => cmd.options?.devOnly);
474
+ if (devOnlyCommands.length && !this.#data.devGuildIds.length) {
475
+ console.log(
476
+ colors_default.yellow(
477
+ '\u2139\uFE0F Warning: You have commands marked as "devOnly" but "devGuildIds" has not been set.'
478
+ )
479
+ );
480
+ }
481
+ if (devOnlyCommands.length && !this.#data.devUserIds.length && !this.#data.devRoleIds.length) {
482
+ console.log(
483
+ colors_default.yellow(
484
+ '\u2139\uFE0F Warning: You have commands marked as "devOnly" but not "devUserIds" or "devRoleIds" were set.'
485
+ )
486
+ );
487
+ }
488
+ if (this.#data.useRest) {
489
+ await loadCommandsWithRest({
490
+ client: this.#data.client,
491
+ devGuildIds: this.#data.devGuildIds,
492
+ commands: this.#data.commands
493
+ });
494
+ } else {
495
+ await registerCommands({
496
+ client: this.#data.client,
497
+ devGuildIds: this.#data.devGuildIds,
498
+ commands: this.#data.commands
499
+ });
500
+ }
435
501
  this.#handleCommands();
436
502
  }
437
503
  async #buildCommands() {
438
- const commandFilePaths = getFilePaths(this._data.commandsPath, true).filter(
439
- (path3) => path3.endsWith(".js") || path3.endsWith(".ts")
504
+ const allowedExtensions = /\.(js|mjs|cjs|ts)$/i;
505
+ const commandFilePaths = getFilePaths(this.#data.commandsPath, true).filter(
506
+ (path3) => allowedExtensions.test(path3)
440
507
  );
441
508
  for (const commandFilePath of commandFilePaths) {
442
509
  const modulePath = toFileURL(commandFilePath);
443
- let commandObj = await import(modulePath);
510
+ let importedObj = await import(`${modulePath}?t=${Date.now()}`);
511
+ let commandObj = clone(importedObj);
512
+ if (typeof module !== "undefined" && typeof require !== "undefined") {
513
+ delete require.cache[require.resolve(commandFilePath)];
514
+ }
444
515
  const compactFilePath = commandFilePath.split(process.cwd())[1] || commandFilePath;
445
516
  if (commandObj.default)
446
517
  commandObj = commandObj.default;
447
518
  if (!commandObj.data) {
448
519
  console.log(
449
- import_safe2.default.yellow(
520
+ colors_default.yellow(
450
521
  `\u23E9 Ignoring: Command ${compactFilePath} does not export "data".`
451
522
  )
452
523
  );
453
524
  continue;
454
525
  }
526
+ if (!commandObj.data.name) {
527
+ console.log(
528
+ colors_default.yellow(
529
+ `\u23E9 Ignoring: Command ${compactFilePath} does not export "data.name".`
530
+ )
531
+ );
532
+ continue;
533
+ }
455
534
  if (!commandObj.run) {
456
535
  console.log(
457
- import_safe2.default.yellow(`\u23E9 Ignoring: Command ${compactFilePath} does not export "run".`)
536
+ colors_default.yellow(
537
+ `\u23E9 Ignoring: Command ${commandObj.data.name} does not export "run".`
538
+ )
539
+ );
540
+ continue;
541
+ }
542
+ if (typeof commandObj.run !== "function") {
543
+ console.log(
544
+ colors_default.yellow(
545
+ `\u23E9 Ignoring: Command ${commandObj.data.name} does not export "run" as a function.`
546
+ )
458
547
  );
459
548
  continue;
460
549
  }
461
- this._data.commands.push(commandObj);
550
+ commandObj.filePath = commandFilePath;
551
+ let commandCategory = commandFilePath.split(this.#data.commandsPath)[1]?.replace(/\\\\|\\/g, "/").split("/")[1] || null;
552
+ if (commandCategory && allowedExtensions.test(commandCategory)) {
553
+ commandObj.category = null;
554
+ } else {
555
+ commandObj.category = commandCategory;
556
+ }
557
+ this.#data.commands.push(commandObj);
462
558
  }
463
559
  }
464
560
  #buildValidations() {
465
561
  for (const validationFunction of validations_default) {
466
- this._data.builtInValidations.push(validationFunction);
562
+ this.#data.builtInValidations.push(validationFunction);
467
563
  }
468
564
  }
469
- async #registerCommands() {
470
- await registerCommands(this);
471
- }
472
565
  #handleCommands() {
473
- handleCommands(this);
566
+ this.#data.client.on("interactionCreate", async (interaction) => {
567
+ if (!interaction.isChatInputCommand() && !interaction.isContextMenuCommand())
568
+ return;
569
+ const targetCommand = this.#data.commands.find(
570
+ (cmd) => cmd.data.name === interaction.commandName
571
+ );
572
+ if (!targetCommand)
573
+ return;
574
+ const { data, options, run, ...rest } = targetCommand;
575
+ const commandObj = {
576
+ data: targetCommand.data,
577
+ options: targetCommand.options,
578
+ ...rest
579
+ };
580
+ let canRun = true;
581
+ for (const validationFunction of this.#data.customValidations) {
582
+ const stopValidationLoop = await validationFunction({
583
+ interaction,
584
+ commandObj,
585
+ client: this.#data.client,
586
+ handler: this.#data.handler
587
+ });
588
+ if (stopValidationLoop) {
589
+ canRun = false;
590
+ break;
591
+ }
592
+ }
593
+ if (!canRun)
594
+ return;
595
+ if (!this.#data.skipBuiltInValidations) {
596
+ for (const validation of this.#data.builtInValidations) {
597
+ const stopValidationLoop = validation({
598
+ targetCommand,
599
+ interaction,
600
+ handlerData: this.#data
601
+ });
602
+ if (stopValidationLoop) {
603
+ canRun = false;
604
+ break;
605
+ }
606
+ }
607
+ }
608
+ if (!canRun)
609
+ return;
610
+ targetCommand.run({
611
+ interaction,
612
+ client: this.#data.client,
613
+ handler: this.#data.handler
614
+ });
615
+ });
474
616
  }
475
617
  get commands() {
476
- return this._data.commands;
618
+ return this.#data.commands;
619
+ }
620
+ async reloadCommands(type) {
621
+ this.#data.commands = [];
622
+ await this.#buildCommands();
623
+ if (this.#data.useRest) {
624
+ await loadCommandsWithRest({
625
+ client: this.#data.client,
626
+ devGuildIds: this.#data.devGuildIds,
627
+ commands: this.#data.commands,
628
+ reloading: true,
629
+ type
630
+ });
631
+ } else {
632
+ await registerCommands({
633
+ client: this.#data.client,
634
+ devGuildIds: this.#data.devGuildIds,
635
+ commands: this.#data.commands,
636
+ reloading: true,
637
+ type
638
+ });
639
+ }
477
640
  }
478
641
  };
479
642
 
480
643
  // src/handlers/event-handler/EventHandler.ts
481
- var import_safe3 = __toESM(require("colors/safe"));
482
644
  var EventHandler = class {
483
645
  #data;
484
646
  constructor({ ...options }) {
@@ -494,7 +656,7 @@ var EventHandler = class {
494
656
  async #buildEvents() {
495
657
  const eventFolderPaths = getFolderPaths(this.#data.eventsPath);
496
658
  for (const eventFolderPath of eventFolderPaths) {
497
- const eventName = eventFolderPath.replace(/\\/g, "/").split("/").pop();
659
+ const eventName = eventFolderPath.replace(/\\\\|\\/g, "/").split("/").pop();
498
660
  const eventFilePaths = getFilePaths(eventFolderPath, true).filter(
499
661
  (path3) => path3.endsWith(".js") || path3.endsWith(".ts")
500
662
  );
@@ -512,7 +674,7 @@ var EventHandler = class {
512
674
  const compactFilePath = eventFilePath.split(process.cwd())[1] || eventFilePath;
513
675
  if (typeof eventFunction !== "function") {
514
676
  console.log(
515
- import_safe3.default.yellow(
677
+ colors_default.yellow(
516
678
  `\u23E9 Ignoring: Event ${compactFilePath} does not export a function.`
517
679
  )
518
680
  );
@@ -542,7 +704,6 @@ var EventHandler = class {
542
704
  };
543
705
 
544
706
  // src/handlers/validation-handler/ValidationHandler.ts
545
- var import_safe4 = __toESM(require("colors/safe"));
546
707
  var ValidationHandler = class {
547
708
  #data;
548
709
  constructor({ ...options }) {
@@ -567,7 +728,7 @@ var ValidationHandler = class {
567
728
  const compactFilePath = validationFilePath.split(process.cwd())[1] || validationFilePath;
568
729
  if (typeof validationFunction !== "function") {
569
730
  console.log(
570
- import_safe4.default.yellow(
731
+ colors_default.yellow(
571
732
  `\u23E9 Ignoring: Validation ${compactFilePath} does not export a function.`
572
733
  )
573
734
  );
@@ -582,22 +743,18 @@ var ValidationHandler = class {
582
743
  };
583
744
 
584
745
  // src/CommandKit.ts
585
- var import_safe5 = __toESM(require("colors/safe"));
586
746
  var CommandKit = class {
587
747
  #data;
588
- constructor({ ...options }) {
748
+ constructor(options) {
589
749
  if (!options.client) {
590
- throw new Error(import_safe5.default.red('"client" is required when instantiating CommandKit.'));
750
+ throw new Error(colors_default.red('"client" is required when instantiating CommandKit.'));
591
751
  }
592
752
  if (options.validationsPath && !options.commandsPath) {
593
753
  throw new Error(
594
- import_safe5.default.red('"commandsPath" is required when "validationsPath" is set.')
754
+ colors_default.red('"commandsPath" is required when "validationsPath" is set.')
595
755
  );
596
756
  }
597
- this.#data = {
598
- ...options,
599
- commands: []
600
- };
757
+ this.#data = options;
601
758
  this.#init();
602
759
  }
603
760
  async #init() {
@@ -608,6 +765,7 @@ var CommandKit = class {
608
765
  commandKitInstance: this
609
766
  });
610
767
  await eventHandler.init();
768
+ this.#data.eventHandler = eventHandler;
611
769
  }
612
770
  let validationFunctions = [];
613
771
  if (this.#data.validationsPath) {
@@ -616,6 +774,7 @@ var CommandKit = class {
616
774
  });
617
775
  await validationHandler.init();
618
776
  validationHandler.validations.forEach((v) => validationFunctions.push(v));
777
+ this.#data.validationHandler = validationHandler;
619
778
  }
620
779
  if (this.#data.commandsPath) {
621
780
  const commandHandler = new CommandHandler({
@@ -626,24 +785,71 @@ var CommandKit = class {
626
785
  devRoleIds: this.#data.devRoleIds || [],
627
786
  customValidations: validationFunctions,
628
787
  skipBuiltInValidations: this.#data.skipBuiltInValidations || false,
629
- commandKitInstance: this
788
+ handler: this,
789
+ useRest: this.#data.useRest || false
630
790
  });
631
791
  await commandHandler.init();
632
- this.#data.commands = commandHandler.commands;
792
+ this.#data.commandHandler = commandHandler;
633
793
  }
634
794
  }
635
795
  /**
636
- * Returns all the commands that CommandKit is handling.
637
- *
638
- * @returns An array of command objects
796
+ * Updates application commands with the latest from "commandsPath".
797
+ * @experimental
798
+ */
799
+ async reloadCommands(type) {
800
+ if (!this.#data.commandHandler)
801
+ return;
802
+ await this.#data.commandHandler.reloadCommands(type);
803
+ }
804
+ /**
805
+ * @returns An array of objects of all the commands that CommandKit is handling.
639
806
  */
640
807
  get commands() {
641
- const commands = this.#data.commands.map((cmd) => {
808
+ if (!this.#data.commandHandler) {
809
+ return [];
810
+ }
811
+ const commands = this.#data.commandHandler.commands.map((cmd) => {
642
812
  const { run, ...command } = cmd;
643
813
  return command;
644
814
  });
645
815
  return commands;
646
816
  }
817
+ /**
818
+ * @returns The path to the commands folder which was set when instantiating CommandKit.
819
+ */
820
+ get commandsPath() {
821
+ return this.#data.commandsPath;
822
+ }
823
+ /**
824
+ * @returns The path to the events folder which was set when instantiating CommandKit.
825
+ */
826
+ get eventsPath() {
827
+ return this.#data.eventsPath;
828
+ }
829
+ /**
830
+ * @returns The path to the validations folder which was set when instantiating CommandKit.
831
+ */
832
+ get validationsPath() {
833
+ return this.#data.validationsPath;
834
+ }
835
+ /**
836
+ * @returns An array of all the developer user IDs which was set when instantiating CommandKit.
837
+ */
838
+ get devUserIds() {
839
+ return this.#data.devUserIds || [];
840
+ }
841
+ /**
842
+ * @returns An array of all the developer guild IDs which was set when instantiating CommandKit.
843
+ */
844
+ get devGuildIds() {
845
+ return this.#data.devGuildIds || [];
846
+ }
847
+ /**
848
+ * @returns An array of all the developer role IDs which was set when instantiating CommandKit.
849
+ */
850
+ get devRoleIds() {
851
+ return this.#data.devRoleIds || [];
852
+ }
647
853
  };
648
854
 
649
855
  // src/types/index.ts
@@ -653,8 +859,14 @@ var CommandType = /* @__PURE__ */ ((CommandType2) => {
653
859
  CommandType2[CommandType2["User"] = 2] = "User";
654
860
  return CommandType2;
655
861
  })(CommandType || {});
862
+ var ReloadType = /* @__PURE__ */ ((ReloadType2) => {
863
+ ReloadType2["Developer"] = "dev";
864
+ ReloadType2["Global"] = "global";
865
+ return ReloadType2;
866
+ })(ReloadType || {});
656
867
  // Annotate the CommonJS export names for ESM import in node:
657
868
  0 && (module.exports = {
658
869
  CommandKit,
659
- CommandType
870
+ CommandType,
871
+ ReloadType
660
872
  });