@ethlete/query-devtools 1.0.0-next.11 → 1.0.0-next.13
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,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.0-next.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- The pop-out window is styled without inline `style` attributes and keeps the nonce of every stylesheet it copies, so it works under a strict `style-src`.
|
|
8
|
+
|
|
9
|
+
## 1.0.0-next.12
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Outside a development build the devtools session vault now defaults to `none`, so a plain login no longer leaves tokens in `sessionStorage`, and a vault left in either store is removed on load.
|
|
14
|
+
- Client `headers` and per-request `args.headers` accept a plain record as well as `HttpHeaders`, for secure queries too, so a client needs no `@angular/*` import to set a header.
|
|
15
|
+
|
|
3
16
|
## 1.0.0-next.11
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
|
@@ -2,7 +2,7 @@ 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 { takeUntilDestroyed, toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
4
4
|
import { copyToClipboard, injectStyleManager, injectErrorTheme, ProvideColorDirective, clamp, injectRenderer, injectFileDownload, injectViewportSize, injectIsDocumentVisible, injectBreakpointObserver, signalElementDimensions, randomId, reserveOverlayViewportSpace, createObjectUrlHandle, DragHandleDirective, ResizeHandlesComponent } from '@ethlete/core';
|
|
5
|
-
import { queryDevtoolsAbout, hasQueryDevtoolsOverridesAtPath, detectPaginationShape, isDateShapedLeaf, generateQueryDevtoolsStringPreset, generateQueryDevtoolsNumberPreset, collectLeafPaths, armAllQueryDevtoolsMocks, clearQueryDevtoolsArmedMocks, clearQueryDevtoolsFaults, queryDevtoolsResponseHistory, queryDevtoolsMocks, queryDevtoolsAuthSessions, queryDevtoolsArmedMocks, clearQueryDevtoolsAuthSessions, queryDevtoolsApiEnvs, queryDevtoolsApiEnvValues, setQueryDevtoolsApiEnv, queryDevtoolsSettings, queryDevtoolsAllowsLocalAuthSessions, setQueryDevtoolsOverridesScope, setQueryDevtoolsArmedMocksScope, setQueryDevtoolsFaultsScope, setQueryDevtoolsSettings, QUERY_DEVTOOLS_TOKEN_TTL_LIMIT, queryDevtoolsApiEnvIsProduction, queryDevtoolsAuthSessionsFor, queryDevtoolsAuthAccountsFor, queryDevtoolsAuthOtherScopeCount, queryDevtoolsAuthActive, queryDevtoolsAuthTabLocal, switchQueryDevtoolsAuthSession, renameQueryDevtoolsAuthSession, forgetQueryDevtoolsAuthSession, forgetQueryDevtoolsAuthSessionsFor, logoutQueryDevtoolsAuthSession, setQueryDevtoolsAuthTabLocal, loginQueryDevtoolsAuthAccount, setQueryDevtoolsAuthCredentials, clearQueryDevtoolsAuthCredentials, removeQueryDevtoolsAuthAccount, queryDevtoolsAuthFieldsFor, 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, isQueryDevtoolsRepositoryLive, queryDevtoolsFaults, EMPTY_QUERY_DEVTOOLS_FAULT, isQueryDevtoolsFaultArmed, queryDevtoolsFaultsRestored, queryDevtoolsArmedMocksRestored, restoredQueryDevtoolsOverrides, queryDevtoolsRestoredOverridesScope, clearRestoredQueryDevtoolsOverrides, setQueryDevtoolsUiMounted, clearQueryDevtoolsStore, writeQueryDevtoolsStore, registerEthleteVersion, queryDevtoolsOverridePersistence, setQueryDevtoolsOverridePersistence, clearQueryDevtoolsOverrideStore, clearQueryDevtoolsMockStore, createQueryErrorResponse, applyQueryDevtoolsTokenTtl, canOverrideQueryDevtoolsTokenTtl, sumQueryDevtoolsStats } from '@ethlete/query';
|
|
5
|
+
import { queryDevtoolsAbout, hasQueryDevtoolsOverridesAtPath, detectPaginationShape, isDateShapedLeaf, generateQueryDevtoolsStringPreset, generateQueryDevtoolsNumberPreset, collectLeafPaths, armAllQueryDevtoolsMocks, clearQueryDevtoolsArmedMocks, clearQueryDevtoolsFaults, queryDevtoolsResponseHistory, queryDevtoolsMocks, queryDevtoolsAuthSessions, queryDevtoolsArmedMocks, clearQueryDevtoolsAuthSessions, queryDevtoolsApiEnvs, queryDevtoolsApiEnvValues, setQueryDevtoolsApiEnv, queryDevtoolsSettings, queryDevtoolsAllowsLocalAuthSessions, setQueryDevtoolsOverridesScope, setQueryDevtoolsArmedMocksScope, setQueryDevtoolsFaultsScope, setQueryDevtoolsSettings, QUERY_DEVTOOLS_TOKEN_TTL_LIMIT, queryDevtoolsApiEnvIsProduction, queryDevtoolsAuthSessionsFor, queryDevtoolsAuthAccountsFor, queryDevtoolsAuthOtherScopeCount, queryDevtoolsAuthActive, queryDevtoolsAuthTabLocal, switchQueryDevtoolsAuthSession, renameQueryDevtoolsAuthSession, forgetQueryDevtoolsAuthSession, forgetQueryDevtoolsAuthSessionsFor, logoutQueryDevtoolsAuthSession, setQueryDevtoolsAuthTabLocal, loginQueryDevtoolsAuthAccount, setQueryDevtoolsAuthCredentials, clearQueryDevtoolsAuthCredentials, removeQueryDevtoolsAuthAccount, queryDevtoolsAuthFieldsFor, 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, isQueryDevtoolsRepositoryLive, queryDevtoolsFaults, EMPTY_QUERY_DEVTOOLS_FAULT, isQueryDevtoolsFaultArmed, queryDevtoolsFaultsRestored, queryDevtoolsArmedMocksRestored, restoredQueryDevtoolsOverrides, queryDevtoolsRestoredOverridesScope, clearRestoredQueryDevtoolsOverrides, setQueryDevtoolsUiMounted, clearQueryDevtoolsStore, writeQueryDevtoolsStore, registerEthleteVersion, queryDevtoolsOverridePersistence, setQueryDevtoolsOverridePersistence, clearQueryDevtoolsOverrideStore, clearQueryDevtoolsMockStore, createQueryErrorResponse, applyQueryDevtoolsTokenTtl, canOverrideQueryDevtoolsTokenTtl, resolveQueryHeaders, sumQueryDevtoolsStats } from '@ethlete/query';
|
|
6
6
|
import { Subject, switchMap, timer, tap, EMPTY, interval, scan, animationFrames, NEVER, takeUntil, finalize as finalize$1, startWith, merge, map, fromEvent, filter, take } from 'rxjs';
|
|
7
7
|
import { MenuDirective, MenuTriggerDirective, MenuSurfaceDirective, MenuComponent, MenuItemComponent, MenuSearchDirective, MenuSeparatorComponent, MenuItemShortcutComponent, SelectComponent, SelectSearchDirective, COMPONENTS_VERSION, MenuCheckboxItemComponent, MenuRadioGroupComponent, MenuRadioItemComponent } from '@ethlete/components';
|
|
8
8
|
import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
|
|
@@ -1644,7 +1644,7 @@ class QueryDevtoolsSettingsComponent {
|
|
|
1644
1644
|
unavailableReason(row, scope) {
|
|
1645
1645
|
if (row.key !== 'authSessions' || scope !== 'local' || queryDevtoolsAllowsLocalAuthSessions())
|
|
1646
1646
|
return null;
|
|
1647
|
-
return 'Unavailable outside a development build: live access and refresh tokens, and the credentials you typed in, must not outlive this tab on a deployed origin. Session keeps
|
|
1647
|
+
return 'Unavailable outside a development build: live access and refresh tokens, and the credentials you typed in, must not outlive this tab on a deployed origin. The vault keeps nothing here unless you pick Session, which keeps it for as long as the tab.';
|
|
1648
1648
|
}
|
|
1649
1649
|
setScope(key, scope) {
|
|
1650
1650
|
// Everything armed goes through its own module: changing the scope moves an existing store and
|
|
@@ -3554,7 +3554,7 @@ class QueryDevtoolsMocksTabComponent {
|
|
|
3554
3554
|
});
|
|
3555
3555
|
}
|
|
3556
3556
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: QueryDevtoolsMocksTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3557
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: QueryDevtoolsMocksTabComponent, isStandalone: true, selector: "et-query-devtools-mocks-tab", ngImport: i0, template: "<div class=\"et-query-devtools-scroll\">\n <div class=\"et-query-devtools-toolbar et-query-devtools-mocks-toolbar\">\n <p class=\"et-query-devtools-hint\">\n A mock replaces the request, so it answers a route that has never run - or does not exist yet. It bypasses the\n interceptor chain by construction, so a mocked secure route never exercises the token flow. The library is kept;\n whether a mock is <strong>armed</strong> is not, so a reload always stops serving them. GraphQL queries are not\n offered: they all POST one route, so matching them needs the document rather than the path.\n </p>\n <div class=\"et-query-devtools-settings-controls\">\n @if (rows().length && armedCount() < rows().length) {\n <button\n (click)=\"ARM_ALL()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"Serve every mock in the library - the whole screen off the network at once\"\n >\n Arm all ({{ rows().length }})\n </button>\n }\n @if (armedCount()) {\n <button (click)=\"DISARM_ALL()\" class=\"et-query-devtools-btn\" type=\"button\">\n Disarm all ({{ armedCount() }})\n </button>\n }\n <button (click)=\"openDraft()\" class=\"et-query-devtools-btn et-query-devtools-btn--primary\" type=\"button\">\n <span aria-hidden=\"true\">\uFF0B</span>\n New mock\n </button>\n </div>\n </div>\n\n @if (draft(); as form) {\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>New mock</strong>\n <span class=\"et-query-devtools-count\">for any route, whether a query has ever called it or not</span>\n </div>\n\n <div class=\"et-query-devtools-mock-fields\">\n <label class=\"et-query-devtools-field\">\n <span>Client</span>\n <select #clientSelect (change)=\"pickClient(clientSelect.value)\" class=\"et-query-devtools-select\">\n @for (name of host.clientNames(); track name) {\n <option [value]=\"name\" [selected]=\"name === form.clientName\">{{ name }}</option>\n }\n </select>\n <small>a mock answers one client, matched by name</small>\n </label>\n\n <label class=\"et-query-devtools-field\">\n <span>Method</span>\n <select #methodSelect (change)=\"patchDraft({ method: methodSelect.value })\" class=\"et-query-devtools-select\">\n @for (method of METHODS; track method) {\n <option [value]=\"method\" [selected]=\"method === form.method\">{{ method }}</option>\n }\n </select>\n <small>matched exactly</small>\n </label>\n\n <label class=\"et-query-devtools-field et-query-devtools-field--wide\">\n <span>Path</span>\n <input\n #patternInput\n [value]=\"form.pattern\"\n (input)=\"patchDraft({ pattern: patternInput.value })\"\n class=\"et-query-devtools-input\"\n type=\"text\"\n placeholder=\"/posts/:id/comments\"\n />\n <small><code>:name</code> matches any one segment, so the route is mocked rather than one URL</small>\n </label>\n\n <label class=\"et-query-devtools-field et-query-devtools-field--wide\">\n <span>Query</span>\n <input\n #queryInput\n [value]=\"form.query\"\n (input)=\"patchDraft({ query: queryInput.value })\"\n class=\"et-query-devtools-input\"\n type=\"text\"\n placeholder=\"page=2&limit=10\"\n />\n <small>\n parameters the request must carry; anything else it asks for is ignored. Empty answers whatever the query\n string is - and a mock naming parameters wins over one that does not\n </small>\n </label>\n\n <label class=\"et-query-devtools-field\">\n <span>Status</span>\n <input\n #statusDraftInput\n [value]=\"form.status\"\n (input)=\"patchDraft({ status: statusDraftInput.value })\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"100\"\n max=\"599\"\n step=\"1\"\n />\n <small>400 and above arrive as a real error</small>\n </label>\n\n <label class=\"et-query-devtools-field\">\n <span>Latency</span>\n <input\n #latencyDraftInput\n [value]=\"form.latencyMs\"\n (input)=\"patchDraft({ latencyMs: latencyDraftInput.value })\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"0\"\n max=\"60000\"\n step=\"100\"\n />\n <small>ms before it settles</small>\n </label>\n </div>\n\n @if (hasSchema()) {\n <div class=\"et-query-devtools-seed\">\n <span class=\"et-query-devtools-section\">Seed</span>\n @if (isSchemaReady()) {\n <div class=\"et-query-devtools-seed-pick\">\n <et-select\n [options]=\"routeOptions()\"\n (pickOption)=\"pickRoute($event)\"\n class=\"et-query-devtools-combobox\"\n mirrorPanelWidth=\"false\"\n pickOnly\n >\n <input etSelectSearch placeholder=\"search the routes it declares\u2026\" />\n </et-select>\n <button\n (click)=\"seedFromDraftRoute()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"Generate a body from what the description says this path returns\"\n >\n From this path\n </button>\n </div>\n <div class=\"et-query-devtools-seed-pick\">\n <et-select\n [value]=\"pickedSchema()\"\n [options]=\"schemaNameOptions()\"\n (valueChange)=\"pickSchema($event)\"\n class=\"et-query-devtools-combobox\"\n mirrorPanelWidth=\"false\"\n >\n <input etSelectSearch placeholder=\"search its named types\u2026\" />\n </et-select>\n <button\n [disabled]=\"!pickedSchema()\"\n (click)=\"seedFromSchema()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n From this type\n </button>\n </div>\n <select\n #stylePick\n (change)=\"pickSeedStyle(stylePick.value)\"\n class=\"et-query-devtools-select\"\n title=\"How lifelike the generated values are\"\n >\n @for (style of SEED_STYLES; track style.value) {\n <option [value]=\"style.value\" [selected]=\"style.value === seedStyle()\">{{ style.label }}</option>\n }\n </select>\n <small class=\"et-query-devtools-hint et-query-devtools-seed-hint\">{{ seedStyleHint() }}</small>\n } @else if (schemaError(); as error) {\n <span class=\"et-query-devtools-settings-warn\">The API description could not be loaded: {{ error }}</span>\n } @else {\n <span class=\"et-query-devtools-count\">Loading the API description\u2026</span>\n }\n </div>\n }\n\n <label class=\"et-query-devtools-mock-body\">\n <span class=\"et-query-devtools-section\">Body</span>\n <textarea\n #bodyInput\n [value]=\"form.body\"\n (input)=\"patchDraft({ body: bodyInput.value })\"\n class=\"et-query-devtools-input et-query-devtools-mock-textarea\"\n rows=\"8\"\n spellcheck=\"false\"\n ></textarea>\n </label>\n\n @if (draftSeed(); as seed) {\n <p class=\"et-query-devtools-hint\">\n Generated from the API description{{ seed.schemaName ? ' as ' + seed.schemaName : '' }} - a starting point,\n not the contract. Saving opens the designer on it.\n </p>\n @if (seed.notes.length) {\n <ul class=\"et-query-devtools-designer-notes\">\n @for (note of seed.notes; track note) {\n <li>{{ note }}</li>\n }\n </ul>\n }\n }\n\n @if (draftError(); as error) {\n <p class=\"et-query-devtools-settings-warn\">{{ error }}</p>\n }\n\n <div class=\"et-query-devtools-mock-head\">\n <button (click)=\"saveDraft()\" class=\"et-query-devtools-btn et-query-devtools-btn--primary\" type=\"button\">\n Save to the library\n </button>\n <button (click)=\"closeDraft()\" class=\"et-query-devtools-btn\" type=\"button\">Cancel</button>\n </div>\n </div>\n }\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Designed</strong>\n <span class=\"et-query-devtools-count\">{{ rows().length }} in the library</span>\n @if (rows().length) {\n <div class=\"et-query-devtools-spec-export\">\n <select #formatPick (change)=\"pickSpecFormat(formatPick.value)\" class=\"et-query-devtools-select\">\n @for (format of SPEC_FORMATS; track format.value) {\n <option [value]=\"format.value\" [selected]=\"format.value === specFormat()\">{{ format.label }}</option>\n }\n </select>\n <button\n (click)=\"exportLibrary()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"Download every designed route as one OpenAPI 3.1 document - the response schemas inferred from the designed bodies, each body as an example\"\n >\n <span aria-hidden=\"true\">\u21E9</span>\n Export OpenAPI\n </button>\n </div>\n }\n </div>\n\n @for (row of rows(); track row.mock.id) {\n <div [class.et-query-devtools-mock-row--armed]=\"row.armed\" class=\"et-query-devtools-mock-row\">\n <div class=\"et-query-devtools-mock-head\">\n <button\n [class.et-query-devtools-btn--tampered]=\"row.armed\"\n [attr.aria-pressed]=\"row.armed\"\n (click)=\"toggleArmed(row)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"{{ row.armed ? 'Stop serving this response' : 'Serve this response instead of the request' }}\"\n >\n {{ row.armed ? 'Armed' : 'Arm' }}\n </button>\n <span class=\"et-query-devtools-method\">{{ row.mock.method }}</span>\n <span class=\"et-query-devtools-route et-query-devtools-mono\">{{ row.mock.pattern }}</span>\n @if (row.mock.query) {\n <span class=\"et-query-devtools-url\">?{{ row.mock.query }}</span>\n }\n <span class=\"et-query-devtools-url\">{{ row.mock.clientName }}</span>\n @if (row.mock.capturedAt) {\n <span class=\"et-query-devtools-chip\">captured</span>\n }\n @if (row.mock.schemaName; as schemaName) {\n <span class=\"et-query-devtools-chip\" title=\"Seeded from the API description\">{{ schemaName }}</span>\n }\n @if (row.isSecure) {\n <span\n class=\"et-query-devtools-chip et-query-devtools-chip--error\"\n title=\"A mock sends nothing, so no token is attached and the auth flow is never exercised\"\n >\n no auth\n </span>\n }\n <span class=\"et-query-devtools-count\">{{ host.formatBytes(row.bytes) }}</span>\n <button (click)=\"editBody(row)\" class=\"et-query-devtools-btn\" type=\"button\">Body</button>\n <button\n (click)=\"copyDefinition(row)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"Copy this route as a @ethlete/query definition - the response type inferred from the body, the args contract and the creator call\"\n >\n <span aria-hidden=\"true\">\u29C9</span>\n {{ copiedId() === row.mock.id ? 'Copied' : 'TS' }}\n </button>\n <button\n (click)=\"copyPathItem(row)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"Copy this route as an OpenAPI paths entry, ready to paste under an existing description\"\n >\n <span aria-hidden=\"true\">\u29C9</span>\n {{ copiedSpecId() === row.mock.id ? 'Copied' : 'OAS' }}\n </button>\n <button (click)=\"remove(row)\" class=\"et-query-devtools-btn et-query-devtools-btn--danger\" type=\"button\">\n Delete\n </button>\n </div>\n\n <div class=\"et-query-devtools-mock-fields\">\n <label class=\"et-query-devtools-field\">\n <span>Status</span>\n <input\n #statusInput\n [value]=\"row.mock.status\"\n (change)=\"setStatus(row, statusInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"100\"\n max=\"599\"\n step=\"1\"\n />\n <small>400 and above arrive as a real error, body and all</small>\n </label>\n <label class=\"et-query-devtools-field\">\n <span>Latency</span>\n <input\n #latencyInput\n [value]=\"row.mock.latencyMs\"\n (change)=\"setLatency(row, latencyInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"0\"\n max=\"60000\"\n step=\"100\"\n />\n <small>ms before it settles, so the route still has a loading state</small>\n </label>\n </div>\n\n @if (editingId() === row.mock.id) {\n <et-query-devtools-mock-designer\n [body]=\"row.mock.body\"\n [annotations]=\"editingAnnotations()\"\n (save)=\"saveBody(row, $event)\"\n (dismiss)=\"cancelBody()\"\n />\n }\n </div>\n } @empty {\n <p class=\"et-query-devtools-empty\">\n Nothing designed yet. <strong>New mock</strong> writes one from scratch; capturing below seeds one from\n something that actually happened.\n </p>\n }\n\n @if (specNotes().length) {\n <ul class=\"et-query-devtools-designer-notes\">\n @for (note of specNotes(); track note) {\n <li>{{ note }}</li>\n }\n </ul>\n }\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Capture</strong>\n <span class=\"et-query-devtools-count\">live queries holding a response</span>\n </div>\n\n @for (row of captureRows(); track row.entry.id) {\n <div class=\"et-query-devtools-mock-head\">\n <span class=\"et-query-devtools-method\">{{ row.method }}</span>\n <button\n (click)=\"host.selectQuery(row.entry.id)\"\n class=\"et-query-devtools-route et-query-devtools-mono et-query-devtools-row-link\"\n type=\"button\"\n title=\"Open this query\"\n >\n {{ row.pattern }}\n </button>\n <span class=\"et-query-devtools-url\">{{ row.clientName }}</span>\n @if (row.shared > 1) {\n <span class=\"et-query-devtools-count\" title=\"A mock answers the route, so it answers all of them\">\n {{ row.shared }} queries\n </span>\n }\n <span class=\"et-query-devtools-count\">{{ host.formatBytes(row.bytes) }}</span>\n <button (click)=\"capture(row)\" class=\"et-query-devtools-btn\" type=\"button\">\n {{ row.exists ? 'Re-capture' : 'Capture' }}\n </button>\n </div>\n } @empty {\n <p class=\"et-query-devtools-empty\">No live query has a response yet.</p>\n }\n </div>\n</div>\n", styles: ["@layer components{.et-query-devtools-mocks-toolbar{align-items:flex-start}.et-query-devtools-mock-row{padding-block:.6rem;border-block-start:1px solid var(--_et-qdt-border)}.et-query-devtools-card>.et-query-devtools-mock-row:first-of-type{border-block-start:0;padding-block-start:0}.et-query-devtools-mock-row--armed{background:color-mix(in srgb,var(--_et-qdt-error) 6%,transparent)}.et-query-devtools-mock-head{display:flex;align-items:center;flex-wrap:wrap;gap:.6rem;min-block-size:var(--_et-qdt-row-h)}.et-query-devtools-mock-fields,.et-query-devtools-seed,.et-query-devtools-mock-body{max-inline-size:96rem}.et-query-devtools-mock-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(38rem,1fr));align-items:start;gap:.4rem 1.6rem;padding-block-start:.4rem}.et-query-devtools-mock-fields .et-query-devtools-field{display:grid;grid-template-columns:7rem minmax(0,1fr);align-items:baseline;row-gap:.2rem;color:var(--_et-qdt-fg)}.et-query-devtools-mock-fields .et-query-devtools-select{justify-self:start;max-inline-size:100%}.et-query-devtools-mock-fields .et-query-devtools-field small{grid-column:2;color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-mock-fields .et-query-devtools-field--wide{grid-column:1 / -1;grid-template-columns:7rem minmax(0,1fr)}.et-query-devtools-spec-export{display:flex;align-items:center;gap:.6rem;margin-inline-start:auto}.et-query-devtools-seed{display:flex;align-items:center;flex-wrap:wrap;gap:.4rem 2.4rem;padding-block-start:.4rem;min-block-size:var(--_et-qdt-row-h)}.et-query-devtools-seed-pick{display:flex;align-items:center;gap:.2rem}.et-query-devtools-seed .et-query-devtools-select{max-inline-size:32rem}.et-query-devtools-combobox{flex:0 1 auto;inline-size:32rem;min-block-size:var(--_et-qdt-control-h);box-sizing:border-box;background:color-mix(in srgb,var(--_et-qdt-interaction) 5%,var(--_et-qdt-bg));color:var(--_et-qdt-fg);border:1px solid transparent;border-radius:var(--_et-qdt-radius);padding:.4rem .6rem;font-size:1.15rem}.et-query-devtools-combobox input{background:none;border:0;padding:0;color:inherit;font:inherit}.et-query-devtools-seed-hint{flex-basis:100%;margin:0}.et-query-devtools-mock-body{display:block;padding-block-start:.4rem}.et-query-devtools-mock-textarea{display:block;inline-size:100%;resize:vertical;font-family:inherit;font-size:1.15rem;line-height:1.5;tab-size:2}}\n"], dependencies: [{ kind: "component", type: QueryDevtoolsMockDesignerComponent, selector: "et-query-devtools-mock-designer", inputs: ["body", "annotations", "notes"], outputs: ["save", "dismiss"] }, { kind: "component", type: SelectComponent, selector: "et-select", inputs: ["loadMoreLabel", "addNewLabel", "createLabel", "clearable", "clearLabel"] }, { kind: "directive", type: SelectSearchDirective, selector: "input[etSelectSearch]", inputs: ["query"], outputs: ["queryChange"], exportAs: ["etSelectSearch"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
3557
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: QueryDevtoolsMocksTabComponent, isStandalone: true, selector: "et-query-devtools-mocks-tab", ngImport: i0, template: "<div class=\"et-query-devtools-scroll\">\n <div class=\"et-query-devtools-toolbar et-query-devtools-mocks-toolbar\">\n <p class=\"et-query-devtools-hint\">\n A mock replaces the request, so it answers a route that has never run - or does not exist yet. It bypasses the\n interceptor chain by construction, so a mocked secure route never exercises the token flow. The library is kept;\n whether a mock is <strong>armed</strong> is not, so a reload always stops serving them. GraphQL queries are not\n offered: they all POST one route, so matching them needs the document rather than the path.\n </p>\n <div class=\"et-query-devtools-settings-controls\">\n @if (rows().length && armedCount() < rows().length) {\n <button\n (click)=\"ARM_ALL()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"Serve every mock in the library - the whole screen off the network at once\"\n >\n Arm all ({{ rows().length }})\n </button>\n }\n @if (armedCount()) {\n <button (click)=\"DISARM_ALL()\" class=\"et-query-devtools-btn\" type=\"button\">\n Disarm all ({{ armedCount() }})\n </button>\n }\n <button (click)=\"openDraft()\" class=\"et-query-devtools-btn et-query-devtools-btn--primary\" type=\"button\">\n <span aria-hidden=\"true\">\uFF0B</span>\n New mock\n </button>\n </div>\n </div>\n\n @if (draft(); as form) {\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>New mock</strong>\n <span class=\"et-query-devtools-count\">for any route, whether a query has ever called it or not</span>\n </div>\n\n <div class=\"et-query-devtools-mock-fields\">\n <label class=\"et-query-devtools-field\">\n <span>Client</span>\n <select #clientSelect (change)=\"pickClient(clientSelect.value)\" class=\"et-query-devtools-select\">\n @for (name of host.clientNames(); track name) {\n <option [value]=\"name\" [selected]=\"name === form.clientName\">{{ name }}</option>\n }\n </select>\n <small>a mock answers one client, matched by name</small>\n </label>\n\n <label class=\"et-query-devtools-field\">\n <span>Method</span>\n <select #methodSelect (change)=\"patchDraft({ method: methodSelect.value })\" class=\"et-query-devtools-select\">\n @for (method of METHODS; track method) {\n <option [value]=\"method\" [selected]=\"method === form.method\">{{ method }}</option>\n }\n </select>\n <small>matched exactly</small>\n </label>\n\n <label class=\"et-query-devtools-field et-query-devtools-field--wide\">\n <span>Path</span>\n <input\n #patternInput\n [value]=\"form.pattern\"\n (input)=\"patchDraft({ pattern: patternInput.value })\"\n class=\"et-query-devtools-input\"\n type=\"text\"\n placeholder=\"/posts/:id/comments\"\n />\n <small><code>:name</code> matches any one segment, so the route is mocked rather than one URL</small>\n </label>\n\n <label class=\"et-query-devtools-field et-query-devtools-field--wide\">\n <span>Query</span>\n <input\n #queryInput\n [value]=\"form.query\"\n (input)=\"patchDraft({ query: queryInput.value })\"\n class=\"et-query-devtools-input\"\n type=\"text\"\n placeholder=\"page=2&limit=10\"\n />\n <small>\n parameters the request must carry; anything else it asks for is ignored. Empty answers whatever the query\n string is - and a mock naming parameters wins over one that does not\n </small>\n </label>\n\n <label class=\"et-query-devtools-field\">\n <span>Status</span>\n <input\n #statusDraftInput\n [value]=\"form.status\"\n (input)=\"patchDraft({ status: statusDraftInput.value })\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"100\"\n max=\"599\"\n step=\"1\"\n />\n <small>400 and above arrive as a real error</small>\n </label>\n\n <label class=\"et-query-devtools-field\">\n <span>Latency</span>\n <input\n #latencyDraftInput\n [value]=\"form.latencyMs\"\n (input)=\"patchDraft({ latencyMs: latencyDraftInput.value })\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"0\"\n max=\"60000\"\n step=\"100\"\n />\n <small>ms before it settles</small>\n </label>\n </div>\n\n @if (hasSchema()) {\n <div class=\"et-query-devtools-seed\">\n <span class=\"et-query-devtools-section\">Seed</span>\n @if (isSchemaReady()) {\n <div class=\"et-query-devtools-seed-pick\">\n <et-select\n [options]=\"routeOptions()\"\n (pickOption)=\"pickRoute($event)\"\n class=\"et-query-devtools-combobox\"\n mirrorPanelWidth=\"false\"\n pickOnly\n >\n <input etSelectSearch placeholder=\"search the routes it declares\u2026\" />\n </et-select>\n <button\n (click)=\"seedFromDraftRoute()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"Generate a body from what the description says this path returns\"\n >\n From this path\n </button>\n </div>\n <div class=\"et-query-devtools-seed-pick\">\n <et-select\n [value]=\"pickedSchema()\"\n [options]=\"schemaNameOptions()\"\n (valueChange)=\"pickSchema($event)\"\n class=\"et-query-devtools-combobox\"\n mirrorPanelWidth=\"false\"\n >\n <input etSelectSearch placeholder=\"search its named types\u2026\" />\n </et-select>\n <button\n [disabled]=\"!pickedSchema()\"\n (click)=\"seedFromSchema()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n >\n From this type\n </button>\n </div>\n <select\n #stylePick\n (change)=\"pickSeedStyle(stylePick.value)\"\n class=\"et-query-devtools-select\"\n title=\"How lifelike the generated values are\"\n >\n @for (style of SEED_STYLES; track style.value) {\n <option [value]=\"style.value\" [selected]=\"style.value === seedStyle()\">{{ style.label }}</option>\n }\n </select>\n <small class=\"et-query-devtools-hint et-query-devtools-seed-hint\">{{ seedStyleHint() }}</small>\n } @else if (schemaError(); as error) {\n <span class=\"et-query-devtools-settings-warn\">The API description could not be loaded: {{ error }}</span>\n } @else {\n <span class=\"et-query-devtools-count\">Loading the API description\u2026</span>\n }\n </div>\n }\n\n <label class=\"et-query-devtools-mock-body\">\n <span class=\"et-query-devtools-section\">Body</span>\n <textarea\n #bodyInput\n [value]=\"form.body\"\n (input)=\"patchDraft({ body: bodyInput.value })\"\n class=\"et-query-devtools-input et-query-devtools-mock-textarea\"\n rows=\"8\"\n spellcheck=\"false\"\n ></textarea>\n </label>\n\n @if (draftSeed(); as seed) {\n <p class=\"et-query-devtools-hint\">\n Generated from the API description{{ seed.schemaName ? ' as ' + seed.schemaName : '' }} - a starting point,\n not the contract. Saving opens the designer on it.\n </p>\n @if (seed.notes.length) {\n <ul class=\"et-query-devtools-designer-notes\">\n @for (note of seed.notes; track note) {\n <li>{{ note }}</li>\n }\n </ul>\n }\n }\n\n @if (draftError(); as error) {\n <p class=\"et-query-devtools-settings-warn\">{{ error }}</p>\n }\n\n <div class=\"et-query-devtools-mock-head\">\n <button (click)=\"saveDraft()\" class=\"et-query-devtools-btn et-query-devtools-btn--primary\" type=\"button\">\n Save to the library\n </button>\n <button (click)=\"closeDraft()\" class=\"et-query-devtools-btn\" type=\"button\">Cancel</button>\n </div>\n </div>\n }\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Designed</strong>\n <span class=\"et-query-devtools-count\">{{ rows().length }} in the library</span>\n @if (rows().length) {\n <div class=\"et-query-devtools-spec-export\">\n <select #formatPick (change)=\"pickSpecFormat(formatPick.value)\" class=\"et-query-devtools-select\">\n @for (format of SPEC_FORMATS; track format.value) {\n <option [value]=\"format.value\" [selected]=\"format.value === specFormat()\">{{ format.label }}</option>\n }\n </select>\n <button\n (click)=\"exportLibrary()\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"Download every designed route as one OpenAPI 3.1 document - the response schemas inferred from the designed bodies, each body as an example\"\n >\n <span aria-hidden=\"true\">\u21E9</span>\n Export OpenAPI\n </button>\n </div>\n }\n </div>\n\n @for (row of rows(); track row.mock.id) {\n <div [class.et-query-devtools-mock-row--armed]=\"row.armed\" class=\"et-query-devtools-mock-row\">\n <div class=\"et-query-devtools-mock-head\">\n <button\n [class.et-query-devtools-btn--tampered]=\"row.armed\"\n [attr.aria-pressed]=\"row.armed\"\n (click)=\"toggleArmed(row)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"{{ row.armed ? 'Stop serving this response' : 'Serve this response instead of the request' }}\"\n >\n {{ row.armed ? 'Armed' : 'Arm' }}\n </button>\n <span class=\"et-query-devtools-method\">{{ row.mock.method }}</span>\n <span class=\"et-query-devtools-route et-query-devtools-mono\">{{ row.mock.pattern }}</span>\n @if (row.mock.query) {\n <span class=\"et-query-devtools-url\">?{{ row.mock.query }}</span>\n }\n <span class=\"et-query-devtools-url\">{{ row.mock.clientName }}</span>\n @if (row.mock.capturedAt) {\n <span class=\"et-query-devtools-chip\">captured</span>\n }\n @if (row.mock.schemaName; as schemaName) {\n <span class=\"et-query-devtools-chip\" title=\"Seeded from the API description\">{{ schemaName }}</span>\n }\n @if (row.isSecure) {\n <span\n class=\"et-query-devtools-chip et-query-devtools-chip--error\"\n title=\"A mock sends nothing, so no token is attached and the auth flow is never exercised\"\n >\n no auth\n </span>\n }\n <span class=\"et-query-devtools-count\">{{ host.formatBytes(row.bytes) }}</span>\n <button (click)=\"editBody(row)\" class=\"et-query-devtools-btn\" type=\"button\">Body</button>\n <button\n (click)=\"copyDefinition(row)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"Copy this route as a @ethlete/query definition - the response type inferred from the body, the args contract and the creator call\"\n >\n <span aria-hidden=\"true\">\u29C9</span>\n {{ copiedId() === row.mock.id ? 'Copied' : 'TS' }}\n </button>\n <button\n (click)=\"copyPathItem(row)\"\n class=\"et-query-devtools-btn\"\n type=\"button\"\n title=\"Copy this route as an OpenAPI paths entry, ready to paste under an existing description\"\n >\n <span aria-hidden=\"true\">\u29C9</span>\n {{ copiedSpecId() === row.mock.id ? 'Copied' : 'OAS' }}\n </button>\n <button (click)=\"remove(row)\" class=\"et-query-devtools-btn et-query-devtools-btn--danger\" type=\"button\">\n Delete\n </button>\n </div>\n\n <div class=\"et-query-devtools-mock-fields\">\n <label class=\"et-query-devtools-field\">\n <span>Status</span>\n <input\n #statusInput\n [value]=\"row.mock.status\"\n (change)=\"setStatus(row, statusInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"100\"\n max=\"599\"\n step=\"1\"\n />\n <small>400 and above arrive as a real error, body and all</small>\n </label>\n <label class=\"et-query-devtools-field\">\n <span>Latency</span>\n <input\n #latencyInput\n [value]=\"row.mock.latencyMs\"\n (change)=\"setLatency(row, latencyInput.value)\"\n class=\"et-query-devtools-input et-query-devtools-input--number\"\n type=\"number\"\n min=\"0\"\n max=\"60000\"\n step=\"100\"\n />\n <small>ms before it settles, so the route still has a loading state</small>\n </label>\n </div>\n\n @if (editingId() === row.mock.id) {\n <et-query-devtools-mock-designer\n [body]=\"row.mock.body\"\n [annotations]=\"editingAnnotations()\"\n (save)=\"saveBody(row, $event)\"\n (dismiss)=\"cancelBody()\"\n />\n }\n </div>\n } @empty {\n <p class=\"et-query-devtools-empty\">\n Nothing designed yet. <strong>New mock</strong> writes one from scratch; capturing below seeds one from\n something that actually happened.\n </p>\n }\n\n @if (specNotes().length) {\n <ul class=\"et-query-devtools-designer-notes\">\n @for (note of specNotes(); track note) {\n <li>{{ note }}</li>\n }\n </ul>\n }\n </div>\n\n <div class=\"et-query-devtools-card\">\n <div class=\"et-query-devtools-card-head\">\n <strong>Capture</strong>\n <span class=\"et-query-devtools-count\">live queries holding a response</span>\n </div>\n\n @for (row of captureRows(); track row.entry.id) {\n <div class=\"et-query-devtools-mock-head\">\n <span class=\"et-query-devtools-method\">{{ row.method }}</span>\n <button\n (click)=\"host.selectQuery(row.entry.id)\"\n class=\"et-query-devtools-route et-query-devtools-mono et-query-devtools-row-link\"\n type=\"button\"\n title=\"Open this query\"\n >\n {{ row.pattern }}\n </button>\n <span class=\"et-query-devtools-url\">{{ row.clientName }}</span>\n @if (row.shared > 1) {\n <span class=\"et-query-devtools-count\" title=\"A mock answers the route, so it answers all of them\">\n {{ row.shared }} queries\n </span>\n }\n <span class=\"et-query-devtools-count\">{{ host.formatBytes(row.bytes) }}</span>\n <button (click)=\"capture(row)\" class=\"et-query-devtools-btn\" type=\"button\">\n {{ row.exists ? 'Re-capture' : 'Capture' }}\n </button>\n </div>\n } @empty {\n <p class=\"et-query-devtools-empty\">No live query has a response yet.</p>\n }\n </div>\n</div>\n", styles: ["@layer components{.et-query-devtools-mocks-toolbar{align-items:flex-start}.et-query-devtools-mock-row{padding-block:.6rem;border-block-start:1px solid var(--_et-qdt-border)}.et-query-devtools-card>.et-query-devtools-mock-row:first-of-type{border-block-start:0;padding-block-start:0}.et-query-devtools-mock-row--armed{background:color-mix(in srgb,var(--_et-qdt-error) 6%,transparent)}.et-query-devtools-mock-head{display:flex;align-items:center;flex-wrap:wrap;gap:.6rem;min-block-size:var(--_et-qdt-row-h)}.et-query-devtools-mock-fields,.et-query-devtools-seed,.et-query-devtools-mock-body{max-inline-size:96rem}.et-query-devtools-mock-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(38rem,1fr));align-items:start;gap:.4rem 1.6rem;padding-block-start:.4rem}.et-query-devtools-mock-fields .et-query-devtools-field{display:grid;grid-template-columns:7rem minmax(0,1fr);align-items:baseline;row-gap:.2rem;color:var(--_et-qdt-fg)}.et-query-devtools-mock-fields .et-query-devtools-select{justify-self:start;max-inline-size:100%}.et-query-devtools-mock-fields .et-query-devtools-field small{grid-column:2;color:var(--_et-qdt-subtle);font-size:1.1rem}.et-query-devtools-mock-fields .et-query-devtools-field--wide{grid-column:1 / -1;grid-template-columns:7rem minmax(0,1fr)}.et-query-devtools-spec-export{display:flex;align-items:center;gap:.6rem;margin-inline-start:auto}.et-query-devtools-seed{display:flex;align-items:center;flex-wrap:wrap;gap:.4rem 2.4rem;padding-block-start:.4rem;min-block-size:var(--_et-qdt-row-h)}.et-query-devtools-seed-pick{display:flex;align-items:center;gap:.2rem}.et-query-devtools-seed .et-query-devtools-select{max-inline-size:32rem}.et-query-devtools-combobox{flex:0 1 auto;inline-size:32rem;min-block-size:var(--_et-qdt-control-h);box-sizing:border-box;background:color-mix(in srgb,var(--_et-qdt-interaction) 5%,var(--_et-qdt-bg));color:var(--_et-qdt-fg);border:1px solid transparent;border-radius:var(--_et-qdt-radius);padding:.4rem .6rem;font-size:1.15rem}.et-query-devtools-combobox input{background:none;border:0;padding:0;color:inherit;font:inherit}.et-query-devtools-seed-hint{flex-basis:100%;margin:0}.et-query-devtools-mock-body{display:block;padding-block-start:.4rem}.et-query-devtools-mock-textarea{display:block;inline-size:100%;resize:vertical;font-family:inherit;font-size:1.15rem;line-height:1.5;tab-size:2}}\n"], dependencies: [{ kind: "component", type: QueryDevtoolsMockDesignerComponent, selector: "et-query-devtools-mock-designer", inputs: ["body", "annotations", "notes"], outputs: ["save", "dismiss"] }, { kind: "component", type: SelectComponent, selector: "et-select", inputs: ["loadMoreLabel", "addNewLabel", "createLabel", "clearable", "clearLabel", "selectAllLabel"] }, { kind: "directive", type: SelectSearchDirective, selector: "input[etSelectSearch]", inputs: ["query"], outputs: ["queryChange"], exportAs: ["etSelectSearch"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
3558
3558
|
}
|
|
3559
3559
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: QueryDevtoolsMocksTabComponent, decorators: [{
|
|
3560
3560
|
type: Component,
|
|
@@ -3696,7 +3696,7 @@ const summarizeLocks = (options) => {
|
|
|
3696
3696
|
|
|
3697
3697
|
// Generated from package.json by tools/scripts/generate-version.js - do not edit.
|
|
3698
3698
|
/** The version of `@ethlete/query-devtools` this build was cut from. */
|
|
3699
|
-
const QUERY_DEVTOOLS_VERSION = '1.0.0-next.
|
|
3699
|
+
const QUERY_DEVTOOLS_VERSION = '1.0.0-next.13';
|
|
3700
3700
|
|
|
3701
3701
|
/**
|
|
3702
3702
|
* How deep a value is walked before it is replaced by a marker, and how much of a long string or a long
|
|
@@ -4852,7 +4852,7 @@ const POPOUT_DOCUMENT = `<!doctype html>
|
|
|
4852
4852
|
<meta charset="utf-8" />
|
|
4853
4853
|
<title>Query devtools</title>
|
|
4854
4854
|
</head>
|
|
4855
|
-
<body
|
|
4855
|
+
<body></body>
|
|
4856
4856
|
</html>`;
|
|
4857
4857
|
/**
|
|
4858
4858
|
* Every stylesheet the panel injects after it is created rather than with itself. A pop-out copies the
|
|
@@ -7067,9 +7067,7 @@ class QueryDevtoolsComponent {
|
|
|
7067
7067
|
try {
|
|
7068
7068
|
if (request)
|
|
7069
7069
|
return request.subtle.resolveHeaders();
|
|
7070
|
-
return
|
|
7071
|
-
? args.headers()
|
|
7072
|
-
: args?.headers;
|
|
7070
|
+
return resolveQueryHeaders(args?.headers);
|
|
7073
7071
|
}
|
|
7074
7072
|
catch {
|
|
7075
7073
|
return undefined;
|
|
@@ -7170,8 +7168,9 @@ class QueryDevtoolsComponent {
|
|
|
7170
7168
|
const doc = popup.document;
|
|
7171
7169
|
const renderer = this.renderer;
|
|
7172
7170
|
renderer.setAttribute(doc.documentElement, 'class', this.document.documentElement.className);
|
|
7173
|
-
renderer.
|
|
7171
|
+
renderer.setCssProperties(doc.documentElement, this.inlineStyleOf(this.document.documentElement));
|
|
7174
7172
|
renderer.setAttribute(doc.body, 'class', this.document.body.className);
|
|
7173
|
+
renderer.setStyle(doc.body, { margin: '0' });
|
|
7175
7174
|
// Inserted before the stylesheets it applies to: a blob document's own base URL is the blob, so a
|
|
7176
7175
|
// copied `<link href="styles.css">` - and every relative `url()` inside a copied `<style>` - would
|
|
7177
7176
|
// resolve against nothing and silently fail to load.
|
|
@@ -7216,6 +7215,12 @@ class QueryDevtoolsComponent {
|
|
|
7216
7215
|
}
|
|
7217
7216
|
return tokens;
|
|
7218
7217
|
}
|
|
7218
|
+
inlineStyleOf(element) {
|
|
7219
|
+
const styles = {};
|
|
7220
|
+
for (const property of Array.from(element.style))
|
|
7221
|
+
styles[property] = element.style.getPropertyValue(property);
|
|
7222
|
+
return styles;
|
|
7223
|
+
}
|
|
7219
7224
|
/** Whether a `<head>` child carries CSS the pop-out needs a copy of. */
|
|
7220
7225
|
isStyleNode(node) {
|
|
7221
7226
|
if (node.tagName === 'STYLE')
|
|
@@ -7234,6 +7239,9 @@ class QueryDevtoolsComponent {
|
|
|
7234
7239
|
if (!(node instanceof Element) || !this.isStyleNode(node) || copies.has(node))
|
|
7235
7240
|
return;
|
|
7236
7241
|
const clone = doc.importNode(node, true);
|
|
7242
|
+
// A nonce'd element hides its `nonce` attribute once connected, so the clone gets it from the property.
|
|
7243
|
+
if (node instanceof HTMLElement && node.nonce)
|
|
7244
|
+
this.renderer.setAttribute(clone, 'nonce', node.nonce);
|
|
7237
7245
|
copies.set(node, clone);
|
|
7238
7246
|
this.renderer.appendChild(doc.head, clone);
|
|
7239
7247
|
};
|