@rimbu/common 0.9.2 → 0.10.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.
@@ -4,6 +4,7 @@ import {
4
4
  CollectFun,
5
5
  MaybePromise,
6
6
  Reducer,
7
+ Eq,
7
8
  } from './internal';
8
9
 
9
10
  /**
@@ -372,4 +373,666 @@ export namespace AsyncReducer {
372
373
  reducer.stateToResult
373
374
  );
374
375
  }
376
+
377
+ /**
378
+ * A `Reducer` that sums all given numeric input values.
379
+ * @example
380
+ * ```ts
381
+ * console.log(Stream.range({ amount: 5 }).reduce(Reducer.sum))
382
+ * // => 10
383
+ * ```
384
+ */
385
+ export const sum = createMono(0, (state, next): number => state + next);
386
+
387
+ /**
388
+ * A `Reducer` that calculates the product of all given numeric input values.
389
+ * @example
390
+ * ```ts
391
+ * console.log(Stream.range({ start: 1, amount: 5 }).reduce(product))
392
+ * // => 120
393
+ * ```
394
+ */
395
+ export const product = createMono(1, (state, next, _, halt): number => {
396
+ if (0 === next) halt();
397
+ return state * next;
398
+ });
399
+
400
+ /**
401
+ * A `Reducer` that calculates the average of all given numberic input values.
402
+ * @example
403
+ * ```ts
404
+ * console.log(Stream.range({ amount: 5 }).reduce(Reducer.average));
405
+ * // => 2
406
+ * ```
407
+ */
408
+ export const average = createMono(
409
+ 0,
410
+ (avg, value, index): number => avg + (value - avg) / (index + 1)
411
+ );
412
+
413
+ /**
414
+ * Returns a `Reducer` that remembers the minimum value of the inputs using the given `compFun` to compare input values
415
+ * @param compFun - a comparison function for two input values, returning 0 when equal, positive when greater, negetive when smaller
416
+ * @param otherwise - (default: undefineds) a fallback value when there were no input values given
417
+ * @example
418
+ * ```ts
419
+ * const stream = Stream.of('abc', 'a', 'abcde', 'ab')
420
+ * console.log(stream.minBy((s1, s2) => s1.length - s2.length))
421
+ * // 'a'
422
+ * ```
423
+ */
424
+ export const minBy: {
425
+ <T>(compFun: (v1: T, v2: T) => MaybePromise<number>): AsyncReducer<
426
+ T,
427
+ T | undefined
428
+ >;
429
+ <T, O>(
430
+ compFun: (v1: T, v2: T) => MaybePromise<number>,
431
+ otherwise: AsyncOptLazy<O>
432
+ ): AsyncReducer<T, T | O>;
433
+ } = <T, O>(
434
+ compFun: (v1: T, v2: T) => MaybePromise<number>,
435
+ otherwise?: AsyncOptLazy<O>
436
+ ) => {
437
+ const token = Symbol();
438
+ return create<T, T | O, T | typeof token>(
439
+ token,
440
+ async (state, next): Promise<T> => {
441
+ if (token === state) return next;
442
+ return (await compFun(state, next)) < 0 ? state : next;
443
+ },
444
+ (state): MaybePromise<T | O> =>
445
+ token === state ? AsyncOptLazy.toMaybePromise(otherwise!) : state
446
+ );
447
+ };
448
+
449
+ /**
450
+ * Returns a `Reducer` that remembers the minimum value of the numberic inputs.
451
+ * @param otherwise - (default: undefined) a fallback value when there were no input values given
452
+ * @example
453
+ * ```ts
454
+ * console.log(Stream.of(5, 3, 7, 4).reduce(Reducer.min()))
455
+ * // => 3
456
+ * ```
457
+ */
458
+ export const min: {
459
+ (): AsyncReducer<number, number | undefined>;
460
+ <O>(otherwise: AsyncOptLazy<O>): AsyncReducer<number, number | O>;
461
+ } = <O>(otherwise?: AsyncOptLazy<O>) => {
462
+ return create<number, number | O, number | undefined>(
463
+ undefined,
464
+ (state, next): number =>
465
+ undefined !== state && state < next ? state : next,
466
+ (state): MaybePromise<number | O> =>
467
+ state ?? AsyncOptLazy.toMaybePromise(otherwise!)
468
+ );
469
+ };
470
+
471
+ /**
472
+ * Returns a `Reducer` that remembers the maximum value of the inputs using the given `compFun` to compare input values
473
+ * @param compFun - a comparison function for two input values, returning 0 when equal, positive when greater, negetive when smaller
474
+ * @param otherwise - (default: undefined) a fallback value when there were no input values given
475
+ * @example
476
+ * ```ts
477
+ * const stream = Stream.of('abc', 'a', 'abcde', 'ab')
478
+ * console.log(stream.maxBy((s1, s2) => s1.length - s2.length))
479
+ * // 'abcde'
480
+ * ```
481
+ */
482
+ export const maxBy: {
483
+ <T>(compFun: (v1: T, v2: T) => MaybePromise<number>): AsyncReducer<
484
+ T,
485
+ T | undefined
486
+ >;
487
+ <T, O>(
488
+ compFun: (v1: T, v2: T) => MaybePromise<number>,
489
+ otherwise: AsyncOptLazy<O>
490
+ ): AsyncReducer<T, T | O>;
491
+ } = <T, O>(
492
+ compFun: (v1: T, v2: T) => MaybePromise<number>,
493
+ otherwise?: AsyncOptLazy<O>
494
+ ): AsyncReducer<T, T | O> => {
495
+ const token = Symbol();
496
+ return create<T, T | O, T | typeof token>(
497
+ token,
498
+ async (state, next): Promise<T> => {
499
+ if (token === state) return next;
500
+ return (await compFun(state, next)) > 0 ? state : next;
501
+ },
502
+ (state): MaybePromise<T | O> =>
503
+ token === state ? AsyncOptLazy.toMaybePromise(otherwise!) : state
504
+ );
505
+ };
506
+
507
+ /**
508
+ * Returns a `Reducer` that remembers the maximum value of the numberic inputs.
509
+ * @param otherwise - (default: undefined) a fallback value when there were no input values given
510
+ * @example
511
+ * ```ts
512
+ * console.log(Stream.of(5, 3, 7, 4).reduce(Reducer.max()))
513
+ * // => 7
514
+ * ```
515
+ */
516
+ export const max: {
517
+ (): AsyncReducer<number, number | undefined>;
518
+ <O>(otherwise: AsyncOptLazy<O>): AsyncReducer<number, number | O>;
519
+ } = <O>(otherwise?: AsyncOptLazy<O>): AsyncReducer<number, number | O> => {
520
+ return create<number, number | O, number | undefined>(
521
+ undefined,
522
+ (state, next): number =>
523
+ undefined !== state && state > next ? state : next,
524
+ (state): MaybePromise<number | O> =>
525
+ state ?? AsyncOptLazy.toMaybePromise(otherwise!)
526
+ );
527
+ };
528
+
529
+ /**
530
+ * Returns a `Reducer` that joins the given input values into a string using the given options.
531
+ * @param options - an object containing:<br/>
532
+ * - sep: (optional) a seperator string value between values in the output<br/>
533
+ * - start: (optional) a start string to prepend to the output<br/>
534
+ * - end: (optional) an end string to append to the output<br/>
535
+ * @example
536
+ * ```ts
537
+ * console.log(Stream.of(1, 2, 3).reduce(Reducer.join({ sep: '-' })))
538
+ * // => '1-2-3'
539
+ * ```
540
+ */
541
+ export function join<T>({
542
+ sep = '',
543
+ start = '',
544
+ end = '',
545
+ valueToString = String as (value: T) => string,
546
+ } = {}): AsyncReducer<T, string> {
547
+ let curSep = '';
548
+ let curStart = start;
549
+ return create(
550
+ '',
551
+ (state, next): string => {
552
+ const result = curStart.concat(state, curSep, valueToString(next));
553
+ curSep = sep;
554
+ curStart = '';
555
+ return result;
556
+ },
557
+ (state): string => state.concat(end)
558
+ );
559
+ }
560
+
561
+ /**
562
+ * Returns an `AsyncReducer` that remembers the amount of input items provided.
563
+ * @param pred - (optional) a predicate that returns false if the item should not be counted given:<br/>
564
+ * - value: the current input value<br/>
565
+ * - index: the input value index
566
+ * @example
567
+ * ```ts
568
+ * const stream = AsyncStream.from(Stream.range({ amount: 10 }))
569
+ * console.log(await stream.reduce(AsyncReducer.count()))
570
+ * // => 10
571
+ * console.log(await stream.reduce(AsyncReducer.count(async v => v < 5)))
572
+ * // => 5
573
+ * ```
574
+ */
575
+ export const count: {
576
+ (): AsyncReducer<any, number>;
577
+ <T>(pred: (value: T, index: number) => MaybePromise<boolean>): AsyncReducer<
578
+ T,
579
+ number
580
+ >;
581
+ } = (
582
+ pred?: (value: any, index: number) => MaybePromise<boolean>
583
+ ): AsyncReducer<any, number> => {
584
+ if (undefined === pred) return createMono(0, (_, __, i): number => i + 1);
585
+
586
+ return createOutput(0, async (state, next, i): Promise<number> => {
587
+ if (await pred?.(next, i)) return state + 1;
588
+ return state;
589
+ });
590
+ };
591
+
592
+ /**
593
+ * Returns an `AsyncReducer` that remembers the first input value for which the given `pred` function returns true.
594
+ * @param pred - a function taking an input value and its index, and returning true if the value should be remembered
595
+ * @param otherwise - (default: undefined) a fallback value to output if no input value yet has satisfied the given predicate
596
+ * @typeparam T - the input value type
597
+ * @typeparam O - the fallback value type
598
+ * @example
599
+ * ```ts
600
+ * await AsyncStream.from(Stream.range({ amount: 10 })).reduce(AsyncReducer.firstWhere(async v => v > 5)))
601
+ * // => 6
602
+ * ```
603
+ */
604
+ export const firstWhere: {
605
+ <T>(pred: (value: T, index: number) => MaybePromise<boolean>): AsyncReducer<
606
+ T,
607
+ T | undefined
608
+ >;
609
+ <T, O>(
610
+ pred: (value: T, index: number) => MaybePromise<boolean>,
611
+ otherwise: AsyncOptLazy<O>
612
+ ): AsyncReducer<T, T | O>;
613
+ } = <T, O>(
614
+ pred: (value: T, index: number) => MaybePromise<boolean>,
615
+ otherwise?: AsyncOptLazy<O>
616
+ ) => {
617
+ const token = Symbol();
618
+
619
+ return create<T, T | O, T | typeof token>(
620
+ token,
621
+ async (state, next, i, halt): Promise<T | typeof token> => {
622
+ if (token === state && (await pred(next, i))) {
623
+ halt();
624
+ return next;
625
+ }
626
+ return state;
627
+ },
628
+ (state): MaybePromise<T | O> =>
629
+ token === state ? AsyncOptLazy.toMaybePromise(otherwise!) : state
630
+ );
631
+ };
632
+
633
+ /**
634
+ * Returns an `AsyncReducer` that remembers the first input value.
635
+ * @param otherwise - (default: undefined) a fallback value to output if no input value has been provided
636
+ * @typeparam T - the input value type
637
+ * @typeparam O - the fallback value type
638
+ * @example
639
+ * ```ts
640
+ * await AsyncStream.from(Stream.range{ amount: 10 })).reduce(AsyncReducer.first())
641
+ * // => 0
642
+ * ```
643
+ */
644
+ export const first: {
645
+ <T>(): AsyncReducer<T, T | undefined>;
646
+ <T, O>(otherwise: AsyncOptLazy<O>): AsyncReducer<T, T | O>;
647
+ } = <T, O>(otherwise?: AsyncOptLazy<O>): AsyncReducer<T, T | O> => {
648
+ const token = Symbol();
649
+
650
+ return create<T, T | O, T | typeof token>(
651
+ token,
652
+ (state, next, _, halt): T => {
653
+ halt();
654
+ if (token === state) return next;
655
+ return state;
656
+ },
657
+ (state): MaybePromise<T | O> =>
658
+ token === state ? AsyncOptLazy.toMaybePromise(otherwise!) : state
659
+ );
660
+ };
661
+
662
+ /**
663
+ * Returns an `AsyncReducer` that remembers the last input value for which the given `pred` function returns true.
664
+ * @param pred - a function taking an input value and its index, and returning true if the value should be remembered
665
+ * @param otherwise - (default: undefined) a fallback value to output if no input value yet has satisfied the given predicate
666
+ * @typeparam T - the input value type
667
+ * @typeparam O - the fallback value type
668
+ * @example
669
+ * ```ts
670
+ * await AsyncStream.from(Stream.range({ amount: 10 })).reduce(AsyncReducer.lastWhere(async v => v > 5)))
671
+ * // => 9
672
+ * ```
673
+ */
674
+ export const lastWhere: {
675
+ <T>(pred: (value: T, index: number) => MaybePromise<boolean>): AsyncReducer<
676
+ T,
677
+ T | undefined
678
+ >;
679
+ <T, O>(
680
+ pred: (value: T, index: number) => MaybePromise<boolean>,
681
+ otherwise: AsyncOptLazy<O>
682
+ ): AsyncReducer<T, T | O>;
683
+ } = <T, O>(
684
+ pred: (value: T, index: number) => MaybePromise<boolean>,
685
+ otherwise?: AsyncOptLazy<O>
686
+ ) => {
687
+ const token = Symbol();
688
+
689
+ return create<T, T | O, T | typeof token>(
690
+ token,
691
+ async (state, next, i): Promise<T | typeof token> => {
692
+ if (await pred(next, i)) return next;
693
+ return state;
694
+ },
695
+ (state): MaybePromise<T | O> =>
696
+ token === state ? AsyncOptLazy.toMaybePromise(otherwise!) : state
697
+ );
698
+ };
699
+
700
+ /**
701
+ * Returns an `AsyncReducer` that remembers the last input value.
702
+ * @param otherwise - (default: undefined) a fallback value to output if no input value has been provided
703
+ * @typeparam T - the input value type
704
+ * @typeparam O - the fallback value type
705
+ * @example
706
+ * ```ts
707
+ * await AsyncStream.from(Stream.range{ amount: 10 })).reduce(AsyncReducer.last())
708
+ * // => 9
709
+ * ```
710
+ */
711
+ export const last: {
712
+ <T>(): AsyncReducer<T, T | undefined>;
713
+ <T, O>(otherwise: AsyncOptLazy<O>): AsyncReducer<T, T | O>;
714
+ } = <T, O>(otherwise?: AsyncOptLazy<O>): AsyncReducer<T, T | O> => {
715
+ const token = Symbol();
716
+
717
+ return create<T, T | O, T | typeof token>(
718
+ () => token,
719
+ (_, next): T => next,
720
+ (state): MaybePromise<T | O> =>
721
+ token === state ? AsyncOptLazy.toMaybePromise(otherwise!) : state
722
+ );
723
+ };
724
+
725
+ /**
726
+ * Returns a `Reducer` that ouputs false as long as no input value satisfies given `pred`, true otherwise.
727
+ * @typeparam T - the element type
728
+ * @param pred - a function taking an input value and its index, and returning true if the value satisfies the predicate
729
+ * @example
730
+ * ```ts
731
+ * await AsyncStream.from(Stream.range{ amount: 10 })).reduce(AsyncReducer.some(async v => v > 5))
732
+ * // => true
733
+ * ```
734
+ */
735
+ export function some<T>(
736
+ pred: (value: T, index: number) => MaybePromise<boolean>
737
+ ): AsyncReducer<T, boolean> {
738
+ return createOutput<T, boolean>(
739
+ false,
740
+ async (state, next, i, halt): Promise<boolean> => {
741
+ if (state) return state;
742
+ const satisfies = await pred(next, i);
743
+
744
+ if (satisfies) {
745
+ halt();
746
+ }
747
+
748
+ return satisfies;
749
+ }
750
+ );
751
+ }
752
+
753
+ /**
754
+ * Returns an `AsyncReducer` that ouputs true as long as all input values satisfy the given `pred`, false otherwise.
755
+ * @typeparam T - the element type
756
+ * @param pred - a function taking an input value and its index, and returning true if the value satisfies the predicate
757
+ * @example
758
+ * ```ts
759
+ * await AsyncStream.from(Stream.range{ amount: 10 })).reduce(AsyncReducer.every(async v => v < 5))
760
+ * // => false
761
+ * ```
762
+ */
763
+ export function every<T>(
764
+ pred: (value: T, index: number) => MaybePromise<boolean>
765
+ ): AsyncReducer<T, boolean> {
766
+ return createOutput<T, boolean>(
767
+ true,
768
+ async (state, next, i, halt): Promise<boolean> => {
769
+ if (!state) return state;
770
+
771
+ const satisfies = await pred(next, i);
772
+
773
+ if (!satisfies) {
774
+ halt();
775
+ }
776
+
777
+ return satisfies;
778
+ }
779
+ );
780
+ }
781
+
782
+ /**
783
+ * Returns an `AsyncReducer` that outputs false as long as the given `elem` has not been encountered in the input values, true otherwise.
784
+ * @typeparam T - the element type
785
+ * @param elem - the element to search for
786
+ * @param eq - (optional) a comparison function that returns true if te two given input values are considered equal
787
+ * @example
788
+ * ```ts
789
+ * await AsyncStream.from(Stream.range({ amount: 10 })).reduce(AsyncReducer.contains(5)))
790
+ * // => true
791
+ * ```
792
+ */
793
+ export function contains<T>(
794
+ elem: T,
795
+ eq: Eq<T> = Object.is
796
+ ): AsyncReducer<T, boolean> {
797
+ return createOutput<T, boolean>(false, (state, next, _, halt): boolean => {
798
+ if (state) return state;
799
+ const satisfies = eq(next, elem);
800
+
801
+ if (satisfies) {
802
+ halt();
803
+ }
804
+
805
+ return satisfies;
806
+ });
807
+ }
808
+
809
+ /**
810
+ * Returns an `AsyncReducer` that takes boolean values and outputs true if all input values are true, and false otherwise.
811
+ * @example
812
+ * ```ts
813
+ * await AsyncStream.of(true, false, true)).reduce(AsyncReducer.and))
814
+ * // => false
815
+ * ```
816
+ */
817
+ export const and = createMono(true, (state, next, _, halt): boolean => {
818
+ if (!state) return state;
819
+ if (!next) halt();
820
+ return next;
821
+ });
822
+
823
+ /**
824
+ * Returns an `AsyncReducer` that takes boolean values and outputs true if one or more input values are true, and false otherwise.
825
+ * @example
826
+ * ```ts
827
+ * await AsyncStream.of(true, false, true)).reduce(AsyncReducer.or))
828
+ * // => true
829
+ * ```
830
+ */
831
+ export const or = createMono(false, (state, next, _, halt): boolean => {
832
+ if (state) return state;
833
+ if (next) halt();
834
+ return next;
835
+ });
836
+
837
+ /**
838
+ * Returns an `AsyncReducer` that outputs true if no input values are received, false otherwise.
839
+ * @example
840
+ * ```ts
841
+ * await AsyncStream.of(1, 2, 3).reduce(AsyncReducer.isEmpty))
842
+ * // => false
843
+ * ```
844
+ */
845
+ export const isEmpty = createOutput<any, boolean>(
846
+ true,
847
+ (_, __, ___, halt): false => {
848
+ halt();
849
+ return false;
850
+ }
851
+ );
852
+
853
+ /**
854
+ * Returns an `AsyncReducer` that outputs true if one or more input values are received, false otherwise.
855
+ * @example
856
+ * ```ts
857
+ * await AsyncStream.of(1, 2, 3).reduce(AsyncReducer.nonEmpty))
858
+ * // => true
859
+ * ```
860
+ */
861
+ export const nonEmpty = createOutput<any, boolean>(
862
+ false,
863
+ (_, __, ___, halt): true => {
864
+ halt();
865
+ return true;
866
+ }
867
+ );
868
+
869
+ /**
870
+ * Returns an `AsyncReducer` that collects received input values in an array, and returns a copy of that array as an output value when requested.
871
+ * @typeparam T - the element type
872
+ * @example
873
+ * ```ts
874
+ * await AsyncStream.of(1, 2, 3).reduce(AsyncReducer.toArray()))
875
+ * // => [1, 2, 3]
876
+ * ```
877
+ */
878
+ export function toArray<T>(): AsyncReducer<T, T[]> {
879
+ return create(
880
+ (): T[] => [],
881
+ (state, next): T[] => {
882
+ state.push(next);
883
+ return state;
884
+ },
885
+ (state): T[] => state.slice()
886
+ );
887
+ }
888
+
889
+ /**
890
+ * Returns a `AsyncReducer` that collects received input tuples into a mutable JS Map, and returns
891
+ * a copy of that map when output is requested.
892
+ * @typeparam K - the map key type
893
+ * @typeparam V - the map value type
894
+ * @example
895
+ * ```ts
896
+ * await AsyncStream.of([1, 'a'], [2, 'b']).reduce(AsyncReducer.toJSMap()))
897
+ * // Map { 1 => 'a', 2 => 'b' }
898
+ * ```
899
+ */
900
+ export function toJSMap<K, V>(): AsyncReducer<[K, V], Map<K, V>> {
901
+ return create(
902
+ (): Map<K, V> => new Map(),
903
+ (state, next): Map<K, V> => {
904
+ state.set(next[0], next[1]);
905
+ return state;
906
+ },
907
+ (s): Map<K, V> => new Map(s)
908
+ );
909
+ }
910
+
911
+ /**
912
+ * Returns an `AsyncReducer` that collects received input values into a mutable JS Set, and returns
913
+ * a copy of that map when output is requested.
914
+ * @typeparam T - the element type
915
+ * @example
916
+ * ```ts
917
+ * await AsyncStream.of(1, 2, 3).reduce(AsyncReducer.toJSSet()))
918
+ * // Set {1, 2, 3}
919
+ * ```
920
+ */
921
+ export function toJSSet<T>(): AsyncReducer<T, Set<T>> {
922
+ return create(
923
+ (): Set<T> => new Set<T>(),
924
+ (state, next): Set<T> => {
925
+ state.add(next);
926
+ return state;
927
+ },
928
+ (s): Set<T> => new Set(s)
929
+ );
930
+ }
931
+
932
+ /**
933
+ * Returns an `AsyncReducer` that collects 2-tuples containing keys and values into a plain JS object, and
934
+ * returns a copy of that object when output is requested.
935
+ * @typeparam K - the result object key type
936
+ * @typeparam V - the result object value type
937
+ * @example
938
+ * ```ts
939
+ * await AsyncStream.of(['a', 1], ['b', true]).reduce(AsyncReducer.toJSObject()))
940
+ * // { a: 1, b: true }
941
+ * ```
942
+ */
943
+ export function toJSObject<
944
+ K extends string | number | symbol,
945
+ V
946
+ >(): AsyncReducer<[K, V], Record<K, V>> {
947
+ return create(
948
+ () => ({} as Record<K, V>),
949
+ (state, entry) => {
950
+ state[entry[0]] = entry[1];
951
+ return state;
952
+ },
953
+ (s) => ({ ...s })
954
+ );
955
+ }
956
+
957
+ /**
958
+ * Returns a `Reducer` that combines multiple input `reducers` by providing input values to all of them and collecting the outputs in an array.
959
+ * @param reducers - 2 or more reducers to combine
960
+ * @example
961
+ * ```ts
962
+ * const red = Reducer.combine(Reducer.sum, Reducer.average)
963
+ * console.log(Stream.range({amount: 9 }).reduce(red))
964
+ * // => [36, 4]
965
+ * ```
966
+ */
967
+ export function combine<
968
+ T,
969
+ R extends readonly [unknown, unknown, ...unknown[]]
970
+ >(
971
+ ...reducers: { [K in keyof R]: AsyncReducer<T, R[K]> } & AsyncReducer<
972
+ T,
973
+ unknown
974
+ >[]
975
+ ): AsyncReducer<T, R> {
976
+ const createState = (): Promise<
977
+ {
978
+ reducer: AsyncReducer<T, unknown>;
979
+ halted: boolean;
980
+ halt(): void;
981
+ state: unknown;
982
+ }[]
983
+ > => {
984
+ return Promise.all(
985
+ reducers.map(async (reducer) => {
986
+ const result = {
987
+ reducer,
988
+ halted: false,
989
+ halt(): void {
990
+ result.halted = true;
991
+ },
992
+ state: await AsyncOptLazy.toMaybePromise(reducer.init),
993
+ };
994
+
995
+ return result;
996
+ })
997
+ );
998
+ };
999
+
1000
+ return create<
1001
+ T,
1002
+ R,
1003
+ {
1004
+ reducer: AsyncReducer<T, unknown>;
1005
+ halted: boolean;
1006
+ halt(): void;
1007
+ state: unknown;
1008
+ }[]
1009
+ >(
1010
+ createState,
1011
+ async (allState, next, index, halt) => {
1012
+ let anyNotHalted = false;
1013
+
1014
+ await Promise.all(
1015
+ allState.map(async (red) => {
1016
+ if (red.halted) return;
1017
+
1018
+ red.state = await red.reducer.next(
1019
+ red.state,
1020
+ next,
1021
+ index,
1022
+ red.halt
1023
+ );
1024
+ if (!red.halted) anyNotHalted = true;
1025
+ })
1026
+ );
1027
+
1028
+ if (!anyNotHalted) halt();
1029
+
1030
+ return allState;
1031
+ },
1032
+ (allState) =>
1033
+ Promise.all(
1034
+ allState.map((st) => st.reducer.stateToResult(st.state))
1035
+ ) as any
1036
+ );
1037
+ }
375
1038
  }