bakit 2.0.0-alpha.10 → 2.0.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +99 -11
- package/dist/index.js +240 -88
- package/package.json +3 -2
- package/bin/bakit.js +0 -39
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as discord_js from 'discord.js';
|
|
2
|
-
import { GatewayIntentBits, ClientOptions, ChatInputCommandInteraction, CacheType, Message, User, MessageCreateOptions, InteractionReplyOptions, Awaitable, Collection, Events, IntentsBitField,
|
|
2
|
+
import { GatewayIntentBits, ClientOptions, ChatInputCommandInteraction, CacheType, Message, User, MessageCreateOptions, InteractionReplyOptions, Awaitable, Collection, Events, IntentsBitField, ClientEvents, Client } from 'discord.js';
|
|
3
3
|
import z$1, { z } from 'zod';
|
|
4
4
|
import * as jiti from 'jiti';
|
|
5
5
|
import { inspect } from 'node:util';
|
|
@@ -7,7 +7,6 @@ import { inspect } from 'node:util';
|
|
|
7
7
|
declare const ProjectConfigSchema: z.ZodObject<{
|
|
8
8
|
intents: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBigInt, z.ZodArray<z.ZodEnum<typeof GatewayIntentBits>>]>>;
|
|
9
9
|
clientOptions: z.ZodOptional<z.ZodCustom<Omit<ClientOptions, "intents">, Omit<ClientOptions, "intents">>>;
|
|
10
|
-
entryDir: z.ZodDefault<z.ZodString>;
|
|
11
10
|
prefixes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
12
11
|
token: z.ZodString;
|
|
13
12
|
}, z.core.$strip>;
|
|
@@ -41,7 +40,14 @@ declare function tokenize(content: string): string[];
|
|
|
41
40
|
*/
|
|
42
41
|
declare function extractSnowflakeId(input: string): string | null;
|
|
43
42
|
|
|
44
|
-
declare
|
|
43
|
+
declare class Module {
|
|
44
|
+
static jiti: jiti.Jiti;
|
|
45
|
+
static import<T>(module: string, defaultImport?: boolean): Promise<T | null>;
|
|
46
|
+
static isLoaded(module: string): boolean;
|
|
47
|
+
static unload(module: string): boolean;
|
|
48
|
+
static resolve(module: string): string | null;
|
|
49
|
+
static getTopLevel(path: string, entryDir: string): string | null;
|
|
50
|
+
}
|
|
45
51
|
|
|
46
52
|
declare class Context {
|
|
47
53
|
canceled: boolean;
|
|
@@ -295,11 +301,43 @@ declare function defineCommand<const ParamsList extends readonly AnyParam<any>[]
|
|
|
295
301
|
params?: ParamsList;
|
|
296
302
|
}) | string): Command<ParamsList>;
|
|
297
303
|
|
|
304
|
+
declare class BaseClientManager {
|
|
305
|
+
client: BakitClient;
|
|
306
|
+
constructor(client: BakitClient);
|
|
307
|
+
}
|
|
308
|
+
|
|
298
309
|
declare class CommandManager extends BaseClientManager {
|
|
299
310
|
commands: Collection<string, Command<any[]>>;
|
|
300
|
-
|
|
311
|
+
entries: Collection<string, Command<any[]>>;
|
|
312
|
+
loadModules(entryDir: string): Promise<Command[]>;
|
|
313
|
+
/**
|
|
314
|
+
* Load the file and add the command to the registry.
|
|
315
|
+
* @param path The path to the command file.
|
|
316
|
+
* @returns The command object if added successfully.
|
|
317
|
+
*/
|
|
318
|
+
load(path: string): Promise<Command | undefined>;
|
|
319
|
+
/**
|
|
320
|
+
* Unload the file and remove the command from the registry.
|
|
321
|
+
* @param path The path to the command file.
|
|
322
|
+
* @returns The command object if unloaded successfully.
|
|
323
|
+
*/
|
|
324
|
+
unload(path: string): Promise<Command | undefined>;
|
|
325
|
+
/**
|
|
326
|
+
* Add a command to the registry.
|
|
327
|
+
* @param command Command to add.
|
|
328
|
+
*/
|
|
301
329
|
add(command: Command): void;
|
|
330
|
+
/**
|
|
331
|
+
* Remove a command from the registry.
|
|
332
|
+
* @param target Command name or object to remove.
|
|
333
|
+
* @returns The command object if removed successfully.
|
|
334
|
+
*/
|
|
302
335
|
remove(target: string | Command): Command | undefined;
|
|
336
|
+
/**
|
|
337
|
+
* Get a command using its name.
|
|
338
|
+
* @param name The command to get.
|
|
339
|
+
* @returns The command object.
|
|
340
|
+
*/
|
|
303
341
|
get(name: string): Command<any[]> | undefined;
|
|
304
342
|
}
|
|
305
343
|
|
|
@@ -321,11 +359,41 @@ declare function defineListener<const K extends EventKey = EventKey>(options: K
|
|
|
321
359
|
|
|
322
360
|
declare class ListenerManager extends BaseClientManager {
|
|
323
361
|
listeners: Listener[];
|
|
362
|
+
entries: Collection<string, Listener<keyof BakitClientEvents>>;
|
|
324
363
|
private executors;
|
|
325
|
-
loadModules(): Promise<Listener[]>;
|
|
364
|
+
loadModules(entryDir: string): Promise<Listener[]>;
|
|
365
|
+
/**
|
|
366
|
+
* Load the file and add the listener to the registry.
|
|
367
|
+
* @param path The path to the listener file.
|
|
368
|
+
* @returns The listener object if added successfully.
|
|
369
|
+
*/
|
|
370
|
+
load(path: string): Promise<Listener | undefined>;
|
|
371
|
+
/**
|
|
372
|
+
* Unload the file and remove the listener from the registry.
|
|
373
|
+
* @param path The path to the listener file.
|
|
374
|
+
* @returns The listener object if unloaded successfully.
|
|
375
|
+
*/
|
|
376
|
+
unload(path: string): Promise<Listener | undefined>;
|
|
377
|
+
/**
|
|
378
|
+
* Add a listener to the registry and create a listener for client.
|
|
379
|
+
* @param listener Listener to add.
|
|
380
|
+
*/
|
|
326
381
|
add(listener: Listener): void;
|
|
382
|
+
/**
|
|
383
|
+
* Remove a listener from the registry and client.
|
|
384
|
+
* @param target Listener name or object to remove.
|
|
385
|
+
* @returns The list of listener objects if removed successfully.
|
|
386
|
+
*/
|
|
327
387
|
remove(target: string | Listener): Listener[];
|
|
388
|
+
/**
|
|
389
|
+
* Get a list of required intents for Bakit to run correctly.
|
|
390
|
+
* @returns Used intents.
|
|
391
|
+
*/
|
|
328
392
|
getBaseIntents(): IntentsBitField;
|
|
393
|
+
/**
|
|
394
|
+
* Get a list of needed intents based on registered listeners to receive needed events.
|
|
395
|
+
* @returns Used intents.
|
|
396
|
+
*/
|
|
329
397
|
getNeededIntents(): IntentsBitField;
|
|
330
398
|
}
|
|
331
399
|
|
|
@@ -345,8 +413,10 @@ declare class Instance {
|
|
|
345
413
|
cache: ProjectCacheManager;
|
|
346
414
|
constructor();
|
|
347
415
|
start(): Promise<void>;
|
|
416
|
+
private initProcess;
|
|
348
417
|
private loadModules;
|
|
349
418
|
private initIntents;
|
|
419
|
+
private onProcessMessage;
|
|
350
420
|
}
|
|
351
421
|
declare function useApp(): Instance;
|
|
352
422
|
|
|
@@ -379,11 +449,6 @@ declare class BakitClient<Ready extends boolean = boolean> extends Client<Ready>
|
|
|
379
449
|
[inspect.custom](): string;
|
|
380
450
|
}
|
|
381
451
|
|
|
382
|
-
declare class BaseClientManager {
|
|
383
|
-
client: BakitClient;
|
|
384
|
-
constructor(client: BakitClient);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
452
|
declare const Params: {
|
|
388
453
|
readonly string: <Required extends boolean = true>(options: string | {
|
|
389
454
|
name: string;
|
|
@@ -399,8 +464,31 @@ declare const Params: {
|
|
|
399
464
|
maxValue?: number | undefined;
|
|
400
465
|
minValue?: number | undefined;
|
|
401
466
|
}) => NumberParam<Required>;
|
|
467
|
+
readonly user: <Required extends boolean = true>(options: string | {
|
|
468
|
+
name: string;
|
|
469
|
+
description?: string | undefined;
|
|
470
|
+
required?: boolean | undefined;
|
|
471
|
+
}) => UserParam<Required>;
|
|
402
472
|
};
|
|
403
473
|
|
|
474
|
+
interface DevManagerOptions {
|
|
475
|
+
rootDir: string;
|
|
476
|
+
entry: string;
|
|
477
|
+
hotDirs: string[];
|
|
478
|
+
}
|
|
479
|
+
declare class DevProcessManager {
|
|
480
|
+
private options;
|
|
481
|
+
private child;
|
|
482
|
+
private restartTimer;
|
|
483
|
+
constructor(options: DevManagerOptions);
|
|
484
|
+
start(): void;
|
|
485
|
+
private startChild;
|
|
486
|
+
private restartChild;
|
|
487
|
+
private startWatcher;
|
|
488
|
+
private onFileChanged;
|
|
489
|
+
private scheduleRestart;
|
|
490
|
+
}
|
|
491
|
+
|
|
404
492
|
declare class BakitError extends Error {
|
|
405
493
|
constructor(message: string);
|
|
406
494
|
}
|
|
@@ -411,4 +499,4 @@ declare class ArgumentError extends BakitError {
|
|
|
411
499
|
constructor(target: string, reason: string);
|
|
412
500
|
}
|
|
413
501
|
|
|
414
|
-
export {
|
|
502
|
+
export { type AnyParam, ArgumentError, BakitClient, type BakitClientEvents, BakitError, BaseClientManager, BaseCommandContext, BaseParam, type BaseParamOptions, BaseParamSchema, ChatInputContext, type ChatInputContextSendOptions, Command, type CommandContext, CommandManager, type CommandOptions, type CommandOptionsInput, CommandOptionsSchema, Context, type ContextSendOptions, DevProcessManager, EVENT_INTENT_MAPPING, type ErrorHookCallback, type GetPrefixFunction, HookOrder, HookState, type InferParamTuple, type InferParamValue, Instance, LifecycleManager, Listener, ListenerManager, type ListenerOptions, ListenerOptionsSchema, type MainHookCallback, MessageContext, type MessageContextSendOptions, Module, type NumberOptions, NumberParam, NumberParamSchema, type ParamResolvedOutputType, ParamUserType, Params, ProjectCacheManager, type ProjectConfig, type ProjectConfigInput, ProjectConfigSchema, type StringOptions, StringParam, StringParamSchema, type UserOptions, UserParam, UserParamSchema, defineCommand, defineConfig, defineListener, extractSnowflakeId, getConfig, loadConfig, tokenize, useApp, validateParamsOrder };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { GatewayIntentBits, Events, Client,
|
|
1
|
+
import { GatewayIntentBits, Events, Client, Collection, IntentsBitField, SlashCommandBuilder, SlashCommandStringOption, SlashCommandNumberOption, SlashCommandUserOption, ChatInputCommandInteraction, Message } from 'discord.js';
|
|
2
2
|
import z4, { z } from 'zod';
|
|
3
3
|
import glob from 'tiny-glob';
|
|
4
4
|
import { createJiti } from 'jiti';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import path, { relative, sep, posix, join, dirname } from 'path';
|
|
5
7
|
import { inspect } from 'util';
|
|
6
|
-
import {
|
|
8
|
+
import { fork } from 'child_process';
|
|
9
|
+
import chokidar from 'chokidar';
|
|
7
10
|
import { existsSync, mkdirSync, rmSync } from 'fs';
|
|
8
11
|
import { mkdir, writeFile, readFile, rm } from 'fs/promises';
|
|
9
12
|
import { createHash } from 'crypto';
|
|
@@ -132,9 +135,38 @@ function extractSnowflakeId(input) {
|
|
|
132
135
|
let idMatch = /^(\d{17,20})$/.exec(input);
|
|
133
136
|
return idMatch?.[1] ? idMatch[1] : null;
|
|
134
137
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
var Module = class {
|
|
139
|
+
static jiti = createJiti(process.cwd());
|
|
140
|
+
static async import(module, defaultImport = false) {
|
|
141
|
+
let path2 = this.resolve(module);
|
|
142
|
+
if (!path2)
|
|
143
|
+
return null;
|
|
144
|
+
try {
|
|
145
|
+
return await this.jiti.import(path2, { default: defaultImport });
|
|
146
|
+
} catch (error) {
|
|
147
|
+
return console.error(`[Module] Import failed for ${path2}:`, error), null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
static isLoaded(module) {
|
|
151
|
+
let path2 = this.resolve(module);
|
|
152
|
+
return !!path2 && !!this.jiti.cache[path2];
|
|
153
|
+
}
|
|
154
|
+
static unload(module) {
|
|
155
|
+
let path2 = this.resolve(module);
|
|
156
|
+
return !path2 || !this.jiti.cache[path2] ? false : (delete this.jiti.cache[path2], true);
|
|
157
|
+
}
|
|
158
|
+
static resolve(module) {
|
|
159
|
+
try {
|
|
160
|
+
let url = this.jiti.esmResolve(module);
|
|
161
|
+
return fileURLToPath(url);
|
|
162
|
+
} catch {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
static getTopLevel(path2, entryDir) {
|
|
167
|
+
return relative(entryDir, path2).split(sep)[0] ?? null;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
138
170
|
|
|
139
171
|
// src/config.ts
|
|
140
172
|
var ProjectConfigSchema = z.object({
|
|
@@ -156,22 +188,13 @@ var ProjectConfigSchema = z.object({
|
|
|
156
188
|
* @see {@link https://discord.js.org/docs/packages/discord.js/main/ClientOptions:Interface}
|
|
157
189
|
*/
|
|
158
190
|
clientOptions: z.custom().optional(),
|
|
159
|
-
/**
|
|
160
|
-
* The path to the main project source directory.
|
|
161
|
-
*
|
|
162
|
-
* @defaultvalue `src`
|
|
163
|
-
*/
|
|
164
|
-
entryDir: z.string().default("src"),
|
|
165
191
|
prefixes: z.array(z.string()).default([]),
|
|
166
192
|
token: z.string()
|
|
167
193
|
});
|
|
168
194
|
function defineConfig(config) {
|
|
169
195
|
return config;
|
|
170
196
|
}
|
|
171
|
-
var _config;
|
|
172
197
|
async function loadConfig(cwd = process.cwd()) {
|
|
173
|
-
if (_config)
|
|
174
|
-
return console.warn("loadConfig() was called more than once. This shouldn't happen."), _config;
|
|
175
198
|
let globPattern = `bakit.config.{${["ts", "js"].join(",")}}`, [configPath, other] = await glob(globPattern, {
|
|
176
199
|
cwd: cwd.replace(/\\/g, "/"),
|
|
177
200
|
// ensure the path uses `/` instead of `\` on Windows
|
|
@@ -180,22 +203,13 @@ async function loadConfig(cwd = process.cwd()) {
|
|
|
180
203
|
if (!configPath)
|
|
181
204
|
throw new Error("Missing config file");
|
|
182
205
|
other && console.warn(`Multiple config files found in ${cwd}. Using ${configPath}.`);
|
|
183
|
-
let config = await
|
|
184
|
-
return
|
|
206
|
+
let config = await Module.import(configPath, true);
|
|
207
|
+
return Object.freeze(await ProjectConfigSchema.parseAsync(config));
|
|
185
208
|
}
|
|
186
209
|
function getConfig() {
|
|
187
|
-
|
|
188
|
-
throw new Error("Project config is not loaded.");
|
|
189
|
-
return _config;
|
|
210
|
+
throw new Error("Project config is not loaded.");
|
|
190
211
|
}
|
|
191
212
|
|
|
192
|
-
// src/base/BaseClientManager.ts
|
|
193
|
-
var BaseClientManager = class {
|
|
194
|
-
constructor(client) {
|
|
195
|
-
this.client = client;
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
|
|
199
213
|
// src/base/lifecycle/Context.ts
|
|
200
214
|
var Context = class {
|
|
201
215
|
canceled = false;
|
|
@@ -397,16 +411,17 @@ var BaseParam = class {
|
|
|
397
411
|
return this.setOption("required", value);
|
|
398
412
|
}
|
|
399
413
|
async resolve(context, value) {
|
|
400
|
-
let { required, name } = this.options;
|
|
401
|
-
if (value === void 0) {
|
|
402
|
-
if (required)
|
|
403
|
-
throw new ArgumentError(name, "is required");
|
|
404
|
-
return null;
|
|
405
|
-
}
|
|
406
414
|
if (context.isChatInput())
|
|
407
415
|
return await this.resolveChatInput(context);
|
|
408
|
-
if (context.isMessage())
|
|
416
|
+
if (context.isMessage()) {
|
|
417
|
+
let { required, name } = this.options;
|
|
418
|
+
if (value === void 0) {
|
|
419
|
+
if (required)
|
|
420
|
+
throw new ArgumentError(name, "is required");
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
409
423
|
return await this.resolveMessage(context, value);
|
|
424
|
+
}
|
|
410
425
|
throw new Error("Invalid context type provided");
|
|
411
426
|
}
|
|
412
427
|
/**
|
|
@@ -568,31 +583,55 @@ function defineCommand(options) {
|
|
|
568
583
|
return new Command(options);
|
|
569
584
|
}
|
|
570
585
|
|
|
586
|
+
// src/base/client/BaseClientManager.ts
|
|
587
|
+
var BaseClientManager = class {
|
|
588
|
+
constructor(client) {
|
|
589
|
+
this.client = client;
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
|
|
571
593
|
// src/base/command/CommandManager.ts
|
|
572
594
|
var CommandManager = class extends BaseClientManager {
|
|
573
595
|
commands = new Collection();
|
|
574
|
-
|
|
575
|
-
|
|
596
|
+
entries = new Collection();
|
|
597
|
+
async loadModules(entryDir) {
|
|
598
|
+
let pattern = posix.join(posix.resolve(entryDir), "commands", "**/*.{ts,js}"), files = await glob(pattern, {
|
|
576
599
|
cwd: process.cwd(),
|
|
577
600
|
absolute: true
|
|
578
|
-
})
|
|
579
|
-
|
|
580
|
-
let command = await $jiti.import(file, { default: !0 });
|
|
581
|
-
if (!command) {
|
|
582
|
-
console.warn(`[Loader] File has no default export: ${file}`);
|
|
583
|
-
return;
|
|
584
|
-
}
|
|
585
|
-
if (!(command instanceof Command)) {
|
|
586
|
-
console.warn(`[Loader] Default export is not a Command: ${file}`);
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
589
|
-
return this.add(command), command;
|
|
590
|
-
} catch (error) {
|
|
591
|
-
console.error(`An error occurred while trying to add command for '${file}':`, error);
|
|
592
|
-
}
|
|
593
|
-
}), loaded = (await Promise.all(loads)).filter((x) => x !== void 0);
|
|
594
|
-
return console.log(`Loaded ${loaded.length} command(s).`), loaded;
|
|
601
|
+
}), filtered = (await Promise.all(files.map((file) => this.load(file)))).filter((c) => !!c);
|
|
602
|
+
return console.log(`[Loader] Loaded ${filtered.length}/${files.length}`), filtered;
|
|
595
603
|
}
|
|
604
|
+
/**
|
|
605
|
+
* Load the file and add the command to the registry.
|
|
606
|
+
* @param path The path to the command file.
|
|
607
|
+
* @returns The command object if added successfully.
|
|
608
|
+
*/
|
|
609
|
+
async load(path2) {
|
|
610
|
+
let command = await Module.import(path2, true);
|
|
611
|
+
if (!command) {
|
|
612
|
+
console.warn(`[Loader] File has no default export: ${path2}`);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
if (!(command instanceof Command)) {
|
|
616
|
+
console.warn(`[Loader] Default export is not a Command: ${path2}`);
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
return this.add(command), this.entries.set(path2, command), command;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Unload the file and remove the command from the registry.
|
|
623
|
+
* @param path The path to the command file.
|
|
624
|
+
* @returns The command object if unloaded successfully.
|
|
625
|
+
*/
|
|
626
|
+
async unload(path2) {
|
|
627
|
+
let command = this.entries.get(path2);
|
|
628
|
+
if (Module.isLoaded(path2) && (command ??= await Module.import(path2, true), Module.unload(path2)), this.entries.delete(path2), !!command)
|
|
629
|
+
return this.remove(command);
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Add a command to the registry.
|
|
633
|
+
* @param command Command to add.
|
|
634
|
+
*/
|
|
596
635
|
add(command) {
|
|
597
636
|
if (!(command instanceof Command))
|
|
598
637
|
throw new Error("Invalid command provided");
|
|
@@ -603,11 +642,23 @@ var CommandManager = class extends BaseClientManager {
|
|
|
603
642
|
}
|
|
604
643
|
this.commands.set(name, command);
|
|
605
644
|
}
|
|
645
|
+
/**
|
|
646
|
+
* Remove a command from the registry.
|
|
647
|
+
* @param target Command name or object to remove.
|
|
648
|
+
* @returns The command object if removed successfully.
|
|
649
|
+
*/
|
|
606
650
|
remove(target) {
|
|
651
|
+
if (typeof target != "string" && !(target instanceof Command))
|
|
652
|
+
return;
|
|
607
653
|
let name = typeof target == "string" ? target : target.options.name, existing = this.commands.get(name);
|
|
608
654
|
if (existing)
|
|
609
655
|
return this.commands.delete(name), existing;
|
|
610
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* Get a command using its name.
|
|
659
|
+
* @param name The command to get.
|
|
660
|
+
* @returns The command object.
|
|
661
|
+
*/
|
|
611
662
|
get(name) {
|
|
612
663
|
return this.commands.get(name);
|
|
613
664
|
}
|
|
@@ -627,40 +678,59 @@ function defineListener(options) {
|
|
|
627
678
|
}
|
|
628
679
|
var ListenerManager = class extends BaseClientManager {
|
|
629
680
|
listeners = [];
|
|
630
|
-
|
|
681
|
+
entries = new Collection();
|
|
631
682
|
executors = /* @__PURE__ */ new WeakMap();
|
|
632
|
-
async loadModules() {
|
|
633
|
-
let
|
|
683
|
+
async loadModules(entryDir) {
|
|
684
|
+
let pattern = posix.join(posix.resolve(entryDir), "listeners", "**/*.{ts,js}"), files = await glob(pattern, {
|
|
634
685
|
cwd: process.cwd(),
|
|
635
686
|
absolute: true
|
|
636
|
-
})
|
|
637
|
-
|
|
638
|
-
let listener = await $jiti.import(file, { default: !0 });
|
|
639
|
-
if (!listener) {
|
|
640
|
-
console.warn(`[Loader] File has no default export: ${file}`);
|
|
641
|
-
return;
|
|
642
|
-
}
|
|
643
|
-
if (!(listener instanceof Listener)) {
|
|
644
|
-
console.warn(`[Loader] Default export is not a Listener: ${file}`);
|
|
645
|
-
return;
|
|
646
|
-
}
|
|
647
|
-
return this.add(listener), listener;
|
|
648
|
-
} catch (error) {
|
|
649
|
-
console.error(`An error occurred while trying to add listener for '${file}':`, error);
|
|
650
|
-
}
|
|
651
|
-
}), loaded = (await Promise.all(loads)).filter((x) => x !== void 0);
|
|
652
|
-
return console.log(`Loaded ${loaded.length} listener(s).`), loaded;
|
|
687
|
+
}), filtered = (await Promise.all(files.map((file) => this.load(file)))).filter((l) => !!l);
|
|
688
|
+
return console.log(`[Loader] Loaded ${filtered.length}/${files.length}`), filtered;
|
|
653
689
|
}
|
|
690
|
+
/**
|
|
691
|
+
* Load the file and add the listener to the registry.
|
|
692
|
+
* @param path The path to the listener file.
|
|
693
|
+
* @returns The listener object if added successfully.
|
|
694
|
+
*/
|
|
695
|
+
async load(path2) {
|
|
696
|
+
let listener = await Module.import(path2, true);
|
|
697
|
+
if (!listener) {
|
|
698
|
+
console.warn(`[Loader] File has no default export: ${path2}`);
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
if (!(listener instanceof Listener)) {
|
|
702
|
+
console.warn(`[Loader] Default export is not a Listener: ${path2}`);
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
return this.add(listener), this.entries.set(path2, listener), listener;
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Unload the file and remove the listener from the registry.
|
|
709
|
+
* @param path The path to the listener file.
|
|
710
|
+
* @returns The listener object if unloaded successfully.
|
|
711
|
+
*/
|
|
712
|
+
async unload(path2) {
|
|
713
|
+
let listener = this.entries.get(path2);
|
|
714
|
+
if (Module.isLoaded(path2) && (listener ??= await Module.import(path2, true), Module.unload(path2)), this.entries.delete(path2), !!listener)
|
|
715
|
+
return this.remove(listener)?.[0];
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Add a listener to the registry and create a listener for client.
|
|
719
|
+
* @param listener Listener to add.
|
|
720
|
+
*/
|
|
654
721
|
add(listener) {
|
|
655
722
|
if (!(listener instanceof Listener))
|
|
656
723
|
throw new Error("Invalid listener provided");
|
|
657
|
-
let execute = (...args) => {
|
|
724
|
+
let { once, name } = listener.options, execute = (...args) => {
|
|
658
725
|
listener.execute(new Context(), ...args);
|
|
659
726
|
};
|
|
660
|
-
this.listeners.push(listener), this.executors.set(listener, execute);
|
|
661
|
-
let { once, name } = listener.options;
|
|
662
|
-
this.client[once ? "once" : "on"](name, execute);
|
|
727
|
+
this.listeners.push(listener), this.executors.set(listener, execute), this.client[once ? "once" : "on"](name, execute);
|
|
663
728
|
}
|
|
729
|
+
/**
|
|
730
|
+
* Remove a listener from the registry and client.
|
|
731
|
+
* @param target Listener name or object to remove.
|
|
732
|
+
* @returns The list of listener objects if removed successfully.
|
|
733
|
+
*/
|
|
664
734
|
remove(target) {
|
|
665
735
|
let isMatched = (listener) => typeof target == "string" ? listener.options.name === target : listener === target, removed = [];
|
|
666
736
|
return this.listeners = this.listeners.filter((listener) => {
|
|
@@ -671,9 +741,17 @@ var ListenerManager = class extends BaseClientManager {
|
|
|
671
741
|
return execute && (this.client.removeListener(listener.options.name, execute), this.executors.delete(listener)), false;
|
|
672
742
|
}), removed;
|
|
673
743
|
}
|
|
744
|
+
/**
|
|
745
|
+
* Get a list of required intents for Bakit to run correctly.
|
|
746
|
+
* @returns Used intents.
|
|
747
|
+
*/
|
|
674
748
|
getBaseIntents() {
|
|
675
749
|
return new IntentsBitField([GatewayIntentBits.Guilds]);
|
|
676
750
|
}
|
|
751
|
+
/**
|
|
752
|
+
* Get a list of needed intents based on registered listeners to receive needed events.
|
|
753
|
+
* @returns Used intents.
|
|
754
|
+
*/
|
|
677
755
|
getNeededIntents() {
|
|
678
756
|
let result = this.getBaseIntents();
|
|
679
757
|
for (let listener of this.listeners) {
|
|
@@ -684,7 +762,7 @@ var ListenerManager = class extends BaseClientManager {
|
|
|
684
762
|
}
|
|
685
763
|
};
|
|
686
764
|
|
|
687
|
-
// src/base/BakitClient.ts
|
|
765
|
+
// src/base/client/BakitClient.ts
|
|
688
766
|
var BakitClient2 = class extends Client {
|
|
689
767
|
constructor(options, instance) {
|
|
690
768
|
super(options);
|
|
@@ -734,10 +812,66 @@ function createFactory(ctor) {
|
|
|
734
812
|
}
|
|
735
813
|
var Params = {
|
|
736
814
|
string: createFactory(StringParam),
|
|
737
|
-
number: createFactory(NumberParam)
|
|
815
|
+
number: createFactory(NumberParam),
|
|
816
|
+
user: createFactory(UserParam)
|
|
817
|
+
};
|
|
818
|
+
var DevProcessManager = class {
|
|
819
|
+
constructor(options) {
|
|
820
|
+
this.options = options;
|
|
821
|
+
}
|
|
822
|
+
child = null;
|
|
823
|
+
restartTimer = null;
|
|
824
|
+
start() {
|
|
825
|
+
console.log("Starting bakit in dev mode..."), this.startChild(), this.startWatcher();
|
|
826
|
+
}
|
|
827
|
+
startChild() {
|
|
828
|
+
if (this.child) return;
|
|
829
|
+
let entry = path.resolve(this.options.entry);
|
|
830
|
+
this.child = fork(entry, {
|
|
831
|
+
execArgv: ["--import", "tsx"],
|
|
832
|
+
stdio: "inherit",
|
|
833
|
+
env: {
|
|
834
|
+
...process.env,
|
|
835
|
+
NODE_ENV: "development"
|
|
836
|
+
}
|
|
837
|
+
}), this.child.on("exit", () => {
|
|
838
|
+
this.child = null;
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
restartChild() {
|
|
842
|
+
if (!this.child)
|
|
843
|
+
return this.startChild();
|
|
844
|
+
let old = this.child;
|
|
845
|
+
old.once("exit", () => {
|
|
846
|
+
this.child = null, this.startChild();
|
|
847
|
+
}), old.kill("SIGTERM");
|
|
848
|
+
}
|
|
849
|
+
startWatcher() {
|
|
850
|
+
let { rootDir } = this.options;
|
|
851
|
+
chokidar.watch(rootDir, {
|
|
852
|
+
ignoreInitial: true,
|
|
853
|
+
awaitWriteFinish: {
|
|
854
|
+
stabilityThreshold: 200,
|
|
855
|
+
pollInterval: 50
|
|
856
|
+
}
|
|
857
|
+
}).on("change", (file) => this.onFileChanged(file));
|
|
858
|
+
}
|
|
859
|
+
onFileChanged(file) {
|
|
860
|
+
if (!this.child)
|
|
861
|
+
return;
|
|
862
|
+
let top = Module.getTopLevel(file, this.options.rootDir);
|
|
863
|
+
if (top && this.options.hotDirs.includes(top)) {
|
|
864
|
+
this.child.connected && this.child.send({ type: `hmr:${top}`, file });
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
this.scheduleRestart();
|
|
868
|
+
}
|
|
869
|
+
scheduleRestart() {
|
|
870
|
+
this.restartTimer && clearTimeout(this.restartTimer), this.restartTimer = setTimeout(() => {
|
|
871
|
+
console.log("Detected changes, restarting..."), this.restartChild(), this.restartTimer = null;
|
|
872
|
+
}, 150);
|
|
873
|
+
}
|
|
738
874
|
};
|
|
739
|
-
|
|
740
|
-
// src/defaults/command.ts
|
|
741
875
|
var messageCommandHandler = defineListener(Events.MessageCreate), chatInputCommandHandler = defineListener(Events.InteractionCreate), registerCommandsHandler = defineListener({
|
|
742
876
|
name: Events.ClientReady,
|
|
743
877
|
once: true
|
|
@@ -807,14 +941,14 @@ var ProjectCacheManager = class {
|
|
|
807
941
|
getHash(data) {
|
|
808
942
|
return createHash("sha256").update(JSON.stringify(data)).digest("hex");
|
|
809
943
|
}
|
|
810
|
-
async write(
|
|
811
|
-
let fullPath = join(this.rootDir,
|
|
944
|
+
async write(path2, data) {
|
|
945
|
+
let fullPath = join(this.rootDir, path2), dir = dirname(fullPath);
|
|
812
946
|
await mkdir(dir, { recursive: true });
|
|
813
947
|
let content = typeof data == "string" ? data : JSON.stringify(data);
|
|
814
948
|
await writeFile(fullPath, content, "utf-8");
|
|
815
949
|
}
|
|
816
|
-
async read(
|
|
817
|
-
let fullPath = join(this.rootDir,
|
|
950
|
+
async read(path2) {
|
|
951
|
+
let fullPath = join(this.rootDir, path2);
|
|
818
952
|
try {
|
|
819
953
|
let content = await readFile(fullPath, "utf-8");
|
|
820
954
|
return JSON.parse(content);
|
|
@@ -830,7 +964,7 @@ var ProjectCacheManager = class {
|
|
|
830
964
|
}
|
|
831
965
|
};
|
|
832
966
|
|
|
833
|
-
// src/base/Instance.ts
|
|
967
|
+
// src/base/process/Instance.ts
|
|
834
968
|
var Instance = class {
|
|
835
969
|
client;
|
|
836
970
|
cache;
|
|
@@ -846,19 +980,37 @@ var Instance = class {
|
|
|
846
980
|
...config.clientOptions
|
|
847
981
|
},
|
|
848
982
|
this
|
|
849
|
-
), await this.loadModules(), this.initIntents(), await this.client.login(config.token);
|
|
983
|
+
), await this.loadModules(), this.initIntents(), await this.client.login(config.token), this.initProcess();
|
|
984
|
+
}
|
|
985
|
+
initProcess() {
|
|
986
|
+
process.on("message", (msg) => this.onProcessMessage(msg));
|
|
850
987
|
}
|
|
851
988
|
loadModules() {
|
|
852
989
|
let { managers } = this.client, { commands, listeners } = managers;
|
|
853
|
-
return listeners.add(chatInputCommandHandler), listeners.add(messageCommandHandler), listeners.add(registerCommandsHandler), Promise.all([commands.loadModules(), listeners.loadModules()]);
|
|
990
|
+
return listeners.add(chatInputCommandHandler), listeners.add(messageCommandHandler), listeners.add(registerCommandsHandler), Promise.all([commands.loadModules("src"), listeners.loadModules("src")]);
|
|
854
991
|
}
|
|
855
992
|
initIntents() {
|
|
856
993
|
let config = getConfig(), { options, managers } = this.client, { listeners } = managers, intents;
|
|
857
994
|
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;
|
|
858
995
|
}
|
|
996
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
997
|
+
async onProcessMessage(message) {
|
|
998
|
+
let { type, file } = message;
|
|
999
|
+
if (!type.startsWith("hmr:"))
|
|
1000
|
+
return;
|
|
1001
|
+
let target = type.split(":")[1], { listeners, commands } = this.client.managers;
|
|
1002
|
+
switch (target) {
|
|
1003
|
+
case "listeners":
|
|
1004
|
+
listeners.unload(file), await listeners.load(file);
|
|
1005
|
+
break;
|
|
1006
|
+
case "commands":
|
|
1007
|
+
commands.unload(file), await listeners.load(file);
|
|
1008
|
+
break;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
859
1011
|
};
|
|
860
1012
|
function useApp() {
|
|
861
1013
|
return new Instance();
|
|
862
1014
|
}
|
|
863
1015
|
|
|
864
|
-
export {
|
|
1016
|
+
export { ArgumentError, BakitClient2 as BakitClient, BakitError, BaseClientManager, BaseCommandContext, BaseParam, BaseParamSchema, ChatInputContext, Command, CommandManager, CommandOptionsSchema, Context, DevProcessManager, EVENT_INTENT_MAPPING, HookOrder, HookState, Instance, LifecycleManager, Listener, ListenerManager, ListenerOptionsSchema, MessageContext, Module, NumberParam, NumberParamSchema, ParamUserType, Params, ProjectCacheManager, ProjectConfigSchema, StringParam, StringParamSchema, UserParam, UserParamSchema, defineCommand, defineConfig, defineListener, extractSnowflakeId, getConfig, loadConfig, tokenize, useApp, validateParamsOrder };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bakit",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.12",
|
|
4
4
|
"description": "A framework for discord.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"test": "vitest run --pass-with-no-tests"
|
|
12
12
|
},
|
|
13
13
|
"bin": {
|
|
14
|
-
"bakit": "./bin/bakit.js"
|
|
14
|
+
"bakit": "./dist/bin/bakit.js"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"dist"
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"discord.js": "^14.0.0"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
+
"chokidar": "^5.0.0",
|
|
40
41
|
"commander": "^14.0.2",
|
|
41
42
|
"dotenv": "^17.2.1",
|
|
42
43
|
"jiti": "^2.6.1",
|
package/bin/bakit.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
import { config as useEnv } from "dotenv";
|
|
3
|
-
import { program } from "commander";
|
|
4
|
-
|
|
5
|
-
program.name("bakit");
|
|
6
|
-
|
|
7
|
-
program.command("dev").action(async () => {
|
|
8
|
-
useEnv({
|
|
9
|
-
path: [".env.local", ".env"],
|
|
10
|
-
quiet: true,
|
|
11
|
-
});
|
|
12
|
-
const { default: nodemon } = await import("nodemon");
|
|
13
|
-
|
|
14
|
-
nodemon({
|
|
15
|
-
script: "src/index.ts",
|
|
16
|
-
exec: `${process.execPath} --import tsx`,
|
|
17
|
-
ext: "ts,js",
|
|
18
|
-
watch: ["src"],
|
|
19
|
-
env: {
|
|
20
|
-
...process.env,
|
|
21
|
-
FORCE_COLOR: "1",
|
|
22
|
-
NODE_ENV: "development",
|
|
23
|
-
},
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
nodemon.on("start", () => {
|
|
27
|
-
console.log("Starting bakit app...");
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
nodemon.on("restart", () => {
|
|
31
|
-
console.log("Bakit detected changes! Restarting...");
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
nodemon.on("quit", () => {
|
|
35
|
-
process.exit();
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
program.parse();
|