@dereekb/rxjs 10.0.20 → 10.0.22

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/index.cjs.js CHANGED
@@ -3193,7 +3193,13 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
3193
3193
  * @returns
3194
3194
  */
3195
3195
  function iterationHasNextAndCanLoadMore(iteration) {
3196
- return rxjs.combineLatest([iteration.hasNext$, iteration.canLoadMore$]).pipe(rxjs.map(util.reduceBooleansWithAndFn(true)), rxjs.shareReplay(1));
3196
+ return iteration.canLoadMore$.pipe(rxjs.switchMap(canLoadMore => {
3197
+ if (canLoadMore) {
3198
+ return iteration.hasNext$;
3199
+ } else {
3200
+ return rxjs.of(false);
3201
+ }
3202
+ }), rxjs.shareReplay(1));
3197
3203
  }
3198
3204
  /**
3199
3205
  * Automatically calls next up to the current maxPageLoadLimit configured on the iterator.
@@ -3233,16 +3239,23 @@ function iteratorNextPageUntilPage(iteration, page) {
3233
3239
  const maxLimit = Math.min(pageLimit, (_a = iteration.maxPageLoadLimit) !== null && _a !== void 0 ? _a : Number.MAX_SAFE_INTEGER);
3234
3240
  return page + 1 < maxLimit;
3235
3241
  }
3236
- return new Promise(resolve => {
3237
- iteration.latestLoadedPage$.pipe(rxjs.first()).subscribe(firstLatestPage => {
3238
- const promise = util.performTaskLoop({
3239
- initValue: firstLatestPage,
3240
- checkContinue: latestPage => checkPageLimit(latestPage),
3241
- next: () => __awaiter(this, void 0, void 0, function* () {
3242
- return yield iteration.nextPage();
3243
- })
3244
- });
3245
- resolve(promise);
3242
+ return new Promise((resolve, reject) => {
3243
+ iteration.latestLoadedPage$.pipe(rxjs.first()).subscribe({
3244
+ next: firstLatestPage => {
3245
+ const promise = util.performTaskLoop({
3246
+ initValue: firstLatestPage,
3247
+ checkContinue: latestPage => __awaiter(this, void 0, void 0, function* () {
3248
+ return rxjs.firstValueFrom(iterationHasNextAndCanLoadMore(iteration)).then(canLoadMore => canLoadMore && checkPageLimit(latestPage));
3249
+ }),
3250
+ next: () => __awaiter(this, void 0, void 0, function* () {
3251
+ return yield iteration.nextPage();
3252
+ })
3253
+ });
3254
+ resolve(promise);
3255
+ },
3256
+ error: error => {
3257
+ reject(error);
3258
+ }
3246
3259
  });
3247
3260
  });
3248
3261
  }
@@ -4775,6 +4788,67 @@ function itemAccumulator(itemIteration, mapItem) {
4775
4788
  }
4776
4789
  return new ItemAccumulatorInstance(itemIteration, mapItem);
4777
4790
  }
4791
+ /**
4792
+ * Automatically calls next on the accumulator's page item iteration up to the target number of results. Returns the total number of items loaded.
4793
+ *
4794
+ * The promise will reject with an error if an error is encountered.
4795
+ *
4796
+ * @param iteration
4797
+ * @param maxResultsLimit
4798
+ * @returns
4799
+ */
4800
+ function itemAccumulatorNextPageUntilResultsCount(config) {
4801
+ const {
4802
+ accumulator,
4803
+ maxResultsLimit,
4804
+ countResultsFunction: countResults
4805
+ } = config;
4806
+ const getMaxResultsLimit = util.asGetter(maxResultsLimit);
4807
+ const canLoadMoreObs = iterationHasNextAndCanLoadMore(accumulator.itemIteration).pipe(timeoutStartWith(false, 100),
4808
+ // TODO: This can fail to emit anything if the iterator has been destroyed
4809
+ rxjs.shareReplay(1));
4810
+ function checkResultsLimit() {
4811
+ return __awaiter(this, void 0, void 0, function* () {
4812
+ const allItems = yield rxjs.firstValueFrom(accumulator.currentAllItems$);
4813
+ const canLoadMore = yield rxjs.firstValueFrom(canLoadMoreObs);
4814
+ const currentCount = yield countResults(allItems);
4815
+ const maxResultsLimit = getMaxResultsLimit();
4816
+ const shouldContinue = canLoadMore && currentCount < maxResultsLimit;
4817
+ return {
4818
+ shouldContinue,
4819
+ currentCount
4820
+ };
4821
+ });
4822
+ }
4823
+ return new Promise((resolve, reject) => {
4824
+ accumulator.currentAllItems$.pipe(rxjs.first(), rxjs.switchMap(allItems => rxjs.from(util.asPromise(countResults(allItems))))).subscribe({
4825
+ next: currentResultsCount => __awaiter(this, void 0, void 0, function* () {
4826
+ util.performTaskLoop({
4827
+ initValue: currentResultsCount,
4828
+ checkContinue: (x, i) => __awaiter(this, void 0, void 0, function* () {
4829
+ const result = yield checkResultsLimit();
4830
+ currentResultsCount = result.currentCount;
4831
+ return result.shouldContinue;
4832
+ }),
4833
+ next: () => __awaiter(this, void 0, void 0, function* () {
4834
+ return accumulator.itemIteration.nextPage();
4835
+ })
4836
+ }).then(page => {
4837
+ resolve({
4838
+ page,
4839
+ resultsCount: currentResultsCount
4840
+ });
4841
+ }).catch(error => {
4842
+ reject(error);
4843
+ throw error;
4844
+ });
4845
+ }),
4846
+ error: error => {
4847
+ reject(error);
4848
+ }
4849
+ });
4850
+ });
4851
+ }
4778
4852
 
4779
4853
  /**
4780
4854
  * Used for ItemAccumulators that have an array of results returned per page instead of a single item.
@@ -4815,6 +4889,15 @@ function accumulatorCurrentPageListLoadingState(accumulator) {
4815
4889
  mapValue: () => values
4816
4890
  })), rxjs.shareReplay(1));
4817
4891
  }
4892
+ /**
4893
+ * Returns the latest loaded page number from the input PageItemAccumulator.
4894
+ *
4895
+ * @param pageItemAccumulator
4896
+ * @returns
4897
+ */
4898
+ function pageItemAccumulatorCurrentPage(pageItemAccumulator) {
4899
+ return pageItemAccumulator.itemIteration.latestLoadedPage$;
4900
+ }
4818
4901
 
4819
4902
  class MappedItemIterationInstance {
4820
4903
  constructor(itemIterator, config) {
@@ -5043,12 +5126,12 @@ class ItemPageIterationInstance {
5043
5126
  this.latestSuccessfulPageResults$ = this.state$.pipe(rxjs.map(x => x.lastSuccessful), filterMaybe(), rxjs.shareReplay(1));
5044
5127
  this.currentState$ = this.currentPageResultState$.pipe(mapItemPageLoadingStateFromResultPageLoadingState(), rxjs.shareReplay(1));
5045
5128
  this.latestLoadedPage$ = this.latestPageResultState$.pipe(rxjs.map(x => x.page), rxjs.distinctUntilChanged(), rxjs.shareReplay(1));
5046
- this.numberOfPagesLoaded$ = this.latestLoadedPage$.pipe(rxjs.map(x => x + 1), rxjs.shareReplay(1));
5129
+ this.numberOfPagesLoaded$ = this.latestLoadedPage$.pipe(rxjs.map(x => x + 1), rxjs.defaultIfEmpty(0), rxjs.shareReplay(1));
5047
5130
  // MARK: ItemIteration
5048
5131
  /**
5049
5132
  * Whether or not there are more results to load.
5050
5133
  */
5051
- this.hasNext$ = this.hasReachedEndResult$.pipe(rxjs.map(x => !x), rxjs.shareReplay(1));
5134
+ this.hasNext$ = this.hasReachedEndResult$.pipe(rxjs.map(x => !x), rxjs.defaultIfEmpty(false), rxjs.shareReplay(1));
5052
5135
  /**
5053
5136
  * Whether or not the successfulPageResultsCount has passed the maxPageLoadLimit
5054
5137
  */
@@ -5070,18 +5153,24 @@ class ItemPageIterationInstance {
5070
5153
  this._maxPageLoadLimit.next(limit);
5071
5154
  }
5072
5155
  nextPage(request = {}) {
5073
- return new Promise((resolve, reject) => {
5074
- this._nextFinished$.pipe(rxjs.exhaustMap(() => this.latestPageResultState$), rxjs.first()).subscribe({
5156
+ return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
5157
+ this._nextFinished$.pipe(rxjs.exhaustMap(() => this.latestPageResultState$), rxjs.defaultIfEmpty({
5158
+ error: undefined,
5159
+ page: -1
5160
+ }), rxjs.first()).subscribe({
5075
5161
  next: latestState => {
5076
5162
  if (latestState.error) {
5077
5163
  reject(latestState.error);
5078
5164
  } else {
5079
5165
  resolve(latestState.page);
5080
5166
  }
5167
+ },
5168
+ error: error => {
5169
+ reject(error);
5081
5170
  }
5082
5171
  });
5083
5172
  this.next(request);
5084
- });
5173
+ }));
5085
5174
  }
5086
5175
  next(request = {}) {
5087
5176
  this._pushNext(request);
@@ -5535,6 +5624,7 @@ exports.isLoading = isLoading;
5535
5624
  exports.isNot = isNot;
5536
5625
  exports.isSuccessLoadingState = isSuccessLoadingState;
5537
5626
  exports.itemAccumulator = itemAccumulator;
5627
+ exports.itemAccumulatorNextPageUntilResultsCount = itemAccumulatorNextPageUntilResultsCount;
5538
5628
  exports.iterationHasNextAndCanLoadMore = iterationHasNextAndCanLoadMore;
5539
5629
  exports.iteratorNextPageUntilMaxPageLoadLimit = iteratorNextPageUntilMaxPageLoadLimit;
5540
5630
  exports.iteratorNextPageUntilPage = iteratorNextPageUntilPage;
@@ -5576,6 +5666,7 @@ exports.onFalseToTrue = onFalseToTrue;
5576
5666
  exports.onLockSetNextUnlock = onLockSetNextUnlock;
5577
5667
  exports.onMatchDelta = onMatchDelta;
5578
5668
  exports.onTrueToFalse = onTrueToFalse;
5669
+ exports.pageItemAccumulatorCurrentPage = pageItemAccumulatorCurrentPage;
5579
5670
  exports.pageLoadingStateFromObs = pageLoadingStateFromObs;
5580
5671
  exports.pipeIf = pipeIf;
5581
5672
  exports.preventComplete = preventComplete;
package/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
- import { isObservable, of, switchMap, map, filter, skipWhile, EMPTY, combineLatest, delay, startWith, distinctUntilChanged, mergeMap, BehaviorSubject, shareReplay, skip, first, merge, finalize, scan, exhaustMap, identity, throttleTime, timeout, tap, throwError, timer, takeWhile, delayWhen, asyncScheduler, from, catchError, firstValueFrom, defaultIfEmpty } from 'rxjs';
2
- import { getValueFromGetter, isMaybeSo, areEqualPOJOValues, convertToArray, reduceBooleansWithAndFn, asGetter, performTaskLoop, isMaybeNot, pushItemOrArrayItemsIntoArray, pushArrayItemsIntoArray, forEachWithArray, asArray, filterAndMapFunction, objectKeysEqualityComparatorFunction, objectKeyEqualityComparatorFunction, asPromise, randomNumberFactory, mapKeysIntersectionObjectToArray, mapsHaveSameKeys, incrementingNumberFactory, filterUniqueFunction, build, cachedGetter, allKeyValueTuples, keyValueMapFactory, multiKeyValueMapFactory, setContainsAllValues, setContainsAnyValue, setContainsNoneOfValue, hasSameValues, compareEqualityWithValueFromItemsFunction, searchStringFilterFunction, objectHasKey, toReadableError, reduceBooleansWithOr, reduceBooleansWithAnd, valuesAreBothNullishOrEquivalent, filterMaybeValues, mergeObjects, safeCompareEquality, limitArray, hasNonNullValue, mapFunctionOutputPair, lastValue, flattenArray, filteredPage, FIRST_PAGE, hasValueOrNotEmpty, getNextPageNumber, reduceBooleansWithOrFn } from '@dereekb/util';
1
+ import { isObservable, of, switchMap, map, filter, skipWhile, EMPTY, combineLatest, delay, startWith, distinctUntilChanged, mergeMap, BehaviorSubject, shareReplay, skip, first, merge, finalize, firstValueFrom, scan, exhaustMap, identity, throttleTime, timeout, tap, throwError, timer, takeWhile, delayWhen, asyncScheduler, from, catchError, defaultIfEmpty } from 'rxjs';
2
+ import { getValueFromGetter, isMaybeSo, areEqualPOJOValues, convertToArray, asGetter, performTaskLoop, isMaybeNot, pushItemOrArrayItemsIntoArray, pushArrayItemsIntoArray, forEachWithArray, asArray, filterAndMapFunction, objectKeysEqualityComparatorFunction, objectKeyEqualityComparatorFunction, asPromise, randomNumberFactory, mapKeysIntersectionObjectToArray, mapsHaveSameKeys, incrementingNumberFactory, filterUniqueFunction, build, cachedGetter, allKeyValueTuples, keyValueMapFactory, multiKeyValueMapFactory, setContainsAllValues, setContainsAnyValue, setContainsNoneOfValue, hasSameValues, compareEqualityWithValueFromItemsFunction, searchStringFilterFunction, objectHasKey, toReadableError, reduceBooleansWithOr, reduceBooleansWithAnd, valuesAreBothNullishOrEquivalent, filterMaybeValues, mergeObjects, safeCompareEquality, limitArray, hasNonNullValue, mapFunctionOutputPair, lastValue, flattenArray, filteredPage, FIRST_PAGE, hasValueOrNotEmpty, getNextPageNumber, reduceBooleansWithOrFn } from '@dereekb/util';
3
3
  import ms from 'ms';
4
4
 
5
5
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -3283,7 +3283,13 @@ $$1({ target: 'Promise', stat: true, forced: FORCED_PROMISE_CONSTRUCTOR }, {
3283
3283
  * @returns
3284
3284
  */
3285
3285
  function iterationHasNextAndCanLoadMore(iteration) {
3286
- return combineLatest([iteration.hasNext$, iteration.canLoadMore$]).pipe(map(reduceBooleansWithAndFn(true)), shareReplay(1));
3286
+ return iteration.canLoadMore$.pipe(switchMap(canLoadMore => {
3287
+ if (canLoadMore) {
3288
+ return iteration.hasNext$;
3289
+ } else {
3290
+ return of(false);
3291
+ }
3292
+ }), shareReplay(1));
3287
3293
  }
3288
3294
 
3289
3295
  /**
@@ -3325,14 +3331,19 @@ function iteratorNextPageUntilPage(iteration, page) {
3325
3331
  const maxLimit = Math.min(pageLimit, (_iteration$maxPageLoa = iteration.maxPageLoadLimit) != null ? _iteration$maxPageLoa : Number.MAX_SAFE_INTEGER);
3326
3332
  return page + 1 < maxLimit;
3327
3333
  }
3328
- return new Promise(resolve => {
3329
- iteration.latestLoadedPage$.pipe(first()).subscribe(firstLatestPage => {
3330
- const promise = performTaskLoop({
3331
- initValue: firstLatestPage,
3332
- checkContinue: latestPage => checkPageLimit(latestPage),
3333
- next: async () => await iteration.nextPage()
3334
- });
3335
- resolve(promise);
3334
+ return new Promise((resolve, reject) => {
3335
+ iteration.latestLoadedPage$.pipe(first()).subscribe({
3336
+ next: firstLatestPage => {
3337
+ const promise = performTaskLoop({
3338
+ initValue: firstLatestPage,
3339
+ checkContinue: async latestPage => firstValueFrom(iterationHasNextAndCanLoadMore(iteration)).then(canLoadMore => canLoadMore && checkPageLimit(latestPage)),
3340
+ next: async () => await iteration.nextPage()
3341
+ });
3342
+ resolve(promise);
3343
+ },
3344
+ error: error => {
3345
+ reject(error);
3346
+ }
3336
3347
  });
3337
3348
  });
3338
3349
  }
@@ -5097,6 +5108,66 @@ function itemAccumulator(itemIteration, mapItem) {
5097
5108
  return new ItemAccumulatorInstance(itemIteration, mapItem);
5098
5109
  }
5099
5110
 
5111
+ // MARK: Utility
5112
+
5113
+ /**
5114
+ * Automatically calls next on the accumulator's page item iteration up to the target number of results. Returns the total number of items loaded.
5115
+ *
5116
+ * The promise will reject with an error if an error is encountered.
5117
+ *
5118
+ * @param iteration
5119
+ * @param maxResultsLimit
5120
+ * @returns
5121
+ */
5122
+ function itemAccumulatorNextPageUntilResultsCount(config) {
5123
+ const {
5124
+ accumulator,
5125
+ maxResultsLimit,
5126
+ countResultsFunction: countResults
5127
+ } = config;
5128
+ const getMaxResultsLimit = asGetter(maxResultsLimit);
5129
+ const canLoadMoreObs = iterationHasNextAndCanLoadMore(accumulator.itemIteration).pipe(timeoutStartWith(false, 100),
5130
+ // TODO: This can fail to emit anything if the iterator has been destroyed
5131
+ shareReplay(1));
5132
+ async function checkResultsLimit() {
5133
+ const allItems = await firstValueFrom(accumulator.currentAllItems$);
5134
+ const canLoadMore = await firstValueFrom(canLoadMoreObs);
5135
+ const currentCount = await countResults(allItems);
5136
+ const maxResultsLimit = getMaxResultsLimit();
5137
+ const shouldContinue = canLoadMore && currentCount < maxResultsLimit;
5138
+ return {
5139
+ shouldContinue,
5140
+ currentCount
5141
+ };
5142
+ }
5143
+ return new Promise((resolve, reject) => {
5144
+ accumulator.currentAllItems$.pipe(first(), switchMap(allItems => from(asPromise(countResults(allItems))))).subscribe({
5145
+ next: async currentResultsCount => {
5146
+ performTaskLoop({
5147
+ initValue: currentResultsCount,
5148
+ checkContinue: async (x, i) => {
5149
+ const result = await checkResultsLimit();
5150
+ currentResultsCount = result.currentCount;
5151
+ return result.shouldContinue;
5152
+ },
5153
+ next: async () => accumulator.itemIteration.nextPage()
5154
+ }).then(page => {
5155
+ resolve({
5156
+ page,
5157
+ resultsCount: currentResultsCount
5158
+ });
5159
+ }).catch(error => {
5160
+ reject(error);
5161
+ throw error;
5162
+ });
5163
+ },
5164
+ error: error => {
5165
+ reject(error);
5166
+ }
5167
+ });
5168
+ });
5169
+ }
5170
+
5100
5171
  /**
5101
5172
  * Used for ItemAccumulators that have an array of results returned per page instead of a single item.
5102
5173
  *
@@ -5139,6 +5210,16 @@ function accumulatorCurrentPageListLoadingState(accumulator) {
5139
5210
  })), shareReplay(1));
5140
5211
  }
5141
5212
 
5213
+ /**
5214
+ * Returns the latest loaded page number from the input PageItemAccumulator.
5215
+ *
5216
+ * @param pageItemAccumulator
5217
+ * @returns
5218
+ */
5219
+ function pageItemAccumulatorCurrentPage(pageItemAccumulator) {
5220
+ return pageItemAccumulator.itemIteration.latestLoadedPage$;
5221
+ }
5222
+
5142
5223
  /**
5143
5224
  * An object that maps loading states from one mapping to another.
5144
5225
  */
@@ -5384,12 +5465,12 @@ class ItemPageIterationInstance {
5384
5465
  this.latestSuccessfulPageResults$ = this.state$.pipe(map(x => x.lastSuccessful), filterMaybe(), shareReplay(1));
5385
5466
  this.currentState$ = this.currentPageResultState$.pipe(mapItemPageLoadingStateFromResultPageLoadingState(), shareReplay(1));
5386
5467
  this.latestLoadedPage$ = this.latestPageResultState$.pipe(map(x => x.page), distinctUntilChanged(), shareReplay(1));
5387
- this.numberOfPagesLoaded$ = this.latestLoadedPage$.pipe(map(x => x + 1), shareReplay(1));
5468
+ this.numberOfPagesLoaded$ = this.latestLoadedPage$.pipe(map(x => x + 1), defaultIfEmpty(0), shareReplay(1));
5388
5469
  // MARK: ItemIteration
5389
5470
  /**
5390
5471
  * Whether or not there are more results to load.
5391
5472
  */
5392
- this.hasNext$ = this.hasReachedEndResult$.pipe(map(x => !x), shareReplay(1));
5473
+ this.hasNext$ = this.hasReachedEndResult$.pipe(map(x => !x), defaultIfEmpty(false), shareReplay(1));
5393
5474
  /**
5394
5475
  * Whether or not the successfulPageResultsCount has passed the maxPageLoadLimit
5395
5476
  */
@@ -5411,17 +5492,24 @@ class ItemPageIterationInstance {
5411
5492
  this._maxPageLoadLimit.next(limit);
5412
5493
  }
5413
5494
  nextPage(request = {}) {
5414
- return new Promise((resolve, reject) => {
5415
- this._nextFinished$.pipe(exhaustMap(() => this.latestPageResultState$), first()).subscribe({
5495
+ var _this = this;
5496
+ return new Promise(async function (resolve, reject) {
5497
+ _this._nextFinished$.pipe(exhaustMap(() => _this.latestPageResultState$), defaultIfEmpty({
5498
+ error: undefined,
5499
+ page: -1
5500
+ }), first()).subscribe({
5416
5501
  next: latestState => {
5417
5502
  if (latestState.error) {
5418
5503
  reject(latestState.error);
5419
5504
  } else {
5420
5505
  resolve(latestState.page);
5421
5506
  }
5507
+ },
5508
+ error: error => {
5509
+ reject(error);
5422
5510
  }
5423
5511
  });
5424
- this.next(request);
5512
+ _this.next(request);
5425
5513
  });
5426
5514
  }
5427
5515
  next(request = {}) {
@@ -5839,4 +5927,4 @@ function workFactoryForConfigFactory(configFactory) {
5839
5927
  };
5840
5928
  }
5841
5929
 
5842
- export { AbstractLoadingStateContextInstance, DEFAULT_ASYNC_PUSHER_THROTTLE, DEFAULT_FACTORY_TIMER_INTERVAL, DEFAULT_ITEM_PAGE_ITERATOR_MAX, DEFAULT_LOCK_SET_TIME_LOCK_KEY, FilterMap, FilterMapKeyInstance, FilterSource, FilterSourceConnector, FilterSourceInstance, ItemAccumulatorInstance, ItemPageIterationInstance, ItemPageIterator, ListLoadingStateContextInstance, LoadingStateContextInstance, LoadingStateType, LockSet, MappedItemIterationInstance, MappedPageItemIterationInstance, MultiSubscriptionObject, PresetFilterSource, SimpleLoadingContext, SubscriptionObject, ValuesLoadingContext, WorkInstance, accumulatorCurrentPageListLoadingState, accumulatorFlattenPageListLoadingState, allLoadingStatesHaveFinishedLoading, asObservable, asObservableFromGetter, asyncPusher, asyncPusherCache, beginLoading, beginLoadingPage, checkIs, cleanup, cleanupDestroyable, combineLatestFromArrayObsFn, combineLatestFromMapValuesObsFn, combineLatestFromObject, combineLatestMapFrom, combineLoadingStates, combineLoadingStatesStatus, distinctLoadingState, distinctUntilArrayLengthChanges, distinctUntilHasDifferentValues, distinctUntilItemsHaveDifferentValues, distinctUntilItemsValueChanges, distinctUntilKeysChange, distinctUntilMapHasDifferentKeys, distinctUntilModelIdChange, distinctUntilModelKeyChange, distinctUntilObjectKeyChange, distinctUntilObjectValuesChanged, emitAfterDelay, emitDelayObs, errorFromLoadingState, errorPageResult, errorResult, factoryTimer, filterIfObjectValuesUnchanged, filterItemsWithObservableDecision, filterMaybe, filterUnique, filterWithSearchString, flattenAccumulatorResultItemArray, idleLoadingState, incrementingNumberTimer, initialize, invertObservableDecision, isErrorLoadingState, isItemPageIteratorResultEndResult, isListLoadingStateEmpty, isLoading, isNot, isSuccessLoadingState, itemAccumulator, iterationHasNextAndCanLoadMore, iteratorNextPageUntilMaxPageLoadLimit, iteratorNextPageUntilPage, keyValueMap, lazyFrom, listLoadingStateContext, listLoadingStateIsEmpty, loadingStateContext, loadingStateFromObs, loadingStateHasError, loadingStateHasFinishedLoading, loadingStateHasFinishedLoadingWithError, loadingStateHasFinishedLoadingWithValue, loadingStateHasValue, loadingStateIsIdle, loadingStateIsLoading, loadingStateType, loadingStatesHaveEquivalentMetadata, makeCheckIsFunction, makeMapFilterWithPresetFn, makeReturnIfIsFunction, mapEachAsync, mapFilterWithPreset, mapForEach, mapIf, mapItemIteration, mapKeysIntersectionToArray, mapLoadingState, mapLoadingStateResults, mapLoadingStateValueFunction, mapLoadingStateValueWithOperator, mapMaybe, mapMultipleLoadingStateResults, mapPageItemIteration, maybeValueFromObservableOrValueGetter, mergeLoadingStates, multiKeyValueMap, onFalseToTrue, onLockSetNextUnlock, onMatchDelta, onTrueToFalse, pageLoadingStateFromObs, pipeIf, preventComplete, promiseFromLoadingState, randomDelay, randomDelayWithRandomFunction, returnIfIs, scanBuildArray, scanCount, scanIntoArray, setContainsAllValuesFrom, setContainsAnyValueFrom, setContainsNoValueFrom, skipFirstMaybe, startWithBeginLoading, successPageResult, successResult, switchMapMaybeDefault, switchMapMaybeObs, switchMapObject, switchMapOnBoolean, switchMapToDefault, switchMapWhileFalse, switchMapWhileTrue, tapAfterTimeout, tapFirst, tapLog, tapOnLoadingStateSuccess, tapOnLoadingStateType, throwErrorAfterTimeout, timeoutStartWith, unknownLoadingStatesIsLoading, updatedStateForSetError, updatedStateForSetLoading, updatedStateForSetValue, useAsObservable, useFirst, valueFromFinishedLoadingState, valueFromLoadingState, valueFromObservableOrValue, valueFromObservableOrValueGetter, workFactory, workFactoryForConfigFactory };
5930
+ export { AbstractLoadingStateContextInstance, DEFAULT_ASYNC_PUSHER_THROTTLE, DEFAULT_FACTORY_TIMER_INTERVAL, DEFAULT_ITEM_PAGE_ITERATOR_MAX, DEFAULT_LOCK_SET_TIME_LOCK_KEY, FilterMap, FilterMapKeyInstance, FilterSource, FilterSourceConnector, FilterSourceInstance, ItemAccumulatorInstance, ItemPageIterationInstance, ItemPageIterator, ListLoadingStateContextInstance, LoadingStateContextInstance, LoadingStateType, LockSet, MappedItemIterationInstance, MappedPageItemIterationInstance, MultiSubscriptionObject, PresetFilterSource, SimpleLoadingContext, SubscriptionObject, ValuesLoadingContext, WorkInstance, accumulatorCurrentPageListLoadingState, accumulatorFlattenPageListLoadingState, allLoadingStatesHaveFinishedLoading, asObservable, asObservableFromGetter, asyncPusher, asyncPusherCache, beginLoading, beginLoadingPage, checkIs, cleanup, cleanupDestroyable, combineLatestFromArrayObsFn, combineLatestFromMapValuesObsFn, combineLatestFromObject, combineLatestMapFrom, combineLoadingStates, combineLoadingStatesStatus, distinctLoadingState, distinctUntilArrayLengthChanges, distinctUntilHasDifferentValues, distinctUntilItemsHaveDifferentValues, distinctUntilItemsValueChanges, distinctUntilKeysChange, distinctUntilMapHasDifferentKeys, distinctUntilModelIdChange, distinctUntilModelKeyChange, distinctUntilObjectKeyChange, distinctUntilObjectValuesChanged, emitAfterDelay, emitDelayObs, errorFromLoadingState, errorPageResult, errorResult, factoryTimer, filterIfObjectValuesUnchanged, filterItemsWithObservableDecision, filterMaybe, filterUnique, filterWithSearchString, flattenAccumulatorResultItemArray, idleLoadingState, incrementingNumberTimer, initialize, invertObservableDecision, isErrorLoadingState, isItemPageIteratorResultEndResult, isListLoadingStateEmpty, isLoading, isNot, isSuccessLoadingState, itemAccumulator, itemAccumulatorNextPageUntilResultsCount, iterationHasNextAndCanLoadMore, iteratorNextPageUntilMaxPageLoadLimit, iteratorNextPageUntilPage, keyValueMap, lazyFrom, listLoadingStateContext, listLoadingStateIsEmpty, loadingStateContext, loadingStateFromObs, loadingStateHasError, loadingStateHasFinishedLoading, loadingStateHasFinishedLoadingWithError, loadingStateHasFinishedLoadingWithValue, loadingStateHasValue, loadingStateIsIdle, loadingStateIsLoading, loadingStateType, loadingStatesHaveEquivalentMetadata, makeCheckIsFunction, makeMapFilterWithPresetFn, makeReturnIfIsFunction, mapEachAsync, mapFilterWithPreset, mapForEach, mapIf, mapItemIteration, mapKeysIntersectionToArray, mapLoadingState, mapLoadingStateResults, mapLoadingStateValueFunction, mapLoadingStateValueWithOperator, mapMaybe, mapMultipleLoadingStateResults, mapPageItemIteration, maybeValueFromObservableOrValueGetter, mergeLoadingStates, multiKeyValueMap, onFalseToTrue, onLockSetNextUnlock, onMatchDelta, onTrueToFalse, pageItemAccumulatorCurrentPage, pageLoadingStateFromObs, pipeIf, preventComplete, promiseFromLoadingState, randomDelay, randomDelayWithRandomFunction, returnIfIs, scanBuildArray, scanCount, scanIntoArray, setContainsAllValuesFrom, setContainsAnyValueFrom, setContainsNoValueFrom, skipFirstMaybe, startWithBeginLoading, successPageResult, successResult, switchMapMaybeDefault, switchMapMaybeObs, switchMapObject, switchMapOnBoolean, switchMapToDefault, switchMapWhileFalse, switchMapWhileTrue, tapAfterTimeout, tapFirst, tapLog, tapOnLoadingStateSuccess, tapOnLoadingStateType, throwErrorAfterTimeout, timeoutStartWith, unknownLoadingStatesIsLoading, updatedStateForSetError, updatedStateForSetLoading, updatedStateForSetValue, useAsObservable, useFirst, valueFromFinishedLoadingState, valueFromLoadingState, valueFromObservableOrValue, valueFromObservableOrValueGetter, workFactory, workFactoryForConfigFactory };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/rxjs",
3
- "version": "10.0.20",
3
+ "version": "10.0.22",
4
4
  "exports": {
5
5
  ".": {
6
6
  "types": "./src/index.d.ts",
@@ -1,5 +1,5 @@
1
1
  import { type Observable } from 'rxjs';
2
- import { type MapFunctionOutputPair, type Destroyable, type IndexRef } from '@dereekb/util';
2
+ import { type MapFunctionOutputPair, type Destroyable, type IndexRef, type GetterOrValue, type MapFunction, type PromiseOrValue, type Page } from '@dereekb/util';
3
3
  import { type ItemIteration, type PageItemIteration } from './iteration';
4
4
  import { type LoadingState, type MapLoadingStateValueMapFunction } from '../loading';
5
5
  export type ItemAccumulatorMapFunction<O, I> = MapLoadingStateValueMapFunction<O, I>;
@@ -83,3 +83,22 @@ export declare class ItemAccumulatorInstance<O, I = unknown, N extends ItemItera
83
83
  */
84
84
  export declare function itemAccumulator<I, N extends ItemIteration<I> = ItemIteration<I>>(itemIteration: N): ItemAccumulatorInstance<I, I, N>;
85
85
  export declare function itemAccumulator<O, I, N extends ItemIteration<I> = ItemIteration<I>>(itemIteration: N, mapItem?: ItemAccumulatorMapFunction<O, I>): ItemAccumulatorInstance<O, I, N>;
86
+ export type ItemAccumulatorNextPageUntilResultsCountFunction<O> = MapFunction<O[], PromiseOrValue<number>>;
87
+ export interface ItemAccumulatorNextPageUntilResultsCountConfig<O> {
88
+ readonly accumulator: ItemAccumulator<O, any, PageItemIteration<any>>;
89
+ readonly maxResultsLimit: GetterOrValue<number>;
90
+ readonly countResultsFunction: ItemAccumulatorNextPageUntilResultsCountFunction<O>;
91
+ }
92
+ export interface ItemAccumulatorNextPageUntilResultsCountResult extends Page {
93
+ readonly resultsCount: number;
94
+ }
95
+ /**
96
+ * Automatically calls next on the accumulator's page item iteration up to the target number of results. Returns the total number of items loaded.
97
+ *
98
+ * The promise will reject with an error if an error is encountered.
99
+ *
100
+ * @param iteration
101
+ * @param maxResultsLimit
102
+ * @returns
103
+ */
104
+ export declare function itemAccumulatorNextPageUntilResultsCount<O>(config: ItemAccumulatorNextPageUntilResultsCountConfig<O>): Promise<ItemAccumulatorNextPageUntilResultsCountResult>;
@@ -16,3 +16,10 @@ export declare function accumulatorFlattenPageListLoadingState<T, I = unknown>(a
16
16
  * A PageListLoadingState that captures all the values that have been loaded so far, and the current loading state of currentPageResult$.
17
17
  */
18
18
  export declare function accumulatorCurrentPageListLoadingState<V, I = unknown>(accumulator: PageItemAccumulator<V, I>): Observable<PageListLoadingState<V>>;
19
+ /**
20
+ * Returns the latest loaded page number from the input PageItemAccumulator.
21
+ *
22
+ * @param pageItemAccumulator
23
+ * @returns
24
+ */
25
+ export declare function pageItemAccumulatorCurrentPage(pageItemAccumulator: PageItemAccumulator<any, any>): Observable<number>;
@@ -14,7 +14,21 @@ export interface ItemIteratorNextRequest {
14
14
  retry?: boolean;
15
15
  }
16
16
  export interface ItemIteration<V = unknown, L extends LoadingState<V> = LoadingState<V>> extends Destroyable {
17
+ /**
18
+ * Whether or not there are more items to be loaded.
19
+ *
20
+ * This emits every time a page has finished loading.
21
+ *
22
+ * This will not return false when the max page limit has been reached.
23
+ */
17
24
  readonly hasNext$: Observable<boolean>;
25
+ /**
26
+ * Whether or not more items can be loaded.
27
+ *
28
+ * Similar to hasNext$ but does not emit until the value changes.
29
+ *
30
+ * This returns false if the max page limit has been reached.
31
+ */
18
32
  readonly canLoadMore$: Observable<boolean>;
19
33
  /**
20
34
  * The first stable state that has finished loading.
@@ -50,7 +64,7 @@ export interface PageItemIteration<V = unknown, L extends PageLoadingState<V> =
50
64
  /**
51
65
  * Attempts to loads the next page of results and returns a promise.
52
66
  *
53
- * The promise will return when the next action has completed.
67
+ * The promise will return when the next action has completed, and returns the page number of the loaded page.
54
68
  *
55
69
  * If the page result ends in an error, this promise will throw that error.
56
70
  *
@@ -1,6 +1,6 @@
1
1
  import { type Observable } from 'rxjs';
2
2
  import { type ItemIteration, type PageItemIteration } from './iteration';
3
- import { type Maybe, type GetterOrValue } from '@dereekb/util';
3
+ import { type Maybe, type GetterOrValue, type PageNumber } from '@dereekb/util';
4
4
  /**
5
5
  * Creates an observable from the input iteration that checks both the hasNext$ and canLoadMore$ states.
6
6
  *
@@ -29,4 +29,4 @@ export declare function iteratorNextPageUntilMaxPageLoadLimit(iterator: PageItem
29
29
  * @param page
30
30
  * @returns
31
31
  */
32
- export declare function iteratorNextPageUntilPage(iteration: PageItemIteration, page: GetterOrValue<number>): Promise<number>;
32
+ export declare function iteratorNextPageUntilPage(iteration: PageItemIteration, page: GetterOrValue<number>): Promise<PageNumber>;
@@ -165,7 +165,7 @@ export declare class ItemPageIterationInstance<V, F, C extends ItemPageIteration
165
165
  nextPage(request?: ItemIteratorNextRequest): Promise<number>;
166
166
  readonly currentState$: Observable<PageLoadingState<V>>;
167
167
  readonly latestLoadedPage$: Observable<PageNumber>;
168
- readonly numberOfPagesLoaded$: Observable<PageNumber>;
168
+ readonly numberOfPagesLoaded$: Observable<number>;
169
169
  /**
170
170
  * Whether or not there are more results to load.
171
171
  */