@ngxs/store 20.1.0 → 21.0.0-dev.master-05cbecf

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.
@@ -1,11 +1,12 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Injectable, DestroyRef, NgZone, Injector, runInInjectionContext, InjectionToken, ErrorHandler, ɵisPromise as _isPromise, computed, makeEnvironmentProviders, provideEnvironmentInitializer, NgModule, APP_BOOTSTRAP_LISTENER, ApplicationRef, PendingTasks, assertInInjectionContext, EnvironmentInjector, createEnvironmentInjector } from '@angular/core';
2
+ import { inject, Injectable, DestroyRef, NgZone, Injector, runInInjectionContext, InjectionToken, ErrorHandler, ɵisPromise as _isPromise, computed, makeEnvironmentProviders, provideEnvironmentInitializer, NgModule, APP_BOOTSTRAP_LISTENER, PendingTasks, ApplicationRef, assertInInjectionContext, EnvironmentInjector, createEnvironmentInjector } from '@angular/core';
3
3
  import { config, Observable, Subject, of, forkJoin, map, shareReplay, filter, take, mergeMap, EMPTY, from, isObservable, defaultIfEmpty, takeUntil, finalize, catchError, distinctUntilChanged, startWith, skip, buffer, debounceTime } from 'rxjs';
4
4
  import { ɵwrapObserverCalls as _wrapObserverCalls, ɵOrderedSubject as _OrderedSubject, ɵStateStream as _StateStream, ɵhasOwnProperty as _hasOwnProperty, ɵmemoize as _memoize, ɵgetStoreMetadata as _getStoreMetadata, ɵgetSelectorMetadata as _getSelectorMetadata, ɵMETA_KEY as _META_KEY, ɵINITIAL_STATE_TOKEN as _INITIAL_STATE_TOKEN, ɵNgxsActionRegistry as _NgxsActionRegistry, ɵNgxsAppBootstrappedState as _NgxsAppBootstrappedState, ɵensureStoreMetadata as _ensureStoreMetadata, ɵMETA_OPTIONS_KEY as _META_OPTIONS_KEY, ɵensureSelectorMetadata as _ensureSelectorMetadata, ɵNGXS_STATE_CONTEXT_FACTORY as _NGXS_STATE_CONTEXT_FACTORY, ɵNGXS_STATE_FACTORY as _NGXS_STATE_FACTORY } from '@ngxs/store/internals';
5
5
  export { StateToken } from '@ngxs/store/internals';
6
6
  import { NGXS_PLUGINS, getActionTypeFromInstance, InitState, UpdateState, setValue, getValue, ɵisPluginClass as _isPluginClass } from '@ngxs/store/plugins';
7
7
  export { InitState, NGXS_PLUGINS, UpdateState, actionMatcher, getActionTypeFromInstance, getValue, setValue } from '@ngxs/store/plugins';
8
8
  import { isStateOperator } from '@ngxs/store/operators';
9
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
9
10
 
10
11
  class PluginManager {
11
12
  plugins = [];
@@ -30,10 +31,10 @@ class PluginManager {
30
31
  const handlers = this._pluginHandlers || [];
31
32
  return handlers.map((plugin) => (plugin.handle ? plugin.handle.bind(plugin) : plugin));
32
33
  }
33
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PluginManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
34
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PluginManager, providedIn: 'root' });
34
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: PluginManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
35
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: PluginManager, providedIn: 'root' });
35
36
  }
36
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PluginManager, decorators: [{
37
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: PluginManager, decorators: [{
37
38
  type: Injectable,
38
39
  args: [{ providedIn: 'root' }]
39
40
  }], ctorParameters: () => [] });
@@ -132,10 +133,10 @@ class InternalDispatchedActionResults extends Subject {
132
133
  // any actions after the application is destroyed.
133
134
  inject(DestroyRef).onDestroy(() => this.complete());
134
135
  }
135
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatchedActionResults, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
136
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatchedActionResults, providedIn: 'root' });
136
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalDispatchedActionResults, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
137
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalDispatchedActionResults, providedIn: 'root' });
137
138
  }
138
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatchedActionResults, decorators: [{
139
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalDispatchedActionResults, decorators: [{
139
140
  type: Injectable,
140
141
  args: [{ providedIn: 'root' }]
141
142
  }], ctorParameters: () => [] });
@@ -163,10 +164,10 @@ class InternalNgxsExecutionStrategy {
163
164
  }
164
165
  return func();
165
166
  }
166
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalNgxsExecutionStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
167
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalNgxsExecutionStrategy, providedIn: 'root' });
167
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalNgxsExecutionStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
168
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalNgxsExecutionStrategy, providedIn: 'root' });
168
169
  }
169
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalNgxsExecutionStrategy, decorators: [{
170
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalNgxsExecutionStrategy, decorators: [{
170
171
  type: Injectable,
171
172
  args: [{ providedIn: 'root' }]
172
173
  }] });
@@ -204,10 +205,10 @@ class InternalActions extends _OrderedSubject {
204
205
  this.dispatched$.complete();
205
206
  });
206
207
  }
207
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
208
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActions, providedIn: 'root' });
208
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalActions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
209
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalActions, providedIn: 'root' });
209
210
  }
210
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActions, decorators: [{
211
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalActions, decorators: [{
211
212
  type: Injectable,
212
213
  args: [{ providedIn: 'root' }]
213
214
  }], ctorParameters: () => [] });
@@ -237,10 +238,10 @@ class Actions extends Observable {
237
238
  observer.add(childSubscription);
238
239
  });
239
240
  }
240
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Actions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
241
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Actions, providedIn: 'root' });
241
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Actions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
242
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Actions, providedIn: 'root' });
242
243
  }
243
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Actions, decorators: [{
244
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Actions, decorators: [{
244
245
  type: Injectable,
245
246
  args: [{ providedIn: 'root' }]
246
247
  }], ctorParameters: () => [] });
@@ -253,6 +254,7 @@ class InternalDispatcher {
253
254
  _stateStream = inject(_StateStream);
254
255
  _ngxsExecutionStrategy = inject(InternalNgxsExecutionStrategy);
255
256
  _injector = inject(Injector);
257
+ _destroyRef = inject(DestroyRef);
256
258
  /**
257
259
  * Dispatches event(s).
258
260
  */
@@ -280,7 +282,7 @@ class InternalDispatcher {
280
282
  }
281
283
  const prevState = this._stateStream.getValue();
282
284
  const plugins = this._pluginManager.plugins;
283
- return compose(this._injector, [
285
+ return compose(this._injector, this._destroyRef, [
284
286
  ...plugins,
285
287
  (nextState, nextAction) => {
286
288
  if (nextState !== prevState) {
@@ -312,10 +314,10 @@ class InternalDispatcher {
312
314
  }
313
315
  }), shareReplay());
314
316
  }
315
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatcher, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
316
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatcher, providedIn: 'root' });
317
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalDispatcher, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
318
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalDispatcher, providedIn: 'root' });
317
319
  }
318
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatcher, decorators: [{
320
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalDispatcher, decorators: [{
319
321
  type: Injectable,
320
322
  args: [{ providedIn: 'root' }]
321
323
  }] });
@@ -338,9 +340,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImpor
338
340
  *
339
341
  * the last function should not call `next`.
340
342
  */
341
- const compose = (injector, funcs) => (...args) => {
342
- const curr = funcs.shift();
343
- return runInInjectionContext(injector, () => curr(...args, (...nextArgs) => compose(injector, funcs)(...nextArgs)));
343
+ const compose = (injector, destroyRef, fns) => (...args) => {
344
+ const fn = fns.shift();
345
+ if (destroyRef.destroyed || !fn) {
346
+ // Injector was already destroyed → no-op
347
+ return EMPTY;
348
+ }
349
+ return runInInjectionContext(injector, () => fn(...args, (...nextArgs) => compose(injector, destroyRef, fns)(...nextArgs)));
344
350
  };
345
351
 
346
352
  // The injection token is used to resolve a list of states provided at
@@ -378,8 +384,8 @@ class NgxsConfig {
378
384
  injectContainerState: false,
379
385
  suppressErrors: false
380
386
  };
381
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
382
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsConfig, providedIn: 'root', useFactory: () => {
387
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
388
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsConfig, providedIn: 'root', useFactory: () => {
383
389
  const defaultConfig = new NgxsConfig();
384
390
  const config = inject(NGXS_OPTIONS);
385
391
  return {
@@ -392,7 +398,7 @@ class NgxsConfig {
392
398
  };
393
399
  } });
394
400
  }
395
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsConfig, decorators: [{
401
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsConfig, decorators: [{
396
402
  type: Injectable,
397
403
  args: [{
398
404
  providedIn: 'root',
@@ -476,10 +482,10 @@ class InternalStateOperations {
476
482
  // Set the state to the current + new
477
483
  stateOperations.setState({ ...currentState, ...results.defaults });
478
484
  }
479
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalStateOperations, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
480
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalStateOperations, providedIn: 'root' });
485
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalStateOperations, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
486
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalStateOperations, providedIn: 'root' });
481
487
  }
482
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalStateOperations, decorators: [{
488
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalStateOperations, decorators: [{
483
489
  type: Injectable,
484
490
  args: [{ providedIn: 'root' }]
485
491
  }] });
@@ -892,10 +898,10 @@ class NgxsUnhandledActionsLogger {
892
898
  : action.type;
893
899
  console.warn(`The ${action} action has been dispatched but hasn't been handled. This may happen if the state with an action handler for this action is not registered.`);
894
900
  }
895
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledActionsLogger, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
896
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledActionsLogger });
901
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsUnhandledActionsLogger, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
902
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsUnhandledActionsLogger });
897
903
  }
898
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledActionsLogger, decorators: [{
904
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsUnhandledActionsLogger, decorators: [{
899
905
  type: Injectable
900
906
  }], ctorParameters: () => [] });
901
907
 
@@ -916,10 +922,10 @@ class NgxsUnhandledErrorHandler {
916
922
  // `handleError` (see `_callAndReportToErrorHandler`).
917
923
  this._ngZone.runOutsideAngular(() => this._errorHandler.handleError(error));
918
924
  }
919
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledErrorHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
920
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledErrorHandler, providedIn: 'root' });
925
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsUnhandledErrorHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
926
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsUnhandledErrorHandler, providedIn: 'root' });
921
927
  }
922
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledErrorHandler, decorators: [{
928
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsUnhandledErrorHandler, decorators: [{
923
929
  type: Injectable,
924
930
  args: [{ providedIn: 'root' }]
925
931
  }] });
@@ -1054,9 +1060,10 @@ class StateContextFactory {
1054
1060
  /**
1055
1061
  * Create the state context
1056
1062
  */
1057
- createStateContext(path) {
1063
+ createStateContext(path, abortSignal) {
1058
1064
  const root = this._internalStateOperations.getRootStateOperations();
1059
1065
  return {
1066
+ abortSignal,
1060
1067
  getState() {
1061
1068
  const currentAppState = root.getState();
1062
1069
  return getState(currentAppState, path);
@@ -1080,10 +1087,10 @@ class StateContextFactory {
1080
1087
  }
1081
1088
  };
1082
1089
  }
1083
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateContextFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1084
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateContextFactory, providedIn: 'root' });
1090
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: StateContextFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1091
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: StateContextFactory, providedIn: 'root' });
1085
1092
  }
1086
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateContextFactory, decorators: [{
1093
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: StateContextFactory, decorators: [{
1087
1094
  type: Injectable,
1088
1095
  args: [{ providedIn: 'root' }]
1089
1096
  }] });
@@ -1113,7 +1120,8 @@ class InternalActionHandlerFactory {
1113
1120
  createActionHandler(path, handlerFn, options) {
1114
1121
  const { dispatched$ } = this._actions;
1115
1122
  return (action) => {
1116
- const stateContext = this._stateContextFactory.createStateContext(path);
1123
+ const abortController = new AbortController();
1124
+ const stateContext = this._stateContextFactory.createStateContext(path, abortController.signal);
1117
1125
  let result = handlerFn(stateContext, action);
1118
1126
  // We need to use `isPromise` instead of checking whether
1119
1127
  // `result instanceof Promise`. In zone.js patched environments, `global.Promise`
@@ -1132,12 +1140,18 @@ class InternalActionHandlerFactory {
1132
1140
  // For instance, if any action handler had a statement like
1133
1141
  // `handler(ctx) { return EMPTY; }`, then the action would be canceled.
1134
1142
  // See https://github.com/ngxs/store/issues/1568
1135
- // Note that we actually don't care about the return type; we only care
1136
- // about emission, and thus `undefined` is applicable by the framework.
1137
1143
  defaultIfEmpty(undefined));
1138
1144
  if (options.cancelUncompleted) {
1139
1145
  const canceled = dispatched$.pipe(ofActionDispatched(action));
1140
- result = result.pipe(takeUntil(canceled));
1146
+ result = result.pipe(takeUntil(new Observable(subscriber => {
1147
+ return canceled.subscribe(() => {
1148
+ // Note that we shouldn't use `catchError` to catch abort errors
1149
+ // because the observable is canceled before the error is thrown,
1150
+ // so we don't need to handle it.
1151
+ abortController.abort();
1152
+ subscriber.next();
1153
+ });
1154
+ })));
1141
1155
  }
1142
1156
  result = result.pipe(
1143
1157
  // Note that we use the `finalize` operator only when the action handler
@@ -1168,10 +1182,10 @@ class InternalActionHandlerFactory {
1168
1182
  return result;
1169
1183
  };
1170
1184
  }
1171
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActionHandlerFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1172
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActionHandlerFactory, providedIn: 'root' });
1185
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalActionHandlerFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1186
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalActionHandlerFactory, providedIn: 'root' });
1173
1187
  }
1174
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActionHandlerFactory, decorators: [{
1188
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: InternalActionHandlerFactory, decorators: [{
1175
1189
  type: Injectable,
1176
1190
  args: [{ providedIn: 'root' }]
1177
1191
  }] });
@@ -1252,7 +1266,12 @@ class StateFactory {
1252
1266
  return context;
1253
1267
  });
1254
1268
  constructor() {
1255
- inject(DestroyRef).onDestroy(() => this._actionsSubscription?.unsubscribe());
1269
+ inject(DestroyRef).onDestroy(() => {
1270
+ // Clear state references to help the garbage collector in SSR
1271
+ // environments under high load, preventing memory leaks.
1272
+ this._states = [];
1273
+ this._actionsSubscription?.unsubscribe();
1274
+ });
1256
1275
  }
1257
1276
  /**
1258
1277
  * Add a new state to the global defs.
@@ -1399,10 +1418,10 @@ class StateFactory {
1399
1418
  }
1400
1419
  }
1401
1420
  }
1402
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1403
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateFactory, providedIn: 'root' });
1421
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: StateFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1422
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: StateFactory, providedIn: 'root' });
1404
1423
  }
1405
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateFactory, decorators: [{
1424
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: StateFactory, decorators: [{
1406
1425
  type: Injectable,
1407
1426
  args: [{ providedIn: 'root' }]
1408
1427
  }], ctorParameters: () => [] });
@@ -1470,7 +1489,14 @@ class Store {
1470
1489
  */
1471
1490
  selectSignal(selector) {
1472
1491
  const selectorFn = this.getStoreBoundSelectorFn(selector);
1473
- return computed(() => selectorFn(this._stateStream.state()));
1492
+ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
1493
+ return computed(() => selectorFn(this._stateStream.state()), {
1494
+ debugName: 'NGXS selectSignal'
1495
+ });
1496
+ }
1497
+ else {
1498
+ return computed(() => selectorFn(this._stateStream.state()));
1499
+ }
1474
1500
  }
1475
1501
  /**
1476
1502
  * Allow the user to subscribe to the root of the state
@@ -1506,10 +1532,10 @@ class Store {
1506
1532
  this._stateStream.next(initialStateValue);
1507
1533
  }
1508
1534
  }
1509
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Store, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1510
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Store, providedIn: 'root' });
1535
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Store, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1536
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Store, providedIn: 'root' });
1511
1537
  }
1512
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Store, decorators: [{
1538
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: Store, decorators: [{
1513
1539
  type: Injectable,
1514
1540
  args: [{ providedIn: 'root' }]
1515
1541
  }], ctorParameters: () => [] });
@@ -1571,10 +1597,10 @@ class SelectFactory {
1571
1597
  SelectFactory.config = null;
1572
1598
  });
1573
1599
  }
1574
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: SelectFactory, deps: [{ token: Store }, { token: NgxsConfig }], target: i0.ɵɵFactoryTarget.Injectable });
1575
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: SelectFactory, providedIn: 'root' });
1600
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SelectFactory, deps: [{ token: Store }, { token: NgxsConfig }], target: i0.ɵɵFactoryTarget.Injectable });
1601
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SelectFactory, providedIn: 'root' });
1576
1602
  }
1577
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: SelectFactory, decorators: [{
1603
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SelectFactory, decorators: [{
1578
1604
  type: Injectable,
1579
1605
  args: [{ providedIn: 'root' }]
1580
1606
  }], ctorParameters: () => [{ type: Store }, { type: NgxsConfig }] });
@@ -1584,7 +1610,11 @@ class LifecycleStateManager {
1584
1610
  _internalStateOperations = inject(InternalStateOperations);
1585
1611
  _stateContextFactory = inject(StateContextFactory);
1586
1612
  _appBootstrappedState = inject(_NgxsAppBootstrappedState);
1613
+ _abortController = new AbortController();
1587
1614
  _initStateHasBeenDispatched;
1615
+ constructor() {
1616
+ inject(DestroyRef).onDestroy(() => this._abortController.abort());
1617
+ }
1588
1618
  ngxsBootstrap(action, results) {
1589
1619
  if (typeof ngDevMode !== 'undefined' && ngDevMode) {
1590
1620
  if (action instanceof InitState) {
@@ -1643,30 +1673,26 @@ class LifecycleStateManager {
1643
1673
  instance.ngxsOnChanges(change);
1644
1674
  });
1645
1675
  }
1646
- if (instance.ngxsOnInit) {
1647
- instance.ngxsOnInit(this._getStateContext(mappedStore));
1648
- }
1676
+ instance.ngxsOnInit?.(this._getStateContext(mappedStore));
1649
1677
  mappedStore.isInitialised = true;
1650
1678
  }
1651
1679
  }
1652
1680
  _invokeBootstrapOnStates(mappedStores) {
1653
1681
  for (const mappedStore of mappedStores) {
1654
1682
  const instance = mappedStore.instance;
1655
- if (instance.ngxsAfterBootstrap) {
1656
- instance.ngxsAfterBootstrap(this._getStateContext(mappedStore));
1657
- }
1683
+ instance.ngxsAfterBootstrap?.(this._getStateContext(mappedStore));
1658
1684
  }
1659
1685
  }
1660
1686
  _getStateContext(mappedStore) {
1661
- return this._stateContextFactory.createStateContext(mappedStore.path);
1687
+ return this._stateContextFactory.createStateContext(mappedStore.path, this._abortController.signal);
1662
1688
  }
1663
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: LifecycleStateManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1664
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: LifecycleStateManager, providedIn: 'root' });
1689
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LifecycleStateManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1690
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LifecycleStateManager, providedIn: 'root' });
1665
1691
  }
1666
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: LifecycleStateManager, decorators: [{
1692
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LifecycleStateManager, decorators: [{
1667
1693
  type: Injectable,
1668
1694
  args: [{ providedIn: 'root' }]
1669
- }] });
1695
+ }], ctorParameters: () => [] });
1670
1696
 
1671
1697
  /**
1672
1698
  * This function is shared by both NgModule and standalone features.
@@ -1750,11 +1776,11 @@ class NgxsRootModule {
1750
1776
  constructor() {
1751
1777
  rootStoreInitializer();
1752
1778
  }
1753
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsRootModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1754
- /** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: NgxsRootModule });
1755
- /** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsRootModule });
1779
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsRootModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1780
+ /** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.2", ngImport: i0, type: NgxsRootModule });
1781
+ /** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsRootModule });
1756
1782
  }
1757
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsRootModule, decorators: [{
1783
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsRootModule, decorators: [{
1758
1784
  type: NgModule
1759
1785
  }], ctorParameters: () => [] });
1760
1786
 
@@ -1765,11 +1791,11 @@ class NgxsFeatureModule {
1765
1791
  constructor() {
1766
1792
  featureStatesInitializer();
1767
1793
  }
1768
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsFeatureModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1769
- /** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: NgxsFeatureModule });
1770
- /** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsFeatureModule });
1794
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsFeatureModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1795
+ /** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.2", ngImport: i0, type: NgxsFeatureModule });
1796
+ /** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsFeatureModule });
1771
1797
  }
1772
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsFeatureModule, decorators: [{
1798
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsFeatureModule, decorators: [{
1773
1799
  type: NgModule
1774
1800
  }], ctorParameters: () => [] });
1775
1801
 
@@ -1828,11 +1854,11 @@ class NgxsModule {
1828
1854
  providers: getFeatureProviders(states)
1829
1855
  };
1830
1856
  }
1831
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1832
- /** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: NgxsModule });
1833
- /** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsModule });
1857
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1858
+ /** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.2", ngImport: i0, type: NgxsModule });
1859
+ /** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsModule });
1834
1860
  }
1835
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsModule, decorators: [{
1861
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsModule, decorators: [{
1836
1862
  type: NgModule
1837
1863
  }] });
1838
1864
 
@@ -2065,10 +2091,10 @@ class ActionDirector {
2065
2091
  const detach = this._registry.register(Action.type, actionHandler);
2066
2092
  return { detach };
2067
2093
  }
2068
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ActionDirector, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2069
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ActionDirector, providedIn: 'root' });
2094
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ActionDirector, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2095
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ActionDirector, providedIn: 'root' });
2070
2096
  }
2071
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ActionDirector, decorators: [{
2097
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ActionDirector, decorators: [{
2072
2098
  type: Injectable,
2073
2099
  args: [{ providedIn: 'root' }]
2074
2100
  }] });
@@ -2083,11 +2109,11 @@ class NgxsDevelopmentModule {
2083
2109
  ]
2084
2110
  };
2085
2111
  }
2086
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsDevelopmentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2087
- /** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: NgxsDevelopmentModule });
2088
- /** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsDevelopmentModule });
2112
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsDevelopmentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2113
+ /** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.2", ngImport: i0, type: NgxsDevelopmentModule });
2114
+ /** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsDevelopmentModule });
2089
2115
  }
2090
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsDevelopmentModule, decorators: [{
2116
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxsDevelopmentModule, decorators: [{
2091
2117
  type: NgModule
2092
2118
  }] });
2093
2119
  function withNgxsDevelopmentOptions(options) {
@@ -2104,10 +2130,10 @@ class NoopNgxsExecutionStrategy {
2104
2130
  leave(func) {
2105
2131
  return func();
2106
2132
  }
2107
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NoopNgxsExecutionStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2108
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NoopNgxsExecutionStrategy, providedIn: 'root' });
2133
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NoopNgxsExecutionStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2134
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NoopNgxsExecutionStrategy, providedIn: 'root' });
2109
2135
  }
2110
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NoopNgxsExecutionStrategy, decorators: [{
2136
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NoopNgxsExecutionStrategy, decorators: [{
2111
2137
  type: Injectable,
2112
2138
  args: [{ providedIn: 'root' }]
2113
2139
  }] });
@@ -2204,7 +2230,10 @@ function createPickSelector(selector, keys) {
2204
2230
  ensureValidSelector(selector, { prefix: '[createPickSelector]' });
2205
2231
  }
2206
2232
  const validKeys = keys.filter(Boolean);
2207
- const selectors = validKeys.map(key => createSelector([selector], (s) => s[key]));
2233
+ const selectors = validKeys.map(key =>
2234
+ // Optional chaining is used because the state being selected may not be
2235
+ // registered yet — for example, if the selector is called before `provideStates()`.
2236
+ createSelector([selector], (state) => state?.[key]));
2208
2237
  return createSelector([...selectors], (...props) => {
2209
2238
  return validKeys.reduce((acc, key, index) => {
2210
2239
  acc[key] = props[index];
@@ -2224,7 +2253,10 @@ function createPropertySelectors(parentSelector) {
2224
2253
  return new Proxy({}, {
2225
2254
  get(_target, prop) {
2226
2255
  const selector = cache[prop] ||
2227
- createSelector([parentSelector], (s) => s?.[prop]);
2256
+ createSelector([parentSelector],
2257
+ // Optional chaining is used because the state being selected may not be
2258
+ // registered yet — for example, if the selector is called before `provideStates()`.
2259
+ (state) => state?.[prop]);
2228
2260
  cache[prop] = selector;
2229
2261
  return selector;
2230
2262
  }
@@ -2241,9 +2273,13 @@ function createPropertySelectors(parentSelector) {
2241
2273
  */
2242
2274
  function withNgxsPendingTasks() {
2243
2275
  return withNgxsPreboot(() => {
2276
+ if (typeof ngServerMode === 'undefined' || !ngServerMode) {
2277
+ console.warn('[withNgxsPendingTasks] This setup is recommended for server-side rendering only. ' +
2278
+ 'Using it in the browser may lead to redundant change detection cycles and degraded performance.');
2279
+ }
2244
2280
  const actions$ = inject(Actions);
2245
- const appRef = inject(ApplicationRef);
2246
2281
  const pendingTasks = inject(PendingTasks);
2282
+ const destroyRef = inject(DestroyRef);
2247
2283
  // Removing a pending task via the public API forces a scheduled tick, ensuring that
2248
2284
  // stability is async and delayed until there was at least an opportunity to run
2249
2285
  // app synchronization.
@@ -2258,12 +2294,8 @@ function withNgxsPendingTasks() {
2258
2294
  // If the app is forcely destroyed before all actions are completed,
2259
2295
  // we clean up the set of actions being executed to prevent memory leaks
2260
2296
  // and remove the pending task to stabilize the app.
2261
- appRef.onDestroy(() => executedActions.clear());
2262
- let isStable = false;
2263
- appRef.whenStable().then(() => {
2264
- isStable = true;
2265
- });
2266
- const subscription = actions$
2297
+ destroyRef.onDestroy(() => executedActions.clear());
2298
+ actions$
2267
2299
  .pipe(filter(context => {
2268
2300
  if (context.status === ActionStatus.Dispatched) {
2269
2301
  executedActions.add(context.action);
@@ -2278,7 +2310,7 @@ function withNgxsPendingTasks() {
2278
2310
  // task is removed, even if multiple synchronous actions are completed in a row.
2279
2311
  // We use `buffer` to collect action contexts because, if we only use
2280
2312
  // `debounceTime(0)`, we may lose action contexts that are never removed from the set.
2281
- buffer(actions$.pipe(debounceTime(0))))
2313
+ buffer(actions$.pipe(debounceTime(0))), takeUntilDestroyed(destroyRef))
2282
2314
  .subscribe(contexts => {
2283
2315
  for (const context of contexts) {
2284
2316
  if (!executedActions.has(context.action)) {
@@ -2289,12 +2321,6 @@ function withNgxsPendingTasks() {
2289
2321
  if (executedActions.size === 0) {
2290
2322
  removeTask?.();
2291
2323
  removeTask = null;
2292
- if (isStable) {
2293
- // Stop contributing to stability once the application has become stable,
2294
- // which may happen on the server before the platform is destroyed or in
2295
- // the browser once hydration is complete.
2296
- subscription.unsubscribe();
2297
- }
2298
2324
  }
2299
2325
  }
2300
2326
  });