@seedcord/core 0.1.0-next.6 → 0.1.0-next.8
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/HmrModuleHandler-3sNgKHdf.mjs +163 -0
- package/dist/HmrModuleHandler-3sNgKHdf.mjs.map +1 -0
- package/dist/HmrModuleHandler-CTBng7wV.cjs +170 -0
- package/dist/HmrModuleHandler-CTBng7wV.cjs.map +1 -0
- package/dist/Plugin-BZit5HUI.d.mts +555 -0
- package/dist/{Plugin-C2-VHrsX.cjs → Plugin-BlkhHNRm.cjs} +15 -34
- package/dist/Plugin-BlkhHNRm.cjs.map +1 -0
- package/dist/{Plugin-PcdPjAzc.mjs → Plugin-CDAV7P9l.mjs} +16 -29
- package/dist/Plugin-CDAV7P9l.mjs.map +1 -0
- package/dist/basic-1hebYVcN.d.mts +22 -0
- package/dist/contextMenuLeaves-f2rbyo83.d.mts +19 -0
- package/dist/{permissions-DSW_EZfN.cjs → cursor-BMkFAwO2.cjs} +308 -300
- package/dist/cursor-BMkFAwO2.cjs.map +1 -0
- package/dist/{permissions-RVCBhL2n.mjs → cursor-BvSH8tgw.mjs} +249 -247
- package/dist/cursor-BvSH8tgw.mjs.map +1 -0
- package/dist/{AutocompleteOptions-eKhIe6Qt.d.mts → cursor-D6nBjwaE.d.mts} +207 -116
- package/dist/hmr.index.cjs +2 -164
- package/dist/hmr.index.mjs +2 -162
- package/dist/index-Cr4-VV4u.d.mts +142 -0
- package/dist/index.cjs +362 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +239 -38
- package/dist/index.mjs +313 -26
- package/dist/index.mjs.map +1 -1
- package/dist/internal.index.cjs +278 -83
- package/dist/internal.index.cjs.map +1 -1
- package/dist/internal.index.d.mts +111 -42
- package/dist/internal.index.mjs +223 -43
- package/dist/internal.index.mjs.map +1 -1
- package/dist/node-internal.index.cjs +314 -76
- package/dist/node-internal.index.cjs.map +1 -1
- package/dist/node-internal.index.d.mts +123 -2164
- package/dist/node-internal.index.mjs +313 -77
- package/dist/node-internal.index.mjs.map +1 -1
- package/dist/{phases-BfpAG6w3.mjs → phases-BauKJOTT.mjs} +2 -2
- package/dist/phases-BauKJOTT.mjs.map +1 -0
- package/dist/{phases-C_BGNyVo.cjs → phases-DcuDHoQl.cjs} +2 -2
- package/dist/phases-DcuDHoQl.cjs.map +1 -0
- package/dist/plugin.index.cjs +1 -1
- package/dist/plugin.index.d.mts +2 -2
- package/dist/plugin.index.mjs +1 -1
- package/dist/publishDefault-CVlwYUS5.cjs +382 -0
- package/dist/publishDefault-CVlwYUS5.cjs.map +1 -0
- package/dist/publishDefault-CldnxcT2.mjs +287 -0
- package/dist/publishDefault-CldnxcT2.mjs.map +1 -0
- package/dist/slashRouteLeaves-BANDtPFm.mjs +23 -0
- package/dist/slashRouteLeaves-BANDtPFm.mjs.map +1 -0
- package/dist/slashRouteLeaves-nfxOAM7Q.cjs +28 -0
- package/dist/slashRouteLeaves-nfxOAM7Q.cjs.map +1 -0
- package/dist/subscribers-BSJoyKNN.cjs +517 -0
- package/dist/subscribers-BSJoyKNN.cjs.map +1 -0
- package/dist/subscribers-DuxdM2cS.mjs +480 -0
- package/dist/subscribers-DuxdM2cS.mjs.map +1 -0
- package/package.json +7 -6
- package/dist/Plugin-C2-VHrsX.cjs.map +0 -1
- package/dist/Plugin-CNyRKDHT.d.mts +0 -226
- package/dist/Plugin-PcdPjAzc.mjs.map +0 -1
- package/dist/hmr.index.cjs.map +0 -1
- package/dist/hmr.index.mjs.map +0 -1
- package/dist/is-never-Ddaba1Su.d.mts +0 -58
- package/dist/permissions-DSW_EZfN.cjs.map +0 -1
- package/dist/permissions-RVCBhL2n.mjs.map +0 -1
- package/dist/phases-BfpAG6w3.mjs.map +0 -1
- package/dist/phases-C_BGNyVo.cjs.map +0 -1
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_rolldown_runtime = require('./rolldown-runtime-C_NdSu1c.cjs');
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const require_publishDefault = require('./publishDefault-CVlwYUS5.cjs');
|
|
4
|
+
const require_phases = require('./phases-DcuDHoQl.cjs');
|
|
5
|
+
const require_subscribers = require('./subscribers-BSJoyKNN.cjs');
|
|
6
|
+
const require_devChannel = require('./devChannel-CoCmAVDx.cjs');
|
|
7
|
+
const require_Plugin = require('./Plugin-BlkhHNRm.cjs');
|
|
8
|
+
const require_slashRouteLeaves = require('./slashRouteLeaves-nfxOAM7Q.cjs');
|
|
9
|
+
const require_HmrModuleHandler = require('./HmrModuleHandler-CTBng7wV.cjs');
|
|
10
|
+
let _discordjs_builders = require("@discordjs/builders");
|
|
11
|
+
let _seedcord_logger = require("@seedcord/logger");
|
|
12
|
+
let discord_api_types_v10 = require("discord-api-types/v10");
|
|
5
13
|
let _seedcord_errors = require("@seedcord/errors");
|
|
6
14
|
let _seedcord_errors_internal = require("@seedcord/errors/internal");
|
|
7
|
-
let
|
|
15
|
+
let _seedcord_utils = require("@seedcord/utils");
|
|
8
16
|
let chalk = require("chalk");
|
|
9
17
|
chalk = require_rolldown_runtime.__toESM(chalk, 1);
|
|
10
|
-
let
|
|
18
|
+
let envapt = require("envapt");
|
|
19
|
+
let node_path = require("node:path");
|
|
11
20
|
let node_http = require("node:http");
|
|
21
|
+
let _seedcord_utils_node = require("@seedcord/utils/node");
|
|
12
22
|
|
|
13
23
|
//#region src/node/Lifecycle/withTimeout.ts
|
|
14
24
|
async function raceTimer(work, timeoutMs, onTimeout) {
|
|
@@ -39,16 +49,15 @@ function settleWithin(work, timeoutMs) {
|
|
|
39
49
|
*
|
|
40
50
|
* @internal
|
|
41
51
|
*/
|
|
42
|
-
var CoordinatedLifecycle = class
|
|
52
|
+
var CoordinatedLifecycle = class {
|
|
43
53
|
phaseOrder;
|
|
44
54
|
phaseEnum;
|
|
45
55
|
logger;
|
|
46
56
|
tasksMap = /* @__PURE__ */ new Map();
|
|
47
57
|
constructor(loggerName, phaseOrder, phaseEnum) {
|
|
48
|
-
super();
|
|
49
58
|
this.phaseOrder = phaseOrder;
|
|
50
59
|
this.phaseEnum = phaseEnum;
|
|
51
|
-
this.logger = new _seedcord_logger.Logger(loggerName);
|
|
60
|
+
this.logger = new _seedcord_logger.Logger(loggerName, { channel: "lifecycle" });
|
|
52
61
|
this.phaseOrder.forEach((phase) => this.tasksMap.set(phase, []));
|
|
53
62
|
}
|
|
54
63
|
/**
|
|
@@ -95,11 +104,9 @@ var CoordinatedLifecycle = class extends _seedcord_event_emitter.TypedEventEmitt
|
|
|
95
104
|
return;
|
|
96
105
|
}
|
|
97
106
|
this.logger.info(`${chalk.default.bold.yellow("Running")} ${this.getTaskType()} phase ${chalk.default.bold.magenta(this.phaseEnum[phase])} with ${chalk.default.bold.cyan(tasks.length)} tasks`);
|
|
98
|
-
this.emitPhase(phase, "start");
|
|
99
107
|
const failures = (await this.executeTasksInPhase(phase, tasks)).filter((r) => r.status === "rejected").length;
|
|
100
108
|
if (failures > 0) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.LifecyclePhaseFailures, [this.phaseEnum[phase], failures]);
|
|
101
109
|
this.logger.info(`Phase ${chalk.default.bold.magenta(this.phaseEnum[phase])} ${chalk.default.bold.green("completed successfully")}`);
|
|
102
|
-
this.emitPhase(phase, "complete");
|
|
103
110
|
}
|
|
104
111
|
async runTaskWithTimeout(phase, task) {
|
|
105
112
|
this.logger.info(`${chalk.default.italic("Starting")} task ${chalk.default.bold.cyan(task.name)} in phase ${chalk.default.bold.magenta(this.phaseEnum[phase])}`);
|
|
@@ -111,12 +118,6 @@ var CoordinatedLifecycle = class extends _seedcord_event_emitter.TypedEventEmitt
|
|
|
111
118
|
throw error;
|
|
112
119
|
}
|
|
113
120
|
}
|
|
114
|
-
emitPhase(phase, action) {
|
|
115
|
-
this.emitSafeRaw(`phase:${phase}:${action}`);
|
|
116
|
-
}
|
|
117
|
-
onListenerError(error, event) {
|
|
118
|
-
this.logger.error(`listener for ${String(event)} threw`, error);
|
|
119
|
-
}
|
|
120
121
|
};
|
|
121
122
|
|
|
122
123
|
//#endregion
|
|
@@ -179,11 +180,18 @@ var CoordinatedShutdown = class extends CoordinatedLifecycle {
|
|
|
179
180
|
this.onSigInt = null;
|
|
180
181
|
}
|
|
181
182
|
}
|
|
182
|
-
/** @internal run() awaits this so
|
|
183
|
+
/** @internal run() awaits this so boot finishes registering its dispose tasks first */
|
|
183
184
|
gateOnStartup(settled) {
|
|
184
185
|
this.startupGate = settled;
|
|
185
186
|
}
|
|
186
|
-
/**
|
|
187
|
+
/**
|
|
188
|
+
* Adds a shutdown-phase task.
|
|
189
|
+
*
|
|
190
|
+
* @param phase - The shutdown phase to run the task in.
|
|
191
|
+
* @param taskName - A descriptive name for the task.
|
|
192
|
+
* @param task - The async function to run.
|
|
193
|
+
* @param timeoutMs - Task timeout in ms. {@default `5000` }
|
|
194
|
+
*/
|
|
187
195
|
addTask(phase, taskName, task, timeoutMs = 5e3) {
|
|
188
196
|
super.addTask(phase, taskName, task, timeoutMs);
|
|
189
197
|
}
|
|
@@ -195,8 +203,8 @@ var CoordinatedShutdown = class extends CoordinatedLifecycle {
|
|
|
195
203
|
* Runs registered tasks across shutdown phases in `ShutdownPhase` order.
|
|
196
204
|
* Tasks within each phase run in parallel.
|
|
197
205
|
*
|
|
198
|
-
* @param exitCode - Process exit code. {@default `0`}
|
|
199
|
-
* @param exitProcess - Whether to exit the process after shutdown. {@default `true`}
|
|
206
|
+
* @param exitCode - Process exit code. {@default `0` }
|
|
207
|
+
* @param exitProcess - Whether to exit the process after shutdown. {@default `true` }
|
|
200
208
|
* @example
|
|
201
209
|
* ```typescript
|
|
202
210
|
* shutdown.addTask(ShutdownPhase.Disconnect, 'database', () => db.disconnect(), 5000);
|
|
@@ -212,7 +220,6 @@ var CoordinatedShutdown = class extends CoordinatedLifecycle {
|
|
|
212
220
|
this.isShuttingDown = true;
|
|
213
221
|
this.exitCode = exitCode;
|
|
214
222
|
this.logger.info(`${chalk.default.bold.yellow("Starting")} coordinated shutdown with exit code ${chalk.default.bold.cyan(exitCode)}`);
|
|
215
|
-
this.emitSafe("shutdown:start");
|
|
216
223
|
try {
|
|
217
224
|
if (this.startupGate) await this.startupGate;
|
|
218
225
|
const failures = [];
|
|
@@ -221,11 +228,8 @@ var CoordinatedShutdown = class extends CoordinatedLifecycle {
|
|
|
221
228
|
} catch (error) {
|
|
222
229
|
failures.push(error);
|
|
223
230
|
}
|
|
224
|
-
if (failures.length > 0) this.
|
|
225
|
-
else {
|
|
226
|
-
this.logger.info(`${chalk.default.bold.green("Coordinated shutdown completed")} successfully`);
|
|
227
|
-
this.emitSafe("shutdown:complete");
|
|
228
|
-
}
|
|
231
|
+
if (failures.length > 0) this.logger.error(`${chalk.default.bold.red("Coordinated shutdown failed")}`, ...failures);
|
|
232
|
+
else this.logger.info(`${chalk.default.bold.green("Coordinated shutdown completed")} successfully`);
|
|
229
233
|
} finally {
|
|
230
234
|
this.hasShutdown = true;
|
|
231
235
|
if (exitProcess) {
|
|
@@ -239,11 +243,6 @@ var CoordinatedShutdown = class extends CoordinatedLifecycle {
|
|
|
239
243
|
}
|
|
240
244
|
}
|
|
241
245
|
}
|
|
242
|
-
emitFailures(failures) {
|
|
243
|
-
this.logger.error(`${chalk.default.bold.red("Coordinated shutdown failed")}`);
|
|
244
|
-
const error = failures.length === 1 ? failures[0] : new AggregateError(failures, "shutdown phase failures");
|
|
245
|
-
this.emitSafe("shutdown:error", error);
|
|
246
|
-
}
|
|
247
246
|
};
|
|
248
247
|
|
|
249
248
|
//#endregion
|
|
@@ -262,7 +261,14 @@ var CoordinatedStartup = class extends CoordinatedLifecycle {
|
|
|
262
261
|
constructor() {
|
|
263
262
|
super("Startup", PHASE_ORDER, require_phases.StartupPhase);
|
|
264
263
|
}
|
|
265
|
-
/**
|
|
264
|
+
/**
|
|
265
|
+
* Adds a startup-phase task.
|
|
266
|
+
*
|
|
267
|
+
* @param phase - The startup phase to run the task in.
|
|
268
|
+
* @param taskName - A descriptive name for the task.
|
|
269
|
+
* @param task - The async function to run.
|
|
270
|
+
* @param timeoutMs - Task timeout in ms. {@default `10000` }
|
|
271
|
+
*/
|
|
266
272
|
addTask(phase, taskName, task, timeoutMs = 1e4) {
|
|
267
273
|
super.addTask(phase, taskName, task, timeoutMs);
|
|
268
274
|
}
|
|
@@ -299,7 +305,6 @@ var CoordinatedStartup = class extends CoordinatedLifecycle {
|
|
|
299
305
|
}
|
|
300
306
|
this.isStartingUp = true;
|
|
301
307
|
this.logger.info(`${chalk.default.bold.green("Starting")} coordinated startup sequence`);
|
|
302
|
-
this.emitSafe("startup:start");
|
|
303
308
|
try {
|
|
304
309
|
for (const phase of PHASE_ORDER) {
|
|
305
310
|
if (!this.isStartingUp) {
|
|
@@ -310,14 +315,12 @@ var CoordinatedStartup = class extends CoordinatedLifecycle {
|
|
|
310
315
|
}
|
|
311
316
|
this.hasStarted = true;
|
|
312
317
|
this.logger.info(`${chalk.default.bold.green("Coordinated startup completed")} successfully`);
|
|
313
|
-
this.emitSafe("startup:complete");
|
|
314
318
|
} catch (error) {
|
|
315
319
|
if (!this.isStartingUp) {
|
|
316
320
|
this.logger.warn("Startup sequence aborted during error handling");
|
|
317
321
|
return;
|
|
318
322
|
}
|
|
319
323
|
this.logger.error(`${chalk.default.bold.red("Coordinated startup failed")}`);
|
|
320
|
-
this.emitSafe("startup:error", error);
|
|
321
324
|
throw error;
|
|
322
325
|
} finally {
|
|
323
326
|
this.isStartingUp = false;
|
|
@@ -361,7 +364,7 @@ const DEFAULT_HEALTH_CHECK_PATH = "/health";
|
|
|
361
364
|
*/
|
|
362
365
|
var HealthCheck = class HealthCheck {
|
|
363
366
|
/** @internal */
|
|
364
|
-
logger = new _seedcord_logger.Logger("HealthCheck");
|
|
367
|
+
logger = new _seedcord_logger.Logger("HealthCheck", { channel: "health" });
|
|
365
368
|
port;
|
|
366
369
|
path;
|
|
367
370
|
host;
|
|
@@ -406,7 +409,7 @@ var HealthCheck = class HealthCheck {
|
|
|
406
409
|
server.removeListener("error", onListenError);
|
|
407
410
|
server.on("error", (err) => this.logger.error("Health check server error", err));
|
|
408
411
|
const address = this.host ?? "localhost";
|
|
409
|
-
this.logger.info(`${_seedcord_logger.paint.mint.bold("
|
|
412
|
+
this.logger.info(`${_seedcord_logger.paint.mint.bold("✔︎")} Health check server listening on ${_seedcord_logger.paint.sky(`http://${address}:${this.port}${this.path}`)}`);
|
|
410
413
|
resolve();
|
|
411
414
|
});
|
|
412
415
|
if (this.host) {
|
|
@@ -440,19 +443,22 @@ var HealthCheck = class HealthCheck {
|
|
|
440
443
|
|
|
441
444
|
//#endregion
|
|
442
445
|
//#region src/node/Pluggable.ts
|
|
446
|
+
const RESERVED_KEYS = new Set(_seedcord_logger.FRAMEWORK_CHANNELS);
|
|
443
447
|
/**
|
|
444
|
-
* Base class for
|
|
448
|
+
* Base class for a plugin host, a transport `Seedcord` class.
|
|
445
449
|
*
|
|
446
450
|
* Plugins are attached during configuration and initialized during startup, sequentially in attach
|
|
447
|
-
* order within each phase.
|
|
451
|
+
* order within each phase.
|
|
448
452
|
*/
|
|
449
|
-
var Pluggable = class Pluggable
|
|
450
|
-
|
|
451
|
-
startFailed = false;
|
|
453
|
+
var Pluggable = class Pluggable {
|
|
454
|
+
/** @see {@link CoordinatedShutdown} */
|
|
452
455
|
shutdown;
|
|
456
|
+
/** @see {@link CoordinatedStartup} */
|
|
453
457
|
startup;
|
|
458
|
+
isInitialized = false;
|
|
459
|
+
startFailed = false;
|
|
454
460
|
plugins = [];
|
|
455
|
-
pluginLogger = new _seedcord_logger.Logger("Plugins");
|
|
461
|
+
pluginLogger = new _seedcord_logger.Logger("Plugins", { channel: "plugins" });
|
|
456
462
|
attachments = [];
|
|
457
463
|
completedInits = /* @__PURE__ */ new Set();
|
|
458
464
|
disposePhases = /* @__PURE__ */ new Set();
|
|
@@ -464,7 +470,6 @@ var Pluggable = class Pluggable extends _seedcord_event_emitter.TypedEventEmitte
|
|
|
464
470
|
shutdown.removeSignalHandlers();
|
|
465
471
|
throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CoreSingletonViolation);
|
|
466
472
|
}
|
|
467
|
-
super();
|
|
468
473
|
Pluggable.isInstantiated = true;
|
|
469
474
|
Pluggable.liveShutdown = shutdown;
|
|
470
475
|
this.shutdown = shutdown;
|
|
@@ -488,13 +493,11 @@ var Pluggable = class Pluggable extends _seedcord_event_emitter.TypedEventEmitte
|
|
|
488
493
|
this.isInitialized = true;
|
|
489
494
|
return this;
|
|
490
495
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
pluginStore() {
|
|
495
|
-
return this.config.store ?? this.rateLimiter;
|
|
496
|
+
/** @internal codegen reads these to emit the `Core` augmentation */
|
|
497
|
+
get pluginKeys() {
|
|
498
|
+
return this.attachments.map((attachment) => attachment.key);
|
|
496
499
|
}
|
|
497
|
-
/** @internal
|
|
500
|
+
/** @internal so the next host can construct */
|
|
498
501
|
static reset() {
|
|
499
502
|
Pluggable.liveShutdown?.removeSignalHandlers();
|
|
500
503
|
Pluggable.liveShutdown = void 0;
|
|
@@ -504,8 +507,12 @@ var Pluggable = class Pluggable extends _seedcord_event_emitter.TypedEventEmitte
|
|
|
504
507
|
* Attaches a plugin to this instance.
|
|
505
508
|
*
|
|
506
509
|
* The plugin initializes during startup, after every plugin attached before it, and becomes
|
|
507
|
-
* available as a property on `core`.
|
|
508
|
-
*
|
|
510
|
+
* available as a property on `core`. `seedcord codegen` writes the `Core` augmentation that
|
|
511
|
+
* types it.
|
|
512
|
+
*
|
|
513
|
+
* A plugin declaring a `transport` or `runtime` this host does not run is a compile error on
|
|
514
|
+
* this call. An edge host takes no plugins at all. A plugin constructor narrowing its first
|
|
515
|
+
* parameter past `CoreBase` is a compile error here too. Read the transport `Core` off `this.core`.
|
|
509
516
|
*
|
|
510
517
|
* @typeParam Key - The property name for accessing the plugin
|
|
511
518
|
* @typeParam Ctor - The plugin constructor type
|
|
@@ -513,38 +520,25 @@ var Pluggable = class Pluggable extends _seedcord_event_emitter.TypedEventEmitte
|
|
|
513
520
|
* @param Plugin - Plugin constructor class
|
|
514
521
|
* @param args - Additional arguments to pass to the plugin constructor
|
|
515
522
|
* @returns This instance with the plugin attached as a typed property
|
|
516
|
-
* @throws A **SeedcordError** When called after initialization or if key already exists
|
|
523
|
+
* @throws A **SeedcordError** When called after initialization or if key already exists or is reserved
|
|
517
524
|
* @example
|
|
518
525
|
* ```typescript
|
|
519
|
-
* seedcord.attach('db',
|
|
526
|
+
* seedcord.attach('db', Mongoose, { uri: 'mongodb://...', name: 'seedcord', dir: ... })
|
|
520
527
|
* ```
|
|
521
528
|
*/
|
|
522
529
|
attach(key, Plugin, ...args) {
|
|
523
530
|
if (this.isInitialized) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CorePluginAfterInit);
|
|
531
|
+
if (RESERVED_KEYS.has(key)) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CorePluginReservedChannel, [key]);
|
|
524
532
|
if (key in this) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CorePluginKeyExists, [key]);
|
|
525
533
|
const instance = new Plugin(this, ...args);
|
|
534
|
+
instance.logger.setChannel(key);
|
|
526
535
|
this.plugins.push(instance);
|
|
527
536
|
this.attachments.push({
|
|
528
537
|
key,
|
|
529
538
|
instance
|
|
530
539
|
});
|
|
531
|
-
this.finalizeContext(key, instance);
|
|
532
540
|
return Object.assign(this, { [key]: instance });
|
|
533
541
|
}
|
|
534
|
-
finalizeContext(key, instance) {
|
|
535
|
-
const caps = this.pluginCapabilities();
|
|
536
|
-
const readToken = () => this.pluginCapabilities().token;
|
|
537
|
-
require_Plugin.finalizePluginContext(instance, {
|
|
538
|
-
logger: new _seedcord_logger.Logger(key),
|
|
539
|
-
config: this.config,
|
|
540
|
-
store: this.pluginStore(),
|
|
541
|
-
client: caps.client,
|
|
542
|
-
get token() {
|
|
543
|
-
return readToken();
|
|
544
|
-
},
|
|
545
|
-
rest: caps.rest
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
542
|
registerPluginTasks() {
|
|
549
543
|
if (this.pluginTasksRegistered) return;
|
|
550
544
|
this.pluginTasksRegistered = true;
|
|
@@ -558,7 +552,7 @@ var Pluggable = class Pluggable extends _seedcord_event_emitter.TypedEventEmitte
|
|
|
558
552
|
for (const [phase, group] of groups) {
|
|
559
553
|
if (phase === 3) continue;
|
|
560
554
|
const budget = group.reduce((sum, a) => sum + require_Plugin.resolvedLifecycleSpecOf(a.instance).init.timeout, 0);
|
|
561
|
-
this.startup.addTask(phase, "
|
|
555
|
+
this.startup.addTask(phase, "plugins-init", () => this.runInits(group), budget);
|
|
562
556
|
}
|
|
563
557
|
this.registerReadyTask(groups.get(3) ?? []);
|
|
564
558
|
}
|
|
@@ -567,7 +561,7 @@ var Pluggable = class Pluggable extends _seedcord_event_emitter.TypedEventEmitte
|
|
|
567
561
|
const { key, instance } = attachment;
|
|
568
562
|
const spec = require_Plugin.resolvedLifecycleSpecOf(instance);
|
|
569
563
|
instance.logger.utils.initialization(key, "start");
|
|
570
|
-
await withTimeout(`Plugin
|
|
564
|
+
await withTimeout(`Plugin (${key})`, () => instance.init(), spec.init.timeout);
|
|
571
565
|
instance.logger.utils.initialization(key, "end");
|
|
572
566
|
this.completedInits.add(attachment);
|
|
573
567
|
if (instance.dispose) this.registerDisposeTask(spec.dispose.phase);
|
|
@@ -585,7 +579,7 @@ var Pluggable = class Pluggable extends _seedcord_event_emitter.TypedEventEmitte
|
|
|
585
579
|
}, []);
|
|
586
580
|
if (readyInits.length === 0 && steps.length === 0) return;
|
|
587
581
|
const budget = readyInits.reduce((sum, a) => sum + require_Plugin.resolvedLifecycleSpecOf(a.instance).init.timeout, 0) + steps.reduce((sum, step) => sum + step.timeout, 0);
|
|
588
|
-
this.startup.addTask(3, "
|
|
582
|
+
this.startup.addTask(3, "plugins-ready", async () => {
|
|
589
583
|
await this.runInits(readyInits);
|
|
590
584
|
for (const step of steps) await withTimeout(`Plugin:${step.key}:ready`, step.run, step.timeout);
|
|
591
585
|
}, budget);
|
|
@@ -597,7 +591,7 @@ var Pluggable = class Pluggable extends _seedcord_event_emitter.TypedEventEmitte
|
|
|
597
591
|
const spec = require_Plugin.resolvedLifecycleSpecOf(a.instance);
|
|
598
592
|
return a.instance.dispose && spec.dispose.phase === phase ? sum + spec.dispose.timeout : sum;
|
|
599
593
|
}, 0);
|
|
600
|
-
this.shutdown.addTask(phase, "
|
|
594
|
+
this.shutdown.addTask(phase, "plugins-dispose", () => this.runDisposals(phase), budget);
|
|
601
595
|
}
|
|
602
596
|
async runDisposals(phase) {
|
|
603
597
|
const failures = [];
|
|
@@ -624,22 +618,266 @@ var Pluggable = class Pluggable extends _seedcord_event_emitter.TypedEventEmitte
|
|
|
624
618
|
await this.disposeCompleted(void 0, (caught) => this.pluginLogger.warn("rollback dispose failed", caught));
|
|
625
619
|
this.completedInits.clear();
|
|
626
620
|
}
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
//#endregion
|
|
624
|
+
//#region src/node/subscribers/SubscriberLoader.ts
|
|
625
|
+
/**
|
|
626
|
+
* Loads subscribers off the filesystem into a {@link Bus} and stores their hot-reload wiring. Node
|
|
627
|
+
* only, a bundled isolate registers from the manifest instead.
|
|
628
|
+
*
|
|
629
|
+
* @internal
|
|
630
|
+
*/
|
|
631
|
+
var SubscriberLoader = class {
|
|
632
|
+
bus;
|
|
633
|
+
directory;
|
|
634
|
+
isInitialized = false;
|
|
635
|
+
hmrHandler;
|
|
636
|
+
constructor(bus, directory) {
|
|
637
|
+
this.bus = bus;
|
|
638
|
+
this.directory = directory;
|
|
639
|
+
if (!this.directory) return;
|
|
640
|
+
if (!envapt.Envapter.isDevelopment && !envapt.Envapter.isTest) return;
|
|
641
|
+
this.hmrHandler = new require_HmrModuleHandler.HmrModuleHandler({
|
|
642
|
+
handlersDir: this.directory,
|
|
643
|
+
isHandler: this.isSubscriber.bind(this),
|
|
644
|
+
registerHandler: this.registerSubscriber.bind(this),
|
|
645
|
+
unregisterHandler: this.unregisterSubscriber.bind(this),
|
|
646
|
+
getArtifacts: this.getArtifacts.bind(this),
|
|
647
|
+
logger: this.bus.logger
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
/** @internal */
|
|
651
|
+
async init() {
|
|
652
|
+
if (this.isInitialized) return;
|
|
653
|
+
this.isInitialized = true;
|
|
654
|
+
this.bus.registerDefaults();
|
|
655
|
+
const { directory } = this;
|
|
656
|
+
if (directory) {
|
|
657
|
+
this.bus.logger.info(chalk.default.bold(directory));
|
|
658
|
+
await this.load(directory);
|
|
659
|
+
this.bus.logger.utils.list([`${chalk.default.bold.magenta(this.bus.registeredCount)} subscribers`], chalk.default.bold.green("Loaded"));
|
|
660
|
+
}
|
|
661
|
+
if (!envapt.Envapter.isTest) await this.bus.verifyWebhooks();
|
|
662
|
+
}
|
|
663
|
+
/** @internal */
|
|
664
|
+
async onHmr(event) {
|
|
665
|
+
if (this.hmrHandler) await this.hmrHandler.handle(event);
|
|
666
|
+
}
|
|
667
|
+
async load(dir) {
|
|
668
|
+
await (0, _seedcord_utils_node.traverseDirectory)(dir, (fullPath, relativePath, imported) => {
|
|
669
|
+
for (const exportName of Object.keys(imported)) {
|
|
670
|
+
const value = imported[exportName];
|
|
671
|
+
if (!this.isSubscriber(value)) continue;
|
|
672
|
+
this.registerSubscriber(value);
|
|
673
|
+
this.hmrHandler?.trackHandler(fullPath, value);
|
|
674
|
+
this.bus.logger.utils.registration(value.name, relativePath);
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
registerSubscriber(ctor) {
|
|
679
|
+
this.bus.register(require_subscribers.registrationFor(ctor));
|
|
680
|
+
}
|
|
681
|
+
unregisterSubscriber(ctor, artifacts) {
|
|
682
|
+
this.bus.unregister(ctor, artifacts);
|
|
683
|
+
}
|
|
684
|
+
getArtifacts(ctor) {
|
|
685
|
+
return [Reflect.getMetadata(require_publishDefault.SubscribeMetadataKey, ctor).subscriber];
|
|
686
|
+
}
|
|
687
|
+
isSubscriber(value) {
|
|
688
|
+
if (typeof value !== "function") return false;
|
|
689
|
+
return value.prototype instanceof require_subscribers.Subscriber && Reflect.hasMetadata(require_publishDefault.SubscribeMetadataKey, value);
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
//#endregion
|
|
694
|
+
//#region src/node/commands/CommandRegistry.ts
|
|
695
|
+
function indexById(commands) {
|
|
696
|
+
return new Map(commands.map((command) => [command.id, command]));
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Scans the command directory, builds each command, and PUTs the global and guild scopes to Discord.
|
|
700
|
+
*
|
|
701
|
+
* @internal
|
|
702
|
+
*/
|
|
703
|
+
var CommandRegistry = class {
|
|
704
|
+
options;
|
|
705
|
+
logger = new _seedcord_logger.Logger("Commands", { channel: "commands" });
|
|
706
|
+
isInitialised = false;
|
|
707
|
+
globalCommands = [];
|
|
708
|
+
guildCommands = /* @__PURE__ */ new Map();
|
|
709
|
+
ctorToCommand = /* @__PURE__ */ new Map();
|
|
710
|
+
loading = false;
|
|
711
|
+
loadedCommands = [];
|
|
712
|
+
hmrHandler;
|
|
713
|
+
pendingEvents = /* @__PURE__ */ new Map();
|
|
714
|
+
constructor(options) {
|
|
715
|
+
this.options = options;
|
|
716
|
+
if (!options.dir) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CoreControllerPathMissing, ["CommandRegistry", "commands"]);
|
|
717
|
+
if (!envapt.Envapter.isDevelopment && !envapt.Envapter.isTest) return;
|
|
718
|
+
this.hmrHandler = new require_HmrModuleHandler.HmrModuleHandler({
|
|
719
|
+
handlersDir: options.dir,
|
|
720
|
+
isHandler: this.isCommandClass.bind(this),
|
|
721
|
+
registerHandler: this.registerCommand.bind(this),
|
|
722
|
+
unregisterHandler: this.unregisterCommand.bind(this),
|
|
723
|
+
getArtifacts: this.getArtifacts.bind(this),
|
|
724
|
+
logger: this.logger
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
getArtifacts(ctor) {
|
|
728
|
+
return this.ctorToCommand.get(ctor);
|
|
729
|
+
}
|
|
730
|
+
/** @internal */
|
|
731
|
+
async init() {
|
|
732
|
+
if (this.isInitialised) return;
|
|
733
|
+
this.isInitialised = true;
|
|
734
|
+
this.loading = true;
|
|
735
|
+
this.loadedCommands.length = 0;
|
|
736
|
+
try {
|
|
737
|
+
await this.loadCommands(this.options.dir);
|
|
738
|
+
} finally {
|
|
739
|
+
this.loading = false;
|
|
740
|
+
}
|
|
741
|
+
this.reportLoad();
|
|
742
|
+
require_devChannel.getDevChannel()?.on("seedcord:refresh-commands", (data) => {
|
|
743
|
+
this.refresh(data.shouldRefresh);
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
reportLoad() {
|
|
747
|
+
const { utils } = this.logger;
|
|
748
|
+
utils.summary("Loaded commands", {
|
|
749
|
+
global: this.globalCommands.length,
|
|
750
|
+
"guild groups": this.guildCommands.size
|
|
751
|
+
});
|
|
752
|
+
let slash = 0;
|
|
753
|
+
let menu = 0;
|
|
754
|
+
for (const command of this.loadedCommands) if (command.kind === "slash command") slash++;
|
|
755
|
+
else menu++;
|
|
756
|
+
utils.block("Loaded commands", [...utils.entries(this.loadedCommands), ...utils.counts({
|
|
757
|
+
"slash commands": slash,
|
|
758
|
+
"context menus": menu
|
|
759
|
+
})]);
|
|
760
|
+
}
|
|
761
|
+
/** @internal */
|
|
762
|
+
async refresh(shouldRefresh = true) {
|
|
763
|
+
if (!shouldRefresh) {
|
|
764
|
+
this.logger.info(chalk.default.italic("Command refresh cancelled."));
|
|
765
|
+
this.pendingEvents.clear();
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
this.logger.info(chalk.default.italic("Refreshing commands..."));
|
|
769
|
+
for (const event of this.pendingEvents.values()) await this.hmrHandler?.handle(event);
|
|
770
|
+
this.pendingEvents.clear();
|
|
771
|
+
await this.setCommands();
|
|
772
|
+
}
|
|
773
|
+
/** @internal */
|
|
774
|
+
async onHmr(event) {
|
|
775
|
+
if (event.file.startsWith((0, node_path.resolve)(process.cwd(), this.options.dir))) {
|
|
776
|
+
this.pendingEvents.delete(event.file);
|
|
777
|
+
this.pendingEvents.set(event.file, event);
|
|
778
|
+
require_devChannel.getDevChannel()?.send("seedcord:commands-update-prompt", { files: [...this.pendingEvents.keys()].map((f) => (0, _seedcord_utils.formatFilePath)(f)) });
|
|
779
|
+
} else await this.hmrHandler?.handle(event);
|
|
780
|
+
}
|
|
781
|
+
async loadCommands(dir) {
|
|
782
|
+
await (0, _seedcord_utils_node.traverseDirectory)(dir, (fullPath, rel, mod) => {
|
|
783
|
+
for (const exported of Object.values(mod)) if (this.isCommandClass(exported)) {
|
|
784
|
+
this.registerCommand(exported, rel);
|
|
785
|
+
this.hmrHandler?.trackHandler(fullPath, exported);
|
|
786
|
+
}
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
isCommandClass(obj) {
|
|
790
|
+
if (typeof obj !== "function") return false;
|
|
791
|
+
return obj.prototype instanceof require_publishDefault.BuilderComponent && Reflect.hasMetadata(require_publishDefault.CommandMetadataKey, obj);
|
|
792
|
+
}
|
|
793
|
+
registerCommand(ctor, rel) {
|
|
794
|
+
const meta = Reflect.getMetadata(require_publishDefault.CommandMetadataKey, ctor);
|
|
795
|
+
if (!meta) return;
|
|
796
|
+
const comp = new ctor().component;
|
|
797
|
+
const kind = comp instanceof _discordjs_builders.SlashCommandBuilder ? "slash command" : "context menu";
|
|
798
|
+
if (meta.scope === "global") this.globalCommands.push(comp);
|
|
799
|
+
else for (const g of meta.guilds) {
|
|
800
|
+
const arr = this.guildCommands.get(g) ?? [];
|
|
801
|
+
arr.push(comp);
|
|
802
|
+
this.guildCommands.set(g, arr);
|
|
803
|
+
}
|
|
804
|
+
this.ctorToCommand.set(ctor, {
|
|
805
|
+
name: comp.name,
|
|
806
|
+
scope: meta.scope,
|
|
807
|
+
...meta.scope === "guild" && { guilds: meta.guilds }
|
|
808
|
+
});
|
|
809
|
+
if (this.loading) {
|
|
810
|
+
this.loadedCommands.push({
|
|
811
|
+
name: comp.name,
|
|
812
|
+
from: (0, _seedcord_utils.formatFilePath)(rel),
|
|
813
|
+
kind
|
|
814
|
+
});
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
this.logger.utils.registration(comp.name, rel, `${meta.scope} ${kind}`);
|
|
818
|
+
}
|
|
819
|
+
unregisterCommand(ctor, artifacts) {
|
|
820
|
+
const info = artifacts ?? this.ctorToCommand.get(ctor);
|
|
821
|
+
if (!info) return;
|
|
822
|
+
if (info.scope === "global") {
|
|
823
|
+
const idx = this.globalCommands.findIndex((c) => c.name === info.name);
|
|
824
|
+
if (idx !== -1) this.globalCommands.splice(idx, 1);
|
|
825
|
+
} else for (const g of info.guilds ?? []) {
|
|
826
|
+
const arr = this.guildCommands.get(g);
|
|
827
|
+
if (arr) {
|
|
828
|
+
const idx = arr.findIndex((c) => c.name === info.name);
|
|
829
|
+
if (idx !== -1) arr.splice(idx, 1);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
this.ctorToCommand.delete(ctor);
|
|
833
|
+
}
|
|
834
|
+
/** @internal */
|
|
835
|
+
async setCommands() {
|
|
836
|
+
const result = {
|
|
837
|
+
global: /* @__PURE__ */ new Map(),
|
|
838
|
+
guilds: /* @__PURE__ */ new Map()
|
|
839
|
+
};
|
|
840
|
+
const appId = this.options.applicationId();
|
|
841
|
+
if (this.globalCommands.length > 0) {
|
|
842
|
+
result.global = indexById(await this.put(discord_api_types_v10.Routes.applicationCommands(appId), this.globalCommands));
|
|
843
|
+
const tag = this.globalCommands.length === 1 ? "command" : "commands";
|
|
844
|
+
this.logger.utils.block(`Deployed ${this.globalCommands.length} global ${tag}`, this.logger.utils.wrap(this.globalCommands.map((command) => command.name)), "info");
|
|
845
|
+
}
|
|
846
|
+
for (const [guildId, commands] of this.guildCommands.entries()) {
|
|
847
|
+
const deployed = await this.put(discord_api_types_v10.Routes.applicationGuildCommands(appId, guildId), commands);
|
|
848
|
+
result.guilds.set(guildId, indexById(deployed));
|
|
849
|
+
const tag = commands.length === 1 ? "command" : "commands";
|
|
850
|
+
this.logger.utils.block(`Deployed ${commands.length} ${tag} to ${_seedcord_logger.paint.amber.bold(guildId)}`, this.logger.utils.wrap(commands.map((command) => command.name)), "info");
|
|
851
|
+
}
|
|
852
|
+
this.options.onDeployed?.(result);
|
|
853
|
+
return result;
|
|
854
|
+
}
|
|
855
|
+
async put(route, commands) {
|
|
856
|
+
const body = commands.map((command) => command.toJSON());
|
|
857
|
+
return await this.options.rest.put(route, { body });
|
|
858
|
+
}
|
|
859
|
+
/** Every registered builder, global first. A guild command in N guilds appears once per guild. @internal */
|
|
860
|
+
allCommands() {
|
|
861
|
+
return [...this.globalCommands, ...this.guildCommands.values()].flat();
|
|
862
|
+
}
|
|
627
863
|
/** @internal */
|
|
628
|
-
|
|
629
|
-
return
|
|
864
|
+
routeLeaves() {
|
|
865
|
+
return require_slashRouteLeaves.slashRouteLeaves(this.allCommands());
|
|
630
866
|
}
|
|
631
867
|
/** @internal */
|
|
632
|
-
|
|
633
|
-
return
|
|
868
|
+
contextMenuLeaves() {
|
|
869
|
+
return require_publishDefault.contextMenuLeaves(this.allCommands());
|
|
634
870
|
}
|
|
635
871
|
};
|
|
636
872
|
|
|
637
873
|
//#endregion
|
|
874
|
+
exports.CommandRegistry = CommandRegistry;
|
|
638
875
|
exports.CoordinatedShutdown = CoordinatedShutdown;
|
|
639
876
|
exports.CoordinatedStartup = CoordinatedStartup;
|
|
640
877
|
exports.HealthCheck = HealthCheck;
|
|
641
878
|
exports.Pluggable = Pluggable;
|
|
642
879
|
exports.ShutdownPhase = require_phases.ShutdownPhase;
|
|
643
880
|
exports.StartupPhase = require_phases.StartupPhase;
|
|
881
|
+
exports.SubscriberLoader = SubscriberLoader;
|
|
644
882
|
exports.settleWithin = settleWithin;
|
|
645
883
|
//# sourceMappingURL=node-internal.index.cjs.map
|