@seedcord/gateway 0.8.0 → 0.9.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,21 +1,21 @@
1
1
  import "reflect-metadata";
2
+ import { InFlight } from "@seedcord/core/node/internal";
2
3
  import { WinstonConsoleSink, WinstonFileSink } from "@seedcord/logger/node";
3
- import { AutocompletableNames, AutocompleteRouteBrand, CacheFor, ChoiceValueOf, CommandRegistry, ComponentDefsBrand, ComponentKindBrand, ContextMenuKindBrand, ContextMenuLeaves, ContextMenuNamesBrand, EntryFor, FixedScope, FocusedField, GateFitsWith, HasComponentDefs, Initializeable, MatchArms, MenuCacheFor, MiddlewareKindsBrand, NamesFor, PageCursor, SingleParams, SlashOptions as SlashOptions$1, SlashRouteBrand } from "@seedcord/core/internal";
4
- import { ArraySourceBase, AutocompleteOptions, BaseHandler as BaseHandler$1, BaseReplySender, Bus, CoreBase, CursorSourceBase, DispatchContext, DispatchOutcome, DispatchResult, EventDispatchResult, Gate, GateContextBase, GateNoticeOptions, GuildPermissionsContext, HandlerOutcome, InteractionKind, MiddlewareKind, ModalLike, Notice, PageSourceBase, PaginatorBase, PaginatorConfig, PermissionNoticeOverrides, PermissionScope, RepliableHandler as RepliableHandler$1, RequiredOf, ResolvedEmoji, SlashRegistry, Subscriber as Subscriber$1, SubscriptionKey, WebhookLog as WebhookLog$1 } from "@seedcord/core";
4
+ import { AutocompletableNames, AutocompleteResponder, AutocompleteRouteBrand, CacheFor, CaseReturn, ChoiceValueOf, CommandRegistry, ComponentDefsBrand, ComponentKindBrand, ContextMenuKindBrand, ContextMenuLeaves, ContextMenuNamesBrand, EntryFor, FixedScope, FocusedField, GateFitsWith, HasComponentDefs, Initializeable, MatchCases, MatchResult, MenuCacheFor, MiddlewareKindsBrand, MiddlewareRoute, NamesFor, OnlyCases, PageCursor, SingleParams, SlashOptions as SlashOptions$1, SlashRouteBrand } from "@seedcord/core/internal";
5
+ import { AppPermissionsContext, ArraySourceBase, AutocompleteOptions, BaseHandler as BaseHandler$1, BaseReplySender, Bus, CoreBase, CursorSourceBase, DispatchContext as DispatchContext$1, DispatchOutcome, DispatchResult, EventDispatchResult, Gate, GateContextBase, GateNoticeOptions, GuildPermissionsContext, HandlerOutcome, InteractionKind, MiddlewareKind, ModalLike, NoticeConstructor, PageSourceBase, PaginatorBase, PaginatorConfig, PermissionNoticeConstructor, PermissionScope, RepliableHandler as RepliableHandler$1, RequiredOf, ResolvedEmoji, SlashRegistry, Subscriber as Subscriber$1, SubscriptionKey, WebhookLog as WebhookLog$1 } from "@seedcord/core";
6
+ import { APIInteractionGuildMember, APIModalInteractionResponseCallbackData, AnySelectMenuInteraction, ApplicationCommandOptionChoiceData, ApplicationCommandType, ApplicationEmoji, AutocompleteInteraction, BaseMessageOptions, BooleanCache, ButtonInteraction, ButtonStyle, CacheType, CacheTypeReducer, ChannelSelectMenuInteraction, ChatInputCommandInteraction, Client, ClientEvents, ClientOptions, CommandInteractionOption, ContextMenuCommandInteraction, Events, Guild, GuildBasedChannel, GuildEmoji, GuildMember, Interaction, MentionableSelectMenuInteraction, Message, MessageContextMenuCommandInteraction, ModalSubmitFields, ModalSubmitInteraction, Role, RoleSelectMenuInteraction, StringSelectMenuInteraction, User, UserContextMenuCommandInteraction, UserSelectMenuInteraction } from "discord.js";
5
7
  import { Logger } from "@seedcord/logger";
6
- import { APIInteractionGuildMember, APIModalInteractionResponseCallbackData, AnySelectMenuInteraction, ApplicationCommandOptionChoiceData, ApplicationCommandType, ApplicationEmoji, AutocompleteInteraction, BaseMessageOptions, BooleanCache, ButtonInteraction, ButtonStyle, CacheType, CacheTypeReducer, ChannelSelectMenuInteraction, ChatInputCommandInteraction, Client, ClientEvents, ClientOptions, CommandInteractionOption, ContextMenuCommandInteraction, Events, Guild, GuildEmoji, GuildMember, Interaction, MentionableSelectMenuInteraction, Message, MessageContextMenuCommandInteraction, ModalSubmitFields, ModalSubmitInteraction, Role, RoleSelectMenuInteraction, StringSelectMenuInteraction, TextChannel, User, UserContextMenuCommandInteraction, UserSelectMenuInteraction } from "discord.js";
7
8
  import { Plugin as Plugin$1, PluginLifecycleSpec, PluginOptions, PluginOptions as PluginOptions$1 } from "@seedcord/core/plugin";
8
- import { CoordinatedShutdown, CoordinatedStartup, ServerHost } from "@seedcord/core/node";
9
+ import { ServerHost, ShutdownTasks, StartupTasks } from "@seedcord/core/node";
9
10
  import { HostAugmentTarget, HostVersion, SeedcordBrand, SeedcordInstance } from "@seedcord/types/internal";
10
- import { HmrModuleHandler } from "@seedcord/core/hmr";
11
11
  import { AnyCustomId } from "@seedcord/custom-id";
12
- import { BotConfig, Config, DeferOpts, EmojiMap, EventFrequency, HealthCheckOption, HmrAware, HmrUpdateEvent, IRateLimiter, ReplyResponse, SendOpts, TypedOmit } from "@seedcord/types";
12
+ import { HmrModuleHandler } from "@seedcord/core/hmr";
13
+ import { BotConfig, Config, DeferOpts, EmojiMap, EventFrequency, HealthCheckOption, HmrAware, HmrUpdateEvent, ReplyResponse, SendOpts, TypedOmit } from "@seedcord/types";
13
14
  import { Constructor, IsUnion, NonEmptyTuple, Promisable } from "type-fest";
14
15
  import { REST } from "@discordjs/rest";
15
16
  export * from "@seedcord/errors";
16
17
  export * from "@seedcord/core";
17
18
  export * from "@seedcord/logger";
18
- export * from "@seedcord/rate-limiter";
19
19
  export * from "@seedcord/utils";
20
20
  export * from "@seedcord/event-emitter";
21
21
  export type * from "@seedcord/types";
@@ -33,11 +33,11 @@ declare module '@seedcord/core/internal' {
33
33
  args: ClientEvents[Name];
34
34
  }; }[keyof ClientEvents];
35
35
  /**
36
- * Triggered once an event's handlers settle, pairing with `eventDispatching`. A fire that runs no
37
- * handler triggers neither.
36
+ * Published once an event's handlers settle, pairing with `eventDispatching`. When no handlers
37
+ * are registered, neither key is published.
38
38
  */
39
39
  eventDispatched: {
40
- /** The same id `eventDispatching` published for this fire. */
40
+ /** The same id `eventDispatching` published for this dispatch. */
41
41
  dispatchId: string;
42
42
  name: keyof ClientEvents;
43
43
  /** How the middleware chain ended. A chain that refused the event leaves `handlers` empty. */
@@ -102,36 +102,28 @@ interface GatewayConfig extends Config {
102
102
  */
103
103
  declare class EventDispatcher implements Initializeable, HmrAware {
104
104
  protected core: Core;
105
+ private readonly inFlight;
105
106
  private readonly logger;
106
107
  private isInitialized;
107
108
  private readonly eventMap;
108
109
  private readonly middlewares;
109
- private readonly executedOnceHandlers;
110
+ private readonly onceRuns;
110
111
  private readonly attachedEvents;
111
- private readonly inFlight;
112
- private loading;
113
- private readonly loadedHandlers;
114
- private readonly loadedMiddlewares;
115
- private readonly hmrHandler?;
116
- constructor(core: Core);
112
+ private readonly loader;
113
+ constructor(core: Core, inFlight: InFlight);
117
114
  private getArtifacts;
118
115
  init(): Promise<void>;
119
116
  private reportLoad;
120
- private loadHandlers;
121
- private loadMiddlewares;
122
117
  /** @internal */
123
118
  onHmr(event: HmrUpdateEvent): Promise<void>;
124
119
  private unregisterHandler;
125
- private unregisterMiddleware;
126
- private registerMiddleware;
127
120
  private runMiddlewares;
128
121
  private isEventHandlerClass;
129
122
  private isMiddlewareClass;
130
- private registerHandler;
123
+ private storeHandler;
131
124
  private attachToClient;
132
125
  private attachListener;
133
- stopAccepting(): void;
134
- drain(timeoutMs: number): Promise<void>;
126
+ private reportUnhandled;
135
127
  private processEvent;
136
128
  private processHandler;
137
129
  }
@@ -139,55 +131,26 @@ declare class EventDispatcher implements Initializeable, HmrAware {
139
131
  //#region src/bot/controllers/InteractionDispatcher.d.ts
140
132
  declare class InteractionDispatcher implements Initializeable, HmrAware {
141
133
  protected core: Core;
134
+ private readonly inFlight;
142
135
  private readonly logger;
143
136
  private isInitialized;
144
- private readonly maps;
145
- private readonly handlerFiles;
137
+ private readonly routes;
138
+ private get maps();
146
139
  private readonly keysToIgnore;
147
140
  private readonly middlewares;
148
- private readonly inFlight;
149
- private loading;
150
- private readonly loadedHandlers;
151
- private readonly loadedMiddlewares;
152
- private readonly hmrHandler?;
153
- constructor(core: Core);
141
+ private readonly loader;
142
+ constructor(core: Core, inFlight: InFlight);
154
143
  warnUnhandledRoutes(commandLeaves: Iterable<string>): void;
155
144
  warnUnhandledContextMenuRoutes(leaves: ContextMenuLeaves): void;
156
- private getArtifacts;
157
145
  init(): Promise<void>;
158
146
  private reportLoad;
159
- private loadHandlers;
160
- private loadMiddlewares;
161
- private registerMiddleware;
162
147
  private isHandlerClass;
163
148
  private isMiddlewareClass;
164
- private registerHandler;
165
149
  onHmr(event: HmrUpdateEvent): Promise<void>;
166
- private unregisterHandler;
167
- private unregisterMiddleware;
168
150
  private attachToClient;
169
- stopAccepting(): void;
170
- drain(timeoutMs: number): Promise<void>;
171
151
  private handleCustomIdInteraction;
172
152
  private processInteraction;
173
- private answer;
174
- private buildHandler;
175
- private reporterFor;
176
- private refusalBeforeHandler;
177
- private runMiddlewares;
178
- private gateRefusal;
179
153
  private handleInteraction;
180
- private handleSlashCommand;
181
- private handleButton;
182
- private handleModal;
183
- private handleStringSelectMenu;
184
- private handleUserSelectMenu;
185
- private handleRoleSelectMenu;
186
- private handleChannelSelectMenu;
187
- private handleMentionableSelectMenu;
188
- private handleMessageContextMenu;
189
- private handleUserContextMenu;
190
- private handleAutocomplete;
191
154
  }
192
155
  //#endregion
193
156
  //#region src/bot/Bot.d.ts
@@ -236,8 +199,8 @@ declare class Bot implements HmrAware {
236
199
  * ```
237
200
  * */
238
201
  interface Core extends CoreBase {
239
- readonly shutdown: Pick<CoordinatedShutdown, 'addTask'>;
240
- readonly startup: Pick<CoordinatedStartup, 'addTask'>;
202
+ readonly shutdown: ShutdownTasks;
203
+ readonly startup: StartupTasks;
241
204
  readonly bot: Bot;
242
205
  readonly config: GatewayConfig;
243
206
  }
@@ -285,12 +248,12 @@ export declare abstract class BaseHandler<ValidEvent extends ValidEventTypes> ex
285
248
  type SingleEventPayload<Names extends ValidNonInteractionKeys> = IsUnion<Names> extends true ? never : ClientEvents[Names];
286
249
  //#endregion
287
250
  //#region src/handlers/event/EventHandler.d.ts
288
- type EventMatchArms<Names extends ValidNonInteractionKeys, Ret> = { [Name in Names]: (...args: ClientEvents[Name]) => Promisable<Ret>; };
251
+ type EventMatchCases<Names extends ValidNonInteractionKeys, Ret> = { [Name in Names]: (...args: ClientEvents[Name]) => CaseReturn<Ret>; };
289
252
  /**
290
253
  * Base class for a Discord client event handler.
291
254
  *
292
- * Pass the event name(s) as the generic, the same one(s) as `@RegisterEvent`. A single-event handler reads
293
- * `this.event` (the payload tuple) directly. A handler registered for several events branches with `this.match`,
255
+ * Pass the event name(s) as the generic, the same one(s) as `@RegisterEvent`. On a single-event handler, read
256
+ * `this.event` (the payload tuple) directly. On a handler registered for several events, branch with `this.match`,
294
257
  * keyed by event name, since the union of payload tuples is not directly readable.
295
258
  *
296
259
  * @typeParam Names - One or more `ClientEvents` keys, e.g. `Events.MessageCreate` or `Events.MessageCreate | Events.MessageUpdate`.
@@ -309,20 +272,22 @@ type EventMatchArms<Names extends ValidNonInteractionKeys, Ret> = { [Name in Nam
309
272
  * ```
310
273
  */
311
274
  export declare abstract class EventHandler<in out Names extends ValidNonInteractionKeys> extends BaseHandler<ClientEvents[Names]> {
312
- private readonly firedEvent;
313
- constructor(event: ClientEvents[Names], core: Core, dispatch: DispatchContext, eventName?: Names);
275
+ constructor(event: ClientEvents[Names], core: Core, dispatch: DispatchContext$1);
314
276
  protected readonly event: SingleEventPayload<Names>;
277
+ /** The event that started this dispatch, one of the names in the generic. */
278
+ protected readonly route: Names;
315
279
  /**
316
- * Run the arm for whichever event fired. Use this only when the handler is registered for several
317
- * events. A single-event handler reads `this.event` directly. On a multi-event handler `this.event` is
280
+ * Run the case for the current event. Use this only when the handler is registered for several
281
+ * events. On a single-event handler, read `this.event` directly. On a multi-event handler `this.event` is
318
282
  * `never`, so match is the only way to read the payload.
319
283
  *
320
- * Provide one arm per registered event, keyed by its name, and each arm receives that event's own
321
- * payload tuple. The arms must cover every event in the generic, a missing event or an unknown key is a
284
+ * Provide one case per registered event, keyed by its name, and each case receives that event's own
285
+ * payload tuple. The cases must cover every event in the generic. A missing event or an unknown key is a
322
286
  * compile error.
323
287
  *
324
- * @param arms - One handler per registered event, keyed by event name.
325
- * @returns The result of the arm that ran.
288
+ * @param cases - One handler per registered event, keyed by event name.
289
+ * @typeParam Ret - The type that every case must return. Leave it out to get the union of what the cases return.
290
+ * @returns The result of the case that ran.
326
291
  *
327
292
  * @example
328
293
  * ```ts
@@ -337,7 +302,7 @@ export declare abstract class EventHandler<in out Names extends ValidNonInteract
337
302
  * }
338
303
  * ```
339
304
  */
340
- protected match<Ret>(arms: EventMatchArms<Names, Ret>): Promise<Ret>;
305
+ protected match<Ret = never, Cases extends EventMatchCases<Names, Ret> = EventMatchCases<Names, Ret>>(cases: OnlyCases<Cases, EventMatchCases<Names, Ret>>): Promise<MatchResult<Ret, Cases>>;
341
306
  }
342
307
  //#endregion
343
308
  //#region src/handlers/event/EventMiddleware.d.ts
@@ -346,22 +311,20 @@ export declare abstract class EventHandler<in out Names extends ValidNonInteract
346
311
  *
347
312
  * Middleware runs before event handlers and can stop the event by throwing a `Silence`. Unlike `EventHandler`, it
348
313
  * runs the SAME for every event it is registered for, so it has no `match`. Specify a single event in the
349
- * generic and `{ events }` to read `this.event` fully typed. Span several events (or omit `{ events }` for a
350
- * catchall) and `this.event` narrows to `never`, read `this.eventName` and do work that does not depend on the
351
- * payload shape. A middleware that needs each event's payload is written one event per class.
314
+ * generic and `{ events }` to read `this.event` fully typed. If you span several events (or omit `{ events }` for
315
+ * a catchall), `this.event` narrows to `never`. Read `this.route` there, for work that doesn't depend on the
316
+ * payload shape. Write one class per event for a middleware that needs each event's payload.
352
317
  *
353
318
  * @typeParam EventName - One or more `ClientEvents` keys. Defaults to every event (catchall).
354
319
  */
355
320
  export declare abstract class EventMiddleware<in out EventName extends ValidNonInteractionKeys = ValidNonInteractionKeys> extends BaseHandler<ClientEvents[EventName]> {
356
- private readonly firedEvent;
357
- constructor(event: ClientEvents[EventName], core: Core, dispatch: DispatchContext, eventName?: EventName);
321
+ constructor(event: ClientEvents[EventName], core: Core, dispatch: DispatchContext$1);
358
322
  protected readonly event: SingleEventPayload<EventName>;
359
323
  /**
360
- * The event that fired this middleware. Read it on a catchall or multi-event middleware, where `this.event`
361
- * is `never`, to do work that does not depend on the payload shape. A single-event middleware reads
362
- * `this.event` directly and does not need this.
324
+ * The event that started this dispatch, one of the names in the generic. Read it on a catchall or multi-event
325
+ * middleware, where `this.event` is `never`, to do work that doesn't depend on the payload shape.
363
326
  */
364
- protected get eventName(): EventName;
327
+ protected readonly route: EventName;
365
328
  /**
366
329
  * Runs once the event finishes, newest middleware first. Every middleware whose `execute()`
367
330
  * started gets the call, a stopped chain and a throw included. Implement it to release something
@@ -378,7 +341,7 @@ export declare abstract class EventMiddleware<in out EventName extends ValidNonI
378
341
  * }
379
342
  * ```
380
343
  */
381
- after?(result: EventDispatchResult): Promise<void>;
344
+ after?(result: EventDispatchResult): Promisable<void>;
382
345
  }
383
346
  //#endregion
384
347
  //#region src/bot/decorators/Events.d.ts
@@ -440,7 +403,7 @@ type SentMessage = Message;
440
403
  /** Writes interaction responses through discord.js. The repliable handler bases and the dispatcher construct it. */
441
404
  export declare class ReplySender extends BaseReplySender<SentMessage, GatewayFile> {
442
405
  private readonly interaction;
443
- constructor(interaction: Repliables, dispatch: DispatchContext, bus: Bus);
406
+ constructor(interaction: Repliables, dispatch: DispatchContext$1, bus: Bus);
444
407
  protected writeReply(response: GatewayReplyResponse | string, opts?: SendOpts): Promise<SentMessage | undefined>;
445
408
  protected writeDefer(opts?: DeferOpts): Promise<void>;
446
409
  protected writeDeferUpdate(): Promise<void>;
@@ -473,7 +436,8 @@ export declare class ReplySender extends BaseReplySender<SentMessage, GatewayFil
473
436
  export declare abstract class RepliableHandler<Event extends Repliables> extends RepliableHandler$1<Event, Core, SentMessage, GatewayFile, ReplySender> {
474
437
  /** @internal */
475
438
  getEvent(): Event;
476
- protected buildSender(event: Event, core: Core, dispatch: DispatchContext): ReplySender;
439
+ /** The user who sent this interaction. */
440
+ protected get user(): User;
477
441
  }
478
442
  //#endregion
479
443
  //#region src/handlers/interaction/InteractionHandler.d.ts
@@ -487,7 +451,7 @@ export declare abstract class RepliableHandler<Event extends Repliables> extends
487
451
  * @typeParam Repliable - The interaction type this handler processes
488
452
  */
489
453
  export declare abstract class InteractionHandler<Repliable extends Repliables> extends RepliableHandler<Repliable> {
490
- constructor(event: Repliable, core: Core, dispatch: DispatchContext);
454
+ constructor(event: Repliable, core: Core, dispatch: DispatchContext$1, sender: ReplySender);
491
455
  /**
492
456
  * Open a modal. Must be the initial response to this interaction. The modal kind rejects this call at
493
457
  * compile time (Discord forbids a modal in response to a modal).
@@ -497,7 +461,7 @@ export declare abstract class InteractionHandler<Repliable extends Repliables> e
497
461
  //#endregion
498
462
  //#region src/bot/gates/Gate.d.ts
499
463
  /**
500
- * The interaction arm. It extends {@link GuildPermissionsContext} with the live interaction and
464
+ * The context a gate gets on an interaction. It extends {@link GuildPermissionsContext} with the live interaction and
501
465
  * the djs objects resolved from the gateway cache. `Repliable` is the interaction type the gate
502
466
  * supports, inferred from the `ctx` annotation, so a gate reading button-specific fields is rejected
503
467
  * on a slash handler. `interaction` is the reply target, so `user` is always present. Use
@@ -516,7 +480,7 @@ export declare abstract class InteractionHandler<Repliable extends Repliables> e
516
480
  * });
517
481
  * ```
518
482
  */
519
- interface InteractionGateContext<Repliable extends Repliables = Repliables> extends GuildPermissionsContext {
483
+ interface InteractionGateContext<Repliable extends Repliables = Repliables> extends GuildPermissionsContext, AppPermissionsContext {
520
484
  /** The literal `'interaction'`. Narrow on it before reading `interaction`. */
521
485
  readonly kind: 'interaction';
522
486
  /** The running framework, with the gateway's bot and bus. */
@@ -531,12 +495,12 @@ interface InteractionGateContext<Repliable extends Repliables = Repliables> exte
531
495
  readonly member: GuildMember | null;
532
496
  }
533
497
  /**
534
- * The event arm. It extends {@link GuildPermissionsContext} with the event payload and the djs
498
+ * The context a gate gets on an event. It extends {@link GuildPermissionsContext} with the event payload and the djs
535
499
  * objects derived from it. `Names` is the event(s) the gate supports, inferred from the `ctx`
536
500
  * annotation, so a gate that reads one event's `payload` is rejected on a handler for a different
537
501
  * event. The default supports every event.
538
502
  *
539
- * @typeParam Names - The event name or names the gate reads, typing `payload` to that event's args tuple.
503
+ * @typeParam Names - One event or a union of the events the gate reads. `payload` gets that event's args tuple.
540
504
  *
541
505
  * @example
542
506
  * ```ts
@@ -573,7 +537,7 @@ interface EventGateContext<Names extends ValidNonInteractionKeys = ValidNonInter
573
537
  *
574
538
  * @example
575
539
  * ```ts
576
- * // a gate that handles either arm narrows on ctx.kind
540
+ * // a gate that takes either context narrows on ctx.kind
577
541
  * const Either = defineGate('either', (ctx: GateContext) => {
578
542
  * if (ctx.kind === 'interaction') void ctx.interaction;
579
543
  * else void ctx.payload;
@@ -592,7 +556,7 @@ interface Ungateable {
592
556
  readonly [UngateableBrand]: true;
593
557
  }
594
558
  type ProvidedContext<TCtor extends AnyHandlerCtor> = InstanceType<TCtor> extends InteractionHandler<infer Repliable> ? InteractionGateContext<Repliable> : InstanceType<TCtor> extends EventHandler<infer Names> ? EventGateContext<Names> : Ungateable;
595
- type KindName<Ctx> = Ctx extends Ungateable ? 'autocomplete' : Ctx extends InteractionGateContext<infer R> ? R extends ChatInputCommandInteraction ? 'Slash' : R extends MessageContextMenuCommandInteraction ? 'MessageContextMenu' : R extends UserContextMenuCommandInteraction ? 'UserContextMenu' : R extends StringSelectMenuInteraction ? 'StringMenu' : R extends UserSelectMenuInteraction ? 'UserMenu' : R extends RoleSelectMenuInteraction ? 'RoleMenu' : R extends ChannelSelectMenuInteraction ? 'ChannelMenu' : R extends MentionableSelectMenuInteraction ? 'MentionableMenu' : R extends ButtonInteraction ? 'Button' : R extends ModalSubmitInteraction ? 'Modal' : 'an interaction' : Ctx extends EventGateContext<infer N> ? `${N & string} event` : 'an agnostic';
559
+ type KindName<Ctx> = Ctx extends Ungateable ? 'autocomplete' : Ctx extends InteractionGateContext<infer R> ? Repliables extends R ? 'generic interaction' : R extends ChatInputCommandInteraction ? 'Slash' : R extends MessageContextMenuCommandInteraction ? 'MessageContextMenu' : R extends UserContextMenuCommandInteraction ? 'UserContextMenu' : R extends StringSelectMenuInteraction ? 'StringMenu' : R extends UserSelectMenuInteraction ? 'UserMenu' : R extends RoleSelectMenuInteraction ? 'RoleMenu' : R extends ChannelSelectMenuInteraction ? 'ChannelMenu' : R extends MentionableSelectMenuInteraction ? 'MentionableMenu' : R extends ButtonInteraction ? 'Button' : R extends ModalSubmitInteraction ? 'Modal' : 'generic interaction' : Ctx extends EventGateContext<infer N> ? `${N & string} event` : Ctx extends AppPermissionsContext ? 'generic interaction' : 'any';
596
560
  type FitAll<TCtor extends AnyHandlerCtor, Gates extends readonly Gate<GateContextBase>[]> = { [Index in keyof Gates]: GateFitsWith<ProvidedContext<TCtor>, KindName<ProvidedContext<TCtor>>, Gates[Index], KindName<RequiredOf<Gates[Index]>>>; };
597
561
  //#endregion
598
562
  //#region src/bot/decorators/Gated.d.ts
@@ -600,10 +564,10 @@ type FitAll<TCtor extends AnyHandlerCtor, Gates extends readonly Gate<GateContex
600
564
  * Attaches gates to a handler. The gates run before `execute`, and a gate refusing stops the handler with
601
565
  * the reply or drop the gate threw. Multiple gates are ANDed, so each must pass. A gate that requires a
602
566
  * context the handler does not provide (a button gate on a slash handler, an interaction gate on an event
603
- * handler) is a compile error at this line, and the error names the gate and the handler kind. Place it
567
+ * handler) is a compile error at this line, and the error message shows the gate and the handler kind. Place it
604
568
  * above the route decorator.
605
569
  *
606
- * Combine gates with {@link and} or {@link or} to build a single gate from multiple arms.
570
+ * Combine gates into a single gate with {@link and} or {@link or}.
607
571
  *
608
572
  * @example
609
573
  * ```ts
@@ -686,13 +650,42 @@ export declare function RegisterEventMiddleware<const Events extends NonEmptyTup
686
650
  */
687
651
  export declare const IgnoreBots: import("@seedcord/core").Gate<EventGateContext<ValidNonInteractionKeys>, "IgnoreBots">;
688
652
  //#endregion
653
+ //#region src/bot/gates/catalog/MentionPrefix.d.ts
654
+ /**
655
+ * Passes only a message that starts with a mention of the bot, like `@bot ping`. It ignores every other message
656
+ * with a {@link Silence}, including a reply that pings the bot, a role mention, and a mention later in the text.
657
+ *
658
+ * On `messageUpdate` it passes only when the edit adds the mention. An edit that keeps the mention doesn't run the
659
+ * handler again. With `Partials.Message` on, discord.js also emits an edit to a message it didn't cache. That edit
660
+ * runs the handler again. Attach the gate without calling it, since it doesn't take options.
661
+ *
662
+ * A handler behind this gate can read `content` without the Message Content intent, because Discord sends the text of
663
+ * a message that mentions the bot.
664
+ *
665
+ * @see {@link Gated}
666
+ *
667
+ * @example
668
+ * ```ts
669
+ * import { Events } from 'discord.js';
670
+ *
671
+ * \@Gated(IgnoreBots, MentionPrefix)
672
+ * \@RegisterEvent([Events.MessageCreate], [Events.MessageUpdate])
673
+ * class MentionCommands extends EventHandler<Events.MessageCreate | Events.MessageUpdate> {
674
+ * async execute() {
675
+ * // ...
676
+ * }
677
+ * }
678
+ * ```
679
+ */
680
+ export declare const MentionPrefix: import("@seedcord/core").Gate<EventGateContext<"messageCreate" | "messageUpdate">, "MentionPrefix">;
681
+ //#endregion
689
682
  //#region src/bot/gates/catalog/Nsfw.d.ts
690
683
  /**
691
- * Requires an age-restricted channel, else refuses. Pass {@link GateNoticeOptions} to reword or replace the refusal.
684
+ * Requires an age-restricted channel, else refuses. Pass a Notice class as `notice` to replace the refusal.
692
685
  *
693
686
  * A thread inherits its parent channel's nsfw flag. ModalSubmit has no reliable channel, so it is excluded.
694
687
  *
695
- * @param options - Reword the default refusal with `message`, or replace it with `notice`.
688
+ * @param options - Replace the refusal with a Notice class as `notice`.
696
689
  *
697
690
  * @see {@link Gated}
698
691
  *
@@ -731,130 +724,97 @@ type InjectedEmojiMap = { [K in keyof EmojiMap]: EmojiMap[K] extends 'guild' ? G
731
724
  */
732
725
  export declare const Emojis: InjectedEmojiMap;
733
726
  //#endregion
734
- //#region src/bot/utilities/permissions/checkBotPermissions.d.ts
735
- /**
736
- * Checks the bot's own permissions in a {@link Guild} or {@link TextChannel}. Refuses when a permission in
737
- * `scope` is missing, or with `inverse` when one is present. When the bot member is uncached, the refusal
738
- * reports every permission in `scope` as missing.
739
- *
740
- * @example
741
- * ```ts
742
- * import { PermissionFlagsBits } from 'discord.js';
743
- * import { checkBotPermissions } from '@seedcord/gateway';
744
- *
745
- * checkBotPermissions(textChannel, [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]);
746
- * ```
747
- */
748
- export declare function checkBotPermissions(target: Guild | TextChannel, scope: PermissionScope, inverse?: boolean, errors?: PermissionNoticeOverrides): void;
749
- //#endregion
750
727
  //#region src/bot/utilities/permissions/checkPermissions.d.ts
751
728
  /** Options for {@link checkPermissions}. */
752
- interface CheckPermissionOptions extends PermissionNoticeOverrides {
729
+ interface CheckPermissionOptions {
753
730
  /** The role or member to check. */
754
731
  for: Role | GuildMember;
755
- /** A guild reads the base bits from roles, a text channel reads the overwrite-resolved set. */
756
- in: Guild | TextChannel;
732
+ /** A channel or thread, to read the set after its overwrites. Leave it out to read the base set from roles. */
733
+ in?: GuildBasedChannel | undefined;
757
734
  /** The permission flag bits to check. */
758
735
  scope: PermissionScope;
759
736
  /** Refuse when the target holds a scope bit. */
760
737
  inverse?: boolean;
738
+ /** Your Notice class, thrown in place of the default refusal. seedcord constructs it with the target's mention and the refused names. */
739
+ notice?: PermissionNoticeConstructor | undefined;
761
740
  }
762
741
  /**
763
- * Checks a {@link Role} or a {@link GuildMember} against the base permission bits in a {@link Guild},
764
- * before channel overwrites. Refuses when a permission in `scope` is missing, or with `inverse` when one
765
- * is present.
742
+ * Checks a {@link Role} or a {@link GuildMember} against the base permission set from roles, or against a
743
+ * channel's set when `in` is given. Refuses when a permission in `scope` is missing, or with `inverse` when
744
+ * one is present.
745
+ *
746
+ * @throws A {@link Notice} when the check refuses. It lists the missing or present permissions.
766
747
  *
767
748
  * @example
768
749
  * ```ts
769
750
  * import { PermissionFlagsBits } from 'discord.js';
770
751
  * import { checkPermissions } from '@seedcord/gateway';
771
752
  *
772
- * checkPermissions(role, guild, [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.KickMembers]);
753
+ * checkPermissions({ for: member, scope: [PermissionFlagsBits.KickMembers] });
754
+ * checkPermissions({ for: role, in: channel, scope: [PermissionFlagsBits.SendMessages] });
773
755
  * ```
774
756
  *
775
757
  * @example
776
758
  * ```ts
777
- * // refuse when the member holds Administrator, and replace the refusal
778
- * checkPermissions(member, guild, [PermissionFlagsBits.Administrator], true, {
779
- * dangerousNotice: CustomDangerousNotice
780
- * });
759
+ * // refuse when the member holds Administrator, with your own Notice class
760
+ * checkPermissions({ for: member, scope: [PermissionFlagsBits.Administrator], inverse: true, notice: TooPowerful });
781
761
  * ```
782
762
  */
783
- export declare function checkPermissions(target: Role | GuildMember, ctx: Guild, scope: PermissionScope, inverse?: boolean, errors?: PermissionNoticeOverrides): void;
763
+ export declare function checkPermissions({ for: target, in: channel, scope, inverse, notice }: CheckPermissionOptions): void;
764
+ //#endregion
765
+ //#region src/bot/utilities/permissions/checkBotPermissions.d.ts
766
+ /** Options for {@link checkBotPermissions}. */
767
+ interface CheckBotPermissionOptions extends TypedOmit<CheckPermissionOptions, 'for' | 'in'> {
768
+ /** A guild, to read the bot's base set from roles, or a channel or thread, to read its set there. */
769
+ in: Guild | GuildBasedChannel;
770
+ }
784
771
  /**
785
- * Checks a {@link Role} or a {@link GuildMember} against the overwrite-resolved set in a
786
- * {@link TextChannel}. Refuses when a permission in `scope` is missing, or with `inverse` when one is
787
- * present.
772
+ * Checks the bot's own permissions in a {@link Guild}, or in a channel or thread. Refuses when a permission
773
+ * in `scope` is missing, or with `inverse` when one is present.
788
774
  *
789
- * @example
790
- * ```ts
791
- * import { PermissionFlagsBits } from 'discord.js';
792
- * import { checkPermissions } from '@seedcord/gateway';
793
- *
794
- * checkPermissions(role, textChannel, [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]);
795
- * ```
796
- */
797
- export declare function checkPermissions(target: Role | GuildMember, ctx: TextChannel, scope: PermissionScope, inverse?: boolean, errors?: PermissionNoticeOverrides): void;
798
- /**
799
- * Checks permissions with an options object. Refuses when a permission in
800
- * {@link CheckPermissionOptions.scope} is missing, or with `options.inverse` when one is present.
775
+ * @throws A {@link Notice} when the check refuses. It lists the missing or present permissions.
776
+ * @throws A **SeedcordError** when the guild's member cache doesn't hold the bot's member.
801
777
  *
802
778
  * @example
803
779
  * ```ts
804
780
  * import { PermissionFlagsBits } from 'discord.js';
805
- * import { checkPermissions } from '@seedcord/gateway';
781
+ * import { checkBotPermissions } from '@seedcord/gateway';
806
782
  *
807
- * checkPermissions({
808
- * for: member,
809
- * in: textChannel,
810
- * scope: [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel]
811
- * });
783
+ * checkBotPermissions({ in: channel, scope: [PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel] });
812
784
  * ```
813
785
  */
814
- export declare function checkPermissions(options: CheckPermissionOptions): void;
786
+ export declare function checkBotPermissions({ in: where, ...check }: CheckBotPermissionOptions): void;
815
787
  //#endregion
816
788
  //#region src/bot/utilities/permissions/hasPermsToAssign.d.ts
817
- /**
818
- * Optional custom error constructors for {@link HasPermsToAssignOptions}.
819
- */
820
- export interface AssignRoleNoticeOverrides {
821
- higherNotice?: new (message: string, role: Role, botRole: Role) => Notice;
822
- managedNotice?: new (message: string) => Notice;
823
- missingNotice?: new (message: string | undefined, subject: string, missingPerms: readonly string[]) => Notice;
824
- }
825
- /**
826
- * Options for {@link hasPermsToAssign}.
827
- */
789
+ /** Options for {@link hasPermsToAssign}. */
828
790
  export interface HasPermsToAssignOptions {
829
- targetRole: Role;
830
- noticeOverrides?: AssignRoleNoticeOverrides;
791
+ /** The role the bot would assign. */
792
+ role: Role;
793
+ /** Your Notice class, constructed with both roles and thrown in place of the refusal when the role is at or above the bot's. */
794
+ higher?: NoticeConstructor<[role: Role, botRole: Role]>;
795
+ /** Your Notice class, constructed with the role and thrown in place of the refusal when an integration manages the role. */
796
+ managed?: NoticeConstructor<[role: Role]>;
797
+ /** Your Notice class, thrown when the bot lacks Manage Roles. seedcord constructs it with the bot's mention and that permission's name. */
798
+ missing?: PermissionNoticeConstructor;
831
799
  }
832
800
  /**
833
- * Validates that the bot can assign a target role. Refuses when the target role is above the bot's, is managed, or the bot lacks Manage Roles.
801
+ * Validates that the bot can assign a role. Refuses when the role is at or above the bot's, when an
802
+ * integration manages it, or when the bot lacks Manage Roles.
834
803
  *
835
- * @param roleOrOptions - Target role or complete options for the check
836
804
  * @throws A {@link Notice} when the check refuses.
837
- * @throws A **SeedcordError** when the bot has no role in the guild's role cache.
805
+ * @throws A **SeedcordError** when the guild's caches don't hold the bot's role or member.
838
806
  *
839
807
  * @example
840
808
  * ```ts
841
809
  * import { hasPermsToAssign } from '@seedcord/gateway';
842
810
  *
843
- * // Check if the bot can assign a specific role
844
- * hasPermsToAssign(role);
811
+ * hasPermsToAssign({ role });
845
812
  *
846
- * // Check with custom error handling
847
- * hasPermsToAssign({
848
- * targetRole: role,
849
- * noticeOverrides: {
850
- * higherNotice: CustomHigherNotice,
851
- * managedNotice: CustomManagedNotice,
852
- * missingNotice: CustomMissingPermissionsNotice
853
- * }
854
- * });
813
+ * // with your own Notice classes
814
+ * hasPermsToAssign({ role, higher: RoleTooHigh, managed: RoleIsManaged, missing: CannotManageRoles });
855
815
  * ```
856
816
  */
857
- export declare function hasPermsToAssign(roleOrOptions: Role | HasPermsToAssignOptions): void;
817
+ export declare function hasPermsToAssign({ role, higher, managed, missing }: HasPermsToAssignOptions): void;
858
818
  //#endregion
859
819
  //#region src/bot/confirm/getConfirmation.d.ts
860
820
  type Outcome = ReplyResponse | (() => Promisable<ReplyResponse>);
@@ -1025,7 +985,15 @@ type InteractionOf<Kind extends MiddlewareKind> = InteractionForKind[Kind];
1025
985
  export declare abstract class InteractionMiddleware<in out Kind extends MiddlewareKind = MiddlewareKind> extends RepliableHandler<InteractionOf<Kind>> {
1026
986
  /** @internal */
1027
987
  readonly [MiddlewareKindsBrand]?: Kind;
1028
- constructor(event: InteractionOf<Kind>, core: Core, dispatch: DispatchContext, sender: ReplySender);
988
+ constructor(event: InteractionOf<Kind>, core: Core, dispatch: DispatchContext$1, sender: ReplySender);
989
+ /**
990
+ * What started this dispatch: a slash command path like `config/set`, a context menu command's
991
+ * name, or a custom-ID prefix. When the generic lists only slash or context menu kinds, your editor
992
+ * offers your registered commands. It can still be any string, since middleware also runs when no
993
+ * handler matched, like on a deleted command that Discord still shows. For a custom ID that seedcord
994
+ * didn't make, it can be empty or a cut-off piece of that ID.
995
+ */
996
+ protected readonly route: MiddlewareRoute<Kind>;
1029
997
  /**
1030
998
  * Runs once the handler settles, newest middleware first. A refusal or a throw still reaches it,
1031
999
  * since seedcord calls it on every middleware whose `execute()` started. Implement it to release
@@ -1042,7 +1010,7 @@ export declare abstract class InteractionMiddleware<in out Kind extends Middlewa
1042
1010
  * }
1043
1011
  * ```
1044
1012
  */
1045
- after?(result: DispatchResult): Promise<void>;
1013
+ after?(result: DispatchResult): Promisable<void>;
1046
1014
  }
1047
1015
  //#endregion
1048
1016
  //#region src/inputs/SlashOptions.d.ts
@@ -1069,13 +1037,14 @@ interface GatewayLens<Cache extends CacheType> {
1069
1037
  type SlashOptions<Route extends keyof SlashRegistry, Cache extends CacheType = CacheFor<Route>> = SlashOptions$1<Route, GatewayLens<Cache>>;
1070
1038
  //#endregion
1071
1039
  //#region src/handlers/interaction/SlashHandler.d.ts
1072
- type SlashMatchArms<Route extends keyof SlashRegistry, Cache extends CacheType, Ret> = { [Key in Route]: (options: SlashOptions<Key, Cache>) => Promisable<Ret>; };
1040
+ type CaseCache<Route extends keyof SlashRegistry, Cache extends CacheType, Key extends Route> = [Cache] extends [CacheFor<Route>] ? CacheFor<Key> : Cache;
1041
+ type SlashMatchCases<Route extends keyof SlashRegistry, Cache extends CacheType, Ret> = { [Key in Route]: (options: SlashOptions<Key, CaseCache<Route, Cache, Key>>) => CaseReturn<Ret>; };
1073
1042
  /**
1074
1043
  * Base class for a chat-input (slash) command handler.
1075
1044
  *
1076
1045
  * Pass the route from the generated registry as the generic, the same string as `@SlashRoute`, then read
1077
1046
  * `this.options` for a single command or `this.match` for several. Command authoring stays plain
1078
- * discord.js, `seedcord codegen` reads its `toJSON()` to type these options.
1047
+ * discord.js. `seedcord codegen` reads its `toJSON()` to type these options.
1079
1048
  *
1080
1049
  * @typeParam Route - One or more route keys from {@link SlashRegistry}, e.g. `'ban'` or `'ban' | 'kick'`.
1081
1050
  * @typeParam Cache - The interaction cache state. The command's contexts set it.
@@ -1094,30 +1063,32 @@ type SlashMatchArms<Route extends keyof SlashRegistry, Cache extends CacheType,
1094
1063
  export declare abstract class SlashHandler<Route extends keyof SlashRegistry, Cache extends CacheType = CacheFor<Route>> extends InteractionHandler<ChatInputCommandInteraction<Cache>> {
1095
1064
  /** @internal */
1096
1065
  readonly [SlashRouteBrand]?: Route;
1066
+ /** The selected command's path, such as `search/docs`. */
1067
+ protected readonly route: Route;
1097
1068
  /**
1098
1069
  * The typed options for this command's route. Only the getters for kinds this command declares appear.
1099
1070
  * Each getter's name argument is restricted to that command's options of its kind.
1100
1071
  *
1101
- * - A required option drops the null.
1072
+ * - A required option's getter never returns `null`.
1102
1073
  *
1103
1074
  * - Choices narrow to their literal union.
1104
1075
  *
1105
1076
  * - A channel option declared with `addChannelTypes` narrows to those types.
1106
1077
  *
1107
1078
  * Use `this.event.options` directly for anything outside this view, such as `getSubcommand()`.
1108
- * However, for the common case, the methods in this would suffice.
1109
1079
  */
1110
1080
  protected get options(): SlashOptions<Route, Cache>;
1111
1081
  /**
1112
- * Run the arm for whichever command fired. Use this only when the handler is registered for several
1082
+ * Run the case for the selected command. Use this only when the handler is registered for several
1113
1083
  * routes.
1114
1084
  *
1115
- * Provide one arm per registered route, keyed by its route string, and each arm receives that route's
1116
- * own narrowed options. The arms must cover every route in the generic, a missing route or an unknown
1085
+ * Provide one case per registered route, keyed by its route string, and each case receives that route's
1086
+ * own narrowed options. The cases must cover every route in the generic. A missing route or an unknown
1117
1087
  * key is a compile error.
1118
1088
  *
1119
- * @param arms - One handler per registered route, keyed by route string.
1120
- * @returns The result of the arm that ran.
1089
+ * @param cases - One handler per registered route, keyed by route string.
1090
+ * @typeParam Ret - The type that every case must return. Leave it out to get the union of what the cases return.
1091
+ * @returns The result of the case that ran.
1121
1092
  *
1122
1093
  * @example
1123
1094
  * ```ts
@@ -1132,12 +1103,12 @@ export declare abstract class SlashHandler<Route extends keyof SlashRegistry, Ca
1132
1103
  * }
1133
1104
  * ```
1134
1105
  */
1135
- protected match<Ret>(arms: SlashMatchArms<Route, Cache, Ret>): Promise<Ret>;
1106
+ protected match<Ret = never, Cases extends SlashMatchCases<Route, Cache, Ret> = SlashMatchCases<Route, Cache, Ret>>(cases: OnlyCases<Cases, SlashMatchCases<Route, Cache, Ret>>): Promise<MatchResult<Ret, Cases>>;
1136
1107
  }
1137
1108
  //#endregion
1138
1109
  //#region src/handlers/interaction/ContextMenuHandler.d.ts
1139
- type UserMenuArms<Names extends NamesFor<ApplicationCommandType.User>, Ret> = { [Name in Names]: (target: User, member: CacheTypeReducer<MenuCacheFor<ApplicationCommandType.User, Name>, GuildMember, APIInteractionGuildMember> | null) => Promisable<Ret>; };
1140
- type MessageMenuArms<Names extends NamesFor<ApplicationCommandType.Message>, Ret> = { [Name in Names]: (target: Message<BooleanCache<MenuCacheFor<ApplicationCommandType.Message, Name>>>) => Promisable<Ret>; };
1110
+ type UserMenuCases<Names extends NamesFor<ApplicationCommandType.User>, Ret> = { [Name in Names]: (target: User, member: CacheTypeReducer<MenuCacheFor<ApplicationCommandType.User, Name>, GuildMember, APIInteractionGuildMember> | null) => CaseReturn<Ret>; };
1111
+ type MessageMenuCases<Names extends NamesFor<ApplicationCommandType.Message>, Ret> = { [Name in Names]: (target: Message<BooleanCache<MenuCacheFor<ApplicationCommandType.Message, Name>>>) => CaseReturn<Ret>; };
1141
1112
  /**
1142
1113
  * Base class for a user context-menu command handler (right-click a user).
1143
1114
  *
@@ -1165,19 +1136,20 @@ export declare abstract class UserContextMenuHandler<Names extends NamesFor<Appl
1165
1136
  protected get target(): User;
1166
1137
  /** The right-clicked user's guild member, null outside a guild. */
1167
1138
  protected get targetMember(): CacheTypeReducer<Cache, GuildMember, APIInteractionGuildMember> | null;
1168
- /** Which of the registered commands fired. */
1169
- protected get commandName(): Names;
1139
+ /** The selected context-menu command's name, without the interaction-kind prefix. */
1140
+ protected readonly route: Names;
1170
1141
  /**
1171
- * Run the arm for whichever command fired. Use this only when the handler is registered for several
1142
+ * Run the case for the selected command. Use this only when the handler is registered for several
1172
1143
  * names.
1173
1144
  *
1174
- * Provide one arm per registered name, keyed by the name Discord shows in the right-click menu. Each
1175
- * arm receives the clicked user and that user's guild member, both narrowed to the cache state of that
1176
- * one command. The arms must cover every name in the generic. A missing name or an unknown key is a
1145
+ * Provide one case per registered name, keyed by the name Discord shows in the right-click menu. Each
1146
+ * case receives the clicked user and that user's guild member, both narrowed to the cache state of that
1147
+ * one command. The cases must cover every name in the generic. A missing name or an unknown key is a
1177
1148
  * compile error.
1178
1149
  *
1179
- * @param arms - One handler per registered command name.
1180
- * @returns The result of the arm that ran.
1150
+ * @param cases - One handler per registered command name.
1151
+ * @typeParam Ret - The type that every case must return. Leave it out to get the union of what the cases return.
1152
+ * @returns The result of the case that ran.
1181
1153
  *
1182
1154
  * @example
1183
1155
  * ```ts
@@ -1192,7 +1164,7 @@ export declare abstract class UserContextMenuHandler<Names extends NamesFor<Appl
1192
1164
  * }
1193
1165
  * ```
1194
1166
  */
1195
- protected match<Ret>(arms: UserMenuArms<Names, Ret>): Promise<Ret>;
1167
+ protected match<Ret = never, Cases extends UserMenuCases<Names, Ret> = UserMenuCases<Names, Ret>>(cases: OnlyCases<Cases, UserMenuCases<Names, Ret>>): Promise<MatchResult<Ret, Cases>>;
1196
1168
  }
1197
1169
  /**
1198
1170
  * Base class for a message context-menu command handler (right-click a message).
@@ -1219,18 +1191,19 @@ export declare abstract class MessageContextMenuHandler<Names extends NamesFor<A
1219
1191
  /** @internal */
1220
1192
  readonly [ContextMenuNamesBrand]?: Names;
1221
1193
  protected get target(): Message<BooleanCache<Cache>>;
1222
- /** Which of the registered commands fired. */
1223
- protected get commandName(): Names;
1194
+ /** The selected context-menu command's name, without the interaction-kind prefix. */
1195
+ protected readonly route: Names;
1224
1196
  /**
1225
- * Run the arm for whichever command fired. Use this only when the handler is registered for several
1197
+ * Run the case for the selected command. Use this only when the handler is registered for several
1226
1198
  * names.
1227
1199
  *
1228
- * Provide one arm per registered name, keyed by the name Discord shows in the right-click menu. Each
1229
- * arm receives the clicked message, narrowed to the cache state of that one command. The arms must
1200
+ * Provide one case per registered name, keyed by the name Discord shows in the right-click menu. Each
1201
+ * case receives the clicked message, narrowed to the cache state of that one command. The cases must
1230
1202
  * cover every name in the generic. A missing name or an unknown key is a compile error.
1231
1203
  *
1232
- * @param arms - One handler per registered command name.
1233
- * @returns The result of the arm that ran.
1204
+ * @param cases - One handler per registered command name.
1205
+ * @typeParam Ret - The type that every case must return. Leave it out to get the union of what the cases return.
1206
+ * @returns The result of the case that ran.
1234
1207
  *
1235
1208
  * @example
1236
1209
  * ```ts
@@ -1245,17 +1218,17 @@ export declare abstract class MessageContextMenuHandler<Names extends NamesFor<A
1245
1218
  * }
1246
1219
  * ```
1247
1220
  */
1248
- protected match<Ret>(arms: MessageMenuArms<Names, Ret>): Promise<Ret>;
1221
+ protected match<Ret = never, Cases extends MessageMenuCases<Names, Ret> = MessageMenuCases<Names, Ret>>(cases: OnlyCases<Cases, MessageMenuCases<Names, Ret>>): Promise<MatchResult<Ret, Cases>>;
1249
1222
  }
1250
1223
  //#endregion
1251
1224
  //#region src/handlers/interaction/AutocompleteHandler.d.ts
1252
- type FocusedArms<Route extends keyof SlashRegistry, Ret> = { [Name in AutocompletableNames<Route>]: (value: string, respond: (choices: readonly ApplicationCommandOptionChoiceData<ChoiceValueOf<EntryFor<Route, Name>>>[]) => Promise<void>) => Promisable<Ret>; };
1225
+ type FocusedCases<Route extends keyof SlashRegistry, Ret> = { [Name in AutocompletableNames<Route>]: (value: string, respond: (choices: readonly ApplicationCommandOptionChoiceData<ChoiceValueOf<EntryFor<Route, Name>>>[]) => Promise<void>) => CaseReturn<Ret>; };
1253
1226
  /**
1254
1227
  * Base class for a Discord autocomplete handler.
1255
1228
  *
1256
1229
  * Pass the command route(s) from the generated registry as the generic, the same string(s) as
1257
1230
  * `@AutocompleteRoute`. Branch on the focused field with `this.match`, read already-entered sibling options
1258
- * with `this.options`, and find which command fired with `this.route`.
1231
+ * with `this.options`, and read the selected command's path from `this.route`.
1259
1232
  *
1260
1233
  * @typeParam Route - One or more route keys from {@link SlashRegistry}, e.g. `'search'` or `'search' | 'find'`.
1261
1234
  * @typeParam Cache - The interaction cache state. The command's contexts set it.
@@ -1273,9 +1246,12 @@ type FocusedArms<Route extends keyof SlashRegistry, Ret> = { [Name in Autocomple
1273
1246
  * ```
1274
1247
  */
1275
1248
  export declare abstract class AutocompleteHandler<Route extends keyof SlashRegistry, Cache extends CacheType = CacheFor<Route>> extends BaseHandler<AutocompleteInteraction<Cache>> {
1249
+ #private;
1276
1250
  /** @internal */
1277
1251
  readonly [AutocompleteRouteBrand]?: Route;
1278
- constructor(event: AutocompleteInteraction<Cache>, core: Core, dispatch: DispatchContext);
1252
+ constructor(event: AutocompleteInteraction<Cache>, core: Core, dispatch: DispatchContext$1, responder: AutocompleteResponder<ApplicationCommandOptionChoiceData>);
1253
+ /** The user who sent this interaction. */
1254
+ protected get user(): User;
1279
1255
  private decodedFocused?;
1280
1256
  /**
1281
1257
  * The focused option for this interaction. `value` is always the raw partial string the user is typing,
@@ -1283,16 +1259,17 @@ export declare abstract class AutocompleteHandler<Route extends keyof SlashRegis
1283
1259
  */
1284
1260
  protected get focused(): FocusedField<Route>;
1285
1261
  /**
1286
- * Run the arm for the focused field. Because an autocomplete always dispatches by which field is
1262
+ * Run the case for the focused field. Because an autocomplete always dispatches by which field is
1287
1263
  * focused, match is how you read it. There is no single-field shortcut the way slash/component handlers have one.
1288
1264
  *
1289
- * Provide one arm per autocompletable field across the registered commands, keyed by field name. Each
1290
- * arm receives the focused partial value and a `respond` typed to that field's choice value. The
1291
- * arms must cover every autocompletable field. A missing field or an unknown key is a compile error.
1265
+ * Provide one case per autocompletable field across the registered commands, keyed by field name. Each
1266
+ * case receives the focused partial value and a `respond` typed to that field's choice value. The
1267
+ * cases must cover every autocompletable field. A missing field or an unknown key is a compile error.
1292
1268
  *
1293
- * @param arms - One handler per autocompletable field, keyed by field name.
1294
- * @returns The result of the arm that ran.
1295
- * @throws A **SeedcordTypeError** with `MatchArmMissing` when the focused field has no arm. Only a stale-deployed command can send one.
1269
+ * @param cases - One handler per autocompletable field, keyed by field name.
1270
+ * @typeParam Ret - The type that every case must return. Leave it out to get the union of what the cases return.
1271
+ * @returns The result of the case that ran.
1272
+ * @throws A **SeedcordTypeError** with `MatchCaseMissing` when the focused field doesn't have a case. Only a stale-deployed command can send one.
1296
1273
  *
1297
1274
  * @example
1298
1275
  * ```ts
@@ -1307,11 +1284,11 @@ export declare abstract class AutocompleteHandler<Route extends keyof SlashRegis
1307
1284
  * }
1308
1285
  * ```
1309
1286
  */
1310
- protected match<Ret>(arms: FocusedArms<Route, Ret>): Promise<Ret>;
1287
+ protected match<Ret = never, Cases extends FocusedCases<Route, Ret> = FocusedCases<Route, Ret>>(cases: OnlyCases<Cases, FocusedCases<Route, Ret>>): Promise<MatchResult<Ret, Cases>>;
1311
1288
  /** Send autocomplete suggestions, callback type 8. Prefer {@link match}, which restricts each field's choices to its declared type. */
1312
1289
  protected respond(choices: readonly ApplicationCommandOptionChoiceData[]): Promise<void>;
1313
- /** The firing command route, for a field whose completion differs per registered command. */
1314
- protected get route(): Route;
1290
+ /** The selected command's path, such as `search/docs`, without the interaction-kind prefix. */
1291
+ protected readonly route: Route;
1315
1292
  /**
1316
1293
  * The already-entered options on this command, restricted to the kinds Discord resolves during autocomplete
1317
1294
  * (string, integer, number, boolean) with every read nullable, since a sibling is partial while the user
@@ -1339,7 +1316,9 @@ export declare abstract class ComponentHandler<Event extends ComponentInteractio
1339
1316
  /** Acknowledge the component without changing the source message. */
1340
1317
  protected deferUpdate(): Promise<void>;
1341
1318
  private decoded?;
1342
- private get route();
1319
+ private get decodedRoute();
1320
+ /** The matched custom-ID prefix, such as `approve`, without encoded params. */
1321
+ protected readonly route: Defs[number]['prefix'];
1343
1322
  /**
1344
1323
  * The decoded params of the single route this handler is registered for.
1345
1324
  *
@@ -1351,17 +1330,18 @@ export declare abstract class ComponentHandler<Event extends ComponentInteractio
1351
1330
  */
1352
1331
  protected get params(): SingleParams<Defs>;
1353
1332
  /**
1354
- * Run the arm for whichever route the component was minted from. Use this only when the handler is
1355
- * registered for several routes. A single-route handler reads `this.params` directly. On a multi-route
1333
+ * Run the case for whichever route the component was minted from. Use this only when the handler is
1334
+ * registered for several routes. On a single-route handler, read `this.params` directly. On a multi-route
1356
1335
  * handler `this.params` is `never`, leaving match as the only way to read the decoded params.
1357
1336
  *
1358
- * Provide one arm per registered route, keyed by its prefix, and each arm receives that route's own
1359
- * decoded params. The compiler checks that the arms cover every registered route prefix. `match`
1360
- * decodes the wire before it runs an arm.
1337
+ * Provide one case per registered route, keyed by its prefix, and each case receives that route's own
1338
+ * decoded params. The compiler checks that the cases cover every registered route prefix. `match`
1339
+ * decodes the wire before it runs a case.
1361
1340
  *
1362
- * @param arms - One callback per registered route, keyed by prefix.
1363
- * @returns The result of the arm that ran.
1364
- * @throws A **SeedcordTypeError** with `MatchArmMissing` when the wire's prefix has no arm.
1341
+ * @param cases - One callback per registered route, keyed by prefix.
1342
+ * @typeParam Ret - The type that every case must return. Leave it out to get the union of what the cases return.
1343
+ * @returns The result of the case that ran.
1344
+ * @throws A **SeedcordTypeError** with `MatchCaseMissing` when the wire's prefix doesn't have a case.
1365
1345
  * @throws A **StaleCustomId** when the wire was encoded under an older shape.
1366
1346
  * @throws An **InvalidCustomId** when the wire is corrupt.
1367
1347
  *
@@ -1378,7 +1358,7 @@ export declare abstract class ComponentHandler<Event extends ComponentInteractio
1378
1358
  * }
1379
1359
  * ```
1380
1360
  */
1381
- protected match<Ret>(arms: MatchArms<Defs, Ret>): Promise<Ret>;
1361
+ protected match<Ret = never, Cases extends MatchCases<Defs, Ret> = MatchCases<Defs, Ret>>(cases: OnlyCases<Cases, MatchCases<Defs, Ret>>): Promise<MatchResult<Ret, Cases>>;
1382
1362
  }
1383
1363
  //#endregion
1384
1364
  //#region src/handlers/interaction/components/ButtonHandler.d.ts
@@ -1681,14 +1661,14 @@ export declare class CursorSource<Item> extends CursorSourceBase<Item, PageConte
1681
1661
  /**
1682
1662
  * Base class for a gateway subscriber, binding `this.core` to the gateway {@link Core}.
1683
1663
  *
1684
- * @typeParam KeyOfSubscribers - The subscription key this handler receives
1664
+ * @typeParam KeyOfSubscribers - The subscription key or keys that this handler receives, the same ones as `@Subscribe`
1685
1665
  */
1686
1666
  export declare abstract class Subscriber<KeyOfSubscribers extends SubscriptionKey> extends Subscriber$1<KeyOfSubscribers, Core> {}
1687
1667
  /**
1688
1668
  * Base class for a gateway subscriber that delivers its event to a Discord webhook, binding
1689
1669
  * `this.core` to the gateway {@link Core}.
1690
1670
  *
1691
- * @typeParam KeyOfSubscribers - The subscription key this reporter receives
1671
+ * @typeParam KeyOfSubscribers - The subscription key or keys that this reporter receives, the same ones as `@Subscribe`
1692
1672
  */
1693
1673
  export declare abstract class WebhookLog<KeyOfSubscribers extends SubscriptionKey> extends WebhookLog$1<KeyOfSubscribers, Core> {}
1694
1674
  //#endregion
@@ -1708,8 +1688,8 @@ declare const GATEWAY_SCOPE: {
1708
1688
  /**
1709
1689
  * Base class for a gateway plugin, binding `this.core` to the gateway {@link Core}.
1710
1690
  *
1711
- * A plugin that runs on either transport extends the base from `@seedcord/core/plugin`, whose
1712
- * `this.core` is typed to the shared members only.
1691
+ * To run on either transport, extend the base from `@seedcord/core/plugin`. Its `this.core` carries
1692
+ * only the shared members.
1713
1693
  *
1714
1694
  * @typeParam Opts - The transport and runtime the plugin declares.
1715
1695
  */
@@ -1738,16 +1718,12 @@ export declare class Seedcord extends ServerHost<'gateway'> implements SeedcordI
1738
1718
  readonly [HostAugmentTarget] = "@seedcord/gateway";
1739
1719
  /** @internal */
1740
1720
  readonly [HostVersion]: string;
1741
- /** @see {@link Bus} */
1742
- readonly bus: Bus;
1743
1721
  /** @see {@link Bot} */
1744
1722
  readonly bot: Bot;
1745
1723
  /** The discord.js client's REST client. Its token is set during the Login phase. */
1746
1724
  readonly rest: REST;
1747
1725
  /** The bot's Discord application id. Throws if you read it before login. */
1748
1726
  get applicationId(): string;
1749
- /** @see {@link IRateLimiter} */
1750
- readonly rateLimiter: IRateLimiter;
1751
1727
  /**
1752
1728
  * @param config - Bot configuration including paths and Discord client options
1753
1729
  * @throws A **SeedcordError** when another `Seedcord` exists in this process and has not shut down.
@@ -1770,5 +1746,5 @@ export declare class Seedcord extends ServerHost<'gateway'> implements SeedcordI
1770
1746
  /** Package version */
1771
1747
  export declare const version: string;
1772
1748
  //#endregion
1773
- export { type CheckPermissionOptions, type ConfirmOptions, type Core, type DefaultConfirmOptions, type EventGateContext, type EventMiddlewareOptions, type EventSpec, type EventsConfig, type GateContext, type GatewayBotConfig, type GatewayConfig, type GatewayFile, type GatewayPluginOptions, type GatewayReplyResponse, HmrModuleHandler, type InjectedEmojiMap, type InteractionGateContext, type PageContext, type PageSource, type PluginLifecycleSpec, type PluginOptions, type RegisterEventOptions, type Repliables, type SentMessage, type SlashOptions, type ValidEventTypes, type ValidInteractionTypes, type ValidNonInteractionKeys, WinstonConsoleSink, WinstonFileSink };
1749
+ export { type CheckBotPermissionOptions, type CheckPermissionOptions, type ConfirmOptions, type Core, type DefaultConfirmOptions, type EventGateContext, type EventMiddlewareOptions, type EventSpec, type EventsConfig, type GateContext, type GatewayBotConfig, type GatewayConfig, type GatewayFile, type GatewayPluginOptions, type GatewayReplyResponse, HmrModuleHandler, type InjectedEmojiMap, type InteractionGateContext, type PageContext, type PageSource, type PluginLifecycleSpec, type PluginOptions, type RegisterEventOptions, type Repliables, type SentMessage, type SlashOptions, type ValidEventTypes, type ValidInteractionTypes, type ValidNonInteractionKeys, WinstonConsoleSink, WinstonFileSink };
1774
1750
  //# sourceMappingURL=index.d.mts.map