@ethlete/query 6.0.0-next.26 → 6.0.0-next.27

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.27
4
+
5
+ ### Patch Changes
6
+
7
+ - [#3046](https://github.com/ethlete-io/ethdk/pull/3046) [`291e8a9`](https://github.com/ethlete-io/ethdk/commit/291e8a9c6ecb9c51c191b4ed6e40d41465ff4cfa) Thanks [@github-actions](https://github.com/apps/github-actions)! - Secure queries executed after `setTokens()` (SSO/OIDC callbacks, native shells) no longer wait forever - they now also proceed once `executionState` reports a successful token seed.
8
+
3
9
  ## 6.0.0-next.26
4
10
 
5
11
  ### Minor Changes
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { DestroyRef, InjectionToken, inject, Injector, EnvironmentInjector, ElementRef, ErrorHandler, createEnvironmentInjector, effect, untracked, signal, linkedSignal, computed, runInInjectionContext, isDevMode, PLATFORM_ID, resource, DOCUMENT, makeEnvironmentProviders, assertInInjectionContext, provideEnvironmentInitializer, ChangeDetectorRef, ViewContainerRef, TemplateRef, Input, Directive, input, Pipe, ViewEncapsulation, Component, NgZone } from '@angular/core';
3
3
  import { defineStaticProvider, RuntimeError, clamp, randomId, defineRootProvider, isObject, injectUnsavedChangesCoordinator, injectRoute, getCookie, getDomain, setCookie, deleteCookie, createDestroy, computedTillTruthy, defineProvider, toProvideFn, toInjectFn, nextFrame, injectQueryParams, injectQueryParamChanges, clone, equal, ET_PROPERTY_REMOVED, previousSignalValue } from '@ethlete/core';
4
- import { filter, Subject, Subscription, defer, throwError, timer, switchMap, tap, retry, catchError, take, of, firstValueFrom, merge, fromEvent, throttleTime, interval, combineLatest, map, Observable, takeUntil, startWith, pairwise, BehaviorSubject, ReplaySubject, shareReplay, skip, takeWhile, EMPTY, withLatestFrom, debounceTime } from 'rxjs';
4
+ import { filter, Subject, Subscription, defer, throwError, timer, switchMap, tap, retry, catchError, take, of, merge, firstValueFrom, fromEvent, throttleTime, interval, combineLatest, map, Observable, takeUntil, startWith, pairwise, BehaviorSubject, ReplaySubject, shareReplay, skip, takeWhile, EMPTY, withLatestFrom, debounceTime } from 'rxjs';
5
5
  import { HttpClient, HttpEventType, HttpErrorResponse, HttpHeaders, HttpStatusCode } from '@angular/common/http';
6
6
  import { toObservable, takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
7
7
  import { getActiveConsumer, setActiveConsumer } from '@angular/core/primitives/signals';
@@ -3780,6 +3780,13 @@ const createSecureExecuteFactory = (options) => {
3780
3780
  return currentError?.code === 401;
3781
3781
  }), take(1), tap(() => exec(execArgsWithDefaults)))
3782
3782
  .subscribe();
3783
+ // `setTokens()` seeds an auth session from outside the query registry (an SSO/OIDC callback, a
3784
+ // native shell) - no query ever runs for `latestExecutedQuery` to report, so a successful token
3785
+ // seed is treated as an auth query that already resolved.
3786
+ if (options.authProvider.executionState()?.type === 'tokenSeed') {
3787
+ authAndExecWhenTokenReady(execArgsWithDefaults);
3788
+ return;
3789
+ }
3783
3790
  const latestQuery = options.authProvider.latestExecutedQuery();
3784
3791
  const authQuery = latestQuery?.snapshot;
3785
3792
  // This might happen if a secure query gets executed while the auth query has just been created.
@@ -3787,10 +3794,9 @@ const createSecureExecuteFactory = (options) => {
3787
3794
  const isAuthQueryFreshlyExecuted = authQuery?.lastTimeExecutedAt() === null;
3788
3795
  if (!authQuery || authQuery.loading() || isAuthQueryFreshlyExecuted) {
3789
3796
  options.state.loading.set({ executeTime: Date.now(), progress: null });
3790
- authQuerySubscription = toObservable(options.authProvider.latestExecutedQuery, {
3797
+ const latestExecutedQuery$ = toObservable(options.authProvider.latestExecutedQuery, {
3791
3798
  injector: options.deps.injector,
3792
- })
3793
- .pipe(switchMap((latestQuery) => {
3799
+ }).pipe(switchMap((latestQuery) => {
3794
3800
  if (!latestQuery)
3795
3801
  return of(null);
3796
3802
  const query = latestQuery.snapshot;
@@ -3804,8 +3810,14 @@ const createSecureExecuteFactory = (options) => {
3804
3810
  authAndExecWhenTokenReady(execArgsWithDefaults);
3805
3811
  }
3806
3812
  }));
3807
- }))
3808
- .subscribe();
3813
+ }));
3814
+ // A `setTokens()` call that lands while this is already waiting (e.g. the SSO redirect
3815
+ // resolves after this secure query mounted) never touches `latestExecutedQuery` either -
3816
+ // wake up on `executionState` becoming a token seed too.
3817
+ const tokenSeed$ = toObservable(options.authProvider.executionState, {
3818
+ injector: options.deps.injector,
3819
+ }).pipe(filter((state) => state?.type === 'tokenSeed'), take(1), tap(() => authAndExecWhenTokenReady(execArgsWithDefaults)));
3820
+ authQuerySubscription = merge(latestExecutedQuery$, tokenSeed$).subscribe();
3809
3821
  }
3810
3822
  else if (authQuery.response()) {
3811
3823
  authAndExecWhenTokenReady(execArgsWithDefaults);