unwrapped 0.1.5 → 0.1.6

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # unwrapped
2
2
 
3
+ ## 0.1.6
4
+
5
+ ### Patch Changes
6
+
7
+ - 58d5299: Added AsyncResultList
8
+
3
9
  ## 0.1.5
4
10
 
5
11
  ### Patch Changes
@@ -261,6 +261,11 @@ declare class AsyncResult<T, E extends ErrorBase = ErrorBase> {
261
261
  * @throws an normal JS Error if the result is not successful
262
262
  */
263
263
  unwrapOrThrow(): T;
264
+ /**
265
+ * Returns the error value if the AsyncResult is in an error state, otherwise returns null.
266
+ * @returns the error value or null
267
+ */
268
+ unwrapErrorOrNull(): E | null;
264
269
  private set state(value);
265
270
  private setState;
266
271
  /**
@@ -475,6 +480,110 @@ declare class AsyncResult<T, E extends ErrorBase = ErrorBase> {
475
480
  debug(name?: string): () => void;
476
481
  }
477
482
 
483
+ /**
484
+ * The possible states of an AsyncResultList.
485
+ */
486
+ type AsyncResultListState = "any-loading" | "all-settled";
487
+ /**
488
+ * A list that manages multiple AsyncResult instances, tracking their states and providing utilities to monitor them.
489
+ */
490
+ declare class AsyncResultList<T = any, E extends ErrorBase = ErrorBase> {
491
+ private _list;
492
+ private _listeners;
493
+ private _state;
494
+ /**
495
+ * Gets the current tasks in the AsyncResultList.
496
+ */
497
+ get tasks(): Map<string, AsyncResult<T, E>>;
498
+ /**
499
+ * Gets the number of tasks in the list.
500
+ */
501
+ get length(): number;
502
+ /**
503
+ * Gets all tasks in the list as an array.
504
+ */
505
+ get items(): AsyncResult<T, E>[];
506
+ /**
507
+ * Gets the current state of the AsyncResultList.
508
+ */
509
+ get state(): AsyncResultListState;
510
+ private set state(value);
511
+ private _onTaskFinished;
512
+ /**
513
+ * Adds a listener that gets called whenever the state of the AsyncResultList changes.
514
+ * @param listener the function to call when the state changes
515
+ * @returns a function to unsubscribe the listener
516
+ */
517
+ listen(listener: (taskQueue: AsyncResultList<T, E>) => void): () => void;
518
+ /**
519
+ * Adds an AsyncResult task to the list.
520
+ * @param key the unique key for the task
521
+ * @param task the AsyncResult task to add
522
+ * @param removeOnSettle whether to remove the task from the list once it settles (defaults to true)
523
+ * @returns the added AsyncResult task
524
+ */
525
+ add(key: string, task: AsyncResult<T, E>, removeOnSettle?: boolean): AsyncResult<T, E>;
526
+ /**
527
+ * Checks if any task in the list is currently loading.
528
+ * @returns true if any task is loading, false otherwise
529
+ */
530
+ anyLoading(): boolean;
531
+ /**
532
+ * Gets all tasks that satisfy the given predicate.
533
+ * @param predicate the function to test each task
534
+ * @returns an array of tasks that satisfy the predicate
535
+ */
536
+ getAllFiltered(predicate: (task: AsyncResult<T, E>) => boolean): AsyncResult<T, E>[];
537
+ /**
538
+ * Gets all tasks that satisfy the given predicate and maps them using the provided function.
539
+ * @param filterPredicate the function to test each task
540
+ * @param mapFunc the function to map each task
541
+ * @returns an array of mapped values
542
+ */
543
+ getAllFilteredAndMap<U>(filterPredicate: (task: AsyncResult<T, E>) => boolean, mapFunc: (task: AsyncResult<T, E>) => U): U[];
544
+ /**
545
+ * Gets all tasks that have succeeded.
546
+ * @returns an array of successful AsyncResult tasks
547
+ */
548
+ getAllSuccess(): AsyncResult<T, E>[];
549
+ /**
550
+ * Gets the success values of all tasks that have succeeded.
551
+ * @returns an array of successful values
552
+ */
553
+ getAllSuccessValues(): T[];
554
+ /**
555
+ * Gets all tasks that have errored.
556
+ * @returns an array of error AsyncResult tasks
557
+ */
558
+ getAllErrors(): AsyncResult<T, E>[];
559
+ /**
560
+ * Gets the error values of all tasks that have errored.
561
+ * @returns an array of error values
562
+ */
563
+ getAllErrorValues(): E[];
564
+ /**
565
+ * Gets all tasks that are currently loading.
566
+ * @returns an array of loading AsyncResult tasks
567
+ */
568
+ getAllLoading(): AsyncResult<T, E>[];
569
+ /**
570
+ * Gets the promises of all tasks that are currently loading.
571
+ * @returns an array of promises for loading tasks
572
+ */
573
+ getAllLoadingPromises(): Promise<Result<T, E>>[];
574
+ /**
575
+ * Logs the current state and tasks of the AsyncResultList to the console.
576
+ * @param name an optional name to identify the log
577
+ */
578
+ log(name?: string): void;
579
+ /**
580
+ * Sets up a listener to log the state and tasks of the AsyncResultList whenever it changes.
581
+ * @param name an optional name to identify the log
582
+ * @returns a function to unsubscribe the debug listener
583
+ */
584
+ debug(name?: string): () => void;
585
+ }
586
+
478
587
  type KeyedAsyncCacheRefetchOptions = {
479
588
  policy: 'refetch' | 'if-error' | 'no-refetch';
480
589
  };
@@ -541,4 +650,6 @@ declare class KeyedAsyncCache<P, V, E extends ErrorBase = ErrorBase> {
541
650
  invalidateAll(): void;
542
651
  }
543
652
 
544
- export { type Action, AsyncResult, type AsyncResultGenerator, type AsyncResultListener, type AsyncResultState, type ChainStep, ErrorBase, type FlatChainStep, KeyedAsyncCache, type LazyAction, Result, type ResultState };
653
+ declare function delay(ms: number): AsyncResult<true>;
654
+
655
+ export { type Action, AsyncResult, type AsyncResultGenerator, AsyncResultList, type AsyncResultListState, type AsyncResultListener, type AsyncResultState, type ChainStep, ErrorBase, type FlatChainStep, KeyedAsyncCache, type LazyAction, Result, type ResultState, delay };
@@ -261,6 +261,11 @@ declare class AsyncResult<T, E extends ErrorBase = ErrorBase> {
261
261
  * @throws an normal JS Error if the result is not successful
262
262
  */
263
263
  unwrapOrThrow(): T;
264
+ /**
265
+ * Returns the error value if the AsyncResult is in an error state, otherwise returns null.
266
+ * @returns the error value or null
267
+ */
268
+ unwrapErrorOrNull(): E | null;
264
269
  private set state(value);
265
270
  private setState;
266
271
  /**
@@ -475,6 +480,110 @@ declare class AsyncResult<T, E extends ErrorBase = ErrorBase> {
475
480
  debug(name?: string): () => void;
476
481
  }
477
482
 
483
+ /**
484
+ * The possible states of an AsyncResultList.
485
+ */
486
+ type AsyncResultListState = "any-loading" | "all-settled";
487
+ /**
488
+ * A list that manages multiple AsyncResult instances, tracking their states and providing utilities to monitor them.
489
+ */
490
+ declare class AsyncResultList<T = any, E extends ErrorBase = ErrorBase> {
491
+ private _list;
492
+ private _listeners;
493
+ private _state;
494
+ /**
495
+ * Gets the current tasks in the AsyncResultList.
496
+ */
497
+ get tasks(): Map<string, AsyncResult<T, E>>;
498
+ /**
499
+ * Gets the number of tasks in the list.
500
+ */
501
+ get length(): number;
502
+ /**
503
+ * Gets all tasks in the list as an array.
504
+ */
505
+ get items(): AsyncResult<T, E>[];
506
+ /**
507
+ * Gets the current state of the AsyncResultList.
508
+ */
509
+ get state(): AsyncResultListState;
510
+ private set state(value);
511
+ private _onTaskFinished;
512
+ /**
513
+ * Adds a listener that gets called whenever the state of the AsyncResultList changes.
514
+ * @param listener the function to call when the state changes
515
+ * @returns a function to unsubscribe the listener
516
+ */
517
+ listen(listener: (taskQueue: AsyncResultList<T, E>) => void): () => void;
518
+ /**
519
+ * Adds an AsyncResult task to the list.
520
+ * @param key the unique key for the task
521
+ * @param task the AsyncResult task to add
522
+ * @param removeOnSettle whether to remove the task from the list once it settles (defaults to true)
523
+ * @returns the added AsyncResult task
524
+ */
525
+ add(key: string, task: AsyncResult<T, E>, removeOnSettle?: boolean): AsyncResult<T, E>;
526
+ /**
527
+ * Checks if any task in the list is currently loading.
528
+ * @returns true if any task is loading, false otherwise
529
+ */
530
+ anyLoading(): boolean;
531
+ /**
532
+ * Gets all tasks that satisfy the given predicate.
533
+ * @param predicate the function to test each task
534
+ * @returns an array of tasks that satisfy the predicate
535
+ */
536
+ getAllFiltered(predicate: (task: AsyncResult<T, E>) => boolean): AsyncResult<T, E>[];
537
+ /**
538
+ * Gets all tasks that satisfy the given predicate and maps them using the provided function.
539
+ * @param filterPredicate the function to test each task
540
+ * @param mapFunc the function to map each task
541
+ * @returns an array of mapped values
542
+ */
543
+ getAllFilteredAndMap<U>(filterPredicate: (task: AsyncResult<T, E>) => boolean, mapFunc: (task: AsyncResult<T, E>) => U): U[];
544
+ /**
545
+ * Gets all tasks that have succeeded.
546
+ * @returns an array of successful AsyncResult tasks
547
+ */
548
+ getAllSuccess(): AsyncResult<T, E>[];
549
+ /**
550
+ * Gets the success values of all tasks that have succeeded.
551
+ * @returns an array of successful values
552
+ */
553
+ getAllSuccessValues(): T[];
554
+ /**
555
+ * Gets all tasks that have errored.
556
+ * @returns an array of error AsyncResult tasks
557
+ */
558
+ getAllErrors(): AsyncResult<T, E>[];
559
+ /**
560
+ * Gets the error values of all tasks that have errored.
561
+ * @returns an array of error values
562
+ */
563
+ getAllErrorValues(): E[];
564
+ /**
565
+ * Gets all tasks that are currently loading.
566
+ * @returns an array of loading AsyncResult tasks
567
+ */
568
+ getAllLoading(): AsyncResult<T, E>[];
569
+ /**
570
+ * Gets the promises of all tasks that are currently loading.
571
+ * @returns an array of promises for loading tasks
572
+ */
573
+ getAllLoadingPromises(): Promise<Result<T, E>>[];
574
+ /**
575
+ * Logs the current state and tasks of the AsyncResultList to the console.
576
+ * @param name an optional name to identify the log
577
+ */
578
+ log(name?: string): void;
579
+ /**
580
+ * Sets up a listener to log the state and tasks of the AsyncResultList whenever it changes.
581
+ * @param name an optional name to identify the log
582
+ * @returns a function to unsubscribe the debug listener
583
+ */
584
+ debug(name?: string): () => void;
585
+ }
586
+
478
587
  type KeyedAsyncCacheRefetchOptions = {
479
588
  policy: 'refetch' | 'if-error' | 'no-refetch';
480
589
  };
@@ -541,4 +650,6 @@ declare class KeyedAsyncCache<P, V, E extends ErrorBase = ErrorBase> {
541
650
  invalidateAll(): void;
542
651
  }
543
652
 
544
- export { type Action, AsyncResult, type AsyncResultGenerator, type AsyncResultListener, type AsyncResultState, type ChainStep, ErrorBase, type FlatChainStep, KeyedAsyncCache, type LazyAction, Result, type ResultState };
653
+ declare function delay(ms: number): AsyncResult<true>;
654
+
655
+ export { type Action, AsyncResult, type AsyncResultGenerator, AsyncResultList, type AsyncResultListState, type AsyncResultListener, type AsyncResultState, type ChainStep, ErrorBase, type FlatChainStep, KeyedAsyncCache, type LazyAction, Result, type ResultState, delay };
@@ -21,9 +21,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AsyncResult: () => AsyncResult,
24
+ AsyncResultList: () => AsyncResultList,
24
25
  ErrorBase: () => ErrorBase,
25
26
  KeyedAsyncCache: () => KeyedAsyncCache,
26
- Result: () => Result
27
+ Result: () => Result,
28
+ delay: () => delay
27
29
  });
28
30
  module.exports = __toCommonJS(index_exports);
29
31
 
@@ -308,6 +310,16 @@ var AsyncResult = class _AsyncResult {
308
310
  }
309
311
  throw new Error("Tried to unwrap an AsyncResult that is not successful");
310
312
  }
313
+ /**
314
+ * Returns the error value if the AsyncResult is in an error state, otherwise returns null.
315
+ * @returns the error value or null
316
+ */
317
+ unwrapErrorOrNull() {
318
+ if (this._state.status === "error") {
319
+ return this._state.error;
320
+ }
321
+ return null;
322
+ }
311
323
  // === Creating/updating from settled values ===
312
324
  set state(newState) {
313
325
  this._state = newState;
@@ -691,7 +703,7 @@ var AsyncResult = class _AsyncResult {
691
703
  }
692
704
  // === Debuging ===
693
705
  log(name) {
694
- const time = (/* @__PURE__ */ new Date()).toTimeString().slice(0, 7);
706
+ const time = (/* @__PURE__ */ new Date()).toTimeString().slice(0, 8);
695
707
  console.log(`${name ?? "<Anonymous AsyncResult>"} ; State at ${time} :`, this.state);
696
708
  }
697
709
  debug(name) {
@@ -699,6 +711,185 @@ var AsyncResult = class _AsyncResult {
699
711
  }
700
712
  };
701
713
 
714
+ // src/core/asyncResultList.ts
715
+ var AsyncResultList = class {
716
+ _list = /* @__PURE__ */ new Map();
717
+ _listeners = /* @__PURE__ */ new Set();
718
+ _state = "all-settled";
719
+ // === Getters ===
720
+ /**
721
+ * Gets the current tasks in the AsyncResultList.
722
+ */
723
+ get tasks() {
724
+ return this._list;
725
+ }
726
+ /**
727
+ * Gets the number of tasks in the list.
728
+ */
729
+ get length() {
730
+ return this._list.size;
731
+ }
732
+ /**
733
+ * Gets all tasks in the list as an array.
734
+ */
735
+ get items() {
736
+ return Array.from(this._list.values());
737
+ }
738
+ /**
739
+ * Gets the current state of the AsyncResultList.
740
+ */
741
+ get state() {
742
+ return this._state;
743
+ }
744
+ set state(s) {
745
+ this._state = s;
746
+ this._listeners.forEach((f) => f(this));
747
+ }
748
+ _onTaskFinished() {
749
+ this.state = this.anyLoading() ? "any-loading" : "all-settled";
750
+ }
751
+ // === Listeners ===
752
+ /**
753
+ * Adds a listener that gets called whenever the state of the AsyncResultList changes.
754
+ * @param listener the function to call when the state changes
755
+ * @returns a function to unsubscribe the listener
756
+ */
757
+ listen(listener) {
758
+ this._listeners.add(listener);
759
+ return () => {
760
+ this._listeners.delete(listener);
761
+ };
762
+ }
763
+ // === Managing tasks ===
764
+ /**
765
+ * Adds an AsyncResult task to the list.
766
+ * @param key the unique key for the task
767
+ * @param task the AsyncResult task to add
768
+ * @param removeOnSettle whether to remove the task from the list once it settles (defaults to true)
769
+ * @returns the added AsyncResult task
770
+ */
771
+ add(key, task, removeOnSettle = true) {
772
+ this._list.set(key, task);
773
+ this.state = "any-loading";
774
+ if (removeOnSettle) {
775
+ task.listenUntilSettled((r) => {
776
+ if (r.isLoading() || r.isIdle()) return;
777
+ this._onTaskFinished();
778
+ this._list.delete(key);
779
+ }, true);
780
+ } else {
781
+ task.listen((r) => {
782
+ if (r.isLoading() || r.isIdle()) return;
783
+ this._onTaskFinished();
784
+ }, true);
785
+ }
786
+ return task;
787
+ }
788
+ // === Querying tasks ===
789
+ /**
790
+ * Checks if any task in the list is currently loading.
791
+ * @returns true if any task is loading, false otherwise
792
+ */
793
+ anyLoading() {
794
+ for (const task of this._list.values()) {
795
+ if (task.isLoading()) {
796
+ return true;
797
+ }
798
+ }
799
+ return false;
800
+ }
801
+ /**
802
+ * Gets all tasks that satisfy the given predicate.
803
+ * @param predicate the function to test each task
804
+ * @returns an array of tasks that satisfy the predicate
805
+ */
806
+ getAllFiltered(predicate) {
807
+ const filtered = [];
808
+ for (const task of this._list.values()) {
809
+ if (predicate(task)) {
810
+ filtered.push(task);
811
+ }
812
+ }
813
+ return filtered;
814
+ }
815
+ /**
816
+ * Gets all tasks that satisfy the given predicate and maps them using the provided function.
817
+ * @param filterPredicate the function to test each task
818
+ * @param mapFunc the function to map each task
819
+ * @returns an array of mapped values
820
+ */
821
+ getAllFilteredAndMap(filterPredicate, mapFunc) {
822
+ const results = [];
823
+ for (const task of this._list.values()) {
824
+ if (filterPredicate(task)) {
825
+ results.push(mapFunc(task));
826
+ }
827
+ }
828
+ return results;
829
+ }
830
+ /**
831
+ * Gets all tasks that have succeeded.
832
+ * @returns an array of successful AsyncResult tasks
833
+ */
834
+ getAllSuccess() {
835
+ return this.getAllFiltered((task) => task.isSuccess());
836
+ }
837
+ /**
838
+ * Gets the success values of all tasks that have succeeded.
839
+ * @returns an array of successful values
840
+ */
841
+ getAllSuccessValues() {
842
+ return this.getAllFilteredAndMap((task) => task.isSuccess(), (task) => task.unwrapOrThrow());
843
+ }
844
+ /**
845
+ * Gets all tasks that have errored.
846
+ * @returns an array of error AsyncResult tasks
847
+ */
848
+ getAllErrors() {
849
+ return this.getAllFiltered((task) => task.isError());
850
+ }
851
+ /**
852
+ * Gets the error values of all tasks that have errored.
853
+ * @returns an array of error values
854
+ */
855
+ getAllErrorValues() {
856
+ return this.getAllFilteredAndMap((task) => task.isError(), (task) => task.unwrapErrorOrNull());
857
+ }
858
+ /**
859
+ * Gets all tasks that are currently loading.
860
+ * @returns an array of loading AsyncResult tasks
861
+ */
862
+ getAllLoading() {
863
+ return this.getAllFiltered((task) => task.isLoading());
864
+ }
865
+ /**
866
+ * Gets the promises of all tasks that are currently loading.
867
+ * @returns an array of promises for loading tasks
868
+ */
869
+ getAllLoadingPromises() {
870
+ return this.getAllFilteredAndMap((task) => task.isLoading(), (task) => task.toResultPromise());
871
+ }
872
+ // === Debugging utilities ===
873
+ /**
874
+ * Logs the current state and tasks of the AsyncResultList to the console.
875
+ * @param name an optional name to identify the log
876
+ */
877
+ log(name) {
878
+ const time = (/* @__PURE__ */ new Date()).toTimeString().slice(0, 8);
879
+ console.log(`${name ?? "<Anonymous TaskQueue>"} ; State at ${time} :`, this.state, this._list);
880
+ }
881
+ /**
882
+ * Sets up a listener to log the state and tasks of the AsyncResultList whenever it changes.
883
+ * @param name an optional name to identify the log
884
+ * @returns a function to unsubscribe the debug listener
885
+ */
886
+ debug(name) {
887
+ return this.listen(() => {
888
+ this.log(name);
889
+ });
890
+ }
891
+ };
892
+
702
893
  // src/core/cache.ts
703
894
  var _defaultRefetchOptions = { policy: "no-refetch" };
704
895
  function defaultParamsToKey(params) {
@@ -836,11 +1027,20 @@ var KeyedAsyncCache = class {
836
1027
  }
837
1028
  }
838
1029
  };
1030
+
1031
+ // src/core/utils.ts
1032
+ function delay(ms) {
1033
+ return AsyncResult.fromValuePromise(new Promise((resolve) => {
1034
+ setTimeout(() => resolve(true), ms);
1035
+ }));
1036
+ }
839
1037
  // Annotate the CommonJS export names for ESM import in node:
840
1038
  0 && (module.exports = {
841
1039
  AsyncResult,
1040
+ AsyncResultList,
842
1041
  ErrorBase,
843
1042
  KeyedAsyncCache,
844
- Result
1043
+ Result,
1044
+ delay
845
1045
  });
846
1046
  //# sourceMappingURL=index.js.map