@neontechspace/fluxerly 1000.0.0-nightly.12

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 (1319) hide show
  1. package/CHANGELOG.md +833 -0
  2. package/LICENSE +201 -0
  3. package/README.md +129 -0
  4. package/agents/AGENTS.md +195 -0
  5. package/dist/api/default/application.d.ts +34 -0
  6. package/dist/api/default/application.d.ts.map +1 -0
  7. package/dist/api/default/application.js +2 -0
  8. package/dist/api/default/application.js.map +1 -0
  9. package/dist/api/default/attachments.d.ts +89 -0
  10. package/dist/api/default/attachments.d.ts.map +1 -0
  11. package/dist/api/default/attachments.js +2 -0
  12. package/dist/api/default/attachments.js.map +1 -0
  13. package/dist/api/default/audit-logs.d.ts +48 -0
  14. package/dist/api/default/audit-logs.d.ts.map +1 -0
  15. package/dist/api/default/audit-logs.js +2 -0
  16. package/dist/api/default/audit-logs.js.map +1 -0
  17. package/dist/api/default/bot.d.ts +200 -0
  18. package/dist/api/default/bot.d.ts.map +1 -0
  19. package/dist/api/default/bot.js +309 -0
  20. package/dist/api/default/bot.js.map +1 -0
  21. package/dist/api/default/cache.d.ts +105 -0
  22. package/dist/api/default/cache.d.ts.map +1 -0
  23. package/dist/api/default/cache.js +2 -0
  24. package/dist/api/default/cache.js.map +1 -0
  25. package/dist/api/default/channels.d.ts +249 -0
  26. package/dist/api/default/channels.d.ts.map +1 -0
  27. package/dist/api/default/channels.js +2 -0
  28. package/dist/api/default/channels.js.map +1 -0
  29. package/dist/api/default/client.d.ts +528 -0
  30. package/dist/api/default/client.d.ts.map +1 -0
  31. package/dist/api/default/client.js +301 -0
  32. package/dist/api/default/client.js.map +1 -0
  33. package/dist/api/default/collectors.d.ts +76 -0
  34. package/dist/api/default/collectors.d.ts.map +1 -0
  35. package/dist/api/default/collectors.js +2 -0
  36. package/dist/api/default/collectors.js.map +1 -0
  37. package/dist/api/default/commands.d.ts +91 -0
  38. package/dist/api/default/commands.d.ts.map +1 -0
  39. package/dist/api/default/commands.js +92 -0
  40. package/dist/api/default/commands.js.map +1 -0
  41. package/dist/api/default/direct-messages.d.ts +111 -0
  42. package/dist/api/default/direct-messages.d.ts.map +1 -0
  43. package/dist/api/default/direct-messages.js +2 -0
  44. package/dist/api/default/direct-messages.js.map +1 -0
  45. package/dist/api/default/discovery.d.ts +76 -0
  46. package/dist/api/default/discovery.d.ts.map +1 -0
  47. package/dist/api/default/discovery.js +2 -0
  48. package/dist/api/default/discovery.js.map +1 -0
  49. package/dist/api/default/emojis.d.ts +88 -0
  50. package/dist/api/default/emojis.d.ts.map +1 -0
  51. package/dist/api/default/emojis.js +2 -0
  52. package/dist/api/default/emojis.js.map +1 -0
  53. package/dist/api/default/events.d.ts +127 -0
  54. package/dist/api/default/events.d.ts.map +1 -0
  55. package/dist/api/default/events.js +2 -0
  56. package/dist/api/default/events.js.map +1 -0
  57. package/dist/api/default/gateway.d.ts +62 -0
  58. package/dist/api/default/gateway.d.ts.map +1 -0
  59. package/dist/api/default/gateway.js +2 -0
  60. package/dist/api/default/gateway.js.map +1 -0
  61. package/dist/api/default/guards.d.ts +87 -0
  62. package/dist/api/default/guards.d.ts.map +1 -0
  63. package/dist/api/default/guards.js +78 -0
  64. package/dist/api/default/guards.js.map +1 -0
  65. package/dist/api/default/guilds.d.ts +230 -0
  66. package/dist/api/default/guilds.d.ts.map +1 -0
  67. package/dist/api/default/guilds.js +2 -0
  68. package/dist/api/default/guilds.js.map +1 -0
  69. package/dist/api/default/helpers.d.ts +79 -0
  70. package/dist/api/default/helpers.d.ts.map +1 -0
  71. package/dist/api/default/helpers.js +79 -0
  72. package/dist/api/default/helpers.js.map +1 -0
  73. package/dist/api/default/instance.d.ts +47 -0
  74. package/dist/api/default/instance.d.ts.map +1 -0
  75. package/dist/api/default/instance.js +2 -0
  76. package/dist/api/default/instance.js.map +1 -0
  77. package/dist/api/default/invites.d.ts +57 -0
  78. package/dist/api/default/invites.d.ts.map +1 -0
  79. package/dist/api/default/invites.js +2 -0
  80. package/dist/api/default/invites.js.map +1 -0
  81. package/dist/api/default/logging.d.ts +37 -0
  82. package/dist/api/default/logging.d.ts.map +1 -0
  83. package/dist/api/default/logging.js +2 -0
  84. package/dist/api/default/logging.js.map +1 -0
  85. package/dist/api/default/members.d.ts +442 -0
  86. package/dist/api/default/members.d.ts.map +1 -0
  87. package/dist/api/default/members.js +2 -0
  88. package/dist/api/default/members.js.map +1 -0
  89. package/dist/api/default/messages.d.ts +898 -0
  90. package/dist/api/default/messages.d.ts.map +1 -0
  91. package/dist/api/default/messages.js +2 -0
  92. package/dist/api/default/messages.js.map +1 -0
  93. package/dist/api/default/oauth.d.ts +168 -0
  94. package/dist/api/default/oauth.d.ts.map +1 -0
  95. package/dist/api/default/oauth.js +84 -0
  96. package/dist/api/default/oauth.js.map +1 -0
  97. package/dist/api/default/permissions.d.ts +44 -0
  98. package/dist/api/default/permissions.d.ts.map +1 -0
  99. package/dist/api/default/permissions.js +2 -0
  100. package/dist/api/default/permissions.js.map +1 -0
  101. package/dist/api/default/presence.d.ts +88 -0
  102. package/dist/api/default/presence.d.ts.map +1 -0
  103. package/dist/api/default/presence.js +2 -0
  104. package/dist/api/default/presence.js.map +1 -0
  105. package/dist/api/default/rest.d.ts +28 -0
  106. package/dist/api/default/rest.d.ts.map +1 -0
  107. package/dist/api/default/rest.js +2 -0
  108. package/dist/api/default/rest.js.map +1 -0
  109. package/dist/api/default/results.d.ts +31 -0
  110. package/dist/api/default/results.d.ts.map +1 -0
  111. package/dist/api/default/results.js +14 -0
  112. package/dist/api/default/results.js.map +1 -0
  113. package/dist/api/default/roles.d.ts +119 -0
  114. package/dist/api/default/roles.d.ts.map +1 -0
  115. package/dist/api/default/roles.js +2 -0
  116. package/dist/api/default/roles.js.map +1 -0
  117. package/dist/api/default/stickers.d.ts +92 -0
  118. package/dist/api/default/stickers.d.ts.map +1 -0
  119. package/dist/api/default/stickers.js +2 -0
  120. package/dist/api/default/stickers.js.map +1 -0
  121. package/dist/api/default/supervisor.d.ts +51 -0
  122. package/dist/api/default/supervisor.d.ts.map +1 -0
  123. package/dist/api/default/supervisor.js +53 -0
  124. package/dist/api/default/supervisor.js.map +1 -0
  125. package/dist/api/default/threads.d.ts +158 -0
  126. package/dist/api/default/threads.d.ts.map +1 -0
  127. package/dist/api/default/threads.js +2 -0
  128. package/dist/api/default/threads.js.map +1 -0
  129. package/dist/api/default/users.d.ts +73 -0
  130. package/dist/api/default/users.d.ts.map +1 -0
  131. package/dist/api/default/users.js +2 -0
  132. package/dist/api/default/users.js.map +1 -0
  133. package/dist/api/default/webhook-client.d.ts +149 -0
  134. package/dist/api/default/webhook-client.d.ts.map +1 -0
  135. package/dist/api/default/webhook-client.js +69 -0
  136. package/dist/api/default/webhook-client.js.map +1 -0
  137. package/dist/api/default/webhooks.d.ts +62 -0
  138. package/dist/api/default/webhooks.d.ts.map +1 -0
  139. package/dist/api/default/webhooks.js +2 -0
  140. package/dist/api/default/webhooks.js.map +1 -0
  141. package/dist/api/effect/application.d.ts +29 -0
  142. package/dist/api/effect/application.d.ts.map +1 -0
  143. package/dist/api/effect/application.js +2 -0
  144. package/dist/api/effect/application.js.map +1 -0
  145. package/dist/api/effect/attachments.d.ts +84 -0
  146. package/dist/api/effect/attachments.d.ts.map +1 -0
  147. package/dist/api/effect/attachments.js +2 -0
  148. package/dist/api/effect/attachments.js.map +1 -0
  149. package/dist/api/effect/audit-logs.d.ts +42 -0
  150. package/dist/api/effect/audit-logs.d.ts.map +1 -0
  151. package/dist/api/effect/audit-logs.js +2 -0
  152. package/dist/api/effect/audit-logs.js.map +1 -0
  153. package/dist/api/effect/bot.d.ts +233 -0
  154. package/dist/api/effect/bot.d.ts.map +1 -0
  155. package/dist/api/effect/bot.js +230 -0
  156. package/dist/api/effect/bot.js.map +1 -0
  157. package/dist/api/effect/cache.d.ts +103 -0
  158. package/dist/api/effect/cache.d.ts.map +1 -0
  159. package/dist/api/effect/cache.js +2 -0
  160. package/dist/api/effect/cache.js.map +1 -0
  161. package/dist/api/effect/channels.d.ts +231 -0
  162. package/dist/api/effect/channels.d.ts.map +1 -0
  163. package/dist/api/effect/channels.js +2 -0
  164. package/dist/api/effect/channels.js.map +1 -0
  165. package/dist/api/effect/client.d.ts +622 -0
  166. package/dist/api/effect/client.d.ts.map +1 -0
  167. package/dist/api/effect/client.js +191 -0
  168. package/dist/api/effect/client.js.map +1 -0
  169. package/dist/api/effect/collectors.d.ts +90 -0
  170. package/dist/api/effect/collectors.d.ts.map +1 -0
  171. package/dist/api/effect/collectors.js +2 -0
  172. package/dist/api/effect/collectors.js.map +1 -0
  173. package/dist/api/effect/commands.d.ts +86 -0
  174. package/dist/api/effect/commands.d.ts.map +1 -0
  175. package/dist/api/effect/commands.js +87 -0
  176. package/dist/api/effect/commands.js.map +1 -0
  177. package/dist/api/effect/direct-messages.d.ts +102 -0
  178. package/dist/api/effect/direct-messages.d.ts.map +1 -0
  179. package/dist/api/effect/direct-messages.js +2 -0
  180. package/dist/api/effect/direct-messages.js.map +1 -0
  181. package/dist/api/effect/discovery.d.ts +68 -0
  182. package/dist/api/effect/discovery.d.ts.map +1 -0
  183. package/dist/api/effect/discovery.js +2 -0
  184. package/dist/api/effect/discovery.js.map +1 -0
  185. package/dist/api/effect/emojis.d.ts +77 -0
  186. package/dist/api/effect/emojis.d.ts.map +1 -0
  187. package/dist/api/effect/emojis.js +2 -0
  188. package/dist/api/effect/emojis.js.map +1 -0
  189. package/dist/api/effect/events.d.ts +78 -0
  190. package/dist/api/effect/events.d.ts.map +1 -0
  191. package/dist/api/effect/events.js +12 -0
  192. package/dist/api/effect/events.js.map +1 -0
  193. package/dist/api/effect/failures.d.ts +14 -0
  194. package/dist/api/effect/failures.d.ts.map +1 -0
  195. package/dist/api/effect/failures.js +2 -0
  196. package/dist/api/effect/failures.js.map +1 -0
  197. package/dist/api/effect/gateway.d.ts +63 -0
  198. package/dist/api/effect/gateway.d.ts.map +1 -0
  199. package/dist/api/effect/gateway.js +2 -0
  200. package/dist/api/effect/gateway.js.map +1 -0
  201. package/dist/api/effect/guards.d.ts +91 -0
  202. package/dist/api/effect/guards.d.ts.map +1 -0
  203. package/dist/api/effect/guards.js +94 -0
  204. package/dist/api/effect/guards.js.map +1 -0
  205. package/dist/api/effect/guilds.d.ts +221 -0
  206. package/dist/api/effect/guilds.d.ts.map +1 -0
  207. package/dist/api/effect/guilds.js +2 -0
  208. package/dist/api/effect/guilds.js.map +1 -0
  209. package/dist/api/effect/helpers.d.ts +300 -0
  210. package/dist/api/effect/helpers.d.ts.map +1 -0
  211. package/dist/api/effect/helpers.js +156 -0
  212. package/dist/api/effect/helpers.js.map +1 -0
  213. package/dist/api/effect/hierarchy.d.ts +26 -0
  214. package/dist/api/effect/hierarchy.d.ts.map +1 -0
  215. package/dist/api/effect/hierarchy.js +26 -0
  216. package/dist/api/effect/hierarchy.js.map +1 -0
  217. package/dist/api/effect/instance.d.ts +46 -0
  218. package/dist/api/effect/instance.d.ts.map +1 -0
  219. package/dist/api/effect/instance.js +8 -0
  220. package/dist/api/effect/instance.js.map +1 -0
  221. package/dist/api/effect/invites.d.ts +49 -0
  222. package/dist/api/effect/invites.d.ts.map +1 -0
  223. package/dist/api/effect/invites.js +2 -0
  224. package/dist/api/effect/invites.js.map +1 -0
  225. package/dist/api/effect/logging.d.ts +37 -0
  226. package/dist/api/effect/logging.d.ts.map +1 -0
  227. package/dist/api/effect/logging.js +2 -0
  228. package/dist/api/effect/logging.js.map +1 -0
  229. package/dist/api/effect/members.d.ts +433 -0
  230. package/dist/api/effect/members.d.ts.map +1 -0
  231. package/dist/api/effect/members.js +2 -0
  232. package/dist/api/effect/members.js.map +1 -0
  233. package/dist/api/effect/messages.d.ts +877 -0
  234. package/dist/api/effect/messages.d.ts.map +1 -0
  235. package/dist/api/effect/messages.js +2 -0
  236. package/dist/api/effect/messages.js.map +1 -0
  237. package/dist/api/effect/oauth.d.ts +148 -0
  238. package/dist/api/effect/oauth.d.ts.map +1 -0
  239. package/dist/api/effect/oauth.js +51 -0
  240. package/dist/api/effect/oauth.js.map +1 -0
  241. package/dist/api/effect/permissions.d.ts +41 -0
  242. package/dist/api/effect/permissions.d.ts.map +1 -0
  243. package/dist/api/effect/permissions.js +2 -0
  244. package/dist/api/effect/permissions.js.map +1 -0
  245. package/dist/api/effect/presence.d.ts +83 -0
  246. package/dist/api/effect/presence.d.ts.map +1 -0
  247. package/dist/api/effect/presence.js +2 -0
  248. package/dist/api/effect/presence.js.map +1 -0
  249. package/dist/api/effect/rest.d.ts +27 -0
  250. package/dist/api/effect/rest.d.ts.map +1 -0
  251. package/dist/api/effect/rest.js +2 -0
  252. package/dist/api/effect/rest.js.map +1 -0
  253. package/dist/api/effect/roles.d.ts +104 -0
  254. package/dist/api/effect/roles.d.ts.map +1 -0
  255. package/dist/api/effect/roles.js +2 -0
  256. package/dist/api/effect/roles.js.map +1 -0
  257. package/dist/api/effect/service.d.ts +76 -0
  258. package/dist/api/effect/service.d.ts.map +1 -0
  259. package/dist/api/effect/service.js +79 -0
  260. package/dist/api/effect/service.js.map +1 -0
  261. package/dist/api/effect/stickers.d.ts +81 -0
  262. package/dist/api/effect/stickers.d.ts.map +1 -0
  263. package/dist/api/effect/stickers.js +2 -0
  264. package/dist/api/effect/stickers.js.map +1 -0
  265. package/dist/api/effect/supervisor.d.ts +56 -0
  266. package/dist/api/effect/supervisor.d.ts.map +1 -0
  267. package/dist/api/effect/supervisor.js +58 -0
  268. package/dist/api/effect/supervisor.js.map +1 -0
  269. package/dist/api/effect/threads.d.ts +154 -0
  270. package/dist/api/effect/threads.d.ts.map +1 -0
  271. package/dist/api/effect/threads.js +2 -0
  272. package/dist/api/effect/threads.js.map +1 -0
  273. package/dist/api/effect/users.d.ts +62 -0
  274. package/dist/api/effect/users.d.ts.map +1 -0
  275. package/dist/api/effect/users.js +2 -0
  276. package/dist/api/effect/users.js.map +1 -0
  277. package/dist/api/effect/webhook-client.d.ts +140 -0
  278. package/dist/api/effect/webhook-client.d.ts.map +1 -0
  279. package/dist/api/effect/webhook-client.js +50 -0
  280. package/dist/api/effect/webhook-client.js.map +1 -0
  281. package/dist/api/effect/webhooks.d.ts +54 -0
  282. package/dist/api/effect/webhooks.d.ts.map +1 -0
  283. package/dist/api/effect/webhooks.js +2 -0
  284. package/dist/api/effect/webhooks.js.map +1 -0
  285. package/dist/api-errors.d.ts +609 -0
  286. package/dist/api-errors.d.ts.map +1 -0
  287. package/dist/api-errors.js +589 -0
  288. package/dist/api-errors.js.map +1 -0
  289. package/dist/application.d.ts +85 -0
  290. package/dist/application.d.ts.map +1 -0
  291. package/dist/application.js +44 -0
  292. package/dist/application.js.map +1 -0
  293. package/dist/assets.d.ts +197 -0
  294. package/dist/assets.d.ts.map +1 -0
  295. package/dist/assets.js +419 -0
  296. package/dist/assets.js.map +1 -0
  297. package/dist/attachments.d.ts +400 -0
  298. package/dist/attachments.d.ts.map +1 -0
  299. package/dist/attachments.js +88 -0
  300. package/dist/attachments.js.map +1 -0
  301. package/dist/audit-logs.d.ts +292 -0
  302. package/dist/audit-logs.d.ts.map +1 -0
  303. package/dist/audit-logs.js +46 -0
  304. package/dist/audit-logs.js.map +1 -0
  305. package/dist/bot-runner.d.ts +69 -0
  306. package/dist/bot-runner.d.ts.map +1 -0
  307. package/dist/bot-runner.js +41 -0
  308. package/dist/bot-runner.js.map +1 -0
  309. package/dist/builders.d.ts +153 -0
  310. package/dist/builders.d.ts.map +1 -0
  311. package/dist/builders.js +326 -0
  312. package/dist/builders.js.map +1 -0
  313. package/dist/cache.d.ts +187 -0
  314. package/dist/cache.d.ts.map +1 -0
  315. package/dist/cache.js +2 -0
  316. package/dist/cache.js.map +1 -0
  317. package/dist/channels.d.ts +903 -0
  318. package/dist/channels.d.ts.map +1 -0
  319. package/dist/channels.js +125 -0
  320. package/dist/channels.js.map +1 -0
  321. package/dist/cli.d.ts +9 -0
  322. package/dist/cli.d.ts.map +1 -0
  323. package/dist/cli.js +65 -0
  324. package/dist/cli.js.map +1 -0
  325. package/dist/client.d.ts +645 -0
  326. package/dist/client.d.ts.map +1 -0
  327. package/dist/client.js +2 -0
  328. package/dist/client.js.map +1 -0
  329. package/dist/collectors.d.ts +205 -0
  330. package/dist/collectors.d.ts.map +1 -0
  331. package/dist/collectors.js +71 -0
  332. package/dist/collectors.js.map +1 -0
  333. package/dist/colors.d.ts +55 -0
  334. package/dist/colors.d.ts.map +1 -0
  335. package/dist/colors.js +40 -0
  336. package/dist/colors.js.map +1 -0
  337. package/dist/command-arguments.d.ts +353 -0
  338. package/dist/command-arguments.d.ts.map +1 -0
  339. package/dist/command-arguments.js +2 -0
  340. package/dist/command-arguments.js.map +1 -0
  341. package/dist/command-help.d.ts +54 -0
  342. package/dist/command-help.d.ts.map +1 -0
  343. package/dist/command-help.js +2 -0
  344. package/dist/command-help.js.map +1 -0
  345. package/dist/commands.d.ts +328 -0
  346. package/dist/commands.d.ts.map +1 -0
  347. package/dist/commands.js +62 -0
  348. package/dist/commands.js.map +1 -0
  349. package/dist/counts.d.ts +124 -0
  350. package/dist/counts.d.ts.map +1 -0
  351. package/dist/counts.js +52 -0
  352. package/dist/counts.js.map +1 -0
  353. package/dist/default-commands.d.ts +400 -0
  354. package/dist/default-commands.d.ts.map +1 -0
  355. package/dist/default-commands.js +488 -0
  356. package/dist/default-commands.js.map +1 -0
  357. package/dist/default-supervisor.d.ts +111 -0
  358. package/dist/default-supervisor.d.ts.map +1 -0
  359. package/dist/default-supervisor.js +277 -0
  360. package/dist/default-supervisor.js.map +1 -0
  361. package/dist/discovery.d.ts +223 -0
  362. package/dist/discovery.d.ts.map +1 -0
  363. package/dist/discovery.js +18 -0
  364. package/dist/discovery.js.map +1 -0
  365. package/dist/effect-testing.d.ts +388 -0
  366. package/dist/effect-testing.d.ts.map +1 -0
  367. package/dist/effect-testing.js +261 -0
  368. package/dist/effect-testing.js.map +1 -0
  369. package/dist/effect.d.ts +220 -0
  370. package/dist/effect.d.ts.map +1 -0
  371. package/dist/effect.js +101 -0
  372. package/dist/effect.js.map +1 -0
  373. package/dist/embeds.d.ts +243 -0
  374. package/dist/embeds.d.ts.map +1 -0
  375. package/dist/embeds.js +2 -0
  376. package/dist/embeds.js.map +1 -0
  377. package/dist/error-tools.d.ts +101 -0
  378. package/dist/error-tools.d.ts.map +1 -0
  379. package/dist/error-tools.js +125 -0
  380. package/dist/error-tools.js.map +1 -0
  381. package/dist/errors.d.ts +386 -0
  382. package/dist/errors.d.ts.map +1 -0
  383. package/dist/errors.js +440 -0
  384. package/dist/errors.js.map +1 -0
  385. package/dist/events.d.ts +798 -0
  386. package/dist/events.d.ts.map +1 -0
  387. package/dist/events.js +2 -0
  388. package/dist/events.js.map +1 -0
  389. package/dist/expressions.d.ts +188 -0
  390. package/dist/expressions.d.ts.map +1 -0
  391. package/dist/expressions.js +2 -0
  392. package/dist/expressions.js.map +1 -0
  393. package/dist/failures.d.ts +53 -0
  394. package/dist/failures.d.ts.map +1 -0
  395. package/dist/failures.js +2 -0
  396. package/dist/failures.js.map +1 -0
  397. package/dist/gateway.d.ts +48 -0
  398. package/dist/gateway.d.ts.map +1 -0
  399. package/dist/gateway.js +60 -0
  400. package/dist/gateway.js.map +1 -0
  401. package/dist/guilds.d.ts +923 -0
  402. package/dist/guilds.d.ts.map +1 -0
  403. package/dist/guilds.js +204 -0
  404. package/dist/guilds.js.map +1 -0
  405. package/dist/helpers.d.ts +423 -0
  406. package/dist/helpers.d.ts.map +1 -0
  407. package/dist/helpers.js +434 -0
  408. package/dist/helpers.js.map +1 -0
  409. package/dist/index.d.ts +228 -0
  410. package/dist/index.d.ts.map +1 -0
  411. package/dist/index.js +109 -0
  412. package/dist/index.js.map +1 -0
  413. package/dist/input-validation.d.ts +51 -0
  414. package/dist/input-validation.d.ts.map +1 -0
  415. package/dist/input-validation.js +34 -0
  416. package/dist/input-validation.js.map +1 -0
  417. package/dist/instance.d.ts +101 -0
  418. package/dist/instance.d.ts.map +1 -0
  419. package/dist/instance.js +2 -0
  420. package/dist/instance.js.map +1 -0
  421. package/dist/internal/agents-section.d.ts +22 -0
  422. package/dist/internal/agents-section.d.ts.map +1 -0
  423. package/dist/internal/agents-section.js +101 -0
  424. package/dist/internal/agents-section.js.map +1 -0
  425. package/dist/internal/application.d.ts +16 -0
  426. package/dist/internal/application.d.ts.map +1 -0
  427. package/dist/internal/application.js +33 -0
  428. package/dist/internal/application.js.map +1 -0
  429. package/dist/internal/attachment-refresh.d.ts +18 -0
  430. package/dist/internal/attachment-refresh.d.ts.map +1 -0
  431. package/dist/internal/attachment-refresh.js +39 -0
  432. package/dist/internal/attachment-refresh.js.map +1 -0
  433. package/dist/internal/attachments.d.ts +45 -0
  434. package/dist/internal/attachments.d.ts.map +1 -0
  435. package/dist/internal/attachments.js +230 -0
  436. package/dist/internal/attachments.js.map +1 -0
  437. package/dist/internal/audit-logs.d.ts +13 -0
  438. package/dist/internal/audit-logs.d.ts.map +1 -0
  439. package/dist/internal/audit-logs.js +295 -0
  440. package/dist/internal/audit-logs.js.map +1 -0
  441. package/dist/internal/audit.d.ts +12 -0
  442. package/dist/internal/audit.d.ts.map +1 -0
  443. package/dist/internal/audit.js +22 -0
  444. package/dist/internal/audit.js.map +1 -0
  445. package/dist/internal/binding/default-adapters.d.ts +22 -0
  446. package/dist/internal/binding/default-adapters.d.ts.map +1 -0
  447. package/dist/internal/binding/default-adapters.js +304 -0
  448. package/dist/internal/binding/default-adapters.js.map +1 -0
  449. package/dist/internal/binding/default.d.ts +45 -0
  450. package/dist/internal/binding/default.d.ts.map +1 -0
  451. package/dist/internal/binding/default.js +86 -0
  452. package/dist/internal/binding/default.js.map +1 -0
  453. package/dist/internal/binding/execute.d.ts +51 -0
  454. package/dist/internal/binding/execute.d.ts.map +1 -0
  455. package/dist/internal/binding/execute.js +123 -0
  456. package/dist/internal/binding/execute.js.map +1 -0
  457. package/dist/internal/binding/native-adapters.d.ts +23 -0
  458. package/dist/internal/binding/native-adapters.d.ts.map +1 -0
  459. package/dist/internal/binding/native-adapters.js +90 -0
  460. package/dist/internal/binding/native-adapters.js.map +1 -0
  461. package/dist/internal/binding/native.d.ts +41 -0
  462. package/dist/internal/binding/native.d.ts.map +1 -0
  463. package/dist/internal/binding/native.js +34 -0
  464. package/dist/internal/binding/native.js.map +1 -0
  465. package/dist/internal/binding/operations.d.ts +361 -0
  466. package/dist/internal/binding/operations.d.ts.map +1 -0
  467. package/dist/internal/binding/operations.js +272 -0
  468. package/dist/internal/binding/operations.js.map +1 -0
  469. package/dist/internal/bot-runner.d.ts +65 -0
  470. package/dist/internal/bot-runner.d.ts.map +1 -0
  471. package/dist/internal/bot-runner.js +363 -0
  472. package/dist/internal/bot-runner.js.map +1 -0
  473. package/dist/internal/cache-changes.d.ts +43 -0
  474. package/dist/internal/cache-changes.d.ts.map +1 -0
  475. package/dist/internal/cache-changes.js +320 -0
  476. package/dist/internal/cache-changes.js.map +1 -0
  477. package/dist/internal/cache.d.ts +57 -0
  478. package/dist/internal/cache.d.ts.map +1 -0
  479. package/dist/internal/cache.js +318 -0
  480. package/dist/internal/cache.js.map +1 -0
  481. package/dist/internal/calls.d.ts +16 -0
  482. package/dist/internal/calls.d.ts.map +1 -0
  483. package/dist/internal/calls.js +108 -0
  484. package/dist/internal/calls.js.map +1 -0
  485. package/dist/internal/channel-cache.d.ts +69 -0
  486. package/dist/internal/channel-cache.d.ts.map +1 -0
  487. package/dist/internal/channel-cache.js +413 -0
  488. package/dist/internal/channel-cache.js.map +1 -0
  489. package/dist/internal/channel-decode.d.ts +44 -0
  490. package/dist/internal/channel-decode.d.ts.map +1 -0
  491. package/dist/internal/channel-decode.js +377 -0
  492. package/dist/internal/channel-decode.js.map +1 -0
  493. package/dist/internal/channels.d.ts +60 -0
  494. package/dist/internal/channels.d.ts.map +1 -0
  495. package/dist/internal/channels.js +605 -0
  496. package/dist/internal/channels.js.map +1 -0
  497. package/dist/internal/client/backoff.d.ts +42 -0
  498. package/dist/internal/client/backoff.d.ts.map +1 -0
  499. package/dist/internal/client/backoff.js +36 -0
  500. package/dist/internal/client/backoff.js.map +1 -0
  501. package/dist/internal/client/configuration-fields.d.ts +14 -0
  502. package/dist/internal/client/configuration-fields.d.ts.map +1 -0
  503. package/dist/internal/client/configuration-fields.js +11 -0
  504. package/dist/internal/client/configuration-fields.js.map +1 -0
  505. package/dist/internal/client/drain.d.ts +33 -0
  506. package/dist/internal/client/drain.d.ts.map +1 -0
  507. package/dist/internal/client/drain.js +109 -0
  508. package/dist/internal/client/drain.js.map +1 -0
  509. package/dist/internal/client/intake.d.ts +27 -0
  510. package/dist/internal/client/intake.d.ts.map +1 -0
  511. package/dist/internal/client/intake.js +198 -0
  512. package/dist/internal/client/intake.js.map +1 -0
  513. package/dist/internal/client/lifetime.d.ts +35 -0
  514. package/dist/internal/client/lifetime.d.ts.map +1 -0
  515. package/dist/internal/client/lifetime.js +109 -0
  516. package/dist/internal/client/lifetime.js.map +1 -0
  517. package/dist/internal/client/shard-loop.d.ts +93 -0
  518. package/dist/internal/client/shard-loop.d.ts.map +1 -0
  519. package/dist/internal/client/shard-loop.js +452 -0
  520. package/dist/internal/client/shard-loop.js.map +1 -0
  521. package/dist/internal/client-registry.d.ts +26 -0
  522. package/dist/internal/client-registry.d.ts.map +1 -0
  523. package/dist/internal/client-registry.js +11 -0
  524. package/dist/internal/client-registry.js.map +1 -0
  525. package/dist/internal/client.d.ts +189 -0
  526. package/dist/internal/client.d.ts.map +1 -0
  527. package/dist/internal/client.js +1935 -0
  528. package/dist/internal/client.js.map +1 -0
  529. package/dist/internal/clock.d.ts +9 -0
  530. package/dist/internal/clock.d.ts.map +1 -0
  531. package/dist/internal/clock.js +5 -0
  532. package/dist/internal/clock.js.map +1 -0
  533. package/dist/internal/code-catalogue.d.ts +712 -0
  534. package/dist/internal/code-catalogue.d.ts.map +1 -0
  535. package/dist/internal/code-catalogue.js +655 -0
  536. package/dist/internal/code-catalogue.js.map +1 -0
  537. package/dist/internal/collector.d.ts +34 -0
  538. package/dist/internal/collector.d.ts.map +1 -0
  539. package/dist/internal/collector.js +400 -0
  540. package/dist/internal/collector.js.map +1 -0
  541. package/dist/internal/command-arguments.d.ts +29 -0
  542. package/dist/internal/command-arguments.d.ts.map +1 -0
  543. package/dist/internal/command-arguments.js +484 -0
  544. package/dist/internal/command-arguments.js.map +1 -0
  545. package/dist/internal/command-guards.d.ts +57 -0
  546. package/dist/internal/command-guards.d.ts.map +1 -0
  547. package/dist/internal/command-guards.js +81 -0
  548. package/dist/internal/command-guards.js.map +1 -0
  549. package/dist/internal/command-help.d.ts +15 -0
  550. package/dist/internal/command-help.d.ts.map +1 -0
  551. package/dist/internal/command-help.js +121 -0
  552. package/dist/internal/command-help.js.map +1 -0
  553. package/dist/internal/commands.d.ts +212 -0
  554. package/dist/internal/commands.d.ts.map +1 -0
  555. package/dist/internal/commands.js +1004 -0
  556. package/dist/internal/commands.js.map +1 -0
  557. package/dist/internal/configuration.d.ts +86 -0
  558. package/dist/internal/configuration.d.ts.map +1 -0
  559. package/dist/internal/configuration.js +401 -0
  560. package/dist/internal/configuration.js.map +1 -0
  561. package/dist/internal/counts.d.ts +33 -0
  562. package/dist/internal/counts.d.ts.map +1 -0
  563. package/dist/internal/counts.js +348 -0
  564. package/dist/internal/counts.js.map +1 -0
  565. package/dist/internal/decode/primitives.d.ts +30 -0
  566. package/dist/internal/decode/primitives.d.ts.map +1 -0
  567. package/dist/internal/decode/primitives.js +56 -0
  568. package/dist/internal/decode/primitives.js.map +1 -0
  569. package/dist/internal/decode/timestamp.d.ts +13 -0
  570. package/dist/internal/decode/timestamp.d.ts.map +1 -0
  571. package/dist/internal/decode/timestamp.js +27 -0
  572. package/dist/internal/decode/timestamp.js.map +1 -0
  573. package/dist/internal/decode/trace.d.ts +11 -0
  574. package/dist/internal/decode/trace.d.ts.map +1 -0
  575. package/dist/internal/decode/trace.js +69 -0
  576. package/dist/internal/decode/trace.js.map +1 -0
  577. package/dist/internal/defects.d.ts +48 -0
  578. package/dist/internal/defects.d.ts.map +1 -0
  579. package/dist/internal/defects.js +100 -0
  580. package/dist/internal/defects.js.map +1 -0
  581. package/dist/internal/effect-failures.d.ts +12 -0
  582. package/dist/internal/effect-failures.d.ts.map +1 -0
  583. package/dist/internal/effect-failures.js +45 -0
  584. package/dist/internal/effect-failures.js.map +1 -0
  585. package/dist/internal/embeds.d.ts +12 -0
  586. package/dist/internal/embeds.d.ts.map +1 -0
  587. package/dist/internal/embeds.js +308 -0
  588. package/dist/internal/embeds.js.map +1 -0
  589. package/dist/internal/events.d.ts +156 -0
  590. package/dist/internal/events.d.ts.map +1 -0
  591. package/dist/internal/events.js +1071 -0
  592. package/dist/internal/events.js.map +1 -0
  593. package/dist/internal/expiry-queue.d.ts +42 -0
  594. package/dist/internal/expiry-queue.d.ts.map +1 -0
  595. package/dist/internal/expiry-queue.js +138 -0
  596. package/dist/internal/expiry-queue.js.map +1 -0
  597. package/dist/internal/expressions.d.ts +35 -0
  598. package/dist/internal/expressions.d.ts.map +1 -0
  599. package/dist/internal/expressions.js +311 -0
  600. package/dist/internal/expressions.js.map +1 -0
  601. package/dist/internal/failures.d.ts +107 -0
  602. package/dist/internal/failures.d.ts.map +1 -0
  603. package/dist/internal/failures.js +416 -0
  604. package/dist/internal/failures.js.map +1 -0
  605. package/dist/internal/field-text.d.ts +10 -0
  606. package/dist/internal/field-text.d.ts.map +1 -0
  607. package/dist/internal/field-text.js +37 -0
  608. package/dist/internal/field-text.js.map +1 -0
  609. package/dist/internal/gateway/commands.d.ts +92 -0
  610. package/dist/internal/gateway/commands.d.ts.map +1 -0
  611. package/dist/internal/gateway/commands.js +223 -0
  612. package/dist/internal/gateway/commands.js.map +1 -0
  613. package/dist/internal/gateway/dispatch-table.d.ts +42 -0
  614. package/dist/internal/gateway/dispatch-table.d.ts.map +1 -0
  615. package/dist/internal/gateway/dispatch-table.js +288 -0
  616. package/dist/internal/gateway/dispatch-table.js.map +1 -0
  617. package/dist/internal/gateway/event-dispatches.d.ts +97 -0
  618. package/dist/internal/gateway/event-dispatches.d.ts.map +1 -0
  619. package/dist/internal/gateway/event-dispatches.js +172 -0
  620. package/dist/internal/gateway/event-dispatches.js.map +1 -0
  621. package/dist/internal/gateway/frames.d.ts +45 -0
  622. package/dist/internal/gateway/frames.d.ts.map +1 -0
  623. package/dist/internal/gateway/frames.js +121 -0
  624. package/dist/internal/gateway/frames.js.map +1 -0
  625. package/dist/internal/gateway/options.d.ts +24 -0
  626. package/dist/internal/gateway/options.d.ts.map +1 -0
  627. package/dist/internal/gateway/options.js +103 -0
  628. package/dist/internal/gateway/options.js.map +1 -0
  629. package/dist/internal/gateway/session.d.ts +104 -0
  630. package/dist/internal/gateway/session.d.ts.map +1 -0
  631. package/dist/internal/gateway/session.js +420 -0
  632. package/dist/internal/gateway/session.js.map +1 -0
  633. package/dist/internal/gateway-requests.d.ts +10 -0
  634. package/dist/internal/gateway-requests.d.ts.map +1 -0
  635. package/dist/internal/gateway-requests.js +26 -0
  636. package/dist/internal/gateway-requests.js.map +1 -0
  637. package/dist/internal/gateway.d.ts +19 -0
  638. package/dist/internal/gateway.d.ts.map +1 -0
  639. package/dist/internal/gateway.js +11 -0
  640. package/dist/internal/gateway.js.map +1 -0
  641. package/dist/internal/guild-cache.d.ts +69 -0
  642. package/dist/internal/guild-cache.d.ts.map +1 -0
  643. package/dist/internal/guild-cache.js +402 -0
  644. package/dist/internal/guild-cache.js.map +1 -0
  645. package/dist/internal/guild-discovery.d.ts +15 -0
  646. package/dist/internal/guild-discovery.d.ts.map +1 -0
  647. package/dist/internal/guild-discovery.js +258 -0
  648. package/dist/internal/guild-discovery.js.map +1 -0
  649. package/dist/internal/guild-lifecycle.d.ts +18 -0
  650. package/dist/internal/guild-lifecycle.d.ts.map +1 -0
  651. package/dist/internal/guild-lifecycle.js +119 -0
  652. package/dist/internal/guild-lifecycle.js.map +1 -0
  653. package/dist/internal/guild-settings.d.ts +11 -0
  654. package/dist/internal/guild-settings.d.ts.map +1 -0
  655. package/dist/internal/guild-settings.js +150 -0
  656. package/dist/internal/guild-settings.js.map +1 -0
  657. package/dist/internal/guilds.d.ts +94 -0
  658. package/dist/internal/guilds.d.ts.map +1 -0
  659. package/dist/internal/guilds.js +785 -0
  660. package/dist/internal/guilds.js.map +1 -0
  661. package/dist/internal/init-command.d.ts +54 -0
  662. package/dist/internal/init-command.d.ts.map +1 -0
  663. package/dist/internal/init-command.js +248 -0
  664. package/dist/internal/init-command.js.map +1 -0
  665. package/dist/internal/instance.d.ts +69 -0
  666. package/dist/internal/instance.d.ts.map +1 -0
  667. package/dist/internal/instance.js +455 -0
  668. package/dist/internal/instance.js.map +1 -0
  669. package/dist/internal/invalid-callback-return.d.ts +3 -0
  670. package/dist/internal/invalid-callback-return.d.ts.map +1 -0
  671. package/dist/internal/invalid-callback-return.js +26 -0
  672. package/dist/internal/invalid-callback-return.js.map +1 -0
  673. package/dist/internal/invites.d.ts +19 -0
  674. package/dist/internal/invites.d.ts.map +1 -0
  675. package/dist/internal/invites.js +182 -0
  676. package/dist/internal/invites.js.map +1 -0
  677. package/dist/internal/logging.d.ts +129 -0
  678. package/dist/internal/logging.d.ts.map +1 -0
  679. package/dist/internal/logging.js +868 -0
  680. package/dist/internal/logging.js.map +1 -0
  681. package/dist/internal/logical-scheduler.d.ts +27 -0
  682. package/dist/internal/logical-scheduler.d.ts.map +1 -0
  683. package/dist/internal/logical-scheduler.js +102 -0
  684. package/dist/internal/logical-scheduler.js.map +1 -0
  685. package/dist/internal/masking.d.ts +13 -0
  686. package/dist/internal/masking.d.ts.map +1 -0
  687. package/dist/internal/masking.js +235 -0
  688. package/dist/internal/masking.js.map +1 -0
  689. package/dist/internal/member-chunks.d.ts +96 -0
  690. package/dist/internal/member-chunks.d.ts.map +1 -0
  691. package/dist/internal/member-chunks.js +557 -0
  692. package/dist/internal/member-chunks.js.map +1 -0
  693. package/dist/internal/member-search-workflow.d.ts +19 -0
  694. package/dist/internal/member-search-workflow.d.ts.map +1 -0
  695. package/dist/internal/member-search-workflow.js +143 -0
  696. package/dist/internal/member-search-workflow.js.map +1 -0
  697. package/dist/internal/member-search.d.ts +20 -0
  698. package/dist/internal/member-search.d.ts.map +1 -0
  699. package/dist/internal/member-search.js +201 -0
  700. package/dist/internal/member-search.js.map +1 -0
  701. package/dist/internal/message-cleanup.d.ts +9 -0
  702. package/dist/internal/message-cleanup.d.ts.map +1 -0
  703. package/dist/internal/message-cleanup.js +368 -0
  704. package/dist/internal/message-cleanup.js.map +1 -0
  705. package/dist/internal/message-fields.d.ts +9 -0
  706. package/dist/internal/message-fields.d.ts.map +1 -0
  707. package/dist/internal/message-fields.js +55 -0
  708. package/dist/internal/message-fields.js.map +1 -0
  709. package/dist/internal/message-search-workflow.d.ts +14 -0
  710. package/dist/internal/message-search-workflow.d.ts.map +1 -0
  711. package/dist/internal/message-search-workflow.js +101 -0
  712. package/dist/internal/message-search-workflow.js.map +1 -0
  713. package/dist/internal/message-search.d.ts +19 -0
  714. package/dist/internal/message-search.d.ts.map +1 -0
  715. package/dist/internal/message-search.js +317 -0
  716. package/dist/internal/message-search.js.map +1 -0
  717. package/dist/internal/message.d.ts +34 -0
  718. package/dist/internal/message.d.ts.map +1 -0
  719. package/dist/internal/message.js +723 -0
  720. package/dist/internal/message.js.map +1 -0
  721. package/dist/internal/metrics.d.ts +16 -0
  722. package/dist/internal/metrics.d.ts.map +1 -0
  723. package/dist/internal/metrics.js +49 -0
  724. package/dist/internal/metrics.js.map +1 -0
  725. package/dist/internal/moderation.d.ts +20 -0
  726. package/dist/internal/moderation.d.ts.map +1 -0
  727. package/dist/internal/moderation.js +219 -0
  728. package/dist/internal/moderation.js.map +1 -0
  729. package/dist/internal/multipart.d.ts +10 -0
  730. package/dist/internal/multipart.d.ts.map +1 -0
  731. package/dist/internal/multipart.js +156 -0
  732. package/dist/internal/multipart.js.map +1 -0
  733. package/dist/internal/node-version.d.ts +10 -0
  734. package/dist/internal/node-version.d.ts.map +1 -0
  735. package/dist/internal/node-version.js +21 -0
  736. package/dist/internal/node-version.js.map +1 -0
  737. package/dist/internal/oauth.d.ts +29 -0
  738. package/dist/internal/oauth.d.ts.map +1 -0
  739. package/dist/internal/oauth.js +721 -0
  740. package/dist/internal/oauth.js.map +1 -0
  741. package/dist/internal/observer.d.ts +21 -0
  742. package/dist/internal/observer.d.ts.map +1 -0
  743. package/dist/internal/observer.js +48 -0
  744. package/dist/internal/observer.js.map +1 -0
  745. package/dist/internal/operation-signal.d.ts +9 -0
  746. package/dist/internal/operation-signal.d.ts.map +1 -0
  747. package/dist/internal/operation-signal.js +19 -0
  748. package/dist/internal/operation-signal.js.map +1 -0
  749. package/dist/internal/pagination.d.ts +67 -0
  750. package/dist/internal/pagination.d.ts.map +1 -0
  751. package/dist/internal/pagination.js +306 -0
  752. package/dist/internal/pagination.js.map +1 -0
  753. package/dist/internal/permission-requirements.d.ts +34 -0
  754. package/dist/internal/permission-requirements.d.ts.map +1 -0
  755. package/dist/internal/permission-requirements.js +204 -0
  756. package/dist/internal/permission-requirements.js.map +1 -0
  757. package/dist/internal/permissions.d.ts +28 -0
  758. package/dist/internal/permissions.d.ts.map +1 -0
  759. package/dist/internal/permissions.js +314 -0
  760. package/dist/internal/permissions.js.map +1 -0
  761. package/dist/internal/pins.d.ts +24 -0
  762. package/dist/internal/pins.d.ts.map +1 -0
  763. package/dist/internal/pins.js +83 -0
  764. package/dist/internal/pins.js.map +1 -0
  765. package/dist/internal/presence.d.ts +101 -0
  766. package/dist/internal/presence.d.ts.map +1 -0
  767. package/dist/internal/presence.js +581 -0
  768. package/dist/internal/presence.js.map +1 -0
  769. package/dist/internal/protocol/gateway.d.ts +116 -0
  770. package/dist/internal/protocol/gateway.d.ts.map +1 -0
  771. package/dist/internal/protocol/gateway.js +258 -0
  772. package/dist/internal/protocol/gateway.js.map +1 -0
  773. package/dist/internal/rate-limit-templates.d.ts +2 -0
  774. package/dist/internal/rate-limit-templates.d.ts.map +1 -0
  775. package/dist/internal/rate-limit-templates.js +132 -0
  776. package/dist/internal/rate-limit-templates.js.map +1 -0
  777. package/dist/internal/rate-limits.d.ts +32 -0
  778. package/dist/internal/rate-limits.d.ts.map +1 -0
  779. package/dist/internal/rate-limits.js +306 -0
  780. package/dist/internal/rate-limits.js.map +1 -0
  781. package/dist/internal/reaction-collector.d.ts +39 -0
  782. package/dist/internal/reaction-collector.d.ts.map +1 -0
  783. package/dist/internal/reaction-collector.js +441 -0
  784. package/dist/internal/reaction-collector.js.map +1 -0
  785. package/dist/internal/reaction-pages.d.ts +18 -0
  786. package/dist/internal/reaction-pages.d.ts.map +1 -0
  787. package/dist/internal/reaction-pages.js +213 -0
  788. package/dist/internal/reaction-pages.js.map +1 -0
  789. package/dist/internal/reactions.d.ts +30 -0
  790. package/dist/internal/reactions.d.ts.map +1 -0
  791. package/dist/internal/reactions.js +160 -0
  792. package/dist/internal/reactions.js.map +1 -0
  793. package/dist/internal/rejection-scope.d.ts +25 -0
  794. package/dist/internal/rejection-scope.d.ts.map +1 -0
  795. package/dist/internal/rejection-scope.js +103 -0
  796. package/dist/internal/rejection-scope.js.map +1 -0
  797. package/dist/internal/response-json.d.ts +12 -0
  798. package/dist/internal/response-json.d.ts.map +1 -0
  799. package/dist/internal/response-json.js +74 -0
  800. package/dist/internal/response-json.js.map +1 -0
  801. package/dist/internal/rest/admission.d.ts +77 -0
  802. package/dist/internal/rest/admission.d.ts.map +1 -0
  803. package/dist/internal/rest/admission.js +178 -0
  804. package/dist/internal/rest/admission.js.map +1 -0
  805. package/dist/internal/rest/attempt.d.ts +124 -0
  806. package/dist/internal/rest/attempt.d.ts.map +1 -0
  807. package/dist/internal/rest/attempt.js +410 -0
  808. package/dist/internal/rest/attempt.js.map +1 -0
  809. package/dist/internal/rest/classify.d.ts +93 -0
  810. package/dist/internal/rest/classify.d.ts.map +1 -0
  811. package/dist/internal/rest/classify.js +304 -0
  812. package/dist/internal/rest/classify.js.map +1 -0
  813. package/dist/internal/rest/download.d.ts +66 -0
  814. package/dist/internal/rest/download.d.ts.map +1 -0
  815. package/dist/internal/rest/download.js +552 -0
  816. package/dist/internal/rest/download.js.map +1 -0
  817. package/dist/internal/rest/options.d.ts +42 -0
  818. package/dist/internal/rest/options.d.ts.map +1 -0
  819. package/dist/internal/rest/options.js +99 -0
  820. package/dist/internal/rest/options.js.map +1 -0
  821. package/dist/internal/rest/owner.d.ts +154 -0
  822. package/dist/internal/rest/owner.d.ts.map +1 -0
  823. package/dist/internal/rest/owner.js +1292 -0
  824. package/dist/internal/rest/owner.js.map +1 -0
  825. package/dist/internal/rest/request.d.ts +31 -0
  826. package/dist/internal/rest/request.d.ts.map +1 -0
  827. package/dist/internal/rest/request.js +227 -0
  828. package/dist/internal/rest/request.js.map +1 -0
  829. package/dist/internal/rest.d.ts +10 -0
  830. package/dist/internal/rest.d.ts.map +1 -0
  831. package/dist/internal/rest.js +9 -0
  832. package/dist/internal/rest.js.map +1 -0
  833. package/dist/internal/retention-age.d.ts +11 -0
  834. package/dist/internal/retention-age.d.ts.map +1 -0
  835. package/dist/internal/retention-age.js +29 -0
  836. package/dist/internal/retention-age.js.map +1 -0
  837. package/dist/internal/role-hierarchy-workflow.d.ts +15 -0
  838. package/dist/internal/role-hierarchy-workflow.d.ts.map +1 -0
  839. package/dist/internal/role-hierarchy-workflow.js +122 -0
  840. package/dist/internal/role-hierarchy-workflow.js.map +1 -0
  841. package/dist/internal/role-hierarchy.d.ts +11 -0
  842. package/dist/internal/role-hierarchy.d.ts.map +1 -0
  843. package/dist/internal/role-hierarchy.js +87 -0
  844. package/dist/internal/role-hierarchy.js.map +1 -0
  845. package/dist/internal/scheduled-tasks.d.ts +46 -0
  846. package/dist/internal/scheduled-tasks.d.ts.map +1 -0
  847. package/dist/internal/scheduled-tasks.js +190 -0
  848. package/dist/internal/scheduled-tasks.js.map +1 -0
  849. package/dist/internal/sharding.d.ts +62 -0
  850. package/dist/internal/sharding.d.ts.map +1 -0
  851. package/dist/internal/sharding.js +205 -0
  852. package/dist/internal/sharding.js.map +1 -0
  853. package/dist/internal/starter-project.d.ts +27 -0
  854. package/dist/internal/starter-project.d.ts.map +1 -0
  855. package/dist/internal/starter-project.js +224 -0
  856. package/dist/internal/starter-project.js.map +1 -0
  857. package/dist/internal/suggest.d.ts +12 -0
  858. package/dist/internal/suggest.d.ts.map +1 -0
  859. package/dist/internal/suggest.js +51 -0
  860. package/dist/internal/suggest.js.map +1 -0
  861. package/dist/internal/supervisor.d.ts +95 -0
  862. package/dist/internal/supervisor.d.ts.map +1 -0
  863. package/dist/internal/supervisor.js +1829 -0
  864. package/dist/internal/supervisor.js.map +1 -0
  865. package/dist/internal/testing/discovery.d.ts +24 -0
  866. package/dist/internal/testing/discovery.d.ts.map +1 -0
  867. package/dist/internal/testing/discovery.js +22 -0
  868. package/dist/internal/testing/discovery.js.map +1 -0
  869. package/dist/internal/testing/errors.d.ts +43 -0
  870. package/dist/internal/testing/errors.d.ts.map +1 -0
  871. package/dist/internal/testing/errors.js +63 -0
  872. package/dist/internal/testing/errors.js.map +1 -0
  873. package/dist/internal/testing/fixtures.d.ts +477 -0
  874. package/dist/internal/testing/fixtures.d.ts.map +1 -0
  875. package/dist/internal/testing/fixtures.js +233 -0
  876. package/dist/internal/testing/fixtures.js.map +1 -0
  877. package/dist/internal/testing/gateway.d.ts +51 -0
  878. package/dist/internal/testing/gateway.d.ts.map +1 -0
  879. package/dist/internal/testing/gateway.js +265 -0
  880. package/dist/internal/testing/gateway.js.map +1 -0
  881. package/dist/internal/testing/harness.d.ts +60 -0
  882. package/dist/internal/testing/harness.d.ts.map +1 -0
  883. package/dist/internal/testing/harness.js +280 -0
  884. package/dist/internal/testing/harness.js.map +1 -0
  885. package/dist/internal/testing/http.d.ts +31 -0
  886. package/dist/internal/testing/http.d.ts.map +1 -0
  887. package/dist/internal/testing/http.js +347 -0
  888. package/dist/internal/testing/http.js.map +1 -0
  889. package/dist/internal/testing/types.d.ts +222 -0
  890. package/dist/internal/testing/types.d.ts.map +1 -0
  891. package/dist/internal/testing/types.js +2 -0
  892. package/dist/internal/testing/types.js.map +1 -0
  893. package/dist/internal/testing/wait.d.ts +16 -0
  894. package/dist/internal/testing/wait.d.ts.map +1 -0
  895. package/dist/internal/testing/wait.js +55 -0
  896. package/dist/internal/testing/wait.js.map +1 -0
  897. package/dist/internal/thread-events.d.ts +40 -0
  898. package/dist/internal/thread-events.d.ts.map +1 -0
  899. package/dist/internal/thread-events.js +121 -0
  900. package/dist/internal/thread-events.js.map +1 -0
  901. package/dist/internal/threads.d.ts +47 -0
  902. package/dist/internal/threads.d.ts.map +1 -0
  903. package/dist/internal/threads.js +587 -0
  904. package/dist/internal/threads.js.map +1 -0
  905. package/dist/internal/transfer-source.d.ts +29 -0
  906. package/dist/internal/transfer-source.d.ts.map +1 -0
  907. package/dist/internal/transfer-source.js +347 -0
  908. package/dist/internal/transfer-source.js.map +1 -0
  909. package/dist/internal/transport/http.d.ts +12 -0
  910. package/dist/internal/transport/http.d.ts.map +1 -0
  911. package/dist/internal/transport/http.js +44 -0
  912. package/dist/internal/transport/http.js.map +1 -0
  913. package/dist/internal/transport/index.d.ts +21 -0
  914. package/dist/internal/transport/index.d.ts.map +1 -0
  915. package/dist/internal/transport/index.js +15 -0
  916. package/dist/internal/transport/index.js.map +1 -0
  917. package/dist/internal/transport/socket.d.ts +51 -0
  918. package/dist/internal/transport/socket.d.ts.map +1 -0
  919. package/dist/internal/transport/socket.js +27 -0
  920. package/dist/internal/transport/socket.js.map +1 -0
  921. package/dist/internal/transport/user-agent.d.ts +7 -0
  922. package/dist/internal/transport/user-agent.d.ts.map +1 -0
  923. package/dist/internal/transport/user-agent.js +42 -0
  924. package/dist/internal/transport/user-agent.js.map +1 -0
  925. package/dist/internal/uploads.d.ts +23 -0
  926. package/dist/internal/uploads.d.ts.map +1 -0
  927. package/dist/internal/uploads.js +89 -0
  928. package/dist/internal/uploads.js.map +1 -0
  929. package/dist/internal/user-cache.d.ts +50 -0
  930. package/dist/internal/user-cache.d.ts.map +1 -0
  931. package/dist/internal/user-cache.js +273 -0
  932. package/dist/internal/user-cache.js.map +1 -0
  933. package/dist/internal/users.d.ts +41 -0
  934. package/dist/internal/users.d.ts.map +1 -0
  935. package/dist/internal/users.js +333 -0
  936. package/dist/internal/users.js.map +1 -0
  937. package/dist/internal/vanity-url.d.ts +11 -0
  938. package/dist/internal/vanity-url.d.ts.map +1 -0
  939. package/dist/internal/vanity-url.js +58 -0
  940. package/dist/internal/vanity-url.js.map +1 -0
  941. package/dist/internal/webhooks.d.ts +58 -0
  942. package/dist/internal/webhooks.d.ts.map +1 -0
  943. package/dist/internal/webhooks.js +490 -0
  944. package/dist/internal/webhooks.js.map +1 -0
  945. package/dist/invites.d.ts +86 -0
  946. package/dist/invites.d.ts.map +1 -0
  947. package/dist/invites.js +2 -0
  948. package/dist/invites.js.map +1 -0
  949. package/dist/logging.d.ts +228 -0
  950. package/dist/logging.d.ts.map +1 -0
  951. package/dist/logging.js +2 -0
  952. package/dist/logging.js.map +1 -0
  953. package/dist/member-chunks.d.ts +145 -0
  954. package/dist/member-chunks.d.ts.map +1 -0
  955. package/dist/member-chunks.js +68 -0
  956. package/dist/member-chunks.js.map +1 -0
  957. package/dist/member-search.d.ts +140 -0
  958. package/dist/member-search.d.ts.map +1 -0
  959. package/dist/member-search.js +14 -0
  960. package/dist/member-search.js.map +1 -0
  961. package/dist/message-cleanup.d.ts +227 -0
  962. package/dist/message-cleanup.d.ts.map +1 -0
  963. package/dist/message-cleanup.js +101 -0
  964. package/dist/message-cleanup.js.map +1 -0
  965. package/dist/message-errors.d.ts +172 -0
  966. package/dist/message-errors.d.ts.map +1 -0
  967. package/dist/message-errors.js +173 -0
  968. package/dist/message-errors.js.map +1 -0
  969. package/dist/message-search.d.ts +201 -0
  970. package/dist/message-search.d.ts.map +1 -0
  971. package/dist/message-search.js +2 -0
  972. package/dist/message-search.js.map +1 -0
  973. package/dist/messages.d.ts +694 -0
  974. package/dist/messages.d.ts.map +1 -0
  975. package/dist/messages.js +37 -0
  976. package/dist/messages.js.map +1 -0
  977. package/dist/native-commands.d.ts +451 -0
  978. package/dist/native-commands.d.ts.map +1 -0
  979. package/dist/native-commands.js +432 -0
  980. package/dist/native-commands.js.map +1 -0
  981. package/dist/native-supervisor.d.ts +125 -0
  982. package/dist/native-supervisor.d.ts.map +1 -0
  983. package/dist/native-supervisor.js +126 -0
  984. package/dist/native-supervisor.js.map +1 -0
  985. package/dist/oauth.d.ts +298 -0
  986. package/dist/oauth.d.ts.map +1 -0
  987. package/dist/oauth.js +128 -0
  988. package/dist/oauth.js.map +1 -0
  989. package/dist/observer.d.ts +111 -0
  990. package/dist/observer.d.ts.map +1 -0
  991. package/dist/observer.js +2 -0
  992. package/dist/observer.js.map +1 -0
  993. package/dist/pagination.d.ts +117 -0
  994. package/dist/pagination.d.ts.map +1 -0
  995. package/dist/pagination.js +61 -0
  996. package/dist/pagination.js.map +1 -0
  997. package/dist/permissions.d.ts +73 -0
  998. package/dist/permissions.d.ts.map +1 -0
  999. package/dist/permissions.js +2 -0
  1000. package/dist/permissions.js.map +1 -0
  1001. package/dist/pins.d.ts +62 -0
  1002. package/dist/pins.d.ts.map +1 -0
  1003. package/dist/pins.js +2 -0
  1004. package/dist/pins.js.map +1 -0
  1005. package/dist/presence.d.ts +84 -0
  1006. package/dist/presence.d.ts.map +1 -0
  1007. package/dist/presence.js +46 -0
  1008. package/dist/presence.js.map +1 -0
  1009. package/dist/reaction-pages.d.ts +99 -0
  1010. package/dist/reaction-pages.d.ts.map +1 -0
  1011. package/dist/reaction-pages.js +2 -0
  1012. package/dist/reaction-pages.js.map +1 -0
  1013. package/dist/reactions.d.ts +118 -0
  1014. package/dist/reactions.d.ts.map +1 -0
  1015. package/dist/reactions.js +2 -0
  1016. package/dist/reactions.js.map +1 -0
  1017. package/dist/rest.d.ts +260 -0
  1018. package/dist/rest.d.ts.map +1 -0
  1019. package/dist/rest.js +46 -0
  1020. package/dist/rest.js.map +1 -0
  1021. package/dist/role-hierarchy.d.ts +81 -0
  1022. package/dist/role-hierarchy.d.ts.map +1 -0
  1023. package/dist/role-hierarchy.js +53 -0
  1024. package/dist/role-hierarchy.js.map +1 -0
  1025. package/dist/sharding.d.ts +219 -0
  1026. package/dist/sharding.d.ts.map +1 -0
  1027. package/dist/sharding.js +86 -0
  1028. package/dist/sharding.js.map +1 -0
  1029. package/dist/supervisor.d.ts +392 -0
  1030. package/dist/supervisor.d.ts.map +1 -0
  1031. package/dist/supervisor.js +101 -0
  1032. package/dist/supervisor.js.map +1 -0
  1033. package/dist/testing.d.ts +258 -0
  1034. package/dist/testing.d.ts.map +1 -0
  1035. package/dist/testing.js +202 -0
  1036. package/dist/testing.js.map +1 -0
  1037. package/dist/text.d.ts +38 -0
  1038. package/dist/text.d.ts.map +1 -0
  1039. package/dist/text.js +46 -0
  1040. package/dist/text.js.map +1 -0
  1041. package/dist/threads.d.ts +258 -0
  1042. package/dist/threads.d.ts.map +1 -0
  1043. package/dist/threads.js +2 -0
  1044. package/dist/threads.js.map +1 -0
  1045. package/dist/users.d.ts +204 -0
  1046. package/dist/users.d.ts.map +1 -0
  1047. package/dist/users.js +44 -0
  1048. package/dist/users.js.map +1 -0
  1049. package/dist/webhooks.d.ts +423 -0
  1050. package/dist/webhooks.d.ts.map +1 -0
  1051. package/dist/webhooks.js +68 -0
  1052. package/dist/webhooks.js.map +1 -0
  1053. package/esm-only.cjs +3 -0
  1054. package/examples/starter/bot-effect.ts +17 -0
  1055. package/examples/starter/bot.js +13 -0
  1056. package/examples/starter/bot.ts +13 -0
  1057. package/package.json +82 -0
  1058. package/src/api/default/application.ts +40 -0
  1059. package/src/api/default/attachments.ts +106 -0
  1060. package/src/api/default/audit-logs.ts +58 -0
  1061. package/src/api/default/bot.ts +586 -0
  1062. package/src/api/default/cache.ts +106 -0
  1063. package/src/api/default/channels.ts +317 -0
  1064. package/src/api/default/client.ts +829 -0
  1065. package/src/api/default/collectors.ts +81 -0
  1066. package/src/api/default/commands.ts +92 -0
  1067. package/src/api/default/direct-messages.ts +143 -0
  1068. package/src/api/default/discovery.ts +103 -0
  1069. package/src/api/default/emojis.ts +125 -0
  1070. package/src/api/default/events.ts +144 -0
  1071. package/src/api/default/gateway.ts +67 -0
  1072. package/src/api/default/guards.ts +173 -0
  1073. package/src/api/default/guilds.ts +271 -0
  1074. package/src/api/default/helpers.ts +97 -0
  1075. package/src/api/default/instance.ts +49 -0
  1076. package/src/api/default/invites.ts +73 -0
  1077. package/src/api/default/logging.ts +37 -0
  1078. package/src/api/default/members.ts +550 -0
  1079. package/src/api/default/messages.ts +1053 -0
  1080. package/src/api/default/oauth.ts +293 -0
  1081. package/src/api/default/permissions.ts +47 -0
  1082. package/src/api/default/presence.ts +88 -0
  1083. package/src/api/default/rest.ts +30 -0
  1084. package/src/api/default/results.ts +44 -0
  1085. package/src/api/default/roles.ts +154 -0
  1086. package/src/api/default/stickers.ts +129 -0
  1087. package/src/api/default/supervisor.ts +53 -0
  1088. package/src/api/default/threads.ts +233 -0
  1089. package/src/api/default/users.ts +82 -0
  1090. package/src/api/default/webhook-client.ts +266 -0
  1091. package/src/api/default/webhooks.ts +89 -0
  1092. package/src/api/effect/application.ts +29 -0
  1093. package/src/api/effect/attachments.ts +100 -0
  1094. package/src/api/effect/audit-logs.ts +50 -0
  1095. package/src/api/effect/bot.ts +546 -0
  1096. package/src/api/effect/cache.ts +110 -0
  1097. package/src/api/effect/channels.ts +293 -0
  1098. package/src/api/effect/client.ts +792 -0
  1099. package/src/api/effect/collectors.ts +103 -0
  1100. package/src/api/effect/commands.ts +87 -0
  1101. package/src/api/effect/direct-messages.ts +119 -0
  1102. package/src/api/effect/discovery.ts +87 -0
  1103. package/src/api/effect/emojis.ts +108 -0
  1104. package/src/api/effect/events.ts +92 -0
  1105. package/src/api/effect/failures.ts +14 -0
  1106. package/src/api/effect/gateway.ts +63 -0
  1107. package/src/api/effect/guards.ts +194 -0
  1108. package/src/api/effect/guilds.ts +247 -0
  1109. package/src/api/effect/helpers.ts +359 -0
  1110. package/src/api/effect/hierarchy.ts +26 -0
  1111. package/src/api/effect/instance.ts +50 -0
  1112. package/src/api/effect/invites.ts +59 -0
  1113. package/src/api/effect/logging.ts +37 -0
  1114. package/src/api/effect/members.ts +521 -0
  1115. package/src/api/effect/messages.ts +1003 -0
  1116. package/src/api/effect/oauth.ts +208 -0
  1117. package/src/api/effect/permissions.ts +44 -0
  1118. package/src/api/effect/presence.ts +83 -0
  1119. package/src/api/effect/rest.ts +27 -0
  1120. package/src/api/effect/roles.ts +136 -0
  1121. package/src/api/effect/service.ts +104 -0
  1122. package/src/api/effect/stickers.ts +112 -0
  1123. package/src/api/effect/supervisor.ts +58 -0
  1124. package/src/api/effect/threads.ts +221 -0
  1125. package/src/api/effect/users.ts +66 -0
  1126. package/src/api/effect/webhook-client.ts +206 -0
  1127. package/src/api/effect/webhooks.ts +75 -0
  1128. package/src/api-errors.ts +985 -0
  1129. package/src/application.ts +103 -0
  1130. package/src/assets.ts +731 -0
  1131. package/src/attachments.ts +469 -0
  1132. package/src/audit-logs.ts +355 -0
  1133. package/src/bot-runner.ts +91 -0
  1134. package/src/builders.ts +390 -0
  1135. package/src/cache.ts +190 -0
  1136. package/src/channels.ts +1051 -0
  1137. package/src/cli.ts +60 -0
  1138. package/src/client.ts +663 -0
  1139. package/src/collectors.ts +248 -0
  1140. package/src/colors.ts +91 -0
  1141. package/src/command-arguments.ts +432 -0
  1142. package/src/command-help.ts +55 -0
  1143. package/src/commands.ts +403 -0
  1144. package/src/counts.ts +160 -0
  1145. package/src/default-commands.ts +1147 -0
  1146. package/src/default-supervisor.ts +484 -0
  1147. package/src/discovery.ts +241 -0
  1148. package/src/effect-testing.ts +603 -0
  1149. package/src/effect.ts +751 -0
  1150. package/src/embeds.ts +253 -0
  1151. package/src/error-tools.ts +191 -0
  1152. package/src/errors.ts +849 -0
  1153. package/src/events.ts +830 -0
  1154. package/src/expressions.ts +198 -0
  1155. package/src/failures.ts +55 -0
  1156. package/src/gateway.ts +86 -0
  1157. package/src/guilds.ts +1108 -0
  1158. package/src/helpers.ts +836 -0
  1159. package/src/index.ts +796 -0
  1160. package/src/input-validation.ts +94 -0
  1161. package/src/instance.ts +111 -0
  1162. package/src/internal/agents-section.ts +114 -0
  1163. package/src/internal/application.ts +51 -0
  1164. package/src/internal/attachment-refresh.ts +57 -0
  1165. package/src/internal/attachments.ts +313 -0
  1166. package/src/internal/audit-logs.ts +336 -0
  1167. package/src/internal/audit.ts +33 -0
  1168. package/src/internal/binding/default-adapters.ts +482 -0
  1169. package/src/internal/binding/default.ts +155 -0
  1170. package/src/internal/binding/execute.ts +221 -0
  1171. package/src/internal/binding/native-adapters.ts +199 -0
  1172. package/src/internal/binding/native.ts +72 -0
  1173. package/src/internal/binding/operations.ts +1171 -0
  1174. package/src/internal/bot-runner.ts +480 -0
  1175. package/src/internal/cache-changes.ts +363 -0
  1176. package/src/internal/cache.ts +323 -0
  1177. package/src/internal/calls.ts +119 -0
  1178. package/src/internal/channel-cache.ts +435 -0
  1179. package/src/internal/channel-decode.ts +399 -0
  1180. package/src/internal/channels.ts +874 -0
  1181. package/src/internal/client/backoff.ts +69 -0
  1182. package/src/internal/client/configuration-fields.ts +18 -0
  1183. package/src/internal/client/drain.ts +150 -0
  1184. package/src/internal/client/intake.ts +228 -0
  1185. package/src/internal/client/lifetime.ts +165 -0
  1186. package/src/internal/client/shard-loop.ts +586 -0
  1187. package/src/internal/client-registry.ts +35 -0
  1188. package/src/internal/client.ts +2448 -0
  1189. package/src/internal/clock.ts +11 -0
  1190. package/src/internal/code-catalogue.ts +739 -0
  1191. package/src/internal/collector.ts +452 -0
  1192. package/src/internal/command-arguments.ts +585 -0
  1193. package/src/internal/command-guards.ts +96 -0
  1194. package/src/internal/command-help.ts +156 -0
  1195. package/src/internal/commands.ts +1319 -0
  1196. package/src/internal/configuration.ts +529 -0
  1197. package/src/internal/counts.ts +471 -0
  1198. package/src/internal/decode/primitives.ts +67 -0
  1199. package/src/internal/decode/timestamp.ts +29 -0
  1200. package/src/internal/decode/trace.ts +65 -0
  1201. package/src/internal/defects.ts +115 -0
  1202. package/src/internal/effect-failures.ts +65 -0
  1203. package/src/internal/embeds.ts +355 -0
  1204. package/src/internal/events.ts +1345 -0
  1205. package/src/internal/expiry-queue.ts +148 -0
  1206. package/src/internal/expressions.ts +415 -0
  1207. package/src/internal/failures.ts +492 -0
  1208. package/src/internal/field-text.ts +40 -0
  1209. package/src/internal/gateway/commands.ts +328 -0
  1210. package/src/internal/gateway/dispatch-table.ts +383 -0
  1211. package/src/internal/gateway/event-dispatches.ts +201 -0
  1212. package/src/internal/gateway/frames.ts +176 -0
  1213. package/src/internal/gateway/options.ts +144 -0
  1214. package/src/internal/gateway/session.ts +625 -0
  1215. package/src/internal/gateway-requests.ts +26 -0
  1216. package/src/internal/gateway.ts +22 -0
  1217. package/src/internal/guild-cache.ts +424 -0
  1218. package/src/internal/guild-discovery.ts +332 -0
  1219. package/src/internal/guild-lifecycle.ts +128 -0
  1220. package/src/internal/guild-settings.ts +209 -0
  1221. package/src/internal/guilds.ts +949 -0
  1222. package/src/internal/init-command.ts +305 -0
  1223. package/src/internal/instance.ts +645 -0
  1224. package/src/internal/invalid-callback-return.ts +28 -0
  1225. package/src/internal/invites.ts +234 -0
  1226. package/src/internal/logging.ts +1007 -0
  1227. package/src/internal/logical-scheduler.ts +139 -0
  1228. package/src/internal/masking.ts +224 -0
  1229. package/src/internal/member-chunks.ts +649 -0
  1230. package/src/internal/member-search-workflow.ts +237 -0
  1231. package/src/internal/member-search.ts +272 -0
  1232. package/src/internal/message-cleanup.ts +515 -0
  1233. package/src/internal/message-fields.ts +71 -0
  1234. package/src/internal/message-search-workflow.ts +166 -0
  1235. package/src/internal/message-search.ts +476 -0
  1236. package/src/internal/message.ts +879 -0
  1237. package/src/internal/metrics.ts +55 -0
  1238. package/src/internal/moderation.ts +288 -0
  1239. package/src/internal/multipart.ts +171 -0
  1240. package/src/internal/node-version.ts +22 -0
  1241. package/src/internal/oauth.ts +1146 -0
  1242. package/src/internal/observer.ts +62 -0
  1243. package/src/internal/operation-signal.ts +26 -0
  1244. package/src/internal/pagination.ts +494 -0
  1245. package/src/internal/permission-requirements.ts +359 -0
  1246. package/src/internal/permissions.ts +417 -0
  1247. package/src/internal/pins.ts +115 -0
  1248. package/src/internal/presence.ts +745 -0
  1249. package/src/internal/protocol/gateway.ts +299 -0
  1250. package/src/internal/rate-limit-templates.ts +138 -0
  1251. package/src/internal/rate-limits.ts +346 -0
  1252. package/src/internal/reaction-collector.ts +499 -0
  1253. package/src/internal/reaction-pages.ts +260 -0
  1254. package/src/internal/reactions.ts +174 -0
  1255. package/src/internal/rejection-scope.ts +119 -0
  1256. package/src/internal/response-json.ts +76 -0
  1257. package/src/internal/rest/admission.ts +210 -0
  1258. package/src/internal/rest/attempt.ts +617 -0
  1259. package/src/internal/rest/classify.ts +391 -0
  1260. package/src/internal/rest/download.ts +658 -0
  1261. package/src/internal/rest/options.ts +145 -0
  1262. package/src/internal/rest/owner.ts +1828 -0
  1263. package/src/internal/rest/request.ts +289 -0
  1264. package/src/internal/rest.ts +9 -0
  1265. package/src/internal/retention-age.ts +33 -0
  1266. package/src/internal/role-hierarchy-workflow.ts +150 -0
  1267. package/src/internal/role-hierarchy.ts +93 -0
  1268. package/src/internal/scheduled-tasks.ts +217 -0
  1269. package/src/internal/sharding.ts +270 -0
  1270. package/src/internal/starter-project.ts +251 -0
  1271. package/src/internal/suggest.ts +50 -0
  1272. package/src/internal/supervisor.ts +2253 -0
  1273. package/src/internal/testing/discovery.ts +23 -0
  1274. package/src/internal/testing/errors.ts +67 -0
  1275. package/src/internal/testing/fixtures.ts +714 -0
  1276. package/src/internal/testing/gateway.ts +305 -0
  1277. package/src/internal/testing/harness.ts +328 -0
  1278. package/src/internal/testing/http.ts +395 -0
  1279. package/src/internal/testing/types.ts +240 -0
  1280. package/src/internal/testing/wait.ts +63 -0
  1281. package/src/internal/thread-events.ts +128 -0
  1282. package/src/internal/threads.ts +718 -0
  1283. package/src/internal/transfer-source.ts +359 -0
  1284. package/src/internal/transport/http.ts +46 -0
  1285. package/src/internal/transport/index.ts +23 -0
  1286. package/src/internal/transport/socket.ts +71 -0
  1287. package/src/internal/transport/user-agent.ts +46 -0
  1288. package/src/internal/uploads.ts +111 -0
  1289. package/src/internal/user-cache.ts +294 -0
  1290. package/src/internal/users.ts +402 -0
  1291. package/src/internal/vanity-url.ts +80 -0
  1292. package/src/internal/webhooks.ts +690 -0
  1293. package/src/invites.ts +87 -0
  1294. package/src/logging.ts +247 -0
  1295. package/src/member-chunks.ts +195 -0
  1296. package/src/member-search.ts +152 -0
  1297. package/src/message-cleanup.ts +308 -0
  1298. package/src/message-errors.ts +245 -0
  1299. package/src/message-search.ts +213 -0
  1300. package/src/messages.ts +768 -0
  1301. package/src/native-commands.ts +1249 -0
  1302. package/src/native-supervisor.ts +345 -0
  1303. package/src/oauth.ts +413 -0
  1304. package/src/observer.ts +118 -0
  1305. package/src/pagination.ts +172 -0
  1306. package/src/permissions.ts +74 -0
  1307. package/src/pins.ts +65 -0
  1308. package/src/presence.ts +124 -0
  1309. package/src/reaction-pages.ts +106 -0
  1310. package/src/reactions.ts +126 -0
  1311. package/src/rest.ts +282 -0
  1312. package/src/role-hierarchy.ts +127 -0
  1313. package/src/sharding.ts +272 -0
  1314. package/src/supervisor.ts +460 -0
  1315. package/src/testing.ts +424 -0
  1316. package/src/text.ts +76 -0
  1317. package/src/threads.ts +274 -0
  1318. package/src/users.ts +237 -0
  1319. package/src/webhooks.ts +512 -0
@@ -0,0 +1,2448 @@
1
+ /**
2
+ * Client owner: Configuration, caches, REST, instance discovery, shard state and the one client lifetime, split into
3
+ * [shard loop](/projects/sdk/src/internal/client/shard-loop.ts), [intake](/projects/sdk/src/internal/client/intake.ts),
4
+ * [backoff](/projects/sdk/src/internal/client/backoff.ts) and [lifetime](/projects/sdk/src/internal/client/lifetime.ts).
5
+ * Invariant: The client manages its assigned sessions as one lifetime, spaces out Identify sends, coordinates initial state
6
+ * delivery with subscription setup and retains one lifetime outcome. Implements [SDK contracts: Connection and recovery](/docs/SDK-CONTRACTS.md#connection-and-recovery)
7
+ */
8
+ import * as Cause from "effect/Cause"
9
+ import * as Clock from "effect/Clock"
10
+ import type * as Context from "effect/Context"
11
+ import * as Deferred from "effect/Deferred"
12
+ import * as Effect from "effect/Effect"
13
+ import * as Exit from "effect/Exit"
14
+ import * as Fiber from "effect/Fiber"
15
+ import * as Queue from "effect/Queue"
16
+ import * as Redacted from "effect/Redacted"
17
+ import * as Scope from "effect/Scope"
18
+ import * as Semaphore from "effect/Semaphore"
19
+ import * as Stream from "effect/Stream"
20
+ import type {
21
+ CacheDiagnostic,
22
+ CacheEntriesOptions,
23
+ CachedResources,
24
+ CacheKind,
25
+ ClientDiagnostics,
26
+ ConnectionState,
27
+ } from "#sdk/client"
28
+ import type { SessionSnapshot, ShardState } from "#sdk/sharding"
29
+ import {
30
+ admitReshard,
31
+ automaticShardPlan,
32
+ guildShardId,
33
+ guildsPerShard,
34
+ largerShardPlan,
35
+ type ShardPlan,
36
+ } from "./sharding.js"
37
+ import { guildList } from "./guild-lifecycle.js"
38
+ import type { IdentifyFields } from "./gateway/commands.js"
39
+ import { automaticIgnoredEvents, suppressedRegistrations } from "./gateway/event-dispatches.js"
40
+ import { maxClientPayloadBytes, Opcode, reservedClientOpcodes } from "./protocol/gateway.js"
41
+ import { MessageError, MessageOperationError, type MessageOperationFailure, type SendError } from "#sdk/message-errors"
42
+ import { replyInput, snapshotReference } from "./message.js"
43
+ import { identifier, record } from "./decode/primitives.js"
44
+ import { MessageCache } from "./cache.js"
45
+ import { unsupportedKeyHint } from "./suggest.js"
46
+ import { GuildCache, type ResourceKind, type Resources } from "./guild-cache.js"
47
+ import { ChannelCache } from "./channel-cache.js"
48
+ import { CacheChangeHub } from "./cache-changes.js"
49
+ import type { DefaultRestRequest, RestRequest, RestRequestFailure, RestResponse } from "#sdk/rest"
50
+ import { GatewaySendError, type GatewaySendFailure } from "#sdk/gateway"
51
+ import { UserCache, type UserResources } from "./user-cache.js"
52
+ import { PresenceOwner } from "./presence.js"
53
+ import { PresenceError, type PresenceInput, type PresenceFailure } from "#sdk/presence"
54
+ import {
55
+ UserOperationError,
56
+ type UserOperation,
57
+ type UserOperationOptions,
58
+ type User,
59
+ type DirectMessageChannel,
60
+ } from "#sdk/users"
61
+ import { decodeUser, directMessageFetch, userFetch, type UserRequest } from "./users.js"
62
+ import {
63
+ ChannelOperationError,
64
+ type ChannelOperation,
65
+ type ChannelOperationOptions,
66
+ type GuildChannel,
67
+ } from "#sdk/channels"
68
+ import { channelList, type ChannelRequest } from "./channels.js"
69
+ import type { WebhookRequest } from "./webhooks.js"
70
+ import type { WebhookOperation, WebhookOperationOptions } from "#sdk/webhooks"
71
+ import { FailureReporter, messageIds, primaryError, publicReport, throwIfErr, type InternalReport } from "./failures.js"
72
+ import {
73
+ AuthenticationError,
74
+ ClientBusyError,
75
+ ClientClosedError,
76
+ ConnectionError,
77
+ ConfigurationError,
78
+ ConnectionTimeoutError,
79
+ RateLimitError,
80
+ type ConnectError,
81
+ type ConnectionFailure,
82
+ } from "#sdk/errors"
83
+ import { type Configuration, validateConfiguration } from "./configuration.js"
84
+ import { InstanceResolver } from "./instance.js"
85
+ import type { LinkHelpers } from "#sdk/helpers"
86
+ import { CountOwner } from "./counts.js"
87
+ import { GatewayRequestBudget } from "./gateway-requests.js"
88
+ import { MemberChunkOwner, type MemberRequestGate } from "./member-chunks.js"
89
+ import { LogicalScheduler, type LogicalTimer, makeLogicalScheduler } from "./logical-scheduler.js"
90
+ import { AttemptFailure } from "./gateway.js"
91
+ import { sdkVersion } from "./logging.js"
92
+ import { EventBus } from "./events.js"
93
+ import { nowMs } from "./clock.js"
94
+ import { defaultTransport, type Transport } from "./transport/index.js"
95
+ import { identifySpacingMs, startupBudgetMs } from "./client/backoff.js"
96
+ import { clearCaches } from "./client/intake.js"
97
+ import { drainWork } from "./client/drain.js"
98
+ import { ScheduledTasks } from "./scheduled-tasks.js"
99
+ import {
100
+ closeAll,
101
+ defectsOnly,
102
+ formatDuration,
103
+ logShutdownEnd,
104
+ logShutdownStart,
105
+ superviseShards,
106
+ } from "./client/lifetime.js"
107
+ import { readCaller, suspendInput, suspendMarked } from "./defects.js"
108
+ import { runShardLoop, type ShardLoopHost, type ShardRuntime } from "./client/shard-loop.js"
109
+ import type { MessageCollector } from "./collector.js"
110
+ import type { ReactionCollector } from "./reaction-collector.js"
111
+ import {
112
+ GuildOperationError,
113
+ type GuildOperation,
114
+ type GuildOperationOptions,
115
+ type MemberReference,
116
+ type RoleReference,
117
+ } from "#sdk/guilds"
118
+ import { guildFetch, roleList, type GuildRequest } from "./guilds.js"
119
+ import { guildDeleteOwnMessages, guildLeave, ownDeletionOptions } from "./guild-lifecycle.js"
120
+ import { RestOwner } from "./rest.js"
121
+ import type { BotApplicationOperation, BotApplicationOperationOptions } from "#sdk/application"
122
+ import type { BotApplicationRequest } from "./application.js"
123
+ import type { ReactionEmojiInput, ReactionUsersQuery } from "#sdk/reactions"
124
+ import type { MessagePinsQuery } from "#sdk/pins"
125
+ import type { MessageSearchContext, MessageSearchQuery } from "#sdk/message-search"
126
+ import type { ClientLogger } from "./logging.js"
127
+ import type {
128
+ Message,
129
+ MessageCore,
130
+ MessageFields,
131
+ SelectedMessage,
132
+ EditMessageInput,
133
+ ForwardMessageInput,
134
+ MessageHistoryQuery,
135
+ MessageInput,
136
+ MessageOperationOptions,
137
+ MessageReference,
138
+ SendOptions,
139
+ } from "#sdk/messages"
140
+ import type {
141
+ Attachment,
142
+ AttachmentDownloadFailure,
143
+ AttachmentDownloadOptions,
144
+ AttachmentRefreshFailure,
145
+ AttachmentRefreshOptions,
146
+ RefreshedAttachmentUrl,
147
+ } from "#sdk/attachments"
148
+ import type { AttachmentDownloadSource } from "./rest.js"
149
+ import { InputValidationFailure, inputValidationFailure, unsupportedKeyFailure } from "#sdk/input-validation"
150
+
151
+ const cacheKinds = [
152
+ "messages",
153
+ "guilds",
154
+ "members",
155
+ "roles",
156
+ "channels",
157
+ "users",
158
+ "directMessages",
159
+ "emojis",
160
+ "stickers",
161
+ ] as const satisfies readonly CacheKind[]
162
+ const emptyEntries = Object.freeze([])
163
+ /** The documented two-part CacheChange key format of each kind that has one */
164
+ const cachePairKeys = {
165
+ messages: "channelId:messageId",
166
+ members: "guildId:userId",
167
+ roles: "guildId:id",
168
+ emojis: "guildId:id",
169
+ stickers: "guildId:id",
170
+ } as const
171
+ /** The cache kind, or ConfigurationError for misuse */
172
+ function validCacheKind(kind: unknown): CacheKind {
173
+ if (!(cacheKinds as readonly unknown[]).includes(kind))
174
+ throw new ConfigurationError("kind", `The cache kind must be one of ${cacheKinds.join(", ")}`)
175
+ return kind as CacheKind
176
+ }
177
+ const disabledCacheDiagnostic: CacheDiagnostic = Object.freeze({
178
+ configured: false,
179
+ retainedEntries: 0,
180
+ accountedBytes: 0,
181
+ maxEntries: null,
182
+ maxBytes: null,
183
+ hits: 0,
184
+ misses: 0,
185
+ evictions: Object.freeze({ capacity: 0, expiry: 0 }),
186
+ })
187
+ const freezeCacheDiagnostic = (diagnostic: CacheDiagnostic | undefined): CacheDiagnostic =>
188
+ diagnostic === undefined
189
+ ? disabledCacheDiagnostic
190
+ : Object.freeze({
191
+ configured: diagnostic.configured,
192
+ retainedEntries: diagnostic.retainedEntries,
193
+ accountedBytes: diagnostic.accountedBytes,
194
+ maxEntries: diagnostic.maxEntries,
195
+ maxBytes: diagnostic.maxBytes,
196
+ hits: diagnostic.hits,
197
+ misses: diagnostic.misses,
198
+ evictions: Object.freeze({
199
+ capacity: diagnostic.evictions.capacity,
200
+ expiry: diagnostic.evictions.expiry,
201
+ }),
202
+ })
203
+
204
+ const typingRefreshMs = 8_000
205
+ /** Time allowed for each session store save during shutdown */
206
+ const sessionSaveTimeoutMs = 5_000
207
+ /** Guild list page size used to count guilds for automatic sharding, the largest Fluxer accepts */
208
+ const guildCountPageSize = 200
209
+ /** Communities whose cache refill may fail before the refill stops */
210
+ const refillFailureLimit = 10
211
+
212
+ type GuildBuild<A> = () => GuildRequest<A> | InputValidationFailure
213
+
214
+ /** Marks a JSON encoding failure that this module detected itself, so it is not mistaken for a caller throw */
215
+ class CommandDataUnencodable {
216
+ constructor(readonly cause: unknown) {}
217
+ }
218
+
219
+ /**
220
+ * Encode gateway command data as JSON. A circular structure, a BigInt or nesting too deep for the stack returns the
221
+ * encoding failure. Any other throw comes from caller code run while encoding, such as a getter, a proxy trap or a
222
+ * toJSON method, and propagates unchanged
223
+ */
224
+ function encodeCommandData(data: unknown): { readonly json: string | undefined } | { readonly failure: unknown } {
225
+ // Objects on the path from the root to the value being encoded, the same path JSON.stringify checks for cycles
226
+ const path: unknown[] = []
227
+ try {
228
+ const json = JSON.stringify(data, function (this: unknown, _key, value: unknown) {
229
+ path.length = path.lastIndexOf(this) + 1
230
+ if (typeof value === "bigint")
231
+ throw new CommandDataUnencodable(new TypeError("BigInt values cannot be encoded as JSON"))
232
+ if (typeof value === "object" && value !== null) {
233
+ if (path.includes(value))
234
+ throw new CommandDataUnencodable(new TypeError("Circular structures cannot be encoded as JSON"))
235
+ path.push(value)
236
+ }
237
+ return value
238
+ })
239
+ return { json }
240
+ } catch (error) {
241
+ if (error instanceof CommandDataUnencodable) return { failure: error.cause }
242
+ if (error instanceof RangeError) return { failure: error }
243
+ throw error
244
+ }
245
+ }
246
+
247
+ /** Translate a failed guild-count read into the startup failure that connect and run report */
248
+ function automaticPlanFailure(
249
+ error: GuildOperationError | ClientClosedError,
250
+ startupTimeoutMs: number,
251
+ ): ConnectionFailure {
252
+ // Closure during startup surfaces as ClientClosedError from connect, as for discovery
253
+ if (error instanceof ClientClosedError) return new ConnectionError("discovery", "closed")
254
+ if (error.status === 401) return new AuthenticationError()
255
+ if (error.reason === "rateLimit") return new RateLimitError("http", error.retryAfterMs)
256
+ if (error.reason === "timeout") return new ConnectionTimeoutError(startupTimeoutMs)
257
+ return new ConnectionError("discovery", error.reason === "response" ? "protocol" : "network", error.status, {
258
+ cause: error,
259
+ details: { detail: "the community count for automatic sharding could not be read" },
260
+ hint: "Check that the bot token can list the bot's communities, or set sharding.totalShards to a number",
261
+ })
262
+ }
263
+
264
+ /** Internal fresh-Identify coordination used only by supervisor.child.run */
265
+ export interface IdentifyGate {
266
+ permit(shardId: number, send: () => void): Effect.Effect<void, ConnectionError>
267
+ }
268
+
269
+ const identifyGates = new WeakMap<object, IdentifyGate>()
270
+
271
+ /** Attach a non-public gateway permit to the helper-owned client configuration object */
272
+ export function attachIdentifyGate<T extends object>(options: T, gate: IdentifyGate): T {
273
+ identifyGates.set(options, gate)
274
+ return options
275
+ }
276
+
277
+ /** Internal sharing of Fluxer's account-wide limits with the other children of a supervisor, used only by supervisor.child.run */
278
+ export interface AccountLimits {
279
+ /** Pass a global pause this client learned from Fluxer, lasting waitMs from now, to the other children */
280
+ readonly shareGlobalPause: (waitMs: number) => void
281
+ /** Apply global pauses the other children learned. A pause that is still running reaches the listener at once */
282
+ readonly onGlobalPause: (listener: (waitMs: number) => void) => void
283
+ /** The parent's member request window */
284
+ readonly members: MemberRequestGate
285
+ }
286
+
287
+ const accountLimits = new WeakMap<object, AccountLimits>()
288
+
289
+ /** Attach non-public account limit sharing to the helper-owned client configuration object */
290
+ export function attachAccountLimits<T extends object>(options: T, limits: AccountLimits): T {
291
+ accountLimits.set(options, limits)
292
+ return options
293
+ }
294
+
295
+ export class ClientOwner<M extends MessageCore = Message> {
296
+ readonly presence: PresenceOwner
297
+ readonly #gatewayRequests = new GatewayRequestBudget()
298
+ readonly #identify = Semaphore.makeUnsafe(1)
299
+ /** SDK-private owner for fresh correlated gateway-count replies, with no count cache */
300
+ readonly counts: CountOwner
301
+ readonly memberChunks: MemberChunkOwner
302
+
303
+ setPresence(input: PresenceInput) {
304
+ // The presence owner marks its reads of the caller input, so its own faults stay SDK faults
305
+ return suspendMarked((): Effect.Effect<void, PresenceFailure> => {
306
+ if (this.#state === "Closing" || this.#state === "Closed") return Effect.fail(new ClientClosedError())
307
+ const failure = this.presence.set(input)
308
+ if (failure === undefined) return Effect.void
309
+ if (failure === false) return Effect.fail(new ClientClosedError())
310
+ return Effect.fail(new PresenceError({ reason: "input", inputValidation: failure.detail }))
311
+ })
312
+ }
313
+ setPresenceMembers(guildId: string, memberIds: readonly string[]) {
314
+ return suspendMarked((): Effect.Effect<void, PresenceFailure> => {
315
+ if (this.#state === "Closing" || this.#state === "Closed") return Effect.fail(new ClientClosedError())
316
+ const failure = this.presence.setMembers(guildId, memberIds)
317
+ if (failure === undefined) return Effect.void
318
+ if (failure === "limit") return Effect.fail(new PresenceError({ reason: "limit" }))
319
+ if (failure === false) return Effect.fail(new ClientClosedError())
320
+ return Effect.fail(new PresenceError({ reason: "input", inputValidation: failure.detail }))
321
+ })
322
+ }
323
+ #messageCollectors = new Set<MessageCollector<M>>()
324
+ trackMessageCollector(collector: MessageCollector<M>) {
325
+ this.#messageCollectors.add(collector)
326
+ // A collector that ends while the client closes stays until shutdown has collected its cleanup outcome
327
+ return () => void (this.#closingOrClosed() || this.#messageCollectors.delete(collector))
328
+ }
329
+ #reactionCollectors = new Set<ReactionCollector>()
330
+ trackReactionCollector(collector: ReactionCollector) {
331
+ this.#reactionCollectors.add(collector)
332
+ return () => void (this.#closingOrClosed() || this.#reactionCollectors.delete(collector))
333
+ }
334
+ #closingOrClosed() {
335
+ return this.#state === "Closing" || this.#state === "Closed"
336
+ }
337
+ readonly logging: ClientLogger
338
+ /** Client-wide failure reports, delivered to onError or logged */
339
+ readonly failures: FailureReporter
340
+ /** Tasks started with client.schedule, which end with this client */
341
+ readonly tasks: ScheduledTasks
342
+ readonly events = new EventBus<M>(
343
+ () => this.logging,
344
+ () => this.failures,
345
+ )
346
+ readonly decodeMessage: Configuration<M>["decodeMessage"]
347
+ readonly rest: RestOwner<M>
348
+ /** One owner-scoped immutable discovery result, independent of credentials and REST admission state */
349
+ readonly instance: InstanceResolver
350
+ readonly cache: MessageCache<M> | undefined
351
+ readonly resources: GuildCache | undefined
352
+ readonly channelCache: ChannelCache | undefined
353
+ readonly userCache: UserCache
354
+ /** Client-wide cache change notifications, shared by every cache this client owns */
355
+ readonly cacheChanges = new CacheChangeHub()
356
+ #configuration: Configuration<M> | undefined
357
+ #state: ConnectionState = "Disconnected"
358
+ /** Known shard plan. An automatic plan stays undefined until the first connect computes it */
359
+ #plan: ShardPlan | undefined
360
+ readonly #shards = new Map<number, ShardRuntime>()
361
+ readonly #shardListeners = new Map<number, Set<(state: ConnectionState) => void>>()
362
+ readonly #shardHost: ShardLoopHost<M>
363
+ #groupReady = false
364
+ /** Shards whose sessions shutdown saves, captured when shutdown begins */
365
+ #saveOnClose: ReadonlySet<number> | undefined
366
+ /** Logical time before which the next fresh Identify may not be sent */
367
+ #nextIdentifyAt = 0
368
+ #worker: Fiber.Fiber<void> | undefined
369
+ #workerExit: Exit.Exit<void, ConnectionFailure> | undefined
370
+ /** The service cleanup the worker ran when an explicit shutdown interrupted it, which that shutdown logs */
371
+ #workerCleanup: Exit.Exit<void> | undefined
372
+ #terminal = Deferred.makeUnsafe<void, ConnectionFailure>()
373
+ #shutdown = Deferred.makeUnsafe<void>()
374
+ #typingClosed = Deferred.makeUnsafe<void>()
375
+ #typing = new Map<symbol, Fiber.Fiber<never, MessageOperationFailure>>()
376
+ #listeners = new Set<(state: ConnectionState) => void>()
377
+ #managed = false
378
+ #shutdownStarted = false
379
+ /** Whether connect or run began, so shutdown records describe a client that did something */
380
+ #everStarted = false
381
+ /** Logical times of recent moves to a larger automatic plan, oldest first */
382
+ #reshards: number[] = []
383
+ /** The shard whose 4011 closure started a move to a larger plan, until the new plan is adopted */
384
+ #reshardShard: number | undefined
385
+ /** Shards that resumed a session from the session store, whose guild caches wait for a refill */
386
+ readonly #restoredShards = new Set<number>()
387
+
388
+ constructor(
389
+ configuration: Configuration<M>,
390
+ readonly scope: Scope.Scope,
391
+ failures: FailureReporter,
392
+ readonly logical: LogicalScheduler,
393
+ private readonly identifyGate: IdentifyGate | undefined,
394
+ /** Account limits shared with a supervisor's other children, only in a supervised child */
395
+ limits: AccountLimits | undefined,
396
+ /** Network implementations for REST, discovery and the gateway */
397
+ readonly transport: Transport = defaultTransport,
398
+ ) {
399
+ this.decodeMessage = configuration.decodeMessage
400
+ this.#configuration = configuration
401
+ const route = (guildId: string) => this.shardIdForGuild(guildId)
402
+ this.presence = new PresenceOwner(
403
+ {
404
+ now: () => logical.now(),
405
+ set: (callback, delay) => logical.set(callback, delay, "presence"),
406
+ clear: (timer) => logical.clear(timer as LogicalTimer),
407
+ },
408
+ route,
409
+ )
410
+ // The configured initial presence is the first presence intent: Identify carries it and READY publishes it
411
+ if (configuration.gateway.presence !== undefined) this.presence.set(configuration.gateway.presence)
412
+ this.counts = new CountOwner(this.#gatewayRequests, route)
413
+ this.memberChunks = new MemberChunkOwner(
414
+ this.#gatewayRequests,
415
+ logical,
416
+ route,
417
+ limits?.members,
418
+ configuration.logging,
419
+ )
420
+ this.logging = configuration.logging
421
+ this.failures = failures
422
+ this.tasks = new ScheduledTasks(logical, failures, configuration.logging)
423
+ const reportCache = (error: unknown) => this.failures.report({ kind: "cache", error })
424
+ this.cache = configuration.cache
425
+ ? new MessageCache(
426
+ configuration.cache,
427
+ (error, message) => this.failures.report({ kind: "cache", error, message: messageIds(message) }),
428
+ () => logical.now(),
429
+ logical,
430
+ this.cacheChanges,
431
+ )
432
+ : undefined
433
+ this.resources = Object.keys(configuration.resourceCache).length
434
+ ? new GuildCache(configuration.resourceCache, () => logical.now(), logical, this.cacheChanges, reportCache)
435
+ : undefined
436
+ this.channelCache = configuration.channelCache
437
+ ? new ChannelCache(configuration.channelCache, () => logical.now(), logical, this.cacheChanges, reportCache)
438
+ : undefined
439
+ this.userCache = new UserCache(
440
+ configuration.userCache,
441
+ () => logical.now(),
442
+ logical,
443
+ this.cacheChanges,
444
+ reportCache,
445
+ )
446
+ this.instance = new InstanceResolver(configuration.instance, scope, {
447
+ http: transport.http,
448
+ onDiscovered: (resolved) => {
449
+ this.#instanceLinks = resolved.links
450
+ const migration = resolved.domainMigration
451
+ if (!migration) return
452
+ const webapp = new URL(resolved.endpoints.webapp).host
453
+ this.logging.log({
454
+ level: migration.enabled ? "info" : "debug",
455
+ category: "lifecycle",
456
+ code: "lifecycle.domainMigration",
457
+ message: migration.enabled
458
+ ? `The Fluxer instance announced a web domain migration, so links and OAuth URLs use the web app at ${webapp}`
459
+ : "The Fluxer instance announced a web domain migration that is switched off, so links and OAuth URLs are unchanged",
460
+ fields: {
461
+ enabled: migration.enabled,
462
+ webapp,
463
+ anonymousRolloutBasisPoints: migration.anonymousRolloutBasisPoints,
464
+ },
465
+ })
466
+ },
467
+ })
468
+ this.rest = new RestOwner({
469
+ cache: this.cache,
470
+ uploadMaxBytes: configuration.uploadMaxBytes,
471
+ resources: this.resources,
472
+ channels: this.channelCache,
473
+ users: this.userCache,
474
+ resolveInstance: () => this.instance.resolve(),
475
+ decodeMessage: configuration.decodeMessage,
476
+ logical,
477
+ logging: configuration.logging,
478
+ http: transport.http,
479
+ settings: configuration.rest,
480
+ shareGlobalPause: limits?.shareGlobalPause,
481
+ })
482
+ // Fluxer pauses every request of the account, so a pause another child learned holds this client's requests too
483
+ limits?.onGlobalPause((waitMs) => this.rest.pauseGlobal(waitMs))
484
+ if (configuration.sharding !== "auto") this.#adoptPlan(configuration.sharding, "Disconnected")
485
+ this.#shardHost = {
486
+ logging: this.logging,
487
+ instance: this.instance,
488
+ caches: this,
489
+ events: this.events,
490
+ presence: this.presence,
491
+ counts: this.counts,
492
+ memberChunks: this.memberChunks,
493
+ sockets: transport.sockets,
494
+ state: () => this.#state,
495
+ setShardState: (shard, state) => this.#setShardState(shard, state),
496
+ newSession: (shardId) => this.#clearShardGuilds(shardId),
497
+ identify: (shardId, send) => this.#identifyPermit(shardId, send),
498
+ identifyFields: (shardId) => this.#identifyFields(configuration, shardId),
499
+ sessions: configuration.sessions,
500
+ saveSessionOnClose: (shardId) =>
501
+ configuration.sessions !== undefined && this.#saveOnClose?.has(shardId) === true,
502
+ ...(configuration.reshard ? { reshard: (shardId: number) => this.#acceptReshard(shardId) } : {}),
503
+ ...(configuration.sessions && configuration.refillCaches
504
+ ? { restored: (shardId: number) => void this.#restoredShards.add(shardId) }
505
+ : {}),
506
+ // Fluxer replays every missed dispatch on Resume except THREAD_LIST_SYNC, so cached threads may be stale
507
+ resumed: (shardId) => this.channelCache?.dropThreads(this.#shardGuilds(shardId)),
508
+ readyUser: (body, shardId) => this.#readyUser(body, shardId),
509
+ }
510
+ }
511
+
512
+ /**
513
+ * Record the known plan, replace the shard runtimes and size REST concurrency for the local shard count. Called at
514
+ * creation, when an automatic plan is computed and when an automatic plan moves to a larger one
515
+ */
516
+ #adoptPlan(plan: ShardPlan, state: ConnectionState) {
517
+ this.#plan = plan
518
+ this.#shards.clear()
519
+ this.rest.scaleConcurrency(plan.shardIds.length)
520
+ for (const shardId of plan.shardIds)
521
+ this.#shards.set(shardId, {
522
+ shardId,
523
+ state,
524
+ latency: null,
525
+ recovery: null,
526
+ session: { id: undefined, sequence: null },
527
+ submit: undefined,
528
+ gatewayUrl: undefined,
529
+ })
530
+ }
531
+
532
+ /**
533
+ * Pace a fresh Identify across this client's shards, then wait for the supervisor's gate when one is configured.
534
+ * An application identify coordinator replaces the SDK's own spacing, and its permits are requested one at a time.
535
+ * A single unsharded, uncoordinated shard sends immediately
536
+ */
537
+ #identifyPermit(shardId: number, send: () => void): Effect.Effect<void, AttemptFailure> {
538
+ const owner = this
539
+ const plan = owner.#plan!
540
+ const coordinator = owner.#configuration?.identifyCoordinator
541
+ const permit = coordinator
542
+ ? // @effect-diagnostics-next-line unknownInEffectCatch:off
543
+ Effect.tryPromise({
544
+ try: (signal) => Promise.resolve(coordinator.permit(shardId, plan.totalShards, signal)),
545
+ catch: (error) => error,
546
+ }).pipe(
547
+ Effect.asVoid,
548
+ Effect.mapError((error) => {
549
+ owner.logging.log({
550
+ level: "error",
551
+ category: "lifecycle",
552
+ code: "lifecycle.identifyPermitFailed",
553
+ message: `The identify coordinator (sharding.identify) failed to grant shard ${shardId} permission to start a new session, so the SDK retries the connection as after a network failure`,
554
+ shardId,
555
+ error,
556
+ origin: "application",
557
+ })
558
+ return new AttemptFailure(
559
+ new ConnectionError("gateway", "network", null, {
560
+ cause: error,
561
+ details: {
562
+ detail: "the identify coordinator did not grant permission to start a new session",
563
+ },
564
+ hint: "Check the permit function of the sharding.identify coordinator",
565
+ }),
566
+ true,
567
+ )
568
+ }),
569
+ )
570
+ : Effect.void
571
+ const grant = () =>
572
+ owner.identifyGate
573
+ ? owner.identifyGate
574
+ .permit(shardId, send)
575
+ .pipe(Effect.mapError((error) => new AttemptFailure(error, true)))
576
+ : Effect.sync(send)
577
+ if (!plan.identifyShards) return permit.pipe(Effect.andThen(Effect.suspend(grant)))
578
+ if (coordinator) return owner.#identify.withPermit(permit.pipe(Effect.andThen(Effect.suspend(grant))))
579
+ return owner.#identify.withPermit(
580
+ Effect.gen(function* () {
581
+ const clock = yield* Clock.Clock
582
+ const now = () => nowMs(clock)
583
+ // Pace actual Identify sends, including handshakes that finish out of order
584
+ while (owner.#nextIdentifyAt > now()) yield* Effect.sleep(owner.#nextIdentifyAt - now())
585
+ yield* grant()
586
+ owner.#nextIdentifyAt = now() + identifySpacingMs
587
+ }),
588
+ )
589
+ }
590
+
591
+ /**
592
+ * Identify fields for one new session: The current presence intent, the flags and the ignored dispatch names.
593
+ * Automatic filtering reads the event registrations present now, so later registrations take effect at the next
594
+ * new session only
595
+ */
596
+ #identifyFields(configuration: Configuration<M>, shardId: number): IdentifyFields {
597
+ const gateway = configuration.gateway
598
+ const registered = this.events.registeredEvents()
599
+ let ignoredEvents: readonly string[]
600
+ if (gateway.ignoredEvents === "auto") {
601
+ ignoredEvents = automaticIgnoredEvents(registered, gateway.automaticNeeds)
602
+ } else {
603
+ ignoredEvents = gateway.ignoredEvents
604
+ const suppressed = suppressedRegistrations(registered, new Set(ignoredEvents))
605
+ if (suppressed.length)
606
+ this.logging.log({
607
+ level: "warn",
608
+ category: "gateway",
609
+ code: "gateway.ignoredEventRegistered",
610
+ message: `Handlers for ${suppressed.join(", ")} receive nothing on shard ${shardId}, because gateway.ignoredEvents suppresses every gateway event that delivers them`,
611
+ shardId,
612
+ fields: { events: suppressed.join(",") },
613
+ })
614
+ }
615
+ if (ignoredEvents.length && this.logging.enabled("debug", "gateway"))
616
+ this.logging.log({
617
+ level: "debug",
618
+ category: "gateway",
619
+ code: "gateway.identifyFilter",
620
+ message: `Shard ${shardId} asks Fluxer not to send ${ignoredEvents.length} gateway event type${ignoredEvents.length === 1 ? "" : "s"}`,
621
+ shardId,
622
+ fields: { ignoredEvents: ignoredEvents.join(","), automatic: gateway.ignoredEvents === "auto" },
623
+ })
624
+ return {
625
+ presence: this.presence.identifyPresence(),
626
+ ignoredEvents,
627
+ flags: gateway.flags,
628
+ }
629
+ }
630
+ get state(): ConnectionState {
631
+ return this.#state
632
+ }
633
+ /** Default deadline for multi-step REST workflows, from rest.defaultTimeoutMs */
634
+ get defaultTimeoutMs(): number {
635
+ return this.rest.defaultTimeoutMs
636
+ }
637
+ get gatewayLatencyMs(): number | null {
638
+ if (this.#state !== "Connected") return null
639
+ let maximum = 0
640
+ for (const shard of this.#shards.values()) {
641
+ if (shard.latency === null) return null
642
+ maximum = Math.max(maximum, shard.latency)
643
+ }
644
+ return maximum
645
+ }
646
+ get shards(): readonly ShardState[] {
647
+ return Object.freeze(
648
+ [...this.#shards.values()].map((shard) =>
649
+ Object.freeze({
650
+ shardId: shard.shardId,
651
+ state: shard.state,
652
+ gatewayLatencyMs: shard.latency,
653
+ recovery:
654
+ shard.recovery === null
655
+ ? null
656
+ : Object.freeze({
657
+ phase: shard.recovery.phase,
658
+ attempt: shard.recovery.attempt,
659
+ retryDelayMs: shard.recovery.retryDelayMs,
660
+ }),
661
+ }),
662
+ ),
663
+ )
664
+ }
665
+ diagnostics(): ClientDiagnostics {
666
+ const rest = this.rest.diagnostics()
667
+ const caches = Object.freeze({
668
+ messages: freezeCacheDiagnostic(this.cache?.diagnostics()),
669
+ guilds: freezeCacheDiagnostic(this.resources?.diagnostics("guilds")),
670
+ members: freezeCacheDiagnostic(this.resources?.diagnostics("members")),
671
+ roles: freezeCacheDiagnostic(this.resources?.diagnostics("roles")),
672
+ channels: freezeCacheDiagnostic(this.channelCache?.diagnostics()),
673
+ users: freezeCacheDiagnostic(this.userCache.diagnostics("users")),
674
+ directMessages: freezeCacheDiagnostic(this.userCache.diagnostics("directMessages")),
675
+ emojis: freezeCacheDiagnostic(this.resources?.diagnostics("emojis")),
676
+ stickers: freezeCacheDiagnostic(this.resources?.diagnostics("stickers")),
677
+ })
678
+ return Object.freeze({
679
+ state: this.state,
680
+ gatewayLatencyMs: this.gatewayLatencyMs,
681
+ shards: this.shards,
682
+ rest: Object.freeze({
683
+ activeRequests: rest.activeRequests,
684
+ activeCapacity: rest.activeCapacity,
685
+ queuedRequests: rest.queuedRequests,
686
+ queuedCapacity: rest.queuedCapacity,
687
+ queuedJsonBytes: rest.queuedJsonBytes,
688
+ queuedJsonByteCapacity: rest.queuedJsonByteCapacity,
689
+ }),
690
+ uploads: Object.freeze({ reservedBytes: rest.reservedUploadBytes, byteCapacity: rest.uploadByteCapacity }),
691
+ gatewayRequests: Object.freeze(this.#gatewayRequests.diagnostics()),
692
+ events: Object.freeze(this.events.diagnostics()),
693
+ caches,
694
+ counters: this.logging.counters(),
695
+ })
696
+ }
697
+ cacheEntries<K extends CacheKind>(
698
+ kind: K,
699
+ options?: CacheEntriesOptions,
700
+ ): Effect.Effect<readonly CachedResources<M>[K][], ConfigurationError> {
701
+ return suspendInput(() => {
702
+ if (!cacheKinds.includes(kind))
703
+ return Effect.fail(
704
+ new ConfigurationError("kind", `The cache kind must be one of ${cacheKinds.join(", ")}`),
705
+ )
706
+ if (options !== undefined && (typeof options !== "object" || options === null || Array.isArray(options)))
707
+ return Effect.fail(new ConfigurationError("limit", "Cache entry options must contain only limit"))
708
+ const unsupported = options && Object.keys(options).find((key) => key !== "limit")
709
+ if (unsupported !== undefined)
710
+ return Effect.fail(
711
+ new ConfigurationError(
712
+ "limit",
713
+ `Unsupported option ${JSON.stringify(unsupported)} in the cache entry options`,
714
+ { hint: unsupportedKeyHint(unsupported, ["limit"]) },
715
+ ),
716
+ )
717
+ // Read limit once, so the validated limit is the one applied
718
+ const limitInput = options?.limit
719
+ const limit = limitInput === undefined ? 100 : limitInput
720
+ if (typeof limit !== "number" || !Number.isSafeInteger(limit) || limit < 1 || limit > 1_000)
721
+ return Effect.fail(
722
+ new ConfigurationError("limit", "Cache entry limit must be a safe integer from 1 through 1,000"),
723
+ )
724
+ return Effect.sync(() => this.#cacheEntries(kind, limit))
725
+ })
726
+ }
727
+ /** The public cache.clear: Every cache, or one validated kind */
728
+ clearCache(kind?: CacheKind) {
729
+ if (kind === undefined) {
730
+ clearCaches(this)
731
+ return
732
+ }
733
+ const valid = validCacheKind(kind)
734
+ switch (valid) {
735
+ case "messages":
736
+ return this.cache?.clear()
737
+ case "guilds":
738
+ case "members":
739
+ case "roles":
740
+ case "emojis":
741
+ case "stickers":
742
+ return this.resources?.clearKind(valid)
743
+ case "channels":
744
+ return this.channelCache?.clear()
745
+ case "users":
746
+ case "directMessages":
747
+ return this.userCache.invalidate(valid)
748
+ }
749
+ }
750
+ /** The public cache.delete: One entry by its validated CacheChange key */
751
+ deleteCacheEntry(kind: CacheKind, key: string) {
752
+ const valid = validCacheKind(kind)
753
+ const format = cachePairKeys[valid as keyof typeof cachePairKeys] as string | undefined
754
+ const parts = typeof key === "string" ? key.split(":") : []
755
+ if (parts.length !== (format === undefined ? 1 : 2) || !parts.every(identifier))
756
+ throw new ConfigurationError("key", `A ${valid} cache key must be ${format ?? "a decimal ID"}`)
757
+ const [first, second] = parts as [string, string | undefined]
758
+ switch (valid) {
759
+ case "messages":
760
+ return this.cache?.deleteMany(first, [second!])
761
+ case "guilds":
762
+ case "members":
763
+ case "roles":
764
+ case "emojis":
765
+ case "stickers":
766
+ // A community's own key is its ID, which the guild cache stores as both community and resource ID
767
+ return this.resources?.delete(valid, first, second ?? first)
768
+ case "channels":
769
+ return this.channelCache?.delete(first)
770
+ case "users":
771
+ case "directMessages":
772
+ return this.userCache.invalidate(valid, first)
773
+ }
774
+ }
775
+ #cacheEntries<K extends CacheKind>(kind: K, limit: number): readonly CachedResources<M>[K][] {
776
+ switch (kind) {
777
+ case "messages":
778
+ return (this.cache?.entries(limit) ?? emptyEntries) as readonly CachedResources<M>[K][]
779
+ case "guilds":
780
+ case "members":
781
+ case "roles":
782
+ case "emojis":
783
+ case "stickers":
784
+ return (this.resources?.entries(kind, limit) ?? emptyEntries) as readonly CachedResources<M>[K][]
785
+ case "channels":
786
+ return (this.channelCache?.entries(limit) ?? emptyEntries) as readonly CachedResources<M>[K][]
787
+ case "users":
788
+ case "directMessages":
789
+ return this.userCache.entries(kind, limit) as readonly CachedResources<M>[K][]
790
+ }
791
+ }
792
+ shardIdForGuild(guildId: string): number | undefined {
793
+ if (this.#plan === undefined) return undefined
794
+ const id = guildShardId(guildId, this.#plan.totalShards)
795
+ return this.#shards.has(id) ? id : undefined
796
+ }
797
+ /** The public client.shardIdForGuild: shardIdForGuild after checking the caller's ID */
798
+ ownedShardForGuild(guildId: unknown): number | undefined {
799
+ if (!identifier(guildId)) throw new ConfigurationError("guildId", "Guild IDs must be decimal strings")
800
+ return this.shardIdForGuild(guildId)
801
+ }
802
+ gatewayState(guildId?: string): ConnectionState {
803
+ if (guildId === undefined) return this.#state
804
+ if (this.#state === "Closing" || this.#state === "Closed") return this.#state
805
+ const id = this.shardIdForGuild(guildId)
806
+ return id === undefined ? "Disconnected" : this.#shards.get(id)!.state
807
+ }
808
+ subscribeGateway(guildId: string | undefined, listener: (state: ConnectionState) => void) {
809
+ if (guildId === undefined) return this.subscribe(listener)
810
+ const id = this.shardIdForGuild(guildId)
811
+ if (id === undefined) {
812
+ listener(this.gatewayState(guildId))
813
+ return () => {}
814
+ }
815
+ let listeners = this.#shardListeners.get(id)
816
+ if (!listeners) this.#shardListeners.set(id, (listeners = new Set()))
817
+ if (this.#state !== "Closed") listeners.add(listener)
818
+ listener(this.gatewayState(guildId))
819
+ return () => {
820
+ listeners.delete(listener)
821
+ // A move to a larger plan replaces the listener sets, and a new set for the same ID must stay
822
+ if (!listeners.size && this.#shardListeners.get(id) === listeners) this.#shardListeners.delete(id)
823
+ }
824
+ }
825
+ #shardGuilds(shardId: number) {
826
+ const totalShards = this.#plan?.totalShards ?? 1
827
+ return (guildId: string | null | undefined) =>
828
+ guildId === undefined || (guildId === null ? shardId === 0 : guildShardId(guildId, totalShards) === shardId)
829
+ }
830
+ /**
831
+ * Invalidate a shard's cached observations when its connection is lost. Guild-scoped entries stay while the shard
832
+ * can still resume, because Fluxer's Resume replays every missed dispatch or refuses the session, and
833
+ * #clearShardGuilds releases them once a new session is needed. Messages and users are cleared at once
834
+ */
835
+ #gapShard(shardId: number, resumable: boolean) {
836
+ const affects = this.#shardGuilds(shardId)
837
+ this.cache?.gap(affects)
838
+ if (resumable) {
839
+ this.resources?.pause(affects)
840
+ this.channelCache?.pause(affects)
841
+ } else this.#clearShardGuilds(shardId)
842
+ this.userCache.gap(affects)
843
+ this.counts.detach(shardId)
844
+ this.memberChunks.detach(shardId)
845
+ this.presence.detach(shardId)
846
+ }
847
+ /** Release a shard's guild-scoped entries when its next connection starts a new session, which replays nothing */
848
+ #clearShardGuilds(shardId: number) {
849
+ const affects = this.#shardGuilds(shardId)
850
+ this.resources?.gap(affects)
851
+ this.channelCache?.gap(affects)
852
+ }
853
+ #setShardState(shard: ShardRuntime, state: ConnectionState) {
854
+ if (this.#state === "Closing" || this.#state === "Closed" || shard.state === state) return
855
+ if (state === "Recovering") this.#gapShard(shard.shardId, true)
856
+ shard.state = state
857
+ if (state !== "Connected") shard.latency = null
858
+ for (const listener of this.#shardListeners.get(shard.shardId) ?? []) listener(state)
859
+ if ([...this.#shards.values()].every((value) => value.state === "Connected")) {
860
+ this.#groupReady = true
861
+ this.#setState("Connected")
862
+ } else this.#setState(this.#groupReady ? "Recovering" : "Connecting")
863
+ }
864
+
865
+ #setState(state: ConnectionState) {
866
+ if (this.#state === state) return
867
+ if (state === "Disconnected") {
868
+ // A reusable startup can have delivered events from a ready sibling before the group failed
869
+ for (const shard of this.#shards.values())
870
+ if (shard.state === "Connected" || shard.state === "Recovering") this.#gapShard(shard.shardId, false)
871
+ }
872
+ if (state === "Closing" || state === "Closed") this.cache?.close()
873
+ if (state === "Closing" || state === "Closed") this.counts.close()
874
+ if (state === "Closing" || state === "Closed") this.memberChunks.close()
875
+ if (state === "Closing" || state === "Closed") this.resources?.close()
876
+ if (state === "Closing" || state === "Closed") this.userCache.close()
877
+ if (state === "Closing" || state === "Closed") this.presence.close()
878
+ if (state === "Closing" || state === "Closed") this.channelCache?.close()
879
+ this.#state = state
880
+ if (state === "Disconnected" || state === "Closing" || state === "Closed") {
881
+ for (const shard of this.#shards.values()) {
882
+ shard.state = state
883
+ shard.latency = null
884
+ if (state !== "Closing") shard.session = { id: undefined, sequence: null }
885
+ shard.recovery = null
886
+ for (const listener of this.#shardListeners.get(shard.shardId) ?? []) listener(state)
887
+ }
888
+ }
889
+ for (const listener of this.#listeners) listener(state)
890
+ if (state === "Closed") {
891
+ this.#listeners.clear()
892
+ this.#shardListeners.clear()
893
+ }
894
+ }
895
+
896
+ subscribe(listener: (state: ConnectionState) => void) {
897
+ if (this.#state !== "Closed") this.#listeners.add(listener)
898
+ listener(this.#state)
899
+ return () => {
900
+ this.#listeners.delete(listener)
901
+ }
902
+ }
903
+
904
+ observeState() {
905
+ const owner = this
906
+ return Stream.unwrap(
907
+ Effect.gen(function* () {
908
+ const queue = yield* Queue.sliding<ConnectionState, Cause.Done>(1)
909
+ let initial: ConnectionState | undefined
910
+ const unsubscribe = owner.subscribe((state) => {
911
+ if (initial === undefined) initial = state
912
+ else Queue.offerUnsafe(queue, state)
913
+ if (state === "Closed") Queue.endUnsafe(queue)
914
+ })
915
+ yield* Effect.addFinalizer(() => Effect.sync(unsubscribe).pipe(Effect.andThen(Queue.shutdown(queue))))
916
+ return Stream.concat(Stream.succeed(initial!), Stream.fromQueue(queue))
917
+ }),
918
+ )
919
+ }
920
+
921
+ #finish() {
922
+ Deferred.doneUnsafe(this.#typingClosed, Effect.void)
923
+ this.events.stop()
924
+ this.rest.stop()
925
+ if (this.#configuration) Redacted.wipeUnsafe(this.#configuration.token)
926
+ this.#configuration = undefined
927
+ this.#setState("Closed")
928
+ }
929
+
930
+ #selfUserId: string | undefined
931
+ /** The bot account ID once READY or a self read supplied it, without starting a read, for gateway cache intake */
932
+ get botUserId(): string | undefined {
933
+ return this.#selfUserId
934
+ }
935
+ /** The bot's own public account from the latest READY that carried a complete one, for users.getSelf */
936
+ #selfUser: User | undefined
937
+ /** The one users.fetchSelf read in flight, which concurrent mentions share */
938
+ #selfUserRead: Deferred.Deferred<string | undefined> | undefined
939
+ /** Consecutive failed reads, and the logical time before which no new read starts */
940
+ #selfUserFailures = 0
941
+ #selfUserRetryAtMs = 0
942
+ static readonly #selfUserBackoffMs = 5_000
943
+ static readonly #selfUserMaxBackoffMs = 300_000
944
+
945
+ /** The bot's username from the latest READY, for the connected record */
946
+ #readyName: string | undefined
947
+ /** Each shard's community count from its latest READY, for the connected record */
948
+ readonly #readyCommunities = new Map<number, number>()
949
+ /** Links for the discovered instance, so the connected record can offer an installation link */
950
+ #instanceLinks: LinkHelpers | undefined
951
+
952
+ /**
953
+ * Keep the bot account ID from a READY body's user, so mention prefixes need no REST read, its public account for
954
+ * users.getSelf when the user is complete, so an incomplete one keeps the previous account, and the bot's username and the shard's community count for the connected record. For a bot, READY
955
+ * lists each community as unavailable
956
+ */
957
+ #readyUser(body: unknown, shardId: number) {
958
+ const user = record(body) && record(body.user) ? body.user : undefined
959
+ if (identifier(user?.id) && user.id !== "0") this.#selfUserId = user.id
960
+ const self = decodeUser(user)
961
+ if (self !== undefined && self.id !== "0") this.#selfUser = self
962
+ if (typeof user?.username === "string" && user.username.length > 0) this.#readyName = user.username
963
+ if (record(body) && Array.isArray(body.guilds)) this.#readyCommunities.set(shardId, body.guilds.length)
964
+ else this.#readyCommunities.delete(shardId)
965
+ }
966
+
967
+ /**
968
+ * Log once per start that every local shard is connected, naming the bot and its community count when READY
969
+ * supplied them. A bot that owns every shard and is in no community gets a Warn with an installation link instead
970
+ */
971
+ #logConnected(context: Context.Context<never>) {
972
+ const plan = this.#plan
973
+ if (plan === undefined) return
974
+ const counts = plan.shardIds.map((shardId) => this.#readyCommunities.get(shardId))
975
+ const communities = counts.every((count) => count !== undefined)
976
+ ? counts.reduce<number>((total, count) => total + count!, 0)
977
+ : undefined
978
+ const everyShard = plan.shardIds.length === plan.totalShards
979
+ const subject = `Connected to Fluxer${this.#readyName === undefined ? "" : ` as ${this.#readyName}`}`
980
+ const empty = communities === 0 && everyShard
981
+ const message = empty
982
+ ? `${subject}, but the bot is not in any community yet. ${this.#inviteText()}`
983
+ : communities === undefined
984
+ ? subject
985
+ : `${subject} in ${communities} ${communities === 1 ? "community" : "communities"}${everyShard ? "" : " on this client's shards"}`
986
+ this.logging.log(
987
+ {
988
+ level: empty ? "warn" : "info",
989
+ category: "lifecycle",
990
+ code: "lifecycle.connected",
991
+ message,
992
+ fields: { communities: communities ?? null, shards: plan.shardIds.length },
993
+ },
994
+ context,
995
+ )
996
+ }
997
+
998
+ /** Where to invite the bot: Its installation link when the bot account ID and instance are known */
999
+ #inviteText(): string {
1000
+ const id = this.#selfUserId
1001
+ if (id === undefined || this.#instanceLinks === undefined)
1002
+ return "Invite it with an installation link that uses the application ID"
1003
+ try {
1004
+ return `Invite it by opening ${this.#instanceLinks.installation(id)}`
1005
+ } catch {
1006
+ // allow-silent: An ID the link helper rejects still gets the general instruction
1007
+ return "Invite it with an installation link that uses the application ID"
1008
+ }
1009
+ }
1010
+
1011
+ /** The bot's own public account from the latest READY, kept for the client lifetime. It never fails */
1012
+ getSelf(): Effect.Effect<User | undefined> {
1013
+ return Effect.sync(() => this.#selfUser)
1014
+ }
1015
+
1016
+ /**
1017
+ * The bot account ID for command mention prefixes, kept for the client lifetime.
1018
+ * READY normally supplies it. Until then it is read through users.fetchSelf, and concurrent callers share one read.
1019
+ * A failed read is logged at Warn and produces undefined, and callers get undefined without a new read for a backoff
1020
+ * that starts at 5 seconds and doubles per consecutive failure up to 5 minutes, unless READY supplies the ID first
1021
+ */
1022
+ selfUserId(): Effect.Effect<string | undefined> {
1023
+ return Effect.suspend(() => {
1024
+ if (this.#selfUserId !== undefined) return Effect.succeed(this.#selfUserId)
1025
+ if (this.#selfUserRead !== undefined) return Deferred.await(this.#selfUserRead)
1026
+ if (this.logical.now() < this.#selfUserRetryAtMs) return Effect.succeed(undefined)
1027
+ const read = Deferred.makeUnsafe<string | undefined>()
1028
+ this.#selfUserRead = read
1029
+ return this.user("users.fetchSelf", () => userFetch("@me")).pipe(
1030
+ Effect.map((user) => {
1031
+ this.#selfUserFailures = 0
1032
+ return (this.#selfUserId = user.id)
1033
+ }),
1034
+ Effect.catch((error) =>
1035
+ Effect.sync(() => {
1036
+ this.#selfUserFailures += 1
1037
+ const retryInMs = Math.min(
1038
+ ClientOwner.#selfUserMaxBackoffMs,
1039
+ ClientOwner.#selfUserBackoffMs * 2 ** (this.#selfUserFailures - 1),
1040
+ )
1041
+ this.#selfUserRetryAtMs = this.logical.now() + retryInMs
1042
+ this.logging.log({
1043
+ level: "warn",
1044
+ category: "commands",
1045
+ code: "commands.mentionPrefixUnavailable",
1046
+ message: `The bot's user ID could not be read, so commands that start with a mention of the bot are ignored for ${retryInMs / 1_000} s. The next such command after that reads the ID again`,
1047
+ error,
1048
+ fields: { retryInMs, failures: this.#selfUserFailures },
1049
+ })
1050
+ return undefined
1051
+ }),
1052
+ ),
1053
+ // Waiters get the reader's result. An interrupted or defective read releases them with undefined and
1054
+ // lets the next mention read again
1055
+ Effect.onExit((exit) =>
1056
+ Effect.sync(() => {
1057
+ this.#selfUserRead = undefined
1058
+ Deferred.doneUnsafe(read, Effect.succeed(Exit.isSuccess(exit) ? exit.value : undefined))
1059
+ }),
1060
+ ),
1061
+ )
1062
+ })
1063
+ }
1064
+
1065
+ user<A>(
1066
+ operation: UserOperation,
1067
+ build: () => UserRequest<A> | InputValidationFailure,
1068
+ options?: UserOperationOptions,
1069
+ ) {
1070
+ return suspendInput(() => {
1071
+ if (!this.#configuration || this.#state === "Closing" || this.#state === "Closed")
1072
+ return Effect.fail(new ClientClosedError())
1073
+ const request = build()
1074
+ if (request instanceof InputValidationFailure)
1075
+ return Effect.fail(
1076
+ new UserOperationError({
1077
+ operation,
1078
+ reason: "input",
1079
+ outcome: "notDispatched",
1080
+ inputValidation: request.detail,
1081
+ }),
1082
+ )
1083
+ const owner = this
1084
+ const token = this.#configuration.token
1085
+ // Read the caller's options here, where a throwing getter is reported as an application fault
1086
+ const timeout = options?.timeoutMs ?? owner.rest.defaultTimeoutMs
1087
+ const unsupportedOption = record(options)
1088
+ ? unsupportedKeyFailure(options, ["timeoutMs", "signal"], "options", "the operation options")
1089
+ : undefined
1090
+ return Effect.gen(function* () {
1091
+ if (options !== undefined && !record(options))
1092
+ return yield* Effect.fail(
1093
+ new UserOperationError({
1094
+ operation,
1095
+ reason: "input",
1096
+ outcome: "notDispatched",
1097
+ inputValidation: inputValidationFailure(
1098
+ "options",
1099
+ "type",
1100
+ "Operation options must be an object",
1101
+ ).detail,
1102
+ }),
1103
+ )
1104
+ if (unsupportedOption)
1105
+ return yield* Effect.fail(
1106
+ new UserOperationError({
1107
+ operation,
1108
+ reason: "input",
1109
+ outcome: "notDispatched",
1110
+ inputValidation: unsupportedOption.detail,
1111
+ }),
1112
+ )
1113
+ if (!Number.isSafeInteger(timeout) || timeout <= 0 || timeout > 2_147_483_647)
1114
+ return yield* Effect.fail(
1115
+ new UserOperationError({
1116
+ operation,
1117
+ reason: "input",
1118
+ outcome: "notDispatched",
1119
+ inputValidation: inputValidationFailure(
1120
+ "options.timeoutMs",
1121
+ "range",
1122
+ "Operation timeoutMs must be an integer from 1 through 2,147,483,647 milliseconds",
1123
+ ).detail,
1124
+ }),
1125
+ )
1126
+ const deadline = owner.logical.now() + timeout
1127
+ if (request.verifyType) {
1128
+ const channel = yield* owner.rest.user(
1129
+ token,
1130
+ operation,
1131
+ () => directMessageFetch(request.id!),
1132
+ options,
1133
+ )
1134
+ if (request.verifyType === "group" && channel.type !== "group")
1135
+ return yield* Effect.fail(
1136
+ new UserOperationError({
1137
+ operation,
1138
+ reason: "input",
1139
+ outcome: "notDispatched",
1140
+ inputValidation: inputValidationFailure(
1141
+ "channelId",
1142
+ "relationship",
1143
+ "This operation requires a group DM channel",
1144
+ ).detail,
1145
+ }),
1146
+ )
1147
+ }
1148
+ const remaining = Math.floor(deadline - owner.logical.now())
1149
+ if (remaining <= 0)
1150
+ return yield* Effect.fail(
1151
+ new UserOperationError({ operation, reason: "timeout", outcome: "notDispatched" }),
1152
+ )
1153
+ if (request.noCache)
1154
+ return yield* owner.rest.user(token, operation, () => request, { timeoutMs: remaining })
1155
+ const guard = owner.userCache.begin(request.resource, {
1156
+ ...(request.id === undefined ? {} : { id: request.id }),
1157
+ mutation: request.method !== "GET",
1158
+ ...(request.replace === undefined ? {} : { replace: request.replace }),
1159
+ })
1160
+ return yield* owner.rest
1161
+ .user(token, operation, () => request, { timeoutMs: remaining })
1162
+ .pipe(
1163
+ Effect.tap((value) =>
1164
+ Effect.sync(() =>
1165
+ owner.userCache.complete(
1166
+ guard,
1167
+ (value === undefined ? [] : Array.isArray(value) ? value : [value]) as readonly (
1168
+ User | DirectMessageChannel
1169
+ )[],
1170
+ ),
1171
+ ),
1172
+ ),
1173
+ Effect.onExit((exit) =>
1174
+ Effect.sync(() => {
1175
+ if (exit._tag === "Failure") {
1176
+ owner.userCache.failed(guard)
1177
+ }
1178
+ if (request.method === "DELETE" && request.id) owner.cache?.deleteChannel(request.id)
1179
+ }),
1180
+ ),
1181
+ )
1182
+ })
1183
+ })
1184
+ }
1185
+
1186
+ application<A>(
1187
+ operation: BotApplicationOperation,
1188
+ build: () => BotApplicationRequest<A>,
1189
+ options?: BotApplicationOperationOptions,
1190
+ ) {
1191
+ return Effect.suspend(() =>
1192
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1193
+ ? this.rest.application(this.#configuration.token, operation, build, options)
1194
+ : Effect.fail(new ClientClosedError()),
1195
+ )
1196
+ }
1197
+
1198
+ getUserResource<K extends "users" | "directMessages">(kind: K, id: string) {
1199
+ return Effect.suspend(
1200
+ (): Effect.Effect<UserResources[K] | undefined, ClientClosedError | UserOperationError> => {
1201
+ if (!this.#configuration || this.#state === "Closing" || this.#state === "Closed")
1202
+ return Effect.fail(new ClientClosedError())
1203
+ if (!identifier(id))
1204
+ return Effect.fail(
1205
+ new UserOperationError({
1206
+ operation: `${kind}.get`,
1207
+ reason: "input",
1208
+ outcome: "notDispatched",
1209
+ inputValidation: inputValidationFailure(
1210
+ kind === "users" ? "userId" : "channelId",
1211
+ "format",
1212
+ kind === "users"
1213
+ ? "User IDs must be decimal strings"
1214
+ : "Channel IDs must be decimal strings",
1215
+ ).detail,
1216
+ }),
1217
+ )
1218
+ return Effect.succeed(this.userCache.get(kind, id))
1219
+ },
1220
+ )
1221
+ }
1222
+
1223
+ /** Send one caller-described request through this client's REST scheduler */
1224
+ request<T>(input: RestRequest | DefaultRestRequest): Effect.Effect<RestResponse<T>, RestRequestFailure> {
1225
+ return Effect.suspend(() =>
1226
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1227
+ ? this.rest.request<T>(this.#configuration.token, input)
1228
+ : Effect.fail(new ClientClosedError()),
1229
+ )
1230
+ }
1231
+
1232
+ /**
1233
+ * Send one application command on a ready local shard through that socket's paced path.
1234
+ * Validation happens before anything is queued. The data is copied through JSON so later caller changes cannot
1235
+ * alter the frame, and a frame above Fluxer's 4,096-byte limit is rejected rather than closing the connection
1236
+ */
1237
+ gatewaySend(shardId: number, op: number, d: unknown, options?: unknown): Effect.Effect<void, GatewaySendFailure> {
1238
+ // Only encoding the caller data is marked, so a throw from its getters or toJSON is an application fault
1239
+ return suspendMarked((): Effect.Effect<void, GatewaySendFailure> => {
1240
+ if (!this.#configuration || this.#state === "Closing" || this.#state === "Closed")
1241
+ return Effect.fail(new ClientClosedError())
1242
+ const validShard = typeof shardId === "number" && Number.isSafeInteger(shardId) && shardId >= 0
1243
+ const validOpcode = typeof op === "number" && Number.isSafeInteger(op) && op >= 0
1244
+ const input = (path: string, explanation: string, cause?: unknown) =>
1245
+ Effect.fail(
1246
+ new GatewaySendError({
1247
+ reason: "input",
1248
+ shardId: validShard ? shardId : null,
1249
+ opcode: validOpcode ? op : null,
1250
+ inputValidation: inputValidationFailure(path, path === "d" ? "format" : "type", explanation)
1251
+ .detail,
1252
+ cause,
1253
+ }),
1254
+ )
1255
+ if (!validShard) return input("shardId", "Shard IDs must be non-negative integers")
1256
+ if (!validOpcode) return input("op", "Opcodes must be non-negative integers")
1257
+ // Only the default API passes options, whose signal the operation executor reads
1258
+ const unsupported = record(options)
1259
+ ? readCaller(() => unsupportedKeyFailure(options, ["signal"], "options", "the gateway send options"))
1260
+ : undefined
1261
+ if (unsupported)
1262
+ return Effect.fail(
1263
+ new GatewaySendError({ reason: "input", shardId, opcode: op, inputValidation: unsupported.detail }),
1264
+ )
1265
+ if (reservedClientOpcodes.has(op))
1266
+ return Effect.fail(new GatewaySendError({ reason: "reserved", shardId, opcode: op }))
1267
+ const result = readCaller(() => encodeCommandData(d))
1268
+ if ("failure" in result) return input("d", "Command data must be encodable as JSON", result.failure)
1269
+ const encoded = result.json
1270
+ if (encoded === undefined) return input("d", "Command data must be a JSON value; use null for no data")
1271
+ if (Buffer.byteLength(`{"op":${op},"d":${encoded}}`) > maxClientPayloadBytes)
1272
+ return input("d", "The encoded command must be at most 4,096 bytes")
1273
+ const shard = this.#shards.get(shardId)
1274
+ if (!shard) return Effect.fail(new GatewaySendError({ reason: "notOwned", shardId, opcode: op }))
1275
+ if (shard.state !== "Connected" || shard.submit === undefined)
1276
+ return Effect.fail(new GatewaySendError({ reason: "notReady", shardId, opcode: op }))
1277
+ // Fluxer limits raw member requests together with members.iterateChunks, so one counts there too, and in a
1278
+ // supervisor's account-wide window, from the moment the socket takes it, because a caller interrupted before it
1279
+ // resumes cannot withdraw a sent frame. It is counted, never refused
1280
+ const sent = op === Opcode.requestGuildMembers ? () => this.memberChunks.countSent() : undefined
1281
+ return shard.submit(op, JSON.parse(encoded), sent).pipe(
1282
+ Effect.mapError(
1283
+ (reason) =>
1284
+ new GatewaySendError({
1285
+ reason: reason === "busy" ? "busy" : "notReady",
1286
+ shardId,
1287
+ opcode: op,
1288
+ }),
1289
+ ),
1290
+ )
1291
+ })
1292
+ }
1293
+
1294
+ webhook<A>(
1295
+ operation: WebhookOperation,
1296
+ build: () => WebhookRequest<A> | InputValidationFailure,
1297
+ options?: WebhookOperationOptions,
1298
+ ) {
1299
+ return Effect.suspend(() =>
1300
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1301
+ ? this.rest.webhook(this.#configuration.token, operation, build, options)
1302
+ : Effect.fail(new ClientClosedError()),
1303
+ )
1304
+ }
1305
+
1306
+ guild<A>(operation: GuildOperation, build: GuildBuild<A>, options?: GuildOperationOptions) {
1307
+ return Effect.suspend(() =>
1308
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1309
+ ? this.rest.guild(this.#configuration.token, operation, build, options)
1310
+ : Effect.fail(new ClientClosedError()),
1311
+ )
1312
+ }
1313
+
1314
+ leaveGuild(guildId: string, options?: GuildOperationOptions) {
1315
+ return this.guild("guilds.leave", () => guildLeave(guildId), options).pipe(
1316
+ Effect.tap(() => Effect.sync(() => this.presence.forgetMembers(guildId))),
1317
+ )
1318
+ }
1319
+
1320
+ deleteOwnGuildMessages(guildId: string, options: unknown) {
1321
+ return suspendInput(() => {
1322
+ const checked = ownDeletionOptions<GuildOperationOptions>(options)
1323
+ return checked instanceof InputValidationFailure
1324
+ ? this.guild<void>("guilds.deleteOwnMessages", () => checked)
1325
+ : this.guild("guilds.deleteOwnMessages", () => guildDeleteOwnMessages(guildId), checked)
1326
+ })
1327
+ }
1328
+
1329
+ channel<A>(
1330
+ operation: ChannelOperation,
1331
+ build: () => ChannelRequest<A> | InputValidationFailure,
1332
+ options?: ChannelOperationOptions,
1333
+ ) {
1334
+ return Effect.suspend(() =>
1335
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1336
+ ? this.rest.channel(this.#configuration.token, operation, build, options)
1337
+ : Effect.fail(new ClientClosedError()),
1338
+ )
1339
+ }
1340
+
1341
+ getChannel(id: string) {
1342
+ return Effect.suspend(
1343
+ (): Effect.Effect<GuildChannel | undefined, ClientClosedError | ChannelOperationError> => {
1344
+ if (!this.#configuration || this.#state === "Closing" || this.#state === "Closed")
1345
+ return Effect.fail(new ClientClosedError())
1346
+ if (!identifier(id))
1347
+ return Effect.fail(
1348
+ new ChannelOperationError({
1349
+ operation: "channels.get",
1350
+ reason: "input",
1351
+ outcome: "notDispatched",
1352
+ inputValidation: inputValidationFailure(
1353
+ "channelId",
1354
+ "format",
1355
+ "Channel IDs must be decimal strings",
1356
+ ).detail,
1357
+ }),
1358
+ )
1359
+ return Effect.succeed(this.channelCache?.get(id))
1360
+ },
1361
+ )
1362
+ }
1363
+
1364
+ getResource<K extends ResourceKind>(kind: K, target: string | MemberReference | RoleReference) {
1365
+ return suspendInput((): Effect.Effect<Resources[K] | undefined, ClientClosedError | GuildOperationError> => {
1366
+ if (!this.#configuration || this.#state === "Closing" || this.#state === "Closed")
1367
+ return Effect.fail(new ClientClosedError())
1368
+ const guildId = kind === "guilds" ? target : record(target) ? target.guildId : undefined
1369
+ const id =
1370
+ kind === "guilds"
1371
+ ? guildId
1372
+ : record(target)
1373
+ ? kind === "members"
1374
+ ? target.userId
1375
+ : target.id
1376
+ : undefined
1377
+ if (!identifier(guildId) || !identifier(id))
1378
+ return Effect.fail(
1379
+ new GuildOperationError({
1380
+ operation: `${kind}.get`,
1381
+ reason: "input",
1382
+ outcome: "notDispatched",
1383
+ inputValidation: inputValidationFailure(
1384
+ kind === "guilds" ? "guildId" : "target",
1385
+ "format",
1386
+ kind === "guilds"
1387
+ ? "Guild IDs must be decimal strings"
1388
+ : "Resource targets require decimal guild and resource IDs",
1389
+ ).detail,
1390
+ }),
1391
+ )
1392
+ return Effect.sync(() => this.resources?.get(kind, guildId, id))
1393
+ })
1394
+ }
1395
+
1396
+ reply(target: MessageReference, input: MessageInput | string, options?: SendOptions) {
1397
+ return suspendInput(() => {
1398
+ const request = replyInput(target, input)
1399
+ if (request instanceof MessageError) return Effect.fail(request)
1400
+ return this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1401
+ ? this.rest.reply(this.#configuration.token, request.target, request.input, options)
1402
+ : Effect.fail(new ClientClosedError())
1403
+ })
1404
+ }
1405
+
1406
+ send(channelId: string, input: MessageInput | string, options?: SendOptions) {
1407
+ return Effect.suspend(() =>
1408
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1409
+ ? this.rest.send(this.#configuration.token, channelId, input, options)
1410
+ : Effect.fail(new ClientClosedError()),
1411
+ )
1412
+ }
1413
+ refreshAttachmentUrls(
1414
+ urls: readonly string[],
1415
+ options?: AttachmentRefreshOptions,
1416
+ ): Effect.Effect<readonly RefreshedAttachmentUrl[], AttachmentRefreshFailure> {
1417
+ return Effect.suspend(() =>
1418
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1419
+ ? this.rest.refreshAttachmentUrls(this.#configuration.token, urls, options)
1420
+ : Effect.fail(new ClientClosedError()),
1421
+ )
1422
+ }
1423
+ downloadAttachment(
1424
+ attachment: Attachment,
1425
+ options?: AttachmentDownloadOptions,
1426
+ ): Effect.Effect<Uint8Array, AttachmentDownloadFailure> {
1427
+ return Effect.suspend(() =>
1428
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1429
+ ? this.rest.download(attachment, options)
1430
+ : Effect.fail(new ClientClosedError()),
1431
+ )
1432
+ }
1433
+ streamAttachment(
1434
+ attachment: Attachment,
1435
+ options?: AttachmentDownloadOptions,
1436
+ ): Effect.Effect<AttachmentDownloadSource, AttachmentDownloadFailure> {
1437
+ return Effect.suspend(() =>
1438
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1439
+ ? this.rest.openDownload(attachment, options)
1440
+ : Effect.fail(new ClientClosedError()),
1441
+ )
1442
+ }
1443
+
1444
+ forward(channelId: string, input: ForwardMessageInput, options?: SendOptions) {
1445
+ return Effect.suspend(() =>
1446
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1447
+ ? this.rest.forward(this.#configuration.token, channelId, input, options)
1448
+ : Effect.fail(new ClientClosedError()),
1449
+ )
1450
+ }
1451
+
1452
+ sendDirectMessage(userId: string, input: MessageInput | string, options?: SendOptions) {
1453
+ return suspendInput((): Effect.Effect<M, SendError> => {
1454
+ if (!this.#configuration || this.#state === "Closing" || this.#state === "Closed")
1455
+ return Effect.fail(new ClientClosedError())
1456
+ if (!identifier(userId))
1457
+ return Effect.fail(
1458
+ new MessageError({
1459
+ reason: "input",
1460
+ outcome: "notDispatched",
1461
+ inputValidation: inputValidationFailure("userId", "format", "User IDs must be decimal strings")
1462
+ .detail,
1463
+ }),
1464
+ )
1465
+ if (typeof input !== "string" && !record(input))
1466
+ return Effect.fail(
1467
+ new MessageError({
1468
+ reason: "input",
1469
+ outcome: "notDispatched",
1470
+ inputValidation: inputValidationFailure(
1471
+ "input",
1472
+ "type",
1473
+ "Direct message input must be a string or an object",
1474
+ ).detail,
1475
+ }),
1476
+ )
1477
+ // The send encoder rejects a messageReference first, reading it only once with the other fields
1478
+ return this.rest.send(this.#configuration.token, userId, input, options, userId)
1479
+ })
1480
+ }
1481
+
1482
+ fetchReactionUsers(
1483
+ target: MessageReference,
1484
+ emoji: ReactionEmojiInput,
1485
+ query?: ReactionUsersQuery,
1486
+ options?: MessageOperationOptions,
1487
+ ) {
1488
+ return Effect.suspend(() =>
1489
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1490
+ ? this.rest.fetchReactionUsers(this.#configuration.token, target, emoji, query, options)
1491
+ : Effect.fail(new ClientClosedError()),
1492
+ )
1493
+ }
1494
+
1495
+ reaction(
1496
+ operation: "addReaction" | "removeReaction" | "removeUserReaction" | "clearReaction" | "clearReactions",
1497
+ target: MessageReference,
1498
+ emoji: ReactionEmojiInput | undefined,
1499
+ options?: MessageOperationOptions,
1500
+ userId?: string,
1501
+ ) {
1502
+ return Effect.suspend(() =>
1503
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1504
+ ? this.rest.reaction(this.#configuration.token, operation, target, emoji, options, userId)
1505
+ : Effect.fail(new ClientClosedError()),
1506
+ )
1507
+ }
1508
+
1509
+ fetch(target: MessageReference, options?: MessageOperationOptions) {
1510
+ return Effect.suspend(() =>
1511
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1512
+ ? this.rest.fetch(this.#configuration.token, target, options)
1513
+ : Effect.fail(new ClientClosedError()),
1514
+ )
1515
+ }
1516
+
1517
+ publish(target: MessageReference, options?: MessageOperationOptions) {
1518
+ return Effect.suspend(() =>
1519
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1520
+ ? this.rest.publish(this.#configuration.token, target, options)
1521
+ : Effect.fail(new ClientClosedError()),
1522
+ )
1523
+ }
1524
+
1525
+ fetchCrosspostSource(target: MessageReference, options?: MessageOperationOptions) {
1526
+ return Effect.suspend(() =>
1527
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1528
+ ? this.rest.fetchCrosspostSource(this.#configuration.token, target, options)
1529
+ : Effect.fail(new ClientClosedError()),
1530
+ )
1531
+ }
1532
+
1533
+ typing(channelId: string, options?: MessageOperationOptions) {
1534
+ return Effect.suspend(() =>
1535
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1536
+ ? this.rest.typing(this.#configuration.token, channelId, options)
1537
+ : Effect.fail(new ClientClosedError()),
1538
+ )
1539
+ }
1540
+
1541
+ keepTyping<A, E, R>(
1542
+ channelId: string,
1543
+ task: Effect.Effect<A, E, R>,
1544
+ options?: MessageOperationOptions,
1545
+ ): Effect.Effect<A, E | MessageOperationFailure, R> {
1546
+ const owner = this
1547
+ if (!Effect.isEffect(task))
1548
+ return Effect.fail(
1549
+ new MessageOperationError({
1550
+ operation: "typing",
1551
+ reason: "input",
1552
+ outcome: "notDispatched",
1553
+ inputValidation: inputValidationFailure(
1554
+ "task",
1555
+ "type",
1556
+ "The task passed to keepTyping must be an Effect",
1557
+ ).detail,
1558
+ }),
1559
+ )
1560
+ return Effect.uninterruptibleMask((restore) =>
1561
+ restore(owner.typing(channelId, options)).pipe(
1562
+ Effect.flatMap(() =>
1563
+ Effect.gen(function* () {
1564
+ const id = Symbol("typing")
1565
+ const started = Deferred.makeUnsafe<void>()
1566
+ const refresh = yield* Effect.forkChild(
1567
+ Deferred.await(started).pipe(
1568
+ Effect.andThen(owner.#refreshTyping(channelId, options)),
1569
+ Effect.ensuring(Effect.sync(() => owner.#typing.delete(id))),
1570
+ ),
1571
+ )
1572
+ owner.#typing.set(id, refresh)
1573
+ Deferred.doneUnsafe(started, Effect.void)
1574
+ return yield* restore(task).pipe(Effect.onExit(() => owner.#stopTyping(refresh)))
1575
+ }),
1576
+ ),
1577
+ ),
1578
+ )
1579
+ }
1580
+
1581
+ #refreshTyping(
1582
+ channelId: string,
1583
+ options?: MessageOperationOptions,
1584
+ ): Effect.Effect<never, MessageOperationFailure> {
1585
+ const owner = this
1586
+ return Effect.forever(
1587
+ Effect.raceFirst(
1588
+ Effect.sleep(typingRefreshMs),
1589
+ Deferred.await(owner.#typingClosed).pipe(Effect.andThen(Effect.fail(new ClientClosedError()))),
1590
+ ).pipe(Effect.andThen(owner.typing(channelId, options))),
1591
+ )
1592
+ }
1593
+
1594
+ #stopTyping(fiber: Fiber.Fiber<never, MessageOperationFailure>): Effect.Effect<void, MessageOperationFailure> {
1595
+ return Effect.uninterruptible(
1596
+ Fiber.interrupt(fiber).pipe(
1597
+ Effect.andThen(Fiber.await(fiber)),
1598
+ Effect.flatMap((exit) =>
1599
+ Exit.isFailure(exit) && !Cause.hasInterruptsOnly(exit.cause)
1600
+ ? Effect.failCause(exit.cause)
1601
+ : Effect.void,
1602
+ ),
1603
+ ),
1604
+ )
1605
+ }
1606
+
1607
+ pin(operation: "pin" | "unpin", target: MessageReference, options?: MessageOperationOptions) {
1608
+ return Effect.suspend(() =>
1609
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1610
+ ? this.rest.pin(this.#configuration.token, operation, target, options)
1611
+ : Effect.fail(new ClientClosedError()),
1612
+ )
1613
+ }
1614
+
1615
+ fetchPins(channel: string, query?: MessagePinsQuery, options?: MessageOperationOptions) {
1616
+ return Effect.suspend(() =>
1617
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1618
+ ? this.rest.fetchPins(this.#configuration.token, channel, query, options)
1619
+ : Effect.fail(new ClientClosedError()),
1620
+ )
1621
+ }
1622
+
1623
+ fetchHistory(channelId: string, query?: MessageHistoryQuery, options?: MessageOperationOptions) {
1624
+ return Effect.suspend(() =>
1625
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1626
+ ? this.rest.fetchHistory(this.#configuration.token, channelId, query, options)
1627
+ : Effect.fail(new ClientClosedError()),
1628
+ )
1629
+ }
1630
+
1631
+ searchMessages(context: MessageSearchContext, query?: MessageSearchQuery, options?: MessageOperationOptions) {
1632
+ return Effect.suspend(() =>
1633
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1634
+ ? this.rest.search(this.#configuration.token, context, query, options)
1635
+ : Effect.fail(new ClientClosedError()),
1636
+ )
1637
+ }
1638
+
1639
+ edit(target: MessageReference, input: EditMessageInput | string, options?: MessageOperationOptions) {
1640
+ return Effect.suspend(() =>
1641
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1642
+ ? this.rest.edit(this.#configuration.token, target, input, options)
1643
+ : Effect.fail(new ClientClosedError()),
1644
+ )
1645
+ }
1646
+
1647
+ delete(target: MessageReference, options?: MessageOperationOptions) {
1648
+ return Effect.suspend(() =>
1649
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1650
+ ? this.rest.delete(this.#configuration.token, target, options)
1651
+ : Effect.fail(new ClientClosedError()),
1652
+ )
1653
+ }
1654
+
1655
+ deleteAttachment(target: MessageReference, attachmentId: string, options?: MessageOperationOptions) {
1656
+ return Effect.suspend(() =>
1657
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1658
+ ? this.rest.deleteAttachment(this.#configuration.token, target, attachmentId, options)
1659
+ : Effect.fail(new ClientClosedError()),
1660
+ )
1661
+ }
1662
+
1663
+ deleteMany(channelId: string, ids: readonly string[], options?: MessageOperationOptions) {
1664
+ return Effect.suspend(() =>
1665
+ this.#configuration && this.#state !== "Closing" && this.#state !== "Closed"
1666
+ ? this.rest.deleteMany(this.#configuration.token, channelId, ids, options)
1667
+ : Effect.fail(new ClientClosedError()),
1668
+ )
1669
+ }
1670
+
1671
+ deleteOwnMessages(channelId: string, options: unknown) {
1672
+ return suspendInput(() => {
1673
+ if (!this.#configuration || this.#state === "Closing" || this.#state === "Closed")
1674
+ return Effect.fail(new ClientClosedError())
1675
+ const checked = ownDeletionOptions<MessageOperationOptions>(options)
1676
+ if (checked instanceof InputValidationFailure)
1677
+ return Effect.fail(
1678
+ new MessageOperationError({
1679
+ operation: "deleteOwnMessages",
1680
+ reason: "input",
1681
+ outcome: "notDispatched",
1682
+ inputValidation: checked.detail,
1683
+ }),
1684
+ )
1685
+ return this.rest.deleteOwnMessages(this.#configuration.token, channelId, checked)
1686
+ })
1687
+ }
1688
+
1689
+ get(target: MessageReference) {
1690
+ return suspendInput((): Effect.Effect<M | undefined, ClientClosedError | MessageOperationError> => {
1691
+ if (!this.#configuration || this.#state === "Closing" || this.#state === "Closed")
1692
+ return Effect.fail(new ClientClosedError())
1693
+ const reference = snapshotReference(target)
1694
+ if (reference === undefined)
1695
+ return Effect.fail(
1696
+ new MessageOperationError({
1697
+ operation: "messages.get",
1698
+ reason: "input",
1699
+ outcome: "notDispatched",
1700
+ inputValidation: inputValidationFailure(
1701
+ "target",
1702
+ "format",
1703
+ "Message targets require decimal id and channelId strings",
1704
+ ).detail,
1705
+ }),
1706
+ )
1707
+ return Effect.sync(() => this.cache?.get(reference))
1708
+ })
1709
+ }
1710
+
1711
+ #closeServices() {
1712
+ Deferred.doneUnsafe(this.#typingClosed, Effect.void)
1713
+ this.events.stop()
1714
+ this.rest.stop()
1715
+ return closeAll([
1716
+ Effect.exit(this.instance.shutdown()),
1717
+ Effect.exit(this.events.shutdown()),
1718
+ Effect.exit(this.tasks.shutdown()),
1719
+ Effect.exit(this.rest.shutdown()),
1720
+ Effect.exit(this.failures.shutdown()),
1721
+ Effect.all(
1722
+ [
1723
+ Effect.forEach(
1724
+ [...this.#messageCollectors],
1725
+ (collector) => Effect.exit(Deferred.await(collector.closed).pipe(Effect.asVoid)),
1726
+ { concurrency: "unbounded" },
1727
+ ),
1728
+ Effect.forEach(
1729
+ [...this.#reactionCollectors],
1730
+ (collector) => Effect.exit(Deferred.await(collector.closed).pipe(Effect.asVoid)),
1731
+ { concurrency: "unbounded" },
1732
+ ),
1733
+ ],
1734
+ { concurrency: "unbounded" },
1735
+ ).pipe(
1736
+ Effect.map((exits) => defectsOnly(exits.flat())),
1737
+ Effect.ensuring(
1738
+ Effect.sync(() => {
1739
+ this.#messageCollectors.clear()
1740
+ this.#reactionCollectors.clear()
1741
+ }),
1742
+ ),
1743
+ ),
1744
+ ]).pipe(Effect.onExit(() => this.#awaitTyping()))
1745
+ }
1746
+
1747
+ #awaitTyping(): Effect.Effect<void> {
1748
+ return Effect.forEach([...this.#typing.values()], (fiber) => Fiber.await(fiber), {
1749
+ concurrency: "unbounded",
1750
+ }).pipe(
1751
+ Effect.flatMap((exits) => {
1752
+ const reasons = exits.flatMap((exit) =>
1753
+ Exit.isFailure(exit) ? exit.cause.reasons.filter((reason) => reason._tag === "Die") : [],
1754
+ )
1755
+ return reasons.length ? Effect.failCause(Cause.fromReasons<never>(reasons)) : Effect.void
1756
+ }),
1757
+ )
1758
+ }
1759
+
1760
+ #supervise(configuration: Configuration<M>, startup: Deferred.Deferred<void, ConnectError>) {
1761
+ const owner = this
1762
+ return Effect.gen(function* () {
1763
+ // Automatic sizing counts guilds under its own deadline, so the shard group always gets its full budget
1764
+ let plan = owner.#plan ?? (yield* owner.#automaticPlan(configuration))
1765
+ // The refill waits for the whole group, and a failed startup ends this worker and the refill with it
1766
+ yield* Effect.forkChild(
1767
+ Effect.exit(Deferred.await(startup)).pipe(
1768
+ Effect.flatMap((ready) => (Exit.isSuccess(ready) ? owner.#refillRestored() : Effect.void)),
1769
+ ),
1770
+ )
1771
+ for (let first = true; ; first = false) {
1772
+ // Capture and rethrow defects or interruption while masked, as REST attempts do. Otherwise an interruption that
1773
+ // skips this handler discards the plan's typed failure, and one pending at the mask's end discards the whole cause
1774
+ const exit = yield* Effect.uninterruptibleMask((restore) =>
1775
+ Effect.exit(restore(owner.#runPlan(configuration, startup, plan, first))).pipe(
1776
+ Effect.flatMap((exit) =>
1777
+ Exit.isFailure(exit) && (Cause.hasDies(exit.cause) || Cause.hasInterrupts(exit.cause))
1778
+ ? Effect.failCause(exit.cause)
1779
+ : Effect.succeed(exit),
1780
+ ),
1781
+ ),
1782
+ )
1783
+ const shardId = owner.#reshardShard
1784
+ if (Exit.isSuccess(exit)) return
1785
+ if (shardId === undefined || Cause.hasDies(exit.cause)) return yield* Effect.failCause(exit.cause)
1786
+ plan = yield* owner.#reshard(configuration, plan, shardId)
1787
+ }
1788
+ })
1789
+ }
1790
+
1791
+ /**
1792
+ * Run every shard of one plan until one fails permanently. Only the first plan offers stored sessions, because a
1793
+ * snapshot belongs to the plan it was saved under
1794
+ */
1795
+ #runPlan(
1796
+ configuration: Configuration<M>,
1797
+ startup: Deferred.Deferred<void, ConnectError>,
1798
+ plan: ShardPlan,
1799
+ loadSessions: boolean,
1800
+ ) {
1801
+ const owner = this
1802
+ return Effect.gen(function* () {
1803
+ const spaced = plan.identifyShards && configuration.identifyCoordinator === undefined
1804
+ const startupTimeoutMs = startupBudgetMs(configuration.startupTimeoutMs, spaced ? plan.shardIds.length : 1)
1805
+ if (startupTimeoutMs > configuration.startupTimeoutMs)
1806
+ owner.logging.log({
1807
+ level: "info",
1808
+ category: "lifecycle",
1809
+ code: "lifecycle.startupDeadline",
1810
+ message: `Startup of ${plan.shardIds.length} shards may take up to ${formatDuration(startupTimeoutMs)}: The configured ${formatDuration(configuration.startupTimeoutMs)} (connection.startupTimeoutMs) plus ${identifySpacingMs / 1_000} s per additional shard, because the SDK starts shard sessions ${identifySpacingMs / 1_000} s apart`,
1811
+ fields: {
1812
+ startupTimeoutMs,
1813
+ configuredMs: configuration.startupTimeoutMs,
1814
+ shards: plan.shardIds.length,
1815
+ },
1816
+ })
1817
+ return yield* superviseShards({
1818
+ shards: [...owner.#shards.values()],
1819
+ startupTimeoutMs,
1820
+ attributeShards: plan.identifyShards,
1821
+ startup,
1822
+ runShard: (shard, deadline) =>
1823
+ runShardLoop({
1824
+ host: owner.#shardHost,
1825
+ configuration,
1826
+ startup,
1827
+ shard,
1828
+ plan,
1829
+ deadline,
1830
+ startupTimeoutMs,
1831
+ established: owner.#groupReady,
1832
+ loadSessions,
1833
+ }),
1834
+ })
1835
+ })
1836
+ }
1837
+
1838
+ /**
1839
+ * Decide whether a 4011 (sharding required) closure on this shard moves the automatic plan to a larger one: True when
1840
+ * it does, otherwise why not. Closures of sibling shards during the same move join it
1841
+ */
1842
+ #acceptReshard(shardId: number): true | string {
1843
+ if (this.#reshardShard !== undefined) return true
1844
+ const refused = admitReshard(this.#reshards, this.logical.now(), this.#plan!.totalShards)
1845
+ if (refused !== undefined) return refused
1846
+ this.#reshardShard = shardId
1847
+ return true
1848
+ }
1849
+
1850
+ /**
1851
+ * Move every local shard to a larger automatic plan after Fluxer closed shardId with 4011, from an automatic plan or
1852
+ * the one-shard plan of omitted settings. The old sessions are already closed. Their guild-scoped observations are
1853
+ * released under the old routing, the guilds are counted again and the new plan's shards start new sessions.
1854
+ * Guild-scoped state observers see the waiting state, because the shard that served their guild is gone
1855
+ */
1856
+ #reshard(
1857
+ configuration: Configuration<M>,
1858
+ previous: ShardPlan,
1859
+ shardId: number,
1860
+ ): Effect.Effect<ShardPlan, ConnectionFailure> {
1861
+ const owner = this
1862
+ return Effect.gen(function* () {
1863
+ const waiting = owner.#groupReady ? "Recovering" : "Connecting"
1864
+ for (const shard of owner.#shards.values()) {
1865
+ owner.#gapShard(shard.shardId, false)
1866
+ shard.state = waiting
1867
+ shard.latency = null
1868
+ shard.recovery = null
1869
+ shard.submit = undefined
1870
+ }
1871
+ const listeners = [...owner.#shardListeners.values()]
1872
+ owner.#shardListeners.clear()
1873
+ owner.#setState(waiting)
1874
+ for (const set of listeners) for (const listener of set) listener(waiting)
1875
+ const guilds = yield* owner.countGuilds(configuration.startupTimeoutMs)
1876
+ const plan = largerShardPlan(guilds, previous.totalShards)
1877
+ owner.#reshardShard = undefined
1878
+ owner.#adoptPlan(plan, "Connecting")
1879
+ owner.presence.reroute()
1880
+ // Omitted settings start with this fixed one-shard plan and switch to automatic sharding at the first move
1881
+ const switched = previous === configuration.sharding
1882
+ owner.logging.log({
1883
+ level: "warn",
1884
+ category: "lifecycle",
1885
+ code: "lifecycle.resharded",
1886
+ message: `Fluxer closed shard ${shardId} with close code 4011 (sharding required), so ${switched ? "the client without sharding settings switched to automatic sharding and moved" : "automatic sharding moved"} from ${previous.totalShards} to ${plan.totalShards} shards for ${guilds} communit${guilds === 1 ? "y" : "ies"}. Every shard starts a new session, so events sent during the move are missed${switched ? '. Set sharding to "auto" to start with enough shards next time' : ""}`,
1887
+ shardId,
1888
+ fields: { guilds, previousTotalShards: previous.totalShards, totalShards: plan.totalShards },
1889
+ })
1890
+ return plan
1891
+ })
1892
+ }
1893
+
1894
+ /**
1895
+ * Refill the enabled guild, role and channel caches for the guilds of shards that resumed a stored session, since a
1896
+ * resumed session receives no guild data. Guilds are fetched one request at a time through the REST scheduler, so
1897
+ * the refill holds at most one REST slot and waits out rate limits. It stops after refillFailureLimit failed guilds,
1898
+ * when a guild-list page does not move past the previous one and when the client closes
1899
+ */
1900
+ #refillRestored(): Effect.Effect<void> {
1901
+ const owner = this
1902
+ const shards = new Set(owner.#restoredShards)
1903
+ owner.#restoredShards.clear()
1904
+ const guildsEnabled = owner.resources?.diagnostics("guilds").configured === true
1905
+ const rolesEnabled = owner.resources?.diagnostics("roles").configured === true
1906
+ const channelsEnabled = owner.channelCache !== undefined
1907
+ if (shards.size === 0 || (!guildsEnabled && !rolesEnabled && !channelsEnabled)) return Effect.void
1908
+ return Effect.gen(function* () {
1909
+ const startedAt = owner.logical.now()
1910
+ const plan = owner.#plan!
1911
+ const guildIds: string[] = []
1912
+ let after: string | undefined
1913
+ let failed = 0
1914
+ let firstError: unknown
1915
+ let stopped: string | undefined
1916
+ while (true) {
1917
+ const page = yield* Effect.result(
1918
+ owner.guild("guilds.fetchPage", () =>
1919
+ guildList({ limit: guildCountPageSize, ...(after === undefined ? {} : { after }) }),
1920
+ ),
1921
+ )
1922
+ if (page._tag === "Failure") {
1923
+ if (page.failure instanceof ClientClosedError) return
1924
+ firstError = page.failure
1925
+ stopped = "the bot's community list could not be read"
1926
+ break
1927
+ }
1928
+ // As in guilds.iterate, a page that repeats or goes back past the cursor would page forever
1929
+ const cursor = after
1930
+ if (cursor !== undefined && page.success.some((guild) => BigInt(guild.id) <= BigInt(cursor))) {
1931
+ stopped = "the bot's community list returned a page that did not move past the previous one"
1932
+ break
1933
+ }
1934
+ for (const guild of page.success)
1935
+ if (shards.has(guildShardId(guild.id, plan.totalShards))) guildIds.push(guild.id)
1936
+ if (page.success.length < guildCountPageSize) break
1937
+ after = page.success.at(-1)!.id
1938
+ }
1939
+ let refilled = 0
1940
+ for (const guildId of stopped === undefined ? guildIds : []) {
1941
+ const reads: Effect.Effect<unknown, unknown>[] = [
1942
+ ...(guildsEnabled ? [owner.guild("guilds.fetch", () => guildFetch(guildId))] : []),
1943
+ ...(rolesEnabled ? [owner.guild("roles.fetchAll", () => roleList(guildId))] : []),
1944
+ ...(channelsEnabled ? [owner.channel("channels.fetchAll", () => channelList(guildId))] : []),
1945
+ ]
1946
+ let failure: unknown
1947
+ for (const read of reads) {
1948
+ const result = yield* Effect.result(read)
1949
+ if (result._tag === "Success") continue
1950
+ if (result.failure instanceof ClientClosedError) return
1951
+ failure ??= result.failure
1952
+ }
1953
+ if (failure === undefined) {
1954
+ refilled += 1
1955
+ continue
1956
+ }
1957
+ failed += 1
1958
+ firstError ??= failure
1959
+ if (failed >= refillFailureLimit) {
1960
+ stopped = `${failed} communities failed`
1961
+ break
1962
+ }
1963
+ }
1964
+ const durationMs = Math.round(owner.logical.now() - startedAt)
1965
+ const shardText = `${shards.size} shard${shards.size === 1 ? "" : "s"}`
1966
+ owner.logging.log({
1967
+ level: failed > 0 || stopped !== undefined ? "warn" : "info",
1968
+ category: "lifecycle",
1969
+ code: "lifecycle.cacheRefill",
1970
+ message:
1971
+ stopped !== undefined
1972
+ ? `The cache refill after ${shardText} resumed saved sessions stopped after ${refilled} of ${guildIds.length} communities, because ${stopped}. The remaining cache entries fill as events and requests arrive`
1973
+ : failed > 0
1974
+ ? `Refilled the caches of ${refilled} of ${guildIds.length} communities after ${shardText} resumed saved sessions. The others failed, so their cache entries fill as events and requests arrive`
1975
+ : `Refilled the caches of ${refilled} communit${refilled === 1 ? "y" : "ies"} after ${shardText} resumed saved sessions, in ${formatDuration(durationMs)}`,
1976
+ durationMs,
1977
+ ...(firstError === undefined ? {} : { error: firstError }),
1978
+ fields: { guilds: guildIds.length, refilled, failed, shards: shards.size },
1979
+ })
1980
+ })
1981
+ }
1982
+
1983
+ /**
1984
+ * Count the bot's guilds by paging the current-user guild list within timeoutMs. Automatic sharding and the
1985
+ * supervisor's automatic plan both size their plans from this count. A page that does not move past the previous
1986
+ * one fails at once as a discovery ConnectionError, instead of paging until the deadline
1987
+ */
1988
+ countGuilds(timeoutMs: number): Effect.Effect<number, ConnectionFailure> {
1989
+ const owner = this
1990
+ return Effect.gen(function* () {
1991
+ const clock = yield* Clock.Clock
1992
+ const deadline = nowMs(clock) + timeoutMs
1993
+ let guilds = 0
1994
+ let after: string | undefined
1995
+ while (true) {
1996
+ const remaining = Math.floor(deadline - nowMs(clock))
1997
+ if (remaining <= 0) return yield* Effect.fail(new ConnectionTimeoutError(timeoutMs))
1998
+ const page = yield* owner
1999
+ .guild(
2000
+ "guilds.fetchPage",
2001
+ () => guildList({ limit: guildCountPageSize, ...(after === undefined ? {} : { after }) }),
2002
+ { timeoutMs: remaining },
2003
+ )
2004
+ .pipe(Effect.mapError((error) => automaticPlanFailure(error, timeoutMs)))
2005
+ // As in guilds.iterate, a page that repeats or goes back past the cursor would page until the deadline
2006
+ const cursor = after
2007
+ if (cursor !== undefined && page.some((guild) => BigInt(guild.id) <= BigInt(cursor)))
2008
+ return yield* Effect.fail(
2009
+ new ConnectionError("discovery", "protocol", null, {
2010
+ details: {
2011
+ detail: "the community list returned a page that did not move past the previous one, so the community count for automatic sharding could not be read",
2012
+ },
2013
+ hint: 'Set sharding.totalShards to a number instead of "auto"',
2014
+ }),
2015
+ )
2016
+ guilds += page.length
2017
+ if (page.length < guildCountPageSize) return guilds
2018
+ after = page.at(-1)!.id
2019
+ }
2020
+ })
2021
+ }
2022
+
2023
+ /**
2024
+ * Size the plan from the bot's guild count, read by paging the current-user guild list under the startup deadline.
2025
+ * GET /gateway/bot is never used, because Fluxer returns a fixed compatibility shard count there
2026
+ */
2027
+ #automaticPlan(configuration: Configuration<M>): Effect.Effect<ShardPlan, ConnectionFailure> {
2028
+ const owner = this
2029
+ return Effect.gen(function* () {
2030
+ const guilds = yield* owner.countGuilds(configuration.startupTimeoutMs)
2031
+ if (owner.#plan !== undefined) return owner.#plan
2032
+ const plan = automaticShardPlan(guilds)
2033
+ owner.#adoptPlan(plan, "Connecting")
2034
+ owner.logging.log({
2035
+ level: "info",
2036
+ category: "lifecycle",
2037
+ code: "lifecycle.automaticSharding",
2038
+ message: `Automatic sharding chose ${plan.totalShards} shard${plan.totalShards === 1 ? "" : "s"} for ${guilds} communit${guilds === 1 ? "y" : "ies"}, aiming for at most ${guildsPerShard} communities per shard on average`,
2039
+ fields: { guilds, totalShards: plan.totalShards, guildsPerShard },
2040
+ })
2041
+ return plan
2042
+ })
2043
+ }
2044
+
2045
+ /**
2046
+ * Save the resumable session of each shard that was Connected when shutdown began, once, after its socket closed.
2047
+ * A shard that was recovering is skipped, because its session may already have expired. Failures are logged in
2048
+ * full and never block shutdown
2049
+ */
2050
+ #saveSessions(): Effect.Effect<void> {
2051
+ const store = this.#configuration?.sessions
2052
+ const live = this.#saveOnClose
2053
+ this.#saveOnClose = undefined
2054
+ const plan = this.#plan
2055
+ if (!store || !live || !plan) return Effect.void
2056
+ const owner = this
2057
+ const shards = [...this.#shards.values()].filter(
2058
+ (shard) =>
2059
+ live.has(shard.shardId) &&
2060
+ shard.session.id !== undefined &&
2061
+ shard.session.sequence !== null &&
2062
+ shard.gatewayUrl !== undefined,
2063
+ )
2064
+ return Effect.forEach(
2065
+ shards,
2066
+ (shard) => {
2067
+ const snapshot: SessionSnapshot = Object.freeze({
2068
+ sessionId: shard.session.id!,
2069
+ sequence: shard.session.sequence!,
2070
+ resumeUrl: shard.gatewayUrl!,
2071
+ savedAt: Date.now(),
2072
+ totalShards: plan.totalShards,
2073
+ })
2074
+ // @effect-diagnostics-next-line unknownInEffectCatch:off
2075
+ return Effect.tryPromise({
2076
+ try: () => Promise.resolve(store.save(shard.shardId, snapshot)),
2077
+ catch: (error) => error,
2078
+ }).pipe(
2079
+ Effect.timeoutOrElse({
2080
+ duration: sessionSaveTimeoutMs,
2081
+ orElse: () =>
2082
+ Effect.fail(
2083
+ // @effect-diagnostics-next-line globalErrorInEffectFailure:off
2084
+ new Error(
2085
+ `The session store's save did not finish within ${formatDuration(sessionSaveTimeoutMs)}`,
2086
+ ),
2087
+ ),
2088
+ }),
2089
+ Effect.matchEffect({
2090
+ onSuccess: () =>
2091
+ Effect.sync(() =>
2092
+ owner.logging.log({
2093
+ level: "debug",
2094
+ category: "lifecycle",
2095
+ code: "lifecycle.sessionSaved",
2096
+ message: `Saved shard ${shard.shardId}'s session, so the next start can resume it`,
2097
+ shardId: shard.shardId,
2098
+ }),
2099
+ ),
2100
+ onFailure: (error) =>
2101
+ Effect.sync(() =>
2102
+ owner.logging.log({
2103
+ level: "error",
2104
+ category: "lifecycle",
2105
+ code: "lifecycle.sessionSaveFailed",
2106
+ message: `Shard ${shard.shardId}'s session could not be saved, so the next start begins a new session`,
2107
+ shardId: shard.shardId,
2108
+ error,
2109
+ origin: "application",
2110
+ }),
2111
+ ),
2112
+ }),
2113
+ )
2114
+ },
2115
+ { concurrency: "unbounded", discard: true },
2116
+ )
2117
+ }
2118
+
2119
+ #start(): Effect.Effect<void, ConnectError> {
2120
+ const owner = this
2121
+ return Effect.uninterruptibleMask((restore) =>
2122
+ Effect.gen(function* () {
2123
+ if (owner.#state === "Closing" || owner.#state === "Closed")
2124
+ return yield* Effect.fail(new ClientClosedError())
2125
+ if (owner.#state === "Connected") return
2126
+ if (owner.#state !== "Disconnected") return yield* Effect.fail(new ClientBusyError())
2127
+ const configuration = owner.#configuration!
2128
+ owner.#everStarted = true
2129
+ const creator = yield* Effect.withFiber((fiber) => Effect.succeed(fiber))
2130
+ owner.logging.banners(creator.context)
2131
+ const plan = owner.#plan
2132
+ const host = new URL(configuration.instance.bootstrap).host
2133
+ owner.logging.log(
2134
+ {
2135
+ level: "info",
2136
+ category: "lifecycle",
2137
+ code: "lifecycle.starting",
2138
+ message:
2139
+ plan === undefined
2140
+ ? `Starting Fluxerly ${sdkVersion()} for ${host} with an automatic shard count`
2141
+ : `Starting Fluxerly ${sdkVersion()} for ${host} with ${plan.shardIds.length} shard${plan.shardIds.length === 1 ? "" : "s"}`,
2142
+ fields: {
2143
+ version: sdkVersion(),
2144
+ instance: host,
2145
+ shards: plan?.shardIds.length ?? null,
2146
+ totalShards: plan?.totalShards ?? null,
2147
+ },
2148
+ },
2149
+ creator.context,
2150
+ )
2151
+ const startup = Deferred.makeUnsafe<void, ConnectError>()
2152
+ let becameReady = false
2153
+ owner.#workerExit = undefined
2154
+ owner.#groupReady = false
2155
+ for (const shard of owner.#shards.values()) {
2156
+ shard.state = "Connecting"
2157
+ shard.recovery = null
2158
+ }
2159
+ owner.#setState("Connecting")
2160
+ const trackReady = owner.subscribe((state) => {
2161
+ if (state === "Connected") becameReady = true
2162
+ })
2163
+ owner.#worker = yield* Effect.forkIn(
2164
+ owner.#supervise(configuration, startup).pipe(
2165
+ Effect.provideService(Clock.Clock, owner.logical.clock),
2166
+ Effect.onExit((exit) =>
2167
+ Effect.gen(function* () {
2168
+ trackReady()
2169
+ owner.#workerExit = exit
2170
+ const closing = owner.#state === "Closing" || owner.#state === "Closed"
2171
+ const interrupted = Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause)
2172
+ const defect = Exit.isFailure(exit) && Cause.hasDies(exit.cause)
2173
+ if (closing && !defect)
2174
+ Deferred.doneUnsafe(startup, Effect.fail(new ClientClosedError()))
2175
+ else Deferred.doneUnsafe(startup, exit)
2176
+ if (becameReady || defect) {
2177
+ const fiber = yield* Effect.withFiber((fiber) => Effect.succeed(fiber))
2178
+ const startedAt = Date.now()
2179
+ if (!closing)
2180
+ logShutdownStart(
2181
+ owner.logging,
2182
+ fiber.context,
2183
+ owner.#everStarted,
2184
+ "the connection ended",
2185
+ )
2186
+ owner.#setState("Closing")
2187
+ // An explicit shutdown lands here once the sockets are closed
2188
+ if (closing) yield* owner.#saveSessions()
2189
+ const services = yield* Effect.exit(owner.#closeServices())
2190
+ // The explicit shutdown that interrupted this worker logs the cleanup, including a socket
2191
+ // close that died. Otherwise this worker logs it below, even when a shutdown arrives during
2192
+ // the cleanup
2193
+ if (closing) {
2194
+ const dies = Exit.isFailure(exit)
2195
+ ? exit.cause.reasons.filter((reason) => reason._tag === "Die")
2196
+ : []
2197
+ owner.#workerCleanup =
2198
+ dies.length > 0
2199
+ ? Exit.failCause(
2200
+ Cause.combine(
2201
+ Cause.fromReasons(dies),
2202
+ Exit.isFailure(services) ? services.cause : Cause.empty,
2203
+ ),
2204
+ )
2205
+ : services
2206
+ }
2207
+ const outcome = Exit.isFailure(services)
2208
+ ? Exit.failCause(
2209
+ Cause.combine(
2210
+ Exit.isFailure(exit) ? exit.cause : Cause.empty,
2211
+ services.cause,
2212
+ ),
2213
+ )
2214
+ : exit
2215
+ owner.#workerExit = outcome
2216
+ owner.#finish()
2217
+ if (!closing)
2218
+ logShutdownEnd(owner.logging, fiber.context, {
2219
+ everStarted: owner.#everStarted,
2220
+ startedAt,
2221
+ services,
2222
+ })
2223
+ Deferred.doneUnsafe(
2224
+ owner.#terminal,
2225
+ interrupted && !Exit.isFailure(services) ? Effect.void : outcome,
2226
+ )
2227
+ } else if (!closing) {
2228
+ owner.#setState("Disconnected")
2229
+ }
2230
+ }),
2231
+ ),
2232
+ // Outcomes are retained above, not left as unobserved fiber failures
2233
+ // allow-silent: Outcomes are retained above, not left as unobserved fiber failures
2234
+ Effect.catchCause(() => Effect.void),
2235
+ ),
2236
+ owner.scope,
2237
+ )
2238
+ const worker = owner.#worker
2239
+ // A shutdown can interrupt the worker before it runs, and then its exit handler above never runs.
2240
+ // Startup still ends, with the same ClientClosedError a closing client gives, instead of waiting forever
2241
+ worker.addObserver(() => Deferred.doneUnsafe(startup, Effect.fail(new ClientClosedError())))
2242
+ return yield* restore(Deferred.await(startup)).pipe(
2243
+ Effect.tap(() => Effect.sync(() => owner.#logConnected(creator.context))),
2244
+ Effect.onInterrupt(() =>
2245
+ Effect.gen(function* () {
2246
+ yield* Fiber.interrupt(worker)
2247
+ const exit = owner.#workerExit
2248
+ if (exit && Exit.isFailure(exit) && Cause.hasDies(exit.cause))
2249
+ return yield* Effect.failCause(exit.cause)
2250
+ }),
2251
+ ),
2252
+ )
2253
+ }),
2254
+ )
2255
+ }
2256
+
2257
+ connect(): Effect.Effect<void, ConnectError> {
2258
+ return Effect.suspend(() => {
2259
+ // A draining shutdown keeps the state until the drain ends, but the client never connects again
2260
+ if (this.#shutdownStarted || this.#state === "Closing" || this.#state === "Closed")
2261
+ return Effect.fail(new ClientClosedError())
2262
+ return this.#managed ? Effect.fail(new ClientBusyError()) : this.#start()
2263
+ })
2264
+ }
2265
+
2266
+ waitForClose(): Effect.Effect<void, ConnectionFailure> {
2267
+ return Deferred.await(this.#terminal)
2268
+ }
2269
+
2270
+ /**
2271
+ * Shut down once. A positive drainMs first stops event intake and lets running work finish until that deadline, while
2272
+ * the state and REST admission stay as they were
2273
+ */
2274
+ shutdown(drainMs = 0): Effect.Effect<void> {
2275
+ return Effect.withFiber((fiber) =>
2276
+ this.events.ownsHandler(fiber.id) ||
2277
+ this.failures.owns(fiber.id) ||
2278
+ this.tasks.owns(fiber.id) ||
2279
+ [...this.#messageCollectors].some((collector) => collector.owns(fiber.id)) ||
2280
+ [...this.#reactionCollectors].some((collector) => collector.owns(fiber.id))
2281
+ ? // A native handler cannot join its own cleanup: The client scope owns shutdown and interrupts this caller.
2282
+ // A drain would wait for this handler, so the handler ends at once instead of when the drain ends
2283
+ Effect.forkIn(this.#performShutdown(drainMs), this.scope).pipe(
2284
+ Effect.andThen(drainMs > 0 ? Effect.interrupt : Effect.never),
2285
+ )
2286
+ : this.#performShutdown(drainMs),
2287
+ )
2288
+ }
2289
+
2290
+ #performShutdown(drainMs: number): Effect.Effect<void> {
2291
+ const owner = this
2292
+ return Effect.uninterruptible(
2293
+ Effect.suspend(() => {
2294
+ if (owner.#shutdownStarted) return Deferred.await(owner.#shutdown)
2295
+ if (owner.#state === "Closed") return Effect.void
2296
+ owner.#shutdownStarted = true
2297
+ const drain =
2298
+ drainMs > 0
2299
+ ? Effect.withFiber((fiber) =>
2300
+ drainWork({
2301
+ events: owner.events,
2302
+ tasks: owner.tasks,
2303
+ requests: () => owner.rest.inFlight(),
2304
+ logging: owner.logging,
2305
+ drainMs,
2306
+ context: fiber.context,
2307
+ }).pipe(Effect.provideService(Clock.Clock, owner.logical.clock)),
2308
+ )
2309
+ : Effect.void
2310
+ return drain.pipe(
2311
+ Effect.andThen(owner.#closeAfterDrain()),
2312
+ Effect.onExit((exit) => Deferred.done(owner.#shutdown, exit)),
2313
+ )
2314
+ }),
2315
+ )
2316
+ }
2317
+
2318
+ /** The shutdown steps after any drain. A connection that ended during the drain has already closed the client */
2319
+ #closeAfterDrain(): Effect.Effect<void> {
2320
+ const owner = this
2321
+ return Effect.suspend(() => {
2322
+ if (owner.#state === "Closed") return Effect.void
2323
+ // Only sessions that are live now are worth resuming later
2324
+ owner.#saveOnClose = new Set(
2325
+ [...owner.#shards.values()]
2326
+ .filter((shard) => shard.state === "Connected")
2327
+ .map((shard) => shard.shardId),
2328
+ )
2329
+ owner.#setState("Closing")
2330
+ owner.events.stop()
2331
+ owner.rest.stop()
2332
+ owner.tasks.stop()
2333
+ return Effect.gen(function* () {
2334
+ const fiber = yield* Effect.withFiber((fiber) => Effect.succeed(fiber))
2335
+ const startedAt = Date.now()
2336
+ logShutdownStart(owner.logging, fiber.context, owner.#everStarted, undefined)
2337
+ if (owner.#worker) yield* Fiber.interrupt(owner.#worker)
2338
+ // Every shard's socket is closed now, so a saved session cannot receive further dispatches
2339
+ yield* owner.#saveSessions()
2340
+ const services = yield* Effect.exit(owner.#closeServices())
2341
+ const exit = owner.#workerExit
2342
+ // An interrupted worker already closed its sockets and ran the service cleanup, so its failures are logged here
2343
+ const earlier = owner.#workerCleanup
2344
+ const cleaned =
2345
+ earlier && Exit.isFailure(earlier)
2346
+ ? Exit.failCause(
2347
+ Cause.combine(earlier.cause, Exit.isFailure(services) ? services.cause : Cause.empty),
2348
+ )
2349
+ : services
2350
+ owner.#finish()
2351
+ logShutdownEnd(owner.logging, fiber.context, {
2352
+ everStarted: owner.#everStarted,
2353
+ startedAt,
2354
+ services: cleaned,
2355
+ })
2356
+ if (Exit.isFailure(services)) {
2357
+ Deferred.doneUnsafe(owner.#terminal, services)
2358
+ return yield* Effect.failCause(services.cause)
2359
+ }
2360
+ if (exit && Exit.isFailure(exit) && Cause.hasDies(exit.cause)) {
2361
+ Deferred.doneUnsafe(owner.#terminal, exit)
2362
+ return yield* Effect.failCause(
2363
+ Cause.fromReasons<never>(exit.cause.reasons.filter((reason) => reason._tag !== "Fail")),
2364
+ )
2365
+ }
2366
+ Deferred.doneUnsafe(owner.#terminal, Effect.void)
2367
+ })
2368
+ })
2369
+ }
2370
+
2371
+ run(): Effect.Effect<void, ConnectError> {
2372
+ const owner = this
2373
+ return Effect.uninterruptibleMask((restore) =>
2374
+ Effect.suspend(() => {
2375
+ if (owner.#shutdownStarted || owner.#state === "Closed" || owner.#state === "Closing")
2376
+ return Effect.fail(new ClientClosedError())
2377
+ if (owner.#managed || owner.#state !== "Disconnected") return Effect.fail(new ClientBusyError())
2378
+ owner.#managed = true
2379
+ return restore(owner.#start().pipe(Effect.andThen(owner.waitForClose()))).pipe(
2380
+ Effect.ensuring(owner.shutdown()),
2381
+ )
2382
+ }),
2383
+ )
2384
+ }
2385
+ }
2386
+
2387
+ export function makeClient<F extends MessageFields | undefined = undefined>(
2388
+ options: unknown,
2389
+ scope: Scope.Scope,
2390
+ native = false,
2391
+ ): Effect.Effect<ClientOwner<SelectedMessage<F>>, ConfigurationError> {
2392
+ return Effect.gen(function* () {
2393
+ const identifyGate = typeof options === "object" && options !== null ? identifyGates.get(options) : undefined
2394
+ const limits = typeof options === "object" && options !== null ? accountLimits.get(options) : undefined
2395
+ if (typeof options === "object" && options !== null) {
2396
+ identifyGates.delete(options)
2397
+ accountLimits.delete(options)
2398
+ }
2399
+ const configuration = yield* validateConfiguration<F>(options, native)
2400
+ return yield* configuration.logging.provide(
2401
+ Effect.gen(function* () {
2402
+ const context = yield* Effect.context<never>()
2403
+ if (native) configuration.logging.context = context
2404
+ const callback = configuration.onError as ((report: unknown) => unknown) | undefined
2405
+ const hook = callback
2406
+ ? (report: InternalReport): Effect.Effect<unknown, unknown> =>
2407
+ native
2408
+ ? Effect.suspend(() => {
2409
+ const result = callback(report)
2410
+ // The report worker supplies the captured creation context, including the hook's services
2411
+ return Effect.isEffect(result)
2412
+ ? (result as Effect.Effect<unknown, unknown>)
2413
+ : Effect.die(
2414
+ new TypeError(
2415
+ "An onError hook in the native Effect API must return an Effect",
2416
+ ),
2417
+ )
2418
+ })
2419
+ : // @effect-diagnostics-next-line unknownInEffectCatch:off
2420
+ Effect.tryPromise({
2421
+ try: () => Promise.resolve(callback(publicReport(report))).then(throwIfErr),
2422
+ catch: (error) => error,
2423
+ })
2424
+ : undefined
2425
+ const failures = new FailureReporter(configuration.logging, hook, () => context)
2426
+ const logical = yield* makeLogicalScheduler(scope, (owner, cause) =>
2427
+ configuration.logging.log({
2428
+ level: "error",
2429
+ category: owner.includes("cache") ? "cache" : "sdk",
2430
+ code: "sdk.timerFailed",
2431
+ message: `The ${owner} timer callback failed`,
2432
+ error: primaryError(cause),
2433
+ cause,
2434
+ }),
2435
+ )
2436
+ return new ClientOwner(
2437
+ configuration,
2438
+ scope,
2439
+ failures,
2440
+ logical,
2441
+ identifyGate,
2442
+ limits,
2443
+ configuration.transport.transport,
2444
+ )
2445
+ }),
2446
+ )
2447
+ })
2448
+ }