@seedcord/core 0.1.4 → 0.2.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -5
- package/dist/{subscribers-nEpbJj3Z.mjs → Bus-DcuUtOEL.mjs} +401 -31
- package/dist/Bus-DcuUtOEL.mjs.map +1 -0
- package/dist/{HmrModuleHandler-KxRP8lqJ.mjs → HmrModuleHandler-9AUfKXRl.mjs} +2 -2
- package/dist/{HmrModuleHandler-KxRP8lqJ.mjs.map → HmrModuleHandler-9AUfKXRl.mjs.map} +1 -1
- package/dist/{Plugin-CDAV7P9l.mjs → Plugin-Bkeqcjy6.mjs} +12 -3
- package/dist/Plugin-Bkeqcjy6.mjs.map +1 -0
- package/dist/{Plugin-qRc7Ch4g.d.mts → Plugin-Cl5P7-PO.d.mts} +19 -7
- package/dist/{cursor-D207VrRo.mjs → cursor-B07ArwDz.mjs} +4 -4
- package/dist/cursor-B07ArwDz.mjs.map +1 -0
- package/dist/{cursor-C77xH5QT.d.mts → cursor-__0_F4rW.d.mts} +10 -3
- package/dist/hmr.index.mjs +1 -1
- package/dist/{index-C0k7lRDi.d.mts → index-TYnQ-ztr.d.mts} +15 -4
- package/dist/index.d.mts +24 -11
- package/dist/index.mjs +26 -6
- package/dist/index.mjs.map +1 -1
- package/dist/internal.index.d.mts +13 -18
- package/dist/internal.index.mjs +16 -48
- package/dist/internal.index.mjs.map +1 -1
- package/dist/node-internal.index.d.mts +6 -5
- package/dist/node-internal.index.mjs +54 -49
- package/dist/node-internal.index.mjs.map +1 -1
- package/dist/plugin.index.d.mts +1 -1
- package/dist/plugin.index.mjs +1 -1
- package/dist/subscribers-DuHg-bGT.mjs +3 -0
- package/package.json +25 -34
- package/dist/HmrModuleHandler-CxGOo1LT.cjs +0 -182
- package/dist/HmrModuleHandler-CxGOo1LT.cjs.map +0 -1
- package/dist/Plugin-CDAV7P9l.mjs.map +0 -1
- package/dist/Plugin-DVNh1kvX.cjs +0 -95
- package/dist/Plugin-DVNh1kvX.cjs.map +0 -1
- package/dist/cursor-D207VrRo.mjs.map +0 -1
- package/dist/cursor-DFgJ70_B.cjs +0 -1339
- package/dist/cursor-DFgJ70_B.cjs.map +0 -1
- package/dist/devChannel-Cdnmz6hd.cjs +0 -25
- package/dist/devChannel-Cdnmz6hd.cjs.map +0 -1
- package/dist/hmr.index.cjs +0 -4
- package/dist/hmr.index.d.cts +0 -1
- package/dist/index.cjs +0 -889
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -1
- package/dist/internal.index.cjs +0 -717
- package/dist/internal.index.cjs.map +0 -1
- package/dist/internal.index.d.cts +0 -1
- package/dist/node-internal.index.cjs +0 -799
- package/dist/node-internal.index.cjs.map +0 -1
- package/dist/node-internal.index.d.cts +0 -1
- package/dist/phases-8qiiLKjS.cjs +0 -42
- package/dist/phases-8qiiLKjS.cjs.map +0 -1
- package/dist/plugin.index.cjs +0 -4
- package/dist/plugin.index.d.cts +0 -1
- package/dist/publishDefault-BCrMG9T8.mjs +0 -273
- package/dist/publishDefault-BCrMG9T8.mjs.map +0 -1
- package/dist/publishDefault-D52iT8mF.cjs +0 -368
- package/dist/publishDefault-D52iT8mF.cjs.map +0 -1
- package/dist/slashRouteLeaves-HVl6Ymr0.cjs +0 -28
- package/dist/slashRouteLeaves-HVl6Ymr0.cjs.map +0 -1
- package/dist/subscribers-6x4xw39Z.cjs +0 -531
- package/dist/subscribers-6x4xw39Z.cjs.map +0 -1
- package/dist/subscribers-nEpbJj3Z.mjs.map +0 -1
|
@@ -1,799 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_subscribers = require('./subscribers-6x4xw39Z.cjs');
|
|
3
|
-
const require_publishDefault = require('./publishDefault-D52iT8mF.cjs');
|
|
4
|
-
const require_phases = require('./phases-8qiiLKjS.cjs');
|
|
5
|
-
const require_devChannel = require('./devChannel-Cdnmz6hd.cjs');
|
|
6
|
-
const require_Plugin = require('./Plugin-DVNh1kvX.cjs');
|
|
7
|
-
const require_slashRouteLeaves = require('./slashRouteLeaves-HVl6Ymr0.cjs');
|
|
8
|
-
const require_HmrModuleHandler = require('./HmrModuleHandler-CxGOo1LT.cjs');
|
|
9
|
-
let _discordjs_builders = require("@discordjs/builders");
|
|
10
|
-
let _seedcord_logger = require("@seedcord/logger");
|
|
11
|
-
let discord_api_types_v10 = require("discord-api-types/v10");
|
|
12
|
-
let _seedcord_errors = require("@seedcord/errors");
|
|
13
|
-
let _seedcord_errors_internal = require("@seedcord/errors/internal");
|
|
14
|
-
let _seedcord_utils = require("@seedcord/utils");
|
|
15
|
-
let chalk = require("chalk");
|
|
16
|
-
chalk = require_subscribers.__toESM(chalk, 1);
|
|
17
|
-
let envapt = require("envapt");
|
|
18
|
-
let node_path = require("node:path");
|
|
19
|
-
let node_http = require("node:http");
|
|
20
|
-
let _seedcord_utils_node = require("@seedcord/utils/node");
|
|
21
|
-
|
|
22
|
-
//#region src/node/Lifecycle/withTimeout.ts
|
|
23
|
-
async function raceTimer(work, timeoutMs, onTimeout) {
|
|
24
|
-
let timer;
|
|
25
|
-
try {
|
|
26
|
-
await Promise.race([work, new Promise((resolve, reject) => {
|
|
27
|
-
timer = setTimeout(() => onTimeout(resolve, reject), timeoutMs);
|
|
28
|
-
})]);
|
|
29
|
-
} finally {
|
|
30
|
-
if (timer) clearTimeout(timer);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function withTimeout(name, run, timeoutMs) {
|
|
34
|
-
return raceTimer(run(), timeoutMs, (_, reject) => {
|
|
35
|
-
reject(new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.LifecycleTaskTimeout, [name, timeoutMs]));
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
function settleWithin(work, timeoutMs) {
|
|
39
|
-
return raceTimer(work, timeoutMs, (resolve) => resolve());
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
//#endregion
|
|
43
|
-
//#region src/node/Lifecycle/CoordinatedLifecycle.ts
|
|
44
|
-
var CoordinatedLifecycle = class {
|
|
45
|
-
phaseOrder;
|
|
46
|
-
phaseEnum;
|
|
47
|
-
logger;
|
|
48
|
-
tasksMap = /* @__PURE__ */ new Map();
|
|
49
|
-
constructor(loggerName, phaseOrder, phaseEnum) {
|
|
50
|
-
this.phaseOrder = phaseOrder;
|
|
51
|
-
this.phaseEnum = phaseEnum;
|
|
52
|
-
this.logger = new _seedcord_logger.Logger(loggerName, { channel: "lifecycle" });
|
|
53
|
-
this.phaseOrder.forEach((phase) => this.tasksMap.set(phase, []));
|
|
54
|
-
}
|
|
55
|
-
addTask(phase, taskName, task, timeoutMs) {
|
|
56
|
-
if (!this.canAddTask()) return;
|
|
57
|
-
const tasks = this.tasksMap.get(phase);
|
|
58
|
-
if (!tasks) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.LifecycleUnknownPhase, [phase]);
|
|
59
|
-
tasks.push({
|
|
60
|
-
name: taskName,
|
|
61
|
-
task,
|
|
62
|
-
timeout: timeoutMs
|
|
63
|
-
});
|
|
64
|
-
this.logger.debug(`${chalk.default.italic("Added")} ${this.getTaskType()} task ${_seedcord_logger.paint.sky.bold(taskName)} to phase ${_seedcord_logger.paint.iris.bold(this.phaseEnum[phase])}`);
|
|
65
|
-
}
|
|
66
|
-
removeTask(phase, taskName) {
|
|
67
|
-
if (!this.canRemoveTask()) return false;
|
|
68
|
-
const tasks = this.tasksMap.get(phase);
|
|
69
|
-
if (!tasks) return false;
|
|
70
|
-
const initialLength = tasks.length;
|
|
71
|
-
const filteredTasks = tasks.filter((task) => task.name !== taskName);
|
|
72
|
-
this.tasksMap.set(phase, filteredTasks);
|
|
73
|
-
const removed = initialLength !== filteredTasks.length;
|
|
74
|
-
if (removed) this.logger.debug(`${chalk.default.italic("Removed")} ${this.getTaskType()} task ${_seedcord_logger.paint.sky.bold(taskName)} from phase ${_seedcord_logger.paint.iris.bold(this.phaseEnum[phase])}`);
|
|
75
|
-
return removed;
|
|
76
|
-
}
|
|
77
|
-
async runPhase(phase) {
|
|
78
|
-
const tasks = this.tasksMap.get(phase) ?? [];
|
|
79
|
-
if (tasks.length === 0) {
|
|
80
|
-
this.logger.trace(`No tasks to run in phase ${_seedcord_logger.paint.iris.bold(this.phaseEnum[phase])}`);
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
this.logger.debug(`${_seedcord_logger.paint.amber.bold("Running")} ${this.getTaskType()} phase ${_seedcord_logger.paint.iris.bold(this.phaseEnum[phase])} with ${_seedcord_logger.paint.sky.bold(String(tasks.length))} tasks`);
|
|
84
|
-
const failures = (await this.executeTasksInPhase(phase, tasks)).filter((r) => r.status === "rejected").length;
|
|
85
|
-
if (failures > 0) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.LifecyclePhaseFailures, [this.phaseEnum[phase], failures]);
|
|
86
|
-
this.logger.debug(`Phase ${_seedcord_logger.paint.iris.bold(this.phaseEnum[phase])} ${_seedcord_logger.paint.mint.bold("completed successfully")}`);
|
|
87
|
-
}
|
|
88
|
-
async runTaskWithTimeout(phase, task) {
|
|
89
|
-
this.logger.trace(`${chalk.default.italic("Starting")} task ${_seedcord_logger.paint.sky.bold(task.name)} in phase ${_seedcord_logger.paint.iris.bold(this.phaseEnum[phase])}`);
|
|
90
|
-
try {
|
|
91
|
-
await withTimeout(task.name, task.task, task.timeout);
|
|
92
|
-
this.logger.trace(`${chalk.default.italic("Completed")} task ${_seedcord_logger.paint.sky.bold(task.name)} in phase ${_seedcord_logger.paint.iris.bold(this.phaseEnum[phase])}`);
|
|
93
|
-
} catch (error) {
|
|
94
|
-
if (this.isAborted()) return;
|
|
95
|
-
this.logger.error(`${chalk.default.italic("Failed")} task ${_seedcord_logger.paint.sky.bold(task.name)} in phase ${_seedcord_logger.paint.iris.bold(this.phaseEnum[phase])}:`, error);
|
|
96
|
-
throw error;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
isAborted() {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
//#endregion
|
|
105
|
-
//#region src/node/Lifecycle/CoordinatedShutdown.ts
|
|
106
|
-
const PHASE_ORDER$1 = [
|
|
107
|
-
1,
|
|
108
|
-
2,
|
|
109
|
-
3,
|
|
110
|
-
4
|
|
111
|
-
];
|
|
112
|
-
const LOG_FLUSH_DELAY_MS = 3e3;
|
|
113
|
-
var CoordinatedShutdown = class extends CoordinatedLifecycle {
|
|
114
|
-
isShuttingDown = false;
|
|
115
|
-
hasShutdown = false;
|
|
116
|
-
exitCode = 0;
|
|
117
|
-
onSigTerm = null;
|
|
118
|
-
onSigInt = null;
|
|
119
|
-
startupGate;
|
|
120
|
-
constructor() {
|
|
121
|
-
super("Shutdown", PHASE_ORDER$1, require_phases.ShutdownPhase);
|
|
122
|
-
this.registerSignalHandlers();
|
|
123
|
-
}
|
|
124
|
-
canAddTask() {
|
|
125
|
-
return true;
|
|
126
|
-
}
|
|
127
|
-
canRemoveTask() {
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
getTaskType() {
|
|
131
|
-
return "shutdown";
|
|
132
|
-
}
|
|
133
|
-
async executeTasksInPhase(phase, tasks) {
|
|
134
|
-
const promises = tasks.map((task) => this.runTaskWithTimeout(phase, task));
|
|
135
|
-
return Promise.allSettled(promises);
|
|
136
|
-
}
|
|
137
|
-
registerSignalHandlers() {
|
|
138
|
-
this.onSigTerm = () => {
|
|
139
|
-
this.logger.info(`Received ${chalk.default.yellow.bold("SIGTERM")} signal`);
|
|
140
|
-
this.run(0);
|
|
141
|
-
};
|
|
142
|
-
this.onSigInt = () => {
|
|
143
|
-
this.logger.info(`Received ${chalk.default.yellow.bold("SIGINT")} signal`);
|
|
144
|
-
this.run(0);
|
|
145
|
-
};
|
|
146
|
-
process.on("SIGTERM", this.onSigTerm);
|
|
147
|
-
process.on("SIGINT", this.onSigInt);
|
|
148
|
-
}
|
|
149
|
-
/** @internal */
|
|
150
|
-
removeSignalHandlers() {
|
|
151
|
-
if (this.onSigTerm) {
|
|
152
|
-
process.off("SIGTERM", this.onSigTerm);
|
|
153
|
-
this.onSigTerm = null;
|
|
154
|
-
}
|
|
155
|
-
if (this.onSigInt) {
|
|
156
|
-
process.off("SIGINT", this.onSigInt);
|
|
157
|
-
this.onSigInt = null;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
/** @internal run() awaits this so boot finishes registering its dispose tasks first */
|
|
161
|
-
gateOnStartup(settled) {
|
|
162
|
-
this.startupGate = settled;
|
|
163
|
-
}
|
|
164
|
-
addTask(phase, taskName, task, timeoutMs = 5e3) {
|
|
165
|
-
super.addTask(phase, taskName, task, timeoutMs);
|
|
166
|
-
}
|
|
167
|
-
removeTask(phase, taskName) {
|
|
168
|
-
return super.removeTask(phase, taskName);
|
|
169
|
-
}
|
|
170
|
-
async run(exitCode = 0, exitProcess = true) {
|
|
171
|
-
this.removeSignalHandlers();
|
|
172
|
-
if (this.hasShutdown || this.isShuttingDown) {
|
|
173
|
-
this.logger.warn("Shutdown sequence already ran or is in progress");
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
this.isShuttingDown = true;
|
|
177
|
-
this.exitCode = exitCode;
|
|
178
|
-
this.logger.info(`${chalk.default.bold.yellow("Starting")} coordinated shutdown with exit code ${chalk.default.bold.cyan(exitCode)}`);
|
|
179
|
-
try {
|
|
180
|
-
if (this.startupGate) await this.startupGate;
|
|
181
|
-
const failures = [];
|
|
182
|
-
for (const phase of PHASE_ORDER$1) try {
|
|
183
|
-
await this.runPhase(phase);
|
|
184
|
-
} catch (error) {
|
|
185
|
-
failures.push(error);
|
|
186
|
-
}
|
|
187
|
-
if (failures.length > 0) this.logger.error(`${chalk.default.bold.red("Coordinated shutdown failed")}`, ...failures);
|
|
188
|
-
else this.logger.info(`${chalk.default.bold.green("Coordinated shutdown completed")} successfully`);
|
|
189
|
-
} finally {
|
|
190
|
-
this.hasShutdown = true;
|
|
191
|
-
if (exitProcess) {
|
|
192
|
-
this.logger.debug(`${chalk.default.bold.red("Exiting")} process with code ${chalk.default.bold.cyan(this.exitCode)}`);
|
|
193
|
-
setTimeout(() => {
|
|
194
|
-
process.exit(this.exitCode);
|
|
195
|
-
}, LOG_FLUSH_DELAY_MS);
|
|
196
|
-
} else {
|
|
197
|
-
this.logger.debug(`${chalk.default.bold.yellow("Skipping")} process exit (dev mode)`);
|
|
198
|
-
this.isShuttingDown = false;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
//#endregion
|
|
205
|
-
//#region src/node/Lifecycle/CoordinatedStartup.ts
|
|
206
|
-
const PHASE_ORDER = [
|
|
207
|
-
1,
|
|
208
|
-
2,
|
|
209
|
-
3
|
|
210
|
-
];
|
|
211
|
-
var CoordinatedStartup = class extends CoordinatedLifecycle {
|
|
212
|
-
isStartingUp = false;
|
|
213
|
-
hasStarted = false;
|
|
214
|
-
constructor() {
|
|
215
|
-
super("Startup", PHASE_ORDER, require_phases.StartupPhase);
|
|
216
|
-
}
|
|
217
|
-
addTask(phase, taskName, task, timeoutMs = 1e4) {
|
|
218
|
-
super.addTask(phase, taskName, task, timeoutMs);
|
|
219
|
-
}
|
|
220
|
-
canAddTask() {
|
|
221
|
-
if (this.hasStarted) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.LifecycleAddAfterCompletion);
|
|
222
|
-
if (this.isStartingUp) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.LifecycleAddDuringRun);
|
|
223
|
-
return true;
|
|
224
|
-
}
|
|
225
|
-
canRemoveTask() {
|
|
226
|
-
if (this.isStartingUp) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.LifecycleRemoveDuringRun);
|
|
227
|
-
return true;
|
|
228
|
-
}
|
|
229
|
-
getTaskType() {
|
|
230
|
-
return "startup";
|
|
231
|
-
}
|
|
232
|
-
async executeTasksInPhase(phase, tasks) {
|
|
233
|
-
const promises = tasks.map((task) => this.runTaskWithTimeout(phase, task));
|
|
234
|
-
return Promise.allSettled(promises);
|
|
235
|
-
}
|
|
236
|
-
async run() {
|
|
237
|
-
if (this.hasStarted) {
|
|
238
|
-
this.logger.warn("Startup sequence has already completed");
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
if (this.isStartingUp) {
|
|
242
|
-
this.logger.warn("Startup sequence already in progress");
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
this.isStartingUp = true;
|
|
246
|
-
this.logger.info(`${chalk.default.bold.green("Starting")} coordinated startup sequence`);
|
|
247
|
-
try {
|
|
248
|
-
for (const phase of PHASE_ORDER) {
|
|
249
|
-
if (!this.isStartingUp) {
|
|
250
|
-
this.logger.warn("Startup sequence aborted");
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
await this.runPhase(phase);
|
|
254
|
-
}
|
|
255
|
-
this.hasStarted = true;
|
|
256
|
-
this.logger.info(`${chalk.default.bold.green("Coordinated startup completed")} successfully`);
|
|
257
|
-
} catch (error) {
|
|
258
|
-
if (!this.isStartingUp) {
|
|
259
|
-
this.logger.warn("Startup sequence aborted during error handling");
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
this.logger.error(`${chalk.default.bold.red("Coordinated startup failed")}`);
|
|
263
|
-
throw error;
|
|
264
|
-
} finally {
|
|
265
|
-
this.isStartingUp = false;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
isAborted() {
|
|
269
|
-
return !this.isStartingUp;
|
|
270
|
-
}
|
|
271
|
-
abort() {
|
|
272
|
-
if (!this.isStartingUp) return;
|
|
273
|
-
this.isStartingUp = false;
|
|
274
|
-
this.logger.warn("Aborting coordinated startup sequence");
|
|
275
|
-
}
|
|
276
|
-
get isReady() {
|
|
277
|
-
return this.hasStarted;
|
|
278
|
-
}
|
|
279
|
-
get isRunning() {
|
|
280
|
-
return this.isStartingUp;
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
//#endregion
|
|
285
|
-
//#region src/node/HealthResponder.ts
|
|
286
|
-
const HTTP_OK = 200;
|
|
287
|
-
const DEFAULT_HEALTH_CHECK_PATH = "/health";
|
|
288
|
-
var HealthResponder = class {
|
|
289
|
-
path;
|
|
290
|
-
constructor(path) {
|
|
291
|
-
this.path = path ?? DEFAULT_HEALTH_CHECK_PATH;
|
|
292
|
-
}
|
|
293
|
-
tryRespond(req, res) {
|
|
294
|
-
if (req.method !== "GET" || req.url !== this.path) return false;
|
|
295
|
-
res.writeHead(HTTP_OK, { "Content-Type": "application/json" });
|
|
296
|
-
res.end(JSON.stringify({
|
|
297
|
-
status: "ok",
|
|
298
|
-
timestamp: Date.now()
|
|
299
|
-
}));
|
|
300
|
-
return true;
|
|
301
|
-
}
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
//#endregion
|
|
305
|
-
//#region src/node/HealthCheck.ts
|
|
306
|
-
const HTTP_NOT_FOUND = 404;
|
|
307
|
-
const DEFAULT_HEALTH_CHECK_PORT = 6967;
|
|
308
|
-
var HealthCheck = class HealthCheck {
|
|
309
|
-
logger = new _seedcord_logger.Logger("HealthCheck", { channel: "health" });
|
|
310
|
-
port;
|
|
311
|
-
host;
|
|
312
|
-
responder;
|
|
313
|
-
server;
|
|
314
|
-
constructor(shutdown, options) {
|
|
315
|
-
this.port = options?.port ?? DEFAULT_HEALTH_CHECK_PORT;
|
|
316
|
-
this.host = options?.host;
|
|
317
|
-
this.responder = new HealthResponder(options?.path);
|
|
318
|
-
shutdown.addTask(2, "stop-healthcheck-server", () => this.stop());
|
|
319
|
-
}
|
|
320
|
-
get path() {
|
|
321
|
-
return this.responder.path;
|
|
322
|
-
}
|
|
323
|
-
static fromOption(shutdown, option) {
|
|
324
|
-
if (option === false) return void 0;
|
|
325
|
-
return new HealthCheck(shutdown, typeof option === "object" ? option : void 0);
|
|
326
|
-
}
|
|
327
|
-
async init() {
|
|
328
|
-
return new Promise((resolve, reject) => {
|
|
329
|
-
const server = (0, node_http.createServer)((req, res) => {
|
|
330
|
-
if (this.responder.tryRespond(req, res)) return;
|
|
331
|
-
res.writeHead(HTTP_NOT_FOUND, { "Content-Type": "application/json" });
|
|
332
|
-
res.end(JSON.stringify({ status: "not found" }));
|
|
333
|
-
});
|
|
334
|
-
this.server = server;
|
|
335
|
-
const onListenError = (err) => reject(err);
|
|
336
|
-
server.on("error", onListenError);
|
|
337
|
-
server.once("listening", () => {
|
|
338
|
-
server.removeListener("error", onListenError);
|
|
339
|
-
server.on("error", (err) => this.logger.error("Health check server error", err));
|
|
340
|
-
const address = this.host ?? "localhost";
|
|
341
|
-
this.logger.info(`${_seedcord_logger.paint.mint.bold("✔︎")} Health check server listening on ${_seedcord_logger.paint.sky(`http://${address}:${this.port}${this.path}`)}`);
|
|
342
|
-
resolve();
|
|
343
|
-
});
|
|
344
|
-
if (this.host) {
|
|
345
|
-
this.logger.debug(`Binding health check server to ${this.host}`);
|
|
346
|
-
server.listen(this.port, this.host);
|
|
347
|
-
} else {
|
|
348
|
-
this.logger.debug("Binding health check server to all interfaces");
|
|
349
|
-
server.listen(this.port);
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
stop() {
|
|
354
|
-
const server = this.server;
|
|
355
|
-
if (!server?.listening) return Promise.resolve();
|
|
356
|
-
return new Promise((resolve, reject) => {
|
|
357
|
-
server.close((err) => {
|
|
358
|
-
if (err) {
|
|
359
|
-
reject(err);
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
this.logger.info(_seedcord_logger.paint.coral.bold("Health check server stopped"));
|
|
363
|
-
resolve();
|
|
364
|
-
});
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
//#endregion
|
|
370
|
-
//#region src/node/Pluggable.ts
|
|
371
|
-
const RESERVED_KEYS = new Set(_seedcord_logger.FRAMEWORK_CHANNELS);
|
|
372
|
-
/**
|
|
373
|
-
* Base class for a plugin host, a transport `Seedcord` class.
|
|
374
|
-
*
|
|
375
|
-
* Plugins are attached during configuration and initialized during startup, sequentially in attach
|
|
376
|
-
* order within each phase.
|
|
377
|
-
*/
|
|
378
|
-
var Pluggable = class Pluggable {
|
|
379
|
-
/** @see {@link CoordinatedShutdown} */
|
|
380
|
-
shutdown;
|
|
381
|
-
/** @see {@link CoordinatedStartup} */
|
|
382
|
-
startup;
|
|
383
|
-
isInitialized = false;
|
|
384
|
-
startFailed = false;
|
|
385
|
-
plugins = [];
|
|
386
|
-
pluginLogger = new _seedcord_logger.Logger("Plugins", { channel: "plugins" });
|
|
387
|
-
attachments = [];
|
|
388
|
-
completedInits = /* @__PURE__ */ new Set();
|
|
389
|
-
disposePhases = /* @__PURE__ */ new Set();
|
|
390
|
-
pluginTasksRegistered = false;
|
|
391
|
-
static isInstantiated = false;
|
|
392
|
-
static liveShutdown;
|
|
393
|
-
constructor(shutdown, startup) {
|
|
394
|
-
if (Pluggable.isInstantiated) {
|
|
395
|
-
shutdown.removeSignalHandlers();
|
|
396
|
-
throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CoreSingletonViolation);
|
|
397
|
-
}
|
|
398
|
-
Pluggable.isInstantiated = true;
|
|
399
|
-
Pluggable.liveShutdown = shutdown;
|
|
400
|
-
this.shutdown = shutdown;
|
|
401
|
-
this.startup = startup;
|
|
402
|
-
}
|
|
403
|
-
/** @internal */
|
|
404
|
-
async init() {
|
|
405
|
-
if (this.isInitialized) return this;
|
|
406
|
-
if (this.startFailed) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.LifecycleRestartAfterFailure);
|
|
407
|
-
this.registerPluginTasks();
|
|
408
|
-
const startupSettled = Promise.withResolvers();
|
|
409
|
-
this.shutdown.gateOnStartup(startupSettled.promise);
|
|
410
|
-
try {
|
|
411
|
-
await this.startup.run();
|
|
412
|
-
} catch (caught) {
|
|
413
|
-
await this.rollback();
|
|
414
|
-
throw caught;
|
|
415
|
-
} finally {
|
|
416
|
-
startupSettled.resolve();
|
|
417
|
-
}
|
|
418
|
-
this.isInitialized = true;
|
|
419
|
-
return this;
|
|
420
|
-
}
|
|
421
|
-
/** @internal codegen reads these to emit the `Core` augmentation */
|
|
422
|
-
get pluginKeys() {
|
|
423
|
-
return this.attachments.map((attachment) => attachment.key);
|
|
424
|
-
}
|
|
425
|
-
/** @internal so the next host can construct */
|
|
426
|
-
static reset() {
|
|
427
|
-
Pluggable.liveShutdown?.removeSignalHandlers();
|
|
428
|
-
Pluggable.liveShutdown = void 0;
|
|
429
|
-
Pluggable.isInstantiated = false;
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Attaches a plugin to this instance.
|
|
433
|
-
*
|
|
434
|
-
* The plugin initializes during startup, after every plugin attached before it, and becomes
|
|
435
|
-
* available as a property on `core`. `seedcord codegen` writes the `Core` augmentation that
|
|
436
|
-
* types it.
|
|
437
|
-
*
|
|
438
|
-
* A plugin declaring a `transport` or `runtime` this host does not run is a compile error on
|
|
439
|
-
* this call. An edge host takes no plugins at all. A plugin constructor narrowing its first
|
|
440
|
-
* parameter past `CoreBase` is a compile error here too. Read the transport `Core` off `this.core`.
|
|
441
|
-
*
|
|
442
|
-
* @typeParam Key - The property name for accessing the plugin
|
|
443
|
-
* @typeParam Ctor - The plugin constructor type
|
|
444
|
-
* @param key - Property name to access the plugin instance
|
|
445
|
-
* @param Plugin - Plugin constructor class
|
|
446
|
-
* @param args - Additional arguments to pass to the plugin constructor
|
|
447
|
-
* @returns This instance with the plugin attached as a typed property
|
|
448
|
-
* @throws A **SeedcordError** When called after initialization or if key already exists or is reserved
|
|
449
|
-
* @example
|
|
450
|
-
* ```typescript
|
|
451
|
-
* seedcord.attach('db', Mongoose, { uri: 'mongodb://...', name: 'seedcord', dir: ... })
|
|
452
|
-
* ```
|
|
453
|
-
*/
|
|
454
|
-
attach(key, Plugin, ...args) {
|
|
455
|
-
if (this.isInitialized) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CorePluginAfterInit);
|
|
456
|
-
if (RESERVED_KEYS.has(key)) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CorePluginReservedChannel, [key]);
|
|
457
|
-
if (key in this) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CorePluginKeyExists, [key]);
|
|
458
|
-
const instance = new Plugin(this, ...args);
|
|
459
|
-
instance.logger.setChannel(key);
|
|
460
|
-
this.plugins.push(instance);
|
|
461
|
-
this.attachments.push({
|
|
462
|
-
key,
|
|
463
|
-
instance
|
|
464
|
-
});
|
|
465
|
-
return Object.assign(this, { [key]: instance });
|
|
466
|
-
}
|
|
467
|
-
registerPluginTasks() {
|
|
468
|
-
if (this.pluginTasksRegistered) return;
|
|
469
|
-
this.pluginTasksRegistered = true;
|
|
470
|
-
const groups = /* @__PURE__ */ new Map();
|
|
471
|
-
for (const attachment of this.attachments) {
|
|
472
|
-
const phase = require_Plugin.resolvedLifecycleSpecOf(attachment.instance).init.phase;
|
|
473
|
-
const group = groups.get(phase) ?? [];
|
|
474
|
-
group.push(attachment);
|
|
475
|
-
groups.set(phase, group);
|
|
476
|
-
}
|
|
477
|
-
for (const [phase, group] of groups) {
|
|
478
|
-
if (phase === 3) continue;
|
|
479
|
-
const budget = group.reduce((sum, a) => sum + require_Plugin.resolvedLifecycleSpecOf(a.instance).init.timeout, 0);
|
|
480
|
-
this.startup.addTask(phase, "plugins-init", () => this.runInits(group), budget);
|
|
481
|
-
}
|
|
482
|
-
this.registerReadyTask(groups.get(3) ?? []);
|
|
483
|
-
}
|
|
484
|
-
async runInits(group) {
|
|
485
|
-
for (const attachment of group) {
|
|
486
|
-
const { key, instance } = attachment;
|
|
487
|
-
const spec = require_Plugin.resolvedLifecycleSpecOf(instance);
|
|
488
|
-
instance.logger.utils.initialization(key, "start");
|
|
489
|
-
await withTimeout(`Plugin (${key})`, () => instance.init(), spec.init.timeout);
|
|
490
|
-
instance.logger.utils.initialization(key, "end");
|
|
491
|
-
this.completedInits.add(attachment);
|
|
492
|
-
if (instance.dispose) this.registerDisposeTask(spec.dispose.phase);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
registerReadyTask(readyInits) {
|
|
496
|
-
const steps = this.attachments.reduce((acc, a) => {
|
|
497
|
-
const ready = a.instance.ready?.bind(a.instance);
|
|
498
|
-
if (ready) acc.push({
|
|
499
|
-
key: a.key,
|
|
500
|
-
run: ready,
|
|
501
|
-
timeout: require_Plugin.resolvedLifecycleSpecOf(a.instance).ready.timeout
|
|
502
|
-
});
|
|
503
|
-
return acc;
|
|
504
|
-
}, []);
|
|
505
|
-
if (readyInits.length === 0 && steps.length === 0) return;
|
|
506
|
-
const budget = readyInits.reduce((sum, a) => sum + require_Plugin.resolvedLifecycleSpecOf(a.instance).init.timeout, 0) + steps.reduce((sum, step) => sum + step.timeout, 0);
|
|
507
|
-
this.startup.addTask(3, "plugins-ready", async () => {
|
|
508
|
-
await this.runInits(readyInits);
|
|
509
|
-
for (const step of steps) await withTimeout(`Plugin:${step.key}:ready`, step.run, step.timeout);
|
|
510
|
-
}, budget);
|
|
511
|
-
}
|
|
512
|
-
registerDisposeTask(phase) {
|
|
513
|
-
if (this.disposePhases.has(phase)) return;
|
|
514
|
-
this.disposePhases.add(phase);
|
|
515
|
-
const budget = this.attachments.reduce((sum, a) => {
|
|
516
|
-
const spec = require_Plugin.resolvedLifecycleSpecOf(a.instance);
|
|
517
|
-
return a.instance.dispose && spec.dispose.phase === phase ? sum + spec.dispose.timeout : sum;
|
|
518
|
-
}, 0);
|
|
519
|
-
this.shutdown.addTask(phase, "plugins-dispose", () => this.runDisposals(phase), budget);
|
|
520
|
-
}
|
|
521
|
-
async runDisposals(phase) {
|
|
522
|
-
const failures = [];
|
|
523
|
-
await this.disposeCompleted(phase, (caught) => failures.push(caught));
|
|
524
|
-
if (failures.length === 1) throw failures[0];
|
|
525
|
-
if (failures.length > 1) throw new AggregateError(failures, "plugin dispose failures");
|
|
526
|
-
}
|
|
527
|
-
async disposeCompleted(phase, onError) {
|
|
528
|
-
for (const attachment of [...this.attachments].reverse()) {
|
|
529
|
-
if (!this.completedInits.has(attachment)) continue;
|
|
530
|
-
const dispose = attachment.instance.dispose?.bind(attachment.instance);
|
|
531
|
-
if (!dispose) continue;
|
|
532
|
-
const spec = require_Plugin.resolvedLifecycleSpecOf(attachment.instance);
|
|
533
|
-
if (phase !== void 0 && spec.dispose.phase !== phase) continue;
|
|
534
|
-
try {
|
|
535
|
-
await withTimeout(`Plugin:${attachment.key}:dispose`, dispose, spec.dispose.timeout);
|
|
536
|
-
} catch (caught) {
|
|
537
|
-
onError(caught);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
async rollback() {
|
|
542
|
-
this.startFailed = true;
|
|
543
|
-
await this.disposeCompleted(void 0, (caught) => this.pluginLogger.warn("rollback dispose failed", caught));
|
|
544
|
-
this.completedInits.clear();
|
|
545
|
-
}
|
|
546
|
-
};
|
|
547
|
-
|
|
548
|
-
//#endregion
|
|
549
|
-
//#region src/node/subscribers/SubscriberLoader.ts
|
|
550
|
-
var SubscriberLoader = class {
|
|
551
|
-
bus;
|
|
552
|
-
directory;
|
|
553
|
-
isInitialized = false;
|
|
554
|
-
hmrHandler;
|
|
555
|
-
constructor(bus, directory) {
|
|
556
|
-
this.bus = bus;
|
|
557
|
-
this.directory = directory;
|
|
558
|
-
if (!this.directory) return;
|
|
559
|
-
if (!envapt.Envapter.isDevelopment && !envapt.Envapter.isTest) return;
|
|
560
|
-
this.hmrHandler = new require_HmrModuleHandler.HmrModuleHandler({
|
|
561
|
-
handlersDir: this.directory,
|
|
562
|
-
isHandler: this.isSubscriber.bind(this),
|
|
563
|
-
registerHandler: this.registerSubscriber.bind(this),
|
|
564
|
-
unregisterHandler: this.unregisterSubscriber.bind(this),
|
|
565
|
-
getArtifacts: this.getArtifacts.bind(this),
|
|
566
|
-
logger: this.bus.logger
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
/** @internal */
|
|
570
|
-
async init() {
|
|
571
|
-
if (this.isInitialized) return;
|
|
572
|
-
this.isInitialized = true;
|
|
573
|
-
this.bus.registerDefaults();
|
|
574
|
-
const { directory } = this;
|
|
575
|
-
if (directory) {
|
|
576
|
-
this.bus.logger.debug(chalk.default.bold(directory));
|
|
577
|
-
await this.load(directory);
|
|
578
|
-
this.bus.logger.utils.list([`${chalk.default.bold.magenta(this.bus.registeredCount)} subscribers`], chalk.default.bold.green("Loaded"), "debug");
|
|
579
|
-
}
|
|
580
|
-
if (!envapt.Envapter.isTest) await this.bus.verifyWebhooks();
|
|
581
|
-
}
|
|
582
|
-
/** @internal */
|
|
583
|
-
async onHmr(event) {
|
|
584
|
-
if (this.hmrHandler) await this.hmrHandler.handle(event);
|
|
585
|
-
}
|
|
586
|
-
async load(dir) {
|
|
587
|
-
await (0, _seedcord_utils_node.traverseDirectory)(dir, (fullPath, relativePath, imported) => {
|
|
588
|
-
for (const exportName of Object.keys(imported)) {
|
|
589
|
-
const value = imported[exportName];
|
|
590
|
-
if (!this.isSubscriber(value)) continue;
|
|
591
|
-
this.registerSubscriber(value);
|
|
592
|
-
this.hmrHandler?.trackHandler(fullPath, value);
|
|
593
|
-
this.bus.logger.utils.registration(value.name, relativePath, void 0, "trace");
|
|
594
|
-
}
|
|
595
|
-
});
|
|
596
|
-
}
|
|
597
|
-
registerSubscriber(ctor) {
|
|
598
|
-
this.bus.register(require_subscribers.registrationFor(ctor));
|
|
599
|
-
}
|
|
600
|
-
unregisterSubscriber(ctor, artifacts) {
|
|
601
|
-
this.bus.unregister(ctor, artifacts);
|
|
602
|
-
}
|
|
603
|
-
getArtifacts(ctor) {
|
|
604
|
-
return [Reflect.getMetadata(require_publishDefault.SubscribeMetadataKey, ctor).subscriber];
|
|
605
|
-
}
|
|
606
|
-
isSubscriber(value) {
|
|
607
|
-
if (typeof value !== "function") return false;
|
|
608
|
-
return value.prototype instanceof require_subscribers.Subscriber && Reflect.hasMetadata(require_publishDefault.SubscribeMetadataKey, value);
|
|
609
|
-
}
|
|
610
|
-
};
|
|
611
|
-
|
|
612
|
-
//#endregion
|
|
613
|
-
//#region src/node/commands/CommandRegistry.ts
|
|
614
|
-
function indexById(commands) {
|
|
615
|
-
return new Map(commands.map((command) => [command.id, command]));
|
|
616
|
-
}
|
|
617
|
-
/**
|
|
618
|
-
* Scans the command directory, builds each command, and PUTs the global and guild scopes to Discord.
|
|
619
|
-
*
|
|
620
|
-
* @internal
|
|
621
|
-
*/
|
|
622
|
-
var CommandRegistry = class {
|
|
623
|
-
options;
|
|
624
|
-
logger = new _seedcord_logger.Logger("Commands", { channel: "commands" });
|
|
625
|
-
isInitialised = false;
|
|
626
|
-
globalCommands = [];
|
|
627
|
-
guildCommands = /* @__PURE__ */ new Map();
|
|
628
|
-
ctorToCommand = /* @__PURE__ */ new Map();
|
|
629
|
-
loading = false;
|
|
630
|
-
loadedCommands = [];
|
|
631
|
-
hmrHandler;
|
|
632
|
-
pendingEvents = /* @__PURE__ */ new Map();
|
|
633
|
-
constructor(options) {
|
|
634
|
-
this.options = options;
|
|
635
|
-
if (!options.dir) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CoreControllerPathMissing, ["CommandRegistry", "commands"]);
|
|
636
|
-
if (!envapt.Envapter.isDevelopment && !envapt.Envapter.isTest) return;
|
|
637
|
-
this.hmrHandler = new require_HmrModuleHandler.HmrModuleHandler({
|
|
638
|
-
handlersDir: options.dir,
|
|
639
|
-
isHandler: this.isCommandClass.bind(this),
|
|
640
|
-
registerHandler: this.registerCommand.bind(this),
|
|
641
|
-
unregisterHandler: this.unregisterCommand.bind(this),
|
|
642
|
-
getArtifacts: this.getArtifacts.bind(this),
|
|
643
|
-
logger: this.logger
|
|
644
|
-
});
|
|
645
|
-
}
|
|
646
|
-
getArtifacts(ctor) {
|
|
647
|
-
return this.ctorToCommand.get(ctor);
|
|
648
|
-
}
|
|
649
|
-
/** @internal */
|
|
650
|
-
async init() {
|
|
651
|
-
if (this.isInitialised) return;
|
|
652
|
-
this.isInitialised = true;
|
|
653
|
-
this.loading = true;
|
|
654
|
-
this.loadedCommands.length = 0;
|
|
655
|
-
try {
|
|
656
|
-
await this.loadCommands(this.options.dir);
|
|
657
|
-
} finally {
|
|
658
|
-
this.loading = false;
|
|
659
|
-
}
|
|
660
|
-
this.reportLoad();
|
|
661
|
-
require_devChannel.getDevChannel()?.on("seedcord:refresh-commands", (data) => {
|
|
662
|
-
this.refresh(data.shouldRefresh);
|
|
663
|
-
});
|
|
664
|
-
}
|
|
665
|
-
reportLoad() {
|
|
666
|
-
const { utils } = this.logger;
|
|
667
|
-
utils.summary("Loaded commands", {
|
|
668
|
-
global: this.globalCommands.length,
|
|
669
|
-
"guild groups": this.guildCommands.size
|
|
670
|
-
}, "debug");
|
|
671
|
-
let slash = 0;
|
|
672
|
-
let menu = 0;
|
|
673
|
-
for (const command of this.loadedCommands) if (command.kind === "slash command") slash++;
|
|
674
|
-
else menu++;
|
|
675
|
-
utils.block("Loaded commands", [...utils.entries(this.loadedCommands), ...utils.counts({
|
|
676
|
-
"slash commands": slash,
|
|
677
|
-
"context menus": menu
|
|
678
|
-
})], "debug");
|
|
679
|
-
}
|
|
680
|
-
/** @internal */
|
|
681
|
-
async refresh(shouldRefresh = true) {
|
|
682
|
-
if (!shouldRefresh) {
|
|
683
|
-
this.logger.debug(chalk.default.italic("Command refresh cancelled."));
|
|
684
|
-
this.pendingEvents.clear();
|
|
685
|
-
return;
|
|
686
|
-
}
|
|
687
|
-
this.logger.debug(chalk.default.italic("Refreshing commands..."));
|
|
688
|
-
for (const event of this.pendingEvents.values()) await this.hmrHandler?.handle(event);
|
|
689
|
-
this.pendingEvents.clear();
|
|
690
|
-
await this.setCommands();
|
|
691
|
-
}
|
|
692
|
-
/** @internal */
|
|
693
|
-
async onHmr(event) {
|
|
694
|
-
if (event.file.startsWith((0, node_path.resolve)(process.cwd(), this.options.dir))) {
|
|
695
|
-
this.pendingEvents.delete(event.file);
|
|
696
|
-
this.pendingEvents.set(event.file, event);
|
|
697
|
-
require_devChannel.getDevChannel()?.send("seedcord:commands-update-prompt", { files: [...this.pendingEvents.keys()].map((f) => (0, _seedcord_utils.formatFilePath)(f)) });
|
|
698
|
-
} else await this.hmrHandler?.handle(event);
|
|
699
|
-
}
|
|
700
|
-
async loadCommands(dir) {
|
|
701
|
-
await (0, _seedcord_utils_node.traverseDirectory)(dir, (fullPath, rel, mod) => {
|
|
702
|
-
for (const exported of Object.values(mod)) if (this.isCommandClass(exported)) {
|
|
703
|
-
this.registerCommand(exported, rel);
|
|
704
|
-
this.hmrHandler?.trackHandler(fullPath, exported);
|
|
705
|
-
}
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
isCommandClass(obj) {
|
|
709
|
-
if (typeof obj !== "function") return false;
|
|
710
|
-
return obj.prototype instanceof require_publishDefault.BuilderComponent && Reflect.hasMetadata(require_publishDefault.CommandMetadataKey, obj);
|
|
711
|
-
}
|
|
712
|
-
registerCommand(ctor, rel) {
|
|
713
|
-
const meta = Reflect.getMetadata(require_publishDefault.CommandMetadataKey, ctor);
|
|
714
|
-
if (!meta) return;
|
|
715
|
-
const comp = new ctor().component;
|
|
716
|
-
const kind = comp instanceof _discordjs_builders.SlashCommandBuilder ? "slash command" : "context menu";
|
|
717
|
-
if (meta.scope === "global") this.globalCommands.push(comp);
|
|
718
|
-
else for (const g of meta.guilds) {
|
|
719
|
-
const arr = this.guildCommands.get(g) ?? [];
|
|
720
|
-
arr.push(comp);
|
|
721
|
-
this.guildCommands.set(g, arr);
|
|
722
|
-
}
|
|
723
|
-
this.ctorToCommand.set(ctor, {
|
|
724
|
-
name: comp.name,
|
|
725
|
-
scope: meta.scope,
|
|
726
|
-
...meta.scope === "guild" && { guilds: meta.guilds }
|
|
727
|
-
});
|
|
728
|
-
if (this.loading) this.loadedCommands.push({
|
|
729
|
-
name: comp.name,
|
|
730
|
-
from: (0, _seedcord_utils.formatFilePath)(rel),
|
|
731
|
-
kind
|
|
732
|
-
});
|
|
733
|
-
}
|
|
734
|
-
unregisterCommand(ctor, artifacts) {
|
|
735
|
-
const info = artifacts ?? this.ctorToCommand.get(ctor);
|
|
736
|
-
if (!info) return;
|
|
737
|
-
if (info.scope === "global") {
|
|
738
|
-
const idx = this.globalCommands.findIndex((c) => c.name === info.name);
|
|
739
|
-
if (idx !== -1) this.globalCommands.splice(idx, 1);
|
|
740
|
-
} else for (const g of info.guilds ?? []) {
|
|
741
|
-
const arr = this.guildCommands.get(g);
|
|
742
|
-
if (arr) {
|
|
743
|
-
const idx = arr.findIndex((c) => c.name === info.name);
|
|
744
|
-
if (idx !== -1) arr.splice(idx, 1);
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
this.ctorToCommand.delete(ctor);
|
|
748
|
-
}
|
|
749
|
-
/** @internal */
|
|
750
|
-
async setCommands() {
|
|
751
|
-
const result = {
|
|
752
|
-
global: /* @__PURE__ */ new Map(),
|
|
753
|
-
guilds: /* @__PURE__ */ new Map()
|
|
754
|
-
};
|
|
755
|
-
const appId = this.options.applicationId();
|
|
756
|
-
if (this.globalCommands.length > 0) {
|
|
757
|
-
result.global = indexById(await this.put(discord_api_types_v10.Routes.applicationCommands(appId), this.globalCommands));
|
|
758
|
-
const tag = this.globalCommands.length === 1 ? "command" : "commands";
|
|
759
|
-
this.logger.utils.block(`Deployed ${this.globalCommands.length} global ${tag}`, this.logger.utils.wrap(this.globalCommands.map((command) => command.name)), "info");
|
|
760
|
-
}
|
|
761
|
-
for (const [guildId, commands] of this.guildCommands.entries()) {
|
|
762
|
-
const deployed = await this.put(discord_api_types_v10.Routes.applicationGuildCommands(appId, guildId), commands);
|
|
763
|
-
result.guilds.set(guildId, indexById(deployed));
|
|
764
|
-
const tag = commands.length === 1 ? "command" : "commands";
|
|
765
|
-
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");
|
|
766
|
-
}
|
|
767
|
-
this.options.onDeployed?.(result);
|
|
768
|
-
return result;
|
|
769
|
-
}
|
|
770
|
-
async put(route, commands) {
|
|
771
|
-
const body = commands.map((command) => command.toJSON());
|
|
772
|
-
return await this.options.rest.put(route, { body });
|
|
773
|
-
}
|
|
774
|
-
/** Every registered builder, global first. A guild command in N guilds appears once per guild. @internal */
|
|
775
|
-
allCommands() {
|
|
776
|
-
return [...this.globalCommands, ...this.guildCommands.values()].flat();
|
|
777
|
-
}
|
|
778
|
-
/** @internal */
|
|
779
|
-
routeLeaves() {
|
|
780
|
-
return require_slashRouteLeaves.slashRouteLeaves(this.allCommands());
|
|
781
|
-
}
|
|
782
|
-
/** @internal */
|
|
783
|
-
contextMenuLeaves() {
|
|
784
|
-
return require_publishDefault.contextMenuLeaves(this.allCommands());
|
|
785
|
-
}
|
|
786
|
-
};
|
|
787
|
-
|
|
788
|
-
//#endregion
|
|
789
|
-
exports.CommandRegistry = CommandRegistry;
|
|
790
|
-
exports.CoordinatedShutdown = CoordinatedShutdown;
|
|
791
|
-
exports.CoordinatedStartup = CoordinatedStartup;
|
|
792
|
-
exports.HealthCheck = HealthCheck;
|
|
793
|
-
exports.HealthResponder = HealthResponder;
|
|
794
|
-
exports.Pluggable = Pluggable;
|
|
795
|
-
exports.ShutdownPhase = require_phases.ShutdownPhase;
|
|
796
|
-
exports.StartupPhase = require_phases.StartupPhase;
|
|
797
|
-
exports.SubscriberLoader = SubscriberLoader;
|
|
798
|
-
exports.settleWithin = settleWithin;
|
|
799
|
-
//# sourceMappingURL=node-internal.index.cjs.map
|