@ethlete/query 2.9.2 → 3.0.1

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 +18 -24
  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 +314 -473
  26. package/fesm2015/ethlete-query.mjs.map +1 -1
  27. package/fesm2020/ethlete-query.mjs +308 -476
  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 -11
  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 +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, startWith, finalize, timer, map, combineLatest, skip, 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';
@@ -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$.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
  }
@@ -751,7 +751,7 @@ class Query {
751
751
  this._args = _args;
752
752
  this._currentId = 0;
753
753
  this._pollingSubscription = null;
754
- this._entitySubscription = null;
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 triggeredVia = options?._triggeredVia ?? 'program';
816
- if (!this.isExpired && !options?.skipCache && isQueryStateSuccess(this.state)) {
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 (this._queryConfig.secure && !this._client.authProvider) {
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
- if (isQueryStateLoading(this._state$.value)) {
777
+ const meta = { id, triggeredVia };
778
+ if (isQueryStateLoading(this.rawState)) {
824
779
  this.abort();
825
780
  }
826
- const meta = { id, triggeredVia };
827
- this._state$.next({
828
- type: "LOADING" /* QueryStateType.Loading */,
829
- meta,
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: this._queryConfig.reportProgress,
846
- responseType: this._queryConfig.responseType,
847
- withCredentials: this._queryConfig.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 _interval = config.triggerImmediately
964
- ? interval(config.interval).pipe(startWith(-1))
965
- : interval(config.interval);
966
- this._pollingSubscription = _interval
967
- .pipe(takeUntil(config.takeUntil), finalize(() => this.stopPolling()))
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._entitySubscription?.unsubscribe();
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()?.state)) {
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
- query: null,
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.query = state.response;
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.query = null;
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: "[query]", inputs: { query: "query", cache: ["queryCache", "cache"] }, ngImport: i0 });
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: '[query]',
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: ['queryCache']
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$.asObservable();
1229
+ return this._data$;
1338
1230
  }
1339
- get data() {
1340
- return this._data$.getValue();
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._currentQuery$ = new BehaviorSubject(null);
1349
- this._data$ = new BehaviorSubject([]);
1350
- this._subscriptions = [];
1351
- this._responsiveDataSubscription = null;
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._handleNewQuery(query);
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._currentQuery$.next(null);
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 = {
@@ -1493,7 +1368,7 @@ class InfinityQueryDirective {
1493
1368
  this._queryConfigChanged$ = new Subject();
1494
1369
  this._viewContext = {
1495
1370
  $implicit: null,
1496
- infinityQuery: null,
1371
+ etInfinityQuery: null,
1497
1372
  loading: false,
1498
1373
  error: null,
1499
1374
  isFirstLoad: false,
@@ -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,27 +1417,25 @@ 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;
1564
- this._viewContext.isFirstLoad = this.context.infinityQuery === null;
1438
+ this._viewContext.isFirstLoad = this.context.etInfinityQuery === null;
1565
1439
  }
1566
1440
  else if (isQueryStateFailure(state)) {
1567
1441
  this._viewContext.loading = false;
@@ -1577,13 +1451,14 @@ class InfinityQueryDirective {
1577
1451
  else {
1578
1452
  this._viewContext.loading = false;
1579
1453
  this._viewContext.error = null;
1580
- this._viewContext.infinityQuery = null;
1454
+ this._viewContext.etInfinityQuery = null;
1581
1455
  this._viewContext.$implicit = null;
1582
1456
  this._viewContext.isFirstLoad = false;
1583
1457
  this._viewContext.canLoadMore = false;
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();
@@ -1591,7 +1466,7 @@ class InfinityQueryDirective {
1591
1466
  .subscribe();
1592
1467
  instance.data$
1593
1468
  .pipe(skip(1), tap((data) => {
1594
- this._viewContext.infinityQuery = this._viewContext.$implicit = data;
1469
+ this._viewContext.etInfinityQuery = this._viewContext.$implicit = data;
1595
1470
  this._data$.next(data);
1596
1471
  if (!this._didReceiveFirstData$.getValue()) {
1597
1472
  this._didReceiveFirstData$.next(true);
@@ -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,33 +1499,34 @@ 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
- this._viewContext.infinityQuery = null;
1504
+ this._viewContext.etInfinityQuery = null;
1638
1505
  this._viewContext.$implicit = null;
1639
1506
  this._viewContext.isFirstLoad = false;
1640
1507
  this._viewContext.canLoadMore = false;
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: "[infinityQuery]", inputs: { infinityQuery: "infinityQuery" }, providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }, DestroyService], exportAs: ["infinityQuery"], hostDirectives: [{ directive: i1.DelayableDirective }], ngImport: i0 });
1516
+ InfinityQueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: InfinityQueryDirective, isStandalone: true, selector: "[etInfinityQuery]", inputs: { infinityQuery: ["etInfinityQuery", "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: '[infinityQuery]',
1654
- exportAs: 'infinityQuery',
1521
+ selector: '[etInfinityQuery]',
1522
+ exportAs: 'etInfinityQuery',
1655
1523
  standalone: true,
1656
1524
  providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }, DestroyService],
1657
1525
  hostDirectives: [DelayableDirective],
1658
1526
  }]
1659
1527
  }], propDecorators: { infinityQuery: [{
1660
- type: Input
1528
+ type: Input,
1529
+ args: ['etInfinityQuery']
1661
1530
  }] } });
1662
1531
 
1663
1532
  class InfinityQueryTriggerDirective {
@@ -1670,7 +1539,7 @@ class InfinityQueryTriggerDirective {
1670
1539
  this.scrollContainerSelector = null;
1671
1540
  }
1672
1541
  ngOnInit() {
1673
- const isInteractive = this._elementRef.nativeElement.hasAttribute('infinityQueryTrigger');
1542
+ const isInteractive = this._elementRef.nativeElement.hasAttribute('etInfinityQueryTrigger');
1674
1543
  if (isInteractive) {
1675
1544
  this.click$.pipe(takeUntil(this._destroy)).subscribe(() => this._infinityQuery.loadNextPage());
1676
1545
  }
@@ -1698,155 +1567,144 @@ class InfinityQueryTriggerDirective {
1698
1567
  }
1699
1568
  }
1700
1569
  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: "[infinityQueryTrigger], infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 });
1570
+ 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
1571
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
1703
1572
  type: Directive,
1704
1573
  args: [{
1705
1574
  // eslint-disable-next-line @angular-eslint/directive-selector
1706
- selector: '[infinityQueryTrigger], infinity-query-trigger',
1575
+ selector: '[etInfinityQueryTrigger], et-infinity-query-trigger',
1707
1576
  standalone: true,
1708
1577
  }]
1709
1578
  }], propDecorators: { scrollContainerSelector: [{
1710
1579
  type: Input
1711
1580
  }] } });
1712
1581
 
1713
- class EntityStore {
1714
- get events$() {
1715
- return this._events$.asObservable();
1716
- }
1717
- get keys() {
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';
1582
+ class EntityStoreError extends Error {
1583
+ constructor(message, detail) {
1584
+ super(message);
1585
+ this.detail = detail;
1586
+ this.name = 'EntityStoreError';
1734
1587
  }
1588
+ }
1589
+ class EntityStore {
1735
1590
  constructor(_config) {
1736
1591
  this._config = _config;
1737
1592
  this._dictionary = new Map();
1738
- this._keys = new Set();
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;
1593
+ this._change$ = new Subject();
1755
1594
  }
1756
- getMany(keys) {
1757
- return keys.map((key) => this.getOne(key));
1595
+ select(keyOrKeys) {
1596
+ if (Array.isArray(keyOrKeys)) {
1597
+ return this._selectMany(keyOrKeys);
1598
+ }
1599
+ return this._select(keyOrKeys);
1758
1600
  }
1759
- addOne(value) {
1760
- const key = this.getKey(value);
1761
- if (this._dictionary.has(key)) {
1762
- console.error(`EntityStore: ${this._config.name || 'unknown'}: duplicate key "${key}" for add`);
1763
- return null;
1601
+ set(keyOrKeys, valueOrValues) {
1602
+ if (Array.isArray(keyOrKeys)) {
1603
+ if (!Array.isArray(valueOrValues)) {
1604
+ throw new EntityStoreError('When setting multiple keys, values must be an array', {
1605
+ keyOrValues: keyOrKeys,
1606
+ valueOrValues,
1607
+ });
1608
+ }
1609
+ for (let i = 0; i < keyOrKeys.length; i++) {
1610
+ this._set(keyOrKeys[i], valueOrValues[i]);
1611
+ }
1764
1612
  }
1765
- this._dictionary.set(key, value);
1766
- this._keys.add(key);
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}"`);
1613
+ else {
1614
+ this._set(keyOrKeys, valueOrValues);
1771
1615
  }
1772
- return event;
1773
- }
1774
- addMany(values) {
1775
- const events = values.map((value) => this.addOne(value));
1776
- return events;
1616
+ this._change$.next(keyOrKeys);
1777
1617
  }
1778
- updateOne(value) {
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;
1618
+ remove(keyOrKeys) {
1619
+ if (Array.isArray(keyOrKeys)) {
1620
+ for (const key of keyOrKeys) {
1621
+ this._remove(key);
1622
+ }
1784
1623
  }
1785
- this._dictionary.set(key, value);
1786
- const event = { type: 'update', key };
1787
- this._events$.next(event);
1788
- if (this._config.logActions) {
1789
- console.log(`EntityStore: ${this._config.name || 'unknown'}: update "${key}"`);
1624
+ else {
1625
+ this._remove(keyOrKeys);
1790
1626
  }
1791
- return event;
1627
+ this._change$.next(keyOrKeys);
1792
1628
  }
1793
- updateMany(values) {
1794
- const events = values.map((value) => this.updateOne(value));
1795
- return events;
1629
+ logState() {
1630
+ console.log('EntityStore:', this._config.name, {
1631
+ dictionary: this._dictionary,
1632
+ });
1796
1633
  }
1797
- setOne(value) {
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);
1634
+ _select(key) {
1803
1635
  if (this._config.logActions) {
1804
- console.log(`EntityStore: ${this._config.name || 'unknown'}: set "${key}"`);
1636
+ console.log('EntityStore: select', this._config.name, key);
1805
1637
  }
1806
- return event;
1807
- }
1808
- setMany(values) {
1809
- const events = values.map((value) => this.setOne(value));
1810
- return events;
1638
+ return this._change$.pipe(startWith(null), filter((v) => {
1639
+ if (v === null) {
1640
+ return true;
1641
+ }
1642
+ if (Array.isArray(v)) {
1643
+ return v.includes(key);
1644
+ }
1645
+ return v === key;
1646
+ }), map(() => this._dictionary.get(key) ?? null));
1811
1647
  }
1812
- removeOne(key) {
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);
1648
+ _selectMany(keys) {
1821
1649
  if (this._config.logActions) {
1822
- console.log(`EntityStore: ${this._config.name || 'unknown'}: remove "${key}"`);
1650
+ console.log('EntityStore: selectMany', this._config.name, keys);
1823
1651
  }
1824
- return event;
1825
- }
1826
- removeMany(keys) {
1827
- const events = keys.map((key) => this.removeOne(key));
1828
- return events;
1829
- }
1830
- has(key) {
1831
- return this._dictionary.has(key);
1652
+ return this._change$.pipe(startWith(null), filter((v) => {
1653
+ if (v === null) {
1654
+ return true;
1655
+ }
1656
+ if (Array.isArray(v)) {
1657
+ return keys.some((key) => v.includes(key));
1658
+ }
1659
+ return keys.includes(v);
1660
+ }), map(() => keys.map((key) => this._dictionary.get(key)).filter((value) => value !== undefined)));
1832
1661
  }
1833
- clear() {
1834
- this._dictionary.clear();
1835
- this._keys.clear();
1662
+ _set(key, value) {
1663
+ if (this._config.logActions) {
1664
+ console.log('EntityStore: set', this._config.name, key, value);
1665
+ }
1666
+ this._dictionary.set(key, value);
1836
1667
  }
1837
- getKey(value) {
1838
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1839
- const key = value[this._config.idKey || 'id'];
1840
- if (key === undefined) {
1841
- throw new Error(`EntityStore: ${this._config.name || 'unknown'}: missing key`);
1668
+ _remove(key) {
1669
+ if (this._config.logActions) {
1670
+ console.log('EntityStore: remove', this._config.name, key);
1842
1671
  }
1843
- return key;
1672
+ this._dictionary.delete(key);
1844
1673
  }
1845
- logState() {
1846
- console.log('EntityStore:', this._config.name, {
1847
- dictionary: this._dictionary,
1848
- keys: this._keys,
1849
- });
1674
+ }
1675
+
1676
+ function mapToPaginated(response) {
1677
+ return map((items) => ({ ...response, items }));
1678
+ }
1679
+
1680
+ class QueryCreator {
1681
+ constructor(_queryConfig, _client, _store) {
1682
+ this._queryConfig = _queryConfig;
1683
+ this._client = _client;
1684
+ this._store = _store;
1685
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1686
+ // @ts-ignore
1687
+ this.prepare = (args) => {
1688
+ const route = buildRoute({
1689
+ base: this._client.config.baseRoute,
1690
+ route: this._queryConfig.route,
1691
+ pathParams: args?.pathParams,
1692
+ queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
1693
+ });
1694
+ const cacheKey = isGqlQueryConfig(this._queryConfig) ? buildGqlCacheKey(this._queryConfig, args) : route;
1695
+ if (shouldCacheQuery(this._queryConfig.method)) {
1696
+ const existingQuery = this._store.get(cacheKey);
1697
+ if (existingQuery) {
1698
+ return existingQuery;
1699
+ }
1700
+ }
1701
+ const query = new Query(this._client, this._queryConfig, route, args ?? {});
1702
+ if (shouldCacheQuery(this._queryConfig.method)) {
1703
+ this._store.add(cacheKey, query);
1704
+ }
1705
+ return query;
1706
+ };
1707
+ this.behaviorSubject = (initialValue) => new BehaviorSubject(initialValue ?? null);
1850
1708
  }
1851
1709
  }
1852
1710
 
@@ -1979,20 +1837,6 @@ class QueryStore {
1979
1837
  }
1980
1838
  }
1981
1839
 
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
1840
  class QueryClient {
1997
1841
  get config() {
1998
1842
  return this._clientConfig;
@@ -2034,33 +1878,7 @@ class QueryClient {
2034
1878
  ...queryConfig,
2035
1879
  method: 'GQL_MUTATE',
2036
1880
  });
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
- };
1881
+ this.fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
2064
1882
  this.setAuthProvider = (authProvider) => {
2065
1883
  if (this.authProvider) {
2066
1884
  throw new Error('The auth provider is already set. Please call clearAuthProvider() first.');
@@ -2093,6 +1911,20 @@ class QueryClient {
2093
1911
  }
2094
1912
  }
2095
1913
 
1914
+ const shouldCacheQuery = (method) => {
1915
+ return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
1916
+ };
1917
+ const buildGqlCacheKey = (config, args) => {
1918
+ const { query } = config;
1919
+ const variables = args?.variables || {};
1920
+ const queryWithoutNewLinesAndWhitespace = query.replace(/\s/g, '');
1921
+ const queryFirst50Chars = queryWithoutNewLinesAndWhitespace.slice(0, 50);
1922
+ const queryMiddle25Chars = queryWithoutNewLinesAndWhitespace.slice(queryWithoutNewLinesAndWhitespace.length / 2 - 25, queryWithoutNewLinesAndWhitespace.length / 2 + 25);
1923
+ const queryLast50Chars = queryWithoutNewLinesAndWhitespace.slice(-50);
1924
+ const vars = JSON.stringify(variables);
1925
+ return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
1926
+ };
1927
+
2096
1928
  class QueryField {
2097
1929
  get control() {
2098
1930
  return this.data.control;
@@ -2336,5 +2168,5 @@ const def = () => null;
2336
2168
  * Generated bundle index. Do not edit.
2337
2169
  */
2338
2170
 
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, 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 };
2340
2172
  //# sourceMappingURL=ethlete-query.mjs.map