lunibee 0.2.2 → 0.2.4

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 (70) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +225 -225
  3. package/dist/builders/attachment.d.ts +10 -2
  4. package/dist/builders/commands.d.ts +161 -101
  5. package/dist/builders/components.d.ts +54 -75
  6. package/dist/builders/embed.d.ts +68 -35
  7. package/dist/builders/index.d.ts +1 -1
  8. package/dist/builders/index.js +108 -133
  9. package/dist/builders/index.js.map +8 -8
  10. package/dist/collection/cache.d.ts +13 -6
  11. package/dist/collection/index.d.ts +90 -17
  12. package/dist/collection/index.js +442 -266
  13. package/dist/collection/index.js.map +4 -4
  14. package/dist/core/index.d.ts +9 -0
  15. package/dist/core/index.js +791 -436
  16. package/dist/core/index.js.map +47 -47
  17. package/dist/core/permissions.d.ts +9 -5
  18. package/dist/formatters/index.js +9 -5
  19. package/dist/formatters/index.js.map +3 -3
  20. package/dist/handlers/index.js +5 -10
  21. package/dist/handlers/index.js.map +3 -3
  22. package/dist/index.js +1010 -679
  23. package/dist/index.js.map +66 -65
  24. package/dist/managers/base.d.ts +26 -14
  25. package/dist/managers/emoji.d.ts +7 -1
  26. package/dist/managers/guild-resources.d.ts +11 -3
  27. package/dist/managers/guild.d.ts +13 -5
  28. package/dist/managers/index.d.ts +28 -14
  29. package/dist/managers/index.js +580 -340
  30. package/dist/managers/index.js.map +26 -26
  31. package/dist/managers/member.d.ts +5 -3
  32. package/dist/managers/message.d.ts +7 -3
  33. package/dist/managers/role.d.ts +13 -1
  34. package/dist/rest/error-codes.d.ts +48 -0
  35. package/dist/rest/errors.d.ts +14 -6
  36. package/dist/rest/index.d.ts +25 -12
  37. package/dist/rest/index.js +105 -18
  38. package/dist/rest/index.js.map +15 -14
  39. package/dist/rest/redis.d.ts +1 -1
  40. package/dist/rest/route.d.ts +8 -4
  41. package/dist/rest/routes.d.ts +102 -46
  42. package/dist/rest/transport.d.ts +10 -5
  43. package/dist/rest/webhook.d.ts +9 -5
  44. package/dist/sharding/bus.d.ts +34 -17
  45. package/dist/sharding/index.d.ts +34 -17
  46. package/dist/sharding/index.js +68 -36
  47. package/dist/sharding/index.js.map +17 -17
  48. package/dist/structures/base.d.ts +28 -10
  49. package/dist/structures/channels.d.ts +28 -14
  50. package/dist/structures/index.d.ts +6 -6
  51. package/dist/structures/index.js +81 -99
  52. package/dist/structures/index.js.map +19 -18
  53. package/dist/structures/interactions.d.ts +98 -50
  54. package/dist/structures/resources.d.ts +90 -46
  55. package/dist/types/gateway.d.ts +1 -1
  56. package/dist/types/index.d.ts +43 -18
  57. package/dist/types/index.js +20 -22
  58. package/dist/types/index.js.map +4 -4
  59. package/dist/utils/index.js.map +2 -2
  60. package/dist/voice/index.d.ts +12 -4
  61. package/dist/voice/index.js +17 -20
  62. package/dist/voice/index.js.map +3 -3
  63. package/dist/ws/decoder.d.ts +6 -2
  64. package/dist/ws/index.d.ts +25 -13
  65. package/dist/ws/index.js +63 -31
  66. package/dist/ws/index.js.map +14 -14
  67. package/dist/ws/protocol.d.ts +10 -2
  68. package/dist/ws/session.d.ts +14 -4
  69. package/dist/ws/state.d.ts +22 -11
  70. package/package.json +16 -15
@@ -1,65 +1,98 @@
1
1
  /** Discord API embed field payload. */
2
2
  export interface EmbedField {
3
- /** Field name. */ name: string;
4
- /** Field value. */ value: string;
5
- /** Whether the field is displayed inline. */ inline?: boolean;
3
+ /** Field name. */
4
+ name: string;
5
+ /** Field value. */
6
+ value: string;
7
+ /** Whether the field is displayed inline. */
8
+ inline?: boolean;
6
9
  }
7
10
  /** Discord API embed footer payload. */
8
11
  export interface EmbedFooter {
9
- /** Footer text. */ text: string;
10
- /** Footer icon URL. */ icon_url?: string;
12
+ /** Footer text. */
13
+ text: string;
14
+ /** Footer icon URL. */
15
+ icon_url?: string;
11
16
  }
12
17
  /** Discord API embed author payload. */
13
18
  export interface EmbedAuthor {
14
- /** Author display name. */ name: string;
15
- /** Author URL. */ url?: string;
16
- /** Author icon URL. */ icon_url?: string;
19
+ /** Author display name. */
20
+ name: string;
21
+ /** Author URL. */
22
+ url?: string;
23
+ /** Author icon URL. */
24
+ icon_url?: string;
17
25
  }
18
26
  /** Strict Discord API embed payload. */
19
27
  export interface APIEmbed {
20
- /** Embed title. */ title?: string;
21
- /** Embed description. */ description?: string;
22
- /** Embed URL. */ url?: string;
23
- /** Embed color. */ color?: number;
24
- /** ISO-8601 timestamp. */ timestamp?: string;
25
- /** Embed footer. */ footer?: EmbedFooter;
26
- /** Embed author. */ author?: EmbedAuthor;
27
- /** Thumbnail payload. */ thumbnail?: {
28
+ /** Embed title. */
29
+ title?: string;
30
+ /** Embed description. */
31
+ description?: string;
32
+ /** Embed URL. */
33
+ url?: string;
34
+ /** Embed color. */
35
+ color?: number;
36
+ /** ISO-8601 timestamp. */
37
+ timestamp?: string;
38
+ /** Embed footer. */
39
+ footer?: EmbedFooter;
40
+ /** Embed author. */
41
+ author?: EmbedAuthor;
42
+ /** Thumbnail payload. */
43
+ thumbnail?: {
28
44
  url: string;
29
45
  };
30
- /** Image payload. */ image?: {
46
+ /** Image payload. */
47
+ image?: {
31
48
  url: string;
32
49
  };
33
- /** Embed fields. */ fields?: EmbedField[];
50
+ /** Embed fields. */
51
+ fields?: EmbedField[];
34
52
  }
35
53
  /** Builds compile-time-safe rich embed payloads for Discord API requests. */
36
54
  export declare class CreateEmbed {
37
55
  #private;
38
- /** Sets the embed title. @param value Title text, or null to clear. @returns This builder. @throws {RangeError} If title exceeds Discord's limit. */ setTitle(value: string | null): this;
39
- /** Sets the embed description. @param value Description text, or null to clear. @returns This builder. @throws {RangeError} If description exceeds Discord's limit. */ setDescription(value: string | null): this;
40
- /** Sets the embed URL. @param value Absolute URL, or null to clear. @returns This builder. @throws {TypeError} If URL is invalid. */ setURL(value: string | null): this;
41
- /** Sets the embed color. @param value RGB integer. @returns This builder. @throws {RangeError} If color is outside 24-bit RGB range. */ setColor(value: number): this;
42
- /** Sets the embed timestamp. @param value Date value. @returns This builder. @throws {RangeError} If date is invalid. */ setTimestamp(value?: Date): this;
43
- /** Sets the embed footer. @param value Footer payload. @returns This builder. @throws {RangeError} If footer text exceeds Discord's limit. */ setFooter(value: EmbedFooter): this;
44
- /** Sets the embed author. @param value Author payload. @returns This builder. @throws {RangeError} If author name exceeds Discord's limit. */ setAuthor(value: EmbedAuthor): this;
45
- /** Sets the thumbnail URL. @param value Thumbnail URL or payload, or null to clear. @returns This builder. @throws {TypeError} If URL is invalid. */ setThumbnail(value: {
56
+ /** Sets the embed title. @param value Title text, or null to clear. @returns This builder. @throws {RangeError} If title exceeds Discord's limit. */
57
+ setTitle(value: string | null): this;
58
+ /** Sets the embed description. @param value Description text, or null to clear. @returns This builder. @throws {RangeError} If description exceeds Discord's limit. */
59
+ setDescription(value: string | null): this;
60
+ /** Sets the embed URL. @param value Absolute URL, or null to clear. @returns This builder. @throws {TypeError} If URL is invalid. */
61
+ setURL(value: string | null): this;
62
+ /** Sets the embed color. @param value RGB integer. @returns This builder. @throws {RangeError} If color is outside 24-bit RGB range. */
63
+ setColor(value: number): this;
64
+ /** Sets the embed timestamp. @param value Date value. @returns This builder. @throws {RangeError} If date is invalid. */
65
+ setTimestamp(value?: Date): this;
66
+ /** Sets the embed footer. @param value Footer payload. @returns This builder. @throws {RangeError} If footer text exceeds Discord's limit. */
67
+ setFooter(value: EmbedFooter): this;
68
+ /** Sets the embed author. @param value Author payload. @returns This builder. @throws {RangeError} If author name exceeds Discord's limit. */
69
+ setAuthor(value: EmbedAuthor): this;
70
+ /** Sets the thumbnail URL. @param value Thumbnail URL or payload, or null to clear. @returns This builder. @throws {TypeError} If URL is invalid. */
71
+ setThumbnail(value: {
46
72
  url: string;
47
73
  } | string | null): this;
48
- /** Sets the image URL. @param value Image URL or payload, or null to clear. @returns This builder. @throws {TypeError} If URL is invalid. */ setImage(value: {
74
+ /** Sets the image URL. @param value Image URL or payload, or null to clear. @returns This builder. @throws {TypeError} If URL is invalid. */
75
+ setImage(value: {
49
76
  url: string;
50
77
  } | string | null): this;
51
78
  /** Adds embed fields. Accepts both the spread form `addFields(a, b)` and the
52
79
  * single-array form `addFields([a, b])` for discord.js `RestOrArray` parity.
53
- * @param fields Field payloads, spread or as a single array. @returns This builder. @throws {RangeError} If the 25-field limit is exceeded. */ addFields(...fields: EmbedField[] | [EmbedField[]]): this;
80
+ * @param fields Field payloads, spread or as a single array. @returns This builder. @throws {RangeError} If the 25-field limit is exceeded. */
81
+ addFields(...fields: EmbedField[] | [EmbedField[]]): this;
54
82
  setFields(fields: EmbedField[]): this;
55
- /** Replaces fields starting at an index. @param index Start index. @param deleteCount Number of fields to remove. @param fields Replacement fields. @returns This builder. @throws {RangeError} If arguments are invalid or the 25-field limit is exceeded. */ spliceFields(index: number, deleteCount: number, ...fields: EmbedField[]): this;
56
- /** Removes all embed fields. @returns This builder. */ clearFields(): this;
57
- /** Removes the embed title. @returns This builder. */ clearTitle(): this;
58
- /** Removes the embed description. @returns This builder. */ clearDescription(): this;
59
- /** Returns a deep-cloned Discord API payload. @returns Strict embed payload. */ get data(): APIEmbed;
83
+ /** Replaces fields starting at an index. @param index Start index. @param deleteCount Number of fields to remove. @param fields Replacement fields. @returns This builder. @throws {RangeError} If arguments are invalid or the 25-field limit is exceeded. */
84
+ spliceFields(index: number, deleteCount: number, ...fields: EmbedField[]): this;
85
+ /** Removes all embed fields. @returns This builder. */
86
+ clearFields(): this;
87
+ /** Removes the embed title. @returns This builder. */
88
+ clearTitle(): this;
89
+ /** Removes the embed description. @returns This builder. */
90
+ clearDescription(): this;
91
+ /** Returns a deep-cloned Discord API payload. @returns Strict embed payload. */
92
+ get data(): APIEmbed;
60
93
  toJSON(): APIEmbed;
61
94
  }
62
- /** @deprecated Use {@link CreateEmbed}. Removed in 2.0. */
95
+ /** @deprecated Use {@link CreateEmbed}. Removed in 0.3.0. */
63
96
  export declare const EmbedBuilder: typeof CreateEmbed;
64
- /** @deprecated Use {@link CreateEmbed}. Removed in 2.0. */
97
+ /** @deprecated Use {@link CreateEmbed}. Removed in 0.3.0. */
65
98
  export type EmbedBuilder = CreateEmbed;
@@ -1,7 +1,7 @@
1
1
  export { CreateEmbed } from "./embed.js";
2
2
  export type { EmbedField } from "./embed.js";
3
3
  export { CreateButton, ButtonType, ComponentEnum, CreateActionRow, CreateStringSelect, CreateStringSelectMenu, CreateEntitySelect, CreateUserSelectMenu, CreateRoleSelectMenu, CreateMentionableSelectMenu, CreateChannelSelectMenu, CreateModal, CreateTextInput, TextInputType, CreateContainer, CreateSection, CreateTextDisplay, CreateMediaGallery, CreateFileComponent, CreateSeparator, CreateThumbnail, CreateContentInventoryEntry, componentsV2Message, } from "./components.js";
4
- export { CreateSlashCommand, CreateStringOption, CreateIntegerOption, CreateNumberOption, CreateBooleanOption, CreateUserOption, CreateChannelOption, CreateRoleOption, CreateMentionableOption, CreateAttachmentOption, CreateSubcommand, CreateSubcommandGroup, ApplicationCommandOptionEnum, CreateUserCommand, CreateMessageCommand, CreateContextMenuCommand, } from "./commands.js";
4
+ export { CreateSlashCommand, CreateCommandOption, CreateStringOption, CreateIntegerOption, CreateNumberOption, CreateBooleanOption, CreateUserOption, CreateChannelOption, CreateRoleOption, CreateMentionableOption, CreateAttachmentOption, CreateSubcommand, CreateSubcommandGroup, ApplicationCommandOptionEnum, CreateUserCommand, CreateMessageCommand, CreateContextMenuCommand, } from "./commands.js";
5
5
  export { CreateAttachment, type AttachmentData } from "./attachment.js";
6
6
  export { AttachmentBuilder } from "./attachment.js";
7
7
  export { EmbedBuilder } from "./embed.js";
@@ -185,16 +185,6 @@ var IntentBits = {
185
185
  directMessagePolls: 1 << 25
186
186
  };
187
187
  // packages/types/src/index.ts
188
- var ButtonType = {
189
- Primary: 1,
190
- Secondary: 2,
191
- Success: 3,
192
- Danger: 4,
193
- Link: 5,
194
- Premium: 6
195
- };
196
-
197
- // packages/builders/src/components.ts
198
188
  var ComponentEnum = {
199
189
  ActionRow: 1,
200
190
  Button: 2,
@@ -213,6 +203,16 @@ var ComponentEnum = {
213
203
  ContentInventoryEntry: 16,
214
204
  Container: 17
215
205
  };
206
+ var ButtonType = {
207
+ Primary: 1,
208
+ Secondary: 2,
209
+ Success: 3,
210
+ Danger: 4,
211
+ Link: 5,
212
+ Premium: 6
213
+ };
214
+
215
+ // packages/builders/src/components.ts
216
216
  var TextInputType = { Short: 1, Paragraph: 2 };
217
217
 
218
218
  class CreateActionRow {
@@ -240,38 +240,50 @@ class CreateActionRow {
240
240
  }
241
241
  }
242
242
 
243
- class CreateStringSelect {
244
- #data = {
245
- type: ComponentEnum.StringSelect
246
- };
243
+ class CreateSelectMenu {
244
+ #select;
245
+ constructor(data) {
246
+ this.#select = data;
247
+ }
247
248
  setCustomId(value) {
248
249
  validateText(value, 100, "Component custom ID");
249
- this.#data.custom_id = value;
250
+ this.#select.custom_id = value;
250
251
  return this;
251
252
  }
252
253
  setPlaceholder(value) {
253
254
  validateText(value, 150, "Component placeholder");
254
- this.#data.placeholder = value;
255
+ this.#select.placeholder = value;
255
256
  return this;
256
257
  }
257
258
  setMinValues(value) {
258
259
  validateCount(value, "min_values", 0);
259
- this.#data.min_values = value;
260
+ this.#select.min_values = value;
260
261
  return this;
261
262
  }
262
263
  setMaxValues(value) {
263
264
  validateCount(value, "max_values", 1);
264
- this.#data.max_values = value;
265
+ this.#select.max_values = value;
265
266
  return this;
266
267
  }
267
268
  setRequired(value = true) {
268
- this.#data.required = value;
269
+ this.#select.required = value;
269
270
  return this;
270
271
  }
271
272
  setDisabled(value = true) {
272
- this.#data.disabled = value;
273
+ this.#select.disabled = value;
273
274
  return this;
274
275
  }
276
+ }
277
+
278
+ class CreateStringSelect extends CreateSelectMenu {
279
+ #data;
280
+ constructor() {
281
+ const data = {
282
+ type: ComponentEnum.StringSelect
283
+ };
284
+ super(data);
285
+ this.#data = data;
286
+ }
275
287
  addOptions(...options) {
276
288
  if (!options.length)
277
289
  throw new TypeError("At least one select option is required.");
@@ -387,40 +399,14 @@ class CreateButton {
387
399
  }
388
400
  }
389
401
 
390
- class CreateEntitySelect {
402
+ class CreateEntitySelect extends CreateSelectMenu {
391
403
  #data;
392
404
  constructor(type) {
393
405
  if (type !== ComponentEnum.UserSelect && type !== ComponentEnum.RoleSelect && type !== ComponentEnum.MentionableSelect && type !== ComponentEnum.ChannelSelect)
394
406
  throw new TypeError("Invalid select component type.");
395
- this.#data = { type };
396
- }
397
- setCustomId(value) {
398
- validateText(value, 100, "Component custom ID");
399
- this.#data.custom_id = value;
400
- return this;
401
- }
402
- setPlaceholder(value) {
403
- validateText(value, 150, "Component placeholder");
404
- this.#data.placeholder = value;
405
- return this;
406
- }
407
- setMinValues(value) {
408
- validateCount(value, "min_values", 0);
409
- this.#data.min_values = value;
410
- return this;
411
- }
412
- setMaxValues(value) {
413
- validateCount(value, "max_values", 1);
414
- this.#data.max_values = value;
415
- return this;
416
- }
417
- setRequired(value = true) {
418
- this.#data.required = value;
419
- return this;
420
- }
421
- setDisabled(value = true) {
422
- this.#data.disabled = value;
423
- return this;
407
+ const data = { type };
408
+ super(data);
409
+ this.#data = data;
424
410
  }
425
411
  setDefaultValues(...values) {
426
412
  this.#data.default_values = values.map((value) => ({ ...value }));
@@ -800,6 +786,10 @@ var ApplicationCommandOptionEnum = {
800
786
  Number: 10,
801
787
  Attachment: 11
802
788
  };
789
+ function validateContexts(contexts) {
790
+ if (contexts.some((context) => context !== 0 && context !== 1 && context !== 2))
791
+ throw new RangeError("Command contexts must be 0, 1 or 2.");
792
+ }
803
793
 
804
794
  class CreateSlashCommand {
805
795
  #data = { type: 1 };
@@ -813,6 +803,11 @@ class CreateSlashCommand {
813
803
  this.#data.description = description;
814
804
  return this;
815
805
  }
806
+ setContexts(...contexts) {
807
+ validateContexts(contexts);
808
+ this.#data.contexts = [...contexts];
809
+ return this;
810
+ }
816
811
  setDMPermission(enabled) {
817
812
  this.#data.dm_permission = enabled;
818
813
  return this;
@@ -869,16 +864,7 @@ class CreateSlashCommand {
869
864
  return structuredClone(this.#data);
870
865
  }
871
866
  addOption(option) {
872
- const options = this.#data.options ?? [];
873
- if (options.length >= 25)
874
- throw new RangeError("An application command cannot contain more than 25 options.");
875
- const payload = option.toJSON();
876
- if (options.some((existing) => existing.name === payload.name))
877
- throw new RangeError(`Duplicate option name: ${String(payload.name)}.`);
878
- if (payload.required === true && options.some((existing) => existing.required !== true))
879
- throw new RangeError("Required application command options must be placed before optional options.");
880
- options.push(payload);
881
- this.#data.options = options;
867
+ this.#data.options = appendOption(this.#data.options, option.toJSON(), "application command");
882
868
  return this;
883
869
  }
884
870
  }
@@ -916,21 +902,9 @@ class CreateStringOption extends CreateCommandOption {
916
902
  super(ApplicationCommandOptionEnum.String);
917
903
  }
918
904
  addChoices(...choices) {
919
- const current = this.data.choices ?? [];
920
- if (!choices.length)
921
- throw new TypeError("At least one choice is required.");
922
- if (this.data.autocomplete === true)
923
- throw new RangeError("Autocomplete options cannot define choices.");
924
- if (current.length + choices.length > 25)
925
- throw new RangeError("An option cannot contain more than 25 choices.");
926
- for (const choice of choices) {
927
- validateText2(choice.name, "Choice name", 100);
905
+ for (const choice of choices)
928
906
  validateText2(choice.value, "Choice value", 100);
929
- }
930
- this.data.choices = [
931
- ...current,
932
- ...choices.map((choice) => ({ ...choice }))
933
- ];
907
+ appendChoices(this.data, choices);
934
908
  return this;
935
909
  }
936
910
  setMinLength(value) {
@@ -947,18 +921,21 @@ class CreateStringOption extends CreateCommandOption {
947
921
  }
948
922
  }
949
923
 
950
- class CreateIntegerOption extends CreateCommandOption {
951
- constructor() {
952
- super(ApplicationCommandOptionEnum.Integer);
924
+ class CreateNumericOption extends CreateCommandOption {
925
+ #integer;
926
+ constructor(type, integer) {
927
+ super(type);
928
+ this.#integer = integer;
953
929
  }
954
930
  setMinValue(value) {
955
- validateNumberRange(value, -9007199254740991, 9007199254740991, "min_value", true);
931
+ validateNumberRange(value, -MAX_SAFE, MAX_SAFE, "min_value", this.#integer);
956
932
  this.data.min_value = value;
957
933
  return this;
958
934
  }
959
935
  setMaxValue(value) {
960
- validateNumberRange(value, -9007199254740991, 9007199254740991, "max_value", true);
961
- if (this.data.min_value !== undefined && this.data.min_value > value)
936
+ validateNumberRange(value, -MAX_SAFE, MAX_SAFE, "max_value", this.#integer);
937
+ const min = this.data.min_value;
938
+ if (min !== undefined && min > value)
962
939
  throw new RangeError("min_value cannot exceed max_value.");
963
940
  this.data.max_value = value;
964
941
  return this;
@@ -970,50 +947,20 @@ class CreateIntegerOption extends CreateCommandOption {
970
947
  return this;
971
948
  }
972
949
  addChoices(...choices) {
973
- const current = this.data.choices ?? [];
974
- if (!choices.length)
975
- throw new TypeError("At least one choice is required.");
976
- if (this.data.autocomplete === true)
977
- throw new RangeError("Autocomplete options cannot define choices.");
978
- if (current.length + choices.length > 25)
979
- throw new RangeError("An option cannot contain more than 25 choices.");
980
- this.data.choices = [...current, ...choices];
950
+ appendChoices(this.data, choices);
981
951
  return this;
982
952
  }
983
953
  }
984
954
 
985
- class CreateNumberOption extends CreateCommandOption {
955
+ class CreateIntegerOption extends CreateNumericOption {
986
956
  constructor() {
987
- super(ApplicationCommandOptionEnum.Number);
988
- }
989
- setMinValue(value) {
990
- validateNumberRange(value, -9007199254740991, 9007199254740991, "min_value", false);
991
- this.data.min_value = value;
992
- return this;
957
+ super(ApplicationCommandOptionEnum.Integer, true);
993
958
  }
994
- setMaxValue(value) {
995
- validateNumberRange(value, -9007199254740991, 9007199254740991, "max_value", false);
996
- if (this.data.min_value !== undefined && this.data.min_value > value)
997
- throw new RangeError("min_value cannot exceed max_value.");
998
- this.data.max_value = value;
999
- return this;
1000
- }
1001
- setAutocomplete(enabled = true) {
1002
- if (enabled && Array.isArray(this.data.choices) && this.data.choices.length)
1003
- throw new RangeError("Autocomplete options cannot define choices.");
1004
- this.data.autocomplete = enabled;
1005
- return this;
1006
- }
1007
- addChoices(...choices) {
1008
- const current = this.data.choices ?? [];
1009
- if (!choices.length)
1010
- throw new TypeError("At least one choice is required.");
1011
- if (this.data.autocomplete === true)
1012
- throw new RangeError("Autocomplete options cannot define choices.");
1013
- if (current.length + choices.length > 25)
1014
- throw new RangeError("An option cannot contain more than 25 choices.");
1015
- this.data.choices = [...current, ...choices];
1016
- return this;
959
+ }
960
+
961
+ class CreateNumberOption extends CreateNumericOption {
962
+ constructor() {
963
+ super(ApplicationCommandOptionEnum.Number, false);
1017
964
  }
1018
965
  }
1019
966
 
@@ -1092,17 +1039,9 @@ class CreateSubcommand extends CreateCommandOption {
1092
1039
  }
1093
1040
  addChildOption(option) {
1094
1041
  const options = this.data.options ?? [];
1095
- if (options.length >= 25)
1096
- throw new RangeError("A subcommand cannot contain more than 25 options.");
1097
- const payload = option.toJSON();
1098
- if (options.some((existing) => existing.name === payload.name))
1099
- throw new RangeError(`Duplicate option name: ${String(payload.name)}.`);
1100
- if (payload.required === true && options.some((existing) => existing.required !== true))
1101
- throw new RangeError("Required subcommand options must be placed before optional options.");
1102
1042
  if (options.some((existing) => existing.type === ApplicationCommandOptionEnum.Subcommand))
1103
1043
  throw new RangeError("Subcommands cannot contain nested subcommands.");
1104
- options.push(payload);
1105
- this.data.options = options;
1044
+ this.data.options = appendOption(options, option.toJSON(), "subcommand");
1106
1045
  return this;
1107
1046
  }
1108
1047
  }
@@ -1125,6 +1064,29 @@ class CreateSubcommandGroup extends CreateCommandOption {
1125
1064
  return this;
1126
1065
  }
1127
1066
  }
1067
+ var MAX_SAFE = Number.MAX_SAFE_INTEGER;
1068
+ function appendOption(options, payload, parent) {
1069
+ const list = options ?? [];
1070
+ if (list.length >= 25)
1071
+ throw new RangeError(`${parent === "subcommand" ? "A subcommand" : "An application command"} cannot contain more than 25 options.`);
1072
+ if (list.some((existing) => existing.name === payload.name))
1073
+ throw new RangeError(`Duplicate option name: ${String(payload.name)}.`);
1074
+ if (payload.required === true && list.some((existing) => existing.required !== true))
1075
+ throw new RangeError(`Required ${parent} options must be placed before optional options.`);
1076
+ return [...list, payload];
1077
+ }
1078
+ function appendChoices(data, choices) {
1079
+ const current = data.choices ?? [];
1080
+ if (!choices.length)
1081
+ throw new TypeError("At least one choice is required.");
1082
+ if (data.autocomplete === true)
1083
+ throw new RangeError("Autocomplete options cannot define choices.");
1084
+ if (current.length + choices.length > 25)
1085
+ throw new RangeError("An option cannot contain more than 25 choices.");
1086
+ for (const choice of choices)
1087
+ validateText2(choice.name, "Choice name", 100);
1088
+ data.choices = [...current, ...choices.map((choice) => ({ ...choice }))];
1089
+ }
1128
1090
  function validateName(value, field) {
1129
1091
  if (!/^[\p{L}\p{N}_-]{1,32}$/u.test(value) || value !== value.toLowerCase())
1130
1092
  throw new RangeError(`${field} must contain 1-32 lowercase letters, numbers, underscores, or hyphens.`);
@@ -1172,8 +1134,7 @@ class CreateContextMenuCommand {
1172
1134
  return this;
1173
1135
  }
1174
1136
  setContexts(...contexts) {
1175
- if (contexts.some((context) => context !== 0 && context !== 1 && context !== 2))
1176
- throw new RangeError("Command contexts must be 0, 1 or 2.");
1137
+ validateContexts(contexts);
1177
1138
  this.data.contexts = [...contexts];
1178
1139
  return this;
1179
1140
  }
@@ -1215,13 +1176,14 @@ var UserCommandBuilder = CreateUserCommand;
1215
1176
  var UserOptionBuilder = CreateUserOption;
1216
1177
  var ApplicationCommandOptionType = ApplicationCommandOptionEnum;
1217
1178
  // packages/builders/src/attachment.ts
1218
- import { readFile } from "fs/promises";
1219
- import { basename } from "path";
1179
+ import { readFile, realpath } from "fs/promises";
1180
+ import { basename, isAbsolute, relative, resolve } from "path";
1220
1181
 
1221
1182
  class CreateAttachment {
1222
1183
  name;
1223
1184
  description;
1224
1185
  file;
1186
+ root;
1225
1187
  constructor(file, data) {
1226
1188
  this.file = file;
1227
1189
  if (typeof data === "string") {
@@ -1229,6 +1191,7 @@ class CreateAttachment {
1229
1191
  } else {
1230
1192
  this.name = data?.name ?? (typeof file === "string" ? basename(file) : "file.bin");
1231
1193
  this.description = data?.description;
1194
+ this.root = data?.root;
1232
1195
  }
1233
1196
  }
1234
1197
  setName(name) {
@@ -1245,7 +1208,8 @@ class CreateAttachment {
1245
1208
  }
1246
1209
  async toBuffer() {
1247
1210
  if (typeof this.file === "string") {
1248
- const buffer = await readFile(this.file);
1211
+ const path = this.root === undefined ? this.file : await insideRoot(this.root, this.file);
1212
+ const buffer = await readFile(path);
1249
1213
  return new Uint8Array(buffer);
1250
1214
  }
1251
1215
  if (this.file instanceof Uint8Array)
@@ -1263,6 +1227,16 @@ class CreateAttachment {
1263
1227
  }
1264
1228
  }
1265
1229
  var AttachmentBuilder = CreateAttachment;
1230
+ async function insideRoot(root, file) {
1231
+ const base = await realpath(root);
1232
+ const target = await realpath(resolve(base, file)).catch(() => {
1233
+ throw new Error("Attachment file was not found inside its root.");
1234
+ });
1235
+ const rel = relative(base, target);
1236
+ if (rel === "" || rel.startsWith("..") || isAbsolute(rel))
1237
+ throw new Error("Attachment file is outside its root folder.");
1238
+ return target;
1239
+ }
1266
1240
  export {
1267
1241
  ActionRowBuilder,
1268
1242
  ApplicationCommandOptionEnum,
@@ -1288,6 +1262,7 @@ export {
1288
1262
  CreateButton,
1289
1263
  CreateChannelOption,
1290
1264
  CreateChannelSelectMenu,
1265
+ CreateCommandOption,
1291
1266
  CreateContainer,
1292
1267
  CreateContentInventoryEntry,
1293
1268
  CreateContextMenuCommand,
@@ -1348,4 +1323,4 @@ export {
1348
1323
  componentsV2Message
1349
1324
  };
1350
1325
 
1351
- //# debugId=E27BC2383A77150B64756E2164756E21
1326
+ //# debugId=AAEFB888B204975D64756E2164756E21