lunibee 0.2.3 → 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 (61) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +225 -225
  3. package/dist/builders/attachment.d.ts +8 -0
  4. package/dist/builders/commands.d.ts +122 -65
  5. package/dist/builders/components.d.ts +10 -31
  6. package/dist/builders/embed.d.ts +66 -33
  7. package/dist/builders/index.js +97 -131
  8. package/dist/builders/index.js.map +8 -8
  9. package/dist/collection/cache.d.ts +13 -6
  10. package/dist/collection/index.d.ts +90 -17
  11. package/dist/collection/index.js +442 -266
  12. package/dist/collection/index.js.map +4 -4
  13. package/dist/core/index.d.ts +8 -0
  14. package/dist/core/index.js +607 -352
  15. package/dist/core/index.js.map +47 -47
  16. package/dist/core/permissions.d.ts +7 -3
  17. package/dist/formatters/index.js +9 -5
  18. package/dist/formatters/index.js.map +3 -3
  19. package/dist/handlers/index.js +5 -10
  20. package/dist/handlers/index.js.map +3 -3
  21. package/dist/index.js +769 -587
  22. package/dist/index.js.map +65 -65
  23. package/dist/managers/base.d.ts +22 -14
  24. package/dist/managers/index.d.ts +2 -1
  25. package/dist/managers/index.js +445 -276
  26. package/dist/managers/index.js.map +26 -26
  27. package/dist/managers/message.d.ts +7 -3
  28. package/dist/rest/errors.d.ts +14 -7
  29. package/dist/rest/index.d.ts +24 -12
  30. package/dist/rest/index.js +54 -17
  31. package/dist/rest/index.js.map +14 -14
  32. package/dist/rest/redis.d.ts +1 -1
  33. package/dist/rest/route.d.ts +8 -4
  34. package/dist/rest/routes.d.ts +102 -48
  35. package/dist/rest/transport.d.ts +10 -5
  36. package/dist/rest/webhook.d.ts +9 -5
  37. package/dist/sharding/bus.d.ts +34 -17
  38. package/dist/sharding/index.d.ts +34 -17
  39. package/dist/sharding/index.js +64 -32
  40. package/dist/sharding/index.js.map +17 -17
  41. package/dist/structures/base.d.ts +19 -10
  42. package/dist/structures/channels.d.ts +28 -14
  43. package/dist/structures/index.js +9 -59
  44. package/dist/structures/index.js.map +19 -18
  45. package/dist/structures/interactions.d.ts +96 -48
  46. package/dist/structures/resources.d.ts +88 -44
  47. package/dist/types/gateway.d.ts +1 -1
  48. package/dist/types/index.js +20 -22
  49. package/dist/types/index.js.map +4 -4
  50. package/dist/utils/index.js.map +2 -2
  51. package/dist/voice/index.d.ts +12 -4
  52. package/dist/voice/index.js +14 -18
  53. package/dist/voice/index.js.map +3 -3
  54. package/dist/ws/decoder.d.ts +6 -2
  55. package/dist/ws/index.d.ts +25 -13
  56. package/dist/ws/index.js +63 -31
  57. package/dist/ws/index.js.map +14 -14
  58. package/dist/ws/protocol.d.ts +10 -2
  59. package/dist/ws/session.d.ts +14 -4
  60. package/dist/ws/state.d.ts +22 -11
  61. package/package.json +15 -14
@@ -6,7 +6,7 @@ import { type RateLimitStore, type BucketState, type Reservation } from "./store
6
6
  export interface MinimalRedisClient {
7
7
  get(key: string): Promise<string | null>;
8
8
  mget(keys: string[]): Promise<Array<string | null>>;
9
- set(key: string, value: string | number, mode?: string, duration?: number): Promise<any>;
9
+ set(key: string, value: string | number, mode?: string, duration?: number): Promise<string | null>;
10
10
  del(...keys: string[]): Promise<number>;
11
11
  /**
12
12
  * Optional Lua evaluation (ioredis/node-redis compatible). When present,
@@ -9,10 +9,14 @@ export type RESTQuery = URLSearchParams | Record<string, string | number | boole
9
9
  * make two channels share one counter.
10
10
  */
11
11
  export interface RouteKey {
12
- /** Uppercased HTTP method. */ method: string;
13
- /** Raw request path, without query string. */ path: string;
14
- /** Normalized `METHOD:/path/:id` route used for bucket-hash lookup. */ route: string;
15
- /** Major parameter scoping the limit (channel, guild, webhook id[:token]). */ major: string;
12
+ /** Uppercased HTTP method. */
13
+ method: string;
14
+ /** Raw request path, without query string. */
15
+ path: string;
16
+ /** Normalized `METHOD:/path/:id` route used for bucket-hash lookup. */
17
+ route: string;
18
+ /** Major parameter scoping the limit (channel, guild, webhook id[:token]). */
19
+ major: string;
16
20
  }
17
21
  /** Normalizes Discord routes for stable bucket discovery. */
18
22
  export declare function normalizeRoutePath(path: string): string;
@@ -1,53 +1,107 @@
1
1
  /** Discord REST API route definitions. */
2
2
  export declare const Routes: {
3
- /** Returns the current bot user. @returns User route. */ readonly user: () => string;
4
- /** Returns one user. @param userId User identifier. @returns User route. */ readonly userById: (userId: string) => string;
5
- /** Returns a guild. @param guildId Guild identifier. @returns Guild route. */ readonly guild: (guildId: string) => string;
6
- /** Returns a guild preview. @param guildId Guild identifier. */ readonly guildPreview: (guildId: string) => string;
7
- /** Returns active threads for a guild. @param guildId Guild identifier. */ readonly guildActiveThreads: (guildId: string) => string;
8
- /** Returns webhooks for a guild. @param guildId Guild identifier. */ readonly guildWebhooks: (guildId: string) => string;
9
- /** Returns invites for a guild. @param guildId Guild identifier. */ readonly guildInvites: (guildId: string) => string;
10
- /** Returns channels in a guild. @param guildId Guild identifier. @returns Channel collection route. */ readonly guildChannels: (guildId: string) => string;
11
- /** Returns a guild member. @param guildId Guild identifier. @param userId User identifier. @returns Guild-member route. */ readonly guildMember: (guildId: string, userId: string) => string;
12
- /** Returns all guild roles. @param guildId Guild identifier. @returns Guild-role route. */ readonly guildRoles: (guildId: string) => string;
13
- /** Returns an individual guild role. */ readonly guildRole: (guildId: string, roleId: string) => string;
14
- /** Returns a member role route. */ readonly guildMemberRole: (guildId: string, userId: string, roleId: string) => string;
15
- /** Returns guild bans collection. */ readonly guildBans: (guildId: string) => string;
16
- /** Returns an individual guild ban. */ readonly guildBan: (guildId: string, userId: string) => string;
17
- /** Returns a channel. @param channelId Channel identifier. @returns Channel route. */ readonly channel: (channelId: string) => string;
18
- /** Returns messages in a channel. @param channelId Channel identifier. @returns Message collection route. */ readonly channelMessages: (channelId: string) => string;
19
- /** Returns a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Message route. */ readonly message: (channelId: string, messageId: string) => string;
20
- /** Crossposts a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Crosspost route. */ readonly crosspostMessage: (channelId: string, messageId: string) => string;
21
- /** Returns reactions for a message and emoji. @param channelId Channel identifier. @param messageId Message identifier. @param emoji Emoji name or ID. @returns Reaction route. */ readonly messageReactions: (channelId: string, messageId: string, emoji: string) => string;
22
- /** Removes all reactions from a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Reaction collection route. */ readonly messageReactionsAll: (channelId: string, messageId: string) => string;
23
- /** Returns pinned messages, newest first, in pages of up to 50 (`before`, `limit`). @param channelId Channel identifier. @returns Pins route. */ readonly channelMessagesPins: (channelId: string) => string;
24
- /** Pins (PUT) or unpins (DELETE) a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Pin route. */ readonly channelMessagesPin: (channelId: string, messageId: string) => string;
25
- /** @deprecated Discord deprecated this endpoint. Use {@link Routes.channelMessagesPins}, which returns `{ items, has_more }`. Removed in 0.3.0. */ readonly channelPins: (channelId: string) => string;
26
- /** @deprecated Discord deprecated this endpoint. Use {@link Routes.channelMessagesPin}. Removed in 0.3.0. */ readonly channelPin: (channelId: string, messageId: string) => string;
27
- /** Creates a thread from a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Message-thread route. */ readonly messageThread: (channelId: string, messageId: string) => string;
28
- /** Bulk deletes messages. @param channelId Channel identifier. @returns Bulk-delete route. */ readonly channelBulkDelete: (channelId: string) => string;
29
- /** Returns channel webhooks. @param channelId Channel identifier. @returns Webhook collection route. */ readonly channelWebhooks: (channelId: string) => string;
30
- /** Returns channel invites. @param channelId Channel identifier. @returns Invite collection route. */ readonly channelInvites: (channelId: string) => string;
31
- /** Returns a webhook. @param webhookId Webhook identifier. @param token Optional webhook token. @returns Webhook route. */ readonly webhook: (webhookId: string, token?: string) => string;
32
- /** Returns a webhook message. */ readonly webhookMessage: (webhookId: string, token: string, messageId: string) => string;
33
- /** Returns application commands for an application. @param applicationId Application identifier. @returns Global command route. */ readonly applicationCommands: (applicationId: string) => string;
34
- /** Returns one application command. @param applicationId Application identifier. @param commandId Command identifier. @returns Command route. */ readonly applicationCommand: (applicationId: string, commandId: string) => string;
35
- /** Returns guild application commands. @param applicationId Application identifier. @param guildId Guild identifier. @returns Guild command route. */ readonly guildApplicationCommands: (applicationId: string, guildId: string) => string;
36
- /** Returns a single guild application command. @param applicationId Application identifier. @param guildId Guild identifier. @param commandId Command identifier. @returns Guild command route. */ readonly guildApplicationCommand: (applicationId: string, guildId: string, commandId: string) => string;
37
- /** Returns an interaction callback endpoint. @param interactionId Interaction identifier. @param token Interaction token. @returns Interaction callback route. */ readonly interactionCallback: (interactionId: string, token: string) => string;
38
- /** Returns the original interaction response endpoint. @param applicationId Application identifier. @param token Interaction token. @returns Original-response route. */ readonly interactionOriginalResponse: (applicationId: string, token: string) => string;
39
- /** Returns public archived threads for a channel. @param channelId Channel identifier. @returns Public-archive route. */ readonly channelPublicArchivedThreads: (channelId: string) => string;
40
- /** Returns private archived threads for a channel. @param channelId Channel identifier. @returns Private-archive route. */ readonly channelPrivateArchivedThreads: (channelId: string) => string;
41
- /** Returns a thread's members. @param threadId Thread identifier. @returns Thread-member route. */ readonly threadMembers: (threadId: string) => string;
42
- /** Returns guild scheduled events. @param guildId Guild identifier. @returns Scheduled-event collection route. */ readonly guildScheduledEvents: (guildId: string) => string;
43
- /** Returns one guild scheduled event. @param guildId Guild identifier. @param eventId Event identifier. @returns Scheduled-event route. */ readonly guildScheduledEvent: (guildId: string, eventId: string) => string;
44
- /** Returns users subscribed to a scheduled event. @param guildId Guild identifier. @param eventId Event identifier. @returns Scheduled-event users route. */ readonly guildScheduledEventUsers: (guildId: string, eventId: string) => string;
45
- /** Returns a channel permission overwrite. @param channelId Channel identifier. @param overwriteId Role or user identifier. @returns Permission overwrite route. */ readonly channelPermission: (channelId: string, overwriteId: string) => string;
46
- /** Returns guild automod rules. @param guildId Guild identifier. @returns Automod-rule collection route. */ readonly guildAutoModerationRules: (guildId: string) => string;
47
- /** Returns one automod rule. @param guildId Guild identifier. @param ruleId Rule identifier. @returns Automod-rule route. */ readonly guildAutoModerationRule: (guildId: string, ruleId: string) => string;
48
- /** Returns current voice regions. @returns Voice-region route. */ readonly voiceRegions: () => string;
49
- /** Returns the generic Gateway endpoint. @returns Gateway route. */ readonly gateway: () => string;
50
- /** Returns the Gateway endpoint and recommended shard count for bots. @returns Gateway bot route. */ readonly gatewayBot: () => string;
3
+ /** Returns the current bot user. @returns User route. */
4
+ readonly user: () => string;
5
+ /** Returns one user. @param userId User identifier. @returns User route. */
6
+ readonly userById: (userId: string) => string;
7
+ /** Returns a guild. @param guildId Guild identifier. @returns Guild route. */
8
+ readonly guild: (guildId: string) => string;
9
+ /** Leaves a guild as the current user (DELETE). @param guildId Guild identifier. @returns Current-user guild route. */
10
+ readonly currentUserGuild: (guildId: string) => string;
11
+ /** Returns a sticker. @param stickerId Sticker identifier. @returns Sticker route. */
12
+ readonly sticker: (stickerId: string) => string;
13
+ /** Removes one user's reaction (DELETE). @param channelId Channel identifier. @param messageId Message identifier. @param emoji Emoji name or ID. @param userId User identifier. @returns Reaction-user route. */
14
+ readonly messageReactionUser: (channelId: string, messageId: string, emoji: string, userId: string) => string;
15
+ /** Returns a guild preview. @param guildId Guild identifier. */
16
+ readonly guildPreview: (guildId: string) => string;
17
+ /** Returns active threads for a guild. @param guildId Guild identifier. */
18
+ readonly guildActiveThreads: (guildId: string) => string;
19
+ /** Returns webhooks for a guild. @param guildId Guild identifier. */
20
+ readonly guildWebhooks: (guildId: string) => string;
21
+ /** Returns invites for a guild. @param guildId Guild identifier. */
22
+ readonly guildInvites: (guildId: string) => string;
23
+ /** Returns channels in a guild. @param guildId Guild identifier. @returns Channel collection route. */
24
+ readonly guildChannels: (guildId: string) => string;
25
+ /** Returns a guild member. @param guildId Guild identifier. @param userId User identifier. @returns Guild-member route. */
26
+ readonly guildMember: (guildId: string, userId: string) => string;
27
+ /** Returns all guild roles. @param guildId Guild identifier. @returns Guild-role route. */
28
+ readonly guildRoles: (guildId: string) => string;
29
+ /** Returns an individual guild role. */
30
+ readonly guildRole: (guildId: string, roleId: string) => string;
31
+ /** Returns a member role route. */
32
+ readonly guildMemberRole: (guildId: string, userId: string, roleId: string) => string;
33
+ /** Returns guild bans collection. */
34
+ readonly guildBans: (guildId: string) => string;
35
+ /** Returns an individual guild ban. */
36
+ readonly guildBan: (guildId: string, userId: string) => string;
37
+ /** Returns a channel. @param channelId Channel identifier. @returns Channel route. */
38
+ readonly channel: (channelId: string) => string;
39
+ /** Returns messages in a channel. @param channelId Channel identifier. @returns Message collection route. */
40
+ readonly channelMessages: (channelId: string) => string;
41
+ /** Returns a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Message route. */
42
+ readonly message: (channelId: string, messageId: string) => string;
43
+ /** Crossposts a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Crosspost route. */
44
+ readonly crosspostMessage: (channelId: string, messageId: string) => string;
45
+ /** Returns reactions for a message and emoji. @param channelId Channel identifier. @param messageId Message identifier. @param emoji Emoji name or ID. @returns Reaction route. */
46
+ readonly messageReactions: (channelId: string, messageId: string, emoji: string) => string;
47
+ /** Removes all reactions from a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Reaction collection route. */
48
+ readonly messageReactionsAll: (channelId: string, messageId: string) => string;
49
+ /** Returns pinned messages, newest first, in pages of up to 50 (`before`, `limit`). @param channelId Channel identifier. @returns Pins route. */
50
+ readonly channelMessagesPins: (channelId: string) => string;
51
+ /** Pins (PUT) or unpins (DELETE) a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Pin route. */
52
+ readonly channelMessagesPin: (channelId: string, messageId: string) => string;
53
+ /** @deprecated Discord deprecated this endpoint. Use {@link Routes.channelMessagesPins}, which returns `{ items, has_more }`. Removed in 0.3.0. */
54
+ readonly channelPins: (channelId: string) => string;
55
+ /** @deprecated Discord deprecated this endpoint. Use {@link Routes.channelMessagesPin}. Removed in 0.3.0. */
56
+ readonly channelPin: (channelId: string, messageId: string) => string;
57
+ /** Creates a thread from a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Message-thread route. */
58
+ readonly messageThread: (channelId: string, messageId: string) => string;
59
+ /** Bulk deletes messages. @param channelId Channel identifier. @returns Bulk-delete route. */
60
+ readonly channelBulkDelete: (channelId: string) => string;
61
+ /** Returns channel webhooks. @param channelId Channel identifier. @returns Webhook collection route. */
62
+ readonly channelWebhooks: (channelId: string) => string;
63
+ /** Returns channel invites. @param channelId Channel identifier. @returns Invite collection route. */
64
+ readonly channelInvites: (channelId: string) => string;
65
+ /** Returns a webhook. @param webhookId Webhook identifier. @param token Optional webhook token. @returns Webhook route. */
66
+ readonly webhook: (webhookId: string, token?: string) => string;
67
+ /** Returns a webhook message. */
68
+ readonly webhookMessage: (webhookId: string, token: string, messageId: string) => string;
69
+ /** Returns application commands for an application. @param applicationId Application identifier. @returns Global command route. */
70
+ readonly applicationCommands: (applicationId: string) => string;
71
+ /** Returns one application command. @param applicationId Application identifier. @param commandId Command identifier. @returns Command route. */
72
+ readonly applicationCommand: (applicationId: string, commandId: string) => string;
73
+ /** Returns guild application commands. @param applicationId Application identifier. @param guildId Guild identifier. @returns Guild command route. */
74
+ readonly guildApplicationCommands: (applicationId: string, guildId: string) => string;
75
+ /** Returns a single guild application command. @param applicationId Application identifier. @param guildId Guild identifier. @param commandId Command identifier. @returns Guild command route. */
76
+ readonly guildApplicationCommand: (applicationId: string, guildId: string, commandId: string) => string;
77
+ /** Returns an interaction callback endpoint. @param interactionId Interaction identifier. @param token Interaction token. @returns Interaction callback route. */
78
+ readonly interactionCallback: (interactionId: string, token: string) => string;
79
+ /** Returns the original interaction response endpoint. @param applicationId Application identifier. @param token Interaction token. @returns Original-response route. */
80
+ readonly interactionOriginalResponse: (applicationId: string, token: string) => string;
81
+ /** Returns public archived threads for a channel. @param channelId Channel identifier. @returns Public-archive route. */
82
+ readonly channelPublicArchivedThreads: (channelId: string) => string;
83
+ /** Returns private archived threads for a channel. @param channelId Channel identifier. @returns Private-archive route. */
84
+ readonly channelPrivateArchivedThreads: (channelId: string) => string;
85
+ /** Returns a thread's members. @param threadId Thread identifier. @returns Thread-member route. */
86
+ readonly threadMembers: (threadId: string) => string;
87
+ /** Returns guild scheduled events. @param guildId Guild identifier. @returns Scheduled-event collection route. */
88
+ readonly guildScheduledEvents: (guildId: string) => string;
89
+ /** Returns one guild scheduled event. @param guildId Guild identifier. @param eventId Event identifier. @returns Scheduled-event route. */
90
+ readonly guildScheduledEvent: (guildId: string, eventId: string) => string;
91
+ /** Returns users subscribed to a scheduled event. @param guildId Guild identifier. @param eventId Event identifier. @returns Scheduled-event users route. */
92
+ readonly guildScheduledEventUsers: (guildId: string, eventId: string) => string;
93
+ /** Returns a channel permission overwrite. @param channelId Channel identifier. @param overwriteId Role or user identifier. @returns Permission overwrite route. */
94
+ readonly channelPermission: (channelId: string, overwriteId: string) => string;
95
+ /** Returns guild automod rules. @param guildId Guild identifier. @returns Automod-rule collection route. */
96
+ readonly guildAutoModerationRules: (guildId: string) => string;
97
+ /** Returns one automod rule. @param guildId Guild identifier. @param ruleId Rule identifier. @returns Automod-rule route. */
98
+ readonly guildAutoModerationRule: (guildId: string, ruleId: string) => string;
99
+ /** Returns current voice regions. @returns Voice-region route. */
100
+ readonly voiceRegions: () => string;
101
+ /** Returns the generic Gateway endpoint. @returns Gateway route. */
102
+ readonly gateway: () => string;
103
+ /** Returns the Gateway endpoint and recommended shard count for bots. @returns Gateway bot route. */
104
+ readonly gatewayBot: () => string;
51
105
  /** Returns audit log entries for a guild. @param guildId Guild identifier. @returns Audit log route. */
52
106
  readonly guildAuditLog: (guildId: string) => string;
53
107
  /** Returns members in a guild (paginated). @param guildId Guild identifier. @returns Members collection route. */
@@ -2,11 +2,16 @@
2
2
  export type FetchLike = (input: string, init: RequestInit) => Promise<Response>;
3
3
  /** One HTTP attempt, fully resolved: no routing, retry or rate-limit concerns. */
4
4
  export interface TransportRequest {
5
- /** Uppercased HTTP method. */ method: string;
6
- /** Path with query string, relative to the transport's base URL. */ path: string;
7
- /** Request headers, already including authorization. */ headers: Record<string, string>;
8
- /** Encoded body, or undefined for a bodyless request. */ body?: BodyInit;
9
- /** Caller cancellation signal. */ signal?: AbortSignal;
5
+ /** Uppercased HTTP method. */
6
+ method: string;
7
+ /** Path with query string, relative to the transport's base URL. */
8
+ path: string;
9
+ /** Request headers, already including authorization. */
10
+ headers: Record<string, string>;
11
+ /** Encoded body, or undefined for a bodyless request. */
12
+ body?: BodyInit;
13
+ /** Caller cancellation signal. */
14
+ signal?: AbortSignal;
10
15
  }
11
16
  /** Thrown by {@link HttpTransport} when the attempt never produced a response. */
12
17
  export declare class TransportError extends Error {
@@ -1,4 +1,5 @@
1
- import type { APIEmbed, APIMessage } from "@lunibee/types";
1
+ import { type RESTFileAttachment } from "./index.js";
2
+ import type { APIEmbed, APIMessage, APIMessageComponent } from "@lunibee/types";
2
3
  export interface WebhookClientOptions {
3
4
  id?: string;
4
5
  token?: string;
@@ -12,8 +13,11 @@ export interface WebhookMessageOptions {
12
13
  embeds?: (APIEmbed | {
13
14
  toJSON(): APIEmbed;
14
15
  })[];
15
- components?: any[];
16
- files?: any[];
16
+ components?: (APIMessageComponent | {
17
+ toJSON(): APIMessageComponent;
18
+ })[];
19
+ /** Uploaded as multipart form data. */
20
+ files?: RESTFileAttachment[];
17
21
  flags?: number;
18
22
  thread_id?: string;
19
23
  }
@@ -33,8 +37,8 @@ export declare class WebhookClient {
33
37
  /** Edits a previously sent webhook message. */
34
38
  editMessage(messageId: string, options: string | {
35
39
  content?: string;
36
- embeds?: any[];
37
- }): Promise<any>;
40
+ embeds?: APIEmbed[];
41
+ }): Promise<APIMessage>;
38
42
  /** Deletes a previously sent webhook message. */
39
43
  deleteMessage(messageId: string): Promise<void>;
40
44
  }
@@ -1,17 +1,26 @@
1
1
  /** Message envelope exchanged between Lunibee shards. */
2
2
  export interface ShardMessage<T = unknown> {
3
- /** Sending shard ID. */ source: number;
4
- /** Target shard ID, or null for broadcast. */ target: number | null;
5
- /** Application message type. */ type: string;
6
- /** Message payload. */ data: T;
7
- /** Unique message ID. */ id: string;
8
- /** Set on requests that expect a reply (see {@link ShardBus.request}). */ expectsReply?: boolean;
3
+ /** Sending shard ID. */
4
+ source: number;
5
+ /** Target shard ID, or null for broadcast. */
6
+ target: number | null;
7
+ /** Application message type. */
8
+ type: string;
9
+ /** Message payload. */
10
+ data: T;
11
+ /** Unique message ID. */
12
+ id: string;
13
+ /** Set on requests that expect a reply (see {@link ShardBus.request}). */
14
+ expectsReply?: boolean;
9
15
  }
10
16
  /** A reply collected by {@link ShardBus.broadcastRequest}. */
11
17
  export interface ShardReply<R = unknown> {
12
- /** Replying shard ID. */ shardId: number;
13
- /** Handler result, when it succeeded. */ result?: R;
14
- /** Handler error message, when it failed. */ error?: string;
18
+ /** Replying shard ID. */
19
+ shardId: number;
20
+ /** Handler result, when it succeeded. */
21
+ result?: R;
22
+ /** Handler error message, when it failed. */
23
+ error?: string;
15
24
  }
16
25
  /** Handler invoked for shard messages. @typeParam T Message payload type. */
17
26
  export type ShardMessageHandler<T = unknown> = (message: ShardMessage<T>) => unknown;
@@ -20,15 +29,22 @@ export type ShardBusErrorHandler = (error: unknown, message: ShardMessage) => vo
20
29
  /** Bun/Node-compatible cross-shard transport using BroadcastChannel. */
21
30
  export declare class ShardBus {
22
31
  #private;
23
- /** BroadcastChannel name used by this bus. */ readonly channelName: string;
32
+ /** BroadcastChannel name used by this bus. */
33
+ readonly channelName: string;
24
34
  /** Creates a shard bus. @param shardId Shard ID. @param channelName Application-specific channel name. @throws {RangeError} If shard ID is invalid. @throws {TypeError} If channel name is empty. */
25
35
  constructor(shardId: number, channelName: string);
26
- /** Registers a message handler. @param type Message type. @param handler Handler callback. @returns This bus. @throws {TypeError} If type or handler is invalid. */ on<T>(type: string, handler: ShardMessageHandler<T>): this;
27
- /** Removes a message handler. @param type Message type. @param handler Handler callback. @returns This bus. */ off<T>(type: string, handler: ShardMessageHandler<T>): this;
28
- /** Registers a listener for errors thrown or rejected by message handlers. Without one, handler errors are isolated and dropped. @param handler Error listener. @returns This bus. @throws {TypeError} If handler is invalid. */ onError(handler: ShardBusErrorHandler): this;
29
- /** Removes a handler error listener. @param handler Error listener. @returns This bus. */ offError(handler: ShardBusErrorHandler): this;
30
- /** Sends a targeted shard message. @param target Target shard ID. @param type Message type. @param data Payload. @returns Unique message ID. */ send<T>(target: number, type: string, data: T): string;
31
- /** Broadcasts to all other shards. @param type Message type. @param data Payload. @returns Unique message ID. */ broadcast<T>(type: string, data: T): string;
36
+ /** Registers a message handler. @param type Message type. @param handler Handler callback. @returns This bus. @throws {TypeError} If type or handler is invalid. */
37
+ on<T>(type: string, handler: ShardMessageHandler<T>): this;
38
+ /** Removes a message handler. @param type Message type. @param handler Handler callback. @returns This bus. */
39
+ off<T>(type: string, handler: ShardMessageHandler<T>): this;
40
+ /** Registers a listener for errors thrown or rejected by message handlers. Without one, handler errors are isolated and dropped. @param handler Error listener. @returns This bus. @throws {TypeError} If handler is invalid. */
41
+ onError(handler: ShardBusErrorHandler): this;
42
+ /** Removes a handler error listener. @param handler Error listener. @returns This bus. */
43
+ offError(handler: ShardBusErrorHandler): this;
44
+ /** Sends a targeted shard message. @param target Target shard ID. @param type Message type. @param data Payload. @returns Unique message ID. */
45
+ send<T>(target: number, type: string, data: T): string;
46
+ /** Broadcasts to all other shards. @param type Message type. @param data Payload. @returns Unique message ID. */
47
+ broadcast<T>(type: string, data: T): string;
32
48
  /**
33
49
  * Registers a handler that answers requests of `type`. Its return value (or
34
50
  * thrown error) is sent back to the requesting shard. Discord.js-familiar
@@ -49,5 +65,6 @@ export declare class ShardBus {
49
65
  timeoutMs?: number;
50
66
  expected?: number;
51
67
  }): Promise<ShardReply<R>[]>;
52
- /** Closes the transport. @returns Nothing. */ close(): void;
68
+ /** Closes the transport. @returns Nothing. */
69
+ close(): void;
53
70
  }
@@ -5,10 +5,14 @@ export { ClusterManager } from "./cluster.js";
5
5
  export type { ClusterManagerOptions, ClusterInfo } from "./cluster.js";
6
6
  /** Configuration for a sharded Gateway client. */
7
7
  export interface ShardManagerOptions {
8
- /** Bot token. */ token: string;
9
- /** Gateway intents. */ intents: number;
10
- /** Number of shards. Use `"auto"` to request Discord's recommended count. */ shardCount?: number | "auto";
11
- /** Gateway reconnect behavior. */ reconnect?: boolean;
8
+ /** Bot token. */
9
+ token: string;
10
+ /** Gateway intents. */
11
+ intents: number;
12
+ /** Number of shards. Use `"auto"` to request Discord's recommended count. */
13
+ shardCount?: number | "auto";
14
+ /** Gateway reconnect behavior. */
15
+ reconnect?: boolean;
12
16
  /**
13
17
  * Delay between shard starts in milliseconds. Defaults to 5000 to respect
14
18
  * Discord's IDENTIFY rate limit (one per 5s per rate-limit key); set 0 to
@@ -23,37 +27,48 @@ export interface ShardManagerOptions {
23
27
  * How long a startup round waits for its shards to send IDENTIFY/RESUME
24
28
  * before the next round's `spawnDelay` starts. Defaults to 15000 ms.
25
29
  */ handshakeTimeout?: number;
26
- /** Interval in milliseconds to automatically check for recommended shard count and re-scale if needed. Must be an integer >= 1000. */ autoScaleInterval?: number;
27
- /** Optional handler invoked when a background auto-scale check fails. Receives the thrown error. */ onAutoScaleError?: (error: unknown) => void;
30
+ /** Interval in milliseconds to automatically check for recommended shard count and re-scale if needed. Must be an integer >= 1000. */
31
+ autoScaleInterval?: number;
32
+ /** Optional handler invoked when a background auto-scale check fails. Receives the thrown error. */
33
+ onAutoScaleError?: (error: unknown) => void;
28
34
  }
29
35
  /** `/gateway/bot` information used to pace shard startup. */
30
36
  export interface GatewayBotInfo {
31
- /** Recommended shard count. */ shards: number;
32
- /** IDENTIFY budget, when Discord reported it. */ sessionStartLimit?: {
37
+ /** Recommended shard count. */
38
+ shards: number;
39
+ /** IDENTIFY budget, when Discord reported it. */
40
+ sessionStartLimit?: {
33
41
  total: number;
34
42
  remaining: number;
35
- /** Milliseconds until `remaining` resets. */ resetAfter: number;
43
+ /** Milliseconds until `remaining` resets. */
44
+ resetAfter: number;
36
45
  maxConcurrency: number;
37
46
  };
38
47
  }
39
48
  /** Health snapshot for one shard. */
40
49
  export interface ShardHealth {
41
50
  id: number;
42
- /** Gateway connection state. */ state: Gateway["state"];
43
- /** Last heartbeat round-trip in ms, or -1 before the first ACK. */ ping: number;
51
+ /** Gateway connection state. */
52
+ state: Gateway["state"];
53
+ /** Last heartbeat round-trip in ms, or -1 before the first ACK. */
54
+ ping: number;
44
55
  }
45
56
  /** Runtime state for a managed shard. */
46
57
  export interface ShardInfo {
47
- /** Shard identifier. */ id: number;
48
- /** Gateway instance. */ gateway: Gateway;
58
+ /** Shard identifier. */
59
+ id: number;
60
+ /** Gateway instance. */
61
+ gateway: Gateway;
49
62
  }
50
63
  /** Manages independent Discord Gateway shards with explicit destruction and reinitialization semantics. */
51
64
  export declare class ShardManager {
52
65
  #private;
53
66
  /** Discord's minimum interval between IDENTIFY payloads, in milliseconds. */
54
67
  static readonly IDENTIFY_INTERVAL = 5000;
55
- /** Active Gateway shards indexed by shard identifier. */ readonly shards: Map<number, Gateway>;
56
- /** Number of shards managed by this instance after initialization. */ get shardCount(): number;
68
+ /** Active Gateway shards indexed by shard identifier. */
69
+ readonly shards: Map<number, Gateway>;
70
+ /** Number of shards managed by this instance after initialization. */
71
+ get shardCount(): number;
57
72
  /** Creates a shard manager. @param options Sharding configuration. @throws {TypeError} If token or intents are invalid. @throws {RangeError} If shard count is invalid. */
58
73
  constructor(options: ShardManagerOptions);
59
74
  /** Retrieves Discord's recommended shard count. @returns Recommended shard count. @throws {Error} If discovery fails or returns invalid data. */
@@ -70,10 +85,12 @@ export declare class ShardManager {
70
85
  destroy(): void;
71
86
  /** Calculates the target shard ID for a Discord guild snowflake. @param guildId Guild snowflake. @returns Shard identifier. */
72
87
  getShardIdForGuild(guildId: string): number;
73
- /** Gets a shard by ID. @param id Shard identifier. @returns Gateway instance or undefined. */ get(id: number): Gateway | undefined;
88
+ /** Gets a shard by ID. @param id Shard identifier. @returns Gateway instance or undefined. */
89
+ get(id: number): Gateway | undefined;
74
90
  /** Returns each shard's connection state and heartbeat latency. */
75
91
  health(): ShardHealth[];
76
- /** Returns information for all managed shards. @returns Shard information snapshots. */ values(): ShardInfo[];
92
+ /** Returns information for all managed shards. @returns Shard information snapshots. */
93
+ values(): ShardInfo[];
77
94
  }
78
95
  /** Discord.js-familiar alias for {@link ShardManager}. */
79
96
  export { ShardManager as ShardingManager };
@@ -2,7 +2,7 @@
2
2
  // packages/sharding/package.json
3
3
  var package_default = {
4
4
  name: "@lunibee/sharding",
5
- version: "0.2.3",
5
+ version: "0.2.4",
6
6
  type: "module",
7
7
  module: "./src/index.ts",
8
8
  types: "./src/index.ts",
@@ -88,7 +88,26 @@ class GatewaySession {
88
88
  return resume ? { type: "resume", ...resume } : { type: "identify" };
89
89
  }
90
90
  connectURL(fallback) {
91
- return this.resumeInfo()?.resumeURL ?? fallback;
91
+ const resume = this.resumeInfo()?.resumeURL;
92
+ return resume !== undefined && isTrustedGatewayURL(resume, fallback) ? resume : fallback;
93
+ }
94
+ }
95
+ function isTrustedGatewayURL(url, fallback) {
96
+ let parsed;
97
+ try {
98
+ parsed = new URL(url);
99
+ } catch {
100
+ return false;
101
+ }
102
+ if (parsed.protocol !== "wss:" || parsed.username || parsed.password)
103
+ return false;
104
+ const host = parsed.hostname.toLowerCase();
105
+ if (host === "discord.gg" || host.endsWith(".discord.gg"))
106
+ return true;
107
+ try {
108
+ return host === new URL(fallback).hostname.toLowerCase();
109
+ } catch {
110
+ return false;
92
111
  }
93
112
  }
94
113
 
@@ -364,12 +383,15 @@ class PlainTextDecoder {
364
383
 
365
384
  class ZlibStreamDecoder {
366
385
  #create;
386
+ #maxFrameBytes;
367
387
  #inflate;
368
388
  #chunks = [];
389
+ #size = 0;
369
390
  #failure;
370
391
  #pendingReject;
371
- constructor(create = () => createInflate()) {
392
+ constructor(create = () => createInflate(), maxFrameBytes = 64 * 1024 * 1024) {
372
393
  this.#create = create;
394
+ this.#maxFrameBytes = maxFrameBytes;
373
395
  }
374
396
  push(data) {
375
397
  if (typeof data === "string")
@@ -388,6 +410,7 @@ class ZlibStreamDecoder {
388
410
  await this.#awaiting((settle) => inflate.flush(zlibConstants.Z_SYNC_FLUSH, () => settle()));
389
411
  const parts = this.#chunks;
390
412
  this.#chunks = [];
413
+ this.#size = 0;
391
414
  if (parts.length === 0)
392
415
  return [];
393
416
  const total = parts.reduce((size, part) => size + part.length, 0);
@@ -403,6 +426,7 @@ class ZlibStreamDecoder {
403
426
  const inflate = this.#inflate;
404
427
  this.#inflate = undefined;
405
428
  this.#chunks = [];
429
+ this.#size = 0;
406
430
  this.#failure = undefined;
407
431
  this.#pendingReject = undefined;
408
432
  if (!inflate)
@@ -430,7 +454,17 @@ class ZlibStreamDecoder {
430
454
  }
431
455
  #open() {
432
456
  const inflate = this.#create();
433
- inflate.on("data", (chunk) => this.#chunks.push(chunk));
457
+ inflate.on("data", (chunk) => {
458
+ if (this.#failure)
459
+ return;
460
+ this.#size += chunk.length;
461
+ if (this.#size > this.#maxFrameBytes) {
462
+ this.#chunks = [];
463
+ inflate.emit("error", new Error(`Gateway frame inflated past ${this.#maxFrameBytes} bytes.`));
464
+ return;
465
+ }
466
+ this.#chunks.push(chunk);
467
+ });
434
468
  inflate.on("error", (error) => {
435
469
  this.#failure = error;
436
470
  const reject = this.#pendingReject;
@@ -673,9 +707,9 @@ function classifyPayload(payload) {
673
707
  }
674
708
  function identifyPayload(options) {
675
709
  const props = options.properties ?? {};
676
- const os = props.os ?? "Android";
677
- const browser = props.browser ?? "Discord Android";
678
- const device = props.device ?? "Discord Android";
710
+ const os = props.os ?? process.platform;
711
+ const browser = props.browser ?? "Lunibee";
712
+ const device = props.device ?? "Lunibee";
679
713
  return {
680
714
  op: GatewayOpcodes.Identify,
681
715
  d: {
@@ -771,28 +805,26 @@ var IntentBits = {
771
805
  directMessagePolls: 1 << 25
772
806
  };
773
807
  function resolveGatewayIntents(intents) {
774
- if (typeof intents === "number")
775
- return intents;
776
- if (intents && typeof intents === "object" && !Array.isArray(intents))
808
+ if (Array.isArray(intents))
809
+ return intents.reduce((acc, intent) => acc | resolveIntent(intent), 0);
810
+ if (typeof intents === "object")
777
811
  return intents.bitfield;
778
- if (Array.isArray(intents)) {
779
- return intents.reduce((acc, intent) => {
780
- return acc | resolveGatewayIntents(intent);
781
- }, 0);
782
- }
783
- if (typeof intents === "string") {
784
- if (intents in GatewayIntentBits)
785
- return GatewayIntentBits[intents];
786
- if (intents in IntentBits)
787
- return IntentBits[intents];
788
- const lower = intents.charAt(0).toLowerCase() + intents.slice(1);
789
- if (lower in IntentBits)
790
- return IntentBits[lower];
791
- const num = Number(intents);
792
- if (!Number.isNaN(num))
793
- return num;
794
- }
795
- return 0;
812
+ return resolveIntent(intents);
813
+ }
814
+ function resolveIntent(intent) {
815
+ if (typeof intent === "number")
816
+ return intent;
817
+ const bits = {
818
+ ...IntentBits,
819
+ ...GatewayIntentBits
820
+ };
821
+ const lower = intent.charAt(0).toLowerCase() + intent.slice(1);
822
+ if (Object.hasOwn(bits, intent))
823
+ return bits[intent];
824
+ if (Object.hasOwn(bits, lower))
825
+ return bits[lower];
826
+ const num = Number(intent);
827
+ return Number.isNaN(num) ? 0 : num;
796
828
  }
797
829
  // packages/ws/src/state.ts
798
830
  class GatewayError extends Error {
@@ -857,9 +889,9 @@ class Gateway {
857
889
  heartbeatAckTimeout: 1e4,
858
890
  zombieTimeout: 30000,
859
891
  properties: {
860
- os: "Android",
861
- browser: "Discord Android",
862
- device: "Discord Android"
892
+ os: process.platform,
893
+ browser: "Lunibee",
894
+ device: "Lunibee"
863
895
  },
864
896
  presence: {
865
897
  status: "online",
@@ -1702,4 +1734,4 @@ export {
1702
1734
  ShardManager as ShardingManager
1703
1735
  };
1704
1736
 
1705
- //# debugId=B02B71EDFB220DDE64756E2164756E21
1737
+ //# debugId=E65F505DB72D610764756E2164756E21