@dereekb/rxjs 13.0.7 → 13.2.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.
Files changed (52) hide show
  1. package/index.cjs.js +1284 -336
  2. package/index.cjs.js.map +1 -1
  3. package/index.esm.js +1284 -336
  4. package/index.esm.js.map +1 -1
  5. package/package.json +2 -2
  6. package/src/lib/filter/filter.d.ts +28 -13
  7. package/src/lib/filter/filter.map.d.ts +69 -2
  8. package/src/lib/filter/filter.preset.d.ts +35 -0
  9. package/src/lib/filter/filter.source.d.ts +61 -2
  10. package/src/lib/iterator/iteration.accumulator.d.ts +39 -13
  11. package/src/lib/iterator/iteration.accumulator.rxjs.d.ts +25 -8
  12. package/src/lib/iterator/iteration.d.ts +16 -5
  13. package/src/lib/iterator/iteration.mapped.d.ts +19 -6
  14. package/src/lib/iterator/iteration.mapped.page.d.ts +9 -6
  15. package/src/lib/iterator/iteration.next.d.ts +17 -14
  16. package/src/lib/iterator/iterator.page.d.ts +54 -16
  17. package/src/lib/loading/loading.context.rxjs.d.ts +17 -1
  18. package/src/lib/loading/loading.context.simple.d.ts +38 -1
  19. package/src/lib/loading/loading.context.state.d.ts +32 -4
  20. package/src/lib/loading/loading.context.state.list.d.ts +25 -3
  21. package/src/lib/loading/loading.context.value.d.ts +43 -3
  22. package/src/lib/loading/loading.state.d.ts +272 -41
  23. package/src/lib/loading/loading.state.list.d.ts +50 -9
  24. package/src/lib/lock.d.ts +149 -6
  25. package/src/lib/object.d.ts +28 -4
  26. package/src/lib/rxjs/array.d.ts +39 -13
  27. package/src/lib/rxjs/boolean.d.ts +8 -4
  28. package/src/lib/rxjs/decision.d.ts +13 -7
  29. package/src/lib/rxjs/delta.d.ts +14 -2
  30. package/src/lib/rxjs/expires.d.ts +20 -8
  31. package/src/lib/rxjs/factory.d.ts +16 -3
  32. package/src/lib/rxjs/getter.d.ts +24 -10
  33. package/src/lib/rxjs/key.d.ts +7 -5
  34. package/src/lib/rxjs/lifecycle.d.ts +10 -7
  35. package/src/lib/rxjs/loading.d.ts +10 -2
  36. package/src/lib/rxjs/map.d.ts +6 -5
  37. package/src/lib/rxjs/misc.d.ts +26 -6
  38. package/src/lib/rxjs/model.d.ts +2 -2
  39. package/src/lib/rxjs/number.d.ts +8 -4
  40. package/src/lib/rxjs/rxjs.async.d.ts +20 -7
  41. package/src/lib/rxjs/rxjs.d.ts +26 -18
  42. package/src/lib/rxjs/rxjs.error.d.ts +17 -0
  43. package/src/lib/rxjs/rxjs.map.d.ts +37 -9
  44. package/src/lib/rxjs/rxjs.unique.d.ts +6 -3
  45. package/src/lib/rxjs/set.d.ts +34 -0
  46. package/src/lib/rxjs/string.d.ts +18 -1
  47. package/src/lib/rxjs/timeout.d.ts +21 -1
  48. package/src/lib/rxjs/use.d.ts +4 -2
  49. package/src/lib/rxjs/value.d.ts +73 -39
  50. package/src/lib/subscription.d.ts +80 -3
  51. package/src/lib/work/work.factory.d.ts +42 -9
  52. package/src/lib/work/work.instance.d.ts +26 -2
@@ -2,31 +2,34 @@ import { type Observable } from 'rxjs';
2
2
  import { type ItemIteration, type PageItemIteration } from './iteration';
3
3
  import { type Maybe, type GetterOrValue, type PageNumber } from '@dereekb/util';
4
4
  /**
5
- * Creates an observable from the input iteration that checks both the hasNext$ and canLoadMore$ states.
5
+ * Combines an iteration's `hasNext$` and `canLoadMore$` into a single observable that emits
6
+ * `true` only when both conditions are met (more items exist and the page limit hasn't been reached).
6
7
  *
7
- * @param iteration
8
- * @returns
8
+ * @param iteration - the iteration to check
9
+ * @returns observable that emits `true` when more items can be loaded
9
10
  */
10
11
  export declare function iterationHasNextAndCanLoadMore<V>(iteration: ItemIteration<V>): Observable<boolean>;
11
12
  /**
12
- * Automatically calls next up to the current maxPageLoadLimit configured on the iterator.
13
+ * Automatically pages through a {@link PageItemIteration} until its configured max page load limit is reached.
13
14
  *
14
- * If no maximum limit is defined, uses the defaultLimit. If default limit is not defined or null, this will result in an error.
15
+ * Falls back to the provided default limit if no max is configured on the iterator.
15
16
  *
16
- * The promise will reject with an error if an error is encountered.
17
+ * @param iterator - the page iteration to advance
18
+ * @param defaultLimit - fallback page limit if none is configured (defaults to 100)
19
+ * @returns promise resolving to the last loaded page number
17
20
  *
18
- * @param iterator
19
- * @param defaultLimit
20
- * @returns
21
+ * @throws {Error} If neither a max page load limit nor a default limit is defined
22
+ * @throws Rejects if the iteration encounters a loading error
21
23
  */
22
24
  export declare function iteratorNextPageUntilMaxPageLoadLimit(iterator: PageItemIteration, defaultLimit?: Maybe<number>): Promise<number>;
23
25
  /**
24
- * Automatically calls next on the PageItemIteration up to the target page, the number of total pages that should be loaded.
26
+ * Automatically pages through a {@link PageItemIteration} until the specified page number is reached,
27
+ * respecting the iteration's max page load limit.
25
28
  *
26
- * The promise will reject with an error if an error is encountered.
29
+ * @param iteration - the page iteration to advance
30
+ * @param page - target page number (or getter returning one) representing total pages to load
31
+ * @returns promise resolving to the last loaded page number
27
32
  *
28
- * @param iteration
29
- * @param page
30
- * @returns
33
+ * @throws Rejects if the iteration encounters a loading error
31
34
  */
32
35
  export declare function iteratorNextPageUntilPage(iteration: PageItemIteration, page: GetterOrValue<number>): Promise<PageNumber>;
@@ -2,16 +2,20 @@ import { type PageLoadingState } from '../loading';
2
2
  import { type Destroyable, type Filter, type Maybe, type PageNumber, type Page } from '@dereekb/util';
3
3
  import { type Observable } from 'rxjs';
4
4
  import { type ItemIteratorNextRequest, type PageItemIteration } from './iteration';
5
+ /**
6
+ * Configuration for limiting the number of pages that can be loaded by a page iterator.
7
+ */
5
8
  export interface ItemPageLimit {
6
9
  /**
7
- * Maximum number of pages to load.
8
- *
9
- * This value should be defined in most cases.
10
- *
11
- * If not defined, the will be no ending iteration.
10
+ * Maximum number of pages to load. Should be defined in most cases to prevent
11
+ * unbounded iteration. If not defined, there is no limit.
12
12
  */
13
13
  readonly maxPageLoadLimit?: Maybe<number>;
14
14
  }
15
+ /**
16
+ * Request object passed to the {@link ItemPageIteratorDelegate.loadItemsForPage} method,
17
+ * providing all context needed to load a specific page.
18
+ */
15
19
  export interface ItemPageIteratorRequest<V, F, C extends ItemPageIterationConfig<F> = ItemPageIterationConfig<F>> extends Page {
16
20
  /**
17
21
  * The base iterator config.
@@ -38,6 +42,10 @@ export interface ItemPageIteratorRequest<V, F, C extends ItemPageIterationConfig
38
42
  */
39
43
  readonly lastState$: Observable<Maybe<PageLoadingState<ItemPageIteratorResult<V>>>>;
40
44
  }
45
+ /**
46
+ * Result returned by the delegate for a single page load, containing the loaded values
47
+ * and pagination status.
48
+ */
41
49
  export interface ItemPageIteratorResult<V> {
42
50
  /**
43
51
  * Error result.
@@ -56,6 +64,10 @@ export interface ItemPageIteratorResult<V> {
56
64
  */
57
65
  readonly end?: boolean;
58
66
  }
67
+ /**
68
+ * Delegate responsible for loading items for a given page request.
69
+ * Implementations define the data-fetching logic for each page.
70
+ */
59
71
  export interface ItemPageIteratorDelegate<V, F, C extends ItemPageIterationConfig<F> = ItemPageIterationConfig<F>> {
60
72
  /**
61
73
  * Returns an observable of items given the input request.
@@ -64,14 +76,30 @@ export interface ItemPageIteratorDelegate<V, F, C extends ItemPageIterationConfi
64
76
  */
65
77
  loadItemsForPage(request: ItemPageIteratorRequest<V, F, C>): Observable<ItemPageIteratorResult<V>>;
66
78
  }
79
+ /**
80
+ * Combined configuration for page iteration, including filter criteria and page limits.
81
+ */
67
82
  export interface ItemPageIterationConfig<F = unknown> extends Filter<F>, ItemPageLimit {
68
83
  }
69
84
  /**
70
- * Default number of pages that can be loaded.
85
+ * Default maximum number of pages that can be loaded by an {@link ItemPageIterator}.
71
86
  */
72
87
  export declare const DEFAULT_ITEM_PAGE_ITERATOR_MAX = 100;
73
88
  /**
74
- * Used for generating new iterations.
89
+ * Factory for creating paginated iteration instances from a delegate and configuration.
90
+ *
91
+ * The iterator itself holds the delegate (data-loading logic) and optional global page limits.
92
+ * Call {@link instance} to create a new iteration session with a specific configuration.
93
+ *
94
+ * @example
95
+ * ```ts
96
+ * const iterator = new ItemPageIterator({
97
+ * loadItemsForPage: (request) => fetchPage(request.page)
98
+ * });
99
+ *
100
+ * const instance = iterator.instance({ filter: 'active', maxPageLoadLimit: 10 });
101
+ * instance.next(); // loads first page
102
+ * ```
75
103
  */
76
104
  export declare class ItemPageIterator<V, F, C extends ItemPageIterationConfig<F> = ItemPageIterationConfig<F>> {
77
105
  private readonly _delegate;
@@ -83,13 +111,17 @@ export declare class ItemPageIterator<V, F, C extends ItemPageIterationConfig<F>
83
111
  getMaxPageLoadLimit(): Maybe<number>;
84
112
  setMaxPageLoadLimit(maxPageLoadLimit: Maybe<number>): void;
85
113
  /**
86
- * Creates a new instance based on the input config.
114
+ * Creates a new iteration instance with the given configuration.
87
115
  *
88
- * @param config
89
- * @returns
116
+ * @param config - filter and page limit configuration for this iteration session
117
+ * @returns new iteration instance ready to begin loading pages
90
118
  */
91
119
  instance(config: C): ItemPageIterationInstance<V, F, C>;
92
120
  }
121
+ /**
122
+ * Internal state snapshot of an {@link ItemPageIterationInstance}, tracking the current
123
+ * and historical loading states across page loads.
124
+ */
93
125
  export interface ItemPageIterationInstanceState<V> {
94
126
  /**
95
127
  * Used for tracking the start/end of a specific next call.
@@ -105,7 +137,11 @@ export interface ItemPageIterationInstanceState<V> {
105
137
  readonly lastSuccessful: Maybe<PageLoadingState<ItemPageIteratorResult<V>>>;
106
138
  }
107
139
  /**
108
- * Configured Iterator instance.
140
+ * Active iteration session created by an {@link ItemPageIterator}.
141
+ *
142
+ * Manages the lifecycle of paginated loading: triggering page loads via {@link next},
143
+ * tracking loading/success/error states, and exposing all results as reactive observables.
144
+ * Implements {@link PageItemIteration} for use with accumulators and other iteration utilities.
109
145
  */
110
146
  export declare class ItemPageIterationInstance<V, F, C extends ItemPageIterationConfig<F> = ItemPageIterationConfig<F>> implements PageItemIteration<V, PageLoadingState<V>>, Destroyable {
111
147
  private readonly _iterator;
@@ -191,12 +227,14 @@ export declare class ItemPageIterationInstance<V, F, C extends ItemPageIteration
191
227
  destroy(): void;
192
228
  }
193
229
  /**
194
- * Is considered the "end" result if:
230
+ * Determines whether an {@link ItemPageIteratorResult} represents the end of iteration.
195
231
  *
196
- * - end is true
197
- * - end is not false and the result value is not empty/null. Uses hasValueOrNotEmpty internally to decide.
232
+ * End is detected when:
233
+ * - `end` is explicitly `true`
234
+ * - `end` is not explicitly `false` and the result value is empty/null (via `hasValueOrNotEmpty`)
235
+ * - Error results are never considered the end
198
236
  *
199
- * @param result
200
- * @returns
237
+ * @param result - the page result to check
238
+ * @returns `true` if this result indicates no more pages are available
201
239
  */
202
240
  export declare function isItemPageIteratorResultEndResult<V>(result: ItemPageIteratorResult<V>): boolean;
@@ -2,6 +2,22 @@ import { type OperatorFunction } from 'rxjs';
2
2
  import { type LoadingContext, type LoadingContextEvent } from './loading.context';
3
3
  import { type Maybe } from '@dereekb/util';
4
4
  /**
5
- * Creates a switchMap operator that will emit the stream of events from the input LoadingContext as soon as a non-null LoadingContext is emitted.
5
+ * Creates a `switchMap` operator that subscribes to the {@link LoadingContext.stream$} of each emitted {@link LoadingContext},
6
+ * emitting `undefined` when the context is nullish.
7
+ *
8
+ * Useful for flattening an observable of optional loading contexts into a single stream of loading events.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const context$ = new BehaviorSubject<Maybe<LoadingContext>>(myLoadingContext);
13
+ *
14
+ * const events$ = context$.pipe(
15
+ * switchMapMaybeLoadingContextStream()
16
+ * );
17
+ * // emits LoadingContextEvent values from myLoadingContext.stream$
18
+ * // emits undefined when context$ emits null/undefined
19
+ * ```
20
+ *
21
+ * @returns an RxJS operator that switches to the stream$ of each non-null LoadingContext
6
22
  */
7
23
  export declare function switchMapMaybeLoadingContextStream(): OperatorFunction<Maybe<LoadingContext>, Maybe<LoadingContextEvent>>;
@@ -2,16 +2,53 @@ import { type Destroyable, type ReadableError } from '@dereekb/util';
2
2
  import { type Observable } from 'rxjs';
3
3
  import { type LoadingContext, type LoadingContextEvent } from './loading.context';
4
4
  /**
5
- * Simple LoadingContext implementation
5
+ * Simple imperative {@link LoadingContext} implementation backed by a {@link BehaviorSubject}.
6
+ *
7
+ * Provides methods to manually set loading, success, and error states. Useful in components
8
+ * or services that need to drive a loading indicator without a dedicated state observable.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const context = new SimpleLoadingContext();
13
+ * // context starts in loading state by default
14
+ *
15
+ * context.setSuccess(); // marks loading as complete
16
+ * context.setError({ message: 'Something went wrong' }); // sets an error
17
+ * context.clearError(); // clears the error but preserves loading state
18
+ * context.destroy(); // completes the internal subject
19
+ * ```
6
20
  */
7
21
  export declare class SimpleLoadingContext implements LoadingContext, Destroyable {
8
22
  private readonly _subject;
9
23
  readonly stream$: Observable<LoadingContextEvent>;
10
24
  constructor(loading?: boolean);
25
+ /**
26
+ * Completes the internal subject, ending the stream.
27
+ */
11
28
  destroy(): void;
29
+ /**
30
+ * Whether the current state has a non-null error.
31
+ */
12
32
  hasError(): boolean;
33
+ /**
34
+ * Clears the current error while preserving other state.
35
+ */
13
36
  clearError(): void;
37
+ /**
38
+ * Convenience method to mark loading as complete (sets loading to false).
39
+ */
14
40
  setSuccess(): void;
41
+ /**
42
+ * Sets the loading flag and clears any existing error.
43
+ *
44
+ * @param loading - whether loading is in progress (defaults to true)
45
+ */
15
46
  setLoading(loading?: boolean): void;
47
+ /**
48
+ * Sets an error state with an optional loading flag.
49
+ *
50
+ * @param error - the error to set
51
+ * @param loading - whether loading is still in progress (defaults to false)
52
+ */
16
53
  setError(error: ReadableError, loading?: boolean): void;
17
54
  }
@@ -74,15 +74,43 @@ export interface LoadingStateContextConfig<T = unknown, S extends LoadingState<T
74
74
  readonly loadingEventForLoadingPair?: Maybe<(state: S, config: LoadingEventForLoadingPairConfigInput) => E>;
75
75
  }
76
76
  export type LoadingEventForLoadingPairConfigInput = Pick<LoadingStateContextConfig, 'showLoadingOnUndefinedValue'>;
77
+ /**
78
+ * Default function for converting a {@link LoadingState} into a {@link LoadingStateContextEvent}.
79
+ *
80
+ * Determines the `loading` flag based on whether an error is present, whether the value is defined,
81
+ * and the `showLoadingOnUndefinedValue` setting. Loading progress is only included while loading.
82
+ */
77
83
  export declare const DEFAULT_LOADING_EVENT_FOR_LOADING_PAIR_FUNCTION: <T = unknown, S extends LoadingState<T> = LoadingState<T>, E extends LoadingStateContextEvent = LoadingContextEvent & S>(state: S, input: LoadingEventForLoadingPairConfigInput) => LoadingStateContextEvent<T>;
78
84
  /**
79
85
  * Input for loadingStateContext()
80
86
  */
81
87
  export type LoadingStateContextInput<T = unknown, S extends LoadingState<T> = LoadingState<T>, E extends LoadingStateContextEvent = LoadingContextEvent & S> = LoadingStateContextConfig<T, S, E> | LoadingStateContextConfig<T, S, E>['obs'];
82
88
  /**
83
- * Creates a new LoadingStateContext from the input.
84
-
85
- * @param input LoadingStateContextInput
86
- * @returns LoadingStateContext
89
+ * Creates a new {@link MutableLoadingStateContext} that wraps an observable of {@link LoadingState} values
90
+ * and exposes reactive accessors for the loading flag, current value, errors, and state stream.
91
+ *
92
+ * Accepts either a raw observable or a {@link LoadingStateContextConfig} for fine-grained control
93
+ * over how loading events are derived from the state.
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * // Create a context from a state observable
98
+ * const context = loadingStateContext(myLoadingState$);
99
+ *
100
+ * // Subscribe to the loading flag
101
+ * context.loading$.subscribe((loading) => console.log('Loading:', loading));
102
+ *
103
+ * // Access the value after loading completes
104
+ * context.value$.subscribe((value) => console.log('Value:', value));
105
+ *
106
+ * // Update the state observable later
107
+ * context.setStateObs(newLoadingState$);
108
+ *
109
+ * // Clean up
110
+ * context.destroy();
111
+ * ```
112
+ *
113
+ * @param input - optional observable or config to initialize the context
114
+ * @returns a mutable loading state context with reactive accessors
87
115
  */
88
116
  export declare function loadingStateContext<T = unknown, S extends LoadingState<T> = LoadingState<T>, E extends LoadingStateContextEvent = LoadingContextEvent & S>(input?: LoadingStateContextInput<T, S, E>): MutableLoadingStateContext<T, S, E>;
@@ -49,9 +49,31 @@ export type ListLoadingStateContextConfig<L, S extends ListLoadingState<L> = Lis
49
49
  */
50
50
  export type ListLoadingStateContextInput<L, S extends ListLoadingState<L> = ListLoadingState<L>> = Omit<LoadingStateContextInput<L[], S>, 'loadingEventForLoadingPair'> | ListLoadingStateContextConfig<L, S>;
51
51
  /**
52
- * Creates a ListLoadingStateContext.
52
+ * Creates a {@link MutableListLoadingStateContext} that wraps a {@link ListLoadingState} observable
53
+ * and provides list-specific reactive accessors like `isEmpty$` and `list$`.
53
54
  *
54
- * @param input Optional configuration for the ListLoadingStateContext.
55
- * @returns A ListLoadingStateContext.
55
+ * Extends {@link loadingStateContext} with list-aware behavior, including optional array length limiting
56
+ * via {@link LimitArrayConfig} and empty-state detection streams.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * const context = listLoadingStateContext<string>();
61
+ *
62
+ * // Set a state observable
63
+ * context.setStateObs(of(successResult(['a', 'b', 'c'])));
64
+ *
65
+ * // Access the list (defaults to [] when undefined)
66
+ * context.list$.subscribe((list) => console.log(list));
67
+ * // => ['a', 'b', 'c']
68
+ *
69
+ * // Check if the list is empty
70
+ * context.isEmpty$.subscribe((empty) => console.log('Empty:', empty));
71
+ * // => false
72
+ *
73
+ * context.destroy();
74
+ * ```
75
+ *
76
+ * @param input - optional observable or config to initialize the context
77
+ * @returns a mutable list loading state context
56
78
  */
57
79
  export declare function listLoadingStateContext<L, S extends ListLoadingState<L> = ListLoadingState<L>>(input?: ListLoadingStateContextInput<L, S>): MutableListLoadingStateContext<L, S>;
@@ -1,19 +1,59 @@
1
1
  import { SimpleLoadingContext } from './loading.context.simple';
2
+ /**
3
+ * Function that returns an array of values to check for completion.
4
+ * If any element is `undefined`, the check considers loading to still be in progress.
5
+ */
2
6
  export type LoadingContextCheckCompletionFunction = () => unknown[];
7
+ /**
8
+ * Configuration for {@link ValuesLoadingContext}.
9
+ */
3
10
  export interface LoadingContextConfiguration {
11
+ /**
12
+ * Initial loading state. Defaults to `true`.
13
+ */
4
14
  loading?: boolean;
15
+ /**
16
+ * Function that returns values to check for loading completion.
17
+ */
5
18
  checkDone?: LoadingContextCheckCompletionFunction;
6
19
  }
7
20
  /**
8
- * Utility object for maintaining a loading stream$. Is triggered into loading, then can be triggered again to see if elements have all completed loading or not.
21
+ * A {@link SimpleLoadingContext} that determines loading completion by checking whether
22
+ * all values returned by a check function are defined.
23
+ *
24
+ * Useful when loading depends on multiple values arriving asynchronously — call {@link check}
25
+ * to re-evaluate whether all required values are present.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * let valueA: string | undefined;
30
+ * let valueB: string | undefined;
31
+ *
32
+ * const context = new ValuesLoadingContext({
33
+ * checkDone: () => [valueA, valueB]
34
+ * });
35
+ * // context.stream$ emits { loading: true }
36
+ *
37
+ * valueA = 'hello';
38
+ * context.check(); // still loading (valueB is undefined)
39
+ *
40
+ * valueB = 'world';
41
+ * context.check(); // loading complete (both defined)
42
+ * // context.stream$ emits { loading: false }
43
+ *
44
+ * context.destroy();
45
+ * ```
9
46
  */
10
47
  export declare class ValuesLoadingContext extends SimpleLoadingContext {
11
48
  private _checkDone?;
12
49
  constructor({ checkDone, loading }?: LoadingContextConfiguration);
13
50
  /**
14
- * Check the array for objects to see if loading is completed.
51
+ * Re-evaluates the check function to determine whether all values are loaded.
52
+ *
53
+ * Sets loading to `false` when every element in the check array is defined.
54
+ * Does nothing if the context currently has an error.
15
55
  *
16
- * The loading state is always modified unless there is an error or no check function.
56
+ * @throws {Error} When no check function was provided in the constructor configuration.
17
57
  */
18
58
  check(): void;
19
59
  }