@ethlete/query 2.0.0 → 2.1.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.
- package/esm2020/lib/directives/infinity-query-trigger.directive.mjs +3 -3
- package/esm2020/lib/directives/infinity-query.directive.mjs +6 -6
- package/esm2020/lib/directives/query.directive.mjs +3 -3
- package/esm2020/lib/infinite-query/infinity-query.mjs +13 -4
- package/esm2020/lib/query/query.mjs +46 -8
- package/esm2020/lib/query/query.types.mjs +1 -1
- package/esm2020/lib/query-client/query-client.mjs +3 -1
- package/esm2020/lib/query-client/query-client.types.mjs +1 -1
- package/esm2020/lib/query-store/query-store.mjs +36 -3
- package/fesm2015/ethlete-query.mjs +118 -32
- package/fesm2015/ethlete-query.mjs.map +1 -1
- package/fesm2020/ethlete-query.mjs +104 -23
- package/fesm2020/ethlete-query.mjs.map +1 -1
- package/lib/auth/auth-provider.types.d.ts +0 -5
- package/lib/infinite-query/infinity-query.d.ts +1 -1
- package/lib/query/query.d.ts +6 -2
- package/lib/query/query.types.d.ts +39 -7
- package/lib/query-client/query-client.types.d.ts +11 -0
- package/lib/query-store/query-store.d.ts +3 -0
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BehaviorSubjectWithSubscriberCount, getCookie, setCookie, deleteCookie, DestroyService, equal, clone } from '@ethlete/core';
|
|
2
|
-
import { Observable, filter, takeWhile, switchMap, of, BehaviorSubject, Subject, takeUntil, interval, tap, timer, fromEvent,
|
|
2
|
+
import { Observable, filter, takeWhile, switchMap, of, BehaviorSubject, Subject, takeUntil, interval, startWith, tap, timer, fromEvent, concat, take, debounceTime, combineLatest, map, distinctUntilChanged } from 'rxjs';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { Directive, Input, InjectionToken, inject, ChangeDetectorRef, ViewContainerRef, TemplateRef, ErrorHandler, ElementRef } from '@angular/core';
|
|
5
5
|
import { FormGroup } from '@angular/forms';
|
|
@@ -548,8 +548,22 @@ class Query {
|
|
|
548
548
|
get isInUse() {
|
|
549
549
|
return this._state$.subscriberCount > 0;
|
|
550
550
|
}
|
|
551
|
-
get
|
|
552
|
-
return this.
|
|
551
|
+
get isPolling() {
|
|
552
|
+
return !!this._pollingSubscription;
|
|
553
|
+
}
|
|
554
|
+
get autoRefreshOnConfig() {
|
|
555
|
+
const base = this._queryConfig.autoRefreshOn ?? {};
|
|
556
|
+
const transformed = {
|
|
557
|
+
queryClientDefaultHeadersChange: base.queryClientDefaultHeadersChange ?? true,
|
|
558
|
+
windowFocus: base.windowFocus ?? true,
|
|
559
|
+
};
|
|
560
|
+
return transformed;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* @internal
|
|
564
|
+
*/
|
|
565
|
+
get _enableSmartPolling() {
|
|
566
|
+
return this._queryConfig.enableSmartPolling ?? true;
|
|
553
567
|
}
|
|
554
568
|
constructor(_client, _queryConfig, _routeWithParams, _args) {
|
|
555
569
|
this._client = _client;
|
|
@@ -559,15 +573,21 @@ class Query {
|
|
|
559
573
|
this._currentId = 0;
|
|
560
574
|
this._pollingSubscription = null;
|
|
561
575
|
this._onAbort$ = new Subject();
|
|
576
|
+
this._currentPollConfig = null;
|
|
577
|
+
/**
|
|
578
|
+
* @internal
|
|
579
|
+
*/
|
|
580
|
+
this._isPollingPaused = false;
|
|
562
581
|
this._state$ = new BehaviorSubjectWithSubscriberCount({
|
|
563
582
|
type: "PREPARED" /* QueryStateType.Prepared */,
|
|
564
|
-
meta: { id: this._currentId },
|
|
583
|
+
meta: { id: this._currentId, triggeredVia: 'program' },
|
|
565
584
|
});
|
|
566
585
|
}
|
|
567
586
|
clone() {
|
|
568
587
|
return this._client.fetch(this._queryConfig);
|
|
569
588
|
}
|
|
570
589
|
execute(options) {
|
|
590
|
+
const triggeredVia = options?._triggeredVia ?? 'program';
|
|
571
591
|
if (!this.isExpired && !options?.skipCache && isQueryStateSuccess(this.state)) {
|
|
572
592
|
return this;
|
|
573
593
|
}
|
|
@@ -578,7 +598,7 @@ class Query {
|
|
|
578
598
|
if (isQueryStateLoading(this._state$.value)) {
|
|
579
599
|
this.abort();
|
|
580
600
|
}
|
|
581
|
-
const meta = { id };
|
|
601
|
+
const meta = { id, triggeredVia };
|
|
582
602
|
this._state$.next({
|
|
583
603
|
type: "LOADING" /* QueryStateType.Loading */,
|
|
584
604
|
meta,
|
|
@@ -688,16 +708,34 @@ class Query {
|
|
|
688
708
|
if (this._pollingSubscription) {
|
|
689
709
|
return this;
|
|
690
710
|
}
|
|
691
|
-
this.
|
|
711
|
+
this._currentPollConfig = config;
|
|
712
|
+
const _interval = config.triggerImmediately
|
|
713
|
+
? interval(config.interval).pipe(startWith(-1))
|
|
714
|
+
: interval(config.interval);
|
|
715
|
+
this._pollingSubscription = _interval
|
|
692
716
|
.pipe(takeUntil(config.takeUntil))
|
|
693
|
-
.subscribe(() => this.execute({ skipCache: true }));
|
|
717
|
+
.subscribe(() => this.execute({ skipCache: true, _triggeredVia: 'poll' }));
|
|
694
718
|
return this;
|
|
695
719
|
}
|
|
696
720
|
stopPolling() {
|
|
697
721
|
this._pollingSubscription?.unsubscribe();
|
|
698
722
|
this._pollingSubscription = null;
|
|
723
|
+
this._currentPollConfig = null;
|
|
724
|
+
return this;
|
|
725
|
+
}
|
|
726
|
+
pausePolling() {
|
|
727
|
+
this._pollingSubscription?.unsubscribe();
|
|
728
|
+
this._pollingSubscription = null;
|
|
729
|
+
this._isPollingPaused = true;
|
|
699
730
|
return this;
|
|
700
731
|
}
|
|
732
|
+
resumePolling() {
|
|
733
|
+
if (!this._isPollingPaused || !this._currentPollConfig) {
|
|
734
|
+
return this;
|
|
735
|
+
}
|
|
736
|
+
this._isPollingPaused = false;
|
|
737
|
+
return this.poll({ ...this._currentPollConfig, triggerImmediately: true });
|
|
738
|
+
}
|
|
701
739
|
_updateUseResultInDependencies() {
|
|
702
740
|
if (!this._args?.useResultIn?.length) {
|
|
703
741
|
return;
|
|
@@ -963,9 +1001,9 @@ class QueryDirective {
|
|
|
963
1001
|
}
|
|
964
1002
|
}
|
|
965
1003
|
}
|
|
966
|
-
QueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1
|
|
967
|
-
QueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1
|
|
968
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1
|
|
1004
|
+
QueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: QueryDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: i0.ErrorHandler }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
1005
|
+
QueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.1", type: QueryDirective, isStandalone: true, selector: "[query]", inputs: { query: "query", cache: ["queryCache", "cache"] }, ngImport: i0 });
|
|
1006
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: QueryDirective, decorators: [{
|
|
969
1007
|
type: Directive,
|
|
970
1008
|
args: [{
|
|
971
1009
|
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
@@ -1038,6 +1076,7 @@ class InfinityQuery {
|
|
|
1038
1076
|
console.error('Cannot load more pages, already at the end. Make sure to not render the infinity query trigger using *ngIf canLoadMore');
|
|
1039
1077
|
return;
|
|
1040
1078
|
}
|
|
1079
|
+
this._clearSubscriptions();
|
|
1041
1080
|
const args = this._prepareArgs(this._config, calculatedPage);
|
|
1042
1081
|
const query = this._config.queryCreator.prepare(args).execute();
|
|
1043
1082
|
this._handleNewQuery(query);
|
|
@@ -1046,7 +1085,7 @@ class InfinityQuery {
|
|
|
1046
1085
|
this._currentQuery$.next(query);
|
|
1047
1086
|
}
|
|
1048
1087
|
reset(newConfig) {
|
|
1049
|
-
this.
|
|
1088
|
+
this._clearSubscriptions();
|
|
1050
1089
|
this._config = { ...this._config, ...(newConfig ?? {}) };
|
|
1051
1090
|
this._currentPage$.next(null);
|
|
1052
1091
|
this._currentCalculatedPage$.next(null);
|
|
@@ -1054,8 +1093,9 @@ class InfinityQuery {
|
|
|
1054
1093
|
this._itemsPerPage$.next(this._config.limitParam?.value ?? 10);
|
|
1055
1094
|
this._currentQuery$.next(null);
|
|
1056
1095
|
this._data$.next([]);
|
|
1096
|
+
this.nextPage();
|
|
1057
1097
|
}
|
|
1058
|
-
|
|
1098
|
+
_clearSubscriptions() {
|
|
1059
1099
|
this._subscriptions.forEach((sub) => sub.unsubscribe());
|
|
1060
1100
|
this._subscriptions = [];
|
|
1061
1101
|
}
|
|
@@ -1085,7 +1125,14 @@ class InfinityQuery {
|
|
|
1085
1125
|
this._subscriptions = this._subscriptions.filter((sub) => sub !== stateChangesSub);
|
|
1086
1126
|
},
|
|
1087
1127
|
});
|
|
1088
|
-
|
|
1128
|
+
const queryAutoRefreshSub = query.state$.subscribe({
|
|
1129
|
+
next: (state) => {
|
|
1130
|
+
if (state.meta.triggeredVia === 'auto') {
|
|
1131
|
+
this.reset();
|
|
1132
|
+
}
|
|
1133
|
+
},
|
|
1134
|
+
});
|
|
1135
|
+
this._subscriptions.push(stateChangesSub, queryAutoRefreshSub);
|
|
1089
1136
|
}
|
|
1090
1137
|
_prepareArgs(config, page) {
|
|
1091
1138
|
const pageParamLocation = this._getPageParamLocation(config?.pageParam?.location);
|
|
@@ -1199,7 +1246,7 @@ class InfinityQueryDirective {
|
|
|
1199
1246
|
this._renderMainView();
|
|
1200
1247
|
}
|
|
1201
1248
|
ngOnDestroy() {
|
|
1202
|
-
this.instance?.
|
|
1249
|
+
this.instance?._clearSubscriptions();
|
|
1203
1250
|
}
|
|
1204
1251
|
_setupInfinityQuery(config) {
|
|
1205
1252
|
const instance = new InfinityQuery(config);
|
|
@@ -1265,7 +1312,7 @@ class InfinityQueryDirective {
|
|
|
1265
1312
|
}
|
|
1266
1313
|
_cleanup() {
|
|
1267
1314
|
this._queryConfigChanged$.next(true);
|
|
1268
|
-
this.instance?.
|
|
1315
|
+
this.instance?._clearSubscriptions();
|
|
1269
1316
|
this._viewContext.loading = false;
|
|
1270
1317
|
this._viewContext.error = null;
|
|
1271
1318
|
this._viewContext.infinityQuery = null;
|
|
@@ -1278,9 +1325,9 @@ class InfinityQueryDirective {
|
|
|
1278
1325
|
this._data$.next([]);
|
|
1279
1326
|
}
|
|
1280
1327
|
}
|
|
1281
|
-
InfinityQueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1
|
|
1282
|
-
InfinityQueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1
|
|
1283
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1
|
|
1328
|
+
InfinityQueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1329
|
+
InfinityQueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.1", type: InfinityQueryDirective, isStandalone: true, selector: "[infinityQuery]", inputs: { infinityQuery: "infinityQuery" }, providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }, DestroyService], exportAs: ["infinityQuery"], ngImport: i0 });
|
|
1330
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: InfinityQueryDirective, decorators: [{
|
|
1284
1331
|
type: Directive,
|
|
1285
1332
|
args: [{
|
|
1286
1333
|
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
@@ -1330,9 +1377,9 @@ class InfinityQueryTriggerDirective {
|
|
|
1330
1377
|
this._observer.observe(this._elementRef.nativeElement);
|
|
1331
1378
|
}
|
|
1332
1379
|
}
|
|
1333
|
-
InfinityQueryTriggerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1
|
|
1334
|
-
InfinityQueryTriggerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1
|
|
1335
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1
|
|
1380
|
+
InfinityQueryTriggerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1381
|
+
InfinityQueryTriggerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.1", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[infinityQueryTrigger], infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 });
|
|
1382
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
|
|
1336
1383
|
type: Directive,
|
|
1337
1384
|
args: [{
|
|
1338
1385
|
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
@@ -1348,6 +1395,7 @@ class QueryStore {
|
|
|
1348
1395
|
this._config = _config;
|
|
1349
1396
|
this._store = new Map();
|
|
1350
1397
|
this._garbageCollector = null;
|
|
1398
|
+
this._initSmartQueryHandling();
|
|
1351
1399
|
}
|
|
1352
1400
|
add(id, query) {
|
|
1353
1401
|
this._store.set(id, query);
|
|
@@ -1371,14 +1419,45 @@ class QueryStore {
|
|
|
1371
1419
|
for (const [key, query] of this._store) {
|
|
1372
1420
|
if (query.isInUse &&
|
|
1373
1421
|
(query.isExpired || ignoreCacheValidity) &&
|
|
1374
|
-
|
|
1375
|
-
query.execute({ skipCache: true });
|
|
1422
|
+
query.autoRefreshOnConfig.queryClientDefaultHeadersChange) {
|
|
1423
|
+
query.execute({ skipCache: true, _triggeredVia: 'auto' });
|
|
1376
1424
|
}
|
|
1377
1425
|
else if (purgeUnused && !query.isInUse) {
|
|
1378
1426
|
this.remove(key);
|
|
1379
1427
|
}
|
|
1380
1428
|
}
|
|
1381
1429
|
}
|
|
1430
|
+
_initSmartQueryHandling() {
|
|
1431
|
+
const windowBlur$ = fromEvent(window, 'blur');
|
|
1432
|
+
const windowFocus$ = fromEvent(window, 'focus');
|
|
1433
|
+
windowBlur$.subscribe(() => {
|
|
1434
|
+
this._stopGarbageCollector();
|
|
1435
|
+
if (this._config?.enableSmartPolling) {
|
|
1436
|
+
this.forEach((query) => {
|
|
1437
|
+
if (!query.isPolling || !query._enableSmartPolling) {
|
|
1438
|
+
return;
|
|
1439
|
+
}
|
|
1440
|
+
query.pausePolling();
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
windowFocus$.subscribe(() => {
|
|
1445
|
+
if (this._config?.enableSmartPolling || this._config?.autoRefreshQueriesOnWindowFocus) {
|
|
1446
|
+
this.forEach((query) => {
|
|
1447
|
+
if (this._config?.enableSmartPolling && query._isPollingPaused) {
|
|
1448
|
+
query.resumePolling();
|
|
1449
|
+
}
|
|
1450
|
+
if (this._config?.autoRefreshQueriesOnWindowFocus &&
|
|
1451
|
+
query.isExpired &&
|
|
1452
|
+
query.isInUse &&
|
|
1453
|
+
query.autoRefreshOnConfig.windowFocus) {
|
|
1454
|
+
query.execute({ skipCache: true, _triggeredVia: 'auto' });
|
|
1455
|
+
}
|
|
1456
|
+
});
|
|
1457
|
+
}
|
|
1458
|
+
this._initGarbageCollector();
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1382
1461
|
_logState(key, item, operation) {
|
|
1383
1462
|
if (!this._config?.enableChangeLogging)
|
|
1384
1463
|
return;
|
|
@@ -1538,6 +1617,8 @@ class QueryClient {
|
|
|
1538
1617
|
this._store = new QueryStore({
|
|
1539
1618
|
enableChangeLogging: _clientConfig.logging?.queryStateChanges,
|
|
1540
1619
|
enableGarbageCollectorLogging: _clientConfig.logging?.queryStateGarbageCollector,
|
|
1620
|
+
autoRefreshQueriesOnWindowFocus: _clientConfig.request?.autoRefreshQueriesOnWindowFocus ?? true,
|
|
1621
|
+
enableSmartPolling: _clientConfig.request?.enableSmartPolling ?? true,
|
|
1541
1622
|
});
|
|
1542
1623
|
}
|
|
1543
1624
|
}
|