@seedcord/http 0.5.0 → 0.6.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.
@@ -1,15 +1,17 @@
1
1
  import "reflect-metadata";
2
- import { GatedMetadataKey, PublishDefault, RegisterDefaults, RegisterSubscriber, accessorStore, asError, clearStore, decodeComponentRoute, deferFlags, guardedAccessor, isEmojiTuple, outcomeFor, prefixOf, queuedMsFor, reportDispatch, reportedWrite, runHandlerGates, sendFlags, slowGateMonitor } from "@seedcord/core/internal";
2
+ import { GatedMetadataKey, PublishDefault, RegisterDefaults, RegisterSubscriber, accessorStore, asError, clearStore, decodeComponentRoute, deferFlags, guardedAccessor, isEmojiTuple, outcomeFor, queuedMsFor, reportDispatch, reportedWrite, runHandlerGates, sendFlags, slowGateMonitor } from "@seedcord/core/internal";
3
3
  import { SeedcordError, SeedcordTypeError, applicationIdFromToken, validateDiscordToken } from "@seedcord/errors/internal";
4
4
  import { Logger } from "@seedcord/logger";
5
5
  import { Converters, Envapter } from "envapt";
6
6
  import { DiscordAPIError, REST } from "@discordjs/rest";
7
- import { ArraySourceBase, BaseHandler, BaseReplySender, Bus, CursorSourceBase, DispatchContext, Fault, Notice, PaginatorBase, RepliableHandler, ResolvedEmoji, Silence, Subscriber, WebhookLog } from "@seedcord/core";
7
+ import { ArraySourceBase, BaseHandler, BaseReplySender, Bus, CursorSourceBase, DispatchContext, Fault, InteractionKind, Notice, PaginatorBase, RepliableHandler, ResolvedEmoji, Silence, Subscriber, WebhookLog } from "@seedcord/core";
8
8
  import { SeedcordErrorCode, paint } from "@seedcord/errors";
9
9
  import { MemoryRateLimiter } from "@seedcord/rate-limiter";
10
10
  import { ApplicationCommandOptionType, ApplicationCommandType, ChannelType, ComponentType, InteractionResponseType, InteractionType, MessageFlags, RESTJSONErrorCodes, Routes } from "discord-api-types/v10";
11
11
  import { API } from "@discordjs/core/http-only";
12
12
  import { buildSlashRoute } from "@seedcord/utils/internal";
13
+ import { prefixOf } from "@seedcord/custom-id";
14
+ import { Collection } from "@discordjs/collection";
13
15
 
14
16
  //#region src/reply/ReplySender.ts
15
17
  function wireAllowedMentions(mentions) {
@@ -138,8 +140,8 @@ function apiFor(rest) {
138
140
  * Shared base the repliable HTTP interaction handlers extend.
139
141
  *
140
142
  * Not a public entry point. Extend {@link SlashHandler}, {@link ButtonHandler}, {@link ModalHandler},
141
- * {@link SelectMenuHandler}, or {@link ContextMenuHandler} instead. This class binds the core reply base
142
- * to the http sender.
143
+ * {@link ContextMenuHandler}, or one of the select menu bases instead. This class binds the core
144
+ * reply base to the http sender.
143
145
  *
144
146
  * @typeParam Event - The repliable interaction type this handler processes
145
147
  */
@@ -672,8 +674,8 @@ var UnhandledAutocomplete = class extends AutocompleteHandler {
672
674
  * Shared base the repliable interaction handlers extend.
673
675
  *
674
676
  * Not a public entry point. Extend {@link SlashHandler}, {@link ContextMenuHandler}, {@link ButtonHandler},
675
- * {@link SelectMenuHandler}, or {@link ModalHandler} instead. This class adds `showModal` on top of the
676
- * reply members.
677
+ * {@link ModalHandler}, or one of the select menu bases instead. This class adds `showModal` on top
678
+ * of the reply members.
677
679
  *
678
680
  * @typeParam Event - The repliable interaction type this handler processes
679
681
  */
@@ -700,31 +702,22 @@ var UnhandledRepliable = class extends InteractionHandler {
700
702
 
701
703
  //#endregion
702
704
  //#region src/dispatch/resolve.ts
703
- const COMPONENT_KIND = {
704
- button: "button",
705
- stringSelect: "stringMenu",
706
- userSelect: "userMenu",
707
- roleSelect: "roleMenu",
708
- channelSelect: "channelMenu",
709
- mentionableSelect: "mentionableMenu",
710
- modal: "modal"
711
- };
712
705
  function commandKind(type) {
713
706
  switch (type) {
714
- case ApplicationCommandType.ChatInput: return "slash";
715
- case ApplicationCommandType.User: return "userContextMenu";
716
- case ApplicationCommandType.Message: return "messageContextMenu";
707
+ case ApplicationCommandType.ChatInput: return InteractionKind.Slash;
708
+ case ApplicationCommandType.User: return InteractionKind.UserContextMenu;
709
+ case ApplicationCommandType.Message: return InteractionKind.MessageContextMenu;
717
710
  default: return null;
718
711
  }
719
712
  }
720
713
  function componentMapKey(type) {
721
714
  switch (type) {
722
- case ComponentType.Button: return "button";
723
- case ComponentType.StringSelect: return "stringSelect";
724
- case ComponentType.UserSelect: return "userSelect";
725
- case ComponentType.RoleSelect: return "roleSelect";
726
- case ComponentType.ChannelSelect: return "channelSelect";
727
- case ComponentType.MentionableSelect: return "mentionableSelect";
715
+ case ComponentType.Button: return InteractionKind.Button;
716
+ case ComponentType.StringSelect: return InteractionKind.StringMenu;
717
+ case ComponentType.UserSelect: return InteractionKind.UserMenu;
718
+ case ComponentType.RoleSelect: return InteractionKind.RoleMenu;
719
+ case ComponentType.ChannelSelect: return InteractionKind.ChannelMenu;
720
+ case ComponentType.MentionableSelect: return InteractionKind.MentionableMenu;
728
721
  default: return null;
729
722
  }
730
723
  }
@@ -754,22 +747,20 @@ function describeRow(row) {
754
747
  */
755
748
  function buildRouteMaps(manifest) {
756
749
  const maps = {
757
- slash: /* @__PURE__ */ new Map(),
758
- userContextMenu: /* @__PURE__ */ new Map(),
759
- messageContextMenu: /* @__PURE__ */ new Map(),
760
- autocomplete: /* @__PURE__ */ new Map(),
761
- components: {
762
- button: /* @__PURE__ */ new Map(),
763
- stringSelect: /* @__PURE__ */ new Map(),
764
- userSelect: /* @__PURE__ */ new Map(),
765
- roleSelect: /* @__PURE__ */ new Map(),
766
- channelSelect: /* @__PURE__ */ new Map(),
767
- mentionableSelect: /* @__PURE__ */ new Map(),
768
- modal: /* @__PURE__ */ new Map()
769
- }
750
+ [InteractionKind.Slash]: /* @__PURE__ */ new Map(),
751
+ [InteractionKind.UserContextMenu]: /* @__PURE__ */ new Map(),
752
+ [InteractionKind.MessageContextMenu]: /* @__PURE__ */ new Map(),
753
+ [InteractionKind.Autocomplete]: /* @__PURE__ */ new Map(),
754
+ [InteractionKind.Button]: /* @__PURE__ */ new Map(),
755
+ [InteractionKind.StringMenu]: /* @__PURE__ */ new Map(),
756
+ [InteractionKind.UserMenu]: /* @__PURE__ */ new Map(),
757
+ [InteractionKind.RoleMenu]: /* @__PURE__ */ new Map(),
758
+ [InteractionKind.ChannelMenu]: /* @__PURE__ */ new Map(),
759
+ [InteractionKind.MentionableMenu]: /* @__PURE__ */ new Map(),
760
+ [InteractionKind.Modal]: /* @__PURE__ */ new Map()
770
761
  };
771
762
  const owners = /* @__PURE__ */ new Map();
772
- function set(map, kind, key, row) {
763
+ function set(kind, key, row) {
773
764
  const routeId = `${kind}:${key}`;
774
765
  const owner = owners.get(routeId);
775
766
  if (owner) throw new SeedcordError(SeedcordErrorCode.InteractionDuplicateRoute, [
@@ -778,7 +769,7 @@ function buildRouteMaps(manifest) {
778
769
  describeRow(row)
779
770
  ]);
780
771
  owners.set(routeId, row);
781
- map.set(key, {
772
+ maps[kind].set(key, {
782
773
  kind,
783
774
  routeId,
784
775
  load: namedExport(routeId, row)
@@ -786,10 +777,10 @@ function buildRouteMaps(manifest) {
786
777
  }
787
778
  for (const row of manifest.commandRoutes) {
788
779
  const kind = commandKind(row.type);
789
- if (kind) set(maps[kind], kind, row.name, row);
780
+ if (kind) set(kind, row.name, row);
790
781
  }
791
- for (const row of manifest.autocompleteRoutes) set(maps.autocomplete, "autocomplete", row.name, row);
792
- for (const row of manifest.componentRoutes) set(maps.components[row.kind], COMPONENT_KIND[row.kind], row.prefix, row);
782
+ for (const row of manifest.autocompleteRoutes) set(InteractionKind.Autocomplete, row.name, row);
783
+ for (const row of manifest.componentRoutes) set(row.kind, row.prefix, row);
793
784
  return maps;
794
785
  }
795
786
  function unhandled(kind, attemptedKey) {
@@ -797,7 +788,7 @@ function unhandled(kind, attemptedKey) {
797
788
  kind,
798
789
  routeId: null,
799
790
  attemptedKey,
800
- load: () => Promise.resolve(kind === "autocomplete" ? UnhandledAutocomplete : UnhandledRepliable)
791
+ load: () => Promise.resolve(kind === InteractionKind.Autocomplete ? UnhandledAutocomplete : UnhandledRepliable)
801
792
  };
802
793
  }
803
794
  /**
@@ -812,24 +803,24 @@ function resolve(maps, interaction) {
812
803
  case InteractionType.ApplicationCommand: {
813
804
  if (interaction.data.type === ApplicationCommandType.ChatInput) {
814
805
  const route = slashRouteOf(interaction.data);
815
- return maps.slash.get(route) ?? unhandled("slash", route);
806
+ return maps[InteractionKind.Slash].get(route) ?? unhandled(InteractionKind.Slash, route);
816
807
  }
817
808
  const kind = commandKind(interaction.data.type);
818
809
  return kind ? maps[kind].get(interaction.data.name) ?? unhandled(kind, interaction.data.name) : null;
819
810
  }
820
811
  case InteractionType.ApplicationCommandAutocomplete: {
821
812
  const route = slashRouteOf(interaction.data);
822
- return maps.autocomplete.get(route) ?? unhandled("autocomplete", route);
813
+ return maps[InteractionKind.Autocomplete].get(route) ?? unhandled(InteractionKind.Autocomplete, route);
823
814
  }
824
815
  case InteractionType.MessageComponent: {
825
816
  const key = componentMapKey(interaction.data.component_type);
826
817
  if (!key) return null;
827
818
  const prefix = prefixOf(interaction.data.custom_id);
828
- return maps.components[key].get(prefix) ?? unhandled(COMPONENT_KIND[key], prefix);
819
+ return maps[key].get(prefix) ?? unhandled(key, prefix);
829
820
  }
830
821
  case InteractionType.ModalSubmit: {
831
822
  const prefix = prefixOf(interaction.data.custom_id);
832
- return maps.components.modal.get(prefix) ?? unhandled("modal", prefix);
823
+ return maps[InteractionKind.Modal].get(prefix) ?? unhandled(InteractionKind.Modal, prefix);
833
824
  }
834
825
  default: return null;
835
826
  }
@@ -1005,7 +996,7 @@ function createSeedcord(config, manifest) {
1005
996
  //#endregion
1006
997
  //#region src/inputs/pick.ts
1007
998
  function pick(ids, bucket) {
1008
- const found = /* @__PURE__ */ new Map();
999
+ const found = new Collection();
1009
1000
  if (!ids || !bucket) return found;
1010
1001
  for (const id of ids) if (Object.hasOwn(bucket, id)) found.set(id, bucket[id]);
1011
1002
  return found;
@@ -1071,7 +1062,7 @@ function isKind(entry, kinds) {
1071
1062
  * kind that getter does not read. The message names the getter that does.
1072
1063
  *
1073
1064
  * A select getter resolves the ids its field picked against the interaction's `resolved` data and returns a
1074
- * `Map` keyed by id. A field that picked nothing returns null. Pass `required` to throw there instead.
1065
+ * `Collection` keyed by id. A field that picked nothing returns null. Pass `required` to throw there instead.
1075
1066
  */
1076
1067
  var ModalFields = class {
1077
1068
  entries = /* @__PURE__ */ new Map();
@@ -1401,9 +1392,9 @@ var MessageContextMenuHandler = class extends InteractionHandler {
1401
1392
  /**
1402
1393
  * Shared base the customId-routed component handlers extend on the HTTP transport.
1403
1394
  *
1404
- * Not a public entry point. Extend {@link ButtonHandler}, {@link SelectMenuHandler}, or {@link ModalHandler}
1405
- * instead. This class defines the customId decode, the route matching, and the source-message verbs
1406
- * `update` and `deferUpdate`.
1395
+ * Not a public entry point. Extend {@link ButtonHandler}, {@link ModalHandler}, or one of the select menu
1396
+ * bases instead. This class defines the customId decode, the route matching, and the source-message
1397
+ * verbs `update` and `deferUpdate`.
1407
1398
  *
1408
1399
  * @typeParam Event - The component or modal interaction type this handler processes
1409
1400
  * @typeParam Defs - The customId route definitions registered on the concrete handler
@@ -1529,23 +1520,58 @@ var ModalHandler = class extends ComponentHandler {
1529
1520
 
1530
1521
  //#endregion
1531
1522
  //#region src/handlers/interaction/components/SelectMenuHandler.ts
1523
+ function resolvedOf(data) {
1524
+ return data.resolved ?? {};
1525
+ }
1526
+ /**
1527
+ * Shared base the select menu handlers extend on the HTTP transport.
1528
+ *
1529
+ * Not a public entry point. Extend {@link StringMenuHandler}, {@link UserMenuHandler},
1530
+ * {@link RoleMenuHandler}, {@link ChannelMenuHandler}, or {@link MentionableMenuHandler} instead. This
1531
+ * class defines the `values` getter those bases share.
1532
+ *
1533
+ * @typeParam Event - The select menu interaction type this handler processes
1534
+ * @typeParam Defs - The customId route definitions registered on the concrete handler
1535
+ */
1536
+ var SelectMenuHandler = class extends ComponentHandler {
1537
+ /** The values this select picked. On every kind but the string menu they are snowflake ids. */
1538
+ get values() {
1539
+ return this.event.data.values ?? [];
1540
+ }
1541
+ };
1532
1542
  /**
1533
- * Base class for a select menu handler on the HTTP transport.
1543
+ * Base class for a string select menu handler on the HTTP transport.
1544
+ *
1545
+ * Register the customId definitions with `@StringMenuRoute`, list the same ones in the generic, then read
1546
+ * the chosen option values from `this.values`. Read `this.params` for a single route or `this.match` for
1547
+ * several. Reply through the handler members, or rewrite the source message with `this.update`.
1548
+ *
1549
+ * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof TopicsId]`.
1534
1550
  *
1535
- * Pass the select kind first and the customId definitions second, the same order as `@SelectMenuRoute`.
1536
- * Read the picked ids from `this.values`. The kind decides which of `this.users`, `this.members`,
1537
- * `this.roles`, and `this.channels` this handler carries. The rest are `never`.
1551
+ * @example
1552
+ * ```ts
1553
+ * \@StringMenuRoute(TopicsId)
1554
+ * class Topics extends StringMenuHandler<[typeof TopicsId]> {
1555
+ * async execute() {
1556
+ * const { userId } = this.params;
1557
+ * await this.update(`<@${userId}> now follows ${this.values.join(', ')}`);
1558
+ * }
1559
+ * }
1560
+ * ```
1561
+ */
1562
+ var StringMenuHandler = class extends SelectMenuHandler {};
1563
+ /**
1564
+ * Base class for a user select menu handler on the HTTP transport.
1538
1565
  *
1539
- * Read `this.params` for a single route or `this.match` for several. Reply through the handler members, or
1540
- * rewrite the source message with `this.update`.
1566
+ * Beside `this.values` this handler declares `this.users` and `this.members`. Register the customId
1567
+ * definitions with `@UserMenuRoute` and list the same ones in the generic.
1541
1568
  *
1542
- * @typeParam Kind - The select kind from {@link SelectMenuKind}, e.g. `SelectMenuKind.User`.
1543
1569
  * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof AssignId]`.
1544
1570
  *
1545
1571
  * @example
1546
1572
  * ```ts
1547
- * \@SelectMenuRoute(SelectMenuKind.User, AssignId)
1548
- * class AssignSelect extends SelectMenuHandler<SelectMenuKind.User, [typeof AssignId]> {
1573
+ * \@UserMenuRoute(AssignId)
1574
+ * class Assign extends UserMenuHandler<[typeof AssignId]> {
1549
1575
  * async execute() {
1550
1576
  * const { roleId } = this.params;
1551
1577
  * await this.reply(`assigning ${this.users.size} member(s) to <@&${roleId}>`);
@@ -1553,32 +1579,94 @@ var ModalHandler = class extends ComponentHandler {
1553
1579
  * }
1554
1580
  * ```
1555
1581
  */
1556
- var SelectMenuHandler = class extends ComponentHandler {
1557
- get selection() {
1558
- return this.event.data;
1559
- }
1560
- resolvedMap(bucket) {
1561
- return pick(this.selection.values, bucket);
1562
- }
1563
- /** The ids this select picked. */
1564
- get values() {
1565
- return this.selection.values ?? [];
1566
- }
1582
+ var UserMenuHandler = class extends SelectMenuHandler {
1567
1583
  /** The users this select picked. */
1568
1584
  get users() {
1569
- return this.resolvedMap(this.selection.resolved?.users);
1585
+ return pick(this.values, resolvedOf(this.event.data).users);
1570
1586
  }
1571
1587
  /** The guild members behind the picked users. Discord resolves these only inside a guild. */
1572
1588
  get members() {
1573
- return this.resolvedMap(this.selection.resolved?.members);
1589
+ return pick(this.values, resolvedOf(this.event.data).members);
1574
1590
  }
1591
+ };
1592
+ /**
1593
+ * Base class for a role select menu handler on the HTTP transport.
1594
+ *
1595
+ * Beside `this.values` this handler declares `this.roles`. Register the customId definitions with
1596
+ * `@RoleMenuRoute` and list the same ones in the generic.
1597
+ *
1598
+ * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof GrantId]`.
1599
+ *
1600
+ * @example
1601
+ * ```ts
1602
+ * \@RoleMenuRoute(GrantId)
1603
+ * class Grant extends RoleMenuHandler<[typeof GrantId]> {
1604
+ * async execute() {
1605
+ * await this.update(`granting ${this.roles.size} role(s)`);
1606
+ * }
1607
+ * }
1608
+ * ```
1609
+ */
1610
+ var RoleMenuHandler = class extends SelectMenuHandler {
1575
1611
  /** The roles this select picked. */
1576
1612
  get roles() {
1577
- return this.resolvedMap(this.selection.resolved?.roles);
1613
+ return pick(this.values, resolvedOf(this.event.data).roles);
1578
1614
  }
1615
+ };
1616
+ /**
1617
+ * Base class for a channel select menu handler on the HTTP transport.
1618
+ *
1619
+ * Beside `this.values` this handler declares `this.channels`. Register the customId definitions with
1620
+ * `@ChannelMenuRoute` and list the same ones in the generic.
1621
+ *
1622
+ * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof LogTargetId]`.
1623
+ *
1624
+ * @example
1625
+ * ```ts
1626
+ * \@ChannelMenuRoute(LogTargetId)
1627
+ * class LogTarget extends ChannelMenuHandler<[typeof LogTargetId]> {
1628
+ * async execute() {
1629
+ * await this.update(`logging to ${this.channels.size} channel(s)`);
1630
+ * }
1631
+ * }
1632
+ * ```
1633
+ */
1634
+ var ChannelMenuHandler = class extends SelectMenuHandler {
1579
1635
  /** The channels this select picked. */
1580
1636
  get channels() {
1581
- return this.resolvedMap(this.selection.resolved?.channels);
1637
+ return pick(this.values, resolvedOf(this.event.data).channels);
1638
+ }
1639
+ };
1640
+ /**
1641
+ * Base class for a mentionable select menu handler on the HTTP transport.
1642
+ *
1643
+ * A mentionable menu accepts users and roles together. `this.users`, `this.members`, and `this.roles`
1644
+ * can each come back empty.
1645
+ *
1646
+ * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof InviteId]`.
1647
+ *
1648
+ * @example
1649
+ * ```ts
1650
+ * \@MentionableMenuRoute(InviteId)
1651
+ * class Invite extends MentionableMenuHandler<[typeof InviteId]> {
1652
+ * async execute() {
1653
+ * await this.update(`inviting ${this.users.size} user(s) and ${this.roles.size} role(s)`);
1654
+ * }
1655
+ * }
1656
+ * ```
1657
+ */
1658
+ var MentionableMenuHandler = class extends SelectMenuHandler {
1659
+ /** The users this select picked. */
1660
+ get users() {
1661
+ return pick(this.values, resolvedOf(this.event.data).users);
1662
+ }
1663
+ /** The guild members behind the picked users. Discord resolves these only inside a guild. */
1664
+ get members() {
1665
+ return pick(this.values, resolvedOf(this.event.data).members);
1666
+ }
1667
+ /** The roles this select picked. */
1668
+ get roles() {
1669
+ return pick(this.values, resolvedOf(this.event.data).roles);
1582
1670
  }
1583
1671
  };
1584
1672
 
@@ -1725,8 +1813,8 @@ function Gated(...gates) {
1725
1813
 
1726
1814
  //#endregion
1727
1815
  //#region src/version.ts
1728
- const version = "0.5.0";
1816
+ const version = "0.6.0";
1729
1817
 
1730
1818
  //#endregion
1731
- export { RepliableHandler$1 as C, AutocompleteHandler as S, ModalFields as _, Paginator as a, buildRouteMaps as b, SelectMenuHandler as c, ComponentHandler as d, MessageContextMenuHandler as f, Emojis as g, EmojiInjector as h, CursorSource as i, ModalHandler as l, SlashHandler as m, Gated as n, Subscriber$1 as o, UserContextMenuHandler as p, ArraySource as r, WebhookLog$1 as s, version as t, ButtonHandler as u, createSeedcord as v, ReplySender as w, InteractionHandler as x, buildEngine as y };
1732
- //# sourceMappingURL=edge.index-DwRPmkh2.mjs.map
1819
+ export { createSeedcord as C, AutocompleteHandler as D, InteractionHandler as E, RepliableHandler$1 as O, ModalFields as S, buildRouteMaps as T, MessageContextMenuHandler as _, Paginator as a, EmojiInjector as b, ChannelMenuHandler as c, SelectMenuHandler as d, StringMenuHandler as f, ComponentHandler as g, ButtonHandler as h, CursorSource as i, ReplySender as k, MentionableMenuHandler as l, ModalHandler as m, Gated as n, Subscriber$1 as o, UserMenuHandler as p, ArraySource as r, WebhookLog$1 as s, version as t, RoleMenuHandler as u, UserContextMenuHandler as v, buildEngine as w, Emojis as x, SlashHandler as y };
1820
+ //# sourceMappingURL=edge.index-CZHoclPi.mjs.map