@ovencord/builders 1.12.8 → 1.13.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.
Files changed (49) hide show
  1. package/package.json +2 -3
  2. package/src/components/ActionRow.ts +14 -13
  3. package/src/components/Assertions.ts +38 -27
  4. package/src/components/Component.ts +3 -3
  5. package/src/components/Components.ts +35 -27
  6. package/src/components/button/Button.ts +1 -1
  7. package/src/components/button/ButtonBuilder.ts +7 -6
  8. package/src/components/button/CustomIdButton.ts +4 -2
  9. package/src/components/button/LinkButton.ts +3 -2
  10. package/src/components/button/mixins/EmojiOrLabelButtonMixin.ts +3 -5
  11. package/src/components/label/Label.ts +4 -1
  12. package/src/components/selectMenu/ChannelSelectMenu.ts +2 -2
  13. package/src/components/selectMenu/MentionableSelectMenu.ts +2 -2
  14. package/src/components/selectMenu/RoleSelectMenu.ts +2 -2
  15. package/src/components/selectMenu/StringSelectMenu.ts +1 -1
  16. package/src/components/selectMenu/UserSelectMenu.ts +2 -2
  17. package/src/components/textInput/TextInput.ts +1 -1
  18. package/src/components/v2/Assertions.ts +11 -6
  19. package/src/components/v2/Container.ts +12 -7
  20. package/src/components/v2/File.ts +1 -1
  21. package/src/components/v2/MediaGallery.ts +1 -1
  22. package/src/components/v2/Section.ts +7 -20
  23. package/src/components/v2/Separator.ts +1 -1
  24. package/src/components/v2/TextDisplay.ts +2 -2
  25. package/src/components/v2/Thumbnail.ts +8 -8
  26. package/src/index.ts +29 -42
  27. package/src/interactions/commands/Command.ts +11 -7
  28. package/src/interactions/commands/SharedName.ts +2 -3
  29. package/src/interactions/commands/SharedNameAndDescription.ts +2 -1
  30. package/src/interactions/commands/chatInput/Assertions.ts +17 -5
  31. package/src/interactions/commands/chatInput/ChatInputCommandSubcommands.ts +5 -4
  32. package/src/interactions/commands/chatInput/mixins/ApplicationCommandNumericOptionMinMaxValueMixin.ts +3 -5
  33. package/src/interactions/commands/chatInput/mixins/ApplicationCommandOptionChannelTypesMixin.ts +4 -6
  34. package/src/interactions/commands/chatInput/mixins/ApplicationCommandOptionWithAutocompleteMixin.ts +1 -1
  35. package/src/interactions/commands/chatInput/mixins/ApplicationCommandOptionWithChoicesMixin.ts +1 -1
  36. package/src/interactions/commands/chatInput/mixins/SharedChatInputCommandOptions.ts +34 -11
  37. package/src/interactions/commands/chatInput/mixins/SharedSubcommands.ts +2 -2
  38. package/src/interactions/commands/chatInput/options/ApplicationCommandOptionBase.ts +1 -1
  39. package/src/interactions/commands/chatInput/options/string.ts +3 -3
  40. package/src/interactions/modals/Modal.ts +3 -9
  41. package/src/messages/Assertions.ts +6 -3
  42. package/src/messages/Attachment.ts +1 -1
  43. package/src/messages/Message.ts +30 -21
  44. package/src/messages/embed/Assertions.ts +16 -3
  45. package/src/messages/embed/Embed.ts +4 -2
  46. package/src/messages/poll/Poll.ts +1 -1
  47. package/src/util/componentUtil.ts +4 -4
  48. package/src/util/resolveBuilder.ts +5 -2
  49. package/src/util/validation.ts +4 -2
@@ -110,14 +110,10 @@ export class ModalBuilder implements JSONEncodable<APIModalInteractionResponseCa
110
110
  * @param components - The action rows to add
111
111
  */
112
112
  public addActionRowComponents(
113
- ...components: RestOrArray<
114
- ActionRowBuilder | APIActionRowComponent<APIComponentInActionRow>
115
- >
113
+ ...components: RestOrArray<ActionRowBuilder | APIActionRowComponent<APIComponentInActionRow>>
116
114
  ) {
117
115
  const normalized = normalizeArray(components);
118
- const resolved = normalized.map((row) =>
119
- row instanceof ActionRowBuilder ? row : new ActionRowBuilder(row),
120
- );
116
+ const resolved = normalized.map((row) => (row instanceof ActionRowBuilder ? row : new ActionRowBuilder(row)));
121
117
 
122
118
  this.data.components.push(...resolved);
123
119
 
@@ -130,9 +126,7 @@ export class ModalBuilder implements JSONEncodable<APIModalInteractionResponseCa
130
126
  *
131
127
  * @param components - The components to add
132
128
  */
133
- public addComponents(
134
- ...components: RestOrArray<ActionRowBuilder | AnyModalComponentBuilder>
135
- ) {
129
+ public addComponents(...components: RestOrArray<ActionRowBuilder | AnyModalComponentBuilder>) {
136
130
  const normalized = normalizeArray(components);
137
131
  this.data.components.push(...normalized);
138
132
 
@@ -126,9 +126,12 @@ const allTopLevelComponentsPredicate = z
126
126
 
127
127
  const messageComponentsV2Predicate = baseMessagePredicate.extend({
128
128
  components: allTopLevelComponentsPredicate,
129
- flags: z.number().int().refine((flags) => (flags & MessageFlags.IsComponentsV2) === MessageFlags.IsComponentsV2, {
130
- message: 'Must set IsComponentsV2 flag to use Components V2',
131
- }),
129
+ flags: z
130
+ .number()
131
+ .int()
132
+ .refine((flags) => (flags & MessageFlags.IsComponentsV2) === MessageFlags.IsComponentsV2, {
133
+ message: 'Must set IsComponentsV2 flag to use Components V2',
134
+ }),
132
135
  // These fields cannot be set
133
136
  content: z.string().length(0).nullish(),
134
137
  embeds: z.array(z.never()).nullish(),
@@ -109,7 +109,7 @@ export class AttachmentBuilder implements JSONEncodable<RESTAPIAttachment> {
109
109
  * @remarks Note that this data is NOT included in the {@link toJSON} output. To retrieve it, use {@link getRawFile}.
110
110
  */
111
111
  public setFileData(data: Uint8Array | string): this {
112
- this.fileData.data = data as any;
112
+ this.fileData.data = data as unknown as RawFile['data'];
113
113
  return this;
114
114
  }
115
115
 
@@ -3,21 +3,21 @@ import type {
3
3
  APIActionRowComponent,
4
4
  APIAllowedMentions,
5
5
  APIAttachment,
6
- APIEmbed,
6
+ APIComponentInActionRow,
7
7
  APIComponentInMessageActionRow,
8
- APIMessageReference,
9
- APIPoll,
10
- RESTPostAPIChannelMessageJSONBody,
11
- Snowflake,
12
- MessageFlags,
13
8
  APIContainerComponent,
9
+ APIEmbed,
14
10
  APIFileComponent,
15
11
  APIMediaGalleryComponent,
12
+ APIMessageReference,
13
+ APIMessageTopLevelComponent,
14
+ APIPoll,
16
15
  APISectionComponent,
17
16
  APISeparatorComponent,
18
17
  APITextDisplayComponent,
19
- APIMessageTopLevelComponent,
20
- APIComponentInActionRow,
18
+ MessageFlags,
19
+ RESTPostAPIChannelMessageJSONBody,
20
+ Snowflake,
21
21
  } from 'discord-api-types/v10';
22
22
  import { ActionRowBuilder } from '../components/ActionRow.js';
23
23
  import { ComponentBuilder } from '../components/Component.js';
@@ -35,16 +35,17 @@ import { validate } from '../util/validation.js';
35
35
  import { AllowedMentionsBuilder } from './AllowedMentions.js';
36
36
  import { fileBodyMessagePredicate, messagePredicate } from './Assertions.js';
37
37
  import { AttachmentBuilder } from './Attachment.js';
38
- import { MessageReferenceBuilder } from './MessageReference.js';
39
38
  import { EmbedBuilder } from './embed/Embed.js';
39
+ import { MessageReferenceBuilder } from './MessageReference.js';
40
40
  import { PollBuilder } from './poll/Poll.js';
41
41
 
42
- export interface MessageBuilderData extends Partial<
43
- Omit<
44
- RESTPostAPIChannelMessageJSONBody,
45
- 'allowed_mentions' | 'attachments' | 'components' | 'embeds' | 'message_reference' | 'poll'
46
- >
47
- > {
42
+ export interface MessageBuilderData
43
+ extends Partial<
44
+ Omit<
45
+ RESTPostAPIChannelMessageJSONBody,
46
+ 'allowed_mentions' | 'attachments' | 'components' | 'embeds' | 'message_reference' | 'poll'
47
+ >
48
+ > {
48
49
  allowed_mentions?: AllowedMentionsBuilder;
49
50
  attachments: AttachmentBuilder[];
50
51
  components: MessageTopLevelComponentBuilder[];
@@ -252,7 +253,8 @@ export class MessageBuilder
252
253
  * @param updater - The function to update the allowed mentions with
253
254
  */
254
255
  public updateAllowedMentions(updater: (builder: AllowedMentionsBuilder) => void): this {
255
- updater((this.data.allowed_mentions ??= new AllowedMentionsBuilder()));
256
+ this.data.allowed_mentions ??= new AllowedMentionsBuilder();
257
+ updater(this.data.allowed_mentions);
256
258
  return this;
257
259
  }
258
260
 
@@ -285,7 +287,8 @@ export class MessageBuilder
285
287
  * @param updater - The function to update the message reference with
286
288
  */
287
289
  public updateMessageReference(updater: (builder: MessageReferenceBuilder) => void): this {
288
- updater((this.data.message_reference ??= new MessageReferenceBuilder()));
290
+ this.data.message_reference ??= new MessageReferenceBuilder();
291
+ updater(this.data.message_reference);
289
292
  return this;
290
293
  }
291
294
 
@@ -311,7 +314,12 @@ export class MessageBuilder
311
314
  ): this {
312
315
  this.data.components ??= [];
313
316
 
314
- const resolved = normalizeArray(components).map((component) => resolveBuilder<ActionRowBuilder, Partial<APIActionRowComponent<APIComponentInActionRow>>>(component, ActionRowBuilder));
317
+ const resolved = normalizeArray(components).map((component) =>
318
+ resolveBuilder<ActionRowBuilder, Partial<APIActionRowComponent<APIComponentInActionRow>>>(
319
+ component,
320
+ ActionRowBuilder,
321
+ ),
322
+ );
315
323
  this.data.components.push(...resolved);
316
324
 
317
325
  return this;
@@ -479,7 +487,7 @@ export class MessageBuilder
479
487
  */
480
488
  public addStickerIds(...stickerIds: RestOrArray<Snowflake>): this {
481
489
  this.data.sticker_ids ??= [] as unknown as MessageBuilderData['sticker_ids'];
482
- this.data.sticker_ids!.push(...normalizeArray(stickerIds));
490
+ this.data.sticker_ids?.push(...normalizeArray(stickerIds));
483
491
  return this;
484
492
  }
485
493
 
@@ -513,7 +521,7 @@ export class MessageBuilder
513
521
  */
514
522
  public spliceStickerIds(index: number, deleteCount: number, ...stickerIds: RestOrArray<Snowflake>): this {
515
523
  this.data.sticker_ids ??= [] as unknown as MessageBuilderData['sticker_ids'];
516
- this.data.sticker_ids!.splice(index, deleteCount, ...normalizeArray(stickerIds));
524
+ this.data.sticker_ids?.splice(index, deleteCount, ...normalizeArray(stickerIds));
517
525
  return this;
518
526
  }
519
527
 
@@ -625,7 +633,8 @@ export class MessageBuilder
625
633
  * @param updater - The function to update the poll with
626
634
  */
627
635
  public updatePoll(updater: (builder: PollBuilder) => void): this {
628
- updater((this.data.poll ??= new PollBuilder()));
636
+ this.data.poll ??= new PollBuilder();
637
+ updater(this.data.poll);
629
638
  return this;
630
639
  }
631
640
 
@@ -1,11 +1,22 @@
1
1
  import { embedLength } from '@ovencord/util';
2
+ import type { APIEmbed } from 'discord-api-types/v10';
2
3
  import { z } from 'zod';
3
4
 
4
5
  const namePredicate = z.string().max(256);
5
6
 
6
- const URLPredicate = z.string().url().refine((url) => url.startsWith('http:') || url.startsWith('https:'), { message: 'URL must use http or https protocol' });
7
+ const URLPredicate = z
8
+ .string()
9
+ .url()
10
+ .refine((url) => url.startsWith('http:') || url.startsWith('https:'), {
11
+ message: 'URL must use http or https protocol',
12
+ });
7
13
 
8
- const URLWithAttachmentProtocolPredicate = z.string().url().refine((url) => url.startsWith('http:') || url.startsWith('https:') || url.startsWith('attachment:'), { message: 'URL must use http, https, or attachment protocol' });
14
+ const URLWithAttachmentProtocolPredicate = z
15
+ .string()
16
+ .url()
17
+ .refine((url) => url.startsWith('http:') || url.startsWith('https:') || url.startsWith('attachment:'), {
18
+ message: 'URL must use http, https, or attachment protocol',
19
+ });
9
20
 
10
21
  export const embedFieldPredicate = z.object({
11
22
  name: namePredicate,
@@ -50,4 +61,6 @@ export const embedPredicate = z
50
61
  message: 'Embed must have at least a title, description, a field, a footer, an author, an image, OR a thumbnail.',
51
62
  },
52
63
  )
53
- .refine((embed) => embedLength(embed as any) <= 6_000, { message: 'Embeds must not exceed 6000 characters in total.' });
64
+ .refine((embed) => embedLength(embed as unknown as APIEmbed) <= 6_000, {
65
+ message: 'Embeds must not exceed 6000 characters in total.',
66
+ });
@@ -159,7 +159,8 @@ export class EmbedBuilder implements JSONEncodable<APIEmbed> {
159
159
  * @param updater - The function to update the author with
160
160
  */
161
161
  public updateAuthor(updater: (builder: EmbedAuthorBuilder) => void) {
162
- updater((this.data.author ??= new EmbedAuthorBuilder()));
162
+ this.data.author ??= new EmbedAuthorBuilder();
163
+ updater(this.data.author);
163
164
  return this;
164
165
  }
165
166
 
@@ -225,7 +226,8 @@ export class EmbedBuilder implements JSONEncodable<APIEmbed> {
225
226
  * @param updater - The function to update the footer with
226
227
  */
227
228
  public updateFooter(updater: (builder: EmbedFooterBuilder) => void) {
228
- updater((this.data.footer ??= new EmbedFooterBuilder()));
229
+ this.data.footer ??= new EmbedFooterBuilder();
230
+ updater(this.data.footer);
229
231
  return this;
230
232
  }
231
233
 
@@ -1,5 +1,5 @@
1
1
  import type { JSONEncodable } from '@ovencord/util';
2
- import type { RESTAPIPoll, APIPollMedia, PollLayoutType, APIPollAnswer } from 'discord-api-types/v10';
2
+ import type { APIPollAnswer, APIPollMedia, PollLayoutType, RESTAPIPoll } from 'discord-api-types/v10';
3
3
  import { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';
4
4
  import { resolveBuilder } from '../../util/resolveBuilder.js';
5
5
  import { validate } from '../../util/validation.js';
@@ -15,10 +15,10 @@ export function parseEmoji(text: string): APIMessageComponentEmoji {
15
15
  if (/^\d{17,21}$/.test(decodedText)) return { id: decodedText, name: undefined, animated: false };
16
16
  if (!decodedText.includes(':')) return { animated: false, name: decodedText.replace(/\uFE0F/g, ''), id: undefined };
17
17
  const match = /<?(?:(?<animated>a):)?(?<name>\w{2,32}):(?<id>\d{17,19})?>?/.exec(decodedText);
18
-
19
- if (!match || !match.groups) {
20
- return { animated: false, name: decodedText, id: undefined };
21
- }
18
+
19
+ if (!match || !match.groups) {
20
+ return { animated: false, name: decodedText, id: undefined };
21
+ }
22
22
 
23
23
  return {
24
24
  animated: Boolean(match.groups.animated),
@@ -6,7 +6,7 @@ import type { JSONEncodable } from '@ovencord/util';
6
6
  * function, TS doesn't narrow out the type `Builder`, causing a type error on the last return statement.
7
7
  * @internal
8
8
  */
9
- function isBuilder<Builder extends JSONEncodable<any>>(
9
+ function isBuilder<Builder extends JSONEncodable<unknown>>(
10
10
  builder: unknown,
11
11
  Constructor: new () => Builder,
12
12
  ): builder is Builder {
@@ -24,7 +24,10 @@ function isBuilder<Builder extends JSONEncodable<any>>(
24
24
  * @param builder - The user input, as described in the function description
25
25
  * @param Constructor - The constructor of the builder
26
26
  */
27
- export function resolveBuilder<Builder extends JSONEncodable<any>, BuilderData extends Record<PropertyKey, any>>(
27
+ export function resolveBuilder<
28
+ Builder extends JSONEncodable<unknown>,
29
+ BuilderData extends Record<PropertyKey, unknown>,
30
+ >(
28
31
  builder: Builder | BuilderData | ((builder: Builder) => Builder),
29
32
  Constructor: new (data?: BuilderData) => Builder,
30
33
  ): Builder {
@@ -9,7 +9,8 @@ let validationEnabled = true;
9
9
  * @returns Whether validation is occurring.
10
10
  */
11
11
  export function enableValidators() {
12
- return (validationEnabled = true);
12
+ validationEnabled = true;
13
+ return validationEnabled;
13
14
  }
14
15
 
15
16
  /**
@@ -18,7 +19,8 @@ export function enableValidators() {
18
19
  * @returns Whether validation is occurring.
19
20
  */
20
21
  export function disableValidators() {
21
- return (validationEnabled = false);
22
+ validationEnabled = false;
23
+ return validationEnabled;
22
24
  }
23
25
 
24
26
  /**