@ethlete/query 2.9.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +11 -18
  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 +307 -467
  26. package/fesm2015/ethlete-query.mjs.map +1 -1
  27. package/fesm2020/ethlete-query.mjs +301 -470
  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 +5 -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 +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 = {
@@ -1502,6 +1377,7 @@ class InfinityQueryDirective {
1502
1377
  currentCalculatedPage: null,
1503
1378
  totalPages: null,
1504
1379
  itemsPerPage: null,
1380
+ currentQuery: null,
1505
1381
  };
1506
1382
  this._infinityQueryInstance = null;
1507
1383
  this._destroy$ = inject(DestroyService, { host: true }).destroy$;
@@ -1541,23 +1417,21 @@ class InfinityQueryDirective {
1541
1417
  ngOnInit() {
1542
1418
  this._renderMainView();
1543
1419
  }
1544
- ngOnDestroy() {
1545
- this.instance?._clearSubscriptions();
1546
- }
1547
1420
  _setupInfinityQuery(config) {
1548
1421
  const instance = new InfinityQuery(config);
1549
1422
  combineLatest([
1550
- instance.currentQuery$.pipe(switchQueryState()),
1423
+ instance.currentQuery$.pipe(switchQueryState(), withLatestFrom(instance.currentQuery$)),
1551
1424
  this._delayable.isDelayed$,
1552
1425
  this._didReceiveFirstData$,
1553
1426
  ])
1554
- .pipe(tap(([state, isDelayed, didReceiveFirstData]) => {
1427
+ .pipe(tap(([[state, currentQuery], isDelayed, didReceiveFirstData]) => {
1555
1428
  this._viewContext.currentPage = instance.currentPage;
1556
1429
  this._viewContext.totalPages = instance.totalPages;
1557
1430
  this._viewContext.itemsPerPage = instance.itemsPerPage;
1558
1431
  this._viewContext.canLoadMore =
1559
1432
  (instance.totalPages && instance.currentPage && instance.totalPages > instance.currentPage) || false;
1560
1433
  this._viewContext.currentCalculatedPage = instance.currentCalculatedPage;
1434
+ this._viewContext.currentQuery = currentQuery;
1561
1435
  if (isQueryStateLoading(state) || isDelayed || (!didReceiveFirstData && isQueryStateSuccess(state))) {
1562
1436
  this._viewContext.loading = true;
1563
1437
  this._viewContext.error = null;
@@ -1584,6 +1458,7 @@ class InfinityQueryDirective {
1584
1458
  this._viewContext.currentPage = null;
1585
1459
  this._viewContext.itemsPerPage = null;
1586
1460
  this._viewContext.totalPages = null;
1461
+ this._viewContext.currentQuery = null;
1587
1462
  this._data$.next([]);
1588
1463
  }
1589
1464
  this._cdr.markForCheck();
@@ -1601,13 +1476,6 @@ class InfinityQueryDirective {
1601
1476
  .subscribe();
1602
1477
  return instance;
1603
1478
  }
1604
- /**
1605
- * @deprecated Use `loadNextPage` instead
1606
- * @breaking 3.0.0
1607
- */
1608
- _loadNextPage() {
1609
- this.loadNextPage();
1610
- }
1611
1479
  loadNextPage() {
1612
1480
  if (!this._infinityQueryInstance) {
1613
1481
  return;
@@ -1631,7 +1499,6 @@ class InfinityQueryDirective {
1631
1499
  }
1632
1500
  _cleanup() {
1633
1501
  this._queryConfigChanged$.next(true);
1634
- this.instance?._clearSubscriptions();
1635
1502
  this._viewContext.loading = false;
1636
1503
  this._viewContext.error = null;
1637
1504
  this._viewContext.infinityQuery = null;
@@ -1641,17 +1508,18 @@ class InfinityQueryDirective {
1641
1508
  this._viewContext.currentPage = null;
1642
1509
  this._viewContext.itemsPerPage = null;
1643
1510
  this._viewContext.totalPages = null;
1511
+ this._viewContext.currentQuery = null;
1644
1512
  this._data$.next([]);
1645
1513
  }
1646
1514
  }
1647
1515
  InfinityQueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1648
- InfinityQueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: InfinityQueryDirective, isStandalone: true, selector: "[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: "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],
@@ -1670,7 +1538,7 @@ class InfinityQueryTriggerDirective {
1670
1538
  this.scrollContainerSelector = null;
1671
1539
  }
1672
1540
  ngOnInit() {
1673
- const isInteractive = this._elementRef.nativeElement.hasAttribute('infinityQueryTrigger');
1541
+ const isInteractive = this._elementRef.nativeElement.hasAttribute('etInfinityQueryTrigger');
1674
1542
  if (isInteractive) {
1675
1543
  this.click$.pipe(takeUntil(this._destroy)).subscribe(() => this._infinityQuery.loadNextPage());
1676
1544
  }
@@ -1698,155 +1566,144 @@ class InfinityQueryTriggerDirective {
1698
1566
  }
1699
1567
  }
1700
1568
  InfinityQueryTriggerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1701
- InfinityQueryTriggerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[infinityQueryTrigger], infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 });
1569
+ InfinityQueryTriggerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[etInfinityQueryTrigger], et-infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 });
1702
1570
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
1703
1571
  type: Directive,
1704
1572
  args: [{
1705
1573
  // eslint-disable-next-line @angular-eslint/directive-selector
1706
- selector: '[infinityQueryTrigger], infinity-query-trigger',
1574
+ selector: '[etInfinityQueryTrigger], et-infinity-query-trigger',
1707
1575
  standalone: true,
1708
1576
  }]
1709
1577
  }], propDecorators: { scrollContainerSelector: [{
1710
1578
  type: Input
1711
1579
  }] } });
1712
1580
 
1713
- class 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';
1581
+ class EntityStoreError extends Error {
1582
+ constructor(message, detail) {
1583
+ super(message);
1584
+ this.detail = detail;
1585
+ this.name = 'EntityStoreError';
1734
1586
  }
1587
+ }
1588
+ class EntityStore {
1735
1589
  constructor(_config) {
1736
1590
  this._config = _config;
1737
1591
  this._dictionary = new Map();
1738
- this._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;
1592
+ this._change$ = new Subject();
1755
1593
  }
1756
- getMany(keys) {
1757
- return keys.map((key) => this.getOne(key));
1594
+ select(keyOrKeys) {
1595
+ if (Array.isArray(keyOrKeys)) {
1596
+ return this._selectMany(keyOrKeys);
1597
+ }
1598
+ return this._select(keyOrKeys);
1758
1599
  }
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;
1600
+ set(keyOrKeys, valueOrValues) {
1601
+ if (Array.isArray(keyOrKeys)) {
1602
+ if (!Array.isArray(valueOrValues)) {
1603
+ throw new EntityStoreError('When setting multiple keys, values must be an array', {
1604
+ keyOrValues: keyOrKeys,
1605
+ valueOrValues,
1606
+ });
1607
+ }
1608
+ for (let i = 0; i < keyOrKeys.length; i++) {
1609
+ this._set(keyOrKeys[i], valueOrValues[i]);
1610
+ }
1764
1611
  }
1765
- 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}"`);
1612
+ else {
1613
+ this._set(keyOrKeys, valueOrValues);
1771
1614
  }
1772
- return event;
1615
+ this._change$.next(keyOrKeys);
1773
1616
  }
1774
- addMany(values) {
1775
- const events = values.map((value) => this.addOne(value));
1776
- return events;
1777
- }
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;
1617
+ remove(keyOrKeys) {
1618
+ if (Array.isArray(keyOrKeys)) {
1619
+ for (const key of keyOrKeys) {
1620
+ this._remove(key);
1621
+ }
1784
1622
  }
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}"`);
1623
+ else {
1624
+ this._remove(keyOrKeys);
1790
1625
  }
1791
- return event;
1626
+ this._change$.next(keyOrKeys);
1792
1627
  }
1793
- updateMany(values) {
1794
- const events = values.map((value) => this.updateOne(value));
1795
- return events;
1628
+ logState() {
1629
+ console.log('EntityStore:', this._config.name, {
1630
+ dictionary: this._dictionary,
1631
+ });
1796
1632
  }
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);
1633
+ _select(key) {
1803
1634
  if (this._config.logActions) {
1804
- console.log(`EntityStore: ${this._config.name || 'unknown'}: set "${key}"`);
1635
+ console.log('EntityStore: select', this._config.name, key);
1805
1636
  }
1806
- return event;
1807
- }
1808
- setMany(values) {
1809
- const events = values.map((value) => this.setOne(value));
1810
- return events;
1637
+ return this._change$.pipe(startWith(null), filter((v) => {
1638
+ if (v === null) {
1639
+ return true;
1640
+ }
1641
+ if (Array.isArray(v)) {
1642
+ return v.includes(key);
1643
+ }
1644
+ return v === key;
1645
+ }), map(() => this._dictionary.get(key) ?? null));
1811
1646
  }
1812
- 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);
1647
+ _selectMany(keys) {
1821
1648
  if (this._config.logActions) {
1822
- console.log(`EntityStore: ${this._config.name || 'unknown'}: remove "${key}"`);
1649
+ console.log('EntityStore: selectMany', this._config.name, keys);
1823
1650
  }
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);
1651
+ return this._change$.pipe(startWith(null), filter((v) => {
1652
+ if (v === null) {
1653
+ return true;
1654
+ }
1655
+ if (Array.isArray(v)) {
1656
+ return keys.some((key) => v.includes(key));
1657
+ }
1658
+ return keys.includes(v);
1659
+ }), map(() => keys.map((key) => this._dictionary.get(key)).filter((value) => value !== undefined)));
1832
1660
  }
1833
- clear() {
1834
- this._dictionary.clear();
1835
- this._keys.clear();
1661
+ _set(key, value) {
1662
+ if (this._config.logActions) {
1663
+ console.log('EntityStore: set', this._config.name, key, value);
1664
+ }
1665
+ this._dictionary.set(key, value);
1836
1666
  }
1837
- 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`);
1667
+ _remove(key) {
1668
+ if (this._config.logActions) {
1669
+ console.log('EntityStore: remove', this._config.name, key);
1842
1670
  }
1843
- return key;
1671
+ this._dictionary.delete(key);
1844
1672
  }
1845
- logState() {
1846
- console.log('EntityStore:', this._config.name, {
1847
- dictionary: this._dictionary,
1848
- keys: this._keys,
1849
- });
1673
+ }
1674
+
1675
+ function mapToPaginated(response) {
1676
+ return map((items) => ({ ...response, items }));
1677
+ }
1678
+
1679
+ class QueryCreator {
1680
+ constructor(_queryConfig, _client, _store) {
1681
+ this._queryConfig = _queryConfig;
1682
+ this._client = _client;
1683
+ this._store = _store;
1684
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1685
+ // @ts-ignore
1686
+ this.prepare = (args) => {
1687
+ const route = buildRoute({
1688
+ base: this._client.config.baseRoute,
1689
+ route: this._queryConfig.route,
1690
+ pathParams: args?.pathParams,
1691
+ queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
1692
+ });
1693
+ const cacheKey = isGqlQueryConfig(this._queryConfig) ? buildGqlCacheKey(this._queryConfig, args) : route;
1694
+ if (shouldCacheQuery(this._queryConfig.method)) {
1695
+ const existingQuery = this._store.get(cacheKey);
1696
+ if (existingQuery) {
1697
+ return existingQuery;
1698
+ }
1699
+ }
1700
+ const query = new Query(this._client, this._queryConfig, route, args ?? {});
1701
+ if (shouldCacheQuery(this._queryConfig.method)) {
1702
+ this._store.add(cacheKey, query);
1703
+ }
1704
+ return query;
1705
+ };
1706
+ this.behaviorSubject = (initialValue) => new BehaviorSubject(initialValue ?? null);
1850
1707
  }
1851
1708
  }
1852
1709
 
@@ -1979,20 +1836,6 @@ class QueryStore {
1979
1836
  }
1980
1837
  }
1981
1838
 
1982
- const shouldCacheQuery = (method) => {
1983
- return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
1984
- };
1985
- const buildGqlCacheKey = (config, args) => {
1986
- const { query } = config;
1987
- const variables = args?.variables || {};
1988
- const queryWithoutNewLinesAndWhitespace = query.replace(/\s/g, '');
1989
- const queryFirst50Chars = queryWithoutNewLinesAndWhitespace.slice(0, 50);
1990
- const queryMiddle25Chars = queryWithoutNewLinesAndWhitespace.slice(queryWithoutNewLinesAndWhitespace.length / 2 - 25, queryWithoutNewLinesAndWhitespace.length / 2 + 25);
1991
- const queryLast50Chars = queryWithoutNewLinesAndWhitespace.slice(-50);
1992
- const vars = JSON.stringify(variables);
1993
- return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
1994
- };
1995
-
1996
1839
  class QueryClient {
1997
1840
  get config() {
1998
1841
  return this._clientConfig;
@@ -2034,33 +1877,7 @@ class QueryClient {
2034
1877
  ...queryConfig,
2035
1878
  method: 'GQL_MUTATE',
2036
1879
  });
2037
- this.fetch = (queryConfig) => {
2038
- const prepare = (args) => {
2039
- const route = buildRoute({
2040
- base: this._clientConfig.baseRoute,
2041
- route: queryConfig.route,
2042
- pathParams: args?.pathParams,
2043
- queryParams: computeQueryQueryParams({ config: queryConfig, client: this, args }),
2044
- });
2045
- const cacheKey = isGqlQueryConfig(queryConfig) ? buildGqlCacheKey(queryConfig, args) : route;
2046
- if (shouldCacheQuery(queryConfig.method)) {
2047
- const existingQuery = this._store.get(cacheKey);
2048
- if (existingQuery) {
2049
- return existingQuery;
2050
- }
2051
- }
2052
- const query = new Query(this, queryConfig, route, args ?? {});
2053
- if (shouldCacheQuery(queryConfig.method)) {
2054
- this._store.add(cacheKey, query);
2055
- }
2056
- return query;
2057
- };
2058
- const behaviorSubject = (initialValue = null) => new BehaviorSubject(initialValue);
2059
- return {
2060
- prepare,
2061
- behaviorSubject,
2062
- };
2063
- };
1880
+ this.fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
2064
1881
  this.setAuthProvider = (authProvider) => {
2065
1882
  if (this.authProvider) {
2066
1883
  throw new Error('The auth provider is already set. Please call clearAuthProvider() first.');
@@ -2093,6 +1910,20 @@ class QueryClient {
2093
1910
  }
2094
1911
  }
2095
1912
 
1913
+ const shouldCacheQuery = (method) => {
1914
+ return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
1915
+ };
1916
+ const buildGqlCacheKey = (config, args) => {
1917
+ const { query } = config;
1918
+ const variables = args?.variables || {};
1919
+ const queryWithoutNewLinesAndWhitespace = query.replace(/\s/g, '');
1920
+ const queryFirst50Chars = queryWithoutNewLinesAndWhitespace.slice(0, 50);
1921
+ const queryMiddle25Chars = queryWithoutNewLinesAndWhitespace.slice(queryWithoutNewLinesAndWhitespace.length / 2 - 25, queryWithoutNewLinesAndWhitespace.length / 2 + 25);
1922
+ const queryLast50Chars = queryWithoutNewLinesAndWhitespace.slice(-50);
1923
+ const vars = JSON.stringify(variables);
1924
+ return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
1925
+ };
1926
+
2096
1927
  class QueryField {
2097
1928
  get control() {
2098
1929
  return this.data.control;
@@ -2336,5 +2167,5 @@ const def = () => null;
2336
2167
  * Generated bundle index. Do not edit.
2337
2168
  */
2338
2169
 
2339
- export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, Query, QueryClient, QueryDirective, QueryError, QueryField, QueryForm, QueryStore, buildErrorMessage, buildGqlCacheKey, buildQueryArrayString, buildQueryObjectString, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds, extractQuery, filterFailure, filterInvalidParams, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isCustomHeaderAuthProvider, 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 };
2170
+ export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, Query, QueryClient, QueryCreator, QueryDirective, QueryError, QueryField, QueryForm, QueryStore, buildErrorMessage, buildGqlCacheKey, buildQueryArrayString, buildQueryObjectString, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds, extractQuery, filterFailure, filterInvalidParams, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isCustomHeaderAuthProvider, isGqlQueryConfig, isParamValid, isQuery, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, mapToPaginated, mergeHeaders, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, request, serializeBody, shouldCacheQuery, shouldRetryRequest, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
2340
2171
  //# sourceMappingURL=ethlete-query.mjs.map