@ethlete/query 5.22.0 → 5.24.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 (47) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/fesm2022/ethlete-query.mjs +1090 -680
  3. package/fesm2022/ethlete-query.mjs.map +1 -1
  4. package/lib/experimental/{bearer-auth-provider-config.d.ts → auth/bearer-auth-provider-config.d.ts} +1 -3
  5. package/lib/experimental/{bearer-auth-provider.d.ts → auth/bearer-auth-provider.d.ts} +1 -1
  6. package/lib/experimental/auth/index.d.ts +2 -0
  7. package/lib/experimental/gql/gql-query-creator-templates.d.ts +11 -0
  8. package/lib/experimental/gql/gql-query-creator.d.ts +14 -0
  9. package/lib/experimental/gql/gql-query-execute.d.ts +11 -0
  10. package/lib/experimental/gql/gql-query.d.ts +12 -0
  11. package/lib/experimental/gql/index.d.ts +4 -0
  12. package/lib/experimental/{http-request.d.ts → http/http-request.d.ts} +1 -1
  13. package/lib/experimental/http/index.d.ts +20 -0
  14. package/lib/experimental/http/paged-query-stack.d.ts +149 -0
  15. package/lib/experimental/http/query-client-config.d.ts +45 -0
  16. package/lib/experimental/{query-creator-templates.d.ts → http/query-creator-templates.d.ts} +11 -1
  17. package/lib/experimental/http/query-creator.d.ts +73 -0
  18. package/lib/experimental/{query-dependencies.d.ts → http/query-dependencies.d.ts} +5 -0
  19. package/lib/experimental/http/query-errors.d.ts +50 -0
  20. package/lib/experimental/{query-execute-utils.d.ts → http/query-execute-utils.d.ts} +16 -3
  21. package/lib/experimental/{query-execute.d.ts → http/query-execute.d.ts} +5 -3
  22. package/lib/experimental/http/query-features.d.ts +85 -0
  23. package/lib/experimental/{query-repository.d.ts → http/query-repository.d.ts} +3 -1
  24. package/lib/experimental/{query-snapshot.d.ts → http/query-snapshot.d.ts} +2 -2
  25. package/lib/experimental/http/query-stack.d.ts +101 -0
  26. package/lib/experimental/http/query-utils.d.ts +59 -0
  27. package/lib/experimental/{query.d.ts → http/query.d.ts} +24 -2
  28. package/lib/experimental/{secure-query-creator.d.ts → http/secure-query-creator.d.ts} +1 -1
  29. package/lib/experimental/{secure-query-execute.d.ts → http/secure-query-execute.d.ts} +2 -2
  30. package/lib/experimental/index.d.ts +4 -22
  31. package/lib/experimental/ws/index.d.ts +2 -0
  32. package/lib/experimental/ws/web-socket-client-config.d.ts +12 -0
  33. package/lib/experimental/ws/web-socket-client.d.ts +20 -0
  34. package/lib/experimental/ws/web-socket-errors.d.ts +9 -0
  35. package/lib/gql/gql.d.ts +3 -2
  36. package/lib/utils/data.utils.d.ts +5 -2
  37. package/package.json +8 -7
  38. package/lib/experimental/paged-query.d.ts +0 -35
  39. package/lib/experimental/query-client-config.d.ts +0 -18
  40. package/lib/experimental/query-creator.d.ts +0 -39
  41. package/lib/experimental/query-errors.d.ts +0 -49
  42. package/lib/experimental/query-features.d.ts +0 -48
  43. package/lib/experimental/query-stack.d.ts +0 -48
  44. package/lib/experimental/query-utils.d.ts +0 -49
  45. /package/lib/experimental/{query-client.d.ts → http/query-client.d.ts} +0 -0
  46. /package/lib/experimental/{query-state.d.ts → http/query-state.d.ts} +0 -0
  47. /package/lib/experimental/{secure-query.d.ts → http/secure-query.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import * as i1 from '@ethlete/core';
2
- import { createDestroy, computedTillTruthy, getCookie, setCookie, deleteCookie, DelayableDirective, nextFrame, RuntimeError, isObject, getDomain, syncSignal, injectQueryParamChanges, injectQueryParams, clone, equal, ET_PROPERTY_REMOVED } from '@ethlete/core';
3
- import { Observable, takeUntil, startWith, pairwise, tap, switchMap, of, BehaviorSubject, Subject, fromEvent, timer, take, filter, takeWhile, map, shareReplay, ReplaySubject, combineLatest, interval, skip, withLatestFrom, debounceTime, Subscription, retry, throwError, catchError, merge } from 'rxjs';
2
+ import { createDestroy, computedTillTruthy, syncSignal, getCookie, setCookie, deleteCookie, DelayableDirective, nextFrame, RuntimeError, isObject, getDomain, previousSignalValue, injectQueryParamChanges, injectQueryParams, clone, equal, ET_PROPERTY_REMOVED } from '@ethlete/core';
3
+ import { Observable, takeUntil, startWith, pairwise, tap, switchMap, of, BehaviorSubject, Subject, fromEvent, timer, take, filter, takeWhile, map, ReplaySubject, shareReplay, combineLatest, interval, skip, withLatestFrom, debounceTime, Subscription, retry, throwError, catchError, merge } from 'rxjs';
4
4
  import * as i0 from '@angular/core';
5
5
  import { assertInInjectionContext, inject, Injector, computed, signal, isDevMode, untracked, TemplateRef, ViewContainerRef, ErrorHandler, ChangeDetectorRef, Directive, Input, InjectionToken, ElementRef, Pipe, effect, Component, ChangeDetectionStrategy, ViewEncapsulation, runInInjectionContext, EnvironmentInjector, createEnvironmentInjector, DestroyRef, NgZone } from '@angular/core';
6
6
  import { toSignal, toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
@@ -8,9 +8,12 @@ import { AsyncPipe, JsonPipe, NgClass } from '@angular/common';
8
8
  import * as i1$1 from '@angular/forms';
9
9
  import { FormControl, ReactiveFormsModule, FormGroup } from '@angular/forms';
10
10
  import { HttpErrorResponse, HttpStatusCode, HttpEventType, HttpClient, HttpHeaders } from '@angular/common/http';
11
+ import { getActiveConsumer, setActiveConsumer } from '@angular/core/primitives/signals';
12
+ import { io } from 'socket.io-client';
11
13
  import { Router, ActivatedRoute } from '@angular/router';
12
14
 
13
15
  class CustomHeaderAuthProvider {
16
+ _config;
14
17
  get header() {
15
18
  return { [this._config.name]: this._config.value };
16
19
  }
@@ -23,6 +26,7 @@ class CustomHeaderAuthProvider {
23
26
  }
24
27
 
25
28
  class BasicAuthProvider {
29
+ _config;
26
30
  get header() {
27
31
  return { Authorization: `Basic ${this._basicAuthString}` };
28
32
  }
@@ -39,6 +43,7 @@ class BasicAuthProvider {
39
43
 
40
44
  const buildErrorMessage = (code, message) => `[@ethlete\\query:${code}] ${message}`;
41
45
  class QueryError extends Error {
46
+ data;
42
47
  constructor(code, message, data) {
43
48
  super(buildErrorMessage(code, message));
44
49
  this.name = 'QueryError';
@@ -630,7 +635,7 @@ function toQuerySubject(source, options) {
630
635
  }
631
636
  function queryStateSignal(source, options) {
632
637
  const { cacheResponse } = options ?? {};
633
- return toSignal(toObservable(source).pipe(switchMap((q) => extractQuery(q)?.state$ ?? of(null)), switchMap((state) => {
638
+ const roSignal = toSignal(toObservable(source).pipe(switchMap((q) => extractQuery(q)?.state$ ?? of(null)), switchMap((state) => {
634
639
  if (cacheResponse) {
635
640
  return of(state).pipe(filterQueryStates(["SUCCESS" /* QueryStateType.Success */, "FAILURE" /* QueryStateType.Failure */]));
636
641
  }
@@ -638,13 +643,20 @@ function queryStateSignal(source, options) {
638
643
  })), {
639
644
  initialValue: null,
640
645
  });
646
+ const rwSignal = signal(roSignal());
647
+ syncSignal(roSignal, rwSignal);
648
+ return rwSignal;
641
649
  }
642
650
  function queryStateResponseSignal(source, options) {
643
651
  const s = queryStateSignal(source, options);
644
- return computed(() => {
652
+ const dataSignal = computed(() => {
645
653
  const state = s();
646
654
  return isQueryStateSuccess(state) ? state.response : null;
647
655
  });
656
+ dataSignal['reset'] = () => {
657
+ s.set(null);
658
+ };
659
+ return dataSignal;
648
660
  }
649
661
  function queryStateErrorSignal(source) {
650
662
  const s = queryStateSignal(source);
@@ -687,67 +699,71 @@ const deepFreeze = (object) => {
687
699
  const def = () => null;
688
700
 
689
701
  class QueryCreator {
702
+ _queryConfig;
703
+ _client;
704
+ _store;
690
705
  constructor(_queryConfig, _client, _store) {
691
706
  this._queryConfig = _queryConfig;
692
707
  this._client = _client;
693
708
  this._store = _store;
694
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
695
- // @ts-ignore
696
- this.prepare = (args) => {
697
- const route = buildRoute({
698
- base: this._client.config.baseRoute,
699
- route: this._queryConfig.route,
700
- pathParams: args?.pathParams,
701
- queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
702
- queryParamConfig: this._client.config.request?.queryParams,
703
- });
704
- const cacheKey = (args?.config?.queryStoreCacheKey ?? '') + buildQueryCacheKey(route, args);
705
- if (shouldCacheQuery(this._queryConfig.method) && !args?.config?.skipQueryStore) {
706
- const existingQuery = this._store.get(cacheKey);
707
- if (existingQuery) {
708
- return existingQuery;
709
- }
710
- }
711
- const query = new Query(this._client, this._queryConfig, route, args ?? {}, cacheKey);
712
- if (shouldCacheQuery(this._queryConfig.method) && !args?.config?.skipQueryStore) {
713
- this._store.add(cacheKey, query);
714
- }
715
- this._store._dispatchQueryCreated(query);
716
- return query;
717
- };
718
- this.createSubject = (initialValue, config) => {
719
- assertInInjectionContext(this.createSubject);
720
- const subject = new BehaviorSubject(initialValue ?? null);
721
- addQueryContainerHandling(subject, () => subject.getValue(), config);
722
- return subject;
723
- };
724
- this.createSignal = (initialValue, config) => {
725
- assertInInjectionContext(this.createSignal);
726
- const _signal = signal(initialValue ?? null);
727
- addQueryContainerHandling(toObservable(_signal), () => _signal(), config);
728
- return _signal;
729
- };
730
- /**
731
- * @deprecated Use `myQuery.createSubject()` or `myQuery.createSignal()` instead. Will be removed in v6.
732
- */
733
- this.behaviorSubject = (initialValue) => new BehaviorSubject(initialValue ?? null);
734
709
  }
710
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
711
+ // @ts-ignore
712
+ prepare = (args) => {
713
+ const route = buildRoute({
714
+ base: this._client.config.baseRoute,
715
+ route: this._queryConfig.route,
716
+ pathParams: args?.pathParams,
717
+ queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
718
+ queryParamConfig: this._client.config.request?.queryParams,
719
+ });
720
+ const cacheKey = (args?.config?.queryStoreCacheKey ?? '') + buildQueryCacheKey$1(route, args);
721
+ if (shouldCacheQuery$1(this._queryConfig.method) && !args?.config?.skipQueryStore) {
722
+ const existingQuery = this._store.get(cacheKey);
723
+ if (existingQuery) {
724
+ return existingQuery;
725
+ }
726
+ }
727
+ const query = new Query(this._client, this._queryConfig, route, args ?? {}, cacheKey);
728
+ if (shouldCacheQuery$1(this._queryConfig.method) && !args?.config?.skipQueryStore) {
729
+ this._store.add(cacheKey, query);
730
+ }
731
+ this._store._dispatchQueryCreated(query);
732
+ return query;
733
+ };
734
+ createSubject = (initialValue, config) => {
735
+ assertInInjectionContext(this.createSubject);
736
+ const subject = new BehaviorSubject(initialValue ?? null);
737
+ addQueryContainerHandling(subject, () => subject.getValue(), config);
738
+ return subject;
739
+ };
740
+ createSignal = (initialValue, config) => {
741
+ assertInInjectionContext(this.createSignal);
742
+ const _signal = signal(initialValue ?? null);
743
+ addQueryContainerHandling(toObservable(_signal), () => _signal(), config);
744
+ return _signal;
745
+ };
746
+ /**
747
+ * @deprecated Use `myQuery.createSubject()` or `myQuery.createSignal()` instead. Will be removed in v6.
748
+ */
749
+ behaviorSubject = (initialValue) => new BehaviorSubject(initialValue ?? null);
735
750
  }
736
751
 
737
752
  class QueryStore {
753
+ _config;
754
+ /**
755
+ * @internal
756
+ */
757
+ _store = new Map();
758
+ _garbageCollector = null;
759
+ _isInLowResourceMode = false;
760
+ _lastBlurTimestamp = Date.now();
761
+ _storeChange$ = new Subject();
762
+ _queryCreated$ = new Subject();
763
+ storeChange$ = this._storeChange$.asObservable();
764
+ queryCreated$ = this._queryCreated$.asObservable();
738
765
  constructor(_config) {
739
766
  this._config = _config;
740
- /**
741
- * @internal
742
- */
743
- this._store = new Map();
744
- this._garbageCollector = null;
745
- this._isInLowResourceMode = false;
746
- this._lastBlurTimestamp = Date.now();
747
- this._storeChange$ = new Subject();
748
- this._queryCreated$ = new Subject();
749
- this.storeChange$ = this._storeChange$.asObservable();
750
- this.queryCreated$ = this._queryCreated$.asObservable();
751
767
  this._initSmartQueryHandling();
752
768
  }
753
769
  add(id, query) {
@@ -878,6 +894,11 @@ class QueryStore {
878
894
  }
879
895
 
880
896
  class QueryClient {
897
+ _clientConfig;
898
+ /**
899
+ * @internal
900
+ */
901
+ _store;
881
902
  get config() {
882
903
  return this._clientConfig;
883
904
  }
@@ -887,64 +908,9 @@ class QueryClient {
887
908
  get authProvider$() {
888
909
  return this._authProvider$.asObservable() ?? this._clientConfig.parent?._authProvider$.asObservable() ?? null;
889
910
  }
911
+ _authProvider$ = new BehaviorSubject(null);
890
912
  constructor(_clientConfig) {
891
913
  this._clientConfig = _clientConfig;
892
- this._authProvider$ = new BehaviorSubject(null);
893
- this.get = (queryConfig) => this.fetch({
894
- ...queryConfig,
895
- method: 'GET',
896
- });
897
- this.post = (queryConfig) => this.fetch({
898
- ...queryConfig,
899
- method: 'POST',
900
- });
901
- this.put = (queryConfig) => this.fetch({
902
- ...queryConfig,
903
- method: 'PUT',
904
- });
905
- this.patch = (queryConfig) => this.fetch({
906
- ...queryConfig,
907
- method: 'PATCH',
908
- });
909
- this.delete = (queryConfig) => this.fetch({
910
- ...queryConfig,
911
- method: 'DELETE',
912
- });
913
- this.gqlQuery = (queryConfig) => this.fetch({
914
- ...queryConfig,
915
- method: 'GQL_QUERY',
916
- });
917
- this.gqlMutate = (queryConfig) => this.fetch({
918
- ...queryConfig,
919
- method: 'GQL_MUTATE',
920
- });
921
- this.fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
922
- this.setAuthProvider = (authProvider) => {
923
- if (this.authProvider) {
924
- this.authProvider?.cleanUp();
925
- }
926
- this._authProvider$.next(authProvider);
927
- };
928
- this.setDefaultHeaders = (config) => {
929
- if (!this._clientConfig.request) {
930
- this._clientConfig.request = {
931
- headers: config.headers ?? undefined,
932
- };
933
- }
934
- else {
935
- this._clientConfig.request.headers = config.headers ?? undefined;
936
- }
937
- if (config.refreshQueriesInUse) {
938
- this._store.refreshQueriesInUse({ purgeUnused: true, ignoreCacheValidity: true });
939
- }
940
- };
941
- this.clearAuthProvider = () => {
942
- this.authProvider?.cleanUp();
943
- this._authProvider$.next(null);
944
- };
945
- this._updateBaseRoute = (route) => {
946
- this._clientConfig.baseRoute = route;
947
- };
948
914
  this._store = new QueryStore({
949
915
  enableChangeLogging: _clientConfig.logging?.queryStateChanges,
950
916
  enableGarbageCollectorLogging: _clientConfig.logging?.queryStateGarbageCollector,
@@ -952,12 +918,67 @@ class QueryClient {
952
918
  enableSmartPolling: _clientConfig.request?.enableSmartPolling ?? true,
953
919
  });
954
920
  }
921
+ get = (queryConfig) => this.fetch({
922
+ ...queryConfig,
923
+ method: 'GET',
924
+ });
925
+ post = (queryConfig) => this.fetch({
926
+ ...queryConfig,
927
+ method: 'POST',
928
+ });
929
+ put = (queryConfig) => this.fetch({
930
+ ...queryConfig,
931
+ method: 'PUT',
932
+ });
933
+ patch = (queryConfig) => this.fetch({
934
+ ...queryConfig,
935
+ method: 'PATCH',
936
+ });
937
+ delete = (queryConfig) => this.fetch({
938
+ ...queryConfig,
939
+ method: 'DELETE',
940
+ });
941
+ gqlQuery = (queryConfig) => this.fetch({
942
+ ...queryConfig,
943
+ method: 'GQL_QUERY',
944
+ });
945
+ gqlMutate = (queryConfig) => this.fetch({
946
+ ...queryConfig,
947
+ method: 'GQL_MUTATE',
948
+ });
949
+ fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
950
+ setAuthProvider = (authProvider) => {
951
+ if (this.authProvider) {
952
+ this.authProvider?.cleanUp();
953
+ }
954
+ this._authProvider$.next(authProvider);
955
+ };
956
+ setDefaultHeaders = (config) => {
957
+ if (!this._clientConfig.request) {
958
+ this._clientConfig.request = {
959
+ headers: config.headers ?? undefined,
960
+ };
961
+ }
962
+ else {
963
+ this._clientConfig.request.headers = config.headers ?? undefined;
964
+ }
965
+ if (config.refreshQueriesInUse) {
966
+ this._store.refreshQueriesInUse({ purgeUnused: true, ignoreCacheValidity: true });
967
+ }
968
+ };
969
+ clearAuthProvider = () => {
970
+ this.authProvider?.cleanUp();
971
+ this._authProvider$.next(null);
972
+ };
973
+ _updateBaseRoute = (route) => {
974
+ this._clientConfig.baseRoute = route;
975
+ };
955
976
  }
956
977
 
957
- const shouldCacheQuery = (method) => {
978
+ const shouldCacheQuery$1 = (method) => {
958
979
  return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
959
980
  };
960
- const buildQueryCacheKey = (route, args) => {
981
+ const buildQueryCacheKey$1 = (route, args) => {
961
982
  const variables = JSON.stringify(args?.variables || {})
962
983
  // replace all curly braces with empty string
963
984
  .replace(/{|}/g, '')
@@ -981,12 +1002,14 @@ const transformGql = (str) => {
981
1002
  return function (variables) {
982
1003
  const data = { query: str };
983
1004
  if (variables)
984
- data['variables'] = JSON.stringify(variables);
1005
+ data['variables'] = variables;
985
1006
  if (name && name.length) {
986
1007
  const operationName = name[2];
987
1008
  if (operationName)
988
1009
  data['operationName'] = name[2];
989
1010
  }
1011
+ // minify the query
1012
+ data.query = data.query.replace(/\s+/g, ' ').trim();
990
1013
  return data;
991
1014
  };
992
1015
  };
@@ -1241,6 +1264,36 @@ const paginatedEntityValueUpdater = (findFn) => ({ response, rawResponse, entity
1241
1264
 
1242
1265
  let _nextQueryId = 0;
1243
1266
  class Query {
1267
+ _client;
1268
+ _queryConfig;
1269
+ _routeWithParams;
1270
+ _arguments;
1271
+ _queryStoreKey;
1272
+ _id = _nextQueryId++;
1273
+ _currentLocalId = 0;
1274
+ _pollingSubscription = null;
1275
+ _onAbort$ = new Subject();
1276
+ _currentPollConfig = null;
1277
+ /**
1278
+ * @internal
1279
+ * Used to track which components depend on this query.
1280
+ * The key is the component's _tNode index.
1281
+ * The value is the number of times the component has subscribed to this query.
1282
+ * The value might increase since we cant distinguish between a component and a host directive applied to it.
1283
+ */
1284
+ _dependents = {};
1285
+ /**
1286
+ * @internal
1287
+ */
1288
+ _dependentsChanged$ = new ReplaySubject();
1289
+ /**
1290
+ * @internal
1291
+ */
1292
+ _isPollingPaused = false;
1293
+ _state$ = new BehaviorSubject({
1294
+ type: "PREPARED" /* QueryStateType.Prepared */,
1295
+ meta: { id: this._currentLocalId, triggeredVia: 'program' },
1296
+ });
1244
1297
  get _nextId() {
1245
1298
  return ++this._currentLocalId;
1246
1299
  }
@@ -1307,7 +1360,7 @@ class Query {
1307
1360
  return this._queryConfig.entity?.store ?? null;
1308
1361
  }
1309
1362
  get canBeCached() {
1310
- return shouldCacheQuery(this._queryConfig.method);
1363
+ return shouldCacheQuery$1(this._queryConfig.method);
1311
1364
  }
1312
1365
  get _isInMockMode() {
1313
1366
  return !!this._arguments?.mock;
@@ -1334,31 +1387,6 @@ class Query {
1334
1387
  this._routeWithParams = _routeWithParams;
1335
1388
  this._arguments = _arguments;
1336
1389
  this._queryStoreKey = _queryStoreKey;
1337
- this._id = _nextQueryId++;
1338
- this._currentLocalId = 0;
1339
- this._pollingSubscription = null;
1340
- this._onAbort$ = new Subject();
1341
- this._currentPollConfig = null;
1342
- /**
1343
- * @internal
1344
- * Used to track which components depend on this query.
1345
- * The key is the component's _tNode index.
1346
- * The value is the number of times the component has subscribed to this query.
1347
- * The value might increase since we cant distinguish between a component and a host directive applied to it.
1348
- */
1349
- this._dependents = {};
1350
- /**
1351
- * @internal
1352
- */
1353
- this._dependentsChanged$ = new ReplaySubject();
1354
- /**
1355
- * @internal
1356
- */
1357
- this._isPollingPaused = false;
1358
- this._state$ = new BehaviorSubject({
1359
- type: "PREPARED" /* QueryStateType.Prepared */,
1360
- meta: { id: this._currentLocalId, triggeredVia: 'program' },
1361
- });
1362
1390
  }
1363
1391
  execute(options = {}) {
1364
1392
  const { skipCache = false, _triggeredVia: triggeredVia = 'program', cancelPrevious = false } = options;
@@ -1687,6 +1715,13 @@ const decryptBearer = (token) => {
1687
1715
  };
1688
1716
 
1689
1717
  class BearerAuthProvider {
1718
+ _config;
1719
+ _destroy$ = new Subject();
1720
+ _currentRefreshQuery$ = new BehaviorSubject(null);
1721
+ _tokens$ = new BehaviorSubject({
1722
+ token: null,
1723
+ refreshToken: null,
1724
+ });
1690
1725
  get header() {
1691
1726
  return { Authorization: `Bearer ${this._tokens$.getValue().token}` };
1692
1727
  }
@@ -1709,12 +1744,6 @@ class BearerAuthProvider {
1709
1744
  }
1710
1745
  constructor(_config) {
1711
1746
  this._config = _config;
1712
- this._destroy$ = new Subject();
1713
- this._currentRefreshQuery$ = new BehaviorSubject(null);
1714
- this._tokens$ = new BehaviorSubject({
1715
- token: null,
1716
- refreshToken: null,
1717
- });
1718
1747
  const cookieEnabled = _config.refreshConfig?.cookieEnabled ?? true;
1719
1748
  const cookieToken = _config.refreshConfig?.cookieName && cookieEnabled ? (getCookie(_config.refreshConfig.cookieName) ?? null) : null;
1720
1749
  this._tokens$.next({
@@ -1855,25 +1884,22 @@ const isClassValidatorError = (error) => {
1855
1884
  };
1856
1885
 
1857
1886
  class QueryDirective {
1858
- constructor() {
1859
- this._mainTemplateRef = inject(TemplateRef);
1860
- this._viewContainerRef = inject(ViewContainerRef);
1861
- this._errorHandler = inject(ErrorHandler);
1862
- this._cdr = inject(ChangeDetectorRef);
1863
- this._isMainViewCreated = false;
1864
- this._subscription = null;
1865
- this._viewContext = {
1866
- $implicit: null,
1867
- etQuery: null,
1868
- loading: false,
1869
- refreshing: false,
1870
- error: null,
1871
- progress: null,
1872
- scope: null,
1873
- query: null,
1874
- };
1875
- this._cache = false;
1876
- }
1887
+ _mainTemplateRef = inject(TemplateRef);
1888
+ _viewContainerRef = inject(ViewContainerRef);
1889
+ _errorHandler = inject(ErrorHandler);
1890
+ _cdr = inject(ChangeDetectorRef);
1891
+ _isMainViewCreated = false;
1892
+ _subscription = null;
1893
+ _viewContext = {
1894
+ $implicit: null,
1895
+ etQuery: null,
1896
+ loading: false,
1897
+ refreshing: false,
1898
+ error: null,
1899
+ progress: null,
1900
+ scope: null,
1901
+ query: null,
1902
+ };
1877
1903
  get query() {
1878
1904
  return this._query;
1879
1905
  }
@@ -1881,12 +1907,14 @@ class QueryDirective {
1881
1907
  this._query = v;
1882
1908
  this._subscribeToQuery();
1883
1909
  }
1910
+ _query;
1884
1911
  get cache() {
1885
1912
  return this._cache;
1886
1913
  }
1887
1914
  set cache(v) {
1888
1915
  this._cache = v;
1889
1916
  }
1917
+ _cache = false;
1890
1918
  static ngTemplateContextGuard(dir, ctx) {
1891
1919
  return true;
1892
1920
  }
@@ -1955,10 +1983,10 @@ class QueryDirective {
1955
1983
  this._viewContainerRef.createEmbeddedView(this._mainTemplateRef, this._viewContext);
1956
1984
  }
1957
1985
  }
1958
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: QueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1959
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.3", type: QueryDirective, isStandalone: true, selector: "[etQuery]", inputs: { query: ["etQuery", "query"], cache: ["etQueryCache", "cache"] }, ngImport: i0 }); }
1986
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1987
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.4", type: QueryDirective, isStandalone: true, selector: "[etQuery]", inputs: { query: ["etQuery", "query"], cache: ["etQueryCache", "cache"] }, ngImport: i0 });
1960
1988
  }
1961
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: QueryDirective, decorators: [{
1989
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDirective, decorators: [{
1962
1990
  type: Directive,
1963
1991
  args: [{
1964
1992
  selector: '[etQuery]',
@@ -1973,6 +2001,58 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
1973
2001
  }] } });
1974
2002
 
1975
2003
  class InfinityQuery {
2004
+ _config;
2005
+ _destroy$;
2006
+ _queries$ = new BehaviorSubject([]);
2007
+ _currentPage$ = new BehaviorSubject(null);
2008
+ _currentCalculatedPage$ = new BehaviorSubject(null);
2009
+ _totalPages$ = new BehaviorSubject(null);
2010
+ _itemsPerPage$ = new BehaviorSubject(10);
2011
+ _data$ = this._queries$.pipe(switchMap((queries) => {
2012
+ if (!queries.length) {
2013
+ return of([]);
2014
+ }
2015
+ return combineLatest(queries.map((query) => query.state$.pipe(filterSuccess(), map((state) => ({ state, query })))));
2016
+ }), tap((stateMaps) => {
2017
+ const lastState = stateMaps[stateMaps.length - 1]?.state;
2018
+ const lastQuery = stateMaps[stateMaps.length - 1]?.query;
2019
+ if (!lastState || !lastQuery) {
2020
+ return;
2021
+ }
2022
+ const totalPages = this._config.response.totalPagesExtractor?.({
2023
+ response: lastState.response,
2024
+ itemsPerPage: this.itemsPerPage,
2025
+ args: lastQuery._arguments,
2026
+ }) ??
2027
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2028
+ lastState.response?.totalPages ??
2029
+ null;
2030
+ this._totalPages$.next(totalPages);
2031
+ }), map((stateMaps) => {
2032
+ if (!stateMaps.length) {
2033
+ return null;
2034
+ }
2035
+ const fullData = stateMaps.reduce((acc, stateMap) => {
2036
+ const valExtractFn = this._config?.response?.valueExtractor;
2037
+ let data = valExtractFn
2038
+ ? valExtractFn?.(stateMap.state.response)
2039
+ : stateMap.state.response;
2040
+ if (this._config.response.reverse) {
2041
+ data = [...data].reverse();
2042
+ }
2043
+ if (this._config.response.appendItemsTo === 'start') {
2044
+ acc.unshift(...data);
2045
+ }
2046
+ else {
2047
+ acc.push(...data);
2048
+ }
2049
+ return acc;
2050
+ },
2051
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2052
+ []);
2053
+ return fullData;
2054
+ }), shareReplay({ bufferSize: 1, refCount: true }));
2055
+ _lastQuery$ = this._queries$.pipe(map((queries) => queries[queries.length - 1] ?? null), shareReplay({ bufferSize: 1, refCount: true }));
1976
2056
  get currentPage$() {
1977
2057
  return this._currentPage$.asObservable();
1978
2058
  }
@@ -2006,56 +2086,7 @@ class InfinityQuery {
2006
2086
  constructor(_config, _destroy$) {
2007
2087
  this._config = _config;
2008
2088
  this._destroy$ = _destroy$;
2009
- this._queries$ = new BehaviorSubject([]);
2010
- this._currentPage$ = new BehaviorSubject(null);
2011
- this._currentCalculatedPage$ = new BehaviorSubject(null);
2012
- this._totalPages$ = new BehaviorSubject(null);
2013
- this._itemsPerPage$ = new BehaviorSubject(this._config.limitParam?.value ?? 10);
2014
- this._data$ = this._queries$.pipe(switchMap((queries) => {
2015
- if (!queries.length) {
2016
- return of([]);
2017
- }
2018
- return combineLatest(queries.map((query) => query.state$.pipe(filterSuccess(), map((state) => ({ state, query })))));
2019
- }), tap((stateMaps) => {
2020
- const lastState = stateMaps[stateMaps.length - 1]?.state;
2021
- const lastQuery = stateMaps[stateMaps.length - 1]?.query;
2022
- if (!lastState || !lastQuery) {
2023
- return;
2024
- }
2025
- const totalPages = this._config.response.totalPagesExtractor?.({
2026
- response: lastState.response,
2027
- itemsPerPage: this.itemsPerPage,
2028
- args: lastQuery._arguments,
2029
- }) ??
2030
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2031
- lastState.response?.totalPages ??
2032
- null;
2033
- this._totalPages$.next(totalPages);
2034
- }), map((stateMaps) => {
2035
- if (!stateMaps.length) {
2036
- return null;
2037
- }
2038
- const fullData = stateMaps.reduce((acc, stateMap) => {
2039
- const valExtractFn = this._config?.response?.valueExtractor;
2040
- let data = valExtractFn
2041
- ? valExtractFn?.(stateMap.state.response)
2042
- : stateMap.state.response;
2043
- if (this._config.response.reverse) {
2044
- data = [...data].reverse();
2045
- }
2046
- if (this._config.response.appendItemsTo === 'start') {
2047
- acc.unshift(...data);
2048
- }
2049
- else {
2050
- acc.push(...data);
2051
- }
2052
- return acc;
2053
- },
2054
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2055
- []);
2056
- return fullData;
2057
- }), shareReplay({ bufferSize: 1, refCount: true }));
2058
- this._lastQuery$ = this._queries$.pipe(map((queries) => queries[queries.length - 1] ?? null), shareReplay({ bufferSize: 1, refCount: true }));
2089
+ this._itemsPerPage$.next(this._config.limitParam?.value ?? 10);
2059
2090
  }
2060
2091
  nextPage() {
2061
2092
  const newPage = (this._currentPage$.value ?? 0) + 1;
@@ -2147,6 +2178,28 @@ const skipPaginationPageParamCalculator = ({ page, itemsPerPage }) => itemsPerPa
2147
2178
  /* eslint-disable @typescript-eslint/no-explicit-any */
2148
2179
  const INFINITY_QUERY_TOKEN = new InjectionToken('INFINITY_QUERY_TOKEN');
2149
2180
  class InfinityQueryDirective {
2181
+ _queryConfigChanged$ = new Subject();
2182
+ _viewContext = {
2183
+ $implicit: null,
2184
+ etInfinityQuery: null,
2185
+ loading: false,
2186
+ error: null,
2187
+ isFirstLoad: false,
2188
+ canLoadMore: false,
2189
+ currentPage: null,
2190
+ currentCalculatedPage: null,
2191
+ totalPages: null,
2192
+ itemsPerPage: null,
2193
+ currentQuery: null,
2194
+ };
2195
+ _infinityQueryInstance = null;
2196
+ _destroy$ = createDestroy();
2197
+ _cdr = inject(ChangeDetectorRef);
2198
+ _viewContainerRef = inject(ViewContainerRef);
2199
+ _mainTemplateRef = inject((TemplateRef));
2200
+ _errorHandler = inject(ErrorHandler);
2201
+ _delayable = inject(DelayableDirective, { host: true });
2202
+ _data$ = new BehaviorSubject([]);
2150
2203
  get infinityQuery() {
2151
2204
  return this._infinityQuery;
2152
2205
  }
@@ -2156,6 +2209,7 @@ class InfinityQueryDirective {
2156
2209
  this._infinityQueryInstance = this._setupInfinityQuery(v);
2157
2210
  this._infinityQueryInstance.nextPage();
2158
2211
  }
2212
+ _infinityQuery;
2159
2213
  get context() {
2160
2214
  return this._viewContext;
2161
2215
  }
@@ -2165,33 +2219,11 @@ class InfinityQueryDirective {
2165
2219
  get data$() {
2166
2220
  return this._data$.asObservable();
2167
2221
  }
2222
+ data = toSignal(this._data$, { requireSync: true });
2168
2223
  static ngTemplateContextGuard(dir, ctx) {
2169
2224
  return true;
2170
2225
  }
2171
2226
  constructor() {
2172
- this._queryConfigChanged$ = new Subject();
2173
- this._viewContext = {
2174
- $implicit: null,
2175
- etInfinityQuery: null,
2176
- loading: false,
2177
- error: null,
2178
- isFirstLoad: false,
2179
- canLoadMore: false,
2180
- currentPage: null,
2181
- currentCalculatedPage: null,
2182
- totalPages: null,
2183
- itemsPerPage: null,
2184
- currentQuery: null,
2185
- };
2186
- this._infinityQueryInstance = null;
2187
- this._destroy$ = createDestroy();
2188
- this._cdr = inject(ChangeDetectorRef);
2189
- this._viewContainerRef = inject(ViewContainerRef);
2190
- this._mainTemplateRef = inject((TemplateRef));
2191
- this._errorHandler = inject(ErrorHandler);
2192
- this._delayable = inject(DelayableDirective, { host: true });
2193
- this._data$ = new BehaviorSubject([]);
2194
- this.data = toSignal(this._data$, { requireSync: true });
2195
2227
  this._viewContainerRef.createEmbeddedView(this._mainTemplateRef, this._viewContext);
2196
2228
  }
2197
2229
  _setupInfinityQuery(config) {
@@ -2265,10 +2297,10 @@ class InfinityQueryDirective {
2265
2297
  this._viewContext.currentQuery = null;
2266
2298
  this._data$.next([]);
2267
2299
  }
2268
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2269
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.3", type: InfinityQueryDirective, isStandalone: true, selector: "[etInfinityQuery]", inputs: { infinityQuery: ["etInfinityQuery", "infinityQuery"] }, providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }], exportAs: ["etInfinityQuery"], hostDirectives: [{ directive: i1.DelayableDirective }], ngImport: i0 }); }
2300
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2301
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.4", type: InfinityQueryDirective, isStandalone: true, selector: "[etInfinityQuery]", inputs: { infinityQuery: ["etInfinityQuery", "infinityQuery"] }, providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }], exportAs: ["etInfinityQuery"], hostDirectives: [{ directive: i1.DelayableDirective }], ngImport: i0 });
2270
2302
  }
2271
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: InfinityQueryDirective, decorators: [{
2303
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryDirective, decorators: [{
2272
2304
  type: Directive,
2273
2305
  args: [{
2274
2306
  selector: '[etInfinityQuery]',
@@ -2283,14 +2315,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
2283
2315
  }] } });
2284
2316
 
2285
2317
  class InfinityQueryTriggerDirective {
2286
- constructor() {
2287
- this._elementRef = inject((ElementRef));
2288
- this._infinityQuery = inject(INFINITY_QUERY_TOKEN);
2289
- this._destroy = new Subject();
2290
- this._observer = null;
2291
- this.click$ = fromEvent(this._elementRef.nativeElement, 'click');
2292
- this.scrollContainerSelector = null;
2293
- }
2318
+ _elementRef = inject((ElementRef));
2319
+ _infinityQuery = inject(INFINITY_QUERY_TOKEN);
2320
+ _destroy = new Subject();
2321
+ _observer = null;
2322
+ click$ = fromEvent(this._elementRef.nativeElement, 'click');
2323
+ scrollContainerSelector = null;
2294
2324
  ngOnInit() {
2295
2325
  const isInteractive = this._elementRef.nativeElement.tagName === 'BUTTON';
2296
2326
  if (isInteractive) {
@@ -2320,10 +2350,10 @@ class InfinityQueryTriggerDirective {
2320
2350
  });
2321
2351
  this._observer.observe(this._elementRef.nativeElement);
2322
2352
  }
2323
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2324
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.3", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[etInfinityQueryTrigger], et-infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 }); }
2353
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2354
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.4", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[etInfinityQueryTrigger], et-infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 });
2325
2355
  }
2326
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
2356
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
2327
2357
  type: Directive,
2328
2358
  args: [{
2329
2359
  selector: '[etInfinityQueryTrigger], et-infinity-query-trigger',
@@ -2347,10 +2377,10 @@ class QueryShortNamePipe {
2347
2377
  }
2348
2378
  return route;
2349
2379
  }
2350
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: QueryShortNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
2351
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.3", ngImport: i0, type: QueryShortNamePipe, isStandalone: true, name: "queryShortName" }); }
2380
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryShortNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2381
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.1.4", ngImport: i0, type: QueryShortNamePipe, isStandalone: true, name: "queryShortName" });
2352
2382
  }
2353
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: QueryShortNamePipe, decorators: [{
2383
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryShortNamePipe, decorators: [{
2354
2384
  type: Pipe,
2355
2385
  args: [{ name: 'queryShortName', standalone: true }]
2356
2386
  }] });
@@ -2368,161 +2398,159 @@ const provideQueryClientForDevtools = (queryClient) => {
2368
2398
  };
2369
2399
 
2370
2400
  class QueryDevtoolsComponent {
2371
- constructor() {
2372
- this._cdr = inject(ChangeDetectorRef);
2373
- this._destroy$ = createDestroy();
2374
- this.queryClientConfigs = inject(QUERY_CLIENT_DEVTOOLS_TOKEN);
2375
- this.isOpen = signal(false);
2376
- this.isTranslucent = signal(false);
2377
- this.snapLayout = signal('full');
2378
- this.queryListMode = signal('live');
2379
- this.viewMode = signal('query');
2380
- this.showResponse = signal(false);
2381
- this.showRawResponse = signal(false);
2382
- this.showQueryConfig = signal(false);
2383
- this.showEntityStoreValue = signal(false);
2384
- this.showArguments = signal(false);
2385
- this.selectedClientIdCtrl = new FormControl(0);
2386
- this.selectedClientId = toSignal(this.selectedClientIdCtrl.valueChanges.pipe(startWith(this.selectedClientIdCtrl.value)));
2387
- this.selectedQueryId = signal(null);
2388
- this.selectedClientConfig = computed(() => {
2389
- if (this.queryClientConfigs.length === 1) {
2390
- return this.queryClientConfigs[0];
2391
- }
2392
- const index = this.selectedClientId() ?? 0;
2393
- const cfg = this.queryClientConfigs[index];
2394
- if (!cfg) {
2395
- return this.queryClientConfigs[0];
2396
- }
2397
- return cfg;
2398
- });
2399
- this.queryStore = computed(() => {
2400
- const config = this.selectedClientConfig();
2401
- return config.client._store;
2402
- });
2403
- this.queryStore$ = toObservable(this.queryStore);
2404
- this._queries$ = new BehaviorSubject([]);
2405
- this.queries = toSignal(this._queries$);
2406
- this.selectedQuery = computed(() => {
2407
- const id = this.selectedQueryId();
2408
- const mode = this.queryListMode();
2409
- if (id === null || !mode) {
2410
- return null;
2411
- }
2412
- if (mode === 'live') {
2413
- return this.queries()?.find((q) => q._id === id) ?? null;
2414
- }
2415
- return this.queryHistory$.getValue()?.find((q) => q._id === id) ?? null;
2416
- });
2417
- this.selectedQuery$ = toObservable(this.selectedQuery);
2418
- this.selectedQueryEntityStore = computed(() => {
2419
- const query = this.selectedQuery();
2420
- if (!query)
2421
- return null;
2422
- return query.store;
2423
- });
2424
- this.selectedQueryEntityStore$ = toObservable(this.selectedQueryEntityStore);
2425
- this.selectedQueryEntityStoreValue$ = this.selectedQueryEntityStore$.pipe(switchMap((s) => s?._change$.pipe(startWith(''), map(() => {
2426
- if (!s._dictionary)
2427
- return null;
2428
- return Array.from(s._dictionary).reduce((obj, [key, value]) => {
2429
- obj[key] = value;
2430
- return obj;
2431
- }, {});
2432
- })) ?? of(null)));
2433
- this.queryHistory$ = new BehaviorSubject([]);
2434
- this.stringifiedQueryConfig = computed(() => {
2435
- const query = this.selectedQuery();
2436
- if (!query)
2437
- return null;
2438
- const cfg = query._queryConfig;
2439
- const route = typeof cfg.route === 'string' ? cfg.route : cfg.route ? cfg.route({}).replace(/undefined/g, ':param') : null;
2440
- const sharedCfg = {
2441
- method: cfg.method,
2442
- secure: cfg.secure,
2443
- route,
2444
- reportProgress: cfg.reportProgress,
2445
- responseType: cfg.responseType,
2446
- withCredentials: cfg.withCredentials,
2447
- autoRefreshOn: cfg.autoRefreshOn,
2448
- enableSmartPolling: cfg.enableSmartPolling,
2449
- hasEntityStore: !!cfg.entity,
2450
- };
2451
- if (isGqlQueryConfig(cfg)) {
2452
- return {
2453
- ...sharedCfg,
2454
- query: cfg.query,
2455
- transferVia: cfg.transferVia,
2456
- };
2457
- }
2401
+ _cdr = inject(ChangeDetectorRef);
2402
+ _destroy$ = createDestroy();
2403
+ queryClientConfigs = inject(QUERY_CLIENT_DEVTOOLS_TOKEN);
2404
+ isOpen = signal(false);
2405
+ isTranslucent = signal(false);
2406
+ snapLayout = signal('full');
2407
+ queryListMode = signal('live');
2408
+ viewMode = signal('query');
2409
+ showResponse = signal(false);
2410
+ showRawResponse = signal(false);
2411
+ showQueryConfig = signal(false);
2412
+ showEntityStoreValue = signal(false);
2413
+ showArguments = signal(false);
2414
+ selectedClientIdCtrl = new FormControl(0);
2415
+ selectedClientId = toSignal(this.selectedClientIdCtrl.valueChanges.pipe(startWith(this.selectedClientIdCtrl.value)));
2416
+ selectedQueryId = signal(null);
2417
+ selectedClientConfig = computed(() => {
2418
+ if (this.queryClientConfigs.length === 1) {
2419
+ return this.queryClientConfigs[0];
2420
+ }
2421
+ const index = this.selectedClientId() ?? 0;
2422
+ const cfg = this.queryClientConfigs[index];
2423
+ if (!cfg) {
2424
+ return this.queryClientConfigs[0];
2425
+ }
2426
+ return cfg;
2427
+ });
2428
+ queryStore = computed(() => {
2429
+ const config = this.selectedClientConfig();
2430
+ return config.client._store;
2431
+ });
2432
+ queryStore$ = toObservable(this.queryStore);
2433
+ _queries$ = new BehaviorSubject([]);
2434
+ queries = toSignal(this._queries$);
2435
+ selectedQuery = computed(() => {
2436
+ const id = this.selectedQueryId();
2437
+ const mode = this.queryListMode();
2438
+ if (id === null || !mode) {
2439
+ return null;
2440
+ }
2441
+ if (mode === 'live') {
2442
+ return this.queries()?.find((q) => q._id === id) ?? null;
2443
+ }
2444
+ return this.queryHistory$.getValue()?.find((q) => q._id === id) ?? null;
2445
+ });
2446
+ selectedQuery$ = toObservable(this.selectedQuery);
2447
+ selectedQueryEntityStore = computed(() => {
2448
+ const query = this.selectedQuery();
2449
+ if (!query)
2450
+ return null;
2451
+ return query.store;
2452
+ });
2453
+ selectedQueryEntityStore$ = toObservable(this.selectedQueryEntityStore);
2454
+ selectedQueryEntityStoreValue$ = this.selectedQueryEntityStore$.pipe(switchMap((s) => s?._change$.pipe(startWith(''), map(() => {
2455
+ if (!s._dictionary)
2456
+ return null;
2457
+ return Array.from(s._dictionary).reduce((obj, [key, value]) => {
2458
+ obj[key] = value;
2459
+ return obj;
2460
+ }, {});
2461
+ })) ?? of(null)));
2462
+ queryHistory$ = new BehaviorSubject([]);
2463
+ stringifiedQueryConfig = computed(() => {
2464
+ const query = this.selectedQuery();
2465
+ if (!query)
2466
+ return null;
2467
+ const cfg = query._queryConfig;
2468
+ const route = typeof cfg.route === 'string' ? cfg.route : cfg.route ? cfg.route({}).replace(/undefined/g, ':param') : null;
2469
+ const sharedCfg = {
2470
+ method: cfg.method,
2471
+ secure: cfg.secure,
2472
+ route,
2473
+ reportProgress: cfg.reportProgress,
2474
+ responseType: cfg.responseType,
2475
+ withCredentials: cfg.withCredentials,
2476
+ autoRefreshOn: cfg.autoRefreshOn,
2477
+ enableSmartPolling: cfg.enableSmartPolling,
2478
+ hasEntityStore: !!cfg.entity,
2479
+ };
2480
+ if (isGqlQueryConfig(cfg)) {
2458
2481
  return {
2459
2482
  ...sharedCfg,
2483
+ query: cfg.query,
2484
+ transferVia: cfg.transferVia,
2460
2485
  };
2461
- });
2462
- this.authProvider = toSignal(toObservable(this.selectedClientConfig).pipe(switchMap((c) => c.client.authProvider$)));
2463
- this.authProviderDetails = computed(() => {
2464
- const provider = this.authProvider();
2465
- if (!provider)
2466
- return null;
2467
- if (provider instanceof CustomHeaderAuthProvider) {
2468
- return {
2469
- type: 'CustomHeaderAuthProvider',
2470
- header: () => provider.header,
2471
- provider: provider,
2472
- config: {
2473
- name: provider._config.name,
2474
- value: provider._config.value,
2475
- },
2476
- };
2477
- }
2478
- else if (provider instanceof BasicAuthProvider) {
2479
- return {
2480
- type: 'BasicAuthProvider',
2481
- header: () => provider.header,
2482
- provider: provider,
2483
- config: {
2484
- username: provider._config.username,
2485
- password: provider._config.password,
2486
- },
2487
- };
2488
- }
2489
- else if (isBearerAuthProvider(provider)) {
2490
- const refreshCfg = provider._config.refreshConfig;
2491
- return {
2492
- type: 'BearerAuthProvider',
2493
- header: () => provider.header,
2494
- provider: provider,
2495
- config: {
2496
- token: provider._config.token,
2497
- refreshConfig: {
2498
- refreshOnUnauthorizedResponse: refreshCfg?.refreshOnUnauthorizedResponse ?? 'true (default)',
2499
- token: refreshCfg?.token,
2500
- cookieName: refreshCfg?.cookieName,
2501
- cookieDomain: refreshCfg?.cookieDomain ?? 'current origin (default)',
2502
- cookieExpiresInDays: refreshCfg?.cookieExpiresInDays ?? '30 (default)',
2503
- cookiePath: refreshCfg?.cookiePath ?? '/ (default)',
2504
- cookieEnabled: refreshCfg?.cookieEnabled ?? 'true (default)',
2505
- cookieSameSite: refreshCfg?.cookieSameSite ?? 'lax (default)',
2506
- refreshBuffer: refreshCfg?.refreshBuffer ?? '30000 (default)',
2507
- expiresInPropertyName: refreshCfg?.expiresInPropertyName ?? 'exp (default)',
2508
- strategy: refreshCfg?.strategy ?? 'AuthBearerRefreshStrategy.BeforeExpiration (default)',
2509
- requestArgsAdapter: refreshCfg?.requestArgsAdapter ? 'custom' : 'default',
2510
- responseAdapter: refreshCfg?.responseAdapter ? 'custom' : 'default',
2511
- },
2486
+ }
2487
+ return {
2488
+ ...sharedCfg,
2489
+ };
2490
+ });
2491
+ authProvider = toSignal(toObservable(this.selectedClientConfig).pipe(switchMap((c) => c.client.authProvider$)));
2492
+ authProviderDetails = computed(() => {
2493
+ const provider = this.authProvider();
2494
+ if (!provider)
2495
+ return null;
2496
+ if (provider instanceof CustomHeaderAuthProvider) {
2497
+ return {
2498
+ type: 'CustomHeaderAuthProvider',
2499
+ header: () => provider.header,
2500
+ provider: provider,
2501
+ config: {
2502
+ name: provider._config.name,
2503
+ value: provider._config.value,
2504
+ },
2505
+ };
2506
+ }
2507
+ else if (provider instanceof BasicAuthProvider) {
2508
+ return {
2509
+ type: 'BasicAuthProvider',
2510
+ header: () => provider.header,
2511
+ provider: provider,
2512
+ config: {
2513
+ username: provider._config.username,
2514
+ password: provider._config.password,
2515
+ },
2516
+ };
2517
+ }
2518
+ else if (isBearerAuthProvider(provider)) {
2519
+ const refreshCfg = provider._config.refreshConfig;
2520
+ return {
2521
+ type: 'BearerAuthProvider',
2522
+ header: () => provider.header,
2523
+ provider: provider,
2524
+ config: {
2525
+ token: provider._config.token,
2526
+ refreshConfig: {
2527
+ refreshOnUnauthorizedResponse: refreshCfg?.refreshOnUnauthorizedResponse ?? 'true (default)',
2528
+ token: refreshCfg?.token,
2529
+ cookieName: refreshCfg?.cookieName,
2530
+ cookieDomain: refreshCfg?.cookieDomain ?? 'current origin (default)',
2531
+ cookieExpiresInDays: refreshCfg?.cookieExpiresInDays ?? '30 (default)',
2532
+ cookiePath: refreshCfg?.cookiePath ?? '/ (default)',
2533
+ cookieEnabled: refreshCfg?.cookieEnabled ?? 'true (default)',
2534
+ cookieSameSite: refreshCfg?.cookieSameSite ?? 'lax (default)',
2535
+ refreshBuffer: refreshCfg?.refreshBuffer ?? '30000 (default)',
2536
+ expiresInPropertyName: refreshCfg?.expiresInPropertyName ?? 'exp (default)',
2537
+ strategy: refreshCfg?.strategy ?? 'AuthBearerRefreshStrategy.BeforeExpiration (default)',
2538
+ requestArgsAdapter: refreshCfg?.requestArgsAdapter ? 'custom' : 'default',
2539
+ responseAdapter: refreshCfg?.responseAdapter ? 'custom' : 'default',
2512
2540
  },
2513
- };
2514
- }
2515
- else {
2516
- return {
2517
- type: 'UnknownAuthProvider',
2518
- header: () => provider.header,
2519
- provider: provider,
2520
- config: {},
2521
- };
2522
- }
2523
- });
2524
- this.trackByClient = (_, { client }) => client.config.baseRoute;
2525
- this.trackByQuery = (_, { _id }) => _id;
2541
+ },
2542
+ };
2543
+ }
2544
+ else {
2545
+ return {
2546
+ type: 'UnknownAuthProvider',
2547
+ header: () => provider.header,
2548
+ provider: provider,
2549
+ config: {},
2550
+ };
2551
+ }
2552
+ });
2553
+ constructor() {
2526
2554
  this.selectedClientIdCtrl.valueChanges
2527
2555
  .pipe(tap(() => this.clearQueryHistory()), takeUntil(this._destroy$))
2528
2556
  .subscribe();
@@ -2602,6 +2630,8 @@ class QueryDevtoolsComponent {
2602
2630
  this.viewMode.set(parsed.viewMode ?? 'query');
2603
2631
  }
2604
2632
  }
2633
+ trackByClient = (_, { client }) => client.config.baseRoute;
2634
+ trackByQuery = (_, { _id }) => _id;
2605
2635
  toggleOpen() {
2606
2636
  this.isOpen.set(!this.isOpen());
2607
2637
  }
@@ -2641,10 +2671,10 @@ class QueryDevtoolsComponent {
2641
2671
  clearQueryHistory() {
2642
2672
  this.queryHistory$.next([]);
2643
2673
  }
2644
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2645
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: QueryDevtoolsComponent, isStandalone: true, selector: "et-query-devtools", host: { classAttribute: "et-query-devtools" }, ngImport: i0, template: "@if (!isOpen()) {\n <button (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn et-qd-chip\">Query Devtools</button>\n}\n\n@if (isOpen()) {\n <div\n [class.et-query-devtools-container--transparent]=\"isTranslucent()\"\n class=\"et-query-devtools-container et-query-devtools-container--snap-{{ snapLayout() }}\"\n >\n <header class=\"et-qd-header\">\n <h3 class=\"et-qd-header__title\">Query Devtools</h3>\n\n <div class=\"et-qd-header__select\">\n <label for=\"et-query-client-instance\">Client instance</label>\n <select [formControl]=\"selectedClientIdCtrl\" id=\"et-query-client-instance\">\n @for (clientConfig of queryClientConfigs; track trackByClient(i, clientConfig); let i = $index) {\n <option [value]=\"i\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </option>\n }\n </select>\n </div>\n\n <button (click)=\"toggleOpen()\" class=\"et-qd-btn et-qd-btn-secondary\">Close</button>\n </header>\n\n <div class=\"et-qd-sub-header\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !isTranslucent() }\"\n (click)=\"toggleTranslucent()\"\n class=\"et-qd-chip et-qd-translucent-clickable\"\n >\n Translucent\n </button>\n <div class=\"et-qd-sub-header__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'full' }\"\n (click)=\"selectSnapLayout('full')\"\n class=\"et-qd-chip\"\n >\n Fullscreen\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'top' }\"\n (click)=\"selectSnapLayout('top')\"\n class=\"et-qd-chip\"\n >\n Top\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'bottom' }\"\n (click)=\"selectSnapLayout('bottom')\"\n class=\"et-qd-chip\"\n >\n Bottom\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'left' }\"\n (click)=\"selectSnapLayout('left')\"\n class=\"et-qd-chip\"\n >\n Left\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'right' }\"\n (click)=\"selectSnapLayout('right')\"\n class=\"et-qd-chip\"\n >\n Right\n </button>\n </div>\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-client\">\n <p class=\"et-qd-client__title\">{{ cfg.displayName ?? cfg.client.config.baseRoute }}</p>\n\n <div class=\"et-qd-client__actions\">\n <button (click)=\"cfg.client._store.refreshQueriesInUse()\" class=\"et-qd-chip\">Refresh all</button>\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true })\" class=\"et-qd-chip\">\n Refresh all (ignore caches)\n </button>\n <button\n (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true, purgeUnused: true })\"\n class=\"et-qd-chip\"\n >\n Refresh all (ignore caches & purge unused)\n </button>\n </div>\n </div>\n }\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-queries\">\n <p class=\"et-qd-queries__title\">Inspector</p>\n <div class=\"et-qd-queries__actions\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'live' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('live'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Live Queries ({{ queries()?.length ?? 0 }})\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'history' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('history'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Query History ({{ (queryHistory$ | async)?.length ?? 0 }}/50)\n </button>\n @if (queryListMode() === 'history' && viewMode() === 'query') {\n <div class=\"et-qd-queries__divider\"></div>\n <button (click)=\"clearQueryHistory()\" class=\"et-qd-chip et-qd-chip-bordered\">Clear history</button>\n }\n\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': viewMode() !== 'authProvider' }\"\n (click)=\"selectViewMode('authProvider')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Auth Provider\n </button>\n </div>\n\n @if (viewMode() === 'query') {\n <div class=\"et-qd-queries__browser\">\n @if (queryListMode() === 'live') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queries(); track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n @if (queryListMode() === 'history') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queryHistory$ | async; track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n <div class=\"et-qd-queries__browser-detail\">\n @if (selectedQuery(); as query) {\n <p class=\"et-qd-queries__browser-detail__title\">\n {{ query._queryConfig.method }} {{ query._routeWithParams }}\n </p>\n\n <div class=\"et-qd-queries__actions\">\n <button (click)=\"query.execute()\" class=\"et-qd-chip et-qd-chip-bordered\">Execute</button>\n <button (click)=\"query.execute({ skipCache: true })\" class=\"et-qd-chip et-qd-chip-bordered\">\n Execute (ignore cache)\n </button>\n\n <button (click)=\"query.abort()\" class=\"et-qd-chip et-qd-chip-bordered\">Abort</button>\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !query.isPolling }\"\n (click)=\"query.poll({ interval: 5000, takeUntil: _destroy$ })\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Poll\n </button>\n\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': query.isPolling }\"\n (click)=\"query.stopPolling()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Stop polling\n </button>\n @if (query.isPolling || query._isPollingPaused) {\n <button (click)=\"query.pausePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Pause polling\n </button>\n <button (click)=\"query.resumePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Resume polling\n </button>\n }\n </div>\n\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>State type</p>\n <pre>{{ query.rawState.type }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Dependents</p>\n <pre>{{ query._dependents | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is expired</p>\n <pre>{{ query.isExpired }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is in use</p>\n <pre>{{ query.isInUse }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Subscriber count</p>\n <pre>{{ query._subscriberCount }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling</p>\n <pre>{{ query.isPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling paused</p>\n <pre>{{ query._isPollingPaused }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Enable smart polling</p>\n <pre>{{ query._enableSmartPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query store key</p>\n <pre>{{ query._queryStoreKey }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Arguments</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showArguments() }\"\n (click)=\"toggleShowArguments()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showArguments()) {\n <pre>{{ query._arguments | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <p><i> Warning, this will cause a subscription if shown!</i></p>\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showResponse() }\"\n (click)=\"toggleShowResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showResponse()) {\n <pre>{{ query.state$ | async | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Raw state</p>\n <p><i> The query state unaffected by entity stores</i></p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showRawResponse() }\"\n (click)=\"toggleShowRawResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showRawResponse()) {\n <pre>{{ query.rawState | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query config</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showQueryConfig() }\"\n (click)=\"toggleShowQueryConfig()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showQueryConfig()) {\n <pre>{{ stringifiedQueryConfig() | json }}</pre>\n }\n </div>\n\n @if (!!query._queryConfig.entity) {\n <div class=\"et-qd-list-item\">\n <p>Entity store value</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showEntityStoreValue() }\"\n (click)=\"toggleShowEntityStoreValue()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showEntityStoreValue()) {\n <pre>{{ selectedQueryEntityStoreValue$ | async | json }}</pre>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n } @else if (viewMode() === 'authProvider') {\n <div class=\"et-qd-auth-provider__viewer\">\n @if (authProviderDetails(); as details) {\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>Type</p>\n <pre>{{ details.type }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Header value</p>\n <pre>{{ details.header() | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Config</p>\n <pre>{{ details.config | json }}</pre>\n </div>\n\n @if (details.type === 'BearerAuthProvider') {\n <div class=\"et-qd-list-item\">\n <p>Tokens</p>\n <pre>{{ details.provider.tokens$ | async | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Should refresh on unauthorized response</p>\n <pre>{{ details.provider.shouldRefreshOnUnauthorizedResponse }}</pre>\n </div>\n\n <ng-container\n *etQuery=\"\n details.provider.currentRefreshQuery$ | async as response;\n loading as loading;\n error as error;\n query as query\n \"\n >\n <div class=\"et-qd-list-item\">\n <p>Refresh query response</p>\n\n <div>\n <button (click)=\"details.provider._refreshQuery()\" class=\"et-qd-chip et-qd-chip-bordered\">\n Refresh\n </button>\n </div>\n <pre>{{ response | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query loading</p>\n <pre>{{ loading }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query error</p>\n <pre>{{ error ?? 'null' }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <pre>{{ query?.state$ | async | json }}</pre>\n </div>\n </ng-container>\n }\n </div>\n } @else {\n <p>No auth provider set</p>\n }\n </div>\n }\n </div>\n }\n </div>\n}\n", styles: [":host{position:fixed;top:0;z-index:1000000;font-size:14px;color:#fff}.et-query-devtools-container{position:fixed;inset:0;background-color:#25292e;z-index:10000;overflow:auto;font-family:monospace;display:grid;grid-template-rows:auto auto auto minmax(0,1fr)}.et-query-devtools-container.et-query-devtools-container--transparent{opacity:.25;pointer-events:none}.et-query-devtools-container.et-query-devtools-container--transparent .et-query-devtools-translucent-btn{pointer-events:all}.et-query-devtools-container.et-query-devtools-container--snap-left{inset-inline-start:0;inset-block-start:0;inset-block-end:0;width:50%;border-right:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-right{inset-inline-start:unset;inset-inline-end:0;inset-block-start:0;inset-block-end:0;width:50%;border-left:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-top{inset-inline-start:0;inset-block-start:0;inset-inline-end:0;height:50%;border-bottom:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-bottom{inset-inline-start:0;inset-block-start:unset;inset-block-end:0;inset-inline-end:0;height:50%;border-top:1px solid rgb(37,41,46)}button.et-query-devtools-open-btn{position:fixed;inset-inline-end:20px;inset-block-end:0;z-index:9999;font-family:monospace;border-radius:3px 3px 0 0;line-height:14px;font-size:12px}.et-qd-header{background-color:#00ffa1;padding:12px;display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center}.et-qd-header__title{color:#25292e;margin:0;font-size:22px}.et-qd-header__select{display:grid;background-color:#25292e;border-radius:10px;overflow:hidden}.et-qd-header__select select{width:250px;color:#fff;padding:3px 10px 2px;border:none;background-color:#25292e;font-family:monospace}.et-qd-header__select label{padding:3px 10px;color:#25292e;font-size:12px;font-weight:700;color:#fff;border-bottom:1px solid gray}.et-qd-sub-header{background-color:#00b371;padding:12px;display:flex;gap:12px;flex-wrap:wrap}.et-qd-sub-header__divider{width:1px;background-color:#25292e}.et-qd-btn{background-color:#00ffa1;color:#25292e;border:none;padding:12px;cursor:pointer;font-size:14px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;width:100%;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-btn:hover{background-color:#00cc81}.et-qd-btn.et-qd-btn-secondary{background-color:#25292e;color:#00ffa1}.et-qd-btn.et-qd-btn-secondary:hover{background-color:#3c424a}.et-qd-chip{background-color:#00ffa1;color:#25292e;border:none;padding:4px 9px;cursor:pointer;font-size:12px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-chip:hover{background-color:#00cc81}.et-qd-chip.et-qd-chip-secondary{background-color:#25292e;color:#00ffa1}.et-qd-chip.et-qd-chip-secondary:hover{background-color:#3c424a}.et-qd-chip.et-qd-chip-bordered{border:1px solid rgb(0,255,161)}.et-qd-translucent-clickable{pointer-events:all}.et-qd-client{border-bottom:1px solid rgb(59.734939759,66.1927710843,74.265060241);padding:12px}.et-qd-client__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-client__actions{display:flex;gap:12px;margin-top:12px}.et-qd-queries{padding:12px;display:grid;grid-template-rows:auto auto minmax(0,1fr)}.et-qd-queries__actions{display:flex;gap:12px;margin-top:12px;margin-bottom:16px}.et-qd-queries__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-queries__divider{width:1px;background-color:#3c424a}.et-qd-queries__browser{display:grid;grid-template-columns:1fr minmax(0,3fr);margin-left:-12px;margin-right:-12px;border-top:1px solid rgb(59.734939759,66.1927710843,74.265060241);margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid rgb(59.734939759,66.1927710843,74.265060241);list-style:none;padding:0;margin:0;display:grid;grid-auto-flow:row;grid-auto-rows:55px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-list li{margin:0}.et-qd-queries__browser-list li button{all:unset;font-family:monospace;box-sizing:border-box;width:100%;border:none;border-bottom:1px solid rgb(59.734939759,66.1927710843,74.265060241);background-color:#25292e;color:#fff;text-align:left;padding:12px;height:100%;transition:all .3s ease-in-out;cursor:pointer;display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px;display:block}.et-qd-queries__browser-list li button span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.et-qd-queries__browser-list li button span:first-of-type{font-weight:700}.et-qd-queries__browser-list li button:hover,.et-qd-queries__browser-list li button.et-qd-query--active{background-color:#30363c}.et-qd-queries__browser-detail{padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-detail__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-auth-provider__viewer{border-top:1px solid rgb(59.734939759,66.1927710843,74.265060241);margin-left:-12px;margin-right:-12px;margin-bottom:-12px;padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-list{display:grid;gap:12px}.et-qd-list-item{display:grid}.et-qd-list-item p{font-weight:700;margin:0;padding-bottom:8px}.et-qd-list-item p+p{margin-top:-8px}.et-qd-list-item div+pre{margin-top:8px}.et-qd-list-item pre{margin:0;padding:4px;background-color:#0e1012;border-radius:4px;max-height:450px;overflow:auto}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: QueryShortNamePipe, name: "queryShortName" }, { kind: "directive", type: QueryDirective, selector: "[etQuery]", inputs: ["etQuery", "etQueryCache"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom }); }
2674
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2675
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.4", type: QueryDevtoolsComponent, isStandalone: true, selector: "et-query-devtools", host: { classAttribute: "et-query-devtools" }, ngImport: i0, template: "@if (!isOpen()) {\n <button (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn et-qd-chip\">Query Devtools</button>\n}\n\n@if (isOpen()) {\n <div\n [class.et-query-devtools-container--transparent]=\"isTranslucent()\"\n class=\"et-query-devtools-container et-query-devtools-container--snap-{{ snapLayout() }}\"\n >\n <header class=\"et-qd-header\">\n <h3 class=\"et-qd-header__title\">Query Devtools</h3>\n\n <div class=\"et-qd-header__select\">\n <label for=\"et-query-client-instance\">Client instance</label>\n <select [formControl]=\"selectedClientIdCtrl\" id=\"et-query-client-instance\">\n @for (clientConfig of queryClientConfigs; track trackByClient(i, clientConfig); let i = $index) {\n <option [value]=\"i\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </option>\n }\n </select>\n </div>\n\n <button (click)=\"toggleOpen()\" class=\"et-qd-btn et-qd-btn-secondary\">Close</button>\n </header>\n\n <div class=\"et-qd-sub-header\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !isTranslucent() }\"\n (click)=\"toggleTranslucent()\"\n class=\"et-qd-chip et-qd-translucent-clickable\"\n >\n Translucent\n </button>\n <div class=\"et-qd-sub-header__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'full' }\"\n (click)=\"selectSnapLayout('full')\"\n class=\"et-qd-chip\"\n >\n Fullscreen\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'top' }\"\n (click)=\"selectSnapLayout('top')\"\n class=\"et-qd-chip\"\n >\n Top\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'bottom' }\"\n (click)=\"selectSnapLayout('bottom')\"\n class=\"et-qd-chip\"\n >\n Bottom\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'left' }\"\n (click)=\"selectSnapLayout('left')\"\n class=\"et-qd-chip\"\n >\n Left\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'right' }\"\n (click)=\"selectSnapLayout('right')\"\n class=\"et-qd-chip\"\n >\n Right\n </button>\n </div>\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-client\">\n <p class=\"et-qd-client__title\">{{ cfg.displayName ?? cfg.client.config.baseRoute }}</p>\n\n <div class=\"et-qd-client__actions\">\n <button (click)=\"cfg.client._store.refreshQueriesInUse()\" class=\"et-qd-chip\">Refresh all</button>\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true })\" class=\"et-qd-chip\">\n Refresh all (ignore caches)\n </button>\n <button\n (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true, purgeUnused: true })\"\n class=\"et-qd-chip\"\n >\n Refresh all (ignore caches & purge unused)\n </button>\n </div>\n </div>\n }\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-queries\">\n <p class=\"et-qd-queries__title\">Inspector</p>\n <div class=\"et-qd-queries__actions\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'live' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('live'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Live Queries ({{ queries()?.length ?? 0 }})\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'history' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('history'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Query History ({{ (queryHistory$ | async)?.length ?? 0 }}/50)\n </button>\n @if (queryListMode() === 'history' && viewMode() === 'query') {\n <div class=\"et-qd-queries__divider\"></div>\n <button (click)=\"clearQueryHistory()\" class=\"et-qd-chip et-qd-chip-bordered\">Clear history</button>\n }\n\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': viewMode() !== 'authProvider' }\"\n (click)=\"selectViewMode('authProvider')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Auth Provider\n </button>\n </div>\n\n @if (viewMode() === 'query') {\n <div class=\"et-qd-queries__browser\">\n @if (queryListMode() === 'live') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queries(); track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n @if (queryListMode() === 'history') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queryHistory$ | async; track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n <div class=\"et-qd-queries__browser-detail\">\n @if (selectedQuery(); as query) {\n <p class=\"et-qd-queries__browser-detail__title\">\n {{ query._queryConfig.method }} {{ query._routeWithParams }}\n </p>\n\n <div class=\"et-qd-queries__actions\">\n <button (click)=\"query.execute()\" class=\"et-qd-chip et-qd-chip-bordered\">Execute</button>\n <button (click)=\"query.execute({ skipCache: true })\" class=\"et-qd-chip et-qd-chip-bordered\">\n Execute (ignore cache)\n </button>\n\n <button (click)=\"query.abort()\" class=\"et-qd-chip et-qd-chip-bordered\">Abort</button>\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !query.isPolling }\"\n (click)=\"query.poll({ interval: 5000, takeUntil: _destroy$ })\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Poll\n </button>\n\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': query.isPolling }\"\n (click)=\"query.stopPolling()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Stop polling\n </button>\n @if (query.isPolling || query._isPollingPaused) {\n <button (click)=\"query.pausePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Pause polling\n </button>\n <button (click)=\"query.resumePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Resume polling\n </button>\n }\n </div>\n\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>State type</p>\n <pre>{{ query.rawState.type }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Dependents</p>\n <pre>{{ query._dependents | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is expired</p>\n <pre>{{ query.isExpired }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is in use</p>\n <pre>{{ query.isInUse }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Subscriber count</p>\n <pre>{{ query._subscriberCount }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling</p>\n <pre>{{ query.isPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling paused</p>\n <pre>{{ query._isPollingPaused }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Enable smart polling</p>\n <pre>{{ query._enableSmartPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query store key</p>\n <pre>{{ query._queryStoreKey }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Arguments</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showArguments() }\"\n (click)=\"toggleShowArguments()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showArguments()) {\n <pre>{{ query._arguments | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <p><i> Warning, this will cause a subscription if shown!</i></p>\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showResponse() }\"\n (click)=\"toggleShowResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showResponse()) {\n <pre>{{ query.state$ | async | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Raw state</p>\n <p><i> The query state unaffected by entity stores</i></p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showRawResponse() }\"\n (click)=\"toggleShowRawResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showRawResponse()) {\n <pre>{{ query.rawState | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query config</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showQueryConfig() }\"\n (click)=\"toggleShowQueryConfig()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showQueryConfig()) {\n <pre>{{ stringifiedQueryConfig() | json }}</pre>\n }\n </div>\n\n @if (!!query._queryConfig.entity) {\n <div class=\"et-qd-list-item\">\n <p>Entity store value</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showEntityStoreValue() }\"\n (click)=\"toggleShowEntityStoreValue()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showEntityStoreValue()) {\n <pre>{{ selectedQueryEntityStoreValue$ | async | json }}</pre>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n } @else if (viewMode() === 'authProvider') {\n <div class=\"et-qd-auth-provider__viewer\">\n @if (authProviderDetails(); as details) {\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>Type</p>\n <pre>{{ details.type }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Header value</p>\n <pre>{{ details.header() | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Config</p>\n <pre>{{ details.config | json }}</pre>\n </div>\n\n @if (details.type === 'BearerAuthProvider') {\n <div class=\"et-qd-list-item\">\n <p>Tokens</p>\n <pre>{{ details.provider.tokens$ | async | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Should refresh on unauthorized response</p>\n <pre>{{ details.provider.shouldRefreshOnUnauthorizedResponse }}</pre>\n </div>\n\n <ng-container\n *etQuery=\"\n details.provider.currentRefreshQuery$ | async as response;\n loading as loading;\n error as error;\n query as query\n \"\n >\n <div class=\"et-qd-list-item\">\n <p>Refresh query response</p>\n\n <div>\n <button (click)=\"details.provider._refreshQuery()\" class=\"et-qd-chip et-qd-chip-bordered\">\n Refresh\n </button>\n </div>\n <pre>{{ response | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query loading</p>\n <pre>{{ loading }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query error</p>\n <pre>{{ error ?? 'null' }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <pre>{{ query?.state$ | async | json }}</pre>\n </div>\n </ng-container>\n }\n </div>\n } @else {\n <p>No auth provider set</p>\n }\n </div>\n }\n </div>\n }\n </div>\n}\n", styles: [":host{position:fixed;top:0;z-index:1000000;font-size:14px;color:#fff}.et-query-devtools-container{position:fixed;inset:0;background-color:#25292e;z-index:10000;overflow:auto;font-family:monospace;display:grid;grid-template-rows:auto auto auto minmax(0,1fr)}.et-query-devtools-container.et-query-devtools-container--transparent{opacity:.25;pointer-events:none}.et-query-devtools-container.et-query-devtools-container--transparent .et-query-devtools-translucent-btn{pointer-events:all}.et-query-devtools-container.et-query-devtools-container--snap-left{inset-inline-start:0;inset-block-start:0;inset-block-end:0;width:50%;border-right:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-right{inset-inline-start:unset;inset-inline-end:0;inset-block-start:0;inset-block-end:0;width:50%;border-left:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-top{inset-inline-start:0;inset-block-start:0;inset-inline-end:0;height:50%;border-bottom:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-bottom{inset-inline-start:0;inset-block-start:unset;inset-block-end:0;inset-inline-end:0;height:50%;border-top:1px solid rgb(37,41,46)}button.et-query-devtools-open-btn{position:fixed;inset-inline-end:20px;inset-block-end:0;z-index:9999;font-family:monospace;border-radius:3px 3px 0 0;line-height:14px;font-size:12px}.et-qd-header{background-color:#00ffa1;padding:12px;display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center}.et-qd-header__title{color:#25292e;margin:0;font-size:22px}.et-qd-header__select{display:grid;background-color:#25292e;border-radius:10px;overflow:hidden}.et-qd-header__select select{width:250px;color:#fff;padding:3px 10px 2px;border:none;background-color:#25292e;font-family:monospace}.et-qd-header__select label{padding:3px 10px;color:#25292e;font-size:12px;font-weight:700;color:#fff;border-bottom:1px solid gray}.et-qd-sub-header{background-color:#00b371;padding:12px;display:flex;gap:12px;flex-wrap:wrap}.et-qd-sub-header__divider{width:1px;background-color:#25292e}.et-qd-btn{background-color:#00ffa1;color:#25292e;border:none;padding:12px;cursor:pointer;font-size:14px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;width:100%;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-btn:hover{background-color:#00cc81}.et-qd-btn.et-qd-btn-secondary{background-color:#25292e;color:#00ffa1}.et-qd-btn.et-qd-btn-secondary:hover{background-color:#3c424a}.et-qd-chip{background-color:#00ffa1;color:#25292e;border:none;padding:4px 9px;cursor:pointer;font-size:12px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-chip:hover{background-color:#00cc81}.et-qd-chip.et-qd-chip-secondary{background-color:#25292e;color:#00ffa1}.et-qd-chip.et-qd-chip-secondary:hover{background-color:#3c424a}.et-qd-chip.et-qd-chip-bordered{border:1px solid rgb(0,255,161)}.et-qd-translucent-clickable{pointer-events:all}.et-qd-client{border-bottom:1px solid rgb(59.734939759,66.1927710843,74.265060241);padding:12px}.et-qd-client__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-client__actions{display:flex;gap:12px;margin-top:12px}.et-qd-queries{padding:12px;display:grid;grid-template-rows:auto auto minmax(0,1fr)}.et-qd-queries__actions{display:flex;gap:12px;margin-top:12px;margin-bottom:16px}.et-qd-queries__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-queries__divider{width:1px;background-color:#3c424a}.et-qd-queries__browser{display:grid;grid-template-columns:1fr minmax(0,3fr);margin-left:-12px;margin-right:-12px;border-top:1px solid rgb(59.734939759,66.1927710843,74.265060241);margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid rgb(59.734939759,66.1927710843,74.265060241);list-style:none;padding:0;margin:0;display:grid;grid-auto-flow:row;grid-auto-rows:55px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-list li{margin:0}.et-qd-queries__browser-list li button{all:unset;font-family:monospace;box-sizing:border-box;width:100%;border:none;border-bottom:1px solid rgb(59.734939759,66.1927710843,74.265060241);background-color:#25292e;color:#fff;text-align:left;padding:12px;height:100%;transition:all .3s ease-in-out;cursor:pointer;display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px;display:block}.et-qd-queries__browser-list li button span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.et-qd-queries__browser-list li button span:first-of-type{font-weight:700}.et-qd-queries__browser-list li button:hover,.et-qd-queries__browser-list li button.et-qd-query--active{background-color:#30363c}.et-qd-queries__browser-detail{padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-detail__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-auth-provider__viewer{border-top:1px solid rgb(59.734939759,66.1927710843,74.265060241);margin-left:-12px;margin-right:-12px;margin-bottom:-12px;padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-list{display:grid;gap:12px}.et-qd-list-item{display:grid}.et-qd-list-item p{font-weight:700;margin:0;padding-bottom:8px}.et-qd-list-item p+p{margin-top:-8px}.et-qd-list-item div+pre{margin-top:8px}.et-qd-list-item pre{margin:0;padding:4px;background-color:#0e1012;border-radius:4px;max-height:450px;overflow:auto}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: QueryShortNamePipe, name: "queryShortName" }, { kind: "directive", type: QueryDirective, selector: "[etQuery]", inputs: ["etQuery", "etQueryCache"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom });
2646
2676
  }
2647
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
2677
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
2648
2678
  type: Component,
2649
2679
  args: [{ selector: 'et-query-devtools', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, host: {
2650
2680
  class: 'et-query-devtools',
@@ -2652,6 +2682,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
2652
2682
  }], ctorParameters: () => [] });
2653
2683
 
2654
2684
  class EntityStoreError extends Error {
2685
+ detail;
2655
2686
  constructor(message, detail) {
2656
2687
  super(message);
2657
2688
  this.detail = detail;
@@ -2662,16 +2693,17 @@ function flatten(arr) {
2662
2693
  return arr.reduce((acc, val) => acc.concat(val), []);
2663
2694
  }
2664
2695
  class EntityStore {
2696
+ _config;
2697
+ /**
2698
+ * @internal
2699
+ */
2700
+ _dictionary = new Map();
2701
+ /**
2702
+ * @internal
2703
+ */
2704
+ _change$ = new Subject();
2665
2705
  constructor(_config) {
2666
2706
  this._config = _config;
2667
- /**
2668
- * @internal
2669
- */
2670
- this._dictionary = new Map();
2671
- /**
2672
- * @internal
2673
- */
2674
- this._change$ = new Subject();
2675
2707
  }
2676
2708
  select(keyOrKeys) {
2677
2709
  if (Array.isArray(keyOrKeys)) {
@@ -2806,71 +2838,74 @@ const removeFrom = (store, { where, id }) => {
2806
2838
  };
2807
2839
 
2808
2840
  const queryFeatureUsedMultipleTimes = (type) => {
2809
- return new RuntimeError(0 /* RuntimeErrorCode.QUERY_FEATURE_USED_MULTIPLE_TIMES */, `The query feature "${type}()" was used multiple times.`);
2841
+ return new RuntimeError(0 /* QueryRuntimeErrorCode.QUERY_FEATURE_USED_MULTIPLE_TIMES */, `The query feature "${type}()" was used multiple times.`);
2810
2842
  };
2811
2843
  const withArgsQueryFeatureMissingButRouteIsFunction = () => {
2812
- return new RuntimeError(100 /* RuntimeErrorCode.WITH_ARGS_QUERY_FEATURE_MISSING_BUT_ROUTE_IS_FUNCTION */, `This queries route is a function, but a "withArgs()" feature is missing.`);
2844
+ return new RuntimeError(100 /* QueryRuntimeErrorCode.WITH_ARGS_QUERY_FEATURE_MISSING_BUT_ROUTE_IS_FUNCTION */, `This queries route is a function, but a "withArgs()" feature is missing.`);
2813
2845
  };
2814
2846
  const withPollingUsedOnUnsupportedHttpMethod = (method) => {
2815
- return new RuntimeError(101 /* RuntimeErrorCode.WITH_POLLING_USED_ON_UNSUPPORTED_HTTP_METHOD */, `This is a "${method}" request, "withPolling()" is only supported for GET, HEAD, OPTIONS requests and GQL queries.`);
2847
+ return new RuntimeError(101 /* QueryRuntimeErrorCode.WITH_POLLING_USED_ON_UNSUPPORTED_HTTP_METHOD */, `This is a "${method}" request, "withPolling()" is only supported for GET, HEAD, OPTIONS requests and GQL queries.`);
2816
2848
  };
2817
2849
  const withAutoRefreshUsedOnUnsupportedHttpMethod = (method) => {
2818
- return new RuntimeError(102 /* RuntimeErrorCode.WITH_AUTO_REFRESH_USED_ON_UNSUPPORTED_HTTP_METHOD */, `This is a "${method}" request, "withAutoRefresh()" is only supported for GET, HEAD, OPTIONS requests and GQL queries.`);
2850
+ return new RuntimeError(102 /* QueryRuntimeErrorCode.WITH_AUTO_REFRESH_USED_ON_UNSUPPORTED_HTTP_METHOD */, `This is a "${method}" request, "withAutoRefresh()" is only supported for GET, HEAD, OPTIONS requests and GQL queries.`);
2819
2851
  };
2820
2852
  const withAutoRefreshUsedInManualQuery = () => {
2821
- return new RuntimeError(103 /* RuntimeErrorCode.WITH_AUTO_REFRESH_USED_IN_MANUAL_QUERY */, `"withAutoRefresh()" has been used inside a query that has "onlyManualExecution" set to true.` +
2853
+ return new RuntimeError(103 /* QueryRuntimeErrorCode.WITH_AUTO_REFRESH_USED_IN_MANUAL_QUERY */, `"withAutoRefresh()" has been used inside a query that has "onlyManualExecution" set to true.` +
2822
2854
  ` If this is intentional, set "ignoreOnlyManualExecution" to true inside the auto refresh config.`);
2823
2855
  };
2824
2856
  const cookieLoginTriedButCookieDisabled = () => {
2825
- return new RuntimeError(200 /* RuntimeErrorCode.COOKIE_LOGIN_TRIED_BUT_COOKIE_DISABLED */, `Cookie login has been tried, but the cookie is disabled.`);
2857
+ return new RuntimeError(200 /* QueryRuntimeErrorCode.COOKIE_LOGIN_TRIED_BUT_COOKIE_DISABLED */, `Cookie login has been tried, but the cookie is disabled.`);
2826
2858
  };
2827
2859
  const enableCookieCalledWithoutCookieConfig = () => {
2828
- return new RuntimeError(201 /* RuntimeErrorCode.ENABLE_COOKIE_CALLED_WITHOUT_COOKIE_CONFIG */, `enableCookie() has been called but there is no cookie config. Please set it during the auth provider creation.`);
2860
+ return new RuntimeError(201 /* QueryRuntimeErrorCode.ENABLE_COOKIE_CALLED_WITHOUT_COOKIE_CONFIG */, `enableCookie() has been called but there is no cookie config. Please set it during the auth provider creation.`);
2829
2861
  };
2830
2862
  const disableCookieCalledWithoutCookieConfig = () => {
2831
- return new RuntimeError(202 /* RuntimeErrorCode.DISABLE_COOKIE_CALLED_WITHOUT_COOKIE_CONFIG */, `disableCookie() has been called but there is no cookie config. Please set it during the auth provider creation.`);
2863
+ return new RuntimeError(202 /* QueryRuntimeErrorCode.DISABLE_COOKIE_CALLED_WITHOUT_COOKIE_CONFIG */, `disableCookie() has been called but there is no cookie config. Please set it during the auth provider creation.`);
2832
2864
  };
2833
2865
  const loginCalledWithoutConfig = () => {
2834
- return new RuntimeError(203 /* RuntimeErrorCode.LOGIN_CALLED_WITHOUT_CONFIG */, `login() has been called without a config. Please set it during the auth provider creation.`);
2866
+ return new RuntimeError(203 /* QueryRuntimeErrorCode.LOGIN_CALLED_WITHOUT_CONFIG */, `login() has been called without a config. Please set it during the auth provider creation.`);
2835
2867
  };
2836
2868
  const loginWithTokenCalledWithoutConfig = () => {
2837
- return new RuntimeError(204 /* RuntimeErrorCode.LOGIN_WITH_TOKEN_CALLED_WITHOUT_CONFIG */, `loginWithToken() has been called without a config. Please set it during the auth provider creation.`);
2869
+ return new RuntimeError(204 /* QueryRuntimeErrorCode.LOGIN_WITH_TOKEN_CALLED_WITHOUT_CONFIG */, `loginWithToken() has been called without a config. Please set it during the auth provider creation.`);
2838
2870
  };
2839
2871
  const refreshTokenCalledWithoutConfig = () => {
2840
- return new RuntimeError(205 /* RuntimeErrorCode.REFRESH_TOKEN_CALLED_WITHOUT_CONFIG */, `refreshToken() has been called without a config. Please set it during the auth provider creation.`);
2872
+ return new RuntimeError(205 /* QueryRuntimeErrorCode.REFRESH_TOKEN_CALLED_WITHOUT_CONFIG */, `refreshToken() has been called without a config. Please set it during the auth provider creation.`);
2841
2873
  };
2842
2874
  const selectRoleCalledWithoutConfig = () => {
2843
- return new RuntimeError(206 /* RuntimeErrorCode.SELECT_ROLE_CALLED_WITHOUT_CONFIG */, `selectRole() has been called without a config. Please set it during the auth provider creation.`);
2875
+ return new RuntimeError(206 /* QueryRuntimeErrorCode.SELECT_ROLE_CALLED_WITHOUT_CONFIG */, `selectRole() has been called without a config. Please set it during the auth provider creation.`);
2844
2876
  };
2845
2877
  const defaultResponseTransformerResponseNotObject = (currentType) => {
2846
- return new RuntimeError(207 /* RuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_OBJECT */, `The default response transformer expects the response to be an object, but it is a "${currentType}".`);
2878
+ return new RuntimeError(207 /* QueryRuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_OBJECT */, `The default response transformer expects the response to be an object, but it is a "${currentType}".`);
2847
2879
  };
2848
2880
  const defaultResponseTransformerResponseNotContainingAccessToken = () => {
2849
- return new RuntimeError(208 /* RuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_CONTAINING_ACCESS_TOKEN */, `The default response transformer expects the response to contain an "accessToken" property.`);
2881
+ return new RuntimeError(208 /* QueryRuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_CONTAINING_ACCESS_TOKEN */, `The default response transformer expects the response to contain an "accessToken" property.`);
2850
2882
  };
2851
2883
  const defaultResponseTransformerResponseNotContainingRefreshToken = () => {
2852
- return new RuntimeError(209 /* RuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_CONTAINING_REFRESH_TOKEN */, `The default response transformer expects the response to contain a "refreshToken" property.`);
2884
+ return new RuntimeError(209 /* QueryRuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_CONTAINING_REFRESH_TOKEN */, `The default response transformer expects the response to contain a "refreshToken" property.`);
2853
2885
  };
2854
2886
  const unableToDecryptBearerToken = (token) => {
2855
- return new RuntimeError(210 /* RuntimeErrorCode.UNABLE_TO_DECRYPT_BEARER_TOKEN */, `The bearer token could not be decrypted: ${token}`);
2887
+ return new RuntimeError(210 /* QueryRuntimeErrorCode.UNABLE_TO_DECRYPT_BEARER_TOKEN */, `The bearer token could not be decrypted: ${token}`);
2856
2888
  };
2857
2889
  const bearerExpiresInPropertyNotNumber = (expiresIn) => {
2858
- return new RuntimeError(211 /* RuntimeErrorCode.BEARER_EXPIRES_IN_PROPERTY_NOT_NUMBER */, `The expires in property is not a number: ${expiresIn}`);
2890
+ return new RuntimeError(211 /* QueryRuntimeErrorCode.BEARER_EXPIRES_IN_PROPERTY_NOT_NUMBER */, `The expires in property is not a number: ${expiresIn}`);
2859
2891
  };
2860
2892
  const uncacheableRequestHasCacheKeyParam = (key) => {
2861
- return new RuntimeError(300 /* RuntimeErrorCode.UNCACHEABLE_REQUEST_HAS_CACHE_KEY_PARAM */, `This request is uncacheable, but a cache key was provided: ${key}. Please remove it.`);
2893
+ return new RuntimeError(300 /* QueryRuntimeErrorCode.UNCACHEABLE_REQUEST_HAS_CACHE_KEY_PARAM */, `This request is uncacheable, but a cache key was provided: ${key}. Please remove it.`);
2862
2894
  };
2863
- const uncacheableRequestHasSkipCacheParam = () => {
2864
- return new RuntimeError(301 /* RuntimeErrorCode.UNCACHEABLE_REQUEST_HAS_SKIP_CACHE_PARAM */, `This request is uncacheable, but skipCache is set to true. Please remove it.`);
2895
+ const uncacheableRequestHasAllowCacheParam = () => {
2896
+ return new RuntimeError(301 /* QueryRuntimeErrorCode.UNCACHEABLE_REQUEST_HAS_ALLOW_CACHE_PARAM */, `This request is uncacheable, but allowCache is set to true. Please remove it.`);
2865
2897
  };
2866
- const pagedQueryPageBiggerThanTotalPages = (page, totalPages) => {
2867
- return new RuntimeError(400 /* RuntimeErrorCode.PAGED_QUERY_PAGE_BIGGER_THAN_TOTAL_PAGES */, `The page "${page}" is bigger than the total pages "${totalPages}".`);
2898
+ const pagedQueryStackPageBiggerThanTotalPages = (page, totalPages) => {
2899
+ return new RuntimeError(400 /* QueryRuntimeErrorCode.PAGED_QUERY_STACK_PAGE_BIGGER_THAN_TOTAL_PAGES */, `The page "${page}" is bigger than the total pages "${totalPages}".`);
2868
2900
  };
2869
- const pagedQueryNextPageCalledWithoutPreviousPage = () => {
2870
- return new RuntimeError(401 /* RuntimeErrorCode.PAGED_QUERY_NEXT_PAGE_CALLED_WITHOUT_PREVIOUS_PAGE */, `fetchNextPage() has been called but the current page is not yet loaded. Please call it after the previous page has been loaded.`);
2901
+ const pagedQueryStackNextPageCalledWithoutPreviousPage = () => {
2902
+ return new RuntimeError(401 /* QueryRuntimeErrorCode.PAGED_QUERY_STACK_NEXT_PAGE_CALLED_WITHOUT_PREVIOUS_PAGE */, `fetchNextPage() has been called but the current page is not yet loaded. Please call it after the previous page has been loaded.`);
2871
2903
  };
2872
- const pagedQueryPreviousPageCalledButAlreadyAtFirstPage = () => {
2873
- return new RuntimeError(402 /* RuntimeErrorCode.PAGED_QUERY_PREVIOUS_PAGE_CALLED_BUT_ALREADY_AT_FIRST_PAGE */, `fetchPreviousPage() has been called but the current page is already the first page.`);
2904
+ const pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage = () => {
2905
+ return new RuntimeError(402 /* QueryRuntimeErrorCode.PAGED_QUERY_STACK_PREVIOUS_PAGE_CALLED_BUT_ALREADY_AT_FIRST_PAGE */, `fetchPreviousPage() has been called but the current page is already the first page.`);
2906
+ };
2907
+ const queryStackWithArgsUsed = () => {
2908
+ return new RuntimeError(500 /* QueryRuntimeErrorCode.QUERY_STACK_WITH_ARGS_USED */, `withArgs() has been used in a query stack or a paged query stack. This is not supported.`);
2874
2909
  };
2875
2910
 
2876
2911
  const defaultResponseTransformer = (response) => {
@@ -3034,10 +3069,10 @@ const createBearerAuthProvider = (options) => {
3034
3069
  };
3035
3070
  const logout = () => {
3036
3071
  deleteCookie$1();
3037
- loginQuery?.query.execute.reset();
3038
- tokenLoginQuery?.query.execute.reset();
3039
- tokenRefreshQuery?.query.execute.reset();
3040
- selectRoleQuery?.query.execute.reset();
3072
+ loginQuery?.query.reset();
3073
+ tokenLoginQuery?.query.reset();
3074
+ tokenRefreshQuery?.query.reset();
3075
+ selectRoleQuery?.query.reset();
3041
3076
  latestNonInternalQuery.set(null);
3042
3077
  };
3043
3078
  const enableCookie = () => {
@@ -3129,29 +3164,81 @@ const createBearerAuthProviderConfig = (options) => {
3129
3164
  return bearerAuthProviderConfig;
3130
3165
  };
3131
3166
 
3167
+ const setupQueryState = (options) => {
3168
+ const response = signal(null);
3169
+ const args = signal(null);
3170
+ const latestHttpEvent = signal(null);
3171
+ const error = signal(null);
3172
+ const loading = signal(null);
3173
+ const lastTimeExecutedAt = signal(null);
3174
+ const state = {
3175
+ response,
3176
+ args,
3177
+ latestHttpEvent,
3178
+ loading,
3179
+ error,
3180
+ lastTimeExecutedAt,
3181
+ };
3182
+ return state;
3183
+ };
3184
+
3185
+ const createQuerySnapshotFn = (options) => {
3186
+ const { state, deps } = options;
3187
+ const snapshotFn = () => {
3188
+ const snapshotState = setupQueryState({});
3189
+ const isAlive = signal(true);
3190
+ const killEffectRef = effect(() => {
3191
+ const currentLoading = state.loading();
3192
+ const currentError = state.error();
3193
+ const currentResponse = state.response();
3194
+ const currentArgs = state.args();
3195
+ const currentLatestHttpEvent = state.latestHttpEvent();
3196
+ const currentLastTimeExecutedAt = state.lastTimeExecutedAt();
3197
+ untracked(() => {
3198
+ snapshotState.args.set(currentArgs);
3199
+ snapshotState.error.set(currentError);
3200
+ snapshotState.lastTimeExecutedAt.set(currentLastTimeExecutedAt);
3201
+ snapshotState.latestHttpEvent.set(currentLatestHttpEvent);
3202
+ snapshotState.loading.set(currentLoading);
3203
+ snapshotState.response.set(currentResponse);
3204
+ if (currentLoading)
3205
+ return;
3206
+ if (!currentResponse && !currentError)
3207
+ return;
3208
+ // kill the effect once loading is done and we either have a response or an error
3209
+ killEffectRef.destroy();
3210
+ isAlive.set(false);
3211
+ });
3212
+ }, { injector: deps.injector });
3213
+ const snapshot = {
3214
+ args: snapshotState.args.asReadonly(),
3215
+ response: snapshotState.response.asReadonly(),
3216
+ latestHttpEvent: snapshotState.latestHttpEvent.asReadonly(),
3217
+ loading: snapshotState.loading.asReadonly(),
3218
+ error: snapshotState.error.asReadonly(),
3219
+ lastTimeExecutedAt: snapshotState.lastTimeExecutedAt.asReadonly(),
3220
+ isAlive: isAlive.asReadonly(),
3221
+ id: normalizeQueryRepositoryKey(options.execute.currentRepositoryKey),
3222
+ };
3223
+ return snapshot;
3224
+ };
3225
+ return snapshotFn;
3226
+ };
3227
+
3132
3228
  /**
3133
- * Returning this inside e.g. a withComputedArgs feature will reset the query args to null.
3229
+ * Returning this inside a withArgs feature will reset the query args to null.
3134
3230
  * This will also pause polling and auto refresh until new args are set.
3135
3231
  */
3136
- const QUERY_ARGS_RESET = Symbol('QUERY_ARGS_RESET');
3232
+ const CLEAR_QUERY_ARGS = Symbol('CLEAR_QUERY_ARGS');
3137
3233
  const QUERY_EFFECT_ERROR_MESSAGE = 'Effect triggered too often. This is probably due to a circular dependency inside the query.';
3138
3234
  /** A angular effect that will throw an error in dev mode if it is called too often. This indicates a circular dependency inside the effect. */
3139
3235
  const queryEffect = (fn, errorMessage, options) => {
3140
3236
  let lastTriggerTs = 0;
3141
3237
  let illegalWrites = 0;
3142
- // The first run should be synchronous anf not depend on the angular scheduler
3143
- if (options?.injector) {
3144
- runInInjectionContext(options.injector, () => fn());
3145
- }
3146
- else {
3147
- fn();
3148
- }
3149
3238
  let isFirstRun = true;
3150
- return untracked(() => effect(() => {
3151
- if (isFirstRun) {
3152
- isFirstRun = false;
3153
- return;
3154
- }
3239
+ const activeConsumer = getActiveConsumer();
3240
+ setActiveConsumer(null);
3241
+ const eff = effect(() => {
3155
3242
  if (isDevMode()) {
3156
3243
  const now = performance.now();
3157
3244
  if (now - lastTriggerTs < 100) {
@@ -3162,12 +3249,20 @@ const queryEffect = (fn, errorMessage, options) => {
3162
3249
  }
3163
3250
  lastTriggerTs = now;
3164
3251
  }
3165
- fn();
3166
- }, options));
3252
+ fn(isFirstRun);
3253
+ if (isFirstRun) {
3254
+ isFirstRun = false;
3255
+ }
3256
+ }, options);
3257
+ setActiveConsumer(activeConsumer);
3258
+ return eff;
3167
3259
  };
3168
3260
  const shouldAutoExecuteQuery = (method) => {
3169
3261
  return method === 'GET' || method === 'HEAD' || method === 'OPTIONS';
3170
3262
  };
3263
+ const shouldAutoExecuteGqlQuery = (method) => {
3264
+ return method === 'QUERY';
3265
+ };
3171
3266
  const extractExpiresInSeconds = (headers) => {
3172
3267
  const cacheControl = headers.get('cache-control');
3173
3268
  const age = headers.get('age');
@@ -3214,7 +3309,8 @@ const extractExpiresInSeconds = (headers) => {
3214
3309
  return expiresIn;
3215
3310
  };
3216
3311
  const shouldRetryRequest = (options) => {
3217
- const { retryCount, error } = options;
3312
+ const normalizedOptions = options instanceof HttpErrorResponse ? { retryCount: 0, error: options } : options;
3313
+ const { retryCount, error } = normalizedOptions;
3218
3314
  const defaultRetryDelay = 1000 + 1000 * retryCount;
3219
3315
  if (retryCount > 3) {
3220
3316
  return { retry: false };
@@ -3223,8 +3319,8 @@ const shouldRetryRequest = (options) => {
3223
3319
  return { retry: false };
3224
3320
  }
3225
3321
  const { status, error: detail, headers } = error;
3226
- // Retry on 5xx errors
3227
- if (status >= 500) {
3322
+ // Retry on 5xx errors (except 500 internal server error since those are usually not recoverable)
3323
+ if (status >= 501) {
3228
3324
  // Don't retry if a requested page is out of range
3229
3325
  if (isSymfonyPagerfantaOutOfRangeError(detail)) {
3230
3326
  return { retry: false };
@@ -3252,9 +3348,11 @@ const shouldRetryRequest = (options) => {
3252
3348
  return { retry: false };
3253
3349
  };
3254
3350
  const getQueryFeatureUsage = (options) => {
3255
- const { creator, creatorInternals, features, queryConfig } = options;
3351
+ const { creator, features, queryConfig } = options;
3256
3352
  const hasWithArgsFeature = features.some((f) => f.type == "withArgs" /* QueryFeatureType.WithArgs */);
3257
- const shouldAutoExecuteMethod = shouldAutoExecuteQuery(creatorInternals.method);
3353
+ const shouldAutoExecuteMethod = isCreateGqlQueryOptions(options)
3354
+ ? shouldAutoExecuteGqlQuery(options.creatorInternals.method)
3355
+ : shouldAutoExecuteQuery(options.creatorInternals.method);
3258
3356
  const shouldAutoExecute = shouldAutoExecuteMethod && !queryConfig.onlyManualExecution;
3259
3357
  const hasRouteFunction = typeof creator.route === 'function';
3260
3358
  if (hasRouteFunction && !hasWithArgsFeature) {
@@ -3265,12 +3363,16 @@ const getQueryFeatureUsage = (options) => {
3265
3363
  shouldAutoExecuteMethod,
3266
3364
  shouldAutoExecute,
3267
3365
  hasRouteFunction,
3366
+ onlyManualExecution: queryConfig.onlyManualExecution,
3367
+ method: isCreateGqlQueryOptions(options)
3368
+ ? `GQL ${options.creatorInternals.method}`
3369
+ : options.creatorInternals.method,
3268
3370
  };
3269
3371
  return featureFnContext;
3270
3372
  };
3271
- const applyQueryFeatures = (options, context) => {
3373
+ const applyQueryFeatures = (features, context) => {
3272
3374
  const featureTypes = new Set();
3273
- for (const feature of options.features) {
3375
+ for (const feature of features) {
3274
3376
  if (featureTypes.has(feature.type)) {
3275
3377
  throw queryFeatureUsedMultipleTimes(feature.type);
3276
3378
  }
@@ -3278,13 +3380,16 @@ const applyQueryFeatures = (options, context) => {
3278
3380
  feature.fn(context);
3279
3381
  }
3280
3382
  };
3383
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3281
3384
  const maybeExecute = (options) => {
3282
3385
  if (options.flags.shouldAutoExecute && !options.flags.hasRouteFunction && !options.flags.hasWithArgsFeature) {
3283
3386
  options.execute();
3284
3387
  }
3285
3388
  };
3286
3389
  const createQueryObject = (options) => {
3287
- const { state, execute, createSnapshot, destroy } = options;
3390
+ const { state, execute, deps } = options;
3391
+ const destroy = () => deps.injector.destroy();
3392
+ const createSnapshot = createQuerySnapshotFn({ state, deps, execute });
3288
3393
  const query = {
3289
3394
  execute,
3290
3395
  args: state.args.asReadonly(),
@@ -3293,12 +3398,44 @@ const createQueryObject = (options) => {
3293
3398
  loading: state.loading.asReadonly(),
3294
3399
  error: state.error.asReadonly(),
3295
3400
  lastTimeExecutedAt: state.lastTimeExecutedAt.asReadonly(),
3296
- id: execute.currentRepositoryKey,
3401
+ id: normalizeQueryRepositoryKey(execute.currentRepositoryKey),
3297
3402
  createSnapshot,
3298
- destroy,
3403
+ reset: execute.reset,
3404
+ subtle: {
3405
+ destroy,
3406
+ },
3299
3407
  };
3300
3408
  return query;
3301
3409
  };
3410
+ const normalizeQueryRepositoryKey = (key) => computed(() => {
3411
+ const k = key();
3412
+ if (k === false) {
3413
+ // false means the query cannot be cached and thus it is not stored in the repository
3414
+ // We generate a random id in this case to avoid confusion
3415
+ return crypto.randomUUID();
3416
+ }
3417
+ return k;
3418
+ });
3419
+ const shouldCacheQuery = (method) => {
3420
+ return method === 'GET' || method === 'OPTIONS' || method === 'HEAD';
3421
+ };
3422
+ const buildQueryCacheKey = (route, args) => {
3423
+ // We need to hash the body in case it's a gql query and the query get's transported in the body
3424
+ const body = JSON.stringify(args?.body || {})
3425
+ // replace all curly braces with empty string
3426
+ .replace(/{|}/g, '')
3427
+ // replace new lines and whitespaces with empty string
3428
+ .replace(/\s/g, '');
3429
+ const seed = `${route}_${body}`;
3430
+ let hash = 0;
3431
+ for (const char of seed) {
3432
+ hash = (Math.imul(31, hash) + char.charCodeAt(0)) << 0;
3433
+ }
3434
+ // Force positive number hash.
3435
+ // 2147483647 = equivalent of Integer.MAX_VALUE.
3436
+ hash += 2147483647 + 1;
3437
+ return hash.toString();
3438
+ };
3302
3439
 
3303
3440
  const SPEED_BUFFER_TIME_IN_MS = 2000;
3304
3441
  const createHttpRequest = (options) => {
@@ -3341,8 +3478,8 @@ const createHttpRequest = (options) => {
3341
3478
  return throwError(() => e);
3342
3479
  }));
3343
3480
  const execute = (options) => {
3344
- if (loading() || (!isStale() && !options?.skipCache)) {
3345
- // Do not execute if there is already a request in progress or the request is not stale
3481
+ if (loading() || (!isStale() && options?.allowCache)) {
3482
+ // Do not execute if there is already a request in progress or caching is allowed
3346
3483
  return false;
3347
3484
  }
3348
3485
  currentStreamSubscription.unsubscribe();
@@ -3451,6 +3588,15 @@ const createHttpRequest = (options) => {
3451
3588
  const createQueryFeature = (config) => {
3452
3589
  return config;
3453
3590
  };
3591
+ /**
3592
+ * A query feature that allows you to set the arguments of the query.
3593
+ * The arguments are read within a computed function, so you can use reactive values.
3594
+ *
3595
+ * To set the arguments to `null`, return the symbol `CLEAR_QUERY_ARGS`.
3596
+ * If you instead return `null`, the arguments won't change.
3597
+ *
3598
+ * Changing arguments will automatically trigger a new execution of the query if it is eligible for auto execution (e.g. a GET request).
3599
+ */
3454
3600
  const withArgs = (args) => {
3455
3601
  return createQueryFeature({
3456
3602
  type: "withArgs" /* QueryFeatureType.WithArgs */,
@@ -3461,7 +3607,7 @@ const withArgs = (args) => {
3461
3607
  if (currArgsNow === null)
3462
3608
  return;
3463
3609
  untracked(() => {
3464
- if (currArgsNow === QUERY_ARGS_RESET) {
3610
+ if (currArgsNow === CLEAR_QUERY_ARGS) {
3465
3611
  context.state.args.set(null);
3466
3612
  return;
3467
3613
  }
@@ -3473,12 +3619,19 @@ const withArgs = (args) => {
3473
3619
  },
3474
3620
  });
3475
3621
  };
3622
+ /**
3623
+ * A query feature that will automatically execute the query at a given interval.
3624
+ * The interval will be cleared when the query is destroyed.
3625
+ * The interval will be reset when the arguments of the query change.
3626
+ *
3627
+ * @throws If the query is not eligible for auto execution (e.g. a POST request)
3628
+ */
3476
3629
  const withPolling = (options) => {
3477
3630
  return createQueryFeature({
3478
3631
  type: "withPolling" /* QueryFeatureType.WithPolling */,
3479
3632
  fn: (context) => {
3480
3633
  if (!context.flags.shouldAutoExecuteMethod) {
3481
- throw withPollingUsedOnUnsupportedHttpMethod(context.creatorInternals.method);
3634
+ throw withPollingUsedOnUnsupportedHttpMethod(context.flags.method);
3482
3635
  }
3483
3636
  let intervalId = null;
3484
3637
  queryEffect(() => {
@@ -3486,7 +3639,9 @@ const withPolling = (options) => {
3486
3639
  untracked(() => {
3487
3640
  if (intervalId !== null)
3488
3641
  clearInterval(intervalId);
3489
- if (args === null)
3642
+ // Don't start polling if the query doesn't have args.
3643
+ // It should have args because a withArgs feature is present.
3644
+ if (args === null && context.flags.hasWithArgsFeature)
3490
3645
  return;
3491
3646
  if (options.executeInitially) {
3492
3647
  context.execute({ args });
@@ -3500,68 +3655,78 @@ const withPolling = (options) => {
3500
3655
  },
3501
3656
  });
3502
3657
  };
3658
+ /** A query feature that can be used to log the latest http event */
3503
3659
  const withLogging = (options) => {
3504
3660
  return createQueryFeature({
3505
3661
  type: "withLogging" /* QueryFeatureType.WithLogging */,
3506
3662
  fn: (context) => {
3507
- effect(() => {
3663
+ queryEffect(() => {
3508
3664
  const event = context.state.latestHttpEvent();
3509
3665
  if (event === null)
3510
3666
  return;
3511
3667
  untracked(() => {
3512
3668
  options.logFn(event);
3513
3669
  });
3514
- }, { injector: context.deps.injector });
3670
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3515
3671
  },
3516
3672
  });
3517
3673
  };
3674
+ /** A query feature that can be used to handle errors */
3518
3675
  const withErrorHandling = (options) => {
3519
3676
  return createQueryFeature({
3520
3677
  type: "withErrorHandling" /* QueryFeatureType.WithErrorHandling */,
3521
3678
  fn: (context) => {
3522
- effect(() => {
3679
+ queryEffect(() => {
3523
3680
  const error = context.state.error();
3524
3681
  if (error === null)
3525
3682
  return;
3526
3683
  untracked(() => {
3527
3684
  options.handler(error);
3528
3685
  });
3529
- }, { injector: context.deps.injector });
3686
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3530
3687
  },
3531
3688
  });
3532
3689
  };
3690
+ /** A query feature that can be used to handle successful responses */
3533
3691
  const withSuccessHandling = (options) => {
3534
3692
  return createQueryFeature({
3535
3693
  type: "withSuccessHandling" /* QueryFeatureType.WithSuccessHandling */,
3536
3694
  fn: (context) => {
3537
- effect(() => {
3695
+ queryEffect(() => {
3538
3696
  const response = context.state.response();
3539
3697
  if (response === null)
3540
3698
  return;
3541
3699
  untracked(() => {
3542
3700
  options.handler(response);
3543
3701
  });
3544
- }, { injector: context.deps.injector });
3702
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3545
3703
  },
3546
3704
  });
3547
3705
  };
3706
+ /**
3707
+ * A query feature that will automatically execute the query when any of the provided signals change
3708
+ * @throws If the query is not eligible for auto execution (e.g. a POST request)
3709
+ * @throws If the query has the `onlyManualExecution` query config flag set and `ignoreOnlyManualExecution` is not set
3710
+ */
3548
3711
  const withAutoRefresh = (options) => {
3549
3712
  return createQueryFeature({
3550
3713
  type: "withAutoRefresh" /* QueryFeatureType.WithAutoRefresh */,
3551
3714
  fn: (context) => {
3552
3715
  if (!context.flags.shouldAutoExecuteMethod) {
3553
- throw withAutoRefreshUsedOnUnsupportedHttpMethod(context.creatorInternals.method);
3716
+ throw withAutoRefreshUsedOnUnsupportedHttpMethod(context.flags.method);
3554
3717
  }
3555
- if (context.queryConfig.onlyManualExecution && !options.ignoreOnlyManualExecution) {
3556
- throw withAutoRefreshUsedOnUnsupportedHttpMethod(context.creatorInternals.method);
3718
+ if (context.flags.onlyManualExecution && !options.ignoreOnlyManualExecution) {
3719
+ throw withAutoRefreshUsedInManualQuery();
3557
3720
  }
3558
3721
  queryEffect(() => {
3559
- for (const signal of options.signalChanges) {
3722
+ for (const signal of options.onSignalChanges) {
3560
3723
  signal();
3561
3724
  }
3562
3725
  untracked(() => {
3563
3726
  const args = context.state.args();
3564
- if (args === null)
3727
+ // Don't start polling if the query doesn't have args.
3728
+ // It should have args because a withArgs feature is present.
3729
+ if (args === null && context.flags.hasWithArgsFeature)
3565
3730
  return;
3566
3731
  context.execute({ args });
3567
3732
  });
@@ -3570,10 +3735,12 @@ const withAutoRefresh = (options) => {
3570
3735
  });
3571
3736
  };
3572
3737
 
3738
+ /** Transforms an array of arrays into a single array and filters out `null` values. */
3573
3739
  const transformArrayResponse = (responses) => responses.filter((r) => !!r).flatMap((r) => r);
3740
+ /** Transforms an array of paginated responses into a single array and filters out `null` values. */
3574
3741
  const transformPaginatedResponse = (responses) => responses.filter((r) => !!r).flatMap((r) => r.items);
3575
- const createQueryStack = (computation, options) => {
3576
- const { append = false, appendFn = (oldQueries, newQueries) => {
3742
+ const createQueryStack = (options) => {
3743
+ const { args, queryCreator, dependencies, append, features = [], appendFn = (oldQueries, newQueries) => {
3577
3744
  const queries = [...oldQueries, ...newQueries];
3578
3745
  const lastQuery = newQueries[newQueries.length - 1] ?? oldQueries[oldQueries.length - 1] ?? null;
3579
3746
  return { queries, lastQuery };
@@ -3581,9 +3748,21 @@ const createQueryStack = (computation, options) => {
3581
3748
  const injector = inject(Injector);
3582
3749
  const queries = signal([]);
3583
3750
  const lastQuery = signal(null);
3751
+ const hasWithArgsFeature = features.some((f) => f.type == "withArgs" /* QueryFeatureType.WithArgs */);
3752
+ if (hasWithArgsFeature) {
3753
+ throw queryStackWithArgsUsed();
3754
+ }
3755
+ effect(() => {
3756
+ // Clear the stack if dependencies change
3757
+ dependencies?.();
3758
+ untracked(() => clear());
3759
+ });
3584
3760
  effect(() => {
3585
- const newQueryOrQueries = runInInjectionContext(injector, () => computation());
3586
- const newQueries = Array.isArray(newQueryOrQueries) ? newQueryOrQueries : [newQueryOrQueries].filter((q) => !!q);
3761
+ const newArgs = args(dependencies?.());
3762
+ if (newArgs === null)
3763
+ return;
3764
+ const newArgsArray = Array.isArray(newArgs) ? newArgs : [newArgs];
3765
+ const newQueries = runInInjectionContext(injector, () => newArgsArray.map((newArgsEntry) => queryCreator(withArgs(() => newArgsEntry), ...features)));
3587
3766
  untracked(() => {
3588
3767
  const oldQueries = queries();
3589
3768
  if (append) {
@@ -3594,7 +3773,7 @@ const createQueryStack = (computation, options) => {
3594
3773
  else {
3595
3774
  for (const oldQuery of oldQueries) {
3596
3775
  if (!newQueries.some((q) => q.id() === oldQuery.id())) {
3597
- oldQuery.destroy();
3776
+ oldQuery.subtle.destroy();
3598
3777
  }
3599
3778
  }
3600
3779
  queries.set(newQueries);
@@ -3612,12 +3791,12 @@ const createQueryStack = (computation, options) => {
3612
3791
  });
3613
3792
  const execute = (options) => {
3614
3793
  for (const query of queries()) {
3615
- query.execute({ options: { skipCache: options?.skipCache } });
3794
+ query.execute({ options: { allowCache: options?.allowCache } });
3616
3795
  }
3617
3796
  };
3618
3797
  const clear = () => {
3619
3798
  for (const query of queries()) {
3620
- query.destroy();
3799
+ query.subtle.destroy();
3621
3800
  }
3622
3801
  queries.set([]);
3623
3802
  lastQuery.set(null);
@@ -3676,23 +3855,31 @@ const contentfulGqlLikePaginationAdapter = (response) => {
3676
3855
  };
3677
3856
  return pagination;
3678
3857
  };
3679
- const createPagedQuery = (options) => {
3680
- const { responseNormalizer, queryCreator } = options;
3858
+ const fakePaginationAdapter = (totalHits = 10) => {
3859
+ return (response) => {
3860
+ const pagination = {
3861
+ items: [response],
3862
+ totalPages: totalHits,
3863
+ currentPage: 1,
3864
+ itemsPerPage: 1,
3865
+ totalHits,
3866
+ };
3867
+ return pagination;
3868
+ };
3869
+ };
3870
+ const createPagedQueryStack = (options) => {
3871
+ const { responseNormalizer, queryCreator, features } = options;
3681
3872
  const currentPageArgs = signal(null);
3682
3873
  const initialPage = signal(options.initialPage ?? 1);
3683
3874
  const loadedMinPage = signal(initialPage());
3684
3875
  const loadedMaxPage = signal(initialPage());
3685
3876
  const lastResetTimestamp = signal(Date.now());
3686
3877
  const pageDirection = signal('next');
3687
- const stack = createQueryStack(() => {
3688
- const args = currentPageArgs();
3689
- if (!args)
3690
- return null;
3691
- return queryCreator(withArgs(() => {
3692
- return args;
3693
- }));
3694
- }, {
3878
+ const stack = createQueryStack({
3879
+ args: () => currentPageArgs(),
3880
+ queryCreator,
3695
3881
  append: true,
3882
+ features,
3696
3883
  appendFn: (oldQueries, newQueries) => {
3697
3884
  const newQuery = newQueries[0];
3698
3885
  const dir = pageDirection();
@@ -3729,7 +3916,7 @@ const createPagedQuery = (options) => {
3729
3916
  const page = loadedMinPage() - 1;
3730
3917
  if (page < 1) {
3731
3918
  if (isDevMode()) {
3732
- throw pagedQueryPreviousPageCalledButAlreadyAtFirstPage();
3919
+ throw pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage();
3733
3920
  }
3734
3921
  return;
3735
3922
  }
@@ -3742,13 +3929,13 @@ const createPagedQuery = (options) => {
3742
3929
  const currentPagination = pagination();
3743
3930
  if (!currentPagination) {
3744
3931
  if (isDevMode()) {
3745
- throw pagedQueryNextPageCalledWithoutPreviousPage();
3932
+ throw pagedQueryStackNextPageCalledWithoutPreviousPage();
3746
3933
  }
3747
3934
  return;
3748
3935
  }
3749
3936
  if (page > currentPagination.totalPages) {
3750
3937
  if (isDevMode()) {
3751
- throw pagedQueryPageBiggerThanTotalPages(page, currentPagination.totalPages);
3938
+ throw pagedQueryStackPageBiggerThanTotalPages(page, currentPagination.totalPages);
3752
3939
  }
3753
3940
  return;
3754
3941
  }
@@ -3762,7 +3949,12 @@ const createPagedQuery = (options) => {
3762
3949
  pageDirection.set('next');
3763
3950
  lastResetTimestamp.set(Date.now());
3764
3951
  };
3765
- const canFetchPreviousPage = computed(() => loadedMinPage() > 1);
3952
+ const canFetchPreviousPage = computed(() => {
3953
+ const currentPagination = pagination();
3954
+ if (!currentPagination)
3955
+ return false;
3956
+ return loadedMinPage() > 1;
3957
+ });
3766
3958
  const canFetchNextPage = computed(() => {
3767
3959
  const currentPagination = pagination();
3768
3960
  return currentPagination ? loadedMaxPage() < currentPagination.totalPages : false;
@@ -3777,32 +3969,41 @@ const createPagedQuery = (options) => {
3777
3969
  return stack.queries().length === 1 && !!stack.lastQuery()?.loading();
3778
3970
  });
3779
3971
  const execute = (options) => {
3780
- if (options?.where) {
3781
- const queriesToExecute = [];
3972
+ const whereFn = options?.where;
3973
+ if (whereFn) {
3974
+ const queriesToExecute = new Set();
3782
3975
  for (const [index, query] of stack.queries().entries()) {
3783
- // TODO: Use the where condition here.
3784
- if (query.response()) {
3785
- queriesToExecute.push(query);
3786
- if (index !== 0) {
3787
- const prevQuery = stack.queries()[index - 1];
3788
- if (prevQuery) {
3789
- queriesToExecute.push(prevQuery);
3976
+ const res = query.response();
3977
+ const err = query.error();
3978
+ const isErroredAndCanBeRetried = err && shouldRetryRequest(err);
3979
+ if (isErroredAndCanBeRetried) {
3980
+ queriesToExecute.add(query);
3981
+ }
3982
+ else if (res) {
3983
+ if (responseNormalizer(res).items.some((item, i, a) => whereFn(item, i, a))) {
3984
+ queriesToExecute.add(query);
3985
+ // Also execute the previous and next query to the one that matched the condition.
3986
+ if (index !== 0) {
3987
+ const prevQuery = stack.queries()[index - 1];
3988
+ if (prevQuery) {
3989
+ queriesToExecute.add(prevQuery);
3990
+ }
3790
3991
  }
3791
- }
3792
- if (index !== stack.queries().length - 1) {
3793
- const nextQuery = stack.queries()[index + 1];
3794
- if (nextQuery) {
3795
- queriesToExecute.push(nextQuery);
3992
+ if (index !== stack.queries().length - 1) {
3993
+ const nextQuery = stack.queries()[index + 1];
3994
+ if (nextQuery) {
3995
+ queriesToExecute.add(nextQuery);
3996
+ }
3796
3997
  }
3797
3998
  }
3798
3999
  }
3799
4000
  }
3800
4001
  for (const query of queriesToExecute) {
3801
- query.execute({ options: { skipCache: options.skipCache } });
4002
+ query.execute({ options: { allowCache: options.allowCache } });
3802
4003
  }
3803
4004
  }
3804
4005
  else {
3805
- stack.execute({ skipCache: options?.skipCache });
4006
+ stack.execute({ allowCache: options?.allowCache });
3806
4007
  }
3807
4008
  };
3808
4009
  const pagedQuery = {
@@ -3817,7 +4018,7 @@ const createPagedQuery = (options) => {
3817
4018
  error: stack.error,
3818
4019
  lastQuery: stack.lastQuery,
3819
4020
  isFirstLoad,
3820
- queries: stack.queries(),
4021
+ queries: stack.queries,
3821
4022
  reset,
3822
4023
  execute,
3823
4024
  };
@@ -3828,12 +4029,32 @@ const setupQueryDependencies = (options) => {
3828
4029
  const environmentInjector = inject(EnvironmentInjector);
3829
4030
  const queryEnvironmentInjector = createEnvironmentInjector([], environmentInjector);
3830
4031
  const destroyRef = queryEnvironmentInjector.get(DestroyRef);
4032
+ const scopeDestroyRef = inject(DestroyRef);
3831
4033
  const client = inject(options.clientConfig.token);
3832
4034
  const dependencies = {
3833
4035
  destroyRef,
4036
+ scopeDestroyRef,
3834
4037
  client,
3835
4038
  injector: queryEnvironmentInjector,
3836
4039
  };
4040
+ // cleanup the environment injector when the scope (e.g. the component the query is in) is destroyed
4041
+ const scopeDestroyListener = scopeDestroyRef.onDestroy(() => {
4042
+ try {
4043
+ queryEnvironmentInjector.destroy();
4044
+ }
4045
+ catch {
4046
+ // ignore
4047
+ }
4048
+ });
4049
+ destroyRef.onDestroy(() => {
4050
+ // cleanup the scope destroy listener
4051
+ try {
4052
+ scopeDestroyListener();
4053
+ }
4054
+ catch {
4055
+ // ignore
4056
+ }
4057
+ });
3837
4058
  return dependencies;
3838
4059
  };
3839
4060
 
@@ -3856,7 +4077,7 @@ const setupQueryExecuteState = () => {
3856
4077
  };
3857
4078
  };
3858
4079
  const queryExecute = (options) => {
3859
- const { executeOptions, args, executeState, options: runQueryOptions } = options;
4080
+ const { executeOptions, args, executeState, options: runQueryOptions, internalOptions: internalRunQueryOptions, transformResponse, } = options;
3860
4081
  const { deps, state, creator, creatorInternals, queryConfig } = executeOptions;
3861
4082
  const { key, request } = deps.client.repository.request({
3862
4083
  route: creator.route,
@@ -3871,11 +4092,13 @@ const queryExecute = (options) => {
3871
4092
  destroyRef: deps.destroyRef,
3872
4093
  key: queryConfig.key,
3873
4094
  previousKey: executeState.previousKey(),
4095
+ internalRunQueryOptions,
3874
4096
  runQueryOptions,
3875
4097
  });
3876
4098
  executeState.previousKey.set(key);
4099
+ const responseSignal = transformResponse ? computed(() => transformResponse(request.response())) : request.response;
3877
4100
  runInInjectionContext(deps.injector, () => {
3878
- const responseRef = syncSignal(request.response, state.response);
4101
+ const responseRef = syncSignal(responseSignal, state.response);
3879
4102
  const loadingRef = syncSignal(request.loading, state.loading);
3880
4103
  const errorRef = syncSignal(request.error, state.error);
3881
4104
  const latestHttpEventRef = syncSignal(request.currentEvent, state.latestHttpEvent);
@@ -3902,88 +4125,22 @@ const createExecuteFn = (executeOptions) => {
3902
4125
  return exec;
3903
4126
  };
3904
4127
 
3905
- const setupQueryState = (options) => {
3906
- const response = signal(null);
3907
- const args = signal(null);
3908
- const latestHttpEvent = signal(null);
3909
- const error = signal(null);
3910
- const loading = signal(null);
3911
- const lastTimeExecutedAt = signal(null);
3912
- const state = {
3913
- response,
3914
- args,
3915
- latestHttpEvent,
3916
- loading,
3917
- error,
3918
- lastTimeExecutedAt,
3919
- };
3920
- return state;
3921
- };
3922
-
3923
- const createQuerySnapshotFn = (options) => {
3924
- const { state, deps } = options;
3925
- const snapshotFn = () => {
3926
- const snapshotState = setupQueryState({});
3927
- const isAlive = signal(true);
3928
- const killEffectRef = effect(() => {
3929
- const currentLoading = state.loading();
3930
- const currentError = state.error();
3931
- const currentResponse = state.response();
3932
- const currentArgs = state.args();
3933
- const currentLatestHttpEvent = state.latestHttpEvent();
3934
- const currentLastTimeExecutedAt = state.lastTimeExecutedAt();
3935
- untracked(() => {
3936
- snapshotState.args.set(currentArgs);
3937
- snapshotState.error.set(currentError);
3938
- snapshotState.lastTimeExecutedAt.set(currentLastTimeExecutedAt);
3939
- snapshotState.latestHttpEvent.set(currentLatestHttpEvent);
3940
- snapshotState.loading.set(currentLoading);
3941
- snapshotState.response.set(currentResponse);
3942
- if (currentLoading)
3943
- return;
3944
- if (!currentResponse && !currentError)
3945
- return;
3946
- // kill the effect once loading is done and we either have a response or an error
3947
- killEffectRef.destroy();
3948
- isAlive.set(false);
3949
- });
3950
- }, { injector: deps.injector });
3951
- const snapshot = {
3952
- args: snapshotState.args.asReadonly(),
3953
- response: snapshotState.response.asReadonly(),
3954
- latestHttpEvent: snapshotState.latestHttpEvent.asReadonly(),
3955
- loading: snapshotState.loading.asReadonly(),
3956
- error: snapshotState.error.asReadonly(),
3957
- lastTimeExecutedAt: snapshotState.lastTimeExecutedAt.asReadonly(),
3958
- isAlive: isAlive.asReadonly(),
3959
- id: options.execute.currentRepositoryKey,
3960
- };
3961
- return snapshot;
3962
- };
3963
- return snapshotFn;
3964
- };
3965
-
3966
4128
  /* eslint-disable @typescript-eslint/no-explicit-any */
3967
4129
  const createQuery = (options) => {
3968
4130
  const deps = setupQueryDependencies({ clientConfig: options.creatorInternals.client });
3969
4131
  const state = setupQueryState({});
3970
4132
  const { creator, creatorInternals, queryConfig } = options;
3971
4133
  const flags = getQueryFeatureUsage(options);
3972
- const execute = createExecuteFn({ deps, state, creator, creatorInternals, queryConfig: options.queryConfig });
3973
- const createSnapshot = createQuerySnapshotFn({ state, deps, execute });
3974
- const destroy = () => deps.injector.destroy();
4134
+ const execute = createExecuteFn({ deps, state, creator, creatorInternals, queryConfig });
3975
4135
  const featureFnContext = {
3976
4136
  state,
3977
- queryConfig,
3978
- creatorConfig: creator,
3979
- creatorInternals,
3980
4137
  execute,
3981
4138
  flags,
3982
4139
  deps,
3983
4140
  };
3984
- applyQueryFeatures(options, featureFnContext);
4141
+ applyQueryFeatures(options.features, featureFnContext);
3985
4142
  maybeExecute({ execute, flags });
3986
- return createQueryObject({ state, execute, createSnapshot, destroy });
4143
+ return createQueryObject({ state, execute, deps });
3987
4144
  };
3988
4145
 
3989
4146
  const createQueryRepository = (config) => {
@@ -3991,11 +4148,13 @@ const createQueryRepository = (config) => {
3991
4148
  const cache = new Map();
3992
4149
  const request = (options) => {
3993
4150
  const { args, clientOptions, runQueryOptions } = options;
3994
- const shouldCache = shouldCacheQuery(options.method);
4151
+ const shouldCache = options.internalRunQueryOptions?.useQueryRepositoryCache === false
4152
+ ? false
4153
+ : shouldCacheQuery(options.method) || options.internalRunQueryOptions?.useQueryRepositoryCache === true;
3995
4154
  if (!shouldCache && options.key)
3996
4155
  throw uncacheableRequestHasCacheKeyParam(options.key);
3997
- if (!shouldCache && runQueryOptions?.skipCache)
3998
- throw uncacheableRequestHasSkipCacheParam();
4156
+ if (!shouldCache && runQueryOptions?.allowCache)
4157
+ throw uncacheableRequestHasAllowCacheParam();
3999
4158
  const route = buildRoute({
4000
4159
  base: config.baseUrl,
4001
4160
  route: options.route,
@@ -4008,8 +4167,7 @@ const createQueryRepository = (config) => {
4008
4167
  body: args?.body,
4009
4168
  queryParams: args?.queryParams,
4010
4169
  pathParams: args?.pathParams,
4011
- // TODO: remaining props
4012
- // headers: args?.headers,
4170
+ headers: args?.headers,
4013
4171
  });
4014
4172
  const previousKey = options.previousKey;
4015
4173
  if (key !== previousKey && previousKey) {
@@ -4019,8 +4177,8 @@ const createQueryRepository = (config) => {
4019
4177
  const cacheEntry = cache.get(key);
4020
4178
  if (cacheEntry) {
4021
4179
  bind(key, options.destroyRef, cacheEntry.request);
4022
- if (runQueryOptions?.skipCache || cacheEntry.request.isStale()) {
4023
- cacheEntry.request.execute({ skipCache: runQueryOptions?.skipCache });
4180
+ if (!runQueryOptions?.allowCache || cacheEntry.request.isStale()) {
4181
+ cacheEntry.request.execute({ allowCache: runQueryOptions?.allowCache });
4024
4182
  }
4025
4183
  return { key, request: cacheEntry.request };
4026
4184
  }
@@ -4091,6 +4249,10 @@ const provideQueryClient = (config) => {
4091
4249
  };
4092
4250
  };
4093
4251
 
4252
+ /**
4253
+ * This function creates a query client config.
4254
+ * The config is used to create a query client using the `provideQueryClient(myConfig)` function.
4255
+ */
4094
4256
  const createQueryClientConfig = (options) => {
4095
4257
  const token = new InjectionToken(`QueryClient_${options.name}`);
4096
4258
  const clientConfig = {
@@ -4098,6 +4260,9 @@ const createQueryClientConfig = (options) => {
4098
4260
  token,
4099
4261
  name: options.name,
4100
4262
  queryString: options.queryString,
4263
+ // createHttpRequest will use fallbacks if these are not provided
4264
+ cacheAdapter: options.cacheAdapter,
4265
+ retryFn: options.retryFn,
4101
4266
  };
4102
4267
  return clientConfig;
4103
4268
  };
@@ -4214,22 +4379,17 @@ const createSecureQuery = (options) => {
4214
4379
  state,
4215
4380
  creator,
4216
4381
  creatorInternals,
4217
- queryConfig: options.queryConfig,
4382
+ queryConfig,
4218
4383
  });
4219
- const createSnapshot = createQuerySnapshotFn({ state, deps, execute });
4220
- const destroy = () => deps.injector.destroy();
4221
4384
  const featureFnContext = {
4385
+ deps,
4222
4386
  state,
4223
- queryConfig,
4224
- creatorConfig: creator,
4225
- creatorInternals,
4226
4387
  execute,
4227
4388
  flags,
4228
- deps,
4229
4389
  };
4230
- applyQueryFeatures(options, featureFnContext);
4390
+ applyQueryFeatures(options.features, featureFnContext);
4231
4391
  maybeExecute({ execute, flags });
4232
- return createQueryObject({ state, execute, createSnapshot, destroy });
4392
+ return createQueryObject({ state, execute, deps });
4233
4393
  };
4234
4394
 
4235
4395
  const createSecureQueryCreator = (options, internals) => {
@@ -4245,44 +4405,275 @@ const createSecureQueryCreator = (options, internals) => {
4245
4405
  return queryCreator;
4246
4406
  };
4247
4407
 
4408
+ /** A query creator that creates a GET query */
4248
4409
  const createGetQuery = (client) => {
4249
4410
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'GET', client });
4250
4411
  };
4412
+ /** A query creator that creates a secure GET query (requires authentication) */
4251
4413
  const createSecureGetQuery = (client, authProvider) => {
4252
4414
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'GET', client, authProvider });
4253
4415
  };
4416
+ /** A query creator that creates a POST query */
4254
4417
  const createPostQuery = (client) => {
4255
4418
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'POST', client });
4256
4419
  };
4420
+ /** A query creator that creates a secure POST query (requires authentication) */
4257
4421
  const createSecurePostQuery = (client, authProvider) => {
4258
4422
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'POST', client, authProvider });
4259
4423
  };
4424
+ /** A query creator that creates a PUT query */
4260
4425
  const createPutQuery = (client) => {
4261
4426
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'PUT', client });
4262
4427
  };
4428
+ /** A query creator that creates a secure PUT query (requires authentication) */
4263
4429
  const createSecurePutQuery = (client, authProvider) => {
4264
4430
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'PUT', client, authProvider });
4265
4431
  };
4432
+ /** A query creator that creates a DELETE query */
4266
4433
  const createDeleteQuery = (client) => {
4267
4434
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'DELETE', client });
4268
4435
  };
4436
+ /** A query creator that creates a secure DELETE query (requires authentication) */
4269
4437
  const createSecureDeleteQuery = (client, authProvider) => {
4270
4438
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'DELETE', client, authProvider });
4271
4439
  };
4440
+ /** A query creator that creates a PATCH query */
4272
4441
  const createPatchQuery = (client) => {
4273
4442
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'PATCH', client });
4274
4443
  };
4444
+ /** A query creator that creates a secure PATCH query (requires authentication) */
4275
4445
  const createSecurePatchQuery = (client, authProvider) => {
4276
4446
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'PATCH', client, authProvider });
4277
4447
  };
4278
4448
 
4449
+ const createGqlExecuteFn = (executeOptions) => {
4450
+ const executeState = setupQueryExecuteState();
4451
+ const reset = () => resetExecuteState({ executeState, executeOptions });
4452
+ const exec = (executeArgs) => {
4453
+ const { args = executeOptions.state.args(), options } = executeArgs ?? {};
4454
+ cleanupPreviousExecute({ executeOptions, executeState });
4455
+ // TODO: This should get cleaned up
4456
+ const tpl = executeOptions.creator.query;
4457
+ const query = transformGql(tpl);
4458
+ let gqlParams = query(args?.variables);
4459
+ if (args?.queryParams && executeOptions.creatorInternals.transport === 'GET') {
4460
+ gqlParams = { ...gqlParams, ...args.queryParams };
4461
+ }
4462
+ const computedArgs = args ?? {};
4463
+ if (executeOptions.creatorInternals.transport === 'GET') {
4464
+ computedArgs.queryParams = gqlParams;
4465
+ }
4466
+ else {
4467
+ computedArgs.body = gqlParams;
4468
+ }
4469
+ const normalizedOpts = {
4470
+ creator: {
4471
+ route: (executeOptions.creator.route ?? ''),
4472
+ },
4473
+ creatorInternals: {
4474
+ client: executeOptions.creatorInternals.client,
4475
+ method: executeOptions.creatorInternals.transport,
4476
+ },
4477
+ deps: executeOptions.deps,
4478
+ queryConfig: executeOptions.queryConfig,
4479
+ state: executeOptions.state,
4480
+ };
4481
+ queryExecute({
4482
+ executeOptions: normalizedOpts,
4483
+ executeState,
4484
+ args: computedArgs,
4485
+ options,
4486
+ internalOptions: {
4487
+ useQueryRepositoryCache: executeOptions.creatorInternals.method === 'QUERY',
4488
+ },
4489
+ transformResponse: (originalResponse) => {
4490
+ if (originalResponse && 'data' in originalResponse) {
4491
+ return originalResponse.data;
4492
+ }
4493
+ return originalResponse;
4494
+ },
4495
+ });
4496
+ };
4497
+ exec['reset'] = reset;
4498
+ exec['currentRepositoryKey'] = executeState.previousKey.asReadonly();
4499
+ return exec;
4500
+ };
4501
+
4502
+ const isCreateGqlQueryOptions = (options) => {
4503
+ return 'transport' in options.creatorInternals;
4504
+ };
4505
+ const createGqlQuery = (options) => {
4506
+ const deps = setupQueryDependencies({ clientConfig: options.creatorInternals.client });
4507
+ const state = setupQueryState({});
4508
+ const { creator, creatorInternals, queryConfig } = options;
4509
+ const flags = getQueryFeatureUsage(options);
4510
+ const execute = createGqlExecuteFn({
4511
+ deps,
4512
+ state,
4513
+ creator,
4514
+ creatorInternals,
4515
+ queryConfig,
4516
+ });
4517
+ const featureFnContext = {
4518
+ state,
4519
+ execute,
4520
+ flags,
4521
+ deps,
4522
+ };
4523
+ applyQueryFeatures(options.features, featureFnContext);
4524
+ maybeExecute({ execute, flags });
4525
+ return createQueryObject({ state, execute, deps });
4526
+ };
4527
+
4528
+ const createGqlQueryCreator = (options, internals) => {
4529
+ function queryCreator(...args) {
4530
+ const { features, queryConfig } = splitQueryConfig(args);
4531
+ return createGqlQuery({
4532
+ creator: options,
4533
+ creatorInternals: internals,
4534
+ features,
4535
+ queryConfig,
4536
+ });
4537
+ }
4538
+ return queryCreator;
4539
+ };
4540
+
4541
+ /** A query creator that creates a GQL query where the payload is sent via GET (query params) */
4542
+ const createGqlQueryViaGet = (client) => {
4543
+ return (creatorOptions) => createGqlQueryCreator(creatorOptions, { method: 'QUERY', client, transport: 'GET' });
4544
+ };
4545
+ /** A query creator that creates a GQL query where the payload is sent via POST (body) */
4546
+ const createGqlQueryViaPost = (client) => {
4547
+ return (creatorOptions) => createGqlQueryCreator(creatorOptions, { method: 'QUERY', client, transport: 'POST' });
4548
+ };
4549
+ /** A query creator that creates a GQL mutation where the payload is sent via GET (query params) */
4550
+ const createGqlMutationViaGet = (client) => {
4551
+ return (creatorOptions) => createGqlQueryCreator(creatorOptions, { method: 'MUTATE', client, transport: 'GET' });
4552
+ };
4553
+ /** A query creator that creates a GQL mutation where the payload is sent via POST (body) */
4554
+ const createGqlMutationViaPost = (client) => {
4555
+ return (creatorOptions) => createGqlQueryCreator(creatorOptions, { method: 'MUTATE', client, transport: 'POST' });
4556
+ };
4557
+
4558
+ const roomAlreadyJoined = (room) => {
4559
+ return new RuntimeError(1000 /* QueryRuntimeErrorCode.ROOM_ALREADY_JOINED */, `Tried joining the room "${room}" but it has already been joined.`);
4560
+ };
4561
+ const roomNotJoined = (room) => {
4562
+ return new RuntimeError(1001 /* QueryRuntimeErrorCode.ROOM_NOT_JOINED */, `Tried leaving the room "${room}" but it has not been joined.`);
4563
+ };
4564
+ const messageMalformed = () => {
4565
+ return new RuntimeError(1002 /* QueryRuntimeErrorCode.MESSAGE_MALFORMED */, 'A message has been received but it is malformed (cannot be parsed as JSON).');
4566
+ };
4567
+
4568
+ const createWebSocketClient = (config) => {
4569
+ const joinedRooms = new Set();
4570
+ const socket = io(config.url, {
4571
+ withCredentials: true,
4572
+ autoConnect: false,
4573
+ });
4574
+ const currentEvent = signal(null);
4575
+ const isConnected = signal(false);
4576
+ const joinRoom = (room) => {
4577
+ if (joinedRooms.has(room)) {
4578
+ if (isDevMode())
4579
+ throw roomAlreadyJoined(room);
4580
+ return;
4581
+ }
4582
+ socket.emit('join-room', room);
4583
+ joinedRooms.add(room);
4584
+ };
4585
+ const joinComputedRoom = (room) => {
4586
+ const pre = previousSignalValue(computed(() => room()));
4587
+ effect(() => {
4588
+ const current = room();
4589
+ untracked(() => {
4590
+ const previous = pre();
4591
+ if (previous === current)
4592
+ return;
4593
+ if (previous)
4594
+ leaveRoom(previous);
4595
+ if (current)
4596
+ joinRoom(current);
4597
+ });
4598
+ });
4599
+ inject(DestroyRef).onDestroy(() => {
4600
+ const current = room();
4601
+ if (current)
4602
+ leaveRoom(current);
4603
+ });
4604
+ };
4605
+ const leaveRoom = (room) => {
4606
+ if (!joinedRooms.has(room)) {
4607
+ if (isDevMode())
4608
+ throw roomNotJoined(room);
4609
+ return;
4610
+ }
4611
+ socket.emit('leave-room', room);
4612
+ joinedRooms.delete(room);
4613
+ };
4614
+ const leaveAllRooms = () => {
4615
+ joinedRooms.forEach((room) => leaveRoom(room));
4616
+ joinedRooms.clear();
4617
+ };
4618
+ const setupWebSocketConnectionListener = () => {
4619
+ socket.on('connect', () => {
4620
+ isConnected.set(true);
4621
+ joinedRooms.forEach((room) => joinRoom(room));
4622
+ });
4623
+ socket.on('disconnect', () => isConnected.set(false));
4624
+ };
4625
+ const setupWebSocketListener = () => {
4626
+ socket.onAny((data) => {
4627
+ try {
4628
+ const json = JSON.parse(data);
4629
+ currentEvent.set(json);
4630
+ }
4631
+ catch (error) {
4632
+ console.error(error);
4633
+ if (isDevMode())
4634
+ throw messageMalformed();
4635
+ }
4636
+ });
4637
+ };
4638
+ inject(DestroyRef).onDestroy(() => socket.disconnect());
4639
+ setupWebSocketConnectionListener();
4640
+ setupWebSocketListener();
4641
+ socket.connect();
4642
+ const client = {
4643
+ joinRoom,
4644
+ joinComputedRoom,
4645
+ leaveRoom,
4646
+ leaveAllRooms,
4647
+ currentEvent: currentEvent.asReadonly(),
4648
+ isConnected: isConnected.asReadonly(),
4649
+ };
4650
+ return client;
4651
+ };
4652
+ const provideWebSocketClient = (config) => {
4653
+ return {
4654
+ provide: config.token,
4655
+ useFactory: () => createWebSocketClient(config),
4656
+ };
4657
+ };
4658
+
4659
+ const createWebSocketClientConfig = (options) => {
4660
+ const token = new InjectionToken(`WebSocketClient_${options.name}`);
4661
+ const clientConfig = {
4662
+ token,
4663
+ name: options.name,
4664
+ url: options.url,
4665
+ };
4666
+ return clientConfig;
4667
+ };
4668
+
4279
4669
  var index = /*#__PURE__*/Object.freeze({
4280
4670
  __proto__: null,
4281
- QUERY_ARGS_RESET: QUERY_ARGS_RESET,
4671
+ CLEAR_QUERY_ARGS: CLEAR_QUERY_ARGS,
4282
4672
  QUERY_EFFECT_ERROR_MESSAGE: QUERY_EFFECT_ERROR_MESSAGE,
4283
4673
  SPEED_BUFFER_TIME_IN_MS: SPEED_BUFFER_TIME_IN_MS,
4284
4674
  applyQueryFeatures: applyQueryFeatures,
4285
4675
  bearerExpiresInPropertyNotNumber: bearerExpiresInPropertyNotNumber,
4676
+ buildQueryCacheKey: buildQueryCacheKey,
4286
4677
  cleanupPreviousExecute: cleanupPreviousExecute,
4287
4678
  contentfulGqlLikePaginationAdapter: contentfulGqlLikePaginationAdapter,
4288
4679
  cookieLoginTriedButCookieDisabled: cookieLoginTriedButCookieDisabled,
@@ -4291,8 +4682,15 @@ var index = /*#__PURE__*/Object.freeze({
4291
4682
  createDeleteQuery: createDeleteQuery,
4292
4683
  createExecuteFn: createExecuteFn,
4293
4684
  createGetQuery: createGetQuery,
4685
+ createGqlExecuteFn: createGqlExecuteFn,
4686
+ createGqlMutationViaGet: createGqlMutationViaGet,
4687
+ createGqlMutationViaPost: createGqlMutationViaPost,
4688
+ createGqlQuery: createGqlQuery,
4689
+ createGqlQueryCreator: createGqlQueryCreator,
4690
+ createGqlQueryViaGet: createGqlQueryViaGet,
4691
+ createGqlQueryViaPost: createGqlQueryViaPost,
4294
4692
  createHttpRequest: createHttpRequest,
4295
- createPagedQuery: createPagedQuery,
4693
+ createPagedQueryStack: createPagedQueryStack,
4296
4694
  createPatchQuery: createPatchQuery,
4297
4695
  createPostQuery: createPostQuery,
4298
4696
  createPutQuery: createPutQuery,
@@ -4312,6 +4710,8 @@ var index = /*#__PURE__*/Object.freeze({
4312
4710
  createSecurePutQuery: createSecurePutQuery,
4313
4711
  createSecureQuery: createSecureQuery,
4314
4712
  createSecureQueryCreator: createSecureQueryCreator,
4713
+ createWebSocketClient: createWebSocketClient,
4714
+ createWebSocketClientConfig: createWebSocketClientConfig,
4315
4715
  defaultResponseTransformerResponseNotContainingAccessToken: defaultResponseTransformerResponseNotContainingAccessToken,
4316
4716
  defaultResponseTransformerResponseNotContainingRefreshToken: defaultResponseTransformerResponseNotContainingRefreshToken,
4317
4717
  defaultResponseTransformerResponseNotObject: defaultResponseTransformerResponseNotObject,
@@ -4320,33 +4720,40 @@ var index = /*#__PURE__*/Object.freeze({
4320
4720
  enableCookieCalledWithoutCookieConfig: enableCookieCalledWithoutCookieConfig,
4321
4721
  ethletePaginationAdapter: ethletePaginationAdapter,
4322
4722
  extractExpiresInSeconds: extractExpiresInSeconds,
4723
+ fakePaginationAdapter: fakePaginationAdapter,
4323
4724
  getQueryFeatureUsage: getQueryFeatureUsage,
4324
4725
  ggLikePaginationAdapter: ggLikePaginationAdapter,
4726
+ isCreateGqlQueryOptions: isCreateGqlQueryOptions,
4325
4727
  loginCalledWithoutConfig: loginCalledWithoutConfig,
4326
4728
  loginWithTokenCalledWithoutConfig: loginWithTokenCalledWithoutConfig,
4327
4729
  maybeExecute: maybeExecute,
4328
- pagedQueryNextPageCalledWithoutPreviousPage: pagedQueryNextPageCalledWithoutPreviousPage,
4329
- pagedQueryPageBiggerThanTotalPages: pagedQueryPageBiggerThanTotalPages,
4330
- pagedQueryPreviousPageCalledButAlreadyAtFirstPage: pagedQueryPreviousPageCalledButAlreadyAtFirstPage,
4730
+ normalizeQueryRepositoryKey: normalizeQueryRepositoryKey,
4731
+ pagedQueryStackNextPageCalledWithoutPreviousPage: pagedQueryStackNextPageCalledWithoutPreviousPage,
4732
+ pagedQueryStackPageBiggerThanTotalPages: pagedQueryStackPageBiggerThanTotalPages,
4733
+ pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage: pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage,
4331
4734
  provideBearerAuthProvider: provideBearerAuthProvider,
4332
4735
  provideQueryClient: provideQueryClient,
4736
+ provideWebSocketClient: provideWebSocketClient,
4333
4737
  queryEffect: queryEffect,
4334
4738
  queryExecute: queryExecute,
4335
4739
  queryFeatureUsedMultipleTimes: queryFeatureUsedMultipleTimes,
4740
+ queryStackWithArgsUsed: queryStackWithArgsUsed,
4336
4741
  refreshTokenCalledWithoutConfig: refreshTokenCalledWithoutConfig,
4337
4742
  resetExecuteState: resetExecuteState,
4338
4743
  selectRoleCalledWithoutConfig: selectRoleCalledWithoutConfig,
4339
4744
  setupQueryDependencies: setupQueryDependencies,
4340
4745
  setupQueryExecuteState: setupQueryExecuteState,
4341
4746
  setupQueryState: setupQueryState,
4747
+ shouldAutoExecuteGqlQuery: shouldAutoExecuteGqlQuery,
4342
4748
  shouldAutoExecuteQuery: shouldAutoExecuteQuery,
4749
+ shouldCacheQuery: shouldCacheQuery,
4343
4750
  shouldRetryRequest: shouldRetryRequest,
4344
4751
  splitQueryConfig: splitQueryConfig,
4345
4752
  transformArrayResponse: transformArrayResponse,
4346
4753
  transformPaginatedResponse: transformPaginatedResponse,
4347
4754
  unableToDecryptBearerToken: unableToDecryptBearerToken,
4755
+ uncacheableRequestHasAllowCacheParam: uncacheableRequestHasAllowCacheParam,
4348
4756
  uncacheableRequestHasCacheKeyParam: uncacheableRequestHasCacheKeyParam,
4349
- uncacheableRequestHasSkipCacheParam: uncacheableRequestHasSkipCacheParam,
4350
4757
  withArgs: withArgs,
4351
4758
  withArgsQueryFeatureMissingButRouteIsFunction: withArgsQueryFeatureMissingButRouteIsFunction,
4352
4759
  withAutoRefresh: withAutoRefresh,
@@ -4458,6 +4865,7 @@ const transformToSortQueryParam = (value) => {
4458
4865
 
4459
4866
  const ET_ARR_PREFIX = 'ET_ARR__';
4460
4867
  class QueryField {
4868
+ data;
4461
4869
  get control() {
4462
4870
  return this.data.control;
4463
4871
  }
@@ -4468,12 +4876,70 @@ class QueryField {
4468
4876
  const IGNORED_FILTER_COUNT_FIELDS = ['page', 'skip', 'take', 'limit', 'sort', 'sortBy', 'sortOrder', 'query', 'search'];
4469
4877
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4470
4878
  class QueryForm {
4879
+ _fields;
4880
+ _options;
4881
+ _destroy$ = createDestroy();
4882
+ _unobserveTrigger$ = new Subject();
4883
+ _router = inject(Router);
4884
+ _activatedRoute = inject(ActivatedRoute);
4885
+ _defaultValues = this._extractDefaultValues();
4886
+ _zone = inject(NgZone);
4887
+ _didValueChanges$ = new Subject();
4888
+ _isObserving = false;
4889
+ _skipNextResets = false;
4890
+ _queryParamChanges$ = toObservable(injectQueryParamChanges());
4891
+ _queryParams = injectQueryParams();
4892
+ /**
4893
+ * The angular form group that contains all the fields.
4894
+ *
4895
+ * **Do not** use any of the following methods on this form group:
4896
+ * - `setValue`: Use `QueryForm.setValue` instead.
4897
+ * - `patchValue`: Use `QueryForm.patchValue` instead.
4898
+ * - `valueChanges`: Use `QueryForm.changes$` instead.
4899
+ * - `value`: Use `QueryForm.value` instead.
4900
+ * - `controls`: Use `QueryForm.controls` instead.
4901
+ */
4902
+ form = this._setupFormGroup();
4903
+ _lastFormValue$ = new BehaviorSubject(null);
4904
+ _currentFormValue$ = new BehaviorSubject(this._formValue);
4471
4905
  get _formValue() {
4472
4906
  return this.form.getRawValue();
4473
4907
  }
4474
4908
  get _form() {
4475
4909
  return this.form;
4476
4910
  }
4911
+ _changes$ = new BehaviorSubject({
4912
+ previousValue: null,
4913
+ currentValue: this.form.getRawValue(),
4914
+ });
4915
+ changes$ = this._changes$.asObservable();
4916
+ currentValue$ = this._changes$.pipe(map(({ currentValue }) => currentValue));
4917
+ previousValue$ = this._changes$.pipe(map(({ previousValue }) => previousValue));
4918
+ changes = toSignal(this.changes$);
4919
+ currentValue = toSignal(this.currentValue$);
4920
+ previousValue = toSignal(this.previousValue$);
4921
+ /**
4922
+ * The number of active filters.
4923
+ *
4924
+ * Excludes the following fields by default:
4925
+ * - `page`
4926
+ * - `skip`
4927
+ * - `take`
4928
+ * - `limit`
4929
+ * - `sort`
4930
+ * - `sortBy`
4931
+ * - `sortOrder`
4932
+ * - `query`
4933
+ * - `search`
4934
+ */
4935
+ activeFilterCount$ = this.changes$.pipe(map(({ currentValue }) => Object.entries(currentValue)
4936
+ .map(([key, value]) => {
4937
+ if (IGNORED_FILTER_COUNT_FIELDS.includes(key) || this._fields[key]?.data.skipInFilterCount) {
4938
+ return true;
4939
+ }
4940
+ return this._isDefaultValue(key, value);
4941
+ })
4942
+ .filter((v) => v === false).length));
4477
4943
  get controls() {
4478
4944
  return this.form.controls;
4479
4945
  }
@@ -4490,62 +4956,6 @@ class QueryForm {
4490
4956
  constructor(_fields, _options) {
4491
4957
  this._fields = _fields;
4492
4958
  this._options = _options;
4493
- this._destroy$ = createDestroy();
4494
- this._unobserveTrigger$ = new Subject();
4495
- this._router = inject(Router);
4496
- this._activatedRoute = inject(ActivatedRoute);
4497
- this._defaultValues = this._extractDefaultValues();
4498
- this._zone = inject(NgZone);
4499
- this._didValueChanges$ = new Subject();
4500
- this._isObserving = false;
4501
- this._skipNextResets = false;
4502
- this._queryParamChanges$ = toObservable(injectQueryParamChanges());
4503
- this._queryParams = injectQueryParams();
4504
- /**
4505
- * The angular form group that contains all the fields.
4506
- *
4507
- * **Do not** use any of the following methods on this form group:
4508
- * - `setValue`: Use `QueryForm.setValue` instead.
4509
- * - `patchValue`: Use `QueryForm.patchValue` instead.
4510
- * - `valueChanges`: Use `QueryForm.changes$` instead.
4511
- * - `value`: Use `QueryForm.value` instead.
4512
- * - `controls`: Use `QueryForm.controls` instead.
4513
- */
4514
- this.form = this._setupFormGroup();
4515
- this._lastFormValue$ = new BehaviorSubject(null);
4516
- this._currentFormValue$ = new BehaviorSubject(this._formValue);
4517
- this._changes$ = new BehaviorSubject({
4518
- previousValue: null,
4519
- currentValue: this.form.getRawValue(),
4520
- });
4521
- this.changes$ = this._changes$.asObservable();
4522
- this.currentValue$ = this._changes$.pipe(map(({ currentValue }) => currentValue));
4523
- this.previousValue$ = this._changes$.pipe(map(({ previousValue }) => previousValue));
4524
- this.changes = toSignal(this.changes$);
4525
- this.currentValue = toSignal(this.currentValue$);
4526
- this.previousValue = toSignal(this.previousValue$);
4527
- /**
4528
- * The number of active filters.
4529
- *
4530
- * Excludes the following fields by default:
4531
- * - `page`
4532
- * - `skip`
4533
- * - `take`
4534
- * - `limit`
4535
- * - `sort`
4536
- * - `sortBy`
4537
- * - `sortOrder`
4538
- * - `query`
4539
- * - `search`
4540
- */
4541
- this.activeFilterCount$ = this.changes$.pipe(map(({ currentValue }) => Object.entries(currentValue)
4542
- .map(([key, value]) => {
4543
- if (IGNORED_FILTER_COUNT_FIELDS.includes(key) || this._fields[key]?.data.skipInFilterCount) {
4544
- return true;
4545
- }
4546
- return this._isDefaultValue(key, value);
4547
- })
4548
- .filter((v) => v === false).length));
4549
4959
  assertInInjectionContext(QueryForm);
4550
4960
  inject(DestroyRef).onDestroy(() => this._cleanup());
4551
4961
  }
@@ -4867,5 +5277,5 @@ class QueryForm {
4867
5277
  * Generated bundle index. Do not edit.
4868
5278
  */
4869
5279
 
4870
- export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, index as ExperimentalQuery, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, QUERY_CLIENT_DEVTOOLS_TOKEN, Query, QueryClient, QueryCreator, QueryDevtoolsComponent, QueryDirective, QueryError, QueryField, QueryForm, QueryShortNamePipe, QueryStore, addQueryContainerHandling, buildErrorMessage, buildQueryCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, createQueryCollectionSignal, createQueryCollectionSubject, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds$1 as extractExpiresInSeconds, extractQuery, filterFailure, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, insertFrom, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isClassValidatorError, isCustomHeaderAuthProvider, isEmptyString, isGqlQueryConfig, isNaN$1 as isNaN, isQuery, isQueryCollection, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, isSymfonyFormViolationListError, isSymfonyListError, isSymfonyPagerfantaOutOfRangeError, mapToPaginated, mergeHeaders, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, provideQueryClientForDevtools, queryArrayComputed, queryComputed, queryComputedTillTruthy, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, queryStateErrorSignal, queryStateLoadingSignal, queryStateResponseSignal, queryStateSignal, removeFrom, request, resetPageOnError, serializeBody, shouldCacheQuery, shouldRetryRequest$1 as shouldRetryRequest, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, toQuerySignal, toQuerySubject, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
5280
+ export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, index as ExperimentalQuery, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, QUERY_CLIENT_DEVTOOLS_TOKEN, Query, QueryClient, QueryCreator, QueryDevtoolsComponent, QueryDirective, QueryError, QueryField, QueryForm, QueryShortNamePipe, QueryStore, addQueryContainerHandling, buildErrorMessage, buildQueryCacheKey$1 as buildQueryCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, createQueryCollectionSignal, createQueryCollectionSubject, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds$1 as extractExpiresInSeconds, extractQuery, filterFailure, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, insertFrom, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isClassValidatorError, isCustomHeaderAuthProvider, isEmptyString, isGqlQueryConfig, isNaN$1 as isNaN, isQuery, isQueryCollection, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, isSymfonyFormViolationListError, isSymfonyListError, isSymfonyPagerfantaOutOfRangeError, mapToPaginated, mergeHeaders, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, provideQueryClientForDevtools, queryArrayComputed, queryComputed, queryComputedTillTruthy, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, queryStateErrorSignal, queryStateLoadingSignal, queryStateResponseSignal, queryStateSignal, removeFrom, request, resetPageOnError, serializeBody, shouldCacheQuery$1 as shouldCacheQuery, shouldRetryRequest$1 as shouldRetryRequest, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, toQuerySignal, toQuerySubject, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
4871
5281
  //# sourceMappingURL=ethlete-query.mjs.map