@ethlete/query 5.24.0 → 5.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/fesm2022/ethlete-query.mjs +545 -524
- package/fesm2022/ethlete-query.mjs.map +1 -1
- package/lib/experimental/auth/bearer-auth-provider-config.d.ts +10 -0
- package/lib/experimental/http/paged-query-stack.d.ts +10 -10
- package/lib/experimental/http/query-errors.d.ts +3 -1
- package/lib/experimental/http/query-features.d.ts +36 -1
- package/lib/experimental/http/query-state.d.ts +5 -1
- package/lib/experimental/http/query.d.ts +4 -2
- package/lib/experimental/ws/web-socket-client-config.d.ts +3 -1
- package/lib/experimental/ws/web-socket-client.d.ts +27 -10
- package/lib/experimental/ws/web-socket-errors.d.ts +5 -7
- package/package.json +1 -1
|
@@ -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, 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,
|
|
2
|
+
import { createDestroy, computedTillTruthy, syncSignal, getCookie, setCookie, deleteCookie, DelayableDirective, nextFrame, RuntimeError, isObject, injectRoute, 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, shareReplay, ReplaySubject, 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';
|
|
@@ -13,7 +13,6 @@ import { io } from 'socket.io-client';
|
|
|
13
13
|
import { Router, ActivatedRoute } from '@angular/router';
|
|
14
14
|
|
|
15
15
|
class CustomHeaderAuthProvider {
|
|
16
|
-
_config;
|
|
17
16
|
get header() {
|
|
18
17
|
return { [this._config.name]: this._config.value };
|
|
19
18
|
}
|
|
@@ -26,7 +25,6 @@ class CustomHeaderAuthProvider {
|
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
class BasicAuthProvider {
|
|
29
|
-
_config;
|
|
30
28
|
get header() {
|
|
31
29
|
return { Authorization: `Basic ${this._basicAuthString}` };
|
|
32
30
|
}
|
|
@@ -43,7 +41,6 @@ class BasicAuthProvider {
|
|
|
43
41
|
|
|
44
42
|
const buildErrorMessage = (code, message) => `[@ethlete\\query:${code}] ${message}`;
|
|
45
43
|
class QueryError extends Error {
|
|
46
|
-
data;
|
|
47
44
|
constructor(code, message, data) {
|
|
48
45
|
super(buildErrorMessage(code, message));
|
|
49
46
|
this.name = 'QueryError';
|
|
@@ -699,71 +696,67 @@ const deepFreeze = (object) => {
|
|
|
699
696
|
const def = () => null;
|
|
700
697
|
|
|
701
698
|
class QueryCreator {
|
|
702
|
-
_queryConfig;
|
|
703
|
-
_client;
|
|
704
|
-
_store;
|
|
705
699
|
constructor(_queryConfig, _client, _store) {
|
|
706
700
|
this._queryConfig = _queryConfig;
|
|
707
701
|
this._client = _client;
|
|
708
702
|
this._store = _store;
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
703
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
704
|
+
// @ts-ignore
|
|
705
|
+
this.prepare = (args) => {
|
|
706
|
+
const route = buildRoute({
|
|
707
|
+
base: this._client.config.baseRoute,
|
|
708
|
+
route: this._queryConfig.route,
|
|
709
|
+
pathParams: args?.pathParams,
|
|
710
|
+
queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
|
|
711
|
+
queryParamConfig: this._client.config.request?.queryParams,
|
|
712
|
+
});
|
|
713
|
+
const cacheKey = (args?.config?.queryStoreCacheKey ?? '') + buildQueryCacheKey$1(route, args);
|
|
714
|
+
if (shouldCacheQuery$1(this._queryConfig.method) && !args?.config?.skipQueryStore) {
|
|
715
|
+
const existingQuery = this._store.get(cacheKey);
|
|
716
|
+
if (existingQuery) {
|
|
717
|
+
return existingQuery;
|
|
718
|
+
}
|
|
725
719
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
720
|
+
const query = new Query(this._client, this._queryConfig, route, args ?? {}, cacheKey);
|
|
721
|
+
if (shouldCacheQuery$1(this._queryConfig.method) && !args?.config?.skipQueryStore) {
|
|
722
|
+
this._store.add(cacheKey, query);
|
|
723
|
+
}
|
|
724
|
+
this._store._dispatchQueryCreated(query);
|
|
725
|
+
return query;
|
|
726
|
+
};
|
|
727
|
+
this.createSubject = (initialValue, config) => {
|
|
728
|
+
assertInInjectionContext(this.createSubject);
|
|
729
|
+
const subject = new BehaviorSubject(initialValue ?? null);
|
|
730
|
+
addQueryContainerHandling(subject, () => subject.getValue(), config);
|
|
731
|
+
return subject;
|
|
732
|
+
};
|
|
733
|
+
this.createSignal = (initialValue, config) => {
|
|
734
|
+
assertInInjectionContext(this.createSignal);
|
|
735
|
+
const _signal = signal(initialValue ?? null);
|
|
736
|
+
addQueryContainerHandling(toObservable(_signal), () => _signal(), config);
|
|
737
|
+
return _signal;
|
|
738
|
+
};
|
|
739
|
+
/**
|
|
740
|
+
* @deprecated Use `myQuery.createSubject()` or `myQuery.createSignal()` instead. Will be removed in v6.
|
|
741
|
+
*/
|
|
742
|
+
this.behaviorSubject = (initialValue) => new BehaviorSubject(initialValue ?? null);
|
|
743
|
+
}
|
|
750
744
|
}
|
|
751
745
|
|
|
752
746
|
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();
|
|
765
747
|
constructor(_config) {
|
|
766
748
|
this._config = _config;
|
|
749
|
+
/**
|
|
750
|
+
* @internal
|
|
751
|
+
*/
|
|
752
|
+
this._store = new Map();
|
|
753
|
+
this._garbageCollector = null;
|
|
754
|
+
this._isInLowResourceMode = false;
|
|
755
|
+
this._lastBlurTimestamp = Date.now();
|
|
756
|
+
this._storeChange$ = new Subject();
|
|
757
|
+
this._queryCreated$ = new Subject();
|
|
758
|
+
this.storeChange$ = this._storeChange$.asObservable();
|
|
759
|
+
this.queryCreated$ = this._queryCreated$.asObservable();
|
|
767
760
|
this._initSmartQueryHandling();
|
|
768
761
|
}
|
|
769
762
|
add(id, query) {
|
|
@@ -894,11 +887,6 @@ class QueryStore {
|
|
|
894
887
|
}
|
|
895
888
|
|
|
896
889
|
class QueryClient {
|
|
897
|
-
_clientConfig;
|
|
898
|
-
/**
|
|
899
|
-
* @internal
|
|
900
|
-
*/
|
|
901
|
-
_store;
|
|
902
890
|
get config() {
|
|
903
891
|
return this._clientConfig;
|
|
904
892
|
}
|
|
@@ -908,9 +896,64 @@ class QueryClient {
|
|
|
908
896
|
get authProvider$() {
|
|
909
897
|
return this._authProvider$.asObservable() ?? this._clientConfig.parent?._authProvider$.asObservable() ?? null;
|
|
910
898
|
}
|
|
911
|
-
_authProvider$ = new BehaviorSubject(null);
|
|
912
899
|
constructor(_clientConfig) {
|
|
913
900
|
this._clientConfig = _clientConfig;
|
|
901
|
+
this._authProvider$ = new BehaviorSubject(null);
|
|
902
|
+
this.get = (queryConfig) => this.fetch({
|
|
903
|
+
...queryConfig,
|
|
904
|
+
method: 'GET',
|
|
905
|
+
});
|
|
906
|
+
this.post = (queryConfig) => this.fetch({
|
|
907
|
+
...queryConfig,
|
|
908
|
+
method: 'POST',
|
|
909
|
+
});
|
|
910
|
+
this.put = (queryConfig) => this.fetch({
|
|
911
|
+
...queryConfig,
|
|
912
|
+
method: 'PUT',
|
|
913
|
+
});
|
|
914
|
+
this.patch = (queryConfig) => this.fetch({
|
|
915
|
+
...queryConfig,
|
|
916
|
+
method: 'PATCH',
|
|
917
|
+
});
|
|
918
|
+
this.delete = (queryConfig) => this.fetch({
|
|
919
|
+
...queryConfig,
|
|
920
|
+
method: 'DELETE',
|
|
921
|
+
});
|
|
922
|
+
this.gqlQuery = (queryConfig) => this.fetch({
|
|
923
|
+
...queryConfig,
|
|
924
|
+
method: 'GQL_QUERY',
|
|
925
|
+
});
|
|
926
|
+
this.gqlMutate = (queryConfig) => this.fetch({
|
|
927
|
+
...queryConfig,
|
|
928
|
+
method: 'GQL_MUTATE',
|
|
929
|
+
});
|
|
930
|
+
this.fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
|
|
931
|
+
this.setAuthProvider = (authProvider) => {
|
|
932
|
+
if (this.authProvider) {
|
|
933
|
+
this.authProvider?.cleanUp();
|
|
934
|
+
}
|
|
935
|
+
this._authProvider$.next(authProvider);
|
|
936
|
+
};
|
|
937
|
+
this.setDefaultHeaders = (config) => {
|
|
938
|
+
if (!this._clientConfig.request) {
|
|
939
|
+
this._clientConfig.request = {
|
|
940
|
+
headers: config.headers ?? undefined,
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
else {
|
|
944
|
+
this._clientConfig.request.headers = config.headers ?? undefined;
|
|
945
|
+
}
|
|
946
|
+
if (config.refreshQueriesInUse) {
|
|
947
|
+
this._store.refreshQueriesInUse({ purgeUnused: true, ignoreCacheValidity: true });
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
this.clearAuthProvider = () => {
|
|
951
|
+
this.authProvider?.cleanUp();
|
|
952
|
+
this._authProvider$.next(null);
|
|
953
|
+
};
|
|
954
|
+
this._updateBaseRoute = (route) => {
|
|
955
|
+
this._clientConfig.baseRoute = route;
|
|
956
|
+
};
|
|
914
957
|
this._store = new QueryStore({
|
|
915
958
|
enableChangeLogging: _clientConfig.logging?.queryStateChanges,
|
|
916
959
|
enableGarbageCollectorLogging: _clientConfig.logging?.queryStateGarbageCollector,
|
|
@@ -918,61 +961,6 @@ class QueryClient {
|
|
|
918
961
|
enableSmartPolling: _clientConfig.request?.enableSmartPolling ?? true,
|
|
919
962
|
});
|
|
920
963
|
}
|
|
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
|
-
};
|
|
976
964
|
}
|
|
977
965
|
|
|
978
966
|
const shouldCacheQuery$1 = (method) => {
|
|
@@ -1264,36 +1252,6 @@ const paginatedEntityValueUpdater = (findFn) => ({ response, rawResponse, entity
|
|
|
1264
1252
|
|
|
1265
1253
|
let _nextQueryId = 0;
|
|
1266
1254
|
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
|
-
});
|
|
1297
1255
|
get _nextId() {
|
|
1298
1256
|
return ++this._currentLocalId;
|
|
1299
1257
|
}
|
|
@@ -1387,6 +1345,31 @@ class Query {
|
|
|
1387
1345
|
this._routeWithParams = _routeWithParams;
|
|
1388
1346
|
this._arguments = _arguments;
|
|
1389
1347
|
this._queryStoreKey = _queryStoreKey;
|
|
1348
|
+
this._id = _nextQueryId++;
|
|
1349
|
+
this._currentLocalId = 0;
|
|
1350
|
+
this._pollingSubscription = null;
|
|
1351
|
+
this._onAbort$ = new Subject();
|
|
1352
|
+
this._currentPollConfig = null;
|
|
1353
|
+
/**
|
|
1354
|
+
* @internal
|
|
1355
|
+
* Used to track which components depend on this query.
|
|
1356
|
+
* The key is the component's _tNode index.
|
|
1357
|
+
* The value is the number of times the component has subscribed to this query.
|
|
1358
|
+
* The value might increase since we cant distinguish between a component and a host directive applied to it.
|
|
1359
|
+
*/
|
|
1360
|
+
this._dependents = {};
|
|
1361
|
+
/**
|
|
1362
|
+
* @internal
|
|
1363
|
+
*/
|
|
1364
|
+
this._dependentsChanged$ = new ReplaySubject();
|
|
1365
|
+
/**
|
|
1366
|
+
* @internal
|
|
1367
|
+
*/
|
|
1368
|
+
this._isPollingPaused = false;
|
|
1369
|
+
this._state$ = new BehaviorSubject({
|
|
1370
|
+
type: "PREPARED" /* QueryStateType.Prepared */,
|
|
1371
|
+
meta: { id: this._currentLocalId, triggeredVia: 'program' },
|
|
1372
|
+
});
|
|
1390
1373
|
}
|
|
1391
1374
|
execute(options = {}) {
|
|
1392
1375
|
const { skipCache = false, _triggeredVia: triggeredVia = 'program', cancelPrevious = false } = options;
|
|
@@ -1715,13 +1698,6 @@ const decryptBearer = (token) => {
|
|
|
1715
1698
|
};
|
|
1716
1699
|
|
|
1717
1700
|
class BearerAuthProvider {
|
|
1718
|
-
_config;
|
|
1719
|
-
_destroy$ = new Subject();
|
|
1720
|
-
_currentRefreshQuery$ = new BehaviorSubject(null);
|
|
1721
|
-
_tokens$ = new BehaviorSubject({
|
|
1722
|
-
token: null,
|
|
1723
|
-
refreshToken: null,
|
|
1724
|
-
});
|
|
1725
1701
|
get header() {
|
|
1726
1702
|
return { Authorization: `Bearer ${this._tokens$.getValue().token}` };
|
|
1727
1703
|
}
|
|
@@ -1744,6 +1720,12 @@ class BearerAuthProvider {
|
|
|
1744
1720
|
}
|
|
1745
1721
|
constructor(_config) {
|
|
1746
1722
|
this._config = _config;
|
|
1723
|
+
this._destroy$ = new Subject();
|
|
1724
|
+
this._currentRefreshQuery$ = new BehaviorSubject(null);
|
|
1725
|
+
this._tokens$ = new BehaviorSubject({
|
|
1726
|
+
token: null,
|
|
1727
|
+
refreshToken: null,
|
|
1728
|
+
});
|
|
1747
1729
|
const cookieEnabled = _config.refreshConfig?.cookieEnabled ?? true;
|
|
1748
1730
|
const cookieToken = _config.refreshConfig?.cookieName && cookieEnabled ? (getCookie(_config.refreshConfig.cookieName) ?? null) : null;
|
|
1749
1731
|
this._tokens$.next({
|
|
@@ -1884,22 +1866,25 @@ const isClassValidatorError = (error) => {
|
|
|
1884
1866
|
};
|
|
1885
1867
|
|
|
1886
1868
|
class QueryDirective {
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1869
|
+
constructor() {
|
|
1870
|
+
this._mainTemplateRef = inject(TemplateRef);
|
|
1871
|
+
this._viewContainerRef = inject(ViewContainerRef);
|
|
1872
|
+
this._errorHandler = inject(ErrorHandler);
|
|
1873
|
+
this._cdr = inject(ChangeDetectorRef);
|
|
1874
|
+
this._isMainViewCreated = false;
|
|
1875
|
+
this._subscription = null;
|
|
1876
|
+
this._viewContext = {
|
|
1877
|
+
$implicit: null,
|
|
1878
|
+
etQuery: null,
|
|
1879
|
+
loading: false,
|
|
1880
|
+
refreshing: false,
|
|
1881
|
+
error: null,
|
|
1882
|
+
progress: null,
|
|
1883
|
+
scope: null,
|
|
1884
|
+
query: null,
|
|
1885
|
+
};
|
|
1886
|
+
this._cache = false;
|
|
1887
|
+
}
|
|
1903
1888
|
get query() {
|
|
1904
1889
|
return this._query;
|
|
1905
1890
|
}
|
|
@@ -1907,14 +1892,12 @@ class QueryDirective {
|
|
|
1907
1892
|
this._query = v;
|
|
1908
1893
|
this._subscribeToQuery();
|
|
1909
1894
|
}
|
|
1910
|
-
_query;
|
|
1911
1895
|
get cache() {
|
|
1912
1896
|
return this._cache;
|
|
1913
1897
|
}
|
|
1914
1898
|
set cache(v) {
|
|
1915
1899
|
this._cache = v;
|
|
1916
1900
|
}
|
|
1917
|
-
_cache = false;
|
|
1918
1901
|
static ngTemplateContextGuard(dir, ctx) {
|
|
1919
1902
|
return true;
|
|
1920
1903
|
}
|
|
@@ -1983,8 +1966,8 @@ class QueryDirective {
|
|
|
1983
1966
|
this._viewContainerRef.createEmbeddedView(this._mainTemplateRef, this._viewContext);
|
|
1984
1967
|
}
|
|
1985
1968
|
}
|
|
1986
|
-
static
|
|
1987
|
-
static
|
|
1969
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1970
|
+
static { this.ɵ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 }); }
|
|
1988
1971
|
}
|
|
1989
1972
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDirective, decorators: [{
|
|
1990
1973
|
type: Directive,
|
|
@@ -2001,58 +1984,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImpor
|
|
|
2001
1984
|
}] } });
|
|
2002
1985
|
|
|
2003
1986
|
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 }));
|
|
2056
1987
|
get currentPage$() {
|
|
2057
1988
|
return this._currentPage$.asObservable();
|
|
2058
1989
|
}
|
|
@@ -2086,6 +2017,56 @@ class InfinityQuery {
|
|
|
2086
2017
|
constructor(_config, _destroy$) {
|
|
2087
2018
|
this._config = _config;
|
|
2088
2019
|
this._destroy$ = _destroy$;
|
|
2020
|
+
this._queries$ = new BehaviorSubject([]);
|
|
2021
|
+
this._currentPage$ = new BehaviorSubject(null);
|
|
2022
|
+
this._currentCalculatedPage$ = new BehaviorSubject(null);
|
|
2023
|
+
this._totalPages$ = new BehaviorSubject(null);
|
|
2024
|
+
this._itemsPerPage$ = new BehaviorSubject(10);
|
|
2025
|
+
this._data$ = this._queries$.pipe(switchMap((queries) => {
|
|
2026
|
+
if (!queries.length) {
|
|
2027
|
+
return of([]);
|
|
2028
|
+
}
|
|
2029
|
+
return combineLatest(queries.map((query) => query.state$.pipe(filterSuccess(), map((state) => ({ state, query })))));
|
|
2030
|
+
}), tap((stateMaps) => {
|
|
2031
|
+
const lastState = stateMaps[stateMaps.length - 1]?.state;
|
|
2032
|
+
const lastQuery = stateMaps[stateMaps.length - 1]?.query;
|
|
2033
|
+
if (!lastState || !lastQuery) {
|
|
2034
|
+
return;
|
|
2035
|
+
}
|
|
2036
|
+
const totalPages = this._config.response.totalPagesExtractor?.({
|
|
2037
|
+
response: lastState.response,
|
|
2038
|
+
itemsPerPage: this.itemsPerPage,
|
|
2039
|
+
args: lastQuery._arguments,
|
|
2040
|
+
}) ??
|
|
2041
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2042
|
+
lastState.response?.totalPages ??
|
|
2043
|
+
null;
|
|
2044
|
+
this._totalPages$.next(totalPages);
|
|
2045
|
+
}), map((stateMaps) => {
|
|
2046
|
+
if (!stateMaps.length) {
|
|
2047
|
+
return null;
|
|
2048
|
+
}
|
|
2049
|
+
const fullData = stateMaps.reduce((acc, stateMap) => {
|
|
2050
|
+
const valExtractFn = this._config?.response?.valueExtractor;
|
|
2051
|
+
let data = valExtractFn
|
|
2052
|
+
? valExtractFn?.(stateMap.state.response)
|
|
2053
|
+
: stateMap.state.response;
|
|
2054
|
+
if (this._config.response.reverse) {
|
|
2055
|
+
data = [...data].reverse();
|
|
2056
|
+
}
|
|
2057
|
+
if (this._config.response.appendItemsTo === 'start') {
|
|
2058
|
+
acc.unshift(...data);
|
|
2059
|
+
}
|
|
2060
|
+
else {
|
|
2061
|
+
acc.push(...data);
|
|
2062
|
+
}
|
|
2063
|
+
return acc;
|
|
2064
|
+
},
|
|
2065
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2066
|
+
[]);
|
|
2067
|
+
return fullData;
|
|
2068
|
+
}), shareReplay({ bufferSize: 1, refCount: true }));
|
|
2069
|
+
this._lastQuery$ = this._queries$.pipe(map((queries) => queries[queries.length - 1] ?? null), shareReplay({ bufferSize: 1, refCount: true }));
|
|
2089
2070
|
this._itemsPerPage$.next(this._config.limitParam?.value ?? 10);
|
|
2090
2071
|
}
|
|
2091
2072
|
nextPage() {
|
|
@@ -2178,28 +2159,6 @@ const skipPaginationPageParamCalculator = ({ page, itemsPerPage }) => itemsPerPa
|
|
|
2178
2159
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2179
2160
|
const INFINITY_QUERY_TOKEN = new InjectionToken('INFINITY_QUERY_TOKEN');
|
|
2180
2161
|
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([]);
|
|
2203
2162
|
get infinityQuery() {
|
|
2204
2163
|
return this._infinityQuery;
|
|
2205
2164
|
}
|
|
@@ -2209,7 +2168,6 @@ class InfinityQueryDirective {
|
|
|
2209
2168
|
this._infinityQueryInstance = this._setupInfinityQuery(v);
|
|
2210
2169
|
this._infinityQueryInstance.nextPage();
|
|
2211
2170
|
}
|
|
2212
|
-
_infinityQuery;
|
|
2213
2171
|
get context() {
|
|
2214
2172
|
return this._viewContext;
|
|
2215
2173
|
}
|
|
@@ -2219,11 +2177,33 @@ class InfinityQueryDirective {
|
|
|
2219
2177
|
get data$() {
|
|
2220
2178
|
return this._data$.asObservable();
|
|
2221
2179
|
}
|
|
2222
|
-
data = toSignal(this._data$, { requireSync: true });
|
|
2223
2180
|
static ngTemplateContextGuard(dir, ctx) {
|
|
2224
2181
|
return true;
|
|
2225
2182
|
}
|
|
2226
2183
|
constructor() {
|
|
2184
|
+
this._queryConfigChanged$ = new Subject();
|
|
2185
|
+
this._viewContext = {
|
|
2186
|
+
$implicit: null,
|
|
2187
|
+
etInfinityQuery: null,
|
|
2188
|
+
loading: false,
|
|
2189
|
+
error: null,
|
|
2190
|
+
isFirstLoad: false,
|
|
2191
|
+
canLoadMore: false,
|
|
2192
|
+
currentPage: null,
|
|
2193
|
+
currentCalculatedPage: null,
|
|
2194
|
+
totalPages: null,
|
|
2195
|
+
itemsPerPage: null,
|
|
2196
|
+
currentQuery: null,
|
|
2197
|
+
};
|
|
2198
|
+
this._infinityQueryInstance = null;
|
|
2199
|
+
this._destroy$ = createDestroy();
|
|
2200
|
+
this._cdr = inject(ChangeDetectorRef);
|
|
2201
|
+
this._viewContainerRef = inject(ViewContainerRef);
|
|
2202
|
+
this._mainTemplateRef = inject((TemplateRef));
|
|
2203
|
+
this._errorHandler = inject(ErrorHandler);
|
|
2204
|
+
this._delayable = inject(DelayableDirective, { host: true });
|
|
2205
|
+
this._data$ = new BehaviorSubject([]);
|
|
2206
|
+
this.data = toSignal(this._data$, { requireSync: true });
|
|
2227
2207
|
this._viewContainerRef.createEmbeddedView(this._mainTemplateRef, this._viewContext);
|
|
2228
2208
|
}
|
|
2229
2209
|
_setupInfinityQuery(config) {
|
|
@@ -2297,8 +2277,8 @@ class InfinityQueryDirective {
|
|
|
2297
2277
|
this._viewContext.currentQuery = null;
|
|
2298
2278
|
this._data$.next([]);
|
|
2299
2279
|
}
|
|
2300
|
-
static
|
|
2301
|
-
static
|
|
2280
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2281
|
+
static { this.ɵ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 }); }
|
|
2302
2282
|
}
|
|
2303
2283
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryDirective, decorators: [{
|
|
2304
2284
|
type: Directive,
|
|
@@ -2315,12 +2295,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImpor
|
|
|
2315
2295
|
}] } });
|
|
2316
2296
|
|
|
2317
2297
|
class InfinityQueryTriggerDirective {
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2298
|
+
constructor() {
|
|
2299
|
+
this._elementRef = inject((ElementRef));
|
|
2300
|
+
this._infinityQuery = inject(INFINITY_QUERY_TOKEN);
|
|
2301
|
+
this._destroy = new Subject();
|
|
2302
|
+
this._observer = null;
|
|
2303
|
+
this.click$ = fromEvent(this._elementRef.nativeElement, 'click');
|
|
2304
|
+
this.scrollContainerSelector = null;
|
|
2305
|
+
}
|
|
2324
2306
|
ngOnInit() {
|
|
2325
2307
|
const isInteractive = this._elementRef.nativeElement.tagName === 'BUTTON';
|
|
2326
2308
|
if (isInteractive) {
|
|
@@ -2350,8 +2332,8 @@ class InfinityQueryTriggerDirective {
|
|
|
2350
2332
|
});
|
|
2351
2333
|
this._observer.observe(this._elementRef.nativeElement);
|
|
2352
2334
|
}
|
|
2353
|
-
static
|
|
2354
|
-
static
|
|
2335
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2336
|
+
static { this.ɵ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 }); }
|
|
2355
2337
|
}
|
|
2356
2338
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
|
|
2357
2339
|
type: Directive,
|
|
@@ -2377,8 +2359,8 @@ class QueryShortNamePipe {
|
|
|
2377
2359
|
}
|
|
2378
2360
|
return route;
|
|
2379
2361
|
}
|
|
2380
|
-
static
|
|
2381
|
-
static
|
|
2362
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryShortNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
2363
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.1.4", ngImport: i0, type: QueryShortNamePipe, isStandalone: true, name: "queryShortName" }); }
|
|
2382
2364
|
}
|
|
2383
2365
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryShortNamePipe, decorators: [{
|
|
2384
2366
|
type: Pipe,
|
|
@@ -2398,159 +2380,161 @@ const provideQueryClientForDevtools = (queryClient) => {
|
|
|
2398
2380
|
};
|
|
2399
2381
|
|
|
2400
2382
|
class QueryDevtoolsComponent {
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
obj[key]
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
if (isGqlQueryConfig(cfg)) {
|
|
2481
|
-
return {
|
|
2482
|
-
...sharedCfg,
|
|
2483
|
-
query: cfg.query,
|
|
2484
|
-
transferVia: cfg.transferVia,
|
|
2485
|
-
};
|
|
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
|
-
},
|
|
2383
|
+
constructor() {
|
|
2384
|
+
this._cdr = inject(ChangeDetectorRef);
|
|
2385
|
+
this._destroy$ = createDestroy();
|
|
2386
|
+
this.queryClientConfigs = inject(QUERY_CLIENT_DEVTOOLS_TOKEN);
|
|
2387
|
+
this.isOpen = signal(false);
|
|
2388
|
+
this.isTranslucent = signal(false);
|
|
2389
|
+
this.snapLayout = signal('full');
|
|
2390
|
+
this.queryListMode = signal('live');
|
|
2391
|
+
this.viewMode = signal('query');
|
|
2392
|
+
this.showResponse = signal(false);
|
|
2393
|
+
this.showRawResponse = signal(false);
|
|
2394
|
+
this.showQueryConfig = signal(false);
|
|
2395
|
+
this.showEntityStoreValue = signal(false);
|
|
2396
|
+
this.showArguments = signal(false);
|
|
2397
|
+
this.selectedClientIdCtrl = new FormControl(0);
|
|
2398
|
+
this.selectedClientId = toSignal(this.selectedClientIdCtrl.valueChanges.pipe(startWith(this.selectedClientIdCtrl.value)));
|
|
2399
|
+
this.selectedQueryId = signal(null);
|
|
2400
|
+
this.selectedClientConfig = computed(() => {
|
|
2401
|
+
if (this.queryClientConfigs.length === 1) {
|
|
2402
|
+
return this.queryClientConfigs[0];
|
|
2403
|
+
}
|
|
2404
|
+
const index = this.selectedClientId() ?? 0;
|
|
2405
|
+
const cfg = this.queryClientConfigs[index];
|
|
2406
|
+
if (!cfg) {
|
|
2407
|
+
return this.queryClientConfigs[0];
|
|
2408
|
+
}
|
|
2409
|
+
return cfg;
|
|
2410
|
+
});
|
|
2411
|
+
this.queryStore = computed(() => {
|
|
2412
|
+
const config = this.selectedClientConfig();
|
|
2413
|
+
return config.client._store;
|
|
2414
|
+
});
|
|
2415
|
+
this.queryStore$ = toObservable(this.queryStore);
|
|
2416
|
+
this._queries$ = new BehaviorSubject([]);
|
|
2417
|
+
this.queries = toSignal(this._queries$);
|
|
2418
|
+
this.selectedQuery = computed(() => {
|
|
2419
|
+
const id = this.selectedQueryId();
|
|
2420
|
+
const mode = this.queryListMode();
|
|
2421
|
+
if (id === null || !mode) {
|
|
2422
|
+
return null;
|
|
2423
|
+
}
|
|
2424
|
+
if (mode === 'live') {
|
|
2425
|
+
return this.queries()?.find((q) => q._id === id) ?? null;
|
|
2426
|
+
}
|
|
2427
|
+
return this.queryHistory$.getValue()?.find((q) => q._id === id) ?? null;
|
|
2428
|
+
});
|
|
2429
|
+
this.selectedQuery$ = toObservable(this.selectedQuery);
|
|
2430
|
+
this.selectedQueryEntityStore = computed(() => {
|
|
2431
|
+
const query = this.selectedQuery();
|
|
2432
|
+
if (!query)
|
|
2433
|
+
return null;
|
|
2434
|
+
return query.store;
|
|
2435
|
+
});
|
|
2436
|
+
this.selectedQueryEntityStore$ = toObservable(this.selectedQueryEntityStore);
|
|
2437
|
+
this.selectedQueryEntityStoreValue$ = this.selectedQueryEntityStore$.pipe(switchMap((s) => s?._change$.pipe(startWith(''), map(() => {
|
|
2438
|
+
if (!s._dictionary)
|
|
2439
|
+
return null;
|
|
2440
|
+
return Array.from(s._dictionary).reduce((obj, [key, value]) => {
|
|
2441
|
+
obj[key] = value;
|
|
2442
|
+
return obj;
|
|
2443
|
+
}, {});
|
|
2444
|
+
})) ?? of(null)));
|
|
2445
|
+
this.queryHistory$ = new BehaviorSubject([]);
|
|
2446
|
+
this.stringifiedQueryConfig = computed(() => {
|
|
2447
|
+
const query = this.selectedQuery();
|
|
2448
|
+
if (!query)
|
|
2449
|
+
return null;
|
|
2450
|
+
const cfg = query._queryConfig;
|
|
2451
|
+
const route = typeof cfg.route === 'string' ? cfg.route : cfg.route ? cfg.route({}).replace(/undefined/g, ':param') : null;
|
|
2452
|
+
const sharedCfg = {
|
|
2453
|
+
method: cfg.method,
|
|
2454
|
+
secure: cfg.secure,
|
|
2455
|
+
route,
|
|
2456
|
+
reportProgress: cfg.reportProgress,
|
|
2457
|
+
responseType: cfg.responseType,
|
|
2458
|
+
withCredentials: cfg.withCredentials,
|
|
2459
|
+
autoRefreshOn: cfg.autoRefreshOn,
|
|
2460
|
+
enableSmartPolling: cfg.enableSmartPolling,
|
|
2461
|
+
hasEntityStore: !!cfg.entity,
|
|
2505
2462
|
};
|
|
2506
|
-
|
|
2507
|
-
|
|
2463
|
+
if (isGqlQueryConfig(cfg)) {
|
|
2464
|
+
return {
|
|
2465
|
+
...sharedCfg,
|
|
2466
|
+
query: cfg.query,
|
|
2467
|
+
transferVia: cfg.transferVia,
|
|
2468
|
+
};
|
|
2469
|
+
}
|
|
2508
2470
|
return {
|
|
2509
|
-
|
|
2510
|
-
header: () => provider.header,
|
|
2511
|
-
provider: provider,
|
|
2512
|
-
config: {
|
|
2513
|
-
username: provider._config.username,
|
|
2514
|
-
password: provider._config.password,
|
|
2515
|
-
},
|
|
2471
|
+
...sharedCfg,
|
|
2516
2472
|
};
|
|
2517
|
-
}
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
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',
|
|
2473
|
+
});
|
|
2474
|
+
this.authProvider = toSignal(toObservable(this.selectedClientConfig).pipe(switchMap((c) => c.client.authProvider$)));
|
|
2475
|
+
this.authProviderDetails = computed(() => {
|
|
2476
|
+
const provider = this.authProvider();
|
|
2477
|
+
if (!provider)
|
|
2478
|
+
return null;
|
|
2479
|
+
if (provider instanceof CustomHeaderAuthProvider) {
|
|
2480
|
+
return {
|
|
2481
|
+
type: 'CustomHeaderAuthProvider',
|
|
2482
|
+
header: () => provider.header,
|
|
2483
|
+
provider: provider,
|
|
2484
|
+
config: {
|
|
2485
|
+
name: provider._config.name,
|
|
2486
|
+
value: provider._config.value,
|
|
2540
2487
|
},
|
|
2541
|
-
}
|
|
2542
|
-
}
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2488
|
+
};
|
|
2489
|
+
}
|
|
2490
|
+
else if (provider instanceof BasicAuthProvider) {
|
|
2491
|
+
return {
|
|
2492
|
+
type: 'BasicAuthProvider',
|
|
2493
|
+
header: () => provider.header,
|
|
2494
|
+
provider: provider,
|
|
2495
|
+
config: {
|
|
2496
|
+
username: provider._config.username,
|
|
2497
|
+
password: provider._config.password,
|
|
2498
|
+
},
|
|
2499
|
+
};
|
|
2500
|
+
}
|
|
2501
|
+
else if (isBearerAuthProvider(provider)) {
|
|
2502
|
+
const refreshCfg = provider._config.refreshConfig;
|
|
2503
|
+
return {
|
|
2504
|
+
type: 'BearerAuthProvider',
|
|
2505
|
+
header: () => provider.header,
|
|
2506
|
+
provider: provider,
|
|
2507
|
+
config: {
|
|
2508
|
+
token: provider._config.token,
|
|
2509
|
+
refreshConfig: {
|
|
2510
|
+
refreshOnUnauthorizedResponse: refreshCfg?.refreshOnUnauthorizedResponse ?? 'true (default)',
|
|
2511
|
+
token: refreshCfg?.token,
|
|
2512
|
+
cookieName: refreshCfg?.cookieName,
|
|
2513
|
+
cookieDomain: refreshCfg?.cookieDomain ?? 'current origin (default)',
|
|
2514
|
+
cookieExpiresInDays: refreshCfg?.cookieExpiresInDays ?? '30 (default)',
|
|
2515
|
+
cookiePath: refreshCfg?.cookiePath ?? '/ (default)',
|
|
2516
|
+
cookieEnabled: refreshCfg?.cookieEnabled ?? 'true (default)',
|
|
2517
|
+
cookieSameSite: refreshCfg?.cookieSameSite ?? 'lax (default)',
|
|
2518
|
+
refreshBuffer: refreshCfg?.refreshBuffer ?? '30000 (default)',
|
|
2519
|
+
expiresInPropertyName: refreshCfg?.expiresInPropertyName ?? 'exp (default)',
|
|
2520
|
+
strategy: refreshCfg?.strategy ?? 'AuthBearerRefreshStrategy.BeforeExpiration (default)',
|
|
2521
|
+
requestArgsAdapter: refreshCfg?.requestArgsAdapter ? 'custom' : 'default',
|
|
2522
|
+
responseAdapter: refreshCfg?.responseAdapter ? 'custom' : 'default',
|
|
2523
|
+
},
|
|
2524
|
+
},
|
|
2525
|
+
};
|
|
2526
|
+
}
|
|
2527
|
+
else {
|
|
2528
|
+
return {
|
|
2529
|
+
type: 'UnknownAuthProvider',
|
|
2530
|
+
header: () => provider.header,
|
|
2531
|
+
provider: provider,
|
|
2532
|
+
config: {},
|
|
2533
|
+
};
|
|
2534
|
+
}
|
|
2535
|
+
});
|
|
2536
|
+
this.trackByClient = (_, { client }) => client.config.baseRoute;
|
|
2537
|
+
this.trackByQuery = (_, { _id }) => _id;
|
|
2554
2538
|
this.selectedClientIdCtrl.valueChanges
|
|
2555
2539
|
.pipe(tap(() => this.clearQueryHistory()), takeUntil(this._destroy$))
|
|
2556
2540
|
.subscribe();
|
|
@@ -2630,8 +2614,6 @@ class QueryDevtoolsComponent {
|
|
|
2630
2614
|
this.viewMode.set(parsed.viewMode ?? 'query');
|
|
2631
2615
|
}
|
|
2632
2616
|
}
|
|
2633
|
-
trackByClient = (_, { client }) => client.config.baseRoute;
|
|
2634
|
-
trackByQuery = (_, { _id }) => _id;
|
|
2635
2617
|
toggleOpen() {
|
|
2636
2618
|
this.isOpen.set(!this.isOpen());
|
|
2637
2619
|
}
|
|
@@ -2671,8 +2653,8 @@ class QueryDevtoolsComponent {
|
|
|
2671
2653
|
clearQueryHistory() {
|
|
2672
2654
|
this.queryHistory$.next([]);
|
|
2673
2655
|
}
|
|
2674
|
-
static
|
|
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 });
|
|
2656
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2657
|
+
static { this.ɵ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 }); }
|
|
2676
2658
|
}
|
|
2677
2659
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
|
|
2678
2660
|
type: Component,
|
|
@@ -2682,7 +2664,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImpor
|
|
|
2682
2664
|
}], ctorParameters: () => [] });
|
|
2683
2665
|
|
|
2684
2666
|
class EntityStoreError extends Error {
|
|
2685
|
-
detail;
|
|
2686
2667
|
constructor(message, detail) {
|
|
2687
2668
|
super(message);
|
|
2688
2669
|
this.detail = detail;
|
|
@@ -2693,17 +2674,16 @@ function flatten(arr) {
|
|
|
2693
2674
|
return arr.reduce((acc, val) => acc.concat(val), []);
|
|
2694
2675
|
}
|
|
2695
2676
|
class EntityStore {
|
|
2696
|
-
_config;
|
|
2697
|
-
/**
|
|
2698
|
-
* @internal
|
|
2699
|
-
*/
|
|
2700
|
-
_dictionary = new Map();
|
|
2701
|
-
/**
|
|
2702
|
-
* @internal
|
|
2703
|
-
*/
|
|
2704
|
-
_change$ = new Subject();
|
|
2705
2677
|
constructor(_config) {
|
|
2706
2678
|
this._config = _config;
|
|
2679
|
+
/**
|
|
2680
|
+
* @internal
|
|
2681
|
+
*/
|
|
2682
|
+
this._dictionary = new Map();
|
|
2683
|
+
/**
|
|
2684
|
+
* @internal
|
|
2685
|
+
*/
|
|
2686
|
+
this._change$ = new Subject();
|
|
2707
2687
|
}
|
|
2708
2688
|
select(keyOrKeys) {
|
|
2709
2689
|
if (Array.isArray(keyOrKeys)) {
|
|
@@ -2907,6 +2887,9 @@ const pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage = () => {
|
|
|
2907
2887
|
const queryStackWithArgsUsed = () => {
|
|
2908
2888
|
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.`);
|
|
2909
2889
|
};
|
|
2890
|
+
const queryStackWithResponseUpdateUsed = () => {
|
|
2891
|
+
return new RuntimeError(501 /* QueryRuntimeErrorCode.QUERY_STACK_WITH_RESPONSE_UPDATE_USED */, `withResponseUpdate() has been used in a query stack or a paged query stack. This is not supported.`);
|
|
2892
|
+
};
|
|
2910
2893
|
|
|
2911
2894
|
const defaultResponseTransformer = (response) => {
|
|
2912
2895
|
if (!isObject(response)) {
|
|
@@ -2963,6 +2946,7 @@ const createAuthProviderQuery = (config, authProviderConfig) => {
|
|
|
2963
2946
|
};
|
|
2964
2947
|
};
|
|
2965
2948
|
const createBearerAuthProvider = (options) => {
|
|
2949
|
+
const route = injectRoute();
|
|
2966
2950
|
const cookieEnabled = signal(options.cookie === undefined ? false : (options.cookie.enabled ?? true));
|
|
2967
2951
|
const cookieOptions = {
|
|
2968
2952
|
expiresInDays: 30,
|
|
@@ -2971,6 +2955,7 @@ const createBearerAuthProvider = (options) => {
|
|
|
2971
2955
|
sameSite: 'lax',
|
|
2972
2956
|
domain: getDomain() ?? 'localhost',
|
|
2973
2957
|
refreshArgsTransformer: (token) => ({ body: { token } }),
|
|
2958
|
+
autoLoginExcludeRoutes: [],
|
|
2974
2959
|
...(options.cookie ?? {}),
|
|
2975
2960
|
};
|
|
2976
2961
|
const loginQuery = options.login ? createAuthProviderQuery(options.login, options) : null;
|
|
@@ -3135,7 +3120,9 @@ const createBearerAuthProvider = (options) => {
|
|
|
3135
3120
|
tokens,
|
|
3136
3121
|
};
|
|
3137
3122
|
if (cookieEnabled()) {
|
|
3138
|
-
|
|
3123
|
+
if (!cookieOptions.autoLoginExcludeRoutes.some((r) => route().startsWith(r))) {
|
|
3124
|
+
tryLoginWithCookie();
|
|
3125
|
+
}
|
|
3139
3126
|
}
|
|
3140
3127
|
return bearerAuthProvider;
|
|
3141
3128
|
};
|
|
@@ -3171,6 +3158,7 @@ const setupQueryState = (options) => {
|
|
|
3171
3158
|
const error = signal(null);
|
|
3172
3159
|
const loading = signal(null);
|
|
3173
3160
|
const lastTimeExecutedAt = signal(null);
|
|
3161
|
+
const request = signal(null);
|
|
3174
3162
|
const state = {
|
|
3175
3163
|
response,
|
|
3176
3164
|
args,
|
|
@@ -3178,6 +3166,9 @@ const setupQueryState = (options) => {
|
|
|
3178
3166
|
loading,
|
|
3179
3167
|
error,
|
|
3180
3168
|
lastTimeExecutedAt,
|
|
3169
|
+
subtle: {
|
|
3170
|
+
request,
|
|
3171
|
+
},
|
|
3181
3172
|
};
|
|
3182
3173
|
return state;
|
|
3183
3174
|
};
|
|
@@ -3389,6 +3380,7 @@ const maybeExecute = (options) => {
|
|
|
3389
3380
|
const createQueryObject = (options) => {
|
|
3390
3381
|
const { state, execute, deps } = options;
|
|
3391
3382
|
const destroy = () => deps.injector.destroy();
|
|
3383
|
+
const setResponse = (response) => state.response.set(response);
|
|
3392
3384
|
const createSnapshot = createQuerySnapshotFn({ state, deps, execute });
|
|
3393
3385
|
const query = {
|
|
3394
3386
|
execute,
|
|
@@ -3403,6 +3395,7 @@ const createQueryObject = (options) => {
|
|
|
3403
3395
|
reset: execute.reset,
|
|
3404
3396
|
subtle: {
|
|
3405
3397
|
destroy,
|
|
3398
|
+
setResponse,
|
|
3406
3399
|
},
|
|
3407
3400
|
};
|
|
3408
3401
|
return query;
|
|
@@ -3734,6 +3727,22 @@ const withAutoRefresh = (options) => {
|
|
|
3734
3727
|
},
|
|
3735
3728
|
});
|
|
3736
3729
|
};
|
|
3730
|
+
const withResponseUpdate = (options) => {
|
|
3731
|
+
return createQueryFeature({
|
|
3732
|
+
type: "withResponseUpdate" /* QueryFeatureType.WithResponseUpdate */,
|
|
3733
|
+
fn: (context) => {
|
|
3734
|
+
queryEffect(() => {
|
|
3735
|
+
const currentResponse = untracked(() => context.state.response());
|
|
3736
|
+
const response = options.updater({ currentResponse });
|
|
3737
|
+
if (response === null)
|
|
3738
|
+
return;
|
|
3739
|
+
untracked(() => {
|
|
3740
|
+
context.state.response.set(response);
|
|
3741
|
+
});
|
|
3742
|
+
}, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
|
|
3743
|
+
},
|
|
3744
|
+
});
|
|
3745
|
+
};
|
|
3737
3746
|
|
|
3738
3747
|
/** Transforms an array of arrays into a single array and filters out `null` values. */
|
|
3739
3748
|
const transformArrayResponse = (responses) => responses.filter((r) => !!r).flatMap((r) => r);
|
|
@@ -3749,9 +3758,13 @@ const createQueryStack = (options) => {
|
|
|
3749
3758
|
const queries = signal([]);
|
|
3750
3759
|
const lastQuery = signal(null);
|
|
3751
3760
|
const hasWithArgsFeature = features.some((f) => f.type == "withArgs" /* QueryFeatureType.WithArgs */);
|
|
3761
|
+
const hasWithOptimisticUpdateFeature = features.some((f) => f.type == "withResponseUpdate" /* QueryFeatureType.WithResponseUpdate */);
|
|
3752
3762
|
if (hasWithArgsFeature) {
|
|
3753
3763
|
throw queryStackWithArgsUsed();
|
|
3754
3764
|
}
|
|
3765
|
+
if (hasWithOptimisticUpdateFeature) {
|
|
3766
|
+
throw queryStackWithResponseUpdateUsed();
|
|
3767
|
+
}
|
|
3755
3768
|
effect(() => {
|
|
3756
3769
|
// Clear the stack if dependencies change
|
|
3757
3770
|
dependencies?.();
|
|
@@ -4105,6 +4118,7 @@ const queryExecute = (options) => {
|
|
|
4105
4118
|
executeState.effectRefs.push(responseRef, loadingRef, errorRef, latestHttpEventRef);
|
|
4106
4119
|
});
|
|
4107
4120
|
state.lastTimeExecutedAt.set(Date.now());
|
|
4121
|
+
state.subtle.request.set(request);
|
|
4108
4122
|
};
|
|
4109
4123
|
const cleanupPreviousExecute = (options) => {
|
|
4110
4124
|
const { executeState } = options;
|
|
@@ -4555,70 +4569,77 @@ const createGqlMutationViaPost = (client) => {
|
|
|
4555
4569
|
return (creatorOptions) => createGqlQueryCreator(creatorOptions, { method: 'MUTATE', client, transport: 'POST' });
|
|
4556
4570
|
};
|
|
4557
4571
|
|
|
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
4572
|
const roomNotJoined = (room) => {
|
|
4562
|
-
return new RuntimeError(
|
|
4573
|
+
return new RuntimeError(1000 /* WebSocketRuntimeErrorCode.ROOM_NOT_JOINED */, `Tried leaving the room "${room}" but it has not been joined.`);
|
|
4563
4574
|
};
|
|
4564
4575
|
const messageMalformed = () => {
|
|
4565
|
-
return new RuntimeError(
|
|
4576
|
+
return new RuntimeError(1001 /* WebSocketRuntimeErrorCode.MESSAGE_MALFORMED */, 'A message has been received but it is malformed (cannot be parsed as JSON).');
|
|
4566
4577
|
};
|
|
4567
4578
|
|
|
4568
4579
|
const createWebSocketClient = (config) => {
|
|
4569
|
-
const joinedRooms = new Set();
|
|
4570
4580
|
const socket = io(config.url, {
|
|
4571
4581
|
withCredentials: true,
|
|
4572
4582
|
autoConnect: false,
|
|
4573
4583
|
});
|
|
4574
|
-
const
|
|
4584
|
+
const rooms = new Map();
|
|
4575
4585
|
const isConnected = signal(false);
|
|
4576
4586
|
const joinRoom = (room) => {
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
+
const roomFn = typeof room === 'function' ? room : () => room;
|
|
4588
|
+
const join = (name) => {
|
|
4589
|
+
socket.emit('join-room', name);
|
|
4590
|
+
const existingRoom = rooms.get(name);
|
|
4591
|
+
if (existingRoom)
|
|
4592
|
+
return existingRoom;
|
|
4593
|
+
const message = signal(null);
|
|
4594
|
+
const newRoom = {
|
|
4595
|
+
latestMessage: message,
|
|
4596
|
+
};
|
|
4597
|
+
rooms.set(name, newRoom);
|
|
4598
|
+
return newRoom;
|
|
4599
|
+
};
|
|
4600
|
+
const pre = previousSignalValue(computed(() => roomFn()));
|
|
4601
|
+
const roomData = signal(null);
|
|
4587
4602
|
effect(() => {
|
|
4588
|
-
const current =
|
|
4603
|
+
const current = roomFn();
|
|
4589
4604
|
untracked(() => {
|
|
4590
4605
|
const previous = pre();
|
|
4591
4606
|
if (previous === current)
|
|
4592
4607
|
return;
|
|
4593
4608
|
if (previous)
|
|
4594
4609
|
leaveRoom(previous);
|
|
4595
|
-
if (current)
|
|
4596
|
-
|
|
4610
|
+
if (current) {
|
|
4611
|
+
const joinedRoom = join(current);
|
|
4612
|
+
if (joinedRoom)
|
|
4613
|
+
roomData.set(joinedRoom);
|
|
4614
|
+
}
|
|
4615
|
+
else {
|
|
4616
|
+
roomData.set(null);
|
|
4617
|
+
}
|
|
4597
4618
|
});
|
|
4598
4619
|
});
|
|
4599
4620
|
inject(DestroyRef).onDestroy(() => {
|
|
4600
|
-
const current =
|
|
4601
|
-
if (current)
|
|
4621
|
+
const current = roomFn();
|
|
4622
|
+
if (current) {
|
|
4602
4623
|
leaveRoom(current);
|
|
4624
|
+
roomData.set(null);
|
|
4625
|
+
}
|
|
4603
4626
|
});
|
|
4627
|
+
return roomData.asReadonly();
|
|
4604
4628
|
};
|
|
4605
4629
|
const leaveRoom = (room) => {
|
|
4606
|
-
if (!
|
|
4630
|
+
if (!rooms.has(room)) {
|
|
4607
4631
|
if (isDevMode())
|
|
4608
4632
|
throw roomNotJoined(room);
|
|
4609
|
-
return;
|
|
4610
4633
|
}
|
|
4611
4634
|
socket.emit('leave-room', room);
|
|
4612
|
-
|
|
4613
|
-
};
|
|
4614
|
-
const leaveAllRooms = () => {
|
|
4615
|
-
joinedRooms.forEach((room) => leaveRoom(room));
|
|
4616
|
-
joinedRooms.clear();
|
|
4635
|
+
rooms.delete(room);
|
|
4617
4636
|
};
|
|
4618
4637
|
const setupWebSocketConnectionListener = () => {
|
|
4619
4638
|
socket.on('connect', () => {
|
|
4620
4639
|
isConnected.set(true);
|
|
4621
|
-
|
|
4640
|
+
for (const room of rooms.keys()) {
|
|
4641
|
+
joinRoom(room);
|
|
4642
|
+
}
|
|
4622
4643
|
});
|
|
4623
4644
|
socket.on('disconnect', () => isConnected.set(false));
|
|
4624
4645
|
};
|
|
@@ -4626,7 +4647,9 @@ const createWebSocketClient = (config) => {
|
|
|
4626
4647
|
socket.onAny((data) => {
|
|
4627
4648
|
try {
|
|
4628
4649
|
const json = JSON.parse(data);
|
|
4629
|
-
|
|
4650
|
+
const room = rooms.get(json.room);
|
|
4651
|
+
if (room)
|
|
4652
|
+
room.latestMessage.set(json);
|
|
4630
4653
|
}
|
|
4631
4654
|
catch (error) {
|
|
4632
4655
|
console.error(error);
|
|
@@ -4641,11 +4664,10 @@ const createWebSocketClient = (config) => {
|
|
|
4641
4664
|
socket.connect();
|
|
4642
4665
|
const client = {
|
|
4643
4666
|
joinRoom,
|
|
4644
|
-
joinComputedRoom,
|
|
4645
|
-
leaveRoom,
|
|
4646
|
-
leaveAllRooms,
|
|
4647
|
-
currentEvent: currentEvent.asReadonly(),
|
|
4648
4667
|
isConnected: isConnected.asReadonly(),
|
|
4668
|
+
subtle: {
|
|
4669
|
+
leaveRoom,
|
|
4670
|
+
},
|
|
4649
4671
|
};
|
|
4650
4672
|
return client;
|
|
4651
4673
|
};
|
|
@@ -4738,6 +4760,7 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
4738
4760
|
queryExecute: queryExecute,
|
|
4739
4761
|
queryFeatureUsedMultipleTimes: queryFeatureUsedMultipleTimes,
|
|
4740
4762
|
queryStackWithArgsUsed: queryStackWithArgsUsed,
|
|
4763
|
+
queryStackWithResponseUpdateUsed: queryStackWithResponseUpdateUsed,
|
|
4741
4764
|
refreshTokenCalledWithoutConfig: refreshTokenCalledWithoutConfig,
|
|
4742
4765
|
resetExecuteState: resetExecuteState,
|
|
4743
4766
|
selectRoleCalledWithoutConfig: selectRoleCalledWithoutConfig,
|
|
@@ -4763,6 +4786,7 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
4763
4786
|
withLogging: withLogging,
|
|
4764
4787
|
withPolling: withPolling,
|
|
4765
4788
|
withPollingUsedOnUnsupportedHttpMethod: withPollingUsedOnUnsupportedHttpMethod,
|
|
4789
|
+
withResponseUpdate: withResponseUpdate,
|
|
4766
4790
|
withSuccessHandling: withSuccessHandling
|
|
4767
4791
|
});
|
|
4768
4792
|
|
|
@@ -4865,7 +4889,6 @@ const transformToSortQueryParam = (value) => {
|
|
|
4865
4889
|
|
|
4866
4890
|
const ET_ARR_PREFIX = 'ET_ARR__';
|
|
4867
4891
|
class QueryField {
|
|
4868
|
-
data;
|
|
4869
4892
|
get control() {
|
|
4870
4893
|
return this.data.control;
|
|
4871
4894
|
}
|
|
@@ -4876,70 +4899,12 @@ class QueryField {
|
|
|
4876
4899
|
const IGNORED_FILTER_COUNT_FIELDS = ['page', 'skip', 'take', 'limit', 'sort', 'sortBy', 'sortOrder', 'query', 'search'];
|
|
4877
4900
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4878
4901
|
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);
|
|
4905
4902
|
get _formValue() {
|
|
4906
4903
|
return this.form.getRawValue();
|
|
4907
4904
|
}
|
|
4908
4905
|
get _form() {
|
|
4909
4906
|
return this.form;
|
|
4910
4907
|
}
|
|
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));
|
|
4943
4908
|
get controls() {
|
|
4944
4909
|
return this.form.controls;
|
|
4945
4910
|
}
|
|
@@ -4956,6 +4921,62 @@ class QueryForm {
|
|
|
4956
4921
|
constructor(_fields, _options) {
|
|
4957
4922
|
this._fields = _fields;
|
|
4958
4923
|
this._options = _options;
|
|
4924
|
+
this._destroy$ = createDestroy();
|
|
4925
|
+
this._unobserveTrigger$ = new Subject();
|
|
4926
|
+
this._router = inject(Router);
|
|
4927
|
+
this._activatedRoute = inject(ActivatedRoute);
|
|
4928
|
+
this._defaultValues = this._extractDefaultValues();
|
|
4929
|
+
this._zone = inject(NgZone);
|
|
4930
|
+
this._didValueChanges$ = new Subject();
|
|
4931
|
+
this._isObserving = false;
|
|
4932
|
+
this._skipNextResets = false;
|
|
4933
|
+
this._queryParamChanges$ = toObservable(injectQueryParamChanges());
|
|
4934
|
+
this._queryParams = injectQueryParams();
|
|
4935
|
+
/**
|
|
4936
|
+
* The angular form group that contains all the fields.
|
|
4937
|
+
*
|
|
4938
|
+
* **Do not** use any of the following methods on this form group:
|
|
4939
|
+
* - `setValue`: Use `QueryForm.setValue` instead.
|
|
4940
|
+
* - `patchValue`: Use `QueryForm.patchValue` instead.
|
|
4941
|
+
* - `valueChanges`: Use `QueryForm.changes$` instead.
|
|
4942
|
+
* - `value`: Use `QueryForm.value` instead.
|
|
4943
|
+
* - `controls`: Use `QueryForm.controls` instead.
|
|
4944
|
+
*/
|
|
4945
|
+
this.form = this._setupFormGroup();
|
|
4946
|
+
this._lastFormValue$ = new BehaviorSubject(null);
|
|
4947
|
+
this._currentFormValue$ = new BehaviorSubject(this._formValue);
|
|
4948
|
+
this._changes$ = new BehaviorSubject({
|
|
4949
|
+
previousValue: null,
|
|
4950
|
+
currentValue: this.form.getRawValue(),
|
|
4951
|
+
});
|
|
4952
|
+
this.changes$ = this._changes$.asObservable();
|
|
4953
|
+
this.currentValue$ = this._changes$.pipe(map(({ currentValue }) => currentValue));
|
|
4954
|
+
this.previousValue$ = this._changes$.pipe(map(({ previousValue }) => previousValue));
|
|
4955
|
+
this.changes = toSignal(this.changes$);
|
|
4956
|
+
this.currentValue = toSignal(this.currentValue$);
|
|
4957
|
+
this.previousValue = toSignal(this.previousValue$);
|
|
4958
|
+
/**
|
|
4959
|
+
* The number of active filters.
|
|
4960
|
+
*
|
|
4961
|
+
* Excludes the following fields by default:
|
|
4962
|
+
* - `page`
|
|
4963
|
+
* - `skip`
|
|
4964
|
+
* - `take`
|
|
4965
|
+
* - `limit`
|
|
4966
|
+
* - `sort`
|
|
4967
|
+
* - `sortBy`
|
|
4968
|
+
* - `sortOrder`
|
|
4969
|
+
* - `query`
|
|
4970
|
+
* - `search`
|
|
4971
|
+
*/
|
|
4972
|
+
this.activeFilterCount$ = this.changes$.pipe(map(({ currentValue }) => Object.entries(currentValue)
|
|
4973
|
+
.map(([key, value]) => {
|
|
4974
|
+
if (IGNORED_FILTER_COUNT_FIELDS.includes(key) || this._fields[key]?.data.skipInFilterCount) {
|
|
4975
|
+
return true;
|
|
4976
|
+
}
|
|
4977
|
+
return this._isDefaultValue(key, value);
|
|
4978
|
+
})
|
|
4979
|
+
.filter((v) => v === false).length));
|
|
4959
4980
|
assertInInjectionContext(QueryForm);
|
|
4960
4981
|
inject(DestroyRef).onDestroy(() => this._cleanup());
|
|
4961
4982
|
}
|