@ethlete/query 6.0.0-next.50 → 6.0.0-next.51

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,11 @@
1
1
  # @ethlete/query
2
2
 
3
+ ## 6.0.0-next.51
4
+
5
+ ### Patch Changes
6
+
7
+ - The devtools pills' stylesheet now carries the application's `CSP_NONCE`, so it passes a strict `style-src`.
8
+
3
9
  ## 6.0.0-next.50
4
10
 
5
11
  ### Patch Changes
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ApplicationRef, untracked, effect, Injector, runInInjectionContext, DestroyRef, computed, InjectionToken, EnvironmentInjector, ElementRef, ErrorHandler, createEnvironmentInjector, signal, linkedSignal, isDevMode, PLATFORM_ID, resource, DOCUMENT, VERSION, provideEnvironmentInitializer, afterNextRender, makeEnvironmentProviders, assertInInjectionContext, ChangeDetectorRef, ViewContainerRef, TemplateRef, Input, Directive, input, Pipe, ViewEncapsulation, Component, NgZone } from '@angular/core';
2
+ import { inject, ApplicationRef, untracked, effect, Injector, runInInjectionContext, DestroyRef, computed, InjectionToken, EnvironmentInjector, ElementRef, ErrorHandler, createEnvironmentInjector, signal, linkedSignal, isDevMode, PLATFORM_ID, resource, DOCUMENT, VERSION, provideEnvironmentInitializer, CSP_NONCE, afterNextRender, makeEnvironmentProviders, assertInInjectionContext, ChangeDetectorRef, ViewContainerRef, TemplateRef, Input, Directive, input, Pipe, ViewEncapsulation, Component, NgZone } from '@angular/core';
3
3
  import { UrlTree, Router, RedirectCommand, ActivatedRoute } from '@angular/router';
4
4
  import { Observable, defer, from, filter, Subject, Subscription, throwError, of, timer, switchMap, tap, retry, catchError, EMPTY as EMPTY$1, take, takeUntil, finalize, mergeMap, toArray, map, race, NEVER, merge, takeWhile, firstValueFrom, concatMap, fromEvent, throttleTime, interval, startWith, pairwise, BehaviorSubject, combineLatest, ReplaySubject, distinctUntilChanged, shareReplay, withLatestFrom, debounceTime } from 'rxjs';
5
5
  import { defineStaticProvider, RuntimeError, clamp, randomId, defineRootProvider, isObject, injectUnsavedChangesCoordinator, injectRoute, getCookie, setCookie, deleteCookie, CORE_VERSION, createDestroy, computedTillTruthy, defineProvider, toProvideFn, toInjectFn, nextFrame, injectQueryParams, injectQueryParamChanges, clone, equal, ET_PROPERTY_REMOVED, previousSignalValue } from '@ethlete/core';
@@ -8332,16 +8332,20 @@ let envState = null;
8332
8332
  let authState = null;
8333
8333
  /** What the pill on the page renders, or `null` while there is none. */
8334
8334
  let renderedKey = null;
8335
+ let providedNonce = null;
8336
+ /** Until the application provides `CSP_NONCE`, falls back to where Angular's own default reads it from. */
8337
+ const nonceOf = (doc) => providedNonce ?? doc.body?.querySelector('[ngCspNonce]')?.getAttribute('ngCspNonce') ?? null;
8335
8338
  /**
8336
8339
  * Everything the pill renders, as one string. Every access-token rotation syncs the session pill
8337
8340
  * again, and a rebuild would close an open dropdown under whoever opened it - so a sync that renders
8338
8341
  * the same thing must leave the DOM alone. Whatever `render()` reads has to be in here. The callbacks
8339
8342
  * are not: they are new objects on every sync, and they read their own state when they run.
8340
8343
  */
8341
- const keyOf$1 = (switches, rows, collapsed) => JSON.stringify([
8344
+ const keyOf$1 = (switches, rows, collapsed, nonce) => JSON.stringify([
8342
8345
  switches,
8343
8346
  rows.map(({ name, current, tabLocal, options }) => [name, current, tabLocal, options]),
8344
8347
  collapsed,
8348
+ nonce,
8345
8349
  ]);
8346
8350
  const buildAuthRow = (doc, row) => {
8347
8351
  const pill = doc.createElement('div');
@@ -8421,9 +8425,10 @@ const render = (doc) => {
8421
8425
  const production = switches.some((apiSwitch) => resolvedEnvOf(apiSwitch, storedOf(apiSwitch))?.production === true);
8422
8426
  // A production pick unfolds the pills whatever is stored: the warning is the point of the pill.
8423
8427
  const collapsed = !production && readCollapsed();
8428
+ const nonce = nonceOf(doc);
8424
8429
  const paints = (switches.length > 0 || rows.length > 0) && queryDevtoolsPillsAllowed();
8425
8430
  const key = paints
8426
- ? keyOf$1(switches.map((apiSwitch) => [apiSwitch, storedOf(apiSwitch)]), rows, collapsed)
8431
+ ? keyOf$1(switches.map((apiSwitch) => [apiSwitch, storedOf(apiSwitch)]), rows, collapsed, nonce)
8427
8432
  : null;
8428
8433
  const painted = doc.getElementById(HOST_ID);
8429
8434
  if (painted && key !== null && key === renderedKey)
@@ -8438,6 +8443,8 @@ const render = (doc) => {
8438
8443
  // host application's page and must be as isolated from its global CSS (resets, Tailwind) as possible.
8439
8444
  const shadow = host.attachShadow({ mode: 'open' });
8440
8445
  const style = doc.createElement('style');
8446
+ if (nonce)
8447
+ style.setAttribute('nonce', nonce);
8441
8448
  style.textContent = STYLE;
8442
8449
  shadow.append(style);
8443
8450
  if (collapsed)
@@ -8486,6 +8493,14 @@ const renderPills = () => {
8486
8493
  else
8487
8494
  doc.addEventListener('DOMContentLoaded', () => render(doc), { once: true });
8488
8495
  };
8496
+ /**
8497
+ * Hands the pills the application's `CSP_NONCE`, so their stylesheet passes a strict `style-src`.
8498
+ * @internal
8499
+ */
8500
+ const setQueryDevtoolsPillNonce = (nonce) => {
8501
+ providedNonce = nonce;
8502
+ renderPills();
8503
+ };
8489
8504
  /**
8490
8505
  * Declares the API env part of the pill. Called by `setQueryDevtoolsApiEnvs()`.
8491
8506
  * @internal
@@ -10512,7 +10527,7 @@ const armQueryDevtoolsOverrideTransfer = (recorder, ops) => {
10512
10527
 
10513
10528
  // Generated from package.json by tools/scripts/generate-version.js - do not edit.
10514
10529
  /** The version of `@ethlete/query` this build was cut from. */
10515
- const QUERY_VERSION = '6.0.0-next.50';
10530
+ const QUERY_VERSION = '6.0.0-next.51';
10516
10531
 
10517
10532
  /** How deep a schema is expanded before a nested branch is given up on. */
10518
10533
  const MAX_DEPTH = 12;
@@ -11795,6 +11810,7 @@ const ONE_TIME_OPTIONS = ['about', 'apiEnvs', 'authAccounts', 'responseHistory',
11795
11810
  // repeating timer, so it is never stable and the pills would never go.
11796
11811
  const settleThePillsOnFirstRender = () => provideEnvironmentInitializer(() => {
11797
11812
  const destroyRef = inject(DestroyRef);
11813
+ setQueryDevtoolsPillNonce(inject(CSP_NONCE, { optional: true }));
11798
11814
  afterNextRender(() => {
11799
11815
  const settle = setTimeout(markQueryDevtoolsAppSettled, PILL_SETTLE_GRACE_MS);
11800
11816
  destroyRef.onDestroy(() => clearTimeout(settle));