@ethlete/query 6.0.0-next.41 → 6.0.0-next.43
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 +30 -0
- package/fesm2022/ethlete-query.mjs +461 -90
- package/fesm2022/ethlete-query.mjs.map +1 -1
- package/migrations.json +44 -0
- package/package.json +4 -1
- package/types/ethlete-query.d.ts +58 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Injector, effect, DestroyRef, InjectionToken, EnvironmentInjector, ElementRef, ErrorHandler, createEnvironmentInjector, untracked, signal, linkedSignal, computed, runInInjectionContext, isDevMode, PLATFORM_ID, resource, DOCUMENT, VERSION, makeEnvironmentProviders,
|
|
2
|
+
import { inject, Injector, effect, DestroyRef, InjectionToken, EnvironmentInjector, ElementRef, ErrorHandler, createEnvironmentInjector, untracked, signal, linkedSignal, computed, runInInjectionContext, isDevMode, PLATFORM_ID, resource, DOCUMENT, VERSION, makeEnvironmentProviders, provideEnvironmentInitializer, ApplicationRef, assertInInjectionContext, ChangeDetectorRef, ViewContainerRef, TemplateRef, Input, Directive, input, Pipe, ViewEncapsulation, Component, NgZone } from '@angular/core';
|
|
3
3
|
import { UrlTree, Router, RedirectCommand, ActivatedRoute } from '@angular/router';
|
|
4
4
|
import { Observable, defer, from, filter, Subject, Subscription, throwError, of, timer, switchMap, tap, retry, catchError, EMPTY as EMPTY$1, take, takeUntil, finalize, mergeMap, toArray, map, merge, takeWhile, firstValueFrom, race, concatMap, fromEvent, throttleTime, interval, startWith, pairwise, BehaviorSubject, combineLatest, ReplaySubject, shareReplay, skip, withLatestFrom, debounceTime } from 'rxjs';
|
|
5
5
|
import { defineStaticProvider, RuntimeError, clamp, randomId, defineRootProvider, isObject, injectUnsavedChangesCoordinator, injectRoute, getCookie, deleteCookie, setCookie, CORE_VERSION, createDestroy, computedTillTruthy, defineProvider, toProvideFn, toInjectFn, nextFrame, injectQueryParams, injectQueryParamChanges, clone, equal, ET_PROPERTY_REMOVED, previousSignalValue } from '@ethlete/core';
|
|
@@ -5279,6 +5279,10 @@ const createBearerAuthProviderImpl = (config) => {
|
|
|
5279
5279
|
// executionState (e.g. `{ type: 'login', state: 'success' }`) via setupBearerQueryRegistry's
|
|
5280
5280
|
// execute(), so that internal path calls applyTokens directly to avoid stomping it with this.
|
|
5281
5281
|
const setTokens = (access, refresh) => {
|
|
5282
|
+
// A seed supersedes what is in flight, the way a logout does: the tokens are here, so a cookie
|
|
5283
|
+
// auto-login or a refresh still out with an older token can only report a failure that no longer
|
|
5284
|
+
// means anything - or apply the pair it comes back with over this one.
|
|
5285
|
+
invalidateTokenIssuingExecutions();
|
|
5282
5286
|
applyTokens(access, refresh);
|
|
5283
5287
|
executionState.set({ type: 'tokenSeed', state: 'success' });
|
|
5284
5288
|
};
|
|
@@ -5339,6 +5343,7 @@ const createBearerAuthProviderImpl = (config) => {
|
|
|
5339
5343
|
logout,
|
|
5340
5344
|
afterTokenRefresh$,
|
|
5341
5345
|
queries: queries,
|
|
5346
|
+
latestExecutedQuery: latestExecutedQuery.asReadonly(),
|
|
5342
5347
|
executionState: executionState.asReadonly(),
|
|
5343
5348
|
hasTokenIssuingExecutionInFlight,
|
|
5344
5349
|
};
|
|
@@ -5804,7 +5809,18 @@ const withRefreshQuery = (key, config) => {
|
|
|
5804
5809
|
});
|
|
5805
5810
|
effect(() => {
|
|
5806
5811
|
const state = context.executionState();
|
|
5807
|
-
if (state?.
|
|
5812
|
+
if (state?.state !== 'error')
|
|
5813
|
+
return;
|
|
5814
|
+
// `withPersistentAuth` spends the cookie's refresh token through this very query, and that
|
|
5815
|
+
// execution reports as `autoLogin` rather than as `tokenRefresh`. Judged by its type alone it
|
|
5816
|
+
// would end nothing: the tab keeps a rejected cookie's error state for good, `sessionEndCause`
|
|
5817
|
+
// never says `expired`, and an app gated on either never leaves its startup screen. The token
|
|
5818
|
+
// check keeps a session another tab handed over mid-request out of it - that session is not
|
|
5819
|
+
// this restore's to end.
|
|
5820
|
+
const isRejectedRestore = state.type === 'autoLogin' &&
|
|
5821
|
+
untracked(context.latestExecutedQuery)?.key === key &&
|
|
5822
|
+
!untracked(context.accessToken);
|
|
5823
|
+
if (state.type !== 'tokenRefresh' && !isRejectedRestore)
|
|
5808
5824
|
return;
|
|
5809
5825
|
onRefreshFailure({ error: state.error, logout: () => context.logout('expired') });
|
|
5810
5826
|
});
|
|
@@ -7098,20 +7114,71 @@ const queryDevtoolsAbout = () => ({
|
|
|
7098
7114
|
app,
|
|
7099
7115
|
});
|
|
7100
7116
|
|
|
7117
|
+
/**
|
|
7118
|
+
* Whether a devtools UI is on the page, which is what the floating pills follow. Kept apart from the
|
|
7119
|
+
* pills themselves so `@ethlete/query-devtools/toggle` can declare itself without pulling the pill
|
|
7120
|
+
* renderer into the bundle an application ships.
|
|
7121
|
+
*/
|
|
7122
|
+
let mounted = 0;
|
|
7123
|
+
let settled = false;
|
|
7124
|
+
let notify = null;
|
|
7125
|
+
/**
|
|
7126
|
+
* Declares a devtools UI on the page, and takes the declaration back when it goes. The floating pills
|
|
7127
|
+
* paint only while one is mounted, so an application that renders no devtools trigger shows no pills
|
|
7128
|
+
* either.
|
|
7129
|
+
*
|
|
7130
|
+
* Part of the devtools contract. **Not part of the general public contract.**
|
|
7131
|
+
*/
|
|
7132
|
+
const setQueryDevtoolsUiMounted = (isMounted) => {
|
|
7133
|
+
mounted = Math.max(0, mounted + (isMounted ? 1 : -1));
|
|
7134
|
+
notify?.();
|
|
7135
|
+
};
|
|
7136
|
+
/**
|
|
7137
|
+
* Says the application has rendered and settled, which is what lets the pills stop painting where no
|
|
7138
|
+
* devtools UI is mounted. Called by `provideQueryDevtools()`.
|
|
7139
|
+
* @internal
|
|
7140
|
+
*/
|
|
7141
|
+
const markQueryDevtoolsAppSettled = () => {
|
|
7142
|
+
settled = true;
|
|
7143
|
+
notify?.();
|
|
7144
|
+
};
|
|
7145
|
+
/**
|
|
7146
|
+
* Whether the pills may paint. Until the application settles they do whatever the UI does: a boot that
|
|
7147
|
+
* hangs on the backend it was just pointed at renders no component at all, and is the case they exist
|
|
7148
|
+
* for.
|
|
7149
|
+
* @internal
|
|
7150
|
+
*/
|
|
7151
|
+
const queryDevtoolsPillsAllowed = () => mounted > 0 || !settled;
|
|
7152
|
+
/** Hands the pills a way to repaint on a change here. Called by the pill renderer. @internal */
|
|
7153
|
+
const onQueryDevtoolsUiChange = (listener) => {
|
|
7154
|
+
notify = listener;
|
|
7155
|
+
};
|
|
7156
|
+
|
|
7101
7157
|
const HOST_ID = 'et-query-devtools-pill';
|
|
7102
7158
|
/** What the picker writes for "let the application decide", which is the key removed. */
|
|
7103
7159
|
const DEFAULT_VALUE = '';
|
|
7104
7160
|
/** Prefixes a production env's name, so the open dropdown says which option is the real backend. */
|
|
7105
7161
|
const PRODUCTION_MARK = '⚠ ';
|
|
7162
|
+
/** Holds `1` while the pills are folded into the summary chip. Unwritten reads as folded. */
|
|
7163
|
+
const COLLAPSED_KEY = 'et-query-devtools-pills-collapsed';
|
|
7106
7164
|
const STYLE = `
|
|
7107
7165
|
:host {
|
|
7166
|
+
--_accent: var(--et-theme-color-primary-solid, #60a5fa);
|
|
7167
|
+
--_surface: linear-gradient(135deg, #1f1f23, #2a2a30);
|
|
7168
|
+
--_ring: inset 0 0 0 1px rgb(255 255 255 / 0.08);
|
|
7169
|
+
--_lift: 0 6px 20px rgb(0 0 0 / 0.35);
|
|
7170
|
+
--_control: 24px;
|
|
7171
|
+
|
|
7108
7172
|
position: fixed;
|
|
7109
7173
|
display: flex;
|
|
7110
7174
|
flex-direction: column;
|
|
7111
|
-
|
|
7112
|
-
|
|
7175
|
+
/* Stretch, not flex-end: it hands every pill the widest pill's width, so the stack keeps one left
|
|
7176
|
+
edge as well as one right edge. */
|
|
7177
|
+
align-items: stretch;
|
|
7178
|
+
gap: 6px 8px;
|
|
7113
7179
|
inset-block-end: 64px;
|
|
7114
7180
|
inset-inline-end: 16px;
|
|
7181
|
+
max-inline-size: min(420px, calc(100vw - 32px));
|
|
7115
7182
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
7116
7183
|
font-size: 13px;
|
|
7117
7184
|
/* One below the panel and the toggle button (2147483010), so an open panel covers the pill - the
|
|
@@ -7119,47 +7186,97 @@ const STYLE = `
|
|
|
7119
7186
|
z-index: 2147483009;
|
|
7120
7187
|
}
|
|
7121
7188
|
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
display: inline-flex;
|
|
7189
|
+
.pill {
|
|
7190
|
+
display: flex;
|
|
7126
7191
|
align-items: center;
|
|
7127
7192
|
gap: 8px;
|
|
7128
|
-
|
|
7193
|
+
box-sizing: border-box;
|
|
7194
|
+
block-size: 34px;
|
|
7195
|
+
padding-inline: 12px 5px;
|
|
7129
7196
|
border-radius: 999px;
|
|
7130
|
-
background:
|
|
7197
|
+
background: var(--_surface);
|
|
7131
7198
|
color: #fafafa;
|
|
7132
7199
|
box-shadow:
|
|
7133
|
-
|
|
7134
|
-
|
|
7200
|
+
var(--_lift),
|
|
7201
|
+
var(--_ring);
|
|
7202
|
+
}
|
|
7203
|
+
|
|
7204
|
+
.lead {
|
|
7205
|
+
display: inline-flex;
|
|
7206
|
+
flex: none;
|
|
7207
|
+
align-items: center;
|
|
7208
|
+
gap: 6px;
|
|
7209
|
+
overflow: hidden;
|
|
7135
7210
|
}
|
|
7136
7211
|
|
|
7137
7212
|
.name {
|
|
7138
|
-
color: #
|
|
7139
|
-
font-size:
|
|
7213
|
+
color: #8f8f98;
|
|
7214
|
+
font-size: 10px;
|
|
7140
7215
|
font-weight: 600;
|
|
7141
|
-
letter-spacing: 0.
|
|
7216
|
+
letter-spacing: 0.08em;
|
|
7142
7217
|
line-height: 1;
|
|
7143
7218
|
text-transform: uppercase;
|
|
7219
|
+
white-space: nowrap;
|
|
7144
7220
|
}
|
|
7145
7221
|
|
|
7146
7222
|
select {
|
|
7147
|
-
|
|
7148
|
-
|
|
7223
|
+
flex: 1;
|
|
7224
|
+
min-inline-size: 0;
|
|
7225
|
+
box-sizing: border-box;
|
|
7226
|
+
block-size: var(--_control);
|
|
7227
|
+
padding-inline: 8px 24px;
|
|
7149
7228
|
border: none;
|
|
7150
|
-
border-radius:
|
|
7151
|
-
|
|
7229
|
+
border-radius: 7px;
|
|
7230
|
+
appearance: none;
|
|
7231
|
+
background-color: rgb(255 255 255 / 0.07);
|
|
7232
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23a1a1aa' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
7233
|
+
background-repeat: no-repeat;
|
|
7234
|
+
background-position: right 8px center;
|
|
7235
|
+
background-size: 9px 6px;
|
|
7152
7236
|
box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.12);
|
|
7153
7237
|
color: #fafafa;
|
|
7154
7238
|
font: inherit;
|
|
7155
7239
|
font-size: 12px;
|
|
7240
|
+
line-height: var(--_control);
|
|
7241
|
+
text-overflow: ellipsis;
|
|
7242
|
+
cursor: pointer;
|
|
7243
|
+
}
|
|
7244
|
+
|
|
7245
|
+
.pill button {
|
|
7246
|
+
flex: none;
|
|
7247
|
+
box-sizing: border-box;
|
|
7248
|
+
block-size: var(--_control);
|
|
7249
|
+
padding-inline: 9px;
|
|
7250
|
+
border: none;
|
|
7251
|
+
border-radius: 7px;
|
|
7252
|
+
background: rgb(255 255 255 / 0.07);
|
|
7253
|
+
box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.12);
|
|
7254
|
+
color: #d4d4d8;
|
|
7255
|
+
font: inherit;
|
|
7256
|
+
font-size: 11px;
|
|
7156
7257
|
font-weight: 600;
|
|
7157
7258
|
line-height: 1;
|
|
7158
7259
|
cursor: pointer;
|
|
7159
7260
|
}
|
|
7160
7261
|
|
|
7161
|
-
select:hover
|
|
7262
|
+
select:hover,
|
|
7263
|
+
.pill button:hover {
|
|
7264
|
+
background-color: rgb(255 255 255 / 0.13);
|
|
7265
|
+
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--_accent) 60%, transparent);
|
|
7266
|
+
color: #fafafa;
|
|
7267
|
+
}
|
|
7268
|
+
|
|
7269
|
+
select:focus-visible,
|
|
7270
|
+
.pill button:focus-visible,
|
|
7271
|
+
.chip:focus-visible {
|
|
7272
|
+
outline: 2px solid var(--_accent);
|
|
7273
|
+
outline-offset: 2px;
|
|
7274
|
+
}
|
|
7275
|
+
|
|
7276
|
+
.pill button[data-on] {
|
|
7277
|
+
background: color-mix(in srgb, var(--_accent) 20%, transparent);
|
|
7162
7278
|
box-shadow: inset 0 0 0 1px var(--_accent);
|
|
7279
|
+
color: #fafafa;
|
|
7163
7280
|
}
|
|
7164
7281
|
|
|
7165
7282
|
/* The popup is painted by the browser, which does not inherit the pill's dark background. */
|
|
@@ -7168,7 +7285,7 @@ const STYLE = `
|
|
|
7168
7285
|
color: #fafafa;
|
|
7169
7286
|
}
|
|
7170
7287
|
|
|
7171
|
-
|
|
7288
|
+
.pill[data-production] {
|
|
7172
7289
|
background: linear-gradient(135deg, #7f1d1d, #b91c1c);
|
|
7173
7290
|
color: #fff;
|
|
7174
7291
|
box-shadow:
|
|
@@ -7176,50 +7293,119 @@ const STYLE = `
|
|
|
7176
7293
|
inset 0 0 0 1px rgb(254 202 202 / 0.7);
|
|
7177
7294
|
}
|
|
7178
7295
|
|
|
7179
|
-
|
|
7296
|
+
.pill[data-production] .name {
|
|
7180
7297
|
color: #fee2e2;
|
|
7181
7298
|
}
|
|
7182
7299
|
|
|
7183
|
-
|
|
7184
|
-
|
|
7300
|
+
.pill[data-production] .mark {
|
|
7301
|
+
flex: none;
|
|
7302
|
+
font-size: 14px;
|
|
7185
7303
|
line-height: 1;
|
|
7186
7304
|
}
|
|
7187
7305
|
|
|
7188
|
-
|
|
7189
|
-
background: rgb(0 0 0 / 0.35);
|
|
7306
|
+
.pill[data-production] select {
|
|
7307
|
+
background-color: rgb(0 0 0 / 0.35);
|
|
7308
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23fecaca' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
7190
7309
|
box-shadow: inset 0 0 0 1px rgb(254 202 202 / 0.6);
|
|
7191
7310
|
text-transform: uppercase;
|
|
7192
7311
|
}
|
|
7193
7312
|
|
|
7194
|
-
|
|
7195
|
-
background:
|
|
7313
|
+
.pill[data-production] select:hover {
|
|
7314
|
+
background-color: rgb(0 0 0 / 0.5);
|
|
7315
|
+
box-shadow: inset 0 0 0 1px #fecaca;
|
|
7196
7316
|
}
|
|
7197
7317
|
|
|
7198
|
-
|
|
7199
|
-
|
|
7318
|
+
.pill[data-production] option {
|
|
7319
|
+
background: #450a0a;
|
|
7200
7320
|
}
|
|
7201
7321
|
|
|
7202
|
-
|
|
7203
|
-
|
|
7322
|
+
.chip {
|
|
7323
|
+
display: inline-flex;
|
|
7324
|
+
align-items: center;
|
|
7325
|
+
align-self: flex-end;
|
|
7326
|
+
gap: 8px;
|
|
7327
|
+
box-sizing: border-box;
|
|
7328
|
+
block-size: 28px;
|
|
7329
|
+
max-inline-size: 100%;
|
|
7330
|
+
padding-inline: 11px 12px;
|
|
7204
7331
|
border: none;
|
|
7205
|
-
border-radius:
|
|
7206
|
-
background:
|
|
7207
|
-
box-shadow:
|
|
7332
|
+
border-radius: 999px;
|
|
7333
|
+
background: var(--_surface);
|
|
7334
|
+
box-shadow:
|
|
7335
|
+
var(--_lift),
|
|
7336
|
+
var(--_ring);
|
|
7208
7337
|
color: #fafafa;
|
|
7209
7338
|
font: inherit;
|
|
7210
|
-
font-size:
|
|
7339
|
+
font-size: 12px;
|
|
7211
7340
|
font-weight: 600;
|
|
7212
|
-
line-height: 1
|
|
7341
|
+
line-height: 1;
|
|
7213
7342
|
cursor: pointer;
|
|
7214
7343
|
}
|
|
7215
7344
|
|
|
7216
|
-
|
|
7217
|
-
box-shadow:
|
|
7345
|
+
.chip:hover {
|
|
7346
|
+
box-shadow:
|
|
7347
|
+
var(--_lift),
|
|
7348
|
+
inset 0 0 0 1px var(--_accent);
|
|
7349
|
+
}
|
|
7350
|
+
|
|
7351
|
+
.caret {
|
|
7352
|
+
flex: none;
|
|
7353
|
+
color: var(--_accent);
|
|
7354
|
+
font-size: 8px;
|
|
7355
|
+
line-height: 1;
|
|
7356
|
+
transition: transform 0.15s ease;
|
|
7218
7357
|
}
|
|
7219
7358
|
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7359
|
+
.values {
|
|
7360
|
+
overflow: hidden;
|
|
7361
|
+
min-inline-size: 0;
|
|
7362
|
+
color: #d4d4d8;
|
|
7363
|
+
text-overflow: ellipsis;
|
|
7364
|
+
white-space: nowrap;
|
|
7365
|
+
}
|
|
7366
|
+
|
|
7367
|
+
.fold {
|
|
7368
|
+
color: #8f8f98;
|
|
7369
|
+
font-size: 11px;
|
|
7370
|
+
letter-spacing: 0.04em;
|
|
7371
|
+
}
|
|
7372
|
+
|
|
7373
|
+
:host([data-collapsed]) .pill,
|
|
7374
|
+
:host([data-collapsed]) .fold {
|
|
7375
|
+
display: none;
|
|
7376
|
+
}
|
|
7377
|
+
|
|
7378
|
+
:host(:not([data-collapsed])) .caret {
|
|
7379
|
+
transform: rotate(180deg);
|
|
7380
|
+
}
|
|
7381
|
+
|
|
7382
|
+
:host(:not([data-collapsed])) .values {
|
|
7383
|
+
display: none;
|
|
7384
|
+
}
|
|
7385
|
+
|
|
7386
|
+
/* Subgrid, where it exists: one set of columns for the whole stack, so every picker starts and ends
|
|
7387
|
+
on the same edge whatever its provider is called. The flex rules above are the fallback. */
|
|
7388
|
+
@supports (grid-template-columns: subgrid) {
|
|
7389
|
+
:host {
|
|
7390
|
+
display: grid;
|
|
7391
|
+
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
7392
|
+
}
|
|
7393
|
+
|
|
7394
|
+
.pill {
|
|
7395
|
+
display: grid;
|
|
7396
|
+
grid-column: 1 / -1;
|
|
7397
|
+
grid-template-columns: subgrid;
|
|
7398
|
+
}
|
|
7399
|
+
|
|
7400
|
+
/* Nothing follows the picker on an env pill, so it takes the session pill's button column too. */
|
|
7401
|
+
.pill:not([data-auth]) select {
|
|
7402
|
+
grid-column: 2 / -1;
|
|
7403
|
+
}
|
|
7404
|
+
|
|
7405
|
+
.chip {
|
|
7406
|
+
grid-column: 1 / -1;
|
|
7407
|
+
justify-self: end;
|
|
7408
|
+
}
|
|
7223
7409
|
}
|
|
7224
7410
|
|
|
7225
7411
|
/* The whole viewport, so the warning is on screen wherever the reader is looking. Outside the pill's
|
|
@@ -7235,7 +7421,7 @@ const STYLE = `
|
|
|
7235
7421
|
}
|
|
7236
7422
|
|
|
7237
7423
|
@media (prefers-reduced-motion: no-preference) {
|
|
7238
|
-
|
|
7424
|
+
.pill[data-production] {
|
|
7239
7425
|
animation: et-qd-api-env-pulse 1.6s ease-in-out infinite;
|
|
7240
7426
|
}
|
|
7241
7427
|
|
|
@@ -7273,6 +7459,28 @@ const STYLE = `
|
|
|
7273
7459
|
/** The env a stored value lands on, which is the switch's own fallback while nothing is stored. */
|
|
7274
7460
|
const resolvedEnvOf = (apiSwitch, stored) => apiSwitch.envs.find((env) => env.id === (stored || apiSwitch.fallback));
|
|
7275
7461
|
const nameOf = (env) => `${env.production ? PRODUCTION_MARK : ''}${env.label ?? env.id}`;
|
|
7462
|
+
/** The one value a folded switch reads as: the env behind the pick, or a typed URL. */
|
|
7463
|
+
const summaryOfSwitch = (apiSwitch, stored) => {
|
|
7464
|
+
const env = resolvedEnvOf(apiSwitch, stored);
|
|
7465
|
+
return env ? nameOf(env) : stored || apiSwitch.name;
|
|
7466
|
+
};
|
|
7467
|
+
const summaryOfAuthRow = (row) => (row.tabLocal ? `${row.current} · own tab` : row.current);
|
|
7468
|
+
const readCollapsed = () => {
|
|
7469
|
+
try {
|
|
7470
|
+
return window.localStorage.getItem(COLLAPSED_KEY) !== '0';
|
|
7471
|
+
}
|
|
7472
|
+
catch {
|
|
7473
|
+
return true;
|
|
7474
|
+
}
|
|
7475
|
+
};
|
|
7476
|
+
const writeCollapsed = (collapsed) => {
|
|
7477
|
+
try {
|
|
7478
|
+
window.localStorage.setItem(COLLAPSED_KEY, collapsed ? '1' : '0');
|
|
7479
|
+
}
|
|
7480
|
+
catch {
|
|
7481
|
+
// ignore (private mode / disabled storage / quota)
|
|
7482
|
+
}
|
|
7483
|
+
};
|
|
7276
7484
|
const optionsOf = (apiSwitch, stored) => {
|
|
7277
7485
|
const fallback = apiSwitch.envs.find((env) => env.id === apiSwitch.fallback);
|
|
7278
7486
|
const options = [
|
|
@@ -7293,21 +7501,27 @@ const optionsOf = (apiSwitch, stored) => {
|
|
|
7293
7501
|
};
|
|
7294
7502
|
const buildSwitch = (doc, apiSwitch, stored, pick) => {
|
|
7295
7503
|
const production = resolvedEnvOf(apiSwitch, stored)?.production === true;
|
|
7296
|
-
|
|
7297
|
-
|
|
7504
|
+
// A div, not a label: a label forwards its own hover to the control it names, so a pointer over the
|
|
7505
|
+
// pill's trailing button would light the picker up as well.
|
|
7506
|
+
const pill = doc.createElement('div');
|
|
7507
|
+
pill.className = 'pill';
|
|
7508
|
+
pill.title = production
|
|
7298
7509
|
? `${apiSwitch.name} points at production. The data is real. Picking reloads the page.`
|
|
7299
7510
|
: `${apiSwitch.name} — picking reloads the page`;
|
|
7511
|
+
const lead = doc.createElement('span');
|
|
7512
|
+
lead.className = 'lead';
|
|
7300
7513
|
if (production) {
|
|
7301
|
-
|
|
7514
|
+
pill.setAttribute('data-production', '');
|
|
7302
7515
|
const mark = doc.createElement('span');
|
|
7303
7516
|
mark.className = 'mark';
|
|
7304
7517
|
mark.textContent = '⚠';
|
|
7305
7518
|
mark.setAttribute('aria-hidden', 'true');
|
|
7306
|
-
|
|
7519
|
+
lead.append(mark);
|
|
7307
7520
|
}
|
|
7308
7521
|
const name = doc.createElement('span');
|
|
7309
7522
|
name.className = 'name';
|
|
7310
7523
|
name.textContent = production ? `${apiSwitch.name} · live` : apiSwitch.name;
|
|
7524
|
+
lead.append(name);
|
|
7311
7525
|
const select = doc.createElement('select');
|
|
7312
7526
|
select.setAttribute('aria-label', apiSwitch.name);
|
|
7313
7527
|
for (const option of optionsOf(apiSwitch, stored)) {
|
|
@@ -7319,27 +7533,35 @@ const buildSwitch = (doc, apiSwitch, stored, pick) => {
|
|
|
7319
7533
|
select.append(element);
|
|
7320
7534
|
}
|
|
7321
7535
|
select.addEventListener('change', () => pick(apiSwitch.storageKey, select.value === DEFAULT_VALUE ? null : select.value));
|
|
7322
|
-
|
|
7323
|
-
return
|
|
7536
|
+
pill.append(lead, select);
|
|
7537
|
+
return pill;
|
|
7324
7538
|
};
|
|
7325
7539
|
let envState = null;
|
|
7326
7540
|
let authState = null;
|
|
7327
7541
|
const buildAuthRow = (doc, row) => {
|
|
7328
|
-
const
|
|
7329
|
-
|
|
7330
|
-
|
|
7542
|
+
const pill = doc.createElement('div');
|
|
7543
|
+
pill.className = 'pill';
|
|
7544
|
+
pill.setAttribute('data-auth', '');
|
|
7545
|
+
pill.title = row.tabLocal
|
|
7331
7546
|
? `${row.name} holds this tab's own session. The other tabs are on theirs.`
|
|
7332
7547
|
: `${row.name} - the session every tab of this app shares`;
|
|
7548
|
+
const lead = doc.createElement('span');
|
|
7549
|
+
lead.className = 'lead';
|
|
7333
7550
|
const name = doc.createElement('span');
|
|
7334
7551
|
name.className = 'name';
|
|
7335
7552
|
name.textContent = row.tabLocal ? `${row.name} · this tab` : row.name;
|
|
7553
|
+
lead.append(name);
|
|
7336
7554
|
const select = doc.createElement('select');
|
|
7337
7555
|
select.setAttribute('aria-label', `${row.name} session`);
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7556
|
+
// Only where the live tokens belong to no stored session: with one selected below, this would read as
|
|
7557
|
+
// a second session of the same name.
|
|
7558
|
+
if (!row.options.some((option) => option.selected)) {
|
|
7559
|
+
const current = doc.createElement('option');
|
|
7560
|
+
current.value = '';
|
|
7561
|
+
current.textContent = row.current;
|
|
7562
|
+
current.selected = true;
|
|
7563
|
+
select.append(current);
|
|
7564
|
+
}
|
|
7343
7565
|
for (const option of row.options) {
|
|
7344
7566
|
const element = doc.createElement('option');
|
|
7345
7567
|
element.value = option.value;
|
|
@@ -7362,8 +7584,30 @@ const buildAuthRow = (doc, row) => {
|
|
|
7362
7584
|
if (row.tabLocal)
|
|
7363
7585
|
isolate.setAttribute('data-on', '');
|
|
7364
7586
|
isolate.addEventListener('click', row.toggleTabLocal);
|
|
7365
|
-
|
|
7366
|
-
return
|
|
7587
|
+
pill.append(lead, select, isolate);
|
|
7588
|
+
return pill;
|
|
7589
|
+
};
|
|
7590
|
+
const buildChip = (doc, values, collapsed, toggle) => {
|
|
7591
|
+
const chip = doc.createElement('button');
|
|
7592
|
+
chip.type = 'button';
|
|
7593
|
+
chip.className = 'chip';
|
|
7594
|
+
chip.setAttribute('aria-expanded', collapsed ? 'false' : 'true');
|
|
7595
|
+
chip.title = collapsed ? 'Show the devtools switches' : 'Hide the devtools switches';
|
|
7596
|
+
// The visible text says which state the pills are in, not what the click does - hence a name of its own.
|
|
7597
|
+
chip.setAttribute('aria-label', chip.title);
|
|
7598
|
+
const caret = doc.createElement('span');
|
|
7599
|
+
caret.className = 'caret';
|
|
7600
|
+
caret.textContent = '▲';
|
|
7601
|
+
caret.setAttribute('aria-hidden', 'true');
|
|
7602
|
+
const text = doc.createElement('span');
|
|
7603
|
+
text.className = 'values';
|
|
7604
|
+
text.textContent = values.join(' · ');
|
|
7605
|
+
const fold = doc.createElement('span');
|
|
7606
|
+
fold.className = 'fold';
|
|
7607
|
+
fold.textContent = 'hide';
|
|
7608
|
+
chip.append(caret, text, fold);
|
|
7609
|
+
chip.addEventListener('click', toggle);
|
|
7610
|
+
return chip;
|
|
7367
7611
|
};
|
|
7368
7612
|
const render = (doc) => {
|
|
7369
7613
|
doc.getElementById(HOST_ID)?.remove();
|
|
@@ -7371,6 +7615,8 @@ const render = (doc) => {
|
|
|
7371
7615
|
const rows = authState?.rows ?? [];
|
|
7372
7616
|
if (!switches.length && !rows.length)
|
|
7373
7617
|
return;
|
|
7618
|
+
if (!queryDevtoolsPillsAllowed())
|
|
7619
|
+
return;
|
|
7374
7620
|
const host = doc.createElement('div');
|
|
7375
7621
|
host.id = HOST_ID;
|
|
7376
7622
|
// Shadow DOM is intentional, for the same reason the toggle button uses it: this paints over the
|
|
@@ -7379,13 +7625,16 @@ const render = (doc) => {
|
|
|
7379
7625
|
const style = doc.createElement('style');
|
|
7380
7626
|
style.textContent = STYLE;
|
|
7381
7627
|
shadow.append(style);
|
|
7382
|
-
|
|
7628
|
+
const storedOf = (apiSwitch) => envState?.read(apiSwitch.storageKey) ?? DEFAULT_VALUE;
|
|
7629
|
+
const production = switches.some((apiSwitch) => resolvedEnvOf(apiSwitch, storedOf(apiSwitch))?.production === true);
|
|
7630
|
+
// A production pick unfolds the pills whatever is stored: the warning is the point of the pill.
|
|
7631
|
+
const collapsed = !production && readCollapsed();
|
|
7632
|
+
if (collapsed)
|
|
7633
|
+
host.setAttribute('data-collapsed', '');
|
|
7383
7634
|
for (const row of rows)
|
|
7384
7635
|
shadow.append(buildAuthRow(doc, row));
|
|
7385
7636
|
for (const apiSwitch of switches) {
|
|
7386
|
-
|
|
7387
|
-
production ||= resolvedEnvOf(apiSwitch, stored)?.production === true;
|
|
7388
|
-
shadow.append(buildSwitch(doc, apiSwitch, stored, (storageKey, value) => envState?.pick(storageKey, value)));
|
|
7637
|
+
shadow.append(buildSwitch(doc, apiSwitch, storedOf(apiSwitch), (storageKey, value) => envState?.pick(storageKey, value)));
|
|
7389
7638
|
}
|
|
7390
7639
|
if (production) {
|
|
7391
7640
|
const frame = doc.createElement('div');
|
|
@@ -7393,6 +7642,16 @@ const render = (doc) => {
|
|
|
7393
7642
|
frame.setAttribute('aria-hidden', 'true');
|
|
7394
7643
|
shadow.append(frame);
|
|
7395
7644
|
}
|
|
7645
|
+
else {
|
|
7646
|
+
const values = [
|
|
7647
|
+
...rows.map(summaryOfAuthRow),
|
|
7648
|
+
...switches.map((apiSwitch) => summaryOfSwitch(apiSwitch, storedOf(apiSwitch))),
|
|
7649
|
+
];
|
|
7650
|
+
shadow.append(buildChip(doc, values, collapsed, () => {
|
|
7651
|
+
writeCollapsed(!collapsed);
|
|
7652
|
+
render(doc);
|
|
7653
|
+
}));
|
|
7654
|
+
}
|
|
7396
7655
|
doc.body.append(host);
|
|
7397
7656
|
};
|
|
7398
7657
|
/**
|
|
@@ -7405,6 +7664,9 @@ const render = (doc) => {
|
|
|
7405
7664
|
* part of this is on the page before `bootstrapApplication` starts.
|
|
7406
7665
|
*/
|
|
7407
7666
|
const renderPills = () => {
|
|
7667
|
+
// Registered here rather than at module scope: a module-scope call would make this module
|
|
7668
|
+
// unshakeable, and cost every application that never renders a pill the whole renderer.
|
|
7669
|
+
onQueryDevtoolsUiChange(renderPills);
|
|
7408
7670
|
const doc = globalThis.document;
|
|
7409
7671
|
if (!doc)
|
|
7410
7672
|
return;
|
|
@@ -7696,6 +7958,12 @@ const providers = /* @__PURE__ */ signal([], /* @ts-ignore */
|
|
|
7696
7958
|
const tabLocal = /* @__PURE__ */ signal({}, /* @ts-ignore */
|
|
7697
7959
|
...(ngDevMode ? [{ debugName: "tabLocal" }] : /* istanbul ignore next */ []));
|
|
7698
7960
|
const live = /* @__PURE__ */ new Map();
|
|
7961
|
+
/**
|
|
7962
|
+
* The account each provider's next captured token pair was logged in as, set by
|
|
7963
|
+
* `loginQueryDevtoolsAuthAccount` and consumed by the capture it causes. `previous` is the session that
|
|
7964
|
+
* was in force before, which the logout on the way out would otherwise take out of reach.
|
|
7965
|
+
*/
|
|
7966
|
+
const pendingLogins = /* @__PURE__ */ new Map();
|
|
7699
7967
|
let idCounter = 0;
|
|
7700
7968
|
const nextId = (prefix) => `${prefix}-${Date.now().toString(36)}-${++idCounter}`;
|
|
7701
7969
|
/**
|
|
@@ -7773,6 +8041,8 @@ const sanitizeSession = (value) => {
|
|
|
7773
8041
|
accessToken: session.accessToken,
|
|
7774
8042
|
refreshToken: session.refreshToken,
|
|
7775
8043
|
subject: typeof session.subject === 'string' ? session.subject : null,
|
|
8044
|
+
identity: typeof session.identity === 'string' ? session.identity : null,
|
|
8045
|
+
account: typeof session.account === 'string' ? session.account : null,
|
|
7776
8046
|
expiresAt: typeof session.expiresAt === 'number' ? session.expiresAt : null,
|
|
7777
8047
|
savedAt: typeof session.savedAt === 'number' ? session.savedAt : 0,
|
|
7778
8048
|
};
|
|
@@ -7845,9 +8115,12 @@ const trackQueryDevtoolsAuthProvider = (registration) => {
|
|
|
7845
8115
|
const stop = effect(() => {
|
|
7846
8116
|
const accessToken = handle.accessToken();
|
|
7847
8117
|
const refreshToken = handle.refreshToken();
|
|
8118
|
+
const endCause = handle.sessionEndCause();
|
|
7848
8119
|
untracked(() => {
|
|
7849
8120
|
if (accessToken && refreshToken)
|
|
7850
8121
|
remember({ provider: name, accessToken, refreshToken });
|
|
8122
|
+
else if (endCause === 'expired')
|
|
8123
|
+
forgetExpired(name);
|
|
7851
8124
|
else
|
|
7852
8125
|
forgetActive(name);
|
|
7853
8126
|
});
|
|
@@ -7860,6 +8133,21 @@ const trackQueryDevtoolsAuthProvider = (registration) => {
|
|
|
7860
8133
|
syncPill();
|
|
7861
8134
|
};
|
|
7862
8135
|
};
|
|
8136
|
+
/**
|
|
8137
|
+
* Drops what the previous user left behind. Their responses are cached under keys the next user's
|
|
8138
|
+
* requests hit, and a bound secure query would go on rendering a body that was fetched for somebody else.
|
|
8139
|
+
*
|
|
8140
|
+
* Only ever once the new tokens are in force: `unbindAllSecure` re-arms every secure query that
|
|
8141
|
+
* auto-executes on the first access token it sees, so clearing before them re-runs all of them on the
|
|
8142
|
+
* token the previous user still holds - and caches that answer for the one arriving.
|
|
8143
|
+
*/
|
|
8144
|
+
const clearClientData = (entry) => {
|
|
8145
|
+
const { repository } = entry.client;
|
|
8146
|
+
repository.unbindAllSecure();
|
|
8147
|
+
for (const cacheEntry of repository.subtle.cacheEntries())
|
|
8148
|
+
repository.subtle.evict(cacheEntry.key);
|
|
8149
|
+
void entry.client.clearPersistedQueries();
|
|
8150
|
+
};
|
|
7863
8151
|
/**
|
|
7864
8152
|
* Writes a live token pair into the vault. A pair whose subject is already stored updates that session
|
|
7865
8153
|
* rather than adding another, which is what lets a plain login in the application fill the picker.
|
|
@@ -7872,23 +8160,46 @@ const remember = (options) => {
|
|
|
7872
8160
|
const scope = scopeOf();
|
|
7873
8161
|
const identity = identityOf(accessToken);
|
|
7874
8162
|
const activeId = active()[provider] ?? null;
|
|
7875
|
-
const
|
|
7876
|
-
|
|
7877
|
-
|
|
8163
|
+
const account = pendingLogins.get(provider) ?? null;
|
|
8164
|
+
pendingLogins.delete(provider);
|
|
8165
|
+
const mine = store().sessions.filter((session) => session.provider === provider && session.scope === scope);
|
|
8166
|
+
// This pair is already on record: the tab it belongs to lost only the pointer, which a new tab always
|
|
8167
|
+
// does - the pointer is the tab's own. Without this a token that carries no `sub` grows a second entry
|
|
8168
|
+
// per tab, and a third, until the picker is a column of sessions all named the same.
|
|
8169
|
+
const byTokens = mine.find((session) => session.refreshToken === refreshToken || session.accessToken === accessToken);
|
|
8170
|
+
const byAccount = account ? mine.find((session) => session.account === account.id) : undefined;
|
|
8171
|
+
const bySubject = identity.subject ? mine.find((session) => session.subject === identity.subject) : undefined;
|
|
8172
|
+
// The name the token claims, for a backend that issues no `sub`. A session held for another account is
|
|
8173
|
+
// left alone: two accounts are two slots even where one person's name is on both.
|
|
8174
|
+
const byIdentity = identity.label
|
|
8175
|
+
? mine.find((session) => session.identity === identity.label && (!account || !session.account || session.account === account.id))
|
|
7878
8176
|
: undefined;
|
|
7879
|
-
//
|
|
7880
|
-
//
|
|
7881
|
-
|
|
7882
|
-
|
|
7883
|
-
|
|
8177
|
+
// An account login logs out on the way in, and a logout lets go of the pointer, so the session this tab
|
|
8178
|
+
// was on has to be carried in by the pending login instead.
|
|
8179
|
+
const candidate = mine.find((session) => session.id === (activeId ?? account?.previous ?? null));
|
|
8180
|
+
// Whoever the live tokens belong to, the candidate is a different user as soon as one claim says so.
|
|
8181
|
+
// Without this a login as somebody else would overwrite the tokens of the user this tab is leaving,
|
|
8182
|
+
// which is the one pair the vault exists to keep.
|
|
8183
|
+
const isOtherUser = !!candidate &&
|
|
8184
|
+
((!!identity.subject && !!candidate.subject && candidate.subject !== identity.subject) ||
|
|
8185
|
+
(!!identity.label && !!candidate.identity && candidate.identity !== identity.label) ||
|
|
8186
|
+
(!!account && !!candidate.account && candidate.account !== account.id));
|
|
8187
|
+
// The last resort for a token that names nobody at all: the newest session nothing can tell it apart
|
|
8188
|
+
// from. An account login is left out - it is asking for a session of its own.
|
|
8189
|
+
const byNothing = identity.subject || identity.label || account
|
|
8190
|
+
? undefined
|
|
8191
|
+
: mine.filter((session) => !session.subject && !session.account).sort((a, b) => b.savedAt - a.savedAt)[0];
|
|
8192
|
+
const target = byTokens ?? byAccount ?? bySubject ?? byIdentity ?? (isOtherUser ? undefined : candidate) ?? byNothing;
|
|
7884
8193
|
const session = {
|
|
7885
8194
|
id: target?.id ?? nextId('session'),
|
|
7886
8195
|
provider,
|
|
7887
|
-
label: target?.label ?? identity.label ?? 'session',
|
|
8196
|
+
label: target?.label ?? identity.label ?? account?.label ?? 'session',
|
|
7888
8197
|
scope,
|
|
7889
8198
|
accessToken,
|
|
7890
8199
|
refreshToken,
|
|
7891
8200
|
subject: identity.subject,
|
|
8201
|
+
identity: identity.label ?? target?.identity ?? null,
|
|
8202
|
+
account: target?.account ?? account?.id ?? null,
|
|
7892
8203
|
expiresAt: identity.expiresAt,
|
|
7893
8204
|
savedAt: Date.now(),
|
|
7894
8205
|
};
|
|
@@ -7904,6 +8215,13 @@ const remember = (options) => {
|
|
|
7904
8215
|
}
|
|
7905
8216
|
persist();
|
|
7906
8217
|
syncPill();
|
|
8218
|
+
// Another session than this tab was on. A rotation of the same one is not a change of user, and a
|
|
8219
|
+
// login that never landed leaves its pending entry behind for the next rotation to find.
|
|
8220
|
+
if (account && session.id !== account.previous) {
|
|
8221
|
+
const entry = live.get(provider);
|
|
8222
|
+
if (entry)
|
|
8223
|
+
clearClientData(entry);
|
|
8224
|
+
}
|
|
7907
8225
|
};
|
|
7908
8226
|
/** Lets go of the session a provider was on, without forgetting what the vault holds of it. */
|
|
7909
8227
|
const forgetActive = (provider) => {
|
|
@@ -7913,6 +8231,26 @@ const forgetActive = (provider) => {
|
|
|
7913
8231
|
persist();
|
|
7914
8232
|
syncPill();
|
|
7915
8233
|
};
|
|
8234
|
+
/**
|
|
8235
|
+
* Drops the session a provider was on because it expired, tokens and all - unlike every other way a
|
|
8236
|
+
* session ends, this pair is spent. Keeping it offers a switch back that can only fail, and a tab-local
|
|
8237
|
+
* seed would re-apply it on every reload, so the tab meets the same dead token until someone clears the
|
|
8238
|
+
* storage by hand.
|
|
8239
|
+
*/
|
|
8240
|
+
const forgetExpired = (provider) => {
|
|
8241
|
+
const sessionId = active()[provider] ?? null;
|
|
8242
|
+
const { [provider]: _dropped, ...seeds } = readSeeds();
|
|
8243
|
+
writeSeeds(seeds);
|
|
8244
|
+
if (!sessionId)
|
|
8245
|
+
return;
|
|
8246
|
+
store.update((current) => ({
|
|
8247
|
+
...current,
|
|
8248
|
+
sessions: current.sessions.filter((session) => session.id !== sessionId),
|
|
8249
|
+
}));
|
|
8250
|
+
setActive(provider, null);
|
|
8251
|
+
persist();
|
|
8252
|
+
syncPill();
|
|
8253
|
+
};
|
|
7916
8254
|
/** The sessions offered for one provider, which are the ones this backend issued. */
|
|
7917
8255
|
const queryDevtoolsAuthSessionsFor = (provider) => {
|
|
7918
8256
|
const scope = scopeOf();
|
|
@@ -7963,7 +8301,7 @@ const queryDevtoolsAuthAccountsFor = (provider) => {
|
|
|
7963
8301
|
provider,
|
|
7964
8302
|
label: account.label,
|
|
7965
8303
|
loginQuery: account.loginQuery,
|
|
7966
|
-
fields:
|
|
8304
|
+
fields: account.fields?.length ? account.fields : queryDevtoolsAuthFieldsFor(provider, account.loginQuery),
|
|
7967
8305
|
declared: false,
|
|
7968
8306
|
}));
|
|
7969
8307
|
return [...fromApp, ...fromPanel];
|
|
@@ -7988,6 +8326,15 @@ const clearQueryDevtoolsAuthCredentials = (accountId) => {
|
|
|
7988
8326
|
persist();
|
|
7989
8327
|
syncPill();
|
|
7990
8328
|
};
|
|
8329
|
+
/**
|
|
8330
|
+
* What a login needs on one provider, taken from an account the application declared for the same query.
|
|
8331
|
+
* The shape a hand-added account starts from, for a backend whose login is not `email` and `password`.
|
|
8332
|
+
*/
|
|
8333
|
+
const queryDevtoolsAuthFieldsFor = (provider, loginQuery) => {
|
|
8334
|
+
const mine = declared().filter((account) => account.provider === provider && account.fields?.length);
|
|
8335
|
+
const shape = (loginQuery ? mine.find((account) => account.loginQuery === loginQuery) : undefined) ?? mine[0];
|
|
8336
|
+
return (shape?.fields ?? DEFAULT_FIELDS).map(({ name, label, type }) => ({ name, label, type }));
|
|
8337
|
+
};
|
|
7991
8338
|
/** Adds an account the application does not declare, for the backend in force. */
|
|
7992
8339
|
const addQueryDevtoolsAuthAccount = (options) => {
|
|
7993
8340
|
const account = { ...options, id: nextId('account'), scope: scopeOf() };
|
|
@@ -8024,6 +8371,23 @@ const forgetQueryDevtoolsAuthSession = (sessionId) => {
|
|
|
8024
8371
|
persist();
|
|
8025
8372
|
syncPill();
|
|
8026
8373
|
};
|
|
8374
|
+
/**
|
|
8375
|
+
* Drops every session this backend issued for one provider. The accounts and what was typed in for them
|
|
8376
|
+
* are left alone, so the way back in is one login.
|
|
8377
|
+
*/
|
|
8378
|
+
const forgetQueryDevtoolsAuthSessionsFor = (provider) => {
|
|
8379
|
+
const scope = scopeOf();
|
|
8380
|
+
const dropped = new Set(store()
|
|
8381
|
+
.sessions.filter((session) => session.provider === provider && session.scope === scope)
|
|
8382
|
+
.map((session) => session.id));
|
|
8383
|
+
store.update((current) => ({
|
|
8384
|
+
...current,
|
|
8385
|
+
sessions: current.sessions.filter((session) => !dropped.has(session.id)),
|
|
8386
|
+
}));
|
|
8387
|
+
active.update((current) => Object.fromEntries(Object.entries(current).map(([name, id]) => [name, id && dropped.has(id) ? null : id])));
|
|
8388
|
+
persist();
|
|
8389
|
+
syncPill();
|
|
8390
|
+
};
|
|
8027
8391
|
/** Empties the vault: every session, every account added in the panel, every credential. */
|
|
8028
8392
|
const clearQueryDevtoolsAuthSessions = () => {
|
|
8029
8393
|
store.set(EMPTY);
|
|
@@ -8033,17 +8397,6 @@ const clearQueryDevtoolsAuthSessions = () => {
|
|
|
8033
8397
|
syncPill();
|
|
8034
8398
|
};
|
|
8035
8399
|
const reload = () => globalThis.location?.reload();
|
|
8036
|
-
/**
|
|
8037
|
-
* Drops what the previous user left behind. Their responses are cached under keys the next user's
|
|
8038
|
-
* requests hit, and a bound secure query would go on rendering a body that was fetched for somebody else.
|
|
8039
|
-
*/
|
|
8040
|
-
const clearClientData = (entry) => {
|
|
8041
|
-
const { repository } = entry.client;
|
|
8042
|
-
repository.unbindAllSecure();
|
|
8043
|
-
for (const cacheEntry of repository.subtle.cacheEntries())
|
|
8044
|
-
repository.subtle.evict(cacheEntry.key);
|
|
8045
|
-
void entry.client.clearPersistedQueries();
|
|
8046
|
-
};
|
|
8047
8400
|
/**
|
|
8048
8401
|
* Puts one stored session's tokens in force. The reload is the default because a switch only replaces
|
|
8049
8402
|
* what the query layer holds: an application that keeps the user anywhere else - a profile service, the
|
|
@@ -8056,7 +8409,6 @@ const switchQueryDevtoolsAuthSession = (options) => {
|
|
|
8056
8409
|
const entry = live.get(session.provider);
|
|
8057
8410
|
if (!entry || session.scope !== scopeOf())
|
|
8058
8411
|
return;
|
|
8059
|
-
clearClientData(entry);
|
|
8060
8412
|
setActive(session.provider, session.id);
|
|
8061
8413
|
if (tabLocal()[session.provider]) {
|
|
8062
8414
|
writeSeeds({
|
|
@@ -8071,6 +8423,7 @@ const switchQueryDevtoolsAuthSession = (options) => {
|
|
|
8071
8423
|
}
|
|
8072
8424
|
persist();
|
|
8073
8425
|
entry.handle.setTokens(session.accessToken, session.refreshToken);
|
|
8426
|
+
clearClientData(entry);
|
|
8074
8427
|
syncPill();
|
|
8075
8428
|
if (options.reload ?? queryDevtoolsSettings().reloadOnAuthSwitch)
|
|
8076
8429
|
reload();
|
|
@@ -8089,8 +8442,9 @@ const loginQueryDevtoolsAuthAccount = (accountId) => {
|
|
|
8089
8442
|
const query = entry?.handle.queries?.[account.loginQuery];
|
|
8090
8443
|
if (!entry || !query)
|
|
8091
8444
|
return;
|
|
8092
|
-
|
|
8445
|
+
const previous = active()[account.provider] ?? null;
|
|
8093
8446
|
setActive(account.provider, null);
|
|
8447
|
+
pendingLogins.set(account.provider, { id: account.id, label: account.label, previous });
|
|
8094
8448
|
persist();
|
|
8095
8449
|
query.execute(account.buildArgs?.(account.values) ?? { body: account.values });
|
|
8096
8450
|
};
|
|
@@ -8123,6 +8477,10 @@ const setQueryDevtoolsAuthTabLocal = (options) => {
|
|
|
8123
8477
|
writeSeeds({ ...seeds, [provider]: { sessionId, scope: scopeOf(), accessToken, refreshToken } });
|
|
8124
8478
|
reload();
|
|
8125
8479
|
};
|
|
8480
|
+
/** When a session's tokens were last written, which is what tells two same-named ones apart. */
|
|
8481
|
+
const savedAtLabel = (session) => session.savedAt
|
|
8482
|
+
? new Date(session.savedAt).toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })
|
|
8483
|
+
: 'unknown';
|
|
8126
8484
|
/** What the floating pill offers, rebuilt whenever any of it changes. */
|
|
8127
8485
|
const syncPill = () => {
|
|
8128
8486
|
const rows = untracked(() => providers().map((provider) => {
|
|
@@ -8130,6 +8488,10 @@ const syncPill = () => {
|
|
|
8130
8488
|
const accounts = queryDevtoolsAuthAccountsFor(provider);
|
|
8131
8489
|
const activeId = active()[provider] ?? null;
|
|
8132
8490
|
const current = sessions.find((session) => session.id === activeId);
|
|
8491
|
+
const shared = new Map();
|
|
8492
|
+
for (const session of sessions)
|
|
8493
|
+
shared.set(session.label, (shared.get(session.label) ?? 0) + 1);
|
|
8494
|
+
const labelOf = (session) => shared.get(session.label) === 1 ? session.label : `${session.label} · ${savedAtLabel(session)}`;
|
|
8133
8495
|
return {
|
|
8134
8496
|
name: provider,
|
|
8135
8497
|
current: current?.label ?? (live.get(provider)?.handle.accessToken() ? 'unnamed session' : 'anonymous'),
|
|
@@ -8137,7 +8499,7 @@ const syncPill = () => {
|
|
|
8137
8499
|
options: [
|
|
8138
8500
|
...sessions.map((session) => ({
|
|
8139
8501
|
value: `session:${session.id}`,
|
|
8140
|
-
label: session
|
|
8502
|
+
label: labelOf(session),
|
|
8141
8503
|
title: `Switch to ${session.label}`,
|
|
8142
8504
|
selected: session.id === activeId,
|
|
8143
8505
|
disabled: false,
|
|
@@ -9259,7 +9621,7 @@ const armQueryDevtoolsOverrideTransfer = (recorder, ops) => {
|
|
|
9259
9621
|
|
|
9260
9622
|
// Generated from package.json by tools/scripts/generate-version.js - do not edit.
|
|
9261
9623
|
/** The version of `@ethlete/query` this build was cut from. */
|
|
9262
|
-
const QUERY_VERSION = '6.0.0-next.
|
|
9624
|
+
const QUERY_VERSION = '6.0.0-next.43';
|
|
9263
9625
|
|
|
9264
9626
|
/** How deep a schema is expanded before a nested branch is given up on. */
|
|
9265
9627
|
const MAX_DEPTH = 12;
|
|
@@ -10566,7 +10928,16 @@ const provideQueryDevtools = (options) => {
|
|
|
10566
10928
|
if (!isDevMode()) {
|
|
10567
10929
|
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.');
|
|
10568
10930
|
}
|
|
10569
|
-
return makeEnvironmentProviders([
|
|
10931
|
+
return makeEnvironmentProviders([
|
|
10932
|
+
// The floating pills paint before this - before `bootstrapApplication`, so a boot that hangs on the
|
|
10933
|
+
// backend it was just pointed at can still be pointed somewhere else. Once the application has
|
|
10934
|
+
// settled they follow the devtools trigger instead, and an app that renders none shows no pills.
|
|
10935
|
+
provideEnvironmentInitializer(() => {
|
|
10936
|
+
void inject(ApplicationRef)
|
|
10937
|
+
.whenStable()
|
|
10938
|
+
.then(() => markQueryDevtoolsAppSettled());
|
|
10939
|
+
}),
|
|
10940
|
+
]);
|
|
10570
10941
|
};
|
|
10571
10942
|
|
|
10572
10943
|
const getOpName = /\b(?:query|mutation)\s+([\w-]+)(?:\s*\([^)]*\))?\s*\{/;
|
|
@@ -16253,5 +16624,5 @@ const createWebSocketClient = (options) => {
|
|
|
16253
16624
|
* Generated bundle index. Do not edit.
|
|
16254
16625
|
*/
|
|
16255
16626
|
|
|
16256
|
-
export { AuthBearerRefreshStrategy, BasicAuthProvider, BearerAuthFeatureType, BooleanArrayQueryField, 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_BATCH_TOMBSTONES, 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, QueryStateType, QueryStore, SERVER_ERROR_KIND, SERVER_VIOLATION_ERROR_KIND, SPEED_BUFFER_TIME_IN_MS, SearchQueryField, SortQueryField, StringArrayQueryField, V2BearerAuthProvider, V2Query, V2QueryClient, V2QueryCreator, addQueryContainerHandling, addQueryDevtoolsAuthAccount, applyQueryDevtoolsOverrides, applyQueryDevtoolsTokenTtl, applyQueryFeatures, armAllQueryDevtoolsMocks, armQueryDevtoolsMock, armQueryDevtoolsOverrideTransfer, authExtractTokensResponseMissingAccessToken, authExtractTokensResponseMissingRefreshToken, authExtractTokensResponseNotObject, authProviderFeatureUsedMultipleTimes, booleanArrayQueryField, buildQueryCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, canOverrideQueryDevtoolsTokenTtl, castQueryCreatorTypes, circularQueryDependency, circularQueryDependencyChecker, clearQueryDevtoolsArmedMocks, clearQueryDevtoolsAuthCredentials, clearQueryDevtoolsAuthSessions, clearQueryDevtoolsFaults, clearQueryDevtoolsMockStore, clearQueryDevtoolsOverrideStore, clearQueryDevtoolsStore, clearQueryDevtoolsTokenTtl, clearQueryDevtoolsTombstones, clearRestoredQueryDevtoolsOverrides, collectLeafPaths, collectQueryDevtoolsSchemaComponents, collectQueryFormLinks, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, consumeSuppressQueryStackDevtools, contentfulGqlLikePaginationAdapter, countUnresolvedQueryDevtoolsOverrides, createAuthGuard, createBaseQuery, createBaseQueryCreator, createBearerAuthProvider, createDefaultRetryFn, createDeleteQuery, createExecuteFn, createGetQuery, createGqlExecuteFn, createGqlMutationViaGet, createGqlMutationViaPost, createGqlQuery, createGqlQueryCreator, createGqlQueryViaGet, createGqlQueryViaPost, createHttpRequest, createIndexedDbQueryPersistenceAdapter, createInfinityQueryConfig, createLegacyQueryCreator, createNoopQueryPersistenceAdapter, createPagedQueryStack, createPatchQuery, createPersistentAuthFeature, createPostQuery, createPutQuery, createQuery, createQueryBatch, createQueryClient, createQueryCollection, createQueryCollectionSignal, createQueryCollectionSubject, createQueryContext, createQueryCreator, createQueryDevtoolsFormLinks, createQueryDevtoolsFormLinksRecorder, createQueryDevtoolsOverrides, createQueryDevtoolsOverridesRecorder, createQueryDevtoolsStats, createQueryDevtoolsStatsRecorder, createQueryErrorResponse, createQueryFeature, createQueryInvalidationFilter, createQueryKeyLockManager, createQueryObject, createQueryPersistenceEngine, createQueryRepository, createQuerySnapshotFn, createQueryStack, createQuerySubmission, createQuerySyncEngine, createQuerySyncTransport, createSecureDeleteQuery, createSecureExecuteFactory, createSecureExecuteFn, createSecureGetQuery, createSecureGqlExecuteFn, createSecureGqlMutationViaGet, createSecureGqlMutationViaPost, createSecureGqlQuery, createSecureGqlQueryCreator, createSecureGqlQueryViaGet, createSecureGqlQueryViaPost, createSecurePatchQuery, createSecurePostQuery, createSecurePutQuery, createSecureQuery, createSecureQueryCreator, createTrackingFeature, createWebSocketClient, currentQueryDevtoolsBatch, 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, forgetQueryDevtoolsAuthSession, formatQueryDevtoolsDuration, generateQueryDevtoolsNumberPreset, generateQueryDevtoolsSampleNumber, generateQueryDevtoolsStringPreset, getBearerAuthProviderName, getDefaultHeaders, getQueryClientName, getQueryFeatureUsage, getResponseUrl, ggLikePaginationAdapter, gql, gqlDataPropertyMissingInResponse, hasHeader, hasQueryDevtoolsOverridesAtPath, htmlErrorPayload, htmlQueryErrorParser, ignoreAutoRefresh, initQueryDevtoolsAuthSessions, 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, loginQueryDevtoolsAuthAccount, logoutQueryDevtoolsAuthSession, 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, queryBatchAlreadyRunning, queryBatchWithArgsUsed, queryClientFeatureUsedMultipleTimes, queryComputed, queryComputedTillTruthy, queryDevtoolsAbout, queryDevtoolsApiEnvIds, queryDevtoolsApiEnvIsProduction, queryDevtoolsApiEnvScope, queryDevtoolsApiEnvValues, queryDevtoolsApiEnvs, queryDevtoolsArmedMocks, queryDevtoolsArmedMocksRestored, queryDevtoolsAuthAccountsFor, queryDevtoolsAuthActive, queryDevtoolsAuthOtherScopeCount, queryDevtoolsAuthProviders, queryDevtoolsAuthSessions, queryDevtoolsAuthSessionsFor, queryDevtoolsAuthTabLocal, 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, readQueryDevtoolsAuthSeed, readQueryDevtoolsAuthSeedFor, readQueryDevtoolsStore, registerEthleteVersion, registerQueryDevtoolsAuthProvider, registerQueryDevtoolsEntry, registerQueryErrorParser, removeFrom, removeQueryDevtoolsAuthAccount, renameQueryDevtoolsAuthSession, request, resetExecuteState, resetPageOnError, resolveInvalidationUrl, resolveQueryDevtoolsFault, resolveQueryDevtoolsFaultForAttempt, resolveQueryDevtoolsMock, resolveQueryDevtoolsMockForAttempt, restoredQueryDevtoolsOverrides, runDefaultQueryRetry, runInQueryDevtoolsBatch, runQueryErrorParsers, saveQueryDevtoolsMock, searchQueryField, seedQueryDevtoolsSchemaBody, seedQueryDevtoolsSchemaRoute, serializeBody, serializeQueryDevtoolsOverrideTransfer, setDefaultQueryRetryFn, setQueryDevtoolsApiEnv, setQueryDevtoolsApiEnvs, setQueryDevtoolsAppInfo, setQueryDevtoolsArmedMocksScope, setQueryDevtoolsAuthCredentials, setQueryDevtoolsAuthProviderRegistrar, setQueryDevtoolsAuthSeedReader, setQueryDevtoolsAuthTabLocal, 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, switchQueryDevtoolsAuthSession, switchQueryState, symfonyQueryErrorParser, takeUntilResponse, toQuerySignal, toQuerySubject, tokensNotAvailableInsideAuthAndExec, tombstoneOf, trackQueryDevtoolsAuthProvider, 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, withLongPolling, withLongPollingUsedOnUnsupportedHttpMethod, withLongPollingUsedWithPolling, withMultiTabSync, withPageResetOnError, withPersistentAuth, withPolling, withPollingUsedOnUnsupportedHttpMethod, withQueryDevtoolsOverridePersistence, withQueryPersistence, withRefreshQuery, withResponseUpdate, withSuccessHandling, withSymfonyErrors, withTokenExpirationWarning, withTokenRevocation, withTracking, wrapAsObservableSignal, wrapQuerySyncMessage, writeQueryDevtoolsStore };
|
|
16627
|
+
export { AuthBearerRefreshStrategy, BasicAuthProvider, BearerAuthFeatureType, BooleanArrayQueryField, 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_BATCH_TOMBSTONES, 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, QueryStateType, QueryStore, SERVER_ERROR_KIND, SERVER_VIOLATION_ERROR_KIND, SPEED_BUFFER_TIME_IN_MS, SearchQueryField, SortQueryField, StringArrayQueryField, V2BearerAuthProvider, V2Query, V2QueryClient, V2QueryCreator, addQueryContainerHandling, addQueryDevtoolsAuthAccount, applyQueryDevtoolsOverrides, applyQueryDevtoolsTokenTtl, applyQueryFeatures, armAllQueryDevtoolsMocks, armQueryDevtoolsMock, armQueryDevtoolsOverrideTransfer, authExtractTokensResponseMissingAccessToken, authExtractTokensResponseMissingRefreshToken, authExtractTokensResponseNotObject, authProviderFeatureUsedMultipleTimes, booleanArrayQueryField, buildQueryCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, canOverrideQueryDevtoolsTokenTtl, castQueryCreatorTypes, circularQueryDependency, circularQueryDependencyChecker, clearQueryDevtoolsArmedMocks, clearQueryDevtoolsAuthCredentials, clearQueryDevtoolsAuthSessions, clearQueryDevtoolsFaults, clearQueryDevtoolsMockStore, clearQueryDevtoolsOverrideStore, clearQueryDevtoolsStore, clearQueryDevtoolsTokenTtl, clearQueryDevtoolsTombstones, clearRestoredQueryDevtoolsOverrides, collectLeafPaths, collectQueryDevtoolsSchemaComponents, collectQueryFormLinks, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, consumeSuppressQueryStackDevtools, contentfulGqlLikePaginationAdapter, countUnresolvedQueryDevtoolsOverrides, createAuthGuard, createBaseQuery, createBaseQueryCreator, createBearerAuthProvider, createDefaultRetryFn, createDeleteQuery, createExecuteFn, createGetQuery, createGqlExecuteFn, createGqlMutationViaGet, createGqlMutationViaPost, createGqlQuery, createGqlQueryCreator, createGqlQueryViaGet, createGqlQueryViaPost, createHttpRequest, createIndexedDbQueryPersistenceAdapter, createInfinityQueryConfig, createLegacyQueryCreator, createNoopQueryPersistenceAdapter, createPagedQueryStack, createPatchQuery, createPersistentAuthFeature, createPostQuery, createPutQuery, createQuery, createQueryBatch, createQueryClient, createQueryCollection, createQueryCollectionSignal, createQueryCollectionSubject, createQueryContext, createQueryCreator, createQueryDevtoolsFormLinks, createQueryDevtoolsFormLinksRecorder, createQueryDevtoolsOverrides, createQueryDevtoolsOverridesRecorder, createQueryDevtoolsStats, createQueryDevtoolsStatsRecorder, createQueryErrorResponse, createQueryFeature, createQueryInvalidationFilter, createQueryKeyLockManager, createQueryObject, createQueryPersistenceEngine, createQueryRepository, createQuerySnapshotFn, createQueryStack, createQuerySubmission, createQuerySyncEngine, createQuerySyncTransport, createSecureDeleteQuery, createSecureExecuteFactory, createSecureExecuteFn, createSecureGetQuery, createSecureGqlExecuteFn, createSecureGqlMutationViaGet, createSecureGqlMutationViaPost, createSecureGqlQuery, createSecureGqlQueryCreator, createSecureGqlQueryViaGet, createSecureGqlQueryViaPost, createSecurePatchQuery, createSecurePostQuery, createSecurePutQuery, createSecureQuery, createSecureQueryCreator, createTrackingFeature, createWebSocketClient, currentQueryDevtoolsBatch, 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, forgetQueryDevtoolsAuthSession, forgetQueryDevtoolsAuthSessionsFor, formatQueryDevtoolsDuration, generateQueryDevtoolsNumberPreset, generateQueryDevtoolsSampleNumber, generateQueryDevtoolsStringPreset, getBearerAuthProviderName, getDefaultHeaders, getQueryClientName, getQueryFeatureUsage, getResponseUrl, ggLikePaginationAdapter, gql, gqlDataPropertyMissingInResponse, hasHeader, hasQueryDevtoolsOverridesAtPath, htmlErrorPayload, htmlQueryErrorParser, ignoreAutoRefresh, initQueryDevtoolsAuthSessions, 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, loginQueryDevtoolsAuthAccount, logoutQueryDevtoolsAuthSession, 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, queryBatchAlreadyRunning, queryBatchWithArgsUsed, queryClientFeatureUsedMultipleTimes, queryComputed, queryComputedTillTruthy, queryDevtoolsAbout, queryDevtoolsApiEnvIds, queryDevtoolsApiEnvIsProduction, queryDevtoolsApiEnvScope, queryDevtoolsApiEnvValues, queryDevtoolsApiEnvs, queryDevtoolsArmedMocks, queryDevtoolsArmedMocksRestored, queryDevtoolsAuthAccountsFor, queryDevtoolsAuthActive, queryDevtoolsAuthFieldsFor, queryDevtoolsAuthOtherScopeCount, queryDevtoolsAuthProviders, queryDevtoolsAuthSessions, queryDevtoolsAuthSessionsFor, queryDevtoolsAuthTabLocal, 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, readQueryDevtoolsAuthSeed, readQueryDevtoolsAuthSeedFor, readQueryDevtoolsStore, registerEthleteVersion, registerQueryDevtoolsAuthProvider, registerQueryDevtoolsEntry, registerQueryErrorParser, removeFrom, removeQueryDevtoolsAuthAccount, renameQueryDevtoolsAuthSession, request, resetExecuteState, resetPageOnError, resolveInvalidationUrl, resolveQueryDevtoolsFault, resolveQueryDevtoolsFaultForAttempt, resolveQueryDevtoolsMock, resolveQueryDevtoolsMockForAttempt, restoredQueryDevtoolsOverrides, runDefaultQueryRetry, runInQueryDevtoolsBatch, runQueryErrorParsers, saveQueryDevtoolsMock, searchQueryField, seedQueryDevtoolsSchemaBody, seedQueryDevtoolsSchemaRoute, serializeBody, serializeQueryDevtoolsOverrideTransfer, setDefaultQueryRetryFn, setQueryDevtoolsApiEnv, setQueryDevtoolsApiEnvs, setQueryDevtoolsAppInfo, setQueryDevtoolsArmedMocksScope, setQueryDevtoolsAuthCredentials, setQueryDevtoolsAuthProviderRegistrar, setQueryDevtoolsAuthSeedReader, setQueryDevtoolsAuthTabLocal, setQueryDevtoolsFault, setQueryDevtoolsFaultResolver, setQueryDevtoolsFaultsScope, setQueryDevtoolsFormLinksFactory, setQueryDevtoolsMockResolver, setQueryDevtoolsOverridePersistence, setQueryDevtoolsOverridesFactory, setQueryDevtoolsOverridesScope, setQueryDevtoolsRegistrar, setQueryDevtoolsResponseHistory, setQueryDevtoolsSchemaLoader, setQueryDevtoolsSettings, setQueryDevtoolsStatsFactory, setQueryDevtoolsTokenPayloadPatcher, setQueryDevtoolsTokenTtl, setQueryDevtoolsUiMounted, setupQueryDependencies, setupQueryExecuteState, setupQueryState, shouldAutoExecuteGqlQuery, shouldAutoExecuteQuery, shouldCacheQuery, shouldRetryRequest, silenceMissingWithArgsFeatureErrorUsedButWithArgsPresent, skipPaginationPageParamCalculator, smartDuplicateArrayItem, snapshotQueryDevtoolsHandle, sortQueryField, splitQueryConfig, stringArrayQueryField, stringifyQueryRouteParts, sumQueryDevtoolsStats, suppressNextQueryStackDevtools, switchQueryCollectionState, switchQueryDevtoolsAuthSession, switchQueryState, symfonyQueryErrorParser, takeUntilResponse, toQuerySignal, toQuerySubject, tokensNotAvailableInsideAuthAndExec, tombstoneOf, trackQueryDevtoolsAuthProvider, 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, withLongPolling, withLongPollingUsedOnUnsupportedHttpMethod, withLongPollingUsedWithPolling, withMultiTabSync, withPageResetOnError, withPersistentAuth, withPolling, withPollingUsedOnUnsupportedHttpMethod, withQueryDevtoolsOverridePersistence, withQueryPersistence, withRefreshQuery, withResponseUpdate, withSuccessHandling, withSymfonyErrors, withTokenExpirationWarning, withTokenRevocation, withTracking, wrapAsObservableSignal, wrapQuerySyncMessage, writeQueryDevtoolsStore };
|
|
16257
16628
|
//# sourceMappingURL=ethlete-query.mjs.map
|