@wolfstar/plugin-gateway 0.2.0-next-20260926221130 → 0.2.0-next-20260926221949

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
@@ -102,6 +102,7 @@ On top of the `Client` options:
102
102
  | `guildMemberUpdate` | `oldMember \| null`, `newMember` |
103
103
  | `guildMemberRemove` | `member \| null`, `data` |
104
104
  | `guildRoleCreate` / `guildRoleUpdate` / `guildRoleDelete` | same shapes as members |
105
+ | `guildMembersChunk` | `members`, `guild \| null`, `data` |
105
106
  | `userUpdate` | `oldUser \| null`, `newUser` |
106
107
  | `emojiCreate` / `emojiDelete` | `emoji` |
107
108
  | `emojiUpdate` | `oldEmoji`, `newEmoji` |
@@ -242,7 +243,8 @@ events.
242
243
  `{ force: true }` after the IDs to always hit the API, `{ cache: false }` not to store the result:
243
244
  `client.messages.fetch(channelId, messageId, { force: true })`;
244
245
  - `refresh` is `fetch` with `{ force: true }`;
245
- - `resolve` takes a structure (returned as is) or a cache key, like discord.js's `resolve`.
246
+ - `resolve` takes a structure (returned as is) or a cache key, like discord.js's `resolve`;
247
+ - `cached` is `get` without the `await`, for a synchronous cache, see below.
246
248
 
247
249
  Like discord.js's `CachedManager#_add`, every API payload goes through the manager's `_add`, which
248
250
  merges it into the cached entry (the fields a partial payload lacks keep their cached value) and
@@ -258,6 +260,32 @@ the copy embedded in its payload.
258
260
  Swapping `createInMemoryCache()` for `createRedisCache({ redis })` changes nothing else, see
259
261
  [`@wolfstar/plugin-cache`](../plugin-cache).
260
262
 
263
+ ### Synchronous reads
264
+
265
+ Every manager method above is asynchronous since the cache can be Redis, which makes a hot path
266
+ such as a message filter await every lookup even when the cache lives in memory. With a synchronous
267
+ cache (`createInMemoryCache()`), `cached` takes the same arguments as `get` and returns the same
268
+ structure, relations included, without a promise:
269
+
270
+ ```ts
271
+ client.on("messageCreate", (message) => {
272
+ const member = client.members.cached(message.guildId!, message.author.id);
273
+ if (member?.roleIds.includes(mutedRoleId)) return;
274
+ // ...
275
+ });
276
+ ```
277
+
278
+ It returns `undefined` on a miss, or when the client has no cache, like `get`. An asynchronous cache
279
+ cannot tell a miss apart without awaiting it, so there `cached` throws a `TypeError` rather than
280
+ silently returning `undefined`; the same goes for a custom cache mixing both kinds, when a relation
281
+ lives in an asynchronous entity cache. `manager.cache?.synchronous` tells which path to take:
282
+
283
+ ```ts
284
+ const user = client.users.cache?.synchronous
285
+ ? client.users.cached(userId)
286
+ : await client.users.get(userId);
287
+ ```
288
+
261
289
  ## Structures
262
290
 
263
291
  `User`, `Guild`, `Message`, `GuildMember`, and `Role` wrap the raw data behind typed getters.
@@ -327,7 +355,9 @@ The client also has discord.js's `fetchSticker`, `fetchStickerPacks`, and `fetch
327
355
  ### Users, members and roles
328
356
 
329
357
  They follow discord.js's API, with one difference: anything discord.js reads synchronously from its
330
- cache is asynchronous here, since the cache can be Redis.
358
+ cache is asynchronous here, since the cache can be Redis. With an in-memory cache, `cached` reads
359
+ `client.users`, `client.members` and `client.roles` synchronously, see
360
+ [Synchronous reads](#synchronous-reads).
331
361
 
332
362
  ```ts
333
363
  const member = await client.members.fetch(guildId, userId);
@@ -352,6 +382,22 @@ member counts. Permissions are `PermissionsBitField`s, computed like Discord doe
352
382
  administrators get everything, everyone else `@everyone` plus their roles. Channel overwrites
353
383
  apply through `member.fetchPermissionsIn(channel)`, see below.
354
384
 
385
+ `client.members.request(guildId, options)` (or `guild.requestMembers(options)`, discord.js:
386
+ `guild.members.fetch()`) asks the guild's shard for its members over the gateway instead of REST:
387
+ every member by default, those matching a `query` (with a `limit`), or up to 100 `userIds`, with
388
+ their `presences` if asked. It resolves with the `GuildMember`s once Discord's last
389
+ `GUILD_MEMBERS_CHUNK` for its `nonce` is cached, so `client.members.get` sees them, and rejects
390
+ with a `GuildMembersTimeoutError` when no chunk arrives for `time` milliseconds (120 seconds by
391
+ default), or a `GuildMembersRateLimitError` when Discord answers with `RATE_LIMITED`. Every chunk
392
+ is also emitted as `guildMembersChunk`, whose `data.not_found` lists the requested IDs that are
393
+ not members. Requesting every member or a query needs the `GuildMembers` intent, and presences the
394
+ `GuildPresences` one. `@discordjs/ws` keeps the requests within the gateway's rate limit.
395
+
396
+ ```ts
397
+ const members = await client.members.request(guildId); // every member
398
+ const [wolf] = await client.members.request(guildId, { userIds: [userId], presences: true });
399
+ ```
400
+
355
401
  ### Channels and permissions
356
402
 
357
403
  Guild channels follow discord.js: `edit`, `setName`, `clone`, `delete`, and the setters of each
@@ -2,7 +2,7 @@ import { Client, ClientOptions, Listener } from "@wolfstar/http-framework";
2
2
  import { OptionalWebSocketManagerOptions, ShardRange, WebSocketManager } from "@discordjs/ws";
3
3
  import { Client as Client$1 } from "@discordjs/core";
4
4
  import { Awaitable, Cache, CacheEntityName, CacheEntityTypes, EntityCache } from "@wolfstar/plugin-cache";
5
- import { APIApplication, APIApplicationCommand, APIAttachment, APIAuditLogChange, APIAutoModerationAction, APIAutoModerationRule, APIAutoModerationRuleTriggerMetadata, APIAvatarDecorationData, APIChannel, APIChannelMention, APICollectibles, APIEmbed, APIEmbedAuthor, APIEmbedField, APIEmbedFooter, APIEmbedImage, APIEmbedProvider, APIEmbedThumbnail, APIEmbedVideo, APIEmoji, APIExtendedInvite, APIGuild, APIGuildForumDefaultReactionEmoji, APIGuildForumTag, APIGuildMember, APIGuildOnboarding, APIGuildOnboardingPrompt, APIGuildOnboardingPromptOption, APIGuildPreview, APIGuildScheduledEvent, APIGuildScheduledEventEntityMetadata, APIGuildScheduledEventRecurrenceRule, APIGuildWelcomeScreen, APIGuildWidget, APIGuildWidgetMember, APIIncidentsData, APIInviteChannel, APIInviteGuild, APIMessage, APIOverwrite, APIPartialEmoji, APIPoll, APIPollAnswer, APIReaction, APIRole, APIRoleTags, APISoundboardSound, APIStageInstance, APISticker, APIStickerPack, APITemplate, APIThreadChannel, APIThreadMember, APIUser, APIUserPrimaryGuild, APIVoiceRegion, APIWebhook, ActivityFlags, ActivityType, AttachmentFlags, AuditLogEvent, AutoModerationRuleEventType, AutoModerationRuleKeywordPresetType, AutoModerationRuleTriggerType, ChannelFlags, ChannelType, ForumLayoutType, GatewayActivity, GatewayActivityAssets, GatewayActivityUpdateData, GatewayAutoModerationActionExecutionDispatchData, GatewayChannelPinsUpdateDispatchData, GatewayDispatchEvents, GatewayDispatchPayload, GatewayGuildDeleteDispatchData, GatewayGuildIntegrationsUpdateDispatchData, GatewayGuildMemberRemoveDispatchData, GatewayGuildRoleDeleteDispatchData, GatewayGuildScheduledEventUserAddDispatchData, GatewayGuildScheduledEventUserRemoveDispatchData, GatewayGuildSoundboardSoundDeleteDispatchData, GatewayIntegrationDeleteDispatchData, GatewayIntentBits, GatewayInviteCreateDispatchData, GatewayInviteDeleteDispatchData, GatewayMessageDeleteBulkDispatchData, GatewayMessageDeleteDispatchData, GatewayMessageReactionRemoveAllDispatchData, GatewayPresenceClientStatus, GatewayPresenceUpdateData, GatewayReadyDispatchData, GatewayThreadDeleteDispatchData, GatewayThreadListSync, GatewayThreadMembersUpdateDispatchData, GatewayTypingStartDispatchData, GatewayVoiceServerUpdateDispatchData, GatewayWebhooksUpdateDispatchData, GuildDefaultMessageNotifications, GuildExplicitContentFilter, GuildMemberFlags, GuildOnboardingMode, GuildOnboardingPromptType, GuildPremiumTier, GuildScheduledEventEntityType, GuildScheduledEventPrivacyLevel, GuildScheduledEventStatus, GuildSystemChannelFlags, GuildVerificationLevel, GuildWidgetStyle, InviteTargetType, InviteType, Locale, MessageFlags, MessageType, OverwriteType, PermissionFlagsBits, PresenceUpdateReceiveStatus, PresenceUpdateStatus, RESTGetAPIGuildVanityUrlResult, RESTPatchAPIChannelJSONBody, RESTPatchAPIChannelMessageJSONBody, RESTPatchAPIGuildJSONBody, RESTPatchAPIWebhookWithTokenMessageJSONBody, RESTPostAPIChannelMessageJSONBody, RESTPostAPIGuildsJSONBody, RESTPostAPIWebhookWithTokenJSONBody, ReactionType, RoleFlags, Snowflake, SortOrderType, StageInstancePrivacyLevel, StickerFormatType, ThreadAutoArchiveDuration, ThreadChannelType, UserFlags, VideoQualityMode, WebhookType } from "discord-api-types/v10";
5
+ import { APIApplication, APIApplicationCommand, APIAttachment, APIAuditLogChange, APIAutoModerationAction, APIAutoModerationRule, APIAutoModerationRuleTriggerMetadata, APIAvatarDecorationData, APIChannel, APIChannelMention, APICollectibles, APIEmbed, APIEmbedAuthor, APIEmbedField, APIEmbedFooter, APIEmbedImage, APIEmbedProvider, APIEmbedThumbnail, APIEmbedVideo, APIEmoji, APIExtendedInvite, APIGuild, APIGuildForumDefaultReactionEmoji, APIGuildForumTag, APIGuildMember, APIGuildOnboarding, APIGuildOnboardingPrompt, APIGuildOnboardingPromptOption, APIGuildPreview, APIGuildScheduledEvent, APIGuildScheduledEventEntityMetadata, APIGuildScheduledEventRecurrenceRule, APIGuildWelcomeScreen, APIGuildWidget, APIGuildWidgetMember, APIIncidentsData, APIInviteChannel, APIInviteGuild, APIMessage, APIOverwrite, APIPartialEmoji, APIPoll, APIPollAnswer, APIReaction, APIRole, APIRoleTags, APISoundboardSound, APIStageInstance, APISticker, APIStickerPack, APITemplate, APIThreadChannel, APIThreadMember, APIUser, APIUserPrimaryGuild, APIVoiceRegion, APIWebhook, ActivityFlags, ActivityType, AttachmentFlags, AuditLogEvent, AutoModerationRuleEventType, AutoModerationRuleKeywordPresetType, AutoModerationRuleTriggerType, ChannelFlags, ChannelType, ForumLayoutType, GatewayActivity, GatewayActivityAssets, GatewayActivityUpdateData, GatewayAutoModerationActionExecutionDispatchData, GatewayChannelPinsUpdateDispatchData, GatewayDispatchEvents, GatewayDispatchPayload, GatewayGuildDeleteDispatchData, GatewayGuildIntegrationsUpdateDispatchData, GatewayGuildMemberRemoveDispatchData, GatewayGuildMembersChunkDispatchData, GatewayGuildRoleDeleteDispatchData, GatewayGuildScheduledEventUserAddDispatchData, GatewayGuildScheduledEventUserRemoveDispatchData, GatewayGuildSoundboardSoundDeleteDispatchData, GatewayIntegrationDeleteDispatchData, GatewayIntentBits, GatewayInviteCreateDispatchData, GatewayInviteDeleteDispatchData, GatewayMessageDeleteBulkDispatchData, GatewayMessageDeleteDispatchData, GatewayMessageReactionRemoveAllDispatchData, GatewayPresenceClientStatus, GatewayPresenceUpdateData, GatewayRateLimitedDispatchData, GatewayReadyDispatchData, GatewayThreadDeleteDispatchData, GatewayThreadListSync, GatewayThreadMembersUpdateDispatchData, GatewayTypingStartDispatchData, GatewayVoiceServerUpdateDispatchData, GatewayWebhooksUpdateDispatchData, GuildDefaultMessageNotifications, GuildExplicitContentFilter, GuildMemberFlags, GuildOnboardingMode, GuildOnboardingPromptType, GuildPremiumTier, GuildScheduledEventEntityType, GuildScheduledEventPrivacyLevel, GuildScheduledEventStatus, GuildSystemChannelFlags, GuildVerificationLevel, GuildWidgetStyle, InviteTargetType, InviteType, Locale, MessageFlags, MessageType, OverwriteType, PermissionFlagsBits, PresenceUpdateReceiveStatus, PresenceUpdateStatus, RESTGetAPIGuildVanityUrlResult, RESTPatchAPIChannelJSONBody, RESTPatchAPIChannelMessageJSONBody, RESTPatchAPIGuildJSONBody, RESTPatchAPIWebhookWithTokenMessageJSONBody, RESTPostAPIChannelMessageJSONBody, RESTPostAPIGuildsJSONBody, RESTPostAPIWebhookWithTokenJSONBody, ReactionType, RoleFlags, Snowflake, SortOrderType, StageInstancePrivacyLevel, StickerFormatType, ThreadAutoArchiveDuration, ThreadChannelType, UserFlags, VideoQualityMode, WebhookType } from "discord-api-types/v10";
6
6
  import { BaseImageURLOptions, EmojiURLOptions, ImageURLOptions, RawFile } from "@discordjs/rest";
7
7
  //#region src/structures/Structure.d.ts
8
8
  /*!
@@ -647,6 +647,9 @@ export interface AddOptions {
647
647
  * The cache only ever holds raw API data, building structures is always the manager's job. Without a cache, `get`
648
648
  * always resolves to `undefined` and `fetch` always hits the API.
649
649
  *
650
+ * Every method is asynchronous since the cache can be Redis, except {@link CachedManager.cached}, which reads a
651
+ * synchronous cache (`createInMemoryCache`) without awaiting it.
652
+ *
650
653
  * Like discord.js's `CachedManager`, every payload coming from the API goes through {@link CachedManager._add}, which
651
654
  * patches the cached entry and builds the structure. Structures are built by {@link CachedManager.hydrate}, which
652
655
  * resolves their relations (a message's author, a member's user, ...) from the cache, so they carry the latest known
@@ -677,6 +680,36 @@ export declare abstract class CachedManager<Name extends CacheEntityName, Value
677
680
  * @returns The entity, or `undefined` if it is not cached.
678
681
  */
679
682
  get(...args: Args): Promise<Value | undefined>;
683
+ /**
684
+ * Gets an entity from a synchronous cache, without awaiting it: the synchronous counterpart of
685
+ * {@link CachedManager.get}, for hot paths such as message filters.
686
+ *
687
+ * @remarks
688
+ * It builds the same structure as `get`, relations included, so the entity caches they are read from must be
689
+ * synchronous too, which they all are with `createInMemoryCache`. `manager.cache?.synchronous` tells whether it can
690
+ * be called.
691
+ *
692
+ * An asynchronous cache throws rather than returning `undefined`: it cannot tell whether the entity is cached, and
693
+ * reporting a miss would silently skip whatever the caller does with cached entities, e.g. a filter.
694
+ *
695
+ * @example
696
+ * ```typescript
697
+ * const member = client.members.cached(guildId, userId);
698
+ * ```
699
+ *
700
+ * @param args The arguments identifying the entity.
701
+ * @returns The entity, or `undefined` if it is not cached or the client has no cache.
702
+ * @throws {TypeError} When the entity cache, or one of the caches its relations are read from, is asynchronous.
703
+ */
704
+ cached(...args: Args): Value | undefined;
705
+ /**
706
+ * Gets an entity from the cache, synchronously when every cache it reads is: the {@link Awaitable} counterpart of
707
+ * {@link CachedManager.get}, which both `get` and {@link CachedManager.cached} rely on.
708
+ *
709
+ * @param args The arguments identifying the entity.
710
+ * @internal
711
+ */
712
+ _get(...args: Args): Awaitable<Value | undefined>;
680
713
  /**
681
714
  * Resolves a structure or a cache key to a structure, like discord.js's `DataManager#resolve`.
682
715
  *
@@ -710,12 +743,19 @@ export declare abstract class CachedManager<Name extends CacheEntityName, Value
710
743
  */
711
744
  resolveData(data: CacheEntityTypes[Name]): Promise<Value>;
712
745
  /**
713
- * Gets a guild from the cache, to resolve the `guild` of a structure.
746
+ * The {@link Awaitable} counterpart of {@link CachedManager.resolveData}, synchronous when every cache it reads is.
747
+ *
748
+ * @param data The raw data.
749
+ * @internal
750
+ */
751
+ _resolveData(data: CacheEntityTypes[Name]): Awaitable<Value>;
752
+ /**
753
+ * Gets a guild from the cache, to resolve the `guild` of a structure. Synchronous when the guild cache is.
714
754
  *
715
755
  * @param guildId The ID of the guild, if the structure belongs to one.
716
756
  * @returns The guild, or `null` when there is no ID or the guild is not cached.
717
757
  */
718
- protected cachedGuild(guildId: string | null | undefined): Promise<Guild | null>;
758
+ protected cachedGuild(guildId: string | null | undefined): Awaitable<Guild | null>;
719
759
  /**
720
760
  * Builds the structure of raw data, resolving its relations from the cache. Without relations to resolve, the same
721
761
  * as {@link CachedManager.createStructure}.
@@ -723,6 +763,15 @@ export declare abstract class CachedManager<Name extends CacheEntityName, Value
723
763
  * @param data The raw data.
724
764
  */
725
765
  hydrate(data: CacheEntityTypes[Name]): Promise<Value>;
766
+ /**
767
+ * The {@link Awaitable} counterpart of {@link CachedManager.hydrate}, synchronous when every cache the relations
768
+ * are read from is. Managers resolving relations override this one, so `hydrate` and
769
+ * {@link CachedManager.cached} build the same structures.
770
+ *
771
+ * @param data The raw data.
772
+ * @internal
773
+ */
774
+ _hydrate(data: CacheEntityTypes[Name]): Awaitable<Value>;
726
775
  /**
727
776
  * Gets an entity from the cache, fetching it from the API (and caching it) on a cache miss.
728
777
  *
@@ -774,11 +823,11 @@ export declare abstract class CachedManager<Name extends CacheEntityName, Value
774
823
  */
775
824
  protected storeRaw(key: string, raw: CacheEntityTypes[Name]): Promise<void>;
776
825
  /**
777
- * Gets an entity from the cache by its key.
826
+ * Gets an entity from the cache by its key, synchronously when every cache it reads is.
778
827
  *
779
828
  * @param key The cache key of the entity.
780
829
  */
781
- protected getByKey(key: string): Promise<Value | undefined>;
830
+ protected getByKey(key: string): Awaitable<Value | undefined>;
782
831
  }
783
832
  //#endregion
784
833
  //#region src/managers/AutoModerationRuleManager.d.ts
@@ -816,7 +865,7 @@ export declare class AutoModerationRuleManager extends CachedManager<"autoModera
816
865
  createStructure(data: CacheEntityTypes["autoModerationRules"]): AutoModerationRule;
817
866
  keyOf(data: CacheEntityTypes["autoModerationRules"]): string;
818
867
  resolveKey(ruleId: string): string;
819
- hydrate(data: CacheEntityTypes["autoModerationRules"]): Promise<AutoModerationRule>;
868
+ _hydrate(data: CacheEntityTypes["autoModerationRules"]): Awaitable<AutoModerationRule>;
820
869
  /**
821
870
  * Fetches every rule of the guild, and caches them.
822
871
  */
@@ -1265,10 +1314,53 @@ export interface GuildPruneOptions {
1265
1314
  count?: boolean;
1266
1315
  reason?: string;
1267
1316
  }
1317
+ /**
1318
+ * The options to request the members of a guild over the gateway with. Without `query` nor `userIds`, every member is
1319
+ * requested.
1320
+ */
1321
+ export interface GuildMembersRequestOptions {
1322
+ /**
1323
+ * The prefix of the usernames and nicknames to match, `""` for every member. Exclusive with `userIds`.
1324
+ *
1325
+ * @default ""
1326
+ */
1327
+ query?: string;
1328
+ /**
1329
+ * How many members to match with `query`, `0` for no limit (only with an empty `query`).
1330
+ *
1331
+ * @default 0
1332
+ */
1333
+ limit?: number;
1334
+ /**
1335
+ * The IDs of the users to request, up to 100. Exclusive with `query`. The ones that are not members are left out of
1336
+ * the result, and listed in the `not_found` of the `guildMembersChunk` data. An empty array is ignored, like omitting
1337
+ * it.
1338
+ */
1339
+ userIds?: readonly string[];
1340
+ /**
1341
+ * Whether to also receive (and cache) the members' presences. Needs the `GuildPresences` intent.
1342
+ *
1343
+ * @default false
1344
+ */
1345
+ presences?: boolean;
1346
+ /**
1347
+ * The nonce identifying the request's chunks, up to 32 bytes.
1348
+ *
1349
+ * @default A random one.
1350
+ */
1351
+ nonce?: string;
1352
+ /**
1353
+ * How long to wait for each chunk, in milliseconds, before rejecting with a `GuildMembersTimeoutError`.
1354
+ *
1355
+ * @default 120_000
1356
+ */
1357
+ time?: number;
1358
+ }
1268
1359
  /**
1269
1360
  * Manages the {@link GuildMember}s known to the client.
1270
1361
  */
1271
1362
  export declare class GuildMemberManager extends CachedManager<"members", GuildMember, [guildId: string, userId: string]> {
1363
+ #private;
1272
1364
  constructor(client: GatewayClient);
1273
1365
  createStructure(data: CacheEntityTypes["members"]): GuildMember;
1274
1366
  keyOf(data: CacheEntityTypes["members"]): string;
@@ -1278,7 +1370,7 @@ export declare class GuildMemberManager extends CachedManager<"members", GuildMe
1278
1370
  * @internal
1279
1371
  */
1280
1372
  _add(data: CacheEntityTypes["members"], cache?: boolean, options?: AddOptions): Promise<GuildMember>;
1281
- hydrate(data: CacheEntityTypes["members"]): Promise<GuildMember>;
1373
+ _hydrate(data: CacheEntityTypes["members"]): Awaitable<GuildMember>;
1282
1374
  resolveKey(guildId: string, userId: string): string;
1283
1375
  /**
1284
1376
  * Fetches the bot's own member in a guild.
@@ -1306,6 +1398,32 @@ export declare class GuildMemberManager extends CachedManager<"members", GuildMe
1306
1398
  query: string;
1307
1399
  limit?: number;
1308
1400
  }): Promise<GuildMember[]>;
1401
+ /**
1402
+ * Requests the members of a guild over the gateway, every one of them by default, and caches them. discord.js:
1403
+ * `guild.members.fetch()` without a user.
1404
+ *
1405
+ * @remarks
1406
+ * Unlike {@link GuildMemberManager.list}, it gets the members of a large guild in one go, in chunks of up to 1000
1407
+ * that are also emitted as `guildMembersChunk`. Requesting every member or a `query` needs the `GuildMembers`
1408
+ * intent. The request is sent on the guild's shard, which must be one this client runs.
1409
+ *
1410
+ * @param guildId The ID of the guild.
1411
+ * @param options Which members to request.
1412
+ * @returns The members, once the last chunk is cached.
1413
+ */
1414
+ request(guildId: string, options?: GuildMembersRequestOptions): Promise<GuildMember[]>;
1415
+ /**
1416
+ * Adds a cached chunk of members to the request with its nonce, resolving it with the last chunk.
1417
+ *
1418
+ * @internal
1419
+ */
1420
+ handleChunk(members: GuildMember[], data: GatewayGuildMembersChunkDispatchData): void;
1421
+ /**
1422
+ * Rejects the request a `RATE_LIMITED` dispatch refers to, which gets no chunks at all.
1423
+ *
1424
+ * @internal
1425
+ */
1426
+ handleRateLimited(data: GatewayRateLimitedDispatchData): void;
1309
1427
  /**
1310
1428
  * Adds a user to a guild, or fetches their member when they are in it already.
1311
1429
  *
@@ -1409,6 +1527,7 @@ export declare class GuildMemberManager extends CachedManager<"members", GuildMe
1409
1527
  guild_id: string;
1410
1528
  }>;
1411
1529
  private store;
1530
+ private settle;
1412
1531
  private updateCachedRoles;
1413
1532
  }
1414
1533
  //#endregion
@@ -1452,7 +1571,7 @@ export declare class RoleManager extends CachedManager<"roles", Role, [guildId:
1452
1571
  constructor(client: GatewayClient);
1453
1572
  createStructure(data: CacheEntityTypes["roles"]): Role;
1454
1573
  keyOf(data: CacheEntityTypes["roles"]): string;
1455
- hydrate(data: CacheEntityTypes["roles"]): Promise<Role>;
1574
+ _hydrate(data: CacheEntityTypes["roles"]): Awaitable<Role>;
1456
1575
  resolveKey(guildId: string, roleId: string): string;
1457
1576
  /**
1458
1577
  * Fetches every role of a guild from the API, and caches them.
@@ -2410,7 +2529,7 @@ export declare class ThreadMemberManager extends CachedManager<"threadMembers",
2410
2529
  * @internal
2411
2530
  */
2412
2531
  _add(data: CacheEntityTypes["threadMembers"], cache?: boolean, options?: AddOptions): Promise<ThreadMember>;
2413
- hydrate(data: CacheEntityTypes["threadMembers"]): Promise<ThreadMember>;
2532
+ _hydrate(data: CacheEntityTypes["threadMembers"]): Awaitable<ThreadMember>;
2414
2533
  /**
2415
2534
  * Fetches a member of a thread from the API, bypassing the cache, and caches it.
2416
2535
  *
@@ -2639,7 +2758,7 @@ export declare class ThreadManager extends CachedManager<"threads", AnyThreadCha
2639
2758
  constructor(client: GatewayClient);
2640
2759
  createStructure(data: CacheEntityTypes["threads"]): AnyThreadChannel;
2641
2760
  keyOf(data: CacheEntityTypes["threads"]): string;
2642
- hydrate(data: CacheEntityTypes["threads"]): Promise<AnyThreadChannel>;
2761
+ _hydrate(data: CacheEntityTypes["threads"]): Awaitable<AnyThreadChannel>;
2643
2762
  resolveKey(threadId: string): string;
2644
2763
  /**
2645
2764
  * Creates a thread in a channel. With `message`, creates a post of a forum or media channel.
@@ -2711,7 +2830,7 @@ export declare class MessageManager extends CachedManager<"messages", Message, [
2711
2830
  * @internal
2712
2831
  */
2713
2832
  _add(data: CacheEntityTypes["messages"], cache?: boolean, options?: AddOptions): Promise<Message>;
2714
- hydrate(data: CacheEntityTypes["messages"]): Promise<Message>;
2833
+ _hydrate(data: CacheEntityTypes["messages"]): Awaitable<Message>;
2715
2834
  resolveKey(channelId: string, messageId: string): string;
2716
2835
  /**
2717
2836
  * Lists the messages of a channel, newest first, and caches them.
@@ -3745,7 +3864,7 @@ export declare class GuildBanManager extends CachedManager<"bans", GuildBan, [us
3745
3864
  * @internal
3746
3865
  */
3747
3866
  _add(data: CacheEntityTypes["bans"], cache?: boolean, options?: AddOptions): Promise<GuildBan>;
3748
- hydrate(data: CacheEntityTypes["bans"]): Promise<GuildBan>;
3867
+ _hydrate(data: CacheEntityTypes["bans"]): Awaitable<GuildBan>;
3749
3868
  /**
3750
3869
  * Lists the bans of the guild, paginated by user ID, and caches them.
3751
3870
  *
@@ -3942,7 +4061,7 @@ export declare class GuildScheduledEventManager extends CachedManager<"scheduled
3942
4061
  * @internal
3943
4062
  */
3944
4063
  _add(data: CacheEntityTypes["scheduledEvents"], cache?: boolean, options?: AddOptions): Promise<GuildScheduledEvent>;
3945
- hydrate(data: CacheEntityTypes["scheduledEvents"]): Promise<GuildScheduledEvent>;
4064
+ _hydrate(data: CacheEntityTypes["scheduledEvents"]): Awaitable<GuildScheduledEvent>;
3946
4065
  /**
3947
4066
  * Fetches every scheduled event of the guild, and caches them.
3948
4067
  *
@@ -4076,7 +4195,7 @@ export declare class GuildSoundboardSoundManager extends CachedManager<"soundboa
4076
4195
  * @internal
4077
4196
  */
4078
4197
  _add(data: CacheEntityTypes["soundboardSounds"], cache?: boolean, options?: AddOptions): Promise<SoundboardSound>;
4079
- hydrate(data: CacheEntityTypes["soundboardSounds"]): Promise<SoundboardSound>;
4198
+ _hydrate(data: CacheEntityTypes["soundboardSounds"]): Awaitable<SoundboardSound>;
4080
4199
  /**
4081
4200
  * Fetches every soundboard sound of the guild, and caches them.
4082
4201
  */
@@ -4185,7 +4304,7 @@ export declare class StageInstanceManager extends CachedManager<"stageInstances"
4185
4304
  createStructure(data: CacheEntityTypes["stageInstances"]): StageInstance;
4186
4305
  keyOf(data: CacheEntityTypes["stageInstances"]): string;
4187
4306
  resolveKey(channelId: string): string;
4188
- hydrate(data: CacheEntityTypes["stageInstances"]): Promise<StageInstance>;
4307
+ _hydrate(data: CacheEntityTypes["stageInstances"]): Awaitable<StageInstance>;
4189
4308
  /**
4190
4309
  * Starts a stage in a stage channel.
4191
4310
  *
@@ -4416,7 +4535,7 @@ export declare class GuildEmojiManager extends CachedManager<"emojis", GuildEmoj
4416
4535
  * @internal
4417
4536
  */
4418
4537
  _add(data: CacheEntityTypes["emojis"], cache?: boolean, options?: AddOptions): Promise<GuildEmoji>;
4419
- hydrate(data: CacheEntityTypes["emojis"]): Promise<GuildEmoji>;
4538
+ _hydrate(data: CacheEntityTypes["emojis"]): Awaitable<GuildEmoji>;
4420
4539
  resolveKey(emojiId: string): string;
4421
4540
  /**
4422
4541
  * Fetches every emoji of the guild, and caches them.
@@ -4557,7 +4676,7 @@ export declare class GuildIntegrationManager extends CachedManager<"integrations
4557
4676
  * @internal
4558
4677
  */
4559
4678
  _add(data: CacheEntityTypes["integrations"], cache?: boolean, options?: AddOptions): Promise<Integration>;
4560
- hydrate(data: CacheEntityTypes["integrations"]): Promise<Integration>;
4679
+ _hydrate(data: CacheEntityTypes["integrations"]): Awaitable<Integration>;
4561
4680
  /**
4562
4681
  * Fetches every integration of the guild, and caches them.
4563
4682
  */
@@ -4733,7 +4852,7 @@ export declare class GuildInviteManager extends CachedManager<"invites", GuildIn
4733
4852
  * @internal
4734
4853
  */
4735
4854
  _add(data: CacheEntityTypes["invites"], cache?: boolean, options?: AddOptions): Promise<GuildInvite>;
4736
- hydrate(data: CacheEntityTypes["invites"]): Promise<GuildInvite>;
4855
+ _hydrate(data: CacheEntityTypes["invites"]): Awaitable<GuildInvite>;
4737
4856
  resolveKey(code: string): string;
4738
4857
  /**
4739
4858
  * Fetches every invite of the guild, with their metadata, and caches them.
@@ -4929,7 +5048,7 @@ export declare class GuildStickerManager extends CachedManager<"stickers", Stick
4929
5048
  * @internal
4930
5049
  */
4931
5050
  _add(data: CacheEntityTypes["stickers"], cache?: boolean, options?: AddOptions): Promise<Sticker>;
4932
- hydrate(data: CacheEntityTypes["stickers"]): Promise<Sticker>;
5051
+ _hydrate(data: CacheEntityTypes["stickers"]): Awaitable<Sticker>;
4933
5052
  resolveKey(stickerId: string): string;
4934
5053
  /**
4935
5054
  * Fetches every sticker of the guild, and caches them.
@@ -5751,6 +5870,13 @@ export declare class Guild extends AnonymousGuild<CacheEntityTypes["guilds"]> {
5751
5870
  * Fetches the member owning this guild.
5752
5871
  */
5753
5872
  fetchOwner(): Promise<GuildMember>;
5873
+ /**
5874
+ * Requests the members of this guild over the gateway, every one of them by default, and caches them. discord.js:
5875
+ * `guild.members.fetch()`. See `client.members.request`.
5876
+ *
5877
+ * @param options Which members to request.
5878
+ */
5879
+ requestMembers(options?: GuildMembersRequestOptions): Promise<GuildMember[]>;
5754
5880
  /**
5755
5881
  * Fetches every invite of this guild.
5756
5882
  */
@@ -6195,7 +6321,7 @@ export declare class VoiceStateManager extends CachedManager<"voiceStates", Voic
6195
6321
  createStructure(data: CacheEntityTypes["voiceStates"]): VoiceState;
6196
6322
  keyOf(data: CacheEntityTypes["voiceStates"]): string;
6197
6323
  resolveKey(guildId: string, userId: string): string;
6198
- hydrate(data: CacheEntityTypes["voiceStates"]): Promise<VoiceState>;
6324
+ _hydrate(data: CacheEntityTypes["voiceStates"]): Awaitable<VoiceState>;
6199
6325
  /**
6200
6326
  * Lists the cached voice states of a guild.
6201
6327
  *
@@ -6232,7 +6358,7 @@ export declare class PresenceManager extends CachedManager<"presences", Presence
6232
6358
  createStructure(data: CacheEntityTypes["presences"]): Presence;
6233
6359
  keyOf(data: CacheEntityTypes["presences"]): string;
6234
6360
  resolveKey(guildId: string, userId: string): string;
6235
- hydrate(data: CacheEntityTypes["presences"]): Promise<Presence>;
6361
+ _hydrate(data: CacheEntityTypes["presences"]): Awaitable<Presence>;
6236
6362
  /**
6237
6363
  * Lists the cached presences of a guild.
6238
6364
  *
@@ -7139,7 +7265,7 @@ export declare class ChannelManager extends CachedManager<"channels", AnyChannel
7139
7265
  constructor(client: GatewayClient);
7140
7266
  createStructure(data: CacheEntityTypes["channels"]): AnyChannel;
7141
7267
  keyOf(data: CacheEntityTypes["channels"]): string;
7142
- hydrate(data: CacheEntityTypes["channels"]): Promise<AnyChannel>;
7268
+ _hydrate(data: CacheEntityTypes["channels"]): Awaitable<AnyChannel>;
7143
7269
  resolveKey(channelId: string): string;
7144
7270
  /**
7145
7271
  * Adds a channel to the cache, handing threads to `client.threads`, whose cache holds them.
@@ -7148,11 +7274,12 @@ export declare class ChannelManager extends CachedManager<"channels", AnyChannel
7148
7274
  */
7149
7275
  _add(data: CacheEntityTypes["channels"], cache?: boolean, options?: AddOptions): Promise<AnyChannel>;
7150
7276
  /**
7151
- * Gets a channel from the cache, looking it up in the thread cache as well.
7277
+ * Gets a channel from the cache, looking it up in the thread cache as well, which `get` and `cached` rely on.
7152
7278
  *
7153
7279
  * @param channelId The ID of the channel.
7280
+ * @internal
7154
7281
  */
7155
- get(channelId: string): Promise<AnyChannel | undefined>;
7282
+ _get(channelId: string): Awaitable<AnyChannel | undefined>;
7156
7283
  /**
7157
7284
  * Writes a channel to the cache, threads to the thread cache.
7158
7285
  *
@@ -7369,6 +7496,11 @@ interface GatewayEventMap {
7369
7496
  guildMemberAdd: [member: GuildMember];
7370
7497
  guildMemberUpdate: [oldMember: GuildMember | null, newMember: GuildMember];
7371
7498
  guildMemberRemove: [member: GuildMember | null, data: GatewayGuildMemberRemoveDispatchData];
7499
+ /**
7500
+ * Emitted for each chunk of members Discord sends in answer to `client.members.request`, once it is cached.
7501
+ * `data` has the chunk's index and count, its nonce, and the requested IDs that are not members (`not_found`).
7502
+ */
7503
+ guildMembersChunk: [members: GuildMember[], guild: Guild | null, data: GatewayGuildMembersChunkDispatchData];
7372
7504
  guildRoleCreate: [role: Role];
7373
7505
  guildRoleUpdate: [oldRole: Role | null, newRole: Role];
7374
7506
  guildRoleDelete: [role: Role | null, data: GatewayGuildRoleDeleteDispatchData];
@@ -7561,6 +7693,22 @@ type RawAPIType<Value extends Structure<object>> = Value extends Structure<infer
7561
7693
  * A function building a {@link Structure} out of its raw API data.
7562
7694
  */
7563
7695
  type StructureCreator<Value extends Structure<object>, Raw extends RawAPIType<Value> = RawAPIType<Value>> = (data: Raw) => Value;
7696
+ /**
7697
+ * Whether an {@link Awaitable} is a promise, rather than the value itself.
7698
+ *
7699
+ * @internal
7700
+ */
7701
+ declare function isPromiseLike<T>(value: Awaitable<T>): value is Promise<T>;
7702
+ /**
7703
+ * Waits for a list of {@link Awaitable}s like `Promise.all`, then calls a function with their values. Unlike
7704
+ * `Promise.all`, it stays synchronous when none of them is a promise, which is what lets a synchronous cache build
7705
+ * structures without awaiting them.
7706
+ *
7707
+ * @param values The values, some of which may be promises.
7708
+ * @param callback The function to call with the values.
7709
+ * @internal
7710
+ */
7711
+ declare function whenAll<const T extends readonly unknown[], R>(values: T, callback: (values: { -readonly [Index in keyof T]: Awaited<T[Index]>; }) => Awaitable<R>): Awaitable<R>;
7564
7712
  //#endregion
7565
7713
  //#region src/util/container.d.ts
7566
7714
  /**
@@ -7646,6 +7794,45 @@ export declare class DispatchTimeoutError extends Error {
7646
7794
  readonly timeout: number;
7647
7795
  constructor(type: string, shardId: number, partition: string | null, timeout: number);
7648
7796
  }
7797
+ /**
7798
+ * Thrown by `GuildMemberManager#request` when Discord stops sending the chunks of the requested members.
7799
+ *
7800
+ * @remarks
7801
+ * The request is dropped: chunks arriving later still update the cache and emit `guildMembersChunk`.
7802
+ */
7803
+ export declare class GuildMembersTimeoutError extends Error {
7804
+ /**
7805
+ * The ID of the guild whose members were requested.
7806
+ */
7807
+ readonly guildId: string;
7808
+ /**
7809
+ * The nonce of the request.
7810
+ */
7811
+ readonly nonce: string;
7812
+ /**
7813
+ * The timeout that was exceeded, in milliseconds.
7814
+ */
7815
+ readonly timeout: number;
7816
+ constructor(guildId: string, nonce: string, timeout: number);
7817
+ }
7818
+ /**
7819
+ * Thrown by `GuildMemberManager#request` when Discord answers with `RATE_LIMITED` instead of the members' chunks.
7820
+ */
7821
+ export declare class GuildMembersRateLimitError extends Error {
7822
+ /**
7823
+ * The ID of the guild whose members were requested.
7824
+ */
7825
+ readonly guildId: string;
7826
+ /**
7827
+ * The nonce of the request.
7828
+ */
7829
+ readonly nonce: string;
7830
+ /**
7831
+ * How long to wait before requesting the members again, in milliseconds.
7832
+ */
7833
+ readonly retryAfter: number;
7834
+ constructor(guildId: string, nonce: string, retryAfter: number);
7835
+ }
7649
7836
  //#endregion
7650
7837
  //#region src/util/permissions.d.ts
7651
7838
  /**
@@ -7717,5 +7904,5 @@ export declare function computeTargetPermissions(guildId: Snowflake, overwrites:
7717
7904
  */
7718
7905
  export declare function computePermissionsIn(channel: AnyChannel | Snowflake, target: GuildMember | Role | Snowflake): Promise<PermissionsBitField>;
7719
7906
  //#endregion
7720
- export type { GatewayEventMap, GatewayEventName, MessageReactionEventDetails, RawAPIType, StructureCreator };
7907
+ export type { GatewayEventMap, GatewayEventName, MessageReactionEventDetails, RawAPIType, StructureCreator, isPromiseLike, whenAll };
7721
7908
  //# sourceMappingURL=index.d.ts.map