@buape/carbon 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/LICENSE +1 -1
  2. package/dist/package.json +12 -8
  3. package/dist/src/abstracts/BaseCommand.d.ts +19 -3
  4. package/dist/src/abstracts/BaseCommand.d.ts.map +1 -1
  5. package/dist/src/abstracts/BaseCommand.js +55 -3
  6. package/dist/src/abstracts/BaseCommand.js.map +1 -1
  7. package/dist/src/abstracts/BaseComponent.d.ts +2 -2
  8. package/dist/src/abstracts/BaseComponent.d.ts.map +1 -1
  9. package/dist/src/abstracts/BaseInteraction.d.ts +52 -0
  10. package/dist/src/abstracts/BaseInteraction.d.ts.map +1 -1
  11. package/dist/src/abstracts/BaseInteraction.js +43 -5
  12. package/dist/src/abstracts/BaseInteraction.js.map +1 -1
  13. package/dist/src/abstracts/BaseListener.d.ts +7 -4
  14. package/dist/src/abstracts/BaseListener.d.ts.map +1 -1
  15. package/dist/src/abstracts/BaseListener.js.map +1 -1
  16. package/dist/src/abstracts/BaseModalComponent.d.ts +3 -10
  17. package/dist/src/abstracts/BaseModalComponent.d.ts.map +1 -1
  18. package/dist/src/abstracts/BaseModalComponent.js.map +1 -1
  19. package/dist/src/abstracts/Plugin.d.ts +6 -0
  20. package/dist/src/abstracts/Plugin.d.ts.map +1 -1
  21. package/dist/src/abstracts/Plugin.js.map +1 -1
  22. package/dist/src/adapters/bun/index.d.ts +2 -2
  23. package/dist/src/adapters/bun/index.d.ts.map +1 -1
  24. package/dist/src/adapters/bun/index.js +6 -0
  25. package/dist/src/adapters/bun/index.js.map +1 -1
  26. package/dist/src/adapters/fetch/index.d.ts.map +1 -1
  27. package/dist/src/adapters/fetch/index.js +6 -0
  28. package/dist/src/adapters/fetch/index.js.map +1 -1
  29. package/dist/src/classes/Client.d.ts +111 -9
  30. package/dist/src/classes/Client.d.ts.map +1 -1
  31. package/dist/src/classes/Client.js +237 -23
  32. package/dist/src/classes/Client.js.map +1 -1
  33. package/dist/src/classes/EntryPointCommand.d.ts +11 -0
  34. package/dist/src/classes/EntryPointCommand.d.ts.map +1 -0
  35. package/dist/src/classes/EntryPointCommand.js +13 -0
  36. package/dist/src/classes/EntryPointCommand.js.map +1 -0
  37. package/dist/src/classes/Listener.d.ts +85 -83
  38. package/dist/src/classes/Listener.d.ts.map +1 -1
  39. package/dist/src/classes/Listener.js +14 -0
  40. package/dist/src/classes/Listener.js.map +1 -1
  41. package/dist/src/classes/Modal.d.ts +2 -3
  42. package/dist/src/classes/Modal.d.ts.map +1 -1
  43. package/dist/src/classes/Modal.js.map +1 -1
  44. package/dist/src/classes/RequestClient.d.ts +99 -8
  45. package/dist/src/classes/RequestClient.d.ts.map +1 -1
  46. package/dist/src/classes/RequestClient.js +406 -137
  47. package/dist/src/classes/RequestClient.js.map +1 -1
  48. package/dist/src/classes/components/Checkbox.d.ts +12 -0
  49. package/dist/src/classes/components/Checkbox.d.ts.map +1 -0
  50. package/dist/src/classes/components/Checkbox.js +20 -0
  51. package/dist/src/classes/components/Checkbox.js.map +1 -0
  52. package/dist/src/classes/components/CheckboxGroup.d.ts +24 -0
  53. package/dist/src/classes/components/CheckboxGroup.d.ts.map +1 -0
  54. package/dist/src/classes/components/CheckboxGroup.js +37 -0
  55. package/dist/src/classes/components/CheckboxGroup.js.map +1 -0
  56. package/dist/src/classes/components/Container.d.ts +6 -2
  57. package/dist/src/classes/components/Container.d.ts.map +1 -1
  58. package/dist/src/classes/components/Container.js +11 -0
  59. package/dist/src/classes/components/Container.js.map +1 -1
  60. package/dist/src/classes/components/File.d.ts +2 -2
  61. package/dist/src/classes/components/File.d.ts.map +1 -1
  62. package/dist/src/classes/components/File.js +4 -1
  63. package/dist/src/classes/components/File.js.map +1 -1
  64. package/dist/src/classes/components/FileUpload.d.ts +3 -2
  65. package/dist/src/classes/components/FileUpload.d.ts.map +1 -1
  66. package/dist/src/classes/components/FileUpload.js +2 -2
  67. package/dist/src/classes/components/FileUpload.js.map +1 -1
  68. package/dist/src/classes/components/Label.d.ts +9 -5
  69. package/dist/src/classes/components/Label.d.ts.map +1 -1
  70. package/dist/src/classes/components/Label.js +1 -2
  71. package/dist/src/classes/components/Label.js.map +1 -1
  72. package/dist/src/classes/components/MediaGallery.d.ts +8 -13
  73. package/dist/src/classes/components/MediaGallery.d.ts.map +1 -1
  74. package/dist/src/classes/components/MediaGallery.js +5 -0
  75. package/dist/src/classes/components/MediaGallery.js.map +1 -1
  76. package/dist/src/classes/components/RadioGroup.d.ts +24 -0
  77. package/dist/src/classes/components/RadioGroup.d.ts.map +1 -0
  78. package/dist/src/classes/components/RadioGroup.js +33 -0
  79. package/dist/src/classes/components/RadioGroup.js.map +1 -0
  80. package/dist/src/classes/components/Row.d.ts.map +1 -1
  81. package/dist/src/classes/components/Row.js +2 -3
  82. package/dist/src/classes/components/Row.js.map +1 -1
  83. package/dist/src/classes/components/Section.d.ts +4 -3
  84. package/dist/src/classes/components/Section.d.ts.map +1 -1
  85. package/dist/src/classes/components/Section.js +22 -0
  86. package/dist/src/classes/components/Section.js.map +1 -1
  87. package/dist/src/classes/components/TextDisplay.d.ts +2 -2
  88. package/dist/src/classes/components/TextDisplay.d.ts.map +1 -1
  89. package/dist/src/classes/components/TextDisplay.js +3 -0
  90. package/dist/src/classes/components/TextDisplay.js.map +1 -1
  91. package/dist/src/classes/components/Thumbnail.d.ts +3 -2
  92. package/dist/src/classes/components/Thumbnail.d.ts.map +1 -1
  93. package/dist/src/classes/components/Thumbnail.js +11 -0
  94. package/dist/src/classes/components/Thumbnail.js.map +1 -1
  95. package/dist/src/errors/RatelimitError.d.ts +4 -1
  96. package/dist/src/errors/RatelimitError.d.ts.map +1 -1
  97. package/dist/src/errors/RatelimitError.js +7 -1
  98. package/dist/src/errors/RatelimitError.js.map +1 -1
  99. package/dist/src/index.d.ts +4 -0
  100. package/dist/src/index.d.ts.map +1 -1
  101. package/dist/src/index.js +4 -0
  102. package/dist/src/index.js.map +1 -1
  103. package/dist/src/internals/AutocompleteInteraction.d.ts +1 -1
  104. package/dist/src/internals/AutocompleteInteraction.d.ts.map +1 -1
  105. package/dist/src/internals/BoundedExecutor.d.ts +12 -0
  106. package/dist/src/internals/BoundedExecutor.d.ts.map +1 -0
  107. package/dist/src/internals/BoundedExecutor.js +60 -0
  108. package/dist/src/internals/BoundedExecutor.js.map +1 -0
  109. package/dist/src/internals/CommandHandler.d.ts.map +1 -1
  110. package/dist/src/internals/CommandHandler.js +53 -6
  111. package/dist/src/internals/CommandHandler.js.map +1 -1
  112. package/dist/src/internals/CommandInteraction.d.ts +4 -0
  113. package/dist/src/internals/CommandInteraction.d.ts.map +1 -1
  114. package/dist/src/internals/CommandInteraction.js +30 -0
  115. package/dist/src/internals/CommandInteraction.js.map +1 -1
  116. package/dist/src/internals/ComponentHandler.d.ts +5 -10
  117. package/dist/src/internals/ComponentHandler.d.ts.map +1 -1
  118. package/dist/src/internals/ComponentHandler.js +53 -38
  119. package/dist/src/internals/ComponentHandler.js.map +1 -1
  120. package/dist/src/internals/EmojiHandler.d.ts.map +1 -1
  121. package/dist/src/internals/EmojiHandler.js +0 -1
  122. package/dist/src/internals/EmojiHandler.js.map +1 -1
  123. package/dist/src/internals/EventHandler.d.ts +28 -2
  124. package/dist/src/internals/EventHandler.d.ts.map +1 -1
  125. package/dist/src/internals/EventHandler.js +14 -11
  126. package/dist/src/internals/EventHandler.js.map +1 -1
  127. package/dist/src/internals/EventQueue.d.ts +90 -0
  128. package/dist/src/internals/EventQueue.d.ts.map +1 -0
  129. package/dist/src/internals/EventQueue.js +363 -0
  130. package/dist/src/internals/EventQueue.js.map +1 -0
  131. package/dist/src/internals/FieldsHandler.d.ts.map +1 -1
  132. package/dist/src/internals/FieldsHandler.js +10 -1
  133. package/dist/src/internals/FieldsHandler.js.map +1 -1
  134. package/dist/src/internals/OptionsHandler.d.ts +9 -1
  135. package/dist/src/internals/OptionsHandler.d.ts.map +1 -1
  136. package/dist/src/internals/OptionsHandler.js +20 -1
  137. package/dist/src/internals/OptionsHandler.js.map +1 -1
  138. package/dist/src/internals/RequestBody.d.ts +6 -0
  139. package/dist/src/internals/RequestBody.d.ts.map +1 -0
  140. package/dist/src/internals/RequestBody.js +74 -0
  141. package/dist/src/internals/RequestBody.js.map +1 -0
  142. package/dist/src/internals/RequestScheduler.d.ts +131 -0
  143. package/dist/src/internals/RequestScheduler.d.ts.map +1 -0
  144. package/dist/src/internals/RequestScheduler.js +245 -0
  145. package/dist/src/internals/RequestScheduler.js.map +1 -0
  146. package/dist/src/internals/TemporaryListenerManager.d.ts +20 -0
  147. package/dist/src/internals/TemporaryListenerManager.d.ts.map +1 -0
  148. package/dist/src/internals/TemporaryListenerManager.js +59 -0
  149. package/dist/src/internals/TemporaryListenerManager.js.map +1 -0
  150. package/dist/src/permissions.d.ts +1 -0
  151. package/dist/src/permissions.d.ts.map +1 -1
  152. package/dist/src/plugins/client-manager/ClientManager.d.ts +30 -2
  153. package/dist/src/plugins/client-manager/ClientManager.d.ts.map +1 -1
  154. package/dist/src/plugins/client-manager/ClientManager.js +93 -16
  155. package/dist/src/plugins/client-manager/ClientManager.js.map +1 -1
  156. package/dist/src/plugins/cloudflare-gateway/CloudflareGatewayDurableObject.d.ts +43 -0
  157. package/dist/src/plugins/cloudflare-gateway/CloudflareGatewayDurableObject.d.ts.map +1 -0
  158. package/dist/src/plugins/cloudflare-gateway/CloudflareGatewayDurableObject.js +210 -0
  159. package/dist/src/plugins/cloudflare-gateway/CloudflareGatewayDurableObject.js.map +1 -0
  160. package/dist/src/plugins/cloudflare-gateway/CloudflareGatewayPlugin.d.ts +16 -0
  161. package/dist/src/plugins/cloudflare-gateway/CloudflareGatewayPlugin.d.ts.map +1 -0
  162. package/dist/src/plugins/cloudflare-gateway/CloudflareGatewayPlugin.js +129 -0
  163. package/dist/src/plugins/cloudflare-gateway/CloudflareGatewayPlugin.js.map +1 -0
  164. package/dist/src/plugins/cloudflare-gateway/index.d.ts +4 -0
  165. package/dist/src/plugins/cloudflare-gateway/index.d.ts.map +1 -0
  166. package/dist/src/plugins/cloudflare-gateway/index.js +4 -0
  167. package/dist/src/plugins/cloudflare-gateway/index.js.map +1 -0
  168. package/dist/src/plugins/cloudflare-gateway/types.d.ts +63 -0
  169. package/dist/src/plugins/cloudflare-gateway/types.d.ts.map +1 -0
  170. package/dist/src/plugins/cloudflare-gateway/types.js +2 -0
  171. package/dist/src/plugins/cloudflare-gateway/types.js.map +1 -0
  172. package/dist/src/plugins/gateway/BabyCache.d.ts +13 -4
  173. package/dist/src/plugins/gateway/BabyCache.d.ts.map +1 -1
  174. package/dist/src/plugins/gateway/BabyCache.js +47 -0
  175. package/dist/src/plugins/gateway/BabyCache.js.map +1 -1
  176. package/dist/src/plugins/gateway/GatewayPlugin.d.ts +111 -19
  177. package/dist/src/plugins/gateway/GatewayPlugin.d.ts.map +1 -1
  178. package/dist/src/plugins/gateway/GatewayPlugin.js +605 -234
  179. package/dist/src/plugins/gateway/GatewayPlugin.js.map +1 -1
  180. package/dist/src/plugins/gateway/types.d.ts +33 -1
  181. package/dist/src/plugins/gateway/types.d.ts.map +1 -1
  182. package/dist/src/plugins/gateway/types.js +21 -0
  183. package/dist/src/plugins/gateway/types.js.map +1 -1
  184. package/dist/src/plugins/gateway/utils/heartbeat.d.ts +1 -0
  185. package/dist/src/plugins/gateway/utils/heartbeat.d.ts.map +1 -1
  186. package/dist/src/plugins/gateway/utils/heartbeat.js +23 -12
  187. package/dist/src/plugins/gateway/utils/heartbeat.js.map +1 -1
  188. package/dist/src/plugins/gateway/utils/payload.d.ts.map +1 -1
  189. package/dist/src/plugins/gateway/utils/payload.js +0 -4
  190. package/dist/src/plugins/gateway/utils/payload.js.map +1 -1
  191. package/dist/src/plugins/gateway-forwarder/GatewayForwarderPlugin.d.ts +56 -3
  192. package/dist/src/plugins/gateway-forwarder/GatewayForwarderPlugin.d.ts.map +1 -1
  193. package/dist/src/plugins/gateway-forwarder/GatewayForwarderPlugin.js +224 -17
  194. package/dist/src/plugins/gateway-forwarder/GatewayForwarderPlugin.js.map +1 -1
  195. package/dist/src/plugins/paginator/index.d.ts +1 -1
  196. package/dist/src/plugins/paginator/index.d.ts.map +1 -1
  197. package/dist/src/plugins/paginator/index.js +1 -1
  198. package/dist/src/plugins/paginator/index.js.map +1 -1
  199. package/dist/src/plugins/voice/GuildDeleteListener.d.ts +7 -0
  200. package/dist/src/plugins/voice/GuildDeleteListener.d.ts.map +1 -0
  201. package/dist/src/plugins/voice/GuildDeleteListener.js +11 -0
  202. package/dist/src/plugins/voice/GuildDeleteListener.js.map +1 -0
  203. package/dist/src/plugins/voice/VoicePlugin.d.ts +15 -0
  204. package/dist/src/plugins/voice/VoicePlugin.d.ts.map +1 -0
  205. package/dist/src/plugins/voice/VoicePlugin.js +58 -0
  206. package/dist/src/plugins/voice/VoicePlugin.js.map +1 -0
  207. package/dist/src/plugins/voice/VoiceServerUpdateListener.d.ts +10 -0
  208. package/dist/src/plugins/voice/VoiceServerUpdateListener.d.ts.map +1 -0
  209. package/dist/src/plugins/voice/VoiceServerUpdateListener.js +16 -0
  210. package/dist/src/plugins/voice/VoiceServerUpdateListener.js.map +1 -0
  211. package/dist/src/plugins/voice/VoiceStateUpdateListener.d.ts +10 -0
  212. package/dist/src/plugins/voice/VoiceStateUpdateListener.d.ts.map +1 -0
  213. package/dist/src/plugins/voice/VoiceStateUpdateListener.js +21 -0
  214. package/dist/src/plugins/voice/VoiceStateUpdateListener.js.map +1 -0
  215. package/dist/src/plugins/voice/index.d.ts +2 -0
  216. package/dist/src/plugins/voice/index.d.ts.map +1 -0
  217. package/dist/src/plugins/voice/index.js +2 -0
  218. package/dist/src/plugins/voice/index.js.map +1 -0
  219. package/dist/src/structures/DmChannel.d.ts +4 -0
  220. package/dist/src/structures/DmChannel.d.ts.map +1 -1
  221. package/dist/src/structures/DmChannel.js +6 -0
  222. package/dist/src/structures/DmChannel.js.map +1 -1
  223. package/dist/src/structures/GroupDmChannel.d.ts +4 -0
  224. package/dist/src/structures/GroupDmChannel.d.ts.map +1 -1
  225. package/dist/src/structures/GroupDmChannel.js +6 -0
  226. package/dist/src/structures/GroupDmChannel.js.map +1 -1
  227. package/dist/src/structures/Guild.js +1 -1
  228. package/dist/src/structures/Guild.js.map +1 -1
  229. package/dist/src/structures/GuildMember.d.ts +10 -5
  230. package/dist/src/structures/GuildMember.d.ts.map +1 -1
  231. package/dist/src/structures/GuildMember.js.map +1 -1
  232. package/dist/src/structures/Poll.d.ts +1 -1
  233. package/dist/src/structures/Poll.d.ts.map +1 -1
  234. package/dist/src/structures/User.d.ts +1 -1
  235. package/dist/src/structures/User.d.ts.map +1 -1
  236. package/dist/src/structures/User.js +3 -3
  237. package/dist/src/structures/User.js.map +1 -1
  238. package/dist/src/structures/Webhook.d.ts +4 -2
  239. package/dist/src/structures/Webhook.d.ts.map +1 -1
  240. package/dist/src/structures/Webhook.js +42 -29
  241. package/dist/src/structures/Webhook.js.map +1 -1
  242. package/dist/src/types/commandMiddleware.d.ts +64 -0
  243. package/dist/src/types/commandMiddleware.d.ts.map +1 -0
  244. package/dist/src/types/commandMiddleware.js +2 -0
  245. package/dist/src/types/commandMiddleware.js.map +1 -0
  246. package/dist/src/types/index.d.ts +58 -1
  247. package/dist/src/types/index.d.ts.map +1 -1
  248. package/dist/src/types/index.js +1 -0
  249. package/dist/src/types/index.js.map +1 -1
  250. package/dist/src/types/listeners.d.ts +15 -4
  251. package/dist/src/types/listeners.d.ts.map +1 -1
  252. package/dist/src/types/listeners.js.map +1 -1
  253. package/dist/src/utils/LRUCache.d.ts +46 -0
  254. package/dist/src/utils/LRUCache.d.ts.map +1 -0
  255. package/dist/src/utils/LRUCache.js +78 -0
  256. package/dist/src/utils/LRUCache.js.map +1 -0
  257. package/dist/src/utils/customIdParser.d.ts.map +1 -1
  258. package/dist/src/utils/customIdParser.js +6 -2
  259. package/dist/src/utils/customIdParser.js.map +1 -1
  260. package/dist/src/utils/payload.d.ts.map +1 -1
  261. package/dist/src/utils/payload.js +18 -1
  262. package/dist/src/utils/payload.js.map +1 -1
  263. package/dist/tsconfig.tsbuildinfo +1 -1
  264. package/package.json +12 -8
  265. package/dist/src/classes/ApplicationManager.d.ts +0 -88
  266. package/dist/src/classes/ApplicationManager.d.ts.map +0 -1
  267. package/dist/src/classes/ApplicationManager.js +0 -179
  268. package/dist/src/classes/ApplicationManager.js.map +0 -1
  269. package/dist/src/classes/ClientWithCaching.d.ts +0 -51
  270. package/dist/src/classes/ClientWithCaching.d.ts.map +0 -1
  271. package/dist/src/classes/ClientWithCaching.js +0 -108
  272. package/dist/src/classes/ClientWithCaching.js.map +0 -1
  273. package/dist/src/classes/components/ModalChannelSelectMenu.d.ts +0 -62
  274. package/dist/src/classes/components/ModalChannelSelectMenu.d.ts.map +0 -1
  275. package/dist/src/classes/components/ModalChannelSelectMenu.js +0 -73
  276. package/dist/src/classes/components/ModalChannelSelectMenu.js.map +0 -1
  277. package/dist/src/classes/components/ModalMentionableSelectMenu.d.ts +0 -58
  278. package/dist/src/classes/components/ModalMentionableSelectMenu.d.ts.map +0 -1
  279. package/dist/src/classes/components/ModalMentionableSelectMenu.js +0 -68
  280. package/dist/src/classes/components/ModalMentionableSelectMenu.js.map +0 -1
  281. package/dist/src/classes/components/ModalRoleSelectMenu.d.ts +0 -58
  282. package/dist/src/classes/components/ModalRoleSelectMenu.d.ts.map +0 -1
  283. package/dist/src/classes/components/ModalRoleSelectMenu.js +0 -68
  284. package/dist/src/classes/components/ModalRoleSelectMenu.js.map +0 -1
  285. package/dist/src/classes/components/ModalStringSelectMenu.d.ts +0 -58
  286. package/dist/src/classes/components/ModalStringSelectMenu.d.ts.map +0 -1
  287. package/dist/src/classes/components/ModalStringSelectMenu.js +0 -64
  288. package/dist/src/classes/components/ModalStringSelectMenu.js.map +0 -1
  289. package/dist/src/classes/components/ModalUserSelectMenu.d.ts +0 -58
  290. package/dist/src/classes/components/ModalUserSelectMenu.d.ts.map +0 -1
  291. package/dist/src/classes/components/ModalUserSelectMenu.js +0 -68
  292. package/dist/src/classes/components/ModalUserSelectMenu.js.map +0 -1
  293. package/dist/src/internals/Cache.d.ts +0 -76
  294. package/dist/src/internals/Cache.d.ts.map +0 -1
  295. package/dist/src/internals/Cache.js +0 -122
  296. package/dist/src/internals/Cache.js.map +0 -1
  297. package/dist/src/plugins/multi-app/ApplicationManager.d.ts +0 -120
  298. package/dist/src/plugins/multi-app/ApplicationManager.d.ts.map +0 -1
  299. package/dist/src/plugins/multi-app/ApplicationManager.js +0 -207
  300. package/dist/src/plugins/multi-app/ApplicationManager.js.map +0 -1
  301. package/dist/src/plugins/multi-app/index.d.ts +0 -2
  302. package/dist/src/plugins/multi-app/index.d.ts.map +0 -1
  303. package/dist/src/plugins/multi-app/index.js +0 -2
  304. package/dist/src/plugins/multi-app/index.js.map +0 -1
@@ -1,12 +1,16 @@
1
1
  import { DiscordError } from "../errors/DiscordError.js";
2
2
  import { RateLimitError } from "../errors/RatelimitError.js";
3
+ import { serializeRequestBody } from "../internals/RequestBody.js";
4
+ import { normalizeRequestSchedulerOptions, RequestScheduler } from "../internals/RequestScheduler.js";
3
5
  const defaultOptions = {
4
6
  tokenHeader: "Bot",
5
7
  baseUrl: "https://discord.com/api",
6
8
  apiVersion: 10,
7
9
  userAgent: "DiscordBot (https://github.com/buape/carbon, v0.0.0)",
8
10
  timeout: 15000,
9
- queueRequests: true
11
+ queueRequests: true,
12
+ maxQueueSize: 1000,
13
+ runtimeProfile: "serverless"
10
14
  };
11
15
  /**
12
16
  * This is the main class that handles making requests to the Discord API.
@@ -17,23 +21,28 @@ export class RequestClient {
17
21
  * The options used to initialize the client
18
22
  */
19
23
  options;
20
- queue = [];
21
24
  token;
22
- rateLimitResetTime;
23
- abortController = null;
25
+ customFetch;
26
+ nextRequestId = 0;
27
+ wakeupTimer = null;
28
+ wakeupDueAt = null;
29
+ activeWorkers = 0;
30
+ activeBucketKeys = new Set();
31
+ maxConcurrentWorkers = 1;
32
+ maxRateLimitRetries = 2;
33
+ scheduler;
34
+ routeBuckets = new Map();
35
+ bucketStates = new Map();
36
+ globalRateLimitUntil = 0;
37
+ requestControllers = new Set();
24
38
  constructor(token, options) {
25
39
  this.token = token;
40
+ this.customFetch = options?.fetch;
26
41
  this.options = {
27
42
  ...defaultOptions,
28
43
  ...options
29
44
  };
30
- this.rateLimitResetTime = 0;
31
- }
32
- async waitForRateLimit() {
33
- const delay = this.rateLimitResetTime - Date.now();
34
- if (delay > 0) {
35
- await new Promise((resolve) => setTimeout(resolve, delay));
36
- }
45
+ this.configureScheduler();
37
46
  }
38
47
  async get(path, query) {
39
48
  return await this.request("GET", path, { query });
@@ -50,178 +59,438 @@ export class RequestClient {
50
59
  async delete(path, data, query) {
51
60
  return await this.request("DELETE", path, { data, query });
52
61
  }
62
+ configureScheduler() {
63
+ const normalized = normalizeRequestSchedulerOptions({
64
+ runtimeProfile: this.options.runtimeProfile ?? "serverless",
65
+ maxQueueSize: this.options.maxQueueSize,
66
+ scheduler: this.options.scheduler
67
+ });
68
+ this.maxConcurrentWorkers = normalized.maxConcurrency;
69
+ this.maxRateLimitRetries = normalized.maxRateLimitRetries;
70
+ this.scheduler = new RequestScheduler({
71
+ lanes: normalized.lanes
72
+ });
73
+ }
53
74
  async request(method, path, { data, query }) {
54
- if (this.options.queueRequests) {
75
+ const routeKey = this.getRouteKey(method, path);
76
+ if (!this.options.queueRequests) {
55
77
  return new Promise((resolve, reject) => {
56
- this.queue.push({ method, path, data, query, resolve, reject });
57
- this.processQueue();
78
+ this.executeRequest({
79
+ id: this.nextRequestId++,
80
+ method,
81
+ path,
82
+ data,
83
+ query,
84
+ resolve,
85
+ reject,
86
+ routeKey,
87
+ priority: this.getPriority(method, path),
88
+ enqueuedAt: Date.now(),
89
+ retryCount: 0
90
+ })
91
+ .then(resolve)
92
+ .catch((err) => {
93
+ reject(err);
94
+ });
58
95
  });
59
96
  }
60
97
  return new Promise((resolve, reject) => {
61
- this.executeRequest({ method, path, data, query, resolve, reject })
62
- .then(resolve)
63
- .catch((err) => {
64
- reject(err);
98
+ const priority = this.getPriority(method, path);
99
+ const enqueueError = this.enqueueRequest({
100
+ id: this.nextRequestId++,
101
+ method,
102
+ path,
103
+ data,
104
+ query,
105
+ resolve,
106
+ reject,
107
+ routeKey,
108
+ priority,
109
+ enqueuedAt: Date.now(),
110
+ retryCount: 0
65
111
  });
112
+ if (enqueueError) {
113
+ reject(enqueueError);
114
+ return;
115
+ }
116
+ this.pumpQueue();
66
117
  });
67
118
  }
119
+ enqueueRequest(request) {
120
+ return this.scheduler.enqueue(request);
121
+ }
122
+ pumpQueue() {
123
+ if (!this.options.queueRequests)
124
+ return;
125
+ while (this.activeWorkers < this.maxConcurrentWorkers) {
126
+ const next = this.takeNextReadyRequest();
127
+ if (!next)
128
+ return;
129
+ this.activeWorkers += 1;
130
+ const bucketKey = this.getCurrentBucketKey(next.routeKey);
131
+ this.activeBucketKeys.add(bucketKey);
132
+ this.runQueuedRequest(next)
133
+ .catch((error) => {
134
+ console.error("[RequestClient] Queue worker failed", error);
135
+ })
136
+ .finally(() => {
137
+ this.activeBucketKeys.delete(bucketKey);
138
+ this.activeWorkers -= 1;
139
+ this.pumpQueue();
140
+ });
141
+ }
142
+ }
143
+ async runQueuedRequest(request) {
144
+ try {
145
+ const result = await this.executeRequest(request);
146
+ request.resolve(result);
147
+ }
148
+ catch (error) {
149
+ if (error instanceof RateLimitError &&
150
+ this.options.queueRequests &&
151
+ request.retryCount < this.maxRateLimitRetries) {
152
+ const enqueueError = this.enqueueRequest({
153
+ ...request,
154
+ retryCount: request.retryCount + 1,
155
+ enqueuedAt: Date.now()
156
+ });
157
+ if (enqueueError) {
158
+ request.reject(enqueueError);
159
+ return;
160
+ }
161
+ return;
162
+ }
163
+ if (error instanceof Error) {
164
+ request.reject(error);
165
+ return;
166
+ }
167
+ request.reject(new Error("Unknown error during request", { cause: error }));
168
+ }
169
+ }
170
+ takeNextReadyRequest() {
171
+ const next = this.scheduler.takeNext({
172
+ isRouteReady: (routeKey) => this.getRouteWaitTime(routeKey),
173
+ isBucketActive: (routeKey) => this.activeBucketKeys.has(this.getCurrentBucketKey(routeKey))
174
+ });
175
+ if (!next.request) {
176
+ if (next.waitMs !== null) {
177
+ this.scheduleWakeup(next.waitMs);
178
+ }
179
+ return null;
180
+ }
181
+ this.clearWakeupTimer();
182
+ return next.request;
183
+ }
184
+ scheduleWakeup(waitMs) {
185
+ if (waitMs <= 0) {
186
+ this.clearWakeupTimer();
187
+ this.pumpQueue();
188
+ return;
189
+ }
190
+ const dueAt = Date.now() + waitMs;
191
+ if (this.wakeupTimer &&
192
+ this.wakeupDueAt !== null &&
193
+ this.wakeupDueAt <= dueAt) {
194
+ return;
195
+ }
196
+ if (this.wakeupTimer) {
197
+ clearTimeout(this.wakeupTimer);
198
+ this.wakeupTimer = null;
199
+ }
200
+ this.wakeupDueAt = dueAt;
201
+ this.wakeupTimer = setTimeout(() => {
202
+ this.wakeupTimer = null;
203
+ this.wakeupDueAt = null;
204
+ this.pumpQueue();
205
+ }, Math.max(0, dueAt - Date.now()));
206
+ }
207
+ clearWakeupTimer() {
208
+ if (!this.wakeupTimer) {
209
+ this.wakeupDueAt = null;
210
+ return;
211
+ }
212
+ clearTimeout(this.wakeupTimer);
213
+ this.wakeupTimer = null;
214
+ this.wakeupDueAt = null;
215
+ }
216
+ getRouteWaitTime(routeKey, now = Date.now()) {
217
+ if (this.globalRateLimitUntil > now) {
218
+ return this.globalRateLimitUntil - now;
219
+ }
220
+ const bucketKey = this.getCurrentBucketKey(routeKey);
221
+ const bucket = this.bucketStates.get(bucketKey);
222
+ if (bucket && bucket.delayUntil > now) {
223
+ return bucket.delayUntil - now;
224
+ }
225
+ return 0;
226
+ }
227
+ getPriority(method, path) {
228
+ const normalizedPath = path.toLowerCase();
229
+ const normalizedMethod = method.toUpperCase();
230
+ if (/^\/interactions\/\d+\/[^/]+\/callback$/.test(normalizedPath)) {
231
+ return "critical";
232
+ }
233
+ if (normalizedPath.startsWith("/webhooks/") &&
234
+ (normalizedMethod === "POST" ||
235
+ normalizedMethod === "PATCH" ||
236
+ normalizedMethod === "DELETE")) {
237
+ return "standard";
238
+ }
239
+ if (normalizedMethod !== "GET" &&
240
+ /\/channels\/\d+\/messages/.test(normalizedPath)) {
241
+ return "standard";
242
+ }
243
+ return "background";
244
+ }
68
245
  async executeRequest(request) {
69
- await this.waitForRateLimit();
70
- const { method, path, data, query } = request;
246
+ const { method, path, data, query, routeKey } = request;
247
+ await this.waitForBucket(routeKey);
71
248
  const queryString = query
72
249
  ? `?${Object.entries(query)
73
250
  .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
74
251
  .join("&")}`
75
252
  : "";
76
253
  const url = `${this.options.baseUrl}${path}${queryString}`;
254
+ const originalRequest = new Request(url, { method });
77
255
  const headers = this.token === "webhook"
78
256
  ? new Headers()
79
257
  : new Headers({
80
258
  Authorization: `${this.options.tokenHeader} ${this.token}`
81
259
  });
82
- // Add custom headers if provided
83
260
  if (data?.headers) {
84
261
  for (const [key, value] of Object.entries(data.headers)) {
85
262
  headers.set(key, value);
86
263
  }
87
264
  }
88
- this.abortController = new AbortController();
89
- let body;
90
- if (data?.body &&
91
- typeof data.body === "object" &&
92
- ("files" in data.body ||
93
- ("data" in data.body &&
94
- data.body.data &&
95
- typeof data.body.data === "object" &&
96
- "files" in data.body.data))) {
97
- const payload = data.body;
98
- if (typeof payload === "string") {
99
- data.body = { content: payload, attachments: [] };
100
- }
101
- else {
102
- data.body = { ...payload, attachments: [] };
103
- }
104
- const formData = new FormData();
105
- const files = (() => {
106
- if (typeof payload === "object" && payload !== null) {
107
- if ("files" in payload) {
108
- return payload.files || [];
109
- }
110
- if ("data" in payload &&
111
- typeof payload.data === "object" &&
112
- payload.data !== null) {
113
- return (payload.data
114
- .files || []);
115
- }
116
- }
117
- return [];
118
- })();
119
- for (const [index, file] of files.entries()) {
120
- let { data: fileData } = file;
121
- if (!(fileData instanceof Blob)) {
122
- fileData = new Blob([fileData]);
123
- }
124
- formData.append(`files[${index}]`, fileData, file.name);
125
- data.body.attachments.push({
126
- id: index,
127
- filename: file.name,
128
- description: file.description
129
- });
130
- }
131
- if (data.body != null) {
132
- const cleanedBody = {
133
- ...data.body,
134
- files: undefined
135
- };
136
- formData.append("payload_json", JSON.stringify(cleanedBody));
265
+ const abortController = new AbortController();
266
+ this.requestControllers.add(abortController);
267
+ const timeoutMs = typeof this.options.timeout === "number" && this.options.timeout > 0
268
+ ? this.options.timeout
269
+ : undefined;
270
+ const body = serializeRequestBody(data, headers);
271
+ let timeoutId;
272
+ if (timeoutMs !== undefined) {
273
+ timeoutId = setTimeout(() => {
274
+ abortController.abort();
275
+ }, timeoutMs);
276
+ }
277
+ let response;
278
+ const fetchFn = this.customFetch ?? fetch;
279
+ try {
280
+ response = await fetchFn(url, {
281
+ method,
282
+ headers,
283
+ body,
284
+ signal: abortController.signal
285
+ });
286
+ }
287
+ finally {
288
+ if (timeoutId) {
289
+ clearTimeout(timeoutId);
137
290
  }
138
- body = formData;
291
+ this.requestControllers.delete(abortController);
292
+ }
293
+ let rawBody = "";
294
+ let parsedBody;
295
+ try {
296
+ rawBody = await response.text();
297
+ }
298
+ catch {
299
+ rawBody = "";
139
300
  }
140
- else if (data?.body != null) {
141
- headers.set("Content-Type", "application/json");
142
- if (data.rawBody) {
143
- body = data.body;
301
+ if (rawBody.length > 0) {
302
+ try {
303
+ parsedBody = JSON.parse(rawBody);
144
304
  }
145
- else {
146
- body = JSON.stringify(data.body);
305
+ catch {
306
+ parsedBody = undefined;
147
307
  }
148
308
  }
149
- const response = await fetch(url, {
150
- method,
151
- headers,
152
- body,
153
- signal: this.abortController.signal
154
- });
155
309
  if (response.status === 429) {
156
- const responseBody = await response.json();
157
- const rateLimitError = new RateLimitError(response, responseBody);
158
- if (this.options.queueRequests) {
159
- const rateLimitResetTime = Number(response.headers.get("Retry-After")) * 1000;
160
- this.rateLimitResetTime = Date.now() + rateLimitResetTime;
161
- if (rateLimitError.scope === "global") {
162
- await new Promise((res) => setTimeout(res, rateLimitResetTime));
163
- this.queue.unshift(request);
164
- }
165
- }
310
+ const rateLimitBody = parsedBody &&
311
+ typeof parsedBody === "object" &&
312
+ "retry_after" in parsedBody &&
313
+ "message" in parsedBody
314
+ ? parsedBody
315
+ : {
316
+ message: typeof parsedBody === "string"
317
+ ? parsedBody
318
+ : rawBody || "You are being rate limited.",
319
+ retry_after: (() => {
320
+ const retryAfterHeader = response.headers.get("Retry-After");
321
+ if (retryAfterHeader &&
322
+ !Number.isNaN(Number(retryAfterHeader))) {
323
+ return Number(retryAfterHeader);
324
+ }
325
+ return 1;
326
+ })(),
327
+ global: response.headers.get("X-RateLimit-Scope") === "global"
328
+ };
329
+ const rateLimitError = new RateLimitError(response, rateLimitBody, originalRequest);
330
+ this.scheduleRateLimit(routeKey, path, rateLimitError);
166
331
  throw rateLimitError;
167
332
  }
333
+ this.updateBucketFromHeaders(routeKey, path, response);
168
334
  if (response.status >= 400 && response.status < 600) {
169
- throw new DiscordError(response, await response.json());
170
- }
171
- try {
172
- return await response.json();
335
+ const discordErrorBody = parsedBody && typeof parsedBody === "object"
336
+ ? parsedBody
337
+ : {
338
+ message: rawBody || "Discord API error",
339
+ code: 0
340
+ };
341
+ throw new DiscordError(response, discordErrorBody);
173
342
  }
174
- catch (err) {
175
- if (err instanceof SyntaxError) {
176
- // If there is no JSON
177
- return await response.text();
343
+ if (parsedBody !== undefined)
344
+ return parsedBody;
345
+ if (rawBody.length > 0)
346
+ return rawBody;
347
+ return null;
348
+ }
349
+ async waitForBucket(routeKey) {
350
+ while (true) {
351
+ const now = Date.now();
352
+ if (this.globalRateLimitUntil > now) {
353
+ await sleep(this.globalRateLimitUntil - now);
354
+ continue;
355
+ }
356
+ const bucketKey = this.routeBuckets.get(routeKey) ?? routeKey;
357
+ const bucket = this.bucketStates.get(bucketKey);
358
+ if (bucket && bucket.delayUntil > now) {
359
+ await sleep(bucket.delayUntil - now);
360
+ continue;
178
361
  }
179
- throw err;
362
+ break;
180
363
  }
181
364
  }
182
- async processQueue() {
183
- if (this.queue.length === 0)
184
- return;
185
- const queueItem = this.queue.shift();
186
- if (!queueItem)
365
+ scheduleRateLimit(routeKey, path, error) {
366
+ const bucketKey = error.bucket
367
+ ? this.getBucketKey(routeKey, path, error.bucket)
368
+ : this.getCurrentBucketKey(routeKey);
369
+ const waitTime = Math.max(0, Math.ceil(error.retryAfter * 1000));
370
+ const now = Date.now();
371
+ const bucket = this.bucketStates.get(bucketKey) ?? {
372
+ delayUntil: 0,
373
+ extraBackoff: 0,
374
+ remaining: 0
375
+ };
376
+ const existingDelayPassed = bucket.delayUntil <= now;
377
+ const extraBackoff = existingDelayPassed
378
+ ? Math.min(bucket.extraBackoff ? bucket.extraBackoff * 2 : 1000, 60_000)
379
+ : (bucket.extraBackoff ?? 0);
380
+ const nextAvailable = now + waitTime + extraBackoff;
381
+ this.bucketStates.set(bucketKey, {
382
+ delayUntil: nextAvailable,
383
+ extraBackoff,
384
+ remaining: 0
385
+ });
386
+ this.routeBuckets.set(routeKey, bucketKey);
387
+ if (error.scope === "global") {
388
+ this.globalRateLimitUntil = nextAvailable;
389
+ }
390
+ }
391
+ updateBucketFromHeaders(routeKey, path, response) {
392
+ const bucketId = response.headers.get("X-RateLimit-Bucket");
393
+ const remainingRaw = response.headers.get("X-RateLimit-Remaining");
394
+ const resetAfterRaw = response.headers.get("X-RateLimit-Reset-After");
395
+ const hasInfo = !!bucketId || !!remainingRaw || !!resetAfterRaw;
396
+ if (!hasInfo)
187
397
  return;
188
- const { method, path, data, query, resolve, reject } = queueItem;
189
- try {
190
- const result = await this.executeRequest({
191
- method,
192
- path,
193
- data,
194
- query,
195
- resolve,
196
- reject
197
- });
198
- resolve(result);
398
+ const key = bucketId
399
+ ? this.getBucketKey(routeKey, path, bucketId)
400
+ : this.getCurrentBucketKey(routeKey);
401
+ if (bucketId)
402
+ this.routeBuckets.set(routeKey, key);
403
+ const remaining = remainingRaw ? Number(remainingRaw) : undefined;
404
+ const resetAfter = resetAfterRaw ? Number(resetAfterRaw) * 1000 : undefined;
405
+ const now = Date.now();
406
+ const bucket = this.bucketStates.get(key) ?? {
407
+ delayUntil: 0,
408
+ extraBackoff: 0,
409
+ remaining: 1
410
+ };
411
+ if (typeof remaining === "number" && !Number.isNaN(remaining)) {
412
+ bucket.remaining = remaining;
199
413
  }
200
- catch (error) {
201
- if (error instanceof RateLimitError &&
202
- this.options.queueRequests &&
203
- error.scope === "global") {
204
- this.queue.unshift(queueItem);
414
+ if (typeof resetAfter === "number" &&
415
+ !Number.isNaN(resetAfter) &&
416
+ bucket.remaining <= 0) {
417
+ bucket.delayUntil = now + resetAfter;
418
+ }
419
+ else if (bucket.remaining > 0) {
420
+ bucket.delayUntil = 0;
421
+ }
422
+ bucket.extraBackoff = 0;
423
+ this.bucketStates.set(key, bucket);
424
+ }
425
+ getCurrentBucketKey(routeKey) {
426
+ return this.routeBuckets.get(routeKey) ?? routeKey;
427
+ }
428
+ getBucketKey(routeKey, path, bucketId) {
429
+ if (!bucketId)
430
+ return routeKey;
431
+ const major = this.getMajorParameter(path);
432
+ return major ? `${bucketId}:${major}` : bucketId;
433
+ }
434
+ getMajorParameter(path) {
435
+ const segments = path.split("/");
436
+ for (let index = 0; index < segments.length; index += 1) {
437
+ const segment = segments[index];
438
+ const prev = segments[index - 1];
439
+ if (prev === "channels" || prev === "guilds") {
440
+ return segment;
205
441
  }
206
- else {
207
- if (error instanceof Error) {
208
- reject(error);
209
- }
210
- else {
211
- reject(new Error("Unknown error during request", { cause: error }));
212
- }
442
+ if (prev === "webhooks") {
443
+ const webhookToken = segments[index + 1];
444
+ return webhookToken ? `${segment}/${webhookToken}` : segment;
213
445
  }
214
446
  }
215
- finally {
216
- this.abortController = null;
217
- this.processQueue();
218
- }
447
+ return null;
448
+ }
449
+ getRouteKey(method, path) {
450
+ const segments = path.split("/");
451
+ const normalized = segments
452
+ .map((segment, index) => {
453
+ if (!/^\d{16,}$/.test(segment))
454
+ return segment;
455
+ const prev = segments[index - 1];
456
+ if (prev && ["channels", "guilds"].includes(prev)) {
457
+ return segment;
458
+ }
459
+ if (prev === "webhooks") {
460
+ return segment;
461
+ }
462
+ if (segments[index - 2] === "webhooks") {
463
+ return segment;
464
+ }
465
+ return ":id";
466
+ })
467
+ .join("/");
468
+ return `${method}:${normalized}`;
469
+ }
470
+ clearQueue() {
471
+ this.scheduler.clear(new Error("Request queue cleared"));
472
+ }
473
+ get queueSize() {
474
+ return this.scheduler.size;
475
+ }
476
+ getSchedulerMetrics() {
477
+ const schedulerMetrics = this.scheduler.getMetrics();
478
+ return {
479
+ queueSize: this.queueSize,
480
+ activeWorkers: this.activeWorkers,
481
+ maxConcurrentWorkers: this.maxConcurrentWorkers,
482
+ ...schedulerMetrics,
483
+ globalRateLimitUntil: this.globalRateLimitUntil,
484
+ activeBuckets: this.activeBucketKeys.size
485
+ };
219
486
  }
220
487
  abortAllRequests() {
221
- if (this.abortController) {
222
- this.abortController.abort();
488
+ for (const controller of this.requestControllers) {
489
+ controller.abort();
223
490
  }
224
- this.queue = [];
491
+ this.requestControllers.clear();
492
+ this.clearQueue();
225
493
  }
226
494
  }
495
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, Math.max(ms, 0)));
227
496
  //# sourceMappingURL=RequestClient.js.map