bakit 2.0.0-alpha.9 → 2.0.0

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
@@ -1,838 +1,4 @@
1
- import { GatewayIntentBits, Events, Client, IntentsBitField, Collection, SlashCommandBuilder, SlashCommandStringOption, SlashCommandNumberOption, ChatInputCommandInteraction, Message } from 'discord.js';
2
- import z4, { z } from 'zod';
3
- import glob from 'tiny-glob';
4
- import { createJiti } from 'jiti';
5
- import { inspect } from 'util';
6
- import { posix, join, dirname } from 'path';
7
- import { existsSync, mkdirSync, rmSync } from 'fs';
8
- import { mkdir, writeFile, readFile, rm } from 'fs/promises';
9
- import { createHash } from 'crypto';
10
-
11
- // src/config.ts
12
- var INTENT_GROUPS = {
13
- [GatewayIntentBits.Guilds]: [
14
- Events.GuildCreate,
15
- Events.GuildDelete,
16
- Events.GuildUpdate,
17
- Events.GuildUnavailable,
18
- Events.GuildRoleCreate,
19
- Events.GuildRoleDelete,
20
- Events.GuildRoleUpdate,
21
- Events.ChannelCreate,
22
- Events.ChannelDelete,
23
- Events.ChannelUpdate,
24
- Events.ChannelPinsUpdate,
25
- Events.ThreadCreate,
26
- Events.ThreadDelete,
27
- Events.ThreadUpdate,
28
- Events.ThreadListSync,
29
- Events.ThreadMemberUpdate,
30
- Events.ThreadMembersUpdate,
31
- Events.StageInstanceCreate,
32
- Events.StageInstanceUpdate,
33
- Events.StageInstanceDelete
34
- ],
35
- [GatewayIntentBits.GuildMembers]: [
36
- Events.GuildMemberAdd,
37
- Events.GuildMemberUpdate,
38
- Events.GuildMemberRemove,
39
- Events.ThreadMembersUpdate
40
- ],
41
- [GatewayIntentBits.GuildModeration]: [Events.GuildAuditLogEntryCreate, Events.GuildBanAdd, Events.GuildBanRemove],
42
- [GatewayIntentBits.GuildExpressions]: [
43
- Events.GuildEmojiCreate,
44
- Events.GuildEmojiDelete,
45
- Events.GuildEmojiUpdate,
46
- Events.GuildStickerCreate,
47
- Events.GuildStickerDelete,
48
- Events.GuildStickerUpdate,
49
- Events.GuildSoundboardSoundCreate,
50
- Events.GuildSoundboardSoundUpdate,
51
- Events.GuildSoundboardSoundDelete,
52
- Events.GuildSoundboardSoundsUpdate
53
- ],
54
- [GatewayIntentBits.GuildIntegrations]: [Events.GuildIntegrationsUpdate],
55
- [GatewayIntentBits.GuildWebhooks]: [Events.WebhooksUpdate],
56
- [GatewayIntentBits.GuildInvites]: [Events.InviteCreate, Events.InviteDelete],
57
- [GatewayIntentBits.GuildVoiceStates]: [Events.VoiceStateUpdate],
58
- [GatewayIntentBits.GuildPresences]: [Events.PresenceUpdate],
59
- [GatewayIntentBits.GuildMessages]: [
60
- Events.MessageCreate,
61
- Events.MessageUpdate,
62
- Events.MessageDelete,
63
- Events.MessageBulkDelete
64
- ],
65
- [GatewayIntentBits.GuildMessageReactions]: [
66
- Events.MessageReactionAdd,
67
- Events.MessageReactionRemove,
68
- Events.MessageReactionRemoveAll,
69
- Events.MessageReactionRemoveEmoji
70
- ],
71
- [GatewayIntentBits.GuildMessageTyping]: [Events.TypingStart],
72
- [GatewayIntentBits.DirectMessages]: [
73
- Events.MessageCreate,
74
- Events.MessageUpdate,
75
- Events.MessageDelete,
76
- Events.ChannelPinsUpdate
77
- ],
78
- [GatewayIntentBits.DirectMessageReactions]: [
79
- Events.MessageReactionAdd,
80
- Events.MessageReactionRemove,
81
- Events.MessageReactionRemoveAll,
82
- Events.MessageReactionRemoveEmoji
83
- ],
84
- [GatewayIntentBits.DirectMessageTyping]: [Events.TypingStart],
85
- [GatewayIntentBits.MessageContent]: [Events.MessageCreate, Events.MessageUpdate],
86
- [GatewayIntentBits.GuildScheduledEvents]: [
87
- Events.GuildScheduledEventCreate,
88
- Events.GuildScheduledEventDelete,
89
- Events.GuildScheduledEventUpdate,
90
- Events.GuildScheduledEventUserAdd,
91
- Events.GuildScheduledEventUserRemove
92
- ],
93
- [GatewayIntentBits.AutoModerationConfiguration]: [
94
- Events.AutoModerationRuleCreate,
95
- Events.AutoModerationRuleDelete,
96
- Events.AutoModerationRuleUpdate
97
- ],
98
- [GatewayIntentBits.AutoModerationExecution]: [Events.AutoModerationActionExecution],
99
- [GatewayIntentBits.GuildMessagePolls]: [Events.MessagePollVoteAdd, Events.MessagePollVoteRemove],
100
- [GatewayIntentBits.DirectMessagePolls]: [Events.MessagePollVoteAdd, Events.MessagePollVoteRemove]
101
- }, EVENT_INTENT_MAPPING = {};
102
- for (let [intentStr, events] of Object.entries(INTENT_GROUPS)) {
103
- let intent = Number(intentStr);
104
- for (let event of events)
105
- EVENT_INTENT_MAPPING[event] ??= [], EVENT_INTENT_MAPPING[event].includes(intent) || EVENT_INTENT_MAPPING[event].push(intent);
106
- }
107
-
108
- // src/utils/string.ts
109
- function tokenize(content) {
110
- let args = [], current = "", quoteChar = null, isEscaped = false;
111
- for (let i = 0; i < content.length; i++) {
112
- let char = content[i];
113
- if (char === void 0)
114
- break;
115
- if (isEscaped) {
116
- current += char, isEscaped = false;
117
- continue;
118
- }
119
- if (char === "\\") {
120
- isEscaped = true;
121
- continue;
122
- }
123
- quoteChar ? char === quoteChar ? quoteChar = null : current += char : char === '"' ? quoteChar = char : /\s/.test(char) ? current.length > 0 && (args.push(current), current = "") : current += char;
124
- }
125
- return current.length > 0 && args.push(current), args;
126
- }
127
-
128
- // src/utils/index.ts
129
- var $jiti = createJiti(import.meta.url);
130
-
131
- // src/config.ts
132
- var ProjectConfigSchema = z.object({
133
- /**
134
- * The gateway intents to use for the Discord client.
135
- *
136
- * - `auto` — automatically determine the required intents.
137
- * - bigint — a raw bitfield value representing the combined intents.
138
- * - array — a list of individual intent flags from `GatewayIntentBits`.
139
- *
140
- * @defaultvalue `auto`
141
- */
142
- intents: z.union([z.literal("auto"), z.bigint(), z.array(z.enum(GatewayIntentBits))]).default("auto"),
143
- /**
144
- * Optional custom client options for Discord.js (excluding `intents`).
145
- *
146
- * These are passed directly to the `Client` constructor when initializing the bot.
147
- *
148
- * @see {@link https://discord.js.org/docs/packages/discord.js/main/ClientOptions:Interface}
149
- */
150
- clientOptions: z.custom().optional(),
151
- /**
152
- * The path to the main project source directory.
153
- *
154
- * @defaultvalue `src`
155
- */
156
- entryDir: z.string().default("src"),
157
- prefixes: z.array(z.string()).default([]),
158
- token: z.string()
159
- });
160
- function defineConfig(config) {
161
- return config;
162
- }
163
- var _config;
164
- async function loadConfig(cwd = process.cwd()) {
165
- if (_config)
166
- return console.warn("loadConfig() was called more than once. This shouldn't happen."), _config;
167
- let globPattern = `bakit.config.{${["ts", "js"].join(",")}}`, [configPath, other] = await glob(globPattern, {
168
- cwd: cwd.replace(/\\/g, "/"),
169
- // ensure the path uses `/` instead of `\` on Windows
170
- absolute: true
171
- });
172
- if (!configPath)
173
- throw new Error("Missing config file");
174
- other && console.warn(`Multiple config files found in ${cwd}. Using ${configPath}.`);
175
- let config = await $jiti.import(configPath, { default: true });
176
- return _config = Object.freeze(await ProjectConfigSchema.parseAsync(config)), _config;
177
- }
178
- function getConfig() {
179
- if (!_config)
180
- throw new Error("Project config is not loaded.");
181
- return _config;
182
- }
183
-
184
- // src/base/BaseClientManager.ts
185
- var BaseClientManager = class {
186
- constructor(client) {
187
- this.client = client;
188
- }
189
- };
190
-
191
- // src/base/lifecycle/Context.ts
192
- var Context = class {
193
- canceled = false;
194
- cancel() {
195
- this.canceled = true;
196
- }
197
- };
198
-
199
- // src/base/command/CommandContext.ts
200
- var BaseCommandContext = class extends Context {
201
- constructor(source) {
202
- super();
203
- this.source = source;
204
- }
205
- get client() {
206
- return this.source.client;
207
- }
208
- get channel() {
209
- return this.source.channel;
210
- }
211
- get channelId() {
212
- return this.source.channelId;
213
- }
214
- get guild() {
215
- return this.source.guild;
216
- }
217
- get guildId() {
218
- return this.source.guildId;
219
- }
220
- get member() {
221
- return this.source.member;
222
- }
223
- inGuild() {
224
- return !!this.guildId;
225
- }
226
- inCachedGuild() {
227
- if (this.isChatInput())
228
- return this.source.inCachedGuild();
229
- if (this.isMessage())
230
- return this.source.inGuild();
231
- throw new Error("Invalid source");
232
- }
233
- get user() {
234
- if (this.isChatInput())
235
- return this.source.user;
236
- if (this.isMessage())
237
- return this.source.author;
238
- throw new Error("Invalid source");
239
- }
240
- isChatInput() {
241
- return this.source instanceof ChatInputCommandInteraction;
242
- }
243
- isMessage() {
244
- return this.source instanceof Message;
245
- }
246
- }, ChatInputContext = class extends BaseCommandContext {
247
- async send(options) {
248
- typeof options == "string" && (options = { content: options });
249
- let sendOptions = {
250
- ...options,
251
- withResponse: true
252
- };
253
- return this.source.deferred || this.source.replied ? await this.source.followUp(sendOptions) : (await this.source.reply(sendOptions)).resource?.message;
254
- }
255
- }, MessageContext = class extends BaseCommandContext {
256
- async send(options) {
257
- let { channel } = this;
258
- if (!channel?.isSendable())
259
- throw new Error("Invalid channel or channel is not sendable");
260
- return await channel.send(options);
261
- }
262
- };
263
- var HookState = /* @__PURE__ */ ((HookState2) => (HookState2.Pre = "PRE", HookState2.Main = "MAIN", HookState2.Post = "POST", HookState2.Error = "ERROR", HookState2))(HookState || {}), HookOrder = /* @__PURE__ */ ((HookOrder2) => (HookOrder2[HookOrder2.First = 0] = "First", HookOrder2[HookOrder2.Last = 1] = "Last", HookOrder2))(HookOrder || {}), LifecycleManager = class {
264
- constructor(id) {
265
- this.id = id;
266
- }
267
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
268
- hooks = {
269
- MAIN: new Collection(),
270
- PRE: new Collection(),
271
- POST: new Collection(),
272
- ERROR: new Collection()
273
- };
274
- getName(name) {
275
- return `${this.id}:${name}`;
276
- }
277
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
278
- setHook(name, state, callback, order = 1 /* Last */) {
279
- let currentHooks = this.hooks[state], key = this.getName(name);
280
- if (currentHooks.has(key) && console.warn(`Overriding duplicate hook '${key}' for state '${state}'`), order === 1 /* Last */)
281
- currentHooks.set(key, callback);
282
- else {
283
- let existingEntries = [...currentHooks.entries()].filter(([k]) => k !== key);
284
- currentHooks.clear(), currentHooks.set(key, callback);
285
- for (let [k, v] of existingEntries)
286
- currentHooks.set(k, v);
287
- }
288
- return this;
289
- }
290
- main(callback) {
291
- return this.setHook("main", "MAIN" /* Main */, callback);
292
- }
293
- pre(callback) {
294
- return this.setHook("pre", "PRE" /* Pre */, callback);
295
- }
296
- post(callback) {
297
- return this.setHook("post", "POST" /* Post */, callback);
298
- }
299
- error(callback) {
300
- return this.setHook("error", "ERROR" /* Error */, callback);
301
- }
302
- async execute(context, ...args) {
303
- let pipeline = [
304
- ...this.hooks.PRE.values(),
305
- ...this.hooks.MAIN.values(),
306
- ...this.hooks.POST.values()
307
- ], error;
308
- for (let hook of pipeline) {
309
- if (context.canceled)
310
- break;
311
- try {
312
- await hook(context, ...args);
313
- } catch (e) {
314
- error = e;
315
- break;
316
- }
317
- }
318
- if (!error)
319
- return;
320
- if (!this.hooks.ERROR.size)
321
- throw error;
322
- for (let [key, callback] of this.hooks.ERROR.entries()) {
323
- if (context.canceled)
324
- break;
325
- try {
326
- await callback(context, error, ...args);
327
- } catch (innerError) {
328
- console.error(`[Lifecycle] Error handler for '${key}' failed:`, innerError);
329
- }
330
- }
331
- }
332
- };
333
- var ParamUserType = /* @__PURE__ */ ((ParamUserType2) => (ParamUserType2.Bot = "bot", ParamUserType2.Normal = "normal", ParamUserType2.Any = "any", ParamUserType2))(ParamUserType || {}), BaseParamSchema = z.object({
334
- name: z.string(),
335
- description: z.string().optional(),
336
- required: z.boolean().default(true)
337
- }), StringParamSchema = BaseParamSchema.extend({
338
- maxLength: z.number().min(1).optional(),
339
- minLength: z.number().min(1).optional()
340
- }), NumberParamSchema = BaseParamSchema.extend({
341
- maxValue: z.number().optional(),
342
- minValue: z.number().optional()
343
- });
344
-
345
- // src/errors/BakitError.ts
346
- var BakitError = class extends Error {
347
- constructor(message) {
348
- super(message), this.name = this.constructor.name, Object.setPrototypeOf(this, new.target.prototype);
349
- }
350
- };
351
-
352
- // src/errors/ArgumentError.ts
353
- var ArgumentError = class extends BakitError {
354
- constructor(target, reason) {
355
- super(`Invalid argument for '${target}': ${reason}`);
356
- this.target = target;
357
- this.reason = reason;
358
- }
359
- };
360
-
361
- // src/base/command/param/Param.ts
362
- var BaseParam = class {
363
- constructor(options, schema) {
364
- this.schema = schema;
365
- let parsed = schema.parse({
366
- ...options,
367
- description: options.description ?? options.name
368
- });
369
- this.options = parsed;
370
- }
371
- options;
372
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
373
- setOption(key, value) {
374
- if (value === null)
375
- return delete this.options[key], this;
376
- let fieldValidator = this.schema.shape[key];
377
- if (!fieldValidator)
378
- return this.options[key] = value, this;
379
- let parsedValue = fieldValidator.parse(value);
380
- return this.options[key] = parsedValue, this;
381
- }
382
- name(value) {
383
- return this.setOption("name", value);
384
- }
385
- description(value) {
386
- return this.setOption("description", value);
387
- }
388
- required(value) {
389
- return this.setOption("required", value);
390
- }
391
- async resolve(context, value) {
392
- if (context.isChatInput())
393
- return await this.resolveChatInput(context);
394
- if (context.isMessage())
395
- return await this.resolveMessage(context, value);
396
- throw new Error("Invalid context type provided");
397
- }
398
- /**
399
- * Helper to normalize string inputs into an options object.
400
- */
401
- static getOptions(options) {
402
- return typeof options == "string" ? { name: options } : options;
403
- }
404
- }, StringParam = class extends BaseParam {
405
- constructor(options) {
406
- super(BaseParam.getOptions(options), StringParamSchema);
407
- }
408
- required(value) {
409
- return super.required(value);
410
- }
411
- resolveMessage(_context, value) {
412
- let { required, minLength, maxLength, name } = this.options;
413
- if (value === void 0) {
414
- if (required)
415
- throw new ArgumentError(name, "is required");
416
- return null;
417
- }
418
- if (minLength && value.length < minLength)
419
- throw new ArgumentError(name, `must be at least ${minLength} chars long`);
420
- if (maxLength && value.length > maxLength)
421
- throw new ArgumentError(name, `must be at most ${maxLength} chars long`);
422
- return value;
423
- }
424
- resolveChatInput(context) {
425
- let { name, required } = this.options;
426
- return context.source.options.getString(name, required);
427
- }
428
- /**
429
- * Sets the minimum allowed length for this string.
430
- * Pass `null` to remove this constraint.
431
- */
432
- min(length) {
433
- return this.setOption("minLength", length);
434
- }
435
- /**
436
- * Sets the maximum allowed length for this string.
437
- * Pass `null` to remove this constraint.
438
- */
439
- max(length) {
440
- return this.setOption("maxLength", length);
441
- }
442
- }, NumberParam = class extends BaseParam {
443
- constructor(options) {
444
- super(BaseParam.getOptions(options), NumberParamSchema);
445
- }
446
- required(value) {
447
- return super.required(value);
448
- }
449
- resolveMessage(ctx, value) {
450
- let { required, minValue, maxValue, name } = this.options;
451
- if (value === void 0) {
452
- if (required)
453
- throw new ArgumentError(name, "is required");
454
- return null;
455
- }
456
- let num = Number(value);
457
- if (isNaN(num))
458
- throw new ArgumentError(name, "must be a number");
459
- if (minValue !== void 0 && num < minValue)
460
- throw new ArgumentError(name, `must be greater than ${minValue}`);
461
- if (maxValue !== void 0 && num > maxValue)
462
- throw new ArgumentError(name, `must be less than ${minValue}`);
463
- return num;
464
- }
465
- resolveChatInput(context) {
466
- let { name, required } = this.options;
467
- return context.source.options.getString(name, required);
468
- }
469
- /**
470
- * Sets the minimum allowed value for this number.
471
- * Pass `null` to remove this constraint.
472
- */
473
- min(value) {
474
- return this.setOption("minValue", value);
475
- }
476
- /**
477
- * Sets the maximum allowed value for this number.
478
- * Pass `null` to remove this constraint.
479
- */
480
- max(value) {
481
- return this.setOption("maxValue", value);
482
- }
483
- };
484
- function validateParamsOrder(params) {
485
- let seenOptional = false;
486
- for (let param of params)
487
- if (param.options.required) {
488
- if (seenOptional)
489
- return false;
490
- } else
491
- seenOptional = true;
492
- return true;
493
- }
494
- var CommandOptionsSchema = z.object({
495
- name: z.string().readonly(),
496
- description: z.string().min(1).max(100).optional().readonly(),
497
- nsfw: z.boolean().default(false).readonly(),
498
- params: z.array(z.instanceof(BaseParam)).default([]).readonly(),
499
- quotes: z.boolean().default(true).readonly()
500
- }).transform((data) => ({
501
- ...data,
502
- description: data.description ?? `Command ${data.name}`
503
- })).refine(({ params }) => validateParamsOrder(params), {
504
- path: ["params"],
505
- error: "Required params must be placed before optional params"
506
- }), Command = class extends LifecycleManager {
507
- constructor(options) {
508
- let _options = CommandOptionsSchema.parse(typeof options == "string" ? { name: options } : options);
509
- super(`command:${_options.name}`), this.options = _options, this.setHook("syntaxError", "ERROR" /* Error */, async (ctx, error, ...args) => {
510
- await this.handleSyntaxError(ctx, error, args);
511
- });
512
- }
513
- async handleSyntaxError(context, error, _args) {
514
- error instanceof BakitError && await context.send(error.message);
515
- }
516
- toSlashCommandJSON() {
517
- let { name, description, nsfw, params } = this.options, builder = new SlashCommandBuilder().setName(name).setDescription(description).setNSFW(nsfw);
518
- return this.initSlashCommandOptions(builder, params), builder.toJSON();
519
- }
520
- initSlashCommandOptions(builder, params) {
521
- for (let param of params)
522
- this.initSlashCommandOption(builder, param);
523
- }
524
- initSlashCommandOption(builder, param) {
525
- let initOption = (builder2) => {
526
- let { name, description, required } = param.options;
527
- return builder2.setName(name).setDescription(description).setRequired(required);
528
- };
529
- if (param instanceof StringParam) {
530
- let { maxLength, minLength } = param.options, option = initOption(new SlashCommandStringOption());
531
- maxLength && option.setMaxLength(maxLength), minLength && option.setMinLength(minLength), builder.addStringOption(option);
532
- return;
533
- }
534
- if (param instanceof NumberParam) {
535
- let { maxValue, minValue } = param.options, option = initOption(new SlashCommandNumberOption());
536
- maxValue && option.setMaxValue(maxValue), minValue && option.setMinValue(minValue), builder.addNumberOption(option);
537
- return;
538
- }
539
- }
540
- };
541
- function defineCommand(options) {
542
- return new Command(options);
543
- }
544
-
545
- // src/base/command/CommandManager.ts
546
- var CommandManager = class extends BaseClientManager {
547
- commands = new Collection();
548
- async loadModules() {
549
- let entryDir = posix.resolve(getConfig().entryDir), pattern = posix.join(entryDir, "commands", "**/*.{ts,js}"), loads = (await glob(pattern, {
550
- cwd: process.cwd(),
551
- absolute: true
552
- })).map(async (file) => {
553
- try {
554
- let command = await $jiti.import(file, { default: !0 });
555
- if (!command) {
556
- console.warn(`[Loader] File has no default export: ${file}`);
557
- return;
558
- }
559
- if (!(command instanceof Command)) {
560
- console.warn(`[Loader] Default export is not a Command: ${file}`);
561
- return;
562
- }
563
- return this.add(command), command;
564
- } catch (error) {
565
- console.error(`An error occurred while trying to add command for '${file}':`, error);
566
- }
567
- }), loaded = (await Promise.all(loads)).filter((x) => x !== void 0);
568
- return console.log(`Loaded ${loaded.length} command(s).`), loaded;
569
- }
570
- add(command) {
571
- if (!(command instanceof Command))
572
- throw new Error("Invalid command provided");
573
- let { name } = command.options;
574
- if (this.commands.has(name)) {
575
- console.warn(`[Loader] Duplicate command registered: '${name}'`);
576
- return;
577
- }
578
- this.commands.set(name, command);
579
- }
580
- remove(target) {
581
- let name = typeof target == "string" ? target : target.options.name, existing = this.commands.get(name);
582
- if (existing)
583
- return this.commands.delete(name), existing;
584
- }
585
- get(name) {
586
- return this.commands.get(name);
587
- }
588
- };
589
- var ListenerOptionsSchema = z4.object({
590
- name: z4.enum(Events),
591
- once: z4.boolean().default(false)
592
- }), Listener = class extends LifecycleManager {
593
- options;
594
- constructor(options) {
595
- let _options = ListenerOptionsSchema.parse(typeof options == "string" ? { name: options } : options);
596
- super(`listener:${_options.name}`), this.options = _options;
597
- }
598
- };
599
- function defineListener(options) {
600
- return new Listener(options);
601
- }
602
- var ListenerManager = class extends BaseClientManager {
603
- listeners = [];
604
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
605
- executors = /* @__PURE__ */ new WeakMap();
606
- async loadModules() {
607
- let entryDir = posix.resolve(getConfig().entryDir), pattern = posix.join(entryDir, "listeners", "**/*.{ts,js}"), loads = (await glob(pattern, {
608
- cwd: process.cwd(),
609
- absolute: true
610
- })).map(async (file) => {
611
- try {
612
- let listener = await $jiti.import(file, { default: !0 });
613
- if (!listener) {
614
- console.warn(`[Loader] File has no default export: ${file}`);
615
- return;
616
- }
617
- if (!(listener instanceof Listener)) {
618
- console.warn(`[Loader] Default export is not a Listener: ${file}`);
619
- return;
620
- }
621
- return this.add(listener), listener;
622
- } catch (error) {
623
- console.error(`An error occurred while trying to add listener for '${file}':`, error);
624
- }
625
- }), loaded = (await Promise.all(loads)).filter((x) => x !== void 0);
626
- return console.log(`Loaded ${loaded.length} listener(s).`), loaded;
627
- }
628
- add(listener) {
629
- if (!(listener instanceof Listener))
630
- throw new Error("Invalid listener provided");
631
- let execute = (...args) => {
632
- listener.execute(new Context(), ...args);
633
- };
634
- this.listeners.push(listener), this.executors.set(listener, execute);
635
- let { once, name } = listener.options;
636
- this.client[once ? "once" : "on"](name, execute);
637
- }
638
- remove(target) {
639
- let isMatched = (listener) => typeof target == "string" ? listener.options.name === target : listener === target, removed = [];
640
- return this.listeners = this.listeners.filter((listener) => {
641
- if (!isMatched(listener))
642
- return true;
643
- removed.push(listener);
644
- let execute = this.executors.get(listener);
645
- return execute && (this.client.removeListener(listener.options.name, execute), this.executors.delete(listener)), false;
646
- }), removed;
647
- }
648
- getBaseIntents() {
649
- return new IntentsBitField([GatewayIntentBits.Guilds]);
650
- }
651
- getNeededIntents() {
652
- let result = this.getBaseIntents();
653
- for (let listener of this.listeners) {
654
- let eventName = listener.options.name, requiredIntents = EVENT_INTENT_MAPPING[eventName];
655
- requiredIntents && result.add(requiredIntents);
656
- }
657
- return result;
658
- }
659
- };
660
-
661
- // src/base/BakitClient.ts
662
- var BakitClient2 = class extends Client {
663
- constructor(options, instance) {
664
- super(options);
665
- this.instance = instance;
666
- this.managers = {
667
- commands: new CommandManager(this),
668
- listeners: new ListenerManager(this)
669
- };
670
- }
671
- managers;
672
- /**
673
- * Check if the client is connected to gateway successfully and finished initialization.
674
- */
675
- isReady() {
676
- return super.isReady();
677
- }
678
- on(event, listener) {
679
- return super.on(event, listener);
680
- }
681
- once(event, listener) {
682
- return super.once(event, listener);
683
- }
684
- off(event, listener) {
685
- return super.off(event, listener);
686
- }
687
- removeAllListeners(event) {
688
- return super.removeAllListeners(event);
689
- }
690
- removeListener(event, listener) {
691
- return super.removeListener(event, listener);
692
- }
693
- emit(event, ...args) {
694
- return super.emit(event, ...args);
695
- }
696
- /**
697
- * Override BakitClient output when using logger for security concern.
698
- * @returns `BakitClient {}`
699
- */
700
- [inspect.custom]() {
701
- return `${this.constructor.name} {}`;
702
- }
703
- };
704
-
705
- // src/base/command/param/Params.ts
706
- function createFactory(ctor) {
707
- return (...args) => new ctor(...args);
708
- }
709
- var Params = {
710
- string: createFactory(StringParam),
711
- number: createFactory(NumberParam)
712
- };
713
-
714
- // src/defaults/command.ts
715
- var messageCommandHandler = defineListener(Events.MessageCreate), chatInputCommandHandler = defineListener(Events.InteractionCreate), registerCommandsHandler = defineListener({
716
- name: Events.ClientReady,
717
- once: true
718
- });
719
- registerCommandsHandler.main(async (_, client) => {
720
- let { managers, instance } = client, { commands } = managers, { cache } = instance, payload = commands.commands.map((cmd) => cmd.toSlashCommandJSON()).sort((a, b) => a.name.localeCompare(b.name)), currentHash = cache.getHash(payload), CACHE_KEY = "commands/meta.json", cachedMeta = await cache.read(CACHE_KEY);
721
- if (cachedMeta && cachedMeta.hash === currentHash) {
722
- let { timestamp, count } = cachedMeta, time = new Date(timestamp).toLocaleString();
723
- console.log(`${count} command(s) are up to date (Last sync: ${time}). Skipping registration.`);
724
- return;
725
- }
726
- try {
727
- let result = await client.application.commands.set(payload);
728
- cache.write(CACHE_KEY, {
729
- hash: currentHash,
730
- timestamp: Date.now(),
731
- count: result.size
732
- }), cache.write("commands/debug_dump.json", payload), console.log(`Registered ${result.size} application command(s).`);
733
- } catch (error) {
734
- console.error("Failed to register commands:", error);
735
- }
736
- });
737
- messageCommandHandler.main(async (_, message) => {
738
- let config = getConfig();
739
- if (message.author.bot)
740
- return;
741
- let { content } = message, client = message.client, lowerContent = content.toLowerCase(), prefix = config.prefixes.find((p) => lowerContent.startsWith(p));
742
- if (!prefix)
743
- return;
744
- let [name, ...args] = content.slice(prefix.length).trim().split(/\s+/g);
745
- if (!name)
746
- return;
747
- let command = client.managers.commands.get(name);
748
- if (!command)
749
- return;
750
- let context = new MessageContext(message), { params, quotes } = command.options, rawArgs = quotes ? tokenize(args.join(" ")) : args, resolvedArgs = [];
751
- for (let i = 0; i < params.length; i++) {
752
- let param = params[i], arg = rawArgs[i];
753
- if (!param)
754
- break;
755
- let resolved = await param.resolve(context, arg);
756
- resolvedArgs.push(resolved);
757
- }
758
- await command.execute(context, ...resolvedArgs);
759
- });
760
- chatInputCommandHandler.main(async (_, interaction) => {
761
- if (!interaction.isChatInputCommand())
762
- return;
763
- let { commandName } = interaction, command = interaction.client.managers.commands.get(commandName);
764
- if (!command)
765
- return;
766
- let context = new ChatInputContext(interaction), { params } = command.options, resolvedArgs = [];
767
- for (let param of params) {
768
- let resolved = await param.resolve(context);
769
- resolvedArgs.push(resolved);
770
- }
771
- await command.execute(context, ...resolvedArgs);
772
- });
773
- var ProjectCacheManager = class {
774
- rootDir;
775
- constructor(root = process.cwd()) {
776
- this.rootDir = join(root, ".bakit"), this.ensureRoot();
777
- }
778
- ensureRoot() {
779
- existsSync(this.rootDir) || mkdirSync(this.rootDir, { recursive: true });
780
- }
781
- getHash(data) {
782
- return createHash("sha256").update(JSON.stringify(data)).digest("hex");
783
- }
784
- async write(path, data) {
785
- let fullPath = join(this.rootDir, path), dir = dirname(fullPath);
786
- await mkdir(dir, { recursive: true });
787
- let content = typeof data == "string" ? data : JSON.stringify(data);
788
- await writeFile(fullPath, content, "utf-8");
789
- }
790
- async read(path) {
791
- let fullPath = join(this.rootDir, path);
792
- try {
793
- let content = await readFile(fullPath, "utf-8");
794
- return JSON.parse(content);
795
- } catch {
796
- return null;
797
- }
798
- }
799
- async clear() {
800
- await rm(this.rootDir, { recursive: true, force: true });
801
- }
802
- clearSync() {
803
- existsSync(this.rootDir) && rmSync(this.rootDir, { recursive: true, force: true });
804
- }
805
- };
806
-
807
- // src/base/Instance.ts
808
- var Instance = class {
809
- client;
810
- cache;
811
- constructor() {
812
- this.cache = new ProjectCacheManager();
813
- }
814
- async start() {
815
- await loadConfig();
816
- let config = getConfig();
817
- this.client = new BakitClient2(
818
- {
819
- intents: [],
820
- ...config.clientOptions
821
- },
822
- this
823
- ), await this.loadModules(), this.initIntents(), await this.client.login(config.token);
824
- }
825
- loadModules() {
826
- let { managers } = this.client, { commands, listeners } = managers;
827
- return listeners.add(chatInputCommandHandler), listeners.add(messageCommandHandler), listeners.add(registerCommandsHandler), Promise.all([commands.loadModules(), listeners.loadModules()]);
828
- }
829
- initIntents() {
830
- let config = getConfig(), { options, managers } = this.client, { listeners } = managers, intents;
831
- config.intents === "auto" ? intents = listeners.getNeededIntents() : (intents = listeners.getBaseIntents(), typeof config.intents == "bigint" ? intents.bitfield = Number(config.intents) : intents.add(...config.intents)), options.intents = intents;
832
- }
833
- };
834
- function useApp() {
835
- return new Instance();
836
- }
837
-
838
- export { $jiti, ArgumentError, BakitClient2 as BakitClient, BakitError, BaseClientManager, BaseCommandContext, BaseParam, BaseParamSchema, ChatInputContext, Command, CommandManager, CommandOptionsSchema, Context, EVENT_INTENT_MAPPING, HookOrder, HookState, Instance, LifecycleManager, Listener, ListenerManager, ListenerOptionsSchema, MessageContext, NumberParam, NumberParamSchema, ParamUserType, Params, ProjectConfigSchema, StringParam, StringParamSchema, defineCommand, defineConfig, defineListener, getConfig, loadConfig, tokenize, useApp, validateParamsOrder };
1
+ export { DEFAULT_GATEWAY_MANAGER_OPTIONS, DEFAULT_WORKER_PATH, createGatewayManager, createWorker } from '@bakit/gateway';
2
+ export { createREST, createRESTTransportServer } from '@bakit/rest';
3
+ export { Collection, attachEventBus, capitalize, createEventBus, createQueue, isPlainObject, isPromiseLike, promisify, sleep } from '@bakit/utils';
4
+ export { RPCError, createIPCClient, createIPCServer, createService, createServiceClient, createServiceServer, createTransportClient, createTransportServer, deserializeRPCError, getIPCPath, serializeRPCError } from '@bakit/service';