@ethlete/query 5.23.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 (45) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/fesm2022/ethlete-query.mjs +1039 -651
  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/index.d.ts +20 -0
  13. package/lib/experimental/http/paged-query-stack.d.ts +149 -0
  14. package/lib/experimental/http/query-client-config.d.ts +45 -0
  15. package/lib/experimental/{query-creator-templates.d.ts → http/query-creator-templates.d.ts} +11 -1
  16. package/lib/experimental/http/query-creator.d.ts +73 -0
  17. package/lib/experimental/{query-dependencies.d.ts → http/query-dependencies.d.ts} +5 -0
  18. package/lib/experimental/http/query-errors.d.ts +50 -0
  19. package/lib/experimental/{query-execute-utils.d.ts → http/query-execute-utils.d.ts} +15 -2
  20. package/lib/experimental/{query-execute.d.ts → http/query-execute.d.ts} +5 -3
  21. package/lib/experimental/http/query-features.d.ts +85 -0
  22. package/lib/experimental/{query-repository.d.ts → http/query-repository.d.ts} +3 -1
  23. package/lib/experimental/{query-snapshot.d.ts → http/query-snapshot.d.ts} +2 -2
  24. package/lib/experimental/http/query-stack.d.ts +101 -0
  25. package/lib/experimental/{query-utils.d.ts → http/query-utils.d.ts} +25 -15
  26. package/lib/experimental/{query.d.ts → http/query.d.ts} +24 -2
  27. package/lib/experimental/{secure-query-creator.d.ts → http/secure-query-creator.d.ts} +1 -1
  28. package/lib/experimental/{secure-query-execute.d.ts → http/secure-query-execute.d.ts} +2 -2
  29. package/lib/experimental/index.d.ts +4 -22
  30. package/lib/experimental/ws/index.d.ts +2 -0
  31. package/lib/experimental/ws/web-socket-client-config.d.ts +12 -0
  32. package/lib/experimental/ws/web-socket-client.d.ts +20 -0
  33. package/lib/experimental/ws/web-socket-errors.d.ts +9 -0
  34. package/lib/gql/gql.d.ts +3 -2
  35. package/package.json +8 -7
  36. package/lib/experimental/paged-query.d.ts +0 -77
  37. package/lib/experimental/query-client-config.d.ts +0 -18
  38. package/lib/experimental/query-creator.d.ts +0 -39
  39. package/lib/experimental/query-errors.d.ts +0 -49
  40. package/lib/experimental/query-features.d.ts +0 -48
  41. package/lib/experimental/query-stack.d.ts +0 -48
  42. /package/lib/experimental/{http-request.d.ts → http/http-request.d.ts} +0 -0
  43. /package/lib/experimental/{query-client.d.ts → http/query-client.d.ts} +0 -0
  44. /package/lib/experimental/{query-state.d.ts → http/query-state.d.ts} +0 -0
  45. /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, syncSignal, getCookie, setCookie, deleteCookie, DelayableDirective, nextFrame, RuntimeError, isObject, getDomain, 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';
@@ -694,67 +699,71 @@ const deepFreeze = (object) => {
694
699
  const def = () => null;
695
700
 
696
701
  class QueryCreator {
702
+ _queryConfig;
703
+ _client;
704
+ _store;
697
705
  constructor(_queryConfig, _client, _store) {
698
706
  this._queryConfig = _queryConfig;
699
707
  this._client = _client;
700
708
  this._store = _store;
701
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
702
- // @ts-ignore
703
- this.prepare = (args) => {
704
- const route = buildRoute({
705
- base: this._client.config.baseRoute,
706
- route: this._queryConfig.route,
707
- pathParams: args?.pathParams,
708
- queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
709
- queryParamConfig: this._client.config.request?.queryParams,
710
- });
711
- const cacheKey = (args?.config?.queryStoreCacheKey ?? '') + buildQueryCacheKey(route, args);
712
- if (shouldCacheQuery(this._queryConfig.method) && !args?.config?.skipQueryStore) {
713
- const existingQuery = this._store.get(cacheKey);
714
- if (existingQuery) {
715
- return existingQuery;
716
- }
717
- }
718
- const query = new Query(this._client, this._queryConfig, route, args ?? {}, cacheKey);
719
- if (shouldCacheQuery(this._queryConfig.method) && !args?.config?.skipQueryStore) {
720
- this._store.add(cacheKey, query);
721
- }
722
- this._store._dispatchQueryCreated(query);
723
- return query;
724
- };
725
- this.createSubject = (initialValue, config) => {
726
- assertInInjectionContext(this.createSubject);
727
- const subject = new BehaviorSubject(initialValue ?? null);
728
- addQueryContainerHandling(subject, () => subject.getValue(), config);
729
- return subject;
730
- };
731
- this.createSignal = (initialValue, config) => {
732
- assertInInjectionContext(this.createSignal);
733
- const _signal = signal(initialValue ?? null);
734
- addQueryContainerHandling(toObservable(_signal), () => _signal(), config);
735
- return _signal;
736
- };
737
- /**
738
- * @deprecated Use `myQuery.createSubject()` or `myQuery.createSignal()` instead. Will be removed in v6.
739
- */
740
- this.behaviorSubject = (initialValue) => new BehaviorSubject(initialValue ?? null);
741
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);
742
750
  }
743
751
 
744
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();
745
765
  constructor(_config) {
746
766
  this._config = _config;
747
- /**
748
- * @internal
749
- */
750
- this._store = new Map();
751
- this._garbageCollector = null;
752
- this._isInLowResourceMode = false;
753
- this._lastBlurTimestamp = Date.now();
754
- this._storeChange$ = new Subject();
755
- this._queryCreated$ = new Subject();
756
- this.storeChange$ = this._storeChange$.asObservable();
757
- this.queryCreated$ = this._queryCreated$.asObservable();
758
767
  this._initSmartQueryHandling();
759
768
  }
760
769
  add(id, query) {
@@ -885,6 +894,11 @@ class QueryStore {
885
894
  }
886
895
 
887
896
  class QueryClient {
897
+ _clientConfig;
898
+ /**
899
+ * @internal
900
+ */
901
+ _store;
888
902
  get config() {
889
903
  return this._clientConfig;
890
904
  }
@@ -894,64 +908,9 @@ class QueryClient {
894
908
  get authProvider$() {
895
909
  return this._authProvider$.asObservable() ?? this._clientConfig.parent?._authProvider$.asObservable() ?? null;
896
910
  }
911
+ _authProvider$ = new BehaviorSubject(null);
897
912
  constructor(_clientConfig) {
898
913
  this._clientConfig = _clientConfig;
899
- this._authProvider$ = new BehaviorSubject(null);
900
- this.get = (queryConfig) => this.fetch({
901
- ...queryConfig,
902
- method: 'GET',
903
- });
904
- this.post = (queryConfig) => this.fetch({
905
- ...queryConfig,
906
- method: 'POST',
907
- });
908
- this.put = (queryConfig) => this.fetch({
909
- ...queryConfig,
910
- method: 'PUT',
911
- });
912
- this.patch = (queryConfig) => this.fetch({
913
- ...queryConfig,
914
- method: 'PATCH',
915
- });
916
- this.delete = (queryConfig) => this.fetch({
917
- ...queryConfig,
918
- method: 'DELETE',
919
- });
920
- this.gqlQuery = (queryConfig) => this.fetch({
921
- ...queryConfig,
922
- method: 'GQL_QUERY',
923
- });
924
- this.gqlMutate = (queryConfig) => this.fetch({
925
- ...queryConfig,
926
- method: 'GQL_MUTATE',
927
- });
928
- this.fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
929
- this.setAuthProvider = (authProvider) => {
930
- if (this.authProvider) {
931
- this.authProvider?.cleanUp();
932
- }
933
- this._authProvider$.next(authProvider);
934
- };
935
- this.setDefaultHeaders = (config) => {
936
- if (!this._clientConfig.request) {
937
- this._clientConfig.request = {
938
- headers: config.headers ?? undefined,
939
- };
940
- }
941
- else {
942
- this._clientConfig.request.headers = config.headers ?? undefined;
943
- }
944
- if (config.refreshQueriesInUse) {
945
- this._store.refreshQueriesInUse({ purgeUnused: true, ignoreCacheValidity: true });
946
- }
947
- };
948
- this.clearAuthProvider = () => {
949
- this.authProvider?.cleanUp();
950
- this._authProvider$.next(null);
951
- };
952
- this._updateBaseRoute = (route) => {
953
- this._clientConfig.baseRoute = route;
954
- };
955
914
  this._store = new QueryStore({
956
915
  enableChangeLogging: _clientConfig.logging?.queryStateChanges,
957
916
  enableGarbageCollectorLogging: _clientConfig.logging?.queryStateGarbageCollector,
@@ -959,12 +918,67 @@ class QueryClient {
959
918
  enableSmartPolling: _clientConfig.request?.enableSmartPolling ?? true,
960
919
  });
961
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
+ };
962
976
  }
963
977
 
964
- const shouldCacheQuery = (method) => {
978
+ const shouldCacheQuery$1 = (method) => {
965
979
  return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
966
980
  };
967
- const buildQueryCacheKey = (route, args) => {
981
+ const buildQueryCacheKey$1 = (route, args) => {
968
982
  const variables = JSON.stringify(args?.variables || {})
969
983
  // replace all curly braces with empty string
970
984
  .replace(/{|}/g, '')
@@ -988,12 +1002,14 @@ const transformGql = (str) => {
988
1002
  return function (variables) {
989
1003
  const data = { query: str };
990
1004
  if (variables)
991
- data['variables'] = JSON.stringify(variables);
1005
+ data['variables'] = variables;
992
1006
  if (name && name.length) {
993
1007
  const operationName = name[2];
994
1008
  if (operationName)
995
1009
  data['operationName'] = name[2];
996
1010
  }
1011
+ // minify the query
1012
+ data.query = data.query.replace(/\s+/g, ' ').trim();
997
1013
  return data;
998
1014
  };
999
1015
  };
@@ -1248,6 +1264,36 @@ const paginatedEntityValueUpdater = (findFn) => ({ response, rawResponse, entity
1248
1264
 
1249
1265
  let _nextQueryId = 0;
1250
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
+ });
1251
1297
  get _nextId() {
1252
1298
  return ++this._currentLocalId;
1253
1299
  }
@@ -1314,7 +1360,7 @@ class Query {
1314
1360
  return this._queryConfig.entity?.store ?? null;
1315
1361
  }
1316
1362
  get canBeCached() {
1317
- return shouldCacheQuery(this._queryConfig.method);
1363
+ return shouldCacheQuery$1(this._queryConfig.method);
1318
1364
  }
1319
1365
  get _isInMockMode() {
1320
1366
  return !!this._arguments?.mock;
@@ -1341,31 +1387,6 @@ class Query {
1341
1387
  this._routeWithParams = _routeWithParams;
1342
1388
  this._arguments = _arguments;
1343
1389
  this._queryStoreKey = _queryStoreKey;
1344
- this._id = _nextQueryId++;
1345
- this._currentLocalId = 0;
1346
- this._pollingSubscription = null;
1347
- this._onAbort$ = new Subject();
1348
- this._currentPollConfig = null;
1349
- /**
1350
- * @internal
1351
- * Used to track which components depend on this query.
1352
- * The key is the component's _tNode index.
1353
- * The value is the number of times the component has subscribed to this query.
1354
- * The value might increase since we cant distinguish between a component and a host directive applied to it.
1355
- */
1356
- this._dependents = {};
1357
- /**
1358
- * @internal
1359
- */
1360
- this._dependentsChanged$ = new ReplaySubject();
1361
- /**
1362
- * @internal
1363
- */
1364
- this._isPollingPaused = false;
1365
- this._state$ = new BehaviorSubject({
1366
- type: "PREPARED" /* QueryStateType.Prepared */,
1367
- meta: { id: this._currentLocalId, triggeredVia: 'program' },
1368
- });
1369
1390
  }
1370
1391
  execute(options = {}) {
1371
1392
  const { skipCache = false, _triggeredVia: triggeredVia = 'program', cancelPrevious = false } = options;
@@ -1694,6 +1715,13 @@ const decryptBearer = (token) => {
1694
1715
  };
1695
1716
 
1696
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
+ });
1697
1725
  get header() {
1698
1726
  return { Authorization: `Bearer ${this._tokens$.getValue().token}` };
1699
1727
  }
@@ -1716,12 +1744,6 @@ class BearerAuthProvider {
1716
1744
  }
1717
1745
  constructor(_config) {
1718
1746
  this._config = _config;
1719
- this._destroy$ = new Subject();
1720
- this._currentRefreshQuery$ = new BehaviorSubject(null);
1721
- this._tokens$ = new BehaviorSubject({
1722
- token: null,
1723
- refreshToken: null,
1724
- });
1725
1747
  const cookieEnabled = _config.refreshConfig?.cookieEnabled ?? true;
1726
1748
  const cookieToken = _config.refreshConfig?.cookieName && cookieEnabled ? (getCookie(_config.refreshConfig.cookieName) ?? null) : null;
1727
1749
  this._tokens$.next({
@@ -1862,25 +1884,22 @@ const isClassValidatorError = (error) => {
1862
1884
  };
1863
1885
 
1864
1886
  class QueryDirective {
1865
- constructor() {
1866
- this._mainTemplateRef = inject(TemplateRef);
1867
- this._viewContainerRef = inject(ViewContainerRef);
1868
- this._errorHandler = inject(ErrorHandler);
1869
- this._cdr = inject(ChangeDetectorRef);
1870
- this._isMainViewCreated = false;
1871
- this._subscription = null;
1872
- this._viewContext = {
1873
- $implicit: null,
1874
- etQuery: null,
1875
- loading: false,
1876
- refreshing: false,
1877
- error: null,
1878
- progress: null,
1879
- scope: null,
1880
- query: null,
1881
- };
1882
- this._cache = false;
1883
- }
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
+ };
1884
1903
  get query() {
1885
1904
  return this._query;
1886
1905
  }
@@ -1888,12 +1907,14 @@ class QueryDirective {
1888
1907
  this._query = v;
1889
1908
  this._subscribeToQuery();
1890
1909
  }
1910
+ _query;
1891
1911
  get cache() {
1892
1912
  return this._cache;
1893
1913
  }
1894
1914
  set cache(v) {
1895
1915
  this._cache = v;
1896
1916
  }
1917
+ _cache = false;
1897
1918
  static ngTemplateContextGuard(dir, ctx) {
1898
1919
  return true;
1899
1920
  }
@@ -1962,10 +1983,10 @@ class QueryDirective {
1962
1983
  this._viewContainerRef.createEmbeddedView(this._mainTemplateRef, this._viewContext);
1963
1984
  }
1964
1985
  }
1965
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1966
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.5", 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 });
1967
1988
  }
1968
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryDirective, decorators: [{
1989
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDirective, decorators: [{
1969
1990
  type: Directive,
1970
1991
  args: [{
1971
1992
  selector: '[etQuery]',
@@ -1980,6 +2001,58 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1980
2001
  }] } });
1981
2002
 
1982
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 }));
1983
2056
  get currentPage$() {
1984
2057
  return this._currentPage$.asObservable();
1985
2058
  }
@@ -2013,56 +2086,7 @@ class InfinityQuery {
2013
2086
  constructor(_config, _destroy$) {
2014
2087
  this._config = _config;
2015
2088
  this._destroy$ = _destroy$;
2016
- this._queries$ = new BehaviorSubject([]);
2017
- this._currentPage$ = new BehaviorSubject(null);
2018
- this._currentCalculatedPage$ = new BehaviorSubject(null);
2019
- this._totalPages$ = new BehaviorSubject(null);
2020
- this._itemsPerPage$ = new BehaviorSubject(this._config.limitParam?.value ?? 10);
2021
- this._data$ = this._queries$.pipe(switchMap((queries) => {
2022
- if (!queries.length) {
2023
- return of([]);
2024
- }
2025
- return combineLatest(queries.map((query) => query.state$.pipe(filterSuccess(), map((state) => ({ state, query })))));
2026
- }), tap((stateMaps) => {
2027
- const lastState = stateMaps[stateMaps.length - 1]?.state;
2028
- const lastQuery = stateMaps[stateMaps.length - 1]?.query;
2029
- if (!lastState || !lastQuery) {
2030
- return;
2031
- }
2032
- const totalPages = this._config.response.totalPagesExtractor?.({
2033
- response: lastState.response,
2034
- itemsPerPage: this.itemsPerPage,
2035
- args: lastQuery._arguments,
2036
- }) ??
2037
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2038
- lastState.response?.totalPages ??
2039
- null;
2040
- this._totalPages$.next(totalPages);
2041
- }), map((stateMaps) => {
2042
- if (!stateMaps.length) {
2043
- return null;
2044
- }
2045
- const fullData = stateMaps.reduce((acc, stateMap) => {
2046
- const valExtractFn = this._config?.response?.valueExtractor;
2047
- let data = valExtractFn
2048
- ? valExtractFn?.(stateMap.state.response)
2049
- : stateMap.state.response;
2050
- if (this._config.response.reverse) {
2051
- data = [...data].reverse();
2052
- }
2053
- if (this._config.response.appendItemsTo === 'start') {
2054
- acc.unshift(...data);
2055
- }
2056
- else {
2057
- acc.push(...data);
2058
- }
2059
- return acc;
2060
- },
2061
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2062
- []);
2063
- return fullData;
2064
- }), shareReplay({ bufferSize: 1, refCount: true }));
2065
- 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);
2066
2090
  }
2067
2091
  nextPage() {
2068
2092
  const newPage = (this._currentPage$.value ?? 0) + 1;
@@ -2154,6 +2178,28 @@ const skipPaginationPageParamCalculator = ({ page, itemsPerPage }) => itemsPerPa
2154
2178
  /* eslint-disable @typescript-eslint/no-explicit-any */
2155
2179
  const INFINITY_QUERY_TOKEN = new InjectionToken('INFINITY_QUERY_TOKEN');
2156
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([]);
2157
2203
  get infinityQuery() {
2158
2204
  return this._infinityQuery;
2159
2205
  }
@@ -2163,6 +2209,7 @@ class InfinityQueryDirective {
2163
2209
  this._infinityQueryInstance = this._setupInfinityQuery(v);
2164
2210
  this._infinityQueryInstance.nextPage();
2165
2211
  }
2212
+ _infinityQuery;
2166
2213
  get context() {
2167
2214
  return this._viewContext;
2168
2215
  }
@@ -2172,33 +2219,11 @@ class InfinityQueryDirective {
2172
2219
  get data$() {
2173
2220
  return this._data$.asObservable();
2174
2221
  }
2222
+ data = toSignal(this._data$, { requireSync: true });
2175
2223
  static ngTemplateContextGuard(dir, ctx) {
2176
2224
  return true;
2177
2225
  }
2178
2226
  constructor() {
2179
- this._queryConfigChanged$ = new Subject();
2180
- this._viewContext = {
2181
- $implicit: null,
2182
- etInfinityQuery: null,
2183
- loading: false,
2184
- error: null,
2185
- isFirstLoad: false,
2186
- canLoadMore: false,
2187
- currentPage: null,
2188
- currentCalculatedPage: null,
2189
- totalPages: null,
2190
- itemsPerPage: null,
2191
- currentQuery: null,
2192
- };
2193
- this._infinityQueryInstance = null;
2194
- this._destroy$ = createDestroy();
2195
- this._cdr = inject(ChangeDetectorRef);
2196
- this._viewContainerRef = inject(ViewContainerRef);
2197
- this._mainTemplateRef = inject((TemplateRef));
2198
- this._errorHandler = inject(ErrorHandler);
2199
- this._delayable = inject(DelayableDirective, { host: true });
2200
- this._data$ = new BehaviorSubject([]);
2201
- this.data = toSignal(this._data$, { requireSync: true });
2202
2227
  this._viewContainerRef.createEmbeddedView(this._mainTemplateRef, this._viewContext);
2203
2228
  }
2204
2229
  _setupInfinityQuery(config) {
@@ -2272,10 +2297,10 @@ class InfinityQueryDirective {
2272
2297
  this._viewContext.currentQuery = null;
2273
2298
  this._data$.next([]);
2274
2299
  }
2275
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2276
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.5", 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 });
2277
2302
  }
2278
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: InfinityQueryDirective, decorators: [{
2303
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryDirective, decorators: [{
2279
2304
  type: Directive,
2280
2305
  args: [{
2281
2306
  selector: '[etInfinityQuery]',
@@ -2290,14 +2315,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2290
2315
  }] } });
2291
2316
 
2292
2317
  class InfinityQueryTriggerDirective {
2293
- constructor() {
2294
- this._elementRef = inject((ElementRef));
2295
- this._infinityQuery = inject(INFINITY_QUERY_TOKEN);
2296
- this._destroy = new Subject();
2297
- this._observer = null;
2298
- this.click$ = fromEvent(this._elementRef.nativeElement, 'click');
2299
- this.scrollContainerSelector = null;
2300
- }
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;
2301
2324
  ngOnInit() {
2302
2325
  const isInteractive = this._elementRef.nativeElement.tagName === 'BUTTON';
2303
2326
  if (isInteractive) {
@@ -2327,10 +2350,10 @@ class InfinityQueryTriggerDirective {
2327
2350
  });
2328
2351
  this._observer.observe(this._elementRef.nativeElement);
2329
2352
  }
2330
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2331
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.5", 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 });
2332
2355
  }
2333
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
2356
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
2334
2357
  type: Directive,
2335
2358
  args: [{
2336
2359
  selector: '[etInfinityQueryTrigger], et-infinity-query-trigger',
@@ -2354,10 +2377,10 @@ class QueryShortNamePipe {
2354
2377
  }
2355
2378
  return route;
2356
2379
  }
2357
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryShortNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
2358
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.5", 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" });
2359
2382
  }
2360
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryShortNamePipe, decorators: [{
2383
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryShortNamePipe, decorators: [{
2361
2384
  type: Pipe,
2362
2385
  args: [{ name: 'queryShortName', standalone: true }]
2363
2386
  }] });
@@ -2375,161 +2398,159 @@ const provideQueryClientForDevtools = (queryClient) => {
2375
2398
  };
2376
2399
 
2377
2400
  class QueryDevtoolsComponent {
2378
- constructor() {
2379
- this._cdr = inject(ChangeDetectorRef);
2380
- this._destroy$ = createDestroy();
2381
- this.queryClientConfigs = inject(QUERY_CLIENT_DEVTOOLS_TOKEN);
2382
- this.isOpen = signal(false);
2383
- this.isTranslucent = signal(false);
2384
- this.snapLayout = signal('full');
2385
- this.queryListMode = signal('live');
2386
- this.viewMode = signal('query');
2387
- this.showResponse = signal(false);
2388
- this.showRawResponse = signal(false);
2389
- this.showQueryConfig = signal(false);
2390
- this.showEntityStoreValue = signal(false);
2391
- this.showArguments = signal(false);
2392
- this.selectedClientIdCtrl = new FormControl(0);
2393
- this.selectedClientId = toSignal(this.selectedClientIdCtrl.valueChanges.pipe(startWith(this.selectedClientIdCtrl.value)));
2394
- this.selectedQueryId = signal(null);
2395
- this.selectedClientConfig = computed(() => {
2396
- if (this.queryClientConfigs.length === 1) {
2397
- return this.queryClientConfigs[0];
2398
- }
2399
- const index = this.selectedClientId() ?? 0;
2400
- const cfg = this.queryClientConfigs[index];
2401
- if (!cfg) {
2402
- return this.queryClientConfigs[0];
2403
- }
2404
- return cfg;
2405
- });
2406
- this.queryStore = computed(() => {
2407
- const config = this.selectedClientConfig();
2408
- return config.client._store;
2409
- });
2410
- this.queryStore$ = toObservable(this.queryStore);
2411
- this._queries$ = new BehaviorSubject([]);
2412
- this.queries = toSignal(this._queries$);
2413
- this.selectedQuery = computed(() => {
2414
- const id = this.selectedQueryId();
2415
- const mode = this.queryListMode();
2416
- if (id === null || !mode) {
2417
- return null;
2418
- }
2419
- if (mode === 'live') {
2420
- return this.queries()?.find((q) => q._id === id) ?? null;
2421
- }
2422
- return this.queryHistory$.getValue()?.find((q) => q._id === id) ?? null;
2423
- });
2424
- this.selectedQuery$ = toObservable(this.selectedQuery);
2425
- this.selectedQueryEntityStore = computed(() => {
2426
- const query = this.selectedQuery();
2427
- if (!query)
2428
- return null;
2429
- return query.store;
2430
- });
2431
- this.selectedQueryEntityStore$ = toObservable(this.selectedQueryEntityStore);
2432
- this.selectedQueryEntityStoreValue$ = this.selectedQueryEntityStore$.pipe(switchMap((s) => s?._change$.pipe(startWith(''), map(() => {
2433
- if (!s._dictionary)
2434
- return null;
2435
- return Array.from(s._dictionary).reduce((obj, [key, value]) => {
2436
- obj[key] = value;
2437
- return obj;
2438
- }, {});
2439
- })) ?? of(null)));
2440
- this.queryHistory$ = new BehaviorSubject([]);
2441
- this.stringifiedQueryConfig = computed(() => {
2442
- const query = this.selectedQuery();
2443
- if (!query)
2444
- return null;
2445
- const cfg = query._queryConfig;
2446
- const route = typeof cfg.route === 'string' ? cfg.route : cfg.route ? cfg.route({}).replace(/undefined/g, ':param') : null;
2447
- const sharedCfg = {
2448
- method: cfg.method,
2449
- secure: cfg.secure,
2450
- route,
2451
- reportProgress: cfg.reportProgress,
2452
- responseType: cfg.responseType,
2453
- withCredentials: cfg.withCredentials,
2454
- autoRefreshOn: cfg.autoRefreshOn,
2455
- enableSmartPolling: cfg.enableSmartPolling,
2456
- hasEntityStore: !!cfg.entity,
2457
- };
2458
- if (isGqlQueryConfig(cfg)) {
2459
- return {
2460
- ...sharedCfg,
2461
- query: cfg.query,
2462
- transferVia: cfg.transferVia,
2463
- };
2464
- }
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)) {
2465
2481
  return {
2466
2482
  ...sharedCfg,
2483
+ query: cfg.query,
2484
+ transferVia: cfg.transferVia,
2467
2485
  };
2468
- });
2469
- this.authProvider = toSignal(toObservable(this.selectedClientConfig).pipe(switchMap((c) => c.client.authProvider$)));
2470
- this.authProviderDetails = computed(() => {
2471
- const provider = this.authProvider();
2472
- if (!provider)
2473
- return null;
2474
- if (provider instanceof CustomHeaderAuthProvider) {
2475
- return {
2476
- type: 'CustomHeaderAuthProvider',
2477
- header: () => provider.header,
2478
- provider: provider,
2479
- config: {
2480
- name: provider._config.name,
2481
- value: provider._config.value,
2482
- },
2483
- };
2484
- }
2485
- else if (provider instanceof BasicAuthProvider) {
2486
- return {
2487
- type: 'BasicAuthProvider',
2488
- header: () => provider.header,
2489
- provider: provider,
2490
- config: {
2491
- username: provider._config.username,
2492
- password: provider._config.password,
2493
- },
2494
- };
2495
- }
2496
- else if (isBearerAuthProvider(provider)) {
2497
- const refreshCfg = provider._config.refreshConfig;
2498
- return {
2499
- type: 'BearerAuthProvider',
2500
- header: () => provider.header,
2501
- provider: provider,
2502
- config: {
2503
- token: provider._config.token,
2504
- refreshConfig: {
2505
- refreshOnUnauthorizedResponse: refreshCfg?.refreshOnUnauthorizedResponse ?? 'true (default)',
2506
- token: refreshCfg?.token,
2507
- cookieName: refreshCfg?.cookieName,
2508
- cookieDomain: refreshCfg?.cookieDomain ?? 'current origin (default)',
2509
- cookieExpiresInDays: refreshCfg?.cookieExpiresInDays ?? '30 (default)',
2510
- cookiePath: refreshCfg?.cookiePath ?? '/ (default)',
2511
- cookieEnabled: refreshCfg?.cookieEnabled ?? 'true (default)',
2512
- cookieSameSite: refreshCfg?.cookieSameSite ?? 'lax (default)',
2513
- refreshBuffer: refreshCfg?.refreshBuffer ?? '30000 (default)',
2514
- expiresInPropertyName: refreshCfg?.expiresInPropertyName ?? 'exp (default)',
2515
- strategy: refreshCfg?.strategy ?? 'AuthBearerRefreshStrategy.BeforeExpiration (default)',
2516
- requestArgsAdapter: refreshCfg?.requestArgsAdapter ? 'custom' : 'default',
2517
- responseAdapter: refreshCfg?.responseAdapter ? 'custom' : 'default',
2518
- },
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',
2519
2540
  },
2520
- };
2521
- }
2522
- else {
2523
- return {
2524
- type: 'UnknownAuthProvider',
2525
- header: () => provider.header,
2526
- provider: provider,
2527
- config: {},
2528
- };
2529
- }
2530
- });
2531
- this.trackByClient = (_, { client }) => client.config.baseRoute;
2532
- 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() {
2533
2554
  this.selectedClientIdCtrl.valueChanges
2534
2555
  .pipe(tap(() => this.clearQueryHistory()), takeUntil(this._destroy$))
2535
2556
  .subscribe();
@@ -2609,6 +2630,8 @@ class QueryDevtoolsComponent {
2609
2630
  this.viewMode.set(parsed.viewMode ?? 'query');
2610
2631
  }
2611
2632
  }
2633
+ trackByClient = (_, { client }) => client.config.baseRoute;
2634
+ trackByQuery = (_, { _id }) => _id;
2612
2635
  toggleOpen() {
2613
2636
  this.isOpen.set(!this.isOpen());
2614
2637
  }
@@ -2648,10 +2671,10 @@ class QueryDevtoolsComponent {
2648
2671
  clearQueryHistory() {
2649
2672
  this.queryHistory$.next([]);
2650
2673
  }
2651
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2652
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", 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 });
2653
2676
  }
2654
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
2677
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
2655
2678
  type: Component,
2656
2679
  args: [{ selector: 'et-query-devtools', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, host: {
2657
2680
  class: 'et-query-devtools',
@@ -2659,6 +2682,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2659
2682
  }], ctorParameters: () => [] });
2660
2683
 
2661
2684
  class EntityStoreError extends Error {
2685
+ detail;
2662
2686
  constructor(message, detail) {
2663
2687
  super(message);
2664
2688
  this.detail = detail;
@@ -2669,16 +2693,17 @@ function flatten(arr) {
2669
2693
  return arr.reduce((acc, val) => acc.concat(val), []);
2670
2694
  }
2671
2695
  class EntityStore {
2696
+ _config;
2697
+ /**
2698
+ * @internal
2699
+ */
2700
+ _dictionary = new Map();
2701
+ /**
2702
+ * @internal
2703
+ */
2704
+ _change$ = new Subject();
2672
2705
  constructor(_config) {
2673
2706
  this._config = _config;
2674
- /**
2675
- * @internal
2676
- */
2677
- this._dictionary = new Map();
2678
- /**
2679
- * @internal
2680
- */
2681
- this._change$ = new Subject();
2682
2707
  }
2683
2708
  select(keyOrKeys) {
2684
2709
  if (Array.isArray(keyOrKeys)) {
@@ -2813,71 +2838,74 @@ const removeFrom = (store, { where, id }) => {
2813
2838
  };
2814
2839
 
2815
2840
  const queryFeatureUsedMultipleTimes = (type) => {
2816
- 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.`);
2817
2842
  };
2818
2843
  const withArgsQueryFeatureMissingButRouteIsFunction = () => {
2819
- 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.`);
2820
2845
  };
2821
2846
  const withPollingUsedOnUnsupportedHttpMethod = (method) => {
2822
- 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.`);
2823
2848
  };
2824
2849
  const withAutoRefreshUsedOnUnsupportedHttpMethod = (method) => {
2825
- 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.`);
2826
2851
  };
2827
2852
  const withAutoRefreshUsedInManualQuery = () => {
2828
- 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.` +
2829
2854
  ` If this is intentional, set "ignoreOnlyManualExecution" to true inside the auto refresh config.`);
2830
2855
  };
2831
2856
  const cookieLoginTriedButCookieDisabled = () => {
2832
- 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.`);
2833
2858
  };
2834
2859
  const enableCookieCalledWithoutCookieConfig = () => {
2835
- 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.`);
2836
2861
  };
2837
2862
  const disableCookieCalledWithoutCookieConfig = () => {
2838
- 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.`);
2839
2864
  };
2840
2865
  const loginCalledWithoutConfig = () => {
2841
- 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.`);
2842
2867
  };
2843
2868
  const loginWithTokenCalledWithoutConfig = () => {
2844
- 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.`);
2845
2870
  };
2846
2871
  const refreshTokenCalledWithoutConfig = () => {
2847
- 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.`);
2848
2873
  };
2849
2874
  const selectRoleCalledWithoutConfig = () => {
2850
- 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.`);
2851
2876
  };
2852
2877
  const defaultResponseTransformerResponseNotObject = (currentType) => {
2853
- 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}".`);
2854
2879
  };
2855
2880
  const defaultResponseTransformerResponseNotContainingAccessToken = () => {
2856
- 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.`);
2857
2882
  };
2858
2883
  const defaultResponseTransformerResponseNotContainingRefreshToken = () => {
2859
- 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.`);
2860
2885
  };
2861
2886
  const unableToDecryptBearerToken = (token) => {
2862
- 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}`);
2863
2888
  };
2864
2889
  const bearerExpiresInPropertyNotNumber = (expiresIn) => {
2865
- 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}`);
2866
2891
  };
2867
2892
  const uncacheableRequestHasCacheKeyParam = (key) => {
2868
- 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.`);
2869
2894
  };
2870
2895
  const uncacheableRequestHasAllowCacheParam = () => {
2871
- return new RuntimeError(301 /* RuntimeErrorCode.UNCACHEABLE_REQUEST_HAS_ALLOW_CACHE_PARAM */, `This request is uncacheable, but allowCache is set to true. Please remove it.`);
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.`);
2872
2897
  };
2873
- const pagedQueryPageBiggerThanTotalPages = (page, totalPages) => {
2874
- 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}".`);
2875
2900
  };
2876
- const pagedQueryNextPageCalledWithoutPreviousPage = () => {
2877
- 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.`);
2878
2903
  };
2879
- const pagedQueryPreviousPageCalledButAlreadyAtFirstPage = () => {
2880
- 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.`);
2881
2909
  };
2882
2910
 
2883
2911
  const defaultResponseTransformer = (response) => {
@@ -3041,10 +3069,10 @@ const createBearerAuthProvider = (options) => {
3041
3069
  };
3042
3070
  const logout = () => {
3043
3071
  deleteCookie$1();
3044
- loginQuery?.query.execute.reset();
3045
- tokenLoginQuery?.query.execute.reset();
3046
- tokenRefreshQuery?.query.execute.reset();
3047
- selectRoleQuery?.query.execute.reset();
3072
+ loginQuery?.query.reset();
3073
+ tokenLoginQuery?.query.reset();
3074
+ tokenRefreshQuery?.query.reset();
3075
+ selectRoleQuery?.query.reset();
3048
3076
  latestNonInternalQuery.set(null);
3049
3077
  };
3050
3078
  const enableCookie = () => {
@@ -3136,29 +3164,81 @@ const createBearerAuthProviderConfig = (options) => {
3136
3164
  return bearerAuthProviderConfig;
3137
3165
  };
3138
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
+
3139
3228
  /**
3140
- * 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.
3141
3230
  * This will also pause polling and auto refresh until new args are set.
3142
3231
  */
3143
- const QUERY_ARGS_RESET = Symbol('QUERY_ARGS_RESET');
3232
+ const CLEAR_QUERY_ARGS = Symbol('CLEAR_QUERY_ARGS');
3144
3233
  const QUERY_EFFECT_ERROR_MESSAGE = 'Effect triggered too often. This is probably due to a circular dependency inside the query.';
3145
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. */
3146
3235
  const queryEffect = (fn, errorMessage, options) => {
3147
3236
  let lastTriggerTs = 0;
3148
3237
  let illegalWrites = 0;
3149
- // The first run should be synchronous anf not depend on the angular scheduler
3150
- if (options?.injector) {
3151
- runInInjectionContext(options.injector, () => fn());
3152
- }
3153
- else {
3154
- fn();
3155
- }
3156
3238
  let isFirstRun = true;
3157
- return untracked(() => effect(() => {
3158
- if (isFirstRun) {
3159
- isFirstRun = false;
3160
- return;
3161
- }
3239
+ const activeConsumer = getActiveConsumer();
3240
+ setActiveConsumer(null);
3241
+ const eff = effect(() => {
3162
3242
  if (isDevMode()) {
3163
3243
  const now = performance.now();
3164
3244
  if (now - lastTriggerTs < 100) {
@@ -3169,12 +3249,20 @@ const queryEffect = (fn, errorMessage, options) => {
3169
3249
  }
3170
3250
  lastTriggerTs = now;
3171
3251
  }
3172
- fn();
3173
- }, options));
3252
+ fn(isFirstRun);
3253
+ if (isFirstRun) {
3254
+ isFirstRun = false;
3255
+ }
3256
+ }, options);
3257
+ setActiveConsumer(activeConsumer);
3258
+ return eff;
3174
3259
  };
3175
3260
  const shouldAutoExecuteQuery = (method) => {
3176
3261
  return method === 'GET' || method === 'HEAD' || method === 'OPTIONS';
3177
3262
  };
3263
+ const shouldAutoExecuteGqlQuery = (method) => {
3264
+ return method === 'QUERY';
3265
+ };
3178
3266
  const extractExpiresInSeconds = (headers) => {
3179
3267
  const cacheControl = headers.get('cache-control');
3180
3268
  const age = headers.get('age');
@@ -3231,8 +3319,8 @@ const shouldRetryRequest = (options) => {
3231
3319
  return { retry: false };
3232
3320
  }
3233
3321
  const { status, error: detail, headers } = error;
3234
- // Retry on 5xx errors
3235
- if (status >= 500) {
3322
+ // Retry on 5xx errors (except 500 internal server error since those are usually not recoverable)
3323
+ if (status >= 501) {
3236
3324
  // Don't retry if a requested page is out of range
3237
3325
  if (isSymfonyPagerfantaOutOfRangeError(detail)) {
3238
3326
  return { retry: false };
@@ -3260,9 +3348,11 @@ const shouldRetryRequest = (options) => {
3260
3348
  return { retry: false };
3261
3349
  };
3262
3350
  const getQueryFeatureUsage = (options) => {
3263
- const { creator, creatorInternals, features, queryConfig } = options;
3351
+ const { creator, features, queryConfig } = options;
3264
3352
  const hasWithArgsFeature = features.some((f) => f.type == "withArgs" /* QueryFeatureType.WithArgs */);
3265
- const shouldAutoExecuteMethod = shouldAutoExecuteQuery(creatorInternals.method);
3353
+ const shouldAutoExecuteMethod = isCreateGqlQueryOptions(options)
3354
+ ? shouldAutoExecuteGqlQuery(options.creatorInternals.method)
3355
+ : shouldAutoExecuteQuery(options.creatorInternals.method);
3266
3356
  const shouldAutoExecute = shouldAutoExecuteMethod && !queryConfig.onlyManualExecution;
3267
3357
  const hasRouteFunction = typeof creator.route === 'function';
3268
3358
  if (hasRouteFunction && !hasWithArgsFeature) {
@@ -3273,12 +3363,16 @@ const getQueryFeatureUsage = (options) => {
3273
3363
  shouldAutoExecuteMethod,
3274
3364
  shouldAutoExecute,
3275
3365
  hasRouteFunction,
3366
+ onlyManualExecution: queryConfig.onlyManualExecution,
3367
+ method: isCreateGqlQueryOptions(options)
3368
+ ? `GQL ${options.creatorInternals.method}`
3369
+ : options.creatorInternals.method,
3276
3370
  };
3277
3371
  return featureFnContext;
3278
3372
  };
3279
- const applyQueryFeatures = (options, context) => {
3373
+ const applyQueryFeatures = (features, context) => {
3280
3374
  const featureTypes = new Set();
3281
- for (const feature of options.features) {
3375
+ for (const feature of features) {
3282
3376
  if (featureTypes.has(feature.type)) {
3283
3377
  throw queryFeatureUsedMultipleTimes(feature.type);
3284
3378
  }
@@ -3286,13 +3380,16 @@ const applyQueryFeatures = (options, context) => {
3286
3380
  feature.fn(context);
3287
3381
  }
3288
3382
  };
3383
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3289
3384
  const maybeExecute = (options) => {
3290
3385
  if (options.flags.shouldAutoExecute && !options.flags.hasRouteFunction && !options.flags.hasWithArgsFeature) {
3291
3386
  options.execute();
3292
3387
  }
3293
3388
  };
3294
3389
  const createQueryObject = (options) => {
3295
- 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 });
3296
3393
  const query = {
3297
3394
  execute,
3298
3395
  args: state.args.asReadonly(),
@@ -3301,12 +3398,44 @@ const createQueryObject = (options) => {
3301
3398
  loading: state.loading.asReadonly(),
3302
3399
  error: state.error.asReadonly(),
3303
3400
  lastTimeExecutedAt: state.lastTimeExecutedAt.asReadonly(),
3304
- id: execute.currentRepositoryKey,
3401
+ id: normalizeQueryRepositoryKey(execute.currentRepositoryKey),
3305
3402
  createSnapshot,
3306
- destroy,
3403
+ reset: execute.reset,
3404
+ subtle: {
3405
+ destroy,
3406
+ },
3307
3407
  };
3308
3408
  return query;
3309
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
+ };
3310
3439
 
3311
3440
  const SPEED_BUFFER_TIME_IN_MS = 2000;
3312
3441
  const createHttpRequest = (options) => {
@@ -3459,6 +3588,15 @@ const createHttpRequest = (options) => {
3459
3588
  const createQueryFeature = (config) => {
3460
3589
  return config;
3461
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
+ */
3462
3600
  const withArgs = (args) => {
3463
3601
  return createQueryFeature({
3464
3602
  type: "withArgs" /* QueryFeatureType.WithArgs */,
@@ -3469,7 +3607,7 @@ const withArgs = (args) => {
3469
3607
  if (currArgsNow === null)
3470
3608
  return;
3471
3609
  untracked(() => {
3472
- if (currArgsNow === QUERY_ARGS_RESET) {
3610
+ if (currArgsNow === CLEAR_QUERY_ARGS) {
3473
3611
  context.state.args.set(null);
3474
3612
  return;
3475
3613
  }
@@ -3481,12 +3619,19 @@ const withArgs = (args) => {
3481
3619
  },
3482
3620
  });
3483
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
+ */
3484
3629
  const withPolling = (options) => {
3485
3630
  return createQueryFeature({
3486
3631
  type: "withPolling" /* QueryFeatureType.WithPolling */,
3487
3632
  fn: (context) => {
3488
3633
  if (!context.flags.shouldAutoExecuteMethod) {
3489
- throw withPollingUsedOnUnsupportedHttpMethod(context.creatorInternals.method);
3634
+ throw withPollingUsedOnUnsupportedHttpMethod(context.flags.method);
3490
3635
  }
3491
3636
  let intervalId = null;
3492
3637
  queryEffect(() => {
@@ -3494,7 +3639,9 @@ const withPolling = (options) => {
3494
3639
  untracked(() => {
3495
3640
  if (intervalId !== null)
3496
3641
  clearInterval(intervalId);
3497
- 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)
3498
3645
  return;
3499
3646
  if (options.executeInitially) {
3500
3647
  context.execute({ args });
@@ -3508,68 +3655,78 @@ const withPolling = (options) => {
3508
3655
  },
3509
3656
  });
3510
3657
  };
3658
+ /** A query feature that can be used to log the latest http event */
3511
3659
  const withLogging = (options) => {
3512
3660
  return createQueryFeature({
3513
3661
  type: "withLogging" /* QueryFeatureType.WithLogging */,
3514
3662
  fn: (context) => {
3515
- effect(() => {
3663
+ queryEffect(() => {
3516
3664
  const event = context.state.latestHttpEvent();
3517
3665
  if (event === null)
3518
3666
  return;
3519
3667
  untracked(() => {
3520
3668
  options.logFn(event);
3521
3669
  });
3522
- }, { injector: context.deps.injector });
3670
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3523
3671
  },
3524
3672
  });
3525
3673
  };
3674
+ /** A query feature that can be used to handle errors */
3526
3675
  const withErrorHandling = (options) => {
3527
3676
  return createQueryFeature({
3528
3677
  type: "withErrorHandling" /* QueryFeatureType.WithErrorHandling */,
3529
3678
  fn: (context) => {
3530
- effect(() => {
3679
+ queryEffect(() => {
3531
3680
  const error = context.state.error();
3532
3681
  if (error === null)
3533
3682
  return;
3534
3683
  untracked(() => {
3535
3684
  options.handler(error);
3536
3685
  });
3537
- }, { injector: context.deps.injector });
3686
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3538
3687
  },
3539
3688
  });
3540
3689
  };
3690
+ /** A query feature that can be used to handle successful responses */
3541
3691
  const withSuccessHandling = (options) => {
3542
3692
  return createQueryFeature({
3543
3693
  type: "withSuccessHandling" /* QueryFeatureType.WithSuccessHandling */,
3544
3694
  fn: (context) => {
3545
- effect(() => {
3695
+ queryEffect(() => {
3546
3696
  const response = context.state.response();
3547
3697
  if (response === null)
3548
3698
  return;
3549
3699
  untracked(() => {
3550
3700
  options.handler(response);
3551
3701
  });
3552
- }, { injector: context.deps.injector });
3702
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3553
3703
  },
3554
3704
  });
3555
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
+ */
3556
3711
  const withAutoRefresh = (options) => {
3557
3712
  return createQueryFeature({
3558
3713
  type: "withAutoRefresh" /* QueryFeatureType.WithAutoRefresh */,
3559
3714
  fn: (context) => {
3560
3715
  if (!context.flags.shouldAutoExecuteMethod) {
3561
- throw withAutoRefreshUsedOnUnsupportedHttpMethod(context.creatorInternals.method);
3716
+ throw withAutoRefreshUsedOnUnsupportedHttpMethod(context.flags.method);
3562
3717
  }
3563
- if (context.queryConfig.onlyManualExecution && !options.ignoreOnlyManualExecution) {
3564
- throw withAutoRefreshUsedOnUnsupportedHttpMethod(context.creatorInternals.method);
3718
+ if (context.flags.onlyManualExecution && !options.ignoreOnlyManualExecution) {
3719
+ throw withAutoRefreshUsedInManualQuery();
3565
3720
  }
3566
3721
  queryEffect(() => {
3567
- for (const signal of options.signalChanges) {
3722
+ for (const signal of options.onSignalChanges) {
3568
3723
  signal();
3569
3724
  }
3570
3725
  untracked(() => {
3571
3726
  const args = context.state.args();
3572
- 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)
3573
3730
  return;
3574
3731
  context.execute({ args });
3575
3732
  });
@@ -3578,10 +3735,12 @@ const withAutoRefresh = (options) => {
3578
3735
  });
3579
3736
  };
3580
3737
 
3738
+ /** Transforms an array of arrays into a single array and filters out `null` values. */
3581
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. */
3582
3741
  const transformPaginatedResponse = (responses) => responses.filter((r) => !!r).flatMap((r) => r.items);
3583
- const createQueryStack = (computation, options) => {
3584
- const { append = false, appendFn = (oldQueries, newQueries) => {
3742
+ const createQueryStack = (options) => {
3743
+ const { args, queryCreator, dependencies, append, features = [], appendFn = (oldQueries, newQueries) => {
3585
3744
  const queries = [...oldQueries, ...newQueries];
3586
3745
  const lastQuery = newQueries[newQueries.length - 1] ?? oldQueries[oldQueries.length - 1] ?? null;
3587
3746
  return { queries, lastQuery };
@@ -3589,9 +3748,21 @@ const createQueryStack = (computation, options) => {
3589
3748
  const injector = inject(Injector);
3590
3749
  const queries = signal([]);
3591
3750
  const lastQuery = signal(null);
3751
+ const hasWithArgsFeature = features.some((f) => f.type == "withArgs" /* QueryFeatureType.WithArgs */);
3752
+ if (hasWithArgsFeature) {
3753
+ throw queryStackWithArgsUsed();
3754
+ }
3592
3755
  effect(() => {
3593
- const newQueryOrQueries = runInInjectionContext(injector, () => computation());
3594
- const newQueries = Array.isArray(newQueryOrQueries) ? newQueryOrQueries : [newQueryOrQueries].filter((q) => !!q);
3756
+ // Clear the stack if dependencies change
3757
+ dependencies?.();
3758
+ untracked(() => clear());
3759
+ });
3760
+ effect(() => {
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)));
3595
3766
  untracked(() => {
3596
3767
  const oldQueries = queries();
3597
3768
  if (append) {
@@ -3602,7 +3773,7 @@ const createQueryStack = (computation, options) => {
3602
3773
  else {
3603
3774
  for (const oldQuery of oldQueries) {
3604
3775
  if (!newQueries.some((q) => q.id() === oldQuery.id())) {
3605
- oldQuery.destroy();
3776
+ oldQuery.subtle.destroy();
3606
3777
  }
3607
3778
  }
3608
3779
  queries.set(newQueries);
@@ -3625,7 +3796,7 @@ const createQueryStack = (computation, options) => {
3625
3796
  };
3626
3797
  const clear = () => {
3627
3798
  for (const query of queries()) {
3628
- query.destroy();
3799
+ query.subtle.destroy();
3629
3800
  }
3630
3801
  queries.set([]);
3631
3802
  lastQuery.set(null);
@@ -3684,23 +3855,31 @@ const contentfulGqlLikePaginationAdapter = (response) => {
3684
3855
  };
3685
3856
  return pagination;
3686
3857
  };
3687
- const createPagedQuery = (options) => {
3688
- 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;
3689
3872
  const currentPageArgs = signal(null);
3690
3873
  const initialPage = signal(options.initialPage ?? 1);
3691
3874
  const loadedMinPage = signal(initialPage());
3692
3875
  const loadedMaxPage = signal(initialPage());
3693
3876
  const lastResetTimestamp = signal(Date.now());
3694
3877
  const pageDirection = signal('next');
3695
- const stack = createQueryStack(() => {
3696
- const args = currentPageArgs();
3697
- if (!args)
3698
- return null;
3699
- return queryCreator(withArgs(() => {
3700
- return args;
3701
- }));
3702
- }, {
3878
+ const stack = createQueryStack({
3879
+ args: () => currentPageArgs(),
3880
+ queryCreator,
3703
3881
  append: true,
3882
+ features,
3704
3883
  appendFn: (oldQueries, newQueries) => {
3705
3884
  const newQuery = newQueries[0];
3706
3885
  const dir = pageDirection();
@@ -3737,7 +3916,7 @@ const createPagedQuery = (options) => {
3737
3916
  const page = loadedMinPage() - 1;
3738
3917
  if (page < 1) {
3739
3918
  if (isDevMode()) {
3740
- throw pagedQueryPreviousPageCalledButAlreadyAtFirstPage();
3919
+ throw pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage();
3741
3920
  }
3742
3921
  return;
3743
3922
  }
@@ -3750,13 +3929,13 @@ const createPagedQuery = (options) => {
3750
3929
  const currentPagination = pagination();
3751
3930
  if (!currentPagination) {
3752
3931
  if (isDevMode()) {
3753
- throw pagedQueryNextPageCalledWithoutPreviousPage();
3932
+ throw pagedQueryStackNextPageCalledWithoutPreviousPage();
3754
3933
  }
3755
3934
  return;
3756
3935
  }
3757
3936
  if (page > currentPagination.totalPages) {
3758
3937
  if (isDevMode()) {
3759
- throw pagedQueryPageBiggerThanTotalPages(page, currentPagination.totalPages);
3938
+ throw pagedQueryStackPageBiggerThanTotalPages(page, currentPagination.totalPages);
3760
3939
  }
3761
3940
  return;
3762
3941
  }
@@ -3839,7 +4018,7 @@ const createPagedQuery = (options) => {
3839
4018
  error: stack.error,
3840
4019
  lastQuery: stack.lastQuery,
3841
4020
  isFirstLoad,
3842
- queries: stack.queries(),
4021
+ queries: stack.queries,
3843
4022
  reset,
3844
4023
  execute,
3845
4024
  };
@@ -3850,12 +4029,32 @@ const setupQueryDependencies = (options) => {
3850
4029
  const environmentInjector = inject(EnvironmentInjector);
3851
4030
  const queryEnvironmentInjector = createEnvironmentInjector([], environmentInjector);
3852
4031
  const destroyRef = queryEnvironmentInjector.get(DestroyRef);
4032
+ const scopeDestroyRef = inject(DestroyRef);
3853
4033
  const client = inject(options.clientConfig.token);
3854
4034
  const dependencies = {
3855
4035
  destroyRef,
4036
+ scopeDestroyRef,
3856
4037
  client,
3857
4038
  injector: queryEnvironmentInjector,
3858
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
+ });
3859
4058
  return dependencies;
3860
4059
  };
3861
4060
 
@@ -3878,7 +4077,7 @@ const setupQueryExecuteState = () => {
3878
4077
  };
3879
4078
  };
3880
4079
  const queryExecute = (options) => {
3881
- const { executeOptions, args, executeState, options: runQueryOptions } = options;
4080
+ const { executeOptions, args, executeState, options: runQueryOptions, internalOptions: internalRunQueryOptions, transformResponse, } = options;
3882
4081
  const { deps, state, creator, creatorInternals, queryConfig } = executeOptions;
3883
4082
  const { key, request } = deps.client.repository.request({
3884
4083
  route: creator.route,
@@ -3893,11 +4092,13 @@ const queryExecute = (options) => {
3893
4092
  destroyRef: deps.destroyRef,
3894
4093
  key: queryConfig.key,
3895
4094
  previousKey: executeState.previousKey(),
4095
+ internalRunQueryOptions,
3896
4096
  runQueryOptions,
3897
4097
  });
3898
4098
  executeState.previousKey.set(key);
4099
+ const responseSignal = transformResponse ? computed(() => transformResponse(request.response())) : request.response;
3899
4100
  runInInjectionContext(deps.injector, () => {
3900
- const responseRef = syncSignal(request.response, state.response);
4101
+ const responseRef = syncSignal(responseSignal, state.response);
3901
4102
  const loadingRef = syncSignal(request.loading, state.loading);
3902
4103
  const errorRef = syncSignal(request.error, state.error);
3903
4104
  const latestHttpEventRef = syncSignal(request.currentEvent, state.latestHttpEvent);
@@ -3924,88 +4125,22 @@ const createExecuteFn = (executeOptions) => {
3924
4125
  return exec;
3925
4126
  };
3926
4127
 
3927
- const setupQueryState = (options) => {
3928
- const response = signal(null);
3929
- const args = signal(null);
3930
- const latestHttpEvent = signal(null);
3931
- const error = signal(null);
3932
- const loading = signal(null);
3933
- const lastTimeExecutedAt = signal(null);
3934
- const state = {
3935
- response,
3936
- args,
3937
- latestHttpEvent,
3938
- loading,
3939
- error,
3940
- lastTimeExecutedAt,
3941
- };
3942
- return state;
3943
- };
3944
-
3945
- const createQuerySnapshotFn = (options) => {
3946
- const { state, deps } = options;
3947
- const snapshotFn = () => {
3948
- const snapshotState = setupQueryState({});
3949
- const isAlive = signal(true);
3950
- const killEffectRef = effect(() => {
3951
- const currentLoading = state.loading();
3952
- const currentError = state.error();
3953
- const currentResponse = state.response();
3954
- const currentArgs = state.args();
3955
- const currentLatestHttpEvent = state.latestHttpEvent();
3956
- const currentLastTimeExecutedAt = state.lastTimeExecutedAt();
3957
- untracked(() => {
3958
- snapshotState.args.set(currentArgs);
3959
- snapshotState.error.set(currentError);
3960
- snapshotState.lastTimeExecutedAt.set(currentLastTimeExecutedAt);
3961
- snapshotState.latestHttpEvent.set(currentLatestHttpEvent);
3962
- snapshotState.loading.set(currentLoading);
3963
- snapshotState.response.set(currentResponse);
3964
- if (currentLoading)
3965
- return;
3966
- if (!currentResponse && !currentError)
3967
- return;
3968
- // kill the effect once loading is done and we either have a response or an error
3969
- killEffectRef.destroy();
3970
- isAlive.set(false);
3971
- });
3972
- }, { injector: deps.injector });
3973
- const snapshot = {
3974
- args: snapshotState.args.asReadonly(),
3975
- response: snapshotState.response.asReadonly(),
3976
- latestHttpEvent: snapshotState.latestHttpEvent.asReadonly(),
3977
- loading: snapshotState.loading.asReadonly(),
3978
- error: snapshotState.error.asReadonly(),
3979
- lastTimeExecutedAt: snapshotState.lastTimeExecutedAt.asReadonly(),
3980
- isAlive: isAlive.asReadonly(),
3981
- id: options.execute.currentRepositoryKey,
3982
- };
3983
- return snapshot;
3984
- };
3985
- return snapshotFn;
3986
- };
3987
-
3988
4128
  /* eslint-disable @typescript-eslint/no-explicit-any */
3989
4129
  const createQuery = (options) => {
3990
4130
  const deps = setupQueryDependencies({ clientConfig: options.creatorInternals.client });
3991
4131
  const state = setupQueryState({});
3992
4132
  const { creator, creatorInternals, queryConfig } = options;
3993
4133
  const flags = getQueryFeatureUsage(options);
3994
- const execute = createExecuteFn({ deps, state, creator, creatorInternals, queryConfig: options.queryConfig });
3995
- const createSnapshot = createQuerySnapshotFn({ state, deps, execute });
3996
- const destroy = () => deps.injector.destroy();
4134
+ const execute = createExecuteFn({ deps, state, creator, creatorInternals, queryConfig });
3997
4135
  const featureFnContext = {
3998
4136
  state,
3999
- queryConfig,
4000
- creatorConfig: creator,
4001
- creatorInternals,
4002
4137
  execute,
4003
4138
  flags,
4004
4139
  deps,
4005
4140
  };
4006
- applyQueryFeatures(options, featureFnContext);
4141
+ applyQueryFeatures(options.features, featureFnContext);
4007
4142
  maybeExecute({ execute, flags });
4008
- return createQueryObject({ state, execute, createSnapshot, destroy });
4143
+ return createQueryObject({ state, execute, deps });
4009
4144
  };
4010
4145
 
4011
4146
  const createQueryRepository = (config) => {
@@ -4013,7 +4148,9 @@ const createQueryRepository = (config) => {
4013
4148
  const cache = new Map();
4014
4149
  const request = (options) => {
4015
4150
  const { args, clientOptions, runQueryOptions } = options;
4016
- const shouldCache = shouldCacheQuery(options.method);
4151
+ const shouldCache = options.internalRunQueryOptions?.useQueryRepositoryCache === false
4152
+ ? false
4153
+ : shouldCacheQuery(options.method) || options.internalRunQueryOptions?.useQueryRepositoryCache === true;
4017
4154
  if (!shouldCache && options.key)
4018
4155
  throw uncacheableRequestHasCacheKeyParam(options.key);
4019
4156
  if (!shouldCache && runQueryOptions?.allowCache)
@@ -4030,8 +4167,7 @@ const createQueryRepository = (config) => {
4030
4167
  body: args?.body,
4031
4168
  queryParams: args?.queryParams,
4032
4169
  pathParams: args?.pathParams,
4033
- // TODO: remaining props
4034
- // headers: args?.headers,
4170
+ headers: args?.headers,
4035
4171
  });
4036
4172
  const previousKey = options.previousKey;
4037
4173
  if (key !== previousKey && previousKey) {
@@ -4113,6 +4249,10 @@ const provideQueryClient = (config) => {
4113
4249
  };
4114
4250
  };
4115
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
+ */
4116
4256
  const createQueryClientConfig = (options) => {
4117
4257
  const token = new InjectionToken(`QueryClient_${options.name}`);
4118
4258
  const clientConfig = {
@@ -4120,6 +4260,9 @@ const createQueryClientConfig = (options) => {
4120
4260
  token,
4121
4261
  name: options.name,
4122
4262
  queryString: options.queryString,
4263
+ // createHttpRequest will use fallbacks if these are not provided
4264
+ cacheAdapter: options.cacheAdapter,
4265
+ retryFn: options.retryFn,
4123
4266
  };
4124
4267
  return clientConfig;
4125
4268
  };
@@ -4236,22 +4379,17 @@ const createSecureQuery = (options) => {
4236
4379
  state,
4237
4380
  creator,
4238
4381
  creatorInternals,
4239
- queryConfig: options.queryConfig,
4382
+ queryConfig,
4240
4383
  });
4241
- const createSnapshot = createQuerySnapshotFn({ state, deps, execute });
4242
- const destroy = () => deps.injector.destroy();
4243
4384
  const featureFnContext = {
4385
+ deps,
4244
4386
  state,
4245
- queryConfig,
4246
- creatorConfig: creator,
4247
- creatorInternals,
4248
4387
  execute,
4249
4388
  flags,
4250
- deps,
4251
4389
  };
4252
- applyQueryFeatures(options, featureFnContext);
4390
+ applyQueryFeatures(options.features, featureFnContext);
4253
4391
  maybeExecute({ execute, flags });
4254
- return createQueryObject({ state, execute, createSnapshot, destroy });
4392
+ return createQueryObject({ state, execute, deps });
4255
4393
  };
4256
4394
 
4257
4395
  const createSecureQueryCreator = (options, internals) => {
@@ -4267,44 +4405,275 @@ const createSecureQueryCreator = (options, internals) => {
4267
4405
  return queryCreator;
4268
4406
  };
4269
4407
 
4408
+ /** A query creator that creates a GET query */
4270
4409
  const createGetQuery = (client) => {
4271
4410
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'GET', client });
4272
4411
  };
4412
+ /** A query creator that creates a secure GET query (requires authentication) */
4273
4413
  const createSecureGetQuery = (client, authProvider) => {
4274
4414
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'GET', client, authProvider });
4275
4415
  };
4416
+ /** A query creator that creates a POST query */
4276
4417
  const createPostQuery = (client) => {
4277
4418
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'POST', client });
4278
4419
  };
4420
+ /** A query creator that creates a secure POST query (requires authentication) */
4279
4421
  const createSecurePostQuery = (client, authProvider) => {
4280
4422
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'POST', client, authProvider });
4281
4423
  };
4424
+ /** A query creator that creates a PUT query */
4282
4425
  const createPutQuery = (client) => {
4283
4426
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'PUT', client });
4284
4427
  };
4428
+ /** A query creator that creates a secure PUT query (requires authentication) */
4285
4429
  const createSecurePutQuery = (client, authProvider) => {
4286
4430
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'PUT', client, authProvider });
4287
4431
  };
4432
+ /** A query creator that creates a DELETE query */
4288
4433
  const createDeleteQuery = (client) => {
4289
4434
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'DELETE', client });
4290
4435
  };
4436
+ /** A query creator that creates a secure DELETE query (requires authentication) */
4291
4437
  const createSecureDeleteQuery = (client, authProvider) => {
4292
4438
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'DELETE', client, authProvider });
4293
4439
  };
4440
+ /** A query creator that creates a PATCH query */
4294
4441
  const createPatchQuery = (client) => {
4295
4442
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'PATCH', client });
4296
4443
  };
4444
+ /** A query creator that creates a secure PATCH query (requires authentication) */
4297
4445
  const createSecurePatchQuery = (client, authProvider) => {
4298
4446
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'PATCH', client, authProvider });
4299
4447
  };
4300
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
+
4301
4669
  var index = /*#__PURE__*/Object.freeze({
4302
4670
  __proto__: null,
4303
- QUERY_ARGS_RESET: QUERY_ARGS_RESET,
4671
+ CLEAR_QUERY_ARGS: CLEAR_QUERY_ARGS,
4304
4672
  QUERY_EFFECT_ERROR_MESSAGE: QUERY_EFFECT_ERROR_MESSAGE,
4305
4673
  SPEED_BUFFER_TIME_IN_MS: SPEED_BUFFER_TIME_IN_MS,
4306
4674
  applyQueryFeatures: applyQueryFeatures,
4307
4675
  bearerExpiresInPropertyNotNumber: bearerExpiresInPropertyNotNumber,
4676
+ buildQueryCacheKey: buildQueryCacheKey,
4308
4677
  cleanupPreviousExecute: cleanupPreviousExecute,
4309
4678
  contentfulGqlLikePaginationAdapter: contentfulGqlLikePaginationAdapter,
4310
4679
  cookieLoginTriedButCookieDisabled: cookieLoginTriedButCookieDisabled,
@@ -4313,8 +4682,15 @@ var index = /*#__PURE__*/Object.freeze({
4313
4682
  createDeleteQuery: createDeleteQuery,
4314
4683
  createExecuteFn: createExecuteFn,
4315
4684
  createGetQuery: createGetQuery,
4685
+ createGqlExecuteFn: createGqlExecuteFn,
4686
+ createGqlMutationViaGet: createGqlMutationViaGet,
4687
+ createGqlMutationViaPost: createGqlMutationViaPost,
4688
+ createGqlQuery: createGqlQuery,
4689
+ createGqlQueryCreator: createGqlQueryCreator,
4690
+ createGqlQueryViaGet: createGqlQueryViaGet,
4691
+ createGqlQueryViaPost: createGqlQueryViaPost,
4316
4692
  createHttpRequest: createHttpRequest,
4317
- createPagedQuery: createPagedQuery,
4693
+ createPagedQueryStack: createPagedQueryStack,
4318
4694
  createPatchQuery: createPatchQuery,
4319
4695
  createPostQuery: createPostQuery,
4320
4696
  createPutQuery: createPutQuery,
@@ -4334,6 +4710,8 @@ var index = /*#__PURE__*/Object.freeze({
4334
4710
  createSecurePutQuery: createSecurePutQuery,
4335
4711
  createSecureQuery: createSecureQuery,
4336
4712
  createSecureQueryCreator: createSecureQueryCreator,
4713
+ createWebSocketClient: createWebSocketClient,
4714
+ createWebSocketClientConfig: createWebSocketClientConfig,
4337
4715
  defaultResponseTransformerResponseNotContainingAccessToken: defaultResponseTransformerResponseNotContainingAccessToken,
4338
4716
  defaultResponseTransformerResponseNotContainingRefreshToken: defaultResponseTransformerResponseNotContainingRefreshToken,
4339
4717
  defaultResponseTransformerResponseNotObject: defaultResponseTransformerResponseNotObject,
@@ -4342,26 +4720,33 @@ var index = /*#__PURE__*/Object.freeze({
4342
4720
  enableCookieCalledWithoutCookieConfig: enableCookieCalledWithoutCookieConfig,
4343
4721
  ethletePaginationAdapter: ethletePaginationAdapter,
4344
4722
  extractExpiresInSeconds: extractExpiresInSeconds,
4723
+ fakePaginationAdapter: fakePaginationAdapter,
4345
4724
  getQueryFeatureUsage: getQueryFeatureUsage,
4346
4725
  ggLikePaginationAdapter: ggLikePaginationAdapter,
4726
+ isCreateGqlQueryOptions: isCreateGqlQueryOptions,
4347
4727
  loginCalledWithoutConfig: loginCalledWithoutConfig,
4348
4728
  loginWithTokenCalledWithoutConfig: loginWithTokenCalledWithoutConfig,
4349
4729
  maybeExecute: maybeExecute,
4350
- pagedQueryNextPageCalledWithoutPreviousPage: pagedQueryNextPageCalledWithoutPreviousPage,
4351
- pagedQueryPageBiggerThanTotalPages: pagedQueryPageBiggerThanTotalPages,
4352
- pagedQueryPreviousPageCalledButAlreadyAtFirstPage: pagedQueryPreviousPageCalledButAlreadyAtFirstPage,
4730
+ normalizeQueryRepositoryKey: normalizeQueryRepositoryKey,
4731
+ pagedQueryStackNextPageCalledWithoutPreviousPage: pagedQueryStackNextPageCalledWithoutPreviousPage,
4732
+ pagedQueryStackPageBiggerThanTotalPages: pagedQueryStackPageBiggerThanTotalPages,
4733
+ pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage: pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage,
4353
4734
  provideBearerAuthProvider: provideBearerAuthProvider,
4354
4735
  provideQueryClient: provideQueryClient,
4736
+ provideWebSocketClient: provideWebSocketClient,
4355
4737
  queryEffect: queryEffect,
4356
4738
  queryExecute: queryExecute,
4357
4739
  queryFeatureUsedMultipleTimes: queryFeatureUsedMultipleTimes,
4740
+ queryStackWithArgsUsed: queryStackWithArgsUsed,
4358
4741
  refreshTokenCalledWithoutConfig: refreshTokenCalledWithoutConfig,
4359
4742
  resetExecuteState: resetExecuteState,
4360
4743
  selectRoleCalledWithoutConfig: selectRoleCalledWithoutConfig,
4361
4744
  setupQueryDependencies: setupQueryDependencies,
4362
4745
  setupQueryExecuteState: setupQueryExecuteState,
4363
4746
  setupQueryState: setupQueryState,
4747
+ shouldAutoExecuteGqlQuery: shouldAutoExecuteGqlQuery,
4364
4748
  shouldAutoExecuteQuery: shouldAutoExecuteQuery,
4749
+ shouldCacheQuery: shouldCacheQuery,
4365
4750
  shouldRetryRequest: shouldRetryRequest,
4366
4751
  splitQueryConfig: splitQueryConfig,
4367
4752
  transformArrayResponse: transformArrayResponse,
@@ -4480,6 +4865,7 @@ const transformToSortQueryParam = (value) => {
4480
4865
 
4481
4866
  const ET_ARR_PREFIX = 'ET_ARR__';
4482
4867
  class QueryField {
4868
+ data;
4483
4869
  get control() {
4484
4870
  return this.data.control;
4485
4871
  }
@@ -4490,12 +4876,70 @@ class QueryField {
4490
4876
  const IGNORED_FILTER_COUNT_FIELDS = ['page', 'skip', 'take', 'limit', 'sort', 'sortBy', 'sortOrder', 'query', 'search'];
4491
4877
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4492
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);
4493
4905
  get _formValue() {
4494
4906
  return this.form.getRawValue();
4495
4907
  }
4496
4908
  get _form() {
4497
4909
  return this.form;
4498
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));
4499
4943
  get controls() {
4500
4944
  return this.form.controls;
4501
4945
  }
@@ -4512,62 +4956,6 @@ class QueryForm {
4512
4956
  constructor(_fields, _options) {
4513
4957
  this._fields = _fields;
4514
4958
  this._options = _options;
4515
- this._destroy$ = createDestroy();
4516
- this._unobserveTrigger$ = new Subject();
4517
- this._router = inject(Router);
4518
- this._activatedRoute = inject(ActivatedRoute);
4519
- this._defaultValues = this._extractDefaultValues();
4520
- this._zone = inject(NgZone);
4521
- this._didValueChanges$ = new Subject();
4522
- this._isObserving = false;
4523
- this._skipNextResets = false;
4524
- this._queryParamChanges$ = toObservable(injectQueryParamChanges());
4525
- this._queryParams = injectQueryParams();
4526
- /**
4527
- * The angular form group that contains all the fields.
4528
- *
4529
- * **Do not** use any of the following methods on this form group:
4530
- * - `setValue`: Use `QueryForm.setValue` instead.
4531
- * - `patchValue`: Use `QueryForm.patchValue` instead.
4532
- * - `valueChanges`: Use `QueryForm.changes$` instead.
4533
- * - `value`: Use `QueryForm.value` instead.
4534
- * - `controls`: Use `QueryForm.controls` instead.
4535
- */
4536
- this.form = this._setupFormGroup();
4537
- this._lastFormValue$ = new BehaviorSubject(null);
4538
- this._currentFormValue$ = new BehaviorSubject(this._formValue);
4539
- this._changes$ = new BehaviorSubject({
4540
- previousValue: null,
4541
- currentValue: this.form.getRawValue(),
4542
- });
4543
- this.changes$ = this._changes$.asObservable();
4544
- this.currentValue$ = this._changes$.pipe(map(({ currentValue }) => currentValue));
4545
- this.previousValue$ = this._changes$.pipe(map(({ previousValue }) => previousValue));
4546
- this.changes = toSignal(this.changes$);
4547
- this.currentValue = toSignal(this.currentValue$);
4548
- this.previousValue = toSignal(this.previousValue$);
4549
- /**
4550
- * The number of active filters.
4551
- *
4552
- * Excludes the following fields by default:
4553
- * - `page`
4554
- * - `skip`
4555
- * - `take`
4556
- * - `limit`
4557
- * - `sort`
4558
- * - `sortBy`
4559
- * - `sortOrder`
4560
- * - `query`
4561
- * - `search`
4562
- */
4563
- this.activeFilterCount$ = this.changes$.pipe(map(({ currentValue }) => Object.entries(currentValue)
4564
- .map(([key, value]) => {
4565
- if (IGNORED_FILTER_COUNT_FIELDS.includes(key) || this._fields[key]?.data.skipInFilterCount) {
4566
- return true;
4567
- }
4568
- return this._isDefaultValue(key, value);
4569
- })
4570
- .filter((v) => v === false).length));
4571
4959
  assertInInjectionContext(QueryForm);
4572
4960
  inject(DestroyRef).onDestroy(() => this._cleanup());
4573
4961
  }
@@ -4889,5 +5277,5 @@ class QueryForm {
4889
5277
  * Generated bundle index. Do not edit.
4890
5278
  */
4891
5279
 
4892
- 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 };
4893
5281
  //# sourceMappingURL=ethlete-query.mjs.map