t-tasks 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/either.ts CHANGED
@@ -64,6 +64,7 @@ export interface Right<R, L> {
64
64
  * Applied to 'right value' returns self without invoking transformer
65
65
  * Applied to 'left error' returns 'right op(error)'
66
66
  *
67
+ * @template R2 transformer function's return type
67
68
  * @param op transformer to be invoked with underlying error
68
69
  * @returns 'right value' or 'right op(error)'
69
70
  */
@@ -89,6 +90,18 @@ export interface Right<R, L> {
89
90
  // General case
90
91
  match<R2, R3 = R2>(this: Either<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): R2 | R3;
91
92
 
93
+ /**
94
+ * Either pattern matching transformer function
95
+ *
96
+ * Applied to 'right value' returns 'right op.right(value)'
97
+ * Applied to 'left error' returns 'right op.left(error)'
98
+ *
99
+ * @template R2 right transformer function's return type
100
+ * @template R3 left transformer function's return type
101
+ * @param op.right transformer to be invoked with underlying value in case of 'right'
102
+ * @param op.left transformer to be invoked with underlying error in case of 'left'
103
+ * @returns 'right op.right(value)' or 'right op.left(error)'
104
+ */
92
105
  // Right case
93
106
  matchMap<R2, R3 = R2>(this: Right<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): Right<R2, never>;
94
107
  // General case
@@ -115,7 +128,7 @@ export interface Right<R, L> {
115
128
  chain<R2, L2>(this: Either<R, L>, op: (value: R) => Either<R2, L2>): Either<R2, L | L2>;
116
129
 
117
130
  /**
118
- * Either composition function
131
+ * Either fallback composition function
119
132
  *
120
133
  * Applied to 'right value' returns self without invoking composition function
121
134
  * Applied to 'left error' returns 'op(error)'
@@ -146,7 +159,7 @@ export interface Right<R, L> {
146
159
  * @template L3 left transformer function result's underlying error type
147
160
  * @param op.right transformer to be invoked with underlying value in case of 'right'
148
161
  * @param op.left transformer to be invoked with underlying error in case of 'left'
149
- * @returns 'op(value)' or 'op(error)'
162
+ * @returns 'op.right(value)' or 'op.left(error)'
150
163
  */
151
164
  // Right cases
152
165
  matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Right<R3, L3> }): Right<R2, never>;
@@ -273,6 +286,7 @@ export interface Left<R, L> {
273
286
  * Applied to 'right value' returns self without invoking transformer
274
287
  * Applied to 'left error' returns 'right op(error)'
275
288
  *
289
+ * @template R2 transformer function's return type
276
290
  * @param op transformer to be invoked with underlying error
277
291
  * @returns 'right value' or 'right op(error)'
278
292
  */
@@ -298,6 +312,18 @@ export interface Left<R, L> {
298
312
  // General case
299
313
  match<R2, R3 = R2>(this: Either<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): R2 | R3;
300
314
 
315
+ /**
316
+ * Either pattern matching transformer function
317
+ *
318
+ * Applied to 'right value' returns 'right op.right(value)'
319
+ * Applied to 'left error' returns 'right op.left(error)'
320
+ *
321
+ * @template R2 right transformer function's return type
322
+ * @template R3 left transformer function's return type
323
+ * @param op.right transformer to be invoked with underlying value in case of 'right'
324
+ * @param op.left transformer to be invoked with underlying error in case of 'left'
325
+ * @returns 'right op.right(value)' or 'right op.left(error)'
326
+ */
301
327
  // Left case
302
328
  matchMap<R2, R3 = R2>(this: Left<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): Right<R3, never>;
303
329
  // General case
@@ -355,7 +381,7 @@ export interface Left<R, L> {
355
381
  * @template L3 left transformer function result's underlying error type
356
382
  * @param op.right transformer to be invoked with underlying value in case of 'right'
357
383
  * @param op.left transformer to be invoked with underlying error in case of 'left'
358
- * @returns 'op(value)' or 'op(error)'
384
+ * @returns 'op.right(value)' or 'op.left(error)'
359
385
  */
360
386
  // Left cases
361
387
  matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Right<R3, L3> }): Right<R3, never>;
@@ -459,7 +485,23 @@ export namespace Left {
459
485
  }
460
486
  }
461
487
 
488
+ /**
489
+ * Either generator
490
+ *
491
+ * @template T yielded underlying type
492
+ * @template TT yielded Either type
493
+ * @template R returned underlying type
494
+ */
462
495
  export type EitherGenerator<T, TT extends Either<T, any>, R> = Generator<TT, R, T>;
496
+
497
+ /**
498
+ * Function returning Either generator (generator function)
499
+ *
500
+ * @template A argument types
501
+ * @template T yielded underlying type
502
+ * @template TT yielded Either type
503
+ * @template R returned underlying type
504
+ */
463
505
  export type EitherGeneratorFunction<A extends unknown[], T, TT extends Either<T, any>, R> = (...args: A) => EitherGenerator<T, TT, R>;
464
506
 
465
507
  export namespace Either {
@@ -490,6 +532,8 @@ export namespace Either {
490
532
  *
491
533
  * Resolves to 'left error' in case of undefined value and 'right value' otherwise
492
534
  *
535
+ * @template R underlying value type
536
+ * @template L underlying error type
493
537
  * @param value possibly undefined value
494
538
  * @param error error to use in case of undefined value
495
539
  * @returns either 'right value' or 'left error'
@@ -506,8 +550,10 @@ export namespace Either {
506
550
  *
507
551
  * Resolves to 'left error' in case of undefined or null value and 'right value' otherwise
508
552
  *
509
- * @param value possibly undefined or nullable value
510
- * @param error error to use in case of undefined or nullable value
553
+ * @template R underlying value type
554
+ * @template L underlying error type
555
+ * @param value possibly undefined or null value
556
+ * @param error error to use in case of undefined or null value
511
557
  * @returns either 'right value' or 'left error'
512
558
  */
513
559
  export function fromNullable<L>(value: undefined, error: L): Left<never, L>;
@@ -544,6 +590,7 @@ export namespace Either {
544
590
  * Useful for passing as a predicate to collection transformers
545
591
  *
546
592
  * @template R underlying value type
593
+ * @template L underlying error type
547
594
  * @param either Either instance
548
595
  * @returns 'true' in case argument is 'right value' (and resolves type to be 'right')
549
596
  */
@@ -557,6 +604,7 @@ export namespace Either {
557
604
  * Useful for passing as a predicate to collection transformers
558
605
  *
559
606
  * @template R underlying value type
607
+ * @template L underlying error type
560
608
  * @param either Either instance
561
609
  * @returns 'true' in case argument is 'left error' (and resolves type to be 'left')
562
610
  */
@@ -567,6 +615,8 @@ export namespace Either {
567
615
  /**
568
616
  * Standalone list predicate
569
617
  *
618
+ * @template R underlying value type
619
+ * @template L underlying error type
570
620
  * @param eithers a list of Either
571
621
  * @returns true in case every list element is Right
572
622
  */
@@ -577,6 +627,8 @@ export namespace Either {
577
627
  /**
578
628
  * Standalone list predicate
579
629
  *
630
+ * @template R underlying value type
631
+ * @template L underlying error type
580
632
  * @param eithers a list of Either
581
633
  * @returns true in case at least one list element is Right
582
634
  */
@@ -587,6 +639,8 @@ export namespace Either {
587
639
  /**
588
640
  * Standalone list predicate
589
641
  *
642
+ * @template R underlying value type
643
+ * @template L underlying error type
590
644
  * @param eithers a list of Either
591
645
  * @returns true in case every list element is Left
592
646
  */
@@ -597,6 +651,8 @@ export namespace Either {
597
651
  /**
598
652
  * Standalone list predicate
599
653
  *
654
+ * @template R underlying value type
655
+ * @template L underlying error type
600
656
  * @param eithers a list of Either
601
657
  * @returns true in case at least one list element is Left
602
658
  */
@@ -610,6 +666,7 @@ export namespace Either {
610
666
  * Applying yield to an Either within the generator function unwraps the Either and returns underlying value in case of success
611
667
  * However the convenient option for typescript is to use ```yield* either.generator()``` as otherwise one may have to deal with union types
612
668
  *
669
+ * @template T yielded underlying type
613
670
  * @template TT yielded Either type
614
671
  * @template R returned underlying type
615
672
  * @param eitherGeneratorFunction Either generator function
package/src/maybe.ts CHANGED
@@ -63,6 +63,7 @@ export interface Just<R> {
63
63
  * Applied to 'just value' returns self without invoking transformer
64
64
  * Applied to 'nothing' returns 'just op()'
65
65
  *
66
+ * @template R2 transformer function's return type
66
67
  * @param op function to be invoked
67
68
  * @returns 'just value' or 'just op()'
68
69
  */
@@ -88,7 +89,19 @@ export interface Just<R> {
88
89
  // General case
89
90
  match<R2, R3 = R2>(this: Maybe<R>, op: { just: (value: R) => R2; nothing: () => R3 }): R2 | R3;
90
91
 
91
- // Nothing cases
92
+ /**
93
+ * Maybe pattern matching transformer function
94
+ *
95
+ * Applied to 'just value' returns 'just op.just(value)'
96
+ * Applied to 'nothing' returns 'just op.nothing()'
97
+ *
98
+ * @template R2 just transformer function's return type
99
+ * @template R3 nothing transformer function's return type
100
+ * @param op.just transformer to be invoked with underlying value in case of just
101
+ * @param op.nothing transformer to be invoked in case of nothing
102
+ * @returns 'just op.just(value)' or 'just op.nothing()'
103
+ */
104
+ // Just cases
92
105
  matchMap<R2, R3 = R2>(this: Just<R>, op: { just: (value: R) => R2; nothing: () => R3 }): Just<R2>;
93
106
  // General case
94
107
  matchMap<R2, R3 = R2>(this: Maybe<R>, op: { just: (value: R) => R2; nothing: () => R3 }): Just<R2 | R3>;
@@ -207,6 +220,8 @@ export interface Just<R> {
207
220
  * Absolutely Nothing
208
221
  *
209
222
  * Maybe data type specialization representing an absence of any value
223
+ *
224
+ * @template R underlying value
210
225
  */
211
226
  export interface Nothing<R> {
212
227
  /**
@@ -264,6 +279,7 @@ export interface Nothing<R> {
264
279
  * Applied to 'just value' returns self without invoking transformer
265
280
  * Applied to 'nothing' returns 'just op()'
266
281
  *
282
+ * @template R2 transformer function's return type
267
283
  * @param op function to be invoked
268
284
  * @returns 'just value' or 'just op()'
269
285
  */
@@ -289,7 +305,19 @@ export interface Nothing<R> {
289
305
  // General case
290
306
  match<R2, R3 = R2>(this: Maybe<R>, op: { just: (value: R) => R2; nothing: () => R3 }): R2 | R3;
291
307
 
292
- // Just cases
308
+ /**
309
+ * Maybe pattern matching transformer function
310
+ *
311
+ * Applied to 'just value' returns 'just op.just(value)'
312
+ * Applied to 'nothing' returns 'just op.nothing()'
313
+ *
314
+ * @template R2 just transformer function's return type
315
+ * @template R3 nothing transformer function's return type
316
+ * @param op.just transformer to be invoked with underlying value in case of just
317
+ * @param op.nothing transformer to be invoked in case of nothing
318
+ * @returns 'just op.just(value)' or 'just op.nothing()'
319
+ */
320
+ // Nothing cases
293
321
  matchMap<R2, R3 = R2>(this: Nothing<R>, op: { just: (value: R) => R2; nothing: () => R3 }): Just<R3>;
294
322
  // General case
295
323
  matchMap<R2, R3 = R2>(this: Maybe<R>, op: { just: (value: R) => R2; nothing: () => R3 }): Just<R2 | R3>;
@@ -430,7 +458,23 @@ export namespace Just {
430
458
 
431
459
  export namespace Nothing {}
432
460
 
461
+ /**
462
+ * Maybe generator
463
+ *
464
+ * @template T yielded underlying type
465
+ * @template TT yielded Maybe type
466
+ * @template R returned underlying type
467
+ */
433
468
  export type MaybeGenerator<T, TT extends Maybe<T>, R> = Generator<TT, R, T>;
469
+
470
+ /**
471
+ * Function returning Maybe generator (generator function)
472
+ *
473
+ * @template A argument types
474
+ * @template T yielded underlying type
475
+ * @template TT yielded Maybe type
476
+ * @template R returned underlying type
477
+ */
434
478
  export type MaybeGeneratorFunction<A extends unknown[], T, TT extends Maybe<T>, R> = (...args: A) => MaybeGenerator<T, TT, R>;
435
479
 
436
480
  export namespace Maybe {
@@ -459,6 +503,7 @@ export namespace Maybe {
459
503
  *
460
504
  * Resolves to 'nothing' in case of undefined value and 'just value' otherwise
461
505
  *
506
+ * @template R underlying type
462
507
  * @param value possibly undefined value
463
508
  * @returns either 'just value' or 'nothing'
464
509
  */
@@ -474,7 +519,8 @@ export namespace Maybe {
474
519
  *
475
520
  * Resolves to 'nothing' in case of undefined or null value and 'just value' otherwise
476
521
  *
477
- * @param value possibly undefined value
522
+ * @template R underlying type
523
+ * @param value possibly undefined or null value
478
524
  * @returns either 'just value' or 'nothing'
479
525
  */
480
526
  export function fromNullable(value: undefined): Nothing<never>;
@@ -533,6 +579,7 @@ export namespace Maybe {
533
579
  /**
534
580
  * Standalone list predicate
535
581
  *
582
+ * @template R underlying value type
536
583
  * @param maybes a list of Maybe
537
584
  * @returns true in case every list element is Just
538
585
  */
@@ -543,6 +590,7 @@ export namespace Maybe {
543
590
  /**
544
591
  * Standalone list predicate
545
592
  *
593
+ * @template R underlying value type
546
594
  * @param maybes a list of Maybe
547
595
  * @returns true in case at least one list element is Just
548
596
  */
@@ -553,6 +601,7 @@ export namespace Maybe {
553
601
  /**
554
602
  * Standalone list predicate
555
603
  *
604
+ * @template R underlying value type
556
605
  * @param maybes a list of Maybe
557
606
  * @returns true in case every list element is Nothing
558
607
  */
@@ -563,6 +612,7 @@ export namespace Maybe {
563
612
  /**
564
613
  * Standalone list predicate
565
614
  *
615
+ * @template R underlying value type
566
616
  * @param maybes a list of Maybe
567
617
  * @returns true in case at least one list element is Nothing
568
618
  */
@@ -576,6 +626,7 @@ export namespace Maybe {
576
626
  * Applying yield to a Maybe within the generator function unwraps the Maybe and returns underlying value in case of success
577
627
  * However the convenient option for typescript is to use ```yield* maybe.generator()``` as otherwise one may have to deal with union types
578
628
  *
629
+ * @template T yielded underlying type
579
630
  * @template TT yielded Maybe type
580
631
  * @template R returned underlying type
581
632
  * @param maybeGeneratorFunction Maybe generator function
package/src/task.ts CHANGED
@@ -26,6 +26,7 @@ export type TaskFunction<A extends unknown[], R> = (...args: A) => Task<R>;
26
26
  /**
27
27
  * Task generator
28
28
  *
29
+ * @template T yielded underlying type
29
30
  * @template TT yielded task type
30
31
  * @template R returned task resolve type
31
32
  *
@@ -44,6 +45,7 @@ export type TaskGenerator<T, TT extends Task<T>, R> = Generator<TT, R, T>;
44
45
  * Function returning task generator (generator function)
45
46
  *
46
47
  * @template A argument types
48
+ * @template T yielded underlying type
47
49
  * @template TT yielded task type
48
50
  * @template R returned task resolve type
49
51
  *
@@ -178,6 +180,11 @@ export interface Task<R> extends TaskBase<R> {
178
180
  */
179
181
  matchChain<R2, R3 = R2, R4 = R3>(op: { resolved: (value: R) => Task<R2>; rejected: (error: any) => Task<R3>; canceled: () => Task<R4> }): Task<R2 | R3 | R4>;
180
182
 
183
+ /**
184
+ * Read the settled result when the task has already finished
185
+ *
186
+ * @returns settled result, or null when the task is still pending
187
+ */
181
188
  resolved: () => Cancelable<R> | null;
182
189
 
183
190
  /**
@@ -188,14 +195,17 @@ export interface Task<R> extends TaskBase<R> {
188
195
  resolve: () => TaskInvoke<R>;
189
196
 
190
197
  /**
191
- * Invoke underlying canel method without error
198
+ * Invoke underlying cancel method without error
199
+ *
200
+ * @returns 'true' when the task was still pending and cancelation was applied
192
201
  */
193
202
  cancel: () => boolean;
194
203
 
195
204
  /**
196
- * Invoke underlying canel method with error
205
+ * Invoke underlying cancel method with error
197
206
  *
198
207
  * @param error error value to be injected from outside
208
+ * @returns 'true' when the task was still pending and the error was applied
199
209
  */
200
210
  reject: (error: any) => boolean;
201
211
 
@@ -263,7 +273,7 @@ export namespace Task {
263
273
  *
264
274
  * @template R returned task's resolve type
265
275
  * @param error error to be returned upon awaiting
266
- * @returns task resolving to specified value
276
+ * @returns task rejected with the specified error
267
277
  */
268
278
  export function rejected<R>(error: any): Task<R> {
269
279
  return new TaskClass<R>({ resolved: true, result: Maybe.just(Either.left(error)) });
@@ -273,7 +283,7 @@ export namespace Task {
273
283
  * Invariant task constructor creating canceled task
274
284
  *
275
285
  * @template R returned task's resolve type
276
- * @returns task resolving to specified value
286
+ * @returns canceled task
277
287
  */
278
288
  export function canceled<R>(): Task<R> {
279
289
  return new TaskClass<R>({ resolved: true, result: Maybe.nothing() });
@@ -350,10 +360,12 @@ export namespace Task {
350
360
  /**
351
361
  * Generic callback task
352
362
  *
353
- * Usefull for creating custom tasks from success and error callbacks and cancelaton function. Synchronous callbacks are not supported, @see fromFuction
363
+ * Usefull for creating custom tasks from success and error callbacks and cancelaton function. Synchronous callbacks are not supported, @see fromFunction
354
364
  *
365
+ * @template H cancelation handler type
366
+ * @template R returned task resolve type
355
367
  * @param create task body with success and error callbacks
356
- * @param cancel cancelation function intended for stopping task execution
368
+ * @param onCancel cancelation function intended for stopping task execution
357
369
  * @returns task resolving to success value
358
370
  *
359
371
  * @example
@@ -460,9 +472,8 @@ export namespace Task {
460
472
  /**
461
473
  * Convinience shortcut for yielding timers
462
474
  *
463
- * @template R returned generator resolve type
464
- * @param promise promise to be resolved
465
- * @returns generator to be be used with yield*
475
+ * @param delay duration in ms after that the generator resolves
476
+ * @returns generator to be used with yield*
466
477
  */
467
478
  export function timeoutGenerator(delay: number) {
468
479
  return Task.timeout(delay).generator();
@@ -500,6 +511,7 @@ export namespace Task {
500
511
  *
501
512
  * If error is not caught the task is interrupted and returns 'just left error' immediately. In case of cancelation the task is interrupted and returns 'nothing' immediately
502
513
  *
514
+ * @template T yielded underlying type
503
515
  * @template TT yielded task type
504
516
  * @template R returned task resolve type
505
517
  * @param taskGeneratorFunction task generator function
@@ -575,11 +587,12 @@ export namespace Task {
575
587
  *
576
588
  * Simplifies wrighting functions returning generated tasks
577
589
  *
578
- * @template Args generator arguments
590
+ * @template A generator arguments
591
+ * @template T yielded underlying type
579
592
  * @template TT yielded task type
580
593
  * @template R returned task resolve type
581
594
  * @param taskGeneratorFunction function* (...args) task generator function
582
- * @returns task resolving to generator's return type
595
+ * @returns task function resolving to generator's return type
583
596
  */
584
597
  export function generateFunction<A extends any[], T, TT extends Task<T>, R>(taskGeneratorFunction: TaskGeneratorFunction<A, T, TT, R>): TaskFunction<A, R> {
585
598
  return (...args: A) => generate(() => taskGeneratorFunction(...args));
@@ -609,6 +622,7 @@ export namespace Task {
609
622
  /**
610
623
  * Start multiple tasks one after another
611
624
  *
625
+ * @template T underlying task type
612
626
  * @param taskFunctions list of task functions (without arguments)
613
627
  * @returns composite task invoring every task in order and resolving to the list of results
614
628
  */
@@ -631,7 +645,7 @@ export namespace Task {
631
645
  *
632
646
  * @template T underlying task type
633
647
  * @param tasks iterable of tasks to execute
634
- * @retuirns task resolving to the list of results
648
+ * @returns task resolving to the list of results
635
649
  */
636
650
  export function all<T>(tasks: Iterable<Task<T>>) {
637
651
  const taskArray = Array.from(tasks);
@@ -677,7 +691,7 @@ export namespace Task {
677
691
  *
678
692
  * @template T underlying task type
679
693
  * @param tasks iterable of tasks to execute
680
- * @retuirns task resolving to the result of first successfull task
694
+ * @returns task resolving to the result of first successfull task
681
695
  */
682
696
  export function any<T>(tasks: Iterable<Task<T>>) {
683
697
  const cell = settleCell<Cancelable<T>>();
@@ -722,6 +736,7 @@ export namespace Task {
722
736
  * If the second task resolves sooner than the first, resulting task is canceled
723
737
  * Otherwise the resulting task resolves together with the first one
724
738
  *
739
+ * @template T underlying task type
725
740
  * @param task task to limit
726
741
  * @param limitTask limiting task
727
742
  * @returns task limites according to limitTask
@@ -736,7 +751,9 @@ export namespace Task {
736
751
  * Given task is re-generated in case of failure (both external and internal)
737
752
  * Resulting task is still cancelable by standard means
738
753
  *
754
+ * @template T underlying task type
739
755
  * @param taskFunction task preoducing function
756
+ * @returns task that retries until the produced task resolves
740
757
  */
741
758
  export function repeat<T>(taskFunction: TaskFunction<[], T>) {
742
759
  const sequentor = (): Task<T> => taskFunction().chainRejected(sequentor);
@@ -806,7 +823,7 @@ const settleCell = <T>(): SettleCell<T> => {
806
823
  };
807
824
  };
808
825
 
809
- function chainTaskMaybe<R, R2>(parent: TaskBase<R>, op: (value: Cancelable<R>) => Task<R2>) {
826
+ function chainTaskMaybe<R, R2>(parent: Task<R>, op: (value: Cancelable<R>) => Task<R2>): Task<R2> {
810
827
  const cell = settleCell<Cancelable<R2>>();
811
828
 
812
829
  let state:
@@ -862,36 +879,74 @@ function chainTaskMaybe<R, R2>(parent: TaskBase<R>, op: (value: Cancelable<R>) =
862
879
  });
863
880
  }
864
881
 
865
- function chainTaskEither<R, R2>(_task: TaskBase<R>, op: (value: Rejectable<R>) => Task<R2>) {
866
- return chainTaskMaybe<R, R2>(_task, (maybe) => maybe.map(op).orMap<Task<R2>>(Task.canceled).just);
867
- }
882
+ function mapTaskMaybe<R, R2>(parent: Task<R>, op: (value: Cancelable<R>) => Cancelable<R2>): Task<R2> {
883
+ const cell = settleCell<Cancelable<R2>>();
868
884
 
869
- function mapTaskMaybe<R, R2>(_task: TaskBase<R>, op: (value: Cancelable<R>) => Cancelable<R2>) {
870
- return chainTaskMaybe<R, R2>(_task, (maybe) => {
871
- return op(maybe).match<Task<R2>>({
872
- just: (either) =>
873
- either.match<Task<R2>>({
874
- right: Task.resolved,
875
- left: Task.rejected,
876
- }),
877
- nothing: Task.canceled,
878
- });
885
+ let state:
886
+ | { phase: 'parent' }
887
+ | { phase: 'transform', error: Maybe<any> | null }
888
+ | { phase: 'closed' } = { phase: 'parent' };
889
+
890
+ parent._invoke((result) => {
891
+ state = { phase: 'transform', error: null }
892
+
893
+ let value: Cancelable<R2> | null = null;
894
+ try {
895
+ value = op(result);
896
+ } catch (e) {
897
+ cell.resolve(Maybe.just(Either.left(e)));
898
+ state = { phase: 'closed' };
899
+ return;
900
+ }
901
+
902
+ const transformError = state.phase === 'transform' ? state.error : null;
903
+
904
+ if (transformError) {
905
+ cell.resolve(transformError.map(Either.left));
906
+ } else {
907
+ cell.resolve(value);
908
+ }
909
+
910
+ state = { phase: 'closed' };
911
+ });
912
+
913
+ return Task.create(cell.promise, (error) => {
914
+ if (cell.settled()) {
915
+ return false;
916
+ }
917
+
918
+ if (state.phase === 'parent') {
919
+ return parent._cancel(error);
920
+ } else if (state.phase === 'transform') {
921
+ state.error = error;
922
+ return true;
923
+ } else {
924
+ return false;
925
+ }
879
926
  });
880
927
  }
881
928
 
882
- function mapTaskEither<R, R2>(_task: TaskBase<R>, op: (value: Rejectable<R>) => Rejectable<R2>) {
883
- return mapTaskMaybe<R, R2>(_task, (maybe) => maybe.map(op));
929
+ function tapTaskMaybe<R>(parent: Task<R>, op: (value: Cancelable<R>) => void): Task<R> {
930
+ parent._invoke((result) => {
931
+ try {
932
+ op(result);
933
+ } catch (e) {
934
+ reportError(e);
935
+ }
936
+ });
937
+
938
+ return parent;
884
939
  }
885
940
 
886
- function tapTaskMaybe<R>(_task: TaskBase<R>, op: (value: Cancelable<R>) => void) {
887
- return mapTaskMaybe<R, R>(_task, (value) => {
888
- op(value);
941
+ function chainTaskEither<R, R2>(_task: Task<R>, op: (value: Rejectable<R>) => Task<R2>): Task<R2> {
942
+ return chainTaskMaybe<R, R2>(_task, (maybe) => maybe.map(op).orMap<Task<R2>>(Task.canceled).just);
943
+ }
889
944
 
890
- return value;
891
- });
945
+ function mapTaskEither<R, R2>(_task: Task<R>, op: (value: Rejectable<R>) => Rejectable<R2>): Task<R2> {
946
+ return mapTaskMaybe<R, R2>(_task, (maybe) => maybe.map(op));
892
947
  }
893
948
 
894
- function tapTaskEither<R>(_task: TaskBase<R>, op: (value: Rejectable<R>) => void) {
949
+ function tapTaskEither<R>(_task: Task<R>, op: (value: Rejectable<R>) => void): Task<R> {
895
950
  return tapTaskMaybe<R>(_task, (maybe) => maybe.tap(op));
896
951
  }
897
952
 
@@ -927,35 +982,35 @@ class TaskClass<R> implements Task<R> {
927
982
  }
928
983
  }
929
984
 
930
- tapCanceled(op: () => void) {
985
+ tapCanceled(op: () => void): Task<R> {
931
986
  return tapTaskMaybe<R>(this, (maybe) => maybe.orTap(op));
932
987
  }
933
- tapRejected(op: (error: any) => void) {
988
+ tapRejected(op: (error: any) => void): Task<R> {
934
989
  return tapTaskEither<R>(this, (either) => either.orTap(op));
935
990
  }
936
- tap(op: (value: R) => void) {
991
+ tap(op: (value: R) => void): Task<R> {
937
992
  return tapTaskEither<R>(this, (either) => either.tap(op));
938
993
  }
939
994
 
940
- mapCanceled<R2>(op: () => R2) {
995
+ mapCanceled<R2>(op: () => R2): Task<R | R2> {
941
996
  return mapTaskMaybe<R, R | R2>(this, (maybe) => maybe.orMap(() => Either.right(op())));
942
997
  }
943
- mapRejected<R2>(op: (error: any) => R2) {
998
+ mapRejected<R2>(op: (error: any) => R2): Task<R | R2> {
944
999
  return mapTaskEither<R, R | R2>(this, (either) => either.orMap(op));
945
1000
  }
946
- map<R2>(op: (value: R) => R2) {
1001
+ map<R2>(op: (value: R) => R2): Task<R2> {
947
1002
  return mapTaskEither<R, R2>(this, (either) => either.map(op));
948
1003
  }
949
1004
 
950
- chainCanceled<R2>(op: () => Task<R2>) {
1005
+ chainCanceled<R2>(op: () => Task<R2>): Task<R | R2> {
951
1006
  const mapEither = (either: Rejectable<R>) => either.map(Task.resolved).orMap<Task<R>>(Task.rejected).right;
952
1007
 
953
1008
  return chainTaskMaybe<R, R | R2>(this, (maybe) => maybe.map(mapEither).orMap(op).just);
954
1009
  }
955
- chainRejected<R2>(op: (error: any) => Task<R2>) {
1010
+ chainRejected<R2>(op: (error: any) => Task<R2>): Task<R | R2> {
956
1011
  return chainTaskEither<R, R | R2>(this, (either) => either.map(Task.resolved).orMap(op).right);
957
1012
  }
958
- chain<R2>(op: (value: R) => Task<R2>) {
1013
+ chain<R2>(op: (value: R) => Task<R2>): Task<R2> {
959
1014
  return chainTaskEither<R, R2>(this, (either) => either.map(op).orMap<Task<R2>>(Task.rejected).right);
960
1015
  }
961
1016
 
@@ -995,7 +1050,7 @@ class TaskClass<R> implements Task<R> {
995
1050
  })(this);
996
1051
  }
997
1052
 
998
- matchTap(op: { resolved: (value: R) => void; rejected: (error: any) => void; canceled: () => void }) {
1053
+ matchTap(op: { resolved: (value: R) => void; rejected: (error: any) => void; canceled: () => void }): Task<R> {
999
1054
  return tapTaskMaybe(this, (maybe) => {
1000
1055
  return maybe.matchTap({
1001
1056
  just: (either) => {
@@ -1009,7 +1064,7 @@ class TaskClass<R> implements Task<R> {
1009
1064
  });
1010
1065
  }
1011
1066
 
1012
- matchMap<R2, R3 = R2, R4 = R3>(op: { resolved: (value: R) => R2; rejected: (error: any) => R3; canceled: () => R4 }) {
1067
+ matchMap<R2, R3 = R2, R4 = R3>(op: { resolved: (value: R) => R2; rejected: (error: any) => R3; canceled: () => R4 }): Task<R2 | R3 | R4> {
1013
1068
  return mapTaskMaybe(this, (maybe) => {
1014
1069
  return Maybe.just(maybe.match<Right<R2 | R3 | R4, any>>({
1015
1070
  just: (either) => {
@@ -1023,7 +1078,7 @@ class TaskClass<R> implements Task<R> {
1023
1078
  });
1024
1079
  }
1025
1080
 
1026
- matchChain<R2, R3 = R2, R4 = R3>(op: { resolved: (value: R) => Task<R2>; rejected: (error: any) => Task<R3>; canceled: () => Task<R4> }) {
1081
+ matchChain<R2, R3 = R2, R4 = R3>(op: { resolved: (value: R) => Task<R2>; rejected: (error: any) => Task<R3>; canceled: () => Task<R4> }): Task<R2 | R3 | R4> {
1027
1082
  return chainTaskMaybe(this, (maybe) => {
1028
1083
  return maybe.match<Task<R2 | R3 | R4>>({
1029
1084
  just: (either) => {
@@ -1037,3 +1092,9 @@ class TaskClass<R> implements Task<R> {
1037
1092
  });
1038
1093
  }
1039
1094
  }
1095
+
1096
+ function reportError(error: unknown): void {
1097
+ if (typeof globalThis.reportError === 'function') {
1098
+ globalThis.reportError(error);
1099
+ }
1100
+ }