lunibee 0.1.4 → 0.1.6

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 (42) hide show
  1. package/README.md +12 -23
  2. package/dist/builders/components.d.ts +108 -0
  3. package/dist/builders/index.d.ts +1 -1
  4. package/dist/builders/index.js +178 -2
  5. package/dist/builders/index.js.map +3 -3
  6. package/dist/collection/index.d.ts +6 -0
  7. package/dist/collection/index.js +33 -2
  8. package/dist/collection/index.js.map +4 -4
  9. package/dist/core/events.d.ts +67 -3
  10. package/dist/core/index.d.ts +120 -90
  11. package/dist/core/index.js +816 -1021
  12. package/dist/core/index.js.map +20 -21
  13. package/dist/formatters/index.js.map +1 -1
  14. package/dist/index.d.ts +5 -4
  15. package/dist/index.js +2215 -1392
  16. package/dist/index.js.map +29 -26
  17. package/dist/managers/guild.d.ts +30 -0
  18. package/dist/managers/index.d.ts +56 -75
  19. package/dist/managers/index.js +339 -48
  20. package/dist/managers/index.js.map +16 -12
  21. package/dist/managers/message.d.ts +7 -12
  22. package/dist/managers/user.d.ts +20 -0
  23. package/dist/rest/index.d.ts +83 -1
  24. package/dist/rest/index.js +48 -8
  25. package/dist/rest/index.js.map +4 -4
  26. package/dist/rest/routes.d.ts +4 -1
  27. package/dist/sharding/index.js +4 -1
  28. package/dist/sharding/index.js.map +4 -4
  29. package/dist/structures/base.d.ts +99 -48
  30. package/dist/structures/embed.d.ts +65 -0
  31. package/dist/structures/index.d.ts +45 -25
  32. package/dist/structures/index.js +569 -36
  33. package/dist/structures/index.js.map +10 -8
  34. package/dist/structures/interactions.d.ts +72 -17
  35. package/dist/structures/resources.d.ts +9 -5
  36. package/dist/types/index.d.ts +530 -85
  37. package/dist/types/index.js +71 -1
  38. package/dist/types/index.js.map +3 -3
  39. package/dist/voice/index.js.map +1 -1
  40. package/dist/ws/index.js +4 -1
  41. package/dist/ws/index.js.map +4 -4
  42. package/package.json +15 -15
@@ -1,25 +1,20 @@
1
1
  import { Collection } from "@lunibee/collection";
2
2
  import { REST } from "@lunibee/rest";
3
3
  import { Message, type ResourceContext } from "@lunibee/structures";
4
- /** Manages message resources belonging to a single channel with canonical identity. */
4
+ export type MessageCreateOptions = Record<string, unknown> & {
5
+ content?: string;
6
+ };
7
+ export type MessageEditOptions = Record<string, unknown> & {
8
+ content?: string;
9
+ };
5
10
  export declare class MessageManager {
6
11
  #private;
7
- /** Canonical message cache for this channel. */
8
12
  readonly cache: Collection<string, Message>;
9
- /** Creates a message manager. @param rest REST transport. @param context Structure resource context. @param channelId Channel identifier. @throws {TypeError} If channelId is empty. */
10
13
  constructor(rest: REST, context: ResourceContext, channelId: string);
11
- /** Resolves a message from cache or REST. @param messageId Message identifier. @returns Canonical message. */
12
14
  resolve(messageId: string): Promise<Message>;
13
- /** Sends a message and caches it canonically. @param options Message payload. @returns Canonical message. */
14
- send(options: {
15
- content?: string;
16
- }): Promise<Message>;
17
- /** Fetches one message and caches it canonically. @param messageId Message identifier. @returns Canonical message. */
15
+ send(options: MessageCreateOptions): Promise<Message>;
18
16
  fetch(messageId: string): Promise<Message>;
19
- /** Fetches several messages by ID. @param messageIds Message identifiers. @returns Canonical messages. */
20
17
  fetchMany(messageIds: Iterable<string>): Promise<Message[]>;
21
- /** Inserts or updates a message through the shared hydration path. @param data Discord message payload. @returns Canonical message. */
22
18
  upsert(data: ConstructorParameters<typeof Message>[0]): Message;
23
- /** Removes a message from cache. @param messageId Message identifier. @returns Whether a cached message was removed. */
24
19
  delete(messageId: string): boolean;
25
20
  }
@@ -0,0 +1,20 @@
1
+ import { ResourceManager } from "./base.js";
2
+ import { User } from "@lunibee/structures";
3
+ import { type REST } from "@lunibee/rest";
4
+ import type { APIChannel } from "@lunibee/types";
5
+ export interface UserEditOptions {
6
+ username?: string;
7
+ avatar?: string | null;
8
+ }
9
+ export declare class UserManager extends ResourceManager<string, User> {
10
+ #private;
11
+ constructor(rest: REST);
12
+ /** Gets the currently logged-in bot user. */
13
+ fetchMe(): Promise<User>;
14
+ /** Modifies the currently logged-in bot user. */
15
+ editMe(options: UserEditOptions): Promise<User>;
16
+ /** Leaves a guild. */
17
+ leaveGuild(guildId: string): Promise<void>;
18
+ /** Creates a DM channel with a user. */
19
+ createDM(userId: string): Promise<APIChannel>;
20
+ }
@@ -1 +1,83 @@
1
- export * from "./../../packages/rest/src/index.ts";
1
+ /** Error thrown when Discord rejects a REST request. */
2
+ export declare class RESTError extends Error {
3
+ /** HTTP status returned by Discord. */ readonly status: number;
4
+ /** Discord API error code, when provided. */ readonly code?: number;
5
+ /** Raw Discord validation/error payload. */ readonly errors?: unknown;
6
+ /** HTTP method used for the failed request. */ readonly method?: string;
7
+ /** API path used for the failed request. */ readonly path?: string;
8
+ /** Creates a REST error with request context. @param message Error message. @param status HTTP status. @param code Discord error code. @param errors Raw error payload. @param options Request context and cause. */
9
+ constructor(message: string, status: number, code?: number, errors?: unknown, options?: {
10
+ method?: string;
11
+ path?: string;
12
+ cause?: unknown;
13
+ });
14
+ }
15
+ /** Options controlling an individual REST request. */
16
+ export interface RESTRequestOptions {
17
+ /** Abort signal used to cancel the request and any queued wait. */ signal?: AbortSignal;
18
+ }
19
+ export interface RESTFileAttachment {
20
+ name: string;
21
+ data: Blob | Uint8Array | ArrayBuffer;
22
+ contentType?: string;
23
+ }
24
+ /** Configures which REST failures may be retried. */
25
+ export interface RetryPolicy {
26
+ /** Maximum retry attempts. */ maxRetries: number;
27
+ /** Determines whether a request may be retried. @param method HTTP method. @param status HTTP status, or zero for transport errors. @returns True when retrying is safe under the policy. */ shouldRetry(method: string, status: number): boolean;
28
+ /** Calculates delay before the next attempt. @param attempt Zero-based retry number. @param retryAfter Server-provided delay, when available. @returns Delay in milliseconds. */ getDelay(attempt: number, retryAfter?: number): number;
29
+ }
30
+ /** Creates the default conservative REST retry policy. @param maxRetries Maximum retries. @returns Retry policy that retries rate limits and idempotent transient failures. @throws {TypeError} If maxRetries is negative or not finite. */
31
+ export declare function createRetryPolicy(maxRetries?: number): RetryPolicy;
32
+ /** Bun-native REST transport with Discord bucket-aware rate limiting, retries, and cancellation. */
33
+ export declare class REST {
34
+ #private;
35
+ /** Creates a REST transport. @param options Transport configuration. @throws {TypeError} If retry configuration is invalid. */
36
+ constructor(options?: {
37
+ token?: string;
38
+ timeout?: number;
39
+ retries?: number;
40
+ retryPolicy?: RetryPolicy;
41
+ baseURL?: string;
42
+ });
43
+ /** Sets the authentication token. @param token Discord bot token. @returns Nothing. @throws {TypeError} If token is empty. */
44
+ setToken(token: string): void;
45
+ /** Executes an HTTP request with Discord bucket/global rate limits, retry handling, and AbortSignal support.
46
+ * Accepts a JSON body, a FormData body (for file uploads), or undefined.
47
+ * @param method HTTP method.
48
+ * @param path API path.
49
+ * @param body Optional JSON body, FormData for file uploads, or undefined.
50
+ * @param options Cancellation options.
51
+ * @returns Decoded response body.
52
+ * @throws {RESTError} If Discord or transport rejects the request.
53
+ */
54
+ request<T>(method: string, path: string, body?: unknown, options?: RESTRequestOptions): Promise<T>;
55
+ /** Sends a GET request. @param path API path. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ get<T>(path: string, options?: RESTRequestOptions): Promise<T>;
56
+ /** Sends a POST request. @param path API path. @param body Optional JSON body. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ post<T>(path: string, body?: unknown, options?: RESTRequestOptions): Promise<T>;
57
+ /** Sends a PATCH request. @param path API path. @param body Optional JSON body. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ patch<T>(path: string, body?: unknown, options?: RESTRequestOptions): Promise<T>;
58
+ /** Sends a PUT request. @param path API path. @param body Optional JSON body. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ put<T>(path: string, body?: unknown, options?: RESTRequestOptions): Promise<T>;
59
+ /** Sends a DELETE request. @param path API path. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ delete<T>(path: string, options?: RESTRequestOptions): Promise<T>;
60
+ /**
61
+ * Sends a multipart/form-data POST request for file uploads.
62
+ * Attaches a JSON payload as `payload_json` and files as additional fields.
63
+ * @param path API path.
64
+ * @param payload JSON payload (e.g. message content, embeds).
65
+ * @param files Array of file attachments.
66
+ * @param options Cancellation options.
67
+ * @returns Decoded response.
68
+ * @throws {RESTError} When the request fails.
69
+ */
70
+ postWithFiles<T>(path: string, payload: unknown, files: RESTFileAttachment[], options?: RESTRequestOptions): Promise<T>;
71
+ /**
72
+ * Sends a multipart/form-data PATCH request for editing messages with files.
73
+ * @param path API path.
74
+ * @param payload JSON payload.
75
+ * @param files Array of file attachments.
76
+ * @param options Cancellation options.
77
+ * @returns Decoded response.
78
+ * @throws {RESTError} When the request fails.
79
+ */
80
+ patchWithFiles<T>(path: string, payload: unknown, files: RESTFileAttachment[], options?: RESTRequestOptions): Promise<T>;
81
+ }
82
+ export { Routes } from "./routes.js";
83
+ export { WebhookClient, type WebhookClientOptions, type WebhookMessageOptions, } from "./webhook.js";
@@ -1,9 +1,25 @@
1
1
  // @bun
2
+ // packages/rest/package.json
3
+ var package_default = {
4
+ name: "@lunibee/rest",
5
+ version: "0.1.6",
6
+ type: "module",
7
+ module: "./src/index.ts",
8
+ types: "./src/index.ts",
9
+ exports: {
10
+ ".": "./src/index.ts"
11
+ }
12
+ };
13
+
2
14
  // packages/rest/src/routes.ts
3
15
  var Routes = {
4
16
  user: () => "/users/@me",
5
17
  userById: (userId) => `/users/${snowflake(userId, "User ID")}`,
6
18
  guild: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}`,
19
+ guildPreview: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/preview`,
20
+ guildActiveThreads: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/threads/active`,
21
+ guildWebhooks: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/webhooks`,
22
+ guildInvites: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/invites`,
7
23
  guildChannels: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/channels`,
8
24
  guildMember: (guildId, userId) => `/guilds/${snowflake(guildId, "Guild ID")}/members/${snowflake(userId, "User ID")}`,
9
25
  guildRoles: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/roles`,
@@ -31,7 +47,6 @@ var Routes = {
31
47
  guildApplicationCommand: (applicationId, guildId, commandId) => `/applications/${snowflake(applicationId, "Application ID")}/guilds/${snowflake(guildId, "Guild ID")}/commands/${snowflake(commandId, "Command ID")}`,
32
48
  interactionCallback: (interactionId, token) => `/interactions/${snowflake(interactionId, "Interaction ID")}/${encodeURIComponent(token)}/callback`,
33
49
  interactionOriginalResponse: (applicationId, token) => `/webhooks/${snowflake(applicationId, "Application ID")}/${encodeURIComponent(token)}/messages/@original`,
34
- guildActiveThreads: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/threads/active`,
35
50
  channelPublicArchivedThreads: (channelId) => `/channels/${snowflake(channelId, "Channel ID")}/threads/archived/public`,
36
51
  channelPrivateArchivedThreads: (channelId) => `/channels/${snowflake(channelId, "Channel ID")}/threads/archived/private`,
37
52
  threadMembers: (threadId) => `/channels/${snowflake(threadId, "Thread ID")}/thread-members`,
@@ -104,6 +119,9 @@ class RESTError extends Error {
104
119
  this.path = options.path;
105
120
  }
106
121
  }
122
+ var LIBRARY_VERSION = package_default.version;
123
+ var LIBRARY_URL = "https://github.com/Ekretos/lunibee";
124
+ var USER_AGENT = `DiscordBot (${LIBRARY_URL}, ${package_default.version})`;
107
125
  function createRetryPolicy(maxRetries = 2) {
108
126
  if (!Number.isFinite(maxRetries) || maxRetries < 0)
109
127
  throw new TypeError("maxRetries must be a non-negative finite number.");
@@ -170,15 +188,19 @@ class REST {
170
188
  throw this.#abortError(path, options.signal.reason);
171
189
  options.signal?.addEventListener("abort", onAbort, { once: true });
172
190
  const timer = setTimeout(() => controller.abort(new DOMException("REST request timeout", "TimeoutError")), this.#timeout);
191
+ const isFormData = typeof FormData !== "undefined" && body instanceof FormData;
192
+ const headers = {
193
+ ...this.#token ? { Authorization: `Bot ${this.#token}` } : {},
194
+ "User-Agent": USER_AGENT
195
+ };
196
+ if (!isFormData)
197
+ headers["Content-Type"] = "application/json";
198
+ const fetchBody = isFormData ? body : body === undefined ? undefined : JSON.stringify(body);
173
199
  try {
174
200
  const response = await fetch(`${this.#baseURL}${path}`, {
175
201
  method: normalizedMethod,
176
- headers: {
177
- ...this.#token ? { Authorization: `Bot ${this.#token}` } : {},
178
- "Content-Type": "application/json",
179
- "User-Agent": "Lunibee/0.1.0"
180
- },
181
- body: body === undefined ? undefined : JSON.stringify(body),
202
+ headers,
203
+ body: fetchBody,
182
204
  signal: controller.signal
183
205
  });
184
206
  bucket = this.#update(response, bucket, route, bucketKey);
@@ -231,6 +253,24 @@ class REST {
231
253
  delete(path, options) {
232
254
  return this.request("DELETE", path, undefined, options);
233
255
  }
256
+ #fileForm(payload, files) {
257
+ const form = new FormData;
258
+ form.append("payload_json", JSON.stringify(payload));
259
+ for (let i = 0;i < files.length; i++) {
260
+ const file = files[i];
261
+ const blob = file.data instanceof Blob ? file.data : new Blob([file.data], {
262
+ type: file.contentType ?? "application/octet-stream"
263
+ });
264
+ form.append(`files[${i}]`, blob, file.name);
265
+ }
266
+ return form;
267
+ }
268
+ postWithFiles(path, payload, files, options) {
269
+ return this.request("POST", path, this.#fileForm(payload, files), options);
270
+ }
271
+ patchWithFiles(path, payload, files, options) {
272
+ return this.request("PATCH", path, this.#fileForm(payload, files), options);
273
+ }
234
274
  async#wait(bucket, signal, path) {
235
275
  const delay = bucket.resetAt - Date.now();
236
276
  if (bucket.remaining <= 0 && delay > 0)
@@ -341,4 +381,4 @@ export {
341
381
  createRetryPolicy
342
382
  };
343
383
 
344
- //# debugId=69F9FDE9A0B8ECD864756E2164756E21
384
+ //# debugId=429E85E3F97473C964756E2164756E21
@@ -2,11 +2,11 @@
2
2
  "version": 3,
3
3
  "sources": ["../../packages/rest/src/routes.ts", "../../packages/rest/src/webhook.ts", "../../packages/rest/src/index.ts"],
4
4
  "sourcesContent": [
5
- "/** Discord REST API route definitions. */\r\nexport const Routes = {\r\n /** Returns the current bot user. @returns User route. */ user: () =>\r\n \"/users/@me\",\r\n /** Returns one user. @param userId User identifier. @returns User route. */ userById:\r\n (userId: string) => `/users/${snowflake(userId, \"User ID\")}`,\r\n /** Returns a guild. @param guildId Guild identifier. @returns Guild route. */ guild:\r\n (guildId: string) => `/guilds/${snowflake(guildId, \"Guild ID\")}`,\r\n /** Returns channels in a guild. @param guildId Guild identifier. @returns Channel collection route. */ guildChannels:\r\n (guildId: string) => `/guilds/${snowflake(guildId, \"Guild ID\")}/channels`,\r\n /** Returns a guild member. @param guildId Guild identifier. @param userId User identifier. @returns Guild-member route. */ guildMember:\r\n (guildId: string, userId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/members/${snowflake(userId, \"User ID\")}`,\r\n /** Returns all guild roles. @param guildId Guild identifier. @returns Guild-role route. */ guildRoles:\r\n (guildId: string) => `/guilds/${snowflake(guildId, \"Guild ID\")}/roles`,\r\n /** Returns an individual guild role. */ guildRole: (\r\n guildId: string,\r\n roleId: string,\r\n ) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/roles/${snowflake(roleId, \"Role ID\")}`,\r\n /** Returns a member role route. */ guildMemberRole: (\r\n guildId: string,\r\n userId: string,\r\n roleId: string,\r\n ) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/members/${snowflake(userId, \"User ID\")}/roles/${snowflake(roleId, \"Role ID\")}`,\r\n /** Returns guild bans collection. */ guildBans: (guildId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/bans`,\r\n /** Returns an individual guild ban. */ guildBan: (\r\n guildId: string,\r\n userId: string,\r\n ) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/bans/${snowflake(userId, \"User ID\")}`,\r\n /** Returns a channel. @param channelId Channel identifier. @returns Channel route. */ channel:\r\n (channelId: string) => `/channels/${snowflake(channelId, \"Channel ID\")}`,\r\n /** Returns messages in a channel. @param channelId Channel identifier. @returns Message collection route. */ channelMessages:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/messages`,\r\n /** Returns a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Message route. */ message:\r\n (channelId: string, messageId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/messages/${snowflake(messageId, \"Message ID\")}`,\r\n /** Crossposts a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Crosspost route. */ crosspostMessage:\r\n (channelId: string, messageId: string) =>\r\n `${Routes.message(channelId, messageId)}/crosspost`,\r\n /** Returns reactions for a message and emoji. @param channelId Channel identifier. @param messageId Message identifier. @param emoji Emoji name or ID. @returns Reaction route. */ messageReactions:\r\n (channelId: string, messageId: string, emoji: string) =>\r\n `${Routes.message(channelId, messageId)}/reactions/${encodeURIComponent(emoji)}`,\r\n /** Removes all reactions from a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Reaction collection route. */ messageReactionsAll:\r\n (channelId: string, messageId: string) =>\r\n `${Routes.message(channelId, messageId)}/reactions`,\r\n /** Returns pinned messages. @param channelId Channel identifier. @returns Pins route. */ channelPins:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/pins`,\r\n /** Pins a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Pin route. */ channelPin:\r\n (channelId: string, messageId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/pins/${snowflake(messageId, \"Message ID\")}`,\r\n /** Creates a thread from a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Message-thread route. */ messageThread:\r\n (channelId: string, messageId: string) =>\r\n `${Routes.message(channelId, messageId)}/threads`,\r\n /** Bulk deletes messages. @param channelId Channel identifier. @returns Bulk-delete route. */ channelBulkDelete:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/messages/bulk-delete`,\r\n /** Returns channel webhooks. @param channelId Channel identifier. @returns Webhook collection route. */ channelWebhooks:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/webhooks`,\r\n /** Returns channel invites. @param channelId Channel identifier. @returns Invite collection route. */ channelInvites:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/invites`,\r\n /** Returns a webhook. @param webhookId Webhook identifier. @param token Optional webhook token. @returns Webhook route. */ webhook:\r\n (webhookId: string, token?: string) =>\r\n `/webhooks/${snowflake(webhookId, \"Webhook ID\")}${token ? `/${encodeURIComponent(token)}` : \"\"}`,\r\n /** Returns a webhook message. */ webhookMessage: (\r\n webhookId: string,\r\n token: string,\r\n messageId: string,\r\n ) =>\r\n `/webhooks/${snowflake(webhookId, \"Webhook ID\")}/${encodeURIComponent(token)}/messages/${snowflake(messageId, \"Message ID\")}`,\r\n /** Returns application commands for an application. @param applicationId Application identifier. @returns Global command route. */ applicationCommands:\r\n (applicationId: string) =>\r\n `/applications/${snowflake(applicationId, \"Application ID\")}/commands`,\r\n /** Returns one application command. @param applicationId Application identifier. @param commandId Command identifier. @returns Command route. */ applicationCommand:\r\n (applicationId: string, commandId: string) =>\r\n `/applications/${snowflake(applicationId, \"Application ID\")}/commands/${snowflake(commandId, \"Command ID\")}`,\r\n /** Returns guild application commands. @param applicationId Application identifier. @param guildId Guild identifier. @returns Guild command route. */ guildApplicationCommands:\r\n (applicationId: string, guildId: string) =>\r\n `/applications/${snowflake(applicationId, \"Application ID\")}/guilds/${snowflake(guildId, \"Guild ID\")}/commands`,\r\n /** Returns a single guild application command. @param applicationId Application identifier. @param guildId Guild identifier. @param commandId Command identifier. @returns Guild command route. */ guildApplicationCommand:\r\n (applicationId: string, guildId: string, commandId: string) =>\r\n `/applications/${snowflake(applicationId, \"Application ID\")}/guilds/${snowflake(guildId, \"Guild ID\")}/commands/${snowflake(commandId, \"Command ID\")}`,\r\n /** Returns an interaction callback endpoint. @param interactionId Interaction identifier. @param token Interaction token. @returns Interaction callback route. */ interactionCallback:\r\n (interactionId: string, token: string) =>\r\n `/interactions/${snowflake(interactionId, \"Interaction ID\")}/${encodeURIComponent(token)}/callback`,\r\n /** Returns the original interaction response endpoint. @param applicationId Application identifier. @param token Interaction token. @returns Original-response route. */ interactionOriginalResponse:\r\n (applicationId: string, token: string) =>\r\n `/webhooks/${snowflake(applicationId, \"Application ID\")}/${encodeURIComponent(token)}/messages/@original`,\r\n /** Returns guild threads that are active. @param guildId Guild identifier. @returns Active-thread route. */ guildActiveThreads:\r\n (guildId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/threads/active`,\r\n /** Returns public archived threads for a channel. @param channelId Channel identifier. @returns Public-archive route. */ channelPublicArchivedThreads:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/threads/archived/public`,\r\n /** Returns private archived threads for a channel. @param channelId Channel identifier. @returns Private-archive route. */ channelPrivateArchivedThreads:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/threads/archived/private`,\r\n /** Returns a thread's members. @param threadId Thread identifier. @returns Thread-member route. */ threadMembers:\r\n (threadId: string) =>\r\n `/channels/${snowflake(threadId, \"Thread ID\")}/thread-members`,\r\n /** Returns guild scheduled events. @param guildId Guild identifier. @returns Scheduled-event collection route. */ guildScheduledEvents:\r\n (guildId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/scheduled-events`,\r\n /** Returns one guild scheduled event. @param guildId Guild identifier. @param eventId Event identifier. @returns Scheduled-event route. */ guildScheduledEvent:\r\n (guildId: string, eventId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/scheduled-events/${snowflake(eventId, \"Event ID\")}`,\r\n /** Returns guild automod rules. @param guildId Guild identifier. @returns Automod-rule collection route. */ guildAutoModerationRules:\r\n (guildId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/auto-moderation/rules`,\r\n /** Returns one automod rule. @param guildId Guild identifier. @param ruleId Rule identifier. @returns Automod-rule route. */ guildAutoModerationRule:\r\n (guildId: string, ruleId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/auto-moderation/rules/${snowflake(ruleId, \"Rule ID\")}`,\r\n /** Returns current voice regions. @returns Voice-region route. */ voiceRegions:\r\n () => \"/voice/regions\",\r\n /** Returns the generic Gateway endpoint. @returns Gateway route. */ gateway:\r\n () => \"/gateway\",\r\n /** Returns the Gateway endpoint and recommended shard count for bots. @returns Gateway bot route. */ gatewayBot:\r\n () => \"/gateway/bot\",\r\n} as const;\r\n\r\n/** Validates a Discord snowflake route parameter. @param value Candidate identifier. @param field Human-readable field name. @returns The validated identifier. @throws {TypeError} If the identifier is not a Discord snowflake. */\r\nfunction snowflake(value: string, field: string): string {\r\n if (!/^\\d{1,20}$/.test(value))\r\n throw new TypeError(`${field} must be a valid Discord snowflake.`);\r\n return value;\r\n}\r\n",
5
+ "/** Discord REST API route definitions. */\r\nexport const Routes = {\r\n /** Returns the current bot user. @returns User route. */ user: () =>\r\n \"/users/@me\",\r\n /** Returns one user. @param userId User identifier. @returns User route. */ userById:\r\n (userId: string) => `/users/${snowflake(userId, \"User ID\")}`,\r\n /** Returns a guild. @param guildId Guild identifier. @returns Guild route. */ guild:\r\n (guildId: string) => `/guilds/${snowflake(guildId, \"Guild ID\")}`,\r\n /** Returns a guild preview. @param guildId Guild identifier. */ guildPreview:\r\n (guildId: string) => `/guilds/${snowflake(guildId, \"Guild ID\")}/preview`,\r\n /** Returns active threads for a guild. @param guildId Guild identifier. */ guildActiveThreads:\r\n (guildId: string) => `/guilds/${snowflake(guildId, \"Guild ID\")}/threads/active`,\r\n /** Returns webhooks for a guild. @param guildId Guild identifier. */ guildWebhooks:\r\n (guildId: string) => `/guilds/${snowflake(guildId, \"Guild ID\")}/webhooks`,\r\n /** Returns invites for a guild. @param guildId Guild identifier. */ guildInvites:\r\n (guildId: string) => `/guilds/${snowflake(guildId, \"Guild ID\")}/invites`,\r\n /** Returns channels in a guild. @param guildId Guild identifier. @returns Channel collection route. */ guildChannels:\r\n (guildId: string) => `/guilds/${snowflake(guildId, \"Guild ID\")}/channels`,\r\n /** Returns a guild member. @param guildId Guild identifier. @param userId User identifier. @returns Guild-member route. */ guildMember:\r\n (guildId: string, userId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/members/${snowflake(userId, \"User ID\")}`,\r\n /** Returns all guild roles. @param guildId Guild identifier. @returns Guild-role route. */ guildRoles:\r\n (guildId: string) => `/guilds/${snowflake(guildId, \"Guild ID\")}/roles`,\r\n /** Returns an individual guild role. */ guildRole: (\r\n guildId: string,\r\n roleId: string,\r\n ) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/roles/${snowflake(roleId, \"Role ID\")}`,\r\n /** Returns a member role route. */ guildMemberRole: (\r\n guildId: string,\r\n userId: string,\r\n roleId: string,\r\n ) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/members/${snowflake(userId, \"User ID\")}/roles/${snowflake(roleId, \"Role ID\")}`,\r\n /** Returns guild bans collection. */ guildBans: (guildId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/bans`,\r\n /** Returns an individual guild ban. */ guildBan: (\r\n guildId: string,\r\n userId: string,\r\n ) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/bans/${snowflake(userId, \"User ID\")}`,\r\n /** Returns a channel. @param channelId Channel identifier. @returns Channel route. */ channel:\r\n (channelId: string) => `/channels/${snowflake(channelId, \"Channel ID\")}`,\r\n /** Returns messages in a channel. @param channelId Channel identifier. @returns Message collection route. */ channelMessages:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/messages`,\r\n /** Returns a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Message route. */ message:\r\n (channelId: string, messageId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/messages/${snowflake(messageId, \"Message ID\")}`,\r\n /** Crossposts a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Crosspost route. */ crosspostMessage:\r\n (channelId: string, messageId: string) =>\r\n `${Routes.message(channelId, messageId)}/crosspost`,\r\n /** Returns reactions for a message and emoji. @param channelId Channel identifier. @param messageId Message identifier. @param emoji Emoji name or ID. @returns Reaction route. */ messageReactions:\r\n (channelId: string, messageId: string, emoji: string) =>\r\n `${Routes.message(channelId, messageId)}/reactions/${encodeURIComponent(emoji)}`,\r\n /** Removes all reactions from a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Reaction collection route. */ messageReactionsAll:\r\n (channelId: string, messageId: string) =>\r\n `${Routes.message(channelId, messageId)}/reactions`,\r\n /** Returns pinned messages. @param channelId Channel identifier. @returns Pins route. */ channelPins:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/pins`,\r\n /** Pins a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Pin route. */ channelPin:\r\n (channelId: string, messageId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/pins/${snowflake(messageId, \"Message ID\")}`,\r\n /** Creates a thread from a message. @param channelId Channel identifier. @param messageId Message identifier. @returns Message-thread route. */ messageThread:\r\n (channelId: string, messageId: string) =>\r\n `${Routes.message(channelId, messageId)}/threads`,\r\n /** Bulk deletes messages. @param channelId Channel identifier. @returns Bulk-delete route. */ channelBulkDelete:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/messages/bulk-delete`,\r\n /** Returns channel webhooks. @param channelId Channel identifier. @returns Webhook collection route. */ channelWebhooks:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/webhooks`,\r\n /** Returns channel invites. @param channelId Channel identifier. @returns Invite collection route. */ channelInvites:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/invites`,\r\n /** Returns a webhook. @param webhookId Webhook identifier. @param token Optional webhook token. @returns Webhook route. */ webhook:\r\n (webhookId: string, token?: string) =>\r\n `/webhooks/${snowflake(webhookId, \"Webhook ID\")}${token ? `/${encodeURIComponent(token)}` : \"\"}`,\r\n /** Returns a webhook message. */ webhookMessage: (\r\n webhookId: string,\r\n token: string,\r\n messageId: string,\r\n ) =>\r\n `/webhooks/${snowflake(webhookId, \"Webhook ID\")}/${encodeURIComponent(token)}/messages/${snowflake(messageId, \"Message ID\")}`,\r\n /** Returns application commands for an application. @param applicationId Application identifier. @returns Global command route. */ applicationCommands:\r\n (applicationId: string) =>\r\n `/applications/${snowflake(applicationId, \"Application ID\")}/commands`,\r\n /** Returns one application command. @param applicationId Application identifier. @param commandId Command identifier. @returns Command route. */ applicationCommand:\r\n (applicationId: string, commandId: string) =>\r\n `/applications/${snowflake(applicationId, \"Application ID\")}/commands/${snowflake(commandId, \"Command ID\")}`,\r\n /** Returns guild application commands. @param applicationId Application identifier. @param guildId Guild identifier. @returns Guild command route. */ guildApplicationCommands:\r\n (applicationId: string, guildId: string) =>\r\n `/applications/${snowflake(applicationId, \"Application ID\")}/guilds/${snowflake(guildId, \"Guild ID\")}/commands`,\r\n /** Returns a single guild application command. @param applicationId Application identifier. @param guildId Guild identifier. @param commandId Command identifier. @returns Guild command route. */ guildApplicationCommand:\r\n (applicationId: string, guildId: string, commandId: string) =>\r\n `/applications/${snowflake(applicationId, \"Application ID\")}/guilds/${snowflake(guildId, \"Guild ID\")}/commands/${snowflake(commandId, \"Command ID\")}`,\r\n /** Returns an interaction callback endpoint. @param interactionId Interaction identifier. @param token Interaction token. @returns Interaction callback route. */ interactionCallback:\r\n (interactionId: string, token: string) =>\r\n `/interactions/${snowflake(interactionId, \"Interaction ID\")}/${encodeURIComponent(token)}/callback`,\r\n /** Returns the original interaction response endpoint. @param applicationId Application identifier. @param token Interaction token. @returns Original-response route. */ interactionOriginalResponse:\r\n (applicationId: string, token: string) =>\r\n `/webhooks/${snowflake(applicationId, \"Application ID\")}/${encodeURIComponent(token)}/messages/@original`,\r\n\r\n /** Returns public archived threads for a channel. @param channelId Channel identifier. @returns Public-archive route. */ channelPublicArchivedThreads:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/threads/archived/public`,\r\n /** Returns private archived threads for a channel. @param channelId Channel identifier. @returns Private-archive route. */ channelPrivateArchivedThreads:\r\n (channelId: string) =>\r\n `/channels/${snowflake(channelId, \"Channel ID\")}/threads/archived/private`,\r\n /** Returns a thread's members. @param threadId Thread identifier. @returns Thread-member route. */ threadMembers:\r\n (threadId: string) =>\r\n `/channels/${snowflake(threadId, \"Thread ID\")}/thread-members`,\r\n /** Returns guild scheduled events. @param guildId Guild identifier. @returns Scheduled-event collection route. */ guildScheduledEvents:\r\n (guildId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/scheduled-events`,\r\n /** Returns one guild scheduled event. @param guildId Guild identifier. @param eventId Event identifier. @returns Scheduled-event route. */ guildScheduledEvent:\r\n (guildId: string, eventId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/scheduled-events/${snowflake(eventId, \"Event ID\")}`,\r\n /** Returns guild automod rules. @param guildId Guild identifier. @returns Automod-rule collection route. */ guildAutoModerationRules:\r\n (guildId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/auto-moderation/rules`,\r\n /** Returns one automod rule. @param guildId Guild identifier. @param ruleId Rule identifier. @returns Automod-rule route. */ guildAutoModerationRule:\r\n (guildId: string, ruleId: string) =>\r\n `/guilds/${snowflake(guildId, \"Guild ID\")}/auto-moderation/rules/${snowflake(ruleId, \"Rule ID\")}`,\r\n /** Returns current voice regions. @returns Voice-region route. */ voiceRegions:\r\n () => \"/voice/regions\",\r\n /** Returns the generic Gateway endpoint. @returns Gateway route. */ gateway:\r\n () => \"/gateway\",\r\n /** Returns the Gateway endpoint and recommended shard count for bots. @returns Gateway bot route. */ gatewayBot:\r\n () => \"/gateway/bot\",\r\n} as const;\r\n\r\n/** Validates a Discord snowflake route parameter. @param value Candidate identifier. @param field Human-readable field name. @returns The validated identifier. @throws {TypeError} If the identifier is not a Discord snowflake. */\r\nfunction snowflake(value: string, field: string): string {\r\n if (!/^\\d{1,20}$/.test(value))\r\n throw new TypeError(`${field} must be a valid Discord snowflake.`);\r\n return value;\r\n}\r\n",
6
6
  "import { REST } from \"./index.js\";\nimport { Routes } from \"./routes.js\";\nimport type { APIEmbed } from \"@lunibee/types\";\n\nexport interface WebhookClientOptions {\n id?: string;\n token?: string;\n url?: string;\n}\n\nexport interface WebhookMessageOptions {\n content?: string;\n username?: string;\n avatar_url?: string;\n tts?: boolean;\n embeds?: (APIEmbed | { toJSON(): APIEmbed })[];\n components?: any[];\n files?: any[];\n flags?: number;\n thread_id?: string;\n}\n\n/** Standalone client for sending Discord webhooks. */\nexport class WebhookClient {\n /** Webhook ID. */\n public readonly id: string;\n /** Webhook security token. */\n public readonly token: string;\n readonly #rest: REST;\n\n public constructor(\n options: WebhookClientOptions,\n restOptions?: { timeout?: number; retries?: number },\n ) {\n if (options.url) {\n const match = options.url.match(\n /discord(?:app)?.com\\/api\\/webhooks\\/(\\d+)\\/([A-Za-z0-9_-]+)/,\n );\n if (!match) throw new Error(\"Invalid Discord webhook URL format.\");\n this.id = match[1]!;\n this.token = match[2]!;\n } else if (options.id && options.token) {\n this.id = options.id;\n this.token = options.token;\n } else {\n throw new Error(\n \"WebhookClient requires either a webhook 'url' or both 'id' and 'token'.\",\n );\n }\n this.#rest = new REST(restOptions);\n }\n\n /** Sends a message to the webhook. */\n public async send(options: string | WebhookMessageOptions): Promise<any> {\n const payload =\n typeof options === \"string\" ? { content: options } : options;\n const { thread_id, ...body } = payload;\n const query = thread_id\n ? `?thread_id=${thread_id}&wait=true`\n : `?wait=true`;\n const formattedEmbeds = body.embeds?.map((e) =>\n typeof e === \"object\" && e !== null && \"toJSON\" in e\n ? (e as any).toJSON()\n : e,\n );\n return this.#rest.post(`${Routes.webhook(this.id, this.token)}${query}`, {\n ...body,\n embeds: formattedEmbeds,\n });\n }\n\n /** Edits a previously sent webhook message. */\n public async editMessage(\n messageId: string,\n options: string | { content?: string; embeds?: any[] },\n ): Promise<any> {\n const payload =\n typeof options === \"string\" ? { content: options } : options;\n return this.#rest.patch(\n Routes.webhookMessage(this.id, this.token, messageId),\n payload,\n );\n }\n\n /** Deletes a previously sent webhook message. */\n public async deleteMessage(messageId: string): Promise<void> {\n await this.#rest.delete(\n Routes.webhookMessage(this.id, this.token, messageId),\n );\n }\n}\n",
7
- "/** Error thrown when Discord rejects a REST request. */\nexport class RESTError extends Error {\n /** HTTP status returned by Discord. */ public readonly status: number;\n /** Discord API error code, when provided. */ public readonly code?: number;\n /** Raw Discord validation/error payload. */ public readonly errors?: unknown;\n /** HTTP method used for the failed request. */ public readonly method?: string;\n /** API path used for the failed request. */ public readonly path?: string;\n /** Creates a REST error with request context. @param message Error message. @param status HTTP status. @param code Discord error code. @param errors Raw error payload. @param options Request context and cause. */\n public constructor(\n message: string,\n status: number,\n code?: number,\n errors?: unknown,\n options: { method?: string; path?: string; cause?: unknown } = {},\n ) {\n super(\n message,\n options.cause === undefined ? undefined : { cause: options.cause },\n );\n this.name = \"RESTError\";\n this.status = status;\n this.code = code;\n this.errors = errors;\n this.method = options.method;\n this.path = options.path;\n }\n}\n\n/** Internal state shared by requests mapped to one Discord rate-limit bucket. */\ntype Bucket = { remaining: number; resetAt: number; queue: Promise<void> };\n/** Options controlling an individual REST request. */\nexport interface RESTRequestOptions {\n /** Abort signal used to cancel the request and any queued wait. */ signal?: AbortSignal;\n}\n\n/** Configures which REST failures may be retried. */\nexport interface RetryPolicy {\n /** Maximum retry attempts. */ maxRetries: number;\n /** Determines whether a request may be retried. @param method HTTP method. @param status HTTP status, or zero for transport errors. @returns True when retrying is safe under the policy. */ shouldRetry(\n method: string,\n status: number,\n ): boolean;\n /** Calculates delay before the next attempt. @param attempt Zero-based retry number. @param retryAfter Server-provided delay, when available. @returns Delay in milliseconds. */ getDelay(\n attempt: number,\n retryAfter?: number,\n ): number;\n}\n/** Creates the default conservative REST retry policy. @param maxRetries Maximum retries. @returns Retry policy that retries rate limits and idempotent transient failures. @throws {TypeError} If maxRetries is negative or not finite. */\nexport function createRetryPolicy(maxRetries = 2): RetryPolicy {\n if (!Number.isFinite(maxRetries) || maxRetries < 0)\n throw new TypeError(\"maxRetries must be a non-negative finite number.\");\n return {\n maxRetries: Math.floor(maxRetries),\n shouldRetry(method, status) {\n const normalized = method.toUpperCase();\n return (\n status === 429 ||\n (status >= 500 &&\n status <= 599 &&\n [\"GET\", \"HEAD\", \"PUT\", \"DELETE\"].includes(normalized))\n );\n },\n getDelay(attempt, retryAfter) {\n if (retryAfter !== undefined) return Math.max(0, retryAfter * 1000);\n return Math.min(10_000, 500 * 2 ** attempt) + Math.random() * 250;\n },\n };\n}\n\n/** Bun-native REST transport with Discord bucket-aware rate limiting, retries, and cancellation. */\nexport class REST {\n readonly #baseURL: string;\n readonly #timeout: number;\n readonly #retryPolicy: RetryPolicy;\n #token?: string;\n #globalResetAt = 0;\n readonly #buckets = new Map<string, Bucket>();\n readonly #routeBuckets = new Map<string, string>();\n /** Creates a REST transport. @param options Transport configuration. @throws {TypeError} If retry configuration is invalid. */\n public constructor(\n options: {\n token?: string;\n timeout?: number;\n retries?: number;\n retryPolicy?: RetryPolicy;\n baseURL?: string;\n } = {},\n ) {\n this.#token = options.token;\n this.#timeout = Math.max(1, options.timeout ?? 15_000);\n this.#retryPolicy =\n options.retryPolicy ?? createRetryPolicy(options.retries ?? 2);\n this.#baseURL = (options.baseURL ?? \"https://discord.com/api/v10\").replace(\n /\\/$/,\n \"\",\n );\n }\n /** Sets the authentication token. @param token Discord bot token. @returns Nothing. @throws {TypeError} If token is empty. */\n public setToken(token: string): void {\n if (!token.trim()) throw new TypeError(\"A Discord bot token is required.\");\n this.#token = token;\n }\n /** Executes an HTTP request with Discord bucket/global rate limits, retry handling, and AbortSignal support. @param method HTTP method. @param path API path. @param body Optional JSON body. @param options Cancellation options. @returns Decoded response body. @throws {RESTError} If Discord or transport rejects the request. */\n public async request<T>(\n method: string,\n path: string,\n body?: unknown,\n options: RESTRequestOptions = {},\n ): Promise<T> {\n const normalizedMethod = method.toUpperCase();\n if (!normalizedMethod) throw new TypeError(\"REST method is required.\");\n if (!path.startsWith(\"/\"))\n throw new TypeError(\"REST paths must start with '/'.\");\n const route = `${normalizedMethod}:${this.#normalizeRoute(path)}`;\n let bucketKey = this.#routeBuckets.get(route) ?? route;\n let bucket = this.#buckets.get(bucketKey) ?? {\n remaining: 1,\n resetAt: 0,\n queue: Promise.resolve(),\n };\n this.#buckets.set(bucketKey, bucket);\n const previous = bucket.queue;\n let release!: () => void;\n bucket.queue = new Promise((resolve) => {\n release = resolve;\n });\n await this.#abortable(previous, options.signal, path);\n try {\n for (\n let attempt = 0;\n attempt <= this.#retryPolicy.maxRetries;\n attempt++\n ) {\n await this.#wait(bucket, options.signal, path);\n await this.#waitGlobal(options.signal, path);\n const controller = new AbortController();\n const onAbort = () => controller.abort(options.signal?.reason);\n if (options.signal?.aborted)\n throw this.#abortError(path, options.signal.reason);\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n const timer = setTimeout(\n () =>\n controller.abort(\n new DOMException(\"REST request timeout\", \"TimeoutError\"),\n ),\n this.#timeout,\n );\n try {\n const response = await fetch(`${this.#baseURL}${path}`, {\n method: normalizedMethod,\n headers: {\n ...(this.#token ? { Authorization: `Bot ${this.#token}` } : {}),\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Lunibee/0.1.0\",\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: controller.signal,\n });\n bucket = this.#update(response, bucket, route, bucketKey);\n bucketKey = this.#routeBuckets.get(route) ?? bucketKey;\n const payload = await this.#readPayload(response);\n if (response.ok)\n return (response.status === 204 ? undefined : payload) as T;\n const data = this.#errorData(payload);\n const retryAfter =\n response.status === 429\n ? this.#retryAfter(response, data)\n : undefined;\n if (data.global && retryAfter !== undefined)\n this.#globalResetAt = Date.now() + retryAfter * 1000;\n if (\n attempt < this.#retryPolicy.maxRetries &&\n this.#retryPolicy.shouldRetry(normalizedMethod, response.status)\n ) {\n await this.#sleep(\n this.#retryPolicy.getDelay(attempt, retryAfter),\n options.signal,\n path,\n );\n continue;\n }\n throw new RESTError(\n data.message ??\n response.statusText ??\n `Discord REST request failed with status ${response.status}`,\n response.status,\n data.code,\n payload,\n { method: normalizedMethod, path },\n );\n } catch (error) {\n if (error instanceof RESTError) throw error;\n if (options.signal?.aborted)\n throw this.#abortError(path, options.signal.reason);\n const isTimeout =\n error instanceof DOMException &&\n (error.name === \"TimeoutError\" || error.name === \"AbortError\");\n if (\n !isTimeout &&\n attempt < this.#retryPolicy.maxRetries &&\n this.#retryPolicy.shouldRetry(normalizedMethod, 0)\n ) {\n await this.#sleep(\n this.#retryPolicy.getDelay(attempt),\n options.signal,\n path,\n );\n continue;\n }\n throw new RESTError(\n isTimeout\n ? `Discord REST request timed out after ${this.#timeout}ms`\n : \"Discord REST request failed\",\n 0,\n undefined,\n undefined,\n { method: normalizedMethod, path, cause: error },\n );\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n throw new RESTError(\n \"Discord REST request exhausted its retry attempts\",\n 0,\n undefined,\n undefined,\n { method: normalizedMethod, path },\n );\n } finally {\n release();\n }\n }\n /** Sends a GET request. @param path API path. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ public get<\n T,\n >(path: string, options?: RESTRequestOptions): Promise<T> {\n return this.request<T>(\"GET\", path, undefined, options);\n }\n /** Sends a POST request. @param path API path. @param body Optional JSON body. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ public post<\n T,\n >(path: string, body?: unknown, options?: RESTRequestOptions): Promise<T> {\n return this.request<T>(\"POST\", path, body, options);\n }\n /** Sends a PATCH request. @param path API path. @param body Optional JSON body. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ public patch<\n T,\n >(path: string, body?: unknown, options?: RESTRequestOptions): Promise<T> {\n return this.request<T>(\"PATCH\", path, body, options);\n }\n /** Sends a PUT request. @param path API path. @param body Optional JSON body. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ public put<\n T,\n >(path: string, body?: unknown, options?: RESTRequestOptions): Promise<T> {\n return this.request<T>(\"PUT\", path, body, options);\n }\n /** Sends a DELETE request. @param path API path. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ public delete<\n T,\n >(path: string, options?: RESTRequestOptions): Promise<T> {\n return this.request<T>(\"DELETE\", path, undefined, options);\n }\n /** Waits for a route bucket while respecting cancellation. @param bucket Bucket state. @param signal Optional cancellation signal. @param path Request path for error context. @returns Promise fulfilled when sending is permitted. @throws {RESTError} If the request is aborted. */\n async #wait(\n bucket: Bucket,\n signal: AbortSignal | undefined,\n path: string,\n ): Promise<void> {\n const delay = bucket.resetAt - Date.now();\n if (bucket.remaining <= 0 && delay > 0)\n await this.#sleep(delay, signal, path);\n }\n /** Waits for the global Discord rate limit while respecting cancellation. @param signal Optional cancellation signal. @param path Request path for error context. @returns Promise fulfilled when the global limit expires. @throws {RESTError} If the request is aborted. */\n async #waitGlobal(\n signal: AbortSignal | undefined,\n path: string,\n ): Promise<void> {\n const delay = this.#globalResetAt - Date.now();\n if (delay > 0) await this.#sleep(delay, signal, path);\n }\n /** Waits for a delay or aborts immediately. @param delay Delay in milliseconds. @param signal Optional cancellation signal. @param path Request path. @returns Promise fulfilled after delay. @throws {RESTError} If aborted. */\n async #sleep(\n delay: number,\n signal: AbortSignal | undefined,\n path: string,\n ): Promise<void> {\n if (delay <= 0) return;\n await new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, delay);\n const abort = () => {\n clearTimeout(timer);\n reject(this.#abortError(path, signal?.reason));\n };\n if (signal?.aborted) return abort();\n signal?.addEventListener(\"abort\", abort, { once: true });\n });\n }\n /** Waits for a queued request or aborts. @param promise Queue predecessor. @param signal Optional cancellation signal. @param path Request path. @returns Promise fulfilled when predecessor releases. @throws {RESTError} If aborted. */\n async #abortable(\n promise: Promise<void>,\n signal: AbortSignal | undefined,\n path: string,\n ): Promise<void> {\n if (!signal) return promise;\n if (signal.aborted) throw this.#abortError(path, signal.reason);\n return Promise.race([\n promise,\n new Promise<void>((_, reject) =>\n signal.addEventListener(\n \"abort\",\n () => reject(this.#abortError(path, signal.reason)),\n { once: true },\n ),\n ),\n ]);\n }\n /** Creates a consistent cancellation error. @param path Request path. @param reason Abort reason. @returns REST cancellation error. */\n #abortError(path: string, reason: unknown): RESTError {\n return new RESTError(\n reason instanceof Error\n ? reason.message\n : \"Discord REST request was aborted\",\n 0,\n undefined,\n undefined,\n { path, cause: reason },\n );\n }\n /** Reads a Discord response payload. @param response HTTP response. @returns JSON or text payload. */\n async #readPayload(response: Response): Promise<unknown> {\n if (response.status === 204) return undefined;\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"application/json\"))\n return response.json().catch(() => undefined);\n return response.text().catch(() => undefined);\n }\n /** Extracts retry metadata from a Discord payload. @param payload Response payload. @returns Normalized error metadata. */\n #errorData(payload: unknown): {\n message?: string;\n code?: number;\n retry_after?: number;\n global?: boolean;\n } {\n if (!payload || typeof payload !== \"object\") return {};\n const data = payload as Record<string, unknown>;\n return {\n message: typeof data.message === \"string\" ? data.message : undefined,\n code: typeof data.code === \"number\" ? data.code : undefined,\n retry_after:\n typeof data.retry_after === \"number\" ? data.retry_after : undefined,\n global: data.global === true,\n };\n }\n /** Resolves Retry-After from headers or JSON. @param response HTTP response. @param data Parsed response metadata. @returns Retry delay in seconds. */\n #retryAfter(response: Response, data: { retry_after?: number }): number {\n const header = Number(response.headers.get(\"Retry-After\"));\n const retryAfter =\n data.retry_after ?? (Number.isFinite(header) ? header : 1);\n return Math.max(0, retryAfter);\n }\n /** Normalizes Discord routes for stable bucket discovery. @param path API path. @returns Normalized route. */\n #normalizeRoute(path: string): string {\n const queryIndex = path.indexOf(\"?\");\n const routePath = queryIndex === -1 ? path : path.slice(0, queryIndex);\n return routePath.replace(/\\/\\d+(?=\\/|$)/g, \"/:id\");\n }\n /** Updates bucket state from Discord's rate-limit headers and records the server bucket hash. @param response HTTP response. @param bucket Current bucket. @param route Normalized local route key. @param bucketKey Current bucket identifier. @returns Bucket state used for subsequent attempts. */\n #update(\n response: Response,\n bucket: Bucket,\n route: string,\n bucketKey: string,\n ): Bucket {\n const serverBucket = response.headers.get(\"X-RateLimit-Bucket\");\n if (serverBucket) {\n this.#routeBuckets.set(route, serverBucket);\n if (serverBucket !== bucketKey) {\n const shared = this.#buckets.get(serverBucket) ?? bucket;\n this.#buckets.set(serverBucket, shared);\n bucket = shared;\n }\n }\n const remaining = Number(response.headers.get(\"X-RateLimit-Remaining\"));\n const resetAfter = Number(response.headers.get(\"X-RateLimit-Reset-After\"));\n const reset = Number(response.headers.get(\"X-RateLimit-Reset\"));\n if (Number.isFinite(remaining)) bucket.remaining = Math.max(0, remaining);\n if (Number.isFinite(resetAfter))\n bucket.resetAt = Date.now() + Math.max(0, resetAfter) * 1000;\n else if (Number.isFinite(reset)) bucket.resetAt = reset * 1000;\n if (response.status === 429) {\n const retryAfter = Number(response.headers.get(\"Retry-After\"));\n if (Number.isFinite(retryAfter))\n bucket.resetAt = Math.max(\n bucket.resetAt,\n Date.now() + retryAfter * 1000,\n );\n }\n if (response.headers.get(\"X-RateLimit-Global\") === \"true\") {\n const retryAfter = Number(response.headers.get(\"Retry-After\"));\n if (Number.isFinite(retryAfter))\n this.#globalResetAt = Math.max(\n this.#globalResetAt,\n Date.now() + retryAfter * 1000,\n );\n }\n return bucket;\n }\n}\n\nexport { Routes } from \"./routes.js\";\n\nexport {\n WebhookClient,\n type WebhookClientOptions,\n type WebhookMessageOptions,\n} from \"./webhook.js\";\n"
7
+ "/** Error thrown when Discord rejects a REST request. */\r\nexport class RESTError extends Error {\r\n /** HTTP status returned by Discord. */ public readonly status: number;\r\n /** Discord API error code, when provided. */ public readonly code?: number;\r\n /** Raw Discord validation/error payload. */ public readonly errors?: unknown;\r\n /** HTTP method used for the failed request. */ public readonly method?: string;\r\n /** API path used for the failed request. */ public readonly path?: string;\r\n /** Creates a REST error with request context. @param message Error message. @param status HTTP status. @param code Discord error code. @param errors Raw error payload. @param options Request context and cause. */\r\n public constructor(\r\n message: string,\r\n status: number,\r\n code?: number,\r\n errors?: unknown,\r\n options: { method?: string; path?: string; cause?: unknown } = {},\r\n ) {\r\n super(\r\n message,\r\n options.cause === undefined ? undefined : { cause: options.cause },\r\n );\r\n this.name = \"RESTError\";\r\n this.status = status;\r\n this.code = code;\r\n this.errors = errors;\r\n this.method = options.method;\r\n this.path = options.path;\r\n }\r\n}\r\n\r\n/** Library version and source URL used for the Discord-compliant User-Agent. */\r\nimport packageJson from \"../package.json\" with { type: \"json\" };\r\nconst LIBRARY_VERSION = packageJson.version;\r\nconst LIBRARY_URL = \"https://github.com/Ekretos/lunibee\";\r\nconst USER_AGENT = `DiscordBot (${LIBRARY_URL}, ${packageJson.version})`;\r\n\r\n/** Internal state shared by requests mapped to one Discord rate-limit bucket. */\r\ntype Bucket = { remaining: number; resetAt: number; queue: Promise<void> };\r\n/** Options controlling an individual REST request. */\r\nexport interface RESTRequestOptions {\r\n /** Abort signal used to cancel the request and any queued wait. */ signal?: AbortSignal;\r\n}\r\n\r\nexport interface RESTFileAttachment {\r\n name: string;\r\n data: Blob | Uint8Array | ArrayBuffer;\r\n contentType?: string;\r\n}\r\n\r\n/** Configures which REST failures may be retried. */\r\nexport interface RetryPolicy {\r\n /** Maximum retry attempts. */ maxRetries: number;\r\n /** Determines whether a request may be retried. @param method HTTP method. @param status HTTP status, or zero for transport errors. @returns True when retrying is safe under the policy. */ shouldRetry(\r\n method: string,\r\n status: number,\r\n ): boolean;\r\n /** Calculates delay before the next attempt. @param attempt Zero-based retry number. @param retryAfter Server-provided delay, when available. @returns Delay in milliseconds. */ getDelay(\r\n attempt: number,\r\n retryAfter?: number,\r\n ): number;\r\n}\r\n/** Creates the default conservative REST retry policy. @param maxRetries Maximum retries. @returns Retry policy that retries rate limits and idempotent transient failures. @throws {TypeError} If maxRetries is negative or not finite. */\r\nexport function createRetryPolicy(maxRetries = 2): RetryPolicy {\r\n if (!Number.isFinite(maxRetries) || maxRetries < 0)\r\n throw new TypeError(\"maxRetries must be a non-negative finite number.\");\r\n return {\r\n maxRetries: Math.floor(maxRetries),\r\n shouldRetry(method, status) {\r\n const normalized = method.toUpperCase();\r\n return (\r\n status === 429 ||\r\n (status >= 500 &&\r\n status <= 599 &&\r\n [\"GET\", \"HEAD\", \"PUT\", \"DELETE\"].includes(normalized))\r\n );\r\n },\r\n getDelay(attempt, retryAfter) {\r\n if (retryAfter !== undefined) return Math.max(0, retryAfter * 1000);\r\n return Math.min(10_000, 500 * 2 ** attempt) + Math.random() * 250;\r\n },\r\n };\r\n}\r\n\r\n/** Bun-native REST transport with Discord bucket-aware rate limiting, retries, and cancellation. */\r\nexport class REST {\r\n readonly #baseURL: string;\r\n readonly #timeout: number;\r\n readonly #retryPolicy: RetryPolicy;\r\n #token?: string;\r\n #globalResetAt = 0;\r\n readonly #buckets = new Map<string, Bucket>();\r\n readonly #routeBuckets = new Map<string, string>();\r\n /** Creates a REST transport. @param options Transport configuration. @throws {TypeError} If retry configuration is invalid. */\r\n public constructor(\r\n options: {\r\n token?: string;\r\n timeout?: number;\r\n retries?: number;\r\n retryPolicy?: RetryPolicy;\r\n baseURL?: string;\r\n } = {},\r\n ) {\r\n this.#token = options.token;\r\n this.#timeout = Math.max(1, options.timeout ?? 15_000);\r\n this.#retryPolicy =\r\n options.retryPolicy ?? createRetryPolicy(options.retries ?? 2);\r\n this.#baseURL = (options.baseURL ?? \"https://discord.com/api/v10\").replace(\r\n /\\/$/,\r\n \"\",\r\n );\r\n }\r\n /** Sets the authentication token. @param token Discord bot token. @returns Nothing. @throws {TypeError} If token is empty. */\r\n public setToken(token: string): void {\r\n if (!token.trim()) throw new TypeError(\"A Discord bot token is required.\");\r\n this.#token = token;\r\n }\r\n /** Executes an HTTP request with Discord bucket/global rate limits, retry handling, and AbortSignal support.\r\n * Accepts a JSON body, a FormData body (for file uploads), or undefined.\r\n * @param method HTTP method.\r\n * @param path API path.\r\n * @param body Optional JSON body, FormData for file uploads, or undefined.\r\n * @param options Cancellation options.\r\n * @returns Decoded response body.\r\n * @throws {RESTError} If Discord or transport rejects the request.\r\n */\r\n public async request<T>(\r\n method: string,\r\n path: string,\r\n body?: unknown,\r\n options: RESTRequestOptions = {},\r\n ): Promise<T> {\r\n const normalizedMethod = method.toUpperCase();\r\n if (!normalizedMethod) throw new TypeError(\"REST method is required.\");\r\n if (!path.startsWith(\"/\"))\r\n throw new TypeError(\"REST paths must start with '/'.\");\r\n const route = `${normalizedMethod}:${this.#normalizeRoute(path)}`;\r\n let bucketKey = this.#routeBuckets.get(route) ?? route;\r\n let bucket = this.#buckets.get(bucketKey) ?? {\r\n remaining: 1,\r\n resetAt: 0,\r\n queue: Promise.resolve(),\r\n };\r\n this.#buckets.set(bucketKey, bucket);\r\n const previous = bucket.queue;\r\n let release!: () => void;\r\n bucket.queue = new Promise((resolve) => {\r\n release = resolve;\r\n });\r\n await this.#abortable(previous, options.signal, path);\r\n try {\r\n for (\r\n let attempt = 0;\r\n attempt <= this.#retryPolicy.maxRetries;\r\n attempt++\r\n ) {\r\n await this.#wait(bucket, options.signal, path);\r\n await this.#waitGlobal(options.signal, path);\r\n const controller = new AbortController();\r\n const onAbort = () => controller.abort(options.signal?.reason);\r\n if (options.signal?.aborted)\r\n throw this.#abortError(path, options.signal.reason);\r\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\r\n const timer = setTimeout(\r\n () =>\r\n controller.abort(\r\n new DOMException(\"REST request timeout\", \"TimeoutError\"),\r\n ),\r\n this.#timeout,\r\n );\r\n // Build headers and body based on whether this is a multipart request\r\n const isFormData =\r\n typeof FormData !== \"undefined\" && body instanceof FormData;\r\n const headers: Record<string, string> = {\r\n ...(this.#token ? { Authorization: `Bot ${this.#token}` } : {}),\r\n \"User-Agent\": USER_AGENT,\r\n };\r\n if (!isFormData) headers[\"Content-Type\"] = \"application/json\";\r\n const fetchBody = isFormData\r\n ? (body as FormData)\r\n : body === undefined\r\n ? undefined\r\n : JSON.stringify(body);\r\n try {\r\n const response = await fetch(`${this.#baseURL}${path}`, {\r\n method: normalizedMethod,\r\n headers,\r\n body: fetchBody,\r\n signal: controller.signal,\r\n });\r\n bucket = this.#update(response, bucket, route, bucketKey);\r\n bucketKey = this.#routeBuckets.get(route) ?? bucketKey;\r\n const payload = await this.#readPayload(response);\r\n if (response.ok)\r\n return (response.status === 204 ? undefined : payload) as T;\r\n const data = this.#errorData(payload);\r\n const retryAfter =\r\n response.status === 429\r\n ? this.#retryAfter(response, data)\r\n : undefined;\r\n if (data.global && retryAfter !== undefined)\r\n this.#globalResetAt = Date.now() + retryAfter * 1000;\r\n if (\r\n attempt < this.#retryPolicy.maxRetries &&\r\n this.#retryPolicy.shouldRetry(normalizedMethod, response.status)\r\n ) {\r\n await this.#sleep(\r\n this.#retryPolicy.getDelay(attempt, retryAfter),\r\n options.signal,\r\n path,\r\n );\r\n continue;\r\n }\r\n throw new RESTError(\r\n data.message ??\r\n response.statusText ??\r\n `Discord REST request failed with status ${response.status}`,\r\n response.status,\r\n data.code,\r\n payload,\r\n { method: normalizedMethod, path },\r\n );\r\n } catch (error) {\r\n if (error instanceof RESTError) throw error;\r\n if (options.signal?.aborted)\r\n throw this.#abortError(path, options.signal.reason);\r\n const isTimeout =\r\n error instanceof DOMException &&\r\n (error.name === \"TimeoutError\" || error.name === \"AbortError\");\r\n if (\r\n !isTimeout &&\r\n attempt < this.#retryPolicy.maxRetries &&\r\n this.#retryPolicy.shouldRetry(normalizedMethod, 0)\r\n ) {\r\n await this.#sleep(\r\n this.#retryPolicy.getDelay(attempt),\r\n options.signal,\r\n path,\r\n );\r\n continue;\r\n }\r\n throw new RESTError(\r\n isTimeout\r\n ? `Discord REST request timed out after ${this.#timeout}ms`\r\n : \"Discord REST request failed\",\r\n 0,\r\n undefined,\r\n undefined,\r\n { method: normalizedMethod, path, cause: error },\r\n );\r\n } finally {\r\n clearTimeout(timer);\r\n options.signal?.removeEventListener(\"abort\", onAbort);\r\n }\r\n }\r\n throw new RESTError(\r\n \"Discord REST request exhausted its retry attempts\",\r\n 0,\r\n undefined,\r\n undefined,\r\n { method: normalizedMethod, path },\r\n );\r\n } finally {\r\n release();\r\n }\r\n }\r\n /** Sends a GET request. @param path API path. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ public get<\r\n T,\r\n >(path: string, options?: RESTRequestOptions): Promise<T> {\r\n return this.request<T>(\"GET\", path, undefined, options);\r\n }\r\n /** Sends a POST request. @param path API path. @param body Optional JSON body. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ public post<\r\n T,\r\n >(path: string, body?: unknown, options?: RESTRequestOptions): Promise<T> {\r\n return this.request<T>(\"POST\", path, body, options);\r\n }\r\n /** Sends a PATCH request. @param path API path. @param body Optional JSON body. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ public patch<\r\n T,\r\n >(path: string, body?: unknown, options?: RESTRequestOptions): Promise<T> {\r\n return this.request<T>(\"PATCH\", path, body, options);\r\n }\r\n /** Sends a PUT request. @param path API path. @param body Optional JSON body. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ public put<\r\n T,\r\n >(path: string, body?: unknown, options?: RESTRequestOptions): Promise<T> {\r\n return this.request<T>(\"PUT\", path, body, options);\r\n }\r\n /** Sends a DELETE request. @param path API path. @param options Cancellation options. @returns Decoded response. @throws {RESTError} When the request fails. */ public delete<\r\n T,\r\n >(path: string, options?: RESTRequestOptions): Promise<T> {\r\n return this.request<T>(\"DELETE\", path, undefined, options);\r\n }\r\n /**\r\n * Builds a multipart form with a JSON payload and file attachments.\r\n */\r\n #fileForm(payload: unknown, files: RESTFileAttachment[]): FormData {\r\n const form = new FormData();\r\n form.append(\"payload_json\", JSON.stringify(payload));\r\n for (let i = 0; i < files.length; i++) {\r\n const file = files[i]!;\r\n const blob =\r\n file.data instanceof Blob\r\n ? file.data\r\n : new Blob([file.data as ArrayBuffer], {\r\n type: file.contentType ?? \"application/octet-stream\",\r\n });\r\n form.append(`files[${i}]`, blob, file.name);\r\n }\r\n return form;\r\n }\r\n\r\n /**\r\n * Sends a multipart/form-data POST request for file uploads.\r\n * Attaches a JSON payload as `payload_json` and files as additional fields.\r\n * @param path API path.\r\n * @param payload JSON payload (e.g. message content, embeds).\r\n * @param files Array of file attachments.\r\n * @param options Cancellation options.\r\n * @returns Decoded response.\r\n * @throws {RESTError} When the request fails.\r\n */\r\n public postWithFiles<T>(\r\n path: string,\r\n payload: unknown,\r\n files: RESTFileAttachment[],\r\n options?: RESTRequestOptions,\r\n ): Promise<T> {\r\n return this.request<T>(\"POST\", path, this.#fileForm(payload, files), options);\r\n }\r\n\r\n /**\r\n * Sends a multipart/form-data PATCH request for editing messages with files.\r\n * @param path API path.\r\n * @param payload JSON payload.\r\n * @param files Array of file attachments.\r\n * @param options Cancellation options.\r\n * @returns Decoded response.\r\n * @throws {RESTError} When the request fails.\r\n */\r\n public patchWithFiles<T>(\r\n path: string,\r\n payload: unknown,\r\n files: RESTFileAttachment[],\r\n options?: RESTRequestOptions,\r\n ): Promise<T> {\r\n return this.request<T>(\"PATCH\", path, this.#fileForm(payload, files), options);\r\n }\r\n /** Waits for a route bucket while respecting cancellation. @param bucket Bucket state. @param signal Optional cancellation signal. @param path Request path for error context. @returns Promise fulfilled when sending is permitted. @throws {RESTError} If the request is aborted. */\r\n async #wait(\r\n bucket: Bucket,\r\n signal: AbortSignal | undefined,\r\n path: string,\r\n ): Promise<void> {\r\n const delay = bucket.resetAt - Date.now();\r\n if (bucket.remaining <= 0 && delay > 0)\r\n await this.#sleep(delay, signal, path);\r\n }\r\n /** Waits for the global Discord rate limit while respecting cancellation. @param signal Optional cancellation signal. @param path Request path for error context. @returns Promise fulfilled when the global limit expires. @throws {RESTError} If the request is aborted. */\r\n async #waitGlobal(\r\n signal: AbortSignal | undefined,\r\n path: string,\r\n ): Promise<void> {\r\n const delay = this.#globalResetAt - Date.now();\r\n if (delay > 0) await this.#sleep(delay, signal, path);\r\n }\r\n /** Waits for a delay or aborts immediately. @param delay Delay in milliseconds. @param signal Optional cancellation signal. @param path Request path. @returns Promise fulfilled after delay. @throws {RESTError} If aborted. */\r\n async #sleep(\r\n delay: number,\r\n signal: AbortSignal | undefined,\r\n path: string,\r\n ): Promise<void> {\r\n if (delay <= 0) return;\r\n await new Promise<void>((resolve, reject) => {\r\n const timer = setTimeout(resolve, delay);\r\n const abort = () => {\r\n clearTimeout(timer);\r\n reject(this.#abortError(path, signal?.reason));\r\n };\r\n if (signal?.aborted) return abort();\r\n signal?.addEventListener(\"abort\", abort, { once: true });\r\n });\r\n }\r\n /** Waits for a queued request or aborts. @param promise Queue predecessor. @param signal Optional cancellation signal. @param path Request path. @returns Promise fulfilled when predecessor releases. @throws {RESTError} If aborted. */\r\n async #abortable(\r\n promise: Promise<void>,\r\n signal: AbortSignal | undefined,\r\n path: string,\r\n ): Promise<void> {\r\n if (!signal) return promise;\r\n if (signal.aborted) throw this.#abortError(path, signal.reason);\r\n return Promise.race([\r\n promise,\r\n new Promise<void>((_, reject) =>\r\n signal.addEventListener(\r\n \"abort\",\r\n () => reject(this.#abortError(path, signal.reason)),\r\n { once: true },\r\n ),\r\n ),\r\n ]);\r\n }\r\n /** Creates a consistent cancellation error. @param path Request path. @param reason Abort reason. @returns REST cancellation error. */\r\n #abortError(path: string, reason: unknown): RESTError {\r\n return new RESTError(\r\n reason instanceof Error\r\n ? reason.message\r\n : \"Discord REST request was aborted\",\r\n 0,\r\n undefined,\r\n undefined,\r\n { path, cause: reason },\r\n );\r\n }\r\n /** Reads a Discord response payload. @param response HTTP response. @returns JSON or text payload. */\r\n async #readPayload(response: Response): Promise<unknown> {\r\n if (response.status === 204) return undefined;\r\n const contentType = response.headers.get(\"content-type\") ?? \"\";\r\n if (contentType.includes(\"application/json\"))\r\n return response.json().catch(() => undefined);\r\n return response.text().catch(() => undefined);\r\n }\r\n /** Extracts retry metadata from a Discord payload. @param payload Response payload. @returns Normalized error metadata. */\r\n #errorData(payload: unknown): {\r\n message?: string;\r\n code?: number;\r\n retry_after?: number;\r\n global?: boolean;\r\n } {\r\n if (!payload || typeof payload !== \"object\") return {};\r\n const data = payload as Record<string, unknown>;\r\n return {\r\n message: typeof data.message === \"string\" ? data.message : undefined,\r\n code: typeof data.code === \"number\" ? data.code : undefined,\r\n retry_after:\r\n typeof data.retry_after === \"number\" ? data.retry_after : undefined,\r\n global: data.global === true,\r\n };\r\n }\r\n /** Resolves Retry-After from headers or JSON. @param response HTTP response. @param data Parsed response metadata. @returns Retry delay in seconds. */\r\n #retryAfter(response: Response, data: { retry_after?: number }): number {\r\n const header = Number(response.headers.get(\"Retry-After\"));\r\n const retryAfter =\r\n data.retry_after ?? (Number.isFinite(header) ? header : 1);\r\n return Math.max(0, retryAfter);\r\n }\r\n /** Normalizes Discord routes for stable bucket discovery. @param path API path. @returns Normalized route. */\r\n #normalizeRoute(path: string): string {\r\n const queryIndex = path.indexOf(\"?\");\r\n const routePath = queryIndex === -1 ? path : path.slice(0, queryIndex);\r\n return routePath.replace(/\\/\\d+(?=\\/|$)/g, \"/:id\");\r\n }\r\n /** Updates bucket state from Discord's rate-limit headers and records the server bucket hash. @param response HTTP response. @param bucket Current bucket. @param route Normalized local route key. @param bucketKey Current bucket identifier. @returns Bucket state used for subsequent attempts. */\r\n #update(\r\n response: Response,\r\n bucket: Bucket,\r\n route: string,\r\n bucketKey: string,\r\n ): Bucket {\r\n const serverBucket = response.headers.get(\"X-RateLimit-Bucket\");\r\n if (serverBucket) {\r\n this.#routeBuckets.set(route, serverBucket);\r\n if (serverBucket !== bucketKey) {\r\n const shared = this.#buckets.get(serverBucket) ?? bucket;\r\n this.#buckets.set(serverBucket, shared);\r\n bucket = shared;\r\n }\r\n }\r\n const remaining = Number(response.headers.get(\"X-RateLimit-Remaining\"));\r\n const resetAfter = Number(response.headers.get(\"X-RateLimit-Reset-After\"));\r\n const reset = Number(response.headers.get(\"X-RateLimit-Reset\"));\r\n if (Number.isFinite(remaining)) bucket.remaining = Math.max(0, remaining);\r\n if (Number.isFinite(resetAfter))\r\n bucket.resetAt = Date.now() + Math.max(0, resetAfter) * 1000;\r\n else if (Number.isFinite(reset)) bucket.resetAt = reset * 1000;\r\n if (response.status === 429) {\r\n const retryAfter = Number(response.headers.get(\"Retry-After\"));\r\n if (Number.isFinite(retryAfter))\r\n bucket.resetAt = Math.max(\r\n bucket.resetAt,\r\n Date.now() + retryAfter * 1000,\r\n );\r\n }\r\n if (response.headers.get(\"X-RateLimit-Global\") === \"true\") {\r\n const retryAfter = Number(response.headers.get(\"Retry-After\"));\r\n if (Number.isFinite(retryAfter))\r\n this.#globalResetAt = Math.max(\r\n this.#globalResetAt,\r\n Date.now() + retryAfter * 1000,\r\n );\r\n }\r\n return bucket;\r\n }\r\n}\r\n\r\nexport { Routes } from \"./routes.js\";\r\n\r\nexport {\r\n WebhookClient,\r\n type WebhookClientOptions,\r\n type WebhookMessageOptions,\r\n} from \"./webhook.js\";\r\n"
8
8
  ],
9
- "mappings": "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",
10
- "debugId": "69F9FDE9A0B8ECD864756E2164756E21",
9
+ "mappings": "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",
10
+ "debugId": "429E85E3F97473C964756E2164756E21",
11
11
  "names": []
12
12
  }
@@ -3,6 +3,10 @@ export declare const Routes: {
3
3
  /** Returns the current bot user. @returns User route. */ readonly user: () => string;
4
4
  /** Returns one user. @param userId User identifier. @returns User route. */ readonly userById: (userId: string) => string;
5
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;
6
10
  /** Returns channels in a guild. @param guildId Guild identifier. @returns Channel collection route. */ readonly guildChannels: (guildId: string) => string;
7
11
  /** Returns a guild member. @param guildId Guild identifier. @param userId User identifier. @returns Guild-member route. */ readonly guildMember: (guildId: string, userId: string) => string;
8
12
  /** Returns all guild roles. @param guildId Guild identifier. @returns Guild-role route. */ readonly guildRoles: (guildId: string) => string;
@@ -30,7 +34,6 @@ export declare const Routes: {
30
34
  /** 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;
31
35
  /** Returns an interaction callback endpoint. @param interactionId Interaction identifier. @param token Interaction token. @returns Interaction callback route. */ readonly interactionCallback: (interactionId: string, token: string) => string;
32
36
  /** 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;
33
- /** Returns guild threads that are active. @param guildId Guild identifier. @returns Active-thread route. */ readonly guildActiveThreads: (guildId: string) => string;
34
37
  /** Returns public archived threads for a channel. @param channelId Channel identifier. @returns Public-archive route. */ readonly channelPublicArchivedThreads: (channelId: string) => string;
35
38
  /** Returns private archived threads for a channel. @param channelId Channel identifier. @returns Private-archive route. */ readonly channelPrivateArchivedThreads: (channelId: string) => string;
36
39
  /** Returns a thread's members. @param threadId Thread identifier. @returns Thread-member route. */ readonly threadMembers: (threadId: string) => string;
@@ -357,6 +357,9 @@ class Gateway {
357
357
  this.#setState("READY" /* Ready */);
358
358
  this.#emit("ready", data);
359
359
  }
360
+ this.#emit("RAW", { event: event ?? "UNKNOWN", data });
361
+ if (this.#closed)
362
+ return;
360
363
  this.#emit(event ?? "dispatch", data);
361
364
  }
362
365
  #handleHello(data) {
@@ -729,4 +732,4 @@ export {
729
732
  ShardManager
730
733
  };
731
734
 
732
- //# debugId=3D6EA7786F9CDC6964756E2164756E21
735
+ //# debugId=155A3557E58FD4CF64756E2164756E21