@ngxs/store 18.1.1 → 18.1.2-dev.master-cbc269d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/esm2022/internals/memoize.mjs +14 -3
- package/esm2022/internals/testing/index.mjs +2 -2
- package/esm2022/internals/testing/ngxs.setup.mjs +4 -3
- package/esm2022/internals/testing/skip-console-logging.mjs +17 -7
- package/esm2022/src/actions/action-registry.mjs +34 -0
- package/esm2022/src/actions-stream.mjs +13 -5
- package/esm2022/src/internal/lifecycle-state-manager.mjs +2 -2
- package/esm2022/src/internal/state-context-factory.mjs +6 -6
- package/esm2022/src/internal/state-factory.mjs +82 -85
- package/esm2022/src/plugin-manager.mjs +15 -19
- package/esm2022/src/selectors/selector-checks.util.mjs +29 -4
- package/esm2022/src/standalone-features/plugin.mjs +10 -3
- package/fesm2022/ngxs-store-internals-testing.mjs +40 -30
- package/fesm2022/ngxs-store-internals-testing.mjs.map +1 -1
- package/fesm2022/ngxs-store-internals.mjs +13 -2
- package/fesm2022/ngxs-store-internals.mjs.map +1 -1
- package/fesm2022/ngxs-store.mjs +353 -285
- package/fesm2022/ngxs-store.mjs.map +1 -1
- package/internals/testing/index.d.ts +1 -1
- package/internals/testing/skip-console-logging.d.ts +4 -1
- package/package.json +8 -8
- package/schematics/src/utils/versions.json +1 -1
- package/src/actions/action-registry.d.ts +12 -0
- package/src/actions-stream.d.ts +3 -1
- package/src/internal/state-context-factory.d.ts +1 -2
- package/src/internal/state-factory.d.ts +13 -17
- package/src/plugin-manager.d.ts +7 -7
package/fesm2022/ngxs-store.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, NgZone, PLATFORM_ID, Inject, InjectionToken, inject, INJECTOR,
|
|
3
|
-
import { Observable,
|
|
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 {
|
|
9
|
-
import { NGXS_PLUGINS, getActionTypeFromInstance,
|
|
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:
|
|
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(
|
|
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
|
|
260
|
-
return
|
|
273
|
+
get _rootPlugins() {
|
|
274
|
+
return this._parentManager?.plugins || this.plugins;
|
|
261
275
|
}
|
|
262
276
|
registerHandlers() {
|
|
263
277
|
const pluginHandlers = this.getPluginHandlers();
|
|
264
|
-
this.
|
|
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: [
|
|
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: () => [
|
|
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
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
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
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
setStateFromOperator(root, currentAppState, patchOperator, mappedStore.path);
|
|
1039
|
-
},
|
|
1040
|
-
setState(val) {
|
|
1041
|
-
const currentAppState = root.getState();
|
|
1042
|
-
if (isStateOperator(val)) {
|
|
1043
|
-
setStateFromOperator(root, currentAppState, val, mappedStore.path);
|
|
1044
|
-
}
|
|
1045
|
-
else {
|
|
1046
|
-
setStateValue(root, currentAppState, val, mappedStore.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:
|
|
1055
|
-
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type:
|
|
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:
|
|
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
|
-
}]
|
|
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,16 +1263,17 @@ function cloneDefaults(defaults) {
|
|
|
1226
1263
|
* @ignore
|
|
1227
1264
|
*/
|
|
1228
1265
|
class StateFactory {
|
|
1229
|
-
constructor(
|
|
1230
|
-
this._injector =
|
|
1231
|
-
this._config =
|
|
1232
|
-
this._parentFactory =
|
|
1233
|
-
this.
|
|
1234
|
-
this.
|
|
1235
|
-
this.
|
|
1236
|
-
this._initialState =
|
|
1237
|
-
this.
|
|
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
1278
|
this._states = [];
|
|
1241
1279
|
this._statesByName = {};
|
|
@@ -1331,6 +1369,7 @@ class StateFactory {
|
|
|
1331
1369
|
bootstrappedStores.push(stateMap);
|
|
1332
1370
|
}
|
|
1333
1371
|
this.states.push(stateMap);
|
|
1372
|
+
this.hydrateActionMetasMap(stateMap);
|
|
1334
1373
|
}
|
|
1335
1374
|
return bootstrappedStores;
|
|
1336
1375
|
}
|
|
@@ -1350,12 +1389,10 @@ class StateFactory {
|
|
|
1350
1389
|
if (this._parentFactory || this._actionsSubscription !== null) {
|
|
1351
1390
|
return;
|
|
1352
1391
|
}
|
|
1353
|
-
const dispatched$ = new Subject();
|
|
1354
1392
|
this._actionsSubscription = this._actions
|
|
1355
1393
|
.pipe(filter((ctx) => ctx.status === "DISPATCHED" /* ActionStatus.Dispatched */), mergeMap(ctx => {
|
|
1356
|
-
dispatched$.next(ctx);
|
|
1357
1394
|
const action = ctx.action;
|
|
1358
|
-
return this.invokeActions(
|
|
1395
|
+
return this.invokeActions(action).pipe(map$1(() => ({ action, status: "SUCCESSFUL" /* ActionStatus.Successful */ })), defaultIfEmpty({ action, status: "CANCELED" /* ActionStatus.Canceled */ }), catchError(error => {
|
|
1359
1396
|
const ngxsUnhandledErrorHandler = (this._ngxsUnhandledErrorHandler ||=
|
|
1360
1397
|
this._injector.get(NgxsUnhandledErrorHandler));
|
|
1361
1398
|
const handleableError = assignUnhandledCallback(error, () => ngxsUnhandledErrorHandler.handleError(error, { action }));
|
|
@@ -1371,61 +1408,24 @@ class StateFactory {
|
|
|
1371
1408
|
/**
|
|
1372
1409
|
* Invoke actions on the states.
|
|
1373
1410
|
*/
|
|
1374
|
-
invokeActions(
|
|
1411
|
+
invokeActions(action) {
|
|
1375
1412
|
const type = getActionTypeFromInstance(action);
|
|
1376
1413
|
const results = [];
|
|
1377
1414
|
// Determines whether the dispatched action has been handled, this is assigned
|
|
1378
1415
|
// to `true` within the below `for` loop if any `actionMetas` has been found.
|
|
1379
1416
|
let actionHasBeenHandled = false;
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
// is the `ZoneAwarePromise`. Some APIs, which are likely not patched by zone.js
|
|
1390
|
-
// for certain reasons, might not work with `instanceof`. For instance, the dynamic
|
|
1391
|
-
// import returns a native promise (not a `ZoneAwarePromise`), causing this check to
|
|
1392
|
-
// be falsy.
|
|
1393
|
-
if (_isPromise(result)) {
|
|
1394
|
-
result = from(result);
|
|
1395
|
-
}
|
|
1396
|
-
if (isObservable(result)) {
|
|
1397
|
-
// If this observable has been completed w/o emitting
|
|
1398
|
-
// any value then we wouldn't want to complete the whole chain
|
|
1399
|
-
// of actions. Since if any observable completes then
|
|
1400
|
-
// action will be canceled.
|
|
1401
|
-
// For instance if any action handler would've had such statement:
|
|
1402
|
-
// `handler(ctx) { return EMPTY; }`
|
|
1403
|
-
// then the action will be canceled.
|
|
1404
|
-
// See https://github.com/ngxs/store/issues/1568
|
|
1405
|
-
result = result.pipe(mergeMap((value) => {
|
|
1406
|
-
if (_isPromise(value)) {
|
|
1407
|
-
return from(value);
|
|
1408
|
-
}
|
|
1409
|
-
if (isObservable(value)) {
|
|
1410
|
-
return value;
|
|
1411
|
-
}
|
|
1412
|
-
return of(value);
|
|
1413
|
-
}), defaultIfEmpty({}));
|
|
1414
|
-
if (actionMeta.options.cancelUncompleted) {
|
|
1415
|
-
// todo: ofActionDispatched should be used with action class
|
|
1416
|
-
result = result.pipe(takeUntil(dispatched$.pipe(ofActionDispatched(action))));
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
|
-
else {
|
|
1420
|
-
result = of({}).pipe(shareReplay());
|
|
1421
|
-
}
|
|
1422
|
-
results.push(result);
|
|
1423
|
-
}
|
|
1424
|
-
catch (e) {
|
|
1425
|
-
results.push(throwError(e));
|
|
1426
|
-
}
|
|
1427
|
-
actionHasBeenHandled = true;
|
|
1417
|
+
const actionHandlers = this._actionRegistry.get(type);
|
|
1418
|
+
if (actionHandlers) {
|
|
1419
|
+
for (const actionHandler of actionHandlers) {
|
|
1420
|
+
let result;
|
|
1421
|
+
try {
|
|
1422
|
+
result = actionHandler(action);
|
|
1423
|
+
}
|
|
1424
|
+
catch (e) {
|
|
1425
|
+
result = throwError(e);
|
|
1428
1426
|
}
|
|
1427
|
+
results.push(result);
|
|
1428
|
+
actionHasBeenHandled = true;
|
|
1429
1429
|
}
|
|
1430
1430
|
}
|
|
1431
1431
|
// The `NgxsUnhandledActionsLogger` is a tree-shakable class which functions
|
|
@@ -1435,9 +1435,7 @@ class StateFactory {
|
|
|
1435
1435
|
// The `NgxsUnhandledActionsLogger` will not be resolved by the injector if the
|
|
1436
1436
|
// `NgxsDevelopmentModule` is not provided. It's enough to check whether the `injector.get`
|
|
1437
1437
|
// didn't return `null` so we may ensure the module has been imported.
|
|
1438
|
-
|
|
1439
|
-
unhandledActionsLogger.warn(action);
|
|
1440
|
-
}
|
|
1438
|
+
unhandledActionsLogger?.warn(action);
|
|
1441
1439
|
}
|
|
1442
1440
|
if (!results.length) {
|
|
1443
1441
|
results.push(of({}));
|
|
@@ -1473,21 +1471,61 @@ class StateFactory {
|
|
|
1473
1471
|
// its lifecycle is in 'bootstrapped' state.
|
|
1474
1472
|
return this.statesByName[name] && valueIsBootstrappedInInitialState;
|
|
1475
1473
|
}
|
|
1476
|
-
|
|
1474
|
+
hydrateActionMetasMap({ path, actions, instance }) {
|
|
1475
|
+
const { dispatched$ } = this._actions;
|
|
1476
|
+
for (const actionType of Object.keys(actions)) {
|
|
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);
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1477
1524
|
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateFactory }); }
|
|
1478
1525
|
}
|
|
1479
1526
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: StateFactory, decorators: [{
|
|
1480
1527
|
type: Injectable
|
|
1481
|
-
}]
|
|
1482
|
-
type: Optional
|
|
1483
|
-
}, {
|
|
1484
|
-
type: SkipSelf
|
|
1485
|
-
}] }, { type: InternalActions }, { type: InternalDispatchedActionResults }, { type: StateContextFactory }, { type: undefined, decorators: [{
|
|
1486
|
-
type: Optional
|
|
1487
|
-
}, {
|
|
1488
|
-
type: Inject,
|
|
1489
|
-
args: [_INITIAL_STATE_TOKEN]
|
|
1490
|
-
}] }] });
|
|
1528
|
+
}] });
|
|
1491
1529
|
|
|
1492
1530
|
class Store {
|
|
1493
1531
|
constructor(_stateStream, _internalStateOperations, _config, _internalExecutionStrategy, _stateFactory, initialStateValue) {
|
|
@@ -1515,7 +1553,7 @@ class Store {
|
|
|
1515
1553
|
*/
|
|
1516
1554
|
select(selector) {
|
|
1517
1555
|
const selectorFn = this.getStoreBoundSelectorFn(selector);
|
|
1518
|
-
return this._selectableStateStream.pipe(map$1(selectorFn), catchError
|
|
1556
|
+
return this._selectableStateStream.pipe(map$1(selectorFn), catchError((error) => {
|
|
1519
1557
|
// if error is TypeError we swallow it to prevent usual errors with property access
|
|
1520
1558
|
if (this._config.selectorOptions.suppressErrors && error instanceof TypeError) {
|
|
1521
1559
|
return of(undefined);
|
|
@@ -1675,7 +1713,7 @@ class LifecycleStateManager {
|
|
|
1675
1713
|
this._internalStateOperations
|
|
1676
1714
|
.getRootStateOperations()
|
|
1677
1715
|
.dispatch(action)
|
|
1678
|
-
.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$))
|
|
1679
1717
|
.subscribe(() => this._invokeBootstrapOnStates(results.states));
|
|
1680
1718
|
}
|
|
1681
1719
|
_invokeInitOnStates(mappedStores) {
|
|
@@ -1684,7 +1722,7 @@ class LifecycleStateManager {
|
|
|
1684
1722
|
if (instance.ngxsOnChanges) {
|
|
1685
1723
|
this._store
|
|
1686
1724
|
.select(state => getValue(state, mappedStore.path))
|
|
1687
|
-
.pipe(startWith(undefined), pairwise(), takeUntil(this._destroy$))
|
|
1725
|
+
.pipe(startWith(undefined), pairwise(), takeUntil$1(this._destroy$))
|
|
1688
1726
|
.subscribe(([previousValue, currentValue]) => {
|
|
1689
1727
|
const change = new NgxsSimpleChange(previousValue, currentValue, !mappedStore.isInitialised);
|
|
1690
1728
|
instance.ngxsOnChanges(change);
|
|
@@ -1705,7 +1743,7 @@ class LifecycleStateManager {
|
|
|
1705
1743
|
}
|
|
1706
1744
|
}
|
|
1707
1745
|
_getStateContext(mappedStore) {
|
|
1708
|
-
return this._stateContextFactory.createStateContext(mappedStore);
|
|
1746
|
+
return this._stateContextFactory.createStateContext(mappedStore.path);
|
|
1709
1747
|
}
|
|
1710
1748
|
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: LifecycleStateManager, deps: [{ token: Store }, { token: InternalStateOperations }, { token: StateContextFactory }, { token: i1.ɵNgxsAppBootstrappedState }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1711
1749
|
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: LifecycleStateManager, providedIn: 'root' }); }
|
|
@@ -2131,13 +2169,37 @@ function withNgxsDevelopmentOptions(options) {
|
|
|
2131
2169
|
]);
|
|
2132
2170
|
}
|
|
2133
2171
|
|
|
2172
|
+
function getMissingMetaDataError(selector, context = {}) {
|
|
2173
|
+
const metadata = _getSelectorMetadata(selector) || _getStoreMetadata(selector);
|
|
2174
|
+
if (!metadata) {
|
|
2175
|
+
return new Error(`${context.prefix}The value provided as the ${context.noun} is not a valid selector.`);
|
|
2176
|
+
}
|
|
2177
|
+
return null;
|
|
2178
|
+
}
|
|
2134
2179
|
function ensureValidSelector(selector, context = {}) {
|
|
2135
2180
|
const noun = context.noun || 'selector';
|
|
2136
2181
|
const prefix = context.prefix ? context.prefix + ': ' : '';
|
|
2137
2182
|
ensureValueProvided(selector, { noun, prefix: context.prefix });
|
|
2138
|
-
const
|
|
2139
|
-
if (
|
|
2140
|
-
|
|
2183
|
+
const error = getMissingMetaDataError(selector, { noun, prefix });
|
|
2184
|
+
if (error) {
|
|
2185
|
+
// If we have used this utility within a state class, we may be
|
|
2186
|
+
// before the @State or @Selector decorators have been applied.
|
|
2187
|
+
// wait until the next microtask to verify.
|
|
2188
|
+
// Theoretically this situation is only encountered when the javascript
|
|
2189
|
+
// files are being loaded and we are outside the angular zone.
|
|
2190
|
+
if (!NgZone.isInAngularZone()) {
|
|
2191
|
+
Promise.resolve().then(() => {
|
|
2192
|
+
const errorAgain = getMissingMetaDataError(selector, { noun, prefix });
|
|
2193
|
+
if (errorAgain) {
|
|
2194
|
+
// Throw the originally captured error so that the stack trace shows the
|
|
2195
|
+
// original utility call site.
|
|
2196
|
+
console.error(error);
|
|
2197
|
+
}
|
|
2198
|
+
});
|
|
2199
|
+
}
|
|
2200
|
+
else {
|
|
2201
|
+
throw error;
|
|
2202
|
+
}
|
|
2141
2203
|
}
|
|
2142
2204
|
}
|
|
2143
2205
|
function ensureValueProvided(value, context = {}) {
|
|
@@ -2269,7 +2331,13 @@ function provideStates(states, ...features) {
|
|
|
2269
2331
|
* ```
|
|
2270
2332
|
*/
|
|
2271
2333
|
function withNgxsPlugin(plugin) {
|
|
2272
|
-
return makeEnvironmentProviders([
|
|
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
|
+
]);
|
|
2273
2341
|
}
|
|
2274
2342
|
|
|
2275
2343
|
/**
|