@ethlete/query 6.0.0-next.33 → 6.0.0-next.34
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 +16 -0
- package/fesm2022/ethlete-query.mjs +504 -154
- package/fesm2022/ethlete-query.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ethlete-query.d.ts +203 -87
|
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { inject, computed, DestroyRef, InjectionToken, Injector, EnvironmentInjector, ElementRef, ErrorHandler, createEnvironmentInjector, effect, untracked, signal, linkedSignal, runInInjectionContext, isDevMode, PLATFORM_ID, resource, DOCUMENT, VERSION, makeEnvironmentProviders, assertInInjectionContext, provideEnvironmentInitializer, ChangeDetectorRef, ViewContainerRef, TemplateRef, Input, Directive, input, Pipe, ViewEncapsulation, Component, NgZone } from '@angular/core';
|
|
3
3
|
import { toObservable, takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
4
4
|
import { UrlTree, Router, RedirectCommand, ActivatedRoute } from '@angular/router';
|
|
5
|
-
import { filter, take, map, defer, from, Subject, Subscription, throwError, of, timer, switchMap, tap, retry, catchError, EMPTY, takeWhile,
|
|
5
|
+
import { filter, take, map, defer, from, Subject, Subscription, throwError, of, timer, switchMap, tap, retry, catchError, merge, EMPTY, takeWhile, firstValueFrom, concatMap, fromEvent, throttleTime, interval, combineLatest, Observable, takeUntil, startWith, pairwise, BehaviorSubject, ReplaySubject, shareReplay, skip, withLatestFrom, debounceTime } from 'rxjs';
|
|
6
6
|
import { defineStaticProvider, RuntimeError, clamp, randomId, defineRootProvider, isObject, injectUnsavedChangesCoordinator, injectRoute, getCookie, getDomain, deleteCookie, setCookie, CORE_VERSION, createDestroy, computedTillTruthy, defineProvider, toProvideFn, toInjectFn, nextFrame, injectQueryParams, injectQueryParamChanges, clone, equal, ET_PROPERTY_REMOVED, previousSignalValue } from '@ethlete/core';
|
|
7
7
|
import { HttpClient, HttpEventType, HttpErrorResponse, HttpResponse, HttpHeaders, HttpStatusCode } from '@angular/common/http';
|
|
8
8
|
import { getActiveConsumer, setActiveConsumer } from '@angular/core/primitives/signals';
|
|
@@ -265,6 +265,24 @@ const resolveQueryDevtoolsMock = (target) => mockResolver?.(target) ?? null;
|
|
|
265
265
|
* @internal
|
|
266
266
|
*/
|
|
267
267
|
const resolveQueryDevtoolsFault = (target) => faultResolver?.(target) ?? null;
|
|
268
|
+
let tokenPayloadPatcher = null;
|
|
269
|
+
/**
|
|
270
|
+
* Installs the access-token payload patcher. Called by `provideQueryDevtools()`; nothing else may call it.
|
|
271
|
+
* @internal
|
|
272
|
+
*/
|
|
273
|
+
const setQueryDevtoolsTokenPayloadPatcher = (fn) => {
|
|
274
|
+
tokenPayloadPatcher = fn;
|
|
275
|
+
};
|
|
276
|
+
/**
|
|
277
|
+
* A decoded access token as the devtools want it seen, which today means with an overridden lifetime
|
|
278
|
+
* applied. Returns the payload as decoded unless `provideQueryDevtools()` installed a patcher.
|
|
279
|
+
*
|
|
280
|
+
* Auth code must reach the override through this rather than importing the registry it lives in: a
|
|
281
|
+
* static import would pin that module into every bundle that builds an auth provider, and a runtime
|
|
282
|
+
* guard at the call site does not undo that.
|
|
283
|
+
* @internal
|
|
284
|
+
*/
|
|
285
|
+
const patchQueryDevtoolsTokenPayload = (options) => (tokenPayloadPatcher ? tokenPayloadPatcher(options) : options.payload);
|
|
268
286
|
let suppressStackRegistration = false;
|
|
269
287
|
/**
|
|
270
288
|
* Suppresses devtools registration for the next {@link createQueryStack} call. Used by
|
|
@@ -1630,6 +1648,7 @@ const SPEED_BUFFER_TIME_IN_MS = 2000;
|
|
|
1630
1648
|
const MOCKED_STATUS_TEXT = 'Served by the query devtools';
|
|
1631
1649
|
const createHttpRequest = (options) => {
|
|
1632
1650
|
let currentStreamSubscription = Subscription.EMPTY;
|
|
1651
|
+
let lastSentHeaders;
|
|
1633
1652
|
const { args, clientOptions, dependencies } = options;
|
|
1634
1653
|
const currentEvent = signal(null, /* @ts-ignore */
|
|
1635
1654
|
...(ngDevMode ? [{ debugName: "currentEvent" }] : /* istanbul ignore next */ []));
|
|
@@ -1751,6 +1770,7 @@ const createHttpRequest = (options) => {
|
|
|
1751
1770
|
});
|
|
1752
1771
|
const createStream = () => {
|
|
1753
1772
|
const headers = resolveHeaders();
|
|
1773
|
+
lastSentHeaders = headers;
|
|
1754
1774
|
const source$ = isQueryDevtoolsRequestInterceptionEnabled() ? sendWithFaults(headers) : send(headers);
|
|
1755
1775
|
return source$.pipe(tap((event) => updateState(event)), retry({
|
|
1756
1776
|
delay: (error, retryCount) => {
|
|
@@ -1923,6 +1943,7 @@ const createHttpRequest = (options) => {
|
|
|
1923
1943
|
applyPersistedResponse,
|
|
1924
1944
|
lastPersistedResponseAt: lastPersistedResponseAt.asReadonly(),
|
|
1925
1945
|
resolveHeaders,
|
|
1946
|
+
lastSentHeaders: () => lastSentHeaders,
|
|
1926
1947
|
attempts: attempts.asReadonly(),
|
|
1927
1948
|
retryState: retryState.asReadonly(),
|
|
1928
1949
|
lastDurationMs: lastDurationMs.asReadonly(),
|
|
@@ -3863,6 +3884,7 @@ const createSecureExecuteFactory = (options) => {
|
|
|
3863
3884
|
let lastExecuteArgs;
|
|
3864
3885
|
/** The access token the last request went out with - what the 401 retry below compares against. */
|
|
3865
3886
|
let lastRequestedWithToken = null;
|
|
3887
|
+
const error$ = toObservable(options.state.error, { injector: options.deps.injector });
|
|
3866
3888
|
const reset = () => {
|
|
3867
3889
|
authQuerySubscription.unsubscribe();
|
|
3868
3890
|
authQuerySubscription = Subscription.EMPTY;
|
|
@@ -3973,7 +3995,13 @@ const createSecureExecuteFactory = (options) => {
|
|
|
3973
3995
|
// another refresh - an endless refresh/retry loop for as long as the server keeps handing out
|
|
3974
3996
|
// tokens it rejects. A refresh that did not change the access token is therefore not a reason to
|
|
3975
3997
|
// retry; the subscription stays open, so a later one that does change it still is.
|
|
3976
|
-
|
|
3998
|
+
//
|
|
3999
|
+
// The error landing is a trigger of its own: a refresh can complete before this query's 401 has
|
|
4000
|
+
// even come back (which is also why that 401 must not start another refresh - see
|
|
4001
|
+
// withRefreshQuery's 401 handling), and the refresh emission alone would find no error to act
|
|
4002
|
+
// on. Emissions of the error this execution armed with are not landings, only replays.
|
|
4003
|
+
const errorAtArm = options.state.error();
|
|
4004
|
+
tokenRefreshSubscription = merge(options.authProvider.afterTokenRefresh$, error$.pipe(filter((landedError) => landedError !== errorAtArm)))
|
|
3977
4005
|
.pipe(filter(() => {
|
|
3978
4006
|
const currentError = options.state.error();
|
|
3979
4007
|
return currentError?.code === 401 && options.authProvider.accessToken() !== lastRequestedWithToken;
|
|
@@ -4655,7 +4683,12 @@ const createBearerAuthProviderImpl = (config) => {
|
|
|
4655
4683
|
if (!token)
|
|
4656
4684
|
return null;
|
|
4657
4685
|
try {
|
|
4658
|
-
|
|
4686
|
+
const decoded = config.bearerDecryptFn?.(token) ?? decryptBearer(token);
|
|
4687
|
+
return patchQueryDevtoolsTokenPayload({
|
|
4688
|
+
payload: decoded,
|
|
4689
|
+
providerName: config.name,
|
|
4690
|
+
expiresInPropertyName: 'exp',
|
|
4691
|
+
});
|
|
4659
4692
|
}
|
|
4660
4693
|
catch (error) {
|
|
4661
4694
|
if (isDevMode()) {
|
|
@@ -4728,6 +4761,7 @@ const createBearerAuthProviderImpl = (config) => {
|
|
|
4728
4761
|
sessionEndCause: sessionEndCause.asReadonly(),
|
|
4729
4762
|
});
|
|
4730
4763
|
const querySetupContext = {
|
|
4764
|
+
name: config.name,
|
|
4731
4765
|
accessToken,
|
|
4732
4766
|
refreshToken,
|
|
4733
4767
|
bearerDecryptFn: config.bearerDecryptFn,
|
|
@@ -4808,6 +4842,12 @@ const rescheduleDelayMs = 5000;
|
|
|
4808
4842
|
* declining is either not the leader or busy issuing tokens; either way a 401 still forces a refresh.
|
|
4809
4843
|
*/
|
|
4810
4844
|
const maxRescheduleAttempts = 5;
|
|
4845
|
+
/**
|
|
4846
|
+
* How many 401-driven refreshes may run back to back before they fall back to `minRefreshInterval`.
|
|
4847
|
+
* Every refresh in such a streak means the token the previous one issued was rejected too, so an
|
|
4848
|
+
* unbounded streak is a refresh loop, not recovery. A secure request succeeding ends the streak.
|
|
4849
|
+
*/
|
|
4850
|
+
const maxUnauthorizedRefreshStreak = 3;
|
|
4811
4851
|
const withAuthenticationQuery = (key, config, setup) => ({
|
|
4812
4852
|
_type: 'authQuery',
|
|
4813
4853
|
key,
|
|
@@ -4850,6 +4890,8 @@ const withRefreshQuery = (key, config) => {
|
|
|
4850
4890
|
const minRefreshInterval = config.minRefreshInterval ?? 30000; // 30 seconds default
|
|
4851
4891
|
const refreshIfExpired = config.refreshIfExpired ?? true;
|
|
4852
4892
|
let lastRefreshTime = 0;
|
|
4893
|
+
let lastUnauthorizedRefreshTime = 0;
|
|
4894
|
+
let unauthorizedRefreshStreak = 0;
|
|
4853
4895
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
4854
4896
|
const refreshQuery = () => context.queries[key];
|
|
4855
4897
|
const executeRefresh = (reason) => {
|
|
@@ -4873,6 +4915,15 @@ const withRefreshQuery = (key, config) => {
|
|
|
4873
4915
|
return 'throttled';
|
|
4874
4916
|
lastRefreshTime = now;
|
|
4875
4917
|
}
|
|
4918
|
+
else {
|
|
4919
|
+
const now = Date.now();
|
|
4920
|
+
if (unauthorizedRefreshStreak >= maxUnauthorizedRefreshStreak &&
|
|
4921
|
+
now - lastUnauthorizedRefreshTime < minRefreshInterval) {
|
|
4922
|
+
return 'throttled';
|
|
4923
|
+
}
|
|
4924
|
+
unauthorizedRefreshStreak++;
|
|
4925
|
+
lastUnauthorizedRefreshTime = now;
|
|
4926
|
+
}
|
|
4876
4927
|
refreshQuery().execute(buildArgs(currentRefreshToken), { triggeredBy: 'token-refresh' });
|
|
4877
4928
|
return 'executed';
|
|
4878
4929
|
};
|
|
@@ -4907,7 +4958,12 @@ const withRefreshQuery = (key, config) => {
|
|
|
4907
4958
|
/** When this access token is due to be refreshed, or `null` if it cannot be scheduled at all. */
|
|
4908
4959
|
const scheduledRefreshDelay = (token) => {
|
|
4909
4960
|
try {
|
|
4910
|
-
const
|
|
4961
|
+
const decoded = context.bearerDecryptFn ? context.bearerDecryptFn(token) : decryptBearer(token);
|
|
4962
|
+
const bearerDataValue = patchQueryDevtoolsTokenPayload({
|
|
4963
|
+
payload: decoded,
|
|
4964
|
+
providerName: context.name,
|
|
4965
|
+
expiresInPropertyName,
|
|
4966
|
+
});
|
|
4911
4967
|
const expiresIn = bearerDataValue?.[expiresInPropertyName];
|
|
4912
4968
|
if (typeof expiresIn !== 'number') {
|
|
4913
4969
|
if (isDevMode()) {
|
|
@@ -4939,13 +4995,17 @@ const withRefreshQuery = (key, config) => {
|
|
|
4939
4995
|
const retryInMs = retryScheduledIn(executeRefresh('scheduled'));
|
|
4940
4996
|
return retryInMs === null || attemptsLeft <= 0 ? EMPTY : scheduledRefresh(retryInMs, attemptsLeft - 1);
|
|
4941
4997
|
}));
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4998
|
+
// The delay is read in a computed rather than in the `switchMap` so that a devtools-armed token
|
|
4999
|
+
// lifetime re-arms the schedule: the override is a signal, and only a reactive read of it moves the
|
|
5000
|
+
// timer before the next token arrives. The wrapper object keeps every recomputation an emission, so
|
|
5001
|
+
// two tokens that happen to be due at the same moment still restart the timer.
|
|
5002
|
+
const nextScheduledRefresh = computed(() => {
|
|
5003
|
+
const token = context.accessToken();
|
|
5004
|
+
return { dueInMs: token ? scheduledRefreshDelay(token) : null };
|
|
5005
|
+
}, /* @ts-ignore */
|
|
5006
|
+
...(ngDevMode ? [{ debugName: "nextScheduledRefresh" }] : /* istanbul ignore next */ []));
|
|
5007
|
+
toObservable(nextScheduledRefresh)
|
|
5008
|
+
.pipe(switchMap(({ dueInMs }) => (dueInMs === null ? EMPTY : scheduledRefresh(dueInMs, maxRescheduleAttempts))), takeUntilDestroyed())
|
|
4949
5009
|
.subscribe();
|
|
4950
5010
|
context.refreshCoordination?.requests$.pipe(takeUntilDestroyed()).subscribe(() => executeRefresh('unauthorized'));
|
|
4951
5011
|
const onRefreshFailure = config.onRefreshFailure ??
|
|
@@ -4965,18 +5025,22 @@ const withRefreshQuery = (key, config) => {
|
|
|
4965
5025
|
// Auto-retry on 401: Listen to repository events and trigger refresh on 401 errors
|
|
4966
5026
|
const autoRetryOn401 = config.autoRetryOn401 ?? true;
|
|
4967
5027
|
if (autoRetryOn401) {
|
|
4968
|
-
context.repository.events
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
if (!event.isSecure)
|
|
4974
|
-
return
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
5028
|
+
context.repository.events$.pipe(takeUntilDestroyed()).subscribe((event) => {
|
|
5029
|
+
if (event.type === 'request-success' && event.isSecure) {
|
|
5030
|
+
unauthorizedRefreshStreak = 0;
|
|
5031
|
+
return;
|
|
5032
|
+
}
|
|
5033
|
+
if (event.type !== 'request-error' || !event.isSecure || event.error?.status !== 401)
|
|
5034
|
+
return;
|
|
5035
|
+
// A 401 from a request that went out with an older access token asks for a refresh that
|
|
5036
|
+
// already happened - the query re-runs itself with the current token (see
|
|
5037
|
+
// createSecureExecuteFactory). Refreshing again here would spend the refresh token that
|
|
5038
|
+
// pair came with, invalidating the tokens every other in-flight request is using; their
|
|
5039
|
+
// 401s would each do the same, keeping the loop alive for as long as queries are in flight.
|
|
5040
|
+
const sentAuthorization = event.request.subtle.lastSentHeaders()?.get('Authorization');
|
|
5041
|
+
const currentToken = context.accessToken();
|
|
5042
|
+
if (sentAuthorization && currentToken && sentAuthorization !== `Bearer ${currentToken}`)
|
|
5043
|
+
return;
|
|
4980
5044
|
executeRefresh('unauthorized');
|
|
4981
5045
|
});
|
|
4982
5046
|
}
|
|
@@ -5811,124 +5875,13 @@ const queryDevtoolsAbout = () => ({
|
|
|
5811
5875
|
app,
|
|
5812
5876
|
});
|
|
5813
5877
|
|
|
5814
|
-
/** The neutral fault: nothing armed. */
|
|
5815
|
-
const EMPTY_QUERY_DEVTOOLS_FAULT = {
|
|
5816
|
-
latencyMs: 0,
|
|
5817
|
-
failNext: 0,
|
|
5818
|
-
failRate: 0,
|
|
5819
|
-
status: 503,
|
|
5820
|
-
};
|
|
5821
|
-
/**
|
|
5822
|
-
* Statuses worth injecting, and whether the SDK's default retry policy retries them. A picker built from
|
|
5823
|
-
* this cannot arm a 500 and then leave you wondering why no retry fired.
|
|
5824
|
-
* @see runDefaultQueryRetry
|
|
5825
|
-
*/
|
|
5826
|
-
const QUERY_DEVTOOLS_FAULT_STATUSES = [
|
|
5827
|
-
{ status: 0, label: 'Network error', retryable: true },
|
|
5828
|
-
{ status: 400, label: 'Bad Request', retryable: false },
|
|
5829
|
-
{ status: 401, label: 'Unauthorized', retryable: false },
|
|
5830
|
-
{ status: 403, label: 'Forbidden', retryable: false },
|
|
5831
|
-
{ status: 404, label: 'Not Found', retryable: false },
|
|
5832
|
-
{ status: 408, label: 'Request Timeout', retryable: true },
|
|
5833
|
-
{ status: 429, label: 'Too Many Requests', retryable: true },
|
|
5834
|
-
{ status: 500, label: 'Internal Server Error', retryable: false },
|
|
5835
|
-
{ status: 502, label: 'Bad Gateway', retryable: true },
|
|
5836
|
-
{ status: 503, label: 'Service Unavailable', retryable: true },
|
|
5837
|
-
];
|
|
5838
|
-
const faults = /* @__PURE__ */ signal({}, /* @ts-ignore */
|
|
5839
|
-
...(ngDevMode ? [{ debugName: "faults" }] : /* istanbul ignore next */ []));
|
|
5840
|
-
/**
|
|
5841
|
-
* The faults armed per client name, consumed by the `<et-query-devtools>` UI. Clients with nothing armed
|
|
5842
|
-
* are absent rather than present with an {@link EMPTY_QUERY_DEVTOOLS_FAULT}.
|
|
5843
|
-
*/
|
|
5844
|
-
const queryDevtoolsFaults = /* @__PURE__ */ faults.asReadonly();
|
|
5845
|
-
/** Whether anything at all is armed on a fault. */
|
|
5846
|
-
const isQueryDevtoolsFaultArmed = (fault) => fault.latencyMs > 0 || fault.failNext > 0 || fault.failRate > 0;
|
|
5847
|
-
/**
|
|
5848
|
-
* Arms (or updates) the fault of one client. Only the given fields change; the rest keep their current
|
|
5849
|
-
* value. A client whose resulting fault has nothing armed is dropped from {@link queryDevtoolsFaults}.
|
|
5850
|
-
*
|
|
5851
|
-
* Part of the devtools contract consumed by `<et-query-devtools>`; a fault is a debugging tool, not
|
|
5852
|
-
* something an application should arm on itself.
|
|
5853
|
-
*/
|
|
5854
|
-
const setQueryDevtoolsFault = (options) => {
|
|
5855
|
-
const { clientName, patch } = options;
|
|
5856
|
-
faults.update((current) => {
|
|
5857
|
-
const next = { ...(current[clientName] ?? EMPTY_QUERY_DEVTOOLS_FAULT), ...patch };
|
|
5858
|
-
if (!isQueryDevtoolsFaultArmed(next)) {
|
|
5859
|
-
const { [clientName]: _removed, ...rest } = current;
|
|
5860
|
-
return rest;
|
|
5861
|
-
}
|
|
5862
|
-
return { ...current, [clientName]: next };
|
|
5863
|
-
});
|
|
5864
|
-
};
|
|
5865
|
-
/**
|
|
5866
|
-
* Disarms every fault of one client, or of all clients when no name is given.
|
|
5867
|
-
*
|
|
5868
|
-
* @see setQueryDevtoolsFault
|
|
5869
|
-
*/
|
|
5870
|
-
const clearQueryDevtoolsFaults = (clientName) => faults.update((current) => {
|
|
5871
|
-
if (clientName === undefined)
|
|
5872
|
-
return {};
|
|
5873
|
-
const { [clientName]: _removed, ...rest } = current;
|
|
5874
|
-
return rest;
|
|
5875
|
-
});
|
|
5876
|
-
/**
|
|
5877
|
-
* Resolves what to do with one upcoming attempt, consuming a `failNext` budget in the process - so this
|
|
5878
|
-
* must be called once per attempt and never speculatively.
|
|
5879
|
-
*
|
|
5880
|
-
* Installed as the fault resolver by `provideQueryDevtools()`; nothing else may call it.
|
|
5881
|
-
* @internal
|
|
5882
|
-
*/
|
|
5883
|
-
const resolveQueryDevtoolsFaultForAttempt = (target) => {
|
|
5884
|
-
const fault = faults()[target.clientName];
|
|
5885
|
-
if (!fault || !isQueryDevtoolsFaultArmed(fault))
|
|
5886
|
-
return null;
|
|
5887
|
-
let shouldFail = false;
|
|
5888
|
-
if (fault.failNext > 0) {
|
|
5889
|
-
shouldFail = true;
|
|
5890
|
-
setQueryDevtoolsFault({ clientName: target.clientName, patch: { failNext: fault.failNext - 1 } });
|
|
5891
|
-
}
|
|
5892
|
-
else if (fault.failRate > 0) {
|
|
5893
|
-
shouldFail = Math.random() * 100 < fault.failRate;
|
|
5894
|
-
}
|
|
5895
|
-
return {
|
|
5896
|
-
latencyMs: fault.latencyMs,
|
|
5897
|
-
status: shouldFail ? fault.status : null,
|
|
5898
|
-
};
|
|
5899
|
-
};
|
|
5900
|
-
|
|
5901
|
-
/**
|
|
5902
|
-
* Records which query forms feed one query's args, so the devtools can answer "which query does this
|
|
5903
|
-
* form drive?" from the reads themselves rather than from a naming convention.
|
|
5904
|
-
* @internal
|
|
5905
|
-
*/
|
|
5906
|
-
const createQueryDevtoolsFormLinks = () => {
|
|
5907
|
-
const ids = signal([], /* @ts-ignore */
|
|
5908
|
-
...(ngDevMode ? [{ debugName: "ids" }] : /* istanbul ignore next */ []));
|
|
5909
|
-
return {
|
|
5910
|
-
ids: ids.asReadonly(),
|
|
5911
|
-
track: (build) => {
|
|
5912
|
-
const collected = collectQueryFormLinks(build);
|
|
5913
|
-
// Args are built inside a reactive computation, which may not write to a signal - `untracked`
|
|
5914
|
-
// lifts that restriction, and skipping the write unless something is new keeps the panel from
|
|
5915
|
-
// being notified on every evaluation.
|
|
5916
|
-
untracked(() => {
|
|
5917
|
-
const known = ids();
|
|
5918
|
-
const added = collected.ids.filter((id) => !known.includes(id));
|
|
5919
|
-
if (added.length)
|
|
5920
|
-
ids.set([...known, ...added]);
|
|
5921
|
-
});
|
|
5922
|
-
return collected.value;
|
|
5923
|
-
},
|
|
5924
|
-
};
|
|
5925
|
-
};
|
|
5926
|
-
|
|
5927
5878
|
const DEFAULTS = {
|
|
5928
5879
|
viewState: 'session',
|
|
5929
5880
|
pins: 'local',
|
|
5930
5881
|
overrides: 'none',
|
|
5931
5882
|
mocks: 'local',
|
|
5883
|
+
armedMocks: 'none',
|
|
5884
|
+
armedFaults: 'none',
|
|
5932
5885
|
maxEvents: 100,
|
|
5933
5886
|
maxDroppedCacheEntries: 20,
|
|
5934
5887
|
responseHistory: null,
|
|
@@ -6031,6 +5984,8 @@ const sanitize = (value) => ({
|
|
|
6031
5984
|
pins: asScope(value?.pins, DEFAULTS.pins),
|
|
6032
5985
|
overrides: asScope(value?.overrides, DEFAULTS.overrides),
|
|
6033
5986
|
mocks: asScope(value?.mocks, DEFAULTS.mocks),
|
|
5987
|
+
armedMocks: asScope(value?.armedMocks, DEFAULTS.armedMocks),
|
|
5988
|
+
armedFaults: asScope(value?.armedFaults, DEFAULTS.armedFaults),
|
|
6034
5989
|
maxEvents: asCount(value?.maxEvents, LIMITS.maxEvents, DEFAULTS.maxEvents),
|
|
6035
5990
|
maxDroppedCacheEntries: asCount(value?.maxDroppedCacheEntries, LIMITS.maxDroppedCacheEntries, DEFAULTS.maxDroppedCacheEntries),
|
|
6036
5991
|
responseHistory: asOptionalCount(value?.responseHistory, LIMITS.responseHistory),
|
|
@@ -6059,23 +6014,213 @@ const setQueryDevtoolsSettings = (patch) => {
|
|
|
6059
6014
|
writeQueryDevtoolsStore('local', SETTINGS_KEY, next);
|
|
6060
6015
|
};
|
|
6061
6016
|
|
|
6017
|
+
/** The neutral fault: nothing armed. */
|
|
6018
|
+
const EMPTY_QUERY_DEVTOOLS_FAULT = {
|
|
6019
|
+
latencyMs: 0,
|
|
6020
|
+
failNext: 0,
|
|
6021
|
+
failRate: 0,
|
|
6022
|
+
status: 503,
|
|
6023
|
+
};
|
|
6062
6024
|
/**
|
|
6063
|
-
*
|
|
6025
|
+
* Statuses worth injecting, and whether the SDK's default retry policy retries them. A picker built from
|
|
6026
|
+
* this cannot arm a 500 and then leave you wondering why no retry fired.
|
|
6027
|
+
* @see runDefaultQueryRetry
|
|
6028
|
+
*/
|
|
6029
|
+
const QUERY_DEVTOOLS_FAULT_STATUSES = [
|
|
6030
|
+
{ status: 0, label: 'Network error', retryable: true },
|
|
6031
|
+
{ status: 400, label: 'Bad Request', retryable: false },
|
|
6032
|
+
{ status: 401, label: 'Unauthorized', retryable: false },
|
|
6033
|
+
{ status: 403, label: 'Forbidden', retryable: false },
|
|
6034
|
+
{ status: 404, label: 'Not Found', retryable: false },
|
|
6035
|
+
{ status: 408, label: 'Request Timeout', retryable: true },
|
|
6036
|
+
{ status: 429, label: 'Too Many Requests', retryable: true },
|
|
6037
|
+
{ status: 500, label: 'Internal Server Error', retryable: false },
|
|
6038
|
+
{ status: 502, label: 'Bad Gateway', retryable: true },
|
|
6039
|
+
{ status: 503, label: 'Service Unavailable', retryable: true },
|
|
6040
|
+
];
|
|
6041
|
+
const STORAGE_KEY$2 = 'ethlete:query:devtools:faults:v1';
|
|
6042
|
+
const faults = /* @__PURE__ */ signal({}, /* @ts-ignore */
|
|
6043
|
+
...(ngDevMode ? [{ debugName: "faults" }] : /* istanbul ignore next */ []));
|
|
6044
|
+
const restored$1 = /* @__PURE__ */ signal(false, /* @ts-ignore */
|
|
6045
|
+
...(ngDevMode ? [{ debugName: "restored" }] : /* istanbul ignore next */ []));
|
|
6046
|
+
const scope$2 = () => queryDevtoolsSettings().armedFaults;
|
|
6047
|
+
/**
|
|
6048
|
+
* The faults armed per client name, consumed by the `<et-query-devtools>` UI. Clients with nothing armed
|
|
6049
|
+
* are absent rather than present with an {@link EMPTY_QUERY_DEVTOOLS_FAULT}.
|
|
6050
|
+
*/
|
|
6051
|
+
const queryDevtoolsFaults = /* @__PURE__ */ faults.asReadonly();
|
|
6052
|
+
/**
|
|
6053
|
+
* Whether what is armed right now came back from a previous page load rather than being armed by hand.
|
|
6054
|
+
* The panel's armed bar says so, because injected failures nobody remembers arming look exactly like a
|
|
6055
|
+
* broken API.
|
|
6056
|
+
*/
|
|
6057
|
+
const queryDevtoolsFaultsRestored = /* @__PURE__ */ restored$1.asReadonly();
|
|
6058
|
+
const write$1 = () => {
|
|
6059
|
+
if (scope$2() === 'none') {
|
|
6060
|
+
clearQueryDevtoolsStore(STORAGE_KEY$2);
|
|
6061
|
+
return;
|
|
6062
|
+
}
|
|
6063
|
+
writeQueryDevtoolsStore(scope$2(), STORAGE_KEY$2, faults());
|
|
6064
|
+
};
|
|
6065
|
+
const asFault = (value) => {
|
|
6066
|
+
const fault = value;
|
|
6067
|
+
if (!fault || typeof fault !== 'object')
|
|
6068
|
+
return null;
|
|
6069
|
+
const next = {
|
|
6070
|
+
latencyMs: Number(fault.latencyMs) || 0,
|
|
6071
|
+
failNext: Number(fault.failNext) || 0,
|
|
6072
|
+
failRate: Number(fault.failRate) || 0,
|
|
6073
|
+
status: Number.isFinite(Number(fault.status)) ? Number(fault.status) : EMPTY_QUERY_DEVTOOLS_FAULT.status,
|
|
6074
|
+
};
|
|
6075
|
+
return isQueryDevtoolsFaultArmed(next) ? next : null;
|
|
6076
|
+
};
|
|
6077
|
+
/**
|
|
6078
|
+
* Reads the armed faults back, when the `armedFaults` setting asks for them. Called by
|
|
6079
|
+
* `provideQueryDevtools()` after the settings it takes its scope from; nothing else may call it.
|
|
6080
|
+
* @internal
|
|
6081
|
+
*/
|
|
6082
|
+
const initQueryDevtoolsFaults = () => {
|
|
6083
|
+
const stored = readQueryDevtoolsStore(scope$2(), STORAGE_KEY$2);
|
|
6084
|
+
const inherited = {};
|
|
6085
|
+
for (const [clientName, value] of Object.entries(stored ?? {})) {
|
|
6086
|
+
const fault = asFault(value);
|
|
6087
|
+
if (fault)
|
|
6088
|
+
inherited[clientName] = fault;
|
|
6089
|
+
}
|
|
6090
|
+
faults.set(inherited);
|
|
6091
|
+
restored$1.set(Object.keys(inherited).length > 0);
|
|
6092
|
+
};
|
|
6093
|
+
/**
|
|
6094
|
+
* Where the armed faults are kept. Switching to a scope that keeps them stores whatever is armed right
|
|
6095
|
+
* now; switching to `none` empties the store and leaves this page's faults exactly where they are.
|
|
6096
|
+
*/
|
|
6097
|
+
const setQueryDevtoolsFaultsScope = (next) => {
|
|
6098
|
+
if (next === scope$2())
|
|
6099
|
+
return;
|
|
6100
|
+
// Off both stores first: whichever the previous scope was, its copy must not outlive the change.
|
|
6101
|
+
clearQueryDevtoolsStore(STORAGE_KEY$2);
|
|
6102
|
+
setQueryDevtoolsSettings({ armedFaults: next });
|
|
6103
|
+
write$1();
|
|
6104
|
+
};
|
|
6105
|
+
/** Whether anything at all is armed on a fault. */
|
|
6106
|
+
const isQueryDevtoolsFaultArmed = (fault) => fault.latencyMs > 0 || fault.failNext > 0 || fault.failRate > 0;
|
|
6107
|
+
const patchFault = (options) => {
|
|
6108
|
+
const { clientName, patch } = options;
|
|
6109
|
+
faults.update((current) => {
|
|
6110
|
+
const next = { ...(current[clientName] ?? EMPTY_QUERY_DEVTOOLS_FAULT), ...patch };
|
|
6111
|
+
if (!isQueryDevtoolsFaultArmed(next)) {
|
|
6112
|
+
const { [clientName]: _removed, ...rest } = current;
|
|
6113
|
+
return rest;
|
|
6114
|
+
}
|
|
6115
|
+
return { ...current, [clientName]: next };
|
|
6116
|
+
});
|
|
6117
|
+
write$1();
|
|
6118
|
+
};
|
|
6119
|
+
/**
|
|
6120
|
+
* Arms (or updates) the fault of one client. Only the given fields change; the rest keep their current
|
|
6121
|
+
* value. A client whose resulting fault has nothing armed is dropped from {@link queryDevtoolsFaults}.
|
|
6122
|
+
*
|
|
6123
|
+
* Part of the devtools contract consumed by `<et-query-devtools>`; a fault is a debugging tool, not
|
|
6124
|
+
* something an application should arm on itself.
|
|
6125
|
+
*/
|
|
6126
|
+
const setQueryDevtoolsFault = (options) => {
|
|
6127
|
+
patchFault(options);
|
|
6128
|
+
restored$1.set(false);
|
|
6129
|
+
};
|
|
6130
|
+
/**
|
|
6131
|
+
* Disarms every fault of one client, or of all clients when no name is given.
|
|
6132
|
+
*
|
|
6133
|
+
* @see setQueryDevtoolsFault
|
|
6134
|
+
*/
|
|
6135
|
+
const clearQueryDevtoolsFaults = (clientName) => {
|
|
6136
|
+
faults.update((current) => {
|
|
6137
|
+
if (clientName === undefined)
|
|
6138
|
+
return {};
|
|
6139
|
+
const { [clientName]: _removed, ...rest } = current;
|
|
6140
|
+
return rest;
|
|
6141
|
+
});
|
|
6142
|
+
restored$1.set(false);
|
|
6143
|
+
write$1();
|
|
6144
|
+
};
|
|
6145
|
+
/**
|
|
6146
|
+
* Resolves what to do with one upcoming attempt, consuming a `failNext` budget in the process - so this
|
|
6147
|
+
* must be called once per attempt and never speculatively.
|
|
6148
|
+
*
|
|
6149
|
+
* Installed as the fault resolver by `provideQueryDevtools()`; nothing else may call it.
|
|
6150
|
+
* @internal
|
|
6151
|
+
*/
|
|
6152
|
+
const resolveQueryDevtoolsFaultForAttempt = (target) => {
|
|
6153
|
+
const fault = faults()[target.clientName];
|
|
6154
|
+
if (!fault || !isQueryDevtoolsFaultArmed(fault))
|
|
6155
|
+
return null;
|
|
6156
|
+
let shouldFail = false;
|
|
6157
|
+
if (fault.failNext > 0) {
|
|
6158
|
+
shouldFail = true;
|
|
6159
|
+
// Not the public setter: spending the budget is the armed fault doing its job, not someone re-arming
|
|
6160
|
+
// it, so it must not clear what the panel's bar says about where the fault came from.
|
|
6161
|
+
patchFault({ clientName: target.clientName, patch: { failNext: fault.failNext - 1 } });
|
|
6162
|
+
}
|
|
6163
|
+
else if (fault.failRate > 0) {
|
|
6164
|
+
shouldFail = Math.random() * 100 < fault.failRate;
|
|
6165
|
+
}
|
|
6166
|
+
return {
|
|
6167
|
+
latencyMs: fault.latencyMs,
|
|
6168
|
+
status: shouldFail ? fault.status : null,
|
|
6169
|
+
};
|
|
6170
|
+
};
|
|
6171
|
+
|
|
6172
|
+
/**
|
|
6173
|
+
* Records which query forms feed one query's args, so the devtools can answer "which query does this
|
|
6174
|
+
* form drive?" from the reads themselves rather than from a naming convention.
|
|
6175
|
+
* @internal
|
|
6176
|
+
*/
|
|
6177
|
+
const createQueryDevtoolsFormLinks = () => {
|
|
6178
|
+
const ids = signal([], /* @ts-ignore */
|
|
6179
|
+
...(ngDevMode ? [{ debugName: "ids" }] : /* istanbul ignore next */ []));
|
|
6180
|
+
return {
|
|
6181
|
+
ids: ids.asReadonly(),
|
|
6182
|
+
track: (build) => {
|
|
6183
|
+
const collected = collectQueryFormLinks(build);
|
|
6184
|
+
// Args are built inside a reactive computation, which may not write to a signal - `untracked`
|
|
6185
|
+
// lifts that restriction, and skipping the write unless something is new keeps the panel from
|
|
6186
|
+
// being notified on every evaluation.
|
|
6187
|
+
untracked(() => {
|
|
6188
|
+
const known = ids();
|
|
6189
|
+
const added = collected.ids.filter((id) => !known.includes(id));
|
|
6190
|
+
if (added.length)
|
|
6191
|
+
ids.set([...known, ...added]);
|
|
6192
|
+
});
|
|
6193
|
+
return collected.value;
|
|
6194
|
+
},
|
|
6195
|
+
};
|
|
6196
|
+
};
|
|
6197
|
+
|
|
6198
|
+
/**
|
|
6199
|
+
* The designed library. Which of them is **armed** is a separate store under a separate scope - see
|
|
6064
6200
|
* {@link queryDevtoolsArmedMocks}.
|
|
6065
6201
|
*/
|
|
6066
6202
|
const STORAGE_KEY$1 = 'ethlete:query:devtools:mocks:v1';
|
|
6203
|
+
const ARMED_STORAGE_KEY = 'ethlete:query:devtools:mocks:armed:v1';
|
|
6067
6204
|
const mocks = /* @__PURE__ */ signal([], /* @ts-ignore */
|
|
6068
6205
|
...(ngDevMode ? [{ debugName: "mocks" }] : /* istanbul ignore next */ []));
|
|
6069
6206
|
const armed = /* @__PURE__ */ signal(/* @__PURE__ */ new Set(), /* @ts-ignore */
|
|
6070
6207
|
...(ngDevMode ? [{ debugName: "armed" }] : /* istanbul ignore next */ []));
|
|
6208
|
+
const armedRestored = /* @__PURE__ */ signal(false, /* @ts-ignore */
|
|
6209
|
+
...(ngDevMode ? [{ debugName: "armedRestored" }] : /* istanbul ignore next */ []));
|
|
6071
6210
|
const scope$1 = () => queryDevtoolsSettings().mocks;
|
|
6211
|
+
const armedScope = () => queryDevtoolsSettings().armedMocks;
|
|
6072
6212
|
/** The designed mocks, armed or not. Persisted, because losing an hour of authoring is unacceptable. */
|
|
6073
6213
|
const queryDevtoolsMocks = /* @__PURE__ */ mocks.asReadonly();
|
|
6074
6214
|
/**
|
|
6075
|
-
* The ids currently being served.
|
|
6076
|
-
* data tomorrow morning is worse than losing which mocks were armed
|
|
6215
|
+
* The ids currently being served. Not kept across page loads unless the `armedMocks` setting asks for it -
|
|
6216
|
+
* an app that silently serves designed data tomorrow morning is worse than losing which mocks were armed.
|
|
6077
6217
|
*/
|
|
6078
6218
|
const queryDevtoolsArmedMocks = /* @__PURE__ */ armed.asReadonly();
|
|
6219
|
+
/**
|
|
6220
|
+
* Whether what is armed right now came back from a previous page load rather than being armed by hand.
|
|
6221
|
+
* The panel's armed bar says so, because mocks nobody remembers arming look exactly like a broken API.
|
|
6222
|
+
*/
|
|
6223
|
+
const queryDevtoolsArmedMocksRestored = /* @__PURE__ */ armedRestored.asReadonly();
|
|
6079
6224
|
/**
|
|
6080
6225
|
* The identity of a designed mock: one per client, method, route **and** declared query. The query is part
|
|
6081
6226
|
* of it so `/posts?page=1` and `/posts?page=2` can hold different bodies.
|
|
@@ -6088,6 +6233,19 @@ const write = () => {
|
|
|
6088
6233
|
}
|
|
6089
6234
|
writeQueryDevtoolsStore(scope$1(), STORAGE_KEY$1, mocks());
|
|
6090
6235
|
};
|
|
6236
|
+
const writeArmed = () => {
|
|
6237
|
+
if (armedScope() === 'none') {
|
|
6238
|
+
clearQueryDevtoolsStore(ARMED_STORAGE_KEY);
|
|
6239
|
+
return;
|
|
6240
|
+
}
|
|
6241
|
+
writeQueryDevtoolsStore(armedScope(), ARMED_STORAGE_KEY, [...armed()]);
|
|
6242
|
+
};
|
|
6243
|
+
/** Every change made by hand goes through here, so none of them can leave the store or the bar behind. */
|
|
6244
|
+
const setArmed = (next) => {
|
|
6245
|
+
armed.set(next);
|
|
6246
|
+
armedRestored.set(false);
|
|
6247
|
+
writeArmed();
|
|
6248
|
+
};
|
|
6091
6249
|
const isMock = (value) => {
|
|
6092
6250
|
const mock = value;
|
|
6093
6251
|
return (!!mock &&
|
|
@@ -6106,7 +6264,15 @@ const initQueryDevtoolsMocks = () => {
|
|
|
6106
6264
|
const stored = readQueryDevtoolsStore(scope$1(), STORAGE_KEY$1);
|
|
6107
6265
|
// `query` was added after the first version of the store, so an entry written before it still loads.
|
|
6108
6266
|
mocks.set(Array.isArray(stored) ? stored.filter(isMock).map((mock) => ({ ...mock, query: mock.query ?? '' })) : []);
|
|
6109
|
-
|
|
6267
|
+
const kept = readQueryDevtoolsStore(armedScope(), ARMED_STORAGE_KEY);
|
|
6268
|
+
const library = new Set(mocks().map((mock) => mock.id));
|
|
6269
|
+
// An id the library no longer holds would arm nothing, so it is dropped rather than kept waiting for a
|
|
6270
|
+
// mock that may never be designed again.
|
|
6271
|
+
const inherited = Array.isArray(kept)
|
|
6272
|
+
? kept.filter((id) => typeof id === 'string' && library.has(id))
|
|
6273
|
+
: [];
|
|
6274
|
+
armed.set(new Set(inherited));
|
|
6275
|
+
armedRestored.set(inherited.length > 0);
|
|
6110
6276
|
};
|
|
6111
6277
|
/** The path of a request URL, without its origin or query string - what a pattern is matched against. */
|
|
6112
6278
|
const queryDevtoolsRequestPath = (url) => {
|
|
@@ -6163,24 +6329,39 @@ const deleteQueryDevtoolsMock = (id) => {
|
|
|
6163
6329
|
};
|
|
6164
6330
|
/** Starts or stops serving one designed mock. Arming a mock that is not in the library does nothing. */
|
|
6165
6331
|
const armQueryDevtoolsMock = (id, isArmed) => {
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6332
|
+
if (isArmed && !mocks().some((mock) => mock.id === id))
|
|
6333
|
+
return;
|
|
6334
|
+
const next = new Set(armed());
|
|
6335
|
+
if (isArmed)
|
|
6336
|
+
next.add(id);
|
|
6337
|
+
else
|
|
6338
|
+
next.delete(id);
|
|
6339
|
+
setArmed(next);
|
|
6340
|
+
};
|
|
6341
|
+
/** Starts serving every mock in the library - the counterpart of {@link clearQueryDevtoolsArmedMocks}. */
|
|
6342
|
+
const armAllQueryDevtoolsMocks = () => setArmed(new Set(mocks().map((mock) => mock.id)));
|
|
6177
6343
|
/** Stops serving every mock, leaving the library alone - the armed bar's one-click way out. */
|
|
6178
|
-
const clearQueryDevtoolsArmedMocks = () =>
|
|
6344
|
+
const clearQueryDevtoolsArmedMocks = () => setArmed(new Set());
|
|
6345
|
+
/**
|
|
6346
|
+
* Where the armed set is kept. Switching to a scope that keeps it stores whatever is armed right now, so
|
|
6347
|
+
* the choice reads as "keep these"; switching to `none` empties the store and leaves this page serving
|
|
6348
|
+
* exactly what it was already serving.
|
|
6349
|
+
*/
|
|
6350
|
+
const setQueryDevtoolsArmedMocksScope = (next) => {
|
|
6351
|
+
if (next === armedScope())
|
|
6352
|
+
return;
|
|
6353
|
+
// Off both stores first: whichever the previous scope was, its copy must not outlive the change.
|
|
6354
|
+
clearQueryDevtoolsStore(ARMED_STORAGE_KEY);
|
|
6355
|
+
setQueryDevtoolsSettings({ armedMocks: next });
|
|
6356
|
+
writeArmed();
|
|
6357
|
+
};
|
|
6179
6358
|
/** Empties the designed library and disarms everything - the panel's "Reset devtools". */
|
|
6180
6359
|
const clearQueryDevtoolsMockStore = () => {
|
|
6181
6360
|
mocks.set([]);
|
|
6182
6361
|
armed.set(new Set());
|
|
6362
|
+
armedRestored.set(false);
|
|
6183
6363
|
clearQueryDevtoolsStore(STORAGE_KEY$1);
|
|
6364
|
+
clearQueryDevtoolsStore(ARMED_STORAGE_KEY);
|
|
6184
6365
|
};
|
|
6185
6366
|
const declaredParamCount = (mock) => (mock.query ? [...new URLSearchParams(mock.query)].length : 0);
|
|
6186
6367
|
/**
|
|
@@ -6916,7 +7097,7 @@ const armQueryDevtoolsOverrideTransfer = (recorder, ops) => {
|
|
|
6916
7097
|
|
|
6917
7098
|
// Generated from package.json by tools/scripts/generate-version.js - do not edit.
|
|
6918
7099
|
/** The version of `@ethlete/query` this build was cut from. */
|
|
6919
|
-
const QUERY_VERSION = '6.0.0-next.
|
|
7100
|
+
const QUERY_VERSION = '6.0.0-next.34';
|
|
6920
7101
|
|
|
6921
7102
|
/** How deep a schema is expanded before a nested branch is given up on. */
|
|
6922
7103
|
const MAX_DEPTH = 12;
|
|
@@ -7248,6 +7429,89 @@ const seedQueryDevtoolsSchemaBody = (name) => {
|
|
|
7248
7429
|
return null;
|
|
7249
7430
|
return seedFrom(schema, name);
|
|
7250
7431
|
};
|
|
7432
|
+
/** Where a schema was collected from, so the same name arriving from two pointers is caught. */
|
|
7433
|
+
const originOf = (label, pointer) => pointer ?? `named:${label}`;
|
|
7434
|
+
/**
|
|
7435
|
+
* Copies a schema, pointing every local `$ref` at `#/components/schemas/<name>` and queueing that name -
|
|
7436
|
+
* so a document assembled from these resolves against its own `components`, whether the description kept
|
|
7437
|
+
* its schemas under `components.schemas`, `definitions` or `$defs`.
|
|
7438
|
+
*/
|
|
7439
|
+
const rewriteRefs = (value, queue) => {
|
|
7440
|
+
if (Array.isArray(value))
|
|
7441
|
+
return value.map((entry) => rewriteRefs(entry, queue));
|
|
7442
|
+
if (!isRecord(value))
|
|
7443
|
+
return value;
|
|
7444
|
+
const result = {};
|
|
7445
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
7446
|
+
if (key === '$ref' && typeof entry === 'string') {
|
|
7447
|
+
if (!entry.startsWith('#/')) {
|
|
7448
|
+
result[key] = entry;
|
|
7449
|
+
continue;
|
|
7450
|
+
}
|
|
7451
|
+
const label = refLabel(entry);
|
|
7452
|
+
queue({ label, pointer: entry });
|
|
7453
|
+
result[key] = `#/components/schemas/${label}`;
|
|
7454
|
+
continue;
|
|
7455
|
+
}
|
|
7456
|
+
result[key] = rewriteRefs(entry, queue);
|
|
7457
|
+
}
|
|
7458
|
+
return result;
|
|
7459
|
+
};
|
|
7460
|
+
/**
|
|
7461
|
+
* Collects the named schemas a set of routes was designed against, ready to be handed back as the
|
|
7462
|
+
* `components.schemas` of an exported document - so a route seeded from `MatchView` can reference
|
|
7463
|
+
* `MatchView` instead of an anonymous shape inferred from one body.
|
|
7464
|
+
*
|
|
7465
|
+
* Part of the devtools contract. **Not part of the general public contract.**
|
|
7466
|
+
*/
|
|
7467
|
+
const collectQueryDevtoolsSchemaComponents = (names) => {
|
|
7468
|
+
const declared = namedSchemas();
|
|
7469
|
+
const schemas = {};
|
|
7470
|
+
const notes = new Set();
|
|
7471
|
+
const origins = new Map();
|
|
7472
|
+
const pending = names.map((label) => ({ label, pointer: null }));
|
|
7473
|
+
while (pending.length) {
|
|
7474
|
+
const request = pending.shift();
|
|
7475
|
+
const origin = originOf(request.label, request.pointer);
|
|
7476
|
+
const seen = origins.get(request.label);
|
|
7477
|
+
if (seen !== undefined) {
|
|
7478
|
+
if (seen !== origin) {
|
|
7479
|
+
notes.add(`Two different schemas are both called ${request.label} - only the one from ${seen} was kept.`);
|
|
7480
|
+
}
|
|
7481
|
+
continue;
|
|
7482
|
+
}
|
|
7483
|
+
const schema = request.pointer === null ? declared[request.label] : resolveRef(request.pointer);
|
|
7484
|
+
if (schema === undefined) {
|
|
7485
|
+
if (request.pointer !== null) {
|
|
7486
|
+
notes.add(`${request.pointer} could not be resolved, so ${request.label} is missing from the export.`);
|
|
7487
|
+
}
|
|
7488
|
+
continue;
|
|
7489
|
+
}
|
|
7490
|
+
origins.set(request.label, origin);
|
|
7491
|
+
schemas[request.label] = rewriteRefs(schema, (next) => pending.push(next));
|
|
7492
|
+
}
|
|
7493
|
+
for (const schema of Object.values(schemas)) {
|
|
7494
|
+
collectRemoteRefs(schema, notes);
|
|
7495
|
+
}
|
|
7496
|
+
return { schemas, notes: [...notes] };
|
|
7497
|
+
};
|
|
7498
|
+
/** A `$ref` to another file is left as it was written, so a document says where it stops resolving. */
|
|
7499
|
+
const collectRemoteRefs = (value, notes) => {
|
|
7500
|
+
if (Array.isArray(value)) {
|
|
7501
|
+
for (const entry of value)
|
|
7502
|
+
collectRemoteRefs(entry, notes);
|
|
7503
|
+
return;
|
|
7504
|
+
}
|
|
7505
|
+
if (!isRecord(value))
|
|
7506
|
+
return;
|
|
7507
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
7508
|
+
if (key === '$ref' && typeof entry === 'string' && !entry.startsWith('#/')) {
|
|
7509
|
+
notes.add(`${entry} points outside the description - it was exported unchanged and will not resolve.`);
|
|
7510
|
+
continue;
|
|
7511
|
+
}
|
|
7512
|
+
collectRemoteRefs(entry, notes);
|
|
7513
|
+
}
|
|
7514
|
+
};
|
|
7251
7515
|
const segmentsOf = (pattern) => pattern.split('/').filter(Boolean);
|
|
7252
7516
|
/** `/matches/{id}` and `/matches/:id` describe the same route; a mock's pattern is written the second way. */
|
|
7253
7517
|
const toColonPattern = (path) => path.replace(/\{([^}]+)\}/g, ':$1');
|
|
@@ -7662,6 +7926,90 @@ const sumQueryDevtoolsStats = (handles) => {
|
|
|
7662
7926
|
return total;
|
|
7663
7927
|
};
|
|
7664
7928
|
|
|
7929
|
+
/**
|
|
7930
|
+
* The longest lifetime an armed override may claim, in seconds (7 days). Anything beyond it is never
|
|
7931
|
+
* refreshed at all, which is what arming nothing already does.
|
|
7932
|
+
*/
|
|
7933
|
+
const QUERY_DEVTOOLS_TOKEN_TTL_LIMIT = 604800;
|
|
7934
|
+
/** The claims an overridden lifetime is measured from, in the order they are tried. */
|
|
7935
|
+
const ANCHOR_CLAIMS = ['iat', 'nbf'];
|
|
7936
|
+
const ttls = /* @__PURE__ */ signal({}, /* @ts-ignore */
|
|
7937
|
+
...(ngDevMode ? [{ debugName: "ttls" }] : /* istanbul ignore next */ []));
|
|
7938
|
+
/**
|
|
7939
|
+
* The access-token lifetime armed per auth provider name, in seconds, consumed by the
|
|
7940
|
+
* `<et-query-devtools>` panel. A provider on its token's real lifetime is absent rather than present
|
|
7941
|
+
* with it.
|
|
7942
|
+
*/
|
|
7943
|
+
const queryDevtoolsTokenTtls = /* @__PURE__ */ ttls.asReadonly();
|
|
7944
|
+
const tokenTtlAnchor = (options) => {
|
|
7945
|
+
const { payload, expiresInPropertyName } = options;
|
|
7946
|
+
if (!payload || typeof payload[expiresInPropertyName] !== 'number')
|
|
7947
|
+
return null;
|
|
7948
|
+
for (const claim of ANCHOR_CLAIMS) {
|
|
7949
|
+
const value = payload[claim];
|
|
7950
|
+
if (typeof value === 'number')
|
|
7951
|
+
return value;
|
|
7952
|
+
}
|
|
7953
|
+
return null;
|
|
7954
|
+
};
|
|
7955
|
+
/**
|
|
7956
|
+
* Whether an overridden lifetime can be applied to a decoded access token at all. It needs the claim
|
|
7957
|
+
* carrying the expiry - so a lifetime is never invented for a token that declares none - plus `iat` or
|
|
7958
|
+
* `nbf` to measure the new lifetime from.
|
|
7959
|
+
*/
|
|
7960
|
+
const canOverrideQueryDevtoolsTokenTtl = (options) => tokenTtlAnchor({ payload: options.payload, expiresInPropertyName: options.expiresInPropertyName ?? 'exp' }) !== null;
|
|
7961
|
+
/**
|
|
7962
|
+
* Presents one auth provider's access token as living `seconds` from the moment it was issued, rather
|
|
7963
|
+
* than as long as it says it does. Everything that reads the expiry sees the shortened lifetime - the
|
|
7964
|
+
* proactive refresh schedule, `withBearerAuthTokenExpirationWarning`, and the panel's own countdown -
|
|
7965
|
+
* so arming 60 seconds makes a real refresh happen a minute after each token is issued, and keeps
|
|
7966
|
+
* happening for every token that refresh brings back.
|
|
7967
|
+
*
|
|
7968
|
+
* It is a lifetime, not a remaining time: `0` presents the current token as long expired, which is what
|
|
7969
|
+
* makes a refresh happen at once. Nothing is persisted, so a reload leaves every provider on its real
|
|
7970
|
+
* lifetime.
|
|
7971
|
+
*
|
|
7972
|
+
* Part of the devtools contract consumed by `<et-query-devtools>`; a token's lifetime is not something
|
|
7973
|
+
* an application should override on itself.
|
|
7974
|
+
*/
|
|
7975
|
+
const setQueryDevtoolsTokenTtl = (options) => {
|
|
7976
|
+
const { providerName, seconds } = options;
|
|
7977
|
+
const clamped = Math.min(Math.max(Math.trunc(seconds) || 0, 0), QUERY_DEVTOOLS_TOKEN_TTL_LIMIT);
|
|
7978
|
+
ttls.update((current) => ({ ...current, [providerName]: clamped }));
|
|
7979
|
+
};
|
|
7980
|
+
/**
|
|
7981
|
+
* Puts one provider back on its token's real lifetime, or every provider when no name is given.
|
|
7982
|
+
*
|
|
7983
|
+
* @see setQueryDevtoolsTokenTtl
|
|
7984
|
+
*/
|
|
7985
|
+
const clearQueryDevtoolsTokenTtl = (providerName) => {
|
|
7986
|
+
ttls.update((current) => {
|
|
7987
|
+
if (providerName === undefined)
|
|
7988
|
+
return {};
|
|
7989
|
+
const { [providerName]: _removed, ...rest } = current;
|
|
7990
|
+
return rest;
|
|
7991
|
+
});
|
|
7992
|
+
};
|
|
7993
|
+
/**
|
|
7994
|
+
* The decoded access token as the devtools want it seen: the claim carrying the expiry rewritten to the
|
|
7995
|
+
* armed lifetime, measured from `iat`. Returns `payload` untouched when nothing is armed for the
|
|
7996
|
+
* provider, or when the token cannot carry the override - see {@link canOverrideQueryDevtoolsTokenTtl}.
|
|
7997
|
+
*
|
|
7998
|
+
* Installed as the token payload patcher by `provideQueryDevtools()`, and called directly by the panel
|
|
7999
|
+
* for its own countdown.
|
|
8000
|
+
*/
|
|
8001
|
+
const applyQueryDevtoolsTokenTtl = (options) => {
|
|
8002
|
+
const { payload, providerName, expiresInPropertyName = 'exp' } = options;
|
|
8003
|
+
const seconds = ttls()[providerName];
|
|
8004
|
+
if (seconds === undefined || !payload || typeof payload !== 'object')
|
|
8005
|
+
return payload;
|
|
8006
|
+
const record = payload;
|
|
8007
|
+
const anchor = tokenTtlAnchor({ payload: record, expiresInPropertyName });
|
|
8008
|
+
if (anchor === null)
|
|
8009
|
+
return payload;
|
|
8010
|
+
return { ...record, [expiresInPropertyName]: anchor + seconds };
|
|
8011
|
+
};
|
|
8012
|
+
|
|
7665
8013
|
/**
|
|
7666
8014
|
* How many destroyed queries the registry keeps. A tombstone holds the last response body it captured,
|
|
7667
8015
|
* so the list is capped for the same reason the repository caps its unused entries.
|
|
@@ -7942,6 +8290,7 @@ const provideQueryDevtools = (options) => {
|
|
|
7942
8290
|
setQueryDevtoolsAppInfo(options?.about);
|
|
7943
8291
|
initQueryDevtoolsOverridePersistence();
|
|
7944
8292
|
initQueryDevtoolsMocks();
|
|
8293
|
+
initQueryDevtoolsFaults();
|
|
7945
8294
|
setQueryDevtoolsSchemaLoader(options?.schema);
|
|
7946
8295
|
setQueryDevtoolsRegistrar(registerEntry);
|
|
7947
8296
|
setQueryDevtoolsStatsFactory(createQueryDevtoolsStats);
|
|
@@ -7949,6 +8298,7 @@ const provideQueryDevtools = (options) => {
|
|
|
7949
8298
|
setQueryDevtoolsOverridesFactory(createQueryDevtoolsOverrides);
|
|
7950
8299
|
setQueryDevtoolsFaultResolver(resolveQueryDevtoolsFaultForAttempt);
|
|
7951
8300
|
setQueryDevtoolsMockResolver(resolveQueryDevtoolsMockForAttempt);
|
|
8301
|
+
setQueryDevtoolsTokenPayloadPatcher(applyQueryDevtoolsTokenTtl);
|
|
7952
8302
|
if (!isDevMode()) {
|
|
7953
8303
|
console.warn('You are using the Query Devtools in production mode. This increases the size of your bundle and should only be used for development purposes.');
|
|
7954
8304
|
}
|
|
@@ -13489,5 +13839,5 @@ const createWebSocketClient = (options) => {
|
|
|
13489
13839
|
* Generated bundle index. Do not edit.
|
|
13490
13840
|
*/
|
|
13491
13841
|
|
|
13492
|
-
export { BasicAuthProvider, BearerAuthFeatureType, BooleanArrayQueryField, CLEAR_QUERY_ARGS, CustomHeaderAuthProvider, DEFAULT_KEEP_UNUSED_FOR, DEFAULT_QUERY_PERSISTENCE_MAX_AGE, DEFAULT_QUERY_PERSISTENCE_MAX_ENTRIES, DEFAULT_QUERY_PERSISTENCE_VERSION, DEFAULT_QUERY_PERSISTENCE_WRITE_DELAY, DateArrayQueryField, DateQueryField, EMPTY_QUERY_DEVTOOLS_FAULT, EntityStore, IGNORED_FILTER_COUNT_FIELDS, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, LegacyQuery, LegacyQueryCreator, MAX_QUERY_DEVTOOLS_TOMBSTONES, MAX_UNUSED_ENTRIES, NumberArrayQueryField, ParseHttpErrorCodeToMessageDePipe, ParseHttpErrorCodeToMessageEnPipe, ParseHttpErrorCodeToTitleDePipe, ParseHttpErrorCodeToTitleEnPipe, QUERY_CLIENT_DEVTOOLS_TOKEN, QUERY_DEVTOOLS_FAULT_STATUSES, QUERY_PERSISTENCE_STORE_VERSION, QUERY_SYNC_PROTOCOL_VERSION, QUERY_VERSION, QueryClientFeatureType, QueryDevtoolsComponent, QueryDirective, QueryFeatureType, QueryField, QueryForm, QueryRuntimeErrorCode, QueryShortNamePipe, QueryStore, SERVER_ERROR_KIND, SERVER_VIOLATION_ERROR_KIND, SPEED_BUFFER_TIME_IN_MS, SearchQueryField, SortQueryField, StringArrayQueryField, V2BearerAuthProvider, V2Query, V2QueryClient, V2QueryCreator, addQueryContainerHandling, applyQueryDevtoolsOverrides, applyQueryFeatures, armQueryDevtoolsMock, armQueryDevtoolsOverrideTransfer, authExtractTokensResponseMissingAccessToken, authExtractTokensResponseMissingRefreshToken, authExtractTokensResponseNotObject, authProviderFeatureUsedMultipleTimes, booleanArrayQueryField, buildQueryCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, circularQueryDependency, circularQueryDependencyChecker, clearQueryDevtoolsArmedMocks, clearQueryDevtoolsFaults, clearQueryDevtoolsMockStore, clearQueryDevtoolsOverrideStore, clearQueryDevtoolsStore, clearQueryDevtoolsTombstones, clearRestoredQueryDevtoolsOverrides, collectLeafPaths, collectQueryFormLinks, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, consumeSuppressQueryStackDevtools, contentfulGqlLikePaginationAdapter, countUnresolvedQueryDevtoolsOverrides, createAuthGuard, createBaseQuery, createBaseQueryCreator, createBearerAuthProvider, createDeleteQuery, createExecuteFn, createGetQuery, createGqlExecuteFn, createGqlMutationViaGet, createGqlMutationViaPost, createGqlQuery, createGqlQueryCreator, createGqlQueryViaGet, createGqlQueryViaPost, createHttpRequest, createIndexedDbQueryPersistenceAdapter, createInfinityQueryConfig, createLegacyQueryCreator, createNoopQueryPersistenceAdapter, createPagedQueryStack, createPatchQuery, createPersistentAuthFeature, createPostQuery, createPutQuery, createQuery, createQueryClient, createQueryCollection, createQueryCollectionSignal, createQueryCollectionSubject, createQueryContext, createQueryCreator, createQueryDevtoolsFormLinks, createQueryDevtoolsFormLinksRecorder, createQueryDevtoolsOverrides, createQueryDevtoolsOverridesRecorder, createQueryDevtoolsStats, createQueryDevtoolsStatsRecorder, createQueryErrorResponse, createQueryFeature, createQueryInvalidationFilter, createQueryKeyLockManager, createQueryObject, createQueryPersistenceEngine, createQueryRepository, createQuerySnapshotFn, createQueryStack, createQuerySyncEngine, createQuerySyncTransport, createSecureDeleteQuery, createSecureExecuteFactory, createSecureExecuteFn, createSecureGetQuery, createSecureGqlExecuteFn, createSecureGqlMutationViaGet, createSecureGqlMutationViaPost, createSecureGqlQuery, createSecureGqlQueryCreator, createSecureGqlQueryViaGet, createSecureGqlQueryViaPost, createSecurePatchQuery, createSecurePostQuery, createSecurePutQuery, createSecureQuery, createSecureQueryCreator, createTrackingFeature, createWebSocketClient, dateArrayQueryField, dateQueryField, decryptBearer, deepFreeze, def, defineQueryForm, deleteQueryDevtoolsMock, describeQueryDevtoolsFeatures, detectContentTypeHeader, detectPaginationShape, dynLikePaginationAdapter, effectComputed, emptyQueryArgs, ethletePaginationAdapter, executeUntilSettled, extractExpiresInSeconds, extractFormViolations, extractHtmlErrorMessage, extractQuery, fakePaginationAdapter, filterFailure, filterNull, filterQueryStates, filterSuccess, forEachHeader, formatQueryDevtoolsDuration, generateQueryDevtoolsNumberPreset, generateQueryDevtoolsStringPreset, getBearerAuthProviderName, getDefaultHeaders, getQueryClientName, getQueryFeatureUsage, getResponseUrl, ggLikePaginationAdapter, gql, gqlDataPropertyMissingInResponse, hasHeader, hasQueryDevtoolsOverridesAtPath, htmlErrorPayload, htmlQueryErrorParser, ignoreAutoRefresh, initQueryDevtoolsMocks, initQueryDevtoolsOverridePersistence, initQueryDevtoolsSettings, injectInfinityQueryResponseDelay, injectQueryContext, insertFrom, invalidBaseRouteError, invalidBodyError, invalidRouteError, invalidStateInsideSecureExecuteFactory, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isClassValidatorError, isCreateGqlQueryOptions, isCustomHeaderAuthProvider, isDateShapedLeaf, isEmptyString, isGqlQueryConfig, isHtmlErrorPayload, isLegacyQuery, isNaN$1 as isNaN, isPageOutOfRangeError, isQuery, isQueryCollection, isQueryDevtoolsEnabled, isQueryDevtoolsFaultArmed, isQueryDevtoolsRequestInterceptionEnabled, isQueryErrorResponse, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, isSymfonyFormViolationListError, isSymfonyListError, isSymfonyPagerfantaOutOfRangeError, isUnderInvalidatedUrl, legacyPrepareFallbackInjector, legacyPrepareWithoutInjectionContext, loadQueryDevtoolsSchema, mapToPaginated, mapViolationsToFormErrors, matchesQueryDevtoolsMockPattern, matchesQueryDevtoolsMockQuery, maybeExecute, measureQueryDevtoolsPayload, mergeHeaders, nestedEffect, noteQueryFormRead, numberArrayQueryField, pagedQueryStackNextPageCalledWithoutPreviousPage, pagedQueryStackPageBiggerThanTotalPages, pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, parseHttpErrorCodeToMessageDe, parseHttpErrorCodeToMessageEn, parseHttpErrorCodeToTitleDe, parseHttpErrorCodeToTitleEn, parseQueryDevtoolsOverrideTransfer, parseQueryRoute, pathParamsMissingInRouteFunctionError, provideInfinityQueryResponseDelay, provideLegacyPrepareFallback, provideQueryClientForDevtools, provideQueryDevtools, queryArrayComputed, queryClientFeatureUsedMultipleTimes, queryComputed, queryComputedTillTruthy, queryDevtoolsAbout, queryDevtoolsArmedMocks, queryDevtoolsEntries, queryDevtoolsFaults, queryDevtoolsFnDetail, queryDevtoolsMockId, queryDevtoolsMocks, queryDevtoolsOverridePersistence, queryDevtoolsRequestPath, queryDevtoolsResponseHistory, queryDevtoolsRestoredOverridesScope, queryDevtoolsSchemaNames, queryDevtoolsSchemaRoutes, queryDevtoolsSchemaState, queryDevtoolsSettings, queryDevtoolsStorage, queryErrorMessage, queryErrorMessages, queryExecute, queryFeatureUsedMultipleTimes, queryField, querySequence, querySequenceAlreadyRunning, queryStackTotalQueriesAndExpectedQueriesMismatch, queryStackWithArgsUsed, queryStackWithResponseUpdateUsed, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, queryStateErrorSignal, queryStateLoadingSignal, queryStateResponseSignal, queryStateSignal, readQueryDevtoolsStore, registerEthleteVersion, registerQueryDevtoolsEntry, registerQueryErrorParser, removeFrom, request, resetExecuteState, resetPageOnError, resolveInvalidationUrl, resolveQueryDevtoolsFault, resolveQueryDevtoolsFaultForAttempt, resolveQueryDevtoolsMock, resolveQueryDevtoolsMockForAttempt, restoredQueryDevtoolsOverrides, runDefaultQueryRetry, runQueryErrorParsers, saveQueryDevtoolsMock, searchQueryField, seedQueryDevtoolsSchemaBody, seedQueryDevtoolsSchemaRoute, serializeBody, serializeQueryDevtoolsOverrideTransfer, setDefaultQueryRetryFn, setQueryDevtoolsAppInfo, setQueryDevtoolsFault, setQueryDevtoolsFaultResolver, setQueryDevtoolsFormLinksFactory, setQueryDevtoolsMockResolver, setQueryDevtoolsOverridePersistence, setQueryDevtoolsOverridesFactory, setQueryDevtoolsOverridesScope, setQueryDevtoolsRegistrar, setQueryDevtoolsResponseHistory, setQueryDevtoolsSchemaLoader, setQueryDevtoolsSettings, setQueryDevtoolsStatsFactory, setupQueryDependencies, setupQueryExecuteState, setupQueryState, shouldAutoExecuteGqlQuery, shouldAutoExecuteQuery, shouldCacheQuery, shouldRetryRequest, silenceMissingWithArgsFeatureErrorUsedButWithArgsPresent, skipPaginationPageParamCalculator, smartDuplicateArrayItem, snapshotQueryDevtoolsHandle, sortQueryField, splitQueryConfig, stringArrayQueryField, stringifyQueryRouteParts, sumQueryDevtoolsStats, suppressNextQueryStackDevtools, switchQueryCollectionState, switchQueryState, symfonyQueryErrorParser, takeUntilResponse, toQuerySignal, toQuerySubject, tokensNotAvailableInsideAuthAndExec, tombstoneOf, transformArrayResponse, transformExecStateToQueryState, transformGql, transformMethod, transformPaginatedResponse, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray, uncacheableRequestHasAllowCacheParam, uncacheableRequestHasCacheKeyParam, unwrapQuerySyncMessage, v2BuildQueryCacheKey, v2ExtractExpiresInSeconds, v2ShouldCacheQuery, v2ShouldRetryRequest, validateWithQuery, validateWithV2Query, withArgs, withArgsQueryFeatureMissingButRouteIsFunction, withAuthenticationQuery, withAutoRefresh, withAutoRefreshUsedInManualQuery, withAutoRefreshUsedOnUnsupportedHttpMethod, withBearerAuthMultiTabSync, withDefaultRetry, withErrorHandling, withEthleteApiErrors, withHtmlErrorParsing, withInactivityLogout, withLogging, withMultiTabSync, withPageResetOnError, withPersistentAuth, withPolling, withPollingUsedOnUnsupportedHttpMethod, withQueryDevtoolsOverridePersistence, withQueryPersistence, withRefreshQuery, withResponseUpdate, withSuccessHandling, withSymfonyErrors, withTokenExpirationWarning, withTokenRevocation, withTracking, wrapAsObservableSignal, wrapQuerySyncMessage, writeQueryDevtoolsStore };
|
|
13842
|
+
export { BasicAuthProvider, BearerAuthFeatureType, BooleanArrayQueryField, CLEAR_QUERY_ARGS, CustomHeaderAuthProvider, DEFAULT_KEEP_UNUSED_FOR, DEFAULT_QUERY_PERSISTENCE_MAX_AGE, DEFAULT_QUERY_PERSISTENCE_MAX_ENTRIES, DEFAULT_QUERY_PERSISTENCE_VERSION, DEFAULT_QUERY_PERSISTENCE_WRITE_DELAY, DateArrayQueryField, DateQueryField, EMPTY_QUERY_DEVTOOLS_FAULT, EntityStore, IGNORED_FILTER_COUNT_FIELDS, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, LegacyQuery, LegacyQueryCreator, MAX_QUERY_DEVTOOLS_TOMBSTONES, MAX_UNUSED_ENTRIES, NumberArrayQueryField, ParseHttpErrorCodeToMessageDePipe, ParseHttpErrorCodeToMessageEnPipe, ParseHttpErrorCodeToTitleDePipe, ParseHttpErrorCodeToTitleEnPipe, QUERY_CLIENT_DEVTOOLS_TOKEN, QUERY_DEVTOOLS_FAULT_STATUSES, QUERY_DEVTOOLS_TOKEN_TTL_LIMIT, QUERY_PERSISTENCE_STORE_VERSION, QUERY_SYNC_PROTOCOL_VERSION, QUERY_VERSION, QueryClientFeatureType, QueryDevtoolsComponent, QueryDirective, QueryFeatureType, QueryField, QueryForm, QueryRuntimeErrorCode, QueryShortNamePipe, QueryStore, SERVER_ERROR_KIND, SERVER_VIOLATION_ERROR_KIND, SPEED_BUFFER_TIME_IN_MS, SearchQueryField, SortQueryField, StringArrayQueryField, V2BearerAuthProvider, V2Query, V2QueryClient, V2QueryCreator, addQueryContainerHandling, applyQueryDevtoolsOverrides, applyQueryDevtoolsTokenTtl, applyQueryFeatures, armAllQueryDevtoolsMocks, armQueryDevtoolsMock, armQueryDevtoolsOverrideTransfer, authExtractTokensResponseMissingAccessToken, authExtractTokensResponseMissingRefreshToken, authExtractTokensResponseNotObject, authProviderFeatureUsedMultipleTimes, booleanArrayQueryField, buildQueryCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, canOverrideQueryDevtoolsTokenTtl, castQueryCreatorTypes, circularQueryDependency, circularQueryDependencyChecker, clearQueryDevtoolsArmedMocks, clearQueryDevtoolsFaults, clearQueryDevtoolsMockStore, clearQueryDevtoolsOverrideStore, clearQueryDevtoolsStore, clearQueryDevtoolsTokenTtl, clearQueryDevtoolsTombstones, clearRestoredQueryDevtoolsOverrides, collectLeafPaths, collectQueryDevtoolsSchemaComponents, collectQueryFormLinks, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, consumeSuppressQueryStackDevtools, contentfulGqlLikePaginationAdapter, countUnresolvedQueryDevtoolsOverrides, createAuthGuard, createBaseQuery, createBaseQueryCreator, createBearerAuthProvider, createDeleteQuery, createExecuteFn, createGetQuery, createGqlExecuteFn, createGqlMutationViaGet, createGqlMutationViaPost, createGqlQuery, createGqlQueryCreator, createGqlQueryViaGet, createGqlQueryViaPost, createHttpRequest, createIndexedDbQueryPersistenceAdapter, createInfinityQueryConfig, createLegacyQueryCreator, createNoopQueryPersistenceAdapter, createPagedQueryStack, createPatchQuery, createPersistentAuthFeature, createPostQuery, createPutQuery, createQuery, createQueryClient, createQueryCollection, createQueryCollectionSignal, createQueryCollectionSubject, createQueryContext, createQueryCreator, createQueryDevtoolsFormLinks, createQueryDevtoolsFormLinksRecorder, createQueryDevtoolsOverrides, createQueryDevtoolsOverridesRecorder, createQueryDevtoolsStats, createQueryDevtoolsStatsRecorder, createQueryErrorResponse, createQueryFeature, createQueryInvalidationFilter, createQueryKeyLockManager, createQueryObject, createQueryPersistenceEngine, createQueryRepository, createQuerySnapshotFn, createQueryStack, createQuerySyncEngine, createQuerySyncTransport, createSecureDeleteQuery, createSecureExecuteFactory, createSecureExecuteFn, createSecureGetQuery, createSecureGqlExecuteFn, createSecureGqlMutationViaGet, createSecureGqlMutationViaPost, createSecureGqlQuery, createSecureGqlQueryCreator, createSecureGqlQueryViaGet, createSecureGqlQueryViaPost, createSecurePatchQuery, createSecurePostQuery, createSecurePutQuery, createSecureQuery, createSecureQueryCreator, createTrackingFeature, createWebSocketClient, dateArrayQueryField, dateQueryField, decryptBearer, deepFreeze, def, defineQueryForm, deleteQueryDevtoolsMock, describeQueryDevtoolsFeatures, detectContentTypeHeader, detectPaginationShape, dynLikePaginationAdapter, effectComputed, emptyQueryArgs, ethletePaginationAdapter, executeUntilSettled, extractExpiresInSeconds, extractFormViolations, extractHtmlErrorMessage, extractQuery, fakePaginationAdapter, filterFailure, filterNull, filterQueryStates, filterSuccess, forEachHeader, formatQueryDevtoolsDuration, generateQueryDevtoolsNumberPreset, generateQueryDevtoolsStringPreset, getBearerAuthProviderName, getDefaultHeaders, getQueryClientName, getQueryFeatureUsage, getResponseUrl, ggLikePaginationAdapter, gql, gqlDataPropertyMissingInResponse, hasHeader, hasQueryDevtoolsOverridesAtPath, htmlErrorPayload, htmlQueryErrorParser, ignoreAutoRefresh, initQueryDevtoolsFaults, initQueryDevtoolsMocks, initQueryDevtoolsOverridePersistence, initQueryDevtoolsSettings, injectInfinityQueryResponseDelay, injectQueryContext, insertFrom, invalidBaseRouteError, invalidBodyError, invalidRouteError, invalidStateInsideSecureExecuteFactory, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isClassValidatorError, isCreateGqlQueryOptions, isCustomHeaderAuthProvider, isDateShapedLeaf, isEmptyString, isGqlQueryConfig, isHtmlErrorPayload, isLegacyQuery, isNaN$1 as isNaN, isPageOutOfRangeError, isQuery, isQueryCollection, isQueryDevtoolsEnabled, isQueryDevtoolsFaultArmed, isQueryDevtoolsRequestInterceptionEnabled, isQueryErrorResponse, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, isSymfonyFormViolationListError, isSymfonyListError, isSymfonyPagerfantaOutOfRangeError, isUnderInvalidatedUrl, legacyPrepareFallbackInjector, legacyPrepareWithoutInjectionContext, loadQueryDevtoolsSchema, mapToPaginated, mapViolationsToFormErrors, matchesQueryDevtoolsMockPattern, matchesQueryDevtoolsMockQuery, maybeExecute, measureQueryDevtoolsPayload, mergeHeaders, nestedEffect, noteQueryFormRead, numberArrayQueryField, pagedQueryStackNextPageCalledWithoutPreviousPage, pagedQueryStackPageBiggerThanTotalPages, pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, parseHttpErrorCodeToMessageDe, parseHttpErrorCodeToMessageEn, parseHttpErrorCodeToTitleDe, parseHttpErrorCodeToTitleEn, parseQueryDevtoolsOverrideTransfer, parseQueryRoute, patchQueryDevtoolsTokenPayload, pathParamsMissingInRouteFunctionError, provideInfinityQueryResponseDelay, provideLegacyPrepareFallback, provideQueryClientForDevtools, provideQueryDevtools, queryArrayComputed, queryClientFeatureUsedMultipleTimes, queryComputed, queryComputedTillTruthy, queryDevtoolsAbout, queryDevtoolsArmedMocks, queryDevtoolsArmedMocksRestored, queryDevtoolsEntries, queryDevtoolsFaults, queryDevtoolsFaultsRestored, queryDevtoolsFnDetail, queryDevtoolsMockId, queryDevtoolsMocks, queryDevtoolsOverridePersistence, queryDevtoolsRequestPath, queryDevtoolsResponseHistory, queryDevtoolsRestoredOverridesScope, queryDevtoolsSchemaNames, queryDevtoolsSchemaRoutes, queryDevtoolsSchemaState, queryDevtoolsSettings, queryDevtoolsStorage, queryDevtoolsTokenTtls, queryErrorMessage, queryErrorMessages, queryExecute, queryFeatureUsedMultipleTimes, queryField, querySequence, querySequenceAlreadyRunning, queryStackTotalQueriesAndExpectedQueriesMismatch, queryStackWithArgsUsed, queryStackWithResponseUpdateUsed, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, queryStateErrorSignal, queryStateLoadingSignal, queryStateResponseSignal, queryStateSignal, readQueryDevtoolsStore, registerEthleteVersion, registerQueryDevtoolsEntry, registerQueryErrorParser, removeFrom, request, resetExecuteState, resetPageOnError, resolveInvalidationUrl, resolveQueryDevtoolsFault, resolveQueryDevtoolsFaultForAttempt, resolveQueryDevtoolsMock, resolveQueryDevtoolsMockForAttempt, restoredQueryDevtoolsOverrides, runDefaultQueryRetry, runQueryErrorParsers, saveQueryDevtoolsMock, searchQueryField, seedQueryDevtoolsSchemaBody, seedQueryDevtoolsSchemaRoute, serializeBody, serializeQueryDevtoolsOverrideTransfer, setDefaultQueryRetryFn, setQueryDevtoolsAppInfo, setQueryDevtoolsArmedMocksScope, setQueryDevtoolsFault, setQueryDevtoolsFaultResolver, setQueryDevtoolsFaultsScope, setQueryDevtoolsFormLinksFactory, setQueryDevtoolsMockResolver, setQueryDevtoolsOverridePersistence, setQueryDevtoolsOverridesFactory, setQueryDevtoolsOverridesScope, setQueryDevtoolsRegistrar, setQueryDevtoolsResponseHistory, setQueryDevtoolsSchemaLoader, setQueryDevtoolsSettings, setQueryDevtoolsStatsFactory, setQueryDevtoolsTokenPayloadPatcher, setQueryDevtoolsTokenTtl, setupQueryDependencies, setupQueryExecuteState, setupQueryState, shouldAutoExecuteGqlQuery, shouldAutoExecuteQuery, shouldCacheQuery, shouldRetryRequest, silenceMissingWithArgsFeatureErrorUsedButWithArgsPresent, skipPaginationPageParamCalculator, smartDuplicateArrayItem, snapshotQueryDevtoolsHandle, sortQueryField, splitQueryConfig, stringArrayQueryField, stringifyQueryRouteParts, sumQueryDevtoolsStats, suppressNextQueryStackDevtools, switchQueryCollectionState, switchQueryState, symfonyQueryErrorParser, takeUntilResponse, toQuerySignal, toQuerySubject, tokensNotAvailableInsideAuthAndExec, tombstoneOf, transformArrayResponse, transformExecStateToQueryState, transformGql, transformMethod, transformPaginatedResponse, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray, uncacheableRequestHasAllowCacheParam, uncacheableRequestHasCacheKeyParam, unwrapQuerySyncMessage, v2BuildQueryCacheKey, v2ExtractExpiresInSeconds, v2ShouldCacheQuery, v2ShouldRetryRequest, validateWithQuery, validateWithV2Query, withArgs, withArgsQueryFeatureMissingButRouteIsFunction, withAuthenticationQuery, withAutoRefresh, withAutoRefreshUsedInManualQuery, withAutoRefreshUsedOnUnsupportedHttpMethod, withBearerAuthMultiTabSync, withDefaultRetry, withErrorHandling, withEthleteApiErrors, withHtmlErrorParsing, withInactivityLogout, withLogging, withMultiTabSync, withPageResetOnError, withPersistentAuth, withPolling, withPollingUsedOnUnsupportedHttpMethod, withQueryDevtoolsOverridePersistence, withQueryPersistence, withRefreshQuery, withResponseUpdate, withSuccessHandling, withSymfonyErrors, withTokenExpirationWarning, withTokenRevocation, withTracking, wrapAsObservableSignal, wrapQuerySyncMessage, writeQueryDevtoolsStore };
|
|
13493
13843
|
//# sourceMappingURL=ethlete-query.mjs.map
|