@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.
Files changed (53) hide show
  1. package/esm2020/index.mjs +2 -1
  2. package/esm2020/lib/auth/auth-provider.types.mjs +1 -1
  3. package/esm2020/lib/auth/auth-provider.utils.mjs +1 -1
  4. package/esm2020/lib/auth/bearer-auth-provider.mjs +2 -2
  5. package/esm2020/lib/directives/infinity-query-trigger.directive.mjs +4 -4
  6. package/esm2020/lib/directives/infinity-query.directive.mjs +21 -20
  7. package/esm2020/lib/directives/query.directive.mjs +9 -11
  8. package/esm2020/lib/entity/entity-store.mjs +73 -119
  9. package/esm2020/lib/entity/entity.types.mjs +1 -1
  10. package/esm2020/lib/entity/entity.utils.mjs +5 -0
  11. package/esm2020/lib/entity/index.mjs +2 -1
  12. package/esm2020/lib/infinite-query/infinity-query.mjs +47 -71
  13. package/esm2020/lib/infinite-query/infinity-query.types.mjs +1 -1
  14. package/esm2020/lib/infinite-query/infinity-query.utils.mjs +1 -1
  15. package/esm2020/lib/query/query.mjs +118 -211
  16. package/esm2020/lib/query/query.types.mjs +1 -1
  17. package/esm2020/lib/query/query.utils.mjs +1 -1
  18. package/esm2020/lib/query-client/query-client.mjs +3 -31
  19. package/esm2020/lib/query-client/query-client.types.mjs +1 -1
  20. package/esm2020/lib/query-creator/index.mjs +3 -0
  21. package/esm2020/lib/query-creator/query-creator.mjs +35 -0
  22. package/esm2020/lib/query-creator/query-creator.types.mjs +2 -0
  23. package/esm2020/lib/request/request.types.mjs +1 -1
  24. package/esm2020/lib/request/request.util.mjs +1 -7
  25. package/fesm2015/ethlete-query.mjs +317 -469
  26. package/fesm2015/ethlete-query.mjs.map +1 -1
  27. package/fesm2020/ethlete-query.mjs +311 -472
  28. package/fesm2020/ethlete-query.mjs.map +1 -1
  29. package/index.d.ts +1 -0
  30. package/lib/auth/auth-provider.types.d.ts +3 -4
  31. package/lib/auth/auth-provider.utils.d.ts +2 -2
  32. package/lib/auth/bearer-auth-provider.d.ts +1 -1
  33. package/lib/directives/infinity-query-trigger.directive.d.ts +1 -1
  34. package/lib/directives/infinity-query.directive.d.ts +6 -10
  35. package/lib/directives/query.directive.d.ts +7 -7
  36. package/lib/entity/entity-store.d.ts +13 -27
  37. package/lib/entity/entity.types.d.ts +0 -5
  38. package/lib/entity/entity.utils.d.ts +2 -0
  39. package/lib/entity/index.d.ts +1 -0
  40. package/lib/infinite-query/infinity-query.d.ts +10 -19
  41. package/lib/infinite-query/infinity-query.types.d.ts +4 -4
  42. package/lib/infinite-query/infinity-query.utils.d.ts +2 -3
  43. package/lib/query/query.d.ts +19 -12
  44. package/lib/query/query.types.d.ts +86 -51
  45. package/lib/query/query.utils.d.ts +16 -14
  46. package/lib/query-client/query-client.d.ts +12 -10
  47. package/lib/query-client/query-client.types.d.ts +2 -22
  48. package/lib/query-creator/index.d.ts +2 -0
  49. package/lib/query-creator/query-creator.d.ts +14 -0
  50. package/lib/query-creator/query-creator.types.d.ts +13 -0
  51. package/lib/request/request.types.d.ts +1 -1
  52. package/lib/request/request.util.d.ts +0 -1
  53. 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, startWith, finalize, timer, map, combineLatest, fromEvent, debounceTime, take, concat, distinctUntilChanged } from 'rxjs';
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';
@@ -114,12 +114,6 @@ const buildQueryObjectString = (key, object) => {
114
114
  })
115
115
  .join('&');
116
116
  };
117
- const isFetchResponse = (response) => typeof response === 'object' &&
118
- response !== null &&
119
- 'status' in response &&
120
- 'statusText' in response &&
121
- 'json' in response &&
122
- typeof response['json'] === 'function';
123
117
  const filterInvalidParams = (params) => {
124
118
  const filteredParams = Object.entries(params)
125
119
  .map(([key, value]) => {
@@ -706,16 +700,22 @@ class Query {
706
700
  return ++this._currentId;
707
701
  }
708
702
  get state$() {
709
- return this._state$.asObservable();
703
+ return this._state$.pipe(switchMap((s) => this._transformState(s)), shareReplay({ bufferSize: 1, refCount: true }));
710
704
  }
711
- get state() {
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.state)) {
715
+ if (!isQueryStateSuccess(this._state$.value)) {
716
716
  return false;
717
717
  }
718
- const ts = this.state.meta.expiresAt;
718
+ const ts = this._state$.value.meta.expiresAt;
719
719
  if (!ts) {
720
720
  return true;
721
721
  }
@@ -748,14 +748,13 @@ class Query {
748
748
  return (_b = (_a = this._queryConfig.entity) === null || _a === void 0 ? void 0 : _a.store) !== null && _b !== void 0 ? _b : null;
749
749
  }
750
750
  constructor(_client, _queryConfig, _routeWithParams, _args) {
751
- var _a;
752
751
  this._client = _client;
753
752
  this._queryConfig = _queryConfig;
754
753
  this._routeWithParams = _routeWithParams;
755
754
  this._args = _args;
756
755
  this._currentId = 0;
757
756
  this._pollingSubscription = null;
758
- this._entitySubscription = null;
757
+ this._requestSubscription = null;
759
758
  this._onAbort$ = new Subject();
760
759
  this._currentPollConfig = null;
761
760
  /**
@@ -766,183 +765,40 @@ class Query {
766
765
  type: "PREPARED" /* QueryStateType.Prepared */,
767
766
  meta: { id: this._currentId, triggeredVia: 'program' },
768
767
  });
769
- if ((_a = this._queryConfig.entity) === null || _a === void 0 ? void 0 : _a.store) {
770
- this._entitySubscription = this._queryConfig.entity.store.events$.subscribe((event) => {
771
- var _a, _b, _c, _d;
772
- if (event.type !== 'update' && event.type !== 'set') {
773
- return;
774
- }
775
- if (!isQueryStateSuccess(this.state)) {
776
- return;
777
- }
778
- const response = this.state.response;
779
- const rawResponse = this.state.rawResponse;
780
- const key = (_a = this._queryConfig.entity) === null || _a === void 0 ? void 0 : _a.store.config.idKey;
781
- if (!key) {
782
- return;
783
- }
784
- const newData = (_b = this._queryConfig.entity) === null || _b === void 0 ? void 0 : _b.store.getOne(event.key);
785
- if (!newData) {
786
- return;
787
- }
788
- const newResponse = ((_c = this._queryConfig.entity) === null || _c === void 0 ? void 0 : _c.valueUpdater)
789
- ? (_d = this._queryConfig.entity) === null || _d === void 0 ? void 0 : _d.valueUpdater({
790
- args: this._args,
791
- entity: newData,
792
- rawResponse,
793
- response,
794
- })
795
- : response[key] === newData[key]
796
- ? {
797
- response: newData,
798
- rawResponse: newData,
799
- }
800
- : null;
801
- if (!newResponse) {
802
- return;
803
- }
804
- this._state$.next(Object.assign(Object.assign({}, this.state), { response: newResponse.response, rawResponse: newResponse.rawResponse, meta: Object.assign(Object.assign({}, this.state.meta), { triggeredVia: 'auto' }) }));
805
- });
806
- }
807
768
  }
808
- clone() {
809
- return this._client.fetch(this._queryConfig);
810
- }
811
- execute(options) {
812
- var _a, _b, _c;
813
- const triggeredVia = (_a = options === null || options === void 0 ? void 0 : options._triggeredVia) !== null && _a !== void 0 ? _a : 'program';
814
- if (!this.isExpired && !(options === null || options === void 0 ? void 0 : options.skipCache) && isQueryStateSuccess(this.state)) {
769
+ execute(options = {}) {
770
+ var _a, _b;
771
+ const { skipCache = false, _triggeredVia: triggeredVia = 'program' } = options;
772
+ const { authProvider } = this._client;
773
+ const queryConfig = this._queryConfig;
774
+ if (!this.isExpired && !skipCache && isQueryStateSuccess(this.rawState)) {
815
775
  return this;
816
776
  }
817
- if (this._queryConfig.secure && !this._client.authProvider) {
777
+ if (queryConfig.secure && !authProvider) {
818
778
  throw new Error('Cannot execute secure query without auth provider');
819
779
  }
820
780
  const id = this._nextId;
821
- if (isQueryStateLoading(this._state$.value)) {
781
+ const meta = { id, triggeredVia };
782
+ if (isQueryStateLoading(this.rawState)) {
822
783
  this.abort();
823
784
  }
824
- const meta = { id, triggeredVia };
825
- this._state$.next({
826
- type: "LOADING" /* QueryStateType.Loading */,
827
- meta,
828
- });
829
- this._updateUseResultInDependencies();
830
- const method = computeQueryMethod({ config: this._queryConfig, client: this._client });
831
- const body = computeQueryBody({
832
- config: this._queryConfig,
833
- client: this._client,
834
- args: this._args,
835
- method,
836
- });
837
- const headers = computeQueryHeaders({ client: this._client, config: this._queryConfig, args: this._args });
838
- request({
785
+ this._state$.next({ type: "LOADING" /* QueryStateType.Loading */, meta });
786
+ const method = computeQueryMethod({ config: queryConfig, client: this._client });
787
+ const body = computeQueryBody({ config: queryConfig, client: this._client, args: this._args, method });
788
+ const headers = computeQueryHeaders({ client: this._client, config: queryConfig, args: this._args });
789
+ this._requestSubscription = request({
839
790
  urlWithParams: this._routeWithParams,
840
791
  method,
841
792
  body,
842
793
  headers,
843
- reportProgress: this._queryConfig.reportProgress,
844
- responseType: this._queryConfig.responseType,
845
- withCredentials: this._queryConfig.withCredentials,
846
- cacheAdapter: (_b = this._client.config.request) === null || _b === void 0 ? void 0 : _b.cacheAdapter,
847
- retryFn: (_c = this._client.config.request) === null || _c === void 0 ? void 0 : _c.retryFn,
794
+ reportProgress: queryConfig.reportProgress,
795
+ responseType: queryConfig.responseType,
796
+ withCredentials: queryConfig.withCredentials,
797
+ cacheAdapter: (_a = this._client.config.request) === null || _a === void 0 ? void 0 : _a.cacheAdapter,
798
+ retryFn: (_b = this._client.config.request) === null || _b === void 0 ? void 0 : _b.retryFn,
848
799
  })
849
- .pipe(takeUntil(this._onAbort$))
850
- .subscribe({
851
- next: (state) => {
852
- var _a, _b;
853
- if (state.type === 'start' || state.type === 'delay-retry') {
854
- const newMeta = Object.assign(Object.assign({}, meta), { isWaitingForRetry: state.type === 'delay-retry', retryDelay: state.retryDelay, retryNumber: state.retryNumber });
855
- this._state$.next({
856
- type: "LOADING" /* QueryStateType.Loading */,
857
- meta: newMeta,
858
- });
859
- }
860
- else if (state.type === 'download-progress') {
861
- this._state$.next({
862
- type: "LOADING" /* QueryStateType.Loading */,
863
- progress: state.progress,
864
- partialText: state.partialText,
865
- meta,
866
- });
867
- }
868
- else if (state.type === 'upload-progress') {
869
- this._state$.next({
870
- type: "LOADING" /* QueryStateType.Loading */,
871
- progress: state.progress,
872
- meta,
873
- });
874
- }
875
- else if (state.type === 'success') {
876
- const isResponseObject = typeof state.response === 'object';
877
- const isGql = isGqlQueryConfig(this._queryConfig);
878
- let responseData = null;
879
- if (isGql &&
880
- isResponseObject &&
881
- !!state.response &&
882
- typeof state.response === 'object' &&
883
- 'data' in state.response) {
884
- responseData = state.response['data'];
885
- }
886
- else {
887
- responseData = state.response;
888
- }
889
- const transformedResponse = this._queryConfig.responseTransformer
890
- ? this._queryConfig.responseTransformer(responseData)
891
- : responseData;
892
- (_b = (_a = this._queryConfig.entity) === null || _a === void 0 ? void 0 : _a.successAction) === null || _b === void 0 ? void 0 : _b.call(_a, {
893
- args: this._args,
894
- rawResponse: state.response,
895
- response: transformedResponse,
896
- store: this._queryConfig.entity.store,
897
- });
898
- this._state$.next({
899
- type: "SUCCESS" /* QueryStateType.Success */,
900
- rawResponse: state.response,
901
- response: transformedResponse,
902
- meta: Object.assign(Object.assign({}, meta), { expiresAt: state.expiresInTimestamp }),
903
- });
904
- }
905
- else if (state.type === 'failure') {
906
- const failure = () => {
907
- this._state$.next({
908
- type: "FAILURE" /* QueryStateType.Failure */,
909
- error: state.error,
910
- meta,
911
- });
912
- };
913
- const bearerAuthProvider = this._getBearerAuthProvider();
914
- if (!bearerAuthProvider || (options === null || options === void 0 ? void 0 : options._isUnauthorizedRetry)) {
915
- return failure();
916
- }
917
- else if (state.error.status === 401 /* HttpStatusCode.Unauthorized */ &&
918
- bearerAuthProvider.shouldRefreshOnUnauthorizedResponse) {
919
- const query = bearerAuthProvider._refreshQuery();
920
- if (!query) {
921
- return failure();
922
- }
923
- query.state$
924
- .pipe(takeUntilResponse(), takeUntil(this._onAbort$), tap((state) => {
925
- if (isQueryStateSuccess(state)) {
926
- this.execute(Object.assign(Object.assign({}, options), { _isUnauthorizedRetry: true }));
927
- }
928
- else if (isQueryStateFailure(state)) {
929
- failure();
930
- }
931
- }))
932
- .subscribe();
933
- }
934
- else {
935
- failure();
936
- }
937
- }
938
- else if (state.type === 'cancel') {
939
- this._state$.next({
940
- type: "CANCELLED" /* QueryStateType.Cancelled */,
941
- meta,
942
- });
943
- }
944
- },
945
- });
800
+ .pipe(takeUntil(this._onAbort$), tap((state) => this._updateEntityState(state, meta, options)))
801
+ .subscribe();
946
802
  return this;
947
803
  }
948
804
  abort() {
@@ -954,16 +810,11 @@ class Query {
954
810
  return this;
955
811
  }
956
812
  this._currentPollConfig = config;
957
- const _interval = config.triggerImmediately
958
- ? interval(config.interval).pipe(startWith(-1))
959
- : interval(config.interval);
960
- this._pollingSubscription = _interval
961
- .pipe(takeUntil(config.takeUntil), finalize(() => this.stopPolling()))
962
- .subscribe(() => {
963
- if (this.state.type === "LOADING" /* QueryStateType.Loading */) {
964
- return;
965
- }
966
- this.execute({ skipCache: true, _triggeredVia: 'poll' });
813
+ const interval$ = interval(config.interval);
814
+ const poll$ = interval$.pipe(skip(config.triggerImmediately ? 0 : 1), takeUntil(config.takeUntil), takeWhile(() => !this._isPollingPaused), filter(() => !isQueryStateLoading(this._state$.value)));
815
+ this._pollingSubscription = poll$.subscribe({
816
+ next: () => this.execute({ skipCache: true, _triggeredVia: 'poll' }),
817
+ complete: () => this.stopPolling(),
967
818
  });
968
819
  return this;
969
820
  }
@@ -988,28 +839,6 @@ class Query {
988
839
  this._isPollingPaused = false;
989
840
  return this.poll(Object.assign(Object.assign({}, this._currentPollConfig), { triggerImmediately: true }));
990
841
  }
991
- _updateUseResultInDependencies() {
992
- var _a, _b;
993
- if (!((_b = (_a = this._args) === null || _a === void 0 ? void 0 : _a.useResultIn) === null || _b === void 0 ? void 0 : _b.length)) {
994
- return;
995
- }
996
- this.state$
997
- .pipe(filterSuccess(), takeUntil(this._onAbort$), takeUntilResponse(), tap((state) => {
998
- var _a;
999
- if (!((_a = this._args) === null || _a === void 0 ? void 0 : _a.useResultIn)) {
1000
- return;
1001
- }
1002
- for (const query of this._args.useResultIn) {
1003
- query._state$.next({
1004
- type: "SUCCESS" /* QueryStateType.Success */,
1005
- meta: Object.assign(Object.assign({}, state.meta), { id: query._nextId }),
1006
- rawResponse: state.rawResponse,
1007
- response: state.response,
1008
- });
1009
- }
1010
- }))
1011
- .subscribe();
1012
- }
1013
842
  /**
1014
843
  * @internal
1015
844
  */
@@ -1018,7 +847,7 @@ class Query {
1018
847
  this._state$.complete();
1019
848
  this._onAbort$.complete();
1020
849
  (_a = this._pollingSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
1021
- (_b = this._entitySubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
850
+ (_b = this._requestSubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
1022
851
  }
1023
852
  _getBearerAuthProvider() {
1024
853
  const authProvider = this._client.authProvider;
@@ -1027,6 +856,88 @@ class Query {
1027
856
  }
1028
857
  return null;
1029
858
  }
859
+ _updateEntityState(requestEvent, meta, options) {
860
+ var _a, _b;
861
+ switch (requestEvent.type) {
862
+ case 'start':
863
+ case 'delay-retry': {
864
+ const { type, retryDelay, retryNumber } = requestEvent;
865
+ const newMeta = Object.assign(Object.assign({}, meta), { isWaitingForRetry: type === 'delay-retry', retryDelay, retryNumber });
866
+ this._state$.next({
867
+ type: "LOADING" /* QueryStateType.Loading */,
868
+ meta: newMeta,
869
+ });
870
+ break;
871
+ }
872
+ case 'upload-progress':
873
+ case 'download-progress': {
874
+ this._state$.next({
875
+ type: "LOADING" /* QueryStateType.Loading */,
876
+ progress: requestEvent.progress,
877
+ partialText: 'partialText' in requestEvent ? requestEvent.partialText : undefined,
878
+ meta,
879
+ });
880
+ break;
881
+ }
882
+ case 'success': {
883
+ const { response, expiresInTimestamp } = requestEvent;
884
+ const isGql = isGqlQueryConfig(this._queryConfig);
885
+ const responseData = isGql && typeof response === 'object' && !!response && 'data' in response
886
+ ? response['data']
887
+ : response;
888
+ this._state$.next({
889
+ type: "SUCCESS" /* QueryStateType.Success */,
890
+ response: responseData,
891
+ meta: Object.assign(Object.assign({}, meta), { expiresAt: expiresInTimestamp }),
892
+ });
893
+ if (this._queryConfig.entity && this._queryConfig.entity.set) {
894
+ const id = (_a = this._queryConfig.entity) === null || _a === void 0 ? void 0 : _a.id({ args: this._args, response: responseData });
895
+ (_b = this._queryConfig.entity) === null || _b === void 0 ? void 0 : _b.set({
896
+ args: this._args,
897
+ response: responseData,
898
+ id,
899
+ store: this._queryConfig.entity.store,
900
+ });
901
+ }
902
+ break;
903
+ }
904
+ case 'failure': {
905
+ const { error } = requestEvent;
906
+ const failure = () => this._state$.next({ type: "FAILURE" /* QueryStateType.Failure */, error, meta });
907
+ const bearerAuthProvider = this._getBearerAuthProvider();
908
+ if (!bearerAuthProvider ||
909
+ (options === null || options === void 0 ? void 0 : options._isUnauthorizedRetry) ||
910
+ error.status !== 401 /* HttpStatusCode.Unauthorized */ ||
911
+ !bearerAuthProvider.shouldRefreshOnUnauthorizedResponse) {
912
+ return failure();
913
+ }
914
+ const query = bearerAuthProvider._refreshQuery();
915
+ if (!query)
916
+ return failure();
917
+ query.state$
918
+ .pipe(takeUntilResponse(), takeUntil(this._onAbort$), tap((state) => isQueryStateSuccess(state) ? this.execute(Object.assign(Object.assign({}, options), { _isUnauthorizedRetry: true })) : failure()))
919
+ .subscribe();
920
+ break;
921
+ }
922
+ case 'cancel': {
923
+ this._state$.next({
924
+ type: "CANCELLED" /* QueryStateType.Cancelled */,
925
+ meta,
926
+ });
927
+ break;
928
+ }
929
+ }
930
+ }
931
+ _transformState(s) {
932
+ var _a;
933
+ if (!isQueryStateSuccess(s) || !((_a = this._queryConfig.entity) === null || _a === void 0 ? void 0 : _a.get)) {
934
+ return of(s);
935
+ }
936
+ const id = this._queryConfig.entity.id({ args: this._args, response: s.response });
937
+ return this._queryConfig.entity
938
+ .get({ args: this._args, id, response: s.response, store: this._queryConfig.entity.store })
939
+ .pipe(map((v) => (Object.assign(Object.assign({}, s), { response: v }))));
940
+ }
1030
941
  }
1031
942
 
1032
943
  const isBasicAuthProvider = (authProvider) => authProvider instanceof BasicAuthProvider;
@@ -1159,7 +1070,7 @@ class BearerAuthProvider {
1159
1070
  */
1160
1071
  _refreshQuery() {
1161
1072
  var _a, _b, _c, _d;
1162
- if (isQueryStateLoading((_a = this._currentRefreshQuery$.getValue()) === null || _a === void 0 ? void 0 : _a.state)) {
1073
+ if (isQueryStateLoading((_a = this._currentRefreshQuery$.getValue()) === null || _a === void 0 ? void 0 : _a.rawState)) {
1163
1074
  return;
1164
1075
  }
1165
1076
  const currentRefreshToken = this.tokens.refreshToken;
@@ -1229,8 +1140,7 @@ class QueryDirective {
1229
1140
  this._subscription = null;
1230
1141
  this._viewContext = {
1231
1142
  $implicit: null,
1232
- query: null,
1233
- raw: null,
1143
+ etQuery: null,
1234
1144
  loading: false,
1235
1145
  error: null,
1236
1146
  progress: null,
@@ -1269,14 +1179,12 @@ class QueryDirective {
1269
1179
  this._viewContext.progress = null;
1270
1180
  }
1271
1181
  if (isQueryStateSuccess(state)) {
1272
- this._viewContext.query = state.response;
1182
+ this._viewContext.etQuery = state.response;
1273
1183
  this._viewContext.$implicit = state.response;
1274
- this._viewContext.raw = state.rawResponse;
1275
1184
  }
1276
1185
  else if (!this.cache) {
1277
- this._viewContext.query = null;
1186
+ this._viewContext.etQuery = null;
1278
1187
  this._viewContext.$implicit = null;
1279
- this._viewContext.raw = null;
1280
1188
  }
1281
1189
  if (isQueryStateFailure(state)) {
1282
1190
  this._viewContext.error = state.error;
@@ -1295,22 +1203,22 @@ class QueryDirective {
1295
1203
  }
1296
1204
  }
1297
1205
  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 });
1298
- QueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: QueryDirective, isStandalone: true, selector: "[query]", inputs: { query: "query", cache: ["queryCache", "cache"] }, ngImport: i0 });
1206
+ 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 });
1299
1207
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: QueryDirective, decorators: [{
1300
1208
  type: Directive,
1301
1209
  args: [{
1302
1210
  // eslint-disable-next-line @angular-eslint/directive-selector
1303
- selector: '[query]',
1211
+ selector: '[etQuery]',
1304
1212
  standalone: true,
1305
1213
  }]
1306
1214
  }], ctorParameters: function () { return [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: i0.ErrorHandler }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { query: [{
1307
- type: Input
1215
+ type: Input,
1216
+ args: ['etQuery']
1308
1217
  }], cache: [{
1309
1218
  type: Input,
1310
- args: ['queryCache']
1219
+ args: ['etQueryCache']
1311
1220
  }] } });
1312
1221
 
1313
- /* eslint-disable @typescript-eslint/no-explicit-any */
1314
1222
  class InfinityQuery {
1315
1223
  get currentPage$() {
1316
1224
  return this._currentPage$.asObservable();
@@ -1336,29 +1244,59 @@ class InfinityQuery {
1336
1244
  get itemsPerPage() {
1337
1245
  return this._itemsPerPage$.getValue();
1338
1246
  }
1339
- get currentQuery$() {
1340
- return this._currentQuery$.asObservable();
1341
- }
1342
- get currentQuery() {
1343
- return this._currentQuery$.getValue();
1344
- }
1345
1247
  get data$() {
1346
- return this._data$.asObservable();
1248
+ return this._data$;
1347
1249
  }
1348
- get data() {
1349
- return this._data$.getValue();
1250
+ get currentQuery$() {
1251
+ return this._lastQuery$;
1350
1252
  }
1351
1253
  constructor(_config) {
1352
1254
  var _a, _b;
1353
1255
  this._config = _config;
1256
+ this._queries$ = new BehaviorSubject([]);
1354
1257
  this._currentPage$ = new BehaviorSubject(null);
1355
1258
  this._currentCalculatedPage$ = new BehaviorSubject(null);
1356
1259
  this._totalPages$ = new BehaviorSubject(null);
1357
1260
  this._itemsPerPage$ = new BehaviorSubject((_b = (_a = this._config.limitParam) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 10);
1358
- this._currentQuery$ = new BehaviorSubject(null);
1359
- this._data$ = new BehaviorSubject([]);
1360
- this._subscriptions = [];
1361
- this._responsiveDataSubscription = null;
1261
+ this._data$ = this._queries$.pipe(switchMap((queries) => {
1262
+ if (!queries.length) {
1263
+ return of([]);
1264
+ }
1265
+ return combineLatest(queries.map((query) => query.state$));
1266
+ }), tap((states) => {
1267
+ var _a, _b, _c, _d, _e;
1268
+ const lastState = states[states.length - 1];
1269
+ if (!isQueryStateSuccess(lastState)) {
1270
+ return;
1271
+ }
1272
+ const totalPages = (_e = (_c = (_b = (_a = this._config.response).totalPagesExtractor) === null || _b === void 0 ? void 0 : _b.call(_a, {
1273
+ response: lastState.response,
1274
+ itemsPerPage: this.itemsPerPage,
1275
+ })) !== null && _c !== void 0 ? _c :
1276
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1277
+ (_d = lastState.response) === null || _d === void 0 ? void 0 : _d.totalPages) !== null && _e !== void 0 ? _e : null;
1278
+ this._totalPages$.next(totalPages);
1279
+ }), map((states) => {
1280
+ const fullData = states.reduce((acc, state) => {
1281
+ var _a;
1282
+ if (isQueryStateSuccess(state)) {
1283
+ let data = (_a = this._config) === null || _a === void 0 ? void 0 : _a.response.valueExtractor(state.response);
1284
+ if (this._config.response.reverse) {
1285
+ data = [...data].reverse();
1286
+ }
1287
+ if (this._config.response.appendItemsTo === 'start') {
1288
+ acc.unshift(...data);
1289
+ }
1290
+ else {
1291
+ acc.push(...data);
1292
+ }
1293
+ }
1294
+ return acc;
1295
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1296
+ }, []);
1297
+ return fullData;
1298
+ }), shareReplay({ bufferSize: 1, refCount: true }));
1299
+ this._lastQuery$ = this._queries$.pipe(map((queries) => { var _a; return (_a = queries[queries.length - 1]) !== null && _a !== void 0 ? _a : null; }), shareReplay({ bufferSize: 1, refCount: true }));
1362
1300
  }
1363
1301
  nextPage() {
1364
1302
  var _a, _b, _c, _d, _e;
@@ -1372,74 +1310,22 @@ class InfinityQuery {
1372
1310
  console.error('Cannot load more pages, already at the end. Make sure to not render the infinity query trigger using *ngIf canLoadMore');
1373
1311
  return;
1374
1312
  }
1375
- this._clearSubscriptions();
1376
1313
  const args = this._prepareArgs(this._config, calculatedPage);
1377
1314
  const query = this._config.queryCreator.prepare(args).execute();
1378
- this._handleNewQuery(query);
1315
+ this._queries$.next([...this._queries$.value, query]);
1379
1316
  this._currentPage$.next(newPage);
1380
1317
  this._currentCalculatedPage$.next(calculatedPage);
1381
- this._currentQuery$.next(query);
1382
1318
  }
1383
1319
  reset(newConfig) {
1384
1320
  var _a, _b;
1385
- this._clearSubscriptions();
1386
1321
  this._config = Object.assign(Object.assign({}, this._config), (newConfig !== null && newConfig !== void 0 ? newConfig : {}));
1387
1322
  this._currentPage$.next(null);
1388
1323
  this._currentCalculatedPage$.next(null);
1389
1324
  this._totalPages$.next(null);
1390
1325
  this._itemsPerPage$.next((_b = (_a = this._config.limitParam) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 10);
1391
- this._currentQuery$.next(null);
1392
- this._data$.next([]);
1326
+ this._queries$.next([]);
1393
1327
  this.nextPage();
1394
1328
  }
1395
- /**
1396
- * @internal
1397
- */
1398
- _clearSubscriptions() {
1399
- var _a;
1400
- this._subscriptions.forEach((sub) => sub.unsubscribe());
1401
- this._subscriptions = [];
1402
- (_a = this._responsiveDataSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
1403
- }
1404
- _handleNewQuery(query) {
1405
- const stateChangesSub = query.state$.pipe(takeUntilResponse(), filterSuccess()).subscribe({
1406
- next: (state) => {
1407
- var _a, _b, _c, _d, _e, _f, _g;
1408
- let newData = (_a = this._config) === null || _a === void 0 ? void 0 : _a.response.valueExtractor(state.response);
1409
- if (this._config.response.reverse) {
1410
- newData = [...newData].reverse();
1411
- }
1412
- if (this._config.response.appendItemsTo === 'start') {
1413
- newData = [...newData, ...this.data];
1414
- }
1415
- else {
1416
- newData = [...this.data, ...newData];
1417
- }
1418
- if (query.store) {
1419
- (_b = this._responsiveDataSubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
1420
- const key = query.store.idKey;
1421
- const responsiveData = query.store.entities$.pipe(map((entities) => newData.map((item) => {
1422
- // TODO(TRB): This is kind of unsafe. The entity array keys might not be the same as the response keys
1423
- const index = entities.values.findIndex((entity) => entity[key] === item[key]);
1424
- return index > -1 ? entities.values[index] : item;
1425
- })));
1426
- this._responsiveDataSubscription = responsiveData.subscribe((data) => this._data$.next(data));
1427
- }
1428
- else {
1429
- this._data$.next(newData);
1430
- }
1431
- const totalPages = (_g = (_e = (_d = (_c = this._config.response).totalPagesExtractor) === null || _d === void 0 ? void 0 : _d.call(_c, {
1432
- response: state.response,
1433
- itemsPerPage: this.itemsPerPage,
1434
- })) !== null && _e !== void 0 ? _e : (_f = state.response) === null || _f === void 0 ? void 0 : _f.totalPages) !== null && _g !== void 0 ? _g : null;
1435
- this._totalPages$.next(totalPages);
1436
- },
1437
- complete: () => {
1438
- this._subscriptions = this._subscriptions.filter((sub) => sub !== stateChangesSub);
1439
- },
1440
- });
1441
- this._subscriptions.push(stateChangesSub);
1442
- }
1443
1329
  _prepareArgs(config, page) {
1444
1330
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
1445
1331
  const pageParamLocation = this._getPageParamLocation((_a = config === null || config === void 0 ? void 0 : config.pageParam) === null || _a === void 0 ? void 0 : _a.location);
@@ -1497,6 +1383,7 @@ class InfinityQueryDirective {
1497
1383
  currentCalculatedPage: null,
1498
1384
  totalPages: null,
1499
1385
  itemsPerPage: null,
1386
+ currentQuery: null,
1500
1387
  };
1501
1388
  this._infinityQueryInstance = null;
1502
1389
  this._destroy$ = inject(DestroyService, { host: true }).destroy$;
@@ -1506,6 +1393,7 @@ class InfinityQueryDirective {
1506
1393
  this._errorHandler = inject(ErrorHandler);
1507
1394
  this._delayable = inject(DelayableDirective, { host: true });
1508
1395
  this._data$ = new BehaviorSubject([]);
1396
+ this._didReceiveFirstData$ = new BehaviorSubject(false);
1509
1397
  this._isMainViewCreated = false;
1510
1398
  }
1511
1399
  get infinityQuery() {
@@ -1535,21 +1423,22 @@ class InfinityQueryDirective {
1535
1423
  ngOnInit() {
1536
1424
  this._renderMainView();
1537
1425
  }
1538
- ngOnDestroy() {
1539
- var _a;
1540
- (_a = this.instance) === null || _a === void 0 ? void 0 : _a._clearSubscriptions();
1541
- }
1542
1426
  _setupInfinityQuery(config) {
1543
1427
  const instance = new InfinityQuery(config);
1544
- combineLatest([instance.currentQuery$.pipe(switchQueryState()), this._delayable.isDelayed$])
1545
- .pipe(tap(([state, isDelayed]) => {
1428
+ combineLatest([
1429
+ instance.currentQuery$.pipe(switchQueryState(), withLatestFrom(instance.currentQuery$)),
1430
+ this._delayable.isDelayed$,
1431
+ this._didReceiveFirstData$,
1432
+ ])
1433
+ .pipe(tap(([[state, currentQuery], isDelayed, didReceiveFirstData]) => {
1546
1434
  this._viewContext.currentPage = instance.currentPage;
1547
1435
  this._viewContext.totalPages = instance.totalPages;
1548
1436
  this._viewContext.itemsPerPage = instance.itemsPerPage;
1549
1437
  this._viewContext.canLoadMore =
1550
1438
  (instance.totalPages && instance.currentPage && instance.totalPages > instance.currentPage) || false;
1551
1439
  this._viewContext.currentCalculatedPage = instance.currentCalculatedPage;
1552
- if (isQueryStateLoading(state) || isDelayed) {
1440
+ this._viewContext.currentQuery = currentQuery;
1441
+ if (isQueryStateLoading(state) || isDelayed || (!didReceiveFirstData && isQueryStateSuccess(state))) {
1553
1442
  this._viewContext.loading = true;
1554
1443
  this._viewContext.error = null;
1555
1444
  this._viewContext.isFirstLoad = this.context.infinityQuery === null;
@@ -1575,27 +1464,24 @@ class InfinityQueryDirective {
1575
1464
  this._viewContext.currentPage = null;
1576
1465
  this._viewContext.itemsPerPage = null;
1577
1466
  this._viewContext.totalPages = null;
1467
+ this._viewContext.currentQuery = null;
1578
1468
  this._data$.next([]);
1579
1469
  }
1580
1470
  this._cdr.markForCheck();
1581
1471
  }), takeUntil(this._destroy$), takeUntil(this._queryConfigChanged$))
1582
1472
  .subscribe();
1583
1473
  instance.data$
1584
- .pipe(tap((data) => {
1474
+ .pipe(skip(1), tap((data) => {
1585
1475
  this._viewContext.infinityQuery = this._viewContext.$implicit = data;
1586
1476
  this._data$.next(data);
1477
+ if (!this._didReceiveFirstData$.getValue()) {
1478
+ this._didReceiveFirstData$.next(true);
1479
+ }
1587
1480
  this._cdr.markForCheck();
1588
1481
  }), takeUntil(this._destroy$), takeUntil(this._queryConfigChanged$))
1589
1482
  .subscribe();
1590
1483
  return instance;
1591
1484
  }
1592
- /**
1593
- * @deprecated Use `loadNextPage` instead
1594
- * @breaking 3.0.0
1595
- */
1596
- _loadNextPage() {
1597
- this.loadNextPage();
1598
- }
1599
1485
  loadNextPage() {
1600
1486
  if (!this._infinityQueryInstance) {
1601
1487
  return;
@@ -1618,9 +1504,7 @@ class InfinityQueryDirective {
1618
1504
  }
1619
1505
  }
1620
1506
  _cleanup() {
1621
- var _a;
1622
1507
  this._queryConfigChanged$.next(true);
1623
- (_a = this.instance) === null || _a === void 0 ? void 0 : _a._clearSubscriptions();
1624
1508
  this._viewContext.loading = false;
1625
1509
  this._viewContext.error = null;
1626
1510
  this._viewContext.infinityQuery = null;
@@ -1630,17 +1514,18 @@ class InfinityQueryDirective {
1630
1514
  this._viewContext.currentPage = null;
1631
1515
  this._viewContext.itemsPerPage = null;
1632
1516
  this._viewContext.totalPages = null;
1517
+ this._viewContext.currentQuery = null;
1633
1518
  this._data$.next([]);
1634
1519
  }
1635
1520
  }
1636
1521
  InfinityQueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1637
- InfinityQueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: InfinityQueryDirective, isStandalone: true, selector: "[infinityQuery]", inputs: { infinityQuery: "infinityQuery" }, providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }, DestroyService], exportAs: ["infinityQuery"], hostDirectives: [{ directive: i1.DelayableDirective }], ngImport: i0 });
1522
+ 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 });
1638
1523
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryDirective, decorators: [{
1639
1524
  type: Directive,
1640
1525
  args: [{
1641
1526
  // eslint-disable-next-line @angular-eslint/directive-selector
1642
- selector: '[infinityQuery]',
1643
- exportAs: 'infinityQuery',
1527
+ selector: '[etInfinityQuery]',
1528
+ exportAs: 'etInfinityQuery',
1644
1529
  standalone: true,
1645
1530
  providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }, DestroyService],
1646
1531
  hostDirectives: [DelayableDirective],
@@ -1659,7 +1544,7 @@ class InfinityQueryTriggerDirective {
1659
1544
  this.scrollContainerSelector = null;
1660
1545
  }
1661
1546
  ngOnInit() {
1662
- const isInteractive = this._elementRef.nativeElement.hasAttribute('infinityQueryTrigger');
1547
+ const isInteractive = this._elementRef.nativeElement.hasAttribute('etInfinityQueryTrigger');
1663
1548
  if (isInteractive) {
1664
1549
  this.click$.pipe(takeUntil(this._destroy)).subscribe(() => this._infinityQuery.loadNextPage());
1665
1550
  }
@@ -1688,155 +1573,144 @@ class InfinityQueryTriggerDirective {
1688
1573
  }
1689
1574
  }
1690
1575
  InfinityQueryTriggerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1691
- InfinityQueryTriggerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[infinityQueryTrigger], infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 });
1576
+ 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 });
1692
1577
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
1693
1578
  type: Directive,
1694
1579
  args: [{
1695
1580
  // eslint-disable-next-line @angular-eslint/directive-selector
1696
- selector: '[infinityQueryTrigger], infinity-query-trigger',
1581
+ selector: '[etInfinityQueryTrigger], et-infinity-query-trigger',
1697
1582
  standalone: true,
1698
1583
  }]
1699
1584
  }], propDecorators: { scrollContainerSelector: [{
1700
1585
  type: Input
1701
1586
  }] } });
1702
1587
 
1703
- class EntityStore {
1704
- get events$() {
1705
- return this._events$.asObservable();
1706
- }
1707
- get keys() {
1708
- return [...this._keys];
1709
- }
1710
- get values() {
1711
- return [...this._dictionary.values()];
1712
- }
1713
- get size() {
1714
- return this._keys.size;
1715
- }
1716
- get isEmpty() {
1717
- return this.size === 0;
1718
- }
1719
- get config() {
1720
- return this._config;
1721
- }
1722
- get idKey() {
1723
- return this._config.idKey || 'id';
1588
+ class EntityStoreError extends Error {
1589
+ constructor(message, detail) {
1590
+ super(message);
1591
+ this.detail = detail;
1592
+ this.name = 'EntityStoreError';
1724
1593
  }
1594
+ }
1595
+ class EntityStore {
1725
1596
  constructor(_config) {
1726
1597
  this._config = _config;
1727
1598
  this._dictionary = new Map();
1728
- this._keys = new Set();
1729
- this._events$ = new Subject();
1730
- this.entities$ = this.events$.pipe(startWith(null), debounceTime(0), map(() => ({
1731
- keys: this.keys,
1732
- values: this.values,
1733
- })));
1734
- }
1735
- getOne(key) {
1736
- const value = this._dictionary.get(key);
1737
- if (!value) {
1738
- console.error(`EntityStore: ${this._config.name || 'unknown'}: missing key "${key}" for get`);
1739
- return null;
1740
- }
1741
- if (this._config.logActions) {
1742
- console.log(`EntityStore: ${this._config.name || 'unknown'}: get "${key}"`);
1743
- }
1744
- return value;
1599
+ this._change$ = new Subject();
1745
1600
  }
1746
- getMany(keys) {
1747
- return keys.map((key) => this.getOne(key));
1601
+ select(keyOrKeys) {
1602
+ if (Array.isArray(keyOrKeys)) {
1603
+ return this._selectMany(keyOrKeys);
1604
+ }
1605
+ return this._select(keyOrKeys);
1748
1606
  }
1749
- addOne(value) {
1750
- const key = this.getKey(value);
1751
- if (this._dictionary.has(key)) {
1752
- console.error(`EntityStore: ${this._config.name || 'unknown'}: duplicate key "${key}" for add`);
1753
- return null;
1607
+ set(keyOrKeys, valueOrValues) {
1608
+ if (Array.isArray(keyOrKeys)) {
1609
+ if (!Array.isArray(valueOrValues)) {
1610
+ throw new EntityStoreError('When setting multiple keys, values must be an array', {
1611
+ keyOrValues: keyOrKeys,
1612
+ valueOrValues,
1613
+ });
1614
+ }
1615
+ for (let i = 0; i < keyOrKeys.length; i++) {
1616
+ this._set(keyOrKeys[i], valueOrValues[i]);
1617
+ }
1754
1618
  }
1755
- this._dictionary.set(key, value);
1756
- this._keys.add(key);
1757
- const event = { type: 'add', key };
1758
- this._events$.next(event);
1759
- if (this._config.logActions) {
1760
- console.log(`EntityStore: ${this._config.name || 'unknown'}: add "${key}"`);
1619
+ else {
1620
+ this._set(keyOrKeys, valueOrValues);
1761
1621
  }
1762
- return event;
1622
+ this._change$.next(keyOrKeys);
1763
1623
  }
1764
- addMany(values) {
1765
- const events = values.map((value) => this.addOne(value));
1766
- return events;
1767
- }
1768
- updateOne(value) {
1769
- const key = this.getKey(value);
1770
- const existing = this._dictionary.get(key);
1771
- if (!existing) {
1772
- console.error(`EntityStore: ${this._config.name || 'unknown'}: missing key "${key}" for update`);
1773
- return null;
1624
+ remove(keyOrKeys) {
1625
+ if (Array.isArray(keyOrKeys)) {
1626
+ for (const key of keyOrKeys) {
1627
+ this._remove(key);
1628
+ }
1774
1629
  }
1775
- this._dictionary.set(key, value);
1776
- const event = { type: 'update', key };
1777
- this._events$.next(event);
1778
- if (this._config.logActions) {
1779
- console.log(`EntityStore: ${this._config.name || 'unknown'}: update "${key}"`);
1630
+ else {
1631
+ this._remove(keyOrKeys);
1780
1632
  }
1781
- return event;
1633
+ this._change$.next(keyOrKeys);
1782
1634
  }
1783
- updateMany(values) {
1784
- const events = values.map((value) => this.updateOne(value));
1785
- return events;
1635
+ logState() {
1636
+ console.log('EntityStore:', this._config.name, {
1637
+ dictionary: this._dictionary,
1638
+ });
1786
1639
  }
1787
- setOne(value) {
1788
- const key = this.getKey(value);
1789
- this._dictionary.set(key, value);
1790
- this._keys.add(key);
1791
- const event = { type: 'set', key };
1792
- this._events$.next(event);
1640
+ _select(key) {
1793
1641
  if (this._config.logActions) {
1794
- console.log(`EntityStore: ${this._config.name || 'unknown'}: set "${key}"`);
1642
+ console.log('EntityStore: select', this._config.name, key);
1795
1643
  }
1796
- return event;
1797
- }
1798
- setMany(values) {
1799
- const events = values.map((value) => this.setOne(value));
1800
- return events;
1644
+ return this._change$.pipe(startWith(null), filter((v) => {
1645
+ if (v === null) {
1646
+ return true;
1647
+ }
1648
+ if (Array.isArray(v)) {
1649
+ return v.includes(key);
1650
+ }
1651
+ return v === key;
1652
+ }), map(() => { var _a; return (_a = this._dictionary.get(key)) !== null && _a !== void 0 ? _a : null; }));
1801
1653
  }
1802
- removeOne(key) {
1803
- if (!this._dictionary.has(key)) {
1804
- console.error(`EntityStore: ${this._config.name || 'unknown'}: missing key "${key}" for remove`);
1805
- return null;
1806
- }
1807
- this._dictionary.delete(key);
1808
- this._keys.delete(key);
1809
- const event = { type: 'remove', key };
1810
- this._events$.next(event);
1654
+ _selectMany(keys) {
1811
1655
  if (this._config.logActions) {
1812
- console.log(`EntityStore: ${this._config.name || 'unknown'}: remove "${key}"`);
1656
+ console.log('EntityStore: selectMany', this._config.name, keys);
1813
1657
  }
1814
- return event;
1815
- }
1816
- removeMany(keys) {
1817
- const events = keys.map((key) => this.removeOne(key));
1818
- return events;
1819
- }
1820
- has(key) {
1821
- return this._dictionary.has(key);
1658
+ return this._change$.pipe(startWith(null), filter((v) => {
1659
+ if (v === null) {
1660
+ return true;
1661
+ }
1662
+ if (Array.isArray(v)) {
1663
+ return keys.some((key) => v.includes(key));
1664
+ }
1665
+ return keys.includes(v);
1666
+ }), map(() => keys.map((key) => this._dictionary.get(key)).filter((value) => value !== undefined)));
1822
1667
  }
1823
- clear() {
1824
- this._dictionary.clear();
1825
- this._keys.clear();
1668
+ _set(key, value) {
1669
+ if (this._config.logActions) {
1670
+ console.log('EntityStore: set', this._config.name, key, value);
1671
+ }
1672
+ this._dictionary.set(key, value);
1826
1673
  }
1827
- getKey(value) {
1828
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1829
- const key = value[this._config.idKey || 'id'];
1830
- if (key === undefined) {
1831
- throw new Error(`EntityStore: ${this._config.name || 'unknown'}: missing key`);
1674
+ _remove(key) {
1675
+ if (this._config.logActions) {
1676
+ console.log('EntityStore: remove', this._config.name, key);
1832
1677
  }
1833
- return key;
1678
+ this._dictionary.delete(key);
1834
1679
  }
1835
- logState() {
1836
- console.log('EntityStore:', this._config.name, {
1837
- dictionary: this._dictionary,
1838
- keys: this._keys,
1839
- });
1680
+ }
1681
+
1682
+ function mapToPaginated(response) {
1683
+ return map((items) => (Object.assign(Object.assign({}, response), { items })));
1684
+ }
1685
+
1686
+ class QueryCreator {
1687
+ constructor(_queryConfig, _client, _store) {
1688
+ this._queryConfig = _queryConfig;
1689
+ this._client = _client;
1690
+ this._store = _store;
1691
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1692
+ // @ts-ignore
1693
+ this.prepare = (args) => {
1694
+ const route = buildRoute({
1695
+ base: this._client.config.baseRoute,
1696
+ route: this._queryConfig.route,
1697
+ pathParams: args === null || args === void 0 ? void 0 : args.pathParams,
1698
+ queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
1699
+ });
1700
+ const cacheKey = isGqlQueryConfig(this._queryConfig) ? buildGqlCacheKey(this._queryConfig, args) : route;
1701
+ if (shouldCacheQuery(this._queryConfig.method)) {
1702
+ const existingQuery = this._store.get(cacheKey);
1703
+ if (existingQuery) {
1704
+ return existingQuery;
1705
+ }
1706
+ }
1707
+ const query = new Query(this._client, this._queryConfig, route, args !== null && args !== void 0 ? args : {});
1708
+ if (shouldCacheQuery(this._queryConfig.method)) {
1709
+ this._store.add(cacheKey, query);
1710
+ }
1711
+ return query;
1712
+ };
1713
+ this.behaviorSubject = (initialValue) => new BehaviorSubject(initialValue !== null && initialValue !== void 0 ? initialValue : null);
1840
1714
  }
1841
1715
  }
1842
1716
 
@@ -1976,20 +1850,6 @@ class QueryStore {
1976
1850
  }
1977
1851
  }
1978
1852
 
1979
- const shouldCacheQuery = (method) => {
1980
- return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
1981
- };
1982
- const buildGqlCacheKey = (config, args) => {
1983
- const { query } = config;
1984
- const variables = (args === null || args === void 0 ? void 0 : args.variables) || {};
1985
- const queryWithoutNewLinesAndWhitespace = query.replace(/\s/g, '');
1986
- const queryFirst50Chars = queryWithoutNewLinesAndWhitespace.slice(0, 50);
1987
- const queryMiddle25Chars = queryWithoutNewLinesAndWhitespace.slice(queryWithoutNewLinesAndWhitespace.length / 2 - 25, queryWithoutNewLinesAndWhitespace.length / 2 + 25);
1988
- const queryLast50Chars = queryWithoutNewLinesAndWhitespace.slice(-50);
1989
- const vars = JSON.stringify(variables);
1990
- return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
1991
- };
1992
-
1993
1853
  class QueryClient {
1994
1854
  get config() {
1995
1855
  return this._clientConfig;
@@ -2013,33 +1873,7 @@ class QueryClient {
2013
1873
  this.delete = (queryConfig) => this.fetch(Object.assign(Object.assign({}, queryConfig), { method: 'DELETE' }));
2014
1874
  this.gqlQuery = (queryConfig) => this.fetch(Object.assign(Object.assign({}, queryConfig), { method: 'GQL_QUERY' }));
2015
1875
  this.gqlMutate = (queryConfig) => this.fetch(Object.assign(Object.assign({}, queryConfig), { method: 'GQL_MUTATE' }));
2016
- this.fetch = (queryConfig) => {
2017
- const prepare = (args) => {
2018
- const route = buildRoute({
2019
- base: this._clientConfig.baseRoute,
2020
- route: queryConfig.route,
2021
- pathParams: args === null || args === void 0 ? void 0 : args.pathParams,
2022
- queryParams: computeQueryQueryParams({ config: queryConfig, client: this, args }),
2023
- });
2024
- const cacheKey = isGqlQueryConfig(queryConfig) ? buildGqlCacheKey(queryConfig, args) : route;
2025
- if (shouldCacheQuery(queryConfig.method)) {
2026
- const existingQuery = this._store.get(cacheKey);
2027
- if (existingQuery) {
2028
- return existingQuery;
2029
- }
2030
- }
2031
- const query = new Query(this, queryConfig, route, args !== null && args !== void 0 ? args : {});
2032
- if (shouldCacheQuery(queryConfig.method)) {
2033
- this._store.add(cacheKey, query);
2034
- }
2035
- return query;
2036
- };
2037
- const behaviorSubject = (initialValue = null) => new BehaviorSubject(initialValue);
2038
- return {
2039
- prepare,
2040
- behaviorSubject,
2041
- };
2042
- };
1876
+ this.fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
2043
1877
  this.setAuthProvider = (authProvider) => {
2044
1878
  if (this.authProvider) {
2045
1879
  throw new Error('The auth provider is already set. Please call clearAuthProvider() first.');
@@ -2074,6 +1908,20 @@ class QueryClient {
2074
1908
  }
2075
1909
  }
2076
1910
 
1911
+ const shouldCacheQuery = (method) => {
1912
+ return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
1913
+ };
1914
+ const buildGqlCacheKey = (config, args) => {
1915
+ const { query } = config;
1916
+ const variables = (args === null || args === void 0 ? void 0 : args.variables) || {};
1917
+ const queryWithoutNewLinesAndWhitespace = query.replace(/\s/g, '');
1918
+ const queryFirst50Chars = queryWithoutNewLinesAndWhitespace.slice(0, 50);
1919
+ const queryMiddle25Chars = queryWithoutNewLinesAndWhitespace.slice(queryWithoutNewLinesAndWhitespace.length / 2 - 25, queryWithoutNewLinesAndWhitespace.length / 2 + 25);
1920
+ const queryLast50Chars = queryWithoutNewLinesAndWhitespace.slice(-50);
1921
+ const vars = JSON.stringify(variables);
1922
+ return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
1923
+ };
1924
+
2077
1925
  class QueryField {
2078
1926
  get control() {
2079
1927
  return this.data.control;
@@ -2320,5 +2168,5 @@ const def = () => null;
2320
2168
  * Generated bundle index. Do not edit.
2321
2169
  */
2322
2170
 
2323
- 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, isFetchResponse, isGqlQueryConfig, isParamValid, isQuery, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, 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 };
2171
+ 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 };
2324
2172
  //# sourceMappingURL=ethlete-query.mjs.map