@ngxs/store 18.1.1-dev.master-e935e57 → 18.1.1-dev.master-d6b076c

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,12 +1,12 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, NgZone, PLATFORM_ID, Inject, InjectionToken, inject, INJECTOR, Optional, SkipSelf, ErrorHandler, ɵisPromise as _isPromise, computed, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, NgModule, APP_BOOTSTRAP_LISTENER } from '@angular/core';
3
- import { Observable, config, Subject, of, forkJoin, throwError, EMPTY, from, isObservable, shareReplay as shareReplay$1, map as map$1, catchError as catchError$1, distinctUntilChanged, take as take$1, ReplaySubject } from 'rxjs';
2
+ import { Injectable, NgZone, PLATFORM_ID, Inject, InjectionToken, inject, INJECTOR, ErrorHandler, Injector, ɵisPromise as _isPromise, computed, Optional, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, NgModule, APP_BOOTSTRAP_LISTENER } from '@angular/core';
3
+ import { Subject, filter, Observable, share, config, of, forkJoin, throwError, EMPTY, mergeMap, map as map$1, defaultIfEmpty, catchError, from, isObservable, takeUntil, shareReplay as shareReplay$1, distinctUntilChanged, take as take$1, ReplaySubject } from 'rxjs';
4
4
  import * as i1 from '@ngxs/store/internals';
5
5
  import { ɵwrapObserverCalls as _wrapObserverCalls, ɵ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';
6
6
  export { StateToken } from '@ngxs/store/internals';
7
7
  import { isPlatformServer } from '@angular/common';
8
- import { share, map, shareReplay, filter, take, exhaustMap, mergeMap, defaultIfEmpty, catchError, takeUntil, tap, startWith, pairwise } from 'rxjs/operators';
9
- import { NGXS_PLUGINS, getActionTypeFromInstance, setValue, getValue, InitState, UpdateState } from '@ngxs/store/plugins';
8
+ import { map, shareReplay, filter as filter$1, take, exhaustMap, tap, mergeMap as mergeMap$1, takeUntil as takeUntil$1, startWith, pairwise } from 'rxjs/operators';
9
+ import { NGXS_PLUGINS, getActionTypeFromInstance, InitState, UpdateState, setValue, getValue } from '@ngxs/store/plugins';
10
10
  export { InitState, NGXS_PLUGINS, UpdateState, actionMatcher, getActionTypeFromInstance, getValue, setValue } from '@ngxs/store/plugins';
11
11
  import { isStateOperator } from '@ngxs/store/operators';
12
12
 
@@ -209,16 +209,25 @@ function leaveNgxs(ngxsExecutionStrategy) {
209
209
  * Internal Action stream that is emitted anytime an action is dispatched.
210
210
  */
211
211
  class InternalActions extends _OrderedSubject {
212
+ constructor() {
213
+ super();
214
+ // This subject will be the first to know about the dispatched action, its purpose is for
215
+ // any logic that must be executed before action handlers are invoked (i.e., cancelation).
216
+ this.dispatched$ = new Subject();
217
+ this.pipe(filter(ctx => ctx.status === "DISPATCHED" /* ActionStatus.Dispatched */)).subscribe(ctx => {
218
+ this.dispatched$.next(ctx);
219
+ });
220
+ }
212
221
  ngOnDestroy() {
213
222
  this.complete();
214
223
  }
215
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: InternalActions, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
224
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: InternalActions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
216
225
  /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: InternalActions, providedIn: 'root' }); }
217
226
  }
218
227
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: InternalActions, decorators: [{
219
228
  type: Injectable,
220
229
  args: [{ providedIn: 'root' }]
221
- }] });
230
+ }], ctorParameters: () => [] });
222
231
  /**
223
232
  * Action stream that is emitted anytime an action is dispatched.
224
233
  *
@@ -250,38 +259,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImpor
250
259
  }], ctorParameters: () => [{ type: InternalActions }, { type: InternalNgxsExecutionStrategy }] });
251
260
 
252
261
  class PluginManager {
253
- constructor(_parentManager, _pluginHandlers) {
254
- this._parentManager = _parentManager;
255
- this._pluginHandlers = _pluginHandlers;
262
+ constructor() {
256
263
  this.plugins = [];
264
+ this._parentManager = inject(PluginManager, {
265
+ optional: true,
266
+ skipSelf: true
267
+ });
268
+ this._pluginHandlers = inject(NGXS_PLUGINS, {
269
+ optional: true
270
+ });
257
271
  this.registerHandlers();
258
272
  }
259
- get rootPlugins() {
260
- return (this._parentManager && this._parentManager.plugins) || this.plugins;
273
+ get _rootPlugins() {
274
+ return this._parentManager?.plugins || this.plugins;
261
275
  }
262
276
  registerHandlers() {
263
277
  const pluginHandlers = this.getPluginHandlers();
264
- this.rootPlugins.push(...pluginHandlers);
278
+ this._rootPlugins.push(...pluginHandlers);
265
279
  }
266
280
  getPluginHandlers() {
267
281
  const handlers = this._pluginHandlers || [];
268
282
  return handlers.map((plugin) => (plugin.handle ? plugin.handle.bind(plugin) : plugin));
269
283
  }
270
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: PluginManager, deps: [{ token: PluginManager, optional: true, skipSelf: true }, { token: NGXS_PLUGINS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
284
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: PluginManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
271
285
  /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: PluginManager }); }
272
286
  }
273
287
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: PluginManager, decorators: [{
274
288
  type: Injectable
275
- }], ctorParameters: () => [{ type: PluginManager, decorators: [{
276
- type: Optional
277
- }, {
278
- type: SkipSelf
279
- }] }, { type: undefined, decorators: [{
280
- type: Inject,
281
- args: [NGXS_PLUGINS]
282
- }, {
283
- type: Optional
284
- }] }] });
289
+ }], ctorParameters: () => [] });
285
290
 
286
291
  const ɵɵunhandledRxjsErrorCallbacks = new WeakMap();
287
292
  const existingHandler = config.onUnhandledError;
@@ -412,7 +417,7 @@ class InternalDispatcher {
412
417
  ])(prevState, action).pipe(shareReplay());
413
418
  }
414
419
  getActionResultStream(action) {
415
- return this._actionResults.pipe(filter((ctx) => ctx.action === action && ctx.status !== "DISPATCHED" /* ActionStatus.Dispatched */), take(1), shareReplay());
420
+ return this._actionResults.pipe(filter$1((ctx) => ctx.action === action && ctx.status !== "DISPATCHED" /* ActionStatus.Dispatched */), take(1), shareReplay());
416
421
  }
417
422
  createDispatchObservable(actionResult$) {
418
423
  return actionResult$
@@ -893,190 +898,37 @@ function topologicalSort(graph) {
893
898
  return sorted.reverse();
894
899
  }
895
900
 
896
- /**
897
- * RxJS operator for selecting out specific actions.
898
- *
899
- * This will grab actions that have just been dispatched as well as actions that have completed
900
- */
901
- function ofAction(...allowedTypes) {
902
- return ofActionOperator(allowedTypes);
903
- }
904
- /**
905
- * RxJS operator for selecting out specific actions.
906
- *
907
- * This will ONLY grab actions that have just been dispatched
908
- */
909
- function ofActionDispatched(...allowedTypes) {
910
- return ofActionOperator(allowedTypes, ["DISPATCHED" /* ActionStatus.Dispatched */]);
911
- }
912
- /**
913
- * RxJS operator for selecting out specific actions.
914
- *
915
- * This will ONLY grab actions that have just been successfully completed
916
- */
917
- function ofActionSuccessful(...allowedTypes) {
918
- return ofActionOperator(allowedTypes, ["SUCCESSFUL" /* ActionStatus.Successful */]);
919
- }
920
- /**
921
- * RxJS operator for selecting out specific actions.
922
- *
923
- * This will ONLY grab actions that have just been canceled
924
- */
925
- function ofActionCanceled(...allowedTypes) {
926
- return ofActionOperator(allowedTypes, ["CANCELED" /* ActionStatus.Canceled */]);
927
- }
928
- /**
929
- * RxJS operator for selecting out specific actions.
930
- *
931
- * This will ONLY grab actions that have just been completed
932
- */
933
- function ofActionCompleted(...allowedTypes) {
934
- const allowedStatuses = [
935
- "SUCCESSFUL" /* ActionStatus.Successful */,
936
- "CANCELED" /* ActionStatus.Canceled */,
937
- "ERRORED" /* ActionStatus.Errored */
938
- ];
939
- return ofActionOperator(allowedTypes, allowedStatuses, mapActionResult);
940
- }
941
- /**
942
- * RxJS operator for selecting out specific actions.
943
- *
944
- * This will ONLY grab actions that have just thrown an error
945
- */
946
- function ofActionErrored(...allowedTypes) {
947
- return ofActionOperator(allowedTypes, ["ERRORED" /* ActionStatus.Errored */], mapActionResult);
948
- }
949
- function ofActionOperator(allowedTypes, statuses,
950
- // This could have been written as
951
- // `OperatorFunction<ActionContext, ActionCompletion | any>`, as it maps
952
- // either to `ctx.action` or to `ActionCompletion`. However,
953
- // `ActionCompletion | any` defaults to `any`, rendering the union
954
- // type meaningless.
955
- mapOperator = mapAction) {
956
- const allowedMap = createAllowedActionTypesMap(allowedTypes);
957
- const allowedStatusMap = statuses && createAllowedStatusesMap(statuses);
958
- return function (o) {
959
- return o.pipe(filterStatus(allowedMap, allowedStatusMap), mapOperator());
960
- };
961
- }
962
- function filterStatus(allowedTypes, allowedStatuses) {
963
- return filter((ctx) => {
964
- const actionType = getActionTypeFromInstance(ctx.action);
965
- const typeMatch = allowedTypes[actionType];
966
- const statusMatch = allowedStatuses ? allowedStatuses[ctx.status] : true;
967
- return typeMatch && statusMatch;
968
- });
969
- }
970
- function mapActionResult() {
971
- return map(({ action, status, error }) => {
972
- return {
973
- action,
974
- result: {
975
- successful: "SUCCESSFUL" /* ActionStatus.Successful */ === status,
976
- canceled: "CANCELED" /* ActionStatus.Canceled */ === status,
977
- error
978
- }
979
- };
980
- });
981
- }
982
- function mapAction() {
983
- return map((ctx) => ctx.action);
984
- }
985
- function createAllowedActionTypesMap(types) {
986
- return types.reduce((filterMap, klass) => {
987
- filterMap[getActionTypeFromInstance(klass)] = true;
988
- return filterMap;
989
- }, {});
990
- }
991
- function createAllowedStatusesMap(statuses) {
992
- return statuses.reduce((filterMap, status) => {
993
- filterMap[status] = true;
994
- return filterMap;
995
- }, {});
996
- }
997
-
998
- function simplePatch(value) {
999
- return (existingState) => {
1000
- if (typeof ngDevMode !== 'undefined' && ngDevMode) {
1001
- if (Array.isArray(value)) {
1002
- throwPatchingArrayError();
1003
- }
1004
- else if (typeof value !== 'object') {
1005
- throwPatchingPrimitiveError();
1006
- }
1007
- }
1008
- const newState = { ...existingState };
1009
- for (const key in value) {
1010
- // deep clone for patch compatibility
1011
- newState[key] = value[key];
1012
- }
1013
- return newState;
1014
- };
1015
- }
1016
-
1017
- /**
1018
- * State Context factory class
1019
- * @ignore
1020
- */
1021
- class StateContextFactory {
1022
- constructor(_internalStateOperations) {
1023
- this._internalStateOperations = _internalStateOperations;
901
+ class NgxsActionRegistry {
902
+ constructor() {
903
+ // Instead of going over the states list every time an action is dispatched,
904
+ // we are constructing a map of action types to lists of action metadata.
905
+ // If the `@@Init` action is handled in two different states, the action
906
+ // metadata list will contain two objects that have the state `instance` and
907
+ // method names to be used as action handlers (decorated with `@Action(InitState)`).
908
+ this._actionTypeToHandlersMap = new Map();
1024
909
  }
1025
- /**
1026
- * Create the state context
1027
- */
1028
- createStateContext(path) {
1029
- const root = this._internalStateOperations.getRootStateOperations();
1030
- return {
1031
- getState() {
1032
- const currentAppState = root.getState();
1033
- return getState(currentAppState, path);
1034
- },
1035
- patchState(val) {
1036
- const currentAppState = root.getState();
1037
- const patchOperator = simplePatch(val);
1038
- setStateFromOperator(root, currentAppState, patchOperator, path);
1039
- },
1040
- setState(val) {
1041
- const currentAppState = root.getState();
1042
- if (isStateOperator(val)) {
1043
- setStateFromOperator(root, currentAppState, val, path);
1044
- }
1045
- else {
1046
- setStateValue(root, currentAppState, val, path);
1047
- }
1048
- },
1049
- dispatch(actions) {
1050
- return root.dispatch(actions);
1051
- }
910
+ ngOnDestroy() {
911
+ this._actionTypeToHandlersMap.clear();
912
+ }
913
+ get(type) {
914
+ return this._actionTypeToHandlersMap.get(type);
915
+ }
916
+ register(type, handler) {
917
+ const handlers = this._actionTypeToHandlersMap.get(type) ?? new Set();
918
+ handlers.add(handler);
919
+ this._actionTypeToHandlersMap.set(type, handlers);
920
+ return () => {
921
+ const handlers = this._actionTypeToHandlersMap.get(type);
922
+ handlers.delete(handler);
1052
923
  };
1053
924
  }
1054
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateContextFactory, deps: [{ token: InternalStateOperations }], target: i0.ɵɵFactoryTarget.Injectable }); }
1055
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateContextFactory, providedIn: 'root' }); }
925
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: NgxsActionRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
926
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: NgxsActionRegistry, providedIn: 'root' }); }
1056
927
  }
1057
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateContextFactory, decorators: [{
928
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: NgxsActionRegistry, decorators: [{
1058
929
  type: Injectable,
1059
930
  args: [{ providedIn: 'root' }]
1060
- }], ctorParameters: () => [{ type: InternalStateOperations }] });
1061
- function setStateValue(root, currentAppState, newValue, path) {
1062
- const newAppState = setValue(currentAppState, path, newValue);
1063
- root.setState(newAppState);
1064
- return newAppState;
1065
- // In doing this refactoring I noticed that there is a 'bug' where the
1066
- // application state is returned instead of this state slice.
1067
- // This has worked this way since the beginning see:
1068
- // https://github.com/ngxs/store/blame/324c667b4b7debd8eb979006c67ca0ae347d88cd/src/state-factory.ts
1069
- // This needs to be fixed, but is a 'breaking' change.
1070
- // I will do this fix in a subsequent PR and we can decide how to handle it.
1071
- }
1072
- function setStateFromOperator(root, currentAppState, stateOperator, path) {
1073
- const local = getState(currentAppState, path);
1074
- const newValue = stateOperator(local);
1075
- return setStateValue(root, currentAppState, newValue, path);
1076
- }
1077
- function getState(currentAppState, path) {
1078
- return getValue(currentAppState, path);
1079
- }
931
+ }] });
1080
932
 
1081
933
  const stateNameRegex = new RegExp('^[a-zA-Z0-9_]+$');
1082
934
  function ensureStateNameIsValid(name) {
@@ -1199,6 +1051,191 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImpor
1199
1051
  args: [{ providedIn: 'root' }]
1200
1052
  }] });
1201
1053
 
1054
+ function simplePatch(value) {
1055
+ return (existingState) => {
1056
+ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
1057
+ if (Array.isArray(value)) {
1058
+ throwPatchingArrayError();
1059
+ }
1060
+ else if (typeof value !== 'object') {
1061
+ throwPatchingPrimitiveError();
1062
+ }
1063
+ }
1064
+ const newState = { ...existingState };
1065
+ for (const key in value) {
1066
+ // deep clone for patch compatibility
1067
+ newState[key] = value[key];
1068
+ }
1069
+ return newState;
1070
+ };
1071
+ }
1072
+
1073
+ /**
1074
+ * State Context factory class
1075
+ * @ignore
1076
+ */
1077
+ class StateContextFactory {
1078
+ constructor(_internalStateOperations) {
1079
+ this._internalStateOperations = _internalStateOperations;
1080
+ }
1081
+ /**
1082
+ * Create the state context
1083
+ */
1084
+ createStateContext(path) {
1085
+ const root = this._internalStateOperations.getRootStateOperations();
1086
+ return {
1087
+ getState() {
1088
+ const currentAppState = root.getState();
1089
+ return getState(currentAppState, path);
1090
+ },
1091
+ patchState(val) {
1092
+ const currentAppState = root.getState();
1093
+ const patchOperator = simplePatch(val);
1094
+ setStateFromOperator(root, currentAppState, patchOperator, path);
1095
+ },
1096
+ setState(val) {
1097
+ const currentAppState = root.getState();
1098
+ if (isStateOperator(val)) {
1099
+ setStateFromOperator(root, currentAppState, val, path);
1100
+ }
1101
+ else {
1102
+ setStateValue(root, currentAppState, val, path);
1103
+ }
1104
+ },
1105
+ dispatch(actions) {
1106
+ return root.dispatch(actions);
1107
+ }
1108
+ };
1109
+ }
1110
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateContextFactory, deps: [{ token: InternalStateOperations }], target: i0.ɵɵFactoryTarget.Injectable }); }
1111
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateContextFactory, providedIn: 'root' }); }
1112
+ }
1113
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateContextFactory, decorators: [{
1114
+ type: Injectable,
1115
+ args: [{ providedIn: 'root' }]
1116
+ }], ctorParameters: () => [{ type: InternalStateOperations }] });
1117
+ function setStateValue(root, currentAppState, newValue, path) {
1118
+ const newAppState = setValue(currentAppState, path, newValue);
1119
+ root.setState(newAppState);
1120
+ return newAppState;
1121
+ // In doing this refactoring I noticed that there is a 'bug' where the
1122
+ // application state is returned instead of this state slice.
1123
+ // This has worked this way since the beginning see:
1124
+ // https://github.com/ngxs/store/blame/324c667b4b7debd8eb979006c67ca0ae347d88cd/src/state-factory.ts
1125
+ // This needs to be fixed, but is a 'breaking' change.
1126
+ // I will do this fix in a subsequent PR and we can decide how to handle it.
1127
+ }
1128
+ function setStateFromOperator(root, currentAppState, stateOperator, path) {
1129
+ const local = getState(currentAppState, path);
1130
+ const newValue = stateOperator(local);
1131
+ return setStateValue(root, currentAppState, newValue, path);
1132
+ }
1133
+ function getState(currentAppState, path) {
1134
+ return getValue(currentAppState, path);
1135
+ }
1136
+
1137
+ /**
1138
+ * RxJS operator for selecting out specific actions.
1139
+ *
1140
+ * This will grab actions that have just been dispatched as well as actions that have completed
1141
+ */
1142
+ function ofAction(...allowedTypes) {
1143
+ return ofActionOperator(allowedTypes);
1144
+ }
1145
+ /**
1146
+ * RxJS operator for selecting out specific actions.
1147
+ *
1148
+ * This will ONLY grab actions that have just been dispatched
1149
+ */
1150
+ function ofActionDispatched(...allowedTypes) {
1151
+ return ofActionOperator(allowedTypes, ["DISPATCHED" /* ActionStatus.Dispatched */]);
1152
+ }
1153
+ /**
1154
+ * RxJS operator for selecting out specific actions.
1155
+ *
1156
+ * This will ONLY grab actions that have just been successfully completed
1157
+ */
1158
+ function ofActionSuccessful(...allowedTypes) {
1159
+ return ofActionOperator(allowedTypes, ["SUCCESSFUL" /* ActionStatus.Successful */]);
1160
+ }
1161
+ /**
1162
+ * RxJS operator for selecting out specific actions.
1163
+ *
1164
+ * This will ONLY grab actions that have just been canceled
1165
+ */
1166
+ function ofActionCanceled(...allowedTypes) {
1167
+ return ofActionOperator(allowedTypes, ["CANCELED" /* ActionStatus.Canceled */]);
1168
+ }
1169
+ /**
1170
+ * RxJS operator for selecting out specific actions.
1171
+ *
1172
+ * This will ONLY grab actions that have just been completed
1173
+ */
1174
+ function ofActionCompleted(...allowedTypes) {
1175
+ const allowedStatuses = [
1176
+ "SUCCESSFUL" /* ActionStatus.Successful */,
1177
+ "CANCELED" /* ActionStatus.Canceled */,
1178
+ "ERRORED" /* ActionStatus.Errored */
1179
+ ];
1180
+ return ofActionOperator(allowedTypes, allowedStatuses, mapActionResult);
1181
+ }
1182
+ /**
1183
+ * RxJS operator for selecting out specific actions.
1184
+ *
1185
+ * This will ONLY grab actions that have just thrown an error
1186
+ */
1187
+ function ofActionErrored(...allowedTypes) {
1188
+ return ofActionOperator(allowedTypes, ["ERRORED" /* ActionStatus.Errored */], mapActionResult);
1189
+ }
1190
+ function ofActionOperator(allowedTypes, statuses,
1191
+ // This could have been written as
1192
+ // `OperatorFunction<ActionContext, ActionCompletion | any>`, as it maps
1193
+ // either to `ctx.action` or to `ActionCompletion`. However,
1194
+ // `ActionCompletion | any` defaults to `any`, rendering the union
1195
+ // type meaningless.
1196
+ mapOperator = mapAction) {
1197
+ const allowedMap = createAllowedActionTypesMap(allowedTypes);
1198
+ const allowedStatusMap = statuses && createAllowedStatusesMap(statuses);
1199
+ return function (o) {
1200
+ return o.pipe(filterStatus(allowedMap, allowedStatusMap), mapOperator());
1201
+ };
1202
+ }
1203
+ function filterStatus(allowedTypes, allowedStatuses) {
1204
+ return filter$1((ctx) => {
1205
+ const actionType = getActionTypeFromInstance(ctx.action);
1206
+ const typeMatch = allowedTypes[actionType];
1207
+ const statusMatch = allowedStatuses ? allowedStatuses[ctx.status] : true;
1208
+ return typeMatch && statusMatch;
1209
+ });
1210
+ }
1211
+ function mapActionResult() {
1212
+ return map(({ action, status, error }) => {
1213
+ return {
1214
+ action,
1215
+ result: {
1216
+ successful: "SUCCESSFUL" /* ActionStatus.Successful */ === status,
1217
+ canceled: "CANCELED" /* ActionStatus.Canceled */ === status,
1218
+ error
1219
+ }
1220
+ };
1221
+ });
1222
+ }
1223
+ function mapAction() {
1224
+ return map((ctx) => ctx.action);
1225
+ }
1226
+ function createAllowedActionTypesMap(types) {
1227
+ return types.reduce((filterMap, klass) => {
1228
+ filterMap[getActionTypeFromInstance(klass)] = true;
1229
+ return filterMap;
1230
+ }, {});
1231
+ }
1232
+ function createAllowedStatusesMap(statuses) {
1233
+ return statuses.reduce((filterMap, status) => {
1234
+ filterMap[status] = true;
1235
+ return filterMap;
1236
+ }, {});
1237
+ }
1238
+
1202
1239
  const NG_DEV_MODE$3 = typeof ngDevMode !== 'undefined' && ngDevMode;
1203
1240
  function cloneDefaults(defaults) {
1204
1241
  let value = defaults === undefined ? {} : defaults;
@@ -1226,23 +1263,18 @@ function cloneDefaults(defaults) {
1226
1263
  * @ignore
1227
1264
  */
1228
1265
  class StateFactory {
1229
- constructor(_injector, _config, _parentFactory, _actions, _actionResults, _stateContextFactory, _initialState) {
1230
- this._injector = _injector;
1231
- this._config = _config;
1232
- this._parentFactory = _parentFactory;
1233
- this._actions = _actions;
1234
- this._actionResults = _actionResults;
1235
- this._stateContextFactory = _stateContextFactory;
1236
- this._initialState = _initialState;
1237
- this._actionsSubscription = null;
1266
+ constructor() {
1267
+ this._injector = inject(Injector);
1268
+ this._config = inject(NgxsConfig);
1269
+ this._parentFactory = inject(StateFactory, { optional: true, skipSelf: true });
1270
+ this._stateContextFactory = inject(StateContextFactory);
1271
+ this._actions = inject(InternalActions);
1272
+ this._actionResults = inject(InternalDispatchedActionResults);
1273
+ this._initialState = inject(_INITIAL_STATE_TOKEN, { optional: true });
1274
+ this._actionRegistry = inject(NgxsActionRegistry);
1238
1275
  this._propGetter = inject(ɵPROP_GETTER);
1276
+ this._actionsSubscription = null;
1239
1277
  this._ngxsUnhandledErrorHandler = null;
1240
- // Instead of going over the states list every time an action is dispatched,
1241
- // we are constructing a map of action types to lists of action metadata.
1242
- // If the `@@Init` action is handled in two different states, the action
1243
- // metadata list will contain two objects that have the state `instance` and
1244
- // method names to be used as action handlers (decorated with `@Action(InitState)`).
1245
- this._actionTypeToMetasMap = new Map();
1246
1278
  this._states = [];
1247
1279
  this._statesByName = {};
1248
1280
  this._statePaths = {};
@@ -1283,11 +1315,6 @@ class StateFactory {
1283
1315
  return context;
1284
1316
  });
1285
1317
  }
1286
- get actionTypeToMetasMap() {
1287
- return this._parentFactory
1288
- ? this._parentFactory.actionTypeToMetasMap
1289
- : this._actionTypeToMetasMap;
1290
- }
1291
1318
  get states() {
1292
1319
  return this._parentFactory ? this._parentFactory.states : this._states;
1293
1320
  }
@@ -1362,12 +1389,10 @@ class StateFactory {
1362
1389
  if (this._parentFactory || this._actionsSubscription !== null) {
1363
1390
  return;
1364
1391
  }
1365
- const dispatched$ = new Subject();
1366
1392
  this._actionsSubscription = this._actions
1367
1393
  .pipe(filter((ctx) => ctx.status === "DISPATCHED" /* ActionStatus.Dispatched */), mergeMap(ctx => {
1368
- dispatched$.next(ctx);
1369
1394
  const action = ctx.action;
1370
- return this.invokeActions(dispatched$, action).pipe(map(() => ({ action, status: "SUCCESSFUL" /* ActionStatus.Successful */ })), defaultIfEmpty({ action, status: "CANCELED" /* ActionStatus.Canceled */ }), catchError(error => {
1395
+ return this.invokeActions(action).pipe(map$1(() => ({ action, status: "SUCCESSFUL" /* ActionStatus.Successful */ })), defaultIfEmpty({ action, status: "CANCELED" /* ActionStatus.Canceled */ }), catchError(error => {
1371
1396
  const ngxsUnhandledErrorHandler = (this._ngxsUnhandledErrorHandler ||=
1372
1397
  this._injector.get(NgxsUnhandledErrorHandler));
1373
1398
  const handleableError = assignUnhandledCallback(error, () => ngxsUnhandledErrorHandler.handleError(error, { action }));
@@ -1383,53 +1408,18 @@ class StateFactory {
1383
1408
  /**
1384
1409
  * Invoke actions on the states.
1385
1410
  */
1386
- invokeActions(dispatched$, action) {
1411
+ invokeActions(action) {
1387
1412
  const type = getActionTypeFromInstance(action);
1388
1413
  const results = [];
1389
1414
  // Determines whether the dispatched action has been handled, this is assigned
1390
1415
  // to `true` within the below `for` loop if any `actionMetas` has been found.
1391
1416
  let actionHasBeenHandled = false;
1392
- const actionMetas = this.actionTypeToMetasMap.get(type);
1393
- if (actionMetas) {
1394
- for (const actionMeta of actionMetas) {
1395
- const stateContext = this._stateContextFactory.createStateContext(actionMeta.path);
1417
+ const actionHandlers = this._actionRegistry.get(type);
1418
+ if (actionHandlers) {
1419
+ for (const actionHandler of actionHandlers) {
1396
1420
  let result;
1397
1421
  try {
1398
- result = actionMeta.instance[actionMeta.fn](stateContext, action);
1399
- // We need to use `isPromise` instead of checking whether
1400
- // `result instanceof Promise`. In zone.js patched environments, `global.Promise`
1401
- // is the `ZoneAwarePromise`. Some APIs, which are likely not patched by zone.js
1402
- // for certain reasons, might not work with `instanceof`. For instance, the dynamic
1403
- // import returns a native promise (not a `ZoneAwarePromise`), causing this check to
1404
- // be falsy.
1405
- if (_isPromise(result)) {
1406
- result = from(result);
1407
- }
1408
- if (isObservable(result)) {
1409
- result = result.pipe(mergeMap((value) => {
1410
- if (_isPromise(value)) {
1411
- return from(value);
1412
- }
1413
- if (isObservable(value)) {
1414
- return value;
1415
- }
1416
- return of(value);
1417
- }),
1418
- // If this observable has completed without emitting any values,
1419
- // we wouldn't want to complete the entire chain of actions.
1420
- // If any observable completes, then the action will be canceled.
1421
- // For instance, if any action handler had a statement like
1422
- // `handler(ctx) { return EMPTY; }`, then the action would be canceled.
1423
- // See https://github.com/ngxs/store/issues/1568
1424
- defaultIfEmpty({}));
1425
- if (actionMeta.options.cancelUncompleted) {
1426
- // todo: ofActionDispatched should be used with action class
1427
- result = result.pipe(takeUntil(dispatched$.pipe(ofActionDispatched(action))));
1428
- }
1429
- }
1430
- else {
1431
- result = of({}).pipe(shareReplay());
1432
- }
1422
+ result = actionHandler(action);
1433
1423
  }
1434
1424
  catch (e) {
1435
1425
  result = throwError(e);
@@ -1482,42 +1472,60 @@ class StateFactory {
1482
1472
  return this.statesByName[name] && valueIsBootstrappedInInitialState;
1483
1473
  }
1484
1474
  hydrateActionMetasMap({ path, actions, instance }) {
1485
- const actionTypeToMetasMap = this.actionTypeToMetasMap;
1475
+ const { dispatched$ } = this._actions;
1486
1476
  for (const actionType of Object.keys(actions)) {
1487
- // Initialize the map entry if it does not already exist for that
1488
- // action type. Note that action types may overlap between states,
1489
- // as the same action can be handled by different states.
1490
- if (!actionTypeToMetasMap.has(actionType)) {
1491
- actionTypeToMetasMap.set(actionType, []);
1477
+ const actionHandlers = actions[actionType].map(actionMeta => {
1478
+ // action: Instance<ActionType>
1479
+ return (action) => {
1480
+ const stateContext = this._stateContextFactory.createStateContext(path);
1481
+ let result = instance[actionMeta.fn](stateContext, action);
1482
+ // We need to use `isPromise` instead of checking whether
1483
+ // `result instanceof Promise`. In zone.js patched environments, `global.Promise`
1484
+ // is the `ZoneAwarePromise`. Some APIs, which are likely not patched by zone.js
1485
+ // for certain reasons, might not work with `instanceof`. For instance, the dynamic
1486
+ // import returns a native promise (not a `ZoneAwarePromise`), causing this check to
1487
+ // be falsy.
1488
+ if (_isPromise(result)) {
1489
+ result = from(result);
1490
+ }
1491
+ if (isObservable(result)) {
1492
+ result = result.pipe(mergeMap((value) => {
1493
+ if (_isPromise(value)) {
1494
+ return from(value);
1495
+ }
1496
+ if (isObservable(value)) {
1497
+ return value;
1498
+ }
1499
+ return of(value);
1500
+ }),
1501
+ // If this observable has completed without emitting any values,
1502
+ // we wouldn't want to complete the entire chain of actions.
1503
+ // If any observable completes, then the action will be canceled.
1504
+ // For instance, if any action handler had a statement like
1505
+ // `handler(ctx) { return EMPTY; }`, then the action would be canceled.
1506
+ // See https://github.com/ngxs/store/issues/1568
1507
+ defaultIfEmpty({}));
1508
+ if (actionMeta.options.cancelUncompleted) {
1509
+ result = result.pipe(takeUntil(dispatched$.pipe(ofActionDispatched(action))));
1510
+ }
1511
+ }
1512
+ else {
1513
+ result = of({}).pipe(shareReplay$1());
1514
+ }
1515
+ return result;
1516
+ };
1517
+ });
1518
+ for (const actionHandler of actionHandlers) {
1519
+ this._actionRegistry.register(actionType, actionHandler);
1492
1520
  }
1493
- const extendedActionMetas = actionTypeToMetasMap.get(actionType);
1494
- extendedActionMetas.push(
1495
- // This involves combining each individual action metadata with
1496
- // the state instance and the path—essentially everything needed
1497
- // to invoke an action. This eliminates the need to loop over states
1498
- // every time an action is dispatched.
1499
- ...actions[actionType].map(actionMeta => ({
1500
- ...actionMeta,
1501
- path,
1502
- instance
1503
- })));
1504
1521
  }
1505
1522
  }
1506
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateFactory, deps: [{ token: i0.Injector }, { token: NgxsConfig }, { token: StateFactory, optional: true, skipSelf: true }, { token: InternalActions }, { token: InternalDispatchedActionResults }, { token: StateContextFactory }, { token: _INITIAL_STATE_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
1523
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1507
1524
  /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateFactory }); }
1508
1525
  }
1509
1526
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateFactory, decorators: [{
1510
1527
  type: Injectable
1511
- }], ctorParameters: () => [{ type: i0.Injector }, { type: NgxsConfig }, { type: StateFactory, decorators: [{
1512
- type: Optional
1513
- }, {
1514
- type: SkipSelf
1515
- }] }, { type: InternalActions }, { type: InternalDispatchedActionResults }, { type: StateContextFactory }, { type: undefined, decorators: [{
1516
- type: Optional
1517
- }, {
1518
- type: Inject,
1519
- args: [_INITIAL_STATE_TOKEN]
1520
- }] }] });
1528
+ }] });
1521
1529
 
1522
1530
  class Store {
1523
1531
  constructor(_stateStream, _internalStateOperations, _config, _internalExecutionStrategy, _stateFactory, initialStateValue) {
@@ -1545,7 +1553,7 @@ class Store {
1545
1553
  */
1546
1554
  select(selector) {
1547
1555
  const selectorFn = this.getStoreBoundSelectorFn(selector);
1548
- return this._selectableStateStream.pipe(map$1(selectorFn), catchError$1((error) => {
1556
+ return this._selectableStateStream.pipe(map$1(selectorFn), catchError((error) => {
1549
1557
  // if error is TypeError we swallow it to prevent usual errors with property access
1550
1558
  if (this._config.selectorOptions.suppressErrors && error instanceof TypeError) {
1551
1559
  return of(undefined);
@@ -1705,7 +1713,7 @@ class LifecycleStateManager {
1705
1713
  this._internalStateOperations
1706
1714
  .getRootStateOperations()
1707
1715
  .dispatch(action)
1708
- .pipe(filter(() => !!results), tap(() => this._invokeInitOnStates(results.states)), mergeMap(() => this._appBootstrappedState), filter(appBootstrapped => !!appBootstrapped), takeUntil(this._destroy$))
1716
+ .pipe(filter$1(() => !!results), tap(() => this._invokeInitOnStates(results.states)), mergeMap$1(() => this._appBootstrappedState), filter$1(appBootstrapped => !!appBootstrapped), takeUntil$1(this._destroy$))
1709
1717
  .subscribe(() => this._invokeBootstrapOnStates(results.states));
1710
1718
  }
1711
1719
  _invokeInitOnStates(mappedStores) {
@@ -1714,7 +1722,7 @@ class LifecycleStateManager {
1714
1722
  if (instance.ngxsOnChanges) {
1715
1723
  this._store
1716
1724
  .select(state => getValue(state, mappedStore.path))
1717
- .pipe(startWith(undefined), pairwise(), takeUntil(this._destroy$))
1725
+ .pipe(startWith(undefined), pairwise(), takeUntil$1(this._destroy$))
1718
1726
  .subscribe(([previousValue, currentValue]) => {
1719
1727
  const change = new NgxsSimpleChange(previousValue, currentValue, !mappedStore.isInitialised);
1720
1728
  instance.ngxsOnChanges(change);
@@ -2323,7 +2331,13 @@ function provideStates(states, ...features) {
2323
2331
  * ```
2324
2332
  */
2325
2333
  function withNgxsPlugin(plugin) {
2326
- return makeEnvironmentProviders([{ provide: NGXS_PLUGINS, useClass: plugin, multi: true }]);
2334
+ return makeEnvironmentProviders([
2335
+ { provide: NGXS_PLUGINS, useClass: plugin, multi: true },
2336
+ // We should inject the `PluginManager` to retrieve `NGXS_PLUGINS` and
2337
+ // register those plugins. The plugin can be added from inside the child
2338
+ // route, so the plugin manager should be re-injected.
2339
+ { provide: ENVIRONMENT_INITIALIZER, useValue: () => inject(PluginManager), multi: true }
2340
+ ]);
2327
2341
  }
2328
2342
 
2329
2343
  /**