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