commandkit 0.1.3 → 0.1.4-dev.20231003142112

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