@effect-app/vue 4.0.0-beta.33 → 4.0.0-beta.331

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 (148) hide show
  1. package/CHANGELOG.md +2463 -0
  2. package/dist/atomQuery.d.ts +120 -0
  3. package/dist/atomQuery.d.ts.map +1 -0
  4. package/dist/atomQuery.js +434 -0
  5. package/dist/commander.d.ts +634 -0
  6. package/dist/commander.d.ts.map +1 -0
  7. package/dist/commander.js +1068 -0
  8. package/dist/{experimental/confirm.d.ts → confirm.d.ts} +6 -4
  9. package/dist/confirm.d.ts.map +1 -0
  10. package/dist/confirm.js +26 -0
  11. package/dist/dependencyMetadata.d.ts +18 -0
  12. package/dist/dependencyMetadata.d.ts.map +1 -0
  13. package/dist/dependencyMetadata.js +67 -0
  14. package/dist/errorReporter.d.ts +6 -4
  15. package/dist/errorReporter.d.ts.map +1 -1
  16. package/dist/errorReporter.js +14 -19
  17. package/dist/form.d.ts +5 -5
  18. package/dist/form.d.ts.map +1 -1
  19. package/dist/form.js +42 -16
  20. package/dist/internal/tanstackQuery.d.ts +9 -0
  21. package/dist/internal/tanstackQuery.d.ts.map +1 -0
  22. package/dist/internal/tanstackQuery.js +204 -0
  23. package/dist/intl.d.ts +15 -0
  24. package/dist/intl.d.ts.map +1 -0
  25. package/dist/intl.js +9 -0
  26. package/dist/lib.d.ts +7 -9
  27. package/dist/lib.d.ts.map +1 -1
  28. package/dist/lib.js +35 -10
  29. package/dist/liveQueryInvalidation.d.ts +16 -0
  30. package/dist/liveQueryInvalidation.d.ts.map +1 -0
  31. package/dist/liveQueryInvalidation.js +115 -0
  32. package/dist/makeClient.d.ts +236 -336
  33. package/dist/makeClient.d.ts.map +1 -1
  34. package/dist/makeClient.js +417 -408
  35. package/dist/makeContext.d.ts.map +1 -1
  36. package/dist/makeIntl.d.ts.map +1 -1
  37. package/dist/{experimental/makeUseCommand.d.ts → makeUseCommand.d.ts} +4 -3
  38. package/dist/makeUseCommand.d.ts.map +1 -0
  39. package/dist/makeUseCommand.js +13 -0
  40. package/dist/mutate.d.ts +109 -40
  41. package/dist/mutate.d.ts.map +1 -1
  42. package/dist/mutate.js +235 -58
  43. package/dist/query.d.ts +158 -45
  44. package/dist/query.d.ts.map +1 -1
  45. package/dist/query.js +380 -122
  46. package/dist/queryLifetime.d.ts +25 -0
  47. package/dist/queryLifetime.d.ts.map +1 -0
  48. package/dist/queryLifetime.js +54 -0
  49. package/dist/routeParams.d.ts +4 -4
  50. package/dist/routeParams.d.ts.map +1 -1
  51. package/dist/routeParams.js +4 -3
  52. package/dist/runtime.d.ts +1 -14
  53. package/dist/runtime.d.ts.map +1 -1
  54. package/dist/runtime.js +2 -26
  55. package/dist/suspense.d.ts +19 -0
  56. package/dist/suspense.d.ts.map +1 -0
  57. package/dist/suspense.js +38 -0
  58. package/dist/toast.d.ts +2 -0
  59. package/dist/toast.d.ts.map +1 -0
  60. package/dist/toast.js +2 -0
  61. package/dist/withToast.d.ts +2 -0
  62. package/dist/withToast.d.ts.map +1 -0
  63. package/dist/withToast.js +2 -0
  64. package/docs/atom-query-api-redesign.md +207 -0
  65. package/docs/mutation-command-atoms.md +40 -0
  66. package/docs/query-key-invalidation.md +107 -0
  67. package/examples/streamMutation.ts +72 -0
  68. package/package.json +36 -95
  69. package/src/atomQuery.ts +600 -0
  70. package/src/commander.ts +3408 -0
  71. package/src/{experimental/confirm.ts → confirm.ts} +13 -15
  72. package/src/dependencyMetadata.ts +84 -0
  73. package/src/errorReporter.ts +65 -75
  74. package/src/form.ts +57 -21
  75. package/src/index.ts +7 -7
  76. package/src/internal/tanstackQuery.ts +308 -0
  77. package/src/intl.ts +12 -0
  78. package/src/lib.ts +49 -21
  79. package/src/liveQueryInvalidation.ts +138 -0
  80. package/src/makeClient.ts +971 -1159
  81. package/src/makeIntl.ts +2 -2
  82. package/src/{experimental/makeUseCommand.ts → makeUseCommand.ts} +9 -6
  83. package/src/mutate.ts +406 -153
  84. package/src/query.ts +763 -260
  85. package/src/queryLifetime.ts +74 -0
  86. package/src/routeParams.ts +7 -7
  87. package/src/runtime.ts +1 -31
  88. package/src/suspense.ts +43 -0
  89. package/src/toast.ts +1 -0
  90. package/src/withToast.ts +1 -0
  91. package/test/Mutation.test.ts +181 -24
  92. package/test/dependencyInvalidation.test.ts +444 -0
  93. package/test/dist/dependencyInvalidation.test.d.ts.map +1 -0
  94. package/test/dist/form.test.d.ts.map +1 -1
  95. package/test/dist/inactiveInvalidation.test.d.ts.map +1 -0
  96. package/test/dist/interrupt-refetch-repro.test.d.ts.map +1 -0
  97. package/test/dist/lib.test.d.ts.map +1 -0
  98. package/test/dist/liveQueryInvalidation.test.d.ts.map +1 -0
  99. package/test/dist/query-span.test.d.ts.map +1 -0
  100. package/test/dist/queryOptions.test.d.ts.map +1 -0
  101. package/test/dist/streamFinal.test.d.ts.map +1 -0
  102. package/test/dist/streamFn.test.d.ts.map +1 -0
  103. package/test/dist/stubs.d.ts +3751 -120
  104. package/test/dist/stubs.d.ts.map +1 -1
  105. package/test/dist/stubs.js +190 -30
  106. package/test/dist/suspense-regression.test.d.ts.map +1 -0
  107. package/test/dist/suspense.test.d.ts.map +1 -0
  108. package/test/form-validation-errors.test.ts +24 -19
  109. package/test/form.test.ts +25 -6
  110. package/test/inactiveInvalidation.test.ts +172 -0
  111. package/test/interrupt-refetch-repro.test.ts +625 -0
  112. package/test/lib.test.ts +240 -0
  113. package/test/liveQueryInvalidation.test.ts +108 -0
  114. package/test/makeClient.test.ts +437 -38
  115. package/test/query-span.test.ts +92 -0
  116. package/test/queryOptions.test.ts +88 -0
  117. package/test/streamFinal.test.ts +64 -0
  118. package/test/streamFn.test.ts +457 -0
  119. package/test/stubs.ts +227 -42
  120. package/test/suspense-regression.test.ts +168 -0
  121. package/test/suspense.test.ts +160 -0
  122. package/tsconfig.examples.json +20 -0
  123. package/tsconfig.json +9 -2
  124. package/tsconfig.src.json +34 -34
  125. package/tsconfig.test.json +2 -2
  126. package/vitest.config.ts +5 -5
  127. package/dist/experimental/commander.d.ts +0 -359
  128. package/dist/experimental/commander.d.ts.map +0 -1
  129. package/dist/experimental/commander.js +0 -557
  130. package/dist/experimental/confirm.d.ts.map +0 -1
  131. package/dist/experimental/confirm.js +0 -28
  132. package/dist/experimental/intl.d.ts +0 -16
  133. package/dist/experimental/intl.d.ts.map +0 -1
  134. package/dist/experimental/intl.js +0 -5
  135. package/dist/experimental/makeUseCommand.d.ts.map +0 -1
  136. package/dist/experimental/makeUseCommand.js +0 -13
  137. package/dist/experimental/toast.d.ts +0 -47
  138. package/dist/experimental/toast.d.ts.map +0 -1
  139. package/dist/experimental/toast.js +0 -41
  140. package/dist/experimental/withToast.d.ts +0 -25
  141. package/dist/experimental/withToast.d.ts.map +0 -1
  142. package/dist/experimental/withToast.js +0 -45
  143. package/eslint.config.mjs +0 -24
  144. package/src/experimental/commander.ts +0 -1835
  145. package/src/experimental/intl.ts +0 -9
  146. package/src/experimental/toast.ts +0 -66
  147. package/src/experimental/withToast.ts +0 -99
  148. package/tsconfig.json.bak +0 -12
@@ -0,0 +1,3408 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { reportMessage } from "@effect-app/vue/errorReporter"
3
+ import { deepToRaw, reportRuntimeError } from "@effect-app/vue/lib"
4
+ import { type MissingDependencies } from "@effect-app/vue/makeClient"
5
+ import { asResult, asStreamResult } from "@effect-app/vue/mutate"
6
+ import { SupportedErrors } from "effect-app/client"
7
+ import * as Context from "effect-app/Context"
8
+ import * as Effect from "effect-app/Effect"
9
+ import * as Layer from "effect-app/Layer"
10
+ import * as Option from "effect-app/Option"
11
+ import * as S from "effect-app/Schema"
12
+ import { isGeneratorFunction, wrapEffect } from "effect-app/utils"
13
+ import * as Cause from "effect/Cause"
14
+ import type * as Exit from "effect/Exit"
15
+ import type * as Fiber from "effect/Fiber"
16
+ import { flow } from "effect/Function"
17
+ import * as MutableHashMap from "effect/MutableHashMap"
18
+ import * as Predicate from "effect/Predicate"
19
+ import { type Refinement } from "effect/Predicate"
20
+ import * as Stream from "effect/Stream"
21
+ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"
22
+ import { type FormatXMLElementFn, type PrimitiveType } from "intl-messageformat"
23
+ import { computed, type ComputedRef, reactive, ref, toRaw } from "vue"
24
+ import { Confirm } from "./confirm.ts"
25
+ import { I18n } from "./intl.ts"
26
+ import { CurrentToastId, Toast } from "./toast.ts"
27
+ import { WithToast } from "./withToast.ts"
28
+
29
+ type IntlRecord = Record<string, PrimitiveType | FormatXMLElementFn<string, string>>
30
+
31
+ /**
32
+ * Progress information surfaced by a stream command. Either a plain text label
33
+ * or a `{ text, percentage }` pair when concrete progress is known.
34
+ */
35
+ export type Progress = string | { readonly text: string; readonly percentage: number }
36
+
37
+ type FnOptions<
38
+ Id extends string,
39
+ I18nCustomKey extends string,
40
+ State extends IntlRecord | undefined
41
+ > = {
42
+ i18nCustomKey?: I18nCustomKey
43
+ /**
44
+ * passed to the i18n formatMessage calls so you can use it in translation messagee
45
+ * including the Command `action` string.
46
+ * Automatically wrapped with Computed if just a thunk.
47
+ * provided as Command.state tag, so you can access it in the function.
48
+ */
49
+ state?: ComputedRef<State> | (() => State)
50
+ // TODO: namespaced keys like reactivity keys: ["modify_thing", item], so that one can block also on "modify_thing" *
51
+ blockKey?: (id: Id) => string | undefined
52
+ waitKey?: (id: Id) => string | undefined
53
+ allowed?: (id: Id, state: ComputedRef<State>) => boolean
54
+ }
55
+
56
+ type FnOptionsInternal<I18nCustomKey extends string> = {
57
+ i18nCustomKey?: I18nCustomKey | undefined
58
+ state?: IntlRecord | undefined
59
+ }
60
+
61
+ export const DefaultIntl = {
62
+ de: {
63
+ "handle.confirmation": "{action} bestätigen?",
64
+ "handle.waiting": "{action} wird ausgeführt...",
65
+ "handle.success": "{action} erfolgreich",
66
+ "handle.with_errors": "{action} fehlgeschlagen",
67
+ "handle.with_warnings": "{action} erfolgreich, mit Warnungen",
68
+ "handle.error_response":
69
+ "Die Anfrage war nicht erfolgreich:\n{error}\nWir wurden benachrichtigt und werden das Problem in Kürze beheben.",
70
+ "handle.response_error": "Die Antwort konnte nicht verarbeitet werden:\n{error}",
71
+ "handle.request_error": "Die Anfrage konnte nicht gesendet werden:\n{error}",
72
+ "handle.unexpected_error2": "{action} unerwarteter Fehler, probieren sie es in kurze nochmals.",
73
+
74
+ "handle.unexpected_error": "Unerwarteter Fehler:\n{error}",
75
+ "handle.not_found": "Das gesuchte war nicht gefunden"
76
+ },
77
+ en: {
78
+ "handle.confirmation": "Confirm {action}?",
79
+ "handle.waiting": "{action} executing...",
80
+ "handle.success": "{action} Success",
81
+ "handle.with_errors": "{action} Failed",
82
+ "handle.with_warnings": "{action}, with warnings",
83
+ "handle.error_response":
84
+ "There was an error in processing the response:\n{error}\nWe have been notified and will fix the problem shortly.",
85
+ "handle.request_error": "There was an error in the request:\n{error}",
86
+ "handle.response_error": "The request was not successful:\n{error}",
87
+ "handle.unexpected_error2": "{action} unexpected error, please try again shortly.",
88
+
89
+ "handle.unexpected_error": "Unexpected Error:\n{error}",
90
+ "handle.not_found": "The requested item was not found."
91
+ }
92
+ }
93
+
94
+ export class CommandContext extends Context.Service<CommandContext, {
95
+ id: string
96
+ i18nKey: string
97
+ action: string
98
+ label: string
99
+ namespace: string
100
+ namespaced: (key: string) => string
101
+ state?: IntlRecord | undefined
102
+ }>()(
103
+ "CommandContext"
104
+ ) {}
105
+
106
+ /**
107
+ * Service available inside `streamFn` stream handlers that lets you imperatively push
108
+ * progress updates to the command's reactive `progress` ref.
109
+ *
110
+ * Use `Command.mapProgress(fn)` or `Command.updateProgress(progress)` to interact with this service.
111
+ *
112
+ * @example
113
+ * ```ts
114
+ * // Using mapProgress (recommended) — applied as a stream pipe operator:
115
+ * const exportCmd = Command.streamFn("exportData")(
116
+ * function*(arg, ctx) {
117
+ * return makeExportStream(arg.id).pipe(
118
+ * Command.mapProgress((r) =>
119
+ * AsyncResult.isSuccess(r) && r.value._tag === "OperationProgress"
120
+ * ? { text: `${r.value.completed}/${r.value.total}`, percentage: r.value.completed / r.value.total * 100 }
121
+ * : undefined
122
+ * )
123
+ * )
124
+ * }
125
+ * )
126
+ * // exportCmd.progress is updated for every OperationProgress event
127
+ * ```
128
+ */
129
+ export class CommandProgress extends Context.Reference<{
130
+ readonly update: (progress: Progress | undefined) => Effect.Effect<void>
131
+ }>("Commander.CommandProgress", {
132
+ defaultValue: () => ({ update: (_progress: Progress | undefined): Effect.Effect<void> => Effect.void })
133
+ }) {}
134
+
135
+ export type EmitWithCallback<A, Event extends string> = (event: Event, value: A, onDone: () => void) => void
136
+
137
+ /**
138
+ * Use to wrap emit calls with a callback to signal completion.
139
+ * Useful when the publisher wants to wait for the subscriber to finish processing.
140
+ */
141
+ export const wrapEmit = <A, Event extends string>(
142
+ emit: EmitWithCallback<A, NoInfer<Event>>,
143
+ event: Event
144
+ ) =>
145
+ (value: A) => new Promise<void>((resolve) => emit(event, value, resolve))
146
+
147
+ export declare namespace Commander {
148
+ export type IntlRecord = Record<string, PrimitiveType | FormatXMLElementFn<string, string>>
149
+ export type FnOptions<
150
+ Id extends string,
151
+ I18nKey extends string,
152
+ State extends IntlRecord | undefined
153
+ > = {
154
+ i18nCustomKey?: I18nKey
155
+ state?: ComputedRef<State> | (() => State)
156
+ blockKey?: (id: Id) => string | undefined
157
+ waitKey?: (id: Id) => string | undefined
158
+ allowed?: (id: Id, state: ComputedRef<State>) => boolean
159
+ }
160
+
161
+ export type CommanderBase<RT, Id extends string, I18nKey extends string, State extends IntlRecord | undefined> =
162
+ & Gen<RT, Id, I18nKey, State>
163
+ & NonGen<RT, Id, I18nKey, State>
164
+ & CommandContextLocal<Id, I18nKey>
165
+ & {
166
+ state: Context.Service<`Commander.Command.${Id}.state`, State>
167
+ }
168
+
169
+ export type CommanderFn<RT, Id extends string, I18nKey extends string, State extends IntlRecord | undefined> =
170
+ CommanderBase<RT, Id, I18nKey, State>
171
+
172
+ export type CommanderWrap<
173
+ RT,
174
+ Id extends string,
175
+ I18nCustomKey extends string,
176
+ State extends IntlRecord | undefined,
177
+ I,
178
+ A,
179
+ E,
180
+ R
181
+ > =
182
+ & CommandContextLocal<Id, I18nCustomKey>
183
+ & GenWrap<RT, Id, I18nCustomKey, I, A, E, R, State>
184
+ & NonGenWrap<RT, Id, I18nCustomKey, I, A, E, R, State>
185
+ & {
186
+ state: Context.Service<`Commander.Command.${Id}.state`, State>
187
+ }
188
+
189
+ export interface CommandContextLocal<Id extends string, I18nKey extends string> {
190
+ id: Id
191
+ i18nKey: I18nKey
192
+ namespace: `action.${I18nKey}`
193
+ namespaced: <K extends string>(k: K) => `action.${I18nKey}.${K}`
194
+ }
195
+
196
+ export interface CommandProps<
197
+ A,
198
+ E,
199
+ Id extends string,
200
+ I18nKey extends string,
201
+ State extends IntlRecord | undefined
202
+ > extends CommandContextLocal<Id, I18nKey> {
203
+ /** reactive */
204
+ action: string
205
+ /** reactive */
206
+ label: string
207
+ /** reactive */
208
+ result: AsyncResult.AsyncResult<A, E>
209
+ /**
210
+ * reactive – formatted progress info driven by `Command.mapProgress` or `Command.updateProgress`
211
+ * inside a `streamFn` handler. Undefined for non-stream commands.
212
+ */
213
+ progress: Progress | undefined
214
+ /** reactive */
215
+ waiting: boolean
216
+ /** reactive */
217
+ blocked: boolean
218
+ /** reactive */
219
+ allowed: boolean
220
+ /** reactive */
221
+ state: State
222
+ }
223
+
224
+ export interface CommandOut<
225
+ Arg,
226
+ A,
227
+ E,
228
+ R,
229
+ Id extends string,
230
+ I18nKey extends string,
231
+ State extends IntlRecord | undefined
232
+ > extends CommandProps<A, E, Id, I18nKey, State> {
233
+ new(): {}
234
+
235
+ /** click handlers */
236
+ handle: ((arg: Arg) => Fiber.Fiber<Exit.Exit<A, E>>) & {
237
+ /** @deprecated don't exist */
238
+ effect: (arg: Arg) => Effect.Effect<A, E, R>
239
+ }
240
+
241
+ // // TODO: if we keep them, it would probably be nicer as an option api, deciding the return value like in Atom?
242
+ // /** @experimental */
243
+ // compose: (arg: Arg) => Effect.Effect<Exit.Exit<A, E>, R>
244
+ // /** @experimental */
245
+ // compose2: (arg: Arg) => Effect.Effect<A, E, R>
246
+ // /**
247
+ // * @experimental
248
+ // * captures the current span and returns an Effect that when run will execute the command
249
+ // */
250
+ // handleEffect: (arg: Arg) => Effect.Effect<Fiber.Fiber<Exit.Exit<A, E>, never>>
251
+ // /**
252
+ // * @experimental
253
+ // */
254
+ // exec: (arg: Arg) => Effect.Effect<Exit.Exit<A, E>, never, Exclude<R, CommandContext>>
255
+ }
256
+
257
+ export interface CommandContextLocal2<Id extends string, I18nKey extends string, State extends IntlRecord | undefined>
258
+ extends CommandContextLocal<Id, I18nKey>
259
+ {
260
+ state: State
261
+ }
262
+
263
+ type ArgForCombinator<Arg> = [Arg] extends [void] ? undefined : NoInfer<Arg>
264
+
265
+ type CommandOutHelper<
266
+ Arg,
267
+ Eff extends Effect.Effect<any, any, any>,
268
+ Id extends string,
269
+ I18nKey extends string,
270
+ State extends IntlRecord | undefined
271
+ > = CommandOut<
272
+ Arg,
273
+ Effect.Success<Eff>,
274
+ Effect.Error<Eff>,
275
+ Effect.Services<Eff>,
276
+ Id,
277
+ I18nKey,
278
+ State
279
+ >
280
+
281
+ export type Gen<RT, Id extends string, I18nKey extends string, State extends IntlRecord | undefined> = {
282
+ <
283
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
284
+ AEff,
285
+ Arg = void
286
+ >(
287
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Generator<Eff, AEff, never>
288
+ ): CommandOut<
289
+ Arg,
290
+ AEff,
291
+ [Eff] extends [never] ? never
292
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
293
+ : never,
294
+ [Eff] extends [never] ? never
295
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
296
+ : never,
297
+ Id,
298
+ I18nKey,
299
+ State
300
+ >
301
+ <
302
+ Eff extends Effect.Effect<any, any, any>,
303
+ AEff,
304
+ A extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
305
+ Arg = void
306
+ >(
307
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Generator<Eff, AEff, never>,
308
+ a: (
309
+ _: Effect.Effect<
310
+ AEff,
311
+ [Eff] extends [never] ? never
312
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
313
+ : never,
314
+ [Eff] extends [never] ? never
315
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
316
+ : never
317
+ >,
318
+ arg: ArgForCombinator<Arg>,
319
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
320
+ ) => A
321
+ ): CommandOutHelper<Arg, A, Id, I18nKey, State>
322
+ <
323
+ Eff extends Effect.Effect<any, any, any>,
324
+ AEff,
325
+ A,
326
+ B extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
327
+ Arg = void
328
+ >(
329
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Generator<Eff, AEff, never>,
330
+ a: (
331
+ _: Effect.Effect<
332
+ AEff,
333
+ [Eff] extends [never] ? never
334
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
335
+ : never,
336
+ [Eff] extends [never] ? never
337
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
338
+ : never
339
+ >,
340
+ arg: ArgForCombinator<Arg>,
341
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
342
+ ) => A,
343
+ b: (
344
+ _: A,
345
+ arg: ArgForCombinator<Arg>,
346
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
347
+ ) => B
348
+ ): CommandOutHelper<Arg, B, Id, I18nKey, State>
349
+ <
350
+ Eff extends Effect.Effect<any, any, any>,
351
+ AEff,
352
+ A,
353
+ B,
354
+ C extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
355
+ Arg = void
356
+ >(
357
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Generator<Eff, AEff, never>,
358
+ a: (
359
+ _: Effect.Effect<
360
+ AEff,
361
+ [Eff] extends [never] ? never
362
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
363
+ : never,
364
+ [Eff] extends [never] ? never
365
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
366
+ : never
367
+ >,
368
+ arg: ArgForCombinator<Arg>,
369
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
370
+ ) => A,
371
+ b: (
372
+ _: A,
373
+ arg: ArgForCombinator<Arg>,
374
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
375
+ ) => B,
376
+ c: (
377
+ _: B,
378
+ arg: ArgForCombinator<Arg>,
379
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
380
+ ) => C
381
+ ): CommandOutHelper<Arg, C, Id, I18nKey, State>
382
+ <
383
+ Eff extends Effect.Effect<any, any, any>,
384
+ AEff,
385
+ A,
386
+ B,
387
+ C,
388
+ D extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
389
+ Arg = void
390
+ >(
391
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Generator<Eff, AEff, never>,
392
+ a: (
393
+ _: Effect.Effect<
394
+ AEff,
395
+ [Eff] extends [never] ? never
396
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
397
+ : never,
398
+ [Eff] extends [never] ? never
399
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
400
+ : never
401
+ >,
402
+ arg: ArgForCombinator<Arg>,
403
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
404
+ ) => A,
405
+ b: (
406
+ _: A,
407
+ arg: ArgForCombinator<Arg>,
408
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
409
+ ) => B,
410
+ c: (
411
+ _: B,
412
+ arg: ArgForCombinator<Arg>,
413
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
414
+ ) => C,
415
+ d: (
416
+ _: C,
417
+ arg: ArgForCombinator<Arg>,
418
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
419
+ ) => D
420
+ ): CommandOutHelper<Arg, D, Id, I18nKey, State>
421
+ <
422
+ Eff extends Effect.Effect<any, any, any>,
423
+ AEff,
424
+ A,
425
+ B,
426
+ C,
427
+ D,
428
+ E extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
429
+ Arg = void
430
+ >(
431
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Generator<Eff, AEff, never>,
432
+ a: (
433
+ _: Effect.Effect<
434
+ AEff,
435
+ [Eff] extends [never] ? never
436
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
437
+ : never,
438
+ [Eff] extends [never] ? never
439
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
440
+ : never
441
+ >,
442
+ arg: ArgForCombinator<Arg>,
443
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
444
+ ) => A,
445
+ b: (
446
+ _: A,
447
+ arg: ArgForCombinator<Arg>,
448
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
449
+ ) => B,
450
+ c: (
451
+ _: B,
452
+ arg: ArgForCombinator<Arg>,
453
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
454
+ ) => C,
455
+ d: (
456
+ _: C,
457
+ arg: ArgForCombinator<Arg>,
458
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
459
+ ) => D,
460
+ e: (
461
+ _: D,
462
+ arg: ArgForCombinator<Arg>,
463
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
464
+ ) => E
465
+ ): CommandOutHelper<Arg, E, Id, I18nKey, State>
466
+ <
467
+ Eff extends Effect.Effect<any, any, any>,
468
+ AEff,
469
+ A,
470
+ B,
471
+ C,
472
+ D,
473
+ E,
474
+ F extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
475
+ Arg = void
476
+ >(
477
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Generator<Eff, AEff, never>,
478
+ a: (
479
+ _: Effect.Effect<
480
+ AEff,
481
+ [Eff] extends [never] ? never
482
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
483
+ : never,
484
+ [Eff] extends [never] ? never
485
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
486
+ : never
487
+ >,
488
+ arg: ArgForCombinator<Arg>,
489
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
490
+ ) => A,
491
+ b: (
492
+ _: A,
493
+ arg: ArgForCombinator<Arg>,
494
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
495
+ ) => B,
496
+ c: (
497
+ _: B,
498
+ arg: ArgForCombinator<Arg>,
499
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
500
+ ) => C,
501
+ d: (
502
+ _: C,
503
+ arg: ArgForCombinator<Arg>,
504
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
505
+ ) => D,
506
+ e: (
507
+ _: D,
508
+ arg: ArgForCombinator<Arg>,
509
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
510
+ ) => E,
511
+ f: (
512
+ _: E,
513
+ arg: ArgForCombinator<Arg>,
514
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
515
+ ) => F
516
+ ): CommandOutHelper<Arg, F, Id, I18nKey, State>
517
+ <
518
+ Eff extends Effect.Effect<any, any, any>,
519
+ AEff,
520
+ A,
521
+ B,
522
+ C,
523
+ D,
524
+ E,
525
+ F,
526
+ G extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
527
+ Arg = void
528
+ >(
529
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Generator<Eff, AEff, never>,
530
+ a: (
531
+ _: Effect.Effect<
532
+ AEff,
533
+ [Eff] extends [never] ? never
534
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
535
+ : never,
536
+ [Eff] extends [never] ? never
537
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
538
+ : never
539
+ >,
540
+ arg: ArgForCombinator<Arg>,
541
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
542
+ ) => A,
543
+ b: (
544
+ _: A,
545
+ arg: ArgForCombinator<Arg>,
546
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
547
+ ) => B,
548
+ c: (
549
+ _: B,
550
+ arg: ArgForCombinator<Arg>,
551
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
552
+ ) => C,
553
+ d: (
554
+ _: C,
555
+ arg: ArgForCombinator<Arg>,
556
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
557
+ ) => D,
558
+ e: (
559
+ _: D,
560
+ arg: ArgForCombinator<Arg>,
561
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
562
+ ) => E,
563
+ f: (
564
+ _: E,
565
+ arg: ArgForCombinator<Arg>,
566
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
567
+ ) => F,
568
+ g: (
569
+ _: F,
570
+ arg: ArgForCombinator<Arg>,
571
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
572
+ ) => G
573
+ ): CommandOutHelper<Arg, G, Id, I18nKey, State>
574
+ <
575
+ Eff extends Effect.Effect<any, any, any>,
576
+ AEff,
577
+ A,
578
+ B,
579
+ C,
580
+ D,
581
+ E,
582
+ F,
583
+ G,
584
+ H extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
585
+ Arg = void
586
+ >(
587
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Generator<Eff, AEff, never>,
588
+ a: (
589
+ _: Effect.Effect<
590
+ AEff,
591
+ [Eff] extends [never] ? never
592
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
593
+ : never,
594
+ [Eff] extends [never] ? never
595
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
596
+ : never
597
+ >,
598
+ arg: ArgForCombinator<Arg>,
599
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
600
+ ) => A,
601
+ b: (
602
+ _: A,
603
+ arg: ArgForCombinator<Arg>,
604
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
605
+ ) => B,
606
+ c: (
607
+ _: B,
608
+ arg: ArgForCombinator<Arg>,
609
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
610
+ ) => C,
611
+ d: (
612
+ _: C,
613
+ arg: ArgForCombinator<Arg>,
614
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
615
+ ) => D,
616
+ e: (
617
+ _: D,
618
+ arg: ArgForCombinator<Arg>,
619
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
620
+ ) => E,
621
+ f: (
622
+ _: E,
623
+ arg: ArgForCombinator<Arg>,
624
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
625
+ ) => F,
626
+ g: (
627
+ _: F,
628
+ arg: ArgForCombinator<Arg>,
629
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
630
+ ) => G,
631
+ h: (
632
+ _: G,
633
+ arg: ArgForCombinator<Arg>,
634
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
635
+ ) => H
636
+ ): CommandOutHelper<Arg, H, Id, I18nKey, State>
637
+ <
638
+ Eff extends Effect.Effect<any, any, any>,
639
+ AEff,
640
+ A,
641
+ B,
642
+ C,
643
+ D,
644
+ E,
645
+ F,
646
+ G,
647
+ H,
648
+ I extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
649
+ Arg = void
650
+ >(
651
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Generator<Eff, AEff, never>,
652
+ a: (
653
+ _: Effect.Effect<
654
+ AEff,
655
+ [Eff] extends [never] ? never
656
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
657
+ : never,
658
+ [Eff] extends [never] ? never
659
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
660
+ : never
661
+ >,
662
+ arg: ArgForCombinator<Arg>,
663
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
664
+ ) => A,
665
+ b: (
666
+ _: A,
667
+ arg: ArgForCombinator<Arg>,
668
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
669
+ ) => B,
670
+ c: (
671
+ _: B,
672
+ arg: ArgForCombinator<Arg>,
673
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
674
+ ) => C,
675
+ d: (
676
+ _: C,
677
+ arg: ArgForCombinator<Arg>,
678
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
679
+ ) => D,
680
+ e: (
681
+ _: D,
682
+ arg: ArgForCombinator<Arg>,
683
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
684
+ ) => E,
685
+ f: (
686
+ _: E,
687
+ arg: ArgForCombinator<Arg>,
688
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
689
+ ) => F,
690
+ g: (
691
+ _: F,
692
+ arg: ArgForCombinator<Arg>,
693
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
694
+ ) => G,
695
+ h: (
696
+ _: G,
697
+ arg: ArgForCombinator<Arg>,
698
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
699
+ ) => H,
700
+ i: (
701
+ _: H,
702
+ arg: ArgForCombinator<Arg>,
703
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
704
+ ) => I
705
+ ): CommandOutHelper<Arg, I, Id, I18nKey, State>
706
+ }
707
+
708
+ export type NonGen<RT, Id extends string, I18nKey extends string, State extends IntlRecord | undefined> = {
709
+ <
710
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
711
+ Arg = void
712
+ >(
713
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Eff
714
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
715
+ <
716
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
717
+ A,
718
+ Arg = void
719
+ >(
720
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => A,
721
+ a: (
722
+ _: A,
723
+ arg: ArgForCombinator<Arg>,
724
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
725
+ ) => Eff
726
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
727
+ <
728
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
729
+ A,
730
+ B,
731
+ Arg = void
732
+ >(
733
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => A,
734
+ a: (
735
+ _: A,
736
+ arg: ArgForCombinator<Arg>,
737
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
738
+ ) => B,
739
+ b: (
740
+ _: B,
741
+ arg: ArgForCombinator<Arg>,
742
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
743
+ ) => Eff
744
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
745
+ <
746
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
747
+ A,
748
+ B,
749
+ C,
750
+ Arg = void
751
+ >(
752
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => A,
753
+ a: (
754
+ _: A,
755
+ arg: ArgForCombinator<Arg>,
756
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
757
+ ) => B,
758
+ b: (
759
+ _: B,
760
+ arg: ArgForCombinator<Arg>,
761
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
762
+ ) => C,
763
+ c: (
764
+ _: C,
765
+ arg: ArgForCombinator<Arg>,
766
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
767
+ ) => Eff
768
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
769
+ <
770
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
771
+ A,
772
+ B,
773
+ C,
774
+ D,
775
+ Arg = void
776
+ >(
777
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => A,
778
+ a: (
779
+ _: A,
780
+ arg: ArgForCombinator<Arg>,
781
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
782
+ ) => B,
783
+ b: (
784
+ _: B,
785
+ arg: ArgForCombinator<Arg>,
786
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
787
+ ) => C,
788
+ c: (
789
+ _: C,
790
+ arg: ArgForCombinator<Arg>,
791
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
792
+ ) => D,
793
+ d: (
794
+ _: D,
795
+ arg: ArgForCombinator<Arg>,
796
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
797
+ ) => Eff
798
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
799
+ <
800
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
801
+ A,
802
+ B,
803
+ C,
804
+ D,
805
+ E,
806
+ Arg = void
807
+ >(
808
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => A,
809
+ a: (
810
+ _: A,
811
+ arg: ArgForCombinator<Arg>,
812
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
813
+ ) => B,
814
+ b: (
815
+ _: B,
816
+ arg: ArgForCombinator<Arg>,
817
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
818
+ ) => C,
819
+ c: (
820
+ _: C,
821
+ arg: ArgForCombinator<Arg>,
822
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
823
+ ) => D,
824
+ d: (
825
+ _: D,
826
+ arg: ArgForCombinator<Arg>,
827
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
828
+ ) => E,
829
+ e: (
830
+ _: E,
831
+ arg: ArgForCombinator<Arg>,
832
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
833
+ ) => Eff
834
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
835
+ <
836
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
837
+ A,
838
+ B,
839
+ C,
840
+ D,
841
+ E,
842
+ F,
843
+ Arg = void
844
+ >(
845
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => A,
846
+ a: (
847
+ _: A,
848
+ arg: ArgForCombinator<Arg>,
849
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
850
+ ) => B,
851
+ b: (
852
+ _: B,
853
+ arg: ArgForCombinator<Arg>,
854
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
855
+ ) => C,
856
+ c: (
857
+ _: C,
858
+ arg: ArgForCombinator<Arg>,
859
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
860
+ ) => D,
861
+ d: (
862
+ _: D,
863
+ arg: ArgForCombinator<Arg>,
864
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
865
+ ) => E,
866
+ e: (
867
+ _: E,
868
+ arg: ArgForCombinator<Arg>,
869
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
870
+ ) => F,
871
+ f: (
872
+ _: F,
873
+ arg: ArgForCombinator<Arg>,
874
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
875
+ ) => Eff
876
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
877
+ <
878
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
879
+ A,
880
+ B,
881
+ C,
882
+ D,
883
+ E,
884
+ F,
885
+ G,
886
+ Arg = void
887
+ >(
888
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => A,
889
+ a: (
890
+ _: A,
891
+ arg: ArgForCombinator<Arg>,
892
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
893
+ ) => B,
894
+ b: (
895
+ _: B,
896
+ arg: ArgForCombinator<Arg>,
897
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
898
+ ) => C,
899
+ c: (
900
+ _: C,
901
+ arg: ArgForCombinator<Arg>,
902
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
903
+ ) => D,
904
+ d: (
905
+ _: D,
906
+ arg: ArgForCombinator<Arg>,
907
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
908
+ ) => E,
909
+ e: (
910
+ _: E,
911
+ arg: ArgForCombinator<Arg>,
912
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
913
+ ) => F,
914
+ f: (
915
+ _: F,
916
+ arg: ArgForCombinator<Arg>,
917
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
918
+ ) => G,
919
+ g: (
920
+ _: G,
921
+ arg: ArgForCombinator<Arg>,
922
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
923
+ ) => Eff
924
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
925
+ <
926
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
927
+ A,
928
+ B,
929
+ C,
930
+ D,
931
+ E,
932
+ F,
933
+ G,
934
+ H,
935
+ Arg = void
936
+ >(
937
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => A,
938
+ a: (
939
+ _: A,
940
+ arg: ArgForCombinator<Arg>,
941
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
942
+ ) => B,
943
+ b: (
944
+ _: B,
945
+ arg: ArgForCombinator<Arg>,
946
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
947
+ ) => C,
948
+ c: (
949
+ _: C,
950
+ arg: ArgForCombinator<Arg>,
951
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
952
+ ) => D,
953
+ d: (
954
+ _: D,
955
+ arg: ArgForCombinator<Arg>,
956
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
957
+ ) => E,
958
+ e: (
959
+ _: E,
960
+ arg: ArgForCombinator<Arg>,
961
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
962
+ ) => F,
963
+ f: (
964
+ _: F,
965
+ arg: ArgForCombinator<Arg>,
966
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
967
+ ) => G,
968
+ g: (
969
+ _: G,
970
+ arg: ArgForCombinator<Arg>,
971
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
972
+ ) => H,
973
+ h: (
974
+ _: H,
975
+ arg: ArgForCombinator<Arg>,
976
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
977
+ ) => Eff
978
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
979
+ <
980
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
981
+ A,
982
+ B,
983
+ C,
984
+ D,
985
+ E,
986
+ F,
987
+ G,
988
+ H,
989
+ I,
990
+ Arg = void
991
+ >(
992
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => A,
993
+ a: (
994
+ _: A,
995
+ arg: ArgForCombinator<Arg>,
996
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
997
+ ) => B,
998
+ b: (
999
+ _: B,
1000
+ arg: ArgForCombinator<Arg>,
1001
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1002
+ ) => C,
1003
+ c: (
1004
+ _: C,
1005
+ arg: ArgForCombinator<Arg>,
1006
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1007
+ ) => D,
1008
+ d: (
1009
+ _: D,
1010
+ arg: ArgForCombinator<Arg>,
1011
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1012
+ ) => E,
1013
+ e: (
1014
+ _: E,
1015
+ arg: ArgForCombinator<Arg>,
1016
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1017
+ ) => F,
1018
+ f: (
1019
+ _: F,
1020
+ arg: ArgForCombinator<Arg>,
1021
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1022
+ ) => G,
1023
+ g: (
1024
+ _: G,
1025
+ arg: ArgForCombinator<Arg>,
1026
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1027
+ ) => H,
1028
+ h: (
1029
+ _: H,
1030
+ arg: ArgForCombinator<Arg>,
1031
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1032
+ ) => I,
1033
+ i: (
1034
+ _: H,
1035
+ arg: ArgForCombinator<Arg>,
1036
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1037
+ ) => Eff
1038
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
1039
+ }
1040
+
1041
+ export type GenWrap<
1042
+ RT,
1043
+ Id extends string,
1044
+ I18nKey extends string,
1045
+ Arg,
1046
+ AEff,
1047
+ EEff,
1048
+ REff,
1049
+ State extends IntlRecord | undefined
1050
+ > = {
1051
+ (): Exclude<REff, RT> extends never ? CommandOut<
1052
+ Arg,
1053
+ AEff,
1054
+ EEff,
1055
+ REff,
1056
+ Id,
1057
+ I18nKey,
1058
+ State
1059
+ >
1060
+ : MissingDependencies<RT, REff> & {}
1061
+ <
1062
+ A extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>
1063
+ >(
1064
+ a: (
1065
+ _: Effect.Effect<
1066
+ AEff,
1067
+ EEff,
1068
+ REff
1069
+ >,
1070
+ arg: ArgForCombinator<Arg>,
1071
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1072
+ ) => A
1073
+ ): CommandOutHelper<Arg, A, Id, I18nKey, State>
1074
+ <
1075
+ A,
1076
+ B extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>
1077
+ >(
1078
+ a: (
1079
+ _: Effect.Effect<
1080
+ AEff,
1081
+ EEff,
1082
+ REff
1083
+ >,
1084
+ arg: ArgForCombinator<Arg>,
1085
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1086
+ ) => A,
1087
+ b: (
1088
+ _: A,
1089
+ arg: ArgForCombinator<Arg>,
1090
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1091
+ ) => B
1092
+ ): CommandOutHelper<Arg, B, Id, I18nKey, State>
1093
+ <
1094
+ A,
1095
+ B,
1096
+ C extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>
1097
+ >(
1098
+ a: (
1099
+ _: Effect.Effect<
1100
+ AEff,
1101
+ EEff,
1102
+ REff
1103
+ >,
1104
+ arg: ArgForCombinator<Arg>,
1105
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1106
+ ) => A,
1107
+ b: (
1108
+ _: A,
1109
+ arg: ArgForCombinator<Arg>,
1110
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1111
+ ) => B,
1112
+ c: (
1113
+ _: B,
1114
+ arg: ArgForCombinator<Arg>,
1115
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1116
+ ) => C
1117
+ ): CommandOutHelper<Arg, C, Id, I18nKey, State>
1118
+ <
1119
+ A,
1120
+ B,
1121
+ C,
1122
+ D extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>
1123
+ >(
1124
+ a: (
1125
+ _: Effect.Effect<
1126
+ AEff,
1127
+ EEff,
1128
+ REff
1129
+ >,
1130
+ arg: ArgForCombinator<Arg>,
1131
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1132
+ ) => A,
1133
+ b: (
1134
+ _: A,
1135
+ arg: ArgForCombinator<Arg>,
1136
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1137
+ ) => B,
1138
+ c: (
1139
+ _: B,
1140
+ arg: ArgForCombinator<Arg>,
1141
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1142
+ ) => C,
1143
+ d: (
1144
+ _: C,
1145
+ arg: ArgForCombinator<Arg>,
1146
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1147
+ ) => D
1148
+ ): CommandOutHelper<Arg, D, Id, I18nKey, State>
1149
+ <
1150
+ A,
1151
+ B,
1152
+ C,
1153
+ D,
1154
+ E extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>
1155
+ >(
1156
+ a: (
1157
+ _: Effect.Effect<
1158
+ AEff,
1159
+ EEff,
1160
+ REff
1161
+ >,
1162
+ arg: ArgForCombinator<Arg>,
1163
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1164
+ ) => A,
1165
+ b: (
1166
+ _: A,
1167
+ arg: ArgForCombinator<Arg>,
1168
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1169
+ ) => B,
1170
+ c: (
1171
+ _: B,
1172
+ arg: ArgForCombinator<Arg>,
1173
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1174
+ ) => C,
1175
+ d: (
1176
+ _: C,
1177
+ arg: ArgForCombinator<Arg>,
1178
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1179
+ ) => D,
1180
+ e: (
1181
+ _: D,
1182
+ arg: ArgForCombinator<Arg>,
1183
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1184
+ ) => E
1185
+ ): CommandOutHelper<Arg, E, Id, I18nKey, State>
1186
+ <
1187
+ A,
1188
+ B,
1189
+ C,
1190
+ D,
1191
+ E,
1192
+ F extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>
1193
+ >(
1194
+ a: (
1195
+ _: Effect.Effect<
1196
+ AEff,
1197
+ EEff,
1198
+ REff
1199
+ >,
1200
+ arg: ArgForCombinator<Arg>,
1201
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1202
+ ) => A,
1203
+ b: (
1204
+ _: A,
1205
+ arg: ArgForCombinator<Arg>,
1206
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1207
+ ) => B,
1208
+ c: (
1209
+ _: B,
1210
+ arg: ArgForCombinator<Arg>,
1211
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1212
+ ) => C,
1213
+ d: (
1214
+ _: C,
1215
+ arg: ArgForCombinator<Arg>,
1216
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1217
+ ) => D,
1218
+ e: (
1219
+ _: D,
1220
+ arg: ArgForCombinator<Arg>,
1221
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1222
+ ) => E,
1223
+ f: (
1224
+ _: E,
1225
+ arg: ArgForCombinator<Arg>,
1226
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1227
+ ) => F
1228
+ ): CommandOutHelper<Arg, F, Id, I18nKey, State>
1229
+ <
1230
+ A,
1231
+ B,
1232
+ C,
1233
+ D,
1234
+ E,
1235
+ F,
1236
+ G extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>
1237
+ >(
1238
+ a: (
1239
+ _: Effect.Effect<
1240
+ AEff,
1241
+ EEff,
1242
+ REff
1243
+ >,
1244
+ arg: ArgForCombinator<Arg>,
1245
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1246
+ ) => A,
1247
+ b: (
1248
+ _: A,
1249
+ arg: ArgForCombinator<Arg>,
1250
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1251
+ ) => B,
1252
+ c: (
1253
+ _: B,
1254
+ arg: ArgForCombinator<Arg>,
1255
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1256
+ ) => C,
1257
+ d: (
1258
+ _: C,
1259
+ arg: ArgForCombinator<Arg>,
1260
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1261
+ ) => D,
1262
+ e: (
1263
+ _: D,
1264
+ arg: ArgForCombinator<Arg>,
1265
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1266
+ ) => E,
1267
+ f: (
1268
+ _: E,
1269
+ arg: ArgForCombinator<Arg>,
1270
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1271
+ ) => F,
1272
+ g: (
1273
+ _: F,
1274
+ arg: ArgForCombinator<Arg>,
1275
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1276
+ ) => G
1277
+ ): CommandOutHelper<Arg, G, Id, I18nKey, State>
1278
+ <A, B, C, D, E, F, G, H extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>>(
1279
+ a: (
1280
+ _: Effect.Effect<
1281
+ AEff,
1282
+ EEff,
1283
+ REff
1284
+ >,
1285
+ arg: ArgForCombinator<Arg>,
1286
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1287
+ ) => A,
1288
+ b: (
1289
+ _: A,
1290
+ arg: ArgForCombinator<Arg>,
1291
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1292
+ ) => B,
1293
+ c: (
1294
+ _: B,
1295
+ arg: ArgForCombinator<Arg>,
1296
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1297
+ ) => C,
1298
+ d: (
1299
+ _: C,
1300
+ arg: ArgForCombinator<Arg>,
1301
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1302
+ ) => D,
1303
+ e: (
1304
+ _: D,
1305
+ arg: ArgForCombinator<Arg>,
1306
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1307
+ ) => E,
1308
+ f: (
1309
+ _: E,
1310
+ arg: ArgForCombinator<Arg>,
1311
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1312
+ ) => F,
1313
+ g: (
1314
+ _: F,
1315
+ arg: ArgForCombinator<Arg>,
1316
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1317
+ ) => G,
1318
+ h: (
1319
+ _: G,
1320
+ arg: ArgForCombinator<Arg>,
1321
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1322
+ ) => H
1323
+ ): CommandOutHelper<Arg, H, Id, I18nKey, State>
1324
+ <A, B, C, D, E, F, G, H, I extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>>(
1325
+ a: (
1326
+ _: Effect.Effect<
1327
+ AEff,
1328
+ EEff,
1329
+ REff
1330
+ >,
1331
+ arg: ArgForCombinator<Arg>,
1332
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1333
+ ) => A,
1334
+ b: (
1335
+ _: A,
1336
+ arg: ArgForCombinator<Arg>,
1337
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1338
+ ) => B,
1339
+ c: (
1340
+ _: B,
1341
+ arg: ArgForCombinator<Arg>,
1342
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1343
+ ) => C,
1344
+ d: (
1345
+ _: C,
1346
+ arg: ArgForCombinator<Arg>,
1347
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1348
+ ) => D,
1349
+ e: (
1350
+ _: D,
1351
+ arg: ArgForCombinator<Arg>,
1352
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1353
+ ) => E,
1354
+ f: (
1355
+ _: E,
1356
+ arg: ArgForCombinator<Arg>,
1357
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1358
+ ) => F,
1359
+ g: (
1360
+ _: F,
1361
+ arg: ArgForCombinator<Arg>,
1362
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1363
+ ) => G,
1364
+ h: (
1365
+ _: G,
1366
+ arg: ArgForCombinator<Arg>,
1367
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1368
+ ) => H,
1369
+ i: (
1370
+ _: H,
1371
+ arg: ArgForCombinator<Arg>,
1372
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1373
+ ) => I
1374
+ ): CommandOutHelper<Arg, I, Id, I18nKey, State>
1375
+ }
1376
+
1377
+ export type NonGenWrap<
1378
+ RT,
1379
+ Id extends string,
1380
+ I18nKey extends string,
1381
+ Arg,
1382
+ AEff,
1383
+ EEff,
1384
+ REff,
1385
+ State extends IntlRecord | undefined
1386
+ > = {
1387
+ (): Exclude<REff, RT> extends never ? CommandOutHelper<Arg, Effect.Effect<AEff, EEff, REff>, Id, I18nKey, State>
1388
+ : MissingDependencies<RT, REff> & {}
1389
+ <
1390
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1391
+ Arg
1392
+ >(
1393
+ a: (
1394
+ _: Effect.Effect<
1395
+ AEff,
1396
+ EEff,
1397
+ REff
1398
+ >,
1399
+ arg: ArgForCombinator<Arg>,
1400
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1401
+ ) => Eff
1402
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
1403
+ <
1404
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1405
+ B,
1406
+ Arg
1407
+ >(
1408
+ a: (
1409
+ _: Effect.Effect<
1410
+ AEff,
1411
+ EEff,
1412
+ REff
1413
+ >,
1414
+ arg: ArgForCombinator<Arg>,
1415
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1416
+ ) => B,
1417
+ b: (
1418
+ _: B,
1419
+ arg: ArgForCombinator<Arg>,
1420
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1421
+ ) => Eff
1422
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
1423
+ <
1424
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1425
+ B,
1426
+ C,
1427
+ Arg
1428
+ >(
1429
+ a: (
1430
+ _: Effect.Effect<
1431
+ AEff,
1432
+ EEff,
1433
+ REff
1434
+ >,
1435
+ arg: ArgForCombinator<Arg>,
1436
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1437
+ ) => B,
1438
+ b: (
1439
+ _: B,
1440
+ arg: ArgForCombinator<Arg>,
1441
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1442
+ ) => C,
1443
+ c: (
1444
+ _: C,
1445
+ arg: ArgForCombinator<Arg>,
1446
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1447
+ ) => Eff
1448
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
1449
+ <
1450
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1451
+ B,
1452
+ C,
1453
+ D,
1454
+ Arg
1455
+ >(
1456
+ a: (
1457
+ _: Effect.Effect<
1458
+ AEff,
1459
+ EEff,
1460
+ REff
1461
+ >,
1462
+ arg: ArgForCombinator<Arg>,
1463
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1464
+ ) => B,
1465
+ b: (
1466
+ _: B,
1467
+ arg: ArgForCombinator<Arg>,
1468
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1469
+ ) => C,
1470
+ c: (
1471
+ _: C,
1472
+ arg: ArgForCombinator<Arg>,
1473
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1474
+ ) => D,
1475
+ d: (
1476
+ _: D,
1477
+ arg: ArgForCombinator<Arg>,
1478
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1479
+ ) => Eff
1480
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
1481
+ <
1482
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1483
+ B,
1484
+ C,
1485
+ D,
1486
+ E,
1487
+ Arg
1488
+ >(
1489
+ a: (
1490
+ _: Effect.Effect<
1491
+ AEff,
1492
+ EEff,
1493
+ REff
1494
+ >,
1495
+ arg: ArgForCombinator<Arg>,
1496
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1497
+ ) => B,
1498
+ b: (
1499
+ _: B,
1500
+ arg: ArgForCombinator<Arg>,
1501
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1502
+ ) => C,
1503
+ c: (
1504
+ _: C,
1505
+ arg: ArgForCombinator<Arg>,
1506
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1507
+ ) => D,
1508
+ d: (
1509
+ _: D,
1510
+ arg: ArgForCombinator<Arg>,
1511
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1512
+ ) => E,
1513
+ e: (
1514
+ _: E,
1515
+ arg: ArgForCombinator<Arg>,
1516
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1517
+ ) => Eff
1518
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
1519
+ <
1520
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1521
+ B,
1522
+ C,
1523
+ D,
1524
+ E,
1525
+ F,
1526
+ Arg
1527
+ >(
1528
+ a: (
1529
+ _: Effect.Effect<
1530
+ AEff,
1531
+ EEff,
1532
+ REff
1533
+ >,
1534
+ arg: ArgForCombinator<Arg>,
1535
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1536
+ ) => B,
1537
+ b: (
1538
+ _: B,
1539
+ arg: ArgForCombinator<Arg>,
1540
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1541
+ ) => C,
1542
+ c: (
1543
+ _: C,
1544
+ arg: ArgForCombinator<Arg>,
1545
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1546
+ ) => D,
1547
+ d: (
1548
+ _: D,
1549
+ arg: ArgForCombinator<Arg>,
1550
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1551
+ ) => E,
1552
+ e: (
1553
+ _: E,
1554
+ arg: ArgForCombinator<Arg>,
1555
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1556
+ ) => F,
1557
+ f: (
1558
+ _: F,
1559
+ arg: ArgForCombinator<Arg>,
1560
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1561
+ ) => Eff
1562
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
1563
+ <
1564
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1565
+ B,
1566
+ C,
1567
+ D,
1568
+ E,
1569
+ F,
1570
+ G,
1571
+ Arg
1572
+ >(
1573
+ a: (
1574
+ _: Effect.Effect<
1575
+ AEff,
1576
+ EEff,
1577
+ REff
1578
+ >,
1579
+ arg: ArgForCombinator<Arg>,
1580
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1581
+ ) => B,
1582
+ b: (
1583
+ _: B,
1584
+ arg: ArgForCombinator<Arg>,
1585
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1586
+ ) => C,
1587
+ c: (
1588
+ _: C,
1589
+ arg: ArgForCombinator<Arg>,
1590
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1591
+ ) => D,
1592
+ d: (
1593
+ _: D,
1594
+ arg: ArgForCombinator<Arg>,
1595
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1596
+ ) => E,
1597
+ e: (
1598
+ _: E,
1599
+ arg: ArgForCombinator<Arg>,
1600
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1601
+ ) => F,
1602
+ f: (
1603
+ _: F,
1604
+ arg: ArgForCombinator<Arg>,
1605
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1606
+ ) => G,
1607
+ g: (
1608
+ _: G,
1609
+ arg: ArgForCombinator<Arg>,
1610
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1611
+ ) => Eff
1612
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
1613
+ <
1614
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1615
+ B,
1616
+ C,
1617
+ D,
1618
+ E,
1619
+ F,
1620
+ G,
1621
+ H,
1622
+ Arg
1623
+ >(
1624
+ a: (
1625
+ _: Effect.Effect<
1626
+ AEff,
1627
+ EEff,
1628
+ REff
1629
+ >,
1630
+ arg: ArgForCombinator<Arg>,
1631
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1632
+ ) => B,
1633
+ b: (
1634
+ _: B,
1635
+ arg: ArgForCombinator<Arg>,
1636
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1637
+ ) => C,
1638
+ c: (
1639
+ _: C,
1640
+ arg: ArgForCombinator<Arg>,
1641
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1642
+ ) => D,
1643
+ d: (
1644
+ _: D,
1645
+ arg: ArgForCombinator<Arg>,
1646
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1647
+ ) => E,
1648
+ e: (
1649
+ _: E,
1650
+ arg: ArgForCombinator<Arg>,
1651
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1652
+ ) => F,
1653
+ f: (
1654
+ _: F,
1655
+ arg: ArgForCombinator<Arg>,
1656
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1657
+ ) => G,
1658
+ g: (
1659
+ _: G,
1660
+ arg: ArgForCombinator<Arg>,
1661
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1662
+ ) => H,
1663
+ h: (
1664
+ _: H,
1665
+ arg: ArgForCombinator<Arg>,
1666
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1667
+ ) => Eff
1668
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
1669
+ <
1670
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1671
+ B,
1672
+ C,
1673
+ D,
1674
+ E,
1675
+ F,
1676
+ G,
1677
+ H,
1678
+ I,
1679
+ Arg
1680
+ >(
1681
+ a: (
1682
+ _: Effect.Effect<
1683
+ AEff,
1684
+ EEff,
1685
+ REff
1686
+ >,
1687
+ arg: ArgForCombinator<Arg>,
1688
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1689
+ ) => B,
1690
+ b: (
1691
+ _: B,
1692
+ arg: ArgForCombinator<Arg>,
1693
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1694
+ ) => C,
1695
+ c: (
1696
+ _: C,
1697
+ arg: ArgForCombinator<Arg>,
1698
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1699
+ ) => D,
1700
+ d: (
1701
+ _: D,
1702
+ arg: ArgForCombinator<Arg>,
1703
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1704
+ ) => E,
1705
+ e: (
1706
+ _: E,
1707
+ arg: ArgForCombinator<Arg>,
1708
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1709
+ ) => F,
1710
+ f: (
1711
+ _: F,
1712
+ arg: ArgForCombinator<Arg>,
1713
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1714
+ ) => G,
1715
+ g: (
1716
+ _: G,
1717
+ arg: ArgForCombinator<Arg>,
1718
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1719
+ ) => H,
1720
+ h: (
1721
+ _: H,
1722
+ arg: ArgForCombinator<Arg>,
1723
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1724
+ ) => I,
1725
+ i: (
1726
+ _: H,
1727
+ arg: ArgForCombinator<Arg>,
1728
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1729
+ ) => Eff
1730
+ ): CommandOutHelper<Arg, Eff, Id, I18nKey, State>
1731
+ }
1732
+
1733
+ /**
1734
+ * Type for `streamFn` — generator overload where the body yields Effects and returns a `Stream`.
1735
+ * `waiting` stays `true` while the stream is running, and updates the `result` ref per emitted value.
1736
+ */
1737
+ export type StreamGen<RT, Id extends string, I18nKey extends string, State extends IntlRecord | undefined> = {
1738
+ <
1739
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1740
+ SA,
1741
+ SE,
1742
+ SR,
1743
+ Arg = void
1744
+ >(
1745
+ body: (
1746
+ arg: Arg,
1747
+ ctx: CommandContextLocal2<Id, I18nKey, State>
1748
+ ) => Generator<Eff, Stream.Stream<SA, SE, SR>, never>
1749
+ ): CommandOut<
1750
+ Arg,
1751
+ SA,
1752
+ | SE
1753
+ | ([Eff] extends [never] ? never
1754
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
1755
+ : never),
1756
+ | SR
1757
+ | ([Eff] extends [never] ? never
1758
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
1759
+ : never),
1760
+ Id,
1761
+ I18nKey,
1762
+ State
1763
+ >
1764
+ <
1765
+ Eff extends Effect.Effect<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1766
+ SA,
1767
+ SE,
1768
+ SR,
1769
+ B,
1770
+ Arg = void
1771
+ >(
1772
+ body: (
1773
+ arg: Arg,
1774
+ ctx: CommandContextLocal2<Id, I18nKey, State>
1775
+ ) => Generator<Eff, Stream.Stream<SA, SE, SR>, never>,
1776
+ a: (
1777
+ _: Effect.Effect<
1778
+ Stream.Stream<SA, SE, SR>,
1779
+ ([Eff] extends [never] ? never
1780
+ : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E
1781
+ : never),
1782
+ ([Eff] extends [never] ? never
1783
+ : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R
1784
+ : never)
1785
+ >,
1786
+ arg: ArgForCombinator<Arg>,
1787
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1788
+ ) => B
1789
+ ): B extends Stream.Stream<infer SA2, infer SE2, infer SR2> ? CommandOut<Arg, SA2, SE2, SR2, Id, I18nKey, State>
1790
+ : B extends Effect.Effect<Stream.Stream<infer SA2, infer SE2, infer SR2>, infer EE2, infer ER2>
1791
+ ? CommandOut<Arg, SA2, SE2 | EE2, SR2 | ER2, Id, I18nKey, State>
1792
+ : never
1793
+ }
1794
+
1795
+ /**
1796
+ * Type for `streamFn` — non-generator overload accepting a function that returns a `Stream` directly,
1797
+ * or an `Effect` that resolves to a `Stream`.
1798
+ */
1799
+ export type NonGenStream<RT, Id extends string, I18nKey extends string, State extends IntlRecord | undefined> = {
1800
+ <
1801
+ SA,
1802
+ SE,
1803
+ SR extends RT | CommandContext | `Commander.Command.${Id}.state`,
1804
+ Arg = void
1805
+ >(
1806
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Stream.Stream<SA, SE, SR>
1807
+ ): CommandOut<Arg, SA, SE, SR, Id, I18nKey, State>
1808
+ <
1809
+ SA,
1810
+ SE,
1811
+ SR,
1812
+ A extends Stream.Stream<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>,
1813
+ Arg = void
1814
+ >(
1815
+ body: (arg: Arg, ctx: CommandContextLocal2<Id, I18nKey, State>) => Stream.Stream<SA, SE, SR>,
1816
+ a: (
1817
+ _: Stream.Stream<SA, SE, SR>,
1818
+ arg: ArgForCombinator<Arg>,
1819
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1820
+ ) => A
1821
+ ): CommandOut<Arg, Stream.Success<A>, Stream.Error<A>, Stream.Services<A>, Id, I18nKey, State>
1822
+ <
1823
+ SA,
1824
+ SE,
1825
+ SR,
1826
+ EE,
1827
+ ER extends RT | CommandContext | `Commander.Command.${Id}.state`,
1828
+ Arg = void
1829
+ >(
1830
+ body: (
1831
+ arg: Arg,
1832
+ ctx: CommandContextLocal2<Id, I18nKey, State>
1833
+ ) => Effect.Effect<Stream.Stream<SA, SE, SR>, EE, ER>
1834
+ ): CommandOut<Arg, SA, SE | EE, SR | ER, Id, I18nKey, State>
1835
+ <
1836
+ SA,
1837
+ SE,
1838
+ SR,
1839
+ EE,
1840
+ ER,
1841
+ B,
1842
+ Arg = void
1843
+ >(
1844
+ body: (
1845
+ arg: Arg,
1846
+ ctx: CommandContextLocal2<Id, I18nKey, State>
1847
+ ) => Effect.Effect<Stream.Stream<SA, SE, SR>, EE, ER>,
1848
+ a: (
1849
+ _: Effect.Effect<Stream.Stream<SA, SE, SR>, EE, ER>,
1850
+ arg: ArgForCombinator<Arg>,
1851
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1852
+ ) => B
1853
+ ): B extends Stream.Stream<infer SA2, infer SE2, infer SR2> ? CommandOut<Arg, SA2, SE2, SR2, Id, I18nKey, State>
1854
+ : B extends Effect.Effect<Stream.Stream<infer SA2, infer SE2, infer SR2>, infer EE2, infer ER2>
1855
+ ? CommandOut<Arg, SA2, SE2 | EE2, SR2 | ER2, Id, I18nKey, State>
1856
+ : never
1857
+ }
1858
+
1859
+ /**
1860
+ * Type returned by `mutate.wrap` on a stream handler — analogous to `CommanderWrap` but for streams.
1861
+ * The handler is pre-baked (from the stream mutation), so this is called with only optional combinators.
1862
+ */
1863
+ export type StreamerWrap<
1864
+ RT,
1865
+ Id extends string,
1866
+ I18nKey extends string,
1867
+ State extends IntlRecord | undefined,
1868
+ Arg,
1869
+ SA,
1870
+ SE,
1871
+ SR
1872
+ > =
1873
+ & CommandContextLocal<Id, I18nKey>
1874
+ & { readonly state: Context.Service<`Commander.Command.${Id}.state`, State> }
1875
+ & {
1876
+ (): Exclude<SR, RT> extends never ? CommandOut<Arg, SA, SE, SR, Id, I18nKey, State>
1877
+ : MissingDependencies<RT, SR> & {}
1878
+ <A extends Stream.Stream<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>>(
1879
+ a: (
1880
+ _: Stream.Stream<SA, SE, SR>,
1881
+ arg: ArgForCombinator<Arg>,
1882
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1883
+ ) => A
1884
+ ): CommandOut<Arg, Stream.Success<A>, Stream.Error<A>, Stream.Services<A>, Id, I18nKey, State>
1885
+ <
1886
+ B,
1887
+ A extends Stream.Stream<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>
1888
+ >(
1889
+ a: (
1890
+ _: Stream.Stream<SA, SE, SR>,
1891
+ arg: ArgForCombinator<Arg>,
1892
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1893
+ ) => B,
1894
+ b: (
1895
+ _: B,
1896
+ arg: ArgForCombinator<Arg>,
1897
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1898
+ ) => A
1899
+ ): CommandOut<Arg, Stream.Success<A>, Stream.Error<A>, Stream.Services<A>, Id, I18nKey, State>
1900
+ <
1901
+ B,
1902
+ C,
1903
+ A extends Stream.Stream<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>
1904
+ >(
1905
+ a: (
1906
+ _: Stream.Stream<SA, SE, SR>,
1907
+ arg: ArgForCombinator<Arg>,
1908
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1909
+ ) => B,
1910
+ b: (
1911
+ _: B,
1912
+ arg: ArgForCombinator<Arg>,
1913
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1914
+ ) => C,
1915
+ c: (
1916
+ _: C,
1917
+ arg: ArgForCombinator<Arg>,
1918
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1919
+ ) => A
1920
+ ): CommandOut<Arg, Stream.Success<A>, Stream.Error<A>, Stream.Services<A>, Id, I18nKey, State>
1921
+ <
1922
+ B,
1923
+ C,
1924
+ D,
1925
+ A extends Stream.Stream<any, any, RT | CommandContext | `Commander.Command.${Id}.state`>
1926
+ >(
1927
+ a: (
1928
+ _: Stream.Stream<SA, SE, SR>,
1929
+ arg: ArgForCombinator<Arg>,
1930
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1931
+ ) => B,
1932
+ b: (
1933
+ _: B,
1934
+ arg: ArgForCombinator<Arg>,
1935
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1936
+ ) => C,
1937
+ c: (
1938
+ _: C,
1939
+ arg: ArgForCombinator<Arg>,
1940
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1941
+ ) => D,
1942
+ d: (
1943
+ _: D,
1944
+ arg: ArgForCombinator<Arg>,
1945
+ ctx: CommandContextLocal2<NoInfer<Id>, NoInfer<I18nKey>, NoInfer<State>>
1946
+ ) => A
1947
+ ): CommandOut<Arg, Stream.Success<A>, Stream.Error<A>, Stream.Services<A>, Id, I18nKey, State>
1948
+ }
1949
+ }
1950
+
1951
+ type ErrorRenderer<E, Args extends readonly any[]> = (e: E, action: string, ...args: Args) => string | undefined
1952
+
1953
+ type RegisteredErrorRenderer<A> = {
1954
+ guard: Refinement<unknown, A>
1955
+ render: (guarded: A) => string | undefined
1956
+ }
1957
+
1958
+ export class CommanderErrorRenderers extends Context.Reference("Commander.ErrorRenderers", {
1959
+ defaultValue: () => [] as RegisteredErrorRenderer<any>[]
1960
+ }) {}
1961
+
1962
+ export const makeRegisteredErrorRenderer = <A>(
1963
+ guard: Predicate.Refinement<unknown, A>,
1964
+ render: (guarded: A) => string | undefined
1965
+ ): RegisteredErrorRenderer<A> => ({
1966
+ guard,
1967
+ render
1968
+ })
1969
+
1970
+ const renderErrorMaker = Effect.gen(function*() {
1971
+ const { intl } = yield* I18n
1972
+ const registeredRenderers = yield* CommanderErrorRenderers
1973
+ return (
1974
+ <E, Args extends readonly any[]>(action: string, errorRenderer?: ErrorRenderer<E, Args>) =>
1975
+ (e: E, ...args: Args): string => {
1976
+ if (errorRenderer) {
1977
+ const m = errorRenderer(e, action, ...args)
1978
+ if (m !== undefined) {
1979
+ return m
1980
+ }
1981
+ }
1982
+ for (const entry of registeredRenderers) {
1983
+ if (!entry.guard(e)) {
1984
+ continue
1985
+ }
1986
+ const m = entry.render(e)
1987
+ if (m !== undefined) {
1988
+ return m
1989
+ }
1990
+ }
1991
+ if (!S.is(SupportedErrors)(e) && !S.isSchemaError(e)) {
1992
+ if (typeof e === "object" && e !== null) {
1993
+ if ("message" in e) {
1994
+ return `${e.message}`
1995
+ }
1996
+ if ("_tag" in e) {
1997
+ return `${e._tag}`
1998
+ }
1999
+ }
2000
+ return ""
2001
+ }
2002
+ const e2: SupportedErrors | S.SchemaError = e
2003
+ if (e2._tag === "NotFoundError") {
2004
+ return intl.formatMessage({ id: "handle.not_found" }, { type: e2.type, id: String(e2.id) })
2005
+ }
2006
+ if (e2._tag === "SchemaError") {
2007
+ console.warn(e2.toString())
2008
+ return intl.formatMessage({ id: "validation.failed" })
2009
+ }
2010
+ return e2.message ?? e2._tag ?? e2
2011
+ }
2012
+ )
2013
+ })
2014
+
2015
+ const defaultFailureMessageHandler = <E, Args extends Array<unknown>, AME, AMR>(
2016
+ actionMaker:
2017
+ | string
2018
+ | ((o: Option.Option<E>, ...args: Args) => string)
2019
+ | ((o: Option.Option<E>, ...args: Args) => Effect.Effect<string, AME, AMR>),
2020
+ errorRenderer?: ErrorRenderer<E, Args>
2021
+ ) =>
2022
+ Effect.fnUntraced(function*(o: Option.Option<E>, ...args: Args) {
2023
+ const action = yield* wrapEffect(actionMaker)(o, ...args)
2024
+ const { intl } = yield* I18n
2025
+ const renderError = yield* renderErrorMaker
2026
+
2027
+ return Option.match(o, {
2028
+ onNone: () =>
2029
+ intl.formatMessage(
2030
+ { id: "handle.unexpected_error2" },
2031
+ {
2032
+ action,
2033
+ error: "" // TODO consider again Cause.pretty(cause), // will be reported to Sentry/Otel anyway.. and we shouldn't bother users with error dumps?
2034
+ }
2035
+ ),
2036
+ onSome: (e) => {
2037
+ const rendered = renderError(action, errorRenderer)(e, ...args)
2038
+ return {
2039
+ level: "warn" as const,
2040
+ message: `${
2041
+ intl.formatMessage(
2042
+ { id: "handle.with_errors" },
2043
+ { action }
2044
+ )
2045
+ }:\n` + rendered
2046
+ }
2047
+ }
2048
+ })
2049
+ })
2050
+
2051
+ export const CommanderStatic = {
2052
+ accessArgs: <In, Out, Arg2, Arg = void>(
2053
+ cb: (a: NoInfer<Arg>, b: NoInfer<Arg2>) => (self: NoInfer<In>) => Out
2054
+ ) =>
2055
+ (self: In, arg: Arg, arg2: Arg2) => cb(arg, arg2)(self),
2056
+
2057
+ /**
2058
+ * Stream pipe operator that maps each emitted value to a `Progress` entry and updates the
2059
+ * command's reactive `progress` ref via the `CommandProgress` service.
2060
+ *
2061
+ * The mapper receives an `AsyncResult<A, E>` (each emitted value wrapped as
2062
+ * `AsyncResult.success(value, { waiting: true })`), matching the same shape used by
2063
+ * `CommandButton`'s `:progress-map` prop.
2064
+ *
2065
+ * Designed to be used inside a `streamFn` handler (either directly with `.pipe()`, or as
2066
+ * a combinator argument):
2067
+ *
2068
+ * @example
2069
+ * ```ts
2070
+ * // Inside the handler body:
2071
+ * Command.streamFn("exportData")(function*(arg, ctx) {
2072
+ * return makeExportStream(arg.id).pipe(
2073
+ * Command.mapProgress((r) =>
2074
+ * AsyncResult.isSuccess(r) && r.value._tag === "OperationProgress"
2075
+ * ? { text: `${r.value.completed}/${r.value.total}`, percentage: r.value.completed / r.value.total * 100 }
2076
+ * : undefined
2077
+ * )
2078
+ * )
2079
+ * })
2080
+ *
2081
+ * // Or as a stream combinator argument:
2082
+ * Command.streamFn("exportData")(
2083
+ * function*(arg, ctx) { return makeExportStream(arg.id) },
2084
+ * (s) => s.pipe(Command.mapProgress((r) => AsyncResult.isSuccess(r) && r.value._tag === "OperationProgress" ? { text: `${r.value.completed}/${r.value.total}` } : undefined))
2085
+ * )
2086
+ * ```
2087
+ */
2088
+ mapProgress:
2089
+ <A, E>(fn: (result: AsyncResult.AsyncResult<A, E>) => Progress | undefined) =>
2090
+ <R>(stream: Stream.Stream<A, E, R>): Stream.Stream<A, E, R> =>
2091
+ stream.pipe(
2092
+ Stream.tap((v) => {
2093
+ const p = fn(AsyncResult.success(v, { waiting: true }))
2094
+ return p !== undefined ? CommandProgress.use((s) => s.update(p)) : Effect.void
2095
+ })
2096
+ ),
2097
+
2098
+ /**
2099
+ * Imperatively push a progress update from inside a `streamFn` handler.
2100
+ * Requires `CommandProgress` to be in context — provided automatically for all `streamFn` streams.
2101
+ *
2102
+ * @example
2103
+ * ```ts
2104
+ * // In a streamFn handler:
2105
+ * stream.pipe(
2106
+ * Stream.tap((event) =>
2107
+ * event._tag === "OperationProgress"
2108
+ * ? Command.updateProgress({ text: `${event.completed}/${event.total}`, percentage: event.completed / event.total * 100 })
2109
+ * : Effect.void
2110
+ * )
2111
+ * )
2112
+ * ```
2113
+ */
2114
+ updateProgress: (progress: Progress | undefined): Effect.Effect<void> =>
2115
+ CommandProgress.use((s) => s.update(progress)),
2116
+
2117
+ /** Version of @see confirmOrInterrupt that automatically includes the action name in the default messages */
2118
+ confirmOrInterrupt: Effect.fnUntraced(function*(
2119
+ message?: string
2120
+ ) {
2121
+ const context = yield* CommandContext
2122
+ const { intl } = yield* I18n
2123
+
2124
+ yield* Confirm.confirmOrInterrupt(
2125
+ message
2126
+ ?? intl.formatMessage(
2127
+ { id: "handle.confirmation" },
2128
+ { action: context.action }
2129
+ )
2130
+ )
2131
+ }),
2132
+ /** Version of @see confirm that automatically includes the action name in the default messages */
2133
+ confirm: Effect.fnUntraced(function*(
2134
+ message?: string
2135
+ ) {
2136
+ const context = yield* CommandContext
2137
+ const { intl } = yield* I18n
2138
+ return yield* Confirm.confirm(
2139
+ message
2140
+ ?? intl.formatMessage(
2141
+ { id: "handle.confirmation" },
2142
+ { action: context.action }
2143
+ )
2144
+ )
2145
+ }),
2146
+ updateAction:
2147
+ <Args extends Array<unknown>>(update: (currentActionId: string, ...args: Args) => string) =>
2148
+ <A, E, R>(_: Effect.Effect<A, E, R>, ...input: Args) =>
2149
+ Effect.updateService(
2150
+ _,
2151
+ CommandContext,
2152
+ (c) => ({ ...c, action: update(c.action, ...input) })
2153
+ ),
2154
+ registerErrorRenderer: <A>(
2155
+ guard: Predicate.Refinement<unknown, A>,
2156
+ render: (guarded: A) => string | undefined
2157
+ ) =>
2158
+ Layer.effect(
2159
+ CommanderErrorRenderers,
2160
+ Effect.gen(function*() {
2161
+ const current = yield* CommanderErrorRenderers
2162
+ return [...current, makeRegisteredErrorRenderer(guard, render)]
2163
+ })
2164
+ ),
2165
+ defaultFailureMessageHandler,
2166
+ renderError: renderErrorMaker,
2167
+ /**
2168
+ * Version of withDefaultToast that automatically includes the action name in the default messages and uses intl.
2169
+ * uses the Command id as i18n namespace. `action.{id}` is the main action name,
2170
+ * and `action.{id}.waiting`, `action.{id}.success`, `action.{id}.failure` can be used to override the default messages for the respective states.
2171
+ *
2172
+ * the computed `state` provided to the Command can be used for interpolation in the i18n messages. (the state is captured at the start of each command execution and remains stable throughout)
2173
+ *
2174
+ * Note: if you provide `onWaiting` or `onSuccess` as `null`, no toast will be shown for that state.
2175
+ * If you provide a string or function, it will be used instead of the i18n message.
2176
+ * If you provide an `errorRenderer`, it will be used to render errors in the failure message.
2177
+ */
2178
+ withDefaultToast: <A, E, R, Args extends Array<unknown>>(
2179
+ options?: {
2180
+ /**
2181
+ * if true, previous toasts with this key will be replaced
2182
+ */
2183
+ stableToastId?:
2184
+ | undefined
2185
+ | true
2186
+ | string
2187
+ | ((id: string, arg: NoInfer<Args>[0], ctx: NoInfer<Args>[1]) => true | string | undefined)
2188
+ errorRenderer?: (e: E, action: string, arg: NoInfer<Args>[0], ctx: NoInfer<Args>[1]) => string | undefined
2189
+ showSpanInfo?: false
2190
+ onWaiting?:
2191
+ | null
2192
+ | undefined
2193
+ | string
2194
+ | ((id: string, arg: NoInfer<Args>[0], ctx: NoInfer<Args>[1]) => string | null | undefined)
2195
+ onSuccess?:
2196
+ | null
2197
+ | undefined
2198
+ | string
2199
+ | ((a: A, action: string, arg: NoInfer<Args>[0], ctx: NoInfer<Args>[1]) => string | null | undefined)
2200
+ }
2201
+ ) =>
2202
+ Effect.fnUntraced(function*(
2203
+ self: Effect.Effect<A, E, R>,
2204
+ ...args: Args
2205
+ ) {
2206
+ const cc = yield* CommandContext
2207
+ const { intl } = yield* I18n
2208
+ const withToast = yield* WithToast
2209
+ const customWaiting = cc.namespaced("waiting")
2210
+ const hasCustomWaiting = !!intl.messages[customWaiting]
2211
+ const customSuccess = cc.namespaced("success")
2212
+ const hasCustomSuccess = !!intl.messages[customSuccess]
2213
+ const customFailure = cc.namespaced("failure")
2214
+ const hasCustomFailure = !!intl.messages[customFailure]
2215
+ const stableToastId = options?.stableToastId
2216
+ ? typeof options.stableToastId === "string"
2217
+ ? options.stableToastId
2218
+ : typeof options.stableToastId === "boolean"
2219
+ ? cc.id
2220
+ : typeof options.stableToastId === "function"
2221
+ ? (...args: Args) => {
2222
+ const r = (options.stableToastId as any)(cc.id, ...args)
2223
+ if (typeof r === "string") return r
2224
+ if (r === true) return cc.id
2225
+ return undefined
2226
+ }
2227
+ : undefined
2228
+ : undefined
2229
+ return yield* self.pipe(
2230
+ (_) =>
2231
+ withToast<A, E, Args, R, never, never, I18n>({
2232
+ onWaiting: options?.onWaiting === null ? null : hasCustomWaiting
2233
+ ? intl.formatMessage({
2234
+ id: customWaiting
2235
+ }, cc.state)
2236
+ : intl.formatMessage(
2237
+ { id: "handle.waiting" },
2238
+ { action: cc.action }
2239
+ ),
2240
+ onSuccess: options?.onSuccess === null
2241
+ ? null
2242
+ : (_a, ..._args) =>
2243
+ hasCustomSuccess
2244
+ ? intl.formatMessage(
2245
+ { id: customSuccess },
2246
+ cc.state
2247
+ )
2248
+ : intl.formatMessage({ id: "handle.success" }, { action: cc.action }),
2249
+ onFailure: defaultFailureMessageHandler(
2250
+ hasCustomFailure ? intl.formatMessage({ id: customFailure }, cc.state) : cc.action,
2251
+ options?.errorRenderer as ErrorRenderer<E, Args> | undefined
2252
+ ),
2253
+ stableToastId,
2254
+ groupId: cc.id,
2255
+ ...options?.showSpanInfo === false ? { showSpanInfo: options.showSpanInfo } : {}
2256
+ })(_, ...args)
2257
+ )
2258
+ }),
2259
+
2260
+ /**
2261
+ * Stream-aware version of `withDefaultToast`. Use this as a combinator inside `streamFn`
2262
+ * (or anywhere a `Stream` needs toast lifecycle handling) instead of `withDefaultToast`.
2263
+ *
2264
+ * Unlike `withDefaultToast` (which only wraps the initial `Effect`), this combinator:
2265
+ * - Shows the "waiting" toast **before** the stream starts
2266
+ * - Updates the waiting toast with progress text when `progress` is set and a new element arrives
2267
+ * - Shows the "success" toast only **after** the stream drains fully without error
2268
+ * - Shows the "failure" toast if the stream errors or fails
2269
+ *
2270
+ * Accepts either a `Stream<A, E, R>` or an `Effect<Stream<A, E, R>, EE, ER>` as input,
2271
+ * so it works in both the `NonGenStream` and `StreamGen` overloads of `streamFn`.
2272
+ *
2273
+ * @example
2274
+ * ```ts
2275
+ * Command.streamFn("exportData")(
2276
+ * function*(arg, ctx) { return makeExportStream(arg.id) },
2277
+ * Command.withDefaultToastStream({
2278
+ * progress: (r) =>
2279
+ * AsyncResult.isSuccess(r) && r.value._tag === "OperationProgress"
2280
+ * ? { text: `${r.value.completed}/${r.value.total}`, percentage: r.value.completed / r.value.total * 100 }
2281
+ * : undefined
2282
+ * })
2283
+ * )
2284
+ * ```
2285
+ */
2286
+ withDefaultToastStream: <A, E, R, Args extends Array<unknown>>(
2287
+ options?: {
2288
+ stableToastId?:
2289
+ | undefined
2290
+ | true
2291
+ | string
2292
+ | ((id: string, arg: NoInfer<Args>[0], ctx: NoInfer<Args>[1]) => true | string | undefined)
2293
+ errorRenderer?: (e: E, action: string, arg: NoInfer<Args>[0], ctx: NoInfer<Args>[1]) => string | undefined
2294
+ showSpanInfo?: false
2295
+ onWaiting?:
2296
+ | null
2297
+ | undefined
2298
+ | string
2299
+ | ((id: string, arg: NoInfer<Args>[0], ctx: NoInfer<Args>[1]) => string | null | undefined)
2300
+ onSuccess?:
2301
+ | null
2302
+ | undefined
2303
+ | string
2304
+ | ((a: A, action: string, arg: NoInfer<Args>[0], ctx: NoInfer<Args>[1]) => string | null | undefined)
2305
+ /** Map each stream element to a progress label. When non-`undefined`, updates both the active waiting toast and the `CommandProgress` service (for CommandButton progress display). */
2306
+ progress?: (result: AsyncResult.AsyncResult<A, E>) => Progress | undefined
2307
+ }
2308
+ ) =>
2309
+ (
2310
+ self: Stream.Stream<A, E, R> | Effect.Effect<Stream.Stream<A, E, R>, any, any>,
2311
+ ...args: Args
2312
+ ): Stream.Stream<A, E, R | I18n | Toast | CommandContext> => {
2313
+ const rawStream: Stream.Stream<A, E, R> = Stream.isStream(self)
2314
+ ? self
2315
+ : Stream.unwrap(self)
2316
+
2317
+ return Stream.unwrap(Effect.gen(function*() {
2318
+ const cc = yield* CommandContext
2319
+ const { intl } = yield* I18n
2320
+ const toast = yield* Toast
2321
+
2322
+ const customWaiting = cc.namespaced("waiting")
2323
+ const hasCustomWaiting = !!intl.messages[customWaiting]
2324
+ const customSuccess = cc.namespaced("success")
2325
+ const hasCustomSuccess = !!intl.messages[customSuccess]
2326
+ const customFailure = cc.namespaced("failure")
2327
+ const hasCustomFailure = !!intl.messages[customFailure]
2328
+
2329
+ const stableToastId: string | undefined = options?.stableToastId
2330
+ ? typeof options.stableToastId === "string"
2331
+ ? options.stableToastId
2332
+ : typeof options.stableToastId === "boolean"
2333
+ ? cc.id
2334
+ : typeof options.stableToastId === "function"
2335
+ ? (() => {
2336
+ const r = (options.stableToastId as (...a: any[]) => true | string | undefined)(cc.id, ...args)
2337
+ if (typeof r === "string") return r
2338
+ if (r === true) return cc.id
2339
+ return undefined
2340
+ })()
2341
+ : undefined
2342
+ : undefined
2343
+
2344
+ const baseTimeout = 3_000
2345
+
2346
+ const waitingMsg: string | null = options?.onWaiting === null
2347
+ ? null
2348
+ : typeof options?.onWaiting === "string"
2349
+ ? options.onWaiting
2350
+ : typeof options?.onWaiting === "function"
2351
+ ? (options.onWaiting as (...a: any[]) => string | null | undefined)(cc.id, ...args) ?? null
2352
+ : hasCustomWaiting
2353
+ ? intl.formatMessage({ id: customWaiting }, cc.state)
2354
+ : intl.formatMessage({ id: "handle.waiting" }, { action: cc.action })
2355
+
2356
+ const toastId: string | number | undefined = waitingMsg === null
2357
+ ? stableToastId
2358
+ : stableToastId ?? `wait-${Math.random().toString(36).slice(2)}`
2359
+
2360
+ const requestId: string = yield* Effect.currentSpan.pipe(
2361
+ Effect.map((span) => span.traceId),
2362
+ Effect.orElseSucceed(() => S.StringId.make())
2363
+ )
2364
+ const meta = { groupId: cc.id, requestId }
2365
+
2366
+ if (waitingMsg !== null) {
2367
+ yield* toast.info(waitingMsg, { id: toastId!, timeout: Infinity, ...meta })
2368
+ }
2369
+
2370
+ const failureHandler = defaultFailureMessageHandler<E, [], never, never>(
2371
+ hasCustomFailure ? intl.formatMessage({ id: customFailure }, cc.state) : cc.action,
2372
+ options?.errorRenderer as ErrorRenderer<E, []> | undefined
2373
+ )
2374
+
2375
+ let lastValue: A | undefined = undefined
2376
+ let didFail = false
2377
+
2378
+ const composed = rawStream.pipe(
2379
+ Stream.tap((v) =>
2380
+ Effect.gen(function*() {
2381
+ lastValue = v
2382
+ if (options?.progress !== undefined) {
2383
+ const p = options.progress(AsyncResult.success(v, { waiting: true }))
2384
+ if (p !== undefined) {
2385
+ // Update CommandProgress so CommandButton progress indicator is also driven
2386
+ yield* CommandProgress.use((s) => s.update(p))
2387
+ if (toastId !== undefined) {
2388
+ const progressText = typeof p === "string" ? p : p.text
2389
+ const msg = waitingMsg ? `${waitingMsg}\n${progressText}` : progressText
2390
+ yield* toast.info(msg, { id: toastId, timeout: Infinity, ...meta })
2391
+ }
2392
+ }
2393
+ }
2394
+ })
2395
+ ),
2396
+ Stream.tapCause(Effect.fnUntraced(function*(cause) {
2397
+ didFail = true
2398
+ if (Cause.hasInterruptsOnly(cause)) {
2399
+ if (toastId !== undefined) yield* toast.dismiss(toastId)
2400
+ return
2401
+ }
2402
+
2403
+ const spanInfo = options?.showSpanInfo !== false
2404
+ ? yield* Effect.currentSpan.pipe(
2405
+ Effect.map((span) => `\nTrace: ${span.traceId}\nSpan: ${span.spanId}`),
2406
+ Effect.orElseSucceed(() => "")
2407
+ )
2408
+ : ""
2409
+
2410
+ const t = yield* failureHandler(Cause.findErrorOption(cause))
2411
+ const opts = { timeout: baseTimeout * 2, ...meta }
2412
+
2413
+ if (typeof t === "object") {
2414
+ const message = t.message + spanInfo
2415
+ yield* t.level === "warn"
2416
+ ? toast.warning(message, toastId !== undefined ? { ...opts, id: toastId } : opts)
2417
+ : toast.error(message, toastId !== undefined ? { ...opts, id: toastId } : opts)
2418
+ } else {
2419
+ yield* toast.error(t + spanInfo, toastId !== undefined ? { ...opts, id: toastId } : opts)
2420
+ }
2421
+ }, Effect.uninterruptible)),
2422
+ Stream.ensuring(Effect.suspend(() => {
2423
+ if (didFail) return Effect.void
2424
+
2425
+ if (options?.onSuccess === null) return Effect.void
2426
+
2427
+ const successMsg: string | null = typeof options?.onSuccess === "string"
2428
+ ? options.onSuccess
2429
+ : typeof options?.onSuccess === "function"
2430
+ ? (options.onSuccess as (...a: any[]) => string | null | undefined)(lastValue, cc.action, ...args) ?? null
2431
+ : hasCustomSuccess
2432
+ ? intl.formatMessage({ id: customSuccess }, cc.state)
2433
+ : intl.formatMessage({ id: "handle.success" }, { action: cc.action })
2434
+
2435
+ if (successMsg === null) return Effect.void
2436
+
2437
+ return toast.success(
2438
+ successMsg,
2439
+ toastId !== undefined
2440
+ ? { id: toastId, timeout: baseTimeout, ...meta }
2441
+ : { timeout: baseTimeout, ...meta }
2442
+ )
2443
+ }))
2444
+ )
2445
+
2446
+ return (toastId !== undefined
2447
+ ? composed.pipe(Stream.provideService(CurrentToastId, CurrentToastId.of({ toastId })))
2448
+ : composed) as unknown as Stream.Stream<A, E, R>
2449
+ }))
2450
+ },
2451
+
2452
+ /** borrowing the idea from Families in Effect Atom */
2453
+ family: <T extends object, Arg, ArgIn = Arg>(
2454
+ maker: (arg: Arg) => T,
2455
+ keyMaker?: (arg: ArgIn) => Arg
2456
+ ): (arg: ArgIn) => T => {
2457
+ const commands = MutableHashMap.empty<Arg, WeakRef<T>>()
2458
+ const registry = new FinalizationRegistry<Arg>((arg) => {
2459
+ MutableHashMap.remove(commands, arg)
2460
+ })
2461
+
2462
+ return (_k: ArgIn) => {
2463
+ const k = keyMaker ? keyMaker(_k) : _k as unknown as Arg
2464
+ // we want to compare structurally, unless custom equal/hash has been implemented
2465
+ const item = MutableHashMap.get(commands, k).pipe(Option.flatMap((r) => Option.fromNullishOr(r.deref())))
2466
+ if (item.value) {
2467
+ return item.value
2468
+ }
2469
+ const v = maker(k)
2470
+ MutableHashMap.set(commands, k, new WeakRef(v))
2471
+
2472
+ registry.register(v, k)
2473
+ return v
2474
+ }
2475
+ }
2476
+ }
2477
+
2478
+ const makeBaseInfo = <const Id extends string, const I18nKey extends string = Id>(
2479
+ id: Id,
2480
+ options?: Pick<FnOptionsInternal<I18nKey>, "i18nCustomKey">
2481
+ ) => {
2482
+ if (!id) throw new Error("must specify an id")
2483
+ const i18nKey: I18nKey = options?.i18nCustomKey ?? id as unknown as I18nKey
2484
+
2485
+ const namespace = `action.${i18nKey}` as const
2486
+
2487
+ const context = {
2488
+ id,
2489
+ i18nKey,
2490
+ namespace,
2491
+ namespaced: <const K extends string>(k: K) => `${namespace}.${k}` as const
2492
+ }
2493
+
2494
+ return context
2495
+ }
2496
+
2497
+ const waitState = ref<Record<string, number>>({})
2498
+ const registerWait = (id: string) => {
2499
+ // console.debug("register wait", id)
2500
+ waitState.value[id] = waitState.value[id] ? waitState.value[id] + 1 : 1
2501
+ }
2502
+ const unregisterWait = (id: string) => {
2503
+ // console.debug("unregister wait", id)
2504
+ if (waitState.value[id]) {
2505
+ waitState.value[id] = waitState.value[id] - 1
2506
+ if (waitState.value[id] <= 0) {
2507
+ delete waitState.value[id]
2508
+ }
2509
+ }
2510
+ }
2511
+
2512
+ const getStateValues = <
2513
+ const Id extends string,
2514
+ const I18nKey extends string,
2515
+ State extends IntlRecord | undefined
2516
+ >(
2517
+ options?: FnOptions<Id, I18nKey, State>
2518
+ ): ComputedRef<State> => {
2519
+ const state_ = options?.state
2520
+ const state = !state_ ? computed(() => undefined as State) : typeof state_ === "function"
2521
+ ? computed(state_)
2522
+ : state_
2523
+ return state
2524
+ }
2525
+
2526
+ // class preserves JSDoc throughout..
2527
+ export class CommanderImpl<RT, RTHooks> {
2528
+ private readonly rt: Context.Context<RT>
2529
+ private readonly intl: I18n
2530
+ private readonly hooks: Layer.Layer<RTHooks, never, RT>
2531
+
2532
+ constructor(
2533
+ rt: Context.Context<RT>,
2534
+ intl: I18n,
2535
+ hooks: Layer.Layer<RTHooks, never, RT>
2536
+ ) {
2537
+ this.rt = rt
2538
+ this.intl = intl
2539
+ this.hooks = hooks
2540
+ }
2541
+
2542
+ readonly makeContext = <const Id extends string, const I18nKey extends string = Id>(
2543
+ id: Id,
2544
+ options?: FnOptionsInternal<I18nKey>
2545
+ ) => {
2546
+ if (!id) throw new Error("must specify an id")
2547
+ const i18nKey: I18nKey = options?.i18nCustomKey ?? id as unknown as I18nKey
2548
+
2549
+ const namespace = `action.${i18nKey}` as const
2550
+
2551
+ // must remain stable through out single call
2552
+ const action = this.intl.formatMessage({
2553
+ id: namespace,
2554
+ defaultMessage: id
2555
+ }, { ...options?.state, _isLabel: false })
2556
+
2557
+ const label = this.intl.formatMessage({
2558
+ id: namespace,
2559
+ defaultMessage: id
2560
+ }, { ...options?.state, _isLabel: true })
2561
+
2562
+ const context = CommandContext.of({
2563
+ ...makeBaseInfo(id, options),
2564
+ action,
2565
+ label,
2566
+ state: options?.state
2567
+ })
2568
+
2569
+ return context
2570
+ }
2571
+
2572
+ readonly makeCommand = <
2573
+ const Id extends string,
2574
+ const State extends IntlRecord | undefined,
2575
+ const I18nKey extends string = Id
2576
+ >(
2577
+ id_: Id | { id: Id },
2578
+ options?: FnOptions<Id, I18nKey, State>,
2579
+ errorDef?: Error
2580
+ ) => {
2581
+ const id = typeof id_ === "string" ? id_ : id_.id
2582
+ const state = getStateValues(options)
2583
+
2584
+ return Object.assign(
2585
+ <Arg, A, E, R extends RT | RTHooks | CommandContext | `Commander.Command.${Id}.state`>(
2586
+ handler: (arg: Arg, ctx: Commander.CommandContextLocal2<Id, I18nKey, State>) => Effect.Effect<A, E, R>
2587
+ ) => {
2588
+ // we capture the definition stack here, so we can append it to later stack traces
2589
+ const limit = Error.stackTraceLimit
2590
+ Error.stackTraceLimit = 2
2591
+ const localErrorDef = new Error()
2592
+ Error.stackTraceLimit = limit
2593
+ if (!errorDef) {
2594
+ errorDef = localErrorDef
2595
+ }
2596
+
2597
+ const key = `Commander.Command.${id}.state` as const
2598
+ const stateTag = Context.Service<typeof key, State>(key)
2599
+
2600
+ const makeContext_ = () => this.makeContext(id, { ...options, state: state?.value })
2601
+ const initialContext = makeContext_()
2602
+ const context = computed(() => makeContext_())
2603
+ const action = computed(() => context.value.action)
2604
+ const label = computed(() => context.value.label)
2605
+
2606
+ const errorReporter = <A, E, R>(self: Effect.Effect<A, E, R>) =>
2607
+ self.pipe(
2608
+ Effect.tapCause(
2609
+ Effect.fnUntraced(function*(cause) {
2610
+ if (Cause.hasInterruptsOnly(cause)) {
2611
+ console.info(`Interrupted while trying to ${id}`)
2612
+ return
2613
+ }
2614
+
2615
+ const fail = Cause.findErrorOption(cause)
2616
+ if (Option.isSome(fail)) {
2617
+ // if (fail.value._tag === "SuppressErrors") {
2618
+ // console.info(
2619
+ // `Suppressed error trying to ${action}`,
2620
+ // fail.value,
2621
+ // )
2622
+ // return
2623
+ // }
2624
+ const message = `Failure trying to ${id}`
2625
+ yield* reportMessage(message, {
2626
+ action: id,
2627
+ error: fail.value
2628
+ })
2629
+ return
2630
+ }
2631
+
2632
+ const context = yield* CommandContext
2633
+ const extra = {
2634
+ action: context.action,
2635
+ message: `Unexpected Error trying to ${id}`
2636
+ }
2637
+ yield* reportRuntimeError(cause, extra)
2638
+ }, Effect.uninterruptible)
2639
+ )
2640
+ )
2641
+
2642
+ const currentState = Effect.sync(() => state.value)
2643
+
2644
+ const theHandler = flow(
2645
+ handler,
2646
+ errorReporter,
2647
+ // all must be within the Effect.fn to fit within the Span
2648
+ Effect.provideServiceEffect(
2649
+ stateTag,
2650
+ currentState
2651
+ ),
2652
+ Effect.provideServiceEffect(
2653
+ CommandContext,
2654
+ Effect.sync(() => makeContext_())
2655
+ )
2656
+ )
2657
+ const waitId = options?.waitKey ? options.waitKey(id) : undefined
2658
+ const blockId = options?.blockKey ? options.blockKey(id) : undefined
2659
+
2660
+ const [result, exec_] = asResult(theHandler)
2661
+
2662
+ const exec = Effect
2663
+ .fnUntraced(
2664
+ function*(...args: [any, any]) {
2665
+ if (waitId !== undefined) registerWait(waitId)
2666
+ if (blockId !== undefined && blockId !== waitId) {
2667
+ registerWait(blockId)
2668
+ }
2669
+ return yield* exec_(...args)
2670
+ },
2671
+ Effect.onExit(() =>
2672
+ Effect.sync(() => {
2673
+ if (waitId !== undefined) unregisterWait(waitId)
2674
+ if (blockId !== undefined && blockId !== waitId) {
2675
+ unregisterWait(blockId)
2676
+ }
2677
+ })
2678
+ )
2679
+ )
2680
+
2681
+ const waiting = waitId !== undefined
2682
+ ? computed(() => result.value.waiting || (waitState.value[waitId] ?? 0) > 0)
2683
+ : computed(() => result.value.waiting)
2684
+
2685
+ const blocked = blockId !== undefined
2686
+ ? computed(() => waiting.value || (waitState.value[blockId] ?? 0) > 0)
2687
+ : computed(() => waiting.value)
2688
+
2689
+ const computeAllowed = options?.allowed
2690
+ const allowed = computeAllowed ? computed(() => computeAllowed(id, state)) : true
2691
+
2692
+ const rt = Effect.context<RT | RTHooks>().pipe(Effect.provide(this.hooks)).pipe(Effect.runSyncWith(this.rt))
2693
+ const runFork = Effect.runForkWith(rt)
2694
+
2695
+ const handle = Object.assign((arg: Arg) => {
2696
+ arg = toRaw(arg) // remove outside vue proxy bs
2697
+ // we capture the call site stack here
2698
+ const limit = Error.stackTraceLimit
2699
+ Error.stackTraceLimit = 2
2700
+ const errorCall = new Error()
2701
+ Error.stackTraceLimit = limit
2702
+
2703
+ let cache: false | string = false
2704
+ const captureStackTrace = () => {
2705
+ // in case of an error, we want to append the definition stack to the call site stack,
2706
+ // so we can see where the handler was defined too
2707
+
2708
+ if (cache !== false) {
2709
+ return cache
2710
+ }
2711
+ if (errorCall.stack) {
2712
+ const stackDef = errorDef!.stack!.trim().split("\n")
2713
+ const stackCall = errorCall.stack.trim().split("\n")
2714
+ let endStackDef = stackDef.slice(2).join("\n").trim()
2715
+ if (!endStackDef.includes(`(`)) {
2716
+ endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
2717
+ }
2718
+ let endStackCall = stackCall.slice(2).join("\n").trim()
2719
+ if (!endStackCall.includes(`(`)) {
2720
+ endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
2721
+ }
2722
+ cache = `${endStackDef}\n${endStackCall}`
2723
+ return cache
2724
+ }
2725
+ }
2726
+
2727
+ const command = currentState.pipe(Effect.flatMap((state) => {
2728
+ const rawArg = deepToRaw(arg)
2729
+ const rawState = deepToRaw(state)
2730
+ return Effect.withSpan(
2731
+ exec(arg, { ...context.value, state } as any),
2732
+ id,
2733
+ {
2734
+ captureStackTrace,
2735
+ attributes: {
2736
+ input: rawArg,
2737
+ state: rawState,
2738
+ action: initialContext.action,
2739
+ label: initialContext.label,
2740
+ id: initialContext.id,
2741
+ i18nKey: initialContext.i18nKey
2742
+ }
2743
+ }
2744
+ )
2745
+ }))
2746
+
2747
+ return runFork(command)
2748
+ }, { action, label })
2749
+
2750
+ return reactive({
2751
+ /** static */
2752
+ id,
2753
+
2754
+ /** the base i18n key, based on id by default. static */
2755
+ i18nKey: initialContext.i18nKey,
2756
+ /** the `action.` namespace based on i18nKey.. static */
2757
+ namespace: initialContext.namespace,
2758
+
2759
+ /** easy generate namespaced 18n keys, based on namespace. static */
2760
+ namespaced: initialContext.namespaced,
2761
+
2762
+ /** reactive */
2763
+ result,
2764
+ /** always undefined for non-stream commands */
2765
+ progress: undefined,
2766
+ /** reactive */
2767
+ waiting,
2768
+ /** reactive */
2769
+ blocked,
2770
+ /** reactive */
2771
+ allowed,
2772
+ /** reactive */
2773
+ action,
2774
+ /** reactive */
2775
+ label,
2776
+ /** reactive */
2777
+ state,
2778
+
2779
+ handle
2780
+ })
2781
+ },
2782
+ { id }
2783
+ )
2784
+ }
2785
+
2786
+ // /** @experimental */
2787
+ // takeOver:
2788
+ // <Args extends any[], A, E, R, const Id extends string>(command: Commander.CommandOut<Args, A, E, R, Id,I18nKey>) =>
2789
+ // (...args: Args) => {
2790
+ // // we capture the call site stack here
2791
+ // const limit = Error.stackTraceLimit
2792
+ // Error.stackTraceLimit = 2
2793
+ // const errorCall = new Error()
2794
+ // const localErrorDef = new Error()
2795
+ // Error.stackTraceLimit = limit
2796
+
2797
+ // // TODO
2798
+ // const errorDef = localErrorDef
2799
+
2800
+ // let cache: false | string = false
2801
+ // const captureStackTrace = () => {
2802
+ // // in case of an error, we want to append the definition stack to the call site stack,
2803
+ // // so we can see where the handler was defined too
2804
+
2805
+ // if (cache !== false) {
2806
+ // return cache
2807
+ // }
2808
+ // if (errorCall.stack) {
2809
+ // const stackDef = errorDef.stack!.trim().split("\n")
2810
+ // const stackCall = errorCall.stack.trim().split("\n")
2811
+ // let endStackDef = stackDef.slice(2).join("\n").trim()
2812
+ // if (!endStackDef.includes(`(`)) {
2813
+ // endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
2814
+ // }
2815
+ // let endStackCall = stackCall.slice(2).join("\n").trim()
2816
+ // if (!endStackCall.includes(`(`)) {
2817
+ // endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
2818
+ // }
2819
+ // cache = `${endStackDef}\n${endStackCall}`
2820
+ // return cache
2821
+ // }
2822
+ // }
2823
+
2824
+ // return Effect.gen(function*() {
2825
+ // const ctx = yield* CommandContext
2826
+ // ctx.action = command.action
2827
+ // return yield* command.exec(...args).pipe(
2828
+ // Effect.flatten,
2829
+ // Effect.withSpan(
2830
+ // command.action,
2831
+ // { captureStackTrace }
2832
+ // )
2833
+ // )
2834
+ // })
2835
+ // },
2836
+
2837
+ /**
2838
+ * Define a Command for handling user actions with built-in error reporting and state management.
2839
+ *
2840
+ * @param id The internal identifier for the action. Used as a tracing span and to lookup
2841
+ * the user-facing name via internationalization (`action.${id}`).
2842
+ * @param options Optional configuration for internationalization and state.
2843
+ * @param options.i18nCustomKey Custom i18n key to use instead of `id` (e.g., for grouping similar actions)
2844
+ * @param options.state Optional reactive state object (or function returning one) that is
2845
+ * made available to the command effects and can be used for i18n interpolation.
2846
+ * The state is captured at the start of each command execution and remains stable throughout.
2847
+ * @returns A function that executes the command when called (e.g., directly in `@click` handlers).
2848
+ * Built-in error reporting handles failures automatically.
2849
+ *
2850
+ * **Effect Context**: Effects have access to the `CommandContext` service, which provides
2851
+ * the user-facing action name.
2852
+ *
2853
+ * **Returned Properties**:
2854
+ * - `action`: User-facing action name from intl messages (useful for button labels)
2855
+ * - `result`: The command result state
2856
+ * - `waiting`: Boolean indicating if the command is in progress (shorthand for `result.waiting`)
2857
+ * - `handle`: Function to execute the command
2858
+ * - `exec`: The raw Effect that will be executed when calling `handle` (for advanced use cases)
2859
+ * - `i18nKey`, `namespace`, `namespaced`: Helpers for internationalization keys
2860
+ *
2861
+ * **User Feedback**: Use the `withDefaultToast` helper for status notifications, or render
2862
+ * the `result` inline for custom UI feedback.
2863
+ */
2864
+ fn = <
2865
+ const Id extends string,
2866
+ const State extends IntlRecord = IntlRecord,
2867
+ const I18nKey extends string = Id
2868
+ >(
2869
+ id: Id | { id: Id },
2870
+ options?: FnOptions<Id, I18nKey, State>
2871
+ ): Commander.Gen<RT | RTHooks, Id, I18nKey, State> & Commander.NonGen<RT | RTHooks, Id, I18nKey, State> & {
2872
+ state: Context.Service<`Commander.Command.${Id}.state`, State>
2873
+ } => {
2874
+ const resolvedId: Id = typeof id === "string" ? id : id.id
2875
+ return Object.assign(
2876
+ (
2877
+ fn: any,
2878
+ ...combinators: any[]
2879
+ ): any => {
2880
+ // we capture the definition stack here, so we can append it to later stack traces
2881
+ const limit = Error.stackTraceLimit
2882
+ Error.stackTraceLimit = 2
2883
+ const errorDef = new Error()
2884
+ Error.stackTraceLimit = limit
2885
+
2886
+ return this.makeCommand(resolvedId, options, errorDef)(
2887
+ Effect.fnUntraced(
2888
+ // fnUntraced only supports generators as first arg, so we convert to generator if needed
2889
+ isGeneratorFunction(fn) ? fn : function*(...args) {
2890
+ return yield* fn(...args)
2891
+ },
2892
+ ...combinators as [any]
2893
+ ) as any
2894
+ )
2895
+ },
2896
+ makeBaseInfo(resolvedId, options),
2897
+ {
2898
+ state: Context.Service<`Commander.Command.${Id}.state`, State>(
2899
+ `Commander.Command.${resolvedId}.state`
2900
+ )
2901
+ }
2902
+ )
2903
+ }
2904
+
2905
+ /**
2906
+ * Internal factory for stream-backed commands. Accepts a handler that returns a `Stream` directly.
2907
+ * Services (`CommandContext`, `stateTag`) are provided to the stream via `Stream.provideServiceEffect`.
2908
+ */
2909
+ readonly makeStreamCommand = <
2910
+ const Id extends string,
2911
+ const State extends IntlRecord | undefined,
2912
+ const I18nKey extends string = Id
2913
+ >(
2914
+ id_: Id | { id: Id },
2915
+ options?: FnOptions<Id, I18nKey, State>,
2916
+ errorDef?: Error
2917
+ ) => {
2918
+ const id = typeof id_ === "string" ? id_ : id_.id
2919
+ const state = getStateValues(options)
2920
+
2921
+ return Object.assign(
2922
+ <Arg, SA, SE, SR>(
2923
+ handler: (arg: Arg, ctx: Commander.CommandContextLocal2<Id, I18nKey, State>) => Stream.Stream<SA, SE, SR>
2924
+ ) => {
2925
+ const limit = Error.stackTraceLimit
2926
+ Error.stackTraceLimit = 2
2927
+ const localErrorDef = new Error()
2928
+ Error.stackTraceLimit = limit
2929
+ if (!errorDef) {
2930
+ errorDef = localErrorDef
2931
+ }
2932
+
2933
+ const key = `Commander.Command.${id}.state` as const
2934
+ const stateTag = Context.Service<typeof key, State>(key)
2935
+
2936
+ const makeContext_ = () => this.makeContext(id, { ...options, state: state?.value })
2937
+ const initialContext = makeContext_()
2938
+ const context = computed(() => makeContext_())
2939
+ const action = computed(() => context.value.action)
2940
+ const label = computed(() => context.value.label)
2941
+
2942
+ const currentState = Effect.sync(() => state.value)
2943
+
2944
+ // Reactive ref driven by the CommandProgress service — updated imperatively
2945
+ // from inside the stream via `Command.mapProgress(fn)` or `Command.updateProgress(p)`.
2946
+ const progressRef = ref<Progress | undefined>(undefined)
2947
+ const commandProgressService = {
2948
+ update: (p: Progress | undefined) =>
2949
+ Effect.sync(() => {
2950
+ progressRef.value = p
2951
+ })
2952
+ }
2953
+
2954
+ const streamErrorReporter = <A, E, R>(self: Stream.Stream<A, E, R>) =>
2955
+ self.pipe(
2956
+ Stream.tapCause(
2957
+ Effect.fnUntraced(function*(cause) {
2958
+ if (Cause.hasInterruptsOnly(cause)) {
2959
+ console.info(`Interrupted while trying to ${id}`)
2960
+ return
2961
+ }
2962
+
2963
+ const fail = Cause.findErrorOption(cause)
2964
+ if (Option.isSome(fail)) {
2965
+ const message = `Failure trying to ${id}`
2966
+ yield* reportMessage(message, {
2967
+ action: id,
2968
+ error: fail.value
2969
+ })
2970
+ return
2971
+ }
2972
+
2973
+ const ctx = yield* CommandContext
2974
+ const extra = {
2975
+ action: ctx.action,
2976
+ message: `Unexpected Error trying to ${id}`
2977
+ }
2978
+ yield* reportRuntimeError(cause, extra)
2979
+ }, Effect.uninterruptible)
2980
+ )
2981
+ )
2982
+
2983
+ const theStreamHandler = (arg: Arg, ctx: Commander.CommandContextLocal2<Id, I18nKey, State>) =>
2984
+ handler(arg, ctx).pipe(
2985
+ streamErrorReporter,
2986
+ Stream.provideService(CommandProgress, commandProgressService),
2987
+ Stream.provideServiceEffect(stateTag, currentState),
2988
+ Stream.provideServiceEffect(CommandContext, Effect.sync(() => makeContext_()))
2989
+ )
2990
+
2991
+ const waitId = options?.waitKey ? options.waitKey(id) : undefined
2992
+ const blockId = options?.blockKey ? options.blockKey(id) : undefined
2993
+
2994
+ const [result, exec_] = asStreamResult(theStreamHandler)
2995
+
2996
+ const exec = Effect
2997
+ .fnUntraced(
2998
+ function*(...args: [any, any]) {
2999
+ if (waitId !== undefined) registerWait(waitId)
3000
+ if (blockId !== undefined && blockId !== waitId) {
3001
+ registerWait(blockId)
3002
+ }
3003
+ return yield* exec_(...args)
3004
+ },
3005
+ Effect.onExit(() =>
3006
+ Effect.sync(() => {
3007
+ if (waitId !== undefined) unregisterWait(waitId)
3008
+ if (blockId !== undefined && blockId !== waitId) {
3009
+ unregisterWait(blockId)
3010
+ }
3011
+ })
3012
+ )
3013
+ )
3014
+
3015
+ const waiting = waitId !== undefined
3016
+ ? computed(() => result.value.waiting || (waitState.value[waitId] ?? 0) > 0)
3017
+ : computed(() => result.value.waiting)
3018
+
3019
+ const blocked = blockId !== undefined
3020
+ ? computed(() => waiting.value || (waitState.value[blockId] ?? 0) > 0)
3021
+ : computed(() => waiting.value)
3022
+
3023
+ const computeAllowed = options?.allowed
3024
+ const allowed = computeAllowed ? computed(() => computeAllowed(id, state)) : true
3025
+
3026
+ const rt = Effect.context<RT | RTHooks>().pipe(Effect.provide(this.hooks)).pipe(Effect.runSyncWith(this.rt))
3027
+ const runFork = Effect.runForkWith(rt)
3028
+
3029
+ const progress = progressRef
3030
+
3031
+ const handle = Object.assign((arg: Arg) => {
3032
+ arg = toRaw(arg)
3033
+ progressRef.value = undefined // reset progress on new invocation
3034
+ const limit = Error.stackTraceLimit
3035
+ Error.stackTraceLimit = 2
3036
+ const errorCall = new Error()
3037
+ Error.stackTraceLimit = limit
3038
+
3039
+ let cache: false | string = false
3040
+ const captureStackTrace = () => {
3041
+ if (cache !== false) {
3042
+ return cache
3043
+ }
3044
+ if (errorCall.stack) {
3045
+ const stackDef = errorDef!.stack!.trim().split("\n")
3046
+ const stackCall = errorCall.stack.trim().split("\n")
3047
+ let endStackDef = stackDef.slice(2).join("\n").trim()
3048
+ if (!endStackDef.includes(`(`)) {
3049
+ endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
3050
+ }
3051
+ let endStackCall = stackCall.slice(2).join("\n").trim()
3052
+ if (!endStackCall.includes(`(`)) {
3053
+ endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
3054
+ }
3055
+ cache = `${endStackDef}\n${endStackCall}`
3056
+ return cache
3057
+ }
3058
+ }
3059
+
3060
+ const command = currentState.pipe(Effect.flatMap((state) => {
3061
+ const rawArg = deepToRaw(arg)
3062
+ const rawState = deepToRaw(state)
3063
+ return Effect.withSpan(
3064
+ exec(arg, { ...context.value, state } as any),
3065
+ id,
3066
+ {
3067
+ captureStackTrace,
3068
+ attributes: {
3069
+ input: rawArg,
3070
+ state: rawState,
3071
+ action: initialContext.action,
3072
+ label: initialContext.label,
3073
+ id: initialContext.id,
3074
+ i18nKey: initialContext.i18nKey
3075
+ }
3076
+ }
3077
+ )
3078
+ }))
3079
+
3080
+ return runFork(command as any)
3081
+ }, { action, label })
3082
+
3083
+ return reactive({
3084
+ id,
3085
+ i18nKey: initialContext.i18nKey,
3086
+ namespace: initialContext.namespace,
3087
+ namespaced: initialContext.namespaced,
3088
+ result,
3089
+ /** reactive – progress driven by `Command.mapProgress` or `Command.updateProgress` inside the stream */
3090
+ progress,
3091
+ waiting,
3092
+ blocked,
3093
+ allowed,
3094
+ action,
3095
+ label,
3096
+ state,
3097
+ handle
3098
+ })
3099
+ },
3100
+ { id }
3101
+ )
3102
+ }
3103
+
3104
+ /**
3105
+ * Define a stream-backed Command for handling user actions.
3106
+ *
3107
+ * Like `fn`, but the body generator (or function) must **return** a `Stream` rather than
3108
+ * an `Effect`. The command's `waiting` state stays `true` while the stream is running and
3109
+ * is set to `false` once it terminates. The reactive `result` ref is updated for every
3110
+ * value emitted by the stream.
3111
+ *
3112
+ * Three handler shapes are accepted:
3113
+ * 1. **Generator returning a Stream** (primary) — may yield Effects freely before returning the stream:
3114
+ * ```ts
3115
+ * Command.streamFn("exportData")(
3116
+ * function*(arg, ctx) {
3117
+ * const token = yield* getAuthToken
3118
+ * return Stream.fromEffect(startExport(token, arg.id)).pipe(
3119
+ * Stream.flatMap((job) => pollProgress(job.id))
3120
+ * )
3121
+ * }
3122
+ * )
3123
+ * ```
3124
+ * 2. **Function returning a Stream directly**: `(arg, ctx) => Stream.make(1, 2, 3)`
3125
+ * 3. **Function returning `Effect<Stream>`**: `(arg, ctx) => Effect.map(setup, (s) => s.stream)`
3126
+ *
3127
+ * @param id The internal identifier for the action (used for tracing and i18n lookup).
3128
+ * @param options Same options as `fn` (`state`, `blockKey`, `waitKey`, `allowed`, `i18nCustomKey`).
3129
+ *
3130
+ * **Progress** — use `Command.mapProgress(fn)` as a stream pipe operator; the mapper receives
3131
+ * `AsyncResult<A, E>` (each value wrapped as `AsyncResult.success(v, { waiting: true })`),
3132
+ * matching the same shape as CommandButton’s `:progress-map` prop. Or call
3133
+ * `Command.updateProgress(p)` for imperative control:
3134
+ *
3135
+ * ```ts
3136
+ * // mapProgress as a combinator arg (outside the handler):
3137
+ * Command.streamFn("exportData")(
3138
+ * function*(arg, ctx) { return makeExportStream(arg.id) },
3139
+ * (s) => s.pipe(Command.mapProgress((r) => AsyncResult.isSuccess(r) && r.value._tag === "OperationProgress" ? { text: `${r.value.completed}/${r.value.total}` } : undefined))
3140
+ * )
3141
+ *
3142
+ * // Or inline inside the handler body:
3143
+ * Command.streamFn("exportData")(function*(arg, ctx) {
3144
+ * return makeExportStream(arg.id).pipe(Command.mapProgress((r) => AsyncResult.isSuccess(r) ? ... : undefined))
3145
+ * })
3146
+ * ```
3147
+ *
3148
+ * **Pipeable combinators** — the 2nd–Nth args follow the same pattern as `fn`: each combinator
3149
+ * receives `(stream, arg, ctx)` and returns a transformed stream:
3150
+ * ```ts
3151
+ * Command.streamFn("exportData")(
3152
+ * handler,
3153
+ * (s, arg, ctx) => s.pipe(Command.mapProgress(fn), Stream.take(100))
3154
+ * )
3155
+ * ```
3156
+ *
3157
+ * **Returned Properties**: `action`, `label`, `result`, `progress`, `waiting`, `blocked`,
3158
+ * `allowed`, `handle`, `i18nKey`, `namespace`, `namespaced`.
3159
+ */
3160
+ streamFn = <
3161
+ const Id extends string,
3162
+ const State extends IntlRecord = IntlRecord,
3163
+ const I18nKey extends string = Id
3164
+ >(
3165
+ id: Id | { id: Id },
3166
+ options?: FnOptions<Id, I18nKey, State>
3167
+ ):
3168
+ & Commander.StreamGen<RT | RTHooks, Id, I18nKey, State>
3169
+ & Commander.NonGenStream<RT | RTHooks, Id, I18nKey, State>
3170
+ & {
3171
+ state: Context.Service<`Commander.Command.${Id}.state`, State>
3172
+ } =>
3173
+ {
3174
+ const resolvedId = typeof id === "string" ? id : id.id
3175
+
3176
+ type StreamOrEffect = Stream.Stream<any, any, any> | Effect.Effect<Stream.Stream<any, any, any>, any, any>
3177
+
3178
+ const toRawHandler = (fn: any): (arg: any, ctx: any) => StreamOrEffect => {
3179
+ if (isGeneratorFunction(fn)) {
3180
+ return Effect.fnUntraced(function*(arg: any, ctx: any) {
3181
+ return yield* (fn as (arg: any, ctx: any) => Generator<any, Stream.Stream<any, any, any>>)(arg, ctx)
3182
+ })
3183
+ }
3184
+ return fn
3185
+ }
3186
+
3187
+ const toFinalStream = (value: StreamOrEffect): Stream.Stream<any, any, any> =>
3188
+ Stream.isStream(value) ? value : Stream.unwrap(value as Effect.Effect<Stream.Stream<any, any, any>, any, any>)
3189
+
3190
+ return Object.assign(
3191
+ (fn: any, ...combinators: Array<(s: any, arg: any, ctx: any) => any>): any => {
3192
+ const limit = Error.stackTraceLimit
3193
+ Error.stackTraceLimit = 2
3194
+ const errorDef = new Error()
3195
+ Error.stackTraceLimit = limit
3196
+
3197
+ const rawHandler = toRawHandler(fn)
3198
+ const handler = (arg: any, ctx: any) => {
3199
+ let current: any = rawHandler(arg, ctx)
3200
+ for (const combinator of combinators) {
3201
+ current = combinator(current, arg, ctx)
3202
+ }
3203
+ return toFinalStream(current)
3204
+ }
3205
+
3206
+ return this.makeStreamCommand(id, options, errorDef)(handler)
3207
+ },
3208
+ makeBaseInfo(resolvedId, options),
3209
+ {
3210
+ state: Context.Service<`Commander.Command.${Id}.state`, State>(
3211
+ `Commander.Command.${resolvedId}.state`
3212
+ )
3213
+ }
3214
+ )
3215
+ }
3216
+
3217
+ /** @deprecated */
3218
+
3219
+ alt2: <
3220
+ const Id extends string,
3221
+ MutArg,
3222
+ MutA,
3223
+ MutE,
3224
+ MutR,
3225
+ const I18nKey extends string = Id,
3226
+ State extends IntlRecord | undefined = undefined
3227
+ >(
3228
+ id:
3229
+ | Id
3230
+ | { id: Id; mutate: (arg: MutArg) => Effect.Effect<MutA, MutE, MutR> }
3231
+ | ((arg: MutArg) => Effect.Effect<MutA, MutE, MutR>) & { id: Id },
3232
+ options?: FnOptions<Id, I18nKey, State>
3233
+ ) =>
3234
+ & Commander.CommandContextLocal<Id, I18nKey>
3235
+ & (<A, E, R extends RT | RTHooks | CommandContext | `Commander.Command.${Id}.state`, Arg = void>(
3236
+ handler: (
3237
+ ctx: Effect.fn.Traced & Effect.fn.Untraced & Commander.CommandContextLocal<Id, I18nKey> & {
3238
+ // todo: only if we passed in one
3239
+ mutate: (arg: Arg) => Effect.Effect<MutA, MutE, MutR>
3240
+ }
3241
+ ) => (arg: Arg, ctx: Commander.CommandContextLocal2<Id, I18nKey, State>) => Effect.Effect<A, E, R>
3242
+ ) => Commander.CommandOut<Arg, A, E, R, Id, I18nKey, State>) = (
3243
+ _id,
3244
+ options?
3245
+ ) => {
3246
+ const isObject = Predicate.isObjectKeyword(_id)
3247
+ const id = isObject ? _id.id : _id
3248
+ const baseInfo = makeBaseInfo(id, options)
3249
+ const idCmd = this.makeCommand(id, options)
3250
+ // TODO: implement proper tracing stack
3251
+ return Object.assign((cb: any) =>
3252
+ idCmd(cb(
3253
+ Object.assign(
3254
+ (fn: any, ...combinators: any[]) =>
3255
+ Effect.fnUntraced(
3256
+ // fnUntraced only supports generators as first arg, so we convert to generator if needed
3257
+ isGeneratorFunction(fn) ? fn : function*(...args) {
3258
+ return yield* fn(...args)
3259
+ },
3260
+ ...combinators as [any]
3261
+ ),
3262
+ baseInfo,
3263
+ isObject
3264
+ ? { mutate: "mutate" in _id ? _id.mutate : typeof _id === "function" ? _id : undefined }
3265
+ : {}
3266
+ )
3267
+ )), baseInfo) as any
3268
+ }
3269
+
3270
+ alt = this.makeCommand as unknown as <
3271
+ const Id extends string,
3272
+ const I18nKey extends string = Id,
3273
+ State extends IntlRecord | undefined = undefined
3274
+ >(
3275
+ id: Id,
3276
+ customI18nKey?: I18nKey
3277
+ ) =>
3278
+ & Commander.CommandContextLocal<Id, I18nKey>
3279
+ & (<A, E, R extends RT | CommandContext | `Commander.Command.${Id}.state`, Arg = void>(
3280
+ handler: (arg: Arg, ctx: Commander.CommandContextLocal2<Id, I18nKey, State>) => Effect.Effect<A, E, R>
3281
+ ) => Commander.CommandOut<Arg, A, E, R, Id, I18nKey, State>)
3282
+
3283
+ /**
3284
+ * Define a Command for handling user actions with built-in error reporting and state management.
3285
+ *
3286
+ * @param mutation The mutation function to take the identifier and initial handler from. Used as a tracing span and to lookup
3287
+ * the user-facing name via internationalization (`action.${id}`).
3288
+ * @param options Optional configuration for internationalization and state.
3289
+ * @param options.i18nCustomKey Custom i18n key to use instead of `id` (e.g., for grouping similar actions)
3290
+ * @param options.state Optional reactive state object (or function returning one) that is
3291
+ * made available to the command effects and can be used for i18n interpolation.
3292
+ * The state is captured at the start of each command execution and remains stable throughout.
3293
+ * @returns A function that executes the command when called (e.g., directly in `@click` handlers).
3294
+ * Built-in error reporting handles failures automatically.
3295
+ *
3296
+ * **Effect Context**: Effects have access to the `CommandContext` service, which provides
3297
+ * the user-facing action name.
3298
+ *
3299
+ * **Returned Properties**:
3300
+ * - `action`: User-facing action name from intl messages (useful for button labels)
3301
+ * - `result`: The command result state
3302
+ * - `waiting`: Boolean indicating if the command is in progress (shorthand for `result.waiting`)
3303
+ * - `handle`: Function to execute the command
3304
+ * - `exec`: The raw Effect that will be executed when calling `handle` (for advanced use cases)
3305
+ * - `i18nKey`, `namespace`, `namespaced`: Helpers for internationalization keys
3306
+ *
3307
+ * **User Feedback**: Use the `withDefaultToast` helper for status notifications, or render
3308
+ * the `result` inline for custom UI feedback.
3309
+ */
3310
+ streamWrap = <
3311
+ const Id extends string,
3312
+ Arg,
3313
+ SA,
3314
+ SE,
3315
+ SR,
3316
+ const State extends IntlRecord = IntlRecord,
3317
+ I18nKey extends string = Id
3318
+ >(
3319
+ handler: (arg: Arg, ctx: Commander.CommandContextLocal2<Id, I18nKey, State>) => Stream.Stream<SA, SE, SR>,
3320
+ id: Id,
3321
+ options?: FnOptions<Id, I18nKey, State>
3322
+ ): Commander.StreamerWrap<RT | RTHooks, Id, I18nKey, State, Arg, SA, SE, SR> => {
3323
+ return Object.assign(
3324
+ (...combinators: any[]): any => {
3325
+ const limit = Error.stackTraceLimit
3326
+ Error.stackTraceLimit = 2
3327
+ const errorDef = new Error()
3328
+ Error.stackTraceLimit = limit
3329
+ return this.makeStreamCommand(id, options, errorDef)(
3330
+ combinators.length === 0
3331
+ ? handler
3332
+ : (arg: Arg, ctx: Commander.CommandContextLocal2<Id, I18nKey, State>) => {
3333
+ let current: any = handler(arg, ctx)
3334
+ for (const combinator of combinators) {
3335
+ current = combinator(current, arg, ctx)
3336
+ }
3337
+ return current
3338
+ }
3339
+ )
3340
+ },
3341
+ makeBaseInfo(id, options),
3342
+ {
3343
+ state: Context.Service<`Commander.Command.${Id}.state`, State>(
3344
+ `Commander.Command.${id}.state`
3345
+ )
3346
+ }
3347
+ )
3348
+ }
3349
+
3350
+ wrap = <
3351
+ const Id extends string,
3352
+ Arg,
3353
+ A,
3354
+ E,
3355
+ R,
3356
+ const State extends IntlRecord = IntlRecord,
3357
+ I18nKey extends string = Id
3358
+ >(
3359
+ mutation:
3360
+ | { mutate: (arg: Arg) => Effect.Effect<A, E, R>; id: Id }
3361
+ | ((arg: Arg) => Effect.Effect<A, E, R>) & { id: Id },
3362
+ options?: FnOptions<Id, I18nKey, State>
3363
+ ): Commander.CommanderWrap<RT | RTHooks, Id, I18nKey, State, Arg, A, E, R> => {
3364
+ const callMutation = mutation
3365
+ return Object.assign(
3366
+ (
3367
+ ...combinators: any[]
3368
+ ): any => {
3369
+ // we capture the definition stack here, so we can append it to later stack traces
3370
+ const limit = Error.stackTraceLimit
3371
+ Error.stackTraceLimit = 2
3372
+ const errorDef = new Error()
3373
+ Error.stackTraceLimit = limit
3374
+ const mutate = "mutate" in callMutation
3375
+ ? callMutation.mutate
3376
+ : callMutation
3377
+
3378
+ return this.makeCommand(callMutation.id, options, errorDef)(
3379
+ Effect.fnUntraced(
3380
+ // fnUntraced only supports generators as first arg, so we convert to generator if needed
3381
+ isGeneratorFunction(mutate) ? mutate : function*(arg: Arg) {
3382
+ return yield* mutate(arg)
3383
+ },
3384
+ ...combinators as [any]
3385
+ ) as any
3386
+ )
3387
+ },
3388
+ makeBaseInfo(callMutation.id, options),
3389
+ {
3390
+ state: Context.Service<`Commander.Command.${Id}.state`, State>(
3391
+ `Commander.Command.${callMutation.id}.state`
3392
+ )
3393
+ }
3394
+ )
3395
+ }
3396
+ }
3397
+
3398
+ // @effect-diagnostics-next-line missingEffectServiceDependency:off
3399
+ export class Commander extends Context.Service<Commander>()("Commander", {
3400
+ make: Effect.gen(function*() {
3401
+ const i18n = yield* I18n
3402
+ return <RT, RTHooks>(rt: Context.Context<RT>, rtHooks: Layer.Layer<RTHooks, never, RT>) =>
3403
+ new CommanderImpl(rt, i18n, rtHooks)
3404
+ })
3405
+ }) {
3406
+ static readonly DefaultWithoutDependencies = Layer.effect(this, this.make)
3407
+ static readonly Default = this.DefaultWithoutDependencies
3408
+ }