@ethlete/query 6.0.0-next.1 → 6.0.0-next.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +94 -0
- package/fesm2022/ethlete-query.mjs +372 -236
- package/fesm2022/ethlete-query.mjs.map +1 -1
- package/generators/migrate-to-query-v3/cleanup-migration.js +242 -0
- package/generators/migrate-to-query-v3/legacy-prepare-migration.js +773 -0
- package/generators/migrate-to-query-v3/legacy-query-creator-migration.js +589 -0
- package/generators/migrate-to-query-v3/migration.js +16 -2928
- package/generators/migrate-to-query-v3/query-client-migration.js +477 -0
- package/generators/migrate-to-query-v3/report.js +136 -0
- package/generators/migrate-to-query-v3/shared.js +97 -0
- package/package.json +12 -11
- package/types/ethlete-query.d.ts +70 -11
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { isDevMode, DestroyRef, InjectionToken, inject, Injector, EnvironmentInjector, ErrorHandler,
|
|
2
|
+
import { isDevMode, DestroyRef, InjectionToken, inject, Injector, EnvironmentInjector, ErrorHandler, createEnvironmentInjector, effect, untracked, signal, linkedSignal, computed, runInInjectionContext, assertInInjectionContext, ChangeDetectorRef, ViewContainerRef, TemplateRef, Input, Directive, ElementRef, input, Pipe, ViewEncapsulation, ChangeDetectionStrategy, Component, DOCUMENT, NgZone } from '@angular/core';
|
|
3
3
|
import { createStaticProvider, RuntimeError, clamp, createDestroy, computedTillTruthy, getCookie, setCookie, deleteCookie, createProvider, nextFrame, createRootProvider, isObject, injectRoute, getDomain, injectQueryParamChanges, injectQueryParams, clone, equal, ET_PROPERTY_REMOVED, previousSignalValue } from '@ethlete/core';
|
|
4
|
-
import {
|
|
4
|
+
import { filter, Subject, Subscription, Observable, tap, retry, throwError, timer, catchError, takeUntil, startWith, pairwise, switchMap, of, BehaviorSubject, fromEvent, take, ReplaySubject, map, shareReplay, interval, skip, takeWhile, combineLatest, EMPTY, withLatestFrom, debounceTime, merge, throttleTime } from 'rxjs';
|
|
5
5
|
import { toObservable, takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
6
|
-
import { HttpClient,
|
|
6
|
+
import { HttpClient, HttpEventType, HttpErrorResponse, HttpHeaders, HttpStatusCode } from '@angular/common/http';
|
|
7
7
|
import { getActiveConsumer, setActiveConsumer } from '@angular/core/primitives/signals';
|
|
8
8
|
import { NgClass, AsyncPipe, JsonPipe } from '@angular/common';
|
|
9
9
|
import * as i1 from '@angular/forms';
|
|
@@ -46,9 +46,6 @@ const createGqlExecuteFn = (executeOptions) => {
|
|
|
46
46
|
const reset = () => resetExecuteState({ executeState, executeOptions });
|
|
47
47
|
const exec = (executeArgs) => {
|
|
48
48
|
circularChecker.check();
|
|
49
|
-
// Make sure all effects are flushed before reading the args.
|
|
50
|
-
// A withArgs feature effect might still be pending otherwise resulting in the wrong args being read.
|
|
51
|
-
executeOptions.deps.effectScheduler.flush();
|
|
52
49
|
const { args = executeOptions.state.args(), options } = executeArgs ?? {};
|
|
53
50
|
const query = transformGql(executeOptions.creatorInternals.query);
|
|
54
51
|
let gqlParams = query(args?.variables);
|
|
@@ -133,7 +130,6 @@ const setupQueryDependencies = (options) => {
|
|
|
133
130
|
scopeDestroyRef: hostInjector.get(DestroyRef),
|
|
134
131
|
client: hostInjector.get(clientToken),
|
|
135
132
|
injector: undefined, // Will be set after injector creation
|
|
136
|
-
effectScheduler: hostInjector.get(_EffectScheduler),
|
|
137
133
|
ngErrorHandler: hostInjector.get(ErrorHandler),
|
|
138
134
|
httpClient: hostInjector.get(HttpClient),
|
|
139
135
|
};
|
|
@@ -307,17 +303,27 @@ const withArgs = (args) => {
|
|
|
307
303
|
return createQueryFeature({
|
|
308
304
|
type: QueryFeatureType.WITH_ARGS,
|
|
309
305
|
fn: (context) => {
|
|
310
|
-
|
|
306
|
+
// `state.args` is reactively backed by this source, so every reader (exec, polling,
|
|
307
|
+
// auto-refresh) always sees the latest value with no pending-effect window. Sentinels are
|
|
308
|
+
// resolved here: CLEAR -> null, `null` ("don't change") -> keep the previous value.
|
|
309
|
+
let previous = null;
|
|
310
|
+
context.state.subtle.setArgsSource(() => {
|
|
311
|
+
const value = args();
|
|
312
|
+
if (value === CLEAR_QUERY_ARGS) {
|
|
313
|
+
previous = null;
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
if (value === null)
|
|
317
|
+
return previous;
|
|
318
|
+
previous = value;
|
|
319
|
+
return value;
|
|
320
|
+
});
|
|
321
|
+
// Trigger (auto-)execution whenever the resolved args change.
|
|
311
322
|
nestedEffect(() => {
|
|
312
|
-
const currArgsNow =
|
|
323
|
+
const currArgsNow = context.state.args();
|
|
313
324
|
if (currArgsNow === null)
|
|
314
325
|
return;
|
|
315
326
|
untracked(() => {
|
|
316
|
-
if (currArgsNow === CLEAR_QUERY_ARGS) {
|
|
317
|
-
context.state.args.set(null);
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
context.state.args.set(currArgsNow);
|
|
321
327
|
if (context.flags.shouldAutoExecute)
|
|
322
328
|
context.execute({ args: currArgsNow });
|
|
323
329
|
});
|
|
@@ -366,14 +372,9 @@ const withLogging = (options) => {
|
|
|
366
372
|
return createQueryFeature({
|
|
367
373
|
type: QueryFeatureType.WITH_LOGGING,
|
|
368
374
|
fn: (context) => {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
return;
|
|
373
|
-
untracked(() => {
|
|
374
|
-
options.logFn(event);
|
|
375
|
-
});
|
|
376
|
-
}, { injector: context.deps.injector });
|
|
375
|
+
context.state.events$.pipe(takeUntilDestroyed(context.deps.destroyRef)).subscribe((event) => {
|
|
376
|
+
options.logFn(event);
|
|
377
|
+
});
|
|
377
378
|
},
|
|
378
379
|
});
|
|
379
380
|
};
|
|
@@ -382,14 +383,11 @@ const withErrorHandling = (options) => {
|
|
|
382
383
|
return createQueryFeature({
|
|
383
384
|
type: QueryFeatureType.WITH_ERROR_HANDLING,
|
|
384
385
|
fn: (context) => {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
options.handler(error);
|
|
391
|
-
});
|
|
392
|
-
}, { injector: context.deps.injector });
|
|
386
|
+
context.state.events$
|
|
387
|
+
.pipe(filter((event) => event.type === 'error'), takeUntilDestroyed(context.deps.destroyRef))
|
|
388
|
+
.subscribe((event) => {
|
|
389
|
+
options.handler(event.error);
|
|
390
|
+
});
|
|
393
391
|
},
|
|
394
392
|
});
|
|
395
393
|
};
|
|
@@ -398,14 +396,11 @@ const withSuccessHandling = (options) => {
|
|
|
398
396
|
return createQueryFeature({
|
|
399
397
|
type: QueryFeatureType.WITH_SUCCESS_HANDLING,
|
|
400
398
|
fn: (context) => {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
options.handler(response);
|
|
407
|
-
});
|
|
408
|
-
}, { injector: context.deps.injector });
|
|
399
|
+
context.state.events$
|
|
400
|
+
.pipe(filter((event) => event.type === HttpEventType.Response), takeUntilDestroyed(context.deps.destroyRef))
|
|
401
|
+
.subscribe(() => {
|
|
402
|
+
options.handler(context.state.response());
|
|
403
|
+
});
|
|
409
404
|
},
|
|
410
405
|
});
|
|
411
406
|
};
|
|
@@ -458,20 +453,32 @@ const withResponseUpdate = (options) => {
|
|
|
458
453
|
};
|
|
459
454
|
|
|
460
455
|
const setupQueryState = (options) => {
|
|
461
|
-
const request = signal(null, ...(ngDevMode ? [{ debugName: "request" }] : []));
|
|
462
|
-
const rawResponse = linkedSignal(() => request()?.response() ?? null, ...(ngDevMode ? [{ debugName: "rawResponse" }] : []));
|
|
456
|
+
const request = signal(null, ...(ngDevMode ? [{ debugName: "request" }] : /* istanbul ignore next */ []));
|
|
457
|
+
const rawResponse = linkedSignal(() => request()?.response() ?? null, ...(ngDevMode ? [{ debugName: "rawResponse" }] : /* istanbul ignore next */ []));
|
|
463
458
|
const response = computed(() => {
|
|
464
459
|
const raw = rawResponse();
|
|
465
460
|
if (raw === null)
|
|
466
461
|
return null;
|
|
467
462
|
return options.transformResponse ? options.transformResponse(raw) : raw;
|
|
468
|
-
}, ...(ngDevMode ? [{ debugName: "response" }] : []));
|
|
469
|
-
const loading = linkedSignal(() => request()?.loading() ?? null, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
470
|
-
const error = linkedSignal(() => request()?.error() ?? null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
471
|
-
const latestHttpEvent = linkedSignal(() => request()?.currentEvent() ?? null, ...(ngDevMode ? [{ debugName: "latestHttpEvent" }] : []));
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
463
|
+
}, ...(ngDevMode ? [{ debugName: "response" }] : /* istanbul ignore next */ []));
|
|
464
|
+
const loading = linkedSignal(() => request()?.loading() ?? null, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
465
|
+
const error = linkedSignal(() => request()?.error() ?? null, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
466
|
+
const latestHttpEvent = linkedSignal(() => request()?.currentEvent() ?? null, ...(ngDevMode ? [{ debugName: "latestHttpEvent" }] : /* istanbul ignore next */ []));
|
|
467
|
+
// `args` is reactively sourced: reads always reflect the latest value from the installed source
|
|
468
|
+
// (e.g. the `withArgs` feature), so there is no stale window between a source change and an
|
|
469
|
+
// effect writing it. It stays writable (reset / auth-error clear it via `.set(null)`); a manual
|
|
470
|
+
// set is overridden again the next time the source's dependencies change.
|
|
471
|
+
const argsSource = signal(() => null, ...(ngDevMode ? [{ debugName: "argsSource" }] : /* istanbul ignore next */ []));
|
|
472
|
+
const args = linkedSignal(() => argsSource()(), ...(ngDevMode ? [{ debugName: "args" }] : /* istanbul ignore next */ []));
|
|
473
|
+
const setArgsSource = (source) => argsSource.set(source);
|
|
474
|
+
const lastTimeExecutedAt = signal(null, ...(ngDevMode ? [{ debugName: "lastTimeExecutedAt" }] : /* istanbul ignore next */ []));
|
|
475
|
+
const lastTriggeredBy = signal(null, ...(ngDevMode ? [{ debugName: "lastTriggeredBy" }] : /* istanbul ignore next */ []));
|
|
476
|
+
const requestEvents$ = new Subject();
|
|
477
|
+
let requestEventsSubscription = Subscription.EMPTY;
|
|
478
|
+
const bindRequestEvents = (request) => {
|
|
479
|
+
requestEventsSubscription.unsubscribe();
|
|
480
|
+
requestEventsSubscription = request.events$.subscribe((event) => requestEvents$.next(event));
|
|
481
|
+
};
|
|
475
482
|
const executionState = computed(() => {
|
|
476
483
|
const currentResponse = response();
|
|
477
484
|
const currentError = error();
|
|
@@ -506,7 +513,7 @@ const setupQueryState = (options) => {
|
|
|
506
513
|
else {
|
|
507
514
|
return null;
|
|
508
515
|
}
|
|
509
|
-
}, ...(ngDevMode ? [{ debugName: "executionState" }] : []));
|
|
516
|
+
}, ...(ngDevMode ? [{ debugName: "executionState" }] : /* istanbul ignore next */ []));
|
|
510
517
|
const state = {
|
|
511
518
|
rawResponse,
|
|
512
519
|
response,
|
|
@@ -517,9 +524,12 @@ const setupQueryState = (options) => {
|
|
|
517
524
|
lastTimeExecutedAt,
|
|
518
525
|
lastTriggeredBy,
|
|
519
526
|
executionState,
|
|
527
|
+
events$: requestEvents$.asObservable(),
|
|
520
528
|
subtle: {
|
|
521
529
|
request,
|
|
522
530
|
rawResponse,
|
|
531
|
+
bindRequestEvents,
|
|
532
|
+
setArgsSource,
|
|
523
533
|
},
|
|
524
534
|
};
|
|
525
535
|
return state;
|
|
@@ -530,7 +540,7 @@ const createQuerySnapshotFn = (options) => {
|
|
|
530
540
|
const context = injectQueryContext();
|
|
531
541
|
const snapshotFn = () => {
|
|
532
542
|
const snapshotState = setupQueryState({});
|
|
533
|
-
const isAlive = signal(true, ...(ngDevMode ? [{ debugName: "isAlive" }] : []));
|
|
543
|
+
const isAlive = signal(true, ...(ngDevMode ? [{ debugName: "isAlive" }] : /* istanbul ignore next */ []));
|
|
534
544
|
const killEffectRef = effect(() => {
|
|
535
545
|
const currentLoading = state.loading();
|
|
536
546
|
const currentError = state.error();
|
|
@@ -549,13 +559,14 @@ const createQuerySnapshotFn = (options) => {
|
|
|
549
559
|
snapshotState.rawResponse.set(currentResponse);
|
|
550
560
|
if (currentLoading)
|
|
551
561
|
return;
|
|
552
|
-
|
|
562
|
+
const hasCompletedResponse = currentLatestHttpEvent?.type === HttpEventType.Response;
|
|
563
|
+
if (!hasCompletedResponse && !currentError)
|
|
553
564
|
return;
|
|
554
565
|
// kill the effect once loading is done and we either have a response or an error
|
|
555
566
|
killEffectRef.destroy();
|
|
556
567
|
isAlive.set(false);
|
|
557
568
|
});
|
|
558
|
-
}, { ...(ngDevMode ? { debugName: "killEffectRef" } : {}), injector: context.deps.injector });
|
|
569
|
+
}, { ...(ngDevMode ? { debugName: "killEffectRef" } : /* istanbul ignore next */ {}), injector: context.deps.injector });
|
|
559
570
|
const snapshot = {
|
|
560
571
|
args: wrapAsObservableSignal(snapshotState.args.asReadonly(), context.deps.injector),
|
|
561
572
|
response: wrapAsObservableSignal(snapshotState.response, context.deps.injector),
|
|
@@ -745,6 +756,7 @@ const queryExecute = (options) => {
|
|
|
745
756
|
state.lastTimeExecutedAt.set(Date.now());
|
|
746
757
|
state.lastTriggeredBy.set(runQueryOptions?.triggeredBy ?? null);
|
|
747
758
|
state.subtle.request.set(request);
|
|
759
|
+
state.subtle.bindRequestEvents(request);
|
|
748
760
|
};
|
|
749
761
|
const circularQueryDependencyChecker = () => {
|
|
750
762
|
let lastTriggerTs = 0;
|
|
@@ -778,9 +790,6 @@ const createExecuteFn = (executeOptions) => {
|
|
|
778
790
|
const reset = () => resetExecuteState({ executeState, executeOptions });
|
|
779
791
|
const exec = (executeArgs) => {
|
|
780
792
|
circularChecker.check();
|
|
781
|
-
// Make sure all effects are flushed before reading the args.
|
|
782
|
-
// A withArgs feature effect might still be pending otherwise resulting in the wrong args being read.
|
|
783
|
-
executeOptions.deps.effectScheduler.flush();
|
|
784
793
|
const { args = executeOptions.state.args(), options } = executeArgs ?? {};
|
|
785
794
|
queryExecute({ executeOptions, executeState, args, options });
|
|
786
795
|
};
|
|
@@ -1538,18 +1547,19 @@ const SPEED_BUFFER_TIME_IN_MS = 2000;
|
|
|
1538
1547
|
const createHttpRequest = (options) => {
|
|
1539
1548
|
let currentStreamSubscription = Subscription.EMPTY;
|
|
1540
1549
|
const { args, clientOptions, dependencies } = options;
|
|
1541
|
-
const currentEvent = signal(null, ...(ngDevMode ? [{ debugName: "currentEvent" }] : []));
|
|
1542
|
-
const
|
|
1543
|
-
const
|
|
1544
|
-
const
|
|
1545
|
-
const
|
|
1546
|
-
const
|
|
1547
|
-
const
|
|
1548
|
-
const
|
|
1550
|
+
const currentEvent = signal(null, ...(ngDevMode ? [{ debugName: "currentEvent" }] : /* istanbul ignore next */ []));
|
|
1551
|
+
const event$ = new Subject();
|
|
1552
|
+
const loading = signal(null, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
1553
|
+
const error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
1554
|
+
const response = signal(null, ...(ngDevMode ? [{ debugName: "response" }] : /* istanbul ignore next */ []));
|
|
1555
|
+
const lastLoadEventTime = signal(0, ...(ngDevMode ? [{ debugName: "lastLoadEventTime" }] : /* istanbul ignore next */ []));
|
|
1556
|
+
const lastLoadEventAmount = signal(0, ...(ngDevMode ? [{ debugName: "lastLoadEventAmount" }] : /* istanbul ignore next */ []));
|
|
1557
|
+
const lastExecuteTime = signal(0, ...(ngDevMode ? [{ debugName: "lastExecuteTime" }] : /* istanbul ignore next */ []));
|
|
1558
|
+
const expiresIn = signal(null, ...(ngDevMode ? [{ debugName: "expiresIn" }] : /* istanbul ignore next */ []));
|
|
1549
1559
|
const isStale = computed(() => {
|
|
1550
1560
|
const expiresInTs = expiresIn();
|
|
1551
1561
|
return expiresInTs === null || expiresInTs < Date.now();
|
|
1552
|
-
}, ...(ngDevMode ? [{ debugName: "isStale" }] : []));
|
|
1562
|
+
}, ...(ngDevMode ? [{ debugName: "isStale" }] : /* istanbul ignore next */ []));
|
|
1553
1563
|
const createStream = () => {
|
|
1554
1564
|
const headers = typeof args?.headers === 'function' ? args.headers() : args?.headers;
|
|
1555
1565
|
return dependencies.httpClient
|
|
@@ -1600,14 +1610,12 @@ const createHttpRequest = (options) => {
|
|
|
1600
1610
|
return true;
|
|
1601
1611
|
};
|
|
1602
1612
|
const destroy = () => {
|
|
1603
|
-
|
|
1604
|
-
return false;
|
|
1605
|
-
}
|
|
1613
|
+
const wasActive = !currentStreamSubscription.closed;
|
|
1606
1614
|
currentStreamSubscription.unsubscribe();
|
|
1607
|
-
|
|
1615
|
+
event$.complete();
|
|
1616
|
+
return wasActive;
|
|
1608
1617
|
};
|
|
1609
1618
|
const updateState = (event) => {
|
|
1610
|
-
currentEvent.set(event);
|
|
1611
1619
|
switch (event.type) {
|
|
1612
1620
|
case HttpEventType.Response:
|
|
1613
1621
|
{
|
|
@@ -1634,12 +1642,16 @@ const createHttpRequest = (options) => {
|
|
|
1634
1642
|
}
|
|
1635
1643
|
break;
|
|
1636
1644
|
}
|
|
1645
|
+
currentEvent.set(event);
|
|
1646
|
+
event$.next(event);
|
|
1637
1647
|
};
|
|
1638
1648
|
const updateErrorState = (errorResponse) => {
|
|
1639
1649
|
const errorRes = createQueryErrorResponse(errorResponse);
|
|
1640
1650
|
error.set(errorRes);
|
|
1641
1651
|
loading.set(null);
|
|
1642
|
-
|
|
1652
|
+
const errorEvent = { type: 'error', error: errorRes };
|
|
1653
|
+
currentEvent.set(errorEvent);
|
|
1654
|
+
event$.next(errorEvent);
|
|
1643
1655
|
options.dependencies.ngErrorHandler.handleError(errorRes.raw);
|
|
1644
1656
|
};
|
|
1645
1657
|
const updateLoadingState = (event) => {
|
|
@@ -1679,6 +1691,7 @@ const createHttpRequest = (options) => {
|
|
|
1679
1691
|
error: error.asReadonly(),
|
|
1680
1692
|
response: response.asReadonly(),
|
|
1681
1693
|
currentEvent: currentEvent.asReadonly(),
|
|
1694
|
+
events$: event$.asObservable(),
|
|
1682
1695
|
isStale,
|
|
1683
1696
|
};
|
|
1684
1697
|
return httpRequest;
|
|
@@ -1696,9 +1709,9 @@ const createQueryStack = (options) => {
|
|
|
1696
1709
|
return { queries, lastQuery };
|
|
1697
1710
|
}, transform, argsKeyFn, deduplicateArgs, maxQueries = Infinity, removeStrategy = 'oldest', } = options ?? {};
|
|
1698
1711
|
const injector = inject(Injector);
|
|
1699
|
-
const queries = signal([], ...(ngDevMode ? [{ debugName: "queries" }] : []));
|
|
1700
|
-
const lastQuery = signal(null, ...(ngDevMode ? [{ debugName: "lastQuery" }] : []));
|
|
1701
|
-
const firstQuery = computed(() => queries()[0] ?? null, ...(ngDevMode ? [{ debugName: "firstQuery" }] : []));
|
|
1712
|
+
const queries = signal([], ...(ngDevMode ? [{ debugName: "queries" }] : /* istanbul ignore next */ []));
|
|
1713
|
+
const lastQuery = signal(null, ...(ngDevMode ? [{ debugName: "lastQuery" }] : /* istanbul ignore next */ []));
|
|
1714
|
+
const firstQuery = computed(() => queries()[0] ?? null, ...(ngDevMode ? [{ debugName: "firstQuery" }] : /* istanbul ignore next */ []));
|
|
1702
1715
|
const hasWithArgsFeature = features.some((f) => f.type == QueryFeatureType.WITH_ARGS);
|
|
1703
1716
|
const hasWithOptimisticUpdateFeature = features.some((f) => f.type == QueryFeatureType.WITH_RESPONSE_UPDATE);
|
|
1704
1717
|
if (hasWithArgsFeature) {
|
|
@@ -1780,23 +1793,23 @@ const createQueryStack = (options) => {
|
|
|
1780
1793
|
untracked(() => clear());
|
|
1781
1794
|
});
|
|
1782
1795
|
effect(() => runWithArgs(args(dependencies?.())));
|
|
1783
|
-
const anyLoading = computed(() => queries().some((q) => q.loading()), ...(ngDevMode ? [{ debugName: "anyLoading" }] : []));
|
|
1784
|
-
const loadingCount = computed(() => queries().filter((q) => q.loading()).length, ...(ngDevMode ? [{ debugName: "loadingCount" }] : []));
|
|
1796
|
+
const anyLoading = computed(() => queries().some((q) => q.loading()), ...(ngDevMode ? [{ debugName: "anyLoading" }] : /* istanbul ignore next */ []));
|
|
1797
|
+
const loadingCount = computed(() => queries().filter((q) => q.loading()).length, ...(ngDevMode ? [{ debugName: "loadingCount" }] : /* istanbul ignore next */ []));
|
|
1785
1798
|
const allLoading = computed(() => {
|
|
1786
1799
|
const qs = queries();
|
|
1787
1800
|
return qs.length > 0 && qs.every((q) => q.loading());
|
|
1788
|
-
}, ...(ngDevMode ? [{ debugName: "allLoading" }] : []));
|
|
1801
|
+
}, ...(ngDevMode ? [{ debugName: "allLoading" }] : /* istanbul ignore next */ []));
|
|
1789
1802
|
const loadingProgress = computed(() => {
|
|
1790
1803
|
const total = queries().length;
|
|
1791
1804
|
const loaded = queries().filter((q) => !q.loading()).length;
|
|
1792
1805
|
return { loaded, total };
|
|
1793
|
-
}, ...(ngDevMode ? [{ debugName: "loadingProgress" }] : []));
|
|
1806
|
+
}, ...(ngDevMode ? [{ debugName: "loadingProgress" }] : /* istanbul ignore next */ []));
|
|
1794
1807
|
const anyError = computed(() => queries()
|
|
1795
1808
|
.map((q) => q.error())
|
|
1796
|
-
.find((e) => e !== null) ?? null, ...(ngDevMode ? [{ debugName: "anyError" }] : []));
|
|
1809
|
+
.find((e) => e !== null) ?? null, ...(ngDevMode ? [{ debugName: "anyError" }] : /* istanbul ignore next */ []));
|
|
1797
1810
|
const errors = computed(() => queries()
|
|
1798
1811
|
.map((q) => q.error())
|
|
1799
|
-
.filter((e) => e !== null), ...(ngDevMode ? [{ debugName: "errors" }] : []));
|
|
1812
|
+
.filter((e) => e !== null), ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
1800
1813
|
const response = computed(() => {
|
|
1801
1814
|
const responses = queries().map((q) => q.response());
|
|
1802
1815
|
return transform?.(responses) ?? responses;
|
|
@@ -1891,12 +1904,12 @@ const fakePaginationAdapter = (totalHits = 10) => {
|
|
|
1891
1904
|
};
|
|
1892
1905
|
const createPagedQueryStack = (options) => {
|
|
1893
1906
|
const { responseNormalizer, queryCreator, features } = options;
|
|
1894
|
-
const currentPageArgs = signal(null, ...(ngDevMode ? [{ debugName: "currentPageArgs" }] : []));
|
|
1895
|
-
const initialPage = signal(options.initialPage ?? 1, ...(ngDevMode ? [{ debugName: "initialPage" }] : []));
|
|
1896
|
-
const loadedMinPage = signal(initialPage(), ...(ngDevMode ? [{ debugName: "loadedMinPage" }] : []));
|
|
1897
|
-
const loadedMaxPage = signal(initialPage(), ...(ngDevMode ? [{ debugName: "loadedMaxPage" }] : []));
|
|
1898
|
-
const
|
|
1899
|
-
const pageDirection = signal('next', ...(ngDevMode ? [{ debugName: "pageDirection" }] : []));
|
|
1907
|
+
const currentPageArgs = signal(null, ...(ngDevMode ? [{ debugName: "currentPageArgs" }] : /* istanbul ignore next */ []));
|
|
1908
|
+
const initialPage = signal(options.initialPage ?? 1, ...(ngDevMode ? [{ debugName: "initialPage" }] : /* istanbul ignore next */ []));
|
|
1909
|
+
const loadedMinPage = signal(initialPage(), ...(ngDevMode ? [{ debugName: "loadedMinPage" }] : /* istanbul ignore next */ []));
|
|
1910
|
+
const loadedMaxPage = signal(initialPage(), ...(ngDevMode ? [{ debugName: "loadedMaxPage" }] : /* istanbul ignore next */ []));
|
|
1911
|
+
const resetTrigger = signal(0, ...(ngDevMode ? [{ debugName: "resetTrigger" }] : /* istanbul ignore next */ []));
|
|
1912
|
+
const pageDirection = signal('next', ...(ngDevMode ? [{ debugName: "pageDirection" }] : /* istanbul ignore next */ []));
|
|
1900
1913
|
const stack = createQueryStack({
|
|
1901
1914
|
args: () => null,
|
|
1902
1915
|
queryCreator,
|
|
@@ -1919,7 +1932,7 @@ const createPagedQueryStack = (options) => {
|
|
|
1919
1932
|
transform: transformArrayResponse,
|
|
1920
1933
|
});
|
|
1921
1934
|
effect(() => {
|
|
1922
|
-
|
|
1935
|
+
resetTrigger();
|
|
1923
1936
|
const args = options.args(initialPage(), []);
|
|
1924
1937
|
untracked(() => {
|
|
1925
1938
|
stack.clear();
|
|
@@ -1935,22 +1948,22 @@ const createPagedQueryStack = (options) => {
|
|
|
1935
1948
|
if (!res)
|
|
1936
1949
|
return null;
|
|
1937
1950
|
return responseNormalizer(res, all);
|
|
1938
|
-
}, ...(ngDevMode ? [{ debugName: "maxPagination" }] : []));
|
|
1951
|
+
}, ...(ngDevMode ? [{ debugName: "maxPagination" }] : /* istanbul ignore next */ []));
|
|
1939
1952
|
const minPagination = computed(() => {
|
|
1940
1953
|
const res = stack.firstQuery()?.response();
|
|
1941
1954
|
const all = stack.response();
|
|
1942
1955
|
if (!res)
|
|
1943
1956
|
return null;
|
|
1944
1957
|
return responseNormalizer(res, all);
|
|
1945
|
-
}, ...(ngDevMode ? [{ debugName: "minPagination" }] : []));
|
|
1958
|
+
}, ...(ngDevMode ? [{ debugName: "minPagination" }] : /* istanbul ignore next */ []));
|
|
1946
1959
|
const isFirstPageLoaded = computed(() => {
|
|
1947
1960
|
const min = minPagination();
|
|
1948
1961
|
return min ? loadedMinPage() === min.currentPage : false;
|
|
1949
|
-
}, ...(ngDevMode ? [{ debugName: "isFirstPageLoaded" }] : []));
|
|
1962
|
+
}, ...(ngDevMode ? [{ debugName: "isFirstPageLoaded" }] : /* istanbul ignore next */ []));
|
|
1950
1963
|
const isLastPageLoaded = computed(() => {
|
|
1951
1964
|
const max = maxPagination();
|
|
1952
1965
|
return max ? loadedMaxPage() === max.totalPages : false;
|
|
1953
|
-
}, ...(ngDevMode ? [{ debugName: "isLastPageLoaded" }] : []));
|
|
1966
|
+
}, ...(ngDevMode ? [{ debugName: "isLastPageLoaded" }] : /* istanbul ignore next */ []));
|
|
1954
1967
|
const fetchPreviousPage = () => {
|
|
1955
1968
|
const page = loadedMinPage() - 1;
|
|
1956
1969
|
const allResponses = stack.response();
|
|
@@ -2019,25 +2032,25 @@ const createPagedQueryStack = (options) => {
|
|
|
2019
2032
|
const page = resetOptions?.initialPage ?? initialPage();
|
|
2020
2033
|
initialPage.set(page);
|
|
2021
2034
|
pageDirection.set('next');
|
|
2022
|
-
|
|
2035
|
+
resetTrigger.update((v) => v + 1);
|
|
2023
2036
|
};
|
|
2024
2037
|
const canFetchPreviousPage = computed(() => {
|
|
2025
2038
|
const currentMinPagination = minPagination();
|
|
2026
2039
|
if (!currentMinPagination)
|
|
2027
2040
|
return false;
|
|
2028
2041
|
return loadedMinPage() > 1;
|
|
2029
|
-
}, ...(ngDevMode ? [{ debugName: "canFetchPreviousPage" }] : []));
|
|
2042
|
+
}, ...(ngDevMode ? [{ debugName: "canFetchPreviousPage" }] : /* istanbul ignore next */ []));
|
|
2030
2043
|
const canFetchNextPage = computed(() => {
|
|
2031
2044
|
const currentMaxPagination = maxPagination();
|
|
2032
2045
|
return currentMaxPagination ? loadedMaxPage() < currentMaxPagination.totalPages : false;
|
|
2033
|
-
}, ...(ngDevMode ? [{ debugName: "canFetchNextPage" }] : []));
|
|
2046
|
+
}, ...(ngDevMode ? [{ debugName: "canFetchNextPage" }] : /* istanbul ignore next */ []));
|
|
2034
2047
|
const items = computed(() => {
|
|
2035
2048
|
const res = stack.response();
|
|
2036
2049
|
return res.map((r) => responseNormalizer(r, res).items).flat();
|
|
2037
|
-
}, ...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
2050
|
+
}, ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
2038
2051
|
const isFirstLoad = computed(() => {
|
|
2039
2052
|
return stack.queries().length === 1 && !!stack.lastQuery()?.loading();
|
|
2040
|
-
}, ...(ngDevMode ? [{ debugName: "isFirstLoad" }] : []));
|
|
2053
|
+
}, ...(ngDevMode ? [{ debugName: "isFirstLoad" }] : /* istanbul ignore next */ []));
|
|
2041
2054
|
const execute = (options) => {
|
|
2042
2055
|
const whereFn = options?.where;
|
|
2043
2056
|
if (whereFn) {
|
|
@@ -2210,7 +2223,7 @@ function effectComputed(computation, injector) {
|
|
|
2210
2223
|
// Ignore errors in the initial computation
|
|
2211
2224
|
// Angular might throw an error if required inputs are read but not available yet
|
|
2212
2225
|
}
|
|
2213
|
-
const lastResult = signal(initialData, ...(ngDevMode ? [{ debugName: "lastResult" }] : []));
|
|
2226
|
+
const lastResult = signal(initialData, ...(ngDevMode ? [{ debugName: "lastResult" }] : /* istanbul ignore next */ []));
|
|
2214
2227
|
effect(() => {
|
|
2215
2228
|
const data = runInInjectionContext(injector, () => computation());
|
|
2216
2229
|
untracked(() => {
|
|
@@ -2261,7 +2274,7 @@ function queryStateSignal(source, options) {
|
|
|
2261
2274
|
})), {
|
|
2262
2275
|
initialValue: null,
|
|
2263
2276
|
});
|
|
2264
|
-
const rwSignal = linkedSignal(roSignal, ...(ngDevMode ? [{ debugName: "rwSignal" }] : []));
|
|
2277
|
+
const rwSignal = linkedSignal(roSignal, ...(ngDevMode ? [{ debugName: "rwSignal" }] : /* istanbul ignore next */ []));
|
|
2265
2278
|
return rwSignal;
|
|
2266
2279
|
}
|
|
2267
2280
|
function queryStateResponseSignal(source, options) {
|
|
@@ -2269,7 +2282,7 @@ function queryStateResponseSignal(source, options) {
|
|
|
2269
2282
|
const dataSignal = computed(() => {
|
|
2270
2283
|
const state = s();
|
|
2271
2284
|
return isQueryStateSuccess(state) ? state.response : null;
|
|
2272
|
-
}, ...(ngDevMode ? [{ debugName: "dataSignal" }] : []));
|
|
2285
|
+
}, ...(ngDevMode ? [{ debugName: "dataSignal" }] : /* istanbul ignore next */ []));
|
|
2273
2286
|
dataSignal['reset'] = () => {
|
|
2274
2287
|
s.set(null);
|
|
2275
2288
|
};
|
|
@@ -2352,7 +2365,7 @@ class V2QueryCreator {
|
|
|
2352
2365
|
};
|
|
2353
2366
|
this.createSignal = (initialValue, config) => {
|
|
2354
2367
|
assertInInjectionContext(this.createSignal);
|
|
2355
|
-
const _signal = signal(initialValue ?? null, ...(ngDevMode ? [{ debugName: "_signal" }] : []));
|
|
2368
|
+
const _signal = signal(initialValue ?? null, ...(ngDevMode ? [{ debugName: "_signal" }] : /* istanbul ignore next */ []));
|
|
2356
2369
|
addQueryContainerHandling(toObservable(_signal), () => _signal(), config);
|
|
2357
2370
|
return _signal;
|
|
2358
2371
|
};
|
|
@@ -2622,11 +2635,14 @@ const createSecureExecuteFactory = (options) => {
|
|
|
2622
2635
|
const circularChecker = circularQueryDependencyChecker();
|
|
2623
2636
|
let authQuerySubscription = Subscription.EMPTY;
|
|
2624
2637
|
let tokenRefreshSubscription = Subscription.EMPTY;
|
|
2638
|
+
let tokenWaitSubscription = Subscription.EMPTY;
|
|
2625
2639
|
const reset = () => {
|
|
2626
2640
|
authQuerySubscription.unsubscribe();
|
|
2627
2641
|
authQuerySubscription = Subscription.EMPTY;
|
|
2628
2642
|
tokenRefreshSubscription.unsubscribe();
|
|
2629
2643
|
tokenRefreshSubscription = Subscription.EMPTY;
|
|
2644
|
+
tokenWaitSubscription.unsubscribe();
|
|
2645
|
+
tokenWaitSubscription = Subscription.EMPTY;
|
|
2630
2646
|
resetExecuteState({
|
|
2631
2647
|
executeState,
|
|
2632
2648
|
executeOptions: { deps: options.deps, state: options.state },
|
|
@@ -2667,11 +2683,27 @@ const createSecureExecuteFactory = (options) => {
|
|
|
2667
2683
|
},
|
|
2668
2684
|
}, tokens, headers, executeState);
|
|
2669
2685
|
};
|
|
2686
|
+
// The auth query completing and the access token being populated happen on two
|
|
2687
|
+
// different reactive timelines: the token is set by a separate token-extraction
|
|
2688
|
+
// effect (see `setupBearerQueryRegistry`), and for cross-client / secure auth
|
|
2689
|
+
// queries the completion is delivered through several nested `toObservable` hops.
|
|
2690
|
+
// Calling `authAndExec` purely because the auth query is "done" therefore races
|
|
2691
|
+
// the token and can run while it is still null. Gate on the token signal instead:
|
|
2692
|
+
// execute immediately if it is already available, otherwise wait for it.
|
|
2693
|
+
const authAndExecWhenTokenReady = (executeArgs) => {
|
|
2694
|
+
if (options.authProvider.accessToken()) {
|
|
2695
|
+
authAndExec(executeArgs);
|
|
2696
|
+
return;
|
|
2697
|
+
}
|
|
2698
|
+
tokenWaitSubscription.unsubscribe();
|
|
2699
|
+
tokenWaitSubscription = toObservable(options.authProvider.accessToken, {
|
|
2700
|
+
injector: options.deps.injector,
|
|
2701
|
+
})
|
|
2702
|
+
.pipe(filter(Boolean), take(1), tap(() => authAndExec(executeArgs)))
|
|
2703
|
+
.subscribe();
|
|
2704
|
+
};
|
|
2670
2705
|
const exec = (executeArgs) => {
|
|
2671
2706
|
circularChecker.check();
|
|
2672
|
-
// Make sure all effects are flushed before reading the args.
|
|
2673
|
-
// A withArgs feature effect might still be pending otherwise resulting in the wrong args being read.
|
|
2674
|
-
options.deps.effectScheduler.flush();
|
|
2675
2707
|
const execArgsWithDefaults = {
|
|
2676
2708
|
args: executeArgs?.args ?? options.state.args(),
|
|
2677
2709
|
options: executeArgs?.options,
|
|
@@ -2680,6 +2712,8 @@ const createSecureExecuteFactory = (options) => {
|
|
|
2680
2712
|
authQuerySubscription = Subscription.EMPTY;
|
|
2681
2713
|
tokenRefreshSubscription.unsubscribe();
|
|
2682
2714
|
tokenRefreshSubscription = Subscription.EMPTY;
|
|
2715
|
+
tokenWaitSubscription.unsubscribe();
|
|
2716
|
+
tokenWaitSubscription = Subscription.EMPTY;
|
|
2683
2717
|
tokenRefreshSubscription = options.authProvider.afterTokenRefresh$
|
|
2684
2718
|
.pipe(filter(() => {
|
|
2685
2719
|
const currentError = options.state.error();
|
|
@@ -2707,14 +2741,14 @@ const createSecureExecuteFactory = (options) => {
|
|
|
2707
2741
|
error(query);
|
|
2708
2742
|
}
|
|
2709
2743
|
else if (query.response()) {
|
|
2710
|
-
|
|
2744
|
+
authAndExecWhenTokenReady(execArgsWithDefaults);
|
|
2711
2745
|
}
|
|
2712
2746
|
}));
|
|
2713
2747
|
}))
|
|
2714
2748
|
.subscribe();
|
|
2715
2749
|
}
|
|
2716
2750
|
else if (authQuery.response()) {
|
|
2717
|
-
|
|
2751
|
+
authAndExecWhenTokenReady(execArgsWithDefaults);
|
|
2718
2752
|
}
|
|
2719
2753
|
else if (authQuery.error()) {
|
|
2720
2754
|
error(authQuery);
|
|
@@ -2959,7 +2993,7 @@ class LegacyQuery {
|
|
|
2959
2993
|
});
|
|
2960
2994
|
}
|
|
2961
2995
|
});
|
|
2962
|
-
}, ...(ngDevMode ? [{ debugName: "storeSyncEffect" }] : []));
|
|
2996
|
+
}, ...(ngDevMode ? [{ debugName: "storeSyncEffect" }] : /* istanbul ignore next */ []));
|
|
2963
2997
|
/**
|
|
2964
2998
|
* @internal
|
|
2965
2999
|
*/
|
|
@@ -3112,7 +3146,7 @@ class LegacyQueryCreator {
|
|
|
3112
3146
|
legacyQuery.destroy();
|
|
3113
3147
|
destroyEffect.destroy();
|
|
3114
3148
|
}
|
|
3115
|
-
}, ...(ngDevMode ? [{ debugName: "destroyEffect" }] : []));
|
|
3149
|
+
}, ...(ngDevMode ? [{ debugName: "destroyEffect" }] : /* istanbul ignore next */ []));
|
|
3116
3150
|
}
|
|
3117
3151
|
return legacyQuery;
|
|
3118
3152
|
});
|
|
@@ -3124,7 +3158,7 @@ class LegacyQueryCreator {
|
|
|
3124
3158
|
return subject;
|
|
3125
3159
|
};
|
|
3126
3160
|
this.createSignal = (initialValue, config) => {
|
|
3127
|
-
const _signal = signal(initialValue ?? null, ...(ngDevMode ? [{ debugName: "_signal" }] : []));
|
|
3161
|
+
const _signal = signal(initialValue ?? null, ...(ngDevMode ? [{ debugName: "_signal" }] : /* istanbul ignore next */ []));
|
|
3128
3162
|
addQueryContainerHandling(toObservable(_signal), () => _signal(), config);
|
|
3129
3163
|
return _signal;
|
|
3130
3164
|
};
|
|
@@ -3271,7 +3305,7 @@ const createQueryCollectionSubject = (queryMap, config) => {
|
|
|
3271
3305
|
};
|
|
3272
3306
|
const createQueryCollectionSignal = (queryMap, config) => {
|
|
3273
3307
|
assertInInjectionContext(createQueryCollectionSignal);
|
|
3274
|
-
const _signal = signal(null, ...(ngDevMode ? [{ debugName: "_signal" }] : []));
|
|
3308
|
+
const _signal = signal(null, ...(ngDevMode ? [{ debugName: "_signal" }] : /* istanbul ignore next */ []));
|
|
3275
3309
|
addQueryContainerHandling(toObservable(_signal).pipe(map((s) => s?.query ?? null)), () => _signal()?.query ?? null, config);
|
|
3276
3310
|
return _signal;
|
|
3277
3311
|
};
|
|
@@ -4005,7 +4039,7 @@ class V2BearerAuthProvider {
|
|
|
4005
4039
|
}
|
|
4006
4040
|
|
|
4007
4041
|
const [provideInfinityQueryResponseDelay, injectInfinityQueryResponseDelay] = createProvider(() => {
|
|
4008
|
-
const enabled = signal(false, ...(ngDevMode ? [{ debugName: "enabled" }] : []));
|
|
4042
|
+
const enabled = signal(false, ...(ngDevMode ? [{ debugName: "enabled" }] : /* istanbul ignore next */ []));
|
|
4009
4043
|
const enabled$ = toObservable(enabled);
|
|
4010
4044
|
return {
|
|
4011
4045
|
enabled,
|
|
@@ -4316,13 +4350,13 @@ class InfinityQueryDirective {
|
|
|
4316
4350
|
this._viewContext.currentQuery = null;
|
|
4317
4351
|
this._data$.next([]);
|
|
4318
4352
|
}
|
|
4319
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
4320
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.
|
|
4353
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4354
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: InfinityQueryDirective, isStandalone: true, selector: "[etInfinityQuery]", inputs: { infinityQuery: ["etInfinityQuery", "infinityQuery"] }, providers: [
|
|
4321
4355
|
{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective },
|
|
4322
4356
|
provideInfinityQueryResponseDelay(),
|
|
4323
4357
|
], exportAs: ["etInfinityQuery"], ngImport: i0 }); }
|
|
4324
4358
|
}
|
|
4325
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
4359
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: InfinityQueryDirective, decorators: [{
|
|
4326
4360
|
type: Directive,
|
|
4327
4361
|
args: [{
|
|
4328
4362
|
selector: '[etInfinityQuery]',
|
|
@@ -4344,10 +4378,10 @@ class InfinityQueryTriggerDirective {
|
|
|
4344
4378
|
this._destroy = new Subject();
|
|
4345
4379
|
this._observer = null;
|
|
4346
4380
|
this.click$ = fromEvent(this._elementRef.nativeElement, 'click');
|
|
4347
|
-
this.scrollContainerSelector = input(null, ...(ngDevMode ? [{ debugName: "scrollContainerSelector" }] : []));
|
|
4381
|
+
this.scrollContainerSelector = input(null, ...(ngDevMode ? [{ debugName: "scrollContainerSelector" }] : /* istanbul ignore next */ []));
|
|
4348
4382
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4349
|
-
this.infinityQueryOverride = input(null, ...(ngDevMode ? [{ debugName: "infinityQueryOverride" }] : []));
|
|
4350
|
-
this.infinityQuery = computed(() => this.infinityQueryOverride() ?? this._infinityQuery, ...(ngDevMode ? [{ debugName: "infinityQuery" }] : []));
|
|
4383
|
+
this.infinityQueryOverride = input(null, ...(ngDevMode ? [{ debugName: "infinityQueryOverride" }] : /* istanbul ignore next */ []));
|
|
4384
|
+
this.infinityQuery = computed(() => this.infinityQueryOverride() ?? this._infinityQuery, ...(ngDevMode ? [{ debugName: "infinityQuery" }] : /* istanbul ignore next */ []));
|
|
4351
4385
|
}
|
|
4352
4386
|
ngOnInit() {
|
|
4353
4387
|
const isInteractive = this._elementRef.nativeElement.tagName === 'BUTTON';
|
|
@@ -4379,10 +4413,10 @@ class InfinityQueryTriggerDirective {
|
|
|
4379
4413
|
});
|
|
4380
4414
|
this._observer.observe(this._elementRef.nativeElement);
|
|
4381
4415
|
}
|
|
4382
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
4383
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.
|
|
4416
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4417
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[etInfinityQueryTrigger], et-infinity-query-trigger", inputs: { scrollContainerSelector: { classPropertyName: "scrollContainerSelector", publicName: "scrollContainerSelector", isSignal: true, isRequired: false, transformFunction: null }, infinityQueryOverride: { classPropertyName: "infinityQueryOverride", publicName: "infinityQueryOverride", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
|
|
4384
4418
|
}
|
|
4385
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
4419
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
|
|
4386
4420
|
type: Directive,
|
|
4387
4421
|
args: [{
|
|
4388
4422
|
selector: '[etInfinityQueryTrigger], et-infinity-query-trigger',
|
|
@@ -4406,8 +4440,8 @@ class QueryDirective {
|
|
|
4406
4440
|
scope: null,
|
|
4407
4441
|
query: null,
|
|
4408
4442
|
};
|
|
4409
|
-
this.query = input.required({ ...(ngDevMode ? { debugName: "query" } : {}), alias: 'etQuery' });
|
|
4410
|
-
this.cache = input(false, { ...(ngDevMode ? { debugName: "cache" } : {}), alias: 'etQueryCache' });
|
|
4443
|
+
this.query = input.required({ ...(ngDevMode ? { debugName: "query" } : /* istanbul ignore next */ {}), alias: 'etQuery' });
|
|
4444
|
+
this.cache = input(false, { ...(ngDevMode ? { debugName: "cache" } : /* istanbul ignore next */ {}), alias: 'etQueryCache' });
|
|
4411
4445
|
this.queryState = queryStateSignal(this.query);
|
|
4412
4446
|
inject(ViewContainerRef).createEmbeddedView(inject(TemplateRef), this._viewContext);
|
|
4413
4447
|
effect(() => {
|
|
@@ -4468,10 +4502,10 @@ class QueryDirective {
|
|
|
4468
4502
|
});
|
|
4469
4503
|
});
|
|
4470
4504
|
}
|
|
4471
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
4472
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.
|
|
4505
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: QueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4506
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: QueryDirective, isStandalone: true, selector: "[etQuery]", inputs: { query: { classPropertyName: "query", publicName: "etQuery", isSignal: true, isRequired: true, transformFunction: null }, cache: { classPropertyName: "cache", publicName: "etQueryCache", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
|
|
4473
4507
|
}
|
|
4474
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
4508
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: QueryDirective, decorators: [{
|
|
4475
4509
|
type: Directive,
|
|
4476
4510
|
args: [{
|
|
4477
4511
|
selector: '[etQuery]',
|
|
@@ -4492,10 +4526,10 @@ class QueryShortNamePipe {
|
|
|
4492
4526
|
}
|
|
4493
4527
|
return route;
|
|
4494
4528
|
}
|
|
4495
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
4496
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.
|
|
4529
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: QueryShortNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
4530
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: QueryShortNamePipe, isStandalone: true, name: "queryShortName" }); }
|
|
4497
4531
|
}
|
|
4498
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
4532
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: QueryShortNamePipe, decorators: [{
|
|
4499
4533
|
type: Pipe,
|
|
4500
4534
|
args: [{ name: 'queryShortName' }]
|
|
4501
4535
|
}] });
|
|
@@ -4517,19 +4551,19 @@ class QueryDevtoolsComponent {
|
|
|
4517
4551
|
this._cdr = inject(ChangeDetectorRef);
|
|
4518
4552
|
this._destroy$ = createDestroy();
|
|
4519
4553
|
this.queryClientConfigs = inject(QUERY_CLIENT_DEVTOOLS_TOKEN);
|
|
4520
|
-
this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
4521
|
-
this.isTranslucent = signal(false, ...(ngDevMode ? [{ debugName: "isTranslucent" }] : []));
|
|
4522
|
-
this.snapLayout = signal('full', ...(ngDevMode ? [{ debugName: "snapLayout" }] : []));
|
|
4523
|
-
this.queryListMode = signal('live', ...(ngDevMode ? [{ debugName: "queryListMode" }] : []));
|
|
4524
|
-
this.viewMode = signal('query', ...(ngDevMode ? [{ debugName: "viewMode" }] : []));
|
|
4525
|
-
this.showResponse = signal(false, ...(ngDevMode ? [{ debugName: "showResponse" }] : []));
|
|
4526
|
-
this.showRawResponse = signal(false, ...(ngDevMode ? [{ debugName: "showRawResponse" }] : []));
|
|
4527
|
-
this.showQueryConfig = signal(false, ...(ngDevMode ? [{ debugName: "showQueryConfig" }] : []));
|
|
4528
|
-
this.showEntityStoreValue = signal(false, ...(ngDevMode ? [{ debugName: "showEntityStoreValue" }] : []));
|
|
4529
|
-
this.showArguments = signal(false, ...(ngDevMode ? [{ debugName: "showArguments" }] : []));
|
|
4554
|
+
this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
4555
|
+
this.isTranslucent = signal(false, ...(ngDevMode ? [{ debugName: "isTranslucent" }] : /* istanbul ignore next */ []));
|
|
4556
|
+
this.snapLayout = signal('full', ...(ngDevMode ? [{ debugName: "snapLayout" }] : /* istanbul ignore next */ []));
|
|
4557
|
+
this.queryListMode = signal('live', ...(ngDevMode ? [{ debugName: "queryListMode" }] : /* istanbul ignore next */ []));
|
|
4558
|
+
this.viewMode = signal('query', ...(ngDevMode ? [{ debugName: "viewMode" }] : /* istanbul ignore next */ []));
|
|
4559
|
+
this.showResponse = signal(false, ...(ngDevMode ? [{ debugName: "showResponse" }] : /* istanbul ignore next */ []));
|
|
4560
|
+
this.showRawResponse = signal(false, ...(ngDevMode ? [{ debugName: "showRawResponse" }] : /* istanbul ignore next */ []));
|
|
4561
|
+
this.showQueryConfig = signal(false, ...(ngDevMode ? [{ debugName: "showQueryConfig" }] : /* istanbul ignore next */ []));
|
|
4562
|
+
this.showEntityStoreValue = signal(false, ...(ngDevMode ? [{ debugName: "showEntityStoreValue" }] : /* istanbul ignore next */ []));
|
|
4563
|
+
this.showArguments = signal(false, ...(ngDevMode ? [{ debugName: "showArguments" }] : /* istanbul ignore next */ []));
|
|
4530
4564
|
this.selectedClientIdCtrl = new FormControl(0);
|
|
4531
4565
|
this.selectedClientId = toSignal(this.selectedClientIdCtrl.valueChanges.pipe(startWith(this.selectedClientIdCtrl.value)));
|
|
4532
|
-
this.selectedQueryId = signal(null, ...(ngDevMode ? [{ debugName: "selectedQueryId" }] : []));
|
|
4566
|
+
this.selectedQueryId = signal(null, ...(ngDevMode ? [{ debugName: "selectedQueryId" }] : /* istanbul ignore next */ []));
|
|
4533
4567
|
this.selectedClientConfig = computed(() => {
|
|
4534
4568
|
if (this.queryClientConfigs.length === 1) {
|
|
4535
4569
|
return this.queryClientConfigs[0];
|
|
@@ -4540,11 +4574,11 @@ class QueryDevtoolsComponent {
|
|
|
4540
4574
|
return this.queryClientConfigs[0];
|
|
4541
4575
|
}
|
|
4542
4576
|
return cfg;
|
|
4543
|
-
}, ...(ngDevMode ? [{ debugName: "selectedClientConfig" }] : []));
|
|
4577
|
+
}, ...(ngDevMode ? [{ debugName: "selectedClientConfig" }] : /* istanbul ignore next */ []));
|
|
4544
4578
|
this.queryStore = computed(() => {
|
|
4545
4579
|
const config = this.selectedClientConfig();
|
|
4546
4580
|
return config.client._store;
|
|
4547
|
-
}, ...(ngDevMode ? [{ debugName: "queryStore" }] : []));
|
|
4581
|
+
}, ...(ngDevMode ? [{ debugName: "queryStore" }] : /* istanbul ignore next */ []));
|
|
4548
4582
|
this.queryStore$ = toObservable(this.queryStore);
|
|
4549
4583
|
this._queries$ = new BehaviorSubject([]);
|
|
4550
4584
|
this.queries = toSignal(this._queries$);
|
|
@@ -4558,14 +4592,14 @@ class QueryDevtoolsComponent {
|
|
|
4558
4592
|
return this.queries()?.find((q) => q._id === id) ?? null;
|
|
4559
4593
|
}
|
|
4560
4594
|
return this.queryHistory$.getValue()?.find((q) => q._id === id) ?? null;
|
|
4561
|
-
}, ...(ngDevMode ? [{ debugName: "selectedQuery" }] : []));
|
|
4595
|
+
}, ...(ngDevMode ? [{ debugName: "selectedQuery" }] : /* istanbul ignore next */ []));
|
|
4562
4596
|
this.selectedQuery$ = toObservable(this.selectedQuery);
|
|
4563
4597
|
this.selectedQueryEntityStore = computed(() => {
|
|
4564
4598
|
const query = this.selectedQuery();
|
|
4565
4599
|
if (!query)
|
|
4566
4600
|
return null;
|
|
4567
4601
|
return query.store;
|
|
4568
|
-
}, ...(ngDevMode ? [{ debugName: "selectedQueryEntityStore" }] : []));
|
|
4602
|
+
}, ...(ngDevMode ? [{ debugName: "selectedQueryEntityStore" }] : /* istanbul ignore next */ []));
|
|
4569
4603
|
this.selectedQueryEntityStore$ = toObservable(this.selectedQueryEntityStore);
|
|
4570
4604
|
this.selectedQueryEntityStoreValue$ = this.selectedQueryEntityStore$.pipe(switchMap((s) => s?._change$.pipe(startWith(''), map(() => {
|
|
4571
4605
|
if (!s._dictionary)
|
|
@@ -4603,7 +4637,7 @@ class QueryDevtoolsComponent {
|
|
|
4603
4637
|
return {
|
|
4604
4638
|
...sharedCfg,
|
|
4605
4639
|
};
|
|
4606
|
-
}, ...(ngDevMode ? [{ debugName: "stringifiedQueryConfig" }] : []));
|
|
4640
|
+
}, ...(ngDevMode ? [{ debugName: "stringifiedQueryConfig" }] : /* istanbul ignore next */ []));
|
|
4607
4641
|
this.authProvider = toSignal(toObservable(this.selectedClientConfig).pipe(switchMap((c) => c.client.authProvider$)));
|
|
4608
4642
|
this.authProviderDetails = computed(() => {
|
|
4609
4643
|
const provider = this.authProvider();
|
|
@@ -4665,7 +4699,7 @@ class QueryDevtoolsComponent {
|
|
|
4665
4699
|
config: {},
|
|
4666
4700
|
};
|
|
4667
4701
|
}
|
|
4668
|
-
}, ...(ngDevMode ? [{ debugName: "authProviderDetails" }] : []));
|
|
4702
|
+
}, ...(ngDevMode ? [{ debugName: "authProviderDetails" }] : /* istanbul ignore next */ []));
|
|
4669
4703
|
this.trackByClient = (_, { client }) => client.config.baseRoute;
|
|
4670
4704
|
this.trackByQuery = (_, { _id }) => _id;
|
|
4671
4705
|
this.selectedClientIdCtrl.valueChanges
|
|
@@ -4786,10 +4820,10 @@ class QueryDevtoolsComponent {
|
|
|
4786
4820
|
clearQueryHistory() {
|
|
4787
4821
|
this.queryHistory$.next([]);
|
|
4788
4822
|
}
|
|
4789
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
4790
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: QueryDevtoolsComponent, isStandalone: true, selector: "et-query-devtools", host: { classAttribute: "et-query-devtools" }, ngImport: i0, template: "@if (!isOpen()) {\n <button (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn et-qd-chip\">Query Devtools</button>\n}\n\n@if (isOpen()) {\n <div\n [class.et-query-devtools-container--transparent]=\"isTranslucent()\"\n class=\"et-query-devtools-container et-query-devtools-container--snap-{{ snapLayout() }}\"\n >\n <header class=\"et-qd-header\">\n <h3 class=\"et-qd-header__title\">Query Devtools</h3>\n\n <div class=\"et-qd-header__select\">\n <label for=\"et-query-client-instance\">Client instance</label>\n <select [formControl]=\"selectedClientIdCtrl\" id=\"et-query-client-instance\">\n @for (clientConfig of queryClientConfigs; track trackByClient(i, clientConfig); let i = $index) {\n <option [value]=\"i\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </option>\n }\n </select>\n </div>\n\n <button (click)=\"toggleOpen()\" class=\"et-qd-btn et-qd-btn-secondary\">Close</button>\n </header>\n\n <div class=\"et-qd-sub-header\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !isTranslucent() }\"\n (click)=\"toggleTranslucent()\"\n class=\"et-qd-chip et-qd-translucent-clickable\"\n >\n Translucent\n </button>\n <div class=\"et-qd-sub-header__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'full' }\"\n (click)=\"selectSnapLayout('full')\"\n class=\"et-qd-chip\"\n >\n Fullscreen\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'top' }\"\n (click)=\"selectSnapLayout('top')\"\n class=\"et-qd-chip\"\n >\n Top\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'bottom' }\"\n (click)=\"selectSnapLayout('bottom')\"\n class=\"et-qd-chip\"\n >\n Bottom\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'left' }\"\n (click)=\"selectSnapLayout('left')\"\n class=\"et-qd-chip\"\n >\n Left\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'right' }\"\n (click)=\"selectSnapLayout('right')\"\n class=\"et-qd-chip\"\n >\n Right\n </button>\n </div>\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-client\">\n <p class=\"et-qd-client__title\">{{ cfg.displayName ?? cfg.client.config.baseRoute }}</p>\n\n <div class=\"et-qd-client__actions\">\n <button (click)=\"cfg.client._store.refreshQueriesInUse()\" class=\"et-qd-chip\">Refresh all</button>\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true })\" class=\"et-qd-chip\">\n Refresh all (ignore caches)\n </button>\n <button\n (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true, purgeUnused: true })\"\n class=\"et-qd-chip\"\n >\n Refresh all (ignore caches & purge unused)\n </button>\n </div>\n </div>\n }\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-queries\">\n <p class=\"et-qd-queries__title\">Inspector</p>\n <div class=\"et-qd-queries__actions\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'live' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('live'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Live Queries ({{ queries()?.length ?? 0 }})\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'history' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('history'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Query History ({{ (queryHistory$ | async)?.length ?? 0 }}/50)\n </button>\n @if (queryListMode() === 'history' && viewMode() === 'query') {\n <div class=\"et-qd-queries__divider\"></div>\n <button (click)=\"clearQueryHistory()\" class=\"et-qd-chip et-qd-chip-bordered\">Clear history</button>\n }\n\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': viewMode() !== 'authProvider' }\"\n (click)=\"selectViewMode('authProvider')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Auth Provider\n </button>\n </div>\n\n @if (viewMode() === 'query') {\n <div class=\"et-qd-queries__browser\">\n @if (queryListMode() === 'live') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queries(); track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n @if (queryListMode() === 'history') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queryHistory$ | async; track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n <div class=\"et-qd-queries__browser-detail\">\n @if (selectedQuery(); as query) {\n <p class=\"et-qd-queries__browser-detail__title\">\n {{ query._queryConfig.method }} {{ query._routeWithParams }}\n </p>\n\n <div class=\"et-qd-queries__actions\">\n <button (click)=\"query.execute()\" class=\"et-qd-chip et-qd-chip-bordered\">Execute</button>\n <button (click)=\"query.execute({ skipCache: true })\" class=\"et-qd-chip et-qd-chip-bordered\">\n Execute (ignore cache)\n </button>\n\n <button (click)=\"query.abort()\" class=\"et-qd-chip et-qd-chip-bordered\">Abort</button>\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !query.isPolling }\"\n (click)=\"query.poll({ interval: 5000, takeUntil: _destroy$ })\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Poll\n </button>\n\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': query.isPolling }\"\n (click)=\"query.stopPolling()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Stop polling\n </button>\n @if (query.isPolling || query._isPollingPaused) {\n <button (click)=\"query.pausePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Pause polling\n </button>\n <button (click)=\"query.resumePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Resume polling\n </button>\n }\n </div>\n\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>State type</p>\n <pre>{{ query.rawState.type }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Dependents</p>\n <pre>{{ query._dependents | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is expired</p>\n <pre>{{ query.isExpired }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is in use</p>\n <pre>{{ query.isInUse }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Subscriber count</p>\n <pre>{{ query._subscriberCount }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling</p>\n <pre>{{ query.isPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling paused</p>\n <pre>{{ query._isPollingPaused }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Enable smart polling</p>\n <pre>{{ query._enableSmartPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query store key</p>\n <pre>{{ query._queryStoreKey }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Arguments</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showArguments() }\"\n (click)=\"toggleShowArguments()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showArguments()) {\n <pre>{{ query._arguments | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <p><i> Warning, this will cause a subscription if shown!</i></p>\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showResponse() }\"\n (click)=\"toggleShowResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showResponse()) {\n <pre>{{ query.state$ | async | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Raw state</p>\n <p><i> The query state unaffected by entity stores</i></p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showRawResponse() }\"\n (click)=\"toggleShowRawResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showRawResponse()) {\n <pre>{{ query.rawState | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query config</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showQueryConfig() }\"\n (click)=\"toggleShowQueryConfig()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showQueryConfig()) {\n <pre>{{ stringifiedQueryConfig() | json }}</pre>\n }\n </div>\n\n @if (!!query._queryConfig.entity) {\n <div class=\"et-qd-list-item\">\n <p>Entity store value</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showEntityStoreValue() }\"\n (click)=\"toggleShowEntityStoreValue()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showEntityStoreValue()) {\n <pre>{{ selectedQueryEntityStoreValue$ | async | json }}</pre>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n } @else if (viewMode() === 'authProvider') {\n <div class=\"et-qd-auth-provider__viewer\">\n @if (authProviderDetails(); as details) {\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>Type</p>\n <pre>{{ details.type }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Header value</p>\n <pre>{{ details.header() | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Config</p>\n <pre>{{ details.config | json }}</pre>\n </div>\n\n @if (details.type === 'BearerAuthProvider') {\n <div class=\"et-qd-list-item\">\n <p>Tokens</p>\n <pre>{{ details.provider.tokens$ | async | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Should refresh on unauthorized response</p>\n <pre>{{ details.provider.shouldRefreshOnUnauthorizedResponse }}</pre>\n </div>\n\n <ng-container\n *etQuery=\"\n details.provider.currentRefreshQuery$ | async as response;\n loading as loading;\n error as error;\n query as query\n \"\n >\n <div class=\"et-qd-list-item\">\n <p>Refresh query response</p>\n\n <div>\n <button (click)=\"details.provider._refreshQuery()\" class=\"et-qd-chip et-qd-chip-bordered\">\n Refresh\n </button>\n </div>\n <pre>{{ response | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query loading</p>\n <pre>{{ loading }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query error</p>\n <pre>{{ error ?? 'null' }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <pre>{{ query?.state$ | async | json }}</pre>\n </div>\n </ng-container>\n }\n </div>\n } @else {\n <p>No auth provider set</p>\n }\n </div>\n }\n </div>\n }\n </div>\n}\n", styles: [":host{position:fixed;top:0;z-index:1000000;font-size:14px;color:#fff}.et-query-devtools-container{position:fixed;inset:0;background-color:#25292e;z-index:10000;overflow:auto;font-family:monospace;display:grid;grid-template-rows:auto auto auto minmax(0,1fr)}.et-query-devtools-container.et-query-devtools-container--transparent{opacity:.25;pointer-events:none}.et-query-devtools-container.et-query-devtools-container--transparent .et-query-devtools-translucent-btn{pointer-events:all}.et-query-devtools-container.et-query-devtools-container--snap-left{inset-inline-start:0;inset-block-start:0;inset-block-end:0;width:50%;border-right:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-right{inset-inline-start:unset;inset-inline-end:0;inset-block-start:0;inset-block-end:0;width:50%;border-left:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-top{inset-inline-start:0;inset-block-start:0;inset-inline-end:0;height:50%;border-bottom:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-bottom{inset-inline-start:0;inset-block-start:unset;inset-block-end:0;inset-inline-end:0;height:50%;border-top:1px solid rgb(37,41,46)}button.et-query-devtools-open-btn{position:fixed;inset-inline-end:20px;inset-block-end:0;z-index:9999;font-family:monospace;border-radius:3px 3px 0 0;line-height:14px;font-size:12px}.et-qd-header{background-color:#00ffa1;padding:12px;display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center}.et-qd-header__title{color:#25292e;margin:0;font-size:22px}.et-qd-header__select{display:grid;background-color:#25292e;border-radius:10px;overflow:hidden}.et-qd-header__select select{width:250px;color:#fff;padding:3px 10px 2px;border:none;background-color:#25292e;font-family:monospace}.et-qd-header__select label{padding:3px 10px;color:#25292e;font-size:12px;font-weight:700;color:#fff;border-bottom:1px solid gray}.et-qd-sub-header{background-color:#00b371;padding:12px;display:flex;gap:12px;flex-wrap:wrap}.et-qd-sub-header__divider{width:1px;background-color:#25292e}.et-qd-btn{background-color:#00ffa1;color:#25292e;border:none;padding:12px;cursor:pointer;font-size:14px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;width:100%;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-btn:hover{background-color:#00cc81}.et-qd-btn.et-qd-btn-secondary{background-color:#25292e;color:#00ffa1}.et-qd-btn.et-qd-btn-secondary:hover{background-color:#3c424a}.et-qd-chip{background-color:#00ffa1;color:#25292e;border:none;padding:4px 9px;cursor:pointer;font-size:12px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-chip:hover{background-color:#00cc81}.et-qd-chip.et-qd-chip-secondary{background-color:#25292e;color:#00ffa1}.et-qd-chip.et-qd-chip-secondary:hover{background-color:#3c424a}.et-qd-chip.et-qd-chip-bordered{border:1px solid rgb(0,255,161)}.et-qd-translucent-clickable{pointer-events:all}.et-qd-client{border-bottom:1px solid rgb(59.734939759,66.1927710843,74.265060241);padding:12px}.et-qd-client__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-client__actions{display:flex;gap:12px;margin-top:12px}.et-qd-queries{padding:12px;display:grid;grid-template-rows:auto auto minmax(0,1fr)}.et-qd-queries__actions{display:flex;gap:12px;margin-top:12px;margin-bottom:16px}.et-qd-queries__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-queries__divider{width:1px;background-color:#3c424a}.et-qd-queries__browser{display:grid;grid-template-columns:1fr minmax(0,3fr);margin-left:-12px;margin-right:-12px;border-top:1px solid rgb(59.734939759,66.1927710843,74.265060241);margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid rgb(59.734939759,66.1927710843,74.265060241);list-style:none;padding:0;margin:0;display:grid;grid-auto-flow:row;grid-auto-rows:55px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-list li{margin:0}.et-qd-queries__browser-list li button{all:unset;font-family:monospace;box-sizing:border-box;width:100%;border:none;border-bottom:1px solid rgb(59.734939759,66.1927710843,74.265060241);background-color:#25292e;color:#fff;text-align:left;padding:12px;height:100%;transition:all .3s ease-in-out;cursor:pointer;display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px;display:block}.et-qd-queries__browser-list li button span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.et-qd-queries__browser-list li button span:first-of-type{font-weight:700}.et-qd-queries__browser-list li button:hover,.et-qd-queries__browser-list li button.et-qd-query--active{background-color:#30363c}.et-qd-queries__browser-detail{padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-detail__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-auth-provider__viewer{border-top:1px solid rgb(59.734939759,66.1927710843,74.265060241);margin-left:-12px;margin-right:-12px;margin-bottom:-12px;padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-list{display:grid;gap:12px}.et-qd-list-item{display:grid}.et-qd-list-item p{font-weight:700;margin:0;padding-bottom:8px}.et-qd-list-item p+p{margin-top:-8px}.et-qd-list-item div+pre{margin-top:8px}.et-qd-list-item pre{margin:0;padding:4px;background-color:#0e1012;border-radius:4px;max-height:450px;overflow:auto}\n"], dependencies: [{ kind: "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: "directive", type: QueryDirective, selector: "[etQuery]", inputs: ["etQuery", "etQueryCache"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "pipe", type: QueryShortNamePipe, name: "queryShortName" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom }); }
|
|
4823
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4824
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: QueryDevtoolsComponent, isStandalone: true, selector: "et-query-devtools", host: { classAttribute: "et-query-devtools" }, ngImport: i0, template: "@if (!isOpen()) {\n <button (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn et-qd-chip\">Query Devtools</button>\n}\n\n@if (isOpen()) {\n <div\n [class.et-query-devtools-container--transparent]=\"isTranslucent()\"\n class=\"et-query-devtools-container et-query-devtools-container--snap-{{ snapLayout() }}\"\n >\n <header class=\"et-qd-header\">\n <h3 class=\"et-qd-header__title\">Query Devtools</h3>\n\n <div class=\"et-qd-header__select\">\n <label for=\"et-query-client-instance\">Client instance</label>\n <select [formControl]=\"selectedClientIdCtrl\" id=\"et-query-client-instance\">\n @for (clientConfig of queryClientConfigs; track trackByClient(i, clientConfig); let i = $index) {\n <option [value]=\"i\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </option>\n }\n </select>\n </div>\n\n <button (click)=\"toggleOpen()\" class=\"et-qd-btn et-qd-btn-secondary\">Close</button>\n </header>\n\n <div class=\"et-qd-sub-header\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !isTranslucent() }\"\n (click)=\"toggleTranslucent()\"\n class=\"et-qd-chip et-qd-translucent-clickable\"\n >\n Translucent\n </button>\n <div class=\"et-qd-sub-header__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'full' }\"\n (click)=\"selectSnapLayout('full')\"\n class=\"et-qd-chip\"\n >\n Fullscreen\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'top' }\"\n (click)=\"selectSnapLayout('top')\"\n class=\"et-qd-chip\"\n >\n Top\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'bottom' }\"\n (click)=\"selectSnapLayout('bottom')\"\n class=\"et-qd-chip\"\n >\n Bottom\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'left' }\"\n (click)=\"selectSnapLayout('left')\"\n class=\"et-qd-chip\"\n >\n Left\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'right' }\"\n (click)=\"selectSnapLayout('right')\"\n class=\"et-qd-chip\"\n >\n Right\n </button>\n </div>\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-client\">\n <p class=\"et-qd-client__title\">{{ cfg.displayName ?? cfg.client.config.baseRoute }}</p>\n\n <div class=\"et-qd-client__actions\">\n <button (click)=\"cfg.client._store.refreshQueriesInUse()\" class=\"et-qd-chip\">Refresh all</button>\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true })\" class=\"et-qd-chip\">\n Refresh all (ignore caches)\n </button>\n <button\n (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true, purgeUnused: true })\"\n class=\"et-qd-chip\"\n >\n Refresh all (ignore caches & purge unused)\n </button>\n </div>\n </div>\n }\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-queries\">\n <p class=\"et-qd-queries__title\">Inspector</p>\n <div class=\"et-qd-queries__actions\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'live' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('live'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Live Queries ({{ queries()?.length ?? 0 }})\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'history' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('history'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Query History ({{ (queryHistory$ | async)?.length ?? 0 }}/50)\n </button>\n @if (queryListMode() === 'history' && viewMode() === 'query') {\n <div class=\"et-qd-queries__divider\"></div>\n <button (click)=\"clearQueryHistory()\" class=\"et-qd-chip et-qd-chip-bordered\">Clear history</button>\n }\n\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': viewMode() !== 'authProvider' }\"\n (click)=\"selectViewMode('authProvider')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Auth Provider\n </button>\n </div>\n\n @if (viewMode() === 'query') {\n <div class=\"et-qd-queries__browser\">\n @if (queryListMode() === 'live') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queries(); track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n @if (queryListMode() === 'history') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queryHistory$ | async; track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n <div class=\"et-qd-queries__browser-detail\">\n @if (selectedQuery(); as query) {\n <p class=\"et-qd-queries__browser-detail__title\">\n {{ query._queryConfig.method }} {{ query._routeWithParams }}\n </p>\n\n <div class=\"et-qd-queries__actions\">\n <button (click)=\"query.execute()\" class=\"et-qd-chip et-qd-chip-bordered\">Execute</button>\n <button (click)=\"query.execute({ skipCache: true })\" class=\"et-qd-chip et-qd-chip-bordered\">\n Execute (ignore cache)\n </button>\n\n <button (click)=\"query.abort()\" class=\"et-qd-chip et-qd-chip-bordered\">Abort</button>\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !query.isPolling }\"\n (click)=\"query.poll({ interval: 5000, takeUntil: _destroy$ })\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Poll\n </button>\n\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': query.isPolling }\"\n (click)=\"query.stopPolling()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Stop polling\n </button>\n @if (query.isPolling || query._isPollingPaused) {\n <button (click)=\"query.pausePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Pause polling\n </button>\n <button (click)=\"query.resumePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Resume polling\n </button>\n }\n </div>\n\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>State type</p>\n <pre>{{ query.rawState.type }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Dependents</p>\n <pre>{{ query._dependents | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is expired</p>\n <pre>{{ query.isExpired }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is in use</p>\n <pre>{{ query.isInUse }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Subscriber count</p>\n <pre>{{ query._subscriberCount }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling</p>\n <pre>{{ query.isPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling paused</p>\n <pre>{{ query._isPollingPaused }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Enable smart polling</p>\n <pre>{{ query._enableSmartPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query store key</p>\n <pre>{{ query._queryStoreKey }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Arguments</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showArguments() }\"\n (click)=\"toggleShowArguments()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showArguments()) {\n <pre>{{ query._arguments | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <p><i> Warning, this will cause a subscription if shown!</i></p>\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showResponse() }\"\n (click)=\"toggleShowResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showResponse()) {\n <pre>{{ query.state$ | async | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Raw state</p>\n <p><i> The query state unaffected by entity stores</i></p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showRawResponse() }\"\n (click)=\"toggleShowRawResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showRawResponse()) {\n <pre>{{ query.rawState | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query config</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showQueryConfig() }\"\n (click)=\"toggleShowQueryConfig()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showQueryConfig()) {\n <pre>{{ stringifiedQueryConfig() | json }}</pre>\n }\n </div>\n\n @if (!!query._queryConfig.entity) {\n <div class=\"et-qd-list-item\">\n <p>Entity store value</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showEntityStoreValue() }\"\n (click)=\"toggleShowEntityStoreValue()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showEntityStoreValue()) {\n <pre>{{ selectedQueryEntityStoreValue$ | async | json }}</pre>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n } @else if (viewMode() === 'authProvider') {\n <div class=\"et-qd-auth-provider__viewer\">\n @if (authProviderDetails(); as details) {\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>Type</p>\n <pre>{{ details.type }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Header value</p>\n <pre>{{ details.header() | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Config</p>\n <pre>{{ details.config | json }}</pre>\n </div>\n\n @if (details.type === 'BearerAuthProvider') {\n <div class=\"et-qd-list-item\">\n <p>Tokens</p>\n <pre>{{ details.provider.tokens$ | async | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Should refresh on unauthorized response</p>\n <pre>{{ details.provider.shouldRefreshOnUnauthorizedResponse }}</pre>\n </div>\n\n <ng-container\n *etQuery=\"\n details.provider.currentRefreshQuery$ | async as response;\n loading as loading;\n error as error;\n query as query\n \"\n >\n <div class=\"et-qd-list-item\">\n <p>Refresh query response</p>\n\n <div>\n <button (click)=\"details.provider._refreshQuery()\" class=\"et-qd-chip et-qd-chip-bordered\">\n Refresh\n </button>\n </div>\n <pre>{{ response | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query loading</p>\n <pre>{{ loading }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query error</p>\n <pre>{{ error ?? 'null' }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <pre>{{ query?.state$ | async | json }}</pre>\n </div>\n </ng-container>\n }\n </div>\n } @else {\n <p>No auth provider set</p>\n }\n </div>\n }\n </div>\n }\n </div>\n}\n", styles: [":host{position:fixed;top:0;z-index:1000000;font-size:14px;color:#fff}.et-query-devtools-container{position:fixed;inset:0;background-color:#25292e;z-index:10000;overflow:auto;font-family:monospace;display:grid;grid-template-rows:auto auto auto minmax(0,1fr)}.et-query-devtools-container.et-query-devtools-container--transparent{opacity:.25;pointer-events:none}.et-query-devtools-container.et-query-devtools-container--transparent .et-query-devtools-translucent-btn{pointer-events:all}.et-query-devtools-container.et-query-devtools-container--snap-left{inset-inline-start:0;inset-block-start:0;inset-block-end:0;width:50%;border-right:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-right{inset-inline-start:unset;inset-inline-end:0;inset-block-start:0;inset-block-end:0;width:50%;border-left:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-top{inset-inline-start:0;inset-block-start:0;inset-inline-end:0;height:50%;border-bottom:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-bottom{inset-inline-start:0;inset-block-start:unset;inset-block-end:0;inset-inline-end:0;height:50%;border-top:1px solid rgb(37,41,46)}button.et-query-devtools-open-btn{position:fixed;inset-inline-end:20px;inset-block-end:0;z-index:9999;font-family:monospace;border-radius:3px 3px 0 0;line-height:14px;font-size:12px}.et-qd-header{background-color:#00ffa1;padding:12px;display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center}.et-qd-header__title{color:#25292e;margin:0;font-size:22px}.et-qd-header__select{display:grid;background-color:#25292e;border-radius:10px;overflow:hidden}.et-qd-header__select select{width:250px;color:#fff;padding:3px 10px 2px;border:none;background-color:#25292e;font-family:monospace}.et-qd-header__select label{padding:3px 10px;color:#25292e;font-size:12px;font-weight:700;color:#fff;border-bottom:1px solid gray}.et-qd-sub-header{background-color:#00b371;padding:12px;display:flex;gap:12px;flex-wrap:wrap}.et-qd-sub-header__divider{width:1px;background-color:#25292e}.et-qd-btn{background-color:#00ffa1;color:#25292e;border:none;padding:12px;cursor:pointer;font-size:14px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;width:100%;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-btn:hover{background-color:#00cc81}.et-qd-btn.et-qd-btn-secondary{background-color:#25292e;color:#00ffa1}.et-qd-btn.et-qd-btn-secondary:hover{background-color:#3c424a}.et-qd-chip{background-color:#00ffa1;color:#25292e;border:none;padding:4px 9px;cursor:pointer;font-size:12px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-chip:hover{background-color:#00cc81}.et-qd-chip.et-qd-chip-secondary{background-color:#25292e;color:#00ffa1}.et-qd-chip.et-qd-chip-secondary:hover{background-color:#3c424a}.et-qd-chip.et-qd-chip-bordered{border:1px solid rgb(0,255,161)}.et-qd-translucent-clickable{pointer-events:all}.et-qd-client{border-bottom:1px solid rgb(59.734939759,66.1927710843,74.265060241);padding:12px}.et-qd-client__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-client__actions{display:flex;gap:12px;margin-top:12px}.et-qd-queries{padding:12px;display:grid;grid-template-rows:auto auto minmax(0,1fr)}.et-qd-queries__actions{display:flex;gap:12px;margin-top:12px;margin-bottom:16px}.et-qd-queries__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-queries__divider{width:1px;background-color:#3c424a}.et-qd-queries__browser{display:grid;grid-template-columns:1fr minmax(0,3fr);margin-left:-12px;margin-right:-12px;border-top:1px solid rgb(59.734939759,66.1927710843,74.265060241);margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid rgb(59.734939759,66.1927710843,74.265060241);list-style:none;padding:0;margin:0;display:grid;grid-auto-flow:row;grid-auto-rows:55px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-list li{margin:0}.et-qd-queries__browser-list li button{all:unset;font-family:monospace;box-sizing:border-box;width:100%;border:none;border-bottom:1px solid rgb(59.734939759,66.1927710843,74.265060241);background-color:#25292e;color:#fff;text-align:left;padding:12px;height:100%;transition:all .3s ease-in-out;cursor:pointer;display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px;display:block}.et-qd-queries__browser-list li button span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.et-qd-queries__browser-list li button span:first-of-type{font-weight:700}.et-qd-queries__browser-list li button:hover,.et-qd-queries__browser-list li button.et-qd-query--active{background-color:#30363c}.et-qd-queries__browser-detail{padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-detail__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-auth-provider__viewer{border-top:1px solid rgb(59.734939759,66.1927710843,74.265060241);margin-left:-12px;margin-right:-12px;margin-bottom:-12px;padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-list{display:grid;gap:12px}.et-qd-list-item{display:grid}.et-qd-list-item p{font-weight:700;margin:0;padding-bottom:8px}.et-qd-list-item p+p{margin-top:-8px}.et-qd-list-item div+pre{margin-top:8px}.et-qd-list-item pre{margin:0;padding:4px;background-color:#0e1012;border-radius:4px;max-height:450px;overflow:auto}\n"], dependencies: [{ kind: "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: "directive", type: QueryDirective, selector: "[etQuery]", inputs: ["etQuery", "etQueryCache"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "pipe", type: QueryShortNamePipe, name: "queryShortName" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom }); }
|
|
4791
4825
|
}
|
|
4792
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
4826
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
|
|
4793
4827
|
type: Component,
|
|
4794
4828
|
args: [{ selector: 'et-query-devtools', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, host: {
|
|
4795
4829
|
class: 'et-query-devtools',
|
|
@@ -5040,26 +5074,17 @@ const createQueryRepository = (config) => {
|
|
|
5040
5074
|
else {
|
|
5041
5075
|
const consumers = new Map([]);
|
|
5042
5076
|
consumers.set(consumerDestroyRef, destroyListener);
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
if (
|
|
5048
|
-
|
|
5049
|
-
type: 'request-error',
|
|
5050
|
-
|
|
5051
|
-
key,
|
|
5052
|
-
isSecure,
|
|
5053
|
-
request,
|
|
5054
|
-
});
|
|
5077
|
+
// Drive repository events off the request's discrete, terminal event stream rather than
|
|
5078
|
+
// recombining the `error` + `response` signals via combineLatest (which could observe stale
|
|
5079
|
+
// pairings). Each settle emits exactly one terminal event.
|
|
5080
|
+
const eventSubscription = request.events$.subscribe((event) => {
|
|
5081
|
+
if (event.type === 'error') {
|
|
5082
|
+
if (event.error.raw instanceof HttpErrorResponse) {
|
|
5083
|
+
eventsSubject.next({ type: 'request-error', error: event.error.raw, key, isSecure, request });
|
|
5084
|
+
}
|
|
5055
5085
|
}
|
|
5056
|
-
else if (
|
|
5057
|
-
eventsSubject.next({
|
|
5058
|
-
type: 'request-success',
|
|
5059
|
-
key,
|
|
5060
|
-
isSecure,
|
|
5061
|
-
request,
|
|
5062
|
-
});
|
|
5086
|
+
else if (event.type === HttpEventType.Response) {
|
|
5087
|
+
eventsSubject.next({ type: 'request-success', key, isSecure, request });
|
|
5063
5088
|
}
|
|
5064
5089
|
});
|
|
5065
5090
|
cache.set(key, {
|
|
@@ -5164,7 +5189,10 @@ const setupLeaderElection = () => {
|
|
|
5164
5189
|
const leaderTimeout = 3000;
|
|
5165
5190
|
const storageKey = 'ethlete-auth-leader-heartbeat';
|
|
5166
5191
|
const tabId = `tab-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
5167
|
-
const isLeader = signal(false, ...(ngDevMode ? [{ debugName: "isLeader" }] : []));
|
|
5192
|
+
const isLeader = signal(false, ...(ngDevMode ? [{ debugName: "isLeader" }] : /* istanbul ignore next */ []));
|
|
5193
|
+
const instanceCount = signal(1, ...(ngDevMode ? [{ debugName: "instanceCount" }] : /* istanbul ignore next */ []));
|
|
5194
|
+
const knownTabs = new Map();
|
|
5195
|
+
knownTabs.set(tabId, Date.now());
|
|
5168
5196
|
let channel = null;
|
|
5169
5197
|
let heartbeatIntervalId = null;
|
|
5170
5198
|
let leaderCheckIntervalId = null;
|
|
@@ -5172,6 +5200,7 @@ const setupLeaderElection = () => {
|
|
|
5172
5200
|
isLeader.set(true);
|
|
5173
5201
|
return {
|
|
5174
5202
|
isLeader: isLeader.asReadonly(),
|
|
5203
|
+
instanceCount: instanceCount.asReadonly(),
|
|
5175
5204
|
becomeLeader: () => {
|
|
5176
5205
|
/* no-op */
|
|
5177
5206
|
},
|
|
@@ -5181,6 +5210,7 @@ const setupLeaderElection = () => {
|
|
|
5181
5210
|
};
|
|
5182
5211
|
}
|
|
5183
5212
|
channel = new BroadcastChannel(channelName);
|
|
5213
|
+
channel.postMessage({ type: 'instance-register', tabId });
|
|
5184
5214
|
const updateLeaderHeartbeat = (newTabId = tabId) => {
|
|
5185
5215
|
try {
|
|
5186
5216
|
localStorage.setItem(storageKey, JSON.stringify({ tabId: newTabId, timestamp: Date.now() }));
|
|
@@ -5227,48 +5257,60 @@ const setupLeaderElection = () => {
|
|
|
5227
5257
|
const heartbeat = getLeaderHeartbeat();
|
|
5228
5258
|
const now = Date.now();
|
|
5229
5259
|
if (!heartbeat || now - heartbeat.timestamp > leaderTimeout) {
|
|
5230
|
-
// No leader or leader is dead
|
|
5231
5260
|
if (!isLeader()) {
|
|
5232
5261
|
becomeLeader();
|
|
5233
5262
|
}
|
|
5234
5263
|
}
|
|
5235
5264
|
else if (heartbeat.tabId === tabId) {
|
|
5236
|
-
// We are the leader, update heartbeat
|
|
5237
5265
|
if (!isLeader()) {
|
|
5238
5266
|
isLeader.set(true);
|
|
5239
5267
|
}
|
|
5240
5268
|
updateLeaderHeartbeat();
|
|
5241
5269
|
}
|
|
5242
5270
|
else {
|
|
5243
|
-
// Another tab is leader
|
|
5244
5271
|
if (isLeader()) {
|
|
5245
5272
|
isLeader.set(false);
|
|
5246
5273
|
}
|
|
5247
5274
|
}
|
|
5248
5275
|
};
|
|
5249
|
-
// Handle messages from other tabs
|
|
5250
5276
|
channel.onmessage = (event) => {
|
|
5251
5277
|
const message = event.data;
|
|
5252
5278
|
if (message.type === 'heartbeat') {
|
|
5279
|
+
if (message.tabId !== tabId) {
|
|
5280
|
+
knownTabs.set(message.tabId, Date.now());
|
|
5281
|
+
}
|
|
5253
5282
|
if (message.tabId !== tabId && isLeader()) {
|
|
5254
|
-
// Another tab claims to be leader, resolve conflict
|
|
5255
5283
|
const heartbeat = getLeaderHeartbeat();
|
|
5256
5284
|
if (heartbeat && heartbeat.tabId === message.tabId) {
|
|
5257
|
-
// Other tab is legitimate leader
|
|
5258
5285
|
releaseLeadership();
|
|
5259
5286
|
}
|
|
5260
5287
|
}
|
|
5261
5288
|
}
|
|
5289
|
+
else if (message.type === 'tab-heartbeat') {
|
|
5290
|
+
if (message.tabId !== tabId) {
|
|
5291
|
+
knownTabs.set(message.tabId, Date.now());
|
|
5292
|
+
}
|
|
5293
|
+
}
|
|
5294
|
+
else if (message.type === 'instance-register') {
|
|
5295
|
+
if (message.tabId !== tabId) {
|
|
5296
|
+
knownTabs.set(message.tabId, Date.now());
|
|
5297
|
+
instanceCount.set(knownTabs.size);
|
|
5298
|
+
channel?.postMessage({ type: 'tab-heartbeat', tabId });
|
|
5299
|
+
}
|
|
5300
|
+
}
|
|
5301
|
+
else if (message.type === 'instance-unregister') {
|
|
5302
|
+
if (message.tabId !== tabId) {
|
|
5303
|
+
knownTabs.delete(message.tabId);
|
|
5304
|
+
instanceCount.set(knownTabs.size);
|
|
5305
|
+
}
|
|
5306
|
+
}
|
|
5262
5307
|
else if (message.type === 'leader-claim') {
|
|
5263
5308
|
if (message.tabId !== tabId && isLeader()) {
|
|
5264
|
-
// Conflict: both tabs think they're leader
|
|
5265
|
-
// Let the tab with earlier heartbeat win
|
|
5266
5309
|
const heartbeat = getLeaderHeartbeat();
|
|
5267
5310
|
if (heartbeat && heartbeat.tabId === message.tabId) {
|
|
5268
5311
|
releaseLeadership();
|
|
5269
5312
|
}
|
|
5270
5313
|
else {
|
|
5271
|
-
// We were leader first, send heartbeat to assert dominance
|
|
5272
5314
|
const assertMessage = {
|
|
5273
5315
|
type: 'heartbeat',
|
|
5274
5316
|
tabId,
|
|
@@ -5279,35 +5321,40 @@ const setupLeaderElection = () => {
|
|
|
5279
5321
|
}
|
|
5280
5322
|
else if (message.type === 'leader-release') {
|
|
5281
5323
|
if (message.tabId !== tabId) {
|
|
5282
|
-
// Leader released, try to become new leader
|
|
5283
5324
|
setTimeout(() => checkLeaderStatus(), 100);
|
|
5284
5325
|
}
|
|
5285
5326
|
}
|
|
5286
5327
|
};
|
|
5287
|
-
// Try to become leader on startup
|
|
5288
5328
|
checkLeaderStatus();
|
|
5289
|
-
// Send heartbeat periodically if we're the leader
|
|
5290
5329
|
heartbeatIntervalId = setInterval(() => {
|
|
5330
|
+
knownTabs.set(tabId, Date.now());
|
|
5291
5331
|
if (isLeader()) {
|
|
5292
5332
|
updateLeaderHeartbeat();
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
};
|
|
5297
|
-
|
|
5333
|
+
channel?.postMessage({ type: 'heartbeat', tabId });
|
|
5334
|
+
}
|
|
5335
|
+
else {
|
|
5336
|
+
channel?.postMessage({ type: 'tab-heartbeat', tabId });
|
|
5337
|
+
}
|
|
5338
|
+
const now = Date.now();
|
|
5339
|
+
let changed = false;
|
|
5340
|
+
for (const [id, lastSeen] of knownTabs) {
|
|
5341
|
+
if (id !== tabId && now - lastSeen > leaderTimeout) {
|
|
5342
|
+
knownTabs.delete(id);
|
|
5343
|
+
changed = true;
|
|
5344
|
+
}
|
|
5345
|
+
}
|
|
5346
|
+
if (changed) {
|
|
5347
|
+
instanceCount.set(knownTabs.size);
|
|
5298
5348
|
}
|
|
5299
5349
|
}, heartbeatInterval);
|
|
5300
|
-
// Check leader status periodically
|
|
5301
5350
|
leaderCheckIntervalId = setInterval(() => {
|
|
5302
5351
|
checkLeaderStatus();
|
|
5303
5352
|
}, heartbeatInterval);
|
|
5304
|
-
// Handle tab visibility changes
|
|
5305
5353
|
const handleVisibilityChange = () => {
|
|
5306
5354
|
if (document.hidden && isLeader()) {
|
|
5307
5355
|
// Tab is hidden but we're leader - keep leadership but other tabs will take over if we die
|
|
5308
5356
|
}
|
|
5309
5357
|
else if (!document.hidden && !isLeader()) {
|
|
5310
|
-
// Tab became visible and we're not leader - check if we should become leader
|
|
5311
5358
|
checkLeaderStatus();
|
|
5312
5359
|
}
|
|
5313
5360
|
};
|
|
@@ -5319,10 +5366,10 @@ const setupLeaderElection = () => {
|
|
|
5319
5366
|
if (leaderCheckIntervalId) {
|
|
5320
5367
|
clearInterval(leaderCheckIntervalId);
|
|
5321
5368
|
}
|
|
5369
|
+
channel?.postMessage({ type: 'instance-unregister', tabId });
|
|
5322
5370
|
releaseLeadership();
|
|
5323
5371
|
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
5324
5372
|
channel?.close();
|
|
5325
|
-
// Clean up storage if we were the leader
|
|
5326
5373
|
const heartbeat = getLeaderHeartbeat();
|
|
5327
5374
|
if (heartbeat?.tabId === tabId) {
|
|
5328
5375
|
try {
|
|
@@ -5336,6 +5383,7 @@ const setupLeaderElection = () => {
|
|
|
5336
5383
|
destroyRef.onDestroy(cleanup);
|
|
5337
5384
|
return {
|
|
5338
5385
|
isLeader: isLeader.asReadonly(),
|
|
5386
|
+
instanceCount: instanceCount.asReadonly(),
|
|
5339
5387
|
becomeLeader,
|
|
5340
5388
|
cleanup,
|
|
5341
5389
|
};
|
|
@@ -5516,11 +5564,20 @@ const defaultExtractTokens = (response) => {
|
|
|
5516
5564
|
}
|
|
5517
5565
|
return { accessToken: response['accessToken'], refreshToken: response['refreshToken'] };
|
|
5518
5566
|
};
|
|
5519
|
-
const
|
|
5567
|
+
const deriveExecutionStateType = (builder, triggeredBy) => {
|
|
5568
|
+
if (triggeredBy === 'persistent-auth')
|
|
5569
|
+
return 'autoLogin';
|
|
5570
|
+
if (builder._type === 'tokenRefreshQuery')
|
|
5571
|
+
return 'tokenRefresh';
|
|
5572
|
+
if (triggeredBy === 'token-revocation')
|
|
5573
|
+
return 'revocation';
|
|
5574
|
+
return builder.key;
|
|
5575
|
+
};
|
|
5576
|
+
const setupBearerQueryRegistry = (builders, injector, latestExecutedQuery, latestNonInternalQuery, setTokens, executionState) => {
|
|
5520
5577
|
const queries = {};
|
|
5521
5578
|
const querySnapshots = new Map();
|
|
5522
5579
|
for (const builder of builders) {
|
|
5523
|
-
const querySnapshot = signal(null, ...(ngDevMode ? [{ debugName: "querySnapshot" }] : []));
|
|
5580
|
+
const querySnapshot = signal(null, ...(ngDevMode ? [{ debugName: "querySnapshot" }] : /* istanbul ignore next */ []));
|
|
5524
5581
|
querySnapshots.set(builder.key, querySnapshot);
|
|
5525
5582
|
const extractTokens = builder.config.extractTokens ?? defaultExtractTokens;
|
|
5526
5583
|
effect(() => {
|
|
@@ -5549,10 +5606,27 @@ const setupBearerQueryRegistry = (builders, injector, latestExecutedQuery, lates
|
|
|
5549
5606
|
});
|
|
5550
5607
|
query.execute({ args, options });
|
|
5551
5608
|
const snapshot = query.createSnapshot();
|
|
5552
|
-
|
|
5553
|
-
if (
|
|
5554
|
-
|
|
5609
|
+
const stateType = deriveExecutionStateType(builder, options?.triggeredBy);
|
|
5610
|
+
if (stateType !== 'revocation') {
|
|
5611
|
+
latestExecutedQuery.set({ key: builder.key, snapshot });
|
|
5612
|
+
if (!snapshot.triggeredBy()) {
|
|
5613
|
+
latestNonInternalQuery.set({ key: builder.key, snapshot });
|
|
5614
|
+
}
|
|
5555
5615
|
}
|
|
5616
|
+
executionState.set({ type: stateType, state: 'loading' });
|
|
5617
|
+
effect(() => {
|
|
5618
|
+
const response = snapshot.response();
|
|
5619
|
+
const loading = snapshot.loading();
|
|
5620
|
+
const error = snapshot.error();
|
|
5621
|
+
if (loading)
|
|
5622
|
+
return;
|
|
5623
|
+
if (error) {
|
|
5624
|
+
executionState.set({ type: stateType, state: 'error', error });
|
|
5625
|
+
}
|
|
5626
|
+
else if (response) {
|
|
5627
|
+
executionState.set({ type: stateType, state: 'success', response });
|
|
5628
|
+
}
|
|
5629
|
+
}, { injector });
|
|
5556
5630
|
querySnapshot.set(snapshot);
|
|
5557
5631
|
return snapshot;
|
|
5558
5632
|
};
|
|
@@ -5602,13 +5676,18 @@ const createLeaderElection = (config) => {
|
|
|
5602
5676
|
const leaderElectionEnabled = multiTabSyncEnabled &&
|
|
5603
5677
|
(typeof multiTabSyncConfig === 'object' ? (multiTabSyncConfig?.leaderElection ?? true) : true);
|
|
5604
5678
|
const leaderElection = leaderElectionEnabled ? setupLeaderElection() : null;
|
|
5605
|
-
|
|
5679
|
+
const isLeaderFn = () => (leaderElectionEnabled ? (leaderElection?.isLeader() ?? true) : true);
|
|
5680
|
+
const leaderElectionContext = leaderElection
|
|
5681
|
+
? { isLeader: leaderElection.isLeader, instanceCount: leaderElection.instanceCount }
|
|
5682
|
+
: undefined;
|
|
5683
|
+
return { isLeaderFn, leaderElectionContext };
|
|
5606
5684
|
};
|
|
5607
5685
|
const createBearerAuthProviderImpl = (config) => {
|
|
5608
5686
|
const injector = inject(Injector);
|
|
5687
|
+
const destroyRef = inject(DestroyRef);
|
|
5609
5688
|
const queryClient = config.queryClientRef[1]();
|
|
5610
|
-
const accessToken = signal(null, ...(ngDevMode ? [{ debugName: "accessToken" }] : []));
|
|
5611
|
-
const refreshToken = signal(null, ...(ngDevMode ? [{ debugName: "refreshToken" }] : []));
|
|
5689
|
+
const accessToken = signal(null, ...(ngDevMode ? [{ debugName: "accessToken" }] : /* istanbul ignore next */ []));
|
|
5690
|
+
const refreshToken = signal(null, ...(ngDevMode ? [{ debugName: "refreshToken" }] : /* istanbul ignore next */ []));
|
|
5612
5691
|
const afterTokenRefresh$ = new Subject();
|
|
5613
5692
|
const bearerData = computed(() => {
|
|
5614
5693
|
const token = accessToken();
|
|
@@ -5623,20 +5702,24 @@ const createBearerAuthProviderImpl = (config) => {
|
|
|
5623
5702
|
}
|
|
5624
5703
|
return null;
|
|
5625
5704
|
}
|
|
5626
|
-
}, ...(ngDevMode ? [{ debugName: "bearerData" }] : []));
|
|
5627
|
-
const isAuthenticated = computed(() => !!accessToken(), ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : []));
|
|
5628
|
-
const latestExecutedQuery = signal(null, ...(ngDevMode ? [{ debugName: "latestExecutedQuery" }] : []));
|
|
5629
|
-
const latestNonInternalQuery = signal(null, ...(ngDevMode ? [{ debugName: "latestNonInternalQuery" }] : []));
|
|
5705
|
+
}, ...(ngDevMode ? [{ debugName: "bearerData" }] : /* istanbul ignore next */ []));
|
|
5706
|
+
const isAuthenticated = computed(() => !!accessToken(), ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : /* istanbul ignore next */ []));
|
|
5707
|
+
const latestExecutedQuery = signal(null, ...(ngDevMode ? [{ debugName: "latestExecutedQuery" }] : /* istanbul ignore next */ []));
|
|
5708
|
+
const latestNonInternalQuery = signal(null, ...(ngDevMode ? [{ debugName: "latestNonInternalQuery" }] : /* istanbul ignore next */ []));
|
|
5709
|
+
const executionState = signal(null, ...(ngDevMode ? [{ debugName: "executionState" }] : /* istanbul ignore next */ []));
|
|
5630
5710
|
const setTokens = (access, refresh) => {
|
|
5631
5711
|
accessToken.set(access);
|
|
5632
5712
|
refreshToken.set(refresh);
|
|
5633
5713
|
afterTokenRefresh$.next();
|
|
5634
5714
|
};
|
|
5635
|
-
const { queries } = setupBearerQueryRegistry(config.queries, injector, latestExecutedQuery, latestNonInternalQuery, setTokens);
|
|
5715
|
+
const { queries } = setupBearerQueryRegistry(config.queries, injector, latestExecutedQuery, latestNonInternalQuery, setTokens, executionState);
|
|
5636
5716
|
const logout = () => {
|
|
5637
5717
|
accessToken.set(null);
|
|
5638
5718
|
refreshToken.set(null);
|
|
5639
5719
|
queryClient.repository.unbindAllSecure();
|
|
5720
|
+
latestExecutedQuery.set(null);
|
|
5721
|
+
latestNonInternalQuery.set(null);
|
|
5722
|
+
executionState.set({ type: 'logout', state: 'success' });
|
|
5640
5723
|
};
|
|
5641
5724
|
const isLeader = createLeaderElection(config);
|
|
5642
5725
|
const querySetupContext = {
|
|
@@ -5645,7 +5728,7 @@ const createBearerAuthProviderImpl = (config) => {
|
|
|
5645
5728
|
bearerDecryptFn: config.bearerDecryptFn,
|
|
5646
5729
|
queryClient,
|
|
5647
5730
|
repository: queryClient.repository,
|
|
5648
|
-
isLeader,
|
|
5731
|
+
isLeader: isLeader.isLeaderFn,
|
|
5649
5732
|
afterTokenRefresh$,
|
|
5650
5733
|
queries: queries,
|
|
5651
5734
|
};
|
|
@@ -5658,10 +5741,13 @@ const createBearerAuthProviderImpl = (config) => {
|
|
|
5658
5741
|
bearerData,
|
|
5659
5742
|
logout,
|
|
5660
5743
|
injector,
|
|
5744
|
+
destroyRef,
|
|
5661
5745
|
setTokens,
|
|
5662
|
-
isLeader,
|
|
5746
|
+
isLeader: isLeader.isLeaderFn,
|
|
5747
|
+
leaderElection: isLeader.leaderElectionContext,
|
|
5663
5748
|
afterTokenRefresh$,
|
|
5664
5749
|
queries: queries,
|
|
5750
|
+
executionState,
|
|
5665
5751
|
};
|
|
5666
5752
|
const features = setupFeatures(config.features, featureSetupContext);
|
|
5667
5753
|
setupMultiTabSyncIfEnabled(config, accessToken, refreshToken, queryClient);
|
|
@@ -5674,6 +5760,7 @@ const createBearerAuthProviderImpl = (config) => {
|
|
|
5674
5760
|
isAuthenticated,
|
|
5675
5761
|
latestExecutedQuery: latestExecutedQuery.asReadonly(),
|
|
5676
5762
|
latestNonInternalQuery: latestNonInternalQuery.asReadonly(),
|
|
5763
|
+
executionState: executionState.asReadonly(),
|
|
5677
5764
|
logout,
|
|
5678
5765
|
afterTokenRefresh$,
|
|
5679
5766
|
};
|
|
@@ -5823,8 +5910,8 @@ const withInactivityLogout = (config = {}) => {
|
|
|
5823
5910
|
const activityEvents = config.activityEvents ?? ['mousedown', 'keydown', 'scroll', 'touchstart'];
|
|
5824
5911
|
const destroyRef = inject(DestroyRef);
|
|
5825
5912
|
const document = inject(DOCUMENT);
|
|
5826
|
-
const enabled = signal(true, ...(ngDevMode ? [{ debugName: "enabled" }] : []));
|
|
5827
|
-
const lastActivityTime = signal(Date.now(), ...(ngDevMode ? [{ debugName: "lastActivityTime" }] : []));
|
|
5913
|
+
const enabled = signal(true, ...(ngDevMode ? [{ debugName: "enabled" }] : /* istanbul ignore next */ []));
|
|
5914
|
+
const lastActivityTime = signal(Date.now(), ...(ngDevMode ? [{ debugName: "lastActivityTime" }] : /* istanbul ignore next */ []));
|
|
5828
5915
|
const resetTimer = () => {
|
|
5829
5916
|
lastActivityTime.set(Date.now());
|
|
5830
5917
|
};
|
|
@@ -5907,7 +5994,7 @@ const createPersistentAuthFeature = (config, context) => {
|
|
|
5907
5994
|
}
|
|
5908
5995
|
return config.defaultRememberMe ?? false;
|
|
5909
5996
|
};
|
|
5910
|
-
const rememberMeSignal = signal(initializeRememberMe(), ...(ngDevMode ? [{ debugName: "rememberMeSignal" }] : []));
|
|
5997
|
+
const rememberMeSignal = signal(initializeRememberMe(), ...(ngDevMode ? [{ debugName: "rememberMeSignal" }] : /* istanbul ignore next */ []));
|
|
5911
5998
|
effect(() => {
|
|
5912
5999
|
const token = refreshToken();
|
|
5913
6000
|
const rememberMe = rememberMeSignal();
|
|
@@ -5968,7 +6055,7 @@ const withTokenExpirationWarning = (config = {}) => {
|
|
|
5968
6055
|
if (typeof exp !== 'number')
|
|
5969
6056
|
return null;
|
|
5970
6057
|
return new Date(exp * 1000);
|
|
5971
|
-
}, ...(ngDevMode ? [{ debugName: "expiresAt" }] : []));
|
|
6058
|
+
}, ...(ngDevMode ? [{ debugName: "expiresAt" }] : /* istanbul ignore next */ []));
|
|
5972
6059
|
const expiresIn$ = combineLatest([interval(checkInterval), toObservable(context.bearerData)]).pipe(map(() => {
|
|
5973
6060
|
const expiry = expiresAt();
|
|
5974
6061
|
if (!expiry)
|
|
@@ -5999,23 +6086,26 @@ const withTokenExpirationWarning = (config = {}) => {
|
|
|
5999
6086
|
const withTokenRevocation = (config) => {
|
|
6000
6087
|
return (context) => {
|
|
6001
6088
|
const revokeOnLogout = config.revokeOnLogout ?? true;
|
|
6002
|
-
const enabled = signal(true, ...(ngDevMode ? [{ debugName: "enabled" }] : []));
|
|
6089
|
+
const enabled = signal(true, ...(ngDevMode ? [{ debugName: "enabled" }] : /* istanbul ignore next */ []));
|
|
6003
6090
|
let previousAccessToken = null;
|
|
6091
|
+
let previousRefreshToken = null;
|
|
6004
6092
|
let currentRevocationSnapshot = null;
|
|
6005
|
-
const
|
|
6093
|
+
const revokeWithTokens = (accessToken, refreshToken) => {
|
|
6006
6094
|
if (currentRevocationSnapshot?.isAlive())
|
|
6007
6095
|
return currentRevocationSnapshot;
|
|
6008
|
-
const accessToken = context.accessToken();
|
|
6009
|
-
const refreshToken = context.refreshToken();
|
|
6010
6096
|
if (!accessToken && !refreshToken) {
|
|
6011
6097
|
return null;
|
|
6012
6098
|
}
|
|
6013
6099
|
const args = config.buildArgs({ accessToken, refreshToken });
|
|
6100
|
+
context.executionState.set({ type: 'revocation', state: 'loading' });
|
|
6014
6101
|
currentRevocationSnapshot = context.queries[config.queryKey].execute(args, {
|
|
6015
6102
|
triggeredBy: 'token-revocation',
|
|
6016
6103
|
});
|
|
6017
6104
|
return currentRevocationSnapshot;
|
|
6018
6105
|
};
|
|
6106
|
+
const revoke = () => {
|
|
6107
|
+
return revokeWithTokens(context.accessToken(), context.refreshToken());
|
|
6108
|
+
};
|
|
6019
6109
|
const enable = () => {
|
|
6020
6110
|
enabled.set(true);
|
|
6021
6111
|
};
|
|
@@ -6025,10 +6115,12 @@ const withTokenRevocation = (config) => {
|
|
|
6025
6115
|
if (revokeOnLogout) {
|
|
6026
6116
|
effect(() => {
|
|
6027
6117
|
const currentToken = context.accessToken();
|
|
6118
|
+
const currentRefreshToken = context.refreshToken();
|
|
6028
6119
|
if (previousAccessToken && !currentToken && enabled()) {
|
|
6029
|
-
untracked(() =>
|
|
6120
|
+
untracked(() => revokeWithTokens(previousAccessToken, previousRefreshToken));
|
|
6030
6121
|
}
|
|
6031
6122
|
previousAccessToken = currentToken;
|
|
6123
|
+
previousRefreshToken = currentRefreshToken;
|
|
6032
6124
|
}, { injector: context.injector });
|
|
6033
6125
|
}
|
|
6034
6126
|
const instance = {
|
|
@@ -6074,7 +6166,7 @@ const createTrackingFeature = (context, config) => {
|
|
|
6074
6166
|
}
|
|
6075
6167
|
}
|
|
6076
6168
|
};
|
|
6077
|
-
const
|
|
6169
|
+
const fireHandlers = (event, data) => {
|
|
6078
6170
|
const eventHandlers = handlers.get(event);
|
|
6079
6171
|
if (eventHandlers) {
|
|
6080
6172
|
eventHandlers.forEach((handler) => {
|
|
@@ -6087,6 +6179,27 @@ const createTrackingFeature = (context, config) => {
|
|
|
6087
6179
|
});
|
|
6088
6180
|
}
|
|
6089
6181
|
};
|
|
6182
|
+
const forwardingChannel = context.leaderElection && typeof BroadcastChannel !== 'undefined'
|
|
6183
|
+
? new BroadcastChannel('ethlete-auth-tracking')
|
|
6184
|
+
: null;
|
|
6185
|
+
if (forwardingChannel) {
|
|
6186
|
+
forwardingChannel.onmessage = (messageEvent) => {
|
|
6187
|
+
if (context.isLeader()) {
|
|
6188
|
+
fireHandlers(messageEvent.data.event, messageEvent.data.data);
|
|
6189
|
+
}
|
|
6190
|
+
};
|
|
6191
|
+
context.destroyRef.onDestroy(() => forwardingChannel.close());
|
|
6192
|
+
}
|
|
6193
|
+
const emit = (event, data) => {
|
|
6194
|
+
if (forwardingChannel && !context.isLeader()) {
|
|
6195
|
+
forwardingChannel.postMessage({ event, data });
|
|
6196
|
+
return;
|
|
6197
|
+
}
|
|
6198
|
+
fireHandlers(event, data);
|
|
6199
|
+
};
|
|
6200
|
+
const emitDirect = (event, data) => {
|
|
6201
|
+
fireHandlers(event, data);
|
|
6202
|
+
};
|
|
6090
6203
|
const trackedQueries = new Map();
|
|
6091
6204
|
Object.entries(context.queries).forEach(([key, queryEntry]) => {
|
|
6092
6205
|
const query = queryEntry; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
@@ -6103,17 +6216,11 @@ const createTrackingFeature = (context, config) => {
|
|
|
6103
6216
|
const prevState = trackedQueries.get(key);
|
|
6104
6217
|
if (response && !loading && !error && prevState?.lastResult !== 'success') {
|
|
6105
6218
|
trackedQueries.set(key, { loading: false, lastResult: 'success' });
|
|
6106
|
-
emit(`${key}Success`, {
|
|
6107
|
-
queryKey: key,
|
|
6108
|
-
snapshot,
|
|
6109
|
-
});
|
|
6219
|
+
emit(`${key}Success`, { snapshot });
|
|
6110
6220
|
}
|
|
6111
6221
|
if (error && !loading && prevState?.lastResult !== 'error') {
|
|
6112
6222
|
trackedQueries.set(key, { loading: false, lastResult: 'error' });
|
|
6113
|
-
emit(`${key}Failure`, {
|
|
6114
|
-
queryKey: key,
|
|
6115
|
-
error,
|
|
6116
|
-
});
|
|
6223
|
+
emit(`${key}Failure`, { error });
|
|
6117
6224
|
}
|
|
6118
6225
|
if (loading) {
|
|
6119
6226
|
trackedQueries.set(key, { loading: true, lastResult: null });
|
|
@@ -6143,6 +6250,17 @@ const createTrackingFeature = (context, config) => {
|
|
|
6143
6250
|
}
|
|
6144
6251
|
});
|
|
6145
6252
|
}
|
|
6253
|
+
if (context.leaderElection) {
|
|
6254
|
+
const { isLeader: isLeaderSignal, instanceCount: instanceCountSignal } = context.leaderElection;
|
|
6255
|
+
effect(() => {
|
|
6256
|
+
emitDirect('leaderStatusChange', { isLeader: isLeaderSignal() });
|
|
6257
|
+
});
|
|
6258
|
+
effect(() => {
|
|
6259
|
+
emitDirect('leaderInstanceCountChange', {
|
|
6260
|
+
count: instanceCountSignal(),
|
|
6261
|
+
});
|
|
6262
|
+
});
|
|
6263
|
+
}
|
|
6146
6264
|
return {
|
|
6147
6265
|
on,
|
|
6148
6266
|
off,
|
|
@@ -6326,10 +6444,10 @@ class ParseHttpErrorCodeToTitleDePipe {
|
|
|
6326
6444
|
constructor() {
|
|
6327
6445
|
this.transform = parseHttpErrorCodeToTitleDe;
|
|
6328
6446
|
}
|
|
6329
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6330
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.
|
|
6447
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToTitleDePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
6448
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToTitleDePipe, isStandalone: true, name: "parseHttpErrorCodeToTitleDe" }); }
|
|
6331
6449
|
}
|
|
6332
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6450
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToTitleDePipe, decorators: [{
|
|
6333
6451
|
type: Pipe,
|
|
6334
6452
|
args: [{
|
|
6335
6453
|
name: 'parseHttpErrorCodeToTitleDe',
|
|
@@ -6339,10 +6457,10 @@ class ParseHttpErrorCodeToMessageDePipe {
|
|
|
6339
6457
|
constructor() {
|
|
6340
6458
|
this.transform = parseHttpErrorCodeToMessageDe;
|
|
6341
6459
|
}
|
|
6342
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6343
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.
|
|
6460
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToMessageDePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
6461
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToMessageDePipe, isStandalone: true, name: "parseHttpErrorCodeToMessageDe" }); }
|
|
6344
6462
|
}
|
|
6345
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6463
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToMessageDePipe, decorators: [{
|
|
6346
6464
|
type: Pipe,
|
|
6347
6465
|
args: [{
|
|
6348
6466
|
name: 'parseHttpErrorCodeToMessageDe',
|
|
@@ -6526,10 +6644,10 @@ class ParseHttpErrorCodeToTitleEnPipe {
|
|
|
6526
6644
|
constructor() {
|
|
6527
6645
|
this.transform = parseHttpErrorCodeToTitleEn;
|
|
6528
6646
|
}
|
|
6529
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6530
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.
|
|
6647
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToTitleEnPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
6648
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToTitleEnPipe, isStandalone: true, name: "parseHttpErrorCodeToTitleEn" }); }
|
|
6531
6649
|
}
|
|
6532
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6650
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToTitleEnPipe, decorators: [{
|
|
6533
6651
|
type: Pipe,
|
|
6534
6652
|
args: [{
|
|
6535
6653
|
name: 'parseHttpErrorCodeToTitleEn',
|
|
@@ -6539,10 +6657,10 @@ class ParseHttpErrorCodeToMessageEnPipe {
|
|
|
6539
6657
|
constructor() {
|
|
6540
6658
|
this.transform = parseHttpErrorCodeToMessageEn;
|
|
6541
6659
|
}
|
|
6542
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6543
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.
|
|
6660
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToMessageEnPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
6661
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToMessageEnPipe, isStandalone: true, name: "parseHttpErrorCodeToMessageEn" }); }
|
|
6544
6662
|
}
|
|
6545
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6663
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ParseHttpErrorCodeToMessageEnPipe, decorators: [{
|
|
6546
6664
|
type: Pipe,
|
|
6547
6665
|
args: [{
|
|
6548
6666
|
name: 'parseHttpErrorCodeToMessageEn',
|
|
@@ -6966,8 +7084,11 @@ class QueryForm {
|
|
|
6966
7084
|
continue;
|
|
6967
7085
|
const valueGotRemoved = value === ET_PROPERTY_REMOVED;
|
|
6968
7086
|
if (valueGotRemoved) {
|
|
6969
|
-
|
|
6970
|
-
|
|
7087
|
+
const defaultValue = this._getDefaultValue(key);
|
|
7088
|
+
if (!equal(field.control.value, defaultValue)) {
|
|
7089
|
+
field.control.setValue(defaultValue, { emitEvent: false });
|
|
7090
|
+
didValueChanges = true;
|
|
7091
|
+
}
|
|
6971
7092
|
continue;
|
|
6972
7093
|
}
|
|
6973
7094
|
let deserializedValue = value;
|
|
@@ -7139,6 +7260,21 @@ class QueryForm {
|
|
|
7139
7260
|
});
|
|
7140
7261
|
}
|
|
7141
7262
|
_handleFormChange(forceOverwrite = false) {
|
|
7263
|
+
// Normalize values that have a valueToQueryParamTransformFn returning null/undefined to their
|
|
7264
|
+
// field default before capturing the new value. This prevents intermediate "empty object" states
|
|
7265
|
+
// (e.g. Sort emitting { active: '', direction: '' } when cleared) from being
|
|
7266
|
+
// emitted as distinct form values.
|
|
7267
|
+
for (const [key, field] of Object.entries(this._fields)) {
|
|
7268
|
+
if (!field.data.valueToQueryParamTransformFn)
|
|
7269
|
+
continue;
|
|
7270
|
+
const rawValue = this._formValue[key];
|
|
7271
|
+
if (this._isDefaultValue(key, rawValue))
|
|
7272
|
+
continue;
|
|
7273
|
+
const serialized = field.data.valueToQueryParamTransformFn(rawValue);
|
|
7274
|
+
if (serialized !== null && serialized !== undefined)
|
|
7275
|
+
continue;
|
|
7276
|
+
this.form.controls[key]?.setValue(this._getDefaultValue(key), { emitEvent: false });
|
|
7277
|
+
}
|
|
7142
7278
|
const currentVal = clone(this._currentFormValue$.value);
|
|
7143
7279
|
const newVal = clone(this._formValue);
|
|
7144
7280
|
if (equal(currentVal, newVal)) {
|
|
@@ -7194,17 +7330,17 @@ const createWebSocketClient = (options) => {
|
|
|
7194
7330
|
transports: options.transports,
|
|
7195
7331
|
});
|
|
7196
7332
|
const rooms = new Map();
|
|
7197
|
-
const isConnected = signal(false, ...(ngDevMode ? [{ debugName: "isConnected" }] : []));
|
|
7333
|
+
const isConnected = signal(false, ...(ngDevMode ? [{ debugName: "isConnected" }] : /* istanbul ignore next */ []));
|
|
7198
7334
|
const joinRoom = (room) => {
|
|
7199
7335
|
const roomFn = typeof room === 'function' ? room : () => room;
|
|
7200
7336
|
const pre = previousSignalValue(computed(() => roomFn()));
|
|
7201
|
-
const roomData = signal(null, ...(ngDevMode ? [{ debugName: "roomData" }] : []));
|
|
7337
|
+
const roomData = signal(null, ...(ngDevMode ? [{ debugName: "roomData" }] : /* istanbul ignore next */ []));
|
|
7202
7338
|
const join = (name) => {
|
|
7203
7339
|
socket.emit('join-room', name);
|
|
7204
7340
|
const existingRoom = rooms.get(name);
|
|
7205
7341
|
if (existingRoom)
|
|
7206
7342
|
return existingRoom;
|
|
7207
|
-
const message = signal(null, ...(ngDevMode ? [{ debugName: "message" }] : []));
|
|
7343
|
+
const message = signal(null, ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
|
|
7208
7344
|
const newRoom = {
|
|
7209
7345
|
latestMessage: message,
|
|
7210
7346
|
};
|