dfx 0.44.0 → 0.45.1

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.
@@ -1,10 +1,7 @@
1
- import * as Http from "@effect-http/client"
2
- import { catchTag } from "@effect/io/Effect"
3
- import { DiscordREST } from "dfx"
4
1
  import { Discord, Effect } from "dfx/_common"
5
- import * as D from "./definitions.js"
6
2
 
7
3
  export { response } from "../Helpers/interactions.js"
4
+ export * from "./builder.js"
8
5
  export * from "./context.js"
9
6
  export {
10
7
  InteractionDefinition,
@@ -15,144 +12,6 @@ export {
15
12
  modalSubmit,
16
13
  } from "./definitions.js"
17
14
 
18
- type ExtractTag<A> = A extends { _tag: infer Tag }
19
- ? Tag extends string
20
- ? Tag
21
- : never
22
- : never
23
-
24
- /**
25
- * @tsplus type dfx/InteractionBuilder
26
- */
27
- export class InteractionBuilder<R, E> {
28
- constructor(
29
- readonly definitions: D.InteractionDefinition<R, E>[],
30
- readonly transform: (self: Effect<any, any, any>) => Effect<R, E, void>,
31
- readonly transformRespond: (
32
- self: Effect<any, any, Discord.InteractionResponse>,
33
- ) => Effect<R, E, Discord.InteractionResponse>,
34
- ) {}
35
-
36
- add<R1, E1>(definition: D.InteractionDefinition<R1, E1>) {
37
- return new InteractionBuilder<R | R1, E | E1>(
38
- [...this.definitions, definition],
39
- this.transform,
40
- this.transformRespond,
41
- )
42
- }
43
-
44
- concat<R1, E1>(builder: InteractionBuilder<R1, E1>) {
45
- return new InteractionBuilder<R | R1, E | E1>(
46
- [...this.definitions, ...builder.definitions],
47
- this.transform,
48
- this.transformRespond,
49
- )
50
- }
51
-
52
- catchAllCause<R1, E1>(f: (cause: Cause<E>) => Effect<R1, E1, void>) {
53
- return new InteractionBuilder<R | R1, E1>(
54
- this.definitions as any,
55
- _ => this.transform(_).catchAllCause(f),
56
- this.transformRespond as any,
57
- )
58
- }
59
-
60
- catchAllCauseRespond<R1, E1>(
61
- f: (cause: Cause<E>) => Effect<R1, E1, Discord.InteractionResponse>,
62
- ) {
63
- return new InteractionBuilder<R | R1, E1>(
64
- this.definitions as any,
65
- this.transform as any,
66
- _ => this.transformRespond(_).catchAllCause(f),
67
- )
68
- }
69
-
70
- catchAll<R1, E1>(f: (error: E) => Effect<R1, E1, void>) {
71
- return new InteractionBuilder<R | R1, E1>(
72
- this.definitions as any,
73
- _ => this.transform(_).catchAll(f),
74
- this.transformRespond as any,
75
- )
76
- }
77
-
78
- catchAllRespond<R1, E1>(
79
- f: (error: E) => Effect<R1, E1, Discord.InteractionResponse>,
80
- ) {
81
- return new InteractionBuilder<R | R1, E1>(
82
- this.definitions as any,
83
- this.transform as any,
84
- _ => this.transformRespond(_).catchAll(f),
85
- )
86
- }
87
-
88
- catchTag<T extends ExtractTag<E>, R1, E1>(
89
- tag: T,
90
- f: (error: Extract<E, { _tag: T }>) => Effect<R1, E1, void>,
91
- ) {
92
- return new InteractionBuilder<R | R1, Exclude<E, { _tag: T }> | E1>(
93
- this.definitions as any,
94
- _ => catchTag(this.transform(_) as any, tag, f as any) as any,
95
- this.transformRespond as any,
96
- )
97
- }
98
-
99
- catchTagRespond<T extends ExtractTag<E>, R1, E1>(
100
- tag: T,
101
- f: (
102
- error: Extract<E, { _tag: T }>,
103
- ) => Effect<R1, E1, Discord.InteractionResponse>,
104
- ) {
105
- return new InteractionBuilder<R | R1, Exclude<E, { _tag: T }> | E1>(
106
- this.definitions as any,
107
- this.transform as any,
108
- _ => catchTag(this.transformRespond(_) as any, tag, f as any) as any,
109
- )
110
- }
111
-
112
- get syncGlobal() {
113
- const commands = this.definitions
114
- .filter(
115
- (c): c is D.GlobalApplicationCommand<R, E> =>
116
- c._tag === "GlobalApplicationCommand",
117
- )
118
- .map(c => c.command)
119
-
120
- return DiscordREST.flatMap(rest =>
121
- rest
122
- .getCurrentBotApplicationInformation()
123
- .flatMap(r => r.json)
124
- .flatMap(app =>
125
- rest.bulkOverwriteGlobalApplicationCommands(app.id, {
126
- body: Http.body.json(commands),
127
- }),
128
- ),
129
- )
130
- }
131
-
132
- syncGuild(appId: Discord.Snowflake, guildId: Discord.Snowflake) {
133
- const commands = this.definitions
134
- .filter(
135
- (c): c is D.GuildApplicationCommand<R, E> =>
136
- c._tag === "GuildApplicationCommand",
137
- )
138
- .map(c => c.command)
139
-
140
- return DiscordREST.flatMap(rest =>
141
- rest.bulkOverwriteGuildApplicationCommands(
142
- appId,
143
- guildId,
144
- commands as any,
145
- ),
146
- )
147
- }
148
- }
149
-
150
- export const builder = new InteractionBuilder<never, never>(
151
- [],
152
- identity as any,
153
- identity as any,
154
- )
155
-
156
15
  // Filters
157
16
  export const id = (query: string) => (customId: string) =>
158
17
  Effect.succeed(query === customId)
@@ -1,39 +1,82 @@
1
1
  import * as D from "./definitions.js"
2
+ import * as Ctx from "./context.js"
2
3
 
3
- export const splitDefinitions = <R, E>(
4
- definitions: D.InteractionDefinition<R, E>[],
4
+ export type DefinitionFlattened<R, E, TE, A> = D.InteractionDefinition<
5
+ R,
6
+ E
7
+ > extends infer D
8
+ ? {
9
+ [K in keyof D]: K extends "handle"
10
+ ? (_: Discord.Interaction) => Effect<R, TE, A>
11
+ : D[K]
12
+ }
13
+ : never
14
+
15
+ export type DefinitionFlattenedCommand<R, E, TE, A> = Extract<
16
+ DefinitionFlattened<R, E, TE, A>,
17
+ { _tag: "GlobalApplicationCommand" | "GuildApplicationCommand" }
18
+ >
19
+
20
+ const context: D.CommandHelper<any> = {
21
+ resolve: Ctx.resolved,
22
+ option: Ctx.option,
23
+ optionValue: Ctx.optionValue,
24
+ optionValueOptional: Ctx.optionValueOptional,
25
+ subCommands: Ctx.handleSubCommands,
26
+ } as any
27
+
28
+ export const flattenDefinitions = <R, E, TE, A, B>(
29
+ definitions: Chunk<
30
+ readonly [
31
+ handler: D.InteractionDefinition<R, E>,
32
+ transform: (self: Effect<R, E, A>) => Effect<R, TE, B>,
33
+ ]
34
+ >,
35
+ handleResponse: (
36
+ ix: Discord.Interaction,
37
+ _: Discord.InteractionResponse,
38
+ ) => Effect<R, E, A>,
39
+ ) =>
40
+ definitions.map(([definition, transform]) => ({
41
+ ...definition,
42
+ handle: (i: Discord.Interaction) =>
43
+ Effect.isEffect(definition.handle)
44
+ ? transform(definition.handle.flatMap(_ => handleResponse(i, _)))
45
+ : transform(
46
+ definition.handle(context).flatMap(_ => handleResponse(i, _)),
47
+ ),
48
+ }))
49
+
50
+ export const splitDefinitions = <R, E, TE, A>(
51
+ definitions: Chunk<DefinitionFlattened<R, E, TE, A>>,
5
52
  ) => {
6
- const grouped = definitions.reduce<{
7
- [K in D.InteractionDefinition<R, E>["_tag"]]: Extract<
8
- D.InteractionDefinition<R, E>,
9
- { _tag: K }
10
- >[]
11
- }>(
12
- (acc, a) => ({
13
- ...acc,
14
- [a._tag]: [...(acc[a._tag] ?? []), a],
15
- }),
53
+ const grouped = definitions.reduce(
16
54
  {
17
- Autocomplete: [],
18
- GlobalApplicationCommand: [],
19
- GuildApplicationCommand: [],
20
- MessageComponent: [],
21
- ModalSubmit: [],
55
+ Autocomplete: Chunk.empty(),
56
+ GlobalApplicationCommand: Chunk.empty(),
57
+ GuildApplicationCommand: Chunk.empty(),
58
+ MessageComponent: Chunk.empty(),
59
+ ModalSubmit: Chunk.empty(),
60
+ } as {
61
+ [K in D.InteractionDefinition<R, E>["_tag"]]: Chunk<
62
+ Extract<DefinitionFlattened<R, E, TE, A>, { _tag: K }>
63
+ >
22
64
  },
23
- )
24
-
25
- const Commands = [
26
- ...grouped.GlobalApplicationCommand,
27
- ...grouped.GuildApplicationCommand,
28
- ].reduce(
29
- (acc, a) => ({
65
+ (acc, d) => ({
30
66
  ...acc,
31
- [a.command.name]: a,
67
+ [d._tag]: (acc[d._tag] as Chunk<any>).append(d),
32
68
  }),
33
- {} as Record<
34
- string,
35
- D.GlobalApplicationCommand<R, E> | D.GuildApplicationCommand<R, E>
36
- >,
69
+ )
70
+
71
+ const Commands = grouped.GlobalApplicationCommand.concat(
72
+ grouped.GuildApplicationCommand,
73
+ ).reduce(
74
+ {} as Record<string, DefinitionFlattenedCommand<R, E, TE, A>>,
75
+ (acc, d) =>
76
+ ({
77
+ ...acc,
78
+ [d.command.name]: d,
79
+ } as any),
37
80
  )
38
81
 
39
82
  return {
@@ -62,8 +62,21 @@ const fromHeadersAndBody = (headers: Headers, body: string) =>
62
62
  )
63
63
  })
64
64
 
65
- const run = <R, E>(definitions: D.InteractionDefinition<R, E>[]) => {
66
- const handler = handlers(definitions)
65
+ const run = <R, E>(
66
+ definitions: Chunk<
67
+ readonly [
68
+ handler: D.InteractionDefinition<R, E>,
69
+ transform: (
70
+ self: Effect<R, E, Discord.InteractionResponse>,
71
+ ) => Effect<R, E, Discord.InteractionResponse>,
72
+ ]
73
+ >,
74
+ handleResponse: (
75
+ ix: Discord.Interaction,
76
+ _: Discord.InteractionResponse,
77
+ ) => Effect<R, E, Discord.InteractionResponse>,
78
+ ) => {
79
+ const handler = handlers(definitions, handleResponse)
67
80
  return (headers: Headers, body: string) =>
68
81
  Do($ => {
69
82
  const interaction = $(fromHeadersAndBody(headers, body))
@@ -86,8 +99,11 @@ export interface HandleWebhookOpts<E> {
86
99
  /**
87
100
  * @tsplus getter dfx/InteractionBuilder webhookHandler
88
101
  */
89
- export const makeHandler = <R, E>(ix: InteractionBuilder<R, E>) => {
90
- const handle = run(ix.definitions)
102
+ export const makeHandler = <R, E, TE>(ix: InteractionBuilder<R, E, TE>) => {
103
+ const handle = run(
104
+ ix.definitions.map(([d]) => [d, identity] as any),
105
+ (_i, r) => Effect.succeed(r),
106
+ )
91
107
 
92
108
  return ({
93
109
  headers,
@@ -96,17 +112,19 @@ export const makeHandler = <R, E>(ix: InteractionBuilder<R, E>) => {
96
112
  error,
97
113
  }: HandleWebhookOpts<
98
114
  E | WebhookParseError | BadWebhookSignature | DefinitionNotFound
99
- >) =>
100
- ix
101
- .transform(ix.transformRespond(handle(headers, body)).flatMap(success))
102
- .catchAllCause(error)
115
+ >) => handle(headers, body).flatMap(success).catchAllCause(error)
103
116
  }
104
117
 
105
118
  /**
106
119
  * @tsplus getter dfx/InteractionBuilder simpleWebhookHandler
107
120
  */
108
- export const makeSimpleHandler = <R, E>(ix: InteractionBuilder<R, E>) => {
109
- const handle = run(ix.definitions)
121
+ export const makeSimpleHandler = <R, E, TE>(
122
+ ix: InteractionBuilder<R, E, TE>,
123
+ ) => {
124
+ const handle = run(
125
+ ix.definitions.map(([d]) => [d, identity] as any),
126
+ (_i, r) => Effect.succeed(r),
127
+ )
110
128
 
111
129
  return ({ headers, body }: { headers: Headers; body: string }) =>
112
130
  handle(headers, body)