dfx 0.50.0 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/Cache/memory.js +4 -4
  2. package/Cache/memory.js.map +1 -1
  3. package/Cache/memoryTTL.js +5 -5
  4. package/Cache/memoryTTL.js.map +1 -1
  5. package/Cache/prelude.js +4 -3
  6. package/Cache/prelude.js.map +1 -1
  7. package/Cache.d.ts.map +1 -1
  8. package/Cache.js +15 -7
  9. package/Cache.js.map +1 -1
  10. package/DiscordConfig.d.ts +1 -1
  11. package/DiscordConfig.d.ts.map +1 -1
  12. package/DiscordConfig.js +4 -5
  13. package/DiscordConfig.js.map +1 -1
  14. package/DiscordGateway/DiscordWS.d.ts.map +1 -1
  15. package/DiscordGateway/DiscordWS.js +3 -2
  16. package/DiscordGateway/DiscordWS.js.map +1 -1
  17. package/DiscordGateway/Shard/heartbeats.d.ts +1 -1
  18. package/DiscordGateway/Shard/heartbeats.d.ts.map +1 -1
  19. package/DiscordGateway/Shard/heartbeats.js +4 -1
  20. package/DiscordGateway/Shard/heartbeats.js.map +1 -1
  21. package/DiscordGateway/Shard/identify.d.ts +1 -0
  22. package/DiscordGateway/Shard/identify.d.ts.map +1 -1
  23. package/DiscordGateway/Shard/identify.js +8 -5
  24. package/DiscordGateway/Shard/identify.js.map +1 -1
  25. package/DiscordGateway/Shard/invalidSession.js +1 -1
  26. package/DiscordGateway/Shard/invalidSession.js.map +1 -1
  27. package/DiscordGateway/Shard/utils.d.ts +1 -1
  28. package/DiscordGateway/Shard/utils.d.ts.map +1 -1
  29. package/DiscordGateway/Shard/utils.js +4 -2
  30. package/DiscordGateway/Shard/utils.js.map +1 -1
  31. package/DiscordGateway/Shard.d.ts +2 -1
  32. package/DiscordGateway/Shard.d.ts.map +1 -1
  33. package/DiscordGateway/Shard.js +16 -10
  34. package/DiscordGateway/Shard.js.map +1 -1
  35. package/DiscordGateway/Sharder.d.ts.map +1 -1
  36. package/DiscordGateway/Sharder.js +16 -15
  37. package/DiscordGateway/Sharder.js.map +1 -1
  38. package/DiscordGateway/WS.d.ts.map +1 -1
  39. package/DiscordGateway/WS.js +15 -10
  40. package/DiscordGateway/WS.js.map +1 -1
  41. package/DiscordGateway.d.ts.map +1 -1
  42. package/DiscordGateway.js +7 -6
  43. package/DiscordGateway.js.map +1 -1
  44. package/DiscordREST/utils.d.ts +4 -3
  45. package/DiscordREST/utils.d.ts.map +1 -1
  46. package/DiscordREST/utils.js +6 -6
  47. package/DiscordREST/utils.js.map +1 -1
  48. package/DiscordREST.d.ts.map +1 -1
  49. package/DiscordREST.js +21 -17
  50. package/DiscordREST.js.map +1 -1
  51. package/Helpers/interactions.d.ts +10 -10
  52. package/Helpers/interactions.d.ts.map +1 -1
  53. package/Helpers/interactions.js +12 -13
  54. package/Helpers/interactions.js.map +1 -1
  55. package/Interactions/builder.js +1 -1
  56. package/Interactions/builder.js.map +1 -1
  57. package/Interactions/context.d.ts.map +1 -1
  58. package/Interactions/context.js +4 -1
  59. package/Interactions/context.js.map +1 -1
  60. package/Interactions/gateway.d.ts.map +1 -1
  61. package/Interactions/gateway.js +23 -17
  62. package/Interactions/gateway.js.map +1 -1
  63. package/Interactions/handlers.d.ts.map +1 -1
  64. package/Interactions/handlers.js +25 -10
  65. package/Interactions/handlers.js.map +1 -1
  66. package/Interactions/utils.js +1 -1
  67. package/Interactions/utils.js.map +1 -1
  68. package/Interactions/webhook.d.ts +7 -6
  69. package/Interactions/webhook.d.ts.map +1 -1
  70. package/Interactions/webhook.js +23 -20
  71. package/Interactions/webhook.js.map +1 -1
  72. package/Log.js +1 -1
  73. package/Log.js.map +1 -1
  74. package/RateLimit/memory.js +1 -1
  75. package/RateLimit/memory.js.map +1 -1
  76. package/RateLimit.js +9 -7
  77. package/RateLimit.js.map +1 -1
  78. package/global.d.ts +1 -1
  79. package/global.d.ts.map +1 -1
  80. package/package.json +12 -12
  81. package/src/Cache/memory.ts +4 -4
  82. package/src/Cache/memoryTTL.ts +5 -5
  83. package/src/Cache/prelude.ts +6 -6
  84. package/src/Cache.ts +28 -18
  85. package/src/DiscordConfig.ts +3 -2
  86. package/src/DiscordGateway/DiscordWS.ts +3 -3
  87. package/src/DiscordGateway/Shard/heartbeats.ts +6 -1
  88. package/src/DiscordGateway/Shard/identify.ts +7 -5
  89. package/src/DiscordGateway/Shard/invalidSession.ts +1 -1
  90. package/src/DiscordGateway/Shard/utils.ts +7 -4
  91. package/src/DiscordGateway/Shard.ts +24 -19
  92. package/src/DiscordGateway/Sharder.ts +11 -11
  93. package/src/DiscordGateway/WS.ts +12 -8
  94. package/src/DiscordGateway.ts +4 -3
  95. package/src/DiscordREST/utils.ts +3 -1
  96. package/src/DiscordREST.ts +44 -35
  97. package/src/Helpers/interactions.ts +32 -34
  98. package/src/Interactions/builder.ts +3 -3
  99. package/src/Interactions/context.ts +15 -15
  100. package/src/Interactions/gateway.ts +15 -6
  101. package/src/Interactions/handlers.ts +43 -40
  102. package/src/Interactions/utils.ts +1 -1
  103. package/src/Interactions/webhook.ts +18 -15
  104. package/src/Log.ts +1 -1
  105. package/src/RateLimit.ts +6 -6
  106. package/src/global.ts +1 -1
  107. package/src/package.json +12 -12
  108. package/src/utils/hub.ts +6 -6
  109. package/utils/hub.js +6 -3
  110. package/utils/hub.js.map +1 -1
@@ -24,12 +24,12 @@ export class DiscordRESTError {
24
24
  export { ResponseDecodeError } from "@effect-http/client"
25
25
 
26
26
  const make = Do($ => {
27
- const { token, rest } = $(DiscordConfig)
27
+ const { token, rest } = $(DiscordConfig.accessWith(identity))
28
28
 
29
- const http = $(Http.HttpRequestExecutor)
30
- const log = $(Log)
31
- const store = $(RateLimitStore)
32
- const { maybeWait } = $(RateLimiter)
29
+ const http = $(Http.HttpRequestExecutor.accessWith(identity))
30
+ const log = $(Log.accessWith(identity))
31
+ const store = $(RateLimitStore.accessWith(identity))
32
+ const { maybeWait } = $(RateLimiter.accessWith(identity))
33
33
 
34
34
  const globalRateLimit = maybeWait(
35
35
  "dfx.rest.global",
@@ -40,15 +40,18 @@ const make = Do($ => {
40
40
  // Invalid route handling (40x)
41
41
  const badRoutesRef = $(Ref.make(HashSet.empty<string>()))
42
42
  const addBadRoute = (route: string) =>
43
- Effect.allParDiscard([
44
- log.info("DiscordREST", "addBadRoute", route),
45
- badRoutesRef.update(s => s.add(route)),
46
- store.incrementCounter(
47
- "dfx.rest.invalid",
48
- Duration.minutes(10).millis,
49
- 10000,
50
- ),
51
- ])
43
+ Effect.all(
44
+ [
45
+ log.info("DiscordREST", "addBadRoute", route),
46
+ badRoutesRef.update(s => s.add(route)),
47
+ store.incrementCounter(
48
+ "dfx.rest.invalid",
49
+ Duration.minutes(10).toMillis,
50
+ 10000,
51
+ ),
52
+ ],
53
+ { discard: true, concurrency: "unbounded" },
54
+ )
52
55
  const isBadRoute = (route: string) => badRoutesRef.get.map(s => s.has(route))
53
56
  const removeBadRoute = (route: string) =>
54
57
  badRoutesRef.update(s => s.remove(route))
@@ -57,7 +60,7 @@ const make = Do($ => {
57
60
  isBadRoute(route).tap(invalid =>
58
61
  invalid
59
62
  ? maybeWait("dfx.rest.invalid", Duration.minutes(10), 10000)
60
- : Effect.unit(),
63
+ : Effect.unit,
61
64
  ).asUnit
62
65
 
63
66
  // Request rate limiting
@@ -66,16 +69,16 @@ const make = Do($ => {
66
69
  const route = routeFromConfig(path, request.method)
67
70
  const maybeBucket = $(store.getBucketForRoute(route))
68
71
 
69
- const effect = maybeBucket.match(
70
- () => invalidRateLimit(route),
71
- bucket =>
72
+ const effect = maybeBucket.match({
73
+ onNone: () => invalidRateLimit(route),
74
+ onSome: bucket =>
72
75
  Do($ => {
73
76
  $(invalidRateLimit(route))
74
77
  const resetAfter = millis(bucket.resetAfter)
75
78
 
76
79
  $(maybeWait(`dfx.rest.${bucket.key}`, resetAfter, bucket.limit))
77
80
  }),
78
- )
81
+ })
79
82
 
80
83
  $(effect)
81
84
  })
@@ -99,13 +102,13 @@ const make = Do($ => {
99
102
  store.removeCounter(`dfx.rest.?.${route}`),
100
103
  store.putBucket({
101
104
  key: bucket,
102
- resetAfter: retryAfter.millis,
105
+ resetAfter: retryAfter.toMillis,
103
106
  limit: !hasBucket && remaining > 0 ? remaining : limit,
104
107
  }),
105
108
  )
106
109
  }
107
110
 
108
- $(Effect.allParDiscard(effectsToRun))
111
+ $(Effect.all(effectsToRun, { concurrency: "unbounded", discard: true }))
109
112
  }).ignore
110
113
 
111
114
  const httpExecutor = http.execute.filterStatusOk
@@ -146,11 +149,14 @@ const make = Do($ => {
146
149
  case 403:
147
150
  return Do($ => {
148
151
  $(
149
- Effect.allParDiscard([
150
- log.info("DiscordREST", "403", request.url),
151
- addBadRoute(routeFromConfig(request.url, request.method)),
152
- updateBuckets(request, response),
153
- ]),
152
+ Effect.all(
153
+ [
154
+ log.info("DiscordREST", "403", request.url),
155
+ addBadRoute(routeFromConfig(request.url, request.method)),
156
+ updateBuckets(request, response),
157
+ ],
158
+ { concurrency: "unbounded", discard: true },
159
+ ),
154
160
  )
155
161
  return $(Effect.fail(e))
156
162
  })
@@ -158,16 +164,19 @@ const make = Do($ => {
158
164
  case 429:
159
165
  return Do($ => {
160
166
  $(
161
- Effect.allParDiscard([
162
- log.info("DiscordREST", "429", request.url),
163
- addBadRoute(routeFromConfig(request.url, request.method)),
164
- updateBuckets(request, response),
165
- Effect.sleep(
166
- retryAfter(response.headers).getOrElse(() =>
167
- Duration.seconds(5),
167
+ Effect.all(
168
+ [
169
+ log.info("DiscordREST", "429", request.url),
170
+ addBadRoute(routeFromConfig(request.url, request.method)),
171
+ updateBuckets(request, response),
172
+ Effect.sleep(
173
+ retryAfter(response.headers).getOrElse(() =>
174
+ Duration.seconds(5),
175
+ ),
168
176
  ),
169
- ),
170
- ]),
177
+ ],
178
+ { concurrency: "unbounded", discard: true },
179
+ ),
171
180
  )
172
181
  return $(executor<A>(request))
173
182
  })
@@ -1,4 +1,4 @@
1
- import { Option as Maybe, Product } from "@effect/data/Option"
1
+ import { Option as Maybe } from "@effect/data/Option"
2
2
  import * as Arr from "@effect/data/ReadonlyArray"
3
3
 
4
4
  /**
@@ -29,14 +29,16 @@ export const findSubCommand =
29
29
  /**
30
30
  * If the sub-command exists return `true`, else `false`.
31
31
  */
32
- export const isSubCommand = (name: string) =>
33
- flow(findSubCommand(name), o => o.isSome())
32
+ export const isSubCommand =
33
+ (name: string) => (_: Discord.ApplicationCommandDatum) =>
34
+ findSubCommand(name)(_).isSome()
34
35
 
35
36
  /**
36
37
  * Maybe get the options for a sub-command
37
38
  */
38
- export const subCommandOptions = (name: string) =>
39
- flow(findSubCommand(name), o => o.flatMapNullable(o => o.options))
39
+ export const subCommandOptions =
40
+ (name: string) => (_: Discord.ApplicationCommandDatum) =>
41
+ findSubCommand(name)(_).flatMapNullable(o => o.options)
40
42
 
41
43
  /**
42
44
  * A lens for accessing nested options in a interaction.
@@ -49,7 +51,7 @@ export const optionsWithNested = (
49
51
  ): Discord.ApplicationCommandInteractionDataOption[] =>
50
52
  Maybe.fromNullable(opt.options)
51
53
  .map(opts => [...opts, ...opts.flatMap(optsFromOption)])
52
- .match(() => [], identity)
54
+ .match({ onNone: () => [], onSome: identity })
53
55
 
54
56
  return Maybe.fromNullable(data.options)
55
57
  .map(opts => [...opts, ...opts.flatMap(optsFromOption)])
@@ -70,30 +72,30 @@ export const transformOptions = (
70
72
  /**
71
73
  * Return the interaction options as a name / value map.
72
74
  */
73
- export const optionsMap = flow(optionsWithNested, transformOptions)
75
+ export const optionsMap = (
76
+ data: Pick<Discord.ApplicationCommandDatum, "options">,
77
+ ) => transformOptions(optionsWithNested(data))
74
78
 
75
79
  /**
76
80
  * Try find a matching option from the interaction.
77
81
  */
78
- export const getOption = (name: string) =>
79
- flow(
80
- optionsWithNested,
81
- Arr.findFirst(o => o.name === name),
82
- )
82
+ export const getOption =
83
+ (name: string) => (data: Pick<Discord.ApplicationCommandDatum, "options">) =>
84
+ Arr.findFirst(optionsWithNested(data), o => o.name === name)
83
85
 
84
86
  /**
85
87
  * Try find a matching option from the interaction.
86
88
  */
87
- export const focusedOption = flow(
88
- optionsWithNested,
89
- Arr.findFirst(o => o.focused === true),
90
- )
89
+ export const focusedOption = (
90
+ data: Pick<Discord.ApplicationCommandDatum, "options">,
91
+ ) => Arr.findFirst(optionsWithNested(data), o => o.focused === true)
91
92
 
92
93
  /**
93
94
  * Try find a matching option value from the interaction.
94
95
  */
95
- export const optionValue = (name: string) =>
96
- flow(getOption(name), o => o.flatMapNullable(o => o.value))
96
+ export const optionValue =
97
+ (name: string) => (data: Pick<Discord.ApplicationCommandDatum, "options">) =>
98
+ getOption(name)(data).flatMapNullable(o => o.value)
97
99
 
98
100
  /**
99
101
  * Try extract resolved data
@@ -140,9 +142,7 @@ export const resolveValues =
140
142
  ).flatMapNullable(a => a.values as unknown as string[]),
141
143
  )
142
144
  const r = $(resolved(a))
143
- return $(
144
- Product.productAll(values.map(a => Maybe.fromNullable(f(a as any, r)))),
145
- )
145
+ return Arr.compact(values.map(a => Maybe.fromNullable(f(a as any, r))))
146
146
  })
147
147
 
148
148
  const extractComponents = (c: Discord.Component): Discord.Component[] => {
@@ -166,10 +166,8 @@ export const components = (
166
166
  /**
167
167
  * A lens for accessing the components in a interaction.
168
168
  */
169
- export const componentsWithValue = flow(
170
- components,
171
- Arr.filter(c => "value" in c && c.value !== undefined),
172
- )
169
+ export const componentsWithValue = (data: Discord.ModalSubmitDatum) =>
170
+ Arr.filter(components(data), c => "value" in c && c.value !== undefined)
173
171
 
174
172
  /**
175
173
  * Return the interaction components as an id / value map.
@@ -183,24 +181,24 @@ export const transformComponents = (options: Discord.Component[]) =>
183
181
  /**
184
182
  * Return the interaction components as an id / value map.
185
183
  */
186
- export const componentsMap = flow(components, transformComponents)
184
+ export const componentsMap = (data: Discord.ModalSubmitDatum) =>
185
+ transformComponents(components(data))
187
186
 
188
187
  /**
189
188
  * Try find a matching component from the interaction.
190
189
  */
191
- export const getComponent = (id: string) =>
192
- flow(
193
- components,
194
- Arr.findFirst(o => (o as Discord.TextInput).custom_id === id),
190
+ export const getComponent = (id: string) => (data: Discord.ModalSubmitDatum) =>
191
+ Arr.findFirst(
192
+ components(data),
193
+ o => (o as Discord.TextInput).custom_id === id,
195
194
  )
196
195
 
197
196
  /**
198
197
  * Try find a matching component value from the interaction.
199
198
  */
200
- export const componentValue = (id: string) =>
201
- flow(getComponent(id), o =>
202
- o.flatMapNullable(o => (o as Discord.TextInput).value),
203
- )
199
+ export const componentValue =
200
+ (id: string) => (data: Discord.ModalSubmitDatum) =>
201
+ getComponent(id)(data).flatMapNullable(o => (o as Discord.TextInput).value)
204
202
 
205
203
  export type InteractionResponse =
206
204
  | {
@@ -34,7 +34,7 @@ export class InteractionBuilder<R, E, TE> {
34
34
 
35
35
  concat<R1, E1, TE1>(builder: InteractionBuilder<R1, E1, TE1>) {
36
36
  return new InteractionBuilder<R | R1, E | E1, TE | TE1>(
37
- this.definitions.concat(builder.definitions),
37
+ this.definitions.appendAll(builder.definitions),
38
38
  this.transform,
39
39
  )
40
40
  }
@@ -120,7 +120,7 @@ export class InteractionBuilder<R, E, TE> {
120
120
  )
121
121
  .map(c => c.command)
122
122
 
123
- return DiscordREST.flatMap(rest =>
123
+ return DiscordREST.accessWithEffect(rest =>
124
124
  rest
125
125
  .getCurrentBotApplicationInformation()
126
126
  .flatMap(r => r.json)
@@ -141,7 +141,7 @@ export class InteractionBuilder<R, E, TE> {
141
141
  )
142
142
  .map(c => c.command)
143
143
 
144
- return DiscordREST.flatMap(rest =>
144
+ return DiscordREST.accessWithEffect(rest =>
145
145
  rest.bulkOverwriteGuildApplicationCommands(
146
146
  appId,
147
147
  guildId,
@@ -26,7 +26,7 @@ export class ResolvedDataNotFound {
26
26
  export const resolvedValues = <A>(
27
27
  f: (id: Discord.Snowflake, data: Discord.ResolvedDatum) => A | undefined,
28
28
  ) =>
29
- Interaction.flatMap(ix =>
29
+ Interaction.accessWithEffect(ix =>
30
30
  IxHelpers.resolveValues(f)(ix).mapError(() => new ResolvedDataNotFound(ix)),
31
31
  )
32
32
 
@@ -34,14 +34,14 @@ export const resolved = <A>(
34
34
  name: string,
35
35
  f: (id: Discord.Snowflake, data: Discord.ResolvedDatum) => A | undefined,
36
36
  ) =>
37
- Interaction.flatMap(ix =>
37
+ Interaction.accessWithEffect(ix =>
38
38
  IxHelpers.resolveOptionValue(
39
39
  name,
40
40
  f,
41
41
  )(ix).mapError(() => new ResolvedDataNotFound(ix, name)),
42
42
  )
43
43
 
44
- export const focusedOptionValue = FocusedOptionContext.map(
44
+ export const focusedOptionValue = FocusedOptionContext.accessWith(
45
45
  _ => _.focusedOption.value ?? "",
46
46
  )
47
47
 
@@ -73,7 +73,7 @@ export const handleSubCommands = <
73
73
  | SubCommandNotFound,
74
74
  Discord.InteractionResponse
75
75
  > =>
76
- ApplicationCommand.flatMap(data =>
76
+ ApplicationCommand.accessWithEffect(data =>
77
77
  Arr.findFirst(IxHelpers.allSubCommands(data), _ => !!commands[_.name])
78
78
  .mapError(() => new SubCommandNotFound(data))
79
79
  .flatMap(command =>
@@ -83,9 +83,9 @@ export const handleSubCommands = <
83
83
  ),
84
84
  )
85
85
 
86
- export const currentSubCommand = SubCommandContext.map(_ => _.command)
86
+ export const currentSubCommand = SubCommandContext.accessWith(_ => _.command)
87
87
 
88
- export const optionsMap = ApplicationCommand.map(IxHelpers.optionsMap)
88
+ export const optionsMap = ApplicationCommand.accessWith(IxHelpers.optionsMap)
89
89
 
90
90
  export class RequiredOptionNotFound {
91
91
  readonly _tag = "RequiredOptionNotFound"
@@ -98,26 +98,26 @@ export class RequiredOptionNotFound {
98
98
  }
99
99
 
100
100
  export const option = (name: string) =>
101
- ApplicationCommand.map(IxHelpers.getOption(name))
101
+ ApplicationCommand.accessWith(IxHelpers.getOption(name))
102
102
 
103
103
  export const optionValue = (name: string) =>
104
104
  option(name).flatMap(_ =>
105
- _.flatMapNullable(a => a.value).match(
106
- () =>
107
- ApplicationCommand.flatMap(data =>
105
+ _.flatMapNullable(a => a.value).match({
106
+ onNone: () =>
107
+ ApplicationCommand.accessWithEffect(data =>
108
108
  Effect.fail(new RequiredOptionNotFound(data, name)),
109
109
  ),
110
- Effect.succeed,
111
- ),
110
+ onSome: Effect.succeed,
111
+ }),
112
112
  )
113
113
 
114
114
  export const optionValueOptional = (name: string) =>
115
115
  option(name).map(o => o.flatMapNullable(o => o.value))
116
116
 
117
- export const modalValues = ModalSubmitData.map(IxHelpers.componentsMap)
117
+ export const modalValues = ModalSubmitData.accessWith(IxHelpers.componentsMap)
118
118
 
119
119
  export const modalValueOption = (name: string) =>
120
- ModalSubmitData.map(IxHelpers.componentValue(name))
120
+ ModalSubmitData.accessWith(IxHelpers.componentValue(name))
121
121
 
122
122
  export class ModalValueNotFound {
123
123
  readonly _tag = "ModalValueNotFound"
@@ -125,7 +125,7 @@ export class ModalValueNotFound {
125
125
  }
126
126
 
127
127
  export const modalValue = (name: string) =>
128
- ModalSubmitData.flatMap(data =>
128
+ ModalSubmitData.accessWithEffect(data =>
129
129
  IxHelpers.componentValue(name)(data).mapError(
130
130
  () => new ModalValueNotFound(data, name),
131
131
  ),
@@ -47,8 +47,8 @@ export const run =
47
47
  _._tag === "GuildApplicationCommand",
48
48
  ).toReadonlyArray
49
49
 
50
- const gateway = $(DiscordGateway)
51
- const rest = $(DiscordREST)
50
+ const gateway = $(DiscordGateway.accessWith(identity))
51
+ const rest = $(DiscordREST.accessWith(identity))
52
52
 
53
53
  const application = $(
54
54
  rest.getCurrentBotApplicationInformation().flatMap(a => a.json),
@@ -69,7 +69,7 @@ export const run =
69
69
  GuildApplicationCommand.map(_ => _.command) as any,
70
70
  ),
71
71
  )
72
- : Effect.never()
72
+ : Effect.never
73
73
 
74
74
  const handle = handlers(ix.definitions, (i, r) =>
75
75
  rest.createInteractionResponse(i.id, i.token, r),
@@ -79,7 +79,14 @@ export const run =
79
79
  postHandler(handle[i.type](i)).provideService(Interaction, i),
80
80
  )
81
81
 
82
- return $(sync ? run.zipParRight(globalSync).zipParRight(guildSync) : run)
82
+ return $(
83
+ sync
84
+ ? Effect.all(run, globalSync, guildSync, {
85
+ concurrency: "unbounded",
86
+ discard: true,
87
+ }).forever
88
+ : run,
89
+ )
83
90
  })
84
91
 
85
92
  const makeRegistry = Do($ => {
@@ -124,5 +131,7 @@ export interface InteractionsRegistry {
124
131
  }
125
132
 
126
133
  export const InteractionsRegistry = Tag<InteractionsRegistry>()
127
- export const InteractionsRegistryLive =
128
- makeRegistry.toLayer(InteractionsRegistry)
134
+ export const InteractionsRegistryLive = Layer.effect(
135
+ InteractionsRegistry,
136
+ makeRegistry,
137
+ )
@@ -43,67 +43,70 @@ export const handlers = <R, E, TE, A, B>(
43
43
  [Discord.InteractionType.APPLICATION_COMMAND]: i => {
44
44
  const data = i.data as Discord.ApplicationCommandDatum
45
45
 
46
- return Maybe.fromNullable(Commands[data.name]).match(
47
- () => Effect.fail(new DefinitionNotFound(i)),
48
- command =>
46
+ return Maybe.fromNullable(Commands[data.name]).match({
47
+ onNone: () => Effect.fail(new DefinitionNotFound(i)),
48
+ onSome: command =>
49
49
  command
50
50
  .handle(i)
51
51
  .provideService(Ctx.ApplicationCommand, data) as Handler<R, E, B>,
52
- )
52
+ })
53
53
  },
54
54
 
55
55
  [Discord.InteractionType.MODAL_SUBMIT]: i => {
56
56
  const data = i.data as Discord.ModalSubmitDatum
57
57
 
58
- return ModalSubmit.find(_ => _.predicate(data.custom_id)).flatMap(_ =>
59
- _.match(
60
- () => Effect.fail(new DefinitionNotFound(i)),
61
- match =>
62
- match
63
- .handle(i)
64
- .provideService(Ctx.ModalSubmitData, data) as Handler<R, E, B>,
65
- ),
58
+ return ModalSubmit.findFirst(_ => _.predicate(data.custom_id)).flatMap(
59
+ _ =>
60
+ _.match({
61
+ onNone: () => Effect.fail(new DefinitionNotFound(i)),
62
+ onSome: match =>
63
+ match
64
+ .handle(i)
65
+ .provideService(Ctx.ModalSubmitData, data) as Handler<R, E, B>,
66
+ }),
66
67
  )
67
68
  },
68
69
 
69
70
  [Discord.InteractionType.MESSAGE_COMPONENT]: i => {
70
71
  const data = i.data as Discord.MessageComponentDatum
71
72
 
72
- return MessageComponent.find(_ => _.predicate(data.custom_id)).flatMap(
73
- _ =>
74
- _.match(
75
- () => Effect.fail(new DefinitionNotFound(i)),
76
- match =>
77
- match
78
- .handle(i)
79
- .provideService(Ctx.MessageComponentData, data) as Handler<
80
- R,
81
- E,
82
- B
83
- >,
84
- ),
73
+ return MessageComponent.findFirst(_ =>
74
+ _.predicate(data.custom_id),
75
+ ).flatMap(_ =>
76
+ _.match({
77
+ onNone: () => Effect.fail(new DefinitionNotFound(i)),
78
+ onSome: match =>
79
+ match
80
+ .handle(i)
81
+ .provideService(Ctx.MessageComponentData, data) as Handler<
82
+ R,
83
+ E,
84
+ B
85
+ >,
86
+ }),
85
87
  )
86
88
  },
87
89
 
88
90
  [Discord.InteractionType.APPLICATION_COMMAND_AUTOCOMPLETE]: i => {
89
91
  const data = i.data as Discord.ApplicationCommandDatum
90
92
 
91
- return IxHelpers.focusedOption(data).match(
92
- () => Effect.fail(new DefinitionNotFound(i)),
93
- focusedOption =>
94
- Autocomplete.find(_ => _.predicate(data, focusedOption)).flatMap(_ =>
95
- _.match(
96
- () => Effect.fail(new DefinitionNotFound(i)),
97
- match =>
98
- match
99
- .handle(i)
100
- .provideService(Ctx.ApplicationCommand, data)
101
- .provideService(Ctx.FocusedOptionContext, {
102
- focusedOption,
103
- }) as Handler<R, E, B>,
104
- ),
93
+ return IxHelpers.focusedOption(data).match({
94
+ onNone: () => Effect.fail(new DefinitionNotFound(i)),
95
+ onSome: focusedOption =>
96
+ Autocomplete.findFirst(_ => _.predicate(data, focusedOption)).flatMap(
97
+ _ =>
98
+ _.match({
99
+ onNone: () => Effect.fail(new DefinitionNotFound(i)),
100
+ onSome: match =>
101
+ match
102
+ .handle(i)
103
+ .provideService(Ctx.ApplicationCommand, data)
104
+ .provideService(Ctx.FocusedOptionContext, {
105
+ focusedOption,
106
+ }) as Handler<R, E, B>,
107
+ }),
105
108
  ),
106
- )
109
+ })
107
110
  },
108
111
  }
109
112
  }
@@ -68,7 +68,7 @@ export const splitDefinitions = <R, E, TE, A>(
68
68
  }),
69
69
  )
70
70
 
71
- const Commands = grouped.GlobalApplicationCommand.concat(
71
+ const Commands = grouped.GlobalApplicationCommand.appendAll(
72
72
  grouped.GuildApplicationCommand,
73
73
  ).reduce(
74
74
  {} as Record<string, DefinitionFlattenedCommand<R, E, TE, A>>,
@@ -2,6 +2,8 @@ import * as Verify from "discord-verify"
2
2
  import * as D from "./definitions.js"
3
3
  import { DefinitionNotFound, handlers } from "./handlers.js"
4
4
  import { InteractionBuilder, Interaction } from "./index.js"
5
+ import * as Option from "@effect/data/Option"
6
+ import * as Effect from "@effect/io/Effect"
5
7
 
6
8
  export class BadWebhookSignature {
7
9
  readonly _tag = "BadWebhookSignature"
@@ -16,7 +18,7 @@ const checkSignature = (
16
18
  crypto: SubtleCrypto,
17
19
  algorithm: any,
18
20
  ) =>
19
- Maybe.struct({
21
+ Option.all({
20
22
  signature: Maybe.fromNullable(headers["x-signature-ed25519"]),
21
23
  timestamp: Maybe.fromNullable(headers["x-signature-timestamp"]),
22
24
  })
@@ -54,11 +56,10 @@ const makeConfig = ({
54
56
  })
55
57
  export interface WebhookConfig extends ReturnType<typeof makeConfig> {}
56
58
  export const WebhookConfig = Tag<WebhookConfig>()
57
- export const makeConfigLayer = flow(makeConfig, _ =>
58
- Layer.succeed(WebhookConfig, _),
59
- )
59
+ export const makeConfigLayer = (opts: MakeConfigOpts) =>
60
+ Layer.succeed(WebhookConfig, makeConfig(opts))
60
61
  export const makeFromConfig = (a: Config<MakeConfigOpts>) =>
61
- a.config.map(makeConfig).toLayer(WebhookConfig)
62
+ Layer.effect(WebhookConfig, a.config.map(makeConfig))
62
63
 
63
64
  export class WebhookParseError {
64
65
  readonly _tag = "WebhookParseError"
@@ -67,13 +68,15 @@ export class WebhookParseError {
67
68
 
68
69
  const fromHeadersAndBody = (headers: Headers, body: string) =>
69
70
  Do($ => {
70
- const { publicKey, crypto, algorithm } = $(WebhookConfig)
71
+ const { publicKey, crypto, algorithm } = $(
72
+ WebhookConfig.accessWith(identity),
73
+ )
71
74
  $(checkSignature(publicKey, headers, body, crypto, algorithm))
72
75
  return $(
73
- Effect.tryCatch(
74
- () => JSON.parse(body) as Discord.Interaction,
75
- reason => new WebhookParseError(reason),
76
- ),
76
+ Effect.try({
77
+ try: () => JSON.parse(body) as Discord.Interaction,
78
+ catch: reason => new WebhookParseError(reason),
79
+ }),
77
80
  )
78
81
  })
79
82
 
@@ -82,14 +85,14 @@ const run = <R, E>(
82
85
  readonly [
83
86
  handler: D.InteractionDefinition<R, E>,
84
87
  transform: (
85
- self: Effect<R, E, Discord.InteractionResponse>,
86
- ) => Effect<R, E, Discord.InteractionResponse>,
88
+ self: Effect.Effect<R, E, Discord.InteractionResponse>,
89
+ ) => Effect.Effect<R, E, Discord.InteractionResponse>,
87
90
  ]
88
91
  >,
89
92
  handleResponse: (
90
93
  ix: Discord.Interaction,
91
94
  _: Discord.InteractionResponse,
92
- ) => Effect<R, E, Discord.InteractionResponse>,
95
+ ) => Effect.Effect<R, E, Discord.InteractionResponse>,
93
96
  ) => {
94
97
  const handler = handlers(definitions, handleResponse)
95
98
  return (headers: Headers, body: string) =>
@@ -107,8 +110,8 @@ const run = <R, E>(
107
110
  export interface HandleWebhookOpts<E> {
108
111
  headers: Headers
109
112
  body: string
110
- success: (a: Discord.InteractionResponse) => Effect<never, never, void>
111
- error: (e: Cause<E>) => Effect<never, never, void>
113
+ success: (a: Discord.InteractionResponse) => Effect.Effect<never, never, void>
114
+ error: (e: Cause<E>) => Effect.Effect<never, never, void>
112
115
  }
113
116
 
114
117
  /**
package/src/Log.ts CHANGED
@@ -8,7 +8,7 @@ const make = (debug = false) => ({
8
8
  ? Effect.sync(() => {
9
9
  console.error("DEBUG", ...args)
10
10
  })
11
- : Effect.unit(),
11
+ : Effect.unit,
12
12
  })
13
13
 
14
14
  export interface Log extends ReturnType<typeof make> {}