@ethlete/query 2.9.2 → 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 +11 -18
- 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 +307 -467
- package/fesm2015/ethlete-query.mjs.map +1 -1
- package/fesm2020/ethlete-query.mjs +301 -470
- 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 +5 -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 +1 -1
|
@@ -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$;
|
|
@@ -1541,23 +1417,21 @@ class InfinityQueryDirective {
|
|
|
1541
1417
|
ngOnInit() {
|
|
1542
1418
|
this._renderMainView();
|
|
1543
1419
|
}
|
|
1544
|
-
ngOnDestroy() {
|
|
1545
|
-
this.instance?._clearSubscriptions();
|
|
1546
|
-
}
|
|
1547
1420
|
_setupInfinityQuery(config) {
|
|
1548
1421
|
const instance = new InfinityQuery(config);
|
|
1549
1422
|
combineLatest([
|
|
1550
|
-
instance.currentQuery$.pipe(switchQueryState()),
|
|
1423
|
+
instance.currentQuery$.pipe(switchQueryState(), withLatestFrom(instance.currentQuery$)),
|
|
1551
1424
|
this._delayable.isDelayed$,
|
|
1552
1425
|
this._didReceiveFirstData$,
|
|
1553
1426
|
])
|
|
1554
|
-
.pipe(tap(([state, isDelayed, didReceiveFirstData]) => {
|
|
1427
|
+
.pipe(tap(([[state, currentQuery], isDelayed, didReceiveFirstData]) => {
|
|
1555
1428
|
this._viewContext.currentPage = instance.currentPage;
|
|
1556
1429
|
this._viewContext.totalPages = instance.totalPages;
|
|
1557
1430
|
this._viewContext.itemsPerPage = instance.itemsPerPage;
|
|
1558
1431
|
this._viewContext.canLoadMore =
|
|
1559
1432
|
(instance.totalPages && instance.currentPage && instance.totalPages > instance.currentPage) || false;
|
|
1560
1433
|
this._viewContext.currentCalculatedPage = instance.currentCalculatedPage;
|
|
1434
|
+
this._viewContext.currentQuery = currentQuery;
|
|
1561
1435
|
if (isQueryStateLoading(state) || isDelayed || (!didReceiveFirstData && isQueryStateSuccess(state))) {
|
|
1562
1436
|
this._viewContext.loading = true;
|
|
1563
1437
|
this._viewContext.error = null;
|
|
@@ -1584,6 +1458,7 @@ class InfinityQueryDirective {
|
|
|
1584
1458
|
this._viewContext.currentPage = null;
|
|
1585
1459
|
this._viewContext.itemsPerPage = null;
|
|
1586
1460
|
this._viewContext.totalPages = null;
|
|
1461
|
+
this._viewContext.currentQuery = null;
|
|
1587
1462
|
this._data$.next([]);
|
|
1588
1463
|
}
|
|
1589
1464
|
this._cdr.markForCheck();
|
|
@@ -1601,13 +1476,6 @@ class InfinityQueryDirective {
|
|
|
1601
1476
|
.subscribe();
|
|
1602
1477
|
return instance;
|
|
1603
1478
|
}
|
|
1604
|
-
/**
|
|
1605
|
-
* @deprecated Use `loadNextPage` instead
|
|
1606
|
-
* @breaking 3.0.0
|
|
1607
|
-
*/
|
|
1608
|
-
_loadNextPage() {
|
|
1609
|
-
this.loadNextPage();
|
|
1610
|
-
}
|
|
1611
1479
|
loadNextPage() {
|
|
1612
1480
|
if (!this._infinityQueryInstance) {
|
|
1613
1481
|
return;
|
|
@@ -1631,7 +1499,6 @@ class InfinityQueryDirective {
|
|
|
1631
1499
|
}
|
|
1632
1500
|
_cleanup() {
|
|
1633
1501
|
this._queryConfigChanged$.next(true);
|
|
1634
|
-
this.instance?._clearSubscriptions();
|
|
1635
1502
|
this._viewContext.loading = false;
|
|
1636
1503
|
this._viewContext.error = null;
|
|
1637
1504
|
this._viewContext.infinityQuery = null;
|
|
@@ -1641,17 +1508,18 @@ class InfinityQueryDirective {
|
|
|
1641
1508
|
this._viewContext.currentPage = null;
|
|
1642
1509
|
this._viewContext.itemsPerPage = null;
|
|
1643
1510
|
this._viewContext.totalPages = null;
|
|
1511
|
+
this._viewContext.currentQuery = null;
|
|
1644
1512
|
this._data$.next([]);
|
|
1645
1513
|
}
|
|
1646
1514
|
}
|
|
1647
1515
|
InfinityQueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1648
|
-
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 });
|
|
1649
1517
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryDirective, decorators: [{
|
|
1650
1518
|
type: Directive,
|
|
1651
1519
|
args: [{
|
|
1652
1520
|
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
1653
|
-
selector: '[
|
|
1654
|
-
exportAs: '
|
|
1521
|
+
selector: '[etInfinityQuery]',
|
|
1522
|
+
exportAs: 'etInfinityQuery',
|
|
1655
1523
|
standalone: true,
|
|
1656
1524
|
providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }, DestroyService],
|
|
1657
1525
|
hostDirectives: [DelayableDirective],
|
|
@@ -1670,7 +1538,7 @@ class InfinityQueryTriggerDirective {
|
|
|
1670
1538
|
this.scrollContainerSelector = null;
|
|
1671
1539
|
}
|
|
1672
1540
|
ngOnInit() {
|
|
1673
|
-
const isInteractive = this._elementRef.nativeElement.hasAttribute('
|
|
1541
|
+
const isInteractive = this._elementRef.nativeElement.hasAttribute('etInfinityQueryTrigger');
|
|
1674
1542
|
if (isInteractive) {
|
|
1675
1543
|
this.click$.pipe(takeUntil(this._destroy)).subscribe(() => this._infinityQuery.loadNextPage());
|
|
1676
1544
|
}
|
|
@@ -1698,155 +1566,144 @@ class InfinityQueryTriggerDirective {
|
|
|
1698
1566
|
}
|
|
1699
1567
|
}
|
|
1700
1568
|
InfinityQueryTriggerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1701
|
-
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 });
|
|
1702
1570
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
|
|
1703
1571
|
type: Directive,
|
|
1704
1572
|
args: [{
|
|
1705
1573
|
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
1706
|
-
selector: '[
|
|
1574
|
+
selector: '[etInfinityQueryTrigger], et-infinity-query-trigger',
|
|
1707
1575
|
standalone: true,
|
|
1708
1576
|
}]
|
|
1709
1577
|
}], propDecorators: { scrollContainerSelector: [{
|
|
1710
1578
|
type: Input
|
|
1711
1579
|
}] } });
|
|
1712
1580
|
|
|
1713
|
-
class
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
return [...this._keys];
|
|
1719
|
-
}
|
|
1720
|
-
get values() {
|
|
1721
|
-
return [...this._dictionary.values()];
|
|
1722
|
-
}
|
|
1723
|
-
get size() {
|
|
1724
|
-
return this._keys.size;
|
|
1725
|
-
}
|
|
1726
|
-
get isEmpty() {
|
|
1727
|
-
return this.size === 0;
|
|
1728
|
-
}
|
|
1729
|
-
get config() {
|
|
1730
|
-
return this._config;
|
|
1731
|
-
}
|
|
1732
|
-
get idKey() {
|
|
1733
|
-
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';
|
|
1734
1586
|
}
|
|
1587
|
+
}
|
|
1588
|
+
class EntityStore {
|
|
1735
1589
|
constructor(_config) {
|
|
1736
1590
|
this._config = _config;
|
|
1737
1591
|
this._dictionary = new Map();
|
|
1738
|
-
this.
|
|
1739
|
-
this._events$ = new Subject();
|
|
1740
|
-
this.entities$ = this.events$.pipe(startWith(null), debounceTime(0), map(() => ({
|
|
1741
|
-
keys: this.keys,
|
|
1742
|
-
values: this.values,
|
|
1743
|
-
})));
|
|
1744
|
-
}
|
|
1745
|
-
getOne(key) {
|
|
1746
|
-
const value = this._dictionary.get(key);
|
|
1747
|
-
if (!value) {
|
|
1748
|
-
console.error(`EntityStore: ${this._config.name || 'unknown'}: missing key "${key}" for get`);
|
|
1749
|
-
return null;
|
|
1750
|
-
}
|
|
1751
|
-
if (this._config.logActions) {
|
|
1752
|
-
console.log(`EntityStore: ${this._config.name || 'unknown'}: get "${key}"`);
|
|
1753
|
-
}
|
|
1754
|
-
return value;
|
|
1592
|
+
this._change$ = new Subject();
|
|
1755
1593
|
}
|
|
1756
|
-
|
|
1757
|
-
|
|
1594
|
+
select(keyOrKeys) {
|
|
1595
|
+
if (Array.isArray(keyOrKeys)) {
|
|
1596
|
+
return this._selectMany(keyOrKeys);
|
|
1597
|
+
}
|
|
1598
|
+
return this._select(keyOrKeys);
|
|
1758
1599
|
}
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
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
|
+
}
|
|
1764
1611
|
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
const event = { type: 'add', key };
|
|
1768
|
-
this._events$.next(event);
|
|
1769
|
-
if (this._config.logActions) {
|
|
1770
|
-
console.log(`EntityStore: ${this._config.name || 'unknown'}: add "${key}"`);
|
|
1612
|
+
else {
|
|
1613
|
+
this._set(keyOrKeys, valueOrValues);
|
|
1771
1614
|
}
|
|
1772
|
-
|
|
1615
|
+
this._change$.next(keyOrKeys);
|
|
1773
1616
|
}
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
const key = this.getKey(value);
|
|
1780
|
-
const existing = this._dictionary.get(key);
|
|
1781
|
-
if (!existing) {
|
|
1782
|
-
console.error(`EntityStore: ${this._config.name || 'unknown'}: missing key "${key}" for update`);
|
|
1783
|
-
return null;
|
|
1617
|
+
remove(keyOrKeys) {
|
|
1618
|
+
if (Array.isArray(keyOrKeys)) {
|
|
1619
|
+
for (const key of keyOrKeys) {
|
|
1620
|
+
this._remove(key);
|
|
1621
|
+
}
|
|
1784
1622
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
this._events$.next(event);
|
|
1788
|
-
if (this._config.logActions) {
|
|
1789
|
-
console.log(`EntityStore: ${this._config.name || 'unknown'}: update "${key}"`);
|
|
1623
|
+
else {
|
|
1624
|
+
this._remove(keyOrKeys);
|
|
1790
1625
|
}
|
|
1791
|
-
|
|
1626
|
+
this._change$.next(keyOrKeys);
|
|
1792
1627
|
}
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1628
|
+
logState() {
|
|
1629
|
+
console.log('EntityStore:', this._config.name, {
|
|
1630
|
+
dictionary: this._dictionary,
|
|
1631
|
+
});
|
|
1796
1632
|
}
|
|
1797
|
-
|
|
1798
|
-
const key = this.getKey(value);
|
|
1799
|
-
this._dictionary.set(key, value);
|
|
1800
|
-
this._keys.add(key);
|
|
1801
|
-
const event = { type: 'set', key };
|
|
1802
|
-
this._events$.next(event);
|
|
1633
|
+
_select(key) {
|
|
1803
1634
|
if (this._config.logActions) {
|
|
1804
|
-
console.log(
|
|
1635
|
+
console.log('EntityStore: select', this._config.name, key);
|
|
1805
1636
|
}
|
|
1806
|
-
return
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
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));
|
|
1811
1646
|
}
|
|
1812
|
-
|
|
1813
|
-
if (!this._dictionary.has(key)) {
|
|
1814
|
-
console.error(`EntityStore: ${this._config.name || 'unknown'}: missing key "${key}" for remove`);
|
|
1815
|
-
return null;
|
|
1816
|
-
}
|
|
1817
|
-
this._dictionary.delete(key);
|
|
1818
|
-
this._keys.delete(key);
|
|
1819
|
-
const event = { type: 'remove', key };
|
|
1820
|
-
this._events$.next(event);
|
|
1647
|
+
_selectMany(keys) {
|
|
1821
1648
|
if (this._config.logActions) {
|
|
1822
|
-
console.log(
|
|
1649
|
+
console.log('EntityStore: selectMany', this._config.name, keys);
|
|
1823
1650
|
}
|
|
1824
|
-
return
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
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)));
|
|
1832
1660
|
}
|
|
1833
|
-
|
|
1834
|
-
this.
|
|
1835
|
-
|
|
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);
|
|
1836
1666
|
}
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
if (key === undefined) {
|
|
1841
|
-
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);
|
|
1842
1670
|
}
|
|
1843
|
-
|
|
1671
|
+
this._dictionary.delete(key);
|
|
1844
1672
|
}
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
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);
|
|
1850
1707
|
}
|
|
1851
1708
|
}
|
|
1852
1709
|
|
|
@@ -1979,20 +1836,6 @@ class QueryStore {
|
|
|
1979
1836
|
}
|
|
1980
1837
|
}
|
|
1981
1838
|
|
|
1982
|
-
const shouldCacheQuery = (method) => {
|
|
1983
|
-
return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
|
|
1984
|
-
};
|
|
1985
|
-
const buildGqlCacheKey = (config, args) => {
|
|
1986
|
-
const { query } = config;
|
|
1987
|
-
const variables = args?.variables || {};
|
|
1988
|
-
const queryWithoutNewLinesAndWhitespace = query.replace(/\s/g, '');
|
|
1989
|
-
const queryFirst50Chars = queryWithoutNewLinesAndWhitespace.slice(0, 50);
|
|
1990
|
-
const queryMiddle25Chars = queryWithoutNewLinesAndWhitespace.slice(queryWithoutNewLinesAndWhitespace.length / 2 - 25, queryWithoutNewLinesAndWhitespace.length / 2 + 25);
|
|
1991
|
-
const queryLast50Chars = queryWithoutNewLinesAndWhitespace.slice(-50);
|
|
1992
|
-
const vars = JSON.stringify(variables);
|
|
1993
|
-
return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
|
|
1994
|
-
};
|
|
1995
|
-
|
|
1996
1839
|
class QueryClient {
|
|
1997
1840
|
get config() {
|
|
1998
1841
|
return this._clientConfig;
|
|
@@ -2034,33 +1877,7 @@ class QueryClient {
|
|
|
2034
1877
|
...queryConfig,
|
|
2035
1878
|
method: 'GQL_MUTATE',
|
|
2036
1879
|
});
|
|
2037
|
-
this.fetch = (queryConfig) =>
|
|
2038
|
-
const prepare = (args) => {
|
|
2039
|
-
const route = buildRoute({
|
|
2040
|
-
base: this._clientConfig.baseRoute,
|
|
2041
|
-
route: queryConfig.route,
|
|
2042
|
-
pathParams: args?.pathParams,
|
|
2043
|
-
queryParams: computeQueryQueryParams({ config: queryConfig, client: this, args }),
|
|
2044
|
-
});
|
|
2045
|
-
const cacheKey = isGqlQueryConfig(queryConfig) ? buildGqlCacheKey(queryConfig, args) : route;
|
|
2046
|
-
if (shouldCacheQuery(queryConfig.method)) {
|
|
2047
|
-
const existingQuery = this._store.get(cacheKey);
|
|
2048
|
-
if (existingQuery) {
|
|
2049
|
-
return existingQuery;
|
|
2050
|
-
}
|
|
2051
|
-
}
|
|
2052
|
-
const query = new Query(this, queryConfig, route, args ?? {});
|
|
2053
|
-
if (shouldCacheQuery(queryConfig.method)) {
|
|
2054
|
-
this._store.add(cacheKey, query);
|
|
2055
|
-
}
|
|
2056
|
-
return query;
|
|
2057
|
-
};
|
|
2058
|
-
const behaviorSubject = (initialValue = null) => new BehaviorSubject(initialValue);
|
|
2059
|
-
return {
|
|
2060
|
-
prepare,
|
|
2061
|
-
behaviorSubject,
|
|
2062
|
-
};
|
|
2063
|
-
};
|
|
1880
|
+
this.fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
|
|
2064
1881
|
this.setAuthProvider = (authProvider) => {
|
|
2065
1882
|
if (this.authProvider) {
|
|
2066
1883
|
throw new Error('The auth provider is already set. Please call clearAuthProvider() first.');
|
|
@@ -2093,6 +1910,20 @@ class QueryClient {
|
|
|
2093
1910
|
}
|
|
2094
1911
|
}
|
|
2095
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
|
+
|
|
2096
1927
|
class QueryField {
|
|
2097
1928
|
get control() {
|
|
2098
1929
|
return this.data.control;
|
|
@@ -2336,5 +2167,5 @@ const def = () => null;
|
|
|
2336
2167
|
* Generated bundle index. Do not edit.
|
|
2337
2168
|
*/
|
|
2338
2169
|
|
|
2339
|
-
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 };
|
|
2340
2171
|
//# sourceMappingURL=ethlete-query.mjs.map
|