@ethlete/query 4.7.4 → 4.7.6
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 +100 -25
- 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 +28 -21
- 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 +420 -304
- package/fesm2022/ethlete-query.mjs.map +1 -1
- package/lib/devtools/components/query-devtools/query-devtools.component.d.ts +38 -3
- 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 +14 -7
- package/lib/query-store/query-store.d.ts +2 -0
- package/package.json +1 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import * as i1 from '@ethlete/core';
|
|
2
|
-
import { getCookie, setCookie, deleteCookie, createDestroy, DelayableDirective, RouterStateService, clone, equal, ET_PROPERTY_REMOVED } from '@ethlete/core';
|
|
3
|
-
import { Observable, filter, takeWhile, switchMap, of, tap,
|
|
1
|
+
import * as i1$1 from '@ethlete/core';
|
|
2
|
+
import { getCookie, setCookie, deleteCookie, createDestroy, nextFrame, DelayableDirective, RouterStateService, clone, equal, ET_PROPERTY_REMOVED } from '@ethlete/core';
|
|
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, signal, computed, effect, Component, ChangeDetectionStrategy, ViewEncapsulation, TemplateRef, ViewContainerRef, ErrorHandler,
|
|
6
|
-
import { NgIf, NgFor, AsyncPipe, JsonPipe } from '@angular/common';
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
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
|
+
import { NgIf, NgFor, AsyncPipe, JsonPipe, NgClass } from '@angular/common';
|
|
7
|
+
import { toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
8
|
+
import * as i1 from '@angular/forms';
|
|
9
|
+
import { FormControl, ReactiveFormsModule, FormGroup } from '@angular/forms';
|
|
9
10
|
import { Router, ActivatedRoute } from '@angular/router';
|
|
10
11
|
|
|
11
12
|
class CustomHeaderAuthProvider {
|
|
@@ -492,6 +493,270 @@ const request = (config) => {
|
|
|
492
493
|
});
|
|
493
494
|
};
|
|
494
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
|
+
|
|
495
760
|
const getOpName = /(query|mutation) ?([\w\d-_]+)? ?\(.*?\)? \{/;
|
|
496
761
|
const transformGql = (str) => {
|
|
497
762
|
str = Array.isArray(str) ? str.join('') : str;
|
|
@@ -742,9 +1007,10 @@ const paginatedEntityValueUpdater = (findFn) => ({ response, rawResponse, entity
|
|
|
742
1007
|
};
|
|
743
1008
|
};
|
|
744
1009
|
|
|
1010
|
+
let _nextQueryId = 0;
|
|
745
1011
|
class Query {
|
|
746
1012
|
get _nextId() {
|
|
747
|
-
return ++this.
|
|
1013
|
+
return ++this._currentLocalId;
|
|
748
1014
|
}
|
|
749
1015
|
get state$() {
|
|
750
1016
|
return this._state$.pipe(tap((s) => {
|
|
@@ -800,27 +1066,32 @@ class Query {
|
|
|
800
1066
|
get _enableSmartPolling() {
|
|
801
1067
|
return this._queryConfig.enableSmartPolling ?? true;
|
|
802
1068
|
}
|
|
803
|
-
/**
|
|
804
|
-
* @internal
|
|
805
|
-
*/
|
|
806
|
-
get _arguments() {
|
|
807
|
-
return this._args;
|
|
808
|
-
}
|
|
809
1069
|
get store() {
|
|
810
1070
|
return this._queryConfig.entity?.store ?? null;
|
|
811
1071
|
}
|
|
812
|
-
|
|
1072
|
+
get canBeCached() {
|
|
1073
|
+
return shouldCacheQuery(this._queryConfig.method);
|
|
1074
|
+
}
|
|
1075
|
+
constructor(_client,
|
|
813
1076
|
/**
|
|
814
1077
|
* @internal
|
|
815
1078
|
*/
|
|
816
|
-
|
|
1079
|
+
_queryConfig,
|
|
1080
|
+
/**
|
|
1081
|
+
* @internal
|
|
1082
|
+
*/
|
|
1083
|
+
_routeWithParams,
|
|
1084
|
+
/**
|
|
1085
|
+
* @internal
|
|
1086
|
+
*/
|
|
1087
|
+
_arguments) {
|
|
817
1088
|
this._client = _client;
|
|
818
1089
|
this._queryConfig = _queryConfig;
|
|
819
1090
|
this._routeWithParams = _routeWithParams;
|
|
820
|
-
this.
|
|
821
|
-
this.
|
|
1091
|
+
this._arguments = _arguments;
|
|
1092
|
+
this._id = _nextQueryId++;
|
|
1093
|
+
this._currentLocalId = 0;
|
|
822
1094
|
this._pollingSubscription = null;
|
|
823
|
-
this._requestSubscription = null;
|
|
824
1095
|
this._onAbort$ = new Subject();
|
|
825
1096
|
this._currentPollConfig = null;
|
|
826
1097
|
/**
|
|
@@ -829,7 +1100,7 @@ class Query {
|
|
|
829
1100
|
this._isPollingPaused = false;
|
|
830
1101
|
this._state$ = new BehaviorSubject({
|
|
831
1102
|
type: "PREPARED" /* QueryStateType.Prepared */,
|
|
832
|
-
meta: { id: this.
|
|
1103
|
+
meta: { id: this._currentLocalId, triggeredVia: 'program' },
|
|
833
1104
|
});
|
|
834
1105
|
}
|
|
835
1106
|
execute(options = {}) {
|
|
@@ -854,9 +1125,9 @@ class Query {
|
|
|
854
1125
|
}
|
|
855
1126
|
this._state$.next({ type: "LOADING" /* QueryStateType.Loading */, meta });
|
|
856
1127
|
const method = computeQueryMethod({ config: queryConfig, client: this._client });
|
|
857
|
-
const body = computeQueryBody({ config: queryConfig, client: this._client, args: this.
|
|
858
|
-
const headers = computeQueryHeaders({ client: this._client, config: queryConfig, args: this.
|
|
859
|
-
|
|
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 });
|
|
1130
|
+
request({
|
|
860
1131
|
urlWithParams: this._routeWithParams,
|
|
861
1132
|
method,
|
|
862
1133
|
body,
|
|
@@ -943,9 +1214,9 @@ class Query {
|
|
|
943
1214
|
? response['data']
|
|
944
1215
|
: response;
|
|
945
1216
|
if (this._queryConfig.entity && this._queryConfig.entity.set) {
|
|
946
|
-
const id = this._queryConfig.entity?.id({ args: this.
|
|
1217
|
+
const id = this._queryConfig.entity?.id({ args: this._arguments, response: responseData });
|
|
947
1218
|
this._queryConfig.entity?.set({
|
|
948
|
-
args: this.
|
|
1219
|
+
args: this._arguments,
|
|
949
1220
|
response: responseData,
|
|
950
1221
|
id,
|
|
951
1222
|
store: this._queryConfig.entity.store,
|
|
@@ -989,9 +1260,9 @@ class Query {
|
|
|
989
1260
|
if (!isQueryStateSuccess(s) || !this._queryConfig.entity?.get) {
|
|
990
1261
|
return of(s);
|
|
991
1262
|
}
|
|
992
|
-
const id = this._queryConfig.entity.id({ args: this.
|
|
1263
|
+
const id = this._queryConfig.entity.id({ args: this._arguments, response: s.response });
|
|
993
1264
|
return this._queryConfig.entity
|
|
994
|
-
.get({ args: this.
|
|
1265
|
+
.get({ args: this._arguments, id, response: s.response, store: this._queryConfig.entity.store })
|
|
995
1266
|
.pipe(map((v) => ({ ...s, response: v })));
|
|
996
1267
|
}
|
|
997
1268
|
}
|
|
@@ -1173,6 +1444,29 @@ const isClassValidatorError = (error) => {
|
|
|
1173
1444
|
return typeof error === 'object' && error !== null && 'statusCode' in error && 'message' in error && 'error' in error;
|
|
1174
1445
|
};
|
|
1175
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
|
+
|
|
1176
1470
|
const QUERY_CLIENT_DEVTOOLS_TOKEN = new InjectionToken('QUERY_CLIENT_DEVTOOLS_TOKEN');
|
|
1177
1471
|
const provideQueryClientForDevtools = (queryClient) => {
|
|
1178
1472
|
if (!isDevMode()) {
|
|
@@ -1187,6 +1481,7 @@ const provideQueryClientForDevtools = (queryClient) => {
|
|
|
1187
1481
|
|
|
1188
1482
|
class QueryDevtoolsComponent {
|
|
1189
1483
|
constructor() {
|
|
1484
|
+
this._cdr = inject(ChangeDetectorRef);
|
|
1190
1485
|
this._destroy$ = createDestroy();
|
|
1191
1486
|
this.queryClientConfigs = inject(QUERY_CLIENT_DEVTOOLS_TOKEN);
|
|
1192
1487
|
this.isOpen = signal(false);
|
|
@@ -1195,13 +1490,17 @@ class QueryDevtoolsComponent {
|
|
|
1195
1490
|
this.queryListMode = signal('live');
|
|
1196
1491
|
this.showResponse = signal(false);
|
|
1197
1492
|
this.showRawResponse = signal(false);
|
|
1198
|
-
this.
|
|
1199
|
-
this.
|
|
1493
|
+
this.showQueryConfig = signal(false);
|
|
1494
|
+
this.showEntityStoreValue = signal(false);
|
|
1495
|
+
this.showArguments = signal(false);
|
|
1496
|
+
this.selectedClientIdCtrl = new FormControl(0);
|
|
1497
|
+
this.selectedClientId = toSignal(this.selectedClientIdCtrl.valueChanges.pipe(startWith(this.selectedClientIdCtrl.value)));
|
|
1498
|
+
this.selectedQueryId = signal(null);
|
|
1200
1499
|
this.selectedClientConfig = computed(() => {
|
|
1201
1500
|
if (this.queryClientConfigs.length === 1) {
|
|
1202
1501
|
return this.queryClientConfigs[0];
|
|
1203
1502
|
}
|
|
1204
|
-
const index = this.selectedClientId();
|
|
1503
|
+
const index = this.selectedClientId() ?? 0;
|
|
1205
1504
|
return this.queryClientConfigs[index];
|
|
1206
1505
|
});
|
|
1207
1506
|
this.queryStore = computed(() => {
|
|
@@ -1212,22 +1511,74 @@ class QueryDevtoolsComponent {
|
|
|
1212
1511
|
this._queries$ = new BehaviorSubject([]);
|
|
1213
1512
|
this.queries = toSignal(this._queries$);
|
|
1214
1513
|
this.selectedQuery = computed(() => {
|
|
1215
|
-
const
|
|
1514
|
+
const id = this.selectedQueryId();
|
|
1216
1515
|
const mode = this.queryListMode();
|
|
1217
|
-
if (
|
|
1516
|
+
if (id === null || !mode) {
|
|
1218
1517
|
return null;
|
|
1219
1518
|
}
|
|
1220
1519
|
if (mode === 'live') {
|
|
1221
|
-
return this.queries()?.find((q) => q.
|
|
1520
|
+
return this.queries()?.find((q) => q._id === id) ?? null;
|
|
1222
1521
|
}
|
|
1223
|
-
return this.queryHistory()?.find((q) => q.
|
|
1522
|
+
return this.queryHistory()?.find((q) => q._id === id) ?? null;
|
|
1523
|
+
});
|
|
1524
|
+
this.selectedQueryEntityStore = computed(() => {
|
|
1525
|
+
const query = this.selectedQuery();
|
|
1526
|
+
if (!query)
|
|
1527
|
+
return null;
|
|
1528
|
+
return query.store;
|
|
1224
1529
|
});
|
|
1530
|
+
this.selectedQueryEntityStore$ = toObservable(this.selectedQueryEntityStore);
|
|
1531
|
+
this.selectedQueryEntityStoreValue$ = this.selectedQueryEntityStore$.pipe(switchMap((s) => s?._change$.pipe(startWith(''), map(() => s?._dictionary ?? null)) ?? of(null)));
|
|
1225
1532
|
this.queryHistory = signal([]);
|
|
1533
|
+
this.stringifiedQueryConfig = computed(() => {
|
|
1534
|
+
const query = this.selectedQuery();
|
|
1535
|
+
if (!query)
|
|
1536
|
+
return null;
|
|
1537
|
+
const cfg = query._queryConfig;
|
|
1538
|
+
const route = typeof cfg.route === 'string' ? cfg.route : cfg.route ? cfg.route({}).replace(/undefined/g, ':param') : null;
|
|
1539
|
+
const sharedCfg = {
|
|
1540
|
+
method: cfg.method,
|
|
1541
|
+
secure: cfg.secure,
|
|
1542
|
+
route,
|
|
1543
|
+
reportProgress: cfg.reportProgress,
|
|
1544
|
+
responseType: cfg.responseType,
|
|
1545
|
+
withCredentials: cfg.withCredentials,
|
|
1546
|
+
autoRefreshOn: cfg.autoRefreshOn,
|
|
1547
|
+
enableSmartPolling: cfg.enableSmartPolling,
|
|
1548
|
+
hasEntityStore: !!cfg.entity,
|
|
1549
|
+
};
|
|
1550
|
+
if (isGqlQueryConfig(cfg)) {
|
|
1551
|
+
return {
|
|
1552
|
+
...sharedCfg,
|
|
1553
|
+
query: cfg.query,
|
|
1554
|
+
transferVia: cfg.transferVia,
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1557
|
+
return {
|
|
1558
|
+
...sharedCfg,
|
|
1559
|
+
};
|
|
1560
|
+
});
|
|
1226
1561
|
this.trackByClient = (_, { client }) => client.config.baseRoute;
|
|
1227
|
-
this.trackByQuery = (_, {
|
|
1562
|
+
this.trackByQuery = (_, { _id }) => _id;
|
|
1563
|
+
this.selectedClientIdCtrl.valueChanges
|
|
1564
|
+
.pipe(tap(() => this.clearQueryHistory()), takeUntil(this._destroy$))
|
|
1565
|
+
.subscribe();
|
|
1228
1566
|
this.queryStore$
|
|
1229
1567
|
.pipe(switchMap((s) => s.storeChange$.pipe(startWith(''), map(() => s._store), tap((s) => this._queries$.next(Array.from(s.values()))), takeUntil(this._destroy$))))
|
|
1230
1568
|
.subscribe();
|
|
1569
|
+
this.queryStore$
|
|
1570
|
+
.pipe(switchMap((s) => s.queryCreated$.pipe(tap((query) => {
|
|
1571
|
+
const currentHistory = this.queryHistory();
|
|
1572
|
+
if (!currentHistory)
|
|
1573
|
+
return;
|
|
1574
|
+
const currentHistoryClone = [...currentHistory];
|
|
1575
|
+
if (!currentHistory.some((q) => q._id === query._id)) {
|
|
1576
|
+
currentHistoryClone.unshift(query);
|
|
1577
|
+
}
|
|
1578
|
+
currentHistoryClone.splice(50);
|
|
1579
|
+
this.queryHistory.set(currentHistoryClone);
|
|
1580
|
+
}), takeUntil(this._destroy$))))
|
|
1581
|
+
.subscribe();
|
|
1231
1582
|
this._queries$
|
|
1232
1583
|
.pipe(tap((queries) => {
|
|
1233
1584
|
const currentHistory = this.queryHistory();
|
|
@@ -1235,8 +1586,8 @@ class QueryDevtoolsComponent {
|
|
|
1235
1586
|
return;
|
|
1236
1587
|
const currentHistoryClone = [...currentHistory];
|
|
1237
1588
|
for (const query of queries) {
|
|
1238
|
-
if (!currentHistoryClone.
|
|
1239
|
-
currentHistoryClone.
|
|
1589
|
+
if (!currentHistoryClone.some((q) => q._id === query._id)) {
|
|
1590
|
+
currentHistoryClone.unshift(query);
|
|
1240
1591
|
}
|
|
1241
1592
|
}
|
|
1242
1593
|
currentHistoryClone.splice(50);
|
|
@@ -1250,8 +1601,11 @@ class QueryDevtoolsComponent {
|
|
|
1250
1601
|
snapLayout: this.snapLayout(),
|
|
1251
1602
|
showResponse: this.showResponse(),
|
|
1252
1603
|
showRawResponse: this.showRawResponse(),
|
|
1604
|
+
showQueryConfig: this.showQueryConfig(),
|
|
1605
|
+
showEntityStoreValue: this.showEntityStoreValue(),
|
|
1606
|
+
showArguments: this.showArguments(),
|
|
1253
1607
|
selectedClientId: this.selectedClientId(),
|
|
1254
|
-
selectedQueryPath: this.
|
|
1608
|
+
selectedQueryPath: this.selectedQueryId(),
|
|
1255
1609
|
queryListMode: this.queryListMode(),
|
|
1256
1610
|
};
|
|
1257
1611
|
window.localStorage.setItem('ethlete:query:devtools', JSON.stringify(devtoolConfig));
|
|
@@ -1264,8 +1618,11 @@ class QueryDevtoolsComponent {
|
|
|
1264
1618
|
this.snapLayout.set(parsed.snapLayout ?? 'full');
|
|
1265
1619
|
this.showResponse.set(parsed.showResponse ?? false);
|
|
1266
1620
|
this.showRawResponse.set(parsed.showRawResponse ?? false);
|
|
1267
|
-
this.
|
|
1268
|
-
this.
|
|
1621
|
+
this.showQueryConfig.set(parsed.showQueryConfig ?? false);
|
|
1622
|
+
this.showEntityStoreValue.set(parsed.showEntityStoreValue ?? false);
|
|
1623
|
+
this.showArguments.set(parsed.showArguments ?? false);
|
|
1624
|
+
this.selectedClientIdCtrl.setValue(parsed.selectedClientId ?? 0);
|
|
1625
|
+
this.selectedQueryId.set(parsed.selectedQueryPath ?? null);
|
|
1269
1626
|
this.queryListMode.set(parsed.queryListMode ?? 'live');
|
|
1270
1627
|
}
|
|
1271
1628
|
}
|
|
@@ -1277,34 +1634,42 @@ class QueryDevtoolsComponent {
|
|
|
1277
1634
|
}
|
|
1278
1635
|
toggleShowResponse() {
|
|
1279
1636
|
this.showResponse.set(!this.showResponse());
|
|
1637
|
+
nextFrame(() => {
|
|
1638
|
+
this._cdr.markForCheck();
|
|
1639
|
+
});
|
|
1640
|
+
}
|
|
1641
|
+
toggleShowQueryConfig() {
|
|
1642
|
+
this.showQueryConfig.set(!this.showQueryConfig());
|
|
1280
1643
|
}
|
|
1281
1644
|
toggleShowRawResponse() {
|
|
1282
1645
|
this.showRawResponse.set(!this.showRawResponse());
|
|
1283
1646
|
}
|
|
1647
|
+
toggleShowEntityStoreValue() {
|
|
1648
|
+
this.showEntityStoreValue.set(!this.showEntityStoreValue());
|
|
1649
|
+
}
|
|
1650
|
+
toggleShowArguments() {
|
|
1651
|
+
this.showArguments.set(!this.showArguments());
|
|
1652
|
+
}
|
|
1284
1653
|
selectSnapLayout(layout) {
|
|
1285
1654
|
this.snapLayout.set(layout);
|
|
1286
1655
|
}
|
|
1287
1656
|
selectQueryListMode(mode) {
|
|
1288
1657
|
this.queryListMode.set(mode);
|
|
1289
1658
|
}
|
|
1290
|
-
selectClient(clientId) {
|
|
1291
|
-
this.selectedClientId.set(clientId);
|
|
1292
|
-
this.clearQueryHistory();
|
|
1293
|
-
}
|
|
1294
1659
|
selectQuery(query) {
|
|
1295
|
-
this.
|
|
1660
|
+
this.selectedQueryId.set(query._id);
|
|
1296
1661
|
}
|
|
1297
1662
|
clearQueryHistory() {
|
|
1298
1663
|
this.queryHistory.set([]);
|
|
1299
1664
|
}
|
|
1300
1665
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1301
|
-
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\">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 <button (click)=\"toggleOpen()\" class=\"et-query-devtools-close-btn\">Close Devtools</button>\n <button (click)=\"toggleTranslucent()\" class=\"et-query-devtools-translucent-btn\">Toggle Translucent</button>\n <button (click)=\"selectSnapLayout('full')\" class=\"et-query-devtools-snap-btn\">Snap full</button>\n <button (click)=\"selectSnapLayout('top')\" class=\"et-query-devtools-snap-btn\">Snap top</button>\n <button (click)=\"selectSnapLayout('bottom')\" class=\"et-query-devtools-snap-btn\">Snap bottom</button>\n <button (click)=\"selectSnapLayout('left')\" class=\"et-query-devtools-snap-btn\">Snap left</button>\n <button (click)=\"selectSnapLayout('right')\" class=\"et-query-devtools-snap-btn\">Snap right</button>\n\n <ng-container *ngIf=\"queryClientConfigs.length > 1\">\n <p>Client instance:</p>\n <ul>\n <li *ngFor=\"let clientConfig of queryClientConfigs; index as i; trackBy: trackByClient\">\n <button (click)=\"selectClient(i)\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </button>\n </li>\n </ul>\n </ng-container>\n\n <ng-container *ngIf=\"selectedClientConfig() as cfg\">\n <p>{{ cfg.displayName ?? cfg.client.config.baseRoute }}</p>\n\n <button (click)=\"cfg.client._store.refreshQueriesInUse()\">Force Refresh of in use queries</button> <br />\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true })\">HARD Force Refresh</button>\n <br />\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true, purgeUnused: true })\">\n PURGE & HARD Force Refresh\n </button>\n\n <br />\n <br />\n\n <button (click)=\"selectQueryListMode('live')\">Live</button>\n <button (click)=\"selectQueryListMode('history')\">History (last {{ queryHistory().length }} )</button>\n <button *ngIf=\"queryListMode() === 'history'\" (click)=\"clearQueryHistory()\">Clear</button>\n <ul *ngIf=\"queryListMode() === 'live'\">\n <li *ngFor=\"let query of queries(); trackBy: trackByQuery\">\n <button (click)=\"selectQuery(query)\">\n {{ query._routeWithParams }}\n </button>\n </li>\n </ul>\n\n <ul *ngIf=\"queryListMode() === 'history'\">\n <li *ngFor=\"let query of queryHistory(); trackBy: trackByQuery\">\n <button (click)=\"selectQuery(query)\">\n {{ query._routeWithParams }}\n </button>\n </li>\n </ul>\n </ng-container>\n\n <ng-container *ngIf=\"selectedQuery() as query\">\n <p>{{ query._routeWithParams }}</p>\n\n <button (click)=\"query.execute()\">Execute</button> <br />\n <button (click)=\"query.execute({ skipCache: true })\">FORCE Execute</button> <br />\n <button (click)=\"query.abort()\">Abort</button> <br />\n <button (click)=\"query.poll({ interval: 5000, takeUntil: _destroy$ })\">Poll</button> <br />\n <button (click)=\"query.stopPolling()\">Stop polling</button> <br />\n <button (click)=\"query.pausePolling()\">Pause polling</button> <br />\n <button (click)=\"query.resumePolling()\">Resume polling</button> <br />\n\n <div>\n <p>state type</p>\n <pre>{{ query.rawState.type }}</pre>\n </div>\n\n <div>\n <p>_enableSmartPolling:</p>\n <pre>{{ query._enableSmartPolling }}</pre>\n </div>\n\n <div>\n <p>isExpired:</p>\n <pre>{{ query.isExpired }}</pre>\n </div>\n\n <div>\n <p>isInUse:</p>\n <pre>{{ query.isInUse }}</pre>\n </div>\n\n <div>\n <p>_subscriberCount:</p>\n <pre>{{ query._subscriberCount }}</pre>\n </div>\n\n <div>\n <p>isPolling:</p>\n <pre>{{ query.isPolling }}</pre>\n </div>\n\n <div>\n <p>_arguments:</p>\n <pre>{{ query._arguments | json }}</pre>\n </div>\n\n <div>\n <p>state$:</p>\n <p><i> Warning, this will cause a subscription if shown </i></p>\n <button (click)=\"toggleShowResponse()\">Show/Hide</button>\n <pre *ngIf=\"showResponse()\">{{ query.state$ | async | json }}</pre>\n </div>\n\n <div>\n <p>rawState:</p>\n <button (click)=\"toggleShowRawResponse()\">Show/Hide</button>\n <pre *ngIf=\"showRawResponse()\">{{ query.rawState | json }}</pre>\n </div>\n </ng-container>\n</div>\n", styles: [".et-query-devtools-container{position:fixed;inset:0;background-color:#000;z-index:10000;overflow:auto}.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%}.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%}.et-query-devtools-container.et-query-devtools-container--snap-top{inset-inline-start:0;inset-block-start:0;inset-inline-end:0;height:50%}.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%}.et-query-devtools-open-btn{position:fixed;inset-inline-start:0;inset-block-start:0;z-index:9999}\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" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom }); }
|
|
1666
|
+
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 }); }
|
|
1302
1667
|
}
|
|
1303
1668
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
|
|
1304
1669
|
type: Component,
|
|
1305
1670
|
args: [{ selector: 'et-query-devtools', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, host: {
|
|
1306
1671
|
class: 'et-query-devtools',
|
|
1307
|
-
}, imports: [NgIf, NgFor, AsyncPipe, JsonPipe], hostDirectives: [], template: "<button *ngIf=\"!isOpen()\" (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn\">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 <button (click)=\"toggleOpen()\" class=\"et-query-devtools-close-btn\">Close Devtools</button>\n <button (click)=\"toggleTranslucent()\" class=\"et-query-devtools-translucent-btn\">Toggle Translucent</button>\n <button (click)=\"selectSnapLayout('full')\" class=\"et-query-devtools-snap-btn\">Snap full</button>\n <button (click)=\"selectSnapLayout('top')\" class=\"et-query-devtools-snap-btn\">Snap top</button>\n <button (click)=\"selectSnapLayout('bottom')\" class=\"et-query-devtools-snap-btn\">Snap bottom</button>\n <button (click)=\"selectSnapLayout('left')\" class=\"et-query-devtools-snap-btn\">Snap left</button>\n <button (click)=\"selectSnapLayout('right')\" class=\"et-query-devtools-snap-btn\">Snap right</button>\n\n <ng-container *ngIf=\"queryClientConfigs.length > 1\">\n <p>Client instance:</p>\n <ul>\n <li *ngFor=\"let clientConfig of queryClientConfigs; index as i; trackBy: trackByClient\">\n <button (click)=\"selectClient(i)\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </button>\n </li>\n </ul>\n </ng-container>\n\n <ng-container *ngIf=\"selectedClientConfig() as cfg\">\n <p>{{ cfg.displayName ?? cfg.client.config.baseRoute }}</p>\n\n <button (click)=\"cfg.client._store.refreshQueriesInUse()\">Force Refresh of in use queries</button> <br />\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true })\">HARD Force Refresh</button>\n <br />\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true, purgeUnused: true })\">\n PURGE & HARD Force Refresh\n </button>\n\n <br />\n <br />\n\n <button (click)=\"selectQueryListMode('live')\">Live</button>\n <button (click)=\"selectQueryListMode('history')\">History (last {{ queryHistory().length }} )</button>\n <button *ngIf=\"queryListMode() === 'history'\" (click)=\"clearQueryHistory()\">Clear</button>\n <ul *ngIf=\"queryListMode() === 'live'\">\n <li *ngFor=\"let query of queries(); trackBy: trackByQuery\">\n <button (click)=\"selectQuery(query)\">\n {{ query._routeWithParams }}\n </button>\n </li>\n </ul>\n\n <ul *ngIf=\"queryListMode() === 'history'\">\n <li *ngFor=\"let query of queryHistory(); trackBy: trackByQuery\">\n <button (click)=\"selectQuery(query)\">\n {{ query._routeWithParams }}\n </button>\n </li>\n </ul>\n </ng-container>\n\n <ng-container *ngIf=\"selectedQuery() as query\">\n <p>{{ query._routeWithParams }}</p>\n\n <button (click)=\"query.execute()\">Execute</button> <br />\n <button (click)=\"query.execute({ skipCache: true })\">FORCE Execute</button> <br />\n <button (click)=\"query.abort()\">Abort</button> <br />\n <button (click)=\"query.poll({ interval: 5000, takeUntil: _destroy$ })\">Poll</button> <br />\n <button (click)=\"query.stopPolling()\">Stop polling</button> <br />\n <button (click)=\"query.pausePolling()\">Pause polling</button> <br />\n <button (click)=\"query.resumePolling()\">Resume polling</button> <br />\n\n <div>\n <p>state type</p>\n <pre>{{ query.rawState.type }}</pre>\n </div>\n\n <div>\n <p>_enableSmartPolling:</p>\n <pre>{{ query._enableSmartPolling }}</pre>\n </div>\n\n <div>\n <p>isExpired:</p>\n <pre>{{ query.isExpired }}</pre>\n </div>\n\n <div>\n <p>isInUse:</p>\n <pre>{{ query.isInUse }}</pre>\n </div>\n\n <div>\n <p>_subscriberCount:</p>\n <pre>{{ query._subscriberCount }}</pre>\n </div>\n\n <div>\n <p>isPolling:</p>\n <pre>{{ query.isPolling }}</pre>\n </div>\n\n <div>\n <p>_arguments:</p>\n <pre>{{ query._arguments | json }}</pre>\n </div>\n\n <div>\n <p>state$:</p>\n <p><i> Warning, this will cause a subscription if shown </i></p>\n <button (click)=\"toggleShowResponse()\">Show/Hide</button>\n <pre *ngIf=\"showResponse()\">{{ query.state$ | async | json }}</pre>\n </div>\n\n <div>\n <p>rawState:</p>\n <button (click)=\"toggleShowRawResponse()\">Show/Hide</button>\n <pre *ngIf=\"showRawResponse()\">{{ query.rawState | json }}</pre>\n </div>\n </ng-container>\n</div>\n", styles: [".et-query-devtools-container{position:fixed;inset:0;background-color:#000;z-index:10000;overflow:auto}.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%}.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%}.et-query-devtools-container.et-query-devtools-container--snap-top{inset-inline-start:0;inset-block-start:0;inset-inline-end:0;height:50%}.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%}.et-query-devtools-open-btn{position:fixed;inset-inline-start:0;inset-block-start:0;z-index:9999}\n"] }]
|
|
1672
|
+
}, 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"] }]
|
|
1308
1673
|
}], ctorParameters: function () { return []; } });
|
|
1309
1674
|
|
|
1310
1675
|
class QueryDirective {
|
|
@@ -1734,7 +2099,7 @@ class InfinityQueryDirective {
|
|
|
1734
2099
|
this._data$.next([]);
|
|
1735
2100
|
}
|
|
1736
2101
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1737
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.6", type: InfinityQueryDirective, isStandalone: true, selector: "[etInfinityQuery]", inputs: { infinityQuery: ["etInfinityQuery", "infinityQuery"] }, providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }], exportAs: ["etInfinityQuery"], hostDirectives: [{ directive: i1.DelayableDirective }], ngImport: i0 }); }
|
|
2102
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.6", type: InfinityQueryDirective, isStandalone: true, selector: "[etInfinityQuery]", inputs: { infinityQuery: ["etInfinityQuery", "infinityQuery"] }, providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }], exportAs: ["etInfinityQuery"], hostDirectives: [{ directive: i1$1.DelayableDirective }], ngImport: i0 }); }
|
|
1738
2103
|
}
|
|
1739
2104
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: InfinityQueryDirective, decorators: [{
|
|
1740
2105
|
type: Directive,
|
|
@@ -1814,7 +2179,13 @@ function flatten(arr) {
|
|
|
1814
2179
|
class EntityStore {
|
|
1815
2180
|
constructor(_config) {
|
|
1816
2181
|
this._config = _config;
|
|
2182
|
+
/**
|
|
2183
|
+
* @internal
|
|
2184
|
+
*/
|
|
1817
2185
|
this._dictionary = new Map();
|
|
2186
|
+
/**
|
|
2187
|
+
* @internal
|
|
2188
|
+
*/
|
|
1818
2189
|
this._change$ = new Subject();
|
|
1819
2190
|
}
|
|
1820
2191
|
select(keyOrKeys) {
|
|
@@ -1945,261 +2316,6 @@ const removeFrom = (store, { where, id }) => {
|
|
|
1945
2316
|
.subscribe();
|
|
1946
2317
|
};
|
|
1947
2318
|
|
|
1948
|
-
class QueryCreator {
|
|
1949
|
-
constructor(_queryConfig, _client, _store) {
|
|
1950
|
-
this._queryConfig = _queryConfig;
|
|
1951
|
-
this._client = _client;
|
|
1952
|
-
this._store = _store;
|
|
1953
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1954
|
-
// @ts-ignore
|
|
1955
|
-
this.prepare = (args) => {
|
|
1956
|
-
const route = buildRoute({
|
|
1957
|
-
base: this._client.config.baseRoute,
|
|
1958
|
-
route: this._queryConfig.route,
|
|
1959
|
-
pathParams: args?.pathParams,
|
|
1960
|
-
queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
|
|
1961
|
-
queryParamConfig: this._client.config.request?.queryParams,
|
|
1962
|
-
});
|
|
1963
|
-
const cacheKey = isGqlQueryConfig(this._queryConfig) ? buildGqlCacheKey(this._queryConfig, args) : route;
|
|
1964
|
-
if (shouldCacheQuery(this._queryConfig.method)) {
|
|
1965
|
-
const existingQuery = this._store.get(cacheKey);
|
|
1966
|
-
if (existingQuery) {
|
|
1967
|
-
return existingQuery;
|
|
1968
|
-
}
|
|
1969
|
-
}
|
|
1970
|
-
const query = new Query(this._client, this._queryConfig, route, args ?? {});
|
|
1971
|
-
if (shouldCacheQuery(this._queryConfig.method)) {
|
|
1972
|
-
this._store.add(cacheKey, query);
|
|
1973
|
-
}
|
|
1974
|
-
return query;
|
|
1975
|
-
};
|
|
1976
|
-
this.behaviorSubject = (initialValue) => new BehaviorSubject(initialValue ?? null);
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
|
-
|
|
1980
|
-
class QueryStore {
|
|
1981
|
-
constructor(_config) {
|
|
1982
|
-
this._config = _config;
|
|
1983
|
-
/**
|
|
1984
|
-
* @internal
|
|
1985
|
-
*/
|
|
1986
|
-
this._store = new Map();
|
|
1987
|
-
this._garbageCollector = null;
|
|
1988
|
-
this._isInLowResourceMode = false;
|
|
1989
|
-
this._lastBlurTimestamp = Date.now();
|
|
1990
|
-
this._storeChange$ = new Subject();
|
|
1991
|
-
this.storeChange$ = this._storeChange$.asObservable();
|
|
1992
|
-
this._initSmartQueryHandling();
|
|
1993
|
-
}
|
|
1994
|
-
add(id, query) {
|
|
1995
|
-
this._store.set(id, query);
|
|
1996
|
-
this._initGarbageCollector();
|
|
1997
|
-
this._logState(id, query, 'SET');
|
|
1998
|
-
this._storeChange$.next(id);
|
|
1999
|
-
}
|
|
2000
|
-
get(id) {
|
|
2001
|
-
return this._store.get(id) ?? null;
|
|
2002
|
-
}
|
|
2003
|
-
remove(id) {
|
|
2004
|
-
this._store.delete(id);
|
|
2005
|
-
this._logState(id, null, 'REMOVE');
|
|
2006
|
-
this._storeChange$.next(id);
|
|
2007
|
-
}
|
|
2008
|
-
forEach(callback) {
|
|
2009
|
-
for (const [key, query] of this._store) {
|
|
2010
|
-
callback(query, key);
|
|
2011
|
-
}
|
|
2012
|
-
}
|
|
2013
|
-
refreshQueriesInUse(config) {
|
|
2014
|
-
const { ignoreCacheValidity, purgeUnused } = config ?? {};
|
|
2015
|
-
for (const [key, query] of this._store) {
|
|
2016
|
-
if (query.isInUse &&
|
|
2017
|
-
(query.isExpired || ignoreCacheValidity) &&
|
|
2018
|
-
query.autoRefreshOnConfig.queryClientDefaultHeadersChange) {
|
|
2019
|
-
query.execute({ skipCache: true, _triggeredVia: 'auto' });
|
|
2020
|
-
}
|
|
2021
|
-
else if (purgeUnused && !query.isInUse) {
|
|
2022
|
-
this.remove(key);
|
|
2023
|
-
}
|
|
2024
|
-
}
|
|
2025
|
-
}
|
|
2026
|
-
_initSmartQueryHandling() {
|
|
2027
|
-
const windowBlur$ = fromEvent(window, 'blur');
|
|
2028
|
-
const windowFocus$ = fromEvent(window, 'focus');
|
|
2029
|
-
windowBlur$.subscribe(() => {
|
|
2030
|
-
timer(5000)
|
|
2031
|
-
.pipe(takeUntil(windowFocus$), take(1))
|
|
2032
|
-
.subscribe(() => {
|
|
2033
|
-
this._lastBlurTimestamp = Date.now();
|
|
2034
|
-
this._isInLowResourceMode = true;
|
|
2035
|
-
this._stopGarbageCollector();
|
|
2036
|
-
if (this._config?.enableSmartPolling) {
|
|
2037
|
-
this.forEach((query) => {
|
|
2038
|
-
if (!query.isPolling || !query._enableSmartPolling) {
|
|
2039
|
-
return;
|
|
2040
|
-
}
|
|
2041
|
-
query.pausePolling();
|
|
2042
|
-
});
|
|
2043
|
-
}
|
|
2044
|
-
});
|
|
2045
|
-
});
|
|
2046
|
-
windowFocus$.subscribe(() => {
|
|
2047
|
-
if (!this._isInLowResourceMode) {
|
|
2048
|
-
return;
|
|
2049
|
-
}
|
|
2050
|
-
this._isInLowResourceMode = false;
|
|
2051
|
-
if (this._config?.enableSmartPolling || this._config?.autoRefreshQueriesOnWindowFocus) {
|
|
2052
|
-
this.forEach((query) => {
|
|
2053
|
-
if (this._config?.enableSmartPolling && query._isPollingPaused) {
|
|
2054
|
-
query.resumePolling();
|
|
2055
|
-
}
|
|
2056
|
-
if (Date.now() - this._lastBlurTimestamp > 15000) {
|
|
2057
|
-
if (this._config?.autoRefreshQueriesOnWindowFocus &&
|
|
2058
|
-
query.isExpired &&
|
|
2059
|
-
query.isInUse &&
|
|
2060
|
-
query.autoRefreshOnConfig.windowFocus) {
|
|
2061
|
-
query.execute({ skipCache: true, _triggeredVia: 'auto' });
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
});
|
|
2065
|
-
}
|
|
2066
|
-
this._initGarbageCollector();
|
|
2067
|
-
});
|
|
2068
|
-
}
|
|
2069
|
-
_logState(key, item, operation) {
|
|
2070
|
-
if (!this._config?.enableChangeLogging)
|
|
2071
|
-
return;
|
|
2072
|
-
const stateAsJson = {};
|
|
2073
|
-
this._store.forEach((value, key) => {
|
|
2074
|
-
stateAsJson[key] = value;
|
|
2075
|
-
});
|
|
2076
|
-
console.log(`%c[${operation}] ${key}`, 'font-weight: bold');
|
|
2077
|
-
console.log({ operation, key, item });
|
|
2078
|
-
console.log(stateAsJson);
|
|
2079
|
-
}
|
|
2080
|
-
_initGarbageCollector() {
|
|
2081
|
-
if (this._garbageCollector !== null) {
|
|
2082
|
-
return;
|
|
2083
|
-
}
|
|
2084
|
-
this._logGarbageCollector('Start');
|
|
2085
|
-
this._garbageCollector = window.setInterval(() => {
|
|
2086
|
-
this._runGarbageCollector();
|
|
2087
|
-
}, 15000);
|
|
2088
|
-
}
|
|
2089
|
-
_stopGarbageCollector() {
|
|
2090
|
-
if (this._garbageCollector !== null) {
|
|
2091
|
-
window.clearInterval(this._garbageCollector);
|
|
2092
|
-
this._garbageCollector = null;
|
|
2093
|
-
this._logGarbageCollector('Stop');
|
|
2094
|
-
}
|
|
2095
|
-
}
|
|
2096
|
-
_runGarbageCollector() {
|
|
2097
|
-
this._logGarbageCollector('Collecting...');
|
|
2098
|
-
this._store.forEach((item, key) => {
|
|
2099
|
-
if (item.isExpired && !item.isInUse) {
|
|
2100
|
-
this.remove(key);
|
|
2101
|
-
}
|
|
2102
|
-
});
|
|
2103
|
-
this._logGarbageCollector('Collection done');
|
|
2104
|
-
if (!this._store.size) {
|
|
2105
|
-
this._stopGarbageCollector();
|
|
2106
|
-
}
|
|
2107
|
-
}
|
|
2108
|
-
_logGarbageCollector(action) {
|
|
2109
|
-
if (!this._config?.enableGarbageCollectorLogging)
|
|
2110
|
-
return;
|
|
2111
|
-
console.log(`%cGC: ${action}`, 'color: yellow; font-weight: bold');
|
|
2112
|
-
}
|
|
2113
|
-
}
|
|
2114
|
-
|
|
2115
|
-
class QueryClient {
|
|
2116
|
-
get config() {
|
|
2117
|
-
return this._clientConfig;
|
|
2118
|
-
}
|
|
2119
|
-
get authProvider() {
|
|
2120
|
-
return this._authProvider$.getValue() ?? this._clientConfig.parent?._authProvider$.getValue() ?? null;
|
|
2121
|
-
}
|
|
2122
|
-
get authProvider$() {
|
|
2123
|
-
return this._authProvider$.asObservable() ?? this._clientConfig.parent?._authProvider$.asObservable() ?? null;
|
|
2124
|
-
}
|
|
2125
|
-
constructor(_clientConfig) {
|
|
2126
|
-
this._clientConfig = _clientConfig;
|
|
2127
|
-
this._authProvider$ = new BehaviorSubject(null);
|
|
2128
|
-
this.get = (queryConfig) => this.fetch({
|
|
2129
|
-
...queryConfig,
|
|
2130
|
-
method: 'GET',
|
|
2131
|
-
});
|
|
2132
|
-
this.post = (queryConfig) => this.fetch({
|
|
2133
|
-
...queryConfig,
|
|
2134
|
-
method: 'POST',
|
|
2135
|
-
});
|
|
2136
|
-
this.put = (queryConfig) => this.fetch({
|
|
2137
|
-
...queryConfig,
|
|
2138
|
-
method: 'PUT',
|
|
2139
|
-
});
|
|
2140
|
-
this.patch = (queryConfig) => this.fetch({
|
|
2141
|
-
...queryConfig,
|
|
2142
|
-
method: 'PATCH',
|
|
2143
|
-
});
|
|
2144
|
-
this.delete = (queryConfig) => this.fetch({
|
|
2145
|
-
...queryConfig,
|
|
2146
|
-
method: 'DELETE',
|
|
2147
|
-
});
|
|
2148
|
-
this.gqlQuery = (queryConfig) => this.fetch({
|
|
2149
|
-
...queryConfig,
|
|
2150
|
-
method: 'GQL_QUERY',
|
|
2151
|
-
});
|
|
2152
|
-
this.gqlMutate = (queryConfig) => this.fetch({
|
|
2153
|
-
...queryConfig,
|
|
2154
|
-
method: 'GQL_MUTATE',
|
|
2155
|
-
});
|
|
2156
|
-
this.fetch = (queryConfig) => new QueryCreator(queryConfig, this, this._store);
|
|
2157
|
-
this.setAuthProvider = (authProvider) => {
|
|
2158
|
-
if (this.authProvider) {
|
|
2159
|
-
throw new Error('The auth provider is already set. Please call clearAuthProvider() first.');
|
|
2160
|
-
}
|
|
2161
|
-
this._authProvider$.next(authProvider);
|
|
2162
|
-
};
|
|
2163
|
-
this.setDefaultHeaders = (config) => {
|
|
2164
|
-
if (!this._clientConfig.request) {
|
|
2165
|
-
this._clientConfig.request = {
|
|
2166
|
-
headers: config.headers ?? undefined,
|
|
2167
|
-
};
|
|
2168
|
-
}
|
|
2169
|
-
else {
|
|
2170
|
-
this._clientConfig.request.headers = config.headers ?? undefined;
|
|
2171
|
-
}
|
|
2172
|
-
if (config.refreshQueriesInUse) {
|
|
2173
|
-
this._store.refreshQueriesInUse({ purgeUnused: true, ignoreCacheValidity: true });
|
|
2174
|
-
}
|
|
2175
|
-
};
|
|
2176
|
-
this.clearAuthProvider = () => {
|
|
2177
|
-
this.authProvider?.cleanUp();
|
|
2178
|
-
this._authProvider$.next(null);
|
|
2179
|
-
};
|
|
2180
|
-
this._store = new QueryStore({
|
|
2181
|
-
enableChangeLogging: _clientConfig.logging?.queryStateChanges,
|
|
2182
|
-
enableGarbageCollectorLogging: _clientConfig.logging?.queryStateGarbageCollector,
|
|
2183
|
-
autoRefreshQueriesOnWindowFocus: _clientConfig.request?.autoRefreshQueriesOnWindowFocus ?? true,
|
|
2184
|
-
enableSmartPolling: _clientConfig.request?.enableSmartPolling ?? true,
|
|
2185
|
-
});
|
|
2186
|
-
}
|
|
2187
|
-
}
|
|
2188
|
-
|
|
2189
|
-
const shouldCacheQuery = (method) => {
|
|
2190
|
-
return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
|
|
2191
|
-
};
|
|
2192
|
-
const buildGqlCacheKey = (config, args) => {
|
|
2193
|
-
const { query } = config;
|
|
2194
|
-
const variables = args?.variables || {};
|
|
2195
|
-
const queryWithoutNewLinesAndWhitespace = query.replace(/\s/g, '');
|
|
2196
|
-
const queryFirst50Chars = queryWithoutNewLinesAndWhitespace.slice(0, 50);
|
|
2197
|
-
const queryMiddle25Chars = queryWithoutNewLinesAndWhitespace.slice(queryWithoutNewLinesAndWhitespace.length / 2 - 25, queryWithoutNewLinesAndWhitespace.length / 2 + 25);
|
|
2198
|
-
const queryLast50Chars = queryWithoutNewLinesAndWhitespace.slice(-50);
|
|
2199
|
-
const vars = JSON.stringify(variables);
|
|
2200
|
-
return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
|
|
2201
|
-
};
|
|
2202
|
-
|
|
2203
2319
|
const ET_ARR_PREFIX = 'ET_ARR__';
|
|
2204
2320
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2205
2321
|
class QueryFormGroup extends FormGroup {
|
|
@@ -2560,5 +2676,5 @@ const def = () => null;
|
|
|
2560
2676
|
* Generated bundle index. Do not edit.
|
|
2561
2677
|
*/
|
|
2562
2678
|
|
|
2563
|
-
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 };
|
|
2679
|
+
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 };
|
|
2564
2680
|
//# sourceMappingURL=ethlete-query.mjs.map
|