@ethlete/query-devtools 1.0.0-next.8 → 1.0.0-next.9
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
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.0-next.9
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`acc396a`](https://github.com/ethlete-io/ethdk/commit/acc396aa73313204fc09d54b083562cea5afb5b1) Thanks [@TomTomB](https://github.com/TomTomB)! - `provideQueryDevtools({ apiEnvs })` puts an API environment picker beside the floating toggle and on the Settings tab; a pick writes the app's own `localStorage` key and reloads. An env marked `production` makes the picker shout.
|
|
8
|
+
|
|
9
|
+
- [`d8fea59`](https://github.com/ethlete-io/ethdk/commit/d8fea594beb1094b0715ce24e308862d2ddd4f21) Thanks [@TomTomB](https://github.com/TomTomB)! - The devtools Auth tab now keeps every session you log in as and switches between them, logs in as an
|
|
10
|
+
account declared through `provideQueryDevtools({ authAccounts })`, and can hold one tab's session
|
|
11
|
+
apart from the rest.
|
|
12
|
+
|
|
3
13
|
## 1.0.0-next.8
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { signal, ViewEncapsulation, Component, input, output, computed, viewChild, effect, numberAttribute, linkedSignal, InjectionToken, inject, untracked, ElementRef, NgZone, DestroyRef, booleanAttribute } from '@angular/core';
|
|
3
3
|
import { copyToClipboard, injectStyleManager, injectErrorTheme, ProvideColorDirective, clamp, injectRenderer, injectFileDownload, injectViewportSize, injectIsDocumentVisible, injectBreakpointObserver, signalElementDimensions, randomId, reserveOverlayViewportSpace, createObjectUrlHandle, DragHandleDirective, ResizeHandlesComponent } from '@ethlete/core';
|
|
4
|
-
import { queryDevtoolsAbout, hasQueryDevtoolsOverridesAtPath, detectPaginationShape, isDateShapedLeaf, generateQueryDevtoolsStringPreset, generateQueryDevtoolsNumberPreset, collectLeafPaths, armAllQueryDevtoolsMocks, clearQueryDevtoolsArmedMocks, clearQueryDevtoolsFaults, queryDevtoolsResponseHistory, queryDevtoolsMocks, queryDevtoolsArmedMocks, queryDevtoolsSettings, setQueryDevtoolsOverridesScope, setQueryDevtoolsArmedMocksScope, setQueryDevtoolsFaultsScope, setQueryDevtoolsSettings, QUERY_DEVTOOLS_TOKEN_TTL_LIMIT, setQueryDevtoolsTokenTtl, clearQueryDevtoolsTokenTtl, serializeQueryDevtoolsOverrideTransfer, parseQueryDevtoolsOverrideTransfer, armQueryDevtoolsOverrideTransfer, countUnresolvedQueryDevtoolsOverrides, createQueryDevtoolsOverrides, applyQueryDevtoolsOverrides, queryDevtoolsSchemaNames, queryDevtoolsSchemaRoutes, queryDevtoolsSchemaState, measureQueryDevtoolsPayload, seedQueryDevtoolsSchemaBody, loadQueryDevtoolsSchema, queryDevtoolsMockId, saveQueryDevtoolsMock, armQueryDevtoolsMock, deleteQueryDevtoolsMock, collectQueryDevtoolsSchemaComponents, seedQueryDevtoolsSchemaRoute, QUERY_DEVTOOLS_FAULT_STATUSES, setQueryDevtoolsFault, clearQueryDevtoolsTombstones, readQueryDevtoolsStore, createQueryKeyLockManager, queryDevtoolsEntries, queryDevtoolsTokenTtls, queryDevtoolsFaults, EMPTY_QUERY_DEVTOOLS_FAULT, isQueryDevtoolsFaultArmed, queryDevtoolsFaultsRestored, queryDevtoolsArmedMocksRestored, restoredQueryDevtoolsOverrides, queryDevtoolsRestoredOverridesScope, clearRestoredQueryDevtoolsOverrides, clearQueryDevtoolsStore, writeQueryDevtoolsStore, registerEthleteVersion, queryDevtoolsOverridePersistence, setQueryDevtoolsOverridePersistence, clearQueryDevtoolsOverrideStore, clearQueryDevtoolsMockStore, createQueryErrorResponse, applyQueryDevtoolsTokenTtl, canOverrideQueryDevtoolsTokenTtl, sumQueryDevtoolsStats } from '@ethlete/query';
|
|
4
|
+
import { queryDevtoolsAbout, hasQueryDevtoolsOverridesAtPath, detectPaginationShape, isDateShapedLeaf, generateQueryDevtoolsStringPreset, generateQueryDevtoolsNumberPreset, collectLeafPaths, armAllQueryDevtoolsMocks, clearQueryDevtoolsArmedMocks, clearQueryDevtoolsFaults, queryDevtoolsResponseHistory, queryDevtoolsMocks, queryDevtoolsAuthSessions, queryDevtoolsArmedMocks, clearQueryDevtoolsAuthSessions, queryDevtoolsApiEnvs, queryDevtoolsApiEnvValues, setQueryDevtoolsApiEnv, queryDevtoolsSettings, setQueryDevtoolsOverridesScope, setQueryDevtoolsArmedMocksScope, setQueryDevtoolsFaultsScope, setQueryDevtoolsSettings, QUERY_DEVTOOLS_TOKEN_TTL_LIMIT, queryDevtoolsApiEnvIsProduction, queryDevtoolsAuthSessionsFor, queryDevtoolsAuthAccountsFor, queryDevtoolsAuthOtherScopeCount, queryDevtoolsAuthActive, queryDevtoolsAuthTabLocal, switchQueryDevtoolsAuthSession, renameQueryDevtoolsAuthSession, forgetQueryDevtoolsAuthSession, logoutQueryDevtoolsAuthSession, setQueryDevtoolsAuthTabLocal, loginQueryDevtoolsAuthAccount, setQueryDevtoolsAuthCredentials, clearQueryDevtoolsAuthCredentials, removeQueryDevtoolsAuthAccount, addQueryDevtoolsAuthAccount, setQueryDevtoolsTokenTtl, clearQueryDevtoolsTokenTtl, serializeQueryDevtoolsOverrideTransfer, parseQueryDevtoolsOverrideTransfer, armQueryDevtoolsOverrideTransfer, countUnresolvedQueryDevtoolsOverrides, createQueryDevtoolsOverrides, applyQueryDevtoolsOverrides, queryDevtoolsSchemaNames, queryDevtoolsSchemaRoutes, queryDevtoolsSchemaState, measureQueryDevtoolsPayload, seedQueryDevtoolsSchemaBody, loadQueryDevtoolsSchema, queryDevtoolsMockId, saveQueryDevtoolsMock, armQueryDevtoolsMock, deleteQueryDevtoolsMock, collectQueryDevtoolsSchemaComponents, seedQueryDevtoolsSchemaRoute, QUERY_DEVTOOLS_FAULT_STATUSES, setQueryDevtoolsFault, clearQueryDevtoolsTombstones, readQueryDevtoolsStore, createQueryKeyLockManager, queryDevtoolsEntries, queryDevtoolsTokenTtls, queryDevtoolsFaults, EMPTY_QUERY_DEVTOOLS_FAULT, isQueryDevtoolsFaultArmed, queryDevtoolsFaultsRestored, queryDevtoolsArmedMocksRestored, restoredQueryDevtoolsOverrides, queryDevtoolsRestoredOverridesScope, clearRestoredQueryDevtoolsOverrides, clearQueryDevtoolsStore, writeQueryDevtoolsStore, registerEthleteVersion, queryDevtoolsOverridePersistence, setQueryDevtoolsOverridePersistence, clearQueryDevtoolsOverrideStore, clearQueryDevtoolsMockStore, createQueryErrorResponse, applyQueryDevtoolsTokenTtl, canOverrideQueryDevtoolsTokenTtl, sumQueryDevtoolsStats } from '@ethlete/query';
|
|
5
5
|
import { tap, Subject, switchMap, timer, interval, animationFrames, NEVER, takeUntil, finalize as finalize$1, EMPTY, startWith, merge, map, fromEvent, filter, take } from 'rxjs';
|
|
6
6
|
import { takeUntilDestroyed, toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
7
7
|
import { MenuDirective, MenuTriggerDirective, MenuSurfaceDirective, MenuComponent, MenuItemComponent, MenuSearchDirective, MenuSeparatorComponent, MenuItemShortcutComponent, SelectComponent, SelectSearchDirective, COMPONENTS_VERSION, MenuCheckboxItemComponent, MenuRadioGroupComponent, MenuRadioItemComponent } from '@ethlete/components';
|
|
8
|
+
import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
|
|
8
9
|
import { HttpHeaders, HttpErrorResponse } from '@angular/common/http';
|
|
9
|
-
import { NgTemplateOutlet, DOCUMENT } from '@angular/common';
|
|
10
10
|
import { QUERY_DEVTOOLS_VIEW_STATE_KEY, queryDevtoolsShortcutLabel, QueryDevtoolsToggleComponent } from '@ethlete/query-devtools/toggle';
|
|
11
11
|
|
|
12
12
|
const groupsOf = () => {
|
|
@@ -1343,6 +1343,15 @@ const SCOPE_ROWS = [
|
|
|
1343
1343
|
text: 'The next page load starts serving these routes from the panel, before anyone opens it. The bar above the tabs says when they came back.',
|
|
1344
1344
|
},
|
|
1345
1345
|
},
|
|
1346
|
+
{
|
|
1347
|
+
key: 'authSessions',
|
|
1348
|
+
label: 'Sessions and accounts',
|
|
1349
|
+
hint: 'The token pairs the Auth tab switches between, and the credentials it logs in with. Local is the default: a vault that forgets the other user on every reload is not one. None keeps nothing at all.',
|
|
1350
|
+
warn: {
|
|
1351
|
+
scopes: ['local'],
|
|
1352
|
+
text: 'Access and refresh tokens for every user you logged in as, plus what you typed into the account fields, stay in this browser until you forget them. They are never kept for an API env marked production.',
|
|
1353
|
+
},
|
|
1354
|
+
},
|
|
1346
1355
|
{
|
|
1347
1356
|
key: 'armedFaults',
|
|
1348
1357
|
label: 'Armed faults',
|
|
@@ -1390,6 +1399,7 @@ const LIMIT_ROWS = [
|
|
|
1390
1399
|
*/
|
|
1391
1400
|
class QueryDevtoolsSettingsComponent {
|
|
1392
1401
|
constructor() {
|
|
1402
|
+
this.document = inject(DOCUMENT);
|
|
1393
1403
|
this.host = injectQueryDevtoolsHost();
|
|
1394
1404
|
this.SCOPE_ROWS = SCOPE_ROWS;
|
|
1395
1405
|
this.SCOPES = SCOPES;
|
|
@@ -1403,12 +1413,51 @@ class QueryDevtoolsSettingsComponent {
|
|
|
1403
1413
|
...(ngDevMode ? [{ debugName: "responseHistory" }] : /* istanbul ignore next */ []));
|
|
1404
1414
|
this.mockCount = computed(() => queryDevtoolsMocks().length, /* @ts-ignore */
|
|
1405
1415
|
...(ngDevMode ? [{ debugName: "mockCount" }] : /* istanbul ignore next */ []));
|
|
1416
|
+
this.sessionCount = computed(() => queryDevtoolsAuthSessions().length, /* @ts-ignore */
|
|
1417
|
+
...(ngDevMode ? [{ debugName: "sessionCount" }] : /* istanbul ignore next */ []));
|
|
1406
1418
|
this.armedMockCount = computed(() => queryDevtoolsArmedMocks().size, /* @ts-ignore */
|
|
1407
1419
|
...(ngDevMode ? [{ debugName: "armedMockCount" }] : /* istanbul ignore next */ []));
|
|
1408
1420
|
this.armedFaultCount = computed(() => this.host.faultClients().filter((client) => client.armed).length, /* @ts-ignore */
|
|
1409
1421
|
...(ngDevMode ? [{ debugName: "armedFaultCount" }] : /* istanbul ignore next */ []));
|
|
1410
1422
|
this.resetConfirming = signal(false, /* @ts-ignore */
|
|
1411
1423
|
...(ngDevMode ? [{ debugName: "resetConfirming" }] : /* istanbul ignore next */ []));
|
|
1424
|
+
this.FORGET_SESSIONS = clearQueryDevtoolsAuthSessions;
|
|
1425
|
+
/** The backends the application declared, or an empty list - the card renders only for a declared one. */
|
|
1426
|
+
this.apiEnvs = computed(queryDevtoolsApiEnvs, /* @ts-ignore */
|
|
1427
|
+
...(ngDevMode ? [{ debugName: "apiEnvs" }] : /* istanbul ignore next */ []));
|
|
1428
|
+
}
|
|
1429
|
+
/** The env id (or typed URL) a switch's key holds, or `null` while the application picks for itself. */
|
|
1430
|
+
apiEnvValue(apiSwitch) {
|
|
1431
|
+
return queryDevtoolsApiEnvValues()[apiSwitch.storageKey] ?? null;
|
|
1432
|
+
}
|
|
1433
|
+
/** The env a switch falls back to with nothing stored, described for the default button. */
|
|
1434
|
+
apiEnvFallback(apiSwitch) {
|
|
1435
|
+
const fallback = apiSwitch.envs.find((env) => env.id === apiSwitch.fallback);
|
|
1436
|
+
return {
|
|
1437
|
+
label: fallback ? `default (${fallback.label ?? fallback.id})` : 'default',
|
|
1438
|
+
production: fallback?.production === true,
|
|
1439
|
+
};
|
|
1440
|
+
}
|
|
1441
|
+
/** Whether the pick in force - the stored env, or the fallback behind an unwritten key - is production. */
|
|
1442
|
+
apiEnvIsProduction(apiSwitch) {
|
|
1443
|
+
const stored = this.apiEnvValue(apiSwitch);
|
|
1444
|
+
return apiSwitch.envs.find((env) => env.id === (stored ?? apiSwitch.fallback))?.production === true;
|
|
1445
|
+
}
|
|
1446
|
+
/** A stored value no declared env carries, which is a URL somebody typed in below. */
|
|
1447
|
+
apiEnvCustomUrl(apiSwitch) {
|
|
1448
|
+
const stored = this.apiEnvValue(apiSwitch);
|
|
1449
|
+
return stored && !apiSwitch.envs.some((env) => env.id === stored) ? stored : '';
|
|
1450
|
+
}
|
|
1451
|
+
/** Writes the application's own key and reloads - it is read before Angular boots, so nothing else can. */
|
|
1452
|
+
pickApiEnv(apiSwitch, value) {
|
|
1453
|
+
setQueryDevtoolsApiEnv(apiSwitch.storageKey, value);
|
|
1454
|
+
this.document.defaultView?.location.reload();
|
|
1455
|
+
}
|
|
1456
|
+
setCustomApiUrl(apiSwitch, value) {
|
|
1457
|
+
const url = value.trim();
|
|
1458
|
+
if (url === this.apiEnvCustomUrl(apiSwitch))
|
|
1459
|
+
return;
|
|
1460
|
+
this.pickApiEnv(apiSwitch, url || null);
|
|
1412
1461
|
}
|
|
1413
1462
|
settings() {
|
|
1414
1463
|
return queryDevtoolsSettings();
|
|
@@ -1432,7 +1481,13 @@ class QueryDevtoolsSettingsComponent {
|
|
|
1432
1481
|
return setQueryDevtoolsArmedMocksScope(scope);
|
|
1433
1482
|
if (key === 'armedFaults')
|
|
1434
1483
|
return setQueryDevtoolsFaultsScope(scope);
|
|
1435
|
-
setQueryDevtoolsSettings(key === 'viewState'
|
|
1484
|
+
setQueryDevtoolsSettings(key === 'viewState'
|
|
1485
|
+
? { viewState: scope }
|
|
1486
|
+
: key === 'pins'
|
|
1487
|
+
? { pins: scope }
|
|
1488
|
+
: key === 'authSessions'
|
|
1489
|
+
? { authSessions: scope }
|
|
1490
|
+
: { mocks: scope });
|
|
1436
1491
|
}
|
|
1437
1492
|
setLimit(key, value) {
|
|
1438
1493
|
const count = Number(value);
|
|
@@ -1456,11 +1511,11 @@ class QueryDevtoolsSettingsComponent {
|
|
|
1456
1511
|
return this.host.queryFacets().has('gone');
|
|
1457
1512
|
}
|
|
1458
1513
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: QueryDevtoolsSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1459
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: QueryDevtoolsSettingsComponent, isStandalone: true, selector: "et-query-devtools-settings", ngImport: i0, template: "<div class=\"et-query-devtools-scroll\">\n <div class=\"et-query-devtools-toolbar et-query-devtools-settings-toolbar\">\n <p class=\"et-query-devtools-hint\">\n Panel-wide, and kept in <code class=\"et-query-devtools-mono\">localStorage</code> whatever the scopes below say -\n so a scope of <em>none</em> does not erase the choice that set it. Every switch under <strong>Mirrored</strong> is\n the same one its own tab carries.\n </p>\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Storage</strong>\n <span class=\"et-query-devtools-count\">what survives a reload, and how long</span>\n </div>\n\n @for (row of SCOPE_ROWS; track row.key) {\n @let scope = scopeOf(row.key);\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>{{ row.label }}</span>\n <div class=\"et-query-devtools-btn-group\">\n @for (option of SCOPES; track option.value) {\n <button\n [class.et-query-devtools-btn--active]=\"scope === option.value\"\n [attr.aria-pressed]=\"scope === option.value\"\n (click)=\"setScope(row.key, option.value)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n {{ option.label }}\n </button>\n }\n <button [title]=\"INDEXED_DB_TITLE\" class=\"et-query-devtools-btn\" type=\"button\" disabled>IndexedDB</button>\n </div>\n </div>\n <small>{{ row.hint }}</small>\n @if (warningFor(row, scope); as warning) {\n <p class=\"et-query-devtools-settings-warn\">\n <span aria-hidden=\"true\">\u26A0</span>\n {{ warning }}\n </p>\n }\n </div>\n }\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Reset devtools</span>\n @if (resetConfirming()) {\n <div class=\"et-query-devtools-btn-group\">\n <button (click)=\"reset()\" class=\"et-query-devtools-btn et-query-devtools-btn--danger\" type=\"button\">\n Reset everything\n </button>\n <button (click)=\"resetConfirming.set(false)\" class=\"et-query-devtools-btn\" type=\"button\">Cancel</button>\n </div>\n } @else {\n <button (click)=\"resetConfirming.set(true)\" class=\"et-query-devtools-btn\" type=\"button\">Reset\u2026</button>\n }\n </div>\n <small>\n Clears every one of these keys from both stores, whatever the scopes above say, and puts the panel back where it\n ships - layout, filters, selections and pins. The settings on this tab stay.\n </small>\n </div>\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Limits</strong>\n <span class=\"et-query-devtools-count\">how much the panel keeps in memory</span>\n </div>\n\n <div class=\"et-query-devtools-settings-fields\">\n @for (row of LIMIT_ROWS; track row.key) {\n <label class=\"et-query-devtools-field\">\n <span>{{ row.label }}</span>\n <input\n #limitInput\n [value]=\"limitOf(row.key)\"\n [min]=\"row.min\"\n [max]=\"row.max\"\n [step]=\"row.step\"\n (change)=\"setLimit(row.key, limitInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n />\n <small>{{ row.hint }}</small>\n </label>\n }\n\n <label class=\"et-query-devtools-field\">\n <span>Response history</span>\n <input\n #responseHistoryInput\n [value]=\"responseHistory()\"\n (change)=\"setResponseHistory(responseHistoryInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"1\"\n max=\"50\"\n step=\"1\"\n />\n <small>\n bodies each query keeps, which is how far back a response diff can reach. Bodies dominate what the run buffer\n retains, so this is the one limit that costs real memory. Applies to runs from now on.\n @if (settings().responseHistory !== null) {\n <button (click)=\"clearResponseHistory()\" class=\"et-query-devtools-btn\" type=\"button\">\n Back to the app's own value\n </button>\n }\n </small>\n </label>\n </div>\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Mirrored</strong>\n <span class=\"et-query-devtools-count\">the same switches their tabs carry</span>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Queries</span>\n <div class=\"et-query-devtools-btn-group\">\n @let recentFirst = host.queryRecentFirst();\n <button\n [class.et-query-devtools-btn--active]=\"recentFirst\"\n [attr.aria-pressed]=\"recentFirst\"\n (click)=\"host.queryRecentFirst.set(!recentFirst)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n recent first\n </button>\n @let treeView = host.queryTreeView();\n <button\n [class.et-query-devtools-btn--active]=\"treeView\"\n [attr.aria-pressed]=\"treeView\"\n (click)=\"host.queryTreeView.set(!treeView)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n tree view\n </button>\n @let gone = showsGoneQueries();\n <button\n [class.et-query-devtools-btn--active]=\"gone\"\n [attr.aria-pressed]=\"gone\"\n (click)=\"toggleGoneQueries()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n list gone\n </button>\n </div>\n </div>\n <small>Sort order, whether the list groups by route path, and whether destroyed queries are listed at all.</small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Events</span>\n <div class=\"et-query-devtools-settings-controls\">\n @let errorsOnly = host.eventErrorsOnly();\n <button\n [class.et-query-devtools-btn--active]=\"errorsOnly\"\n [attr.aria-pressed]=\"errorsOnly\"\n (click)=\"host.eventErrorsOnly.set(!errorsOnly)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n failures only\n </button>\n <select\n #eventClientSelect\n [value]=\"host.eventClient() ?? ''\"\n (change)=\"host.eventClient.set(eventClientSelect.value || null)\"\n class=\"et-query-devtools-select\"\n aria-label=\"Event log client\"\n >\n <option value=\"\">All clients</option>\n @for (name of host.clientNames(); track name) {\n <option [value]=\"name\">{{ name }}</option>\n }\n </select>\n </div>\n </div>\n <small>What the event log is narrowed to. The log itself always holds every client's traffic.</small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Response overrides</span>\n @let persist = host.overridesPersist();\n <button\n [class.et-query-devtools-btn--active]=\"persist\"\n [attr.aria-pressed]=\"persist\"\n (click)=\"host.toggleOverridesPersist()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Keep across reloads\n </button>\n </div>\n <small>\n The drawer's own toggle, which is the Storage scope above - currently\n <span class=\"et-query-devtools-mono\">{{ host.overridesScopeLabel() }}</span\n >.\n </small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Armed</span>\n <div class=\"et-query-devtools-settings-controls\">\n <button\n [disabled]=\"!mockCount() || armedMockCount() === mockCount()\"\n (click)=\"ARM_ALL_MOCKS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Arm every mock ({{ mockCount() }})\n </button>\n <button\n [disabled]=\"!armedMockCount()\"\n (click)=\"DISARM_ALL_MOCKS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Disarm mocks ({{ armedMockCount() }})\n </button>\n <button\n [disabled]=\"!armedFaultCount()\"\n (click)=\"DISARM_ALL_FAULTS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Disarm faults ({{ armedFaultCount() }})\n </button>\n </div>\n </div>\n <small>\n The Mocks and Faults tabs' own buttons. Whether either survives a reload is the two <em>Armed</em> scopes above,\n both <em>none</em> unless they were changed.\n </small>\n </div>\n </div>\n</div>\n", styles: ["@layer components{.et-query-devtools-settings-toolbar{align-items:flex-start}.et-query-devtools-settings-row{padding-block:.6rem;border-block-start:1px solid var(--_et-qdt-border)}.et-query-devtools-card>.et-query-devtools-settings-row:first-of-type{border-block-start:0;padding-block-start:0}.et-query-devtools-settings-row-head{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.6rem}.et-query-devtools-settings-controls{display:flex;align-items:center;gap:.5rem}.et-query-devtools-settings-row>small{display:block;max-inline-size:60rem;margin-block-start:.3rem;color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-settings-warn{margin:.4rem 0 0;color:var(--_et-qdt-error);font-size:1.1rem}.et-query-devtools-settings-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(24rem,1fr));align-items:start;gap:.8rem 1.6rem}.et-query-devtools-settings-fields .et-query-devtools-field{display:grid;grid-template-columns:11rem minmax(0,1fr);align-items:baseline;row-gap:.2rem;color:var(--_et-qdt-fg)}.et-query-devtools-settings-fields .et-query-devtools-field small{grid-column:2;color:var(--_et-qdt-subtle);font-size:1.1rem}}\n"], encapsulation: i0.ViewEncapsulation.None }); }
|
|
1514
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: QueryDevtoolsSettingsComponent, isStandalone: true, selector: "et-query-devtools-settings", ngImport: i0, template: "<div class=\"et-query-devtools-scroll\">\n <div class=\"et-query-devtools-toolbar et-query-devtools-settings-toolbar\">\n <p class=\"et-query-devtools-hint\">\n Panel-wide, and kept in <code class=\"et-query-devtools-mono\">localStorage</code> whatever the scopes below say -\n so a scope of <em>none</em> does not erase the choice that set it. Every switch under <strong>Mirrored</strong> is\n the same one its own tab carries.\n </p>\n </div>\n\n @if (apiEnvs().length) {\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>API environment</strong>\n <span class=\"et-query-devtools-count\">the app's own key, not the panel's - picking reloads the page</span>\n </div>\n\n @for (apiSwitch of apiEnvs(); track apiSwitch.storageKey) {\n @let value = apiEnvValue(apiSwitch);\n @let custom = apiEnvCustomUrl(apiSwitch);\n @let fallback = apiEnvFallback(apiSwitch);\n @let production = apiEnvIsProduction(apiSwitch);\n <div [class.et-query-devtools-settings-api--production]=\"production\" class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>{{ apiSwitch.name }}</span>\n <div class=\"et-query-devtools-btn-group\">\n <button\n [class.et-query-devtools-btn--active]=\"value === null\"\n [class.et-query-devtools-btn--danger]=\"fallback.production\"\n [attr.aria-pressed]=\"value === null\"\n (click)=\"pickApiEnv(apiSwitch, null)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n {{ fallback.production ? '\u26A0 ' : '' }}{{ fallback.label }}\n </button>\n @for (env of apiSwitch.envs; track env.id) {\n <button\n [class.et-query-devtools-btn--active]=\"value === env.id\"\n [class.et-query-devtools-btn--danger]=\"env.production\"\n [attr.aria-pressed]=\"value === env.id\"\n [title]=\"env.url ?? env.id\"\n (click)=\"pickApiEnv(apiSwitch, env.id)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n {{ env.production ? '\u26A0 ' : '' }}{{ env.label ?? env.id }}\n </button>\n }\n </div>\n </div>\n @if (production) {\n <strong class=\"et-query-devtools-settings-api-live\">\n Live data. Every request from this app reaches the real backend.\n </strong>\n }\n <small>\n Written to <span class=\"et-query-devtools-mono\">{{ apiSwitch.storageKey }}</span> in\n <code class=\"et-query-devtools-mono\">localStorage</code>, which the app reads before it boots.\n </small>\n @if (apiSwitch.custom) {\n <label class=\"et-query-devtools-field et-query-devtools-settings-api-url\">\n <span>Base URL</span>\n <input\n #customUrlInput\n [value]=\"custom\"\n (change)=\"setCustomApiUrl(apiSwitch, customUrlInput.value)\"\n class=\"et-query-devtools-input\"\n type=\"url\"\n placeholder=\"http://localhost:8040\"\n />\n <small>A backend none of the buttons above name. Empty goes back to the app's own default.</small>\n </label>\n }\n </div>\n }\n </div>\n }\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Storage</strong>\n <span class=\"et-query-devtools-count\">what survives a reload, and how long</span>\n </div>\n\n @for (row of SCOPE_ROWS; track row.key) {\n @let scope = scopeOf(row.key);\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>{{ row.label }}</span>\n <div class=\"et-query-devtools-btn-group\">\n @for (option of SCOPES; track option.value) {\n <button\n [class.et-query-devtools-btn--active]=\"scope === option.value\"\n [attr.aria-pressed]=\"scope === option.value\"\n (click)=\"setScope(row.key, option.value)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n {{ option.label }}\n </button>\n }\n <button [title]=\"INDEXED_DB_TITLE\" class=\"et-query-devtools-btn\" type=\"button\" disabled>IndexedDB</button>\n </div>\n </div>\n <small>{{ row.hint }}</small>\n @if (warningFor(row, scope); as warning) {\n <p class=\"et-query-devtools-settings-warn\">\n <span aria-hidden=\"true\">\u26A0</span>\n {{ warning }}\n </p>\n }\n </div>\n }\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Reset devtools</span>\n @if (resetConfirming()) {\n <div class=\"et-query-devtools-btn-group\">\n <button (click)=\"reset()\" class=\"et-query-devtools-btn et-query-devtools-btn--danger\" type=\"button\">\n Reset everything\n </button>\n <button (click)=\"resetConfirming.set(false)\" class=\"et-query-devtools-btn\" type=\"button\">Cancel</button>\n </div>\n } @else {\n <button (click)=\"resetConfirming.set(true)\" class=\"et-query-devtools-btn\" type=\"button\">Reset\u2026</button>\n }\n </div>\n <small>\n Clears every one of these keys from both stores, whatever the scopes above say, and puts the panel back where it\n ships - layout, filters, selections and pins. The settings on this tab stay.\n </small>\n </div>\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Limits</strong>\n <span class=\"et-query-devtools-count\">how much the panel keeps in memory</span>\n </div>\n\n <div class=\"et-query-devtools-settings-fields\">\n @for (row of LIMIT_ROWS; track row.key) {\n <label class=\"et-query-devtools-field\">\n <span>{{ row.label }}</span>\n <input\n #limitInput\n [value]=\"limitOf(row.key)\"\n [min]=\"row.min\"\n [max]=\"row.max\"\n [step]=\"row.step\"\n (change)=\"setLimit(row.key, limitInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n />\n <small>{{ row.hint }}</small>\n </label>\n }\n\n <label class=\"et-query-devtools-field\">\n <span>Response history</span>\n <input\n #responseHistoryInput\n [value]=\"responseHistory()\"\n (change)=\"setResponseHistory(responseHistoryInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"1\"\n max=\"50\"\n step=\"1\"\n />\n <small>\n bodies each query keeps, which is how far back a response diff can reach. Bodies dominate what the run buffer\n retains, so this is the one limit that costs real memory. Applies to runs from now on.\n @if (settings().responseHistory !== null) {\n <button (click)=\"clearResponseHistory()\" class=\"et-query-devtools-btn\" type=\"button\">\n Back to the app's own value\n </button>\n }\n </small>\n </label>\n </div>\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Mirrored</strong>\n <span class=\"et-query-devtools-count\">the same switches their tabs carry</span>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Queries</span>\n <div class=\"et-query-devtools-btn-group\">\n @let recentFirst = host.queryRecentFirst();\n <button\n [class.et-query-devtools-btn--active]=\"recentFirst\"\n [attr.aria-pressed]=\"recentFirst\"\n (click)=\"host.queryRecentFirst.set(!recentFirst)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n recent first\n </button>\n @let treeView = host.queryTreeView();\n <button\n [class.et-query-devtools-btn--active]=\"treeView\"\n [attr.aria-pressed]=\"treeView\"\n (click)=\"host.queryTreeView.set(!treeView)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n tree view\n </button>\n @let gone = showsGoneQueries();\n <button\n [class.et-query-devtools-btn--active]=\"gone\"\n [attr.aria-pressed]=\"gone\"\n (click)=\"toggleGoneQueries()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n list gone\n </button>\n </div>\n </div>\n <small>Sort order, whether the list groups by route path, and whether destroyed queries are listed at all.</small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Sessions</span>\n <div class=\"et-query-devtools-settings-controls\">\n <span class=\"et-query-devtools-count\">{{ sessionCount() }} stored</span>\n <button\n [disabled]=\"!sessionCount()\"\n (click)=\"FORGET_SESSIONS()\"\n class=\"et-query-devtools-btn et-query-devtools-btn--danger\"\n type=\"button\"\n >\n Forget every session\n </button>\n </div>\n </div>\n <small>\n Drops every stored token pair, every account added in the panel and every credential typed into one. The live\n session is left alone - the Auth tab switches between them.\n </small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Events</span>\n <div class=\"et-query-devtools-settings-controls\">\n @let errorsOnly = host.eventErrorsOnly();\n <button\n [class.et-query-devtools-btn--active]=\"errorsOnly\"\n [attr.aria-pressed]=\"errorsOnly\"\n (click)=\"host.eventErrorsOnly.set(!errorsOnly)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n failures only\n </button>\n <select\n #eventClientSelect\n [value]=\"host.eventClient() ?? ''\"\n (change)=\"host.eventClient.set(eventClientSelect.value || null)\"\n class=\"et-query-devtools-select\"\n aria-label=\"Event log client\"\n >\n <option value=\"\">All clients</option>\n @for (name of host.clientNames(); track name) {\n <option [value]=\"name\">{{ name }}</option>\n }\n </select>\n </div>\n </div>\n <small>What the event log is narrowed to. The log itself always holds every client's traffic.</small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Response overrides</span>\n @let persist = host.overridesPersist();\n <button\n [class.et-query-devtools-btn--active]=\"persist\"\n [attr.aria-pressed]=\"persist\"\n (click)=\"host.toggleOverridesPersist()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Keep across reloads\n </button>\n </div>\n <small>\n The drawer's own toggle, which is the Storage scope above - currently\n <span class=\"et-query-devtools-mono\">{{ host.overridesScopeLabel() }}</span\n >.\n </small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Armed</span>\n <div class=\"et-query-devtools-settings-controls\">\n <button\n [disabled]=\"!mockCount() || armedMockCount() === mockCount()\"\n (click)=\"ARM_ALL_MOCKS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Arm every mock ({{ mockCount() }})\n </button>\n <button\n [disabled]=\"!armedMockCount()\"\n (click)=\"DISARM_ALL_MOCKS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Disarm mocks ({{ armedMockCount() }})\n </button>\n <button\n [disabled]=\"!armedFaultCount()\"\n (click)=\"DISARM_ALL_FAULTS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Disarm faults ({{ armedFaultCount() }})\n </button>\n </div>\n </div>\n <small>\n The Mocks and Faults tabs' own buttons. Whether either survives a reload is the two <em>Armed</em> scopes above,\n both <em>none</em> unless they were changed.\n </small>\n </div>\n </div>\n</div>\n", styles: ["@layer components{.et-query-devtools-settings-toolbar{align-items:flex-start}.et-query-devtools-settings-row{padding-block:.6rem;border-block-start:1px solid var(--_et-qdt-border)}.et-query-devtools-card>.et-query-devtools-settings-row:first-of-type{border-block-start:0;padding-block-start:0}.et-query-devtools-settings-row-head{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.6rem}.et-query-devtools-settings-controls{display:flex;align-items:center;gap:.5rem}.et-query-devtools-settings-row>small{display:block;max-inline-size:60rem;margin-block-start:.3rem;color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-settings-warn{margin:.4rem 0 0;color:var(--_et-qdt-error);font-size:1.1rem}.et-query-devtools-settings-api--production{background:color-mix(in srgb,var(--_et-qdt-error) 8%,transparent);box-shadow:inset .3rem 0 0 var(--_et-qdt-error);padding-inline-start:.8rem}.et-query-devtools-settings-api-live{display:block;margin-block-start:.4rem;color:var(--_et-qdt-error);font-size:1.2rem}.et-query-devtools-btn--danger.et-query-devtools-btn--active{background:color-mix(in srgb,var(--_et-qdt-error) 28%,transparent);border-color:var(--_et-qdt-error);color:#fff}@media(prefers-reduced-motion:no-preference){.et-query-devtools-settings-api-live{animation:et-qdt-settings-api-live 1.6s ease-in-out infinite}}@keyframes et-qdt-settings-api-live{0%,to{opacity:.55}50%{opacity:1}}.et-query-devtools-settings-api-url{display:grid;grid-template-columns:auto minmax(0,32rem);align-items:center;margin-block-start:.5rem;gap:.2rem .6rem}.et-query-devtools-settings-api-url small{grid-column:1 / -1;max-inline-size:60rem;color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-settings-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(24rem,1fr));align-items:start;gap:.8rem 1.6rem}.et-query-devtools-settings-fields .et-query-devtools-field{display:grid;grid-template-columns:11rem minmax(0,1fr);align-items:baseline;row-gap:.2rem;color:var(--_et-qdt-fg)}.et-query-devtools-settings-fields .et-query-devtools-field small{grid-column:2;color:var(--_et-qdt-subtle);font-size:1.1rem}}\n"], encapsulation: i0.ViewEncapsulation.None }); }
|
|
1460
1515
|
}
|
|
1461
1516
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: QueryDevtoolsSettingsComponent, decorators: [{
|
|
1462
1517
|
type: Component,
|
|
1463
|
-
args: [{ selector: 'et-query-devtools-settings', encapsulation: ViewEncapsulation.None, template: "<div class=\"et-query-devtools-scroll\">\n <div class=\"et-query-devtools-toolbar et-query-devtools-settings-toolbar\">\n <p class=\"et-query-devtools-hint\">\n Panel-wide, and kept in <code class=\"et-query-devtools-mono\">localStorage</code> whatever the scopes below say -\n so a scope of <em>none</em> does not erase the choice that set it. Every switch under <strong>Mirrored</strong> is\n the same one its own tab carries.\n </p>\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Storage</strong>\n <span class=\"et-query-devtools-count\">what survives a reload, and how long</span>\n </div>\n\n @for (row of SCOPE_ROWS; track row.key) {\n @let scope = scopeOf(row.key);\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>{{ row.label }}</span>\n <div class=\"et-query-devtools-btn-group\">\n @for (option of SCOPES; track option.value) {\n <button\n [class.et-query-devtools-btn--active]=\"scope === option.value\"\n [attr.aria-pressed]=\"scope === option.value\"\n (click)=\"setScope(row.key, option.value)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n {{ option.label }}\n </button>\n }\n <button [title]=\"INDEXED_DB_TITLE\" class=\"et-query-devtools-btn\" type=\"button\" disabled>IndexedDB</button>\n </div>\n </div>\n <small>{{ row.hint }}</small>\n @if (warningFor(row, scope); as warning) {\n <p class=\"et-query-devtools-settings-warn\">\n <span aria-hidden=\"true\">\u26A0</span>\n {{ warning }}\n </p>\n }\n </div>\n }\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Reset devtools</span>\n @if (resetConfirming()) {\n <div class=\"et-query-devtools-btn-group\">\n <button (click)=\"reset()\" class=\"et-query-devtools-btn et-query-devtools-btn--danger\" type=\"button\">\n Reset everything\n </button>\n <button (click)=\"resetConfirming.set(false)\" class=\"et-query-devtools-btn\" type=\"button\">Cancel</button>\n </div>\n } @else {\n <button (click)=\"resetConfirming.set(true)\" class=\"et-query-devtools-btn\" type=\"button\">Reset\u2026</button>\n }\n </div>\n <small>\n Clears every one of these keys from both stores, whatever the scopes above say, and puts the panel back where it\n ships - layout, filters, selections and pins. The settings on this tab stay.\n </small>\n </div>\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Limits</strong>\n <span class=\"et-query-devtools-count\">how much the panel keeps in memory</span>\n </div>\n\n <div class=\"et-query-devtools-settings-fields\">\n @for (row of LIMIT_ROWS; track row.key) {\n <label class=\"et-query-devtools-field\">\n <span>{{ row.label }}</span>\n <input\n #limitInput\n [value]=\"limitOf(row.key)\"\n [min]=\"row.min\"\n [max]=\"row.max\"\n [step]=\"row.step\"\n (change)=\"setLimit(row.key, limitInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n />\n <small>{{ row.hint }}</small>\n </label>\n }\n\n <label class=\"et-query-devtools-field\">\n <span>Response history</span>\n <input\n #responseHistoryInput\n [value]=\"responseHistory()\"\n (change)=\"setResponseHistory(responseHistoryInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"1\"\n max=\"50\"\n step=\"1\"\n />\n <small>\n bodies each query keeps, which is how far back a response diff can reach. Bodies dominate what the run buffer\n retains, so this is the one limit that costs real memory. Applies to runs from now on.\n @if (settings().responseHistory !== null) {\n <button (click)=\"clearResponseHistory()\" class=\"et-query-devtools-btn\" type=\"button\">\n Back to the app's own value\n </button>\n }\n </small>\n </label>\n </div>\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Mirrored</strong>\n <span class=\"et-query-devtools-count\">the same switches their tabs carry</span>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Queries</span>\n <div class=\"et-query-devtools-btn-group\">\n @let recentFirst = host.queryRecentFirst();\n <button\n [class.et-query-devtools-btn--active]=\"recentFirst\"\n [attr.aria-pressed]=\"recentFirst\"\n (click)=\"host.queryRecentFirst.set(!recentFirst)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n recent first\n </button>\n @let treeView = host.queryTreeView();\n <button\n [class.et-query-devtools-btn--active]=\"treeView\"\n [attr.aria-pressed]=\"treeView\"\n (click)=\"host.queryTreeView.set(!treeView)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n tree view\n </button>\n @let gone = showsGoneQueries();\n <button\n [class.et-query-devtools-btn--active]=\"gone\"\n [attr.aria-pressed]=\"gone\"\n (click)=\"toggleGoneQueries()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n list gone\n </button>\n </div>\n </div>\n <small>Sort order, whether the list groups by route path, and whether destroyed queries are listed at all.</small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Events</span>\n <div class=\"et-query-devtools-settings-controls\">\n @let errorsOnly = host.eventErrorsOnly();\n <button\n [class.et-query-devtools-btn--active]=\"errorsOnly\"\n [attr.aria-pressed]=\"errorsOnly\"\n (click)=\"host.eventErrorsOnly.set(!errorsOnly)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n failures only\n </button>\n <select\n #eventClientSelect\n [value]=\"host.eventClient() ?? ''\"\n (change)=\"host.eventClient.set(eventClientSelect.value || null)\"\n class=\"et-query-devtools-select\"\n aria-label=\"Event log client\"\n >\n <option value=\"\">All clients</option>\n @for (name of host.clientNames(); track name) {\n <option [value]=\"name\">{{ name }}</option>\n }\n </select>\n </div>\n </div>\n <small>What the event log is narrowed to. The log itself always holds every client's traffic.</small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Response overrides</span>\n @let persist = host.overridesPersist();\n <button\n [class.et-query-devtools-btn--active]=\"persist\"\n [attr.aria-pressed]=\"persist\"\n (click)=\"host.toggleOverridesPersist()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Keep across reloads\n </button>\n </div>\n <small>\n The drawer's own toggle, which is the Storage scope above - currently\n <span class=\"et-query-devtools-mono\">{{ host.overridesScopeLabel() }}</span\n >.\n </small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Armed</span>\n <div class=\"et-query-devtools-settings-controls\">\n <button\n [disabled]=\"!mockCount() || armedMockCount() === mockCount()\"\n (click)=\"ARM_ALL_MOCKS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Arm every mock ({{ mockCount() }})\n </button>\n <button\n [disabled]=\"!armedMockCount()\"\n (click)=\"DISARM_ALL_MOCKS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Disarm mocks ({{ armedMockCount() }})\n </button>\n <button\n [disabled]=\"!armedFaultCount()\"\n (click)=\"DISARM_ALL_FAULTS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Disarm faults ({{ armedFaultCount() }})\n </button>\n </div>\n </div>\n <small>\n The Mocks and Faults tabs' own buttons. Whether either survives a reload is the two <em>Armed</em> scopes above,\n both <em>none</em> unless they were changed.\n </small>\n </div>\n </div>\n</div>\n", styles: ["@layer components{.et-query-devtools-settings-toolbar{align-items:flex-start}.et-query-devtools-settings-row{padding-block:.6rem;border-block-start:1px solid var(--_et-qdt-border)}.et-query-devtools-card>.et-query-devtools-settings-row:first-of-type{border-block-start:0;padding-block-start:0}.et-query-devtools-settings-row-head{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.6rem}.et-query-devtools-settings-controls{display:flex;align-items:center;gap:.5rem}.et-query-devtools-settings-row>small{display:block;max-inline-size:60rem;margin-block-start:.3rem;color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-settings-warn{margin:.4rem 0 0;color:var(--_et-qdt-error);font-size:1.1rem}.et-query-devtools-settings-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(24rem,1fr));align-items:start;gap:.8rem 1.6rem}.et-query-devtools-settings-fields .et-query-devtools-field{display:grid;grid-template-columns:11rem minmax(0,1fr);align-items:baseline;row-gap:.2rem;color:var(--_et-qdt-fg)}.et-query-devtools-settings-fields .et-query-devtools-field small{grid-column:2;color:var(--_et-qdt-subtle);font-size:1.1rem}}\n"] }]
|
|
1518
|
+
args: [{ selector: 'et-query-devtools-settings', encapsulation: ViewEncapsulation.None, template: "<div class=\"et-query-devtools-scroll\">\n <div class=\"et-query-devtools-toolbar et-query-devtools-settings-toolbar\">\n <p class=\"et-query-devtools-hint\">\n Panel-wide, and kept in <code class=\"et-query-devtools-mono\">localStorage</code> whatever the scopes below say -\n so a scope of <em>none</em> does not erase the choice that set it. Every switch under <strong>Mirrored</strong> is\n the same one its own tab carries.\n </p>\n </div>\n\n @if (apiEnvs().length) {\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>API environment</strong>\n <span class=\"et-query-devtools-count\">the app's own key, not the panel's - picking reloads the page</span>\n </div>\n\n @for (apiSwitch of apiEnvs(); track apiSwitch.storageKey) {\n @let value = apiEnvValue(apiSwitch);\n @let custom = apiEnvCustomUrl(apiSwitch);\n @let fallback = apiEnvFallback(apiSwitch);\n @let production = apiEnvIsProduction(apiSwitch);\n <div [class.et-query-devtools-settings-api--production]=\"production\" class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>{{ apiSwitch.name }}</span>\n <div class=\"et-query-devtools-btn-group\">\n <button\n [class.et-query-devtools-btn--active]=\"value === null\"\n [class.et-query-devtools-btn--danger]=\"fallback.production\"\n [attr.aria-pressed]=\"value === null\"\n (click)=\"pickApiEnv(apiSwitch, null)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n {{ fallback.production ? '\u26A0 ' : '' }}{{ fallback.label }}\n </button>\n @for (env of apiSwitch.envs; track env.id) {\n <button\n [class.et-query-devtools-btn--active]=\"value === env.id\"\n [class.et-query-devtools-btn--danger]=\"env.production\"\n [attr.aria-pressed]=\"value === env.id\"\n [title]=\"env.url ?? env.id\"\n (click)=\"pickApiEnv(apiSwitch, env.id)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n {{ env.production ? '\u26A0 ' : '' }}{{ env.label ?? env.id }}\n </button>\n }\n </div>\n </div>\n @if (production) {\n <strong class=\"et-query-devtools-settings-api-live\">\n Live data. Every request from this app reaches the real backend.\n </strong>\n }\n <small>\n Written to <span class=\"et-query-devtools-mono\">{{ apiSwitch.storageKey }}</span> in\n <code class=\"et-query-devtools-mono\">localStorage</code>, which the app reads before it boots.\n </small>\n @if (apiSwitch.custom) {\n <label class=\"et-query-devtools-field et-query-devtools-settings-api-url\">\n <span>Base URL</span>\n <input\n #customUrlInput\n [value]=\"custom\"\n (change)=\"setCustomApiUrl(apiSwitch, customUrlInput.value)\"\n class=\"et-query-devtools-input\"\n type=\"url\"\n placeholder=\"http://localhost:8040\"\n />\n <small>A backend none of the buttons above name. Empty goes back to the app's own default.</small>\n </label>\n }\n </div>\n }\n </div>\n }\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Storage</strong>\n <span class=\"et-query-devtools-count\">what survives a reload, and how long</span>\n </div>\n\n @for (row of SCOPE_ROWS; track row.key) {\n @let scope = scopeOf(row.key);\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>{{ row.label }}</span>\n <div class=\"et-query-devtools-btn-group\">\n @for (option of SCOPES; track option.value) {\n <button\n [class.et-query-devtools-btn--active]=\"scope === option.value\"\n [attr.aria-pressed]=\"scope === option.value\"\n (click)=\"setScope(row.key, option.value)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n {{ option.label }}\n </button>\n }\n <button [title]=\"INDEXED_DB_TITLE\" class=\"et-query-devtools-btn\" type=\"button\" disabled>IndexedDB</button>\n </div>\n </div>\n <small>{{ row.hint }}</small>\n @if (warningFor(row, scope); as warning) {\n <p class=\"et-query-devtools-settings-warn\">\n <span aria-hidden=\"true\">\u26A0</span>\n {{ warning }}\n </p>\n }\n </div>\n }\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Reset devtools</span>\n @if (resetConfirming()) {\n <div class=\"et-query-devtools-btn-group\">\n <button (click)=\"reset()\" class=\"et-query-devtools-btn et-query-devtools-btn--danger\" type=\"button\">\n Reset everything\n </button>\n <button (click)=\"resetConfirming.set(false)\" class=\"et-query-devtools-btn\" type=\"button\">Cancel</button>\n </div>\n } @else {\n <button (click)=\"resetConfirming.set(true)\" class=\"et-query-devtools-btn\" type=\"button\">Reset\u2026</button>\n }\n </div>\n <small>\n Clears every one of these keys from both stores, whatever the scopes above say, and puts the panel back where it\n ships - layout, filters, selections and pins. The settings on this tab stay.\n </small>\n </div>\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Limits</strong>\n <span class=\"et-query-devtools-count\">how much the panel keeps in memory</span>\n </div>\n\n <div class=\"et-query-devtools-settings-fields\">\n @for (row of LIMIT_ROWS; track row.key) {\n <label class=\"et-query-devtools-field\">\n <span>{{ row.label }}</span>\n <input\n #limitInput\n [value]=\"limitOf(row.key)\"\n [min]=\"row.min\"\n [max]=\"row.max\"\n [step]=\"row.step\"\n (change)=\"setLimit(row.key, limitInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n />\n <small>{{ row.hint }}</small>\n </label>\n }\n\n <label class=\"et-query-devtools-field\">\n <span>Response history</span>\n <input\n #responseHistoryInput\n [value]=\"responseHistory()\"\n (change)=\"setResponseHistory(responseHistoryInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"1\"\n max=\"50\"\n step=\"1\"\n />\n <small>\n bodies each query keeps, which is how far back a response diff can reach. Bodies dominate what the run buffer\n retains, so this is the one limit that costs real memory. Applies to runs from now on.\n @if (settings().responseHistory !== null) {\n <button (click)=\"clearResponseHistory()\" class=\"et-query-devtools-btn\" type=\"button\">\n Back to the app's own value\n </button>\n }\n </small>\n </label>\n </div>\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Mirrored</strong>\n <span class=\"et-query-devtools-count\">the same switches their tabs carry</span>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Queries</span>\n <div class=\"et-query-devtools-btn-group\">\n @let recentFirst = host.queryRecentFirst();\n <button\n [class.et-query-devtools-btn--active]=\"recentFirst\"\n [attr.aria-pressed]=\"recentFirst\"\n (click)=\"host.queryRecentFirst.set(!recentFirst)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n recent first\n </button>\n @let treeView = host.queryTreeView();\n <button\n [class.et-query-devtools-btn--active]=\"treeView\"\n [attr.aria-pressed]=\"treeView\"\n (click)=\"host.queryTreeView.set(!treeView)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n tree view\n </button>\n @let gone = showsGoneQueries();\n <button\n [class.et-query-devtools-btn--active]=\"gone\"\n [attr.aria-pressed]=\"gone\"\n (click)=\"toggleGoneQueries()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n list gone\n </button>\n </div>\n </div>\n <small>Sort order, whether the list groups by route path, and whether destroyed queries are listed at all.</small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Sessions</span>\n <div class=\"et-query-devtools-settings-controls\">\n <span class=\"et-query-devtools-count\">{{ sessionCount() }} stored</span>\n <button\n [disabled]=\"!sessionCount()\"\n (click)=\"FORGET_SESSIONS()\"\n class=\"et-query-devtools-btn et-query-devtools-btn--danger\"\n type=\"button\"\n >\n Forget every session\n </button>\n </div>\n </div>\n <small>\n Drops every stored token pair, every account added in the panel and every credential typed into one. The live\n session is left alone - the Auth tab switches between them.\n </small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Events</span>\n <div class=\"et-query-devtools-settings-controls\">\n @let errorsOnly = host.eventErrorsOnly();\n <button\n [class.et-query-devtools-btn--active]=\"errorsOnly\"\n [attr.aria-pressed]=\"errorsOnly\"\n (click)=\"host.eventErrorsOnly.set(!errorsOnly)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n failures only\n </button>\n <select\n #eventClientSelect\n [value]=\"host.eventClient() ?? ''\"\n (change)=\"host.eventClient.set(eventClientSelect.value || null)\"\n class=\"et-query-devtools-select\"\n aria-label=\"Event log client\"\n >\n <option value=\"\">All clients</option>\n @for (name of host.clientNames(); track name) {\n <option [value]=\"name\">{{ name }}</option>\n }\n </select>\n </div>\n </div>\n <small>What the event log is narrowed to. The log itself always holds every client's traffic.</small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Response overrides</span>\n @let persist = host.overridesPersist();\n <button\n [class.et-query-devtools-btn--active]=\"persist\"\n [attr.aria-pressed]=\"persist\"\n (click)=\"host.toggleOverridesPersist()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Keep across reloads\n </button>\n </div>\n <small>\n The drawer's own toggle, which is the Storage scope above - currently\n <span class=\"et-query-devtools-mono\">{{ host.overridesScopeLabel() }}</span\n >.\n </small>\n </div>\n\n <div class=\"et-query-devtools-settings-row\">\n <div class=\"et-query-devtools-settings-row-head\">\n <span>Armed</span>\n <div class=\"et-query-devtools-settings-controls\">\n <button\n [disabled]=\"!mockCount() || armedMockCount() === mockCount()\"\n (click)=\"ARM_ALL_MOCKS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Arm every mock ({{ mockCount() }})\n </button>\n <button\n [disabled]=\"!armedMockCount()\"\n (click)=\"DISARM_ALL_MOCKS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Disarm mocks ({{ armedMockCount() }})\n </button>\n <button\n [disabled]=\"!armedFaultCount()\"\n (click)=\"DISARM_ALL_FAULTS()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Disarm faults ({{ armedFaultCount() }})\n </button>\n </div>\n </div>\n <small>\n The Mocks and Faults tabs' own buttons. Whether either survives a reload is the two <em>Armed</em> scopes above,\n both <em>none</em> unless they were changed.\n </small>\n </div>\n </div>\n</div>\n", styles: ["@layer components{.et-query-devtools-settings-toolbar{align-items:flex-start}.et-query-devtools-settings-row{padding-block:.6rem;border-block-start:1px solid var(--_et-qdt-border)}.et-query-devtools-card>.et-query-devtools-settings-row:first-of-type{border-block-start:0;padding-block-start:0}.et-query-devtools-settings-row-head{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.6rem}.et-query-devtools-settings-controls{display:flex;align-items:center;gap:.5rem}.et-query-devtools-settings-row>small{display:block;max-inline-size:60rem;margin-block-start:.3rem;color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-settings-warn{margin:.4rem 0 0;color:var(--_et-qdt-error);font-size:1.1rem}.et-query-devtools-settings-api--production{background:color-mix(in srgb,var(--_et-qdt-error) 8%,transparent);box-shadow:inset .3rem 0 0 var(--_et-qdt-error);padding-inline-start:.8rem}.et-query-devtools-settings-api-live{display:block;margin-block-start:.4rem;color:var(--_et-qdt-error);font-size:1.2rem}.et-query-devtools-btn--danger.et-query-devtools-btn--active{background:color-mix(in srgb,var(--_et-qdt-error) 28%,transparent);border-color:var(--_et-qdt-error);color:#fff}@media(prefers-reduced-motion:no-preference){.et-query-devtools-settings-api-live{animation:et-qdt-settings-api-live 1.6s ease-in-out infinite}}@keyframes et-qdt-settings-api-live{0%,to{opacity:.55}50%{opacity:1}}.et-query-devtools-settings-api-url{display:grid;grid-template-columns:auto minmax(0,32rem);align-items:center;margin-block-start:.5rem;gap:.2rem .6rem}.et-query-devtools-settings-api-url small{grid-column:1 / -1;max-inline-size:60rem;color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-settings-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(24rem,1fr));align-items:start;gap:.8rem 1.6rem}.et-query-devtools-settings-fields .et-query-devtools-field{display:grid;grid-template-columns:11rem minmax(0,1fr);align-items:baseline;row-gap:.2rem;color:var(--_et-qdt-fg)}.et-query-devtools-settings-fields .et-query-devtools-field small{grid-column:2;color:var(--_et-qdt-subtle);font-size:1.1rem}}\n"] }]
|
|
1464
1519
|
}] });
|
|
1465
1520
|
|
|
1466
1521
|
/**
|
|
@@ -1534,11 +1589,127 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
1534
1589
|
`, encapsulation: ViewEncapsulation.None, styles: ["@layer components{.et-query-devtools-features{display:grid;grid-template-columns:max-content minmax(0,1fr);align-items:center;gap:.4rem .8rem;margin:0 0 .8rem;padding:0;list-style:none}.et-query-devtools-meta .et-query-devtools-features{margin-block-end:0}.et-query-devtools-feature{display:contents}.et-query-devtools-feature>.et-query-devtools-chip{justify-self:start}.et-query-devtools-feature-details{display:flex;flex-wrap:wrap;gap:.3rem}.et-query-devtools-feature-detail{display:inline-flex;align-items:baseline;gap:.4rem;padding:.2rem .5rem;border-radius:.4rem;background:color-mix(in srgb,var(--_et-qdt-interaction) 5%,transparent);font-size:1.1rem}.et-query-devtools-feature-label{color:var(--_et-qdt-muted)}.et-query-devtools-feature-value{color:var(--_et-qdt-fg);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}}\n"] }]
|
|
1535
1590
|
}], propDecorators: { features: [{ type: i0.Input, args: [{ isSignal: true, alias: "features", required: true }] }] } });
|
|
1536
1591
|
|
|
1537
|
-
/** The Auth tab: registered bearer auth providers, their tokens and their
|
|
1592
|
+
/** The Auth tab: registered bearer auth providers, their tokens, their sessions and their queries. */
|
|
1538
1593
|
class QueryDevtoolsAuthTabComponent {
|
|
1539
1594
|
constructor() {
|
|
1540
1595
|
this.host = injectQueryDevtoolsHost();
|
|
1541
1596
|
this.TTL_LIMIT = QUERY_DEVTOOLS_TOKEN_TTL_LIMIT;
|
|
1597
|
+
/** Which accounts show their credential fields. Nothing is expanded until somebody asks for it. */
|
|
1598
|
+
this.expandedAccounts = signal(new Set(), /* @ts-ignore */
|
|
1599
|
+
...(ngDevMode ? [{ debugName: "expandedAccounts" }] : /* istanbul ignore next */ []));
|
|
1600
|
+
/** Which providers show the form that adds an account of your own. */
|
|
1601
|
+
this.addingFor = signal(new Set(), /* @ts-ignore */
|
|
1602
|
+
...(ngDevMode ? [{ debugName: "addingFor" }] : /* istanbul ignore next */ []));
|
|
1603
|
+
/** Nothing of a real user is ever kept on this machine, so the whole vault stands down. */
|
|
1604
|
+
this.production = computed(queryDevtoolsApiEnvIsProduction, /* @ts-ignore */
|
|
1605
|
+
...(ngDevMode ? [{ debugName: "production" }] : /* istanbul ignore next */ []));
|
|
1606
|
+
this.reloadOnSwitch = computed(() => queryDevtoolsSettings().reloadOnAuthSwitch, /* @ts-ignore */
|
|
1607
|
+
...(ngDevMode ? [{ debugName: "reloadOnSwitch" }] : /* istanbul ignore next */ []));
|
|
1608
|
+
}
|
|
1609
|
+
sessionsFor(entry) {
|
|
1610
|
+
return queryDevtoolsAuthSessionsFor(this.providerName(entry));
|
|
1611
|
+
}
|
|
1612
|
+
accountsFor(entry) {
|
|
1613
|
+
return queryDevtoolsAuthAccountsFor(this.providerName(entry));
|
|
1614
|
+
}
|
|
1615
|
+
/** How many sessions this provider holds for a backend the app is not pointed at now. */
|
|
1616
|
+
otherScopeCount(entry) {
|
|
1617
|
+
return queryDevtoolsAuthOtherScopeCount(this.providerName(entry));
|
|
1618
|
+
}
|
|
1619
|
+
isActive(entry, session) {
|
|
1620
|
+
return queryDevtoolsAuthActive()[this.providerName(entry)] === session.id;
|
|
1621
|
+
}
|
|
1622
|
+
isTabLocal(entry) {
|
|
1623
|
+
return queryDevtoolsAuthTabLocal()[this.providerName(entry)] === true;
|
|
1624
|
+
}
|
|
1625
|
+
/** The provider's own auth queries, which is what an account added here can log in through. */
|
|
1626
|
+
loginQueries(entry) {
|
|
1627
|
+
return (entry.meta.authQueries ?? []).filter((query) => query.kind === 'auth').map((query) => query.key);
|
|
1628
|
+
}
|
|
1629
|
+
sessionAge(session) {
|
|
1630
|
+
if (!session.savedAt)
|
|
1631
|
+
return 'unknown';
|
|
1632
|
+
const seconds = Math.round((Date.now() - session.savedAt) / 1000);
|
|
1633
|
+
if (seconds < 60)
|
|
1634
|
+
return `${seconds}s ago`;
|
|
1635
|
+
if (seconds < 3600)
|
|
1636
|
+
return `${Math.round(seconds / 60)}m ago`;
|
|
1637
|
+
return `${Math.round(seconds / 3600)}h ago`;
|
|
1638
|
+
}
|
|
1639
|
+
/** Whether the stored access token is spent, which the refresh token is expected to fix on a switch. */
|
|
1640
|
+
isExpired(session) {
|
|
1641
|
+
return session.expiresAt !== null && session.expiresAt * 1000 < Date.now();
|
|
1642
|
+
}
|
|
1643
|
+
switchTo(session) {
|
|
1644
|
+
switchQueryDevtoolsAuthSession({ sessionId: session.id });
|
|
1645
|
+
}
|
|
1646
|
+
rename(session, label) {
|
|
1647
|
+
if (label.trim() === '' || label === session.label)
|
|
1648
|
+
return;
|
|
1649
|
+
renameQueryDevtoolsAuthSession({ sessionId: session.id, label: label.trim() });
|
|
1650
|
+
}
|
|
1651
|
+
forget(session) {
|
|
1652
|
+
forgetQueryDevtoolsAuthSession(session.id);
|
|
1653
|
+
}
|
|
1654
|
+
logout(entry) {
|
|
1655
|
+
logoutQueryDevtoolsAuthSession(this.providerName(entry));
|
|
1656
|
+
}
|
|
1657
|
+
toggleTabLocal(entry) {
|
|
1658
|
+
setQueryDevtoolsAuthTabLocal({ provider: this.providerName(entry), tabLocal: !this.isTabLocal(entry) });
|
|
1659
|
+
}
|
|
1660
|
+
login(account) {
|
|
1661
|
+
loginQueryDevtoolsAuthAccount(account.id);
|
|
1662
|
+
}
|
|
1663
|
+
isExpanded(account) {
|
|
1664
|
+
return this.expandedAccounts().has(account.id);
|
|
1665
|
+
}
|
|
1666
|
+
toggleCredentials(account) {
|
|
1667
|
+
this.expandedAccounts.update((current) => {
|
|
1668
|
+
const next = new Set(current);
|
|
1669
|
+
if (!next.delete(account.id))
|
|
1670
|
+
next.add(account.id);
|
|
1671
|
+
return next;
|
|
1672
|
+
});
|
|
1673
|
+
}
|
|
1674
|
+
/** One field at a time, merged into what is already there - a login form here would be a form to build. */
|
|
1675
|
+
setCredential(options) {
|
|
1676
|
+
const { account, field, value } = options;
|
|
1677
|
+
setQueryDevtoolsAuthCredentials({ accountId: account.id, values: { ...account.values, [field]: value } });
|
|
1678
|
+
}
|
|
1679
|
+
clearCredentials(account) {
|
|
1680
|
+
clearQueryDevtoolsAuthCredentials(account.id);
|
|
1681
|
+
}
|
|
1682
|
+
removeAccount(account) {
|
|
1683
|
+
removeQueryDevtoolsAuthAccount(account.id);
|
|
1684
|
+
}
|
|
1685
|
+
isAdding(entry) {
|
|
1686
|
+
return this.addingFor().has(this.providerName(entry));
|
|
1687
|
+
}
|
|
1688
|
+
toggleAdding(entry) {
|
|
1689
|
+
this.addingFor.update((current) => {
|
|
1690
|
+
const next = new Set(current);
|
|
1691
|
+
if (!next.delete(this.providerName(entry)))
|
|
1692
|
+
next.add(this.providerName(entry));
|
|
1693
|
+
return next;
|
|
1694
|
+
});
|
|
1695
|
+
}
|
|
1696
|
+
addAccount(options) {
|
|
1697
|
+
const { entry, label, loginQuery } = options;
|
|
1698
|
+
if (label.trim() === '' || !loginQuery)
|
|
1699
|
+
return;
|
|
1700
|
+
const id = addQueryDevtoolsAuthAccount({
|
|
1701
|
+
provider: this.providerName(entry),
|
|
1702
|
+
label: label.trim(),
|
|
1703
|
+
loginQuery,
|
|
1704
|
+
});
|
|
1705
|
+
this.expandedAccounts.update((current) => new Set(current).add(id));
|
|
1706
|
+
this.toggleAdding(entry);
|
|
1707
|
+
}
|
|
1708
|
+
setReloadOnSwitch(reload) {
|
|
1709
|
+
setQueryDevtoolsSettings({ reloadOnAuthSwitch: reload });
|
|
1710
|
+
}
|
|
1711
|
+
forgetEverything() {
|
|
1712
|
+
clearQueryDevtoolsAuthSessions();
|
|
1542
1713
|
}
|
|
1543
1714
|
/**
|
|
1544
1715
|
* Arms an access-token lifetime from the input's raw value, or disarms on an empty one. Clamped here
|
|
@@ -1563,11 +1734,11 @@ class QueryDevtoolsAuthTabComponent {
|
|
|
1563
1734
|
return entry.meta.name ?? '';
|
|
1564
1735
|
}
|
|
1565
1736
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: QueryDevtoolsAuthTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1566
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: QueryDevtoolsAuthTabComponent, isStandalone: true, selector: "et-query-devtools-auth-tab", ngImport: i0, template: "<div class=\"et-query-devtools-scroll\">\n @for (entry of host.authEntries(); track entry.id) {\n @let auth = host.asAuth(entry);\n @let lifetime = host.authTokenLifetime(entry);\n <div [class.et-query-devtools-card--armed]=\"lifetime.ttlSeconds !== null\" class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>{{ entry.meta.name || 'auth provider' }}</strong>\n <span\n [class.et-query-devtools-chip--success]=\"auth.isAuthenticated()\"\n [class.et-query-devtools-chip--muted]=\"!auth.isAuthenticated()\"\n class=\"et-query-devtools-chip\"\n >\n {{ auth.isAuthenticated() ? 'authenticated' : 'anonymous' }}\n </span>\n @if (lifetime.ttlSeconds !== null) {\n <span\n [title]=\"\n 'This provider\\'s access token is presented as living ' +\n lifetime.ttlSeconds +\n 's from the moment it was issued, so the refresh happens on that lifetime instead of the real one.'\n \"\n class=\"et-query-devtools-chip et-query-devtools-chip--error\"\n >\n lifetime {{ lifetime.ttlSeconds }}s\n </span>\n }\n @if (host.authLeadership(auth); as leadership) {\n <span\n [class.et-query-devtools-chip--success]=\"leadership.tone === 'success'\"\n [class.et-query-devtools-chip--muted]=\"leadership.tone === 'muted'\"\n [title]=\"leadership.title\"\n class=\"et-query-devtools-chip\"\n >\n {{ leadership.label }}\n </span>\n }\n </div>\n <dl class=\"et-query-devtools-meta\">\n <dt>Base URL</dt>\n <dd class=\"et-query-devtools-mono\">{{ entry.meta.clientBaseUrl || entry.meta.clientName || '\u2014' }}</dd>\n <dt>Access token</dt>\n <dd>{{ auth.accessToken() ? 'present' : 'none' }}</dd>\n <dt>Refresh token</dt>\n <dd>{{ auth.refreshToken() ? 'present' : 'none' }}</dd>\n @if (lifetime.expiresIn; as expiry) {\n <dt>Token expires in</dt>\n <dd>\n {{ expiry }}\n @if (lifetime.realExpiresIn; as real) {\n <small class=\"et-query-devtools-auth-real-expiry\">really {{ real }}</small>\n }\n </dd>\n }\n @if (auth.executionState(); as state) {\n <dt>Execution state</dt>\n <dd>{{ state.type }} \u00B7 {{ state.state }}</dd>\n }\n @if (host.authQueryKeys(auth).length) {\n <dt>Queries</dt>\n <dd>\n <div class=\"et-query-devtools-chips\">\n @for (key of host.authQueryKeys(auth); track key) {\n <span class=\"et-query-devtools-chip\">{{ key }}</span>\n }\n </div>\n </dd>\n }\n @if (entry.meta.features?.length) {\n <dt>Features</dt>\n <dd>\n <et-query-devtools-features [features]=\"entry.meta.features ?? []\" />\n </dd>\n }\n </dl>\n\n @if (auth.accessToken()) {\n <h4 class=\"et-query-devtools-section\">Token lifetime</h4>\n @if (lifetime.overridable) {\n <div class=\"et-query-devtools-auth-ttl\">\n <div class=\"et-query-devtools-auth-ttl-row\">\n <label class=\"et-query-devtools-field\">\n <span>Override</span>\n <input\n #ttlInput\n [value]=\"lifetime.ttlSeconds ?? ''\"\n [max]=\"TTL_LIMIT\"\n (change)=\"armTokenTtl({ entry: entry, value: ttlInput.value })\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"0\"\n step=\"30\"\n />\n <small>seconds, or empty for the lifetime the token was issued with</small>\n </label>\n <div class=\"et-query-devtools-auth-ttl-actions\">\n <button (click)=\"expireTokenNow(entry)\" class=\"et-query-devtools-btn\" type=\"button\">Expire now</button>\n @if (lifetime.ttlSeconds !== null) {\n <button (click)=\"clearTokenTtl(entry)\" class=\"et-query-devtools-btn\" type=\"button\">Clear</button>\n }\n </div>\n </div>\n <p class=\"et-query-devtools-hint\">\n Measured from the token's own <code>iat</code>, so this is a lifetime and not a remaining time - a short\n one on a token issued a while ago refreshes at once, and the token that comes back lives the full\n lifetime. It is what the whole app acts on: the proactive refresh, the expiration warning and the\n countdown above all read it. Never persisted - a reload puts this provider back on its real lifetime.\n </p>\n </div>\n } @else {\n <p class=\"et-query-devtools-hint\">\n This access token carries no <code>exp</code> claim to replace, or no <code>iat</code>/<code>nbf</code> to\n measure a new lifetime from, so it cannot be overridden.\n </p>\n }\n }\n\n @if (host.authTokenPayload(auth); as payload) {\n <h4 class=\"et-query-devtools-section\">Access token payload</h4>\n <et-query-devtools-json [value]=\"payload\" />\n }\n\n @if (auth.latestNonInternalQuery(); as latest) {\n <h4 class=\"et-query-devtools-section\">Latest auth query \u00B7 {{ latest.key }}</h4>\n <et-query-devtools-json [value]=\"latest.snapshot.response()\" />\n }\n </div>\n } @empty {\n <p class=\"et-query-devtools-empty\">No auth providers registered.</p>\n }\n</div>\n", styles: ["@layer components{.et-query-devtools-auth-real-expiry{color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-auth-ttl{display:flex;flex-direction:column;align-items:start;gap:.8rem}.et-query-devtools-auth-ttl-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:.8rem 1.6rem}.et-query-devtools-auth-ttl-row .et-query-devtools-field{color:var(--_et-qdt-fg)}.et-query-devtools-auth-ttl-row .et-query-devtools-field small{color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-auth-ttl-actions{display:flex;flex-wrap:wrap;gap:.6rem}.et-query-devtools-auth-ttl .et-query-devtools-hint{flex:0 0 auto;max-inline-size:90ch}}\n"], dependencies: [{ kind: "component", type: QueryDevtoolsFeaturesComponent, selector: "et-query-devtools-features", inputs: ["features"] }, { kind: "component", type: QueryDevtoolsJsonComponent, selector: "et-query-devtools-json", inputs: ["value", "nodeKey", "depth", "search", "chunk", "path", "expandedPaths", "collapsedPaths", "toggleFn", "jsonPath", "parentKind", "overrides", "annotations"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
1737
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: QueryDevtoolsAuthTabComponent, isStandalone: true, selector: "et-query-devtools-auth-tab", ngImport: i0, template: "<div class=\"et-query-devtools-scroll\">\n @for (entry of host.authEntries(); track entry.id) {\n @let auth = host.asAuth(entry);\n @let lifetime = host.authTokenLifetime(entry);\n <div [class.et-query-devtools-card--armed]=\"lifetime.ttlSeconds !== null\" class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>{{ entry.meta.name || 'auth provider' }}</strong>\n <span\n [class.et-query-devtools-chip--success]=\"auth.isAuthenticated()\"\n [class.et-query-devtools-chip--muted]=\"!auth.isAuthenticated()\"\n class=\"et-query-devtools-chip\"\n >\n {{ auth.isAuthenticated() ? 'authenticated' : 'anonymous' }}\n </span>\n @if (lifetime.ttlSeconds !== null) {\n <span\n [title]=\"\n 'This provider\\'s access token is presented as living ' +\n lifetime.ttlSeconds +\n 's from the moment it was issued, so the refresh happens on that lifetime instead of the real one.'\n \"\n class=\"et-query-devtools-chip et-query-devtools-chip--error\"\n >\n lifetime {{ lifetime.ttlSeconds }}s\n </span>\n }\n @if (host.authLeadership(auth); as leadership) {\n <span\n [class.et-query-devtools-chip--success]=\"leadership.tone === 'success'\"\n [class.et-query-devtools-chip--muted]=\"leadership.tone === 'muted'\"\n [title]=\"leadership.title\"\n class=\"et-query-devtools-chip\"\n >\n {{ leadership.label }}\n </span>\n }\n </div>\n <dl class=\"et-query-devtools-meta\">\n <dt>Base URL</dt>\n <dd class=\"et-query-devtools-mono\">{{ entry.meta.clientBaseUrl || entry.meta.clientName || '\u2014' }}</dd>\n <dt>Access token</dt>\n <dd>{{ auth.accessToken() ? 'present' : 'none' }}</dd>\n <dt>Refresh token</dt>\n <dd>{{ auth.refreshToken() ? 'present' : 'none' }}</dd>\n @if (lifetime.expiresIn; as expiry) {\n <dt>Token expires in</dt>\n <dd>\n {{ expiry }}\n @if (lifetime.realExpiresIn; as real) {\n <small class=\"et-query-devtools-auth-real-expiry\">really {{ real }}</small>\n }\n </dd>\n }\n @if (auth.executionState(); as state) {\n <dt>Execution state</dt>\n <dd>{{ state.type }} \u00B7 {{ state.state }}</dd>\n }\n @if (host.authQueryKeys(auth).length) {\n <dt>Queries</dt>\n <dd>\n <div class=\"et-query-devtools-chips\">\n @for (key of host.authQueryKeys(auth); track key) {\n <span class=\"et-query-devtools-chip\">{{ key }}</span>\n }\n </div>\n </dd>\n }\n @if (entry.meta.features?.length) {\n <dt>Features</dt>\n <dd>\n <et-query-devtools-features [features]=\"entry.meta.features ?? []\" />\n </dd>\n }\n </dl>\n\n <h4 class=\"et-query-devtools-section\">Sessions</h4>\n @if (production()) {\n <p class=\"et-query-devtools-hint\">\n A production env is the pick. Nothing of a real user's session is kept here - no tokens, no credentials - so\n the vault and the accounts stand down until a different backend is picked.\n </p>\n } @else {\n @let sessions = sessionsFor(entry);\n @let accounts = accountsFor(entry);\n <div class=\"et-query-devtools-auth-vault\">\n <div class=\"et-query-devtools-auth-vault-actions\">\n <button\n [class.et-query-devtools-btn--active]=\"isTabLocal(entry)\"\n [attr.aria-pressed]=\"isTabLocal(entry)\"\n [title]=\"\n isTabLocal(entry)\n ? 'Hands this tab back to the session every other tab shares. Reloads the page.'\n : 'Keeps this session in this tab alone, so another tab can be somebody else. Reloads the page.'\n \"\n (click)=\"toggleTabLocal(entry)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n {{ isTabLocal(entry) ? 'Rejoin the shared session' : 'Own this tab' }}\n </button>\n <button\n [disabled]=\"!auth.isAuthenticated()\"\n (click)=\"logout(entry)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Log out\n </button>\n <button\n [class.et-query-devtools-btn--active]=\"reloadOnSwitch()\"\n [attr.aria-pressed]=\"reloadOnSwitch()\"\n (click)=\"setReloadOnSwitch(!reloadOnSwitch())\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"A switch only replaces what the query layer holds. An app that keeps the user in a service, the router or an open form is still showing the last one until it boots again.\"\n >\n reload on switch\n </button>\n </div>\n\n @if (isTabLocal(entry)) {\n <p class=\"et-query-devtools-hint\">\n This tab holds its own session. It syncs nothing to the other tabs and writes no persistence cookie, so\n every other tab stays on whoever it was.\n </p>\n }\n\n @for (session of sessions; track session.id) {\n <div\n [class.et-query-devtools-auth-session--active]=\"isActive(entry, session)\"\n class=\"et-query-devtools-auth-session\"\n >\n <input\n #labelInput\n [value]=\"session.label\"\n (change)=\"rename(session, labelInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-auth-session-label\"\n type=\"text\"\n aria-label=\"Session name\"\n />\n @if (isActive(entry, session)) {\n <span class=\"et-query-devtools-chip et-query-devtools-chip--success\">in force</span>\n }\n @if (isExpired(session)) {\n <span\n class=\"et-query-devtools-chip et-query-devtools-chip--muted\"\n title=\"The stored access token is spent. Switching to it refreshes on the stored refresh token, which works while the server has not spent that one too.\"\n >\n token expired\n </span>\n }\n <span class=\"et-query-devtools-count\"\n >{{ session.subject ?? 'no subject' }} \u00B7 {{ sessionAge(session) }}</span\n >\n <div class=\"et-query-devtools-auth-session-buttons\">\n <button\n [disabled]=\"isActive(entry, session)\"\n (click)=\"switchTo(session)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Switch\n </button>\n <button (click)=\"forget(session)\" class=\"et-query-devtools-btn\" type=\"button\">Forget</button>\n </div>\n </div>\n } @empty {\n <p class=\"et-query-devtools-hint\">\n No session stored for this backend yet. Log in as you normally would and this one appears here, ready to\n be switched back to once you are somebody else.\n </p>\n }\n\n @if (otherScopeCount(entry); as other) {\n <small class=\"et-query-devtools-auth-vault-other\">\n {{ other }} more stored under a different API env. Pick that env again to switch to them.\n </small>\n }\n\n <div class=\"et-query-devtools-auth-vault-head\">\n <strong>Accounts</strong>\n <span class=\"et-query-devtools-count\">credentials are typed in here and stay in this browser</span>\n <button (click)=\"toggleAdding(entry)\" class=\"et-query-devtools-btn\" type=\"button\">\n {{ isAdding(entry) ? 'Cancel' : 'Add account' }}\n </button>\n </div>\n\n @if (isAdding(entry)) {\n <div class=\"et-query-devtools-auth-account-add\">\n <input\n #newLabel\n class=\"et-query-devtools-input\"\n type=\"text\"\n placeholder=\"Admin\"\n aria-label=\"Account name\"\n />\n <select #newQuery class=\"et-query-devtools-select\" aria-label=\"Login query\">\n @for (key of loginQueries(entry); track key) {\n <option [value]=\"key\">{{ key }}</option>\n }\n </select>\n <button\n (click)=\"addAccount({ entry: entry, label: newLabel.value, loginQuery: newQuery.value })\"\n class=\"et-query-devtools-btn et-query-devtools-btn--primary\"\n type=\"button\"\n >\n Add\n </button>\n </div>\n }\n\n @for (account of accounts; track account.id) {\n <div class=\"et-query-devtools-auth-account\">\n <div class=\"et-query-devtools-auth-account-head\">\n <strong>{{ account.label }}</strong>\n @if (account.note) {\n <span class=\"et-query-devtools-count\">{{ account.note }}</span>\n }\n <span class=\"et-query-devtools-chip et-query-devtools-chip--muted\">{{ account.loginQuery }}</span>\n @if (!account.ready) {\n <span class=\"et-query-devtools-chip et-query-devtools-chip--error\">needs credentials</span>\n }\n <div class=\"et-query-devtools-auth-session-buttons\">\n <button\n [disabled]=\"!account.ready\"\n (click)=\"login(account)\"\n class=\"et-query-devtools-btn et-query-devtools-btn--primary\"\n type=\"button\"\n >\n Log in as\n </button>\n <button (click)=\"toggleCredentials(account)\" class=\"et-query-devtools-btn\" type=\"button\">\n {{ isExpanded(account) ? 'Hide' : 'Credentials' }}\n </button>\n @if (!account.declared) {\n <button (click)=\"removeAccount(account)\" class=\"et-query-devtools-btn\" type=\"button\">Remove</button>\n }\n </div>\n </div>\n @if (isExpanded(account)) {\n <div class=\"et-query-devtools-auth-account-fields\">\n @for (field of account.fields; track field.name) {\n <label class=\"et-query-devtools-field\">\n <span>{{ field.label ?? field.name }}</span>\n <input\n #fieldInput\n [value]=\"account.values[field.name] ?? ''\"\n [type]=\"field.type ?? 'text'\"\n [attr.autocomplete]=\"field.type === 'password' ? 'new-password' : 'off'\"\n (change)=\"setCredential({ account: account, field: field.name, value: fieldInput.value })\"\n class=\"et-query-devtools-input\"\n />\n </label>\n }\n <button (click)=\"clearCredentials(account)\" class=\"et-query-devtools-btn\" type=\"button\">\n Forget these\n </button>\n <p class=\"et-query-devtools-hint\">\n Kept in this browser's <code class=\"et-query-devtools-mono\">localStorage</code> under the API env in\n force, and sent to nothing but this provider's own login query. Never put them in the repository\n instead.\n </p>\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (auth.accessToken()) {\n <h4 class=\"et-query-devtools-section\">Token lifetime</h4>\n @if (lifetime.overridable) {\n <div class=\"et-query-devtools-auth-ttl\">\n <div class=\"et-query-devtools-auth-ttl-row\">\n <label class=\"et-query-devtools-field\">\n <span>Override</span>\n <input\n #ttlInput\n [value]=\"lifetime.ttlSeconds ?? ''\"\n [max]=\"TTL_LIMIT\"\n (change)=\"armTokenTtl({ entry: entry, value: ttlInput.value })\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"0\"\n step=\"30\"\n />\n <small>seconds, or empty for the lifetime the token was issued with</small>\n </label>\n <div class=\"et-query-devtools-auth-ttl-actions\">\n <button (click)=\"expireTokenNow(entry)\" class=\"et-query-devtools-btn\" type=\"button\">Expire now</button>\n @if (lifetime.ttlSeconds !== null) {\n <button (click)=\"clearTokenTtl(entry)\" class=\"et-query-devtools-btn\" type=\"button\">Clear</button>\n }\n </div>\n </div>\n <p class=\"et-query-devtools-hint\">\n Measured from the token's own <code>iat</code>, so this is a lifetime and not a remaining time - a short\n one on a token issued a while ago refreshes at once, and the token that comes back lives the full\n lifetime. It is what the whole app acts on: the proactive refresh, the expiration warning and the\n countdown above all read it. Never persisted - a reload puts this provider back on its real lifetime.\n </p>\n </div>\n } @else {\n <p class=\"et-query-devtools-hint\">\n This access token carries no <code>exp</code> claim to replace, or no <code>iat</code>/<code>nbf</code> to\n measure a new lifetime from, so it cannot be overridden.\n </p>\n }\n }\n\n @if (host.authTokenPayload(auth); as payload) {\n <h4 class=\"et-query-devtools-section\">Access token payload</h4>\n <et-query-devtools-json [value]=\"payload\" />\n }\n\n @if (auth.latestNonInternalQuery(); as latest) {\n <h4 class=\"et-query-devtools-section\">Latest auth query \u00B7 {{ latest.key }}</h4>\n <et-query-devtools-json [value]=\"latest.snapshot.response()\" />\n }\n </div>\n } @empty {\n <p class=\"et-query-devtools-empty\">No auth providers registered.</p>\n }\n</div>\n", styles: ["@layer components{.et-query-devtools-auth-real-expiry{color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-auth-ttl{display:flex;flex-direction:column;align-items:start;gap:.8rem}.et-query-devtools-auth-ttl-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:.8rem 1.6rem}.et-query-devtools-auth-ttl-row .et-query-devtools-field{color:var(--_et-qdt-fg)}.et-query-devtools-auth-ttl-row .et-query-devtools-field small{color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-auth-ttl-actions{display:flex;flex-wrap:wrap;gap:.6rem}.et-query-devtools-auth-ttl .et-query-devtools-hint{flex:0 0 auto;max-inline-size:90ch}.et-query-devtools-auth-vault{display:flex;flex-direction:column;gap:.8rem}.et-query-devtools-auth-vault-actions,.et-query-devtools-auth-account-add{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem}.et-query-devtools-auth-vault-head{display:flex;flex-wrap:wrap;align-items:center;gap:.8rem;margin-block-start:.8rem}.et-query-devtools-auth-vault-other{color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-auth-session,.et-query-devtools-auth-account{padding:.8rem;border-radius:.6rem;background:color-mix(in srgb,var(--_et-qdt-interaction) 5%,var(--_et-qdt-bg));box-shadow:inset 0 0 0 1px var(--_et-qdt-border)}.et-query-devtools-auth-session{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem .8rem}.et-query-devtools-auth-session--active{box-shadow:inset 0 0 0 1px var(--_et-qdt-accent)}.et-query-devtools-auth-session-label{inline-size:18rem}.et-query-devtools-auth-session-buttons{display:flex;flex-wrap:wrap;gap:.6rem;margin-inline-start:auto}.et-query-devtools-auth-account{display:flex;flex-direction:column;gap:.8rem}.et-query-devtools-auth-account-head{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem .8rem}.et-query-devtools-auth-account-fields{display:flex;flex-wrap:wrap;align-items:end;gap:.8rem 1.6rem}.et-query-devtools-auth-account-fields .et-query-devtools-field{color:var(--_et-qdt-fg)}.et-query-devtools-auth-account-fields .et-query-devtools-hint{flex:1 1 100%;max-inline-size:90ch}}\n"], dependencies: [{ kind: "component", type: QueryDevtoolsFeaturesComponent, selector: "et-query-devtools-features", inputs: ["features"] }, { kind: "component", type: QueryDevtoolsJsonComponent, selector: "et-query-devtools-json", inputs: ["value", "nodeKey", "depth", "search", "chunk", "path", "expandedPaths", "collapsedPaths", "toggleFn", "jsonPath", "parentKind", "overrides", "annotations"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
1567
1738
|
}
|
|
1568
1739
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: QueryDevtoolsAuthTabComponent, decorators: [{
|
|
1569
1740
|
type: Component,
|
|
1570
|
-
args: [{ selector: 'et-query-devtools-auth-tab', encapsulation: ViewEncapsulation.None, imports: [QueryDevtoolsFeaturesComponent, QueryDevtoolsJsonComponent], template: "<div class=\"et-query-devtools-scroll\">\n @for (entry of host.authEntries(); track entry.id) {\n @let auth = host.asAuth(entry);\n @let lifetime = host.authTokenLifetime(entry);\n <div [class.et-query-devtools-card--armed]=\"lifetime.ttlSeconds !== null\" class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>{{ entry.meta.name || 'auth provider' }}</strong>\n <span\n [class.et-query-devtools-chip--success]=\"auth.isAuthenticated()\"\n [class.et-query-devtools-chip--muted]=\"!auth.isAuthenticated()\"\n class=\"et-query-devtools-chip\"\n >\n {{ auth.isAuthenticated() ? 'authenticated' : 'anonymous' }}\n </span>\n @if (lifetime.ttlSeconds !== null) {\n <span\n [title]=\"\n 'This provider\\'s access token is presented as living ' +\n lifetime.ttlSeconds +\n 's from the moment it was issued, so the refresh happens on that lifetime instead of the real one.'\n \"\n class=\"et-query-devtools-chip et-query-devtools-chip--error\"\n >\n lifetime {{ lifetime.ttlSeconds }}s\n </span>\n }\n @if (host.authLeadership(auth); as leadership) {\n <span\n [class.et-query-devtools-chip--success]=\"leadership.tone === 'success'\"\n [class.et-query-devtools-chip--muted]=\"leadership.tone === 'muted'\"\n [title]=\"leadership.title\"\n class=\"et-query-devtools-chip\"\n >\n {{ leadership.label }}\n </span>\n }\n </div>\n <dl class=\"et-query-devtools-meta\">\n <dt>Base URL</dt>\n <dd class=\"et-query-devtools-mono\">{{ entry.meta.clientBaseUrl || entry.meta.clientName || '\u2014' }}</dd>\n <dt>Access token</dt>\n <dd>{{ auth.accessToken() ? 'present' : 'none' }}</dd>\n <dt>Refresh token</dt>\n <dd>{{ auth.refreshToken() ? 'present' : 'none' }}</dd>\n @if (lifetime.expiresIn; as expiry) {\n <dt>Token expires in</dt>\n <dd>\n {{ expiry }}\n @if (lifetime.realExpiresIn; as real) {\n <small class=\"et-query-devtools-auth-real-expiry\">really {{ real }}</small>\n }\n </dd>\n }\n @if (auth.executionState(); as state) {\n <dt>Execution state</dt>\n <dd>{{ state.type }} \u00B7 {{ state.state }}</dd>\n }\n @if (host.authQueryKeys(auth).length) {\n <dt>Queries</dt>\n <dd>\n <div class=\"et-query-devtools-chips\">\n @for (key of host.authQueryKeys(auth); track key) {\n <span class=\"et-query-devtools-chip\">{{ key }}</span>\n }\n </div>\n </dd>\n }\n @if (entry.meta.features?.length) {\n <dt>Features</dt>\n <dd>\n <et-query-devtools-features [features]=\"entry.meta.features ?? []\" />\n </dd>\n }\n </dl>\n\n @if (auth.accessToken()) {\n <h4 class=\"et-query-devtools-section\">Token lifetime</h4>\n @if (lifetime.overridable) {\n <div class=\"et-query-devtools-auth-ttl\">\n <div class=\"et-query-devtools-auth-ttl-row\">\n <label class=\"et-query-devtools-field\">\n <span>Override</span>\n <input\n #ttlInput\n [value]=\"lifetime.ttlSeconds ?? ''\"\n [max]=\"TTL_LIMIT\"\n (change)=\"armTokenTtl({ entry: entry, value: ttlInput.value })\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"0\"\n step=\"30\"\n />\n <small>seconds, or empty for the lifetime the token was issued with</small>\n </label>\n <div class=\"et-query-devtools-auth-ttl-actions\">\n <button (click)=\"expireTokenNow(entry)\" class=\"et-query-devtools-btn\" type=\"button\">Expire now</button>\n @if (lifetime.ttlSeconds !== null) {\n <button (click)=\"clearTokenTtl(entry)\" class=\"et-query-devtools-btn\" type=\"button\">Clear</button>\n }\n </div>\n </div>\n <p class=\"et-query-devtools-hint\">\n Measured from the token's own <code>iat</code>, so this is a lifetime and not a remaining time - a short\n one on a token issued a while ago refreshes at once, and the token that comes back lives the full\n lifetime. It is what the whole app acts on: the proactive refresh, the expiration warning and the\n countdown above all read it. Never persisted - a reload puts this provider back on its real lifetime.\n </p>\n </div>\n } @else {\n <p class=\"et-query-devtools-hint\">\n This access token carries no <code>exp</code> claim to replace, or no <code>iat</code>/<code>nbf</code> to\n measure a new lifetime from, so it cannot be overridden.\n </p>\n }\n }\n\n @if (host.authTokenPayload(auth); as payload) {\n <h4 class=\"et-query-devtools-section\">Access token payload</h4>\n <et-query-devtools-json [value]=\"payload\" />\n }\n\n @if (auth.latestNonInternalQuery(); as latest) {\n <h4 class=\"et-query-devtools-section\">Latest auth query \u00B7 {{ latest.key }}</h4>\n <et-query-devtools-json [value]=\"latest.snapshot.response()\" />\n }\n </div>\n } @empty {\n <p class=\"et-query-devtools-empty\">No auth providers registered.</p>\n }\n</div>\n", styles: ["@layer components{.et-query-devtools-auth-real-expiry{color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-auth-ttl{display:flex;flex-direction:column;align-items:start;gap:.8rem}.et-query-devtools-auth-ttl-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:.8rem 1.6rem}.et-query-devtools-auth-ttl-row .et-query-devtools-field{color:var(--_et-qdt-fg)}.et-query-devtools-auth-ttl-row .et-query-devtools-field small{color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-auth-ttl-actions{display:flex;flex-wrap:wrap;gap:.6rem}.et-query-devtools-auth-ttl .et-query-devtools-hint{flex:0 0 auto;max-inline-size:90ch}}\n"] }]
|
|
1741
|
+
args: [{ selector: 'et-query-devtools-auth-tab', encapsulation: ViewEncapsulation.None, imports: [QueryDevtoolsFeaturesComponent, QueryDevtoolsJsonComponent], template: "<div class=\"et-query-devtools-scroll\">\n @for (entry of host.authEntries(); track entry.id) {\n @let auth = host.asAuth(entry);\n @let lifetime = host.authTokenLifetime(entry);\n <div [class.et-query-devtools-card--armed]=\"lifetime.ttlSeconds !== null\" class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>{{ entry.meta.name || 'auth provider' }}</strong>\n <span\n [class.et-query-devtools-chip--success]=\"auth.isAuthenticated()\"\n [class.et-query-devtools-chip--muted]=\"!auth.isAuthenticated()\"\n class=\"et-query-devtools-chip\"\n >\n {{ auth.isAuthenticated() ? 'authenticated' : 'anonymous' }}\n </span>\n @if (lifetime.ttlSeconds !== null) {\n <span\n [title]=\"\n 'This provider\\'s access token is presented as living ' +\n lifetime.ttlSeconds +\n 's from the moment it was issued, so the refresh happens on that lifetime instead of the real one.'\n \"\n class=\"et-query-devtools-chip et-query-devtools-chip--error\"\n >\n lifetime {{ lifetime.ttlSeconds }}s\n </span>\n }\n @if (host.authLeadership(auth); as leadership) {\n <span\n [class.et-query-devtools-chip--success]=\"leadership.tone === 'success'\"\n [class.et-query-devtools-chip--muted]=\"leadership.tone === 'muted'\"\n [title]=\"leadership.title\"\n class=\"et-query-devtools-chip\"\n >\n {{ leadership.label }}\n </span>\n }\n </div>\n <dl class=\"et-query-devtools-meta\">\n <dt>Base URL</dt>\n <dd class=\"et-query-devtools-mono\">{{ entry.meta.clientBaseUrl || entry.meta.clientName || '\u2014' }}</dd>\n <dt>Access token</dt>\n <dd>{{ auth.accessToken() ? 'present' : 'none' }}</dd>\n <dt>Refresh token</dt>\n <dd>{{ auth.refreshToken() ? 'present' : 'none' }}</dd>\n @if (lifetime.expiresIn; as expiry) {\n <dt>Token expires in</dt>\n <dd>\n {{ expiry }}\n @if (lifetime.realExpiresIn; as real) {\n <small class=\"et-query-devtools-auth-real-expiry\">really {{ real }}</small>\n }\n </dd>\n }\n @if (auth.executionState(); as state) {\n <dt>Execution state</dt>\n <dd>{{ state.type }} \u00B7 {{ state.state }}</dd>\n }\n @if (host.authQueryKeys(auth).length) {\n <dt>Queries</dt>\n <dd>\n <div class=\"et-query-devtools-chips\">\n @for (key of host.authQueryKeys(auth); track key) {\n <span class=\"et-query-devtools-chip\">{{ key }}</span>\n }\n </div>\n </dd>\n }\n @if (entry.meta.features?.length) {\n <dt>Features</dt>\n <dd>\n <et-query-devtools-features [features]=\"entry.meta.features ?? []\" />\n </dd>\n }\n </dl>\n\n <h4 class=\"et-query-devtools-section\">Sessions</h4>\n @if (production()) {\n <p class=\"et-query-devtools-hint\">\n A production env is the pick. Nothing of a real user's session is kept here - no tokens, no credentials - so\n the vault and the accounts stand down until a different backend is picked.\n </p>\n } @else {\n @let sessions = sessionsFor(entry);\n @let accounts = accountsFor(entry);\n <div class=\"et-query-devtools-auth-vault\">\n <div class=\"et-query-devtools-auth-vault-actions\">\n <button\n [class.et-query-devtools-btn--active]=\"isTabLocal(entry)\"\n [attr.aria-pressed]=\"isTabLocal(entry)\"\n [title]=\"\n isTabLocal(entry)\n ? 'Hands this tab back to the session every other tab shares. Reloads the page.'\n : 'Keeps this session in this tab alone, so another tab can be somebody else. Reloads the page.'\n \"\n (click)=\"toggleTabLocal(entry)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n {{ isTabLocal(entry) ? 'Rejoin the shared session' : 'Own this tab' }}\n </button>\n <button\n [disabled]=\"!auth.isAuthenticated()\"\n (click)=\"logout(entry)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Log out\n </button>\n <button\n [class.et-query-devtools-btn--active]=\"reloadOnSwitch()\"\n [attr.aria-pressed]=\"reloadOnSwitch()\"\n (click)=\"setReloadOnSwitch(!reloadOnSwitch())\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"A switch only replaces what the query layer holds. An app that keeps the user in a service, the router or an open form is still showing the last one until it boots again.\"\n >\n reload on switch\n </button>\n </div>\n\n @if (isTabLocal(entry)) {\n <p class=\"et-query-devtools-hint\">\n This tab holds its own session. It syncs nothing to the other tabs and writes no persistence cookie, so\n every other tab stays on whoever it was.\n </p>\n }\n\n @for (session of sessions; track session.id) {\n <div\n [class.et-query-devtools-auth-session--active]=\"isActive(entry, session)\"\n class=\"et-query-devtools-auth-session\"\n >\n <input\n #labelInput\n [value]=\"session.label\"\n (change)=\"rename(session, labelInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-auth-session-label\"\n type=\"text\"\n aria-label=\"Session name\"\n />\n @if (isActive(entry, session)) {\n <span class=\"et-query-devtools-chip et-query-devtools-chip--success\">in force</span>\n }\n @if (isExpired(session)) {\n <span\n class=\"et-query-devtools-chip et-query-devtools-chip--muted\"\n title=\"The stored access token is spent. Switching to it refreshes on the stored refresh token, which works while the server has not spent that one too.\"\n >\n token expired\n </span>\n }\n <span class=\"et-query-devtools-count\"\n >{{ session.subject ?? 'no subject' }} \u00B7 {{ sessionAge(session) }}</span\n >\n <div class=\"et-query-devtools-auth-session-buttons\">\n <button\n [disabled]=\"isActive(entry, session)\"\n (click)=\"switchTo(session)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n Switch\n </button>\n <button (click)=\"forget(session)\" class=\"et-query-devtools-btn\" type=\"button\">Forget</button>\n </div>\n </div>\n } @empty {\n <p class=\"et-query-devtools-hint\">\n No session stored for this backend yet. Log in as you normally would and this one appears here, ready to\n be switched back to once you are somebody else.\n </p>\n }\n\n @if (otherScopeCount(entry); as other) {\n <small class=\"et-query-devtools-auth-vault-other\">\n {{ other }} more stored under a different API env. Pick that env again to switch to them.\n </small>\n }\n\n <div class=\"et-query-devtools-auth-vault-head\">\n <strong>Accounts</strong>\n <span class=\"et-query-devtools-count\">credentials are typed in here and stay in this browser</span>\n <button (click)=\"toggleAdding(entry)\" class=\"et-query-devtools-btn\" type=\"button\">\n {{ isAdding(entry) ? 'Cancel' : 'Add account' }}\n </button>\n </div>\n\n @if (isAdding(entry)) {\n <div class=\"et-query-devtools-auth-account-add\">\n <input\n #newLabel\n class=\"et-query-devtools-input\"\n type=\"text\"\n placeholder=\"Admin\"\n aria-label=\"Account name\"\n />\n <select #newQuery class=\"et-query-devtools-select\" aria-label=\"Login query\">\n @for (key of loginQueries(entry); track key) {\n <option [value]=\"key\">{{ key }}</option>\n }\n </select>\n <button\n (click)=\"addAccount({ entry: entry, label: newLabel.value, loginQuery: newQuery.value })\"\n class=\"et-query-devtools-btn et-query-devtools-btn--primary\"\n type=\"button\"\n >\n Add\n </button>\n </div>\n }\n\n @for (account of accounts; track account.id) {\n <div class=\"et-query-devtools-auth-account\">\n <div class=\"et-query-devtools-auth-account-head\">\n <strong>{{ account.label }}</strong>\n @if (account.note) {\n <span class=\"et-query-devtools-count\">{{ account.note }}</span>\n }\n <span class=\"et-query-devtools-chip et-query-devtools-chip--muted\">{{ account.loginQuery }}</span>\n @if (!account.ready) {\n <span class=\"et-query-devtools-chip et-query-devtools-chip--error\">needs credentials</span>\n }\n <div class=\"et-query-devtools-auth-session-buttons\">\n <button\n [disabled]=\"!account.ready\"\n (click)=\"login(account)\"\n class=\"et-query-devtools-btn et-query-devtools-btn--primary\"\n type=\"button\"\n >\n Log in as\n </button>\n <button (click)=\"toggleCredentials(account)\" class=\"et-query-devtools-btn\" type=\"button\">\n {{ isExpanded(account) ? 'Hide' : 'Credentials' }}\n </button>\n @if (!account.declared) {\n <button (click)=\"removeAccount(account)\" class=\"et-query-devtools-btn\" type=\"button\">Remove</button>\n }\n </div>\n </div>\n @if (isExpanded(account)) {\n <div class=\"et-query-devtools-auth-account-fields\">\n @for (field of account.fields; track field.name) {\n <label class=\"et-query-devtools-field\">\n <span>{{ field.label ?? field.name }}</span>\n <input\n #fieldInput\n [value]=\"account.values[field.name] ?? ''\"\n [type]=\"field.type ?? 'text'\"\n [attr.autocomplete]=\"field.type === 'password' ? 'new-password' : 'off'\"\n (change)=\"setCredential({ account: account, field: field.name, value: fieldInput.value })\"\n class=\"et-query-devtools-input\"\n />\n </label>\n }\n <button (click)=\"clearCredentials(account)\" class=\"et-query-devtools-btn\" type=\"button\">\n Forget these\n </button>\n <p class=\"et-query-devtools-hint\">\n Kept in this browser's <code class=\"et-query-devtools-mono\">localStorage</code> under the API env in\n force, and sent to nothing but this provider's own login query. Never put them in the repository\n instead.\n </p>\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (auth.accessToken()) {\n <h4 class=\"et-query-devtools-section\">Token lifetime</h4>\n @if (lifetime.overridable) {\n <div class=\"et-query-devtools-auth-ttl\">\n <div class=\"et-query-devtools-auth-ttl-row\">\n <label class=\"et-query-devtools-field\">\n <span>Override</span>\n <input\n #ttlInput\n [value]=\"lifetime.ttlSeconds ?? ''\"\n [max]=\"TTL_LIMIT\"\n (change)=\"armTokenTtl({ entry: entry, value: ttlInput.value })\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"0\"\n step=\"30\"\n />\n <small>seconds, or empty for the lifetime the token was issued with</small>\n </label>\n <div class=\"et-query-devtools-auth-ttl-actions\">\n <button (click)=\"expireTokenNow(entry)\" class=\"et-query-devtools-btn\" type=\"button\">Expire now</button>\n @if (lifetime.ttlSeconds !== null) {\n <button (click)=\"clearTokenTtl(entry)\" class=\"et-query-devtools-btn\" type=\"button\">Clear</button>\n }\n </div>\n </div>\n <p class=\"et-query-devtools-hint\">\n Measured from the token's own <code>iat</code>, so this is a lifetime and not a remaining time - a short\n one on a token issued a while ago refreshes at once, and the token that comes back lives the full\n lifetime. It is what the whole app acts on: the proactive refresh, the expiration warning and the\n countdown above all read it. Never persisted - a reload puts this provider back on its real lifetime.\n </p>\n </div>\n } @else {\n <p class=\"et-query-devtools-hint\">\n This access token carries no <code>exp</code> claim to replace, or no <code>iat</code>/<code>nbf</code> to\n measure a new lifetime from, so it cannot be overridden.\n </p>\n }\n }\n\n @if (host.authTokenPayload(auth); as payload) {\n <h4 class=\"et-query-devtools-section\">Access token payload</h4>\n <et-query-devtools-json [value]=\"payload\" />\n }\n\n @if (auth.latestNonInternalQuery(); as latest) {\n <h4 class=\"et-query-devtools-section\">Latest auth query \u00B7 {{ latest.key }}</h4>\n <et-query-devtools-json [value]=\"latest.snapshot.response()\" />\n }\n </div>\n } @empty {\n <p class=\"et-query-devtools-empty\">No auth providers registered.</p>\n }\n</div>\n", styles: ["@layer components{.et-query-devtools-auth-real-expiry{color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-auth-ttl{display:flex;flex-direction:column;align-items:start;gap:.8rem}.et-query-devtools-auth-ttl-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:.8rem 1.6rem}.et-query-devtools-auth-ttl-row .et-query-devtools-field{color:var(--_et-qdt-fg)}.et-query-devtools-auth-ttl-row .et-query-devtools-field small{color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-auth-ttl-actions{display:flex;flex-wrap:wrap;gap:.6rem}.et-query-devtools-auth-ttl .et-query-devtools-hint{flex:0 0 auto;max-inline-size:90ch}.et-query-devtools-auth-vault{display:flex;flex-direction:column;gap:.8rem}.et-query-devtools-auth-vault-actions,.et-query-devtools-auth-account-add{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem}.et-query-devtools-auth-vault-head{display:flex;flex-wrap:wrap;align-items:center;gap:.8rem;margin-block-start:.8rem}.et-query-devtools-auth-vault-other{color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-auth-session,.et-query-devtools-auth-account{padding:.8rem;border-radius:.6rem;background:color-mix(in srgb,var(--_et-qdt-interaction) 5%,var(--_et-qdt-bg));box-shadow:inset 0 0 0 1px var(--_et-qdt-border)}.et-query-devtools-auth-session{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem .8rem}.et-query-devtools-auth-session--active{box-shadow:inset 0 0 0 1px var(--_et-qdt-accent)}.et-query-devtools-auth-session-label{inline-size:18rem}.et-query-devtools-auth-session-buttons{display:flex;flex-wrap:wrap;gap:.6rem;margin-inline-start:auto}.et-query-devtools-auth-account{display:flex;flex-direction:column;gap:.8rem}.et-query-devtools-auth-account-head{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem .8rem}.et-query-devtools-auth-account-fields{display:flex;flex-wrap:wrap;align-items:end;gap:.8rem 1.6rem}.et-query-devtools-auth-account-fields .et-query-devtools-field{color:var(--_et-qdt-fg)}.et-query-devtools-auth-account-fields .et-query-devtools-hint{flex:1 1 100%;max-inline-size:90ch}}\n"] }]
|
|
1571
1742
|
}] });
|
|
1572
1743
|
|
|
1573
1744
|
/** How the panel spells a teardown cause out - the same wording in the Events tab and the Cache tab. */
|
|
@@ -3245,7 +3416,7 @@ const summarizeLocks = (options) => {
|
|
|
3245
3416
|
|
|
3246
3417
|
// Generated from package.json by tools/scripts/generate-version.js - do not edit.
|
|
3247
3418
|
/** The version of `@ethlete/query-devtools` this build was cut from. */
|
|
3248
|
-
const QUERY_DEVTOOLS_VERSION = '1.0.0-next.
|
|
3419
|
+
const QUERY_DEVTOOLS_VERSION = '1.0.0-next.9';
|
|
3249
3420
|
|
|
3250
3421
|
/* eslint-disable @typescript-eslint/naming-convention -- the `__export_*` keys are Insomnia's file format */
|
|
3251
3422
|
const WORKSPACE_ID = 'wrk_ethlete_query_devtools';
|