@seedcord/core 0.1.0-next.5 → 0.1.0-next.7
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/{AutocompleteOptions-eB87SZ4a.d.mts → AutocompleteOptions-DLp_B8as.d.mts} +66 -124
- 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-3rlH0uxH.d.mts +620 -0
- package/dist/Plugin-Cgp1a0uQ.cjs +123 -0
- package/dist/Plugin-Cgp1a0uQ.cjs.map +1 -0
- package/dist/Plugin-j9GYdroS.mjs +106 -0
- package/dist/Plugin-j9GYdroS.mjs.map +1 -0
- package/dist/{permissions-DQL5ViZn.cjs → Silence-DiP95iwD.cjs} +54 -305
- package/dist/Silence-DiP95iwD.cjs.map +1 -0
- package/dist/{permissions-SokZLJMj.mjs → Silence-dbC2slOB.mjs} +47 -238
- package/dist/Silence-dbC2slOB.mjs.map +1 -0
- package/dist/basic-D7bDlgSP.d.mts +10 -0
- package/dist/devChannel-CQU7hq7Q.mjs +14 -0
- package/dist/devChannel-CQU7hq7Q.mjs.map +1 -0
- package/dist/devChannel-CoCmAVDx.cjs +26 -0
- package/dist/devChannel-CoCmAVDx.cjs.map +1 -0
- package/dist/hmr.index.cjs +2 -164
- package/dist/hmr.index.mjs +2 -162
- package/dist/index-Dueqztyy.d.mts +142 -0
- package/dist/index.cjs +53 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +7 -4
- package/dist/index.mjs +9 -35
- package/dist/index.mjs.map +1 -1
- package/dist/internal.index.cjs +267 -89
- package/dist/internal.index.cjs.map +1 -1
- package/dist/internal.index.d.mts +68 -3
- package/dist/internal.index.mjs +218 -48
- package/dist/internal.index.mjs.map +1 -1
- package/dist/node-internal.index.cjs +716 -0
- package/dist/node-internal.index.cjs.map +1 -0
- package/dist/node-internal.index.d.cts +1 -0
- package/dist/node-internal.index.d.mts +261 -0
- package/dist/node-internal.index.mjs +706 -0
- package/dist/node-internal.index.mjs.map +1 -0
- package/dist/phases-BfpAG6w3.mjs +31 -0
- package/dist/phases-BfpAG6w3.mjs.map +1 -0
- package/dist/phases-C_BGNyVo.cjs +43 -0
- package/dist/phases-C_BGNyVo.cjs.map +1 -0
- package/dist/plugin.index.cjs +4 -0
- package/dist/plugin.index.d.cts +1 -0
- package/dist/plugin.index.d.mts +3 -0
- package/dist/plugin.index.mjs +3 -0
- package/dist/publishDefault-CCf1azzW.mjs +264 -0
- package/dist/publishDefault-CCf1azzW.mjs.map +1 -0
- package/dist/publishDefault-l0NQ-SHo.cjs +353 -0
- package/dist/publishDefault-l0NQ-SHo.cjs.map +1 -0
- package/dist/subscribers-B1G6_LlK.cjs +517 -0
- package/dist/subscribers-B1G6_LlK.cjs.map +1 -0
- package/dist/subscribers-DYqFVP1X.mjs +480 -0
- package/dist/subscribers-DYqFVP1X.mjs.map +1 -0
- package/package.json +25 -13
- 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/node.index.cjs +0 -521
- package/dist/node.index.cjs.map +0 -1
- package/dist/node.index.d.cts +0 -1
- package/dist/node.index.d.mts +0 -2391
- package/dist/node.index.mjs +0 -513
- package/dist/node.index.mjs.map +0 -1
- package/dist/permissions-DQL5ViZn.cjs.map +0 -1
- package/dist/permissions-SokZLJMj.mjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const
|
|
2
|
+
const require_publishDefault = require('./publishDefault-l0NQ-SHo.cjs');
|
|
3
|
+
const require_Silence = require('./Silence-DiP95iwD.cjs');
|
|
4
|
+
const require_phases = require('./phases-C_BGNyVo.cjs');
|
|
5
|
+
const require_subscribers = require('./subscribers-B1G6_LlK.cjs');
|
|
3
6
|
require("reflect-metadata");
|
|
4
7
|
let _seedcord_errors = require("@seedcord/errors");
|
|
5
8
|
let _seedcord_errors_internal = require("@seedcord/errors/internal");
|
|
@@ -9,7 +12,7 @@ let _seedcord_utils = require("@seedcord/utils");
|
|
|
9
12
|
//#region src/decorators/Command.ts
|
|
10
13
|
function RegisterCommand(scope, guilds = []) {
|
|
11
14
|
return (ctor) => {
|
|
12
|
-
const existingMeta = Reflect.getOwnMetadata(
|
|
15
|
+
const existingMeta = Reflect.getOwnMetadata(require_publishDefault.CommandMetadataKey, ctor);
|
|
13
16
|
if (existingMeta) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.DecoratorCommandAlreadyRegistered, [
|
|
14
17
|
ctor.name,
|
|
15
18
|
existingMeta.scope,
|
|
@@ -21,7 +24,7 @@ function RegisterCommand(scope, guilds = []) {
|
|
|
21
24
|
scope,
|
|
22
25
|
guilds
|
|
23
26
|
};
|
|
24
|
-
Reflect.defineMetadata(
|
|
27
|
+
Reflect.defineMetadata(require_publishDefault.CommandMetadataKey, meta, ctor);
|
|
25
28
|
};
|
|
26
29
|
}
|
|
27
30
|
|
|
@@ -48,7 +51,7 @@ function RegisterCommand(scope, guilds = []) {
|
|
|
48
51
|
*/
|
|
49
52
|
function SlashRoute(...routes) {
|
|
50
53
|
return function(constructor) {
|
|
51
|
-
|
|
54
|
+
require_Silence.storeInteractionRoute("slash", routes, constructor);
|
|
52
55
|
};
|
|
53
56
|
}
|
|
54
57
|
/**
|
|
@@ -73,7 +76,7 @@ function SlashRoute(...routes) {
|
|
|
73
76
|
*/
|
|
74
77
|
function AutocompleteRoute(...routes) {
|
|
75
78
|
return function(constructor) {
|
|
76
|
-
|
|
79
|
+
require_Silence.storeInteractionRoute("autocomplete", routes, constructor);
|
|
77
80
|
};
|
|
78
81
|
}
|
|
79
82
|
/**
|
|
@@ -99,7 +102,7 @@ function AutocompleteRoute(...routes) {
|
|
|
99
102
|
*/
|
|
100
103
|
function ContextMenuRoute(kind, ...names) {
|
|
101
104
|
return function(constructor) {
|
|
102
|
-
|
|
105
|
+
require_Silence.storeInteractionRoute(require_Silence.contextMenuRouteOf(kind), names, constructor);
|
|
103
106
|
};
|
|
104
107
|
}
|
|
105
108
|
/**
|
|
@@ -115,7 +118,7 @@ function ContextMenuRoute(kind, ...names) {
|
|
|
115
118
|
*/
|
|
116
119
|
function ButtonRoute(...defs) {
|
|
117
120
|
return function(constructor) {
|
|
118
|
-
|
|
121
|
+
require_Silence.storeComponentRoute("button", defs, constructor);
|
|
119
122
|
};
|
|
120
123
|
}
|
|
121
124
|
/**
|
|
@@ -131,7 +134,7 @@ function ButtonRoute(...defs) {
|
|
|
131
134
|
*/
|
|
132
135
|
function ModalRoute(...defs) {
|
|
133
136
|
return function(constructor) {
|
|
134
|
-
|
|
137
|
+
require_Silence.storeComponentRoute("modal", defs, constructor);
|
|
135
138
|
};
|
|
136
139
|
}
|
|
137
140
|
/**
|
|
@@ -152,7 +155,7 @@ function ModalRoute(...defs) {
|
|
|
152
155
|
*/
|
|
153
156
|
function SelectMenuRoute(type, ...defs) {
|
|
154
157
|
return function(constructor) {
|
|
155
|
-
|
|
158
|
+
require_Silence.storeComponentRoute(require_Silence.selectMenuRouteOf(type), defs, constructor);
|
|
156
159
|
};
|
|
157
160
|
}
|
|
158
161
|
|
|
@@ -191,10 +194,10 @@ var BaseHandler = class {
|
|
|
191
194
|
event;
|
|
192
195
|
logger;
|
|
193
196
|
dispatch;
|
|
194
|
-
constructor(event, core, dispatch) {
|
|
197
|
+
constructor(event, core, dispatch, channel) {
|
|
195
198
|
this.core = core;
|
|
196
199
|
this.event = event;
|
|
197
|
-
this.logger = new _seedcord_logger.Logger(this.constructor.name);
|
|
200
|
+
this.logger = new _seedcord_logger.Logger(this.constructor.name, { channel });
|
|
198
201
|
this.dispatch = dispatch;
|
|
199
202
|
}
|
|
200
203
|
};
|
|
@@ -214,7 +217,7 @@ var RepliableHandler = class extends BaseHandler {
|
|
|
214
217
|
sender;
|
|
215
218
|
routeId;
|
|
216
219
|
constructor(event, core, dispatch) {
|
|
217
|
-
super(event, core, dispatch);
|
|
220
|
+
super(event, core, dispatch, "interactions");
|
|
218
221
|
this.routeId = dispatch?.routeId ?? this.constructor.name;
|
|
219
222
|
this.sender = this.buildSender(event, core, this.routeId);
|
|
220
223
|
}
|
|
@@ -277,21 +280,21 @@ var RepliableHandler = class extends BaseHandler {
|
|
|
277
280
|
* }
|
|
278
281
|
* ```
|
|
279
282
|
*/
|
|
280
|
-
var Fault = class extends
|
|
283
|
+
var Fault = class extends require_Silence.Notice {
|
|
281
284
|
constructor(options) {
|
|
282
285
|
super("A fault occurred", options?.cause === void 0 ? void 0 : { cause: options.cause });
|
|
283
286
|
this.report = options?.report ?? true;
|
|
284
287
|
}
|
|
285
288
|
render(ctx) {
|
|
286
|
-
return { components: [new
|
|
289
|
+
return { components: [new require_Silence.NoticeCard(`Something went wrong. Please reach out to ${ctx.developerUsername ?? "the developer"} with a way to reproduce the error and the following:\n### UUID: \`${ctx.uuid}\``, "Error").component] };
|
|
287
290
|
}
|
|
288
291
|
};
|
|
289
292
|
|
|
290
293
|
//#endregion
|
|
291
294
|
//#region src/gates/combinators.ts
|
|
292
295
|
function and(...gates) {
|
|
293
|
-
return
|
|
294
|
-
for (const gate of gates) await
|
|
296
|
+
return require_Silence.defineGate(gates.map((gate) => gate.name).join(" & "), async (ctx) => {
|
|
297
|
+
for (const gate of gates) await require_Silence.runCheck(gate, ctx);
|
|
295
298
|
});
|
|
296
299
|
}
|
|
297
300
|
function isOrOptions(arg) {
|
|
@@ -301,17 +304,17 @@ function or(...args) {
|
|
|
301
304
|
const last = args.at(-1);
|
|
302
305
|
const options = last !== void 0 && isOrOptions(last) ? last : void 0;
|
|
303
306
|
const gates = options ? args.slice(0, -1) : args;
|
|
304
|
-
return
|
|
307
|
+
return require_Silence.defineGate(gates.map((gate) => gate.name).join(" | "), async (ctx) => {
|
|
305
308
|
const summaries = [];
|
|
306
309
|
let everyArmHasSummary = true;
|
|
307
310
|
for (const gate of gates) {
|
|
308
|
-
const mark =
|
|
311
|
+
const mark = require_Silence.markCommits(ctx);
|
|
309
312
|
try {
|
|
310
|
-
await
|
|
313
|
+
await require_Silence.runCheck(gate, ctx);
|
|
311
314
|
return;
|
|
312
315
|
} catch (error) {
|
|
313
|
-
if (error instanceof
|
|
314
|
-
|
|
316
|
+
if (error instanceof require_Silence.Notice && !(error instanceof Fault) && !error.report) {
|
|
317
|
+
require_Silence.rollbackCommits(ctx, mark);
|
|
315
318
|
if (error.summary === void 0) everyArmHasSummary = false;
|
|
316
319
|
else summaries.push(error.summary);
|
|
317
320
|
continue;
|
|
@@ -320,8 +323,8 @@ function or(...args) {
|
|
|
320
323
|
}
|
|
321
324
|
}
|
|
322
325
|
if (options) throw typeof options.fail === "function" ? options.fail(ctx) : options.fail;
|
|
323
|
-
if (everyArmHasSummary && summaries.length > 0) throw new
|
|
324
|
-
throw new
|
|
326
|
+
if (everyArmHasSummary && summaries.length > 0) throw new require_Silence.NeedsAny(summaries);
|
|
327
|
+
throw new require_Silence.NotAllowed();
|
|
325
328
|
});
|
|
326
329
|
}
|
|
327
330
|
|
|
@@ -354,10 +357,10 @@ function or(...args) {
|
|
|
354
357
|
* ```
|
|
355
358
|
*/
|
|
356
359
|
function OwnerOnly(options) {
|
|
357
|
-
return
|
|
360
|
+
return require_Silence.defineGate("OwnerOnly", (ctx) => {
|
|
358
361
|
const owners = ctx.core.config.ownerIds ?? [];
|
|
359
362
|
if (ctx.userId !== null && owners.includes(ctx.userId)) return;
|
|
360
|
-
throw
|
|
363
|
+
throw require_Silence.pickNotice(options, (message) => new require_Silence.NotOwner(message));
|
|
361
364
|
});
|
|
362
365
|
}
|
|
363
366
|
/**
|
|
@@ -383,9 +386,9 @@ function OwnerOnly(options) {
|
|
|
383
386
|
* ```
|
|
384
387
|
*/
|
|
385
388
|
function GuildOnly(options) {
|
|
386
|
-
return
|
|
389
|
+
return require_Silence.defineGate("GuildOnly", (ctx) => {
|
|
387
390
|
if (ctx.guildId) return;
|
|
388
|
-
throw
|
|
391
|
+
throw require_Silence.pickNotice(options, (message) => new require_Silence.NotInGuild(message));
|
|
389
392
|
});
|
|
390
393
|
}
|
|
391
394
|
/**
|
|
@@ -409,9 +412,9 @@ function GuildOnly(options) {
|
|
|
409
412
|
* ```
|
|
410
413
|
*/
|
|
411
414
|
function DmOnly(options) {
|
|
412
|
-
return
|
|
415
|
+
return require_Silence.defineGate("DmOnly", (ctx) => {
|
|
413
416
|
if (!ctx.guildId) return;
|
|
414
|
-
throw
|
|
417
|
+
throw require_Silence.pickNotice(options, (message) => new require_Silence.NotInDm(message));
|
|
415
418
|
});
|
|
416
419
|
}
|
|
417
420
|
|
|
@@ -483,45 +486,16 @@ function Cooldown(duration, options) {
|
|
|
483
486
|
};
|
|
484
487
|
const anonId = anonSeq++;
|
|
485
488
|
const keyOf = (ctx) => `cooldown:${ctx.routeId ?? `anon${anonId}`}:${per}:w${windowMs}:l${options?.limit ?? 1}:${scopeValue(ctx, per)}`;
|
|
486
|
-
return
|
|
489
|
+
return require_Silence.defineEffectGate("Cooldown", async (ctx) => {
|
|
487
490
|
const result = await ctx.core.rateLimiter.peek(keyOf(ctx), window);
|
|
488
491
|
if (!result.limited) return;
|
|
489
492
|
if (options?.notice) throw options.notice(result.resetAt);
|
|
490
|
-
throw new
|
|
493
|
+
throw new require_Silence.OnCooldown(result.resetAt, options?.message?.(result.resetAt));
|
|
491
494
|
}, async (ctx) => {
|
|
492
495
|
await ctx.core.rateLimiter.charge(keyOf(ctx), window);
|
|
493
496
|
});
|
|
494
497
|
}
|
|
495
498
|
|
|
496
|
-
//#endregion
|
|
497
|
-
//#region src/stops/Silence.ts
|
|
498
|
-
/**
|
|
499
|
-
* Throw to stop a handler with no reply and no report.
|
|
500
|
-
*
|
|
501
|
-
* The framework boundary catches `Silence` before {@link Notice}, makes zero Discord calls, and stops.
|
|
502
|
-
* Ideally you'd only throw this in `EventHandlers` (or `Gates` for those), because it doesn't make sense to
|
|
503
|
-
* leave the user with no reply for an interaction.
|
|
504
|
-
*
|
|
505
|
-
* @example
|
|
506
|
-
* ```ts
|
|
507
|
-
* import { Silence } from '@seedcord/gateway';
|
|
508
|
-
*
|
|
509
|
-
* // before any reply or defer, drop the interaction with no reply and no report
|
|
510
|
-
* if (await isBlacklisted(interaction.user.id)) throw new Silence('blacklisted user');
|
|
511
|
-
* ```
|
|
512
|
-
*/
|
|
513
|
-
var Silence = class extends Error {
|
|
514
|
-
reason;
|
|
515
|
-
/**
|
|
516
|
-
* @param reason - Optional note written only to a debug log, never shown to the user or reported.
|
|
517
|
-
*/
|
|
518
|
-
constructor(reason) {
|
|
519
|
-
super(reason ?? "Silence");
|
|
520
|
-
this.reason = reason;
|
|
521
|
-
Error.captureStackTrace(this, this.constructor);
|
|
522
|
-
}
|
|
523
|
-
};
|
|
524
|
-
|
|
525
499
|
//#endregion
|
|
526
500
|
//#region src/pagination/paginate.ts
|
|
527
501
|
/**
|
|
@@ -551,36 +525,43 @@ function paginate(items, page, perPage) {
|
|
|
551
525
|
//#endregion
|
|
552
526
|
//#region src/index.ts
|
|
553
527
|
/** Package version */
|
|
554
|
-
const version = "0.1.0-next.
|
|
528
|
+
const version = "0.1.0-next.7";
|
|
555
529
|
|
|
556
530
|
//#endregion
|
|
557
531
|
exports.AutocompleteRoute = AutocompleteRoute;
|
|
558
532
|
exports.BaseHandler = BaseHandler;
|
|
559
|
-
exports.BuilderComponent =
|
|
533
|
+
exports.BuilderComponent = require_publishDefault.BuilderComponent;
|
|
534
|
+
exports.Bus = require_subscribers.Bus;
|
|
560
535
|
exports.ButtonRoute = ButtonRoute;
|
|
561
536
|
exports.ContextMenuRoute = ContextMenuRoute;
|
|
562
537
|
exports.Cooldown = Cooldown;
|
|
563
|
-
exports.CustomId =
|
|
538
|
+
exports.CustomId = require_Silence.CustomId;
|
|
564
539
|
exports.DispatchContext = DispatchContext;
|
|
565
540
|
exports.DmOnly = DmOnly;
|
|
566
541
|
exports.Fault = Fault;
|
|
567
542
|
exports.GuildOnly = GuildOnly;
|
|
568
543
|
exports.ModalRoute = ModalRoute;
|
|
569
|
-
exports.Notice =
|
|
544
|
+
exports.Notice = require_Silence.Notice;
|
|
570
545
|
exports.OwnerOnly = OwnerOnly;
|
|
571
546
|
exports.RegisterCommand = RegisterCommand;
|
|
572
547
|
exports.RepliableHandler = RepliableHandler;
|
|
573
|
-
exports.RequireBotPermissions =
|
|
574
|
-
exports.RequirePermissions =
|
|
575
|
-
exports.RequireRole =
|
|
576
|
-
exports.RowComponent =
|
|
577
|
-
exports.SelectMenuKind =
|
|
548
|
+
exports.RequireBotPermissions = require_Silence.RequireBotPermissions;
|
|
549
|
+
exports.RequirePermissions = require_Silence.RequirePermissions;
|
|
550
|
+
exports.RequireRole = require_Silence.RequireRole;
|
|
551
|
+
exports.RowComponent = require_publishDefault.RowComponent;
|
|
552
|
+
exports.SelectMenuKind = require_Silence.SelectMenuKind;
|
|
578
553
|
exports.SelectMenuRoute = SelectMenuRoute;
|
|
579
|
-
exports.
|
|
554
|
+
exports.ShutdownPhase = require_phases.ShutdownPhase;
|
|
555
|
+
exports.Silence = require_Silence.Silence;
|
|
580
556
|
exports.SlashRoute = SlashRoute;
|
|
557
|
+
exports.StartupPhase = require_phases.StartupPhase;
|
|
558
|
+
exports.Subscribe = require_subscribers.Subscribe;
|
|
559
|
+
exports.Subscriber = require_subscribers.Subscriber;
|
|
560
|
+
exports.WebhookLog = require_subscribers.WebhookLog;
|
|
561
|
+
exports.WebhookUrl = require_subscribers.WebhookUrl;
|
|
581
562
|
exports.and = and;
|
|
582
|
-
exports.defineEffectGate =
|
|
583
|
-
exports.defineGate =
|
|
563
|
+
exports.defineEffectGate = require_Silence.defineEffectGate;
|
|
564
|
+
exports.defineGate = require_Silence.defineGate;
|
|
584
565
|
exports.or = or;
|
|
585
566
|
exports.paginate = paginate;
|
|
586
567
|
exports.version = version;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["CommandMetadataKey","SeedcordError","SeedcordErrorCode","contextMenuRouteOf","selectMenuRouteOf","Logger","Notice","NoticeCard","defineGate","runCheck","markCommits","Notice","NeedsAny","NotAllowed","defineGate","pickNotice","NotOwner","NotInGuild","NotInDm","SeedcordTypeError","SeedcordErrorCode","defineEffectGate","OnCooldown","SeedcordRangeError","SeedcordErrorCode"],"sources":["../src/decorators/Command.ts","../src/decorators/routes.ts","../src/dispatch/DispatchContext.ts","../src/handlers/BaseHandler.ts","../src/handlers/RepliableHandler.ts","../src/stops/Fault.ts","../src/gates/combinators.ts","../src/gates/catalog/access.ts","../src/gates/catalog/Cooldown.ts","../src/stops/Silence.ts","../src/pagination/paginate.ts","../src/index.ts"],"sourcesContent":["import 'reflect-metadata';\n\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\n\nimport { CommandMetadataKey } from '@src/metadataKeys';\n\nimport type { BuilderComponent } from '@components/Component';\nimport type { Constructor } from 'type-fest';\n\ntype CommandCtor = Constructor<BuilderComponent<'command' | 'context_menu'>>;\n\ninterface GlobalMeta {\n scope: 'global';\n}\n\ninterface GuildMeta {\n scope: 'guild';\n guilds: string[];\n}\n\nexport type CommandMeta = GlobalMeta | GuildMeta;\n\ntype CommandScope = CommandMeta['scope'];\n\n/**\n * Attaches deployment metadata so the framework registers this command globally or in specific guilds.\n *\n * @param scope - Must be 'global' for global registration\n * @decorator\n * @example\n * ```typescript\n * \\@RegisterCommand('global')\n * class PingCommand extends BuilderComponent<'command'> {} // or BuilderComponent<'context_menu'>\n * ```\n */\nexport function RegisterCommand(scope: 'global'): (ctor: CommandCtor) => void;\n\n/**\n * Registers a command for specific guild deployment.\n *\n * @param scope - Must be 'guild' for guild-specific registration\n * @param guilds - Array of guild IDs where the command should be registered\n * @decorator\n * @example\n * ```typescript\n * \\@RegisterCommand('guild', ['123456789'])\n * class AdminCommand extends BuilderComponent<'command'> {} // or BuilderComponent<'context_menu'>\n * ```\n */\nexport function RegisterCommand(scope: 'guild', guilds: string[]): (ctor: CommandCtor) => void;\n\nexport function RegisterCommand(scope: CommandScope, guilds: string[] = []) {\n return (ctor: CommandCtor): void => {\n const existingMeta = Reflect.getOwnMetadata(CommandMetadataKey, ctor) as CommandMeta | undefined;\n if (existingMeta) {\n throw new SeedcordError(SeedcordErrorCode.DecoratorCommandAlreadyRegistered, [\n ctor.name,\n existingMeta.scope,\n scope\n ]);\n }\n\n if (scope === 'global' && guilds.length > 0) {\n throw new SeedcordError(SeedcordErrorCode.DecoratorCommandGlobalWithGuilds);\n }\n\n if (scope === 'guild' && (!Array.isArray(guilds) || guilds.length === 0)) {\n throw new SeedcordError(SeedcordErrorCode.DecoratorCommandGuildWithoutGuilds);\n }\n\n const meta: GlobalMeta | GuildMeta = scope === 'global' ? { scope } : { scope, guilds };\n Reflect.defineMetadata(CommandMetadataKey, meta, ctor);\n };\n}\n","import {\n contextMenuRouteOf,\n selectMenuRouteOf,\n storeComponentRoute,\n storeInteractionRoute\n} from '@decorators/interactionRoutes';\nimport { InteractionRoutes } from '@src/metadataKeys';\n\nimport type { AnyCustomId } from '@customId/CustomId';\nimport type { SelectMenuKind } from '@decorators/interactionRoutes';\nimport type { MessageContextMenuRegistry, UserContextMenuRegistry } from '@registries/ContextMenuRegistry';\nimport type { SlashOptionRegistry } from '@registries/SlashOptionRegistry';\nimport type { ApplicationCommandType } from 'discord-api-types/v10';\nimport type { Constructor } from 'type-fest';\n\ntype ContextMenuKind = ApplicationCommandType.User | ApplicationCommandType.Message;\n\ntype ComponentBrand = 'button' | 'modal' | SelectMenuKind;\n\n// phantom brands keep the decorators off transport-specific classes\ntype AnyHandlerCtor = new (...args: any[]) => unknown;\n\ntype SlashRouteOf<TCtor extends AnyHandlerCtor> =\n InstanceType<TCtor> extends {\n __slashRoute?: infer Route extends keyof SlashOptionRegistry;\n }\n ? Route\n : never;\n\ntype AutocompleteRouteOf<TCtor extends AnyHandlerCtor> =\n InstanceType<TCtor> extends {\n __autocompleteRoute?: infer Route extends keyof SlashOptionRegistry;\n }\n ? Route\n : never;\n\ntype ContextMenuKindOf<TCtor extends AnyHandlerCtor> =\n InstanceType<TCtor> extends {\n __ctxKind?: infer Kind extends ContextMenuKind;\n }\n ? Kind\n : never;\n\ntype ComponentOf<TCtor extends AnyHandlerCtor> =\n InstanceType<TCtor> extends {\n __component?: infer Brand extends ComponentBrand;\n }\n ? Brand\n : never;\n\ntype DefsOf<TCtor extends AnyHandlerCtor> =\n InstanceType<TCtor> extends {\n __componentDefs?: infer Defs extends readonly AnyCustomId[];\n }\n ? Defs\n : never;\n\ntype AssertSlashRoute<Route extends keyof SlashOptionRegistry, TCtor extends AnyHandlerCtor> = [Route] extends [\n SlashRouteOf<TCtor>\n]\n ? [SlashRouteOf<TCtor>] extends [Route]\n ? TCtor\n : Constructor<['SlashHandler declares a route the SlashRoute decorator does not list', SlashRouteOf<TCtor>]>\n : Constructor<['SlashRoute does not match the SlashHandler generic', Route]>;\n\ntype AssertAutocompleteRoute<Route extends keyof SlashOptionRegistry, TCtor extends AnyHandlerCtor> = [Route] extends [\n AutocompleteRouteOf<TCtor>\n]\n ? [AutocompleteRouteOf<TCtor>] extends [Route]\n ? TCtor\n : Constructor<\n [\n 'AutocompleteHandler declares a command the AutocompleteRoute decorator does not list',\n AutocompleteRouteOf<TCtor>\n ]\n >\n : Constructor<['AutocompleteRoute does not match the AutocompleteHandler generic', Route]>;\n\ntype AssertContextMenuRoute<Kind extends ContextMenuKind, TCtor extends AnyHandlerCtor> = [Kind] extends [\n ContextMenuKindOf<TCtor>\n]\n ? [ContextMenuKindOf<TCtor>] extends [Kind]\n ? TCtor\n : Constructor<\n [\n 'ContextMenuHandler declares a kind the ContextMenuRoute decorator does not match',\n ContextMenuKindOf<TCtor>\n ]\n >\n : Constructor<['ContextMenuRoute does not match the ContextMenuHandler generic', Kind]>;\n\n// one assignability direction for the defs, a bidirectional check would reject const-inferred readonly tuples\ntype AssertComponentRoute<\n Brand extends ComponentBrand,\n Defs extends readonly AnyCustomId[],\n TCtor extends AnyHandlerCtor\n> = [ComponentOf<TCtor>] extends [Brand]\n ? [Brand] extends [ComponentOf<TCtor>]\n ? [DefsOf<TCtor>] extends [Defs]\n ? TCtor\n : Constructor<['the customId definitions do not match the handler generic', DefsOf<TCtor>]>\n : Constructor<['the decorator does not match the handler kind', ComponentOf<TCtor>]>\n : Constructor<['the decorator does not match the handler kind', ComponentOf<TCtor>]>;\n\ntype NamesFor<Kind extends ContextMenuKind> = Kind extends ApplicationCommandType.User\n ? keyof UserContextMenuRegistry\n : keyof MessageContextMenuRegistry;\n\n/**\n * Routes one or more slash commands to a `SlashHandler`.\n *\n * Pass the same route string(s) as the handler's generic. A single command reads `this.options`, several\n * commands branch with `this.match`. The decorator routes and the generic must match exactly, so listing\n * fewer or more than the handler declares is a compile error. Subcommands use a slash path.\n *\n * @param routes - The route string(s) this handler serves, e.g. `'ban'`, `'ban', 'kick'`, or `'demo/setup'`.\n * @decorator\n * @example\n * ```ts\n * \\@SlashRoute('ban')\n * class BanHandler extends SlashHandler<'ban'> {\n * async execute() {\n * const target = this.options.getUser('target');\n * }\n * }\n * ```\n */\nexport function SlashRoute<const Route extends keyof SlashOptionRegistry>(...routes: Route[]) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertSlashRoute<Route, TCtor>): void {\n storeInteractionRoute(InteractionRoutes.Slash, routes, constructor);\n };\n}\n\n/**\n * Routes one or more commands' autocomplete to an `AutocompleteHandler`.\n *\n * Pass the same command route string(s) as the handler's generic. One command branches with `this.match`\n * over its autocompletable fields, several commands share one handler whose arms span every command's\n * fields. The decorator routes and the generic must match exactly, so listing fewer or more than the\n * handler declares is a compile error.\n *\n * @param routes - The command route string(s) this handler serves, e.g. `'search'` or `'search', 'find'`.\n * @decorator\n * @example\n * ```ts\n * \\@AutocompleteRoute('search')\n * class SearchAutocomplete extends AutocompleteHandler<'search'> {\n * async execute() {\n * await this.match({ query: (value, respond) => respond([{ name: value, value }]) });\n * }\n * }\n * ```\n */\nexport function AutocompleteRoute<const Route extends keyof SlashOptionRegistry>(...routes: Route[]) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertAutocompleteRoute<Route, TCtor>): void {\n storeInteractionRoute(InteractionRoutes.Autocomplete, routes, constructor);\n };\n}\n\n/**\n * Routes one or more context-menu commands to a `ContextMenuHandler`.\n *\n * Pass the kind (`ApplicationCommandType.User` or `ApplicationCommandType.Message`) and the command name(s),\n * each checked against that kind's registry, so a typo is a compile error. The handler's generic must\n * declare the same kind, cross-checked both directions. Context menus carry no options, so a multi-name\n * handler reads `this.target` uniformly with no branch.\n *\n * @param kind - The context-menu kind, `ApplicationCommandType.User` or `ApplicationCommandType.Message`.\n * @param names - The command name(s) this handler serves, keyed off the matching registry.\n * @decorator\n * @example\n * ```ts\n * \\@ContextMenuRoute(ApplicationCommandType.User, 'View Profile')\n * class ViewProfile extends ContextMenuHandler<ApplicationCommandType.User> {\n * async execute() {\n * const user = this.target;\n * }\n * }\n * ```\n */\nexport function ContextMenuRoute<const Kind extends ContextMenuKind>(kind: Kind, ...names: NamesFor<Kind>[]) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertContextMenuRoute<Kind, TCtor>): void {\n storeInteractionRoute(contextMenuRouteOf(kind), names, constructor);\n };\n}\n\n/**\n * Routes button interactions to handler classes.\n *\n * Pass the {@link CustomId} definition(s) this handler decodes and list the same ones in the handler's\n * generic. Passing different definitions to the decorator and the generic is a compile error. Routing\n * matches the stable prefix, so a wire minted from an older shape still reaches the handler, where\n * reading this.params throws StaleCustomId and the controller boundary turns it into a reply.\n *\n * @param defs - The customId definition(s) this handler decodes, one per route.\n * @decorator\n */\nexport function ButtonRoute<const Defs extends readonly AnyCustomId[]>(...defs: Defs) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertComponentRoute<'button', Defs, TCtor>): void {\n storeComponentRoute(InteractionRoutes.Button, defs, constructor);\n };\n}\n\n/**\n * Routes modal submissions to handler classes.\n *\n * Pass the {@link CustomId} definition(s) this handler decodes and list the same ones in the handler's\n * generic. Passing different definitions to the decorator and the generic is a compile error. Routing\n * matches the stable prefix, so an older-shape wire still reaches the handler and throws StaleCustomId\n * on read, the same as a button route.\n *\n * @param defs - The customId definition(s) this handler decodes, one per route.\n * @decorator\n */\nexport function ModalRoute<const Defs extends readonly AnyCustomId[]>(...defs: Defs) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertComponentRoute<'modal', Defs, TCtor>): void {\n storeComponentRoute(InteractionRoutes.Modal, defs, constructor);\n };\n}\n\n/**\n * Routes select menu interactions to handler classes.\n *\n * Pass the select kind and the {@link CustomId} definition(s) this handler decodes. The handler's\n * generic must list the same kind and definitions, or it is a compile error.\n *\n * @param type - Select menu kind from {@link SelectMenuKind}.\n * @param defs - The customId definition(s) this handler decodes, one per route.\n * @decorator\n *\n * @example\n * ```typescript\n * \\@SelectMenuRoute(SelectMenuKind.User, AssignId)\n * class AssignSelect extends SelectMenuHandler<SelectMenuKind.User, [typeof AssignId]> {}\n * ```\n */\nexport function SelectMenuRoute<const Kind extends SelectMenuKind, const Defs extends readonly AnyCustomId[]>(\n type: Kind,\n ...defs: Defs\n) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertComponentRoute<Kind, Defs, TCtor>): void {\n storeComponentRoute(selectMenuRouteOf(type), defs, constructor);\n };\n}\n","/**\n * The per-dispatch bag. Any code can merge fields into it by declaration merging, the\n * same pattern as {@link SlashOptionRegistry}. It stays empty until one does, so `keyof DispatchState` is\n * `never` and the bag is inert.\n */\nexport interface DispatchState {}\n\n/**\n * A typed bag allocated once per interaction dispatch and handed to the handler. The middleware and i18n\n * work reads and writes it through {@link DispatchState}. Today the bag is empty, so it only carries the\n * dispatched `routeId`.\n */\nexport class DispatchContext {\n private readonly state: Partial<DispatchState> = {};\n\n constructor(public readonly routeId: string | null) {}\n\n set<Key extends keyof DispatchState>(key: Key, value: DispatchState[Key]): void {\n this.state[key] = value;\n }\n\n get<Key extends keyof DispatchState>(key: Key): DispatchState[Key] | undefined {\n return this.state[key];\n }\n}\n","import { Logger } from '@seedcord/logger';\n\nimport type { CoreBase } from '@interfaces/CoreBase';\nimport type { DispatchContext } from '@src/dispatch/DispatchContext';\n\n/**\n * Base class every transport handler extends. Don't register handlers directly, use the more specific\n * handler subclasses.\n *\n * @typeParam Event - The event or interaction this handler processes\n * @typeParam TCore - The transport's Core\n */\nexport abstract class BaseHandler<Event, TCore extends CoreBase> {\n protected readonly event: Event;\n protected readonly logger: Logger;\n // absent on event handlers\n protected readonly dispatch?: DispatchContext | undefined;\n\n protected constructor(\n event: Event,\n public readonly core: TCore,\n dispatch?: DispatchContext\n ) {\n this.event = event;\n this.logger = new Logger(this.constructor.name);\n this.dispatch = dispatch;\n }\n\n /**\n * Holds the main logic of your handler. The dispatcher calls it after the handler's gates pass, so a\n * gate that refuses stops `execute()` from running.\n */\n abstract execute(): Promise<void>;\n}\n","import { BaseHandler } from './BaseHandler';\n\nimport type { CoreBase } from '@interfaces/CoreBase';\nimport type { BaseReplySender } from '@reply/BaseReplySender';\nimport type { DeferOpts, ReplyResponse, SendOpts } from '@seedcord/types';\nimport type { DispatchContext } from '@src/dispatch/DispatchContext';\n\n/**\n * Shared base the repliable handlers on both transports extend. Defines the reply members over the sender\n * the transport builds.\n *\n * @typeParam Event - The repliable interaction type this handler processes\n * @typeParam TCore - The transport's Core\n * @typeParam TMessage - The transport's created-message lens\n * @typeParam TSender - The transport's reply sender\n */\nexport abstract class RepliableHandler<\n Event,\n TCore extends CoreBase,\n TMessage extends { id: string },\n TSender extends BaseReplySender<TMessage>\n> extends BaseHandler<Event, TCore> {\n protected readonly sender: TSender;\n protected readonly routeId: string;\n\n protected constructor(event: Event, core: TCore, dispatch?: DispatchContext) {\n super(event, core, dispatch);\n this.routeId = dispatch?.routeId ?? this.constructor.name;\n // runs inside the ctor, an override builds from its arguments only, subclass fields are not initialized yet\n this.sender = this.buildSender(event, core, this.routeId);\n }\n\n protected abstract buildSender(event: Event, core: TCore, routeId: string): TSender;\n\n /** @internal The dispatcher's fault boundary replies through the live ack state. */\n public getSender(): TSender {\n return this.sender;\n }\n\n /** Send the initial response, exactly once. */\n protected reply(response: ReplyResponse | string, opts?: SendOpts): Promise<TMessage> {\n return this.sender.reply(response, opts);\n }\n\n /** Show a \"thinking\" placeholder, then fill it later with {@link edit}. */\n protected defer(opts?: DeferOpts): Promise<void> {\n return this.sender.defer(opts);\n }\n\n /** Send a new message once the interaction is acknowledged. */\n protected followUp(response: ReplyResponse | string, opts?: SendOpts): Promise<TMessage> {\n return this.sender.followUp(response, opts);\n }\n\n /** Rewrite the initial reply or deferred placeholder. The targeted form rewrites a message a prior send returned. */\n protected edit(response: ReplyResponse | string): Promise<TMessage>;\n protected edit(target: TMessage, response: ReplyResponse | string): Promise<TMessage>;\n protected edit(\n targetOrResponse: TMessage | ReplyResponse | string,\n maybeResponse?: ReplyResponse | string\n ): Promise<TMessage> {\n // justified: the overloads narrow targetOrResponse to a response once maybeResponse is absent\n if (maybeResponse === undefined) return this.sender.edit(targetOrResponse as ReplyResponse | string);\n // justified: the overloads narrow targetOrResponse to a target message once maybeResponse is defined\n return this.sender.edit(targetOrResponse as TMessage, maybeResponse);\n }\n\n /** Routes to reply, followUp, or edit based on the current ack state. */\n protected send(response: ReplyResponse | string, opts?: SendOpts): Promise<TMessage> {\n return this.sender.send(response, opts);\n }\n\n /** Delete the initial reply or deferred placeholder. Pass a target to delete a message a prior send returned. */\n protected delete(target?: TMessage): Promise<void> {\n return target === undefined ? this.sender.delete() : this.sender.delete(target);\n }\n}\n","import { Notice } from './Notice';\nimport { NoticeCard } from './NoticeCard';\n\nimport type { RenderContext, ReplyResponse } from '@seedcord/types';\n\n/**\n * A generic fault you throw after catching an error you do not have a specific message for.\n *\n * The user sees a fixed generic reply with the tracking uuid, never the cause. `report` defaults to\n * `true`, so the framework logs it and publishes it to the `handledException` bus. Pass `report: false`\n * to show the generic reply without the bus publish. The original error is stored as the standard\n * `cause`, so the real stack reaches the webhook. For a fault the user should see a real message,\n * subclass {@link Notice} and write your own `render` instead.\n *\n * The framework also renders this for an unhandled throw, where it points the user at\n * `ctx.developerUsername`.\n *\n * @example\n * ```ts\n * import { Fault } from '@seedcord/gateway';\n *\n * try {\n * await db.write(record);\n * } catch (cause) {\n * // user sees the generic reply with the uuid, the real error rides along as cause for the webhook\n * throw new Fault({ cause });\n *\n * // pass report: false to show the same reply without publishing to the handledException bus\n * // throw new Fault({ cause, report: false });\n * }\n * ```\n */\nexport class Fault extends Notice {\n public constructor(options?: { cause?: unknown; report?: boolean }) {\n super('A fault occurred', options?.cause === undefined ? undefined : { cause: options.cause });\n this.report = options?.report ?? true;\n }\n\n public render(ctx: RenderContext): ReplyResponse {\n const contact = ctx.developerUsername ?? 'the developer';\n const card = new NoticeCard(\n `Something went wrong. Please reach out to ${contact} with a way to reproduce the error and the following:\\n### UUID: \\`${ctx.uuid}\\``,\n 'Error'\n );\n return { components: [card.component] };\n }\n}\n","import { NeedsAny, NotAllowed } from '@notices/index';\nimport { Fault } from '@stops/Fault';\nimport { Notice } from '@stops/Notice';\n\nimport { markCommits, rollbackCommits, runCheck } from './effects';\nimport { defineGate } from './Gate';\n\nimport type { Gate, GateContextBase, RequiredOf } from './Gate';\nimport type { IntersectRequired, JoinNames, TwoOrMore } from './matching';\n\n/**\n * Runs each gate in order and refuses on the first refusal. Takes two or more arms. The required\n * context is the intersection of the arms, so an event-only and an interaction-only gate cannot be\n * combined.\n *\n * @typeParam Gates - The tuple of two or more gate arms, run left to right.\n * @param gates - The gate arms to run in order, all refused on the first refusal.\n *\n * @see {@link or}\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n *\n * \\@Gated(and(GuildOnly(), RequirePermissions([PermissionFlagsBits.BanMembers])))\n * \\@SlashRoute('ban')\n * class BanHandler extends SlashHandler<'ban'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function and<Gates extends TwoOrMore<Gate<GateContextBase>>>(\n ...gates: Gates\n): Gate<IntersectRequired<Gates> & GateContextBase, JoinNames<Gates, ' & '>>;\nexport function and(...gates: readonly Gate<GateContextBase>[]): Gate<GateContextBase> {\n return defineGate(gates.map((gate) => gate.name).join(' & '), async (ctx) => {\n for (const gate of gates) {\n await runCheck(gate, ctx);\n }\n });\n}\n\n// the caller-supplied refusal when every or arm refuses, replacing the default list or neutral refusal\ninterface OrOptions {\n fail: Notice | ((ctx: GateContextBase) => Notice);\n}\n\n// a gate has a check method, the options object does not\nfunction isOrOptions(arg: Gate<GateContextBase> | OrOptions): arg is OrOptions {\n return !('check' in arg);\n}\n\n/**\n * Runs each gate in order and passes on the first arm that passes. Takes two or more arms. The\n * required context is the union of the arms, so a handler that matches any one arm fits. When every\n * arm refuses it throws the trailing {@link OrOptions} `fail` if given, else an auto list of the\n * arms derived from the summary field, else a default refusal. The trailing options object does not\n * count as an arm.\n *\n * @typeParam Gates - The tuple of two or more gate arms, tried left to right.\n * @param gates - The gate arms to try in order, with an optional trailing {@link OrOptions} object.\n *\n * @see {@link and}\n *\n * @example\n * ```ts\n * \\@Gated(or(OwnerOnly(), RequireRole('123456789012345678')))\n * \\@SlashRoute('admin')\n * class AdminHandler extends SlashHandler<'admin'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function or<Gates extends TwoOrMore<Gate<GateContextBase>>>(\n ...gates: Gates\n): Gate<RequiredOf<Gates[number]>, JoinNames<Gates, ' | '>>;\n/**\n * @example\n * ```ts\n * // custom refusal when every arm refuses\n * or(OwnerOnly(), RequireRole('123456789012345678'), { fail: new NotAllowedNotice() });\n * ```\n */\nexport function or<Gates extends TwoOrMore<Gate<GateContextBase>>>(\n ...args: [...Gates, OrOptions]\n): Gate<RequiredOf<Gates[number]>, JoinNames<Gates, ' | '>>;\nexport function or(...args: readonly (Gate<GateContextBase> | OrOptions)[]): Gate<GateContextBase> {\n const last = args.at(-1);\n const options = last !== undefined && isOrOptions(last) ? last : undefined;\n const gates = (options ? args.slice(0, -1) : args) as readonly Gate<GateContextBase>[];\n\n return defineGate(gates.map((gate) => gate.name).join(' | '), async (ctx) => {\n const summaries: string[] = [];\n let everyArmHasSummary = true;\n for (const gate of gates) {\n const mark = markCommits(ctx);\n try {\n await runCheck(gate, ctx);\n return;\n } catch (error) {\n // only a refusal is an arm declining, a Fault (even report-false), a Silence, or a raw error stops everything\n if (error instanceof Notice && !(error instanceof Fault) && !error.report) {\n // the arm may have queued an effect's commit before refusing, drop it so the winner does not carry it\n rollbackCommits(ctx, mark);\n if (error.summary === undefined) everyArmHasSummary = false;\n else summaries.push(error.summary);\n continue;\n }\n throw error;\n }\n }\n if (options) throw typeof options.fail === 'function' ? options.fail(ctx) : options.fail;\n // the auto-list shows only when every refusal gave a summary, a partial list would mislead by omission\n if (everyArmHasSummary && summaries.length > 0) throw new NeedsAny(summaries);\n throw new NotAllowed();\n });\n}\n","import { defineGate } from '@gates/Gate';\nimport { NotInDm, NotInGuild, NotOwner } from '@notices/index';\n\nimport { pickNotice } from './options';\n\nimport type { GateNoticeOptions } from './options';\nimport type { Gate, GateContextBase } from '@gates/Gate';\n\n/**\n * Passes only for a user id listed in `config.ownerIds`, else refuses.\n *\n * Agnostic, so it attaches to interaction and event handlers alike. With no `ownerIds` configured it refuses every caller. Pass {@link GateNoticeOptions} to reword or replace the refusal.\n *\n * @param options - Reword the default refusal with `message`, or replace it with `notice`.\n *\n * @see the `@Gated` decorator from `seedcord`\n *\n * @example\n * ```ts\n * \\@Gated(OwnerOnly())\n * \\@SlashRoute('shutdown')\n * class ShutdownHandler extends SlashHandler<'shutdown'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * // reword the refusal, keeping the embed styling\n * OwnerOnly({ message: 'Owners only.' });\n * ```\n */\nexport function OwnerOnly(options?: GateNoticeOptions): Gate<GateContextBase, 'OwnerOnly'> {\n return defineGate('OwnerOnly', (ctx) => {\n const owners = ctx.core.config.ownerIds ?? [];\n if (ctx.userId !== null && owners.includes(ctx.userId)) return;\n throw pickNotice(options, (message) => new NotOwner(message));\n });\n}\n\n/**\n * Passes inside a guild, else refuses.\n *\n * Agnostic, so it attaches to any handler kind. Often paired with `RequirePermissions` in an {@link and}.\n *\n * @param options - Reword the default refusal with `message`, or replace it with `notice`.\n *\n * @see the `@Gated` decorator from `seedcord`\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n *\n * \\@Gated(GuildOnly(), RequirePermissions([PermissionFlagsBits.Administrator]))\n * \\@SlashRoute('maintenance')\n * class Maintenance extends SlashHandler<'maintenance'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function GuildOnly(options?: GateNoticeOptions): Gate<GateContextBase, 'GuildOnly'> {\n return defineGate('GuildOnly', (ctx) => {\n if (ctx.guildId) return;\n throw pickNotice(options, (message) => new NotInGuild(message));\n });\n}\n\n/**\n * Passes in a direct message, else refuses.\n *\n * Agnostic, so it attaches to any handler kind. The inverse of {@link GuildOnly}, so combining the two in an {@link and} can never pass.\n *\n * @param options - Reword the default refusal with `message`, or replace it with `notice`.\n *\n * @see the `@Gated` decorator from `seedcord`\n *\n * @example\n * ```ts\n * \\@Gated(DmOnly())\n * \\@SlashRoute('verify')\n * class VerifyHandler extends SlashHandler<'verify'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function DmOnly(options?: GateNoticeOptions): Gate<GateContextBase, 'DmOnly'> {\n return defineGate('DmOnly', (ctx) => {\n if (!ctx.guildId) return;\n throw pickNotice(options, (message) => new NotInDm(message));\n });\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\nimport { parseDuration, type ValidDuration } from '@seedcord/utils';\n\nimport { defineEffectGate } from '@gates/Gate';\nimport { OnCooldown } from '@notices/index';\n\nimport type { EffectGate, GateContextBase } from '@gates/Gate';\nimport type { EpochMs } from '@seedcord/types';\nimport type { Notice } from '@stops/Notice';\n\n/**\n * Options for {@link Cooldown}. `per` sets the bucket the window applies to and `limit` the uses allowed per\n * window. `message` rewords the refusal and `notice` replaces it, both receiving the epoch ms the key frees\n * up so the refusal can show the retry time.\n *\n * @example\n * ```ts\n * // one use per channel, rewording the refusal with the retry time\n * Cooldown('10s', {\n * per: 'channel',\n * message: (resetAt) => `Slow down. Try again <t:${Math.round(resetAt / 1000)}:R>.`\n * });\n * ```\n *\n * @example\n * ```ts\n * // five uses per minute, per user\n * Cooldown('1m', { limit: 5 });\n * ```\n */\nexport interface CooldownOptions {\n /**\n * The bucket the cooldown window applies to. 'user' scopes by user ID, falls back to global when the source carries no user id. 'guild' scopes by guild ID (falls back to global if no guild), and 'channel' scopes by channel ID (falls back to global if no channel).\n *\n * @defaultValue `'user'`\n */\n per?: 'user' | 'guild' | 'channel';\n /**\n * Uses allowed inside one window before the gate refuses.\n *\n * @defaultValue `1`\n */\n limit?: number;\n /**\n * Reword the refusal, keeping the standard notice card. Receives the epoch ms the key frees up, so the\n * text can include the retry time with `<t:${Math.round(resetAt / 1000)}:R>`.\n */\n message?: (resetAt: EpochMs) => string;\n /**\n * Replace the refusal Notice entirely, for full control or a translated copy. Receives the epoch ms the\n * key frees up.\n */\n notice?: (resetAt: EpochMs) => Notice;\n}\n\n// off-route ctxs have no route to key on, so each Cooldown() gets its own id to keep unrelated event handlers isolated\nlet anonSeq = 0;\n\nfunction scopeValue(ctx: GateContextBase, per: 'user' | 'guild' | 'channel'): string {\n if (per === 'guild') return ctx.guildId ?? 'global';\n if (per === 'channel') return ctx.channelId ?? 'global';\n return ctx.userId ?? 'global';\n}\n\n/**\n * Allows `limit` uses per window, scoped by `per`. A number `duration` is **seconds**, a string is\n * a duration like `30m` or `24h`. An unparseable string throws a **SeedcordTypeError** at construction. The\n * slot is charged in commit, only after the whole gate set passes, so a later refusal never burns the cooldown.\n * That split also means two requests racing the same key can both pass before either charges the slot.\n * The key combines the handler's route with the window settings, so two different handlers keep separate\n * windows. Reword the refusal with {@link CooldownOptions.message} or replace it with {@link CooldownOptions.notice}.\n *\n * @param duration - A number is seconds, a string is a duration like `30m` or `24h`. An unparseable string throws a **SeedcordTypeError**.\n * @param options - Sets the scope with `per`, the uses per window with `limit`, and the refusal text with `message` or `notice`.\n *\n * @see the `@Gated` decorator from `seedcord`\n * @see {@link IRateLimiter}\n *\n * @example\n * ```ts\n * // a number argument is SECONDS\n * \\@Gated(Cooldown(5))\n * \\@SlashRoute('daily')\n * class DailyHandler extends SlashHandler<'daily'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * // a string is a duration, here scoped per guild (the default is per user)\n * Cooldown('30m', { per: 'guild' });\n * ```\n *\n * @example\n * ```ts\n * // a burst, 3 uses per 10 minutes per user, then it refuses until a slot frees\n * \\@Gated(Cooldown('10m', { limit: 3 }))\n * \\@SlashRoute('report')\n * class ReportHandler extends SlashHandler<'report'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function Cooldown(\n duration: number | ValidDuration,\n options?: CooldownOptions\n): EffectGate<GateContextBase, 'Cooldown'> {\n let windowMs: number;\n if (typeof duration === 'number') {\n windowMs = duration * 1000;\n } else {\n const parsed = parseDuration(duration);\n if (parsed === null) throw new SeedcordTypeError(SeedcordErrorCode.GateInvalidCooldownDuration, [duration]);\n windowMs = parsed;\n }\n // a zero or negative window would never limit, refuse it the same way an unparseable string is refused\n if (windowMs <= 0) {\n throw new SeedcordTypeError(SeedcordErrorCode.GateInvalidCooldownDuration, [String(duration)]);\n }\n\n const per = options?.per ?? 'user';\n // omit limit when unset so the limiter applies its default of 1, exactOptionalPropertyTypes rejects an explicit undefined\n const window = options?.limit === undefined ? { windowMs } : { windowMs, limit: options.limit };\n const anonId = anonSeq++;\n // routed keys are stable across restarts, so a durable store rebuilds the same window\n const keyOf = (ctx: GateContextBase): string =>\n `cooldown:${ctx.routeId ?? `anon${anonId}`}:${per}:w${windowMs}:l${options?.limit ?? 1}:${scopeValue(ctx, per)}`;\n\n return defineEffectGate(\n 'Cooldown',\n async (ctx) => {\n const result = await ctx.core.rateLimiter.peek(keyOf(ctx), window);\n if (!result.limited) return;\n if (options?.notice) throw options.notice(result.resetAt);\n throw new OnCooldown(result.resetAt, options?.message?.(result.resetAt));\n },\n async (ctx) => {\n await ctx.core.rateLimiter.charge(keyOf(ctx), window);\n }\n );\n}\n","/**\n * Throw to stop a handler with no reply and no report.\n *\n * The framework boundary catches `Silence` before {@link Notice}, makes zero Discord calls, and stops.\n * Ideally you'd only throw this in `EventHandlers` (or `Gates` for those), because it doesn't make sense to\n * leave the user with no reply for an interaction.\n *\n * @example\n * ```ts\n * import { Silence } from '@seedcord/gateway';\n *\n * // before any reply or defer, drop the interaction with no reply and no report\n * if (await isBlacklisted(interaction.user.id)) throw new Silence('blacklisted user');\n * ```\n */\nexport class Silence extends Error {\n /**\n * @param reason - Optional note written only to a debug log, never shown to the user or reported.\n */\n public constructor(public readonly reason?: string) {\n super(reason ?? 'Silence');\n\n Error.captureStackTrace(this, this.constructor);\n }\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordRangeError } from '@seedcord/errors/internal';\n\nimport type { PageView } from './PageView';\n\n/**\n * Pure page math, usable headless. Clamps `page` into range and slices the window.\n *\n * @param items - The full list to page over.\n * @param page - The requested zero-based page, clamped into `[0, totalPages - 1]`.\n * @param perPage - The page size. Must be a positive integer.\n * @returns The sliced {@link PageView}, with `totalPages` always known.\n * @throws SeedcordRangeError when `perPage` is not a positive integer.\n */\nexport function paginate<Item>(items: readonly Item[], page: number, perPage: number): PageView<Item> {\n if (!Number.isSafeInteger(perPage) || perPage <= 0) {\n throw new SeedcordRangeError(SeedcordErrorCode.PaginationInvalidPerPage, [perPage]);\n }\n\n const totalPages = Math.max(1, Math.ceil(items.length / perPage));\n // a headless caller can pass a non-integer or out-of-range page.\n const clamped = Math.min(Math.max(Math.trunc(page), 0), totalPages - 1);\n const start = clamped * perPage;\n\n return {\n items: items.slice(start, start + perPage),\n page: clamped,\n perPage,\n totalPages,\n hasPrev: clamped > 0,\n hasNext: clamped < totalPages - 1\n };\n}\n","import 'reflect-metadata';\n\nexport type * from '@registries/ContextMenuRegistry';\nexport type * from '@registries/SlashOptionRegistry';\n\nexport { RegisterCommand } from '@decorators/Command';\nexport { SelectMenuKind } from '@decorators/interactionRoutes';\nexport {\n AutocompleteRoute,\n ButtonRoute,\n ContextMenuRoute,\n ModalRoute,\n SelectMenuRoute,\n SlashRoute\n} from '@decorators/routes';\n\nexport { DispatchContext } from '@src/dispatch/DispatchContext';\nexport type { DispatchState } from '@src/dispatch/DispatchContext';\n\nexport { BaseHandler } from '@src/handlers/BaseHandler';\nexport { RepliableHandler } from '@src/handlers/RepliableHandler';\n\nexport type { CoreBase } from '@interfaces/CoreBase';\n\nexport { defineEffectGate, defineGate } from '@gates/Gate';\nexport type { EffectGate, Gate, GateContextBase, GuildPermissionsContext, RequiredOf } from '@gates/Gate';\nexport { and, or } from '@gates/combinators';\nexport { DmOnly, GuildOnly, OwnerOnly } from '@gates/catalog/access';\nexport { Cooldown, type CooldownOptions } from '@gates/catalog/Cooldown';\nexport { RequireBotPermissions, RequirePermissions, RequireRole } from '@gates/catalog/permissions';\nexport type { PermissionScope, RequirePermissionsOptions, RequireRoleOptions } from '@gates/catalog/permissions';\nexport type { GateNoticeOptions } from '@gates/catalog/options';\n\nexport { BuilderComponent, RowComponent } from '@components/Component';\nexport { type RowType, type BuilderType } from '@components/builderTypes';\n\nexport { Notice } from '@stops/Notice';\nexport { Fault } from '@stops/Fault';\nexport { Silence } from '@stops/Silence';\n\nexport { CustomId } from '@customId/CustomId';\n\nexport type { AutocompleteOptions } from '@inputs/AutocompleteOptions';\n\nexport { paginate } from '@pagination/paginate';\nexport { type PageView } from '@pagination/PageView';\n\n/** Package version */\nexport const version = process.env.PACKAGE_VERSION ?? '0.0.0';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["CommandMetadataKey","SeedcordError","SeedcordErrorCode","contextMenuRouteOf","selectMenuRouteOf","Logger","Notice","NoticeCard","defineGate","runCheck","markCommits","Notice","NeedsAny","NotAllowed","defineGate","pickNotice","NotOwner","NotInGuild","NotInDm","SeedcordTypeError","SeedcordErrorCode","defineEffectGate","OnCooldown","SeedcordRangeError","SeedcordErrorCode"],"sources":["../src/decorators/Command.ts","../src/decorators/routes.ts","../src/dispatch/DispatchContext.ts","../src/handlers/BaseHandler.ts","../src/handlers/RepliableHandler.ts","../src/stops/Fault.ts","../src/gates/combinators.ts","../src/gates/catalog/access.ts","../src/gates/catalog/Cooldown.ts","../src/pagination/paginate.ts","../src/index.ts"],"sourcesContent":["import 'reflect-metadata';\n\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\n\nimport { CommandMetadataKey } from '@src/metadataKeys';\n\nimport type { BuilderComponent } from '@components/Component';\nimport type { Constructor } from 'type-fest';\n\ntype CommandCtor = Constructor<BuilderComponent<'command' | 'context_menu'>>;\n\ninterface GlobalMeta {\n scope: 'global';\n}\n\ninterface GuildMeta {\n scope: 'guild';\n guilds: string[];\n}\n\nexport type CommandMeta = GlobalMeta | GuildMeta;\n\ntype CommandScope = CommandMeta['scope'];\n\n/**\n * Attaches deployment metadata so the framework registers this command globally or in specific guilds.\n *\n * @param scope - Must be 'global' for global registration\n * @decorator\n * @example\n * ```typescript\n * \\@RegisterCommand('global')\n * class PingCommand extends BuilderComponent<'command'> {} // or BuilderComponent<'context_menu'>\n * ```\n */\nexport function RegisterCommand(scope: 'global'): (ctor: CommandCtor) => void;\n\n/**\n * Registers a command for specific guild deployment.\n *\n * @param scope - Must be 'guild' for guild-specific registration\n * @param guilds - Array of guild IDs where the command should be registered\n * @decorator\n * @example\n * ```typescript\n * \\@RegisterCommand('guild', ['123456789'])\n * class AdminCommand extends BuilderComponent<'command'> {} // or BuilderComponent<'context_menu'>\n * ```\n */\nexport function RegisterCommand(scope: 'guild', guilds: string[]): (ctor: CommandCtor) => void;\n\nexport function RegisterCommand(scope: CommandScope, guilds: string[] = []) {\n return (ctor: CommandCtor): void => {\n const existingMeta = Reflect.getOwnMetadata(CommandMetadataKey, ctor) as CommandMeta | undefined;\n if (existingMeta) {\n throw new SeedcordError(SeedcordErrorCode.DecoratorCommandAlreadyRegistered, [\n ctor.name,\n existingMeta.scope,\n scope\n ]);\n }\n\n if (scope === 'global' && guilds.length > 0) {\n throw new SeedcordError(SeedcordErrorCode.DecoratorCommandGlobalWithGuilds);\n }\n\n if (scope === 'guild' && (!Array.isArray(guilds) || guilds.length === 0)) {\n throw new SeedcordError(SeedcordErrorCode.DecoratorCommandGuildWithoutGuilds);\n }\n\n const meta: GlobalMeta | GuildMeta = scope === 'global' ? { scope } : { scope, guilds };\n Reflect.defineMetadata(CommandMetadataKey, meta, ctor);\n };\n}\n","import {\n contextMenuRouteOf,\n selectMenuRouteOf,\n storeComponentRoute,\n storeInteractionRoute\n} from '@decorators/interactionRoutes';\nimport { InteractionRoutes } from '@src/metadataKeys';\n\nimport type { AnyCustomId } from '@customId/CustomId';\nimport type { SelectMenuKind } from '@decorators/interactionRoutes';\nimport type { MessageContextMenuRegistry, UserContextMenuRegistry } from '@registries/ContextMenuRegistry';\nimport type { SlashOptionRegistry } from '@registries/SlashOptionRegistry';\nimport type { ApplicationCommandType } from 'discord-api-types/v10';\nimport type { Constructor } from 'type-fest';\n\ntype ContextMenuKind = ApplicationCommandType.User | ApplicationCommandType.Message;\n\ntype ComponentBrand = 'button' | 'modal' | SelectMenuKind;\n\n// phantom brands keep the decorators off transport-specific classes\ntype AnyHandlerCtor = new (...args: any[]) => unknown;\n\ntype SlashRouteOf<TCtor extends AnyHandlerCtor> =\n InstanceType<TCtor> extends {\n __slashRoute?: infer Route extends keyof SlashOptionRegistry;\n }\n ? Route\n : never;\n\ntype AutocompleteRouteOf<TCtor extends AnyHandlerCtor> =\n InstanceType<TCtor> extends {\n __autocompleteRoute?: infer Route extends keyof SlashOptionRegistry;\n }\n ? Route\n : never;\n\ntype ContextMenuKindOf<TCtor extends AnyHandlerCtor> =\n InstanceType<TCtor> extends {\n __ctxKind?: infer Kind extends ContextMenuKind;\n }\n ? Kind\n : never;\n\ntype ComponentOf<TCtor extends AnyHandlerCtor> =\n InstanceType<TCtor> extends {\n __component?: infer Brand extends ComponentBrand;\n }\n ? Brand\n : never;\n\ntype DefsOf<TCtor extends AnyHandlerCtor> =\n InstanceType<TCtor> extends {\n __componentDefs?: infer Defs extends readonly AnyCustomId[];\n }\n ? Defs\n : never;\n\ntype AssertSlashRoute<Route extends keyof SlashOptionRegistry, TCtor extends AnyHandlerCtor> = [Route] extends [\n SlashRouteOf<TCtor>\n]\n ? [SlashRouteOf<TCtor>] extends [Route]\n ? TCtor\n : Constructor<['SlashHandler declares a route the SlashRoute decorator does not list', SlashRouteOf<TCtor>]>\n : Constructor<['SlashRoute does not match the SlashHandler generic', Route]>;\n\ntype AssertAutocompleteRoute<Route extends keyof SlashOptionRegistry, TCtor extends AnyHandlerCtor> = [Route] extends [\n AutocompleteRouteOf<TCtor>\n]\n ? [AutocompleteRouteOf<TCtor>] extends [Route]\n ? TCtor\n : Constructor<\n [\n 'AutocompleteHandler declares a command the AutocompleteRoute decorator does not list',\n AutocompleteRouteOf<TCtor>\n ]\n >\n : Constructor<['AutocompleteRoute does not match the AutocompleteHandler generic', Route]>;\n\ntype AssertContextMenuRoute<Kind extends ContextMenuKind, TCtor extends AnyHandlerCtor> = [Kind] extends [\n ContextMenuKindOf<TCtor>\n]\n ? [ContextMenuKindOf<TCtor>] extends [Kind]\n ? TCtor\n : Constructor<\n [\n 'ContextMenuHandler declares a kind the ContextMenuRoute decorator does not match',\n ContextMenuKindOf<TCtor>\n ]\n >\n : Constructor<['ContextMenuRoute does not match the ContextMenuHandler generic', Kind]>;\n\n// one assignability direction for the defs, a bidirectional check would reject const-inferred readonly tuples\ntype AssertComponentRoute<\n Brand extends ComponentBrand,\n Defs extends readonly AnyCustomId[],\n TCtor extends AnyHandlerCtor\n> = [ComponentOf<TCtor>] extends [Brand]\n ? [Brand] extends [ComponentOf<TCtor>]\n ? [DefsOf<TCtor>] extends [Defs]\n ? TCtor\n : Constructor<['the customId definitions do not match the handler generic', DefsOf<TCtor>]>\n : Constructor<['the decorator does not match the handler kind', ComponentOf<TCtor>]>\n : Constructor<['the decorator does not match the handler kind', ComponentOf<TCtor>]>;\n\ntype NamesFor<Kind extends ContextMenuKind> = Kind extends ApplicationCommandType.User\n ? keyof UserContextMenuRegistry\n : keyof MessageContextMenuRegistry;\n\n/**\n * Routes one or more slash commands to a `SlashHandler`.\n *\n * Pass the same route string(s) as the handler's generic. A single command reads `this.options`, several\n * commands branch with `this.match`. The decorator routes and the generic must match exactly, so listing\n * fewer or more than the handler declares is a compile error. Subcommands use a slash path.\n *\n * @param routes - The route string(s) this handler serves, e.g. `'ban'`, `'ban', 'kick'`, or `'demo/setup'`.\n * @decorator\n * @example\n * ```ts\n * \\@SlashRoute('ban')\n * class BanHandler extends SlashHandler<'ban'> {\n * async execute() {\n * const target = this.options.getUser('target');\n * }\n * }\n * ```\n */\nexport function SlashRoute<const Route extends keyof SlashOptionRegistry>(...routes: Route[]) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertSlashRoute<Route, TCtor>): void {\n storeInteractionRoute(InteractionRoutes.Slash, routes, constructor);\n };\n}\n\n/**\n * Routes one or more commands' autocomplete to an `AutocompleteHandler`.\n *\n * Pass the same command route string(s) as the handler's generic. One command branches with `this.match`\n * over its autocompletable fields, several commands share one handler whose arms span every command's\n * fields. The decorator routes and the generic must match exactly, so listing fewer or more than the\n * handler declares is a compile error.\n *\n * @param routes - The command route string(s) this handler serves, e.g. `'search'` or `'search', 'find'`.\n * @decorator\n * @example\n * ```ts\n * \\@AutocompleteRoute('search')\n * class SearchAutocomplete extends AutocompleteHandler<'search'> {\n * async execute() {\n * await this.match({ query: (value, respond) => respond([{ name: value, value }]) });\n * }\n * }\n * ```\n */\nexport function AutocompleteRoute<const Route extends keyof SlashOptionRegistry>(...routes: Route[]) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertAutocompleteRoute<Route, TCtor>): void {\n storeInteractionRoute(InteractionRoutes.Autocomplete, routes, constructor);\n };\n}\n\n/**\n * Routes one or more context-menu commands to a `ContextMenuHandler`.\n *\n * Pass the kind (`ApplicationCommandType.User` or `ApplicationCommandType.Message`) and the command name(s),\n * each checked against that kind's registry, so a typo is a compile error. The handler's generic must\n * declare the same kind, cross-checked both directions. Context menus carry no options, so a multi-name\n * handler reads `this.target` uniformly with no branch.\n *\n * @param kind - The context-menu kind, `ApplicationCommandType.User` or `ApplicationCommandType.Message`.\n * @param names - The command name(s) this handler serves, keyed off the matching registry.\n * @decorator\n * @example\n * ```ts\n * \\@ContextMenuRoute(ApplicationCommandType.User, 'View Profile')\n * class ViewProfile extends ContextMenuHandler<ApplicationCommandType.User> {\n * async execute() {\n * const user = this.target;\n * }\n * }\n * ```\n */\nexport function ContextMenuRoute<const Kind extends ContextMenuKind>(kind: Kind, ...names: NamesFor<Kind>[]) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertContextMenuRoute<Kind, TCtor>): void {\n storeInteractionRoute(contextMenuRouteOf(kind), names, constructor);\n };\n}\n\n/**\n * Routes button interactions to handler classes.\n *\n * Pass the {@link CustomId} definition(s) this handler decodes and list the same ones in the handler's\n * generic. Passing different definitions to the decorator and the generic is a compile error. Routing\n * matches the stable prefix, so a wire minted from an older shape still reaches the handler, where\n * reading this.params throws StaleCustomId and the controller boundary turns it into a reply.\n *\n * @param defs - The customId definition(s) this handler decodes, one per route.\n * @decorator\n */\nexport function ButtonRoute<const Defs extends readonly AnyCustomId[]>(...defs: Defs) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertComponentRoute<'button', Defs, TCtor>): void {\n storeComponentRoute(InteractionRoutes.Button, defs, constructor);\n };\n}\n\n/**\n * Routes modal submissions to handler classes.\n *\n * Pass the {@link CustomId} definition(s) this handler decodes and list the same ones in the handler's\n * generic. Passing different definitions to the decorator and the generic is a compile error. Routing\n * matches the stable prefix, so an older-shape wire still reaches the handler and throws StaleCustomId\n * on read, the same as a button route.\n *\n * @param defs - The customId definition(s) this handler decodes, one per route.\n * @decorator\n */\nexport function ModalRoute<const Defs extends readonly AnyCustomId[]>(...defs: Defs) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertComponentRoute<'modal', Defs, TCtor>): void {\n storeComponentRoute(InteractionRoutes.Modal, defs, constructor);\n };\n}\n\n/**\n * Routes select menu interactions to handler classes.\n *\n * Pass the select kind and the {@link CustomId} definition(s) this handler decodes. The handler's\n * generic must list the same kind and definitions, or it is a compile error.\n *\n * @param type - Select menu kind from {@link SelectMenuKind}.\n * @param defs - The customId definition(s) this handler decodes, one per route.\n * @decorator\n *\n * @example\n * ```typescript\n * \\@SelectMenuRoute(SelectMenuKind.User, AssignId)\n * class AssignSelect extends SelectMenuHandler<SelectMenuKind.User, [typeof AssignId]> {}\n * ```\n */\nexport function SelectMenuRoute<const Kind extends SelectMenuKind, const Defs extends readonly AnyCustomId[]>(\n type: Kind,\n ...defs: Defs\n) {\n return function <TCtor extends AnyHandlerCtor>(constructor: AssertComponentRoute<Kind, Defs, TCtor>): void {\n storeComponentRoute(selectMenuRouteOf(type), defs, constructor);\n };\n}\n","/**\n * The per-dispatch bag. Any code can merge fields into it by declaration merging, the\n * same pattern as {@link SlashOptionRegistry}. It stays empty until one does, so `keyof DispatchState` is\n * `never` and the bag is inert.\n */\nexport interface DispatchState {}\n\n/**\n * A typed bag allocated once per interaction dispatch and handed to the handler. The middleware and i18n\n * work reads and writes it through {@link DispatchState}. Today the bag is empty, so it only carries the\n * dispatched `routeId`.\n */\nexport class DispatchContext {\n private readonly state: Partial<DispatchState> = {};\n\n constructor(public readonly routeId: string | null) {}\n\n set<Key extends keyof DispatchState>(key: Key, value: DispatchState[Key]): void {\n this.state[key] = value;\n }\n\n get<Key extends keyof DispatchState>(key: Key): DispatchState[Key] | undefined {\n return this.state[key];\n }\n}\n","import { Logger } from '@seedcord/logger';\n\nimport type { CoreBase } from '@interfaces/CoreBase';\nimport type { LoggerChannelId } from '@seedcord/logger';\nimport type { DispatchContext } from '@src/dispatch/DispatchContext';\n\n/**\n * Base class every transport handler extends. Don't register handlers directly, use the more specific\n * handler subclasses.\n *\n * @typeParam Event - The event or interaction this handler processes\n * @typeParam TCore - The transport's Core\n */\nexport abstract class BaseHandler<Event, TCore extends CoreBase> {\n protected readonly event: Event;\n protected readonly logger: Logger;\n // absent on event handlers\n protected readonly dispatch?: DispatchContext | undefined;\n\n protected constructor(\n event: Event,\n public readonly core: TCore,\n dispatch?: DispatchContext,\n channel?: LoggerChannelId\n ) {\n this.event = event;\n this.logger = new Logger(this.constructor.name, { channel });\n this.dispatch = dispatch;\n }\n\n /**\n * Holds the main logic of your handler. The dispatcher calls it after the handler's gates pass, so a\n * gate that refuses stops `execute()` from running.\n */\n abstract execute(): Promise<void>;\n}\n","import { BaseHandler } from './BaseHandler';\n\nimport type { CoreBase } from '@interfaces/CoreBase';\nimport type { BaseReplySender } from '@reply/BaseReplySender';\nimport type { DeferOpts, ReplyResponse, SendOpts } from '@seedcord/types';\nimport type { DispatchContext } from '@src/dispatch/DispatchContext';\n\n/**\n * Shared base the repliable handlers on both transports extend. Defines the reply members over the sender\n * the transport builds.\n *\n * @typeParam Event - The repliable interaction type this handler processes\n * @typeParam TCore - The transport's Core\n * @typeParam TMessage - The transport's created-message lens\n * @typeParam TSender - The transport's reply sender\n */\nexport abstract class RepliableHandler<\n Event,\n TCore extends CoreBase,\n TMessage extends { id: string },\n TSender extends BaseReplySender<TMessage>\n> extends BaseHandler<Event, TCore> {\n protected readonly sender: TSender;\n protected readonly routeId: string;\n\n protected constructor(event: Event, core: TCore, dispatch?: DispatchContext) {\n super(event, core, dispatch, 'interactions');\n this.routeId = dispatch?.routeId ?? this.constructor.name;\n // the override runs before its own field initializers\n this.sender = this.buildSender(event, core, this.routeId);\n }\n\n protected abstract buildSender(event: Event, core: TCore, routeId: string): TSender;\n\n /** @internal The dispatcher's fault boundary replies through the live ack state. */\n public getSender(): TSender {\n return this.sender;\n }\n\n /** Send the initial response, exactly once. */\n protected reply(response: ReplyResponse | string, opts?: SendOpts): Promise<TMessage> {\n return this.sender.reply(response, opts);\n }\n\n /** Show a \"thinking\" placeholder, then fill it later with {@link edit}. */\n protected defer(opts?: DeferOpts): Promise<void> {\n return this.sender.defer(opts);\n }\n\n /** Send a new message once the interaction is acknowledged. */\n protected followUp(response: ReplyResponse | string, opts?: SendOpts): Promise<TMessage> {\n return this.sender.followUp(response, opts);\n }\n\n /** Rewrite the initial reply or deferred placeholder. The targeted form rewrites a message a prior send returned. */\n protected edit(response: ReplyResponse | string): Promise<TMessage>;\n protected edit(target: TMessage, response: ReplyResponse | string): Promise<TMessage>;\n protected edit(\n targetOrResponse: TMessage | ReplyResponse | string,\n maybeResponse?: ReplyResponse | string\n ): Promise<TMessage> {\n // justified: the overloads narrow targetOrResponse to a response once maybeResponse is absent\n if (maybeResponse === undefined) return this.sender.edit(targetOrResponse as ReplyResponse | string);\n // justified: the overloads narrow targetOrResponse to a target message once maybeResponse is defined\n return this.sender.edit(targetOrResponse as TMessage, maybeResponse);\n }\n\n /** Routes to reply, followUp, or edit based on the current ack state. */\n protected send(response: ReplyResponse | string, opts?: SendOpts): Promise<TMessage> {\n return this.sender.send(response, opts);\n }\n\n /** Delete the initial reply or deferred placeholder. Pass a target to delete a message a prior send returned. */\n protected delete(target?: TMessage): Promise<void> {\n return target === undefined ? this.sender.delete() : this.sender.delete(target);\n }\n}\n","import { Notice } from './Notice';\nimport { NoticeCard } from './NoticeCard';\n\nimport type { RenderContext, ReplyResponse } from '@seedcord/types';\n\n/**\n * A generic fault you throw after catching an error you do not have a specific message for.\n *\n * The user sees a fixed generic reply with the tracking uuid, never the cause. `report` defaults to\n * `true`, so the framework logs it and publishes it to the `handledException` bus. Pass `report: false`\n * to show the generic reply without the bus publish. The original error is stored as the standard\n * `cause`, so the real stack reaches the webhook. For a fault the user should see a real message,\n * subclass {@link Notice} and write your own `render` instead.\n *\n * The framework also renders this for an unhandled throw, where it points the user at\n * `ctx.developerUsername`.\n *\n * @example\n * ```ts\n * import { Fault } from '@seedcord/gateway';\n *\n * try {\n * await db.write(record);\n * } catch (cause) {\n * // user sees the generic reply with the uuid, the real error rides along as cause for the webhook\n * throw new Fault({ cause });\n *\n * // pass report: false to show the same reply without publishing to the handledException bus\n * // throw new Fault({ cause, report: false });\n * }\n * ```\n */\nexport class Fault extends Notice {\n public constructor(options?: { cause?: unknown; report?: boolean }) {\n super('A fault occurred', options?.cause === undefined ? undefined : { cause: options.cause });\n this.report = options?.report ?? true;\n }\n\n public render(ctx: RenderContext): ReplyResponse {\n const contact = ctx.developerUsername ?? 'the developer';\n const card = new NoticeCard(\n `Something went wrong. Please reach out to ${contact} with a way to reproduce the error and the following:\\n### UUID: \\`${ctx.uuid}\\``,\n 'Error'\n );\n return { components: [card.component] };\n }\n}\n","import { NeedsAny, NotAllowed } from '@notices/index';\nimport { Fault } from '@stops/Fault';\nimport { Notice } from '@stops/Notice';\n\nimport { markCommits, rollbackCommits, runCheck } from './effects';\nimport { defineGate } from './Gate';\n\nimport type { Gate, GateContextBase, RequiredOf } from './Gate';\nimport type { IntersectRequired, JoinNames, TwoOrMore } from './matching';\n\n/**\n * Runs each gate in order and refuses on the first refusal. Takes two or more arms. The required\n * context is the intersection of the arms, so an event-only and an interaction-only gate cannot be\n * combined.\n *\n * @typeParam Gates - The tuple of two or more gate arms, run left to right.\n * @param gates - The gate arms to run in order, all refused on the first refusal.\n *\n * @see {@link or}\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n *\n * \\@Gated(and(GuildOnly(), RequirePermissions([PermissionFlagsBits.BanMembers])))\n * \\@SlashRoute('ban')\n * class BanHandler extends SlashHandler<'ban'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function and<Gates extends TwoOrMore<Gate<GateContextBase>>>(\n ...gates: Gates\n): Gate<IntersectRequired<Gates> & GateContextBase, JoinNames<Gates, ' & '>>;\nexport function and(...gates: readonly Gate<GateContextBase>[]): Gate<GateContextBase> {\n return defineGate(gates.map((gate) => gate.name).join(' & '), async (ctx) => {\n for (const gate of gates) {\n await runCheck(gate, ctx);\n }\n });\n}\n\n// the caller-supplied refusal when every or arm refuses, replacing the default list or neutral refusal\ninterface OrOptions {\n fail: Notice | ((ctx: GateContextBase) => Notice);\n}\n\n// a gate has a check method, the options object does not\nfunction isOrOptions(arg: Gate<GateContextBase> | OrOptions): arg is OrOptions {\n return !('check' in arg);\n}\n\n/**\n * Runs each gate in order and passes on the first arm that passes. Takes two or more arms. The\n * required context is the union of the arms, so a handler that matches any one arm fits. When every\n * arm refuses it throws the trailing {@link OrOptions} `fail` if given, else an auto list of the\n * arms derived from the summary field, else a default refusal. The trailing options object does not\n * count as an arm.\n *\n * @typeParam Gates - The tuple of two or more gate arms, tried left to right.\n * @param gates - The gate arms to try in order, with an optional trailing {@link OrOptions} object.\n *\n * @see {@link and}\n *\n * @example\n * ```ts\n * \\@Gated(or(OwnerOnly(), RequireRole('123456789012345678')))\n * \\@SlashRoute('admin')\n * class AdminHandler extends SlashHandler<'admin'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function or<Gates extends TwoOrMore<Gate<GateContextBase>>>(\n ...gates: Gates\n): Gate<RequiredOf<Gates[number]>, JoinNames<Gates, ' | '>>;\n/**\n * @example\n * ```ts\n * // custom refusal when every arm refuses\n * or(OwnerOnly(), RequireRole('123456789012345678'), { fail: new NotAllowedNotice() });\n * ```\n */\nexport function or<Gates extends TwoOrMore<Gate<GateContextBase>>>(\n ...args: [...Gates, OrOptions]\n): Gate<RequiredOf<Gates[number]>, JoinNames<Gates, ' | '>>;\nexport function or(...args: readonly (Gate<GateContextBase> | OrOptions)[]): Gate<GateContextBase> {\n const last = args.at(-1);\n const options = last !== undefined && isOrOptions(last) ? last : undefined;\n const gates = (options ? args.slice(0, -1) : args) as readonly Gate<GateContextBase>[];\n\n return defineGate(gates.map((gate) => gate.name).join(' | '), async (ctx) => {\n const summaries: string[] = [];\n let everyArmHasSummary = true;\n for (const gate of gates) {\n const mark = markCommits(ctx);\n try {\n await runCheck(gate, ctx);\n return;\n } catch (error) {\n // only a refusal is an arm declining, a Fault (even report-false), a Silence, or a raw error stops everything\n if (error instanceof Notice && !(error instanceof Fault) && !error.report) {\n // the arm may have queued an effect's commit before refusing, drop it so the winner does not carry it\n rollbackCommits(ctx, mark);\n if (error.summary === undefined) everyArmHasSummary = false;\n else summaries.push(error.summary);\n continue;\n }\n throw error;\n }\n }\n if (options) throw typeof options.fail === 'function' ? options.fail(ctx) : options.fail;\n // the auto-list shows only when every refusal gave a summary, a partial list would mislead by omission\n if (everyArmHasSummary && summaries.length > 0) throw new NeedsAny(summaries);\n throw new NotAllowed();\n });\n}\n","import { defineGate } from '@gates/Gate';\nimport { NotInDm, NotInGuild, NotOwner } from '@notices/index';\n\nimport { pickNotice } from './options';\n\nimport type { GateNoticeOptions } from './options';\nimport type { Gate, GateContextBase } from '@gates/Gate';\n\n/**\n * Passes only for a user id listed in `config.ownerIds`, else refuses.\n *\n * Agnostic, so it attaches to interaction and event handlers alike. With no `ownerIds` configured it refuses every caller. Pass {@link GateNoticeOptions} to reword or replace the refusal.\n *\n * @param options - Reword the default refusal with `message`, or replace it with `notice`.\n *\n * @see the `@Gated` decorator from `seedcord`\n *\n * @example\n * ```ts\n * \\@Gated(OwnerOnly())\n * \\@SlashRoute('shutdown')\n * class ShutdownHandler extends SlashHandler<'shutdown'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * // reword the refusal, keeping the embed styling\n * OwnerOnly({ message: 'Owners only.' });\n * ```\n */\nexport function OwnerOnly(options?: GateNoticeOptions): Gate<GateContextBase, 'OwnerOnly'> {\n return defineGate('OwnerOnly', (ctx) => {\n const owners = ctx.core.config.ownerIds ?? [];\n if (ctx.userId !== null && owners.includes(ctx.userId)) return;\n throw pickNotice(options, (message) => new NotOwner(message));\n });\n}\n\n/**\n * Passes inside a guild, else refuses.\n *\n * Agnostic, so it attaches to any handler kind. Often paired with `RequirePermissions` in an {@link and}.\n *\n * @param options - Reword the default refusal with `message`, or replace it with `notice`.\n *\n * @see the `@Gated` decorator from `seedcord`\n *\n * @example\n * ```ts\n * import { PermissionFlagsBits } from 'discord.js';\n *\n * \\@Gated(GuildOnly(), RequirePermissions([PermissionFlagsBits.Administrator]))\n * \\@SlashRoute('maintenance')\n * class Maintenance extends SlashHandler<'maintenance'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function GuildOnly(options?: GateNoticeOptions): Gate<GateContextBase, 'GuildOnly'> {\n return defineGate('GuildOnly', (ctx) => {\n if (ctx.guildId) return;\n throw pickNotice(options, (message) => new NotInGuild(message));\n });\n}\n\n/**\n * Passes in a direct message, else refuses.\n *\n * Agnostic, so it attaches to any handler kind. The inverse of {@link GuildOnly}, so combining the two in an {@link and} can never pass.\n *\n * @param options - Reword the default refusal with `message`, or replace it with `notice`.\n *\n * @see the `@Gated` decorator from `seedcord`\n *\n * @example\n * ```ts\n * \\@Gated(DmOnly())\n * \\@SlashRoute('verify')\n * class VerifyHandler extends SlashHandler<'verify'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function DmOnly(options?: GateNoticeOptions): Gate<GateContextBase, 'DmOnly'> {\n return defineGate('DmOnly', (ctx) => {\n if (!ctx.guildId) return;\n throw pickNotice(options, (message) => new NotInDm(message));\n });\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\nimport { parseDuration, type ValidDuration } from '@seedcord/utils';\n\nimport { defineEffectGate } from '@gates/Gate';\nimport { OnCooldown } from '@notices/index';\n\nimport type { EffectGate, GateContextBase } from '@gates/Gate';\nimport type { EpochMs } from '@seedcord/types';\nimport type { Notice } from '@stops/Notice';\n\n/**\n * Options for {@link Cooldown}. `per` sets the bucket the window applies to and `limit` the uses allowed per\n * window. `message` rewords the refusal and `notice` replaces it, both receiving the epoch ms the key frees\n * up so the refusal can show the retry time.\n *\n * @example\n * ```ts\n * // one use per channel, rewording the refusal with the retry time\n * Cooldown('10s', {\n * per: 'channel',\n * message: (resetAt) => `Slow down. Try again <t:${Math.round(resetAt / 1000)}:R>.`\n * });\n * ```\n *\n * @example\n * ```ts\n * // five uses per minute, per user\n * Cooldown('1m', { limit: 5 });\n * ```\n */\nexport interface CooldownOptions {\n /**\n * The bucket the cooldown window applies to. 'user' scopes by user ID, falls back to global when the source carries no user id. 'guild' scopes by guild ID (falls back to global if no guild), and 'channel' scopes by channel ID (falls back to global if no channel).\n *\n * @defaultValue `'user'`\n */\n per?: 'user' | 'guild' | 'channel';\n /**\n * Uses allowed inside one window before the gate refuses.\n *\n * @defaultValue `1`\n */\n limit?: number;\n /**\n * Reword the refusal, keeping the standard notice card. Receives the epoch ms the key frees up, so the\n * text can include the retry time with `<t:${Math.round(resetAt / 1000)}:R>`.\n */\n message?: (resetAt: EpochMs) => string;\n /**\n * Replace the refusal Notice entirely, for full control or a translated copy. Receives the epoch ms the\n * key frees up.\n */\n notice?: (resetAt: EpochMs) => Notice;\n}\n\n// off-route ctxs have no route to key on, so each Cooldown() gets its own id to keep unrelated event handlers isolated\nlet anonSeq = 0;\n\nfunction scopeValue(ctx: GateContextBase, per: 'user' | 'guild' | 'channel'): string {\n if (per === 'guild') return ctx.guildId ?? 'global';\n if (per === 'channel') return ctx.channelId ?? 'global';\n return ctx.userId ?? 'global';\n}\n\n/**\n * Allows `limit` uses per window, scoped by `per`. A number `duration` is **seconds**, a string is\n * a duration like `30m` or `24h`. An unparseable string throws a **SeedcordTypeError** at construction. The\n * slot is charged in commit, only after the whole gate set passes, so a later refusal never burns the cooldown.\n * That split also means two requests racing the same key can both pass before either charges the slot.\n * The key combines the handler's route with the window settings, so two different handlers keep separate\n * windows. Reword the refusal with {@link CooldownOptions.message} or replace it with {@link CooldownOptions.notice}.\n *\n * @param duration - A number is seconds, a string is a duration like `30m` or `24h`. An unparseable string throws a **SeedcordTypeError**.\n * @param options - Sets the scope with `per`, the uses per window with `limit`, and the refusal text with `message` or `notice`.\n *\n * @see the `@Gated` decorator from `seedcord`\n * @see {@link IRateLimiter}\n *\n * @example\n * ```ts\n * // a number argument is SECONDS\n * \\@Gated(Cooldown(5))\n * \\@SlashRoute('daily')\n * class DailyHandler extends SlashHandler<'daily'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * // a string is a duration, here scoped per guild (the default is per user)\n * Cooldown('30m', { per: 'guild' });\n * ```\n *\n * @example\n * ```ts\n * // a burst, 3 uses per 10 minutes per user, then it refuses until a slot frees\n * \\@Gated(Cooldown('10m', { limit: 3 }))\n * \\@SlashRoute('report')\n * class ReportHandler extends SlashHandler<'report'> {\n * async execute() {\n * // ...\n * }\n * }\n * ```\n */\nexport function Cooldown(\n duration: number | ValidDuration,\n options?: CooldownOptions\n): EffectGate<GateContextBase, 'Cooldown'> {\n let windowMs: number;\n if (typeof duration === 'number') {\n windowMs = duration * 1000;\n } else {\n const parsed = parseDuration(duration);\n if (parsed === null) throw new SeedcordTypeError(SeedcordErrorCode.GateInvalidCooldownDuration, [duration]);\n windowMs = parsed;\n }\n // a zero or negative window would never limit, refuse it the same way an unparseable string is refused\n if (windowMs <= 0) {\n throw new SeedcordTypeError(SeedcordErrorCode.GateInvalidCooldownDuration, [String(duration)]);\n }\n\n const per = options?.per ?? 'user';\n // omit limit when unset so the limiter applies its default of 1, exactOptionalPropertyTypes rejects an explicit undefined\n const window = options?.limit === undefined ? { windowMs } : { windowMs, limit: options.limit };\n const anonId = anonSeq++;\n // routed keys are stable across restarts, so a durable store rebuilds the same window\n const keyOf = (ctx: GateContextBase): string =>\n `cooldown:${ctx.routeId ?? `anon${anonId}`}:${per}:w${windowMs}:l${options?.limit ?? 1}:${scopeValue(ctx, per)}`;\n\n return defineEffectGate(\n 'Cooldown',\n async (ctx) => {\n const result = await ctx.core.rateLimiter.peek(keyOf(ctx), window);\n if (!result.limited) return;\n if (options?.notice) throw options.notice(result.resetAt);\n throw new OnCooldown(result.resetAt, options?.message?.(result.resetAt));\n },\n async (ctx) => {\n await ctx.core.rateLimiter.charge(keyOf(ctx), window);\n }\n );\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordRangeError } from '@seedcord/errors/internal';\n\nimport type { PageView } from './PageView';\n\n/**\n * Pure page math, usable headless. Clamps `page` into range and slices the window.\n *\n * @param items - The full list to page over.\n * @param page - The requested zero-based page, clamped into `[0, totalPages - 1]`.\n * @param perPage - The page size. Must be a positive integer.\n * @returns The sliced {@link PageView}, with `totalPages` always known.\n * @throws SeedcordRangeError when `perPage` is not a positive integer.\n */\nexport function paginate<Item>(items: readonly Item[], page: number, perPage: number): PageView<Item> {\n if (!Number.isSafeInteger(perPage) || perPage <= 0) {\n throw new SeedcordRangeError(SeedcordErrorCode.PaginationInvalidPerPage, [perPage]);\n }\n\n const totalPages = Math.max(1, Math.ceil(items.length / perPage));\n // a headless caller can pass a non-integer or out-of-range page.\n const clamped = Math.min(Math.max(Math.trunc(page), 0), totalPages - 1);\n const start = clamped * perPage;\n\n return {\n items: items.slice(start, start + perPage),\n page: clamped,\n perPage,\n totalPages,\n hasPrev: clamped > 0,\n hasNext: clamped < totalPages - 1\n };\n}\n","import 'reflect-metadata';\n\nexport type * from '@registries/ContextMenuRegistry';\nexport type * from '@registries/SlashOptionRegistry';\n\nexport { RegisterCommand } from '@decorators/Command';\nexport { SelectMenuKind } from '@decorators/interactionRoutes';\nexport {\n AutocompleteRoute,\n ButtonRoute,\n ContextMenuRoute,\n ModalRoute,\n SelectMenuRoute,\n SlashRoute\n} from '@decorators/routes';\n\nexport { DispatchContext } from '@src/dispatch/DispatchContext';\nexport type { DispatchState } from '@src/dispatch/DispatchContext';\n\nexport { BaseHandler } from '@src/handlers/BaseHandler';\nexport { RepliableHandler } from '@src/handlers/RepliableHandler';\n\nexport type { CoreBase } from '@interfaces/CoreBase';\n\nexport type { Initializeable } from '@src/plugin/Plugin';\n// root-visible so a transport can augment it through `declare module '@seedcord/core'`\nexport type { PluginCapabilityTypes } from '@src/plugin/context';\n\nexport { ShutdownPhase, StartupPhase } from '@src/lifecycle/phases';\n\nexport { defineEffectGate, defineGate } from '@gates/Gate';\nexport type { EffectGate, Gate, GateContextBase, GuildPermissionsContext, RequiredOf } from '@gates/Gate';\nexport { and, or } from '@gates/combinators';\nexport { DmOnly, GuildOnly, OwnerOnly } from '@gates/catalog/access';\nexport { Cooldown, type CooldownOptions } from '@gates/catalog/Cooldown';\nexport { RequireBotPermissions, RequirePermissions, RequireRole } from '@gates/catalog/permissions';\nexport type { PermissionScope, RequirePermissionsOptions, RequireRoleOptions } from '@gates/catalog/permissions';\nexport type { GateNoticeOptions } from '@gates/catalog/options';\n\nexport { BuilderComponent, RowComponent } from '@components/Component';\nexport { type RowType, type BuilderType } from '@components/builderTypes';\n\nexport { Notice } from '@stops/Notice';\nexport { Fault } from '@stops/Fault';\nexport { Silence } from '@stops/Silence';\n\nexport { CustomId } from '@customId/CustomId';\n\nexport type { AutocompleteOptions } from '@inputs/AutocompleteOptions';\n\nexport { paginate } from '@pagination/paginate';\nexport { type PageView } from '@pagination/PageView';\n\nexport { Bus, Subscribe, Subscriber, WebhookLog, WebhookUrl } from '@subscribers/index';\nexport type {\n DispatchOutcome,\n FaultSource,\n SubscribeOptions,\n Subscriptions,\n SubscriptionData,\n SubscriptionKey,\n WebhookFile,\n WebhookReport\n} from '@subscribers/index';\n\n/** Package version */\nexport const version = process.env.PACKAGE_VERSION ?? '0.0.0';\n"],"mappings":";;;;;;;;;;;;AAoDA,SAAgB,gBAAgB,OAAqB,SAAmB,CAAC,GAAG;CACxE,QAAQ,SAA4B;EAChC,MAAM,eAAe,QAAQ,eAAeA,2CAAoB,IAAI;EACpE,IAAI,cACA,MAAM,IAAIC,wCAAcC,mCAAkB,mCAAmC;GACzE,KAAK;GACL,aAAa;GACb;EACJ,CAAC;EAGL,IAAI,UAAU,YAAY,OAAO,SAAS,GACtC,MAAM,IAAID,wCAAcC,mCAAkB,gCAAgC;EAG9E,IAAI,UAAU,YAAY,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,WAAW,IAClE,MAAM,IAAID,wCAAcC,mCAAkB,kCAAkC;EAGhF,MAAM,OAA+B,UAAU,WAAW,EAAE,MAAM,IAAI;GAAE;GAAO;EAAO;EACtF,QAAQ,eAAeF,2CAAoB,MAAM,IAAI;CACzD;AACJ;;;;;;;;;;;;;;;;;;;;;;;ACqDA,SAAgB,WAA0D,GAAG,QAAiB;CAC1F,OAAO,SAAwC,aAAmD;EAC9F,+CAA+C,QAAQ,WAAW;CACtE;AACJ;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,kBAAiE,GAAG,QAAiB;CACjG,OAAO,SAAwC,aAA0D;EACrG,sDAAsD,QAAQ,WAAW;CAC7E;AACJ;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,iBAAqD,MAAY,GAAG,OAAyB;CACzG,OAAO,SAAwC,aAAwD;EACnG,sCAAsBG,mCAAmB,IAAI,GAAG,OAAO,WAAW;CACtE;AACJ;;;;;;;;;;;;AAaA,SAAgB,YAAuD,GAAG,MAAY;CAClF,OAAO,SAAwC,aAAgE;EAC3G,8CAA8C,MAAM,WAAW;CACnE;AACJ;;;;;;;;;;;;AAaA,SAAgB,WAAsD,GAAG,MAAY;CACjF,OAAO,SAAwC,aAA+D;EAC1G,6CAA6C,MAAM,WAAW;CAClE;AACJ;;;;;;;;;;;;;;;;;AAkBA,SAAgB,gBACZ,MACA,GAAG,MACL;CACE,OAAO,SAAwC,aAA4D;EACvG,oCAAoBC,kCAAkB,IAAI,GAAG,MAAM,WAAW;CAClE;AACJ;;;;;;;;;ACvOA,IAAa,kBAAb,MAA6B;CAGG;CAF5B,AAAiB,QAAgC,CAAC;CAElD,YAAY,AAAgB,SAAwB;EAAxB;CAAyB;CAErD,IAAqC,KAAU,OAAiC;EAC5E,KAAK,MAAM,OAAO;CACtB;CAEA,IAAqC,KAA0C;EAC3E,OAAO,KAAK,MAAM;CACtB;AACJ;;;;;;;;;;;ACXA,IAAsB,cAAtB,MAAiE;CAQzC;CAPpB,AAAmB;CACnB,AAAmB;CAEnB,AAAmB;CAEnB,AAAU,YACN,OACA,AAAgB,MAChB,UACA,SACF;EAHkB;EAIhB,KAAK,QAAQ;EACb,KAAK,SAAS,IAAIC,wBAAO,KAAK,YAAY,MAAM,EAAE,QAAQ,CAAC;EAC3D,KAAK,WAAW;CACpB;AAOJ;;;;;;;;;;;;;ACnBA,IAAsB,mBAAtB,cAKU,YAA0B;CAChC,AAAmB;CACnB,AAAmB;CAEnB,AAAU,YAAY,OAAc,MAAa,UAA4B;EACzE,MAAM,OAAO,MAAM,UAAU,cAAc;EAC3C,KAAK,UAAU,UAAU,WAAW,KAAK,YAAY;EAErD,KAAK,SAAS,KAAK,YAAY,OAAO,MAAM,KAAK,OAAO;CAC5D;;CAKA,AAAO,YAAqB;EACxB,OAAO,KAAK;CAChB;;CAGA,AAAU,MAAM,UAAkC,MAAoC;EAClF,OAAO,KAAK,OAAO,MAAM,UAAU,IAAI;CAC3C;;CAGA,AAAU,MAAM,MAAiC;EAC7C,OAAO,KAAK,OAAO,MAAM,IAAI;CACjC;;CAGA,AAAU,SAAS,UAAkC,MAAoC;EACrF,OAAO,KAAK,OAAO,SAAS,UAAU,IAAI;CAC9C;CAKA,AAAU,KACN,kBACA,eACiB;EAEjB,IAAI,kBAAkB,QAAW,OAAO,KAAK,OAAO,KAAK,gBAA0C;EAEnG,OAAO,KAAK,OAAO,KAAK,kBAA8B,aAAa;CACvE;;CAGA,AAAU,KAAK,UAAkC,MAAoC;EACjF,OAAO,KAAK,OAAO,KAAK,UAAU,IAAI;CAC1C;;CAGA,AAAU,OAAO,QAAkC;EAC/C,OAAO,WAAW,SAAY,KAAK,OAAO,OAAO,IAAI,KAAK,OAAO,OAAO,MAAM;CAClF;AACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC5CA,IAAa,QAAb,cAA2BC,uBAAO;CAC9B,AAAO,YAAY,SAAiD;EAChE,MAAM,oBAAoB,SAAS,UAAU,SAAY,SAAY,EAAE,OAAO,QAAQ,MAAM,CAAC;EAC7F,KAAK,SAAS,SAAS,UAAU;CACrC;CAEA,AAAO,OAAO,KAAmC;EAM7C,OAAO,EAAE,YAAY,CAAC,IAJLC,2BACb,6CAFY,IAAI,qBAAqB,gBAEgB,qEAAqE,IAAI,KAAK,KACnI,OAEqB,CAAC,CAAC,SAAS,EAAE;CAC1C;AACJ;;;;ACVA,SAAgB,IAAI,GAAG,OAAgE;CACnF,OAAOC,2BAAW,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,KAAK,KAAK,GAAG,OAAO,QAAQ;EACzE,KAAK,MAAM,QAAQ,OACf,MAAMC,yBAAS,MAAM,GAAG;CAEhC,CAAC;AACL;AAQA,SAAS,YAAY,KAA0D;CAC3E,OAAO,EAAE,WAAW;AACxB;AAsCA,SAAgB,GAAG,GAAG,MAA6E;CAC/F,MAAM,OAAO,KAAK,GAAG,EAAE;CACvB,MAAM,UAAU,SAAS,UAAa,YAAY,IAAI,IAAI,OAAO;CACjE,MAAM,QAAS,UAAU,KAAK,MAAM,GAAG,EAAE,IAAI;CAE7C,OAAOD,2BAAW,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,KAAK,KAAK,GAAG,OAAO,QAAQ;EACzE,MAAM,YAAsB,CAAC;EAC7B,IAAI,qBAAqB;EACzB,KAAK,MAAM,QAAQ,OAAO;GACtB,MAAM,OAAOE,4BAAY,GAAG;GAC5B,IAAI;IACA,MAAMD,yBAAS,MAAM,GAAG;IACxB;GACJ,SAAS,OAAO;IAEZ,IAAI,iBAAiBE,0BAAU,EAAE,iBAAiB,UAAU,CAAC,MAAM,QAAQ;KAEvE,gCAAgB,KAAK,IAAI;KACzB,IAAI,MAAM,YAAY,QAAW,qBAAqB;UACjD,UAAU,KAAK,MAAM,OAAO;KACjC;IACJ;IACA,MAAM;GACV;EACJ;EACA,IAAI,SAAS,MAAM,OAAO,QAAQ,SAAS,aAAa,QAAQ,KAAK,GAAG,IAAI,QAAQ;EAEpF,IAAI,sBAAsB,UAAU,SAAS,GAAG,MAAM,IAAIC,yBAAS,SAAS;EAC5E,MAAM,IAAIC,2BAAW;CACzB,CAAC;AACL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtFA,SAAgB,UAAU,SAAiE;CACvF,OAAOC,2BAAW,cAAc,QAAQ;EACpC,MAAM,SAAS,IAAI,KAAK,OAAO,YAAY,CAAC;EAC5C,IAAI,IAAI,WAAW,QAAQ,OAAO,SAAS,IAAI,MAAM,GAAG;EACxD,MAAMC,2BAAW,UAAU,YAAY,IAAIC,yBAAS,OAAO,CAAC;CAChE,CAAC;AACL;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,UAAU,SAAiE;CACvF,OAAOF,2BAAW,cAAc,QAAQ;EACpC,IAAI,IAAI,SAAS;EACjB,MAAMC,2BAAW,UAAU,YAAY,IAAIE,2BAAW,OAAO,CAAC;CAClE,CAAC;AACL;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,OAAO,SAA8D;CACjF,OAAOH,2BAAW,WAAW,QAAQ;EACjC,IAAI,CAAC,IAAI,SAAS;EAClB,MAAMC,2BAAW,UAAU,YAAY,IAAIG,wBAAQ,OAAO,CAAC;CAC/D,CAAC;AACL;;;;ACvCA,IAAI,UAAU;AAEd,SAAS,WAAW,KAAsB,KAA2C;CACjF,IAAI,QAAQ,SAAS,OAAO,IAAI,WAAW;CAC3C,IAAI,QAAQ,WAAW,OAAO,IAAI,aAAa;CAC/C,OAAO,IAAI,UAAU;AACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,SAAgB,SACZ,UACA,SACuC;CACvC,IAAI;CACJ,IAAI,OAAO,aAAa,UACpB,WAAW,WAAW;MACnB;EACH,MAAM,4CAAuB,QAAQ;EACrC,IAAI,WAAW,MAAM,MAAM,IAAIC,4CAAkBC,mCAAkB,6BAA6B,CAAC,QAAQ,CAAC;EAC1G,WAAW;CACf;CAEA,IAAI,YAAY,GACZ,MAAM,IAAID,4CAAkBC,mCAAkB,6BAA6B,CAAC,OAAO,QAAQ,CAAC,CAAC;CAGjG,MAAM,MAAM,SAAS,OAAO;CAE5B,MAAM,SAAS,SAAS,UAAU,SAAY,EAAE,SAAS,IAAI;EAAE;EAAU,OAAO,QAAQ;CAAM;CAC9F,MAAM,SAAS;CAEf,MAAM,SAAS,QACX,YAAY,IAAI,WAAW,OAAO,SAAS,GAAG,IAAI,IAAI,SAAS,IAAI,SAAS,SAAS,EAAE,GAAG,WAAW,KAAK,GAAG;CAEjH,OAAOC,iCACH,YACA,OAAO,QAAQ;EACX,MAAM,SAAS,MAAM,IAAI,KAAK,YAAY,KAAK,MAAM,GAAG,GAAG,MAAM;EACjE,IAAI,CAAC,OAAO,SAAS;EACrB,IAAI,SAAS,QAAQ,MAAM,QAAQ,OAAO,OAAO,OAAO;EACxD,MAAM,IAAIC,2BAAW,OAAO,SAAS,SAAS,UAAU,OAAO,OAAO,CAAC;CAC3E,GACA,OAAO,QAAQ;EACX,MAAM,IAAI,KAAK,YAAY,OAAO,MAAM,GAAG,GAAG,MAAM;CACxD,CACJ;AACJ;;;;;;;;;;;;;ACpIA,SAAgB,SAAe,OAAwB,MAAc,SAAiC;CAClG,IAAI,CAAC,OAAO,cAAc,OAAO,KAAK,WAAW,GAC7C,MAAM,IAAIC,6CAAmBC,mCAAkB,0BAA0B,CAAC,OAAO,CAAC;CAGtF,MAAM,aAAa,KAAK,IAAI,GAAG,KAAK,KAAK,MAAM,SAAS,OAAO,CAAC;CAEhE,MAAM,UAAU,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,GAAG,aAAa,CAAC;CACtE,MAAM,QAAQ,UAAU;CAExB,OAAO;EACH,OAAO,MAAM,MAAM,OAAO,QAAQ,OAAO;EACzC,MAAM;EACN;EACA;EACA,SAAS,UAAU;EACnB,SAAS,UAAU,aAAa;CACpC;AACJ;;;;;ACkCA,MAAa"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $ as SlashOptionRegistry, C as RequiredOf, E as BaseReplySender, G as RegisterCommand, J as RowComponent, Q as SlashOption, R as AnyCustomId, S as GuildPermissionsContext, T as defineGate, X as RowType, Y as BuilderType, Z as OptionKind, _ as JoinNames, b as Gate, c as RequireBotPermissions, d as RequireRole, f as RequireRoleOptions, g as IntersectRequired, j as SelectMenuKind, l as RequirePermissions, n as AutocompleteOptions, p as GateNoticeOptions, q as BuilderComponent, s as PermissionScope, u as RequirePermissionsOptions, v as TwoOrMore, w as defineEffectGate, x as GateContextBase, y as EffectGate, z as CustomId } from "./AutocompleteOptions-DLp_B8as.mjs";
|
|
2
|
+
import { t as Constructor } from "./basic-D7bDlgSP.mjs";
|
|
3
|
+
import { A as Notice, C as Subscriber, D as SubscriptionData, E as FaultSource, O as SubscriptionKey, T as DispatchOutcome, b as Bus, c as ShutdownPhase, d as PluginCapabilityTypes, k as Subscriptions, l as StartupPhase, n as Initializeable, y as CoreBase } from "./Plugin-3rlH0uxH.mjs";
|
|
4
|
+
import { a as Subscribe, i as WebhookFile, n as WebhookLog, o as SubscribeOptions, r as WebhookReport, t as WebhookUrl } from "./index-Dueqztyy.mjs";
|
|
2
5
|
import { ApplicationCommandType } from "discord-api-types/v10";
|
|
3
|
-
import { Logger } from "@seedcord/logger";
|
|
6
|
+
import { Logger, LoggerChannelId } from "@seedcord/logger";
|
|
4
7
|
import { ValidDuration } from "@seedcord/utils";
|
|
5
8
|
import { DeferOpts, EpochMs, RenderContext, ReplyResponse, SendOpts } from "@seedcord/types";
|
|
6
9
|
|
|
@@ -196,7 +199,7 @@ declare abstract class BaseHandler<Event, TCore extends CoreBase> {
|
|
|
196
199
|
protected readonly event: Event;
|
|
197
200
|
protected readonly logger: Logger;
|
|
198
201
|
protected readonly dispatch?: DispatchContext | undefined;
|
|
199
|
-
protected constructor(event: Event, core: TCore, dispatch?: DispatchContext);
|
|
202
|
+
protected constructor(event: Event, core: TCore, dispatch?: DispatchContext, channel?: LoggerChannelId);
|
|
200
203
|
/**
|
|
201
204
|
* Holds the main logic of your handler. The dispatcher calls it after the handler's gates pass, so a
|
|
202
205
|
* gate that refuses stops `execute()` from running.
|
|
@@ -556,5 +559,5 @@ declare function paginate<Item>(items: readonly Item[], page: number, perPage: n
|
|
|
556
559
|
/** Package version */
|
|
557
560
|
declare const version: string;
|
|
558
561
|
//#endregion
|
|
559
|
-
export { type AutocompleteOptions, AutocompleteRoute, BaseHandler, BuilderComponent, type BuilderType, ButtonRoute, ContextMenuRoute, Cooldown, type CooldownOptions, type CoreBase, CustomId, DispatchContext, type DispatchState, DmOnly, type EffectGate, Fault, type Gate, type GateContextBase, type GateNoticeOptions, GuildOnly, type GuildPermissionsContext, type MessageContextMenuRegistry, ModalRoute, Notice, type OptionKind, OwnerOnly, type PageView, type PermissionScope, RegisterCommand, RepliableHandler, RequireBotPermissions, RequirePermissions, type RequirePermissionsOptions, RequireRole, type RequireRoleOptions, type RequiredOf, RowComponent, type RowType, SelectMenuKind, SelectMenuRoute, Silence, type SlashOption, type SlashOptionRegistry, SlashRoute, type UserContextMenuRegistry, and, defineEffectGate, defineGate, or, paginate, version };
|
|
562
|
+
export { type AutocompleteOptions, AutocompleteRoute, BaseHandler, BuilderComponent, type BuilderType, Bus, ButtonRoute, ContextMenuRoute, Cooldown, type CooldownOptions, type CoreBase, CustomId, DispatchContext, type DispatchOutcome, type DispatchState, DmOnly, type EffectGate, Fault, type FaultSource, type Gate, type GateContextBase, type GateNoticeOptions, GuildOnly, type GuildPermissionsContext, type Initializeable, type MessageContextMenuRegistry, ModalRoute, Notice, type OptionKind, OwnerOnly, type PageView, type PermissionScope, type PluginCapabilityTypes, RegisterCommand, RepliableHandler, RequireBotPermissions, RequirePermissions, type RequirePermissionsOptions, RequireRole, type RequireRoleOptions, type RequiredOf, RowComponent, type RowType, SelectMenuKind, SelectMenuRoute, ShutdownPhase, Silence, type SlashOption, type SlashOptionRegistry, SlashRoute, StartupPhase, Subscribe, type SubscribeOptions, Subscriber, type SubscriptionData, type SubscriptionKey, type Subscriptions, type UserContextMenuRegistry, type WebhookFile, WebhookLog, type WebhookReport, WebhookUrl, and, defineEffectGate, defineGate, or, paginate, version };
|
|
560
563
|
//# sourceMappingURL=index.d.mts.map
|