unwrapped 0.1.7 → 0.1.9

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,17 @@
1
1
  # unwrapped
2
2
 
3
+ ## 0.1.9
4
+
5
+ ### Patch Changes
6
+
7
+ - 07818f4: Added onSuccess and onError listeners
8
+
9
+ ## 0.1.8
10
+
11
+ ### Patch Changes
12
+
13
+ - ba3d98f: Tweaks to AsyncResultList
14
+
3
15
  ## 0.1.7
4
16
 
5
17
  ### Patch Changes
@@ -376,6 +376,30 @@ declare class AsyncResult<T, E extends ErrorBase = ErrorBase> {
376
376
  * @returns a function to remove the listener
377
377
  */
378
378
  listenUntilSettled(listener: AsyncResultListener<T, E>, immediate?: boolean): () => void;
379
+ /**
380
+ * Adds a one-time listener that is called once the AsyncResult settles on a success.
381
+ * @param callback callback called once the AsyncResult settled on a success
382
+ * @returns A function to unsubscribe early
383
+ */
384
+ onSuccessOnce(callback: (value: T) => void): () => void;
385
+ /**
386
+ * Adds a perpetual listener that is called every time the AsyncResult settles on a success.
387
+ * @param callback callback called every time the AsyncResult settles on a success
388
+ * @returns A function to unsubscribe
389
+ */
390
+ onSuccessPerpetual(callback: (value: T) => void): () => void;
391
+ /**
392
+ * Adds a one-time listener that is called once the AsyncResult settles on an error.
393
+ * @param callback callback called once the AsyncResult settled on an error
394
+ * @returns A function to unsubscribe early
395
+ */
396
+ onErrorOnce(callback: (error: E) => void): () => void;
397
+ /**
398
+ * Adds a perpetual listener that is called every time the AsyncResult settles on an error.
399
+ * @param callback callback called every time the AsyncResult settles on an error
400
+ * @returns A function to unsubscribe
401
+ */
402
+ onErrorPerpetual(callback: (error: E) => void): () => void;
379
403
  /**
380
404
  * Mirrors the state of another AsyncResult into this one.
381
405
  * Whenever the other AsyncResult changes state, this AsyncResult is updated to match.
@@ -483,23 +507,47 @@ declare class AsyncResult<T, E extends ErrorBase = ErrorBase> {
483
507
  /**
484
508
  * The possible states of an AsyncResultList.
485
509
  */
486
- type AsyncResultListState = "any-loading" | "all-settled";
487
- interface AsyncResultListItem<T = any, E extends ErrorBase = ErrorBase> {
510
+ type AsyncResultCollectionState = "any-loading" | "all-settled";
511
+ interface AsyncResultCollectionItem<T = any, E extends ErrorBase = ErrorBase> {
488
512
  key: string;
489
513
  result: AsyncResult<T, E>;
490
514
  unsub: () => void;
491
515
  }
492
516
  /**
493
- * A list that manages multiple AsyncResult instances, tracking their states and providing utilities to monitor them.
517
+ * Manages a collection of AsyncResult tasks with state tracking and listener support.
518
+ *
519
+ * This class provides a way to group multiple async operations, track their overall state
520
+ * (whether any are loading or all have settled), and react to state changes through listeners.
521
+ *
522
+ * @template T - The success value type for all AsyncResult tasks in this collection
523
+ * @template E - The error type for all AsyncResult tasks, defaults to ErrorBase
524
+ *
525
+ * @example
526
+ * ```typescript
527
+ * const collection = new AsyncResultCollection<User>();
528
+ * const userTask = new AsyncResult<User>();
529
+ *
530
+ * collection.add('user-1', userTask);
531
+ *
532
+ * collection.listen((taskQueue) => {
533
+ * console.log('Collection state changed:', taskQueue.state);
534
+ * });
535
+ * ```
536
+ *
537
+ * @remarks
538
+ * - Tasks can be automatically removed when they settle or kept in the collection
539
+ * - The collection state is either "any-loading" (at least one task is loading) or "all-settled" (no tasks loading)
540
+ * - Listeners are notified whenever the collection state changes
541
+ * - Use filtering methods to query tasks by their state (success, error, loading)
494
542
  */
495
- declare class AsyncResultList<T = any, E extends ErrorBase = ErrorBase> {
543
+ declare class AsyncResultCollection<T = any, E extends ErrorBase = ErrorBase> {
496
544
  private _list;
497
545
  private _listeners;
498
546
  private _state;
499
547
  /**
500
548
  * Gets the current tasks in the AsyncResultList.
501
549
  */
502
- get tasks(): Map<string, AsyncResultListItem<T, E>>;
550
+ get tasks(): Map<string, AsyncResultCollectionItem<T, E>>;
503
551
  /**
504
552
  * Gets the number of tasks in the list.
505
553
  */
@@ -508,10 +556,15 @@ declare class AsyncResultList<T = any, E extends ErrorBase = ErrorBase> {
508
556
  * Gets all tasks in the list as an array.
509
557
  */
510
558
  get items(): AsyncResult<T, E>[];
559
+ /**
560
+ * Gets all tasks in the list as an array of key-value pairs.
561
+ * Each pair contains the key and the corresponding AsyncResult.
562
+ */
563
+ get entries(): [string, AsyncResult<T, E>][];
511
564
  /**
512
565
  * Gets the current state of the AsyncResultList.
513
566
  */
514
- get state(): AsyncResultListState;
567
+ get state(): AsyncResultCollectionState;
515
568
  private set state(value);
516
569
  private _onTaskFinished;
517
570
  /**
@@ -519,7 +572,19 @@ declare class AsyncResultList<T = any, E extends ErrorBase = ErrorBase> {
519
572
  * @param listener the function to call when the state changes
520
573
  * @returns a function to unsubscribe the listener
521
574
  */
522
- listen(listener: (taskQueue: AsyncResultList<T, E>) => void): () => void;
575
+ listen(listener: (taskQueue: AsyncResultCollection<T, E>) => void): () => void;
576
+ /**
577
+ * Adds a listener that gets called whenever any item in the AsyncResultList succeeds.
578
+ * @param listener the function to call when an item succeeds
579
+ * @returns a function to unsubscribe the listener
580
+ */
581
+ onItemSuccess(listener: (task: AsyncResult<T, E>, key: string) => void): () => void;
582
+ /**
583
+ * Adds a listener that gets called whenever any item in the AsyncResultList errors.
584
+ * @param listener the function to call when an item errors
585
+ * @returns a function to unsubscribe the listener
586
+ */
587
+ onItemError(listener: (task: AsyncResult<T, E>, key: string) => void): () => void;
523
588
  /**
524
589
  * Adds an AsyncResult task to the list.
525
590
  * @param key the unique key for the task
@@ -528,6 +593,15 @@ declare class AsyncResultList<T = any, E extends ErrorBase = ErrorBase> {
528
593
  * @returns the added AsyncResult task
529
594
  */
530
595
  add(key: string, task: AsyncResult<T, E>, removeOnSettle?: boolean): AsyncResult<T, E>;
596
+ /**
597
+ * Removes a task from the list by its key.
598
+ * @param key the unique key of the task to remove
599
+ * @returns true if the task was removed, false if it was not found
600
+ */
601
+ remove(key: string): boolean;
602
+ /**
603
+ * Clears all tasks from the list and sets the state to "all-settled".
604
+ */
531
605
  clear(): void;
532
606
  /**
533
607
  * Checks if any task in the list is currently loading.
@@ -658,4 +732,4 @@ declare class KeyedAsyncCache<P, V, E extends ErrorBase = ErrorBase> {
658
732
 
659
733
  declare function delay(ms: number): AsyncResult<true>;
660
734
 
661
- export { type Action, AsyncResult, type AsyncResultGenerator, AsyncResultList, type AsyncResultListItem, type AsyncResultListState, type AsyncResultListener, type AsyncResultState, type ChainStep, ErrorBase, type FlatChainStep, KeyedAsyncCache, type LazyAction, Result, type ResultState, delay };
735
+ export { type Action, AsyncResult, AsyncResultCollection, type AsyncResultCollectionItem, type AsyncResultCollectionState, type AsyncResultGenerator, type AsyncResultListener, type AsyncResultState, type ChainStep, ErrorBase, type FlatChainStep, KeyedAsyncCache, type LazyAction, Result, type ResultState, delay };
@@ -376,6 +376,30 @@ declare class AsyncResult<T, E extends ErrorBase = ErrorBase> {
376
376
  * @returns a function to remove the listener
377
377
  */
378
378
  listenUntilSettled(listener: AsyncResultListener<T, E>, immediate?: boolean): () => void;
379
+ /**
380
+ * Adds a one-time listener that is called once the AsyncResult settles on a success.
381
+ * @param callback callback called once the AsyncResult settled on a success
382
+ * @returns A function to unsubscribe early
383
+ */
384
+ onSuccessOnce(callback: (value: T) => void): () => void;
385
+ /**
386
+ * Adds a perpetual listener that is called every time the AsyncResult settles on a success.
387
+ * @param callback callback called every time the AsyncResult settles on a success
388
+ * @returns A function to unsubscribe
389
+ */
390
+ onSuccessPerpetual(callback: (value: T) => void): () => void;
391
+ /**
392
+ * Adds a one-time listener that is called once the AsyncResult settles on an error.
393
+ * @param callback callback called once the AsyncResult settled on an error
394
+ * @returns A function to unsubscribe early
395
+ */
396
+ onErrorOnce(callback: (error: E) => void): () => void;
397
+ /**
398
+ * Adds a perpetual listener that is called every time the AsyncResult settles on an error.
399
+ * @param callback callback called every time the AsyncResult settles on an error
400
+ * @returns A function to unsubscribe
401
+ */
402
+ onErrorPerpetual(callback: (error: E) => void): () => void;
379
403
  /**
380
404
  * Mirrors the state of another AsyncResult into this one.
381
405
  * Whenever the other AsyncResult changes state, this AsyncResult is updated to match.
@@ -483,23 +507,47 @@ declare class AsyncResult<T, E extends ErrorBase = ErrorBase> {
483
507
  /**
484
508
  * The possible states of an AsyncResultList.
485
509
  */
486
- type AsyncResultListState = "any-loading" | "all-settled";
487
- interface AsyncResultListItem<T = any, E extends ErrorBase = ErrorBase> {
510
+ type AsyncResultCollectionState = "any-loading" | "all-settled";
511
+ interface AsyncResultCollectionItem<T = any, E extends ErrorBase = ErrorBase> {
488
512
  key: string;
489
513
  result: AsyncResult<T, E>;
490
514
  unsub: () => void;
491
515
  }
492
516
  /**
493
- * A list that manages multiple AsyncResult instances, tracking their states and providing utilities to monitor them.
517
+ * Manages a collection of AsyncResult tasks with state tracking and listener support.
518
+ *
519
+ * This class provides a way to group multiple async operations, track their overall state
520
+ * (whether any are loading or all have settled), and react to state changes through listeners.
521
+ *
522
+ * @template T - The success value type for all AsyncResult tasks in this collection
523
+ * @template E - The error type for all AsyncResult tasks, defaults to ErrorBase
524
+ *
525
+ * @example
526
+ * ```typescript
527
+ * const collection = new AsyncResultCollection<User>();
528
+ * const userTask = new AsyncResult<User>();
529
+ *
530
+ * collection.add('user-1', userTask);
531
+ *
532
+ * collection.listen((taskQueue) => {
533
+ * console.log('Collection state changed:', taskQueue.state);
534
+ * });
535
+ * ```
536
+ *
537
+ * @remarks
538
+ * - Tasks can be automatically removed when they settle or kept in the collection
539
+ * - The collection state is either "any-loading" (at least one task is loading) or "all-settled" (no tasks loading)
540
+ * - Listeners are notified whenever the collection state changes
541
+ * - Use filtering methods to query tasks by their state (success, error, loading)
494
542
  */
495
- declare class AsyncResultList<T = any, E extends ErrorBase = ErrorBase> {
543
+ declare class AsyncResultCollection<T = any, E extends ErrorBase = ErrorBase> {
496
544
  private _list;
497
545
  private _listeners;
498
546
  private _state;
499
547
  /**
500
548
  * Gets the current tasks in the AsyncResultList.
501
549
  */
502
- get tasks(): Map<string, AsyncResultListItem<T, E>>;
550
+ get tasks(): Map<string, AsyncResultCollectionItem<T, E>>;
503
551
  /**
504
552
  * Gets the number of tasks in the list.
505
553
  */
@@ -508,10 +556,15 @@ declare class AsyncResultList<T = any, E extends ErrorBase = ErrorBase> {
508
556
  * Gets all tasks in the list as an array.
509
557
  */
510
558
  get items(): AsyncResult<T, E>[];
559
+ /**
560
+ * Gets all tasks in the list as an array of key-value pairs.
561
+ * Each pair contains the key and the corresponding AsyncResult.
562
+ */
563
+ get entries(): [string, AsyncResult<T, E>][];
511
564
  /**
512
565
  * Gets the current state of the AsyncResultList.
513
566
  */
514
- get state(): AsyncResultListState;
567
+ get state(): AsyncResultCollectionState;
515
568
  private set state(value);
516
569
  private _onTaskFinished;
517
570
  /**
@@ -519,7 +572,19 @@ declare class AsyncResultList<T = any, E extends ErrorBase = ErrorBase> {
519
572
  * @param listener the function to call when the state changes
520
573
  * @returns a function to unsubscribe the listener
521
574
  */
522
- listen(listener: (taskQueue: AsyncResultList<T, E>) => void): () => void;
575
+ listen(listener: (taskQueue: AsyncResultCollection<T, E>) => void): () => void;
576
+ /**
577
+ * Adds a listener that gets called whenever any item in the AsyncResultList succeeds.
578
+ * @param listener the function to call when an item succeeds
579
+ * @returns a function to unsubscribe the listener
580
+ */
581
+ onItemSuccess(listener: (task: AsyncResult<T, E>, key: string) => void): () => void;
582
+ /**
583
+ * Adds a listener that gets called whenever any item in the AsyncResultList errors.
584
+ * @param listener the function to call when an item errors
585
+ * @returns a function to unsubscribe the listener
586
+ */
587
+ onItemError(listener: (task: AsyncResult<T, E>, key: string) => void): () => void;
523
588
  /**
524
589
  * Adds an AsyncResult task to the list.
525
590
  * @param key the unique key for the task
@@ -528,6 +593,15 @@ declare class AsyncResultList<T = any, E extends ErrorBase = ErrorBase> {
528
593
  * @returns the added AsyncResult task
529
594
  */
530
595
  add(key: string, task: AsyncResult<T, E>, removeOnSettle?: boolean): AsyncResult<T, E>;
596
+ /**
597
+ * Removes a task from the list by its key.
598
+ * @param key the unique key of the task to remove
599
+ * @returns true if the task was removed, false if it was not found
600
+ */
601
+ remove(key: string): boolean;
602
+ /**
603
+ * Clears all tasks from the list and sets the state to "all-settled".
604
+ */
531
605
  clear(): void;
532
606
  /**
533
607
  * Checks if any task in the list is currently loading.
@@ -658,4 +732,4 @@ declare class KeyedAsyncCache<P, V, E extends ErrorBase = ErrorBase> {
658
732
 
659
733
  declare function delay(ms: number): AsyncResult<true>;
660
734
 
661
- export { type Action, AsyncResult, type AsyncResultGenerator, AsyncResultList, type AsyncResultListItem, type AsyncResultListState, type AsyncResultListener, type AsyncResultState, type ChainStep, ErrorBase, type FlatChainStep, KeyedAsyncCache, type LazyAction, Result, type ResultState, delay };
735
+ export { type Action, AsyncResult, AsyncResultCollection, type AsyncResultCollectionItem, type AsyncResultCollectionState, type AsyncResultGenerator, type AsyncResultListener, type AsyncResultState, type ChainStep, ErrorBase, type FlatChainStep, KeyedAsyncCache, type LazyAction, Result, type ResultState, delay };
@@ -21,7 +21,7 @@ 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
+ AsyncResultCollection: () => AsyncResultCollection,
25
25
  ErrorBase: () => ErrorBase,
26
26
  KeyedAsyncCache: () => KeyedAsyncCache,
27
27
  Result: () => Result,
@@ -519,6 +519,54 @@ var AsyncResult = class _AsyncResult {
519
519
  }, immediate);
520
520
  return unsub;
521
521
  }
522
+ /**
523
+ * Adds a one-time listener that is called once the AsyncResult settles on a success.
524
+ * @param callback callback called once the AsyncResult settled on a success
525
+ * @returns A function to unsubscribe early
526
+ */
527
+ onSuccessOnce(callback) {
528
+ return this.listenUntilSettled((result) => {
529
+ if (result.isSuccess()) {
530
+ callback(result.unwrapOrThrow());
531
+ }
532
+ });
533
+ }
534
+ /**
535
+ * Adds a perpetual listener that is called every time the AsyncResult settles on a success.
536
+ * @param callback callback called every time the AsyncResult settles on a success
537
+ * @returns A function to unsubscribe
538
+ */
539
+ onSuccessPerpetual(callback) {
540
+ return this.listen((result) => {
541
+ if (result.isSuccess()) {
542
+ callback(result.unwrapOrThrow());
543
+ }
544
+ });
545
+ }
546
+ /**
547
+ * Adds a one-time listener that is called once the AsyncResult settles on an error.
548
+ * @param callback callback called once the AsyncResult settled on an error
549
+ * @returns A function to unsubscribe early
550
+ */
551
+ onErrorOnce(callback) {
552
+ return this.listenUntilSettled((result) => {
553
+ if (result.isError()) {
554
+ callback(result.unwrapErrorOrNull());
555
+ }
556
+ });
557
+ }
558
+ /**
559
+ * Adds a perpetual listener that is called every time the AsyncResult settles on an error.
560
+ * @param callback callback called every time the AsyncResult settles on an error
561
+ * @returns A function to unsubscribe
562
+ */
563
+ onErrorPerpetual(callback) {
564
+ return this.listen((result) => {
565
+ if (result.isError()) {
566
+ callback(result.unwrapErrorOrNull());
567
+ }
568
+ });
569
+ }
522
570
  // === Mirroring ===
523
571
  /**
524
572
  * Mirrors the state of another AsyncResult into this one.
@@ -711,8 +759,8 @@ var AsyncResult = class _AsyncResult {
711
759
  }
712
760
  };
713
761
 
714
- // src/core/asyncResultList.ts
715
- var AsyncResultList = class {
762
+ // src/core/asyncResultCollection.ts
763
+ var AsyncResultCollection = class {
716
764
  _list = /* @__PURE__ */ new Map();
717
765
  _listeners = /* @__PURE__ */ new Set();
718
766
  _state = "all-settled";
@@ -735,6 +783,13 @@ var AsyncResultList = class {
735
783
  get items() {
736
784
  return Array.from(this._list.values()).map((i) => i.result);
737
785
  }
786
+ /**
787
+ * Gets all tasks in the list as an array of key-value pairs.
788
+ * Each pair contains the key and the corresponding AsyncResult.
789
+ */
790
+ get entries() {
791
+ return Array.from(this._list.entries()).map(([key, item]) => [key, item.result]);
792
+ }
738
793
  /**
739
794
  * Gets the current state of the AsyncResultList.
740
795
  */
@@ -760,6 +815,34 @@ var AsyncResultList = class {
760
815
  this._listeners.delete(listener);
761
816
  };
762
817
  }
818
+ /**
819
+ * Adds a listener that gets called whenever any item in the AsyncResultList succeeds.
820
+ * @param listener the function to call when an item succeeds
821
+ * @returns a function to unsubscribe the listener
822
+ */
823
+ onItemSuccess(listener) {
824
+ return this.listen((taskQueue) => {
825
+ for (const item of taskQueue._list.values()) {
826
+ if (item.result.isSuccess()) {
827
+ listener(item.result, item.key);
828
+ }
829
+ }
830
+ });
831
+ }
832
+ /**
833
+ * Adds a listener that gets called whenever any item in the AsyncResultList errors.
834
+ * @param listener the function to call when an item errors
835
+ * @returns a function to unsubscribe the listener
836
+ */
837
+ onItemError(listener) {
838
+ return this.listen((taskQueue) => {
839
+ for (const item of taskQueue._list.values()) {
840
+ if (item.result.isError()) {
841
+ listener(item.result, item.key);
842
+ }
843
+ }
844
+ });
845
+ }
763
846
  // === Managing tasks ===
764
847
  /**
765
848
  * Adds an AsyncResult task to the list.
@@ -786,6 +869,22 @@ var AsyncResultList = class {
786
869
  this.state = "any-loading";
787
870
  return task;
788
871
  }
872
+ /**
873
+ * Removes a task from the list by its key.
874
+ * @param key the unique key of the task to remove
875
+ * @returns true if the task was removed, false if it was not found
876
+ */
877
+ remove(key) {
878
+ const item = this._list.get(key);
879
+ if (!item) return false;
880
+ item.unsub();
881
+ this._list.delete(key);
882
+ this._onTaskFinished();
883
+ return true;
884
+ }
885
+ /**
886
+ * Clears all tasks from the list and sets the state to "all-settled".
887
+ */
789
888
  clear() {
790
889
  this._list.forEach(({ unsub }) => unsub());
791
890
  this._list.clear();
@@ -1043,7 +1142,7 @@ function delay(ms) {
1043
1142
  // Annotate the CommonJS export names for ESM import in node:
1044
1143
  0 && (module.exports = {
1045
1144
  AsyncResult,
1046
- AsyncResultList,
1145
+ AsyncResultCollection,
1047
1146
  ErrorBase,
1048
1147
  KeyedAsyncCache,
1049
1148
  Result,