seedcord 0.5.1 → 0.6.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.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { Logger, CoordinatedShutdown, CoordinatedStartup, StartupPhase } from '@seedcord/services';
1
+ import { CoordinatedShutdown, CoordinatedStartup, Logger, StartupPhase } from '@seedcord/services';
2
2
  export * from '@seedcord/services';
3
3
  import { ClientOptions, Guild, User, SlashCommandBuilder, ContextMenuCommandBuilder, Collection, Client, ChatInputCommandInteraction, ButtonInteraction, ModalSubmitInteraction, AutocompleteInteraction, AnySelectMenuInteraction, ContextMenuCommandInteraction, ClientEvents, Events, AutocompleteFocusedOption, SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder, EmbedBuilder, ModalBuilder, LabelBuilder, TextInputBuilder, FileUploadBuilder, ButtonBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, UserSelectMenuBuilder, ChannelSelectMenuBuilder, MentionableSelectMenuBuilder, RoleSelectMenuBuilder, ContainerBuilder, TextDisplayBuilder, FileBuilder, MediaGalleryBuilder, SectionBuilder, SeparatorBuilder, ActionRowBuilder, ColorResolvable, Interaction, Role, TextChannel, TextChannelResolvable, MessageActionRowComponentBuilder, Message, GuildMember, Snowflake, WebhookClient } from 'discord.js';
4
- import { Nullable, Tail, TypedConstructor, TypedExclude } from '@seedcord/types';
4
+ import { Tail, Nullable, TypedConstructor, TypedExclude } from '@seedcord/types';
5
5
  export * from '@seedcord/types';
6
6
  import { UUID } from 'crypto';
7
7
  import { Constructor, RequireAtLeastOne } from 'type-fest';
@@ -108,6 +108,74 @@ interface Config {
108
108
  effects: EffectsConfig;
109
109
  }
110
110
 
111
+ /** Interface for objects that can be initialized asynchronously */
112
+ interface Initializeable {
113
+ init(): Promise<void>;
114
+ }
115
+ /**
116
+ * Base class for Seedcord plugins
117
+ *
118
+ * Extend this class to create plugins that integrate with the Seedcord lifecycle.
119
+ * Plugins have access to the core instance and must implement initialization logic.
120
+ */
121
+ declare abstract class Plugin implements Initializeable {
122
+ protected pluggable: Core;
123
+ /** Logger instance for this plugin - must be implemented by subclasses */
124
+ abstract logger: Logger;
125
+ constructor(pluggable: Core);
126
+ /**
127
+ * Initialize the plugin - implement setup logic here
128
+ * @virtual Override this method in your plugin classes
129
+ */
130
+ abstract init(): Promise<void>;
131
+ }
132
+ /**
133
+ * Constructor type for plugins that can accept additional arguments after Core
134
+ * @typeParam TPlugin - The plugin type being constructed
135
+ */
136
+ type PluginCtor<TPlugin extends Plugin = Plugin> = new (core: Core, ...args: any[]) => TPlugin;
137
+ /**
138
+ * Extracts the argument types for a plugin constructor (excluding the Core parameter)
139
+ * @typeParam Ctor - The plugin constructor to extract arguments from
140
+ */
141
+ type PluginArgs<Ctor extends PluginCtor> = Tail<ConstructorParameters<Ctor>>;
142
+ /**
143
+ * Base class for objects that can have plugins attached
144
+ *
145
+ * Provides plugin attachment capabilities and lifecycle management.
146
+ * Plugins are attached during configuration and initialized during startup.
147
+ */
148
+ declare class Pluggable {
149
+ protected isInitialized: boolean;
150
+ protected readonly shutdown: CoordinatedShutdown;
151
+ protected readonly startup: CoordinatedStartup;
152
+ private static readonly PLUGIN_INIT_TIMEOUT_MS;
153
+ constructor(shutdown: CoordinatedShutdown, startup: CoordinatedStartup);
154
+ protected init(): Promise<this>;
155
+ /**
156
+ * Attaches a plugin to this instance
157
+ *
158
+ * Plugins provide external functionality and are initialized during the specified startup phase.
159
+ * The plugin instance becomes available as a property in `core` wherever it's available.
160
+ *
161
+ * Make sure to augment the {@link Core} interface with the plugin type to ensure TypeScript recognizes it and provides intellisense.
162
+ *
163
+ * @typeParam Key - The property name for accessing the plugin
164
+ * @typeParam Ctor - The plugin constructor type
165
+ * @param key - Property name to access the plugin instance
166
+ * @param Plugin - Plugin constructor class
167
+ * @param startupPhase - When during startup to initialize this plugin ({@link StartupPhase})
168
+ * @param args - Additional arguments to pass to the plugin constructor
169
+ * @returns This instance with the plugin attached as a typed property
170
+ * @throws An {@link Error} When called after initialization or if key already exists
171
+ * @example
172
+ * ```typescript
173
+ * seedcord.attach('db', Mongo, StartupPhase.Configuration, { uri: 'mongodb://...', name: 'seedcord', dir: ... })
174
+ * ```
175
+ */
176
+ attach<Key extends string, Ctor extends PluginCtor>(this: this, key: Key, Plugin: Ctor, startupPhase: StartupPhase, ...args: PluginArgs<Ctor>): this & Record<Key, InstanceType<Ctor>>;
177
+ }
178
+
111
179
  /**
112
180
  * Default side effects that are always available in the framework.
113
181
  */
@@ -211,74 +279,6 @@ interface BaseCore {
211
279
  interface Core extends BaseCore {
212
280
  }
213
281
 
214
- /** Interface for objects that can be initialized asynchronously */
215
- interface Initializeable {
216
- init(): Promise<void>;
217
- }
218
- /**
219
- * Base class for Seedcord plugins
220
- *
221
- * Extend this class to create plugins that integrate with the Seedcord lifecycle.
222
- * Plugins have access to the core instance and must implement initialization logic.
223
- */
224
- declare abstract class Plugin implements Initializeable {
225
- protected pluggable: Core;
226
- /** Logger instance for this plugin - must be implemented by subclasses */
227
- abstract logger: Logger;
228
- constructor(pluggable: Core);
229
- /**
230
- * Initialize the plugin - implement setup logic here
231
- * @virtual Override this method in your plugin classes
232
- */
233
- abstract init(): Promise<void>;
234
- }
235
- /**
236
- * Constructor type for plugins that can accept additional arguments after Core
237
- * @typeParam TPlugin - The plugin type being constructed
238
- */
239
- type PluginCtor<TPlugin extends Plugin = Plugin> = new (core: Core, ...args: any[]) => TPlugin;
240
- /**
241
- * Extracts the argument types for a plugin constructor (excluding the Core parameter)
242
- * @typeParam Ctor - The plugin constructor to extract arguments from
243
- */
244
- type PluginArgs<Ctor extends PluginCtor> = Tail<ConstructorParameters<Ctor>>;
245
- /**
246
- * Base class for objects that can have plugins attached
247
- *
248
- * Provides plugin attachment capabilities and lifecycle management.
249
- * Plugins are attached during configuration and initialized during startup.
250
- */
251
- declare class Pluggable {
252
- protected isInitialized: boolean;
253
- protected readonly shutdown: CoordinatedShutdown;
254
- protected readonly startup: CoordinatedStartup;
255
- private static readonly PLUGIN_INIT_TIMEOUT_MS;
256
- constructor(shutdown: CoordinatedShutdown, startup: CoordinatedStartup);
257
- protected init(): Promise<this>;
258
- /**
259
- * Attaches a plugin to this instance
260
- *
261
- * Plugins provide external functionality and are initialized during the specified startup phase.
262
- * The plugin instance becomes available as a property in `core` wherever it's available.
263
- *
264
- * Make sure to augment the {@link Core} interface with the plugin type to ensure TypeScript recognizes it and provides intellisense.
265
- *
266
- * @typeParam Key - The property name for accessing the plugin
267
- * @typeParam Ctor - The plugin constructor type
268
- * @param key - Property name to access the plugin instance
269
- * @param Plugin - Plugin constructor class
270
- * @param startupPhase - When during startup to initialize this plugin ({@link StartupPhase})
271
- * @param args - Additional arguments to pass to the plugin constructor
272
- * @returns This instance with the plugin attached as a typed property
273
- * @throws An {@link Error} When called after initialization or if key already exists
274
- * @example
275
- * ```typescript
276
- * seedcord.attach('db', Mongo, StartupPhase.Configuration, { uri: 'mongodb://...', name: 'seedcord', dir: ... })
277
- * ```
278
- */
279
- attach<Key extends string, Ctor extends PluginCtor>(this: this, key: Key, Plugin: Ctor, startupPhase: StartupPhase, ...args: PluginArgs<Ctor>): this & Record<Key, InstanceType<Ctor>>;
280
- }
281
-
282
282
  /**
283
283
  * Manages Discord application command registration and deployment.
284
284
  *
@@ -832,15 +832,41 @@ declare function RegisterCommand(scope: 'guild', guilds: string[]): (ctor: Comma
832
832
  */
833
833
  declare function EventCatchable(log?: boolean): (_target: EventHandler<keyof ClientEvents>, _prop: string, descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<void>>) => void;
834
834
 
835
+ /**
836
+ * The frequency at which the event handler should be executed.
837
+ */
838
+ type EventFrequency = 'once' | 'on';
839
+
840
+ /**
841
+ * Metadata key used to store event handler information
842
+ *
843
+ * @internal
844
+ */
835
845
  declare const EventMetadataKey: unique symbol;
846
+ /** Options accepted by the `@RegisterEvent` decorator. */
847
+ interface RegisterEventOptions {
848
+ /** Frequency: `'once'` or `'on'`. Defaults to `'on'`. */
849
+ readonly frequency?: EventFrequency | undefined;
850
+ }
851
+ /**
852
+ * Metadata entry representing a registered event handler.
853
+ *
854
+ * @internal
855
+ */
856
+ interface RegisterEventMetadataEntry<KeyofEvents extends keyof ClientEvents> {
857
+ readonly event: KeyofEvents;
858
+ readonly frequency: EventFrequency;
859
+ }
836
860
  /**
837
861
  * Registers an event handler class with a one or multiple Discord.js event(s).
838
862
  *
839
- * Associates the decorated class with the mentioned Discord client event(s) for automatic
840
- * registration and execution when the event is emitted.
863
+ * Associates the decorated class with the mentioned Discord client event(s) for automatic registration and execution when the event is emitted.
864
+ *
865
+ * You can use this decorator multiple times on the same class to register for different events with varying option settings.
841
866
  *
842
867
  * @typeParam KeyofEvents - The key of the Discord.js ClientEvents to register for
843
868
  * @param events - The Discord.js event name(s) to listen for
869
+ * @param options - Options to configure the event handler registration.
844
870
  * @decorator
845
871
  * @example
846
872
  * ```typescript
@@ -861,8 +887,18 @@ declare const EventMetadataKey: unique symbol;
861
887
  * }
862
888
  * }
863
889
  * ```
890
+ *
891
+ * @example
892
+ * ```ts
893
+ * \@RegisterEvent(Events.MessageCreate, { frequency: 'once' })
894
+ * class OneTimeMessageHandler extends EventHandler<Events.MessageCreate> {
895
+ * async execute() {
896
+ * // Handle only the first message creation
897
+ * }
898
+ * }
899
+ * ```
864
900
  */
865
- declare function RegisterEvent<KeyofEvents extends keyof ClientEvents>(events: KeyofEvents | KeyofEvents[]): (constructor: Constructor<unknown>) => void;
901
+ declare function RegisterEvent<KeyofEvents extends keyof ClientEvents>(events: KeyofEvents | KeyofEvents[], options?: RegisterEventOptions): (constructor: Constructor<unknown>) => void;
866
902
 
867
903
  /**
868
904
  * Enum defining interaction route types for decorators
@@ -1079,6 +1115,7 @@ declare class EventController implements Initializeable {
1079
1115
  private registerHandler;
1080
1116
  private attachToClient;
1081
1117
  private processEvent;
1118
+ private processHandler;
1082
1119
  }
1083
1120
 
1084
1121
  /**
@@ -1596,12 +1633,55 @@ declare class EffectsEmitter {
1596
1633
  emit<KeyOfEffects extends EffectKeys>(event: KeyOfEffects, data: AllEffects[KeyOfEffects]): boolean;
1597
1634
  }
1598
1635
 
1636
+ /**
1637
+ * Abstract base class for handling application side effects.
1638
+ *
1639
+ * Provides type-safe access to effects data and the core framework instance.
1640
+ * Extend this class to create custom side effect handlers.
1641
+ *
1642
+ * @typeParam KeyOfEffects - The specific side effect type this handler processes
1643
+ */
1644
+ declare abstract class EffectsHandler<KeyOfEffects extends EffectKeys> {
1645
+ protected readonly data: AllEffects[KeyOfEffects];
1646
+ protected readonly core: Core;
1647
+ /**
1648
+ * Creates a new effects handler instance.
1649
+ *
1650
+ * @param data - The effect event data
1651
+ * @param core - The core framework instance
1652
+ */
1653
+ constructor(data: AllEffects[KeyOfEffects], core: Core);
1654
+ /**
1655
+ * Executes the effect handler logic.
1656
+ * @virtual Override this method in your handler classes
1657
+ */
1658
+ abstract execute(): Promise<void>;
1659
+ }
1660
+
1599
1661
  /**
1600
1662
  * Metadata key used to store effect handler information
1601
1663
  *
1602
1664
  * @internal
1603
1665
  */
1604
1666
  declare const EffectMetadataKey: unique symbol;
1667
+ /**
1668
+ * Options accepted by the `@RegisterEffect` decorator.
1669
+ */
1670
+ interface RegisterEffectOptions {
1671
+ /** Frequency: `'once'` or `'on'`. Defaults to `'on'`. */
1672
+ readonly frequency?: EventFrequency | undefined;
1673
+ }
1674
+ /**
1675
+ * Metadata entry representing a registered effect handler.
1676
+ *
1677
+ * @internal
1678
+ */
1679
+ interface RegisterEffectMetadataEntry {
1680
+ /** The effect event name to register for. */
1681
+ readonly effect: EffectKeys;
1682
+ /** Frequency: `'once'` or `'on'`. Defaults to `'on'`. */
1683
+ readonly frequency?: EventFrequency | undefined;
1684
+ }
1605
1685
  /**
1606
1686
  * Registers a side effect handler class with a specific side effect event.
1607
1687
  *
@@ -1610,6 +1690,7 @@ declare const EffectMetadataKey: unique symbol;
1610
1690
  *
1611
1691
  * @typeParam TEffect - The side effect event name to register for
1612
1692
  * @param effect - The side effect event name to register for
1693
+ * @param options - Options to configure the effect handler registration.
1613
1694
  * @decorator
1614
1695
  * @example
1615
1696
  * ```typescript
@@ -1620,39 +1701,20 @@ declare const EffectMetadataKey: unique symbol;
1620
1701
  * }
1621
1702
  * }
1622
1703
  * ```
1704
+ * @example
1705
+ * ```ts
1706
+ * \@RegisterEffect('userJoin', { frequency: 'once' })
1707
+ * // or
1708
+ * \@RegisterEffect('userJoin')
1709
+ * ```
1623
1710
  */
1624
- declare function RegisterEffect<TEffect extends EffectKeys>(effect: TEffect): (constructor: Constructor<unknown>) => void;
1625
-
1626
- /**
1627
- * Abstract base class for handling application side effects.
1628
- *
1629
- * Provides type-safe access to effects data and the core framework instance.
1630
- * Extend this class to create custom side effect handlers.
1631
- *
1632
- * @typeParam KeyOfEffects - The specific side effect type this handler processes
1633
- */
1634
- declare abstract class EffectsHandler<KeyOfEffects extends EffectKeys> {
1635
- protected readonly data: AllEffects[KeyOfEffects];
1636
- protected readonly core: Core;
1637
- /**
1638
- * Creates a new effects handler instance.
1639
- *
1640
- * @param data - The effect event data
1641
- * @param core - The core framework instance
1642
- */
1643
- constructor(data: AllEffects[KeyOfEffects], core: Core);
1644
- /**
1645
- * Executes the effect handler logic.
1646
- * @virtual Override this method in your handler classes
1647
- */
1648
- abstract execute(): Promise<void>;
1649
- }
1711
+ declare function RegisterEffect<TEffect extends EffectKeys>(effect: TEffect, options?: RegisterEffectOptions): (constructor: Constructor<unknown>) => void;
1650
1712
 
1651
1713
  /**
1652
1714
  * Abstract webhook logging handler for side effect events.
1653
1715
  *
1654
1716
  * Extends EffectsHandler to provide webhook-based logging capabilities.
1655
- * Implementations must define the webhook client to send messages to.
1717
+ * Implementations must define the `webhook client` to send messages to by implementing the webhook property.
1656
1718
  *
1657
1719
  * @typeParam KeyOfEffects - The specific side effect type this handler processes
1658
1720
  */
@@ -1683,4 +1745,4 @@ declare class UnknownException extends WebhookLog<'unknownException'> {
1683
1745
  private prepareMetadataFile;
1684
1746
  }
1685
1747
 
1686
- export { type ActionRowComponentType, type AllEffects, type AtleastOneMessageComponent, AutocompleteHandler, type AutocompleteHandlerConstructor, AutocompleteRoute, BaseComponent, type BaseCore, BaseErrorEmbed, BaseHandler, Bot, type BotConfig, type BotPermissionScope, type BotPermissionScopeGroups, BuilderComponent, type BuilderType, BuilderTypes, ButtonRoute, CannotAssignBotRole, CannotSendEmbedsError, Catchable, type CatchableOptions, ChannelNotFoundError, ChannelNotTextChannel, Checkable, type CommandCtor, type CommandMeta, CommandMetadataKey, CommandRegistry, type CommandRouteString, type CommandScope, type CommandsConfig, type Config, ContextMenuRoute, type Core, CouldNotFindChannel, CustomError, type CustomErrorConstructor, DatabaseError, type DefaultEffects, type EffectKeys, EffectMetadataKey, type EffectParams, type Effects, type EffectsConfig, EffectsEmitter, EffectsHandler, EffectsRegistry, EmojiInjector, EventCatchable, EventController, EventHandler, type EventHandlerConstructor, EventMetadataKey, EventMiddleware, type EventMiddlewareConstructor, type EventsConfig, type ExtractedErrorResponse, GenericError, type GlobalMeta, type GuildMeta, type Handler, type HandlerConstructor, type HandlerCtor, type HandlerWithChecks, HasDangerousPermissions, type Initializeable, type InstantiatedActionRow, type InstantiatedBuilder, InteractionController, InteractionHandler, InteractionMetadataKey, InteractionMiddleware, type InteractionMiddlewareConstructor, InteractionRoutes, type InteractionsConfig, type MessageContent, Middleware, type MiddlewareConstructor, type MiddlewareMetadata, MiddlewareMetadataKey, type MiddlewareOptions, MiddlewareType, MissingPermissions, ModalRoute, PERM_GROUPS, PermissionNames, Pluggable, Plugin, type PluginArgs, type PluginCtor, RegisterCommand, RegisterEffect, RegisterEvent, type RepliableInteractionHandler, type Repliables, RoleDoesNotExist, RoleHigherThanMe, RowComponent, RowTypes, Seedcord, SelectMenuRoute, SelectMenuType, SlashRoute, UnhandledEvent, UnknownException, UserNotFound, UserNotInGuild, type ValidEventTypes, type ValidInteractionTypes, type ValidNonInteractionTypes, WebhookLog, type WithChecks, attemptSendDM, buildSlashRoute, checkBotPermissions, checkPermissions, extractErrorResponse, fetchGuildMember, fetchManyGuildMembers, fetchManyUsers, fetchRole, fetchText, fetchUser, getBotRole, hasPermsToAssign, sendInText, throwCustomError, updateMemberRoles };
1748
+ export { type ActionRowComponentType, type AllEffects, type AtleastOneMessageComponent, AutocompleteHandler, type AutocompleteHandlerConstructor, AutocompleteRoute, BaseComponent, type BaseCore, BaseErrorEmbed, BaseHandler, Bot, type BotConfig, type BotPermissionScope, type BotPermissionScopeGroups, BuilderComponent, type BuilderType, BuilderTypes, ButtonRoute, CannotAssignBotRole, CannotSendEmbedsError, Catchable, type CatchableOptions, ChannelNotFoundError, ChannelNotTextChannel, Checkable, type CommandCtor, type CommandMeta, CommandMetadataKey, CommandRegistry, type CommandRouteString, type CommandScope, type CommandsConfig, type Config, ContextMenuRoute, type Core, CouldNotFindChannel, CustomError, type CustomErrorConstructor, DatabaseError, type DefaultEffects, type EffectKeys, EffectMetadataKey, type EffectParams, type Effects, type EffectsConfig, EffectsEmitter, EffectsHandler, EffectsRegistry, EmojiInjector, EventCatchable, EventController, EventHandler, type EventHandlerConstructor, EventMetadataKey, EventMiddleware, type EventMiddlewareConstructor, type EventsConfig, type ExtractedErrorResponse, GenericError, type GlobalMeta, type GuildMeta, type Handler, type HandlerConstructor, type HandlerCtor, type HandlerWithChecks, HasDangerousPermissions, type Initializeable, type InstantiatedActionRow, type InstantiatedBuilder, InteractionController, InteractionHandler, InteractionMetadataKey, InteractionMiddleware, type InteractionMiddlewareConstructor, InteractionRoutes, type InteractionsConfig, type MessageContent, Middleware, type MiddlewareConstructor, type MiddlewareMetadata, MiddlewareMetadataKey, type MiddlewareOptions, MiddlewareType, MissingPermissions, ModalRoute, PERM_GROUPS, PermissionNames, Pluggable, Plugin, type PluginArgs, type PluginCtor, RegisterCommand, RegisterEffect, type RegisterEffectMetadataEntry, type RegisterEffectOptions, RegisterEvent, type RegisterEventMetadataEntry, type RegisterEventOptions, type RepliableInteractionHandler, type Repliables, RoleDoesNotExist, RoleHigherThanMe, RowComponent, RowTypes, Seedcord, SelectMenuRoute, SelectMenuType, SlashRoute, UnhandledEvent, UnknownException, UserNotFound, UserNotInGuild, type ValidEventTypes, type ValidInteractionTypes, type ValidNonInteractionTypes, WebhookLog, type WithChecks, attemptSendDM, buildSlashRoute, checkBotPermissions, checkPermissions, extractErrorResponse, fetchGuildMember, fetchManyGuildMembers, fetchManyUsers, fetchRole, fetchText, fetchUser, getBotRole, hasPermsToAssign, sendInText, throwCustomError, updateMemberRoles };