bakit 2.0.0-alpha.24 → 2.0.0-alpha.26
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/cli.js +21 -31
- package/dist/hooks.js +11 -21
- package/dist/index.d.ts +87 -12
- package/dist/index.js +206 -69
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,71 +1,61 @@
|
|
|
1
1
|
import { config } from 'dotenv';
|
|
2
2
|
import { program } from 'commander';
|
|
3
3
|
import { fork } from 'child_process';
|
|
4
|
-
import path, { resolve
|
|
4
|
+
import path, { resolve } from 'path';
|
|
5
5
|
import chokidar from 'chokidar';
|
|
6
|
+
import { RPC } from 'bakit';
|
|
6
7
|
|
|
7
8
|
// src/cli/bin.ts
|
|
8
|
-
function getTopLevelDirectory(path2, entryDir) {
|
|
9
|
-
return relative(entryDir, path2).split(sep)[0] ?? null;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// src/cli/process/DevProcessManager.ts
|
|
13
9
|
var DevProcessManager = class {
|
|
14
10
|
constructor(options) {
|
|
15
11
|
this.options = options;
|
|
16
12
|
}
|
|
17
|
-
|
|
13
|
+
rpc = null;
|
|
18
14
|
restartTimer = null;
|
|
19
15
|
start() {
|
|
20
16
|
console.log("Starting bakit in dev mode..."), this.startChild(), this.startWatcher();
|
|
21
17
|
}
|
|
22
18
|
startChild() {
|
|
23
|
-
if (this.
|
|
24
|
-
|
|
25
|
-
this.child = fork(entry, {
|
|
19
|
+
if (this.rpc)
|
|
20
|
+
return;
|
|
21
|
+
let entry = path.resolve(this.options.entry), child = fork(entry, {
|
|
26
22
|
execArgv: ["--import", "bakit/register"],
|
|
27
23
|
stdio: "inherit",
|
|
28
24
|
env: {
|
|
29
25
|
...process.env,
|
|
30
26
|
NODE_ENV: "development"
|
|
31
27
|
}
|
|
32
|
-
}), this.child.on("exit", () => {
|
|
33
|
-
this.child = null;
|
|
34
28
|
});
|
|
29
|
+
this.rpc = new RPC(child), this.rpc.on("restart", (fileUpdated) => this.scheduleRestart(fileUpdated));
|
|
35
30
|
}
|
|
36
31
|
restartChild() {
|
|
37
|
-
if (!this.
|
|
32
|
+
if (!this.rpc)
|
|
38
33
|
return this.startChild();
|
|
39
|
-
let
|
|
40
|
-
|
|
41
|
-
this.
|
|
42
|
-
}),
|
|
34
|
+
let child = this.rpc.transport;
|
|
35
|
+
child.once("exit", () => {
|
|
36
|
+
this.rpc = null, this.startChild();
|
|
37
|
+
}), child.kill("SIGTERM");
|
|
43
38
|
}
|
|
44
39
|
startWatcher() {
|
|
45
|
-
let { rootDir } = this.options
|
|
46
|
-
chokidar.watch(rootDir, {
|
|
40
|
+
let { rootDir } = this.options, watcher = chokidar.watch(rootDir, {
|
|
47
41
|
ignoreInitial: true,
|
|
48
42
|
awaitWriteFinish: {
|
|
49
43
|
stabilityThreshold: 200,
|
|
50
44
|
pollInterval: 50
|
|
51
45
|
}
|
|
52
|
-
}).on("change", (path2) => {
|
|
53
|
-
this.onFileChanged(path2);
|
|
54
46
|
});
|
|
47
|
+
watcher.on("change", (path2) => this.onFileUpdate("fileChange", path2)), watcher.on("unlink", (path2) => this.onFileUpdate("fileRemove", path2));
|
|
55
48
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
this.child.connected && this.child.send({ type: `hmr:${top}`, path: resolve(path2) });
|
|
62
|
-
return;
|
|
49
|
+
onFileUpdate(type, path2) {
|
|
50
|
+
try {
|
|
51
|
+
this.rpc?.send(type, resolve(path2));
|
|
52
|
+
} catch {
|
|
53
|
+
this.scheduleRestart(true);
|
|
63
54
|
}
|
|
64
|
-
this.scheduleRestart();
|
|
65
55
|
}
|
|
66
|
-
scheduleRestart() {
|
|
56
|
+
scheduleRestart(fileUpdated = false) {
|
|
67
57
|
this.restartTimer && clearTimeout(this.restartTimer), this.restartTimer = setTimeout(() => {
|
|
68
|
-
console.log("
|
|
58
|
+
fileUpdated && console.log("File changes detected, restarting..."), this.restartChild(), this.restartTimer = null;
|
|
69
59
|
}, 150);
|
|
70
60
|
}
|
|
71
61
|
};
|
package/dist/hooks.js
CHANGED
|
@@ -3,14 +3,15 @@ import { readFile } from 'fs/promises';
|
|
|
3
3
|
import { Module } from 'module';
|
|
4
4
|
import { dirname, resolve as resolve$1, basename } from 'path';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
6
|
+
import { RPC } from 'bakit';
|
|
6
7
|
|
|
7
8
|
// src/lib/loader/hooks.ts
|
|
8
|
-
var EXTENSIONS = [".js", ".ts"],
|
|
9
|
+
var EXTENSIONS = [".js", ".ts"], rpc, versions, esbuild;
|
|
9
10
|
function isDevelopment() {
|
|
10
11
|
return process.env.NODE_ENV === "development";
|
|
11
12
|
}
|
|
12
13
|
async function initialize({ port }) {
|
|
13
|
-
|
|
14
|
+
rpc = new RPC(port), versions = /* @__PURE__ */ new Map(), rpc.on("message", onUnload), isDevelopment() && (esbuild = await import('esbuild'));
|
|
14
15
|
}
|
|
15
16
|
async function resolve(specifier, context, nextResolve) {
|
|
16
17
|
if (shouldSkip(specifier))
|
|
@@ -27,10 +28,9 @@ async function resolve(specifier, context, nextResolve) {
|
|
|
27
28
|
let urlObj = new URL(url);
|
|
28
29
|
if (isDevelopment()) {
|
|
29
30
|
let filePath = fileURLToPath(urlObj), version = createVersion(filePath);
|
|
30
|
-
urlObj.searchParams.set("hmr", version), parentURL &&
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
child: url
|
|
31
|
+
urlObj.searchParams.set("hmr", version), parentURL && rpc.send("dependencyAdd", {
|
|
32
|
+
parentURL,
|
|
33
|
+
url
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
return {
|
|
@@ -62,8 +62,8 @@ async function load(url, context, nextLoad) {
|
|
|
62
62
|
return nextLoad(url, context);
|
|
63
63
|
}
|
|
64
64
|
function createVersion(filename) {
|
|
65
|
-
let version = versions
|
|
66
|
-
return version || (version = Date.now().toString(), versions
|
|
65
|
+
let version = versions.get(filename);
|
|
66
|
+
return version || (version = Date.now().toString(), versions.set(filename, version)), version;
|
|
67
67
|
}
|
|
68
68
|
function shouldSkip(specifier) {
|
|
69
69
|
if (Module.isBuiltin(specifier) || specifier.includes("/node_modules/"))
|
|
@@ -74,19 +74,9 @@ function shouldSkip(specifier) {
|
|
|
74
74
|
}
|
|
75
75
|
return true;
|
|
76
76
|
}
|
|
77
|
-
function
|
|
78
|
-
let
|
|
79
|
-
|
|
80
|
-
parentPort?.postMessage({
|
|
81
|
-
id,
|
|
82
|
-
data: false
|
|
83
|
-
});
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
versions?.delete(data), parentPort?.postMessage({
|
|
87
|
-
id,
|
|
88
|
-
data: true
|
|
89
|
-
});
|
|
77
|
+
function onUnload(id, path) {
|
|
78
|
+
let deleted = versions.delete(resolve$1(path));
|
|
79
|
+
rpc.success(id, deleted);
|
|
90
80
|
}
|
|
91
81
|
|
|
92
82
|
export { initialize, load, resolve };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ import * as discord_js from 'discord.js';
|
|
|
2
2
|
import { ChatInputCommandInteraction, CacheType, Message, User, MessageCreateOptions, InteractionReplyOptions, Awaitable, Collection, Events, IntentsBitField, ClientEvents, Client, ClientOptions, GatewayIntentBits } from 'discord.js';
|
|
3
3
|
import { inspect } from 'node:util';
|
|
4
4
|
import z from 'zod';
|
|
5
|
+
import EventEmitter from 'node:events';
|
|
6
|
+
import { Serializable, ChildProcess } from 'node:child_process';
|
|
7
|
+
import { MessagePort as MessagePort$1 } from 'node:worker_threads';
|
|
5
8
|
|
|
6
9
|
declare enum ParamUserType {
|
|
7
10
|
Bot = "bot",
|
|
@@ -367,12 +370,20 @@ declare class ProjectCacheManager {
|
|
|
367
370
|
declare class Instance {
|
|
368
371
|
client: BakitClient;
|
|
369
372
|
cache: ProjectCacheManager;
|
|
373
|
+
private rpc;
|
|
370
374
|
constructor();
|
|
371
375
|
start(): Promise<void>;
|
|
372
376
|
private initProcess;
|
|
373
377
|
private loadModules;
|
|
374
378
|
private initIntents;
|
|
375
|
-
private
|
|
379
|
+
private isInHotDirectory;
|
|
380
|
+
private restart;
|
|
381
|
+
shutdown(): Promise<void>;
|
|
382
|
+
private containsEntryPoint;
|
|
383
|
+
private containsHotModule;
|
|
384
|
+
private onFileRemove;
|
|
385
|
+
private onFileChange;
|
|
386
|
+
private unloadModule;
|
|
376
387
|
}
|
|
377
388
|
declare function useApp(): Instance;
|
|
378
389
|
|
|
@@ -449,20 +460,52 @@ declare function extractSnowflakeId(input: string): string | null;
|
|
|
449
460
|
|
|
450
461
|
declare function getTopLevelDirectory(path: string, entryDir: string): string | null;
|
|
451
462
|
|
|
452
|
-
|
|
453
|
-
|
|
463
|
+
declare function $initLoader(): void;
|
|
464
|
+
declare function $unloadFile(path: string): Promise<boolean>;
|
|
465
|
+
declare function getImporters(path: string, createNew: true): Set<string>;
|
|
466
|
+
declare function getImporters(path: string, createNew?: false): Set<string> | undefined;
|
|
467
|
+
declare function getDependencyChain(path: string): string[];
|
|
468
|
+
declare function isImported(path: string): boolean;
|
|
469
|
+
declare function isImportedBy(path: string, matcher: string | RegExp | ((path: string) => boolean)): boolean;
|
|
470
|
+
|
|
471
|
+
declare const RPC_RESPONSE_MARK = "$DONE:";
|
|
472
|
+
declare const RPC_RESPONSE_TIMEOUT = 5000;
|
|
473
|
+
interface BaseRPCMessage {
|
|
474
|
+
id: string;
|
|
475
|
+
}
|
|
476
|
+
interface BaseRPCResponse {
|
|
477
|
+
id: `${typeof RPC_RESPONSE_MARK}${string}`;
|
|
478
|
+
}
|
|
479
|
+
interface RPCRequest<Data extends Serializable = Serializable> extends BaseRPCMessage {
|
|
454
480
|
type: string;
|
|
455
481
|
data: Data;
|
|
456
482
|
}
|
|
457
|
-
interface
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
483
|
+
interface RPCSuccessResponse<Data extends Serializable = Serializable> extends BaseRPCResponse {
|
|
484
|
+
data: Data;
|
|
485
|
+
}
|
|
486
|
+
interface RPCErrorResponse extends BaseRPCResponse {
|
|
487
|
+
error: string;
|
|
488
|
+
}
|
|
489
|
+
type RPCResponse<Data extends Serializable = Serializable> = RPCSuccessResponse<Data> | RPCErrorResponse;
|
|
490
|
+
type RPCMessage<Data extends Serializable = Serializable> = RPCRequest<Data> | RPCResponse<Data>;
|
|
491
|
+
interface RPCPendingPromise {
|
|
492
|
+
resolve: (data: any) => void;
|
|
493
|
+
reject: (error: unknown) => void;
|
|
494
|
+
timeout: NodeJS.Timeout;
|
|
495
|
+
}
|
|
496
|
+
declare class RPC extends EventEmitter {
|
|
497
|
+
transport: MessagePort$1 | NodeJS.Process | ChildProcess;
|
|
498
|
+
requests: Map<string, RPCPendingPromise>;
|
|
499
|
+
constructor(transport: MessagePort$1 | NodeJS.Process | ChildProcess);
|
|
500
|
+
postMessage(message: Serializable): void;
|
|
501
|
+
private onMessage;
|
|
502
|
+
private handleResponseMessage;
|
|
503
|
+
private handleRequestMessage;
|
|
504
|
+
send<Data extends Serializable>(type: string, data: Data, id?: string): void;
|
|
505
|
+
success<Data extends Serializable>(id: string, data: Data): void;
|
|
506
|
+
error(id: string, error: string): void;
|
|
507
|
+
request<Data extends Serializable, Output extends Serializable>(type: string, data: Data, id?: string): Promise<Output>;
|
|
461
508
|
}
|
|
462
|
-
declare function $initLoader(): void;
|
|
463
|
-
declare function $postLoaderMessage<Data>(type: string, data: Data, wait?: false): void;
|
|
464
|
-
declare function $postLoaderMessage<Data, Output = unknown>(type: string, data: Data, wait: true): Promise<Output>;
|
|
465
|
-
declare function $unloadFile(path: string): Promise<boolean>;
|
|
466
509
|
|
|
467
510
|
declare const messageCommandHandler: Listener<Events.MessageCreate>;
|
|
468
511
|
declare const chatInputCommandHandler: Listener<Events.InteractionCreate>;
|
|
@@ -494,4 +537,36 @@ declare function loadConfig(cwd?: string): Promise<ProjectConfig>;
|
|
|
494
537
|
*/
|
|
495
538
|
declare function getConfig(): ProjectConfig;
|
|
496
539
|
|
|
497
|
-
|
|
540
|
+
interface InitializeData {
|
|
541
|
+
port: MessagePort;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
interface ResolveContext {
|
|
545
|
+
conditions: string[];
|
|
546
|
+
importAttributes: Record<string, string>;
|
|
547
|
+
parentURL?: string;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
interface ResolveResult {
|
|
551
|
+
url: string;
|
|
552
|
+
shortCircuit?: boolean;
|
|
553
|
+
format?: string | null | undefined;
|
|
554
|
+
importAttributes?: Record<string, string>;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
interface LoadContext {
|
|
558
|
+
conditions: string[];
|
|
559
|
+
format: string | null | undefined;
|
|
560
|
+
importAttributes: Record<string, string>;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
interface LoadResult {
|
|
564
|
+
source: string | ArrayBuffer | Uint8Array;
|
|
565
|
+
format: string;
|
|
566
|
+
shortCircuit?: boolean;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
type NextResolve = (specifier: string, context: ResolveContext) => Promise<ResolveResult>;
|
|
570
|
+
type NextLoad = (url: string, context: LoadContext) => Promise<LoadResult>;
|
|
571
|
+
|
|
572
|
+
export { $initLoader, $unloadFile, type AnyParam, ArgumentError, BakitClient, type BakitClientEvents, BakitError, BaseClientManager, BaseCommandContext, BaseParam, type BaseParamOptions, BaseParamSchema, type BaseRPCMessage, type BaseRPCResponse, ChatInputContext, type ChatInputContextSendOptions, Command, type CommandContext, CommandManager, type CommandOptions, type CommandOptionsInput, CommandOptionsSchema, Context, type ContextSendOptions, EVENT_INTENT_MAPPING, type ErrorHookCallback, type GetPrefixFunction, HookOrder, HookState, type InferParamTuple, type InferParamValue, type InitializeData, Instance, LifecycleManager, Listener, ListenerManager, type ListenerOptions, ListenerOptionsSchema, type LoadContext, type LoadResult, type MainHookCallback, MessageContext, type MessageContextSendOptions, type NextLoad, type NextResolve, type NumberOptions, NumberParam, NumberParamSchema, type ParamResolvedOutputType, ParamUserType, Params, ProjectCacheManager, type ProjectConfig, type ProjectConfigInput, ProjectConfigSchema, RPC, type RPCErrorResponse, type RPCMessage, type RPCPendingPromise, type RPCRequest, type RPCResponse, type RPCSuccessResponse, RPC_RESPONSE_MARK, RPC_RESPONSE_TIMEOUT, type ResolveContext, type ResolveResult, type StringOptions, StringParam, StringParamSchema, type UserOptions, UserParam, UserParamSchema, chatInputCommandHandler, defineCommand, defineConfig, defineListener, extractSnowflakeId, getConfig, getDependencyChain, getImporters, getTopLevelDirectory, isImported, isImportedBy, loadConfig, messageCommandHandler, registerCommandsHandler, tokenize, useApp, validateParamsOrder };
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { GatewayIntentBits, Events, Client, Collection, IntentsBitField, SlashCommandBuilder, SlashCommandStringOption, SlashCommandNumberOption, SlashCommandUserOption, ChatInputCommandInteraction, Message } from 'discord.js';
|
|
2
2
|
import { inspect } from 'util';
|
|
3
|
-
import {
|
|
3
|
+
import { pathToFileURL, fileURLToPath } from 'url';
|
|
4
|
+
import { resolve, posix, relative, sep, join, dirname } from 'path';
|
|
4
5
|
import glob from 'tiny-glob';
|
|
5
6
|
import z4 from 'zod';
|
|
6
7
|
import { register } from 'module';
|
|
7
8
|
import { MessageChannel } from 'worker_threads';
|
|
8
|
-
import {
|
|
9
|
+
import { randomUUID, createHash } from 'crypto';
|
|
10
|
+
import EventEmitter from 'events';
|
|
9
11
|
import { existsSync, mkdirSync, rmSync } from 'fs';
|
|
10
12
|
import { mkdir, writeFile, readFile, rm } from 'fs/promises';
|
|
11
|
-
import { createHash } from 'crypto';
|
|
12
13
|
|
|
13
14
|
// src/core/client/BakitClient.ts
|
|
14
15
|
var ParamUserType = /* @__PURE__ */ ((ParamUserType2) => (ParamUserType2.Bot = "bot", ParamUserType2.Normal = "normal", ParamUserType2.Any = "any", ParamUserType2))(ParamUserType || {}), BaseParamSchema = z4.object({
|
|
@@ -164,34 +165,118 @@ function extractSnowflakeId(input) {
|
|
|
164
165
|
function getTopLevelDirectory(path, entryDir) {
|
|
165
166
|
return relative(entryDir, path).split(sep)[0] ?? null;
|
|
166
167
|
}
|
|
167
|
-
var
|
|
168
|
+
var RPC_RESPONSE_MARK = "$DONE:", RPC_RESPONSE_TIMEOUT = 5e3, RPC = class extends EventEmitter {
|
|
169
|
+
constructor(transport) {
|
|
170
|
+
super();
|
|
171
|
+
this.transport = transport;
|
|
172
|
+
this.transport.on("message", (message) => this.onMessage(message));
|
|
173
|
+
}
|
|
174
|
+
requests = /* @__PURE__ */ new Map();
|
|
175
|
+
postMessage(message) {
|
|
176
|
+
let { transport } = this;
|
|
177
|
+
"send" in transport ? transport.send(message) : "postMessage" in transport ? transport.postMessage(message) : console.warn(`${transport.constructor.name} doesn't support IPC`);
|
|
178
|
+
}
|
|
179
|
+
onMessage(message) {
|
|
180
|
+
if (message.id.startsWith(RPC_RESPONSE_MARK)) {
|
|
181
|
+
this.handleResponseMessage(message);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if ("type" in message) {
|
|
185
|
+
this.handleRequestMessage(message);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
handleResponseMessage(message) {
|
|
190
|
+
let id = message.id.slice(RPC_RESPONSE_MARK.length), request = this.requests.get(id);
|
|
191
|
+
if (!request)
|
|
192
|
+
return;
|
|
193
|
+
let { reject, resolve: resolve5, timeout } = request;
|
|
194
|
+
this.requests.delete(id), clearTimeout(timeout), "data" in message ? resolve5(message.data) : reject(new Error(message.error));
|
|
195
|
+
}
|
|
196
|
+
handleRequestMessage(message) {
|
|
197
|
+
this.emit("message", message), this.emit(message.type, message.id, message.data);
|
|
198
|
+
}
|
|
199
|
+
send(type, data, id = randomUUID()) {
|
|
200
|
+
let message = {
|
|
201
|
+
id,
|
|
202
|
+
type,
|
|
203
|
+
data
|
|
204
|
+
};
|
|
205
|
+
this.postMessage(message);
|
|
206
|
+
}
|
|
207
|
+
success(id, data) {
|
|
208
|
+
let message = {
|
|
209
|
+
id: `${RPC_RESPONSE_MARK}${id}`,
|
|
210
|
+
data
|
|
211
|
+
};
|
|
212
|
+
this.postMessage(message);
|
|
213
|
+
}
|
|
214
|
+
error(id, error) {
|
|
215
|
+
let message = {
|
|
216
|
+
id: `${RPC_RESPONSE_MARK}${id}`,
|
|
217
|
+
error
|
|
218
|
+
};
|
|
219
|
+
this.postMessage(message);
|
|
220
|
+
}
|
|
221
|
+
request(type, data, id = randomUUID()) {
|
|
222
|
+
return new Promise((resolve5, reject) => {
|
|
223
|
+
let timeout = setTimeout(() => {
|
|
224
|
+
this.requests.delete(id) && reject(new Error("Request timed out"));
|
|
225
|
+
}, RPC_RESPONSE_TIMEOUT);
|
|
226
|
+
this.requests.set(id, {
|
|
227
|
+
resolve: resolve5,
|
|
228
|
+
reject,
|
|
229
|
+
timeout
|
|
230
|
+
}), this.send(type, data, id);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
// src/lib/loader/loader.ts
|
|
236
|
+
var rpc, reverseDependencyGraph = /* @__PURE__ */ new Map();
|
|
168
237
|
function $initLoader() {
|
|
169
|
-
let
|
|
170
|
-
port1 = channel.port1, port2 = channel.port2;
|
|
171
|
-
let hookPath = new URL("./hooks.js", import.meta.url).href;
|
|
238
|
+
let { port1, port2 } = new MessageChannel(), hookPath = new URL("./hooks.js", import.meta.url).href;
|
|
172
239
|
register(hookPath, import.meta.url, {
|
|
173
240
|
data: { port: port1 },
|
|
174
241
|
transferList: [port1]
|
|
175
|
-
}), port2.on("
|
|
242
|
+
}), rpc = new RPC(port2), rpc.on("dependencyAdd", (_id, data) => onDependencyAdd(data)), port2.unref();
|
|
176
243
|
}
|
|
177
|
-
function
|
|
178
|
-
|
|
179
|
-
|
|
244
|
+
function $unloadFile(path) {
|
|
245
|
+
if (!rpc)
|
|
246
|
+
throw new Error("Loader isn't initialized");
|
|
247
|
+
return rpc.request("unload", resolve(path));
|
|
180
248
|
}
|
|
181
|
-
function
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
249
|
+
function getImporters(path, createNew = false) {
|
|
250
|
+
path = resolve(path);
|
|
251
|
+
let entry = reverseDependencyGraph.get(path);
|
|
252
|
+
return createNew && !entry && (entry = /* @__PURE__ */ new Set(), reverseDependencyGraph.set(path, entry)), entry;
|
|
253
|
+
}
|
|
254
|
+
function getDependencyChain(path) {
|
|
255
|
+
path = resolve(path);
|
|
256
|
+
let queue = [path], visited = /* @__PURE__ */ new Set();
|
|
257
|
+
for (; queue.length > 0; ) {
|
|
258
|
+
let current = queue.shift();
|
|
259
|
+
if (!current || visited.has(current) || (visited.add(current), current.includes("/node_modules/")))
|
|
260
|
+
continue;
|
|
261
|
+
let parents = getImporters(current);
|
|
262
|
+
if (parents)
|
|
263
|
+
for (let parent of parents)
|
|
264
|
+
visited.has(parent) || queue.push(parent);
|
|
186
265
|
}
|
|
187
|
-
return
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
266
|
+
return Array.from(visited);
|
|
267
|
+
}
|
|
268
|
+
function isImported(path) {
|
|
269
|
+
return !!getImporters(path)?.size;
|
|
270
|
+
}
|
|
271
|
+
function isImportedBy(path, matcher) {
|
|
272
|
+
return getDependencyChain(path).slice(1).some((p) => {
|
|
273
|
+
let isMatch = false;
|
|
274
|
+
return typeof matcher == "string" && (isMatch = resolve(matcher) === p), typeof matcher == "function" && (isMatch = matcher(p)), matcher instanceof RegExp && (isMatch = matcher.test(p)), isMatch;
|
|
191
275
|
});
|
|
192
276
|
}
|
|
193
|
-
function
|
|
194
|
-
|
|
277
|
+
function onDependencyAdd(data) {
|
|
278
|
+
let { url, parentURL } = data, path = fileURLToPath(url), parentPath = fileURLToPath(parentURL), entry = reverseDependencyGraph.get(path);
|
|
279
|
+
entry || (entry = /* @__PURE__ */ new Set(), reverseDependencyGraph.set(path, entry)), entry.add(parentPath);
|
|
195
280
|
}
|
|
196
281
|
|
|
197
282
|
// src/core/structures/param/Param.ts
|
|
@@ -475,6 +560,8 @@ var BaseClientManager = class {
|
|
|
475
560
|
this.client = client;
|
|
476
561
|
}
|
|
477
562
|
};
|
|
563
|
+
|
|
564
|
+
// src/core/managers/CommandManager.ts
|
|
478
565
|
var CommandManager = class extends BaseClientManager {
|
|
479
566
|
commands = new Collection();
|
|
480
567
|
entries = new Collection();
|
|
@@ -573,6 +660,8 @@ var Context = class {
|
|
|
573
660
|
this.canceled = true;
|
|
574
661
|
}
|
|
575
662
|
};
|
|
663
|
+
|
|
664
|
+
// src/core/managers/ListenerManager.ts
|
|
576
665
|
var ListenerManager = class extends BaseClientManager {
|
|
577
666
|
listeners = [];
|
|
578
667
|
entries = new Collection();
|
|
@@ -770,7 +859,7 @@ var BaseCommandContext = class extends Context {
|
|
|
770
859
|
return await channel.send(options);
|
|
771
860
|
}
|
|
772
861
|
};
|
|
773
|
-
var ProjectConfigSchema = z4.object({
|
|
862
|
+
var CONFIG_EXTENSIONS = ["ts", "js"], ProjectConfigSchema = z4.object({
|
|
774
863
|
/**
|
|
775
864
|
* The gateway intents to use for the Discord client.
|
|
776
865
|
*
|
|
@@ -789,7 +878,13 @@ var ProjectConfigSchema = z4.object({
|
|
|
789
878
|
* @see {@link https://discord.js.org/docs/packages/discord.js/main/ClientOptions:Interface}
|
|
790
879
|
*/
|
|
791
880
|
clientOptions: z4.custom().optional(),
|
|
881
|
+
/**
|
|
882
|
+
* Your bot prefixes to trigger the commands.
|
|
883
|
+
*/
|
|
792
884
|
prefixes: z4.array(z4.string()).default([]),
|
|
885
|
+
/**
|
|
886
|
+
* Your Discord bot token.
|
|
887
|
+
*/
|
|
793
888
|
token: z4.string()
|
|
794
889
|
});
|
|
795
890
|
function defineConfig(config) {
|
|
@@ -799,7 +894,7 @@ var _config;
|
|
|
799
894
|
async function loadConfig(cwd = process.cwd()) {
|
|
800
895
|
if (_config)
|
|
801
896
|
return console.warn("loadConfig() was called more than once. This shouldn't happen."), _config;
|
|
802
|
-
let globPattern = `bakit.config.{${
|
|
897
|
+
let globPattern = `bakit.config.{${CONFIG_EXTENSIONS.join(",")}}`, [configPath, other] = await glob(globPattern, {
|
|
803
898
|
cwd: cwd.replace(/\\/g, "/"),
|
|
804
899
|
// ensure the path uses `/` instead of `\` on Windows
|
|
805
900
|
absolute: true
|
|
@@ -815,6 +910,39 @@ function getConfig() {
|
|
|
815
910
|
throw new Error("Project config is not loaded.");
|
|
816
911
|
return _config;
|
|
817
912
|
}
|
|
913
|
+
var ProjectCacheManager = class {
|
|
914
|
+
rootDir;
|
|
915
|
+
constructor(root = process.cwd()) {
|
|
916
|
+
this.rootDir = join(root, ".bakit"), this.ensureRoot();
|
|
917
|
+
}
|
|
918
|
+
ensureRoot() {
|
|
919
|
+
existsSync(this.rootDir) || mkdirSync(this.rootDir, { recursive: true });
|
|
920
|
+
}
|
|
921
|
+
getHash(data) {
|
|
922
|
+
return createHash("sha256").update(JSON.stringify(data)).digest("hex");
|
|
923
|
+
}
|
|
924
|
+
async write(path, data) {
|
|
925
|
+
let fullPath = join(this.rootDir, path), dir = dirname(fullPath);
|
|
926
|
+
await mkdir(dir, { recursive: true });
|
|
927
|
+
let content = typeof data == "string" ? data : JSON.stringify(data);
|
|
928
|
+
await writeFile(fullPath, content, "utf-8");
|
|
929
|
+
}
|
|
930
|
+
async read(path) {
|
|
931
|
+
let fullPath = join(this.rootDir, path);
|
|
932
|
+
try {
|
|
933
|
+
let content = await readFile(fullPath, "utf-8");
|
|
934
|
+
return JSON.parse(content);
|
|
935
|
+
} catch {
|
|
936
|
+
return null;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
async clear() {
|
|
940
|
+
await rm(this.rootDir, { recursive: true, force: true });
|
|
941
|
+
}
|
|
942
|
+
clearSync() {
|
|
943
|
+
existsSync(this.rootDir) && rmSync(this.rootDir, { recursive: true, force: true });
|
|
944
|
+
}
|
|
945
|
+
};
|
|
818
946
|
var messageCommandHandler = defineListener(Events.MessageCreate), chatInputCommandHandler = defineListener(Events.InteractionCreate), registerCommandsHandler = defineListener({
|
|
819
947
|
name: Events.ClientReady,
|
|
820
948
|
once: true
|
|
@@ -873,46 +1001,14 @@ chatInputCommandHandler.main(async (_, interaction) => {
|
|
|
873
1001
|
}
|
|
874
1002
|
await command.execute(context, ...resolvedArgs);
|
|
875
1003
|
});
|
|
876
|
-
var ProjectCacheManager = class {
|
|
877
|
-
rootDir;
|
|
878
|
-
constructor(root = process.cwd()) {
|
|
879
|
-
this.rootDir = join(root, ".bakit"), this.ensureRoot();
|
|
880
|
-
}
|
|
881
|
-
ensureRoot() {
|
|
882
|
-
existsSync(this.rootDir) || mkdirSync(this.rootDir, { recursive: true });
|
|
883
|
-
}
|
|
884
|
-
getHash(data) {
|
|
885
|
-
return createHash("sha256").update(JSON.stringify(data)).digest("hex");
|
|
886
|
-
}
|
|
887
|
-
async write(path, data) {
|
|
888
|
-
let fullPath = join(this.rootDir, path), dir = dirname(fullPath);
|
|
889
|
-
await mkdir(dir, { recursive: true });
|
|
890
|
-
let content = typeof data == "string" ? data : JSON.stringify(data);
|
|
891
|
-
await writeFile(fullPath, content, "utf-8");
|
|
892
|
-
}
|
|
893
|
-
async read(path) {
|
|
894
|
-
let fullPath = join(this.rootDir, path);
|
|
895
|
-
try {
|
|
896
|
-
let content = await readFile(fullPath, "utf-8");
|
|
897
|
-
return JSON.parse(content);
|
|
898
|
-
} catch {
|
|
899
|
-
return null;
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
async clear() {
|
|
903
|
-
await rm(this.rootDir, { recursive: true, force: true });
|
|
904
|
-
}
|
|
905
|
-
clearSync() {
|
|
906
|
-
existsSync(this.rootDir) && rmSync(this.rootDir, { recursive: true, force: true });
|
|
907
|
-
}
|
|
908
|
-
};
|
|
909
1004
|
|
|
910
1005
|
// src/core/internal/Instance.ts
|
|
911
|
-
var Instance = class {
|
|
1006
|
+
var HOT_DIRECTORIES = ["listeners", "commands"], SOURCE_ROOT = resolve(process.cwd(), "src"), APP_ENTRY_POINTS = /* @__PURE__ */ new Set([resolve(SOURCE_ROOT, "index.ts"), resolve(SOURCE_ROOT, "index.js")]), Instance = class {
|
|
912
1007
|
client;
|
|
913
1008
|
cache;
|
|
1009
|
+
rpc;
|
|
914
1010
|
constructor() {
|
|
915
|
-
this.cache = new ProjectCacheManager();
|
|
1011
|
+
this.cache = new ProjectCacheManager(), this.rpc = new RPC(process);
|
|
916
1012
|
}
|
|
917
1013
|
async start() {
|
|
918
1014
|
await loadConfig();
|
|
@@ -926,7 +1022,7 @@ var Instance = class {
|
|
|
926
1022
|
), await this.loadModules(), this.initIntents(), await this.client.login(config.token), this.initProcess();
|
|
927
1023
|
}
|
|
928
1024
|
initProcess() {
|
|
929
|
-
process.on("
|
|
1025
|
+
process.env.NODE_ENV === "development" && (this.rpc.on("fileRemove", (_id, path) => this.onFileRemove(path)), this.rpc.on("fileChange", (_id, path) => this.onFileChange(path))), process.on("SIGINT", () => this.shutdown()), process.on("SIGTERM", () => this.shutdown());
|
|
930
1026
|
}
|
|
931
1027
|
loadModules() {
|
|
932
1028
|
let { managers } = this.client, { commands, listeners } = managers;
|
|
@@ -936,18 +1032,59 @@ var Instance = class {
|
|
|
936
1032
|
let config = getConfig(), { options, managers } = this.client, { listeners } = managers, intents;
|
|
937
1033
|
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;
|
|
938
1034
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1035
|
+
isInHotDirectory(path) {
|
|
1036
|
+
if (!path.startsWith(SOURCE_ROOT))
|
|
1037
|
+
return false;
|
|
1038
|
+
let topLevelDir = getTopLevelDirectory(path, SOURCE_ROOT);
|
|
1039
|
+
return !!topLevelDir && HOT_DIRECTORIES.includes(topLevelDir);
|
|
1040
|
+
}
|
|
1041
|
+
restart() {
|
|
1042
|
+
this.rpc.send("restart", {});
|
|
1043
|
+
}
|
|
1044
|
+
async shutdown() {
|
|
1045
|
+
this.client && await this.client.destroy().catch(() => null), process.exit(0);
|
|
1046
|
+
}
|
|
1047
|
+
containsEntryPoint(chain) {
|
|
1048
|
+
return chain.some((x) => APP_ENTRY_POINTS.has(x));
|
|
1049
|
+
}
|
|
1050
|
+
containsHotModule(chain) {
|
|
1051
|
+
return chain.some((x) => this.isInHotDirectory(x));
|
|
1052
|
+
}
|
|
1053
|
+
async onFileRemove(path) {
|
|
1054
|
+
if (!isImported(path))
|
|
1055
|
+
return;
|
|
1056
|
+
let chain = getDependencyChain(path);
|
|
1057
|
+
if (this.containsEntryPoint(chain)) {
|
|
1058
|
+
this.restart();
|
|
943
1059
|
return;
|
|
944
|
-
|
|
945
|
-
|
|
1060
|
+
}
|
|
1061
|
+
if (this.containsHotModule(chain))
|
|
1062
|
+
for (let path2 of chain.reverse())
|
|
1063
|
+
await this.unloadModule(path2);
|
|
1064
|
+
}
|
|
1065
|
+
async onFileChange(path) {
|
|
1066
|
+
if (!isImported(path))
|
|
1067
|
+
return;
|
|
1068
|
+
let chain = getDependencyChain(path);
|
|
1069
|
+
if (this.containsEntryPoint(chain)) {
|
|
1070
|
+
this.restart();
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
if (this.containsHotModule(chain))
|
|
1074
|
+
for (let path2 of chain.reverse())
|
|
1075
|
+
await this.unloadModule(path2, true);
|
|
1076
|
+
}
|
|
1077
|
+
async unloadModule(path, reload = false) {
|
|
1078
|
+
let { listeners, commands } = this.client.managers;
|
|
1079
|
+
switch (getTopLevelDirectory(path, SOURCE_ROOT)) {
|
|
946
1080
|
case "listeners":
|
|
947
|
-
await listeners
|
|
1081
|
+
await listeners[reload ? "reload" : "unload"](path);
|
|
948
1082
|
break;
|
|
949
1083
|
case "commands":
|
|
950
|
-
await commands
|
|
1084
|
+
await commands[reload ? "reload" : "unload"](path);
|
|
1085
|
+
break;
|
|
1086
|
+
default:
|
|
1087
|
+
await $unloadFile(path);
|
|
951
1088
|
break;
|
|
952
1089
|
}
|
|
953
1090
|
}
|
|
@@ -966,4 +1103,4 @@ var Params = {
|
|
|
966
1103
|
user: createFactory(UserParam)
|
|
967
1104
|
};
|
|
968
1105
|
|
|
969
|
-
export { $initLoader, $
|
|
1106
|
+
export { $initLoader, $unloadFile, ArgumentError, 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, ProjectCacheManager, ProjectConfigSchema, RPC, RPC_RESPONSE_MARK, RPC_RESPONSE_TIMEOUT, StringParam, StringParamSchema, UserParam, UserParamSchema, chatInputCommandHandler, defineCommand, defineConfig, defineListener, extractSnowflakeId, getConfig, getDependencyChain, getImporters, getTopLevelDirectory, isImported, isImportedBy, loadConfig, messageCommandHandler, registerCommandsHandler, tokenize, useApp, validateParamsOrder };
|