@ngxs/store 3.8.2-dev.master-87ee261 → 3.8.2-dev.master-3d36414

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,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, NgZone, PLATFORM_ID, Inject, InjectionToken, inject, INJECTOR, ɵglobal as _global, ErrorHandler, Optional, SkipSelf, ɵisPromise as _isPromise, computed, ENVIRONMENT_INITIALIZER, NgModule, APP_BOOTSTRAP_LISTENER, makeEnvironmentProviders } from '@angular/core';
3
- import { Observable, Subject, of, forkJoin, throwError, EMPTY, from, isObservable, ReplaySubject } from 'rxjs';
2
+ import { Injectable, NgZone, PLATFORM_ID, Inject, InjectionToken, inject, INJECTOR, ɵglobal as _global, Optional, SkipSelf, ErrorHandler, ɵisPromise as _isPromise, computed, ENVIRONMENT_INITIALIZER, NgModule, APP_BOOTSTRAP_LISTENER, makeEnvironmentProviders } from '@angular/core';
3
+ import { Observable, config, Subject, of, forkJoin, throwError, EMPTY, from, isObservable, ReplaySubject } from 'rxjs';
4
4
  import { share, map, shareReplay, filter, take, exhaustMap, mergeMap, defaultIfEmpty, catchError, takeUntil, distinctUntilChanged, tap, startWith, pairwise } from 'rxjs/operators';
5
5
  import * as i1 from '@ngxs/store/internals';
6
6
  import { ɵOrderedSubject as _OrderedSubject, ɵmemoize as _memoize, ɵgetStoreMetadata as _getStoreMetadata, ɵgetSelectorMetadata as _getSelectorMetadata, ɵMETA_KEY as _META_KEY, ɵINITIAL_STATE_TOKEN as _INITIAL_STATE_TOKEN, ɵNgxsAppBootstrappedState as _NgxsAppBootstrappedState, ɵNGXS_STATE_CONTEXT_FACTORY as _NGXS_STATE_CONTEXT_FACTORY, ɵNGXS_STATE_FACTORY as _NGXS_STATE_FACTORY, ɵensureStoreMetadata as _ensureStoreMetadata, ɵMETA_OPTIONS_KEY as _META_OPTIONS_KEY, ɵensureSelectorMetadata as _ensureSelectorMetadata } from '@ngxs/store/internals';
@@ -217,66 +217,6 @@ function leaveNgxs(ngxsExecutionStrategy) {
217
217
  };
218
218
  }
219
219
 
220
- /**
221
- * This operator is used for piping the observable result
222
- * from the `dispatch()`. It has a "smart" error handling
223
- * strategy that allows us to decide whether we propagate
224
- * errors to Angular's `ErrorHandler` or enable users to
225
- * handle them manually. We consider following cases:
226
- * 1) `store.dispatch()` (no subscribe) -> call `handleError()`
227
- * 2) `store.dispatch().subscribe()` (no error callback) -> call `handleError()`
228
- * 3) `store.dispatch().subscribe({ error: ... })` -> don't call `handleError()`
229
- * 4) `toPromise()` without `catch` -> do `handleError()`
230
- * 5) `toPromise()` with `catch` -> don't `handleError()`
231
- */
232
- function ngxsErrorHandler(internalErrorReporter, ngxsExecutionStrategy) {
233
- return (source) => {
234
- let subscribed = false;
235
- source.subscribe({
236
- error: error => {
237
- // Do not trigger change detection for a microtask. This depends on the execution
238
- // strategy being used, but the default `DispatchOutsideZoneNgxsExecutionStrategy`
239
- // leaves the Angular zone.
240
- ngxsExecutionStrategy.enter(() => Promise.resolve().then(() => {
241
- if (!subscribed) {
242
- ngxsExecutionStrategy.leave(() => internalErrorReporter.reportErrorSafely(error));
243
- }
244
- }));
245
- }
246
- });
247
- return new Observable(subscriber => {
248
- subscribed = true;
249
- return source.pipe(leaveNgxs(ngxsExecutionStrategy)).subscribe(subscriber);
250
- });
251
- };
252
- }
253
- class InternalErrorReporter {
254
- constructor(_injector) {
255
- this._injector = _injector;
256
- /** Will be set lazily to be backward compatible. */
257
- this._errorHandler = null;
258
- }
259
- reportErrorSafely(error) {
260
- if (this._errorHandler === null) {
261
- this._errorHandler = this._injector.get(ErrorHandler);
262
- }
263
- // The `try-catch` is used to avoid handling the error twice. Suppose we call
264
- // `handleError` which re-throws the error internally. The re-thrown error will
265
- // be caught by zone.js which will then get to the `zone.onError.emit()` and the
266
- // `onError` subscriber will call `handleError` again.
267
- try {
268
- this._errorHandler.handleError(error);
269
- }
270
- catch { }
271
- }
272
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: InternalErrorReporter, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
273
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: InternalErrorReporter, providedIn: 'root' }); }
274
- }
275
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: InternalErrorReporter, decorators: [{
276
- type: Injectable,
277
- args: [{ providedIn: 'root' }]
278
- }], ctorParameters: () => [{ type: i0.Injector }] });
279
-
280
220
  /**
281
221
  * Internal Action stream that is emitted anytime an action is dispatched.
282
222
  */
@@ -355,6 +295,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.5", ngImpor
355
295
  type: Optional
356
296
  }] }] });
357
297
 
298
+ const ɵɵunhandledRxjsErrorCallbacks = new WeakMap();
299
+ const existingHandler = config.onUnhandledError;
300
+ config.onUnhandledError = function (error) {
301
+ const unhandledErrorCallback = ɵɵunhandledRxjsErrorCallbacks.get(error);
302
+ if (unhandledErrorCallback) {
303
+ unhandledErrorCallback();
304
+ }
305
+ else if (existingHandler) {
306
+ existingHandler.call(this, error);
307
+ }
308
+ else {
309
+ throw error;
310
+ }
311
+ };
312
+ function executeUnhandledCallback(error) {
313
+ const unhandledErrorCallback = ɵɵunhandledRxjsErrorCallbacks.get(error);
314
+ if (unhandledErrorCallback) {
315
+ unhandledErrorCallback();
316
+ return true;
317
+ }
318
+ return false;
319
+ }
320
+ function assignUnhandledCallback(error, callback) {
321
+ // Since the error can be essentially anything, we must ensure that we only
322
+ // handle objects, as weak maps do not allow any other key type besides objects.
323
+ // The error can also be a string if thrown in the following manner: `throwError('My Error')`.
324
+ if (error !== null && typeof error === 'object') {
325
+ let hasBeenCalled = false;
326
+ ɵɵunhandledRxjsErrorCallbacks.set(error, () => {
327
+ if (!hasBeenCalled) {
328
+ hasBeenCalled = true;
329
+ callback();
330
+ }
331
+ });
332
+ }
333
+ return error;
334
+ }
335
+
336
+ function fallbackSubscriber(ngZone) {
337
+ return (source) => {
338
+ let subscription = source.subscribe({
339
+ error: error => {
340
+ ngZone.runOutsideAngular(() => {
341
+ // This is necessary to schedule a microtask to ensure that synchronous
342
+ // errors are not reported before the real subscriber arrives. If an error
343
+ // is thrown synchronously in any action, it will be reported to the error
344
+ // handler regardless. Since RxJS reports unhandled errors asynchronously,
345
+ // implementing a microtask ensures that we are also safe in this scenario.
346
+ queueMicrotask(() => {
347
+ if (subscription) {
348
+ executeUnhandledCallback(error);
349
+ }
350
+ });
351
+ });
352
+ }
353
+ });
354
+ return new Observable(subscriber => {
355
+ // Now that there is a real subscriber, we can unsubscribe our pro-active subscription
356
+ subscription?.unsubscribe();
357
+ subscription = null;
358
+ return source.subscribe(subscriber);
359
+ });
360
+ };
361
+ }
362
+
358
363
  /**
359
364
  * Internal Action result stream that is emitted when an action is completed.
360
365
  * This is used as a method of returning the action result to the dispatcher
@@ -370,20 +375,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.5", ngImpor
370
375
  args: [{ providedIn: 'root' }]
371
376
  }] });
372
377
  class InternalDispatcher {
373
- constructor(_actions, _actionResults, _pluginManager, _stateStream, _ngxsExecutionStrategy, _internalErrorReporter) {
378
+ constructor(_ngZone, _actions, _actionResults, _pluginManager, _stateStream, _ngxsExecutionStrategy) {
379
+ this._ngZone = _ngZone;
374
380
  this._actions = _actions;
375
381
  this._actionResults = _actionResults;
376
382
  this._pluginManager = _pluginManager;
377
383
  this._stateStream = _stateStream;
378
384
  this._ngxsExecutionStrategy = _ngxsExecutionStrategy;
379
- this._internalErrorReporter = _internalErrorReporter;
380
385
  }
381
386
  /**
382
387
  * Dispatches event(s).
383
388
  */
384
389
  dispatch(actionOrActions) {
385
390
  const result = this._ngxsExecutionStrategy.enter(() => this.dispatchByEvents(actionOrActions));
386
- return result.pipe(ngxsErrorHandler(this._internalErrorReporter, this._ngxsExecutionStrategy));
391
+ return result.pipe(fallbackSubscriber(this._ngZone), leaveNgxs(this._ngxsExecutionStrategy));
387
392
  }
388
393
  dispatchByEvents(actionOrActions) {
389
394
  if (Array.isArray(actionOrActions)) {
@@ -400,7 +405,7 @@ class InternalDispatcher {
400
405
  const type = getActionTypeFromInstance(action);
401
406
  if (!type) {
402
407
  const error = new Error(`This action doesn't have a type property: ${action.constructor.name}`);
403
- return throwError(error);
408
+ return throwError(() => error);
404
409
  }
405
410
  }
406
411
  const prevState = this._stateStream.getValue();
@@ -430,20 +435,20 @@ class InternalDispatcher {
430
435
  // state, as its result is utilized by plugins.
431
436
  return of(this._stateStream.getValue());
432
437
  case "ERRORED" /* ActionStatus.Errored */:
433
- return throwError(ctx.error);
438
+ return throwError(() => ctx.error);
434
439
  default:
435
440
  return EMPTY;
436
441
  }
437
442
  }))
438
443
  .pipe(shareReplay());
439
444
  }
440
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: InternalDispatcher, deps: [{ token: InternalActions }, { token: InternalDispatchedActionResults }, { token: PluginManager }, { token: i1.ɵStateStream }, { token: InternalNgxsExecutionStrategy }, { token: InternalErrorReporter }], target: i0.ɵɵFactoryTarget.Injectable }); }
445
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: InternalDispatcher, deps: [{ token: i0.NgZone }, { token: InternalActions }, { token: InternalDispatchedActionResults }, { token: PluginManager }, { token: i1.ɵStateStream }, { token: InternalNgxsExecutionStrategy }], target: i0.ɵɵFactoryTarget.Injectable }); }
441
446
  /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: InternalDispatcher, providedIn: 'root' }); }
442
447
  }
443
448
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: InternalDispatcher, decorators: [{
444
449
  type: Injectable,
445
450
  args: [{ providedIn: 'root' }]
446
- }], ctorParameters: () => [{ type: InternalActions }, { type: InternalDispatchedActionResults }, { type: PluginManager }, { type: i1.ɵStateStream }, { type: InternalNgxsExecutionStrategy }, { type: InternalErrorReporter }] });
451
+ }], ctorParameters: () => [{ type: i0.NgZone }, { type: InternalActions }, { type: InternalDispatchedActionResults }, { type: PluginManager }, { type: i1.ɵStateStream }, { type: InternalNgxsExecutionStrategy }] });
447
452
 
448
453
  const NG_DEV_MODE$6 = typeof ngDevMode !== 'undefined' && ngDevMode;
449
454
  // The injection token is used to resolve a list of states provided at
@@ -1179,6 +1184,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.5", ngImpor
1179
1184
  args: [NGXS_DEVELOPMENT_OPTIONS]
1180
1185
  }] }] });
1181
1186
 
1187
+ class NgxsUnhandledErrorHandler {
1188
+ constructor() {
1189
+ this._ngZone = inject(NgZone);
1190
+ this._errorHandler = inject(ErrorHandler);
1191
+ }
1192
+ /**
1193
+ * The `_unhandledErrorContext` is left unused internally since we do not
1194
+ * require it for internal operations. However, developers who wish to provide
1195
+ * their own custom error handler may utilize this context information.
1196
+ */
1197
+ handleError(error, _unhandledErrorContext) {
1198
+ // In order to avoid duplicate error handling, it is necessary to leave
1199
+ // the Angular zone to ensure that errors are not caught twice. The `handleError`
1200
+ // method may contain a `throw error` statement, which is used to re-throw the error.
1201
+ // If the error is re-thrown within the Angular zone, it will be caught again by the
1202
+ // Angular zone. By default, `@angular/core` leaves the Angular zone when invoking
1203
+ // `handleError` (see `_callAndReportToErrorHandler`).
1204
+ this._ngZone.runOutsideAngular(() => this._errorHandler.handleError(error));
1205
+ }
1206
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: NgxsUnhandledErrorHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1207
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: NgxsUnhandledErrorHandler, providedIn: 'root' }); }
1208
+ }
1209
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: NgxsUnhandledErrorHandler, decorators: [{
1210
+ type: Injectable,
1211
+ args: [{ providedIn: 'root' }]
1212
+ }] });
1213
+
1182
1214
  const NG_DEV_MODE$2 = typeof ngDevMode !== 'undefined' && ngDevMode;
1183
1215
  function cloneDefaults(defaults) {
1184
1216
  let value = defaults === undefined ? {} : defaults;
@@ -1216,6 +1248,7 @@ class StateFactory {
1216
1248
  this._initialState = _initialState;
1217
1249
  this._actionsSubscription = null;
1218
1250
  this._propGetter = inject(ɵPROP_GETTER);
1251
+ this._ngxsUnhandledErrorHandler = null;
1219
1252
  this._states = [];
1220
1253
  this._statesByName = {};
1221
1254
  this._statePaths = {};
@@ -1334,7 +1367,16 @@ class StateFactory {
1334
1367
  .pipe(filter((ctx) => ctx.status === "DISPATCHED" /* ActionStatus.Dispatched */), mergeMap(ctx => {
1335
1368
  dispatched$.next(ctx);
1336
1369
  const action = ctx.action;
1337
- return this.invokeActions(dispatched$, action).pipe(map(() => ({ action, status: "SUCCESSFUL" /* ActionStatus.Successful */ })), defaultIfEmpty({ action, status: "CANCELED" /* ActionStatus.Canceled */ }), catchError(error => of({ action, status: "ERRORED" /* ActionStatus.Errored */, error })));
1370
+ return this.invokeActions(dispatched$, action).pipe(map(() => ({ action, status: "SUCCESSFUL" /* ActionStatus.Successful */ })), defaultIfEmpty({ action, status: "CANCELED" /* ActionStatus.Canceled */ }), catchError(error => {
1371
+ const ngxsUnhandledErrorHandler = (this._ngxsUnhandledErrorHandler ||=
1372
+ this._injector.get(NgxsUnhandledErrorHandler));
1373
+ const handleableError = assignUnhandledCallback(error, () => ngxsUnhandledErrorHandler.handleError(error, { action }));
1374
+ return of({
1375
+ action,
1376
+ status: "ERRORED" /* ActionStatus.Errored */,
1377
+ error: handleableError
1378
+ });
1379
+ }));
1338
1380
  }))
1339
1381
  .subscribe(ctx => this._actionResults.next(ctx));
1340
1382
  }
@@ -1585,9 +1627,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.5", ngImpor
1585
1627
 
1586
1628
  const NG_DEV_MODE$1 = typeof ngDevMode !== 'undefined' && ngDevMode;
1587
1629
  class LifecycleStateManager {
1588
- constructor(_store, _internalErrorReporter, _internalStateOperations, _stateContextFactory, _appBootstrappedState) {
1630
+ constructor(_store, _internalStateOperations, _stateContextFactory, _appBootstrappedState) {
1589
1631
  this._store = _store;
1590
- this._internalErrorReporter = _internalErrorReporter;
1591
1632
  this._internalStateOperations = _internalStateOperations;
1592
1633
  this._stateContextFactory = _stateContextFactory;
1593
1634
  this._appBootstrappedState = _appBootstrappedState;
@@ -1615,14 +1656,7 @@ class LifecycleStateManager {
1615
1656
  this._internalStateOperations
1616
1657
  .getRootStateOperations()
1617
1658
  .dispatch(action)
1618
- .pipe(filter(() => !!results), tap(() => this._invokeInitOnStates(results.states)), mergeMap(() => this._appBootstrappedState), filter(appBootstrapped => !!appBootstrapped), catchError(error => {
1619
- // The `SafeSubscriber` (which is used by most RxJS operators) re-throws
1620
- // errors asynchronously (`setTimeout(() => { throw error })`). This might
1621
- // break existing user's code or unit tests. We catch the error manually to
1622
- // be backward compatible with the old behavior.
1623
- this._internalErrorReporter.reportErrorSafely(error);
1624
- return EMPTY;
1625
- }), takeUntil(this._destroy$))
1659
+ .pipe(filter(() => !!results), tap(() => this._invokeInitOnStates(results.states)), mergeMap(() => this._appBootstrappedState), filter(appBootstrapped => !!appBootstrapped), takeUntil(this._destroy$))
1626
1660
  .subscribe(() => this._invokeBootstrapOnStates(results.states));
1627
1661
  }
1628
1662
  _invokeInitOnStates(mappedStores) {
@@ -1654,13 +1688,13 @@ class LifecycleStateManager {
1654
1688
  _getStateContext(mappedStore) {
1655
1689
  return this._stateContextFactory.createStateContext(mappedStore);
1656
1690
  }
1657
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: LifecycleStateManager, deps: [{ token: Store }, { token: InternalErrorReporter }, { token: InternalStateOperations }, { token: StateContextFactory }, { token: i1.ɵNgxsAppBootstrappedState }], target: i0.ɵɵFactoryTarget.Injectable }); }
1691
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: LifecycleStateManager, deps: [{ token: Store }, { token: InternalStateOperations }, { token: StateContextFactory }, { token: i1.ɵNgxsAppBootstrappedState }], target: i0.ɵɵFactoryTarget.Injectable }); }
1658
1692
  /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: LifecycleStateManager, providedIn: 'root' }); }
1659
1693
  }
1660
1694
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: LifecycleStateManager, decorators: [{
1661
1695
  type: Injectable,
1662
1696
  args: [{ providedIn: 'root' }]
1663
- }], ctorParameters: () => [{ type: Store }, { type: InternalErrorReporter }, { type: InternalStateOperations }, { type: StateContextFactory }, { type: i1.ɵNgxsAppBootstrappedState }] });
1697
+ }], ctorParameters: () => [{ type: Store }, { type: InternalStateOperations }, { type: StateContextFactory }, { type: i1.ɵNgxsAppBootstrappedState }] });
1664
1698
 
1665
1699
  const NG_DEV_MODE = typeof ngDevMode !== 'undefined' && ngDevMode;
1666
1700
  /**
@@ -2225,5 +2259,5 @@ function withNgxsPlugin(plugin) {
2225
2259
  * Generated bundle index. Do not edit.
2226
2260
  */
2227
2261
 
2228
- export { Action, Actions, NgxsDevelopmentModule, NgxsModule, NgxsSimpleChange, NgxsUnhandledActionsLogger, NoopNgxsExecutionStrategy, Select, Selector, SelectorOptions, State, Store, createModelSelector, createPickSelector, createPropertySelectors, createSelector, ofAction, ofActionCanceled, ofActionCompleted, ofActionDispatched, ofActionErrored, ofActionSuccessful, provideStates, provideStore, withNgxsDevelopmentOptions, withNgxsPlugin, NgxsFeatureModule as ɵNgxsFeatureModule, NgxsRootModule as ɵNgxsRootModule };
2262
+ export { Action, Actions, NgxsDevelopmentModule, NgxsModule, NgxsSimpleChange, NgxsUnhandledActionsLogger, NgxsUnhandledErrorHandler, NoopNgxsExecutionStrategy, Select, Selector, SelectorOptions, State, Store, createModelSelector, createPickSelector, createPropertySelectors, createSelector, ofAction, ofActionCanceled, ofActionCompleted, ofActionDispatched, ofActionErrored, ofActionSuccessful, provideStates, provideStore, withNgxsDevelopmentOptions, withNgxsPlugin, NgxsFeatureModule as ɵNgxsFeatureModule, NgxsRootModule as ɵNgxsRootModule };
2229
2263
  //# sourceMappingURL=ngxs-store.mjs.map