@seedcord/gateway 0.1.0-next.0 → 0.1.0-next.1

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,8 +1,9 @@
1
- import { BuilderComponent, CoreBase, Gate, GateContextBase, GateNoticeOptions, MessageContextMenuRegistry, Notice, OptionKind, PageView, RegisterCommand, RequiredOf, SlashOptionRegistry, UserContextMenuRegistry } from "@seedcord/core";
1
+ import { BuilderComponent, CoreBase, DispatchContext, Gate, GateContextBase, GateNoticeOptions, MessageContextMenuRegistry, Notice, OptionKind, PageView, RegisterCommand, RequiredOf, SlashOptionRegistry, UserContextMenuRegistry } from "@seedcord/core";
2
2
  import { AnyCustomId, DecodedParams, GateFitsWith, HasComponentDefs, PageCursor } from "@seedcord/core/internal";
3
- import { APIInteractionGuildMember, APIMessageComponentEmoji, AnySelectMenuInteraction, ApplicationCommand, ApplicationCommandOptionChoiceData, ApplicationCommandType, ApplicationEmoji, AutocompleteInteraction, BooleanCache, ButtonInteraction, ButtonStyle, CacheType, CacheTypeReducer, ChannelSelectMenuInteraction, ChatInputCommandInteraction, Client, ClientEvents, ClientOptions, Collection, CommandInteractionOption, ContextMenuCommandInteraction, Events, Guild, GuildEmoji, GuildMember, Interaction, MentionableSelectMenuInteraction, Message, MessageContextMenuCommandInteraction, ModalSubmitInteraction, Role, RoleSelectMenuInteraction, Snowflake, StringSelectMenuInteraction, TextChannel, TextChannelResolvable, User, UserContextMenuCommandInteraction, UserSelectMenuInteraction, WebhookClient } from "discord.js";
4
- import { CoordinatedShutdown, CoordinatedStartup, Logger, SEEventMapLike, SENoEvents, StartupPhase, StrictEventEmitter } from "@seedcord/services";
3
+ import { APIInteractionGuildMember, APIMessageComponentEmoji, AnySelectMenuInteraction, ApplicationCommand, ApplicationCommandOptionChoiceData, ApplicationCommandType, ApplicationEmoji, AutocompleteInteraction, BooleanCache, ButtonInteraction, ButtonStyle, CacheType, CacheTypeReducer, ChannelSelectMenuInteraction, ChannelType, ChatInputCommandInteraction, Client, ClientEvents, ClientOptions, Collection, CommandInteractionOption, ContextMenuCommandInteraction, Events, Guild, GuildEmoji, GuildMember, Interaction, MentionableSelectMenuInteraction, Message, MessageContextMenuCommandInteraction, ModalSubmitInteraction, Role, RoleSelectMenuInteraction, Snowflake, StringSelectMenuInteraction, TextChannel, TextChannelResolvable, User, UserContextMenuCommandInteraction, UserSelectMenuInteraction, WebhookClient } from "discord.js";
4
+ import { CoordinatedShutdown, CoordinatedStartup, Logger, StartupPhase } from "@seedcord/services";
5
5
  import { ActionRowBuilder, ButtonBuilder, ContextMenuCommandBuilder, SlashCommandBuilder } from "@discordjs/builders";
6
+ import { EventMap, NoEvents, TypedEventEmitter } from "@seedcord/event-emitter";
6
7
  import { HmrAware, HmrUpdateEvent, SeedcordBrand, SeedcordInstance } from "@seedcord/types/internal";
7
8
  import { UUID } from "node:crypto";
8
9
  import { BotConfig, Config, EmojiMap, IRateLimiter, Nullable, ReplyResponse, Tail, V2Component } from "@seedcord/types";
@@ -10,6 +11,7 @@ export * from "@seedcord/core";
10
11
  export * from "@seedcord/errors";
11
12
  export * from "@seedcord/utils";
12
13
  export * from "@seedcord/services";
14
+ export * from "@seedcord/event-emitter";
13
15
  export * from "@seedcord/rate-limiter";
14
16
  export type * from "@seedcord/types";
15
17
 
@@ -65,7 +67,7 @@ interface Initializeable {
65
67
  * Extend this class to create plugins that integrate with the Seedcord lifecycle.
66
68
  * Plugins have access to the core instance and must implement initialization logic.
67
69
  */
68
- declare abstract class Plugin<TPluginEvents extends SEEventMapLike<TPluginEvents> = SENoEvents> extends StrictEventEmitter<TPluginEvents> implements Initializeable, HmrAware {
70
+ declare abstract class Plugin<TPluginEvents extends EventMap<TPluginEvents> = NoEvents> extends TypedEventEmitter<TPluginEvents> implements Initializeable, HmrAware {
69
71
  protected pluggable: Core;
70
72
  /** Logger instance for this plugin. */
71
73
  abstract logger: Logger;
@@ -87,11 +89,9 @@ declare abstract class Plugin<TPluginEvents extends SEEventMapLike<TPluginEvents
87
89
  */
88
90
  protected registerCriticalFiles(patterns: string[]): void;
89
91
  /** @internal */
90
- setMaxListeners(n: number): this;
91
- /** @internal */
92
92
  removeListener<TEventKey extends Extract<keyof TPluginEvents, string | symbol>>(event: TEventKey, listener: (...args: TPluginEvents[TEventKey]) => void): this;
93
93
  /** @internal */
94
- removeAllListeners(eventName?: string | symbol): this;
94
+ removeAllListeners(event?: Extract<keyof TPluginEvents, string | symbol>): this;
95
95
  }
96
96
  /**
97
97
  * Constructor type for plugins that can accept additional arguments after Core
@@ -113,7 +113,7 @@ type PluginArgs<Ctor extends PluginCtor> = Tail<ConstructorParameters<Ctor>>;
113
113
  * Provides plugin attachment capabilities and lifecycle management. Plugins are attached during
114
114
  * configuration and initialized during startup. Not constructed directly, the host is a {@link Seedcord}.
115
115
  */
116
- declare class Pluggable<TPluggableEvents extends SEEventMapLike<TPluggableEvents> = SENoEvents> extends StrictEventEmitter<TPluggableEvents> {
116
+ declare class Pluggable<TPluggableEvents extends EventMap<TPluggableEvents> = NoEvents> extends TypedEventEmitter<TPluggableEvents> {
117
117
  protected isInitialized: boolean;
118
118
  protected readonly shutdown: CoordinatedShutdown;
119
119
  protected readonly startup: CoordinatedStartup;
@@ -145,11 +145,9 @@ declare class Pluggable<TPluggableEvents extends SEEventMapLike<TPluggableEvents
145
145
  */
146
146
  attach<Key extends string, Ctor extends PluginCtor>(this: this, key: Key, Plugin: Ctor, startupPhase: StartupPhase, ...args: PluginArgs<Ctor>): this & Record<Key, InstanceType<Ctor>>;
147
147
  /** @internal */
148
- setMaxListeners(n: number): this;
149
- /** @internal */
150
148
  removeListener<TEventKey extends Extract<keyof TPluggableEvents, string | symbol>>(event: TEventKey, listener: (...args: TPluggableEvents[TEventKey]) => void): this;
151
149
  /** @internal */
152
- removeAllListeners(eventName?: string | symbol): this;
150
+ removeAllListeners(event?: Extract<keyof TPluggableEvents, string | symbol>): this;
153
151
  }
154
152
  //#endregion
155
153
  //#region src/subscribers/types/Subscriptions.d.ts
@@ -247,7 +245,7 @@ type SubscriptionKey = keyof AllSubscriptions;
247
245
  */
248
246
  type SubscriptionData<KeyOfSubscribers extends SubscriptionKey> = AllSubscriptions[KeyOfSubscribers];
249
247
  /**
250
- * Event map for Bus, compatible with StrictEventEmitter.
248
+ * Event map for Bus, compatible with TypedEventEmitter.
251
249
  *
252
250
  * @internal
253
251
  */
@@ -454,6 +452,11 @@ declare class Bot extends Plugin<BotEvents> {
454
452
  emit<TKey extends keyof ClientEvents>(event: 'any:event', name: TKey, ...args: ClientEvents[TKey]): boolean;
455
453
  /** @internal */
456
454
  emit<TEventKey extends keyof BotEvents>(event: TEventKey, ...args: BotEvents[TEventKey]): boolean;
455
+ /** @internal */
456
+ emitSafe<TKey extends keyof ClientEvents>(event: 'any:event', name: TKey, ...args: ClientEvents[TKey]): boolean;
457
+ /** @internal */
458
+ emitSafe<TEventKey extends keyof BotEvents>(event: TEventKey, ...args: BotEvents[TEventKey]): boolean;
459
+ protected onListenerError(error: unknown, event: string | symbol): void;
457
460
  }
458
461
  //#endregion
459
462
  //#region src/handlers/BaseHandler.d.ts
@@ -473,7 +476,8 @@ declare abstract class BaseHandler<ValidEvent extends ValidEventTypes> implement
473
476
  readonly core: Core;
474
477
  protected readonly event: ValidEvent;
475
478
  protected readonly logger: Logger;
476
- protected constructor(event: ValidEvent, core: Core);
479
+ protected readonly dispatch?: DispatchContext | undefined;
480
+ protected constructor(event: ValidEvent, core: Core, dispatch?: DispatchContext);
477
481
  /**
478
482
  * Holds the main logic of your handler. The dispatcher calls it after the handler's gates pass, so a
479
483
  * gate that refuses stops `execute()` from running.
@@ -895,7 +899,7 @@ type GateContext = InteractionGateContext | EventGateContext;
895
899
  * @typeParam Repliable - The interaction type this handler processes
896
900
  */
897
901
  declare abstract class InteractionHandler<Repliable extends Repliables> extends BaseHandler<Repliable> implements Handler {
898
- constructor(event: Repliable, core: Core);
902
+ constructor(event: Repliable, core: Core, dispatch?: DispatchContext);
899
903
  }
900
904
  //#endregion
901
905
  //#region src/bot/gates/matching.d.ts
@@ -1013,7 +1017,7 @@ type FocusedArms<Route extends keyof SlashOptionRegistry, Ret> = { [Name in Auto
1013
1017
  * ```
1014
1018
  */
1015
1019
  declare abstract class AutocompleteHandler<Route extends keyof SlashOptionRegistry, Cache extends CacheType = 'cached'> extends BaseHandler<AutocompleteInteraction<Cache>> implements Handler {
1016
- constructor(event: AutocompleteInteraction<Cache>, core: Core);
1020
+ constructor(event: AutocompleteInteraction<Cache>, core: Core, dispatch?: DispatchContext);
1017
1021
  /**
1018
1022
  * The focused option for this interaction. `value` is always the raw partial string the user is typing,
1019
1023
  * even for an integer or number option, so coerce it yourself when you need a number.
@@ -1096,6 +1100,12 @@ type Row<Route extends keyof SlashOptionRegistry> = SlashOptionRegistry[Route];
1096
1100
  type NamesOfKind<Route extends keyof SlashOptionRegistry, Kind extends OptionKind> = { [Name in keyof Row<Route>]: Row<Route>[Name] extends {
1097
1101
  kind: Kind;
1098
1102
  } ? Name : never }[keyof Row<Route>];
1103
+ type ChannelWireType<Types extends number> = Types extends ChannelType.PublicThread | ChannelType.AnnouncementThread ? ChannelType.PublicThread | ChannelType.AnnouncementThread : Types;
1104
+ type ResolvedChannel<Cache extends CacheType, Entry> = Entry extends {
1105
+ channelTypes: readonly (infer Types extends number)[];
1106
+ } ? Extract<NonNullable<CommandInteractionOption<Cache>['channel']>, {
1107
+ type: ChannelWireType<Types>;
1108
+ }> : NonNullable<CommandInteractionOption<Cache>['channel']>;
1099
1109
  type ResolvedValue<Cache extends CacheType, Entry> = Entry extends {
1100
1110
  choices: readonly (infer Choice)[];
1101
1111
  } ? Choice : Entry extends {
@@ -1108,7 +1118,7 @@ type ResolvedValue<Cache extends CacheType, Entry> = Entry extends {
1108
1118
  kind: 'user';
1109
1119
  } ? NonNullable<CommandInteractionOption<Cache>['user']> : Entry extends {
1110
1120
  kind: 'channel';
1111
- } ? NonNullable<CommandInteractionOption<Cache>['channel']> : Entry extends {
1121
+ } ? ResolvedChannel<Cache, Entry> : Entry extends {
1112
1122
  kind: 'role';
1113
1123
  } ? NonNullable<CommandInteractionOption<Cache>['role']> : Entry extends {
1114
1124
  kind: 'mentionable';
@@ -1128,8 +1138,8 @@ type MemberGetter<Route extends keyof SlashOptionRegistry, Cache extends CacheTy
1128
1138
  * on required options, narrows `choices` to their literal union, and only appears when the route has an
1129
1139
  * option of that kind. The rich kinds return exactly what the djs resolver returns.
1130
1140
  *
1131
- * Pass the raw `this.event.options` resolver for anything this view does not cover, such as narrowing a
1132
- * channel option with `getChannel(name, channelTypes)`.
1141
+ * A channel option declared with `addChannelTypes` narrows `getChannel` to the matching channel subtype.
1142
+ * Pass the raw `this.event.options` resolver for anything this view does not cover.
1133
1143
  *
1134
1144
  * @typeParam Route - A route key from the generated {@link SlashOptionRegistry}.
1135
1145
  * @typeParam Cache - The interaction cache state, `'cached'` by default.
package/dist/index.mjs CHANGED
@@ -1,14 +1,15 @@
1
1
  import "reflect-metadata";
2
- import { BuilderComponent, CustomId, Fault, Notice, RegisterCommand, RowComponent, Silence, defineGate, paginate } from "@seedcord/core";
3
- import { CommandMetadataKey, ComponentDefsKey, EventMetadataKey, GateNotice, GatedMetadataKey, InteractionMetadataKey, InteractionRouteKeys, InteractionRoutes, MiddlewareMetadataKey, NotInGuild, NoticeCard, PAGE_MAX, SubscribeMetadataKey, decodeFor, pageCursor, pickNotice, prefixOf, runHandlerGates, setBotColor } from "@seedcord/core/internal";
2
+ import { BuilderComponent, CustomId, DispatchContext, Fault, Notice, RegisterCommand, RowComponent, Silence, defineGate, paginate } from "@seedcord/core";
3
+ import { CommandMetadataKey, ComponentDefsKey, EventMetadataKey, GateNotice, GatedMetadataKey, InteractionMetadataKey, InteractionRouteKeys, InteractionRoutes, MiddlewareMetadataKey, NotInGuild, NoticeCard, PAGE_MAX, SubscribeMetadataKey, decodeFor, pageCursor, pickNotice, prefixOf, routeIdOf, runHandlerGates, setBotColor } from "@seedcord/core/internal";
4
4
  import { ApplicationCommandType, AttachmentBuilder, ButtonStyle, Client, Collection, ComponentType, DiscordAPIError, Events, Guild, GuildMember, Message, MessageFlags, PermissionFlagsBits, RESTJSONErrorCodes, Role, SeparatorSpacingSize, SnowflakeUtil, TextChannel, User, WebhookClient, chatInputApplicationCommandMention } from "discord.js";
5
5
  import { SeedcordErrorCode } from "@seedcord/errors";
6
6
  import { SeedcordError, SeedcordRangeError, SeedcordTypeError, validateDiscordToken } from "@seedcord/errors/internal";
7
7
  import { filterCirculars, formatFilePath, hasKeys, prettify, traverseDirectory } from "@seedcord/utils";
8
- import { CoordinatedShutdown, CoordinatedStartup, HealthCheck, Logger, ShutdownPhase, StartupPhase, StrictEventEmitter } from "@seedcord/services";
8
+ import { CoordinatedShutdown, CoordinatedStartup, HealthCheck, Logger, ShutdownPhase, StartupPhase } from "@seedcord/services";
9
9
  import chalk from "chalk";
10
10
  import { ActionRowBuilder, ButtonBuilder, ContextMenuCommandBuilder, SlashCommandBuilder, TextDisplayBuilder } from "@discordjs/builders";
11
11
  import { buildSlashRoute, routeLeavesOf } from "@seedcord/utils/internal";
12
+ import { TypedEventEmitter } from "@seedcord/event-emitter";
12
13
  import { existsSync } from "node:fs";
13
14
  import { resolve } from "node:path";
14
15
  import { pathToFileURL } from "node:url";
@@ -25,6 +26,8 @@ export * from "@seedcord/utils"
25
26
 
26
27
  export * from "@seedcord/services"
27
28
 
29
+ export * from "@seedcord/event-emitter"
30
+
28
31
  export * from "@seedcord/rate-limiter"
29
32
 
30
33
  //#region src/bot/decorators/Events.ts
@@ -1245,7 +1248,7 @@ function getDevChannel() {
1245
1248
  * Extend this class to create plugins that integrate with the Seedcord lifecycle.
1246
1249
  * Plugins have access to the core instance and must implement initialization logic.
1247
1250
  */
1248
- var Plugin = class extends StrictEventEmitter {
1251
+ var Plugin = class extends TypedEventEmitter {
1249
1252
  pluggable;
1250
1253
  name = this.constructor.name;
1251
1254
  constructor(pluggable) {
@@ -1267,16 +1270,12 @@ var Plugin = class extends StrictEventEmitter {
1267
1270
  getDevChannel()?.send("seedcord:register-critical-files", { patterns });
1268
1271
  }
1269
1272
  /** @internal */
1270
- setMaxListeners(n) {
1271
- return super.setMaxListeners(n);
1272
- }
1273
- /** @internal */
1274
1273
  removeListener(event, listener) {
1275
1274
  return super.removeListener(event, listener);
1276
1275
  }
1277
1276
  /** @internal */
1278
- removeAllListeners(eventName) {
1279
- return super.removeAllListeners(eventName);
1277
+ removeAllListeners(event) {
1278
+ return super.removeAllListeners(event);
1280
1279
  }
1281
1280
  };
1282
1281
  /**
@@ -1285,7 +1284,7 @@ var Plugin = class extends StrictEventEmitter {
1285
1284
  * Provides plugin attachment capabilities and lifecycle management. Plugins are attached during
1286
1285
  * configuration and initialized during startup. Not constructed directly, the host is a {@link Seedcord}.
1287
1286
  */
1288
- var Pluggable = class Pluggable extends StrictEventEmitter {
1287
+ var Pluggable = class Pluggable extends TypedEventEmitter {
1289
1288
  isInitialized = false;
1290
1289
  shutdown;
1291
1290
  startup;
@@ -1338,16 +1337,12 @@ var Pluggable = class Pluggable extends StrictEventEmitter {
1338
1337
  return Object.assign(this, entry);
1339
1338
  }
1340
1339
  /** @internal */
1341
- setMaxListeners(n) {
1342
- return super.setMaxListeners(n);
1343
- }
1344
- /** @internal */
1345
1340
  removeListener(event, listener) {
1346
1341
  return super.removeListener(event, listener);
1347
1342
  }
1348
1343
  /** @internal */
1349
- removeAllListeners(eventName) {
1350
- return super.removeAllListeners(eventName);
1344
+ removeAllListeners(event) {
1345
+ return super.removeAllListeners(event);
1351
1346
  }
1352
1347
  };
1353
1348
 
@@ -1360,10 +1355,12 @@ var BaseHandler = class {
1360
1355
  core;
1361
1356
  event;
1362
1357
  logger;
1363
- constructor(event, core) {
1358
+ dispatch;
1359
+ constructor(event, core, dispatch) {
1364
1360
  this.core = core;
1365
1361
  this.event = event;
1366
1362
  this.logger = new Logger(this.constructor.name);
1363
+ this.dispatch = dispatch;
1367
1364
  }
1368
1365
  /** @internal */
1369
1366
  getEvent() {
@@ -1399,8 +1396,8 @@ var InteractionMiddleware = class extends BaseHandler {
1399
1396
  * @typeParam Repliable - The interaction type this handler processes
1400
1397
  */
1401
1398
  var InteractionHandler = class extends BaseHandler {
1402
- constructor(event, core) {
1403
- super(event, core);
1399
+ constructor(event, core, dispatch) {
1400
+ super(event, core, dispatch);
1404
1401
  }
1405
1402
  };
1406
1403
 
@@ -1545,8 +1542,8 @@ var ContextMenuHandler = class extends InteractionHandler {
1545
1542
  * ```
1546
1543
  */
1547
1544
  var AutocompleteHandler = class extends BaseHandler {
1548
- constructor(event, core) {
1549
- super(event, core);
1545
+ constructor(event, core, dispatch) {
1546
+ super(event, core, dispatch);
1550
1547
  }
1551
1548
  /**
1552
1549
  * The focused option for this interaction. `value` is always the raw partial string the user is typing,
@@ -2582,7 +2579,8 @@ function interactionGateContext(interaction, core) {
2582
2579
  guildId: interaction.guildId,
2583
2580
  channelId: interaction.channelId,
2584
2581
  memberRoleIds,
2585
- memberPermissions: interaction.memberPermissions?.bitfield ?? null
2582
+ memberPermissions: interaction.memberPermissions?.bitfield ?? null,
2583
+ routeId: null
2586
2584
  };
2587
2585
  }
2588
2586
  function eventGateContext(eventName, args, core) {
@@ -2599,7 +2597,8 @@ function eventGateContext(eventName, args, core) {
2599
2597
  guildId: actor.guild?.id ?? null,
2600
2598
  channelId: actor.channelId,
2601
2599
  memberRoleIds: actor.member ? [...actor.member.roles.cache.keys()].filter((id) => id !== actor.guild?.id) : [],
2602
- memberPermissions: actor.member?.permissions.bitfield ?? null
2600
+ memberPermissions: actor.member?.permissions.bitfield ?? null,
2601
+ routeId: null
2603
2602
  };
2604
2603
  }
2605
2604
 
@@ -2973,7 +2972,7 @@ var EventDispatcher = class {
2973
2972
  const handlerEntries = this.eventMap.get(eventName);
2974
2973
  this.logger.debug(`Attaching ${chalk.bold.green(eventName)} to the client with ${chalk.gray(handlerEntries?.length ?? 0)} handler(s)`);
2975
2974
  this.core.bot.client.on(eventName, (...args) => {
2976
- this.core.bot.emit("any:event", eventName, ...args);
2975
+ this.core.bot.emitSafe("any:event", eventName, ...args);
2977
2976
  (async () => {
2978
2977
  await this.processEvent(eventName, args).catch((err) => {
2979
2978
  this.logger.error(`[${chalk.bold.red("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
@@ -3264,7 +3263,7 @@ var InteractionDispatcher = class {
3264
3263
  }
3265
3264
  attachToClient() {
3266
3265
  this.core.bot.client.on(Events.InteractionCreate, (interaction) => {
3267
- this.core.bot.emit("any:interaction", interaction);
3266
+ this.core.bot.emitSafe("any:interaction", interaction);
3268
3267
  this.handleInteraction(interaction).catch((err) => {
3269
3268
  this.logger.error(`[${chalk.bold.red("UNHANDLED ERROR AT ROOT")}] ${err.name}`, err.stack);
3270
3269
  this.core.bot.emit("error:unhandled:interaction", err);
@@ -3287,7 +3286,8 @@ var InteractionDispatcher = class {
3287
3286
  HandlerCtor = UnhandledEvent;
3288
3287
  }
3289
3288
  this.logger.debug(`Processing ${chalk.bold.green(key)} with ${chalk.gray(HandlerCtor.name)}`);
3290
- const handler = new HandlerCtor(interaction, this.core);
3289
+ const dispatch = new DispatchContext(routeIdOf(HandlerCtor));
3290
+ const handler = new HandlerCtor(interaction, this.core, dispatch);
3291
3291
  if (!interaction.isAutocomplete()) await runHandlerGates(HandlerCtor, interactionGateContext(interaction, this.core));
3292
3292
  await handler.execute();
3293
3293
  } catch (caught) {
@@ -3478,6 +3478,12 @@ var Bot = class extends Plugin {
3478
3478
  emit(event, ...args) {
3479
3479
  return super.emit(event, ...args);
3480
3480
  }
3481
+ emitSafe(event, ...args) {
3482
+ return super.emitSafe(event, ...args);
3483
+ }
3484
+ onListenerError(error, event) {
3485
+ this.logger.error(`listener for ${String(event)} threw`, error);
3486
+ }
3481
3487
  };
3482
3488
  __decorate([Envapt("DISCORD_BOT_TOKEN", { converter: (raw) => validateDiscordToken(raw) }), __decorateMetadata("design:type", String)], Bot.prototype, "botToken", void 0);
3483
3489
 
@@ -3811,7 +3817,7 @@ var Bus = class extends Plugin {
3811
3817
  //#endregion
3812
3818
  //#region src/version.ts
3813
3819
  /** Package version */
3814
- const version = "0.1.0-next.0";
3820
+ const version = "0.1.0-next.1";
3815
3821
 
3816
3822
  //#endregion
3817
3823
  //#region src/Seedcord.ts
@@ -3864,7 +3870,7 @@ var Seedcord = class Seedcord extends Pluggable {
3864
3870
  this.hmrManager.init();
3865
3871
  this.bus = new Bus(this);
3866
3872
  this.bot = new Bot(this);
3867
- this.rateLimiter = new MemoryRateLimiter();
3873
+ this.rateLimiter = config.store ?? new MemoryRateLimiter();
3868
3874
  this.healthCheck = new HealthCheck(this.shutdown, config.healthCheck);
3869
3875
  this.registerStartupTasks();
3870
3876
  }