@ethlete/query 4.7.5 → 4.7.7
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/esm2022/lib/devtools/components/query-devtools/query-devtools.component.mjs +81 -5
- package/esm2022/lib/devtools/pipes/index.mjs +2 -0
- package/esm2022/lib/devtools/pipes/public-api.mjs +2 -0
- package/esm2022/lib/devtools/pipes/query-short-name.pipe.mjs +25 -0
- package/esm2022/lib/devtools/public-api.mjs +2 -1
- package/esm2022/lib/entity/entity-store.mjs +7 -1
- package/esm2022/lib/query/query.mjs +22 -16
- package/esm2022/lib/query-creator/query-creator.mjs +2 -1
- package/esm2022/lib/query-store/query-store.mjs +9 -1
- package/fesm2022/ethlete-query.mjs +393 -276
- package/fesm2022/ethlete-query.mjs.map +1 -1
- package/lib/devtools/components/query-devtools/query-devtools.component.d.ts +33 -0
- package/lib/devtools/pipes/index.d.ts +1 -0
- package/lib/devtools/pipes/public-api.d.ts +1 -0
- package/lib/devtools/pipes/query-short-name.pipe.d.ts +8 -0
- package/lib/devtools/public-api.d.ts +1 -0
- package/lib/entity/entity-store.d.ts +0 -2
- package/lib/query/query.d.ts +12 -5
- package/lib/query-store/query-store.d.ts +2 -0
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as i1$1 from '@ethlete/core';
|
|
2
2
|
import { getCookie, setCookie, deleteCookie, createDestroy, nextFrame, DelayableDirective, RouterStateService, clone, equal, ET_PROPERTY_REMOVED } from '@ethlete/core';
|
|
3
|
-
import { Observable, filter, takeWhile, switchMap, of, tap,
|
|
3
|
+
import { Observable, BehaviorSubject, Subject, fromEvent, timer, takeUntil, take, filter, takeWhile, switchMap, of, tap, shareReplay, interval, skip, map, startWith, combineLatest, withLatestFrom, debounceTime, concat } from 'rxjs';
|
|
4
4
|
import * as i0 from '@angular/core';
|
|
5
|
-
import { isDevMode, InjectionToken, inject, ChangeDetectorRef, signal, computed, effect, Component, ChangeDetectionStrategy, ViewEncapsulation, TemplateRef, ViewContainerRef, ErrorHandler, Directive, Input, ElementRef, NgZone, assertInInjectionContext } from '@angular/core';
|
|
5
|
+
import { isDevMode, Pipe, InjectionToken, inject, ChangeDetectorRef, signal, computed, effect, Component, ChangeDetectionStrategy, ViewEncapsulation, TemplateRef, ViewContainerRef, ErrorHandler, Directive, Input, ElementRef, NgZone, assertInInjectionContext } from '@angular/core';
|
|
6
6
|
import { NgIf, NgFor, AsyncPipe, JsonPipe, NgClass } from '@angular/common';
|
|
7
7
|
import { toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
8
8
|
import * as i1 from '@angular/forms';
|
|
@@ -493,6 +493,270 @@ const request = (config) => {
|
|
|
493
493
|
});
|
|
494
494
|
};
|
|
495
495
|
|
|
496
|
+
class QueryCreator {
|
|
497
|
+
constructor(_queryConfig, _client, _store) {
|
|
498
|
+
this._queryConfig = _queryConfig;
|
|
499
|
+
this._client = _client;
|
|
500
|
+
this._store = _store;
|
|
501
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
502
|
+
// @ts-ignore
|
|
503
|
+
this.prepare = (args) => {
|
|
504
|
+
const route = buildRoute({
|
|
505
|
+
base: this._client.config.baseRoute,
|
|
506
|
+
route: this._queryConfig.route,
|
|
507
|
+
pathParams: args?.pathParams,
|
|
508
|
+
queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
|
|
509
|
+
queryParamConfig: this._client.config.request?.queryParams,
|
|
510
|
+
});
|
|
511
|
+
const cacheKey = isGqlQueryConfig(this._queryConfig) ? buildGqlCacheKey(this._queryConfig, args) : route;
|
|
512
|
+
if (shouldCacheQuery(this._queryConfig.method)) {
|
|
513
|
+
const existingQuery = this._store.get(cacheKey);
|
|
514
|
+
if (existingQuery) {
|
|
515
|
+
return existingQuery;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
const query = new Query(this._client, this._queryConfig, route, args ?? {});
|
|
519
|
+
if (shouldCacheQuery(this._queryConfig.method)) {
|
|
520
|
+
this._store.add(cacheKey, query);
|
|
521
|
+
}
|
|
522
|
+
this._store._dispatchQueryCreated(query);
|
|
523
|
+
return query;
|
|
524
|
+
};
|
|
525
|
+
this.behaviorSubject = (initialValue) => new BehaviorSubject(initialValue ?? null);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
class QueryStore {
|
|
530
|
+
constructor(_config) {
|
|
531
|
+
this._config = _config;
|
|
532
|
+
/**
|
|
533
|
+
* @internal
|
|
534
|
+
*/
|
|
535
|
+
this._store = new Map();
|
|
536
|
+
this._garbageCollector = null;
|
|
537
|
+
this._isInLowResourceMode = false;
|
|
538
|
+
this._lastBlurTimestamp = Date.now();
|
|
539
|
+
this._storeChange$ = new Subject();
|
|
540
|
+
this._queryCreated$ = new Subject();
|
|
541
|
+
this.storeChange$ = this._storeChange$.asObservable();
|
|
542
|
+
this.queryCreated$ = this._queryCreated$.asObservable();
|
|
543
|
+
this._initSmartQueryHandling();
|
|
544
|
+
}
|
|
545
|
+
add(id, query) {
|
|
546
|
+
this._store.set(id, query);
|
|
547
|
+
this._initGarbageCollector();
|
|
548
|
+
this._logState(id, query, 'SET');
|
|
549
|
+
this._storeChange$.next(id);
|
|
550
|
+
}
|
|
551
|
+
get(id) {
|
|
552
|
+
return this._store.get(id) ?? null;
|
|
553
|
+
}
|
|
554
|
+
remove(id) {
|
|
555
|
+
this._store.delete(id);
|
|
556
|
+
this._logState(id, null, 'REMOVE');
|
|
557
|
+
this._storeChange$.next(id);
|
|
558
|
+
}
|
|
559
|
+
forEach(callback) {
|
|
560
|
+
for (const [key, query] of this._store) {
|
|
561
|
+
callback(query, key);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
refreshQueriesInUse(config) {
|
|
565
|
+
const { ignoreCacheValidity, purgeUnused } = config ?? {};
|
|
566
|
+
for (const [key, query] of this._store) {
|
|
567
|
+
if (query.isInUse &&
|
|
568
|
+
(query.isExpired || ignoreCacheValidity) &&
|
|
569
|
+
query.autoRefreshOnConfig.queryClientDefaultHeadersChange) {
|
|
570
|
+
query.execute({ skipCache: true, _triggeredVia: 'auto' });
|
|
571
|
+
}
|
|
572
|
+
else if (purgeUnused && !query.isInUse) {
|
|
573
|
+
this.remove(key);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* @internal
|
|
579
|
+
*/
|
|
580
|
+
_dispatchQueryCreated(query) {
|
|
581
|
+
this._queryCreated$.next(query);
|
|
582
|
+
}
|
|
583
|
+
_initSmartQueryHandling() {
|
|
584
|
+
const windowBlur$ = fromEvent(window, 'blur');
|
|
585
|
+
const windowFocus$ = fromEvent(window, 'focus');
|
|
586
|
+
windowBlur$.subscribe(() => {
|
|
587
|
+
timer(5000)
|
|
588
|
+
.pipe(takeUntil(windowFocus$), take(1))
|
|
589
|
+
.subscribe(() => {
|
|
590
|
+
this._lastBlurTimestamp = Date.now();
|
|
591
|
+
this._isInLowResourceMode = true;
|
|
592
|
+
this._stopGarbageCollector();
|
|
593
|
+
if (this._config?.enableSmartPolling) {
|
|
594
|
+
this.forEach((query) => {
|
|
595
|
+
if (!query.isPolling || !query._enableSmartPolling) {
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
query.pausePolling();
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
});
|
|
603
|
+
windowFocus$.subscribe(() => {
|
|
604
|
+
if (!this._isInLowResourceMode) {
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
this._isInLowResourceMode = false;
|
|
608
|
+
if (this._config?.enableSmartPolling || this._config?.autoRefreshQueriesOnWindowFocus) {
|
|
609
|
+
this.forEach((query) => {
|
|
610
|
+
if (this._config?.enableSmartPolling && query._isPollingPaused) {
|
|
611
|
+
query.resumePolling();
|
|
612
|
+
}
|
|
613
|
+
if (Date.now() - this._lastBlurTimestamp > 15000) {
|
|
614
|
+
if (this._config?.autoRefreshQueriesOnWindowFocus &&
|
|
615
|
+
query.isExpired &&
|
|
616
|
+
query.isInUse &&
|
|
617
|
+
query.autoRefreshOnConfig.windowFocus) {
|
|
618
|
+
query.execute({ skipCache: true, _triggeredVia: 'auto' });
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
this._initGarbageCollector();
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
_logState(key, item, operation) {
|
|
627
|
+
if (!this._config?.enableChangeLogging)
|
|
628
|
+
return;
|
|
629
|
+
const stateAsJson = {};
|
|
630
|
+
this._store.forEach((value, key) => {
|
|
631
|
+
stateAsJson[key] = value;
|
|
632
|
+
});
|
|
633
|
+
console.log(`%c[${operation}] ${key}`, 'font-weight: bold');
|
|
634
|
+
console.log({ operation, key, item });
|
|
635
|
+
console.log(stateAsJson);
|
|
636
|
+
}
|
|
637
|
+
_initGarbageCollector() {
|
|
638
|
+
if (this._garbageCollector !== null) {
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
this._logGarbageCollector('Start');
|
|
642
|
+
this._garbageCollector = window.setInterval(() => {
|
|
643
|
+
this._runGarbageCollector();
|
|
644
|
+
}, 15000);
|
|
645
|
+
}
|
|
646
|
+
_stopGarbageCollector() {
|
|
647
|
+
if (this._garbageCollector !== null) {
|
|
648
|
+
window.clearInterval(this._garbageCollector);
|
|
649
|
+
this._garbageCollector = null;
|
|
650
|
+
this._logGarbageCollector('Stop');
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
_runGarbageCollector() {
|
|
654
|
+
this._logGarbageCollector('Collecting...');
|
|
655
|
+
this._store.forEach((item, key) => {
|
|
656
|
+
if (item.isExpired && !item.isInUse) {
|
|
657
|
+
this.remove(key);
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
this._logGarbageCollector('Collection done');
|
|
661
|
+
if (!this._store.size) {
|
|
662
|
+
this._stopGarbageCollector();
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
_logGarbageCollector(action) {
|
|
666
|
+
if (!this._config?.enableGarbageCollectorLogging)
|
|
667
|
+
return;
|
|
668
|
+
console.log(`%cGC: ${action}`, 'color: yellow; font-weight: bold');
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
class QueryClient {
|
|
673
|
+
get config() {
|
|
674
|
+
return this._clientConfig;
|
|
675
|
+
}
|
|
676
|
+
get authProvider() {
|
|
677
|
+
return this._authProvider$.getValue() ?? this._clientConfig.parent?._authProvider$.getValue() ?? null;
|
|
678
|
+
}
|
|
679
|
+
get authProvider$() {
|
|
680
|
+
return this._authProvider$.asObservable() ?? this._clientConfig.parent?._authProvider$.asObservable() ?? null;
|
|
681
|
+
}
|
|
682
|
+
constructor(_clientConfig) {
|
|
683
|
+
this._clientConfig = _clientConfig;
|
|
684
|
+
this._authProvider$ = new BehaviorSubject(null);
|
|
685
|
+
this.get = (queryConfig) => this.fetch({
|
|
686
|
+
...queryConfig,
|
|
687
|
+
method: 'GET',
|
|
688
|
+
});
|
|
689
|
+
this.post = (queryConfig) => this.fetch({
|
|
690
|
+
...queryConfig,
|
|
691
|
+
method: 'POST',
|
|
692
|
+
});
|
|
693
|
+
this.put = (queryConfig) => this.fetch({
|
|
694
|
+
...queryConfig,
|
|
695
|
+
method: 'PUT',
|
|
696
|
+
});
|
|
697
|
+
this.patch = (queryConfig) => this.fetch({
|
|
698
|
+
...queryConfig,
|
|
699
|
+
method: 'PATCH',
|
|
700
|
+
});
|
|
701
|
+
this.delete = (queryConfig) => this.fetch({
|
|
702
|
+
...queryConfig,
|
|
703
|
+
method: 'DELETE',
|
|
704
|
+
});
|
|
705
|
+
this.gqlQuery = (queryConfig) => this.fetch({
|
|
706
|
+
...queryConfig,
|
|
707
|
+
method: 'GQL_QUERY',
|
|
708
|
+
});
|
|
709
|
+
this.gqlMutate = (queryConfig) => this.fetch({
|
|
710
|
+
...queryConfig,
|
|
711
|
+
method: 'GQL_MUTATE',
|
|
712
|
+
});
|
|
713
|
+
this.fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
|
|
714
|
+
this.setAuthProvider = (authProvider) => {
|
|
715
|
+
if (this.authProvider) {
|
|
716
|
+
throw new Error('The auth provider is already set. Please call clearAuthProvider() first.');
|
|
717
|
+
}
|
|
718
|
+
this._authProvider$.next(authProvider);
|
|
719
|
+
};
|
|
720
|
+
this.setDefaultHeaders = (config) => {
|
|
721
|
+
if (!this._clientConfig.request) {
|
|
722
|
+
this._clientConfig.request = {
|
|
723
|
+
headers: config.headers ?? undefined,
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
this._clientConfig.request.headers = config.headers ?? undefined;
|
|
728
|
+
}
|
|
729
|
+
if (config.refreshQueriesInUse) {
|
|
730
|
+
this._store.refreshQueriesInUse({ purgeUnused: true, ignoreCacheValidity: true });
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
this.clearAuthProvider = () => {
|
|
734
|
+
this.authProvider?.cleanUp();
|
|
735
|
+
this._authProvider$.next(null);
|
|
736
|
+
};
|
|
737
|
+
this._store = new QueryStore({
|
|
738
|
+
enableChangeLogging: _clientConfig.logging?.queryStateChanges,
|
|
739
|
+
enableGarbageCollectorLogging: _clientConfig.logging?.queryStateGarbageCollector,
|
|
740
|
+
autoRefreshQueriesOnWindowFocus: _clientConfig.request?.autoRefreshQueriesOnWindowFocus ?? true,
|
|
741
|
+
enableSmartPolling: _clientConfig.request?.enableSmartPolling ?? true,
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
const shouldCacheQuery = (method) => {
|
|
747
|
+
return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
|
|
748
|
+
};
|
|
749
|
+
const buildGqlCacheKey = (config, args) => {
|
|
750
|
+
const { query } = config;
|
|
751
|
+
const variables = args?.variables || {};
|
|
752
|
+
const queryWithoutNewLinesAndWhitespace = query.replace(/\s/g, '');
|
|
753
|
+
const queryFirst50Chars = queryWithoutNewLinesAndWhitespace.slice(0, 50);
|
|
754
|
+
const queryMiddle25Chars = queryWithoutNewLinesAndWhitespace.slice(queryWithoutNewLinesAndWhitespace.length / 2 - 25, queryWithoutNewLinesAndWhitespace.length / 2 + 25);
|
|
755
|
+
const queryLast50Chars = queryWithoutNewLinesAndWhitespace.slice(-50);
|
|
756
|
+
const vars = JSON.stringify(variables);
|
|
757
|
+
return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
|
|
758
|
+
};
|
|
759
|
+
|
|
496
760
|
const getOpName = /(query|mutation) ?([\w\d-_]+)? ?\(.*?\)? \{/;
|
|
497
761
|
const transformGql = (str) => {
|
|
498
762
|
str = Array.isArray(str) ? str.join('') : str;
|
|
@@ -802,24 +1066,29 @@ class Query {
|
|
|
802
1066
|
get _enableSmartPolling() {
|
|
803
1067
|
return this._queryConfig.enableSmartPolling ?? true;
|
|
804
1068
|
}
|
|
805
|
-
/**
|
|
806
|
-
* @internal
|
|
807
|
-
*/
|
|
808
|
-
get _arguments() {
|
|
809
|
-
return this._args;
|
|
810
|
-
}
|
|
811
1069
|
get store() {
|
|
812
1070
|
return this._queryConfig.entity?.store ?? null;
|
|
813
1071
|
}
|
|
814
|
-
|
|
1072
|
+
get canBeCached() {
|
|
1073
|
+
return shouldCacheQuery(this._queryConfig.method);
|
|
1074
|
+
}
|
|
1075
|
+
constructor(_client,
|
|
1076
|
+
/**
|
|
1077
|
+
* @internal
|
|
1078
|
+
*/
|
|
1079
|
+
_queryConfig,
|
|
815
1080
|
/**
|
|
816
1081
|
* @internal
|
|
817
1082
|
*/
|
|
818
|
-
_routeWithParams,
|
|
1083
|
+
_routeWithParams,
|
|
1084
|
+
/**
|
|
1085
|
+
* @internal
|
|
1086
|
+
*/
|
|
1087
|
+
_arguments) {
|
|
819
1088
|
this._client = _client;
|
|
820
1089
|
this._queryConfig = _queryConfig;
|
|
821
1090
|
this._routeWithParams = _routeWithParams;
|
|
822
|
-
this.
|
|
1091
|
+
this._arguments = _arguments;
|
|
823
1092
|
this._id = _nextQueryId++;
|
|
824
1093
|
this._currentLocalId = 0;
|
|
825
1094
|
this._pollingSubscription = null;
|
|
@@ -856,8 +1125,8 @@ class Query {
|
|
|
856
1125
|
}
|
|
857
1126
|
this._state$.next({ type: "LOADING" /* QueryStateType.Loading */, meta });
|
|
858
1127
|
const method = computeQueryMethod({ config: queryConfig, client: this._client });
|
|
859
|
-
const body = computeQueryBody({ config: queryConfig, client: this._client, args: this.
|
|
860
|
-
const headers = computeQueryHeaders({ client: this._client, config: queryConfig, args: this.
|
|
1128
|
+
const body = computeQueryBody({ config: queryConfig, client: this._client, args: this._arguments, method });
|
|
1129
|
+
const headers = computeQueryHeaders({ client: this._client, config: queryConfig, args: this._arguments });
|
|
861
1130
|
request({
|
|
862
1131
|
urlWithParams: this._routeWithParams,
|
|
863
1132
|
method,
|
|
@@ -945,9 +1214,9 @@ class Query {
|
|
|
945
1214
|
? response['data']
|
|
946
1215
|
: response;
|
|
947
1216
|
if (this._queryConfig.entity && this._queryConfig.entity.set) {
|
|
948
|
-
const id = this._queryConfig.entity?.id({ args: this.
|
|
1217
|
+
const id = this._queryConfig.entity?.id({ args: this._arguments, response: responseData });
|
|
949
1218
|
this._queryConfig.entity?.set({
|
|
950
|
-
args: this.
|
|
1219
|
+
args: this._arguments,
|
|
951
1220
|
response: responseData,
|
|
952
1221
|
id,
|
|
953
1222
|
store: this._queryConfig.entity.store,
|
|
@@ -991,9 +1260,9 @@ class Query {
|
|
|
991
1260
|
if (!isQueryStateSuccess(s) || !this._queryConfig.entity?.get) {
|
|
992
1261
|
return of(s);
|
|
993
1262
|
}
|
|
994
|
-
const id = this._queryConfig.entity.id({ args: this.
|
|
1263
|
+
const id = this._queryConfig.entity.id({ args: this._arguments, response: s.response });
|
|
995
1264
|
return this._queryConfig.entity
|
|
996
|
-
.get({ args: this.
|
|
1265
|
+
.get({ args: this._arguments, id, response: s.response, store: this._queryConfig.entity.store })
|
|
997
1266
|
.pipe(map((v) => ({ ...s, response: v })));
|
|
998
1267
|
}
|
|
999
1268
|
}
|
|
@@ -1175,6 +1444,29 @@ const isClassValidatorError = (error) => {
|
|
|
1175
1444
|
return typeof error === 'object' && error !== null && 'statusCode' in error && 'message' in error && 'error' in error;
|
|
1176
1445
|
};
|
|
1177
1446
|
|
|
1447
|
+
class QueryShortNamePipe {
|
|
1448
|
+
transform(value) {
|
|
1449
|
+
const route = value._routeWithParams;
|
|
1450
|
+
if (typeof route === 'string') {
|
|
1451
|
+
// given an url that looks like this: https://api.github.com/repos/EladBezalel/etimo-achievements or https://api.github.com/repos/EladBezalel/etimo-achievements?test=1&test2=2
|
|
1452
|
+
// we want to extract the last 3 parts of the url, so we get: repos/EladBezalel/etimo-achievements
|
|
1453
|
+
const parts = route.split('/');
|
|
1454
|
+
if (parts.length > 3) {
|
|
1455
|
+
return `.../${parts.slice(parts.length - 3).join('/')}`;
|
|
1456
|
+
}
|
|
1457
|
+
return route;
|
|
1458
|
+
}
|
|
1459
|
+
console.log(route);
|
|
1460
|
+
return route;
|
|
1461
|
+
}
|
|
1462
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: QueryShortNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
1463
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "16.1.6", ngImport: i0, type: QueryShortNamePipe, isStandalone: true, name: "queryShortName" }); }
|
|
1464
|
+
}
|
|
1465
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: QueryShortNamePipe, decorators: [{
|
|
1466
|
+
type: Pipe,
|
|
1467
|
+
args: [{ name: 'queryShortName', standalone: true }]
|
|
1468
|
+
}] });
|
|
1469
|
+
|
|
1178
1470
|
const QUERY_CLIENT_DEVTOOLS_TOKEN = new InjectionToken('QUERY_CLIENT_DEVTOOLS_TOKEN');
|
|
1179
1471
|
const provideQueryClientForDevtools = (queryClient) => {
|
|
1180
1472
|
if (!isDevMode()) {
|
|
@@ -1198,6 +1490,9 @@ class QueryDevtoolsComponent {
|
|
|
1198
1490
|
this.queryListMode = signal('live');
|
|
1199
1491
|
this.showResponse = signal(false);
|
|
1200
1492
|
this.showRawResponse = signal(false);
|
|
1493
|
+
this.showQueryConfig = signal(false);
|
|
1494
|
+
this.showEntityStoreValue = signal(false);
|
|
1495
|
+
this.showArguments = signal(false);
|
|
1201
1496
|
this.selectedClientIdCtrl = new FormControl(0);
|
|
1202
1497
|
this.selectedClientId = toSignal(this.selectedClientIdCtrl.valueChanges.pipe(startWith(this.selectedClientIdCtrl.value)));
|
|
1203
1498
|
this.selectedQueryId = signal(null);
|
|
@@ -1226,7 +1521,50 @@ class QueryDevtoolsComponent {
|
|
|
1226
1521
|
}
|
|
1227
1522
|
return this.queryHistory()?.find((q) => q._id === id) ?? null;
|
|
1228
1523
|
});
|
|
1524
|
+
this.selectedQueryEntityStore = computed(() => {
|
|
1525
|
+
const query = this.selectedQuery();
|
|
1526
|
+
if (!query)
|
|
1527
|
+
return null;
|
|
1528
|
+
return query.store;
|
|
1529
|
+
});
|
|
1530
|
+
this.selectedQueryEntityStore$ = toObservable(this.selectedQueryEntityStore);
|
|
1531
|
+
this.selectedQueryEntityStoreValue$ = this.selectedQueryEntityStore$.pipe(switchMap((s) => s?._change$.pipe(startWith(''), map(() => {
|
|
1532
|
+
if (!s._dictionary)
|
|
1533
|
+
return null;
|
|
1534
|
+
return Array.from(s._dictionary).reduce((obj, [key, value]) => {
|
|
1535
|
+
obj[key] = value;
|
|
1536
|
+
return obj;
|
|
1537
|
+
}, {});
|
|
1538
|
+
})) ?? of(null)));
|
|
1229
1539
|
this.queryHistory = signal([]);
|
|
1540
|
+
this.stringifiedQueryConfig = computed(() => {
|
|
1541
|
+
const query = this.selectedQuery();
|
|
1542
|
+
if (!query)
|
|
1543
|
+
return null;
|
|
1544
|
+
const cfg = query._queryConfig;
|
|
1545
|
+
const route = typeof cfg.route === 'string' ? cfg.route : cfg.route ? cfg.route({}).replace(/undefined/g, ':param') : null;
|
|
1546
|
+
const sharedCfg = {
|
|
1547
|
+
method: cfg.method,
|
|
1548
|
+
secure: cfg.secure,
|
|
1549
|
+
route,
|
|
1550
|
+
reportProgress: cfg.reportProgress,
|
|
1551
|
+
responseType: cfg.responseType,
|
|
1552
|
+
withCredentials: cfg.withCredentials,
|
|
1553
|
+
autoRefreshOn: cfg.autoRefreshOn,
|
|
1554
|
+
enableSmartPolling: cfg.enableSmartPolling,
|
|
1555
|
+
hasEntityStore: !!cfg.entity,
|
|
1556
|
+
};
|
|
1557
|
+
if (isGqlQueryConfig(cfg)) {
|
|
1558
|
+
return {
|
|
1559
|
+
...sharedCfg,
|
|
1560
|
+
query: cfg.query,
|
|
1561
|
+
transferVia: cfg.transferVia,
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
return {
|
|
1565
|
+
...sharedCfg,
|
|
1566
|
+
};
|
|
1567
|
+
});
|
|
1230
1568
|
this.trackByClient = (_, { client }) => client.config.baseRoute;
|
|
1231
1569
|
this.trackByQuery = (_, { _id }) => _id;
|
|
1232
1570
|
this.selectedClientIdCtrl.valueChanges
|
|
@@ -1235,6 +1573,19 @@ class QueryDevtoolsComponent {
|
|
|
1235
1573
|
this.queryStore$
|
|
1236
1574
|
.pipe(switchMap((s) => s.storeChange$.pipe(startWith(''), map(() => s._store), tap((s) => this._queries$.next(Array.from(s.values()))), takeUntil(this._destroy$))))
|
|
1237
1575
|
.subscribe();
|
|
1576
|
+
this.queryStore$
|
|
1577
|
+
.pipe(switchMap((s) => s.queryCreated$.pipe(tap((query) => {
|
|
1578
|
+
const currentHistory = this.queryHistory();
|
|
1579
|
+
if (!currentHistory)
|
|
1580
|
+
return;
|
|
1581
|
+
const currentHistoryClone = [...currentHistory];
|
|
1582
|
+
if (!currentHistory.some((q) => q._id === query._id)) {
|
|
1583
|
+
currentHistoryClone.unshift(query);
|
|
1584
|
+
}
|
|
1585
|
+
currentHistoryClone.splice(50);
|
|
1586
|
+
this.queryHistory.set(currentHistoryClone);
|
|
1587
|
+
}), takeUntil(this._destroy$))))
|
|
1588
|
+
.subscribe();
|
|
1238
1589
|
this._queries$
|
|
1239
1590
|
.pipe(tap((queries) => {
|
|
1240
1591
|
const currentHistory = this.queryHistory();
|
|
@@ -1242,7 +1593,7 @@ class QueryDevtoolsComponent {
|
|
|
1242
1593
|
return;
|
|
1243
1594
|
const currentHistoryClone = [...currentHistory];
|
|
1244
1595
|
for (const query of queries) {
|
|
1245
|
-
if (!currentHistoryClone.
|
|
1596
|
+
if (!currentHistoryClone.some((q) => q._id === query._id)) {
|
|
1246
1597
|
currentHistoryClone.unshift(query);
|
|
1247
1598
|
}
|
|
1248
1599
|
}
|
|
@@ -1257,6 +1608,9 @@ class QueryDevtoolsComponent {
|
|
|
1257
1608
|
snapLayout: this.snapLayout(),
|
|
1258
1609
|
showResponse: this.showResponse(),
|
|
1259
1610
|
showRawResponse: this.showRawResponse(),
|
|
1611
|
+
showQueryConfig: this.showQueryConfig(),
|
|
1612
|
+
showEntityStoreValue: this.showEntityStoreValue(),
|
|
1613
|
+
showArguments: this.showArguments(),
|
|
1260
1614
|
selectedClientId: this.selectedClientId(),
|
|
1261
1615
|
selectedQueryPath: this.selectedQueryId(),
|
|
1262
1616
|
queryListMode: this.queryListMode(),
|
|
@@ -1271,6 +1625,9 @@ class QueryDevtoolsComponent {
|
|
|
1271
1625
|
this.snapLayout.set(parsed.snapLayout ?? 'full');
|
|
1272
1626
|
this.showResponse.set(parsed.showResponse ?? false);
|
|
1273
1627
|
this.showRawResponse.set(parsed.showRawResponse ?? false);
|
|
1628
|
+
this.showQueryConfig.set(parsed.showQueryConfig ?? false);
|
|
1629
|
+
this.showEntityStoreValue.set(parsed.showEntityStoreValue ?? false);
|
|
1630
|
+
this.showArguments.set(parsed.showArguments ?? false);
|
|
1274
1631
|
this.selectedClientIdCtrl.setValue(parsed.selectedClientId ?? 0);
|
|
1275
1632
|
this.selectedQueryId.set(parsed.selectedQueryPath ?? null);
|
|
1276
1633
|
this.queryListMode.set(parsed.queryListMode ?? 'live');
|
|
@@ -1288,9 +1645,18 @@ class QueryDevtoolsComponent {
|
|
|
1288
1645
|
this._cdr.markForCheck();
|
|
1289
1646
|
});
|
|
1290
1647
|
}
|
|
1648
|
+
toggleShowQueryConfig() {
|
|
1649
|
+
this.showQueryConfig.set(!this.showQueryConfig());
|
|
1650
|
+
}
|
|
1291
1651
|
toggleShowRawResponse() {
|
|
1292
1652
|
this.showRawResponse.set(!this.showRawResponse());
|
|
1293
1653
|
}
|
|
1654
|
+
toggleShowEntityStoreValue() {
|
|
1655
|
+
this.showEntityStoreValue.set(!this.showEntityStoreValue());
|
|
1656
|
+
}
|
|
1657
|
+
toggleShowArguments() {
|
|
1658
|
+
this.showArguments.set(!this.showArguments());
|
|
1659
|
+
}
|
|
1294
1660
|
selectSnapLayout(layout) {
|
|
1295
1661
|
this.snapLayout.set(layout);
|
|
1296
1662
|
}
|
|
@@ -1304,13 +1670,13 @@ class QueryDevtoolsComponent {
|
|
|
1304
1670
|
this.queryHistory.set([]);
|
|
1305
1671
|
}
|
|
1306
1672
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1307
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.6", type: QueryDevtoolsComponent, isStandalone: true, selector: "et-query-devtools", host: { classAttribute: "et-query-devtools" }, ngImport: i0, template: "<button *ngIf=\"!isOpen()\" (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn et-qd-chip\">Open Devtools</button>\n\n<div\n *ngIf=\"isOpen()\"\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 <option *ngFor=\"let clientConfig of queryClientConfigs; index as i; trackBy: trackByClient\" [value]=\"i\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </option>\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 <div *ngIf=\"selectedClientConfig() as cfg\" 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 <div *ngIf=\"selectedClientConfig() as cfg\" class=\"et-qd-queries\">\n <p class=\"et-qd-queries__title\">Query browser</p>\n <div class=\"et-qd-queries__actions\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'live' }\"\n (click)=\"selectQueryListMode('live')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Live ({{ queries()?.length ?? 0 }})\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'history' }\"\n (click)=\"selectQueryListMode('history')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n History ({{ queryHistory().length }}/50)\n </button>\n <ng-container *ngIf=\"queryListMode() === 'history'\">\n <div class=\"et-qd-queries__divider\"></div>\n <button (click)=\"clearQueryHistory()\" class=\"et-qd-chip et-qd-chip-bordered\">Clear history</button>\n </ng-container>\n </div>\n\n <div class=\"et-qd-queries__browser\">\n <ul *ngIf=\"queryListMode() === 'live'\" class=\"et-qd-queries__browser-list\">\n <li *ngFor=\"let query of queries(); trackBy: trackByQuery\">\n <button [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\" (click)=\"selectQuery(query)\">\n <span> {{ query._routeWithParams }}</span>\n </button>\n </li>\n </ul>\n <ul *ngIf=\"queryListMode() === 'history'\" class=\"et-qd-queries__browser-list\">\n <li *ngFor=\"let query of queryHistory(); trackBy: trackByQuery\">\n <button [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\" (click)=\"selectQuery(query)\">\n {{ query._routeWithParams }}\n </button>\n </li>\n </ul>\n <div class=\"et-qd-queries__browser-detail\">\n <ng-container *ngIf=\"selectedQuery() as query\">\n <p class=\"et-qd-queries__browser-detail__title\">{{ query._routeWithParams }}</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 <ng-container *ngIf=\"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 </ng-container>\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>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>Arguments</p>\n <pre>{{ query._arguments | json }}</pre>\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 <pre *ngIf=\"showResponse()\">{{ query.state$ | async | json }}</pre>\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 <pre *ngIf=\"showRawResponse()\">{{ query.rawState | json }}</pre>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", styles: [".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)}.et-query-devtools-open-btn{position:fixed;inset-inline-start:0;inset-block-start:0;z-index:9999;all:unset;font-family:monospace}.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 #3c424a;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 #3c424a;margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid #3c424a;list-style:none;padding:0;margin:0;display:grid;grid-auto-flow:row;grid-auto-rows:50px;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 #3c424a;background-color:#25292e;color:#fff;text-align:left;padding:12px;height:100%;transition:all .3s ease-in-out;cursor:pointer}.et-qd-queries__browser-list li button span{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}.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-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: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom }); }
|
|
1673
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.6", type: QueryDevtoolsComponent, isStandalone: true, selector: "et-query-devtools", host: { classAttribute: "et-query-devtools" }, ngImport: i0, template: "<button *ngIf=\"!isOpen()\" (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn et-qd-chip\">Open Devtools</button>\n\n<div\n *ngIf=\"isOpen()\"\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 <option *ngFor=\"let clientConfig of queryClientConfigs; index as i; trackBy: trackByClient\" [value]=\"i\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </option>\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 <div *ngIf=\"selectedClientConfig() as cfg\" 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 <div *ngIf=\"selectedClientConfig() as cfg\" class=\"et-qd-queries\">\n <p class=\"et-qd-queries__title\">Query browser</p>\n <div class=\"et-qd-queries__actions\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'live' }\"\n (click)=\"selectQueryListMode('live')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Live ({{ queries()?.length ?? 0 }})\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'history' }\"\n (click)=\"selectQueryListMode('history')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n History ({{ queryHistory().length }}/50)\n </button>\n <ng-container *ngIf=\"queryListMode() === 'history'\">\n <div class=\"et-qd-queries__divider\"></div>\n <button (click)=\"clearQueryHistory()\" class=\"et-qd-chip et-qd-chip-bordered\">Clear history</button>\n </ng-container>\n </div>\n\n <div class=\"et-qd-queries__browser\">\n <ul *ngIf=\"queryListMode() === 'live'\" class=\"et-qd-queries__browser-list\">\n <li *ngFor=\"let query of queries(); trackBy: trackByQuery\">\n <button [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\" (click)=\"selectQuery(query)\">\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n </ul>\n <ul *ngIf=\"queryListMode() === 'history'\" class=\"et-qd-queries__browser-list\">\n <li *ngFor=\"let query of queryHistory(); trackBy: trackByQuery\">\n <button [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\" (click)=\"selectQuery(query)\">\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n </ul>\n <div class=\"et-qd-queries__browser-detail\">\n <ng-container *ngIf=\"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 <ng-container *ngIf=\"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 </ng-container>\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>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>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 <pre *ngIf=\"showArguments()\">{{ query._arguments | json }}</pre>\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 <pre *ngIf=\"showResponse()\">{{ query.state$ | async | json }}</pre>\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 <pre *ngIf=\"showRawResponse()\">{{ query.rawState | json }}</pre>\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 <pre *ngIf=\"showQueryConfig()\">{{ stringifiedQueryConfig() | json }}</pre>\n </div>\n\n <div *ngIf=\"!!query._queryConfig.entity\" 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 <pre *ngIf=\"showEntityStoreValue()\">{{ selectedQueryEntityStoreValue$ | async | json }}</pre>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", styles: [".et-query-devtools{position:fixed;top:0;z-index:1000000;font-size:14px}.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)}.et-query-devtools-open-btn{position:fixed;inset-inline-start:0;inset-block-start:0;z-index:9999;all:unset;font-family:monospace}.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 #3c424a;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 #3c424a;margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid #3c424a;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 #3c424a;background-color:#25292e;color:#fff;text-align:left;padding:12px;height:100%;transition:all .3s ease-in-out;cursor:pointer;display:grid;gap:2px}.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-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: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.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" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom }); }
|
|
1308
1674
|
}
|
|
1309
1675
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
|
|
1310
1676
|
type: Component,
|
|
1311
1677
|
args: [{ selector: 'et-query-devtools', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, host: {
|
|
1312
1678
|
class: 'et-query-devtools',
|
|
1313
|
-
}, imports: [NgIf, NgFor, AsyncPipe, JsonPipe, ReactiveFormsModule, NgClass], hostDirectives: [], template: "<button *ngIf=\"!isOpen()\" (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn et-qd-chip\">Open Devtools</button>\n\n<div\n *ngIf=\"isOpen()\"\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 <option *ngFor=\"let clientConfig of queryClientConfigs; index as i; trackBy: trackByClient\" [value]=\"i\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </option>\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 <div *ngIf=\"selectedClientConfig() as cfg\" 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 <div *ngIf=\"selectedClientConfig() as cfg\" class=\"et-qd-queries\">\n <p class=\"et-qd-queries__title\">Query browser</p>\n <div class=\"et-qd-queries__actions\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'live' }\"\n (click)=\"selectQueryListMode('live')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Live ({{ queries()?.length ?? 0 }})\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'history' }\"\n (click)=\"selectQueryListMode('history')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n History ({{ queryHistory().length }}/50)\n </button>\n <ng-container *ngIf=\"queryListMode() === 'history'\">\n <div class=\"et-qd-queries__divider\"></div>\n <button (click)=\"clearQueryHistory()\" class=\"et-qd-chip et-qd-chip-bordered\">Clear history</button>\n </ng-container>\n </div>\n\n <div class=\"et-qd-queries__browser\">\n <ul *ngIf=\"queryListMode() === 'live'\" class=\"et-qd-queries__browser-list\">\n <li *ngFor=\"let query of queries(); trackBy: trackByQuery\">\n <button [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\" (click)=\"selectQuery(query)\">\n <span> {{ query._routeWithParams }}</span>\n </button>\n </li>\n </ul>\n <ul *ngIf=\"queryListMode() === 'history'\" class=\"et-qd-queries__browser-list\">\n <li *ngFor=\"let query of queryHistory(); trackBy: trackByQuery\">\n <button [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\" (click)=\"selectQuery(query)\">\n {{ query._routeWithParams }}\n </button>\n </li>\n </ul>\n <div class=\"et-qd-queries__browser-detail\">\n <ng-container *ngIf=\"selectedQuery() as query\">\n <p class=\"et-qd-queries__browser-detail__title\">{{ query._routeWithParams }}</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 <ng-container *ngIf=\"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 </ng-container>\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>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>Arguments</p>\n <pre>{{ query._arguments | json }}</pre>\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 <pre *ngIf=\"showResponse()\">{{ query.state$ | async | json }}</pre>\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 <pre *ngIf=\"showRawResponse()\">{{ query.rawState | json }}</pre>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", styles: [".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)}.et-query-devtools-open-btn{position:fixed;inset-inline-start:0;inset-block-start:0;z-index:9999;all:unset;font-family:monospace}.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 #3c424a;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 #3c424a;margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid #3c424a;list-style:none;padding:0;margin:0;display:grid;grid-auto-flow:row;grid-auto-rows:50px;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 #3c424a;background-color:#25292e;color:#fff;text-align:left;padding:12px;height:100%;transition:all .3s ease-in-out;cursor:pointer}.et-qd-queries__browser-list li button span{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}.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-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"] }]
|
|
1679
|
+
}, imports: [NgIf, NgFor, AsyncPipe, JsonPipe, ReactiveFormsModule, NgClass, QueryShortNamePipe], hostDirectives: [], template: "<button *ngIf=\"!isOpen()\" (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn et-qd-chip\">Open Devtools</button>\n\n<div\n *ngIf=\"isOpen()\"\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 <option *ngFor=\"let clientConfig of queryClientConfigs; index as i; trackBy: trackByClient\" [value]=\"i\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </option>\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 <div *ngIf=\"selectedClientConfig() as cfg\" 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 <div *ngIf=\"selectedClientConfig() as cfg\" class=\"et-qd-queries\">\n <p class=\"et-qd-queries__title\">Query browser</p>\n <div class=\"et-qd-queries__actions\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'live' }\"\n (click)=\"selectQueryListMode('live')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Live ({{ queries()?.length ?? 0 }})\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'history' }\"\n (click)=\"selectQueryListMode('history')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n History ({{ queryHistory().length }}/50)\n </button>\n <ng-container *ngIf=\"queryListMode() === 'history'\">\n <div class=\"et-qd-queries__divider\"></div>\n <button (click)=\"clearQueryHistory()\" class=\"et-qd-chip et-qd-chip-bordered\">Clear history</button>\n </ng-container>\n </div>\n\n <div class=\"et-qd-queries__browser\">\n <ul *ngIf=\"queryListMode() === 'live'\" class=\"et-qd-queries__browser-list\">\n <li *ngFor=\"let query of queries(); trackBy: trackByQuery\">\n <button [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\" (click)=\"selectQuery(query)\">\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n </ul>\n <ul *ngIf=\"queryListMode() === 'history'\" class=\"et-qd-queries__browser-list\">\n <li *ngFor=\"let query of queryHistory(); trackBy: trackByQuery\">\n <button [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\" (click)=\"selectQuery(query)\">\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n </ul>\n <div class=\"et-qd-queries__browser-detail\">\n <ng-container *ngIf=\"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 <ng-container *ngIf=\"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 </ng-container>\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>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>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 <pre *ngIf=\"showArguments()\">{{ query._arguments | json }}</pre>\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 <pre *ngIf=\"showResponse()\">{{ query.state$ | async | json }}</pre>\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 <pre *ngIf=\"showRawResponse()\">{{ query.rawState | json }}</pre>\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 <pre *ngIf=\"showQueryConfig()\">{{ stringifiedQueryConfig() | json }}</pre>\n </div>\n\n <div *ngIf=\"!!query._queryConfig.entity\" 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 <pre *ngIf=\"showEntityStoreValue()\">{{ selectedQueryEntityStoreValue$ | async | json }}</pre>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", styles: [".et-query-devtools{position:fixed;top:0;z-index:1000000;font-size:14px}.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)}.et-query-devtools-open-btn{position:fixed;inset-inline-start:0;inset-block-start:0;z-index:9999;all:unset;font-family:monospace}.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 #3c424a;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 #3c424a;margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid #3c424a;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 #3c424a;background-color:#25292e;color:#fff;text-align:left;padding:12px;height:100%;transition:all .3s ease-in-out;cursor:pointer;display:grid;gap:2px}.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-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"] }]
|
|
1314
1680
|
}], ctorParameters: function () { return []; } });
|
|
1315
1681
|
|
|
1316
1682
|
class QueryDirective {
|
|
@@ -1820,7 +2186,13 @@ function flatten(arr) {
|
|
|
1820
2186
|
class EntityStore {
|
|
1821
2187
|
constructor(_config) {
|
|
1822
2188
|
this._config = _config;
|
|
2189
|
+
/**
|
|
2190
|
+
* @internal
|
|
2191
|
+
*/
|
|
1823
2192
|
this._dictionary = new Map();
|
|
2193
|
+
/**
|
|
2194
|
+
* @internal
|
|
2195
|
+
*/
|
|
1824
2196
|
this._change$ = new Subject();
|
|
1825
2197
|
}
|
|
1826
2198
|
select(keyOrKeys) {
|
|
@@ -1951,261 +2323,6 @@ const removeFrom = (store, { where, id }) => {
|
|
|
1951
2323
|
.subscribe();
|
|
1952
2324
|
};
|
|
1953
2325
|
|
|
1954
|
-
class QueryCreator {
|
|
1955
|
-
constructor(_queryConfig, _client, _store) {
|
|
1956
|
-
this._queryConfig = _queryConfig;
|
|
1957
|
-
this._client = _client;
|
|
1958
|
-
this._store = _store;
|
|
1959
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1960
|
-
// @ts-ignore
|
|
1961
|
-
this.prepare = (args) => {
|
|
1962
|
-
const route = buildRoute({
|
|
1963
|
-
base: this._client.config.baseRoute,
|
|
1964
|
-
route: this._queryConfig.route,
|
|
1965
|
-
pathParams: args?.pathParams,
|
|
1966
|
-
queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
|
|
1967
|
-
queryParamConfig: this._client.config.request?.queryParams,
|
|
1968
|
-
});
|
|
1969
|
-
const cacheKey = isGqlQueryConfig(this._queryConfig) ? buildGqlCacheKey(this._queryConfig, args) : route;
|
|
1970
|
-
if (shouldCacheQuery(this._queryConfig.method)) {
|
|
1971
|
-
const existingQuery = this._store.get(cacheKey);
|
|
1972
|
-
if (existingQuery) {
|
|
1973
|
-
return existingQuery;
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
const query = new Query(this._client, this._queryConfig, route, args ?? {});
|
|
1977
|
-
if (shouldCacheQuery(this._queryConfig.method)) {
|
|
1978
|
-
this._store.add(cacheKey, query);
|
|
1979
|
-
}
|
|
1980
|
-
return query;
|
|
1981
|
-
};
|
|
1982
|
-
this.behaviorSubject = (initialValue) => new BehaviorSubject(initialValue ?? null);
|
|
1983
|
-
}
|
|
1984
|
-
}
|
|
1985
|
-
|
|
1986
|
-
class QueryStore {
|
|
1987
|
-
constructor(_config) {
|
|
1988
|
-
this._config = _config;
|
|
1989
|
-
/**
|
|
1990
|
-
* @internal
|
|
1991
|
-
*/
|
|
1992
|
-
this._store = new Map();
|
|
1993
|
-
this._garbageCollector = null;
|
|
1994
|
-
this._isInLowResourceMode = false;
|
|
1995
|
-
this._lastBlurTimestamp = Date.now();
|
|
1996
|
-
this._storeChange$ = new Subject();
|
|
1997
|
-
this.storeChange$ = this._storeChange$.asObservable();
|
|
1998
|
-
this._initSmartQueryHandling();
|
|
1999
|
-
}
|
|
2000
|
-
add(id, query) {
|
|
2001
|
-
this._store.set(id, query);
|
|
2002
|
-
this._initGarbageCollector();
|
|
2003
|
-
this._logState(id, query, 'SET');
|
|
2004
|
-
this._storeChange$.next(id);
|
|
2005
|
-
}
|
|
2006
|
-
get(id) {
|
|
2007
|
-
return this._store.get(id) ?? null;
|
|
2008
|
-
}
|
|
2009
|
-
remove(id) {
|
|
2010
|
-
this._store.delete(id);
|
|
2011
|
-
this._logState(id, null, 'REMOVE');
|
|
2012
|
-
this._storeChange$.next(id);
|
|
2013
|
-
}
|
|
2014
|
-
forEach(callback) {
|
|
2015
|
-
for (const [key, query] of this._store) {
|
|
2016
|
-
callback(query, key);
|
|
2017
|
-
}
|
|
2018
|
-
}
|
|
2019
|
-
refreshQueriesInUse(config) {
|
|
2020
|
-
const { ignoreCacheValidity, purgeUnused } = config ?? {};
|
|
2021
|
-
for (const [key, query] of this._store) {
|
|
2022
|
-
if (query.isInUse &&
|
|
2023
|
-
(query.isExpired || ignoreCacheValidity) &&
|
|
2024
|
-
query.autoRefreshOnConfig.queryClientDefaultHeadersChange) {
|
|
2025
|
-
query.execute({ skipCache: true, _triggeredVia: 'auto' });
|
|
2026
|
-
}
|
|
2027
|
-
else if (purgeUnused && !query.isInUse) {
|
|
2028
|
-
this.remove(key);
|
|
2029
|
-
}
|
|
2030
|
-
}
|
|
2031
|
-
}
|
|
2032
|
-
_initSmartQueryHandling() {
|
|
2033
|
-
const windowBlur$ = fromEvent(window, 'blur');
|
|
2034
|
-
const windowFocus$ = fromEvent(window, 'focus');
|
|
2035
|
-
windowBlur$.subscribe(() => {
|
|
2036
|
-
timer(5000)
|
|
2037
|
-
.pipe(takeUntil(windowFocus$), take(1))
|
|
2038
|
-
.subscribe(() => {
|
|
2039
|
-
this._lastBlurTimestamp = Date.now();
|
|
2040
|
-
this._isInLowResourceMode = true;
|
|
2041
|
-
this._stopGarbageCollector();
|
|
2042
|
-
if (this._config?.enableSmartPolling) {
|
|
2043
|
-
this.forEach((query) => {
|
|
2044
|
-
if (!query.isPolling || !query._enableSmartPolling) {
|
|
2045
|
-
return;
|
|
2046
|
-
}
|
|
2047
|
-
query.pausePolling();
|
|
2048
|
-
});
|
|
2049
|
-
}
|
|
2050
|
-
});
|
|
2051
|
-
});
|
|
2052
|
-
windowFocus$.subscribe(() => {
|
|
2053
|
-
if (!this._isInLowResourceMode) {
|
|
2054
|
-
return;
|
|
2055
|
-
}
|
|
2056
|
-
this._isInLowResourceMode = false;
|
|
2057
|
-
if (this._config?.enableSmartPolling || this._config?.autoRefreshQueriesOnWindowFocus) {
|
|
2058
|
-
this.forEach((query) => {
|
|
2059
|
-
if (this._config?.enableSmartPolling && query._isPollingPaused) {
|
|
2060
|
-
query.resumePolling();
|
|
2061
|
-
}
|
|
2062
|
-
if (Date.now() - this._lastBlurTimestamp > 15000) {
|
|
2063
|
-
if (this._config?.autoRefreshQueriesOnWindowFocus &&
|
|
2064
|
-
query.isExpired &&
|
|
2065
|
-
query.isInUse &&
|
|
2066
|
-
query.autoRefreshOnConfig.windowFocus) {
|
|
2067
|
-
query.execute({ skipCache: true, _triggeredVia: 'auto' });
|
|
2068
|
-
}
|
|
2069
|
-
}
|
|
2070
|
-
});
|
|
2071
|
-
}
|
|
2072
|
-
this._initGarbageCollector();
|
|
2073
|
-
});
|
|
2074
|
-
}
|
|
2075
|
-
_logState(key, item, operation) {
|
|
2076
|
-
if (!this._config?.enableChangeLogging)
|
|
2077
|
-
return;
|
|
2078
|
-
const stateAsJson = {};
|
|
2079
|
-
this._store.forEach((value, key) => {
|
|
2080
|
-
stateAsJson[key] = value;
|
|
2081
|
-
});
|
|
2082
|
-
console.log(`%c[${operation}] ${key}`, 'font-weight: bold');
|
|
2083
|
-
console.log({ operation, key, item });
|
|
2084
|
-
console.log(stateAsJson);
|
|
2085
|
-
}
|
|
2086
|
-
_initGarbageCollector() {
|
|
2087
|
-
if (this._garbageCollector !== null) {
|
|
2088
|
-
return;
|
|
2089
|
-
}
|
|
2090
|
-
this._logGarbageCollector('Start');
|
|
2091
|
-
this._garbageCollector = window.setInterval(() => {
|
|
2092
|
-
this._runGarbageCollector();
|
|
2093
|
-
}, 15000);
|
|
2094
|
-
}
|
|
2095
|
-
_stopGarbageCollector() {
|
|
2096
|
-
if (this._garbageCollector !== null) {
|
|
2097
|
-
window.clearInterval(this._garbageCollector);
|
|
2098
|
-
this._garbageCollector = null;
|
|
2099
|
-
this._logGarbageCollector('Stop');
|
|
2100
|
-
}
|
|
2101
|
-
}
|
|
2102
|
-
_runGarbageCollector() {
|
|
2103
|
-
this._logGarbageCollector('Collecting...');
|
|
2104
|
-
this._store.forEach((item, key) => {
|
|
2105
|
-
if (item.isExpired && !item.isInUse) {
|
|
2106
|
-
this.remove(key);
|
|
2107
|
-
}
|
|
2108
|
-
});
|
|
2109
|
-
this._logGarbageCollector('Collection done');
|
|
2110
|
-
if (!this._store.size) {
|
|
2111
|
-
this._stopGarbageCollector();
|
|
2112
|
-
}
|
|
2113
|
-
}
|
|
2114
|
-
_logGarbageCollector(action) {
|
|
2115
|
-
if (!this._config?.enableGarbageCollectorLogging)
|
|
2116
|
-
return;
|
|
2117
|
-
console.log(`%cGC: ${action}`, 'color: yellow; font-weight: bold');
|
|
2118
|
-
}
|
|
2119
|
-
}
|
|
2120
|
-
|
|
2121
|
-
class QueryClient {
|
|
2122
|
-
get config() {
|
|
2123
|
-
return this._clientConfig;
|
|
2124
|
-
}
|
|
2125
|
-
get authProvider() {
|
|
2126
|
-
return this._authProvider$.getValue() ?? this._clientConfig.parent?._authProvider$.getValue() ?? null;
|
|
2127
|
-
}
|
|
2128
|
-
get authProvider$() {
|
|
2129
|
-
return this._authProvider$.asObservable() ?? this._clientConfig.parent?._authProvider$.asObservable() ?? null;
|
|
2130
|
-
}
|
|
2131
|
-
constructor(_clientConfig) {
|
|
2132
|
-
this._clientConfig = _clientConfig;
|
|
2133
|
-
this._authProvider$ = new BehaviorSubject(null);
|
|
2134
|
-
this.get = (queryConfig) => this.fetch({
|
|
2135
|
-
...queryConfig,
|
|
2136
|
-
method: 'GET',
|
|
2137
|
-
});
|
|
2138
|
-
this.post = (queryConfig) => this.fetch({
|
|
2139
|
-
...queryConfig,
|
|
2140
|
-
method: 'POST',
|
|
2141
|
-
});
|
|
2142
|
-
this.put = (queryConfig) => this.fetch({
|
|
2143
|
-
...queryConfig,
|
|
2144
|
-
method: 'PUT',
|
|
2145
|
-
});
|
|
2146
|
-
this.patch = (queryConfig) => this.fetch({
|
|
2147
|
-
...queryConfig,
|
|
2148
|
-
method: 'PATCH',
|
|
2149
|
-
});
|
|
2150
|
-
this.delete = (queryConfig) => this.fetch({
|
|
2151
|
-
...queryConfig,
|
|
2152
|
-
method: 'DELETE',
|
|
2153
|
-
});
|
|
2154
|
-
this.gqlQuery = (queryConfig) => this.fetch({
|
|
2155
|
-
...queryConfig,
|
|
2156
|
-
method: 'GQL_QUERY',
|
|
2157
|
-
});
|
|
2158
|
-
this.gqlMutate = (queryConfig) => this.fetch({
|
|
2159
|
-
...queryConfig,
|
|
2160
|
-
method: 'GQL_MUTATE',
|
|
2161
|
-
});
|
|
2162
|
-
this.fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
|
|
2163
|
-
this.setAuthProvider = (authProvider) => {
|
|
2164
|
-
if (this.authProvider) {
|
|
2165
|
-
throw new Error('The auth provider is already set. Please call clearAuthProvider() first.');
|
|
2166
|
-
}
|
|
2167
|
-
this._authProvider$.next(authProvider);
|
|
2168
|
-
};
|
|
2169
|
-
this.setDefaultHeaders = (config) => {
|
|
2170
|
-
if (!this._clientConfig.request) {
|
|
2171
|
-
this._clientConfig.request = {
|
|
2172
|
-
headers: config.headers ?? undefined,
|
|
2173
|
-
};
|
|
2174
|
-
}
|
|
2175
|
-
else {
|
|
2176
|
-
this._clientConfig.request.headers = config.headers ?? undefined;
|
|
2177
|
-
}
|
|
2178
|
-
if (config.refreshQueriesInUse) {
|
|
2179
|
-
this._store.refreshQueriesInUse({ purgeUnused: true, ignoreCacheValidity: true });
|
|
2180
|
-
}
|
|
2181
|
-
};
|
|
2182
|
-
this.clearAuthProvider = () => {
|
|
2183
|
-
this.authProvider?.cleanUp();
|
|
2184
|
-
this._authProvider$.next(null);
|
|
2185
|
-
};
|
|
2186
|
-
this._store = new QueryStore({
|
|
2187
|
-
enableChangeLogging: _clientConfig.logging?.queryStateChanges,
|
|
2188
|
-
enableGarbageCollectorLogging: _clientConfig.logging?.queryStateGarbageCollector,
|
|
2189
|
-
autoRefreshQueriesOnWindowFocus: _clientConfig.request?.autoRefreshQueriesOnWindowFocus ?? true,
|
|
2190
|
-
enableSmartPolling: _clientConfig.request?.enableSmartPolling ?? true,
|
|
2191
|
-
});
|
|
2192
|
-
}
|
|
2193
|
-
}
|
|
2194
|
-
|
|
2195
|
-
const shouldCacheQuery = (method) => {
|
|
2196
|
-
return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
|
|
2197
|
-
};
|
|
2198
|
-
const buildGqlCacheKey = (config, args) => {
|
|
2199
|
-
const { query } = config;
|
|
2200
|
-
const variables = args?.variables || {};
|
|
2201
|
-
const queryWithoutNewLinesAndWhitespace = query.replace(/\s/g, '');
|
|
2202
|
-
const queryFirst50Chars = queryWithoutNewLinesAndWhitespace.slice(0, 50);
|
|
2203
|
-
const queryMiddle25Chars = queryWithoutNewLinesAndWhitespace.slice(queryWithoutNewLinesAndWhitespace.length / 2 - 25, queryWithoutNewLinesAndWhitespace.length / 2 + 25);
|
|
2204
|
-
const queryLast50Chars = queryWithoutNewLinesAndWhitespace.slice(-50);
|
|
2205
|
-
const vars = JSON.stringify(variables);
|
|
2206
|
-
return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
|
|
2207
|
-
};
|
|
2208
|
-
|
|
2209
2326
|
const ET_ARR_PREFIX = 'ET_ARR__';
|
|
2210
2327
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2211
2328
|
class QueryFormGroup extends FormGroup {
|
|
@@ -2566,5 +2683,5 @@ const def = () => null;
|
|
|
2566
2683
|
* Generated bundle index. Do not edit.
|
|
2567
2684
|
*/
|
|
2568
2685
|
|
|
2569
|
-
export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, QUERY_CLIENT_DEVTOOLS_TOKEN, Query, QueryClient, QueryCreator, QueryDevtoolsComponent, QueryDirective, QueryError, QueryField, QueryForm, QueryFormGroup, QueryStore, buildErrorMessage, buildGqlCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds, extractQuery, filterFailure, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, insertFrom, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isClassValidatorError, isCustomHeaderAuthProvider, isEmptyString, isGqlQueryConfig, isNaN$1 as isNaN, isQuery, isQueryCollection, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, isSymfonyFormViolationListError, isSymfonyPagerfantaOutOfRangeError, mapToPaginated, mergeHeaders, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, provideQueryClientForDevtools, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, removeFrom, request, resetPageOnError, serializeBody, shouldCacheQuery, shouldRetryRequest, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
|
|
2686
|
+
export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, QUERY_CLIENT_DEVTOOLS_TOKEN, Query, QueryClient, QueryCreator, QueryDevtoolsComponent, QueryDirective, QueryError, QueryField, QueryForm, QueryFormGroup, QueryShortNamePipe, QueryStore, buildErrorMessage, buildGqlCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds, extractQuery, filterFailure, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, insertFrom, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isClassValidatorError, isCustomHeaderAuthProvider, isEmptyString, isGqlQueryConfig, isNaN$1 as isNaN, isQuery, isQueryCollection, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, isSymfonyFormViolationListError, isSymfonyPagerfantaOutOfRangeError, mapToPaginated, mergeHeaders, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, provideQueryClientForDevtools, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, removeFrom, request, resetPageOnError, serializeBody, shouldCacheQuery, shouldRetryRequest, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
|
|
2570
2687
|
//# sourceMappingURL=ethlete-query.mjs.map
|