@ethlete/query 2.9.1 → 3.0.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/index.mjs +2 -1
- package/esm2020/lib/auth/auth-provider.types.mjs +1 -1
- package/esm2020/lib/auth/auth-provider.utils.mjs +1 -1
- package/esm2020/lib/auth/bearer-auth-provider.mjs +2 -2
- package/esm2020/lib/directives/infinity-query-trigger.directive.mjs +4 -4
- package/esm2020/lib/directives/infinity-query.directive.mjs +21 -20
- package/esm2020/lib/directives/query.directive.mjs +9 -11
- package/esm2020/lib/entity/entity-store.mjs +73 -119
- package/esm2020/lib/entity/entity.types.mjs +1 -1
- package/esm2020/lib/entity/entity.utils.mjs +5 -0
- package/esm2020/lib/entity/index.mjs +2 -1
- package/esm2020/lib/infinite-query/infinity-query.mjs +47 -71
- package/esm2020/lib/infinite-query/infinity-query.types.mjs +1 -1
- package/esm2020/lib/infinite-query/infinity-query.utils.mjs +1 -1
- package/esm2020/lib/query/query.mjs +118 -211
- package/esm2020/lib/query/query.types.mjs +1 -1
- package/esm2020/lib/query/query.utils.mjs +1 -1
- package/esm2020/lib/query-client/query-client.mjs +3 -31
- package/esm2020/lib/query-client/query-client.types.mjs +1 -1
- package/esm2020/lib/query-creator/index.mjs +3 -0
- package/esm2020/lib/query-creator/query-creator.mjs +35 -0
- package/esm2020/lib/query-creator/query-creator.types.mjs +2 -0
- package/esm2020/lib/request/request.types.mjs +1 -1
- package/esm2020/lib/request/request.util.mjs +1 -7
- package/fesm2015/ethlete-query.mjs +317 -469
- package/fesm2015/ethlete-query.mjs.map +1 -1
- package/fesm2020/ethlete-query.mjs +311 -472
- package/fesm2020/ethlete-query.mjs.map +1 -1
- package/index.d.ts +1 -0
- package/lib/auth/auth-provider.types.d.ts +3 -4
- package/lib/auth/auth-provider.utils.d.ts +2 -2
- package/lib/auth/bearer-auth-provider.d.ts +1 -1
- package/lib/directives/infinity-query-trigger.directive.d.ts +1 -1
- package/lib/directives/infinity-query.directive.d.ts +6 -10
- package/lib/directives/query.directive.d.ts +7 -7
- package/lib/entity/entity-store.d.ts +13 -27
- package/lib/entity/entity.types.d.ts +0 -5
- package/lib/entity/entity.utils.d.ts +2 -0
- package/lib/entity/index.d.ts +1 -0
- package/lib/infinite-query/infinity-query.d.ts +10 -19
- package/lib/infinite-query/infinity-query.types.d.ts +4 -4
- package/lib/infinite-query/infinity-query.utils.d.ts +2 -3
- package/lib/query/query.d.ts +19 -12
- package/lib/query/query.types.d.ts +86 -51
- package/lib/query/query.utils.d.ts +16 -14
- package/lib/query-client/query-client.d.ts +12 -10
- package/lib/query-client/query-client.types.d.ts +2 -22
- package/lib/query-creator/index.d.ts +2 -0
- package/lib/query-creator/query-creator.d.ts +14 -0
- package/lib/query-creator/query-creator.types.d.ts +13 -0
- package/lib/request/request.types.d.ts +1 -1
- package/lib/request/request.util.d.ts +0 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i1 from '@ethlete/core';
|
|
2
2
|
import { BehaviorSubjectWithSubscriberCount, getCookie, setCookie, deleteCookie, DestroyService, DelayableDirective, equal, clone } from '@ethlete/core';
|
|
3
|
-
import { Observable, filter, takeWhile, switchMap, of, BehaviorSubject, Subject, takeUntil, tap, interval,
|
|
3
|
+
import { Observable, filter, takeWhile, switchMap, of, BehaviorSubject, shareReplay, Subject, takeUntil, tap, interval, skip, map, timer, combineLatest, withLatestFrom, fromEvent, startWith, take, concat, debounceTime, distinctUntilChanged } from 'rxjs';
|
|
4
4
|
import * as i0 from '@angular/core';
|
|
5
5
|
import { Directive, Input, InjectionToken, inject, ChangeDetectorRef, ViewContainerRef, TemplateRef, ErrorHandler, ElementRef } from '@angular/core';
|
|
6
6
|
import { FormGroup } from '@angular/forms';
|
|
@@ -113,12 +113,6 @@ const buildQueryObjectString = (key, object) => {
|
|
|
113
113
|
})
|
|
114
114
|
.join('&');
|
|
115
115
|
};
|
|
116
|
-
const isFetchResponse = (response) => typeof response === 'object' &&
|
|
117
|
-
response !== null &&
|
|
118
|
-
'status' in response &&
|
|
119
|
-
'statusText' in response &&
|
|
120
|
-
'json' in response &&
|
|
121
|
-
typeof response['json'] === 'function';
|
|
122
116
|
const filterInvalidParams = (params) => {
|
|
123
117
|
const filteredParams = Object.entries(params)
|
|
124
118
|
.map(([key, value]) => {
|
|
@@ -706,16 +700,22 @@ class Query {
|
|
|
706
700
|
return ++this._currentId;
|
|
707
701
|
}
|
|
708
702
|
get state$() {
|
|
709
|
-
return this._state$.
|
|
703
|
+
return this._state$.pipe(switchMap((s) => this._transformState(s)), shareReplay({ bufferSize: 1, refCount: true }));
|
|
710
704
|
}
|
|
711
|
-
|
|
705
|
+
/**
|
|
706
|
+
* The current state of the query.
|
|
707
|
+
*
|
|
708
|
+
* **Warning!** This differs from the `state$` observable in that it does not use the query store. Thus, the response data might be outdated.
|
|
709
|
+
* Use `state$` (or `firstValueFrom(state$)`) the most up-to-date data.
|
|
710
|
+
*/
|
|
711
|
+
get rawState() {
|
|
712
712
|
return this._state$.value;
|
|
713
713
|
}
|
|
714
714
|
get isExpired() {
|
|
715
|
-
if (!isQueryStateSuccess(this.
|
|
715
|
+
if (!isQueryStateSuccess(this._state$.value)) {
|
|
716
716
|
return false;
|
|
717
717
|
}
|
|
718
|
-
const ts = this.
|
|
718
|
+
const ts = this._state$.value.meta.expiresAt;
|
|
719
719
|
if (!ts) {
|
|
720
720
|
return true;
|
|
721
721
|
}
|
|
@@ -751,7 +751,7 @@ class Query {
|
|
|
751
751
|
this._args = _args;
|
|
752
752
|
this._currentId = 0;
|
|
753
753
|
this._pollingSubscription = null;
|
|
754
|
-
this.
|
|
754
|
+
this._requestSubscription = null;
|
|
755
755
|
this._onAbort$ = new Subject();
|
|
756
756
|
this._currentPollConfig = null;
|
|
757
757
|
/**
|
|
@@ -762,193 +762,39 @@ class Query {
|
|
|
762
762
|
type: "PREPARED" /* QueryStateType.Prepared */,
|
|
763
763
|
meta: { id: this._currentId, triggeredVia: 'program' },
|
|
764
764
|
});
|
|
765
|
-
if (this._queryConfig.entity?.store) {
|
|
766
|
-
this._entitySubscription = this._queryConfig.entity.store.events$.subscribe((event) => {
|
|
767
|
-
if (event.type !== 'update' && event.type !== 'set') {
|
|
768
|
-
return;
|
|
769
|
-
}
|
|
770
|
-
if (!isQueryStateSuccess(this.state)) {
|
|
771
|
-
return;
|
|
772
|
-
}
|
|
773
|
-
const response = this.state.response;
|
|
774
|
-
const rawResponse = this.state.rawResponse;
|
|
775
|
-
const key = this._queryConfig.entity?.store.config.idKey;
|
|
776
|
-
if (!key) {
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
779
|
-
const newData = this._queryConfig.entity?.store.getOne(event.key);
|
|
780
|
-
if (!newData) {
|
|
781
|
-
return;
|
|
782
|
-
}
|
|
783
|
-
const newResponse = this._queryConfig.entity?.valueUpdater
|
|
784
|
-
? this._queryConfig.entity?.valueUpdater({
|
|
785
|
-
args: this._args,
|
|
786
|
-
entity: newData,
|
|
787
|
-
rawResponse,
|
|
788
|
-
response,
|
|
789
|
-
})
|
|
790
|
-
: response[key] === newData[key]
|
|
791
|
-
? {
|
|
792
|
-
response: newData,
|
|
793
|
-
rawResponse: newData,
|
|
794
|
-
}
|
|
795
|
-
: null;
|
|
796
|
-
if (!newResponse) {
|
|
797
|
-
return;
|
|
798
|
-
}
|
|
799
|
-
this._state$.next({
|
|
800
|
-
...this.state,
|
|
801
|
-
response: newResponse.response,
|
|
802
|
-
rawResponse: newResponse.rawResponse,
|
|
803
|
-
meta: {
|
|
804
|
-
...this.state.meta,
|
|
805
|
-
triggeredVia: 'auto',
|
|
806
|
-
},
|
|
807
|
-
});
|
|
808
|
-
});
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
clone() {
|
|
812
|
-
return this._client.fetch(this._queryConfig);
|
|
813
765
|
}
|
|
814
|
-
execute(options) {
|
|
815
|
-
const
|
|
816
|
-
|
|
766
|
+
execute(options = {}) {
|
|
767
|
+
const { skipCache = false, _triggeredVia: triggeredVia = 'program' } = options;
|
|
768
|
+
const { authProvider } = this._client;
|
|
769
|
+
const queryConfig = this._queryConfig;
|
|
770
|
+
if (!this.isExpired && !skipCache && isQueryStateSuccess(this.rawState)) {
|
|
817
771
|
return this;
|
|
818
772
|
}
|
|
819
|
-
if (
|
|
773
|
+
if (queryConfig.secure && !authProvider) {
|
|
820
774
|
throw new Error('Cannot execute secure query without auth provider');
|
|
821
775
|
}
|
|
822
776
|
const id = this._nextId;
|
|
823
|
-
|
|
777
|
+
const meta = { id, triggeredVia };
|
|
778
|
+
if (isQueryStateLoading(this.rawState)) {
|
|
824
779
|
this.abort();
|
|
825
780
|
}
|
|
826
|
-
|
|
827
|
-
this.
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
this._updateUseResultInDependencies();
|
|
832
|
-
const method = computeQueryMethod({ config: this._queryConfig, client: this._client });
|
|
833
|
-
const body = computeQueryBody({
|
|
834
|
-
config: this._queryConfig,
|
|
835
|
-
client: this._client,
|
|
836
|
-
args: this._args,
|
|
837
|
-
method,
|
|
838
|
-
});
|
|
839
|
-
const headers = computeQueryHeaders({ client: this._client, config: this._queryConfig, args: this._args });
|
|
840
|
-
request({
|
|
781
|
+
this._state$.next({ type: "LOADING" /* QueryStateType.Loading */, meta });
|
|
782
|
+
const method = computeQueryMethod({ config: queryConfig, client: this._client });
|
|
783
|
+
const body = computeQueryBody({ config: queryConfig, client: this._client, args: this._args, method });
|
|
784
|
+
const headers = computeQueryHeaders({ client: this._client, config: queryConfig, args: this._args });
|
|
785
|
+
this._requestSubscription = request({
|
|
841
786
|
urlWithParams: this._routeWithParams,
|
|
842
787
|
method,
|
|
843
788
|
body,
|
|
844
789
|
headers,
|
|
845
|
-
reportProgress:
|
|
846
|
-
responseType:
|
|
847
|
-
withCredentials:
|
|
790
|
+
reportProgress: queryConfig.reportProgress,
|
|
791
|
+
responseType: queryConfig.responseType,
|
|
792
|
+
withCredentials: queryConfig.withCredentials,
|
|
848
793
|
cacheAdapter: this._client.config.request?.cacheAdapter,
|
|
849
794
|
retryFn: this._client.config.request?.retryFn,
|
|
850
795
|
})
|
|
851
|
-
.pipe(takeUntil(this._onAbort$))
|
|
852
|
-
.subscribe(
|
|
853
|
-
next: (state) => {
|
|
854
|
-
if (state.type === 'start' || state.type === 'delay-retry') {
|
|
855
|
-
const newMeta = {
|
|
856
|
-
...meta,
|
|
857
|
-
isWaitingForRetry: state.type === 'delay-retry',
|
|
858
|
-
retryDelay: state.retryDelay,
|
|
859
|
-
retryNumber: state.retryNumber,
|
|
860
|
-
};
|
|
861
|
-
this._state$.next({
|
|
862
|
-
type: "LOADING" /* QueryStateType.Loading */,
|
|
863
|
-
meta: newMeta,
|
|
864
|
-
});
|
|
865
|
-
}
|
|
866
|
-
else if (state.type === 'download-progress') {
|
|
867
|
-
this._state$.next({
|
|
868
|
-
type: "LOADING" /* QueryStateType.Loading */,
|
|
869
|
-
progress: state.progress,
|
|
870
|
-
partialText: state.partialText,
|
|
871
|
-
meta,
|
|
872
|
-
});
|
|
873
|
-
}
|
|
874
|
-
else if (state.type === 'upload-progress') {
|
|
875
|
-
this._state$.next({
|
|
876
|
-
type: "LOADING" /* QueryStateType.Loading */,
|
|
877
|
-
progress: state.progress,
|
|
878
|
-
meta,
|
|
879
|
-
});
|
|
880
|
-
}
|
|
881
|
-
else if (state.type === 'success') {
|
|
882
|
-
const isResponseObject = typeof state.response === 'object';
|
|
883
|
-
const isGql = isGqlQueryConfig(this._queryConfig);
|
|
884
|
-
let responseData = null;
|
|
885
|
-
if (isGql &&
|
|
886
|
-
isResponseObject &&
|
|
887
|
-
!!state.response &&
|
|
888
|
-
typeof state.response === 'object' &&
|
|
889
|
-
'data' in state.response) {
|
|
890
|
-
responseData = state.response['data'];
|
|
891
|
-
}
|
|
892
|
-
else {
|
|
893
|
-
responseData = state.response;
|
|
894
|
-
}
|
|
895
|
-
const transformedResponse = this._queryConfig.responseTransformer
|
|
896
|
-
? this._queryConfig.responseTransformer(responseData)
|
|
897
|
-
: responseData;
|
|
898
|
-
this._queryConfig.entity?.successAction?.({
|
|
899
|
-
args: this._args,
|
|
900
|
-
rawResponse: state.response,
|
|
901
|
-
response: transformedResponse,
|
|
902
|
-
store: this._queryConfig.entity.store,
|
|
903
|
-
});
|
|
904
|
-
this._state$.next({
|
|
905
|
-
type: "SUCCESS" /* QueryStateType.Success */,
|
|
906
|
-
rawResponse: state.response,
|
|
907
|
-
response: transformedResponse,
|
|
908
|
-
meta: { ...meta, expiresAt: state.expiresInTimestamp },
|
|
909
|
-
});
|
|
910
|
-
}
|
|
911
|
-
else if (state.type === 'failure') {
|
|
912
|
-
const failure = () => {
|
|
913
|
-
this._state$.next({
|
|
914
|
-
type: "FAILURE" /* QueryStateType.Failure */,
|
|
915
|
-
error: state.error,
|
|
916
|
-
meta,
|
|
917
|
-
});
|
|
918
|
-
};
|
|
919
|
-
const bearerAuthProvider = this._getBearerAuthProvider();
|
|
920
|
-
if (!bearerAuthProvider || options?._isUnauthorizedRetry) {
|
|
921
|
-
return failure();
|
|
922
|
-
}
|
|
923
|
-
else if (state.error.status === 401 /* HttpStatusCode.Unauthorized */ &&
|
|
924
|
-
bearerAuthProvider.shouldRefreshOnUnauthorizedResponse) {
|
|
925
|
-
const query = bearerAuthProvider._refreshQuery();
|
|
926
|
-
if (!query) {
|
|
927
|
-
return failure();
|
|
928
|
-
}
|
|
929
|
-
query.state$
|
|
930
|
-
.pipe(takeUntilResponse(), takeUntil(this._onAbort$), tap((state) => {
|
|
931
|
-
if (isQueryStateSuccess(state)) {
|
|
932
|
-
this.execute({ ...options, _isUnauthorizedRetry: true });
|
|
933
|
-
}
|
|
934
|
-
else if (isQueryStateFailure(state)) {
|
|
935
|
-
failure();
|
|
936
|
-
}
|
|
937
|
-
}))
|
|
938
|
-
.subscribe();
|
|
939
|
-
}
|
|
940
|
-
else {
|
|
941
|
-
failure();
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
else if (state.type === 'cancel') {
|
|
945
|
-
this._state$.next({
|
|
946
|
-
type: "CANCELLED" /* QueryStateType.Cancelled */,
|
|
947
|
-
meta,
|
|
948
|
-
});
|
|
949
|
-
}
|
|
950
|
-
},
|
|
951
|
-
});
|
|
796
|
+
.pipe(takeUntil(this._onAbort$), tap((state) => this._updateEntityState(state, meta, options)))
|
|
797
|
+
.subscribe();
|
|
952
798
|
return this;
|
|
953
799
|
}
|
|
954
800
|
abort() {
|
|
@@ -960,16 +806,11 @@ class Query {
|
|
|
960
806
|
return this;
|
|
961
807
|
}
|
|
962
808
|
this._currentPollConfig = config;
|
|
963
|
-
const
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
.subscribe(() => {
|
|
969
|
-
if (this.state.type === "LOADING" /* QueryStateType.Loading */) {
|
|
970
|
-
return;
|
|
971
|
-
}
|
|
972
|
-
this.execute({ skipCache: true, _triggeredVia: 'poll' });
|
|
809
|
+
const interval$ = interval(config.interval);
|
|
810
|
+
const poll$ = interval$.pipe(skip(config.triggerImmediately ? 0 : 1), takeUntil(config.takeUntil), takeWhile(() => !this._isPollingPaused), filter(() => !isQueryStateLoading(this._state$.value)));
|
|
811
|
+
this._pollingSubscription = poll$.subscribe({
|
|
812
|
+
next: () => this.execute({ skipCache: true, _triggeredVia: 'poll' }),
|
|
813
|
+
complete: () => this.stopPolling(),
|
|
973
814
|
});
|
|
974
815
|
return this;
|
|
975
816
|
}
|
|
@@ -992,26 +833,6 @@ class Query {
|
|
|
992
833
|
this._isPollingPaused = false;
|
|
993
834
|
return this.poll({ ...this._currentPollConfig, triggerImmediately: true });
|
|
994
835
|
}
|
|
995
|
-
_updateUseResultInDependencies() {
|
|
996
|
-
if (!this._args?.useResultIn?.length) {
|
|
997
|
-
return;
|
|
998
|
-
}
|
|
999
|
-
this.state$
|
|
1000
|
-
.pipe(filterSuccess(), takeUntil(this._onAbort$), takeUntilResponse(), tap((state) => {
|
|
1001
|
-
if (!this._args?.useResultIn) {
|
|
1002
|
-
return;
|
|
1003
|
-
}
|
|
1004
|
-
for (const query of this._args.useResultIn) {
|
|
1005
|
-
query._state$.next({
|
|
1006
|
-
type: "SUCCESS" /* QueryStateType.Success */,
|
|
1007
|
-
meta: { ...state.meta, id: query._nextId },
|
|
1008
|
-
rawResponse: state.rawResponse,
|
|
1009
|
-
response: state.response,
|
|
1010
|
-
});
|
|
1011
|
-
}
|
|
1012
|
-
}))
|
|
1013
|
-
.subscribe();
|
|
1014
|
-
}
|
|
1015
836
|
/**
|
|
1016
837
|
* @internal
|
|
1017
838
|
*/
|
|
@@ -1019,7 +840,7 @@ class Query {
|
|
|
1019
840
|
this._state$.complete();
|
|
1020
841
|
this._onAbort$.complete();
|
|
1021
842
|
this._pollingSubscription?.unsubscribe();
|
|
1022
|
-
this.
|
|
843
|
+
this._requestSubscription?.unsubscribe();
|
|
1023
844
|
}
|
|
1024
845
|
_getBearerAuthProvider() {
|
|
1025
846
|
const authProvider = this._client.authProvider;
|
|
@@ -1028,6 +849,86 @@ class Query {
|
|
|
1028
849
|
}
|
|
1029
850
|
return null;
|
|
1030
851
|
}
|
|
852
|
+
_updateEntityState(requestEvent, meta, options) {
|
|
853
|
+
switch (requestEvent.type) {
|
|
854
|
+
case 'start':
|
|
855
|
+
case 'delay-retry': {
|
|
856
|
+
const { type, retryDelay, retryNumber } = requestEvent;
|
|
857
|
+
const newMeta = { ...meta, isWaitingForRetry: type === 'delay-retry', retryDelay, retryNumber };
|
|
858
|
+
this._state$.next({
|
|
859
|
+
type: "LOADING" /* QueryStateType.Loading */,
|
|
860
|
+
meta: newMeta,
|
|
861
|
+
});
|
|
862
|
+
break;
|
|
863
|
+
}
|
|
864
|
+
case 'upload-progress':
|
|
865
|
+
case 'download-progress': {
|
|
866
|
+
this._state$.next({
|
|
867
|
+
type: "LOADING" /* QueryStateType.Loading */,
|
|
868
|
+
progress: requestEvent.progress,
|
|
869
|
+
partialText: 'partialText' in requestEvent ? requestEvent.partialText : undefined,
|
|
870
|
+
meta,
|
|
871
|
+
});
|
|
872
|
+
break;
|
|
873
|
+
}
|
|
874
|
+
case 'success': {
|
|
875
|
+
const { response, expiresInTimestamp } = requestEvent;
|
|
876
|
+
const isGql = isGqlQueryConfig(this._queryConfig);
|
|
877
|
+
const responseData = isGql && typeof response === 'object' && !!response && 'data' in response
|
|
878
|
+
? response['data']
|
|
879
|
+
: response;
|
|
880
|
+
this._state$.next({
|
|
881
|
+
type: "SUCCESS" /* QueryStateType.Success */,
|
|
882
|
+
response: responseData,
|
|
883
|
+
meta: { ...meta, expiresAt: expiresInTimestamp },
|
|
884
|
+
});
|
|
885
|
+
if (this._queryConfig.entity && this._queryConfig.entity.set) {
|
|
886
|
+
const id = this._queryConfig.entity?.id({ args: this._args, response: responseData });
|
|
887
|
+
this._queryConfig.entity?.set({
|
|
888
|
+
args: this._args,
|
|
889
|
+
response: responseData,
|
|
890
|
+
id,
|
|
891
|
+
store: this._queryConfig.entity.store,
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
break;
|
|
895
|
+
}
|
|
896
|
+
case 'failure': {
|
|
897
|
+
const { error } = requestEvent;
|
|
898
|
+
const failure = () => this._state$.next({ type: "FAILURE" /* QueryStateType.Failure */, error, meta });
|
|
899
|
+
const bearerAuthProvider = this._getBearerAuthProvider();
|
|
900
|
+
if (!bearerAuthProvider ||
|
|
901
|
+
options?._isUnauthorizedRetry ||
|
|
902
|
+
error.status !== 401 /* HttpStatusCode.Unauthorized */ ||
|
|
903
|
+
!bearerAuthProvider.shouldRefreshOnUnauthorizedResponse) {
|
|
904
|
+
return failure();
|
|
905
|
+
}
|
|
906
|
+
const query = bearerAuthProvider._refreshQuery();
|
|
907
|
+
if (!query)
|
|
908
|
+
return failure();
|
|
909
|
+
query.state$
|
|
910
|
+
.pipe(takeUntilResponse(), takeUntil(this._onAbort$), tap((state) => isQueryStateSuccess(state) ? this.execute({ ...options, _isUnauthorizedRetry: true }) : failure()))
|
|
911
|
+
.subscribe();
|
|
912
|
+
break;
|
|
913
|
+
}
|
|
914
|
+
case 'cancel': {
|
|
915
|
+
this._state$.next({
|
|
916
|
+
type: "CANCELLED" /* QueryStateType.Cancelled */,
|
|
917
|
+
meta,
|
|
918
|
+
});
|
|
919
|
+
break;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
_transformState(s) {
|
|
924
|
+
if (!isQueryStateSuccess(s) || !this._queryConfig.entity?.get) {
|
|
925
|
+
return of(s);
|
|
926
|
+
}
|
|
927
|
+
const id = this._queryConfig.entity.id({ args: this._args, response: s.response });
|
|
928
|
+
return this._queryConfig.entity
|
|
929
|
+
.get({ args: this._args, id, response: s.response, store: this._queryConfig.entity.store })
|
|
930
|
+
.pipe(map((v) => ({ ...s, response: v })));
|
|
931
|
+
}
|
|
1031
932
|
}
|
|
1032
933
|
|
|
1033
934
|
const isBasicAuthProvider = (authProvider) => authProvider instanceof BasicAuthProvider;
|
|
@@ -1154,7 +1055,7 @@ class BearerAuthProvider {
|
|
|
1154
1055
|
* @internal
|
|
1155
1056
|
*/
|
|
1156
1057
|
_refreshQuery() {
|
|
1157
|
-
if (isQueryStateLoading(this._currentRefreshQuery$.getValue()?.
|
|
1058
|
+
if (isQueryStateLoading(this._currentRefreshQuery$.getValue()?.rawState)) {
|
|
1158
1059
|
return;
|
|
1159
1060
|
}
|
|
1160
1061
|
const currentRefreshToken = this.tokens.refreshToken;
|
|
@@ -1223,8 +1124,7 @@ class QueryDirective {
|
|
|
1223
1124
|
this._subscription = null;
|
|
1224
1125
|
this._viewContext = {
|
|
1225
1126
|
$implicit: null,
|
|
1226
|
-
|
|
1227
|
-
raw: null,
|
|
1127
|
+
etQuery: null,
|
|
1228
1128
|
loading: false,
|
|
1229
1129
|
error: null,
|
|
1230
1130
|
progress: null,
|
|
@@ -1260,14 +1160,12 @@ class QueryDirective {
|
|
|
1260
1160
|
this._viewContext.progress = null;
|
|
1261
1161
|
}
|
|
1262
1162
|
if (isQueryStateSuccess(state)) {
|
|
1263
|
-
this._viewContext.
|
|
1163
|
+
this._viewContext.etQuery = state.response;
|
|
1264
1164
|
this._viewContext.$implicit = state.response;
|
|
1265
|
-
this._viewContext.raw = state.rawResponse;
|
|
1266
1165
|
}
|
|
1267
1166
|
else if (!this.cache) {
|
|
1268
|
-
this._viewContext.
|
|
1167
|
+
this._viewContext.etQuery = null;
|
|
1269
1168
|
this._viewContext.$implicit = null;
|
|
1270
|
-
this._viewContext.raw = null;
|
|
1271
1169
|
}
|
|
1272
1170
|
if (isQueryStateFailure(state)) {
|
|
1273
1171
|
this._viewContext.error = state.error;
|
|
@@ -1286,22 +1184,22 @@ class QueryDirective {
|
|
|
1286
1184
|
}
|
|
1287
1185
|
}
|
|
1288
1186
|
QueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: QueryDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: i0.ErrorHandler }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
1289
|
-
QueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: QueryDirective, isStandalone: true, selector: "[
|
|
1187
|
+
QueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: QueryDirective, isStandalone: true, selector: "[etQuery]", inputs: { query: ["etQuery", "query"], cache: ["etQueryCache", "cache"] }, ngImport: i0 });
|
|
1290
1188
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: QueryDirective, decorators: [{
|
|
1291
1189
|
type: Directive,
|
|
1292
1190
|
args: [{
|
|
1293
1191
|
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
1294
|
-
selector: '[
|
|
1192
|
+
selector: '[etQuery]',
|
|
1295
1193
|
standalone: true,
|
|
1296
1194
|
}]
|
|
1297
1195
|
}], ctorParameters: function () { return [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: i0.ErrorHandler }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { query: [{
|
|
1298
|
-
type: Input
|
|
1196
|
+
type: Input,
|
|
1197
|
+
args: ['etQuery']
|
|
1299
1198
|
}], cache: [{
|
|
1300
1199
|
type: Input,
|
|
1301
|
-
args: ['
|
|
1200
|
+
args: ['etQueryCache']
|
|
1302
1201
|
}] } });
|
|
1303
1202
|
|
|
1304
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1305
1203
|
class InfinityQuery {
|
|
1306
1204
|
get currentPage$() {
|
|
1307
1205
|
return this._currentPage$.asObservable();
|
|
@@ -1327,28 +1225,57 @@ class InfinityQuery {
|
|
|
1327
1225
|
get itemsPerPage() {
|
|
1328
1226
|
return this._itemsPerPage$.getValue();
|
|
1329
1227
|
}
|
|
1330
|
-
get currentQuery$() {
|
|
1331
|
-
return this._currentQuery$.asObservable();
|
|
1332
|
-
}
|
|
1333
|
-
get currentQuery() {
|
|
1334
|
-
return this._currentQuery$.getValue();
|
|
1335
|
-
}
|
|
1336
1228
|
get data$() {
|
|
1337
|
-
return this._data
|
|
1229
|
+
return this._data$;
|
|
1338
1230
|
}
|
|
1339
|
-
get
|
|
1340
|
-
return this.
|
|
1231
|
+
get currentQuery$() {
|
|
1232
|
+
return this._lastQuery$;
|
|
1341
1233
|
}
|
|
1342
1234
|
constructor(_config) {
|
|
1343
1235
|
this._config = _config;
|
|
1236
|
+
this._queries$ = new BehaviorSubject([]);
|
|
1344
1237
|
this._currentPage$ = new BehaviorSubject(null);
|
|
1345
1238
|
this._currentCalculatedPage$ = new BehaviorSubject(null);
|
|
1346
1239
|
this._totalPages$ = new BehaviorSubject(null);
|
|
1347
1240
|
this._itemsPerPage$ = new BehaviorSubject(this._config.limitParam?.value ?? 10);
|
|
1348
|
-
this.
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1241
|
+
this._data$ = this._queries$.pipe(switchMap((queries) => {
|
|
1242
|
+
if (!queries.length) {
|
|
1243
|
+
return of([]);
|
|
1244
|
+
}
|
|
1245
|
+
return combineLatest(queries.map((query) => query.state$));
|
|
1246
|
+
}), tap((states) => {
|
|
1247
|
+
const lastState = states[states.length - 1];
|
|
1248
|
+
if (!isQueryStateSuccess(lastState)) {
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
const totalPages = this._config.response.totalPagesExtractor?.({
|
|
1252
|
+
response: lastState.response,
|
|
1253
|
+
itemsPerPage: this.itemsPerPage,
|
|
1254
|
+
}) ??
|
|
1255
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1256
|
+
lastState.response?.totalPages ??
|
|
1257
|
+
null;
|
|
1258
|
+
this._totalPages$.next(totalPages);
|
|
1259
|
+
}), map((states) => {
|
|
1260
|
+
const fullData = states.reduce((acc, state) => {
|
|
1261
|
+
if (isQueryStateSuccess(state)) {
|
|
1262
|
+
let data = this._config?.response.valueExtractor(state.response);
|
|
1263
|
+
if (this._config.response.reverse) {
|
|
1264
|
+
data = [...data].reverse();
|
|
1265
|
+
}
|
|
1266
|
+
if (this._config.response.appendItemsTo === 'start') {
|
|
1267
|
+
acc.unshift(...data);
|
|
1268
|
+
}
|
|
1269
|
+
else {
|
|
1270
|
+
acc.push(...data);
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
return acc;
|
|
1274
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1275
|
+
}, []);
|
|
1276
|
+
return fullData;
|
|
1277
|
+
}), shareReplay({ bufferSize: 1, refCount: true }));
|
|
1278
|
+
this._lastQuery$ = this._queries$.pipe(map((queries) => queries[queries.length - 1] ?? null), shareReplay({ bufferSize: 1, refCount: true }));
|
|
1352
1279
|
}
|
|
1353
1280
|
nextPage() {
|
|
1354
1281
|
const newPage = (this._currentPage$.value ?? 0) + 1;
|
|
@@ -1361,73 +1288,21 @@ class InfinityQuery {
|
|
|
1361
1288
|
console.error('Cannot load more pages, already at the end. Make sure to not render the infinity query trigger using *ngIf canLoadMore');
|
|
1362
1289
|
return;
|
|
1363
1290
|
}
|
|
1364
|
-
this._clearSubscriptions();
|
|
1365
1291
|
const args = this._prepareArgs(this._config, calculatedPage);
|
|
1366
1292
|
const query = this._config.queryCreator.prepare(args).execute();
|
|
1367
|
-
this.
|
|
1293
|
+
this._queries$.next([...this._queries$.value, query]);
|
|
1368
1294
|
this._currentPage$.next(newPage);
|
|
1369
1295
|
this._currentCalculatedPage$.next(calculatedPage);
|
|
1370
|
-
this._currentQuery$.next(query);
|
|
1371
1296
|
}
|
|
1372
1297
|
reset(newConfig) {
|
|
1373
|
-
this._clearSubscriptions();
|
|
1374
1298
|
this._config = { ...this._config, ...(newConfig ?? {}) };
|
|
1375
1299
|
this._currentPage$.next(null);
|
|
1376
1300
|
this._currentCalculatedPage$.next(null);
|
|
1377
1301
|
this._totalPages$.next(null);
|
|
1378
1302
|
this._itemsPerPage$.next(this._config.limitParam?.value ?? 10);
|
|
1379
|
-
this.
|
|
1380
|
-
this._data$.next([]);
|
|
1303
|
+
this._queries$.next([]);
|
|
1381
1304
|
this.nextPage();
|
|
1382
1305
|
}
|
|
1383
|
-
/**
|
|
1384
|
-
* @internal
|
|
1385
|
-
*/
|
|
1386
|
-
_clearSubscriptions() {
|
|
1387
|
-
this._subscriptions.forEach((sub) => sub.unsubscribe());
|
|
1388
|
-
this._subscriptions = [];
|
|
1389
|
-
this._responsiveDataSubscription?.unsubscribe();
|
|
1390
|
-
}
|
|
1391
|
-
_handleNewQuery(query) {
|
|
1392
|
-
const stateChangesSub = query.state$.pipe(takeUntilResponse(), filterSuccess()).subscribe({
|
|
1393
|
-
next: (state) => {
|
|
1394
|
-
let newData = this._config?.response.valueExtractor(state.response);
|
|
1395
|
-
if (this._config.response.reverse) {
|
|
1396
|
-
newData = [...newData].reverse();
|
|
1397
|
-
}
|
|
1398
|
-
if (this._config.response.appendItemsTo === 'start') {
|
|
1399
|
-
newData = [...newData, ...this.data];
|
|
1400
|
-
}
|
|
1401
|
-
else {
|
|
1402
|
-
newData = [...this.data, ...newData];
|
|
1403
|
-
}
|
|
1404
|
-
if (query.store) {
|
|
1405
|
-
this._responsiveDataSubscription?.unsubscribe();
|
|
1406
|
-
const key = query.store.idKey;
|
|
1407
|
-
const responsiveData = query.store.entities$.pipe(map((entities) => newData.map((item) => {
|
|
1408
|
-
// TODO(TRB): This is kind of unsafe. The entity array keys might not be the same as the response keys
|
|
1409
|
-
const index = entities.values.findIndex((entity) => entity[key] === item[key]);
|
|
1410
|
-
return index > -1 ? entities.values[index] : item;
|
|
1411
|
-
})));
|
|
1412
|
-
this._responsiveDataSubscription = responsiveData.subscribe((data) => this._data$.next(data));
|
|
1413
|
-
}
|
|
1414
|
-
else {
|
|
1415
|
-
this._data$.next(newData);
|
|
1416
|
-
}
|
|
1417
|
-
const totalPages = this._config.response.totalPagesExtractor?.({
|
|
1418
|
-
response: state.response,
|
|
1419
|
-
itemsPerPage: this.itemsPerPage,
|
|
1420
|
-
}) ??
|
|
1421
|
-
state.response?.totalPages ??
|
|
1422
|
-
null;
|
|
1423
|
-
this._totalPages$.next(totalPages);
|
|
1424
|
-
},
|
|
1425
|
-
complete: () => {
|
|
1426
|
-
this._subscriptions = this._subscriptions.filter((sub) => sub !== stateChangesSub);
|
|
1427
|
-
},
|
|
1428
|
-
});
|
|
1429
|
-
this._subscriptions.push(stateChangesSub);
|
|
1430
|
-
}
|
|
1431
1306
|
_prepareArgs(config, page) {
|
|
1432
1307
|
const pageParamLocation = this._getPageParamLocation(config?.pageParam?.location);
|
|
1433
1308
|
const pageArgs = {
|
|
@@ -1502,6 +1377,7 @@ class InfinityQueryDirective {
|
|
|
1502
1377
|
currentCalculatedPage: null,
|
|
1503
1378
|
totalPages: null,
|
|
1504
1379
|
itemsPerPage: null,
|
|
1380
|
+
currentQuery: null,
|
|
1505
1381
|
};
|
|
1506
1382
|
this._infinityQueryInstance = null;
|
|
1507
1383
|
this._destroy$ = inject(DestroyService, { host: true }).destroy$;
|
|
@@ -1511,6 +1387,7 @@ class InfinityQueryDirective {
|
|
|
1511
1387
|
this._errorHandler = inject(ErrorHandler);
|
|
1512
1388
|
this._delayable = inject(DelayableDirective, { host: true });
|
|
1513
1389
|
this._data$ = new BehaviorSubject([]);
|
|
1390
|
+
this._didReceiveFirstData$ = new BehaviorSubject(false);
|
|
1514
1391
|
this._isMainViewCreated = false;
|
|
1515
1392
|
}
|
|
1516
1393
|
get infinityQuery() {
|
|
@@ -1540,20 +1417,22 @@ class InfinityQueryDirective {
|
|
|
1540
1417
|
ngOnInit() {
|
|
1541
1418
|
this._renderMainView();
|
|
1542
1419
|
}
|
|
1543
|
-
ngOnDestroy() {
|
|
1544
|
-
this.instance?._clearSubscriptions();
|
|
1545
|
-
}
|
|
1546
1420
|
_setupInfinityQuery(config) {
|
|
1547
1421
|
const instance = new InfinityQuery(config);
|
|
1548
|
-
combineLatest([
|
|
1549
|
-
.pipe(
|
|
1422
|
+
combineLatest([
|
|
1423
|
+
instance.currentQuery$.pipe(switchQueryState(), withLatestFrom(instance.currentQuery$)),
|
|
1424
|
+
this._delayable.isDelayed$,
|
|
1425
|
+
this._didReceiveFirstData$,
|
|
1426
|
+
])
|
|
1427
|
+
.pipe(tap(([[state, currentQuery], isDelayed, didReceiveFirstData]) => {
|
|
1550
1428
|
this._viewContext.currentPage = instance.currentPage;
|
|
1551
1429
|
this._viewContext.totalPages = instance.totalPages;
|
|
1552
1430
|
this._viewContext.itemsPerPage = instance.itemsPerPage;
|
|
1553
1431
|
this._viewContext.canLoadMore =
|
|
1554
1432
|
(instance.totalPages && instance.currentPage && instance.totalPages > instance.currentPage) || false;
|
|
1555
1433
|
this._viewContext.currentCalculatedPage = instance.currentCalculatedPage;
|
|
1556
|
-
|
|
1434
|
+
this._viewContext.currentQuery = currentQuery;
|
|
1435
|
+
if (isQueryStateLoading(state) || isDelayed || (!didReceiveFirstData && isQueryStateSuccess(state))) {
|
|
1557
1436
|
this._viewContext.loading = true;
|
|
1558
1437
|
this._viewContext.error = null;
|
|
1559
1438
|
this._viewContext.isFirstLoad = this.context.infinityQuery === null;
|
|
@@ -1579,27 +1458,24 @@ class InfinityQueryDirective {
|
|
|
1579
1458
|
this._viewContext.currentPage = null;
|
|
1580
1459
|
this._viewContext.itemsPerPage = null;
|
|
1581
1460
|
this._viewContext.totalPages = null;
|
|
1461
|
+
this._viewContext.currentQuery = null;
|
|
1582
1462
|
this._data$.next([]);
|
|
1583
1463
|
}
|
|
1584
1464
|
this._cdr.markForCheck();
|
|
1585
1465
|
}), takeUntil(this._destroy$), takeUntil(this._queryConfigChanged$))
|
|
1586
1466
|
.subscribe();
|
|
1587
1467
|
instance.data$
|
|
1588
|
-
.pipe(tap((data) => {
|
|
1468
|
+
.pipe(skip(1), tap((data) => {
|
|
1589
1469
|
this._viewContext.infinityQuery = this._viewContext.$implicit = data;
|
|
1590
1470
|
this._data$.next(data);
|
|
1471
|
+
if (!this._didReceiveFirstData$.getValue()) {
|
|
1472
|
+
this._didReceiveFirstData$.next(true);
|
|
1473
|
+
}
|
|
1591
1474
|
this._cdr.markForCheck();
|
|
1592
1475
|
}), takeUntil(this._destroy$), takeUntil(this._queryConfigChanged$))
|
|
1593
1476
|
.subscribe();
|
|
1594
1477
|
return instance;
|
|
1595
1478
|
}
|
|
1596
|
-
/**
|
|
1597
|
-
* @deprecated Use `loadNextPage` instead
|
|
1598
|
-
* @breaking 3.0.0
|
|
1599
|
-
*/
|
|
1600
|
-
_loadNextPage() {
|
|
1601
|
-
this.loadNextPage();
|
|
1602
|
-
}
|
|
1603
1479
|
loadNextPage() {
|
|
1604
1480
|
if (!this._infinityQueryInstance) {
|
|
1605
1481
|
return;
|
|
@@ -1623,7 +1499,6 @@ class InfinityQueryDirective {
|
|
|
1623
1499
|
}
|
|
1624
1500
|
_cleanup() {
|
|
1625
1501
|
this._queryConfigChanged$.next(true);
|
|
1626
|
-
this.instance?._clearSubscriptions();
|
|
1627
1502
|
this._viewContext.loading = false;
|
|
1628
1503
|
this._viewContext.error = null;
|
|
1629
1504
|
this._viewContext.infinityQuery = null;
|
|
@@ -1633,17 +1508,18 @@ class InfinityQueryDirective {
|
|
|
1633
1508
|
this._viewContext.currentPage = null;
|
|
1634
1509
|
this._viewContext.itemsPerPage = null;
|
|
1635
1510
|
this._viewContext.totalPages = null;
|
|
1511
|
+
this._viewContext.currentQuery = null;
|
|
1636
1512
|
this._data$.next([]);
|
|
1637
1513
|
}
|
|
1638
1514
|
}
|
|
1639
1515
|
InfinityQueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1640
|
-
InfinityQueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: InfinityQueryDirective, isStandalone: true, selector: "[
|
|
1516
|
+
InfinityQueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: InfinityQueryDirective, isStandalone: true, selector: "[etInfinityQuery]", inputs: { infinityQuery: "infinityQuery" }, providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }, DestroyService], exportAs: ["etInfinityQuery"], hostDirectives: [{ directive: i1.DelayableDirective }], ngImport: i0 });
|
|
1641
1517
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryDirective, decorators: [{
|
|
1642
1518
|
type: Directive,
|
|
1643
1519
|
args: [{
|
|
1644
1520
|
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
1645
|
-
selector: '[
|
|
1646
|
-
exportAs: '
|
|
1521
|
+
selector: '[etInfinityQuery]',
|
|
1522
|
+
exportAs: 'etInfinityQuery',
|
|
1647
1523
|
standalone: true,
|
|
1648
1524
|
providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }, DestroyService],
|
|
1649
1525
|
hostDirectives: [DelayableDirective],
|
|
@@ -1662,7 +1538,7 @@ class InfinityQueryTriggerDirective {
|
|
|
1662
1538
|
this.scrollContainerSelector = null;
|
|
1663
1539
|
}
|
|
1664
1540
|
ngOnInit() {
|
|
1665
|
-
const isInteractive = this._elementRef.nativeElement.hasAttribute('
|
|
1541
|
+
const isInteractive = this._elementRef.nativeElement.hasAttribute('etInfinityQueryTrigger');
|
|
1666
1542
|
if (isInteractive) {
|
|
1667
1543
|
this.click$.pipe(takeUntil(this._destroy)).subscribe(() => this._infinityQuery.loadNextPage());
|
|
1668
1544
|
}
|
|
@@ -1690,155 +1566,144 @@ class InfinityQueryTriggerDirective {
|
|
|
1690
1566
|
}
|
|
1691
1567
|
}
|
|
1692
1568
|
InfinityQueryTriggerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1693
|
-
InfinityQueryTriggerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[
|
|
1569
|
+
InfinityQueryTriggerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[etInfinityQueryTrigger], et-infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 });
|
|
1694
1570
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
|
|
1695
1571
|
type: Directive,
|
|
1696
1572
|
args: [{
|
|
1697
1573
|
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
1698
|
-
selector: '[
|
|
1574
|
+
selector: '[etInfinityQueryTrigger], et-infinity-query-trigger',
|
|
1699
1575
|
standalone: true,
|
|
1700
1576
|
}]
|
|
1701
1577
|
}], propDecorators: { scrollContainerSelector: [{
|
|
1702
1578
|
type: Input
|
|
1703
1579
|
}] } });
|
|
1704
1580
|
|
|
1705
|
-
class
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
return [...this._keys];
|
|
1711
|
-
}
|
|
1712
|
-
get values() {
|
|
1713
|
-
return [...this._dictionary.values()];
|
|
1714
|
-
}
|
|
1715
|
-
get size() {
|
|
1716
|
-
return this._keys.size;
|
|
1717
|
-
}
|
|
1718
|
-
get isEmpty() {
|
|
1719
|
-
return this.size === 0;
|
|
1720
|
-
}
|
|
1721
|
-
get config() {
|
|
1722
|
-
return this._config;
|
|
1723
|
-
}
|
|
1724
|
-
get idKey() {
|
|
1725
|
-
return this._config.idKey || 'id';
|
|
1581
|
+
class EntityStoreError extends Error {
|
|
1582
|
+
constructor(message, detail) {
|
|
1583
|
+
super(message);
|
|
1584
|
+
this.detail = detail;
|
|
1585
|
+
this.name = 'EntityStoreError';
|
|
1726
1586
|
}
|
|
1587
|
+
}
|
|
1588
|
+
class EntityStore {
|
|
1727
1589
|
constructor(_config) {
|
|
1728
1590
|
this._config = _config;
|
|
1729
1591
|
this._dictionary = new Map();
|
|
1730
|
-
this.
|
|
1731
|
-
this._events$ = new Subject();
|
|
1732
|
-
this.entities$ = this.events$.pipe(startWith(null), debounceTime(0), map(() => ({
|
|
1733
|
-
keys: this.keys,
|
|
1734
|
-
values: this.values,
|
|
1735
|
-
})));
|
|
1736
|
-
}
|
|
1737
|
-
getOne(key) {
|
|
1738
|
-
const value = this._dictionary.get(key);
|
|
1739
|
-
if (!value) {
|
|
1740
|
-
console.error(`EntityStore: ${this._config.name || 'unknown'}: missing key "${key}" for get`);
|
|
1741
|
-
return null;
|
|
1742
|
-
}
|
|
1743
|
-
if (this._config.logActions) {
|
|
1744
|
-
console.log(`EntityStore: ${this._config.name || 'unknown'}: get "${key}"`);
|
|
1745
|
-
}
|
|
1746
|
-
return value;
|
|
1592
|
+
this._change$ = new Subject();
|
|
1747
1593
|
}
|
|
1748
|
-
|
|
1749
|
-
|
|
1594
|
+
select(keyOrKeys) {
|
|
1595
|
+
if (Array.isArray(keyOrKeys)) {
|
|
1596
|
+
return this._selectMany(keyOrKeys);
|
|
1597
|
+
}
|
|
1598
|
+
return this._select(keyOrKeys);
|
|
1750
1599
|
}
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1600
|
+
set(keyOrKeys, valueOrValues) {
|
|
1601
|
+
if (Array.isArray(keyOrKeys)) {
|
|
1602
|
+
if (!Array.isArray(valueOrValues)) {
|
|
1603
|
+
throw new EntityStoreError('When setting multiple keys, values must be an array', {
|
|
1604
|
+
keyOrValues: keyOrKeys,
|
|
1605
|
+
valueOrValues,
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
for (let i = 0; i < keyOrKeys.length; i++) {
|
|
1609
|
+
this._set(keyOrKeys[i], valueOrValues[i]);
|
|
1610
|
+
}
|
|
1756
1611
|
}
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
const event = { type: 'add', key };
|
|
1760
|
-
this._events$.next(event);
|
|
1761
|
-
if (this._config.logActions) {
|
|
1762
|
-
console.log(`EntityStore: ${this._config.name || 'unknown'}: add "${key}"`);
|
|
1612
|
+
else {
|
|
1613
|
+
this._set(keyOrKeys, valueOrValues);
|
|
1763
1614
|
}
|
|
1764
|
-
|
|
1615
|
+
this._change$.next(keyOrKeys);
|
|
1765
1616
|
}
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
const key = this.getKey(value);
|
|
1772
|
-
const existing = this._dictionary.get(key);
|
|
1773
|
-
if (!existing) {
|
|
1774
|
-
console.error(`EntityStore: ${this._config.name || 'unknown'}: missing key "${key}" for update`);
|
|
1775
|
-
return null;
|
|
1617
|
+
remove(keyOrKeys) {
|
|
1618
|
+
if (Array.isArray(keyOrKeys)) {
|
|
1619
|
+
for (const key of keyOrKeys) {
|
|
1620
|
+
this._remove(key);
|
|
1621
|
+
}
|
|
1776
1622
|
}
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
this._events$.next(event);
|
|
1780
|
-
if (this._config.logActions) {
|
|
1781
|
-
console.log(`EntityStore: ${this._config.name || 'unknown'}: update "${key}"`);
|
|
1623
|
+
else {
|
|
1624
|
+
this._remove(keyOrKeys);
|
|
1782
1625
|
}
|
|
1783
|
-
|
|
1626
|
+
this._change$.next(keyOrKeys);
|
|
1784
1627
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1628
|
+
logState() {
|
|
1629
|
+
console.log('EntityStore:', this._config.name, {
|
|
1630
|
+
dictionary: this._dictionary,
|
|
1631
|
+
});
|
|
1788
1632
|
}
|
|
1789
|
-
|
|
1790
|
-
const key = this.getKey(value);
|
|
1791
|
-
this._dictionary.set(key, value);
|
|
1792
|
-
this._keys.add(key);
|
|
1793
|
-
const event = { type: 'set', key };
|
|
1794
|
-
this._events$.next(event);
|
|
1633
|
+
_select(key) {
|
|
1795
1634
|
if (this._config.logActions) {
|
|
1796
|
-
console.log(
|
|
1635
|
+
console.log('EntityStore: select', this._config.name, key);
|
|
1797
1636
|
}
|
|
1798
|
-
return
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1637
|
+
return this._change$.pipe(startWith(null), filter((v) => {
|
|
1638
|
+
if (v === null) {
|
|
1639
|
+
return true;
|
|
1640
|
+
}
|
|
1641
|
+
if (Array.isArray(v)) {
|
|
1642
|
+
return v.includes(key);
|
|
1643
|
+
}
|
|
1644
|
+
return v === key;
|
|
1645
|
+
}), map(() => this._dictionary.get(key) ?? null));
|
|
1803
1646
|
}
|
|
1804
|
-
|
|
1805
|
-
if (!this._dictionary.has(key)) {
|
|
1806
|
-
console.error(`EntityStore: ${this._config.name || 'unknown'}: missing key "${key}" for remove`);
|
|
1807
|
-
return null;
|
|
1808
|
-
}
|
|
1809
|
-
this._dictionary.delete(key);
|
|
1810
|
-
this._keys.delete(key);
|
|
1811
|
-
const event = { type: 'remove', key };
|
|
1812
|
-
this._events$.next(event);
|
|
1647
|
+
_selectMany(keys) {
|
|
1813
1648
|
if (this._config.logActions) {
|
|
1814
|
-
console.log(
|
|
1649
|
+
console.log('EntityStore: selectMany', this._config.name, keys);
|
|
1815
1650
|
}
|
|
1816
|
-
return
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1651
|
+
return this._change$.pipe(startWith(null), filter((v) => {
|
|
1652
|
+
if (v === null) {
|
|
1653
|
+
return true;
|
|
1654
|
+
}
|
|
1655
|
+
if (Array.isArray(v)) {
|
|
1656
|
+
return keys.some((key) => v.includes(key));
|
|
1657
|
+
}
|
|
1658
|
+
return keys.includes(v);
|
|
1659
|
+
}), map(() => keys.map((key) => this._dictionary.get(key)).filter((value) => value !== undefined)));
|
|
1824
1660
|
}
|
|
1825
|
-
|
|
1826
|
-
this.
|
|
1827
|
-
|
|
1661
|
+
_set(key, value) {
|
|
1662
|
+
if (this._config.logActions) {
|
|
1663
|
+
console.log('EntityStore: set', this._config.name, key, value);
|
|
1664
|
+
}
|
|
1665
|
+
this._dictionary.set(key, value);
|
|
1828
1666
|
}
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
if (key === undefined) {
|
|
1833
|
-
throw new Error(`EntityStore: ${this._config.name || 'unknown'}: missing key`);
|
|
1667
|
+
_remove(key) {
|
|
1668
|
+
if (this._config.logActions) {
|
|
1669
|
+
console.log('EntityStore: remove', this._config.name, key);
|
|
1834
1670
|
}
|
|
1835
|
-
|
|
1671
|
+
this._dictionary.delete(key);
|
|
1836
1672
|
}
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
function mapToPaginated(response) {
|
|
1676
|
+
return map((items) => ({ ...response, items }));
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
class QueryCreator {
|
|
1680
|
+
constructor(_queryConfig, _client, _store) {
|
|
1681
|
+
this._queryConfig = _queryConfig;
|
|
1682
|
+
this._client = _client;
|
|
1683
|
+
this._store = _store;
|
|
1684
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1685
|
+
// @ts-ignore
|
|
1686
|
+
this.prepare = (args) => {
|
|
1687
|
+
const route = buildRoute({
|
|
1688
|
+
base: this._client.config.baseRoute,
|
|
1689
|
+
route: this._queryConfig.route,
|
|
1690
|
+
pathParams: args?.pathParams,
|
|
1691
|
+
queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
|
|
1692
|
+
});
|
|
1693
|
+
const cacheKey = isGqlQueryConfig(this._queryConfig) ? buildGqlCacheKey(this._queryConfig, args) : route;
|
|
1694
|
+
if (shouldCacheQuery(this._queryConfig.method)) {
|
|
1695
|
+
const existingQuery = this._store.get(cacheKey);
|
|
1696
|
+
if (existingQuery) {
|
|
1697
|
+
return existingQuery;
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
const query = new Query(this._client, this._queryConfig, route, args ?? {});
|
|
1701
|
+
if (shouldCacheQuery(this._queryConfig.method)) {
|
|
1702
|
+
this._store.add(cacheKey, query);
|
|
1703
|
+
}
|
|
1704
|
+
return query;
|
|
1705
|
+
};
|
|
1706
|
+
this.behaviorSubject = (initialValue) => new BehaviorSubject(initialValue ?? null);
|
|
1842
1707
|
}
|
|
1843
1708
|
}
|
|
1844
1709
|
|
|
@@ -1971,20 +1836,6 @@ class QueryStore {
|
|
|
1971
1836
|
}
|
|
1972
1837
|
}
|
|
1973
1838
|
|
|
1974
|
-
const shouldCacheQuery = (method) => {
|
|
1975
|
-
return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
|
|
1976
|
-
};
|
|
1977
|
-
const buildGqlCacheKey = (config, args) => {
|
|
1978
|
-
const { query } = config;
|
|
1979
|
-
const variables = args?.variables || {};
|
|
1980
|
-
const queryWithoutNewLinesAndWhitespace = query.replace(/\s/g, '');
|
|
1981
|
-
const queryFirst50Chars = queryWithoutNewLinesAndWhitespace.slice(0, 50);
|
|
1982
|
-
const queryMiddle25Chars = queryWithoutNewLinesAndWhitespace.slice(queryWithoutNewLinesAndWhitespace.length / 2 - 25, queryWithoutNewLinesAndWhitespace.length / 2 + 25);
|
|
1983
|
-
const queryLast50Chars = queryWithoutNewLinesAndWhitespace.slice(-50);
|
|
1984
|
-
const vars = JSON.stringify(variables);
|
|
1985
|
-
return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
|
|
1986
|
-
};
|
|
1987
|
-
|
|
1988
1839
|
class QueryClient {
|
|
1989
1840
|
get config() {
|
|
1990
1841
|
return this._clientConfig;
|
|
@@ -2026,33 +1877,7 @@ class QueryClient {
|
|
|
2026
1877
|
...queryConfig,
|
|
2027
1878
|
method: 'GQL_MUTATE',
|
|
2028
1879
|
});
|
|
2029
|
-
this.fetch = (queryConfig) =>
|
|
2030
|
-
const prepare = (args) => {
|
|
2031
|
-
const route = buildRoute({
|
|
2032
|
-
base: this._clientConfig.baseRoute,
|
|
2033
|
-
route: queryConfig.route,
|
|
2034
|
-
pathParams: args?.pathParams,
|
|
2035
|
-
queryParams: computeQueryQueryParams({ config: queryConfig, client: this, args }),
|
|
2036
|
-
});
|
|
2037
|
-
const cacheKey = isGqlQueryConfig(queryConfig) ? buildGqlCacheKey(queryConfig, args) : route;
|
|
2038
|
-
if (shouldCacheQuery(queryConfig.method)) {
|
|
2039
|
-
const existingQuery = this._store.get(cacheKey);
|
|
2040
|
-
if (existingQuery) {
|
|
2041
|
-
return existingQuery;
|
|
2042
|
-
}
|
|
2043
|
-
}
|
|
2044
|
-
const query = new Query(this, queryConfig, route, args ?? {});
|
|
2045
|
-
if (shouldCacheQuery(queryConfig.method)) {
|
|
2046
|
-
this._store.add(cacheKey, query);
|
|
2047
|
-
}
|
|
2048
|
-
return query;
|
|
2049
|
-
};
|
|
2050
|
-
const behaviorSubject = (initialValue = null) => new BehaviorSubject(initialValue);
|
|
2051
|
-
return {
|
|
2052
|
-
prepare,
|
|
2053
|
-
behaviorSubject,
|
|
2054
|
-
};
|
|
2055
|
-
};
|
|
1880
|
+
this.fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
|
|
2056
1881
|
this.setAuthProvider = (authProvider) => {
|
|
2057
1882
|
if (this.authProvider) {
|
|
2058
1883
|
throw new Error('The auth provider is already set. Please call clearAuthProvider() first.');
|
|
@@ -2085,6 +1910,20 @@ class QueryClient {
|
|
|
2085
1910
|
}
|
|
2086
1911
|
}
|
|
2087
1912
|
|
|
1913
|
+
const shouldCacheQuery = (method) => {
|
|
1914
|
+
return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
|
|
1915
|
+
};
|
|
1916
|
+
const buildGqlCacheKey = (config, args) => {
|
|
1917
|
+
const { query } = config;
|
|
1918
|
+
const variables = args?.variables || {};
|
|
1919
|
+
const queryWithoutNewLinesAndWhitespace = query.replace(/\s/g, '');
|
|
1920
|
+
const queryFirst50Chars = queryWithoutNewLinesAndWhitespace.slice(0, 50);
|
|
1921
|
+
const queryMiddle25Chars = queryWithoutNewLinesAndWhitespace.slice(queryWithoutNewLinesAndWhitespace.length / 2 - 25, queryWithoutNewLinesAndWhitespace.length / 2 + 25);
|
|
1922
|
+
const queryLast50Chars = queryWithoutNewLinesAndWhitespace.slice(-50);
|
|
1923
|
+
const vars = JSON.stringify(variables);
|
|
1924
|
+
return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
|
|
1925
|
+
};
|
|
1926
|
+
|
|
2088
1927
|
class QueryField {
|
|
2089
1928
|
get control() {
|
|
2090
1929
|
return this.data.control;
|
|
@@ -2328,5 +2167,5 @@ const def = () => null;
|
|
|
2328
2167
|
* Generated bundle index. Do not edit.
|
|
2329
2168
|
*/
|
|
2330
2169
|
|
|
2331
|
-
export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, Query, QueryClient, QueryDirective, QueryError, QueryField, QueryForm, QueryStore, buildErrorMessage, buildGqlCacheKey, buildQueryArrayString, buildQueryObjectString, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds, extractQuery, filterFailure, filterInvalidParams, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isCustomHeaderAuthProvider,
|
|
2170
|
+
export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, Query, QueryClient, QueryCreator, QueryDirective, QueryError, QueryField, QueryForm, QueryStore, buildErrorMessage, buildGqlCacheKey, buildQueryArrayString, buildQueryObjectString, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds, extractQuery, filterFailure, filterInvalidParams, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isCustomHeaderAuthProvider, isGqlQueryConfig, isParamValid, isQuery, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, mapToPaginated, mergeHeaders, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, request, serializeBody, shouldCacheQuery, shouldRetryRequest, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
|
|
2332
2171
|
//# sourceMappingURL=ethlete-query.mjs.map
|