seedcord 0.10.5 → 0.11.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,4 +10,4 @@ _This repository is a work in progress._
10
10
  - Till a major v1.0.0 release for seedcord, expect breaking changes in minor versions.
11
11
  - Documentation will come soon as well!
12
12
 
13
- I'm planning to release the first major version by the end of 2025, or Jan 2026. But till then, if you'd like to try using it, you can check out the code in `packages/mock`
13
+ I'm planning to release the first major version by Q1 2026. But till then, if you'd like to try using it, you can check out the code in `mock`
@@ -0,0 +1,244 @@
1
+ import { ActionRowBuilder, ButtonBuilder, ChannelSelectMenuBuilder, ContainerBuilder, ContextMenuCommandBuilder, EmbedBuilder, FileBuilder, FileUploadBuilder, LabelBuilder, MediaGalleryBuilder, MentionableSelectMenuBuilder, ModalBuilder, RoleSelectMenuBuilder, SectionBuilder, SeparatorBuilder, SlashCommandBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, TextDisplayBuilder, TextInputBuilder, UserSelectMenuBuilder } from "discord.js";
2
+
3
+ //#region ../../node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/non-empty-tuple.d.ts
4
+ /**
5
+ Matches any non-empty tuple.
6
+
7
+ @example
8
+ ```
9
+ import type {NonEmptyTuple} from 'type-fest';
10
+
11
+ const sum = (...numbers: NonEmptyTuple<number>) => numbers.reduce((total, value) => total + value, 0);
12
+
13
+ sum(1, 2, 3);
14
+ // Ok
15
+
16
+ // @ts-expect-error
17
+ sum();
18
+ // Error: Expected at least 1 arguments, but got 0.
19
+ ```
20
+
21
+ @see {@link RequireAtLeastOne} for objects
22
+
23
+ @category Array
24
+ */
25
+ type NonEmptyTuple<T = unknown> = readonly [T, ...T[]];
26
+ //#endregion
27
+ //#region ../../node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/join.d.ts
28
+ // The builtin `join` method supports all these natively in the same way that typescript handles them so we can safely accept all of them.
29
+ type JoinableItem = string | number | bigint | boolean | undefined | null; // `null` and `undefined` are treated uniquely in the built-in join method, in a way that differs from the default `toString` that would result in the type `${undefined}`. That's why we need to handle it specifically with this helper.
30
+ // @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join#description
31
+ type NullishCoalesce<Value extends JoinableItem, Fallback extends string> = Value extends undefined | null ? NonNullable<Value> | Fallback : Value;
32
+ /**
33
+ Join an array of strings and/or numbers using the given string as a delimiter.
34
+
35
+ Use-case: Defining key paths in a nested object. For example, for dot-notation fields in MongoDB queries.
36
+
37
+ @example
38
+ ```
39
+ import type {Join} from 'type-fest';
40
+
41
+ // Mixed (strings & numbers) items
42
+ const path1 = ['foo', 0, 'baz'].join('.') as Join<['foo', 0, 'baz'], '.'>;
43
+ //=> 'foo.0.baz'
44
+
45
+ // Only string items
46
+ const path2 = ['foo', 'bar', 'baz'].join('.') as Join<['foo', 'bar', 'baz'], '.'>;
47
+ //=> 'foo.bar.baz'
48
+
49
+ // Only number items
50
+ const path3 = [1, 2, 3].join('.') as Join<[1, 2, 3], '.'>;
51
+ //=> '1.2.3'
52
+
53
+ // Only bigint items
54
+ const path4 = [1n, 2n, 3n].join('.') as Join<[1n, 2n, 3n], '.'>;
55
+ //=> '1.2.3'
56
+
57
+ // Only boolean items
58
+ const path5 = [true, false, true].join('.') as Join<[true, false, true], '.'>;
59
+ //=> 'true.false.true'
60
+
61
+ // Contains nullish items
62
+ const path6 = ['foo', undefined, 'baz', null, 'xyz'].join('.') as Join<['foo', undefined, 'baz', null, 'xyz'], '.'>;
63
+ //=> 'foo..baz..xyz'
64
+
65
+ // Partial tuple shapes (rest param last)
66
+ const path7 = ['prefix'].join('.') as Join<['prefix', ...string[]], '.'>;
67
+ //=> `prefix.${string}`
68
+
69
+ // Partial tuple shapes (rest param first)
70
+ const path8 = ['suffix'].join('.') as Join<[...string[], 'suffix'], '.'>;
71
+ //=> `${string}.suffix`
72
+
73
+ // Tuples items with nullish unions
74
+ const path9 = ['hello', 'world'].join('.') as Join<['hello' | undefined, 'world' | null], '.'>;
75
+ //=> '.' | '.world' | 'hello.' | 'hello.world'
76
+ ```
77
+
78
+ @category Array
79
+ @category Template literal
80
+ */
81
+ type Join<Items extends readonly JoinableItem[], Delimiter extends string> = Items extends readonly [] ? '' : Items extends readonly [JoinableItem?] ? `${NullishCoalesce<Items[0], ''>}` : Items extends readonly [infer First extends JoinableItem, ...infer Tail extends readonly JoinableItem[]] ? `${NullishCoalesce<First, ''>}${Delimiter}${Join<Tail, Delimiter>}` : Items extends readonly [...infer Head extends readonly JoinableItem[], infer Last extends JoinableItem] ? `${Join<Head, Delimiter>}${Delimiter}${NullishCoalesce<Last, ''>}` : string;
82
+ //#endregion
83
+ //#region src/interfaces/Components.d.ts
84
+ /**
85
+ * Available Discord.js builder classes for use with BuilderComponent
86
+ *
87
+ * @internal
88
+ */
89
+ declare const BuilderTypes: {
90
+ command: typeof SlashCommandBuilder;
91
+ context_menu: typeof ContextMenuCommandBuilder;
92
+ subcommand: typeof SlashCommandSubcommandBuilder;
93
+ group: typeof SlashCommandSubcommandGroupBuilder;
94
+ embed: typeof EmbedBuilder;
95
+ modal: typeof ModalBuilder;
96
+ label: typeof LabelBuilder;
97
+ text_input: typeof TextInputBuilder;
98
+ file_upload: typeof FileUploadBuilder;
99
+ button: typeof ButtonBuilder;
100
+ menu_string: typeof StringSelectMenuBuilder;
101
+ menu_option_string: typeof StringSelectMenuOptionBuilder;
102
+ menu_user: typeof UserSelectMenuBuilder;
103
+ menu_channel: typeof ChannelSelectMenuBuilder;
104
+ menu_mentionable: typeof MentionableSelectMenuBuilder;
105
+ menu_role: typeof RoleSelectMenuBuilder;
106
+ container: typeof ContainerBuilder;
107
+ text_display: typeof TextDisplayBuilder;
108
+ file: typeof FileBuilder;
109
+ media: typeof MediaGalleryBuilder;
110
+ section: typeof SectionBuilder;
111
+ separator: typeof SeparatorBuilder;
112
+ };
113
+ /**
114
+ * Available Discord.js action row classes for use with RowComponent
115
+ *
116
+ * @internal
117
+ */
118
+ declare const RowTypes: {
119
+ button: typeof ActionRowBuilder<ButtonBuilder>;
120
+ menu_string: typeof ActionRowBuilder<StringSelectMenuBuilder>;
121
+ menu_user: typeof ActionRowBuilder<UserSelectMenuBuilder>;
122
+ menu_channel: typeof ActionRowBuilder<ChannelSelectMenuBuilder>;
123
+ menu_mentionable: typeof ActionRowBuilder<MentionableSelectMenuBuilder>;
124
+ menu_role: typeof ActionRowBuilder<RoleSelectMenuBuilder>;
125
+ };
126
+ /**
127
+ * Available Discord.js builder types for use with BuilderComponent
128
+ */
129
+ type BuilderType = keyof typeof BuilderTypes;
130
+ /**
131
+ * @internal
132
+ */
133
+ type InstantiatedBuilder<BuilderKey extends BuilderType> = InstanceType<(typeof BuilderTypes)[BuilderKey]>;
134
+ /**
135
+ * Available Discord.js action row types for use with RowComponent
136
+ */
137
+ type ActionRowComponentType = keyof typeof RowTypes;
138
+ /**
139
+ * @internal
140
+ */
141
+ type InstantiatedActionRow<RowKey extends ActionRowComponentType> = InstanceType<(typeof RowTypes)[RowKey]>;
142
+ /**
143
+ * Base class for Discord component wrappers
144
+ *
145
+ * Provides common functionality for building Discord components with proper typing.
146
+ *
147
+ * @typeParam TComponent - The Discord.js component type being wrapped
148
+ *
149
+ * @internal
150
+ */
151
+ declare abstract class BaseComponent<TComponent> {
152
+ private readonly _component;
153
+ protected constructor(ComponentClass: new () => TComponent);
154
+ /**
155
+ * Gets the built component (should be considered read-only)
156
+ *
157
+ * Returns the finalized component ready for use in Discord messages.
158
+ *
159
+ * Please do not use for further configuration, use `this.instance` for that.
160
+ * @example new SomeComponent().component
161
+ */
162
+ abstract get component(): InstantiatedBuilder<BuilderType> | InstantiatedActionRow<ActionRowComponentType>;
163
+ /**
164
+ * Gets the component instance for configuration
165
+ *
166
+ * Use this to access Discord.js builder methods like setTitle(), setDescription(), etc.
167
+ *
168
+ * Use this in your component classes to configure the builder
169
+ * @example this.instance.setTitle('My Modal')
170
+ */
171
+ protected get instance(): TComponent;
172
+ /**
173
+ * Builds a customId string for interactive components with no arguments
174
+ *
175
+ * @param prefix - The route prefix that handlers will match against
176
+ * @returns The prefix as the customId
177
+ */
178
+ buildCustomId<Prefix extends string>(prefix: Prefix): Prefix;
179
+ /**
180
+ * Builds a customId string for interactive components
181
+ *
182
+ * Creates customIds in the format `prefix:arg1-arg2-arg3` for buttons, modals, etc.
183
+ * Arguments are joined with hyphens and separated from prefix with a colon.
184
+ *
185
+ * @param prefix - The route prefix that handlers will match against
186
+ * @param args - Additional arguments to encode in the customId
187
+ * @returns Formatted customId string
188
+ */
189
+ buildCustomId<Prefix extends string, Args extends NonEmptyTuple<string>>(prefix: Prefix, ...args: Args): `${Prefix}:${Join<Args, '-'>}`;
190
+ }
191
+ /**
192
+ * Base class for Discord.js builder components
193
+ *
194
+ * Wraps Discord.js builders (SlashCommandBuilder, EmbedBuilder, etc.) with
195
+ * Seedcord-specific defaults and helper methods.
196
+ *
197
+ * @typeParam BuilderKey - The type of Discord.js builder being wrapped
198
+ */
199
+ declare abstract class BuilderComponent<BuilderKey extends BuilderType> extends BaseComponent<InstantiatedBuilder<BuilderKey>> {
200
+ readonly type: BuilderKey;
201
+ private colorApplied;
202
+ protected constructor(type: BuilderKey);
203
+ get component(): InstantiatedBuilder<BuilderKey>;
204
+ private applyBotColor;
205
+ }
206
+ /**
207
+ * Base class for Discord action row components
208
+ *
209
+ * Wraps Discord.js action row builder with Seedcord-specific defaults and helper methods.
210
+ *
211
+ * @typeParam RowKey - The Discord.js action row type being wrapped
212
+ */
213
+ declare abstract class RowComponent<RowKey extends ActionRowComponentType> extends BaseComponent<InstantiatedActionRow<RowKey>> {
214
+ readonly type: RowKey;
215
+ protected constructor(type: RowKey);
216
+ get component(): InstantiatedActionRow<RowKey>;
217
+ }
218
+ /**
219
+ * Base class for custom error types with Discord embed responses
220
+ *
221
+ * Errors extending CustomError should be used with the `Catchable` decorators to implement a control flow. These errors will be caught and handled by the framework to show the user the configured response.
222
+ */
223
+ declare abstract class CustomError extends Error {
224
+ message: string;
225
+ private _emit;
226
+ readonly response: EmbedBuilder;
227
+ protected constructor(message: string);
228
+ /**
229
+ * Whether this error should be emitted to logs
230
+ *
231
+ * Controls logging behavior. Errors with emit=true will always be logged,
232
+ * while emit=false errors may be suppressed in production.
233
+ *
234
+ * @returns True if the error should be logged
235
+ */
236
+ get emit(): boolean;
237
+ /**
238
+ * Sets whether this error should be emitted to logs
239
+ */
240
+ set emit(value: boolean);
241
+ }
242
+ //#endregion
243
+ export { RowComponent as a, CustomError as i, BuilderComponent as n, NonEmptyTuple as o, BuilderType as r, ActionRowComponentType as t };
244
+ //# sourceMappingURL=Components-D-AZ6ESx.d.mts.map
@@ -0,0 +1,217 @@
1
+ import { ActionRowBuilder, ButtonBuilder, ChannelSelectMenuBuilder, ContainerBuilder, ContextMenuCommandBuilder, EmbedBuilder, FileBuilder, FileUploadBuilder, InteractionContextType, LabelBuilder, MediaGalleryBuilder, MentionableSelectMenuBuilder, ModalBuilder, RoleSelectMenuBuilder, SectionBuilder, SeparatorBuilder, SlashCommandBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, TextDisplayBuilder, TextInputBuilder, UserSelectMenuBuilder, resolveColor } from "discord.js";
2
+
3
+ //#region src/miscellaneous/botColorHolder.ts
4
+ const DEFAULT_COLOR = "Default";
5
+ let current = DEFAULT_COLOR;
6
+ /** @internal */
7
+ function setBotColor(color) {
8
+ current = color ?? DEFAULT_COLOR;
9
+ }
10
+ /** @internal */
11
+ function getBotColor() {
12
+ return current;
13
+ }
14
+
15
+ //#endregion
16
+ //#region src/interfaces/Components.ts
17
+ /**
18
+ * Available Discord.js builder classes for use with BuilderComponent
19
+ *
20
+ * @internal
21
+ */
22
+ const BuilderTypes = {
23
+ command: SlashCommandBuilder,
24
+ context_menu: ContextMenuCommandBuilder,
25
+ subcommand: SlashCommandSubcommandBuilder,
26
+ group: SlashCommandSubcommandGroupBuilder,
27
+ embed: EmbedBuilder,
28
+ modal: ModalBuilder,
29
+ label: LabelBuilder,
30
+ text_input: TextInputBuilder,
31
+ file_upload: FileUploadBuilder,
32
+ button: ButtonBuilder,
33
+ menu_string: StringSelectMenuBuilder,
34
+ menu_option_string: StringSelectMenuOptionBuilder,
35
+ menu_user: UserSelectMenuBuilder,
36
+ menu_channel: ChannelSelectMenuBuilder,
37
+ menu_mentionable: MentionableSelectMenuBuilder,
38
+ menu_role: RoleSelectMenuBuilder,
39
+ container: ContainerBuilder,
40
+ text_display: TextDisplayBuilder,
41
+ file: FileBuilder,
42
+ media: MediaGalleryBuilder,
43
+ section: SectionBuilder,
44
+ separator: SeparatorBuilder
45
+ };
46
+ /**
47
+ * Available Discord.js action row classes for use with RowComponent
48
+ *
49
+ * @internal
50
+ */
51
+ const RowTypes = {
52
+ button: ActionRowBuilder,
53
+ menu_string: ActionRowBuilder,
54
+ menu_user: ActionRowBuilder,
55
+ menu_channel: ActionRowBuilder,
56
+ menu_mentionable: ActionRowBuilder,
57
+ menu_role: ActionRowBuilder
58
+ };
59
+ /**
60
+ * Base class for Discord component wrappers
61
+ *
62
+ * Provides common functionality for building Discord components with proper typing.
63
+ *
64
+ * @typeParam TComponent - The Discord.js component type being wrapped
65
+ *
66
+ * @internal
67
+ */
68
+ var BaseComponent = class {
69
+ _component;
70
+ constructor(ComponentClass) {
71
+ this._component = new ComponentClass();
72
+ }
73
+ /**
74
+ * Gets the component instance for configuration
75
+ *
76
+ * Use this to access Discord.js builder methods like setTitle(), setDescription(), etc.
77
+ *
78
+ * Use this in your component classes to configure the builder
79
+ * @example this.instance.setTitle('My Modal')
80
+ */
81
+ get instance() {
82
+ return this._component;
83
+ }
84
+ buildCustomId(prefix, ...args) {
85
+ return args.length === 0 ? prefix : `${prefix}:${args.join("-")}`;
86
+ }
87
+ };
88
+ /**
89
+ * Base class for Discord.js builder components
90
+ *
91
+ * Wraps Discord.js builders (SlashCommandBuilder, EmbedBuilder, etc.) with
92
+ * Seedcord-specific defaults and helper methods.
93
+ *
94
+ * @typeParam BuilderKey - The type of Discord.js builder being wrapped
95
+ */
96
+ var BuilderComponent = class extends BaseComponent {
97
+ type;
98
+ colorApplied = false;
99
+ constructor(type) {
100
+ const ComponentClass = BuilderTypes[type];
101
+ super(ComponentClass);
102
+ this.type = type;
103
+ if (this.instance instanceof SlashCommandBuilder || this.instance instanceof ContextMenuCommandBuilder) this.instance.setContexts(InteractionContextType.Guild);
104
+ }
105
+ get component() {
106
+ this.applyBotColor();
107
+ return this.instance;
108
+ }
109
+ applyBotColor() {
110
+ if (this.colorApplied) return;
111
+ this.colorApplied = true;
112
+ const color = getBotColor();
113
+ if (this.instance instanceof EmbedBuilder) {
114
+ if (this.instance.data.color === void 0) this.instance.setColor(color);
115
+ } else if (this.instance instanceof ContainerBuilder) {
116
+ const accent = this.instance.data.accent_color;
117
+ if (accent === null || accent === void 0) this.instance.setAccentColor(color === "Default" ? void 0 : resolveColor(color));
118
+ }
119
+ }
120
+ };
121
+ /**
122
+ * Base class for Discord action row components
123
+ *
124
+ * Wraps Discord.js action row builder with Seedcord-specific defaults and helper methods.
125
+ *
126
+ * @typeParam RowKey - The Discord.js action row type being wrapped
127
+ */
128
+ var RowComponent = class extends BaseComponent {
129
+ type;
130
+ constructor(type) {
131
+ const ComponentClass = RowTypes[type];
132
+ super(ComponentClass);
133
+ this.type = type;
134
+ }
135
+ get component() {
136
+ return this.instance;
137
+ }
138
+ };
139
+ /**
140
+ * Pre-configured error embed with default styling
141
+ *
142
+ * This is bundled in {@link CustomError}s as the response.
143
+ *
144
+ * @internal
145
+ */
146
+ var BaseErrorEmbed = class extends BuilderComponent {
147
+ /**
148
+ * Creates a new error embed with default configuration.
149
+ */
150
+ constructor() {
151
+ super("embed");
152
+ this.instance.setTitle("Cannot Proceed");
153
+ }
154
+ };
155
+ /**
156
+ * Base class for custom error types with Discord embed responses
157
+ *
158
+ * Errors extending CustomError should be used with the `Catchable` decorators to implement a control flow. These errors will be caught and handled by the framework to show the user the configured response.
159
+ */
160
+ var CustomError = class extends Error {
161
+ message;
162
+ _emit = false;
163
+ response = new BaseErrorEmbed().component;
164
+ constructor(message) {
165
+ super(message);
166
+ this.message = message;
167
+ Error.captureStackTrace(this, this.constructor);
168
+ }
169
+ /**
170
+ * Whether this error should be emitted to logs
171
+ *
172
+ * Controls logging behavior. Errors with emit=true will always be logged,
173
+ * while emit=false errors may be suppressed in production.
174
+ *
175
+ * @returns True if the error should be logged
176
+ */
177
+ get emit() {
178
+ return this._emit;
179
+ }
180
+ /**
181
+ * Sets whether this error should be emitted to logs
182
+ */
183
+ set emit(value) {
184
+ this._emit = value;
185
+ }
186
+ };
187
+
188
+ //#endregion
189
+ //#region src/bot/defaults/errors/Database.ts
190
+ /**
191
+ * Generic database operation error with UUID tracking.
192
+ *
193
+ * Thrown for various database operation failures and includes
194
+ * a UUID for error tracking and debugging purposes.
195
+ *
196
+ * @internal
197
+ */
198
+ var DatabaseError = class extends CustomError {
199
+ uuid;
200
+ /**
201
+ * Creates a new DatabaseError.
202
+ *
203
+ * @param message - The error message describing what went wrong
204
+ * @param uuid - A unique identifier for this specific error instance
205
+ */
206
+ constructor(message, uuid) {
207
+ super(message);
208
+ this.uuid = uuid;
209
+ this.emit = true;
210
+ this.name = "DatabaseError";
211
+ this.response.setTitle("Database Error").setDescription(`An error occurred while interacting with the database.\n### UUID: \`${this.uuid}\``);
212
+ }
213
+ };
214
+
215
+ //#endregion
216
+ export { setBotColor as a, RowComponent as i, BuilderComponent as n, CustomError as r, DatabaseError as t };
217
+ //# sourceMappingURL=Database-CqvL4DO2.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Database-CqvL4DO2.mjs","names":[],"sources":["../src/miscellaneous/botColorHolder.ts","../src/interfaces/Components.ts","../src/bot/defaults/errors/Database.ts"],"sourcesContent":["import type { ColorResolvable } from 'discord.js';\n\n// 'Default' is Discord.js's own sentinel for \"no explicit color\".\nconst DEFAULT_COLOR: ColorResolvable = 'Default';\n\nlet current: ColorResolvable = DEFAULT_COLOR;\n\n/** @internal */\nexport function setBotColor(color: ColorResolvable | undefined): void {\n current = color ?? DEFAULT_COLOR;\n}\n\n/** @internal */\nexport function getBotColor(): ColorResolvable {\n return current;\n}\n","import {\n ActionRowBuilder,\n ButtonBuilder,\n ChannelSelectMenuBuilder,\n ContainerBuilder,\n ContextMenuCommandBuilder,\n EmbedBuilder,\n FileBuilder,\n FileUploadBuilder,\n InteractionContextType,\n LabelBuilder,\n MediaGalleryBuilder,\n MentionableSelectMenuBuilder,\n ModalBuilder,\n RoleSelectMenuBuilder,\n SectionBuilder,\n SeparatorBuilder,\n SlashCommandBuilder,\n SlashCommandSubcommandBuilder,\n SlashCommandSubcommandGroupBuilder,\n StringSelectMenuBuilder,\n StringSelectMenuOptionBuilder,\n TextDisplayBuilder,\n TextInputBuilder,\n UserSelectMenuBuilder,\n resolveColor\n} from 'discord.js';\n\nimport { getBotColor } from '@miscellaneous/botColorHolder';\n\nimport type { Join, NonEmptyTuple } from 'type-fest';\n\n/**\n * Available Discord.js builder classes for use with BuilderComponent\n *\n * @internal\n */\nexport const BuilderTypes = {\n // Command Components\n command: SlashCommandBuilder,\n context_menu: ContextMenuCommandBuilder,\n subcommand: SlashCommandSubcommandBuilder,\n group: SlashCommandSubcommandGroupBuilder,\n\n // Embed Components\n embed: EmbedBuilder,\n\n // Modal Components\n modal: ModalBuilder,\n label: LabelBuilder,\n text_input: TextInputBuilder,\n file_upload: FileUploadBuilder,\n\n // Action Row Components\n button: ButtonBuilder,\n menu_string: StringSelectMenuBuilder,\n menu_option_string: StringSelectMenuOptionBuilder,\n menu_user: UserSelectMenuBuilder,\n menu_channel: ChannelSelectMenuBuilder,\n menu_mentionable: MentionableSelectMenuBuilder,\n menu_role: RoleSelectMenuBuilder,\n\n // ComponentsV2\n container: ContainerBuilder,\n text_display: TextDisplayBuilder,\n file: FileBuilder,\n media: MediaGalleryBuilder,\n section: SectionBuilder,\n separator: SeparatorBuilder\n};\n\n/**\n * Available Discord.js action row classes for use with RowComponent\n *\n * @internal\n */\nexport const RowTypes: {\n button: typeof ActionRowBuilder<ButtonBuilder>;\n menu_string: typeof ActionRowBuilder<StringSelectMenuBuilder>;\n menu_user: typeof ActionRowBuilder<UserSelectMenuBuilder>;\n menu_channel: typeof ActionRowBuilder<ChannelSelectMenuBuilder>;\n menu_mentionable: typeof ActionRowBuilder<MentionableSelectMenuBuilder>;\n menu_role: typeof ActionRowBuilder<RoleSelectMenuBuilder>;\n} = {\n button: ActionRowBuilder<ButtonBuilder>,\n menu_string: ActionRowBuilder<StringSelectMenuBuilder>,\n menu_user: ActionRowBuilder<UserSelectMenuBuilder>,\n menu_channel: ActionRowBuilder<ChannelSelectMenuBuilder>,\n menu_mentionable: ActionRowBuilder<MentionableSelectMenuBuilder>,\n menu_role: ActionRowBuilder<RoleSelectMenuBuilder>\n};\n\n/**\n * Available Discord.js builder types for use with BuilderComponent\n */\nexport type BuilderType = keyof typeof BuilderTypes;\n\n/**\n * @internal\n */\nexport type InstantiatedBuilder<BuilderKey extends BuilderType> = InstanceType<(typeof BuilderTypes)[BuilderKey]>;\n\n/**\n * Available Discord.js action row types for use with RowComponent\n */\nexport type ActionRowComponentType = keyof typeof RowTypes;\n\n/**\n * @internal\n */\nexport type InstantiatedActionRow<RowKey extends ActionRowComponentType> = InstanceType<(typeof RowTypes)[RowKey]>;\n\n/**\n * Base class for Discord component wrappers\n *\n * Provides common functionality for building Discord components with proper typing.\n *\n * @typeParam TComponent - The Discord.js component type being wrapped\n *\n * @internal\n */\nexport abstract class BaseComponent<TComponent> {\n private readonly _component: TComponent;\n\n protected constructor(ComponentClass: new () => TComponent) {\n this._component = new ComponentClass();\n }\n\n /**\n * Gets the built component (should be considered read-only)\n *\n * Returns the finalized component ready for use in Discord messages.\n *\n * Please do not use for further configuration, use `this.instance` for that.\n * @example new SomeComponent().component\n */\n public abstract get component(): InstantiatedBuilder<BuilderType> | InstantiatedActionRow<ActionRowComponentType>;\n\n /**\n * Gets the component instance for configuration\n *\n * Use this to access Discord.js builder methods like setTitle(), setDescription(), etc.\n *\n * Use this in your component classes to configure the builder\n * @example this.instance.setTitle('My Modal')\n */\n protected get instance(): TComponent {\n return this._component;\n }\n\n /**\n * Builds a customId string for interactive components with no arguments\n *\n * @param prefix - The route prefix that handlers will match against\n * @returns The prefix as the customId\n */\n public buildCustomId<Prefix extends string>(prefix: Prefix): Prefix;\n /**\n * Builds a customId string for interactive components\n *\n * Creates customIds in the format `prefix:arg1-arg2-arg3` for buttons, modals, etc.\n * Arguments are joined with hyphens and separated from prefix with a colon.\n *\n * @param prefix - The route prefix that handlers will match against\n * @param args - Additional arguments to encode in the customId\n * @returns Formatted customId string\n */\n public buildCustomId<Prefix extends string, Args extends NonEmptyTuple<string>>(\n prefix: Prefix,\n ...args: Args\n ): `${Prefix}:${Join<Args, '-'>}`;\n\n public buildCustomId<Prefix extends string, Args extends NonEmptyTuple<string> | []>(\n prefix: Prefix,\n ...args: Args\n ): Prefix | `${Prefix}:${string}` {\n return args.length === 0 ? prefix : `${prefix}:${args.join('-')}`;\n }\n}\n\n/**\n * Base class for Discord.js builder components\n *\n * Wraps Discord.js builders (SlashCommandBuilder, EmbedBuilder, etc.) with\n * Seedcord-specific defaults and helper methods.\n *\n * @typeParam BuilderKey - The type of Discord.js builder being wrapped\n */\nexport abstract class BuilderComponent<BuilderKey extends BuilderType> extends BaseComponent<\n InstantiatedBuilder<BuilderKey>\n> {\n private colorApplied = false;\n\n protected constructor(public readonly type: BuilderKey) {\n const ComponentClass = BuilderTypes[type] as unknown;\n super(ComponentClass as new () => InstantiatedBuilder<BuilderKey>);\n\n if (this.instance instanceof SlashCommandBuilder || this.instance instanceof ContextMenuCommandBuilder) {\n this.instance.setContexts(InteractionContextType.Guild);\n }\n }\n\n get component(): InstantiatedBuilder<BuilderKey> {\n this.applyBotColor();\n return this.instance;\n }\n\n // Resolving in the constructor would capture the default for a component built before setBotColor()\n // ran. The unset check keeps a color the subclass set for itself.\n private applyBotColor(): void {\n if (this.colorApplied) return;\n this.colorApplied = true;\n\n const color = getBotColor();\n if (this.instance instanceof EmbedBuilder) {\n if (this.instance.data.color === undefined) this.instance.setColor(color);\n } else if (this.instance instanceof ContainerBuilder) {\n const accent = this.instance.data.accent_color;\n if (accent === null || accent === undefined) {\n this.instance.setAccentColor(color === 'Default' ? undefined : resolveColor(color));\n }\n }\n }\n}\n\n/**\n * Base class for Discord action row components\n *\n * Wraps Discord.js action row builder with Seedcord-specific defaults and helper methods.\n *\n * @typeParam RowKey - The Discord.js action row type being wrapped\n */\nexport abstract class RowComponent<RowKey extends ActionRowComponentType> extends BaseComponent<\n InstantiatedActionRow<RowKey>\n> {\n protected constructor(public readonly type: RowKey) {\n const ComponentClass = RowTypes[type] as unknown;\n super(ComponentClass as new () => InstantiatedActionRow<RowKey>);\n }\n\n get component(): InstantiatedActionRow<RowKey> {\n return this.instance;\n }\n}\n\n/**\n * Pre-configured error embed with default styling\n *\n * This is bundled in {@link CustomError}s as the response.\n *\n * @internal\n */\nexport class BaseErrorEmbed extends BuilderComponent<'embed'> {\n /**\n * Creates a new error embed with default configuration.\n */\n public constructor() {\n super('embed');\n this.instance.setTitle('Cannot Proceed');\n }\n}\n\n/**\n * Base class for custom error types with Discord embed responses\n *\n * Errors extending CustomError should be used with the `Catchable` decorators to implement a control flow. These errors will be caught and handled by the framework to show the user the configured response.\n */\nexport abstract class CustomError extends Error {\n private _emit = false;\n public readonly response = new BaseErrorEmbed().component;\n\n protected constructor(public override message: string) {\n super(message);\n\n Error.captureStackTrace(this, this.constructor);\n }\n\n /**\n * Whether this error should be emitted to logs\n *\n * Controls logging behavior. Errors with emit=true will always be logged,\n * while emit=false errors may be suppressed in production.\n *\n * @returns True if the error should be logged\n */\n public get emit(): boolean {\n return this._emit;\n }\n\n /**\n * Sets whether this error should be emitted to logs\n */\n public set emit(value: boolean) {\n this._emit = value;\n }\n}\n","import { CustomError } from '@interfaces/Components';\n\nimport type { UUID } from 'crypto';\n\n/**\n * Generic database operation error with UUID tracking.\n *\n * Thrown for various database operation failures and includes\n * a UUID for error tracking and debugging purposes.\n *\n * @internal\n */\nexport class DatabaseError extends CustomError {\n /**\n * Creates a new DatabaseError.\n *\n * @param message - The error message describing what went wrong\n * @param uuid - A unique identifier for this specific error instance\n */\n constructor(\n message: string,\n public uuid: UUID\n ) {\n super(message);\n this.emit = true; // Emit in logs regardless of environment\n this.name = 'DatabaseError';\n\n this.response\n .setTitle('Database Error')\n .setDescription(`An error occurred while interacting with the database.\\n### UUID: \\`${this.uuid}\\``);\n }\n}\n"],"mappings":"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"}