dfx 1.0.5 → 1.0.7

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 (194) hide show
  1. package/dist/Cache/driver.d.ts.map +1 -1
  2. package/dist/Cache/memory.d.ts.map +1 -1
  3. package/dist/Cache/memoryTTL.d.ts.map +1 -1
  4. package/dist/Cache/prelude.d.ts.map +1 -1
  5. package/dist/Cache.d.ts.map +1 -1
  6. package/dist/DiscordConfig.d.ts.map +1 -1
  7. package/dist/DiscordGateway/DiscordWS.d.ts.map +1 -1
  8. package/dist/DiscordGateway/Messaging.d.ts.map +1 -1
  9. package/dist/DiscordGateway/Shard/StateStore.d.ts.map +1 -1
  10. package/dist/DiscordGateway/Shard/heartbeats.d.ts.map +1 -1
  11. package/dist/DiscordGateway/Shard/identify.d.ts.map +1 -1
  12. package/dist/DiscordGateway/Shard/sendEvents.d.ts.map +1 -1
  13. package/dist/DiscordGateway/Shard/utils.d.ts.map +1 -1
  14. package/dist/DiscordGateway/Shard.d.ts.map +1 -1
  15. package/dist/DiscordGateway/ShardStore.d.ts.map +1 -1
  16. package/dist/DiscordGateway/Sharder.d.ts +1 -1
  17. package/dist/DiscordGateway/Sharder.d.ts.map +1 -1
  18. package/dist/DiscordGateway.d.ts.map +1 -1
  19. package/dist/DiscordREST/Generated.d.ts.map +1 -1
  20. package/dist/DiscordREST/utils.d.ts.map +1 -1
  21. package/dist/DiscordREST.d.ts.map +1 -1
  22. package/dist/Helpers/flags.d.ts.map +1 -1
  23. package/dist/Helpers/intents.d.ts.map +1 -1
  24. package/dist/Helpers/interactions.d.ts.map +1 -1
  25. package/dist/Helpers/members.d.ts.map +1 -1
  26. package/dist/Helpers/permissions.d.ts.map +1 -1
  27. package/dist/Helpers/ui.d.ts.map +1 -1
  28. package/dist/Interactions/builder.d.ts.map +1 -1
  29. package/dist/Interactions/commandHelper.d.ts.map +1 -1
  30. package/dist/Interactions/context.d.ts.map +1 -1
  31. package/dist/Interactions/definitions.d.ts.map +1 -1
  32. package/dist/Interactions/error.d.ts.map +1 -1
  33. package/dist/Interactions/gateway.d.ts.map +1 -1
  34. package/dist/Interactions/handlers.d.ts.map +1 -1
  35. package/dist/Interactions/index.d.ts.map +1 -1
  36. package/dist/Interactions/utils.d.ts.map +1 -1
  37. package/dist/Interactions/webhook.d.ts.map +1 -1
  38. package/dist/RateLimit/memory.d.ts.map +1 -1
  39. package/dist/RateLimit/utils.d.ts.map +1 -1
  40. package/dist/RateLimit.d.ts.map +1 -1
  41. package/dist/gateway.d.ts.map +1 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/types.d.ts.map +1 -1
  44. package/dist/utils/Effect.d.ts.map +1 -1
  45. package/dist/version.d.ts +1 -1
  46. package/dist/version.d.ts.map +1 -1
  47. package/dist/version.js +1 -1
  48. package/dist/webhooks.d.ts.map +1 -1
  49. package/package.json +5 -5
  50. package/src/version.ts +1 -1
  51. package/dist/LICENSE +0 -21
  52. package/dist/README.md +0 -66
  53. package/dist/mjs/Cache/driver.mjs +0 -3
  54. package/dist/mjs/Cache/driver.mjs.map +0 -1
  55. package/dist/mjs/Cache/memory.mjs +0 -48
  56. package/dist/mjs/Cache/memory.mjs.map +0 -1
  57. package/dist/mjs/Cache/memoryTTL.mjs +0 -119
  58. package/dist/mjs/Cache/memoryTTL.mjs.map +0 -1
  59. package/dist/mjs/Cache/prelude.mjs +0 -131
  60. package/dist/mjs/Cache/prelude.mjs.map +0 -1
  61. package/dist/mjs/Cache.mjs +0 -90
  62. package/dist/mjs/Cache.mjs.map +0 -1
  63. package/dist/mjs/DiscordConfig.mjs +0 -32
  64. package/dist/mjs/DiscordConfig.mjs.map +0 -1
  65. package/dist/mjs/DiscordGateway/DiscordWS.mjs +0 -77
  66. package/dist/mjs/DiscordGateway/DiscordWS.mjs.map +0 -1
  67. package/dist/mjs/DiscordGateway/Messaging.mjs +0 -35
  68. package/dist/mjs/DiscordGateway/Messaging.mjs.map +0 -1
  69. package/dist/mjs/DiscordGateway/Shard/StateStore.mjs +0 -41
  70. package/dist/mjs/DiscordGateway/Shard/StateStore.mjs.map +0 -1
  71. package/dist/mjs/DiscordGateway/Shard/heartbeats.mjs +0 -25
  72. package/dist/mjs/DiscordGateway/Shard/heartbeats.mjs.map +0 -1
  73. package/dist/mjs/DiscordGateway/Shard/identify.mjs +0 -29
  74. package/dist/mjs/DiscordGateway/Shard/identify.mjs.map +0 -1
  75. package/dist/mjs/DiscordGateway/Shard/sendEvents.mjs +0 -26
  76. package/dist/mjs/DiscordGateway/Shard/sendEvents.mjs.map +0 -1
  77. package/dist/mjs/DiscordGateway/Shard/utils.mjs +0 -3
  78. package/dist/mjs/DiscordGateway/Shard/utils.mjs.map +0 -1
  79. package/dist/mjs/DiscordGateway/Shard.mjs +0 -147
  80. package/dist/mjs/DiscordGateway/Shard.mjs.map +0 -1
  81. package/dist/mjs/DiscordGateway/ShardStore.mjs +0 -24
  82. package/dist/mjs/DiscordGateway/ShardStore.mjs.map +0 -1
  83. package/dist/mjs/DiscordGateway/Sharder.mjs +0 -67
  84. package/dist/mjs/DiscordGateway/Sharder.mjs.map +0 -1
  85. package/dist/mjs/DiscordGateway.mjs +0 -21
  86. package/dist/mjs/DiscordGateway.mjs.map +0 -1
  87. package/dist/mjs/DiscordREST/Generated.mjs +0 -2471
  88. package/dist/mjs/DiscordREST/Generated.mjs.map +0 -1
  89. package/dist/mjs/DiscordREST/utils.mjs +0 -21
  90. package/dist/mjs/DiscordREST/utils.mjs.map +0 -1
  91. package/dist/mjs/DiscordREST.mjs +0 -119
  92. package/dist/mjs/DiscordREST.mjs.map +0 -1
  93. package/dist/mjs/Helpers/flags.mjs +0 -45
  94. package/dist/mjs/Helpers/flags.mjs.map +0 -1
  95. package/dist/mjs/Helpers/intents.mjs +0 -27
  96. package/dist/mjs/Helpers/intents.mjs.map +0 -1
  97. package/dist/mjs/Helpers/interactions.mjs +0 -115
  98. package/dist/mjs/Helpers/interactions.mjs.map +0 -1
  99. package/dist/mjs/Helpers/members.mjs +0 -9
  100. package/dist/mjs/Helpers/members.mjs.map +0 -1
  101. package/dist/mjs/Helpers/permissions.mjs +0 -84
  102. package/dist/mjs/Helpers/permissions.mjs.map +0 -1
  103. package/dist/mjs/Helpers/ui.mjs +0 -137
  104. package/dist/mjs/Helpers/ui.mjs.map +0 -1
  105. package/dist/mjs/Interactions/builder.mjs +0 -56
  106. package/dist/mjs/Interactions/builder.mjs.map +0 -1
  107. package/dist/mjs/Interactions/commandHelper.mjs +0 -49
  108. package/dist/mjs/Interactions/commandHelper.mjs.map +0 -1
  109. package/dist/mjs/Interactions/context.mjs +0 -28
  110. package/dist/mjs/Interactions/context.mjs.map +0 -1
  111. package/dist/mjs/Interactions/definitions.mjs +0 -51
  112. package/dist/mjs/Interactions/definitions.mjs.map +0 -1
  113. package/dist/mjs/Interactions/error.mjs +0 -2
  114. package/dist/mjs/Interactions/error.mjs.map +0 -1
  115. package/dist/mjs/Interactions/gateway.mjs +0 -82
  116. package/dist/mjs/Interactions/gateway.mjs.map +0 -1
  117. package/dist/mjs/Interactions/handlers.mjs +0 -64
  118. package/dist/mjs/Interactions/handlers.mjs.map +0 -1
  119. package/dist/mjs/Interactions/index.mjs +0 -11
  120. package/dist/mjs/Interactions/index.mjs.map +0 -1
  121. package/dist/mjs/Interactions/utils.mjs +0 -26
  122. package/dist/mjs/Interactions/utils.mjs.map +0 -1
  123. package/dist/mjs/Interactions/webhook.mjs +0 -75
  124. package/dist/mjs/Interactions/webhook.mjs.map +0 -1
  125. package/dist/mjs/RateLimit/memory.mjs +0 -39
  126. package/dist/mjs/RateLimit/memory.mjs.map +0 -1
  127. package/dist/mjs/RateLimit/utils.mjs +0 -18
  128. package/dist/mjs/RateLimit/utils.mjs.map +0 -1
  129. package/dist/mjs/RateLimit.mjs +0 -28
  130. package/dist/mjs/RateLimit.mjs.map +0 -1
  131. package/dist/mjs/gateway.mjs +0 -19
  132. package/dist/mjs/gateway.mjs.map +0 -1
  133. package/dist/mjs/index.mjs +0 -18
  134. package/dist/mjs/index.mjs.map +0 -1
  135. package/dist/mjs/types.mjs +0 -356
  136. package/dist/mjs/types.mjs.map +0 -1
  137. package/dist/mjs/utils/Effect.mjs +0 -44
  138. package/dist/mjs/utils/Effect.mjs.map +0 -1
  139. package/dist/mjs/version.mjs +0 -2
  140. package/dist/mjs/version.mjs.map +0 -1
  141. package/dist/mjs/webhooks.mjs +0 -6
  142. package/dist/mjs/webhooks.mjs.map +0 -1
  143. package/dist/package.json +0 -48
  144. package/dist/src/Cache/driver.ts +0 -37
  145. package/dist/src/Cache/memory.ts +0 -83
  146. package/dist/src/Cache/memoryTTL.ts +0 -225
  147. package/dist/src/Cache/prelude.ts +0 -279
  148. package/dist/src/Cache.ts +0 -261
  149. package/dist/src/DiscordConfig.ts +0 -67
  150. package/dist/src/DiscordGateway/DiscordWS.ts +0 -157
  151. package/dist/src/DiscordGateway/Messaging.ts +0 -71
  152. package/dist/src/DiscordGateway/Shard/StateStore.ts +0 -72
  153. package/dist/src/DiscordGateway/Shard/heartbeats.ts +0 -60
  154. package/dist/src/DiscordGateway/Shard/identify.ts +0 -50
  155. package/dist/src/DiscordGateway/Shard/sendEvents.ts +0 -43
  156. package/dist/src/DiscordGateway/Shard/utils.ts +0 -13
  157. package/dist/src/DiscordGateway/Shard.ts +0 -205
  158. package/dist/src/DiscordGateway/ShardStore.ts +0 -42
  159. package/dist/src/DiscordGateway/Sharder.ts +0 -118
  160. package/dist/src/DiscordGateway.ts +0 -79
  161. package/dist/src/DiscordREST/Generated.ts +0 -10832
  162. package/dist/src/DiscordREST/utils.ts +0 -42
  163. package/dist/src/DiscordREST.ts +0 -256
  164. package/dist/src/Helpers/flags.ts +0 -73
  165. package/dist/src/Helpers/intents.ts +0 -35
  166. package/dist/src/Helpers/interactions.ts +0 -317
  167. package/dist/src/Helpers/members.ts +0 -18
  168. package/dist/src/Helpers/permissions.ts +0 -145
  169. package/dist/src/Helpers/ui.ts +0 -253
  170. package/dist/src/Interactions/builder.ts +0 -171
  171. package/dist/src/Interactions/commandHelper.ts +0 -231
  172. package/dist/src/Interactions/context.ts +0 -104
  173. package/dist/src/Interactions/definitions.ts +0 -144
  174. package/dist/src/Interactions/error.ts +0 -3
  175. package/dist/src/Interactions/gateway.ts +0 -193
  176. package/dist/src/Interactions/handlers.ts +0 -108
  177. package/dist/src/Interactions/index.ts +0 -30
  178. package/dist/src/Interactions/utils.ts +0 -93
  179. package/dist/src/Interactions/webhook.ts +0 -204
  180. package/dist/src/RateLimit/memory.ts +0 -63
  181. package/dist/src/RateLimit/utils.ts +0 -28
  182. package/dist/src/RateLimit.ts +0 -90
  183. package/dist/src/gateway.ts +0 -50
  184. package/dist/src/index.ts +0 -44
  185. package/dist/src/types.ts +0 -3090
  186. package/dist/src/utils/Effect.ts +0 -65
  187. package/dist/src/version.ts +0 -1
  188. package/dist/src/webhooks.ts +0 -25
  189. package/dist/tsconfig.base.json +0 -54
  190. package/dist/tsconfig.build.json +0 -10
  191. package/dist/tsconfig.examples.json +0 -10
  192. package/dist/tsconfig.json +0 -14
  193. package/dist/tsconfig.madge.json +0 -12
  194. package/dist/tsconfig.test.json +0 -10
package/dist/src/Cache.ts DELETED
@@ -1,261 +0,0 @@
1
- import type { CacheDriver, ParentCacheDriver } from "./Cache/driver.ts"
2
- import * as Data from "effect/Data"
3
- import * as Effect from "effect/Effect"
4
- import * as Option from "effect/Option"
5
- import * as Schedule from "effect/Schedule"
6
- import type * as Scope from "effect/Scope"
7
- import * as Stream from "effect/Stream"
8
-
9
- export * from "./Cache/driver.ts"
10
- export {
11
- create as memoryDriver,
12
- createWithParent as memoryParentDriver,
13
- } from "./Cache/memory.ts"
14
- export {
15
- create as memoryTTLDriver,
16
- createWithParent as memoryTTLParentDriver,
17
- } from "./Cache/memoryTTL.ts"
18
-
19
- export type ParentCacheOp<T> =
20
- | { op: "create"; parentId: string; resourceId: string; resource: T }
21
- | { op: "update"; parentId: string; resourceId: string; resource: T }
22
- | { op: "delete"; parentId: string; resourceId: string }
23
- | { op: "parentDelete"; parentId: string }
24
-
25
- export type CacheOp<T> =
26
- | { op: "create"; resourceId: string; resource: T }
27
- | { op: "update"; resourceId: string; resource: T }
28
- | { op: "delete"; resourceId: string }
29
-
30
- const retryPolicy = Schedule.exponential("500 millis").pipe(
31
- Schedule.either(Schedule.spaced("10 seconds")),
32
- )
33
-
34
- export interface ParentCache<EDriver, EMiss, EPMiss, A> {
35
- readonly get: (
36
- parentId: string,
37
- id: string,
38
- ) => Effect.Effect<A, EDriver | EMiss>
39
- readonly put: (_: A) => Effect.Effect<void, EDriver | EMiss>
40
- readonly update: <R, E>(
41
- parentId: string,
42
- id: string,
43
- f: (_: A) => Effect.Effect<A, E, R>,
44
- ) => Effect.Effect<A, EDriver | EMiss | E, R>
45
- readonly getForParent: (
46
- parentId: string,
47
- ) => Effect.Effect<ReadonlyMap<string, A>, EDriver | EPMiss>
48
- readonly size: Effect.Effect<number, EDriver>
49
- readonly sizeForParent: (parentId: string) => Effect.Effect<number, EDriver>
50
- readonly set: (
51
- parentId: string,
52
- resourceId: string,
53
- resource: A,
54
- ) => Effect.Effect<void, EDriver>
55
- readonly delete: (
56
- parentId: string,
57
- resourceId: string,
58
- ) => Effect.Effect<void, EDriver>
59
- readonly parentDelete: (parentId: string) => Effect.Effect<void, EDriver>
60
- readonly refreshTTL: (
61
- parentId: string,
62
- resourceId: string,
63
- ) => Effect.Effect<void, EDriver>
64
- }
65
-
66
- export const makeWithParent = <EOps, EDriver, EMiss, EPMiss, A>({
67
- driver,
68
- id: identify,
69
- onMiss,
70
- onParentMiss,
71
- ops = Stream.empty,
72
- }: {
73
- driver: ParentCacheDriver<EDriver, A>
74
- ops?: Stream.Stream<ParentCacheOp<A>, EOps>
75
- id: (_: A) => Effect.Effect<readonly [parentId: string, id: string], EMiss>
76
- onMiss: (parentId: string, id: string) => Effect.Effect<A, EMiss>
77
- onParentMiss: (
78
- parentId: string,
79
- ) => Effect.Effect<Array<readonly [id: string, resource: A]>, EPMiss>
80
- }): Effect.Effect<ParentCache<EDriver, EMiss, EPMiss, A>, never, Scope.Scope> =>
81
- Effect.gen(function* () {
82
- yield* Stream.runDrain(
83
- Stream.tap(ops, (op): Effect.Effect<void, EDriver> => {
84
- switch (op.op) {
85
- case "create":
86
- case "update":
87
- return driver.set(op.parentId, op.resourceId, op.resource)
88
-
89
- case "delete":
90
- return driver.delete(op.parentId, op.resourceId)
91
-
92
- case "parentDelete":
93
- return driver.parentDelete(op.parentId)
94
- }
95
- }),
96
- ).pipe(
97
- Effect.tapCause(cause => Effect.logError("ops error, restarting", cause)),
98
- Effect.retry(retryPolicy),
99
- Effect.forkScoped,
100
- Effect.interruptible,
101
- )
102
- yield* driver.run.pipe(
103
- Effect.tapCause(cause =>
104
- Effect.logError("cache driver error, restarting", cause),
105
- ),
106
- Effect.retry(retryPolicy),
107
- Effect.forkScoped,
108
- Effect.interruptible,
109
- )
110
-
111
- const get = (parentId: string, id: string) =>
112
- Effect.flatMap(driver.get(parentId, id), option =>
113
- Option.match(option, {
114
- onNone: () =>
115
- Effect.tap(onMiss(parentId, id), a => driver.set(parentId, id, a)),
116
- onSome: Effect.succeed,
117
- }),
118
- )
119
-
120
- const put = (_: A) =>
121
- Effect.flatMap(identify(_), ([parentId, id]) =>
122
- driver.set(parentId, id, _),
123
- )
124
-
125
- const update = <R, E>(
126
- parentId: string,
127
- id: string,
128
- f: (_: A) => Effect.Effect<A, E, R>,
129
- ) =>
130
- Effect.flatMap(get(parentId, id), a =>
131
- Effect.tap(f(a), next => driver.set(parentId, id, next)),
132
- )
133
-
134
- return {
135
- ...driver,
136
-
137
- get,
138
- put,
139
- update,
140
-
141
- getForParent: (parentId: string) =>
142
- Effect.flatMap(driver.getForParent(parentId), option =>
143
- Option.match(option, {
144
- onNone: () =>
145
- onParentMiss(parentId).pipe(
146
- Effect.tap(entries =>
147
- Effect.all(
148
- entries.map(([id, a]) => driver.set(parentId, id, a)),
149
- { concurrency: "unbounded" },
150
- ),
151
- ),
152
- Effect.map(
153
- entries => new Map(entries) as ReadonlyMap<string, A>,
154
- ),
155
- ),
156
- onSome: Effect.succeed,
157
- }),
158
- ),
159
- } as const
160
- }).pipe(
161
- Effect.annotateLogs({
162
- package: "dfx",
163
- service: "Cache",
164
- }),
165
- )
166
-
167
- export interface Cache<EDriver, EMiss, A> {
168
- readonly get: (id: string) => Effect.Effect<A, EDriver | EMiss>
169
- readonly put: (_: A) => Effect.Effect<void, EDriver>
170
- readonly update: <R, E>(
171
- id: string,
172
- f: (_: A) => Effect.Effect<A, E, R>,
173
- ) => Effect.Effect<A, EDriver | EMiss | E, R>
174
- readonly size: Effect.Effect<number, EDriver>
175
- readonly set: (
176
- resourceId: string,
177
- resource: A,
178
- ) => Effect.Effect<void, EDriver>
179
- readonly delete: (resourceId: string) => Effect.Effect<void, EDriver>
180
- readonly refreshTTL: (resourceId: string) => Effect.Effect<void, EDriver>
181
- }
182
-
183
- export const make = <EOps, EDriver, EMiss, A>({
184
- driver,
185
- id: identify,
186
- onMiss,
187
- ops = Stream.empty,
188
- }: {
189
- driver: CacheDriver<EDriver, A>
190
- ops?: Stream.Stream<CacheOp<A>, EOps>
191
- id: (_: A) => string
192
- onMiss: (id: string) => Effect.Effect<A, EMiss>
193
- }): Effect.Effect<Cache<EDriver, EMiss, A>, never, Scope.Scope> =>
194
- Effect.gen(function* () {
195
- yield* Stream.runDrain(
196
- Stream.tap(ops, (op): Effect.Effect<void, EDriver> => {
197
- switch (op.op) {
198
- case "create":
199
- case "update":
200
- return driver.set(op.resourceId, op.resource)
201
-
202
- case "delete":
203
- return driver.delete(op.resourceId)
204
- }
205
- }),
206
- ).pipe(
207
- Effect.tapCause(cause => Effect.logError("ops error, restarting", cause)),
208
- Effect.retry(retryPolicy),
209
- Effect.forkScoped,
210
- Effect.interruptible,
211
- )
212
-
213
- yield* driver.run.pipe(
214
- Effect.tapCause(cause =>
215
- Effect.logError("cache driver error, restarting", cause),
216
- ),
217
- Effect.retry(retryPolicy),
218
- Effect.forkScoped,
219
- Effect.interruptible,
220
- )
221
-
222
- const get = (id: string) =>
223
- Effect.flatMap(driver.get(id), option =>
224
- Option.match(option, {
225
- onNone: () => Effect.tap(onMiss(id), a => driver.set(id, a)),
226
- onSome: Effect.succeed,
227
- }),
228
- )
229
-
230
- const put = (_: A) => driver.set(identify(_), _)
231
-
232
- const update = <R, E>(id: string, f: (_: A) => Effect.Effect<A, E, R>) =>
233
- Effect.flatMap(get(id), a =>
234
- Effect.tap(f(a), next => driver.set(id, next)),
235
- )
236
-
237
- return {
238
- ...driver,
239
- get,
240
- put,
241
- update,
242
- } as const
243
- }).pipe(
244
- Effect.annotateLogs({
245
- package: "dfx",
246
- service: "Cache",
247
- }),
248
- )
249
-
250
- export const CacheErrorTypeId = Symbol.for("dfx/Cache/CacheError")
251
-
252
- export class CacheMissError extends Data.Error<{
253
- cacheName: string
254
- id: string
255
- }> {
256
- readonly _tag = "CacheMissError"
257
-
258
- get message() {
259
- return `Cache miss for "${this.cacheName}" with id: ${this.id}`
260
- }
261
- }
@@ -1,67 +0,0 @@
1
- import * as Discord from "./types.ts"
2
- import * as Config from "effect/Config"
3
- import * as Duration from "effect/Duration"
4
- import * as Effect from "effect/Effect"
5
- import * as Layer from "effect/Layer"
6
- import type * as Redacted from "effect/Redacted"
7
- import * as ServiceMap from "effect/ServiceMap"
8
-
9
- const VERSION = 10
10
-
11
- export interface DiscordConfigService {
12
- readonly token: Redacted.Redacted
13
- readonly rest: {
14
- readonly baseUrl: string
15
- readonly globalRateLimit: {
16
- readonly limit: number
17
- readonly window: Duration.Input
18
- }
19
- }
20
- readonly gateway: {
21
- readonly intents: number
22
- readonly presence?: Discord.GatewayPresenceUpdateData
23
- readonly shardCount?: number
24
-
25
- readonly identifyRateLimit: readonly [window: number, limit: number]
26
- }
27
- }
28
- export class DiscordConfig extends ServiceMap.Service<
29
- DiscordConfig,
30
- DiscordConfigService
31
- >()("dfx/DiscordConfig") {}
32
-
33
- export interface MakeOpts {
34
- readonly token: Redacted.Redacted
35
- readonly rest?: Partial<DiscordConfigService["rest"]>
36
- readonly gateway?: Partial<DiscordConfigService["gateway"]>
37
- }
38
-
39
- export const make = ({
40
- gateway,
41
- rest,
42
- token,
43
- }: MakeOpts): DiscordConfigService => ({
44
- token,
45
- rest: {
46
- baseUrl: `https://discord.com/api/v${VERSION}`,
47
- ...rest,
48
- globalRateLimit: {
49
- limit: 50,
50
- window: Duration.seconds(1),
51
- ...rest?.globalRateLimit,
52
- },
53
- },
54
- gateway: {
55
- intents: Discord.GatewayIntentBits.Guilds,
56
- identifyRateLimit: [5000, 1],
57
- ...gateway,
58
- },
59
- })
60
-
61
- export const layer = (opts: MakeOpts): Layer.Layer<DiscordConfig> =>
62
- Layer.succeed(DiscordConfig, make(opts))
63
-
64
- export const layerConfig = (
65
- _: Config.Wrap<MakeOpts>,
66
- ): Layer.Layer<DiscordConfig, Config.ConfigError> =>
67
- Layer.effect(DiscordConfig, Effect.map(Config.unwrap(_).asEffect(), make))
@@ -1,157 +0,0 @@
1
- import * as Effect from "effect/Effect"
2
- import * as Layer from "effect/Layer"
3
- import * as Ref from "effect/Ref"
4
- import type * as Discord from "../types.ts"
5
- import * as Schedule from "effect/Schedule"
6
- import * as Cause from "effect/Cause"
7
- import * as ServiceMap from "effect/ServiceMap"
8
- import * as Queue from "effect/Queue"
9
- import * as Socket from "effect/unstable/socket/Socket"
10
- import type * as Scope from "effect/Scope"
11
- import { CurrentLoggers } from "effect/Logger"
12
- import * as LogLevel from "effect/LogLevel"
13
- import { MinimumLogLevel } from "effect/References"
14
-
15
- export type Message = Discord.GatewayReceivePayload
16
- export type MessageSend = Discord.GatewaySendPayload | Reconnect
17
-
18
- export const Reconnect = Symbol.for("dfx/DiscordGateway/WS/Reconnect")
19
- export type Reconnect = typeof Reconnect
20
-
21
- export interface OpenOpts {
22
- url?: string
23
- version?: number
24
- encoding?: DiscordWSCodec
25
- onConnecting: Effect.Effect<void>
26
- }
27
-
28
- export interface DiscordWSCodecService {
29
- type: "json" | "etf"
30
- encode: (p: Discord.GatewaySendPayload) => Uint8Array | string
31
- decode: (p: Uint8Array | string) => Discord.GatewayReceivePayload
32
- }
33
-
34
- const decoder = new TextDecoder()
35
-
36
- export class DiscordWSCodec extends ServiceMap.Service<
37
- DiscordWSCodec,
38
- DiscordWSCodecService
39
- >()("dfx/DiscordGateway/DiscordWS/Codec") {}
40
-
41
- export const JsonDiscordWSCodecLive = Layer.succeed(DiscordWSCodec, {
42
- type: "json",
43
- encode: p => JSON.stringify(p),
44
- decode: p => JSON.parse(typeof p === "string" ? p : decoder.decode(p)),
45
- })
46
-
47
- const make = Effect.gen(function* () {
48
- const encoding = yield* DiscordWSCodec
49
-
50
- const connect = Effect.fnUntraced(
51
- function* ({
52
- onConnecting,
53
- url = "wss://gateway.discord.gg/",
54
- version = 10,
55
- }: OpenOpts) {
56
- const urlRef = yield* Ref.make(
57
- `${url}?v=${version}&encoding=${encoding.type}`,
58
- )
59
- const setUrl = (nextUrl: string) =>
60
- Ref.set(urlRef, `${nextUrl}?v=${version}&encoding=${encoding.type}`)
61
- const messages = yield* Queue.make<Message>()
62
- const socket = yield* Socket.makeWebSocket(Ref.get(urlRef), {
63
- closeCodeIsError: _ => true,
64
- openTimeout: 5000,
65
- })
66
- const writeRaw = yield* socket.writer
67
- const logWriteError = (cause: Cause.Cause<Socket.SocketError>) =>
68
- Effect.annotateLogs(Effect.logDebug(cause), {
69
- module: "DiscordGateway/DiscordWS",
70
- channel: "outbound",
71
- })
72
- const write = (message: MessageSend): Effect.Effect<void> => {
73
- if (message === Reconnect) {
74
- return Effect.catchCause(
75
- writeRaw(new Socket.CloseEvent(3000, "reconnecting")),
76
- logWriteError,
77
- )
78
- }
79
- return Effect.catchCause(
80
- writeRaw(encoding.encode(message)),
81
- logWriteError,
82
- )
83
- }
84
- const traceEnabled = LogLevel.isLessThanOrEqualTo(
85
- yield* MinimumLogLevel,
86
- "Trace",
87
- )
88
- const loggers = yield* CurrentLoggers
89
- yield* onConnecting.pipe(
90
- Effect.andThen(
91
- Effect.withFiber<void, Socket.SocketError>(fiber =>
92
- socket.runRaw(_ => {
93
- const message = encoding.decode(_)
94
- Queue.offerUnsafe(messages, message)
95
- if (!traceEnabled) return
96
- loggers.forEach(logger => {
97
- logger.log({
98
- message,
99
- cause: Cause.empty,
100
- fiber,
101
- logLevel: "Trace",
102
- date: new Date(),
103
- })
104
- })
105
- }),
106
- ),
107
- ),
108
- Effect.retry({
109
- while: e =>
110
- e.reason._tag === "SocketCloseError" && e.reason.code === 3000,
111
- }),
112
- Effect.catchCause(cause =>
113
- Effect.logDebug("Got socket error, reconnecting", cause),
114
- ),
115
- Effect.repeat(
116
- Schedule.exponential(500).pipe(
117
- Schedule.either(Schedule.spaced(10000)),
118
- ),
119
- ),
120
- Effect.annotateLogs("channel", "inbound"),
121
- Effect.forkScoped,
122
- )
123
-
124
- return {
125
- take: Queue.take(messages),
126
- setUrl,
127
- write,
128
- } as const
129
- },
130
- Effect.annotateLogs({
131
- module: "DiscordGateway/DiscordWS",
132
- }),
133
- )
134
-
135
- return { connect } as const
136
- })
137
-
138
- export class DiscordWS extends ServiceMap.Service<
139
- DiscordWS,
140
- {
141
- readonly connect: (args_0: OpenOpts) => Effect.Effect<
142
- {
143
- readonly take: Effect.Effect<
144
- Discord.GatewayReceivePayload,
145
- never,
146
- never
147
- >
148
- readonly setUrl: (url: string) => Effect.Effect<void, never, never>
149
- readonly write: (message: MessageSend) => Effect.Effect<void>
150
- },
151
- never,
152
- Socket.WebSocketConstructor | Scope.Scope
153
- >
154
- }
155
- >()("dfx/DiscordGateway/DiscordWS") {}
156
-
157
- export const DiscordWSLive = Layer.effect(DiscordWS, make)
@@ -1,71 +0,0 @@
1
- import * as Effect from "effect/Effect"
2
- import * as PubSub from "effect/PubSub"
3
- import * as Layer from "effect/Layer"
4
- import * as Stream from "effect/Stream"
5
- import type * as Discord from "../types.ts"
6
- import * as EffectUtils from "../utils/Effect.ts"
7
- import * as Queue from "effect/Queue"
8
- import * as ServiceMap from "effect/ServiceMap"
9
-
10
- const fromDispatchFactory =
11
- <R, E>(source: Stream.Stream<Discord.GatewayReceivePayload, E, R>) =>
12
- <K extends `${Discord.GatewayDispatchEvents}`>(
13
- event: K,
14
- ): Stream.Stream<
15
- Extract<Discord.DistributedGatewayDispatchPayload, { readonly t: K }>["d"],
16
- E,
17
- R
18
- > =>
19
- Stream.map(
20
- Stream.filter(source, p => p.t === event),
21
- p => p.d,
22
- ) as any
23
-
24
- const handleDispatchFactory =
25
- (hub: PubSub.PubSub<Discord.GatewayReceivePayload>) =>
26
- <K extends `${Discord.GatewayDispatchEvents}`, R, E, A>(
27
- event: K,
28
- handle: (
29
- event: Extract<Discord.GatewayDispatchPayload, { readonly t: K }>["d"],
30
- ) => Effect.Effect<A, E, R>,
31
- ): Effect.Effect<never, E, R> =>
32
- EffectUtils.subscribeForEachPar(hub, _ => {
33
- if (_.t === event) {
34
- return handle(_.d as any)
35
- }
36
- return Effect.void as any
37
- })
38
-
39
- export const make = Effect.gen(function* () {
40
- const hub = yield* Effect.acquireRelease(
41
- PubSub.unbounded<Discord.GatewayReceivePayload>(),
42
- PubSub.shutdown,
43
- )
44
-
45
- const sendMailbox = yield* Effect.acquireRelease(
46
- Queue.make<Discord.GatewaySendPayload>(),
47
- Queue.shutdown,
48
- )
49
- const send = (payload: Discord.GatewaySendPayload) =>
50
- Queue.offer(sendMailbox, payload)
51
-
52
- const dispatch = Stream.fromPubSub(hub)
53
- const fromDispatch = fromDispatchFactory(dispatch)
54
- const handleDispatch = handleDispatchFactory(hub)
55
-
56
- return {
57
- hub,
58
- sendMailbox,
59
- dispatch,
60
- fromDispatch,
61
- handleDispatch,
62
- send,
63
- } as const
64
- })
65
-
66
- export class Messaging extends ServiceMap.Service<Messaging>()(
67
- "dfx/DiscordGateway/Messaging",
68
- { make },
69
- ) {}
70
- export type Messsaging = Messaging
71
- export const MesssagingLive = Layer.effect(Messaging, make)
@@ -1,72 +0,0 @@
1
- import * as Effect from "effect/Effect"
2
- import * as Option from "effect/Option"
3
- import * as Layer from "effect/Layer"
4
- import * as ServiceMap from "effect/ServiceMap"
5
- import * as KeyValueStore from "effect/unstable/persistence/KeyValueStore"
6
- import { flow, pipe } from "effect/Function"
7
-
8
- export interface ShardState {
9
- readonly resumeUrl: string
10
- readonly sequence: number | null
11
- readonly sessionId: string
12
- }
13
-
14
- export interface StateStore {
15
- readonly get: Effect.Effect<Option.Option<ShardState>>
16
- readonly set: (state: ShardState) => Effect.Effect<void>
17
- readonly clear: Effect.Effect<void>
18
- }
19
-
20
- export class ShardStateStore extends ServiceMap.Service<
21
- ShardStateStore,
22
- { readonly forShard: (id: [id: number, count: number]) => StateStore }
23
- >()("dfx/Shard/StateStore") {
24
- static MemoryLive: Layer.Layer<ShardStateStore> = Layer.sync(
25
- ShardStateStore,
26
- () => {
27
- const store = new Map<string, ShardState>()
28
-
29
- return ShardStateStore.of({
30
- forShard: ([id, count]) => {
31
- const key = `${id}-${count}`
32
- return {
33
- get: Effect.sync(() => Option.fromUndefinedOr(store.get(key))),
34
- set(state) {
35
- return Effect.sync(() => {
36
- store.set(key, state)
37
- })
38
- },
39
- clear: Effect.sync(() => {
40
- store.delete(key)
41
- }),
42
- }
43
- },
44
- })
45
- },
46
- )
47
-
48
- static KVSLive: Layer.Layer<
49
- ShardStateStore,
50
- never,
51
- KeyValueStore.KeyValueStore
52
- > = Layer.effect(
53
- ShardStateStore,
54
- Effect.gen(function* () {
55
- const store = yield* KeyValueStore.KeyValueStore
56
- return ShardStateStore.of({
57
- forShard([id, count]) {
58
- const key = `dfx-shard-state-${id}-${count}`
59
- return {
60
- get: pipe(
61
- store.get(key),
62
- Effect.orDie,
63
- Effect.map(flow(Option.fromUndefinedOr, Option.map(JSON.parse))),
64
- ),
65
- set: state => Effect.orDie(store.set(key, JSON.stringify(state))),
66
- clear: Effect.orDie(store.remove(key)),
67
- }
68
- },
69
- })
70
- }),
71
- )
72
- }
@@ -1,60 +0,0 @@
1
- import * as Option from "effect/Option"
2
- import * as Effect from "effect/Effect"
3
- import * as Ref from "effect/Ref"
4
- import * as DiscordWS from "../DiscordWS.ts"
5
- import * as SendEvents from "./sendEvents.ts"
6
- import type * as Discord from "../../types.ts"
7
- import * as EffectU from "../../utils/Effect.ts"
8
- import type { ShardState } from "./StateStore.ts"
9
- import * as Queue from "effect/Queue"
10
-
11
- const payload = (state: Effect.Effect<Option.Option<ShardState>>) =>
12
- Effect.map(state, shardState =>
13
- SendEvents.heartbeat(
14
- Option.getOrNull(Option.map(shardState, s => s.sequence)),
15
- ),
16
- )
17
-
18
- const payloadOrReconnect = (
19
- ref: Ref.Ref<boolean>,
20
- state: Effect.Effect<Option.Option<ShardState>>,
21
- ) =>
22
- Effect.flatMap(
23
- Ref.get(ref),
24
- (acked): Effect.Effect<DiscordWS.MessageSend> =>
25
- acked ? payload(state) : Effect.succeed(DiscordWS.Reconnect),
26
- )
27
-
28
- export const send = (
29
- hellos: Queue.Dequeue<Discord.GatewayHelloData>,
30
- acks: Queue.Dequeue<void>,
31
- state: Effect.Effect<Option.Option<ShardState>>,
32
- sendMessage: (p: DiscordWS.MessageSend) => Effect.Effect<void>,
33
- ) =>
34
- Effect.flatMap(Ref.make(true), ackedRef => {
35
- const sendPayload = payloadOrReconnect(ackedRef, state).pipe(
36
- Effect.tap(Ref.set(ackedRef, false)),
37
- Effect.flatMap(sendMessage),
38
- )
39
-
40
- const heartbeats = EffectU.foreverSwitch(
41
- Effect.tap(Queue.take(hellos), Ref.set(ackedRef, true)),
42
- Effect.fnUntraced(function* (p) {
43
- yield* Effect.sleep(p.heartbeat_interval * Math.random())
44
- while (true) {
45
- yield* sendPayload
46
- yield* Effect.sleep(p.heartbeat_interval)
47
- }
48
- }),
49
- )
50
-
51
- const run = Queue.take(acks).pipe(
52
- Effect.tap(Ref.set(ackedRef, true)),
53
- Effect.forever,
54
- )
55
-
56
- return Effect.all([run, heartbeats], {
57
- concurrency: "unbounded",
58
- discard: true,
59
- })
60
- })