@effect-app/vue 4.0.0-beta.22 → 4.0.0-beta.220
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 +1605 -0
- package/dist/commander.d.ts +628 -0
- package/dist/commander.d.ts.map +1 -0
- package/dist/commander.js +1060 -0
- package/dist/confirm.d.ts +19 -0
- package/dist/confirm.d.ts.map +1 -0
- package/dist/confirm.js +24 -0
- package/dist/errorReporter.d.ts +4 -4
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +12 -18
- package/dist/form.d.ts +14 -5
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +41 -12
- 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 +6 -9
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +35 -10
- package/dist/makeClient.d.ts +152 -339
- package/dist/makeClient.d.ts.map +1 -1
- package/dist/makeClient.js +221 -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 +8 -0
- package/dist/makeUseCommand.d.ts.map +1 -0
- package/dist/makeUseCommand.js +13 -0
- package/dist/mutate.d.ts +52 -34
- package/dist/mutate.d.ts.map +1 -1
- package/dist/mutate.js +137 -46
- package/dist/query.d.ts +19 -39
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +128 -72
- package/dist/routeParams.d.ts +1 -1
- package/dist/runtime.d.ts +7 -4
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +27 -17
- package/dist/toast.d.ts +50 -0
- package/dist/toast.d.ts.map +1 -0
- package/dist/toast.js +32 -0
- package/dist/withToast.d.ts +27 -0
- package/dist/withToast.d.ts.map +1 -0
- package/dist/withToast.js +59 -0
- package/examples/streamMutation.ts +70 -0
- package/package.json +48 -50
- package/src/commander.ts +3393 -0
- package/src/{experimental/confirm.ts → confirm.ts} +10 -14
- package/src/errorReporter.ts +62 -74
- package/src/form.ts +56 -17
- package/src/intl.ts +12 -0
- package/src/lib.ts +47 -20
- package/src/makeClient.ts +568 -1134
- package/src/{experimental/makeUseCommand.ts → makeUseCommand.ts} +6 -4
- package/src/mutate.ts +265 -127
- package/src/query.ts +197 -183
- package/src/runtime.ts +41 -20
- package/src/{experimental/toast.ts → toast.ts} +13 -27
- package/src/{experimental/withToast.ts → withToast.ts} +40 -12
- package/test/Mutation.test.ts +176 -23
- 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 +3529 -122
- package/test/dist/stubs.d.ts.map +1 -1
- package/test/dist/stubs.js +182 -31
- package/test/form-validation-errors.test.ts +23 -19
- package/test/form.test.ts +20 -2
- package/test/lib.test.ts +240 -0
- package/test/makeClient.test.ts +292 -38
- package/test/streamFinal.test.ts +63 -0
- package/test/streamFn.test.ts +455 -0
- package/test/stubs.ts +218 -42
- 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
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { Cause, Effect, Layer, type Option,
|
|
1
|
+
import { Cause, Context, Effect, Fiber, Layer, type Option, S } from "effect-app"
|
|
2
2
|
import { wrapEffect } from "effect-app/utils"
|
|
3
|
-
import { CurrentToastId, Toast } from "./toast.js"
|
|
3
|
+
import { CurrentToastId, Toast, type ToastId } from "./toast.js"
|
|
4
4
|
|
|
5
5
|
export interface ToastOptions<A, E, Args extends ReadonlyArray<unknown>, WaiR, SucR, ErrR> {
|
|
6
6
|
stableToastId?: undefined | string | ((...args: Args) => string | undefined)
|
|
7
7
|
timeout?: number
|
|
8
|
+
showSpanInfo?: false
|
|
9
|
+
groupId?: string
|
|
8
10
|
onWaiting:
|
|
9
11
|
| string
|
|
10
12
|
| ((...args: Args) => string | null)
|
|
@@ -33,10 +35,10 @@ export interface ToastOptions<A, E, Args extends ReadonlyArray<unknown>, WaiR, S
|
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
36
|
-
export class WithToast extends
|
|
38
|
+
export class WithToast extends Context.Service<WithToast>()("WithToast", {
|
|
37
39
|
make: Effect.gen(function*() {
|
|
38
40
|
const toast = yield* Toast
|
|
39
|
-
return <A, E, Args extends
|
|
41
|
+
return <A, E, Args extends readonly unknown[], R, WaiR = never, SucR = never, ErrR = never>(
|
|
40
42
|
options: ToastOptions<A, E, Args, WaiR, SucR, ErrR>
|
|
41
43
|
) =>
|
|
42
44
|
Effect.fnUntraced(function*(self: Effect.Effect<A, E, R>, ...args: Args) {
|
|
@@ -46,23 +48,41 @@ export class WithToast extends ServiceMap.Service<WithToast>()("WithToast", {
|
|
|
46
48
|
? options.stableToastId(...args)
|
|
47
49
|
: options.stableToastId
|
|
48
50
|
|
|
51
|
+
const requestId: string = yield* Effect.currentSpan.pipe(
|
|
52
|
+
Effect.map((span) => span.traceId),
|
|
53
|
+
Effect.orElseSucceed(() => S.StringId.make())
|
|
54
|
+
)
|
|
55
|
+
const groupId = options.groupId
|
|
56
|
+
const meta = { ...(groupId !== undefined ? { groupId } : {}), requestId }
|
|
57
|
+
|
|
49
58
|
const t = yield* wrapEffect(options.onWaiting)(...args)
|
|
50
|
-
const toastId = t === null
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
const toastId: ToastId | undefined = t === null
|
|
60
|
+
? stableToastId
|
|
61
|
+
: stableToastId ?? `wait-${Math.random().toString(36).slice(2)}`
|
|
62
|
+
|
|
63
|
+
const waitingFiber = t === null ? undefined : yield* Effect.forkChild(
|
|
64
|
+
Effect.sleep("1 seconds").pipe(
|
|
65
|
+
Effect.andThen(toast.info(t, { id: toastId!, timeout: Infinity, ...meta }))
|
|
66
|
+
)
|
|
53
67
|
)
|
|
68
|
+
const interruptWaiting = waitingFiber ? Fiber.interrupt(waitingFiber) : Effect.void
|
|
69
|
+
|
|
54
70
|
return yield* self.pipe(
|
|
55
71
|
Effect.tap(Effect.fnUntraced(function*(a) {
|
|
72
|
+
yield* interruptWaiting
|
|
56
73
|
const t = yield* wrapEffect(options.onSuccess)(a, ...args)
|
|
57
74
|
if (t === null) {
|
|
58
75
|
return
|
|
59
76
|
}
|
|
60
77
|
yield* toast.success(
|
|
61
78
|
t,
|
|
62
|
-
toastId !== undefined
|
|
79
|
+
toastId !== undefined
|
|
80
|
+
? { id: toastId, timeout: baseTimeout, ...meta }
|
|
81
|
+
: { timeout: baseTimeout, ...meta }
|
|
63
82
|
)
|
|
64
83
|
})),
|
|
65
84
|
Effect.tapCause(Effect.fnUntraced(function*(cause) {
|
|
85
|
+
yield* interruptWaiting
|
|
66
86
|
yield* Effect.logDebug(
|
|
67
87
|
"WithToast - caught error cause: " + Cause.squash(cause),
|
|
68
88
|
Cause.hasInterruptsOnly(cause),
|
|
@@ -74,15 +94,23 @@ export class WithToast extends ServiceMap.Service<WithToast>()("WithToast", {
|
|
|
74
94
|
return
|
|
75
95
|
}
|
|
76
96
|
|
|
97
|
+
const spanInfo = options.showSpanInfo !== false
|
|
98
|
+
? yield* Effect.currentSpan.pipe(
|
|
99
|
+
Effect.map((span) => `\nTrace: ${span.traceId}\nSpan: ${span.spanId}`),
|
|
100
|
+
Effect.orElseSucceed(() => "")
|
|
101
|
+
)
|
|
102
|
+
: ""
|
|
103
|
+
|
|
77
104
|
const t = yield* wrapEffect(options.onFailure)(Cause.findErrorOption(cause), ...args)
|
|
78
|
-
const opts = { timeout: baseTimeout * 2 }
|
|
105
|
+
const opts = { timeout: baseTimeout * 2, ...meta }
|
|
79
106
|
|
|
80
107
|
if (typeof t === "object") {
|
|
108
|
+
const message = t.message + spanInfo
|
|
81
109
|
return t.level === "warn"
|
|
82
|
-
? yield* toast.warning(
|
|
83
|
-
: yield* toast.error(
|
|
110
|
+
? yield* toast.warning(message, toastId !== undefined ? { ...opts, id: toastId } : opts)
|
|
111
|
+
: yield* toast.error(message, toastId !== undefined ? { ...opts, id: toastId } : opts)
|
|
84
112
|
}
|
|
85
|
-
yield* toast.error(t, toastId !== undefined ? { ...opts, id: toastId } : opts)
|
|
113
|
+
yield* toast.error(t + spanInfo, toastId !== undefined ? { ...opts, id: toastId } : opts)
|
|
86
114
|
}, Effect.uninterruptible)),
|
|
87
115
|
toastId !== undefined ? Effect.provideService(CurrentToastId, CurrentToastId.of({ toastId })) : (_) => _
|
|
88
116
|
)
|
package/test/Mutation.test.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import { it } from "@effect/vitest"
|
|
3
3
|
import { Cause, Effect, Exit, Fiber, Option } from "effect-app"
|
|
4
|
-
import {
|
|
4
|
+
import { TestClock } from "effect/testing"
|
|
5
|
+
import { CommandContext, DefaultIntl } from "../src/commander.js"
|
|
5
6
|
import { AsyncResult } from "../src/lib.js"
|
|
6
|
-
import { useExperimental } from "./stubs.js"
|
|
7
|
+
import { useExperimental, useExperimentalE } from "./stubs.js"
|
|
7
8
|
|
|
8
9
|
const unwrap = <A, E>(r: Fiber.Fiber<Exit.Exit<A, E>, never>) => Fiber.join(r).pipe(Effect.flatten)
|
|
9
10
|
|
|
@@ -71,7 +72,10 @@ describe("alt2", () => {
|
|
|
71
72
|
expect(yield* Effect.currentSpan.pipe(Effect.map((_) => _.name))).toBe("Test Action")
|
|
72
73
|
})),
|
|
73
74
|
Effect.tap(() =>
|
|
74
|
-
Effect.currentSpan.pipe(
|
|
75
|
+
Effect.currentSpan.pipe(
|
|
76
|
+
Effect.map((_) => _.name),
|
|
77
|
+
Effect.tap((_) => Effect.sync(() => expect(_).toBe("Test Action")))
|
|
78
|
+
)
|
|
75
79
|
),
|
|
76
80
|
Effect.tap(() => Effect.sync(() => executed = true))
|
|
77
81
|
)
|
|
@@ -125,7 +129,10 @@ it.live("works", () =>
|
|
|
125
129
|
expect(yield* Effect.currentSpan.pipe(Effect.map((_) => _.name))).toBe("Test Action")
|
|
126
130
|
})),
|
|
127
131
|
Effect.tap(() =>
|
|
128
|
-
Effect.currentSpan.pipe(
|
|
132
|
+
Effect.currentSpan.pipe(
|
|
133
|
+
Effect.map((_) => _.name),
|
|
134
|
+
Effect.tap((_) => Effect.sync(() => expect(_).toBe("Test Action")))
|
|
135
|
+
)
|
|
129
136
|
),
|
|
130
137
|
Effect.tap(() => Effect.sync(() => executed = true))
|
|
131
138
|
)
|
|
@@ -175,7 +182,10 @@ it.live("works non-gen", () =>
|
|
|
175
182
|
expect(yield* Effect.currentSpan.pipe(Effect.map((_) => _.name))).toBe("Test Action")
|
|
176
183
|
})),
|
|
177
184
|
Effect.tap(() =>
|
|
178
|
-
Effect.currentSpan.pipe(
|
|
185
|
+
Effect.currentSpan.pipe(
|
|
186
|
+
Effect.map((_) => _.name),
|
|
187
|
+
Effect.tap((_) => Effect.sync(() => expect(_).toBe("Test Action")))
|
|
188
|
+
)
|
|
179
189
|
),
|
|
180
190
|
Effect.tap(() => Effect.sync(() => executed = true))
|
|
181
191
|
)
|
|
@@ -308,8 +318,8 @@ it.live("with toasts", () =>
|
|
|
308
318
|
function*() {
|
|
309
319
|
expect(yield* Effect.currentSpan.pipe(Effect.map((_) => _.name))).toBe("Test Action")
|
|
310
320
|
|
|
311
|
-
|
|
312
|
-
expect(toasts
|
|
321
|
+
// fast actions complete before the 1s waiting-toast delay, so no waiting toast is shown
|
|
322
|
+
expect(toasts.length).toBe(0)
|
|
313
323
|
|
|
314
324
|
return "test-value"
|
|
315
325
|
},
|
|
@@ -317,7 +327,10 @@ it.live("with toasts", () =>
|
|
|
317
327
|
expect(yield* Effect.currentSpan.pipe(Effect.map((_) => _.name))).toBe("Test Action")
|
|
318
328
|
})),
|
|
319
329
|
Effect.tap(() =>
|
|
320
|
-
Effect.currentSpan.pipe(
|
|
330
|
+
Effect.currentSpan.pipe(
|
|
331
|
+
Effect.map((_) => _.name),
|
|
332
|
+
Effect.tap((_) => Effect.sync(() => expect(_).toBe("Test Action")))
|
|
333
|
+
)
|
|
321
334
|
),
|
|
322
335
|
// WithToast.handle({
|
|
323
336
|
// onFailure: "failed",
|
|
@@ -346,7 +359,7 @@ it.live("interrupted", () =>
|
|
|
346
359
|
|
|
347
360
|
const command = Command.fn("Test Action")(
|
|
348
361
|
function*() {
|
|
349
|
-
expect(toasts.length).toBe(
|
|
362
|
+
expect(toasts.length).toBe(0)
|
|
350
363
|
yield* Effect.interrupt
|
|
351
364
|
return "test-value"
|
|
352
365
|
},
|
|
@@ -373,7 +386,7 @@ it.live("fail", () =>
|
|
|
373
386
|
|
|
374
387
|
const command = Command.fn("Test Action")(
|
|
375
388
|
function*() {
|
|
376
|
-
expect(toasts.length).toBe(
|
|
389
|
+
expect(toasts.length).toBe(0)
|
|
377
390
|
return yield* Effect.fail({ message: "Boom!" })
|
|
378
391
|
},
|
|
379
392
|
Command.withDefaultToast(),
|
|
@@ -388,9 +401,30 @@ it.live("fail", () =>
|
|
|
388
401
|
expect(command.waiting).toBe(false)
|
|
389
402
|
expect(Exit.isFailure(AsyncResult.toExit(command.result))).toBe(true)
|
|
390
403
|
expect(toasts.length).toBe(1) // toast should show error
|
|
391
|
-
expect(toasts[0].
|
|
404
|
+
expect(toasts[0].type).toBe("warning")
|
|
405
|
+
expect(toasts[0].message).toContain("Test Action Failed:\nBoom!")
|
|
406
|
+
expect(toasts[0].message).toMatch(/Trace: [a-f0-9]{32}/)
|
|
407
|
+
expect(toasts[0].message).toMatch(/Span: [a-f0-9]{16}/)
|
|
392
408
|
}))
|
|
393
409
|
|
|
410
|
+
it.live("fail with showSpanInfo disabled", () =>
|
|
411
|
+
Effect
|
|
412
|
+
.gen(function*() {
|
|
413
|
+
const toasts: any[] = []
|
|
414
|
+
const Command = useExperimental({ toasts, messages: DefaultIntl.en })
|
|
415
|
+
|
|
416
|
+
const command = Command.fn("Test Action")(
|
|
417
|
+
function*() {
|
|
418
|
+
return yield* Effect.fail({ message: "Boom!" })
|
|
419
|
+
},
|
|
420
|
+
Command.withDefaultToast({ showSpanInfo: false })
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
yield* Fiber.join(command.handle())
|
|
424
|
+
|
|
425
|
+
expect(toasts.length).toBe(1)
|
|
426
|
+
expect(toasts[0].message).toBe("Test Action Failed:\nBoom!")
|
|
427
|
+
}))
|
|
394
428
|
it.live("fail and recover", () =>
|
|
395
429
|
Effect
|
|
396
430
|
.gen(function*() {
|
|
@@ -400,7 +434,7 @@ it.live("fail and recover", () =>
|
|
|
400
434
|
|
|
401
435
|
const command = Command.fn("Test Action")(
|
|
402
436
|
function*() {
|
|
403
|
-
expect(toasts.length).toBe(
|
|
437
|
+
expect(toasts.length).toBe(0)
|
|
404
438
|
return yield* Effect.fail({ message: "Boom!" })
|
|
405
439
|
},
|
|
406
440
|
Effect.orElseSucceed(() => "recovered"), // we recover from the error here, so the final result is success
|
|
@@ -428,7 +462,7 @@ it.live("defect", () =>
|
|
|
428
462
|
|
|
429
463
|
const command = Command.fn("Test Action")(
|
|
430
464
|
function*() {
|
|
431
|
-
expect(toasts.length).toBe(
|
|
465
|
+
expect(toasts.length).toBe(0)
|
|
432
466
|
return yield* Effect.die({ message: "Boom!" })
|
|
433
467
|
},
|
|
434
468
|
Command.withDefaultToast(),
|
|
@@ -444,7 +478,8 @@ it.live("defect", () =>
|
|
|
444
478
|
expect(command.waiting).toBe(false)
|
|
445
479
|
expect(Exit.isFailure(AsyncResult.toExit(command.result))).toBe(true)
|
|
446
480
|
expect(toasts.length).toBe(1) // toast should show error
|
|
447
|
-
expect(toasts[0].
|
|
481
|
+
expect(toasts[0].type).toBe("error")
|
|
482
|
+
expect(toasts[0].message).toContain("Test Action unexpected error, please try again shortly.")
|
|
448
483
|
}))
|
|
449
484
|
|
|
450
485
|
it.live("works with alt", () =>
|
|
@@ -471,7 +506,10 @@ it.live("works with alt", () =>
|
|
|
471
506
|
expect(yield* Effect.currentSpan.pipe(Effect.map((_) => _.name))).toBe("Test Action")
|
|
472
507
|
})),
|
|
473
508
|
Effect.tap(() =>
|
|
474
|
-
Effect.currentSpan.pipe(
|
|
509
|
+
Effect.currentSpan.pipe(
|
|
510
|
+
Effect.map((_) => _.name),
|
|
511
|
+
Effect.tap((_) => Effect.sync(() => expect(_).toBe("Test Action")))
|
|
512
|
+
)
|
|
475
513
|
),
|
|
476
514
|
Effect.tap(() => Effect.sync(() => executed = true))
|
|
477
515
|
)
|
|
@@ -615,8 +653,8 @@ it.live("with toasts with alt", () =>
|
|
|
615
653
|
function*() {
|
|
616
654
|
expect(yield* Effect.currentSpan.pipe(Effect.map((_) => _.name))).toBe("Test Action")
|
|
617
655
|
|
|
618
|
-
|
|
619
|
-
expect(toasts
|
|
656
|
+
// fast actions complete before the 1s waiting-toast delay, so no waiting toast is shown
|
|
657
|
+
expect(toasts.length).toBe(0)
|
|
620
658
|
|
|
621
659
|
return "test-value"
|
|
622
660
|
},
|
|
@@ -624,7 +662,10 @@ it.live("with toasts with alt", () =>
|
|
|
624
662
|
expect(yield* Effect.currentSpan.pipe(Effect.map((_) => _.name))).toBe("Test Action")
|
|
625
663
|
})),
|
|
626
664
|
Effect.tap(() =>
|
|
627
|
-
Effect.currentSpan.pipe(
|
|
665
|
+
Effect.currentSpan.pipe(
|
|
666
|
+
Effect.map((_) => _.name),
|
|
667
|
+
Effect.tap((_) => Effect.sync(() => expect(_).toBe("Test Action")))
|
|
668
|
+
)
|
|
628
669
|
),
|
|
629
670
|
Command.withDefaultToast(),
|
|
630
671
|
Effect.tap(() => Effect.sync(() => executed = true))
|
|
@@ -650,7 +691,7 @@ it.live("interrupted with alt", () =>
|
|
|
650
691
|
const command = Command.alt("Test Action")(
|
|
651
692
|
Effect.fnUntraced(
|
|
652
693
|
function*() {
|
|
653
|
-
expect(toasts.length).toBe(
|
|
694
|
+
expect(toasts.length).toBe(0)
|
|
654
695
|
// @effect-diagnostics-next-line missingReturnYieldStar:off
|
|
655
696
|
yield* Effect.interrupt
|
|
656
697
|
return "test-value"
|
|
@@ -680,7 +721,7 @@ it.live("fail with alt", () =>
|
|
|
680
721
|
const command = Command.alt("Test Action")(
|
|
681
722
|
Effect.fnUntraced(
|
|
682
723
|
function*() {
|
|
683
|
-
expect(toasts.length).toBe(
|
|
724
|
+
expect(toasts.length).toBe(0)
|
|
684
725
|
return yield* Effect.fail({ message: "Boom!" })
|
|
685
726
|
},
|
|
686
727
|
Command.withDefaultToast(),
|
|
@@ -696,7 +737,8 @@ it.live("fail with alt", () =>
|
|
|
696
737
|
expect(command.waiting).toBe(false)
|
|
697
738
|
expect(Exit.isFailure(AsyncResult.toExit(command.result))).toBe(true)
|
|
698
739
|
expect(toasts.length).toBe(1) // toast should show error
|
|
699
|
-
expect(toasts[0].
|
|
740
|
+
expect(toasts[0].type).toBe("warning")
|
|
741
|
+
expect(toasts[0].message).toContain("Test Action Failed:\nBoom!")
|
|
700
742
|
}))
|
|
701
743
|
|
|
702
744
|
it.live("fail and recover with alt", () =>
|
|
@@ -709,7 +751,7 @@ it.live("fail and recover with alt", () =>
|
|
|
709
751
|
const command = Command.alt("Test Action")(
|
|
710
752
|
Effect.fnUntraced(
|
|
711
753
|
function*() {
|
|
712
|
-
expect(toasts.length).toBe(
|
|
754
|
+
expect(toasts.length).toBe(0)
|
|
713
755
|
return yield* Effect.fail({ message: "Boom!" })
|
|
714
756
|
},
|
|
715
757
|
Effect.orElseSucceed(() => "recovered"), // we recover from the error here, so the final result is success
|
|
@@ -729,6 +771,64 @@ it.live("fail and recover with alt", () =>
|
|
|
729
771
|
expect(toasts[0].message).toBe("Test Action Success")
|
|
730
772
|
}))
|
|
731
773
|
|
|
774
|
+
it.effect("slow action shows waiting toast after the 1s delay", () =>
|
|
775
|
+
Effect
|
|
776
|
+
.gen(function*() {
|
|
777
|
+
const toasts: any[] = []
|
|
778
|
+
const Command = yield* useExperimentalE({ toasts, messages: DefaultIntl.en })
|
|
779
|
+
|
|
780
|
+
const command = Command.fn("Test Action")(
|
|
781
|
+
function*() {
|
|
782
|
+
// before 1s the waiting toast must NOT have surfaced yet
|
|
783
|
+
expect(toasts.length).toBe(0)
|
|
784
|
+
yield* Effect.sleep("1100 millis")
|
|
785
|
+
// after the delay window the waiting info toast should be visible
|
|
786
|
+
expect(toasts.length).toBe(1)
|
|
787
|
+
expect(toasts[0].type).toBe("info")
|
|
788
|
+
expect(toasts[0].message).toBe("Test Action executing...")
|
|
789
|
+
return "test-value"
|
|
790
|
+
},
|
|
791
|
+
Command.withDefaultToast()
|
|
792
|
+
)
|
|
793
|
+
|
|
794
|
+
const fiber = command.handle()
|
|
795
|
+
yield* TestClock.adjust("2 seconds")
|
|
796
|
+
const r = yield* unwrap(fiber)
|
|
797
|
+
|
|
798
|
+
expect(r).toBe("test-value")
|
|
799
|
+
// waiting toast is replaced (same id) with the success toast
|
|
800
|
+
expect(toasts.length).toBe(1)
|
|
801
|
+
expect(toasts[0].type).toBe("success")
|
|
802
|
+
expect(toasts[0].message).toBe("Test Action Success")
|
|
803
|
+
}))
|
|
804
|
+
|
|
805
|
+
it.effect("slow failing action surfaces waiting toast then shows error", () =>
|
|
806
|
+
Effect
|
|
807
|
+
.gen(function*() {
|
|
808
|
+
const toasts: any[] = []
|
|
809
|
+
const Command = yield* useExperimentalE({ toasts, messages: DefaultIntl.en })
|
|
810
|
+
|
|
811
|
+
const command = Command.fn("Test Action")(
|
|
812
|
+
function*() {
|
|
813
|
+
expect(toasts.length).toBe(0)
|
|
814
|
+
yield* Effect.sleep("1100 millis")
|
|
815
|
+
expect(toasts.length).toBe(1)
|
|
816
|
+
expect(toasts[0].type).toBe("info")
|
|
817
|
+
return yield* Effect.fail({ message: "Boom!" })
|
|
818
|
+
},
|
|
819
|
+
Command.withDefaultToast()
|
|
820
|
+
)
|
|
821
|
+
|
|
822
|
+
const fiber = command.handle()
|
|
823
|
+
yield* TestClock.adjust("2 seconds")
|
|
824
|
+
const r = yield* Fiber.join(fiber)
|
|
825
|
+
|
|
826
|
+
expect(Exit.isFailure(r) && Cause.hasFails(r.cause)).toBe(true)
|
|
827
|
+
expect(toasts.length).toBe(1)
|
|
828
|
+
expect(toasts[0].type).toBe("warning")
|
|
829
|
+
expect(toasts[0].message).toContain("Test Action Failed:\nBoom!")
|
|
830
|
+
}))
|
|
831
|
+
|
|
732
832
|
it.live("defect with alt", () =>
|
|
733
833
|
Effect
|
|
734
834
|
.gen(function*() {
|
|
@@ -756,5 +856,58 @@ it.live("defect with alt", () =>
|
|
|
756
856
|
expect(command.waiting).toBe(false)
|
|
757
857
|
expect(Exit.isFailure(AsyncResult.toExit(command.result))).toBe(true)
|
|
758
858
|
expect(toasts.length).toBe(1) // toast should show error
|
|
759
|
-
expect(toasts[0].
|
|
859
|
+
expect(toasts[0].type).toBe("error")
|
|
860
|
+
expect(toasts[0].message).toContain("Test Action unexpected error, please try again shortly.")
|
|
760
861
|
}))
|
|
862
|
+
|
|
863
|
+
describe("state-in-toast", () => {
|
|
864
|
+
it("works", () => {
|
|
865
|
+
const toasts: any[] = []
|
|
866
|
+
const removeMutation = Object.assign(
|
|
867
|
+
Effect.fn(function*(_item: string) {
|
|
868
|
+
yield* Effect.sleep(1000)
|
|
869
|
+
}),
|
|
870
|
+
{ id: "remove_thing" }
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
const item = "x"
|
|
874
|
+
|
|
875
|
+
const Command = useExperimental({ toasts, messages: DefaultIntl.en })
|
|
876
|
+
|
|
877
|
+
Command.fn(removeMutation, {
|
|
878
|
+
state: () => ({ item }),
|
|
879
|
+
waitKey: (id) => `${id}.${item}`,
|
|
880
|
+
blockKey: () => `modify_thing.${item}`
|
|
881
|
+
// allowed: () => role.value === "admin"
|
|
882
|
+
})(
|
|
883
|
+
function*() {
|
|
884
|
+
// yield* Command.confirmOrInterrupt(yield* I18n.formatMessage({ id: "confirm.remove_item" }, { item }))
|
|
885
|
+
yield* removeMutation(item)
|
|
886
|
+
},
|
|
887
|
+
Command.withDefaultToast({
|
|
888
|
+
onSuccess: (a, b, c, d) => {
|
|
889
|
+
console.log("Success", { a, b, c, d })
|
|
890
|
+
expectTypeOf(d.state).toEqualTypeOf<{ readonly item: "x" }>()
|
|
891
|
+
}
|
|
892
|
+
})
|
|
893
|
+
)
|
|
894
|
+
|
|
895
|
+
Command.fn(removeMutation, {
|
|
896
|
+
state: () => ({ item }),
|
|
897
|
+
waitKey: (id) => `${id}.${item}`,
|
|
898
|
+
blockKey: () => `modify_thing.${item}`
|
|
899
|
+
// allowed: () => role.value === "admin"
|
|
900
|
+
})(
|
|
901
|
+
function*() {
|
|
902
|
+
// yield* Command.confirmOrInterrupt(yield* I18n.formatMessage({ id: "confirm.remove_item" }, { item }))
|
|
903
|
+
yield* removeMutation(item)
|
|
904
|
+
},
|
|
905
|
+
Command.withDefaultToast({
|
|
906
|
+
onSuccess: (a, b, c) => {
|
|
907
|
+
console.log("Success", { a, b, c })
|
|
908
|
+
expectTypeOf(c).toEqualTypeOf<undefined>()
|
|
909
|
+
}
|
|
910
|
+
})
|
|
911
|
+
)
|
|
912
|
+
})
|
|
913
|
+
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.test.d.ts","sourceRoot":"","sources":["../form.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,CAAC,EAAE,MAAM,YAAY,CAAA
|
|
1
|
+
{"version":3,"file":"form.test.d.ts","sourceRoot":"","sources":["../form.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,CAAC,EAAE,MAAM,YAAY,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGtC,qBAAa,YAAa,SAAQ,iBAahC;CAAG;;;;AAEL,qBAAa,mBAAoB,SAAQ,wBAEvC;CAAG;;;;;;;;;;;;AAEL,qBAAa,WAAY,SAAQ,gBAK/B;CAAG;;;;;;;;AAEL,cAAM,MAAO,SAAQ,WAEnB;CAAG;;;;;;;;AAEL,cAAM,MAAO,SAAQ,WAEnB;CAAG;;;;;;;;;;;;AAEL,cAAM,QAAS,SAAQ,aAGrB;CAAG;;;;;;;;;;;;;;;;;;;;;;;;AAqBL,qBAAa,cAAe,SAAQ,mBAGlC;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lib.test.d.ts","sourceRoot":"","sources":["../lib.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamFinal.test.d.ts","sourceRoot":"","sources":["../streamFinal.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamFn.test.d.ts","sourceRoot":"","sources":["../streamFn.test.ts"],"names":[],"mappings":""}
|