@ngxs/store 19.0.0 → 20.0.0-dev.master-5e7c96c
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/fesm2022/ngxs-store-internals-testing.mjs +108 -12
- package/fesm2022/ngxs-store-internals-testing.mjs.map +1 -1
- package/fesm2022/ngxs-store-internals.mjs +72 -32
- package/fesm2022/ngxs-store-internals.mjs.map +1 -1
- package/fesm2022/ngxs-store-operators.mjs +11 -23
- package/fesm2022/ngxs-store-operators.mjs.map +1 -1
- package/fesm2022/ngxs-store-plugins.mjs +5 -4
- package/fesm2022/ngxs-store-plugins.mjs.map +1 -1
- package/fesm2022/ngxs-store.mjs +743 -815
- package/fesm2022/ngxs-store.mjs.map +1 -1
- package/index.d.ts +47 -34
- package/internals/index.d.ts +19 -6
- package/internals/testing/index.d.ts +46 -3
- package/operators/index.d.ts +4 -3
- package/package.json +7 -7
- package/plugins/index.d.ts +2 -1
- package/schematics/src/utils/versions.json +1 -1
- package/experimental/package.json +0 -3
- package/internals/package.json +0 -3
- package/internals/testing/package.json +0 -3
- package/operators/package.json +0 -3
- package/plugins/package.json +0 -3
package/fesm2022/ngxs-store.mjs
CHANGED
|
@@ -1,241 +1,22 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { ɵwrapObserverCalls as _wrapObserverCalls, ɵOrderedSubject as _OrderedSubject, ɵStateStream as _StateStream, ɵmemoize as _memoize, ɵgetStoreMetadata as _getStoreMetadata, ɵgetSelectorMetadata as _getSelectorMetadata, ɵMETA_KEY as _META_KEY, ɵINITIAL_STATE_TOKEN as _INITIAL_STATE_TOKEN, ɵNgxsAppBootstrappedState as _NgxsAppBootstrappedState, ɵensureStoreMetadata as _ensureStoreMetadata, ɵMETA_OPTIONS_KEY as _META_OPTIONS_KEY, ɵensureSelectorMetadata as _ensureSelectorMetadata, ɵNGXS_STATE_CONTEXT_FACTORY as _NGXS_STATE_CONTEXT_FACTORY, ɵNGXS_STATE_FACTORY as _NGXS_STATE_FACTORY } from '@ngxs/store/internals';
|
|
2
|
+
import { inject, Injectable, DestroyRef, NgZone, Injector, runInInjectionContext, InjectionToken, ErrorHandler, ɵisPromise as _isPromise, computed, makeEnvironmentProviders, provideEnvironmentInitializer, NgModule, APP_BOOTSTRAP_LISTENER, ApplicationRef, PendingTasks, assertInInjectionContext, EnvironmentInjector, createEnvironmentInjector } from '@angular/core';
|
|
3
|
+
import { config, Observable, Subject, of, forkJoin, map, shareReplay, filter, take, mergeMap, EMPTY, from, isObservable, defaultIfEmpty, takeUntil, finalize, catchError, distinctUntilChanged, startWith, skip, buffer, debounceTime } from 'rxjs';
|
|
4
|
+
import { ɵwrapObserverCalls as _wrapObserverCalls, ɵOrderedSubject as _OrderedSubject, ɵStateStream as _StateStream, ɵhasOwnProperty as _hasOwnProperty, ɵmemoize as _memoize, ɵgetStoreMetadata as _getStoreMetadata, ɵgetSelectorMetadata as _getSelectorMetadata, ɵMETA_KEY as _META_KEY, ɵINITIAL_STATE_TOKEN as _INITIAL_STATE_TOKEN, ɵNgxsActionRegistry as _NgxsActionRegistry, ɵNgxsAppBootstrappedState as _NgxsAppBootstrappedState, ɵensureStoreMetadata as _ensureStoreMetadata, ɵMETA_OPTIONS_KEY as _META_OPTIONS_KEY, ɵensureSelectorMetadata as _ensureSelectorMetadata, ɵNGXS_STATE_CONTEXT_FACTORY as _NGXS_STATE_CONTEXT_FACTORY, ɵNGXS_STATE_FACTORY as _NGXS_STATE_FACTORY } from '@ngxs/store/internals';
|
|
5
5
|
export { StateToken } from '@ngxs/store/internals';
|
|
6
|
-
import { isPlatformServer } from '@angular/common';
|
|
7
|
-
import { map, shareReplay, filter as filter$1, take, mergeMap, tap, takeUntil as takeUntil$1, startWith, pairwise } from 'rxjs/operators';
|
|
8
6
|
import { NGXS_PLUGINS, getActionTypeFromInstance, InitState, UpdateState, setValue, getValue, ɵisPluginClass as _isPluginClass } from '@ngxs/store/plugins';
|
|
9
7
|
export { InitState, NGXS_PLUGINS, UpdateState, actionMatcher, getActionTypeFromInstance, getValue, setValue } from '@ngxs/store/plugins';
|
|
10
8
|
import { isStateOperator } from '@ngxs/store/operators';
|
|
11
9
|
|
|
12
|
-
class NoopNgxsExecutionStrategy {
|
|
13
|
-
enter(func) {
|
|
14
|
-
return func();
|
|
15
|
-
}
|
|
16
|
-
leave(func) {
|
|
17
|
-
return func();
|
|
18
|
-
}
|
|
19
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NoopNgxsExecutionStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
20
|
-
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NoopNgxsExecutionStrategy, providedIn: 'root' }); }
|
|
21
|
-
}
|
|
22
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NoopNgxsExecutionStrategy, decorators: [{
|
|
23
|
-
type: Injectable,
|
|
24
|
-
args: [{ providedIn: 'root' }]
|
|
25
|
-
}] });
|
|
26
|
-
|
|
27
|
-
function throwStateNameError(name) {
|
|
28
|
-
throw new Error(`${name} is not a valid state name. It needs to be a valid object property name.`);
|
|
29
|
-
}
|
|
30
|
-
function throwStateNamePropertyError() {
|
|
31
|
-
throw new Error(`States must register a 'name' property.`);
|
|
32
|
-
}
|
|
33
|
-
function throwStateUniqueError(current, newName, oldName) {
|
|
34
|
-
throw new Error(`State name '${current}' from ${newName} already exists in ${oldName}.`);
|
|
35
|
-
}
|
|
36
|
-
function throwStateDecoratorError(name) {
|
|
37
|
-
throw new Error(`States must be decorated with @State() decorator, but "${name}" isn't.`);
|
|
38
|
-
}
|
|
39
|
-
function throwActionDecoratorError() {
|
|
40
|
-
throw new Error('@Action() decorator cannot be used with static methods.');
|
|
41
|
-
}
|
|
42
|
-
function throwSelectorDecoratorError() {
|
|
43
|
-
throw new Error('Selectors only work on methods.');
|
|
44
|
-
}
|
|
45
|
-
function getZoneWarningMessage() {
|
|
46
|
-
return ('Your application was bootstrapped with nooped zone and your execution strategy requires an actual NgZone!\n' +
|
|
47
|
-
'Please set the value of the executionStrategy property to NoopNgxsExecutionStrategy.\n' +
|
|
48
|
-
'NgxsModule.forRoot(states, { executionStrategy: NoopNgxsExecutionStrategy })');
|
|
49
|
-
}
|
|
50
|
-
function getUndecoratedStateWithInjectableWarningMessage(name) {
|
|
51
|
-
return `'${name}' class should be decorated with @Injectable() right after the @State() decorator`;
|
|
52
|
-
}
|
|
53
|
-
function getInvalidInitializationOrderMessage(addedStates) {
|
|
54
|
-
let message = 'You have an invalid state initialization order. This typically occurs when `NgxsModule.forFeature`\n' +
|
|
55
|
-
'or `provideStates` is called before `NgxsModule.forRoot` or `provideStore`.\n' +
|
|
56
|
-
'One example is when `NgxsRouterPluginModule.forRoot` is called before `NgxsModule.forRoot`.';
|
|
57
|
-
if (addedStates) {
|
|
58
|
-
const stateNames = Object.keys(addedStates).map(stateName => `"${stateName}"`);
|
|
59
|
-
message +=
|
|
60
|
-
'\nFeature states added before the store initialization is complete: ' +
|
|
61
|
-
`${stateNames.join(', ')}.`;
|
|
62
|
-
}
|
|
63
|
-
return message;
|
|
64
|
-
}
|
|
65
|
-
function throwSelectFactoryNotConnectedError() {
|
|
66
|
-
throw new Error('You have forgotten to import the NGXS module!');
|
|
67
|
-
}
|
|
68
|
-
function throwPatchingArrayError() {
|
|
69
|
-
throw new Error('Patching arrays is not supported.');
|
|
70
|
-
}
|
|
71
|
-
function throwPatchingPrimitiveError() {
|
|
72
|
-
throw new Error('Patching primitives is not supported.');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
class DispatchOutsideZoneNgxsExecutionStrategy {
|
|
76
|
-
constructor() {
|
|
77
|
-
this._ngZone = inject(NgZone);
|
|
78
|
-
this._isServer = isPlatformServer(inject(PLATFORM_ID));
|
|
79
|
-
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
80
|
-
verifyZoneIsNotNooped(this._ngZone);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
enter(func) {
|
|
84
|
-
if (this._isServer) {
|
|
85
|
-
return this.runInsideAngular(func);
|
|
86
|
-
}
|
|
87
|
-
return this.runOutsideAngular(func);
|
|
88
|
-
}
|
|
89
|
-
leave(func) {
|
|
90
|
-
return this.runInsideAngular(func);
|
|
91
|
-
}
|
|
92
|
-
runInsideAngular(func) {
|
|
93
|
-
if (NgZone.isInAngularZone()) {
|
|
94
|
-
return func();
|
|
95
|
-
}
|
|
96
|
-
return this._ngZone.run(func);
|
|
97
|
-
}
|
|
98
|
-
runOutsideAngular(func) {
|
|
99
|
-
if (NgZone.isInAngularZone()) {
|
|
100
|
-
return this._ngZone.runOutsideAngular(func);
|
|
101
|
-
}
|
|
102
|
-
return func();
|
|
103
|
-
}
|
|
104
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: DispatchOutsideZoneNgxsExecutionStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
105
|
-
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: DispatchOutsideZoneNgxsExecutionStrategy, providedIn: 'root' }); }
|
|
106
|
-
}
|
|
107
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: DispatchOutsideZoneNgxsExecutionStrategy, decorators: [{
|
|
108
|
-
type: Injectable,
|
|
109
|
-
args: [{ providedIn: 'root' }]
|
|
110
|
-
}], ctorParameters: () => [] });
|
|
111
|
-
// Caretaker note: this should exist as a separate function and not a class method,
|
|
112
|
-
// since class methods are not tree-shakable.
|
|
113
|
-
function verifyZoneIsNotNooped(ngZone) {
|
|
114
|
-
// `NoopNgZone` is not exposed publicly as it doesn't expect
|
|
115
|
-
// to be used outside of the core Angular code, thus we just have
|
|
116
|
-
// to check if the zone doesn't extend or instanceof `NgZone`.
|
|
117
|
-
if (ngZone instanceof NgZone) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
console.warn(getZoneWarningMessage());
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Consumers have the option to utilize the execution strategy provided by
|
|
125
|
-
* `NgxsModule.forRoot({executionStrategy})` or `provideStore([], {executionStrategy})`.
|
|
126
|
-
*/
|
|
127
|
-
const CUSTOM_NGXS_EXECUTION_STRATEGY = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'CUSTOM_NGXS_EXECUTION_STRATEGY' : '');
|
|
128
|
-
/**
|
|
129
|
-
* The injection token is used internally to resolve an instance of the execution
|
|
130
|
-
* strategy. It checks whether consumers have provided their own `executionStrategy`
|
|
131
|
-
* and also verifies if we are operating in a zone-aware environment.
|
|
132
|
-
*/
|
|
133
|
-
const NGXS_EXECUTION_STRATEGY = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'NGXS_EXECUTION_STRATEGY' : '', {
|
|
134
|
-
providedIn: 'root',
|
|
135
|
-
factory: () => {
|
|
136
|
-
const ngZone = inject(NgZone);
|
|
137
|
-
const injector = inject(INJECTOR);
|
|
138
|
-
const executionStrategy = injector.get(CUSTOM_NGXS_EXECUTION_STRATEGY);
|
|
139
|
-
const isNgZoneEnabled = ngZone instanceof NgZone;
|
|
140
|
-
return executionStrategy
|
|
141
|
-
? injector.get(executionStrategy)
|
|
142
|
-
: injector.get(isNgZoneEnabled
|
|
143
|
-
? DispatchOutsideZoneNgxsExecutionStrategy
|
|
144
|
-
: NoopNgxsExecutionStrategy);
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
class InternalNgxsExecutionStrategy {
|
|
149
|
-
constructor() {
|
|
150
|
-
this._executionStrategy = inject(NGXS_EXECUTION_STRATEGY);
|
|
151
|
-
}
|
|
152
|
-
enter(func) {
|
|
153
|
-
return this._executionStrategy.enter(func);
|
|
154
|
-
}
|
|
155
|
-
leave(func) {
|
|
156
|
-
return this._executionStrategy.leave(func);
|
|
157
|
-
}
|
|
158
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: InternalNgxsExecutionStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
159
|
-
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: InternalNgxsExecutionStrategy, providedIn: 'root' }); }
|
|
160
|
-
}
|
|
161
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: InternalNgxsExecutionStrategy, decorators: [{
|
|
162
|
-
type: Injectable,
|
|
163
|
-
args: [{ providedIn: 'root' }]
|
|
164
|
-
}] });
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Returns operator that will run
|
|
168
|
-
* `subscribe` outside of the ngxs execution context
|
|
169
|
-
*/
|
|
170
|
-
function leaveNgxs(ngxsExecutionStrategy) {
|
|
171
|
-
return _wrapObserverCalls(fn => ngxsExecutionStrategy.leave(fn));
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Internal Action stream that is emitted anytime an action is dispatched.
|
|
176
|
-
*/
|
|
177
|
-
class InternalActions extends _OrderedSubject {
|
|
178
|
-
constructor() {
|
|
179
|
-
super();
|
|
180
|
-
// This subject will be the first to know about the dispatched action, its purpose is for
|
|
181
|
-
// any logic that must be executed before action handlers are invoked (i.e., cancelation).
|
|
182
|
-
this.dispatched$ = new Subject();
|
|
183
|
-
this.pipe(filter(ctx => ctx.status === "DISPATCHED" /* ActionStatus.Dispatched */)).subscribe(ctx => {
|
|
184
|
-
this.dispatched$.next(ctx);
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
ngOnDestroy() {
|
|
188
|
-
this.complete();
|
|
189
|
-
}
|
|
190
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: InternalActions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
191
|
-
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: InternalActions, providedIn: 'root' }); }
|
|
192
|
-
}
|
|
193
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: InternalActions, decorators: [{
|
|
194
|
-
type: Injectable,
|
|
195
|
-
args: [{ providedIn: 'root' }]
|
|
196
|
-
}], ctorParameters: () => [] });
|
|
197
|
-
/**
|
|
198
|
-
* Action stream that is emitted anytime an action is dispatched.
|
|
199
|
-
*
|
|
200
|
-
* You can listen to this in services to react without stores.
|
|
201
|
-
*/
|
|
202
|
-
class Actions extends Observable {
|
|
203
|
-
constructor() {
|
|
204
|
-
const internalActions$ = inject(InternalActions);
|
|
205
|
-
const internalExecutionStrategy = inject(InternalNgxsExecutionStrategy);
|
|
206
|
-
const sharedInternalActions$ = internalActions$.pipe(leaveNgxs(internalExecutionStrategy),
|
|
207
|
-
// The `InternalActions` subject emits outside of the Angular zone.
|
|
208
|
-
// We have to re-enter the Angular zone for any incoming consumer.
|
|
209
|
-
// The `share()` operator reduces the number of change detections.
|
|
210
|
-
// This would call leave only once for any stream emission across all active subscribers.
|
|
211
|
-
share());
|
|
212
|
-
super(observer => {
|
|
213
|
-
const childSubscription = sharedInternalActions$.subscribe({
|
|
214
|
-
next: ctx => observer.next(ctx),
|
|
215
|
-
error: error => observer.error(error),
|
|
216
|
-
complete: () => observer.complete()
|
|
217
|
-
});
|
|
218
|
-
observer.add(childSubscription);
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: Actions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
222
|
-
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: Actions, providedIn: 'root' }); }
|
|
223
|
-
}
|
|
224
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: Actions, decorators: [{
|
|
225
|
-
type: Injectable,
|
|
226
|
-
args: [{ providedIn: 'root' }]
|
|
227
|
-
}], ctorParameters: () => [] });
|
|
228
|
-
|
|
229
10
|
class PluginManager {
|
|
11
|
+
plugins = [];
|
|
12
|
+
_parentManager = inject(PluginManager, {
|
|
13
|
+
optional: true,
|
|
14
|
+
skipSelf: true
|
|
15
|
+
});
|
|
16
|
+
_pluginHandlers = inject(NGXS_PLUGINS, {
|
|
17
|
+
optional: true
|
|
18
|
+
});
|
|
230
19
|
constructor() {
|
|
231
|
-
this.plugins = [];
|
|
232
|
-
this._parentManager = inject(PluginManager, {
|
|
233
|
-
optional: true,
|
|
234
|
-
skipSelf: true
|
|
235
|
-
});
|
|
236
|
-
this._pluginHandlers = inject(NGXS_PLUGINS, {
|
|
237
|
-
optional: true
|
|
238
|
-
});
|
|
239
20
|
this.registerHandlers();
|
|
240
21
|
}
|
|
241
22
|
get _rootPlugins() {
|
|
@@ -249,14 +30,22 @@ class PluginManager {
|
|
|
249
30
|
const handlers = this._pluginHandlers || [];
|
|
250
31
|
return handlers.map((plugin) => (plugin.handle ? plugin.handle.bind(plugin) : plugin));
|
|
251
32
|
}
|
|
252
|
-
/** @nocollapse */ static
|
|
253
|
-
/** @nocollapse */ static
|
|
33
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PluginManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
34
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PluginManager, providedIn: 'root' });
|
|
254
35
|
}
|
|
255
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
36
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PluginManager, decorators: [{
|
|
256
37
|
type: Injectable,
|
|
257
38
|
args: [{ providedIn: 'root' }]
|
|
258
39
|
}], ctorParameters: () => [] });
|
|
259
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Returns operator that will run
|
|
43
|
+
* `subscribe` outside of the ngxs execution context
|
|
44
|
+
*/
|
|
45
|
+
function leaveNgxs(ngxsExecutionStrategy) {
|
|
46
|
+
return _wrapObserverCalls(fn => ngxsExecutionStrategy.leave(fn));
|
|
47
|
+
}
|
|
48
|
+
|
|
260
49
|
const ɵɵunhandledRxjsErrorCallbacks = new WeakMap();
|
|
261
50
|
let installed = false;
|
|
262
51
|
function installOnUnhandhedErrorHandler() {
|
|
@@ -290,7 +79,7 @@ function assignUnhandledCallback(error, callback) {
|
|
|
290
79
|
// Since the error can be essentially anything, we must ensure that we only
|
|
291
80
|
// handle objects, as weak maps do not allow any other key type besides objects.
|
|
292
81
|
// The error can also be a string if thrown in the following manner: `throwError('My Error')`.
|
|
293
|
-
if (error
|
|
82
|
+
if (error && typeof error === 'object') {
|
|
294
83
|
let hasBeenCalled = false;
|
|
295
84
|
ɵɵunhandledRxjsErrorCallbacks.set(error, () => {
|
|
296
85
|
if (!hasBeenCalled) {
|
|
@@ -336,23 +125,134 @@ function fallbackSubscriber(ngZone) {
|
|
|
336
125
|
* The dispatcher then asynchronously pushes the result from this stream onto the main action stream as a result.
|
|
337
126
|
*/
|
|
338
127
|
class InternalDispatchedActionResults extends Subject {
|
|
339
|
-
|
|
340
|
-
|
|
128
|
+
constructor() {
|
|
129
|
+
super();
|
|
130
|
+
// Complete the subject once the root injector is destroyed to ensure
|
|
131
|
+
// there are no active subscribers that would receive events or perform
|
|
132
|
+
// any actions after the application is destroyed.
|
|
133
|
+
inject(DestroyRef).onDestroy(() => this.complete());
|
|
134
|
+
}
|
|
135
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatchedActionResults, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
136
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatchedActionResults, providedIn: 'root' });
|
|
341
137
|
}
|
|
342
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
138
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatchedActionResults, decorators: [{
|
|
139
|
+
type: Injectable,
|
|
140
|
+
args: [{ providedIn: 'root' }]
|
|
141
|
+
}], ctorParameters: () => [] });
|
|
142
|
+
|
|
143
|
+
class InternalNgxsExecutionStrategy {
|
|
144
|
+
_ngZone = inject(NgZone);
|
|
145
|
+
enter(func) {
|
|
146
|
+
if (typeof ngServerMode !== 'undefined' && ngServerMode) {
|
|
147
|
+
return this._runInsideAngular(func);
|
|
148
|
+
}
|
|
149
|
+
return this._runOutsideAngular(func);
|
|
150
|
+
}
|
|
151
|
+
leave(func) {
|
|
152
|
+
return this._runInsideAngular(func);
|
|
153
|
+
}
|
|
154
|
+
_runInsideAngular(func) {
|
|
155
|
+
if (NgZone.isInAngularZone()) {
|
|
156
|
+
return func();
|
|
157
|
+
}
|
|
158
|
+
return this._ngZone.run(func);
|
|
159
|
+
}
|
|
160
|
+
_runOutsideAngular(func) {
|
|
161
|
+
if (NgZone.isInAngularZone()) {
|
|
162
|
+
return this._ngZone.runOutsideAngular(func);
|
|
163
|
+
}
|
|
164
|
+
return func();
|
|
165
|
+
}
|
|
166
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalNgxsExecutionStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
167
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalNgxsExecutionStrategy, providedIn: 'root' });
|
|
168
|
+
}
|
|
169
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalNgxsExecutionStrategy, decorators: [{
|
|
343
170
|
type: Injectable,
|
|
344
171
|
args: [{ providedIn: 'root' }]
|
|
345
172
|
}] });
|
|
346
|
-
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Status of a dispatched action
|
|
176
|
+
*/
|
|
177
|
+
var ActionStatus;
|
|
178
|
+
(function (ActionStatus) {
|
|
179
|
+
ActionStatus["Dispatched"] = "DISPATCHED";
|
|
180
|
+
ActionStatus["Successful"] = "SUCCESSFUL";
|
|
181
|
+
ActionStatus["Canceled"] = "CANCELED";
|
|
182
|
+
ActionStatus["Errored"] = "ERRORED";
|
|
183
|
+
})(ActionStatus || (ActionStatus = {}));
|
|
184
|
+
/**
|
|
185
|
+
* Internal Action stream that is emitted anytime an action is dispatched.
|
|
186
|
+
*/
|
|
187
|
+
class InternalActions extends _OrderedSubject {
|
|
188
|
+
// This subject will be the first to know about the dispatched action, its purpose is for
|
|
189
|
+
// any logic that must be executed before action handlers are invoked (i.e., cancelation).
|
|
190
|
+
dispatched$ = new Subject();
|
|
191
|
+
constructor() {
|
|
192
|
+
super();
|
|
193
|
+
this.subscribe(ctx => {
|
|
194
|
+
if (ctx.status === ActionStatus.Dispatched) {
|
|
195
|
+
this.dispatched$.next(ctx);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
const destroyRef = inject(DestroyRef);
|
|
199
|
+
destroyRef.onDestroy(() => {
|
|
200
|
+
// Complete the subject once the root injector is destroyed to ensure
|
|
201
|
+
// there are no active subscribers that would receive events or perform
|
|
202
|
+
// any actions after the application is destroyed.
|
|
203
|
+
this.complete();
|
|
204
|
+
this.dispatched$.complete();
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
208
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActions, providedIn: 'root' });
|
|
209
|
+
}
|
|
210
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActions, decorators: [{
|
|
211
|
+
type: Injectable,
|
|
212
|
+
args: [{ providedIn: 'root' }]
|
|
213
|
+
}], ctorParameters: () => [] });
|
|
214
|
+
/**
|
|
215
|
+
* Action stream that is emitted anytime an action is dispatched.
|
|
216
|
+
*
|
|
217
|
+
* You can listen to this in services to react without stores.
|
|
218
|
+
*/
|
|
219
|
+
class Actions extends Observable {
|
|
347
220
|
constructor() {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
221
|
+
const internalActions$ = inject(InternalActions);
|
|
222
|
+
const internalExecutionStrategy = inject(InternalNgxsExecutionStrategy);
|
|
223
|
+
// The `InternalActions` subject emits outside of the Angular zone.
|
|
224
|
+
// We have to re-enter the Angular zone for any incoming consumer.
|
|
225
|
+
// The shared `Subject` reduces the number of change detections.
|
|
226
|
+
// This would call leave only once for any stream emission across all active subscribers.
|
|
227
|
+
const sharedInternalActions$ = new Subject();
|
|
228
|
+
internalActions$
|
|
229
|
+
.pipe(leaveNgxs(internalExecutionStrategy))
|
|
230
|
+
.subscribe(sharedInternalActions$);
|
|
231
|
+
super(observer => {
|
|
232
|
+
const childSubscription = sharedInternalActions$.subscribe({
|
|
233
|
+
next: ctx => observer.next(ctx),
|
|
234
|
+
error: error => observer.error(error),
|
|
235
|
+
complete: () => observer.complete()
|
|
236
|
+
});
|
|
237
|
+
observer.add(childSubscription);
|
|
238
|
+
});
|
|
355
239
|
}
|
|
240
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Actions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
241
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Actions, providedIn: 'root' });
|
|
242
|
+
}
|
|
243
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Actions, decorators: [{
|
|
244
|
+
type: Injectable,
|
|
245
|
+
args: [{ providedIn: 'root' }]
|
|
246
|
+
}], ctorParameters: () => [] });
|
|
247
|
+
|
|
248
|
+
class InternalDispatcher {
|
|
249
|
+
_ngZone = inject(NgZone);
|
|
250
|
+
_actions = inject(InternalActions);
|
|
251
|
+
_actionResults = inject(InternalDispatchedActionResults);
|
|
252
|
+
_pluginManager = inject(PluginManager);
|
|
253
|
+
_stateStream = inject(_StateStream);
|
|
254
|
+
_ngxsExecutionStrategy = inject(InternalNgxsExecutionStrategy);
|
|
255
|
+
_injector = inject(Injector);
|
|
356
256
|
/**
|
|
357
257
|
* Dispatches event(s).
|
|
358
258
|
*/
|
|
@@ -375,7 +275,7 @@ class InternalDispatcher {
|
|
|
375
275
|
const type = getActionTypeFromInstance(action);
|
|
376
276
|
if (!type) {
|
|
377
277
|
const error = new Error(`This action doesn't have a type property: ${action.constructor.name}`);
|
|
378
|
-
return
|
|
278
|
+
return new Observable(subscriber => subscriber.error(error));
|
|
379
279
|
}
|
|
380
280
|
}
|
|
381
281
|
const prevState = this._stateStream.getValue();
|
|
@@ -388,34 +288,34 @@ class InternalDispatcher {
|
|
|
388
288
|
}
|
|
389
289
|
const actionResult$ = this.getActionResultStream(nextAction);
|
|
390
290
|
actionResult$.subscribe(ctx => this._actions.next(ctx));
|
|
391
|
-
this._actions.next({ action: nextAction, status:
|
|
291
|
+
this._actions.next({ action: nextAction, status: ActionStatus.Dispatched });
|
|
392
292
|
return this.createDispatchObservable(actionResult$);
|
|
393
293
|
}
|
|
394
294
|
])(prevState, action).pipe(shareReplay());
|
|
395
295
|
}
|
|
396
296
|
getActionResultStream(action) {
|
|
397
|
-
return this._actionResults.pipe(filter
|
|
297
|
+
return this._actionResults.pipe(filter((ctx) => ctx.action === action && ctx.status !== ActionStatus.Dispatched), take(1), shareReplay());
|
|
398
298
|
}
|
|
399
299
|
createDispatchObservable(actionResult$) {
|
|
400
300
|
return actionResult$.pipe(mergeMap((ctx) => {
|
|
401
301
|
switch (ctx.status) {
|
|
402
|
-
case
|
|
302
|
+
case ActionStatus.Successful:
|
|
403
303
|
// The `createDispatchObservable` function should return the
|
|
404
304
|
// state, as its result is used by plugins.
|
|
405
305
|
return of(this._stateStream.getValue());
|
|
406
|
-
case
|
|
407
|
-
|
|
306
|
+
case ActionStatus.Errored:
|
|
307
|
+
throw ctx.error;
|
|
408
308
|
default:
|
|
409
309
|
// Once dispatched or canceled, we complete it immediately because
|
|
410
310
|
// `dispatch()` should emit (or error, or complete) as soon as it succeeds or fails.
|
|
411
|
-
return
|
|
311
|
+
return EMPTY;
|
|
412
312
|
}
|
|
413
313
|
}), shareReplay());
|
|
414
314
|
}
|
|
415
|
-
/** @nocollapse */ static
|
|
416
|
-
/** @nocollapse */ static
|
|
315
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatcher, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
316
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatcher, providedIn: 'root' });
|
|
417
317
|
}
|
|
418
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
318
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalDispatcher, decorators: [{
|
|
419
319
|
type: Injectable,
|
|
420
320
|
args: [{ providedIn: 'root' }]
|
|
421
321
|
}] });
|
|
@@ -458,32 +358,28 @@ const NGXS_OPTIONS = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDe
|
|
|
458
358
|
* The NGXS config settings.
|
|
459
359
|
*/
|
|
460
360
|
class NgxsConfig {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
};
|
|
484
|
-
}
|
|
485
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
486
|
-
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsConfig, providedIn: 'root', useFactory: () => {
|
|
361
|
+
/**
|
|
362
|
+
* Run in development mode. This will add additional debugging features:
|
|
363
|
+
* - Object.freeze on the state and actions to guarantee immutability
|
|
364
|
+
* (default: false)
|
|
365
|
+
*
|
|
366
|
+
* Note: this property will be accounted only in development mode.
|
|
367
|
+
* It makes sense to use it only during development to ensure there're no state mutations.
|
|
368
|
+
* When building for production, the `Object.freeze` will be tree-shaken away.
|
|
369
|
+
*/
|
|
370
|
+
developmentMode;
|
|
371
|
+
compatibility = {
|
|
372
|
+
strictContentSecurityPolicy: false
|
|
373
|
+
};
|
|
374
|
+
/**
|
|
375
|
+
* Defining shared selector options
|
|
376
|
+
*/
|
|
377
|
+
selectorOptions = {
|
|
378
|
+
injectContainerState: false,
|
|
379
|
+
suppressErrors: false
|
|
380
|
+
};
|
|
381
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
382
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsConfig, providedIn: 'root', useFactory: () => {
|
|
487
383
|
const defaultConfig = new NgxsConfig();
|
|
488
384
|
const config = inject(NGXS_OPTIONS);
|
|
489
385
|
return {
|
|
@@ -494,9 +390,9 @@ class NgxsConfig {
|
|
|
494
390
|
...config.selectorOptions
|
|
495
391
|
}
|
|
496
392
|
};
|
|
497
|
-
} });
|
|
393
|
+
} });
|
|
498
394
|
}
|
|
499
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
395
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsConfig, decorators: [{
|
|
500
396
|
type: Injectable,
|
|
501
397
|
args: [{
|
|
502
398
|
providedIn: 'root',
|
|
@@ -519,6 +415,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
|
|
|
519
415
|
* Passed as a value in a NgxsSimpleChanges object to the ngxsOnChanges hook.
|
|
520
416
|
*/
|
|
521
417
|
class NgxsSimpleChange {
|
|
418
|
+
previousValue;
|
|
419
|
+
currentValue;
|
|
420
|
+
firstChange;
|
|
522
421
|
constructor(previousValue, currentValue, firstChange) {
|
|
523
422
|
this.previousValue = previousValue;
|
|
524
423
|
this.currentValue = currentValue;
|
|
@@ -533,9 +432,8 @@ class NgxsSimpleChange {
|
|
|
533
432
|
const deepFreeze = (o) => {
|
|
534
433
|
Object.freeze(o);
|
|
535
434
|
const oIsFunction = typeof o === 'function';
|
|
536
|
-
const hasOwnProp = Object.prototype.hasOwnProperty;
|
|
537
435
|
Object.getOwnPropertyNames(o).forEach(function (prop) {
|
|
538
|
-
if (
|
|
436
|
+
if (_hasOwnProperty(o, prop) &&
|
|
539
437
|
(oIsFunction ? prop !== 'caller' && prop !== 'callee' && prop !== 'arguments' : true) &&
|
|
540
438
|
o[prop] !== null &&
|
|
541
439
|
(typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
|
|
@@ -550,11 +448,9 @@ const deepFreeze = (o) => {
|
|
|
550
448
|
* @ignore
|
|
551
449
|
*/
|
|
552
450
|
class InternalStateOperations {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
this._config = inject(NgxsConfig);
|
|
557
|
-
}
|
|
451
|
+
_stateStream = inject(_StateStream);
|
|
452
|
+
_dispatcher = inject(InternalDispatcher);
|
|
453
|
+
_config = inject(NgxsConfig);
|
|
558
454
|
/**
|
|
559
455
|
* Returns the root state operators.
|
|
560
456
|
*/
|
|
@@ -580,10 +476,10 @@ class InternalStateOperations {
|
|
|
580
476
|
// Set the state to the current + new
|
|
581
477
|
stateOperations.setState({ ...currentState, ...results.defaults });
|
|
582
478
|
}
|
|
583
|
-
/** @nocollapse */ static
|
|
584
|
-
/** @nocollapse */ static
|
|
479
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalStateOperations, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
480
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalStateOperations, providedIn: 'root' });
|
|
585
481
|
}
|
|
586
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
482
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalStateOperations, decorators: [{
|
|
587
483
|
type: Injectable,
|
|
588
484
|
args: [{ providedIn: 'root' }]
|
|
589
485
|
}] });
|
|
@@ -635,7 +531,7 @@ function createRootSelectorFactory(selectorMetaData, selectors, memoizedSelector
|
|
|
635
531
|
};
|
|
636
532
|
}
|
|
637
533
|
function createMemoizedSelectorFn(originalFn, creationMetadata) {
|
|
638
|
-
const containerClass = creationMetadata
|
|
534
|
+
const containerClass = creationMetadata?.containerClass;
|
|
639
535
|
const wrappedFn = function wrappedSelectorFn() {
|
|
640
536
|
// eslint-disable-next-line prefer-rest-params
|
|
641
537
|
const returnValue = originalFn.apply(containerClass, arguments);
|
|
@@ -691,7 +587,7 @@ function getSelectorsToApply(selectors = [], selectorOptions, containerClass) {
|
|
|
691
587
|
*/
|
|
692
588
|
function getRootSelectorFactory(selector) {
|
|
693
589
|
const metadata = _getSelectorMetadata(selector) || _getStoreMetadata(selector);
|
|
694
|
-
return
|
|
590
|
+
return metadata?.makeRootSelector || (() => selector);
|
|
695
591
|
}
|
|
696
592
|
|
|
697
593
|
/**
|
|
@@ -733,31 +629,6 @@ function fastPropGetter(paths) {
|
|
|
733
629
|
const fn = new Function('store', 'return ' + expr + ';');
|
|
734
630
|
return fn;
|
|
735
631
|
}
|
|
736
|
-
/**
|
|
737
|
-
* Get a deeply nested value. Example:
|
|
738
|
-
*
|
|
739
|
-
* getValue({ foo: bar: [] }, 'foo.bar') //=> []
|
|
740
|
-
*
|
|
741
|
-
* @ignore
|
|
742
|
-
*
|
|
743
|
-
* Marked for removal. It's only used within `createSelectorFn`.
|
|
744
|
-
*/
|
|
745
|
-
function propGetter(paths, config) {
|
|
746
|
-
if (config?.compatibility?.strictContentSecurityPolicy) {
|
|
747
|
-
return compliantPropGetter(paths);
|
|
748
|
-
}
|
|
749
|
-
else {
|
|
750
|
-
return fastPropGetter(paths);
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
// This injection token selects the prop getter implementation once the app is
|
|
754
|
-
// bootstrapped, as the `propGetter` function's behavior determines the implementation
|
|
755
|
-
// each time it's called. It accepts the config as the second argument. We no longer
|
|
756
|
-
// need to check for the `strictContentSecurityPolicy` every time the prop getter
|
|
757
|
-
// implementation is selected. Now, the `propGetter` function is only used within
|
|
758
|
-
// `createSelectorFn`, which, in turn, is solely used by the `Select` decorator.
|
|
759
|
-
// We've been trying to deprecate the `Select` decorator because it's unstable with
|
|
760
|
-
// server-side rendering and micro-frontend applications.
|
|
761
632
|
const ɵPROP_GETTER = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'PROP_GETTER' : '', {
|
|
762
633
|
providedIn: 'root',
|
|
763
634
|
factory: () => inject(NgxsConfig).compatibility?.strictContentSecurityPolicy
|
|
@@ -783,17 +654,19 @@ const ɵPROP_GETTER = new InjectionToken(typeof ngDevMode !== 'undefined' && ngD
|
|
|
783
654
|
* @ignore
|
|
784
655
|
*/
|
|
785
656
|
function buildGraph(stateClasses) {
|
|
657
|
+
// Resolve a state's name from the class reference.
|
|
786
658
|
const findName = (stateClass) => {
|
|
787
|
-
const meta = stateClasses.find(
|
|
659
|
+
const meta = stateClasses.find(s => s === stateClass);
|
|
788
660
|
if (typeof ngDevMode !== 'undefined' && ngDevMode && !meta) {
|
|
789
661
|
throw new Error(`Child state not found: ${stateClass}. \r\nYou may have forgotten to add states to module`);
|
|
790
662
|
}
|
|
791
663
|
return meta[_META_KEY].name;
|
|
792
664
|
};
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
665
|
+
// Build the dependency graph.
|
|
666
|
+
return stateClasses.reduce((graph, stateClass) => {
|
|
667
|
+
const meta = stateClass[_META_KEY];
|
|
668
|
+
graph[meta.name] = (meta.children || []).map(findName);
|
|
669
|
+
return graph;
|
|
797
670
|
}, {});
|
|
798
671
|
}
|
|
799
672
|
/**
|
|
@@ -833,23 +706,23 @@ function nameToState(states) {
|
|
|
833
706
|
*
|
|
834
707
|
* @ignore
|
|
835
708
|
*/
|
|
836
|
-
function findFullParentPath(obj,
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
709
|
+
function findFullParentPath(obj, out = {}) {
|
|
710
|
+
// Recursively find the full dotted parent path for a given key.
|
|
711
|
+
const find = (graph, target) => {
|
|
712
|
+
for (const key in graph) {
|
|
713
|
+
if (graph[key]?.includes(target)) {
|
|
714
|
+
const parent = find(graph, key);
|
|
715
|
+
return parent ? `${parent}.${key}` : key;
|
|
842
716
|
}
|
|
843
717
|
}
|
|
844
718
|
return null;
|
|
845
719
|
};
|
|
720
|
+
// Build full path for each key
|
|
846
721
|
for (const key in obj) {
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
newObj[key] = parent ? `${parent}.${key}` : key;
|
|
850
|
-
}
|
|
722
|
+
const parent = find(obj, key);
|
|
723
|
+
out[key] = parent ? `${parent}.${key}` : key;
|
|
851
724
|
}
|
|
852
|
-
return
|
|
725
|
+
return out;
|
|
853
726
|
}
|
|
854
727
|
/**
|
|
855
728
|
* Given a object graph, it will return the items topologically sorted Example:
|
|
@@ -873,62 +746,68 @@ function findFullParentPath(obj, newObj = {}) {
|
|
|
873
746
|
function topologicalSort(graph) {
|
|
874
747
|
const sorted = [];
|
|
875
748
|
const visited = {};
|
|
749
|
+
// DFS (Depth-First Search) to visit each node and its dependencies.
|
|
876
750
|
const visit = (name, ancestors = []) => {
|
|
877
|
-
if (!Array.isArray(ancestors)) {
|
|
878
|
-
ancestors = [];
|
|
879
|
-
}
|
|
880
|
-
ancestors.push(name);
|
|
881
751
|
visited[name] = true;
|
|
882
|
-
|
|
883
|
-
|
|
752
|
+
ancestors.push(name);
|
|
753
|
+
for (const dep of graph[name]) {
|
|
754
|
+
if (typeof ngDevMode !== 'undefined' && ngDevMode && ancestors.includes(dep)) {
|
|
884
755
|
throw new Error(`Circular dependency '${dep}' is required by '${name}': ${ancestors.join(' -> ')}`);
|
|
885
756
|
}
|
|
886
|
-
if (visited[dep])
|
|
887
|
-
|
|
888
|
-
}
|
|
889
|
-
visit(dep, ancestors.slice(0));
|
|
890
|
-
});
|
|
891
|
-
if (sorted.indexOf(name) < 0) {
|
|
892
|
-
sorted.push(name);
|
|
757
|
+
if (!visited[dep])
|
|
758
|
+
visit(dep, ancestors.slice());
|
|
893
759
|
}
|
|
760
|
+
// Add to sorted list if not already included.
|
|
761
|
+
if (!sorted.includes(name))
|
|
762
|
+
sorted.push(name);
|
|
894
763
|
};
|
|
895
|
-
|
|
764
|
+
// Start DFS from each key
|
|
765
|
+
for (const key in graph)
|
|
766
|
+
visit(key);
|
|
896
767
|
return sorted.reverse();
|
|
897
768
|
}
|
|
898
769
|
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
770
|
+
function throwStateNameError(name) {
|
|
771
|
+
throw new Error(`${name} is not a valid state name. It needs to be a valid object property name.`);
|
|
772
|
+
}
|
|
773
|
+
function throwStateNamePropertyError() {
|
|
774
|
+
throw new Error(`States must register a 'name' property.`);
|
|
775
|
+
}
|
|
776
|
+
function throwStateUniqueError(current, newName, oldName) {
|
|
777
|
+
throw new Error(`State name '${current}' from ${newName} already exists in ${oldName}.`);
|
|
778
|
+
}
|
|
779
|
+
function throwStateDecoratorError(name) {
|
|
780
|
+
throw new Error(`States must be decorated with @State() decorator, but "${name}" isn't.`);
|
|
781
|
+
}
|
|
782
|
+
function throwActionDecoratorError() {
|
|
783
|
+
throw new Error('@Action() decorator cannot be used with static methods.');
|
|
784
|
+
}
|
|
785
|
+
function throwSelectorDecoratorError() {
|
|
786
|
+
throw new Error('Selectors only work on methods.');
|
|
787
|
+
}
|
|
788
|
+
function getUndecoratedStateWithInjectableWarningMessage(name) {
|
|
789
|
+
return `'${name}' class should be decorated with @Injectable() right after the @State() decorator`;
|
|
790
|
+
}
|
|
791
|
+
function getInvalidInitializationOrderMessage(addedStates) {
|
|
792
|
+
let message = 'You have an invalid state initialization order. This typically occurs when `NgxsModule.forFeature`\n' +
|
|
793
|
+
'or `provideStates` is called before `NgxsModule.forRoot` or `provideStore`.\n' +
|
|
794
|
+
'One example is when `NgxsRouterPluginModule.forRoot` is called before `NgxsModule.forRoot`.';
|
|
795
|
+
if (addedStates) {
|
|
796
|
+
const stateNames = Object.keys(addedStates).map(stateName => `"${stateName}"`);
|
|
797
|
+
message +=
|
|
798
|
+
'\nFeature states added before the store initialization is complete: ' +
|
|
799
|
+
`${stateNames.join(', ')}.`;
|
|
922
800
|
}
|
|
923
|
-
|
|
924
|
-
|
|
801
|
+
return message;
|
|
802
|
+
}
|
|
803
|
+
function throwPatchingArrayError() {
|
|
804
|
+
throw new Error('Patching arrays is not supported.');
|
|
805
|
+
}
|
|
806
|
+
function throwPatchingPrimitiveError() {
|
|
807
|
+
throw new Error('Patching primitives is not supported.');
|
|
925
808
|
}
|
|
926
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsActionRegistry, decorators: [{
|
|
927
|
-
type: Injectable,
|
|
928
|
-
args: [{ providedIn: 'root' }]
|
|
929
|
-
}] });
|
|
930
809
|
|
|
931
|
-
const stateNameRegex = new RegExp('^[a-zA-Z0-9_]+$');
|
|
810
|
+
const stateNameRegex = /* @__PURE__ */ new RegExp('^[a-zA-Z0-9_]+$');
|
|
932
811
|
function ensureStateNameIsValid(name) {
|
|
933
812
|
if (!name) {
|
|
934
813
|
throwStateNamePropertyError();
|
|
@@ -982,12 +861,12 @@ const NGXS_DEVELOPMENT_OPTIONS =
|
|
|
982
861
|
});
|
|
983
862
|
|
|
984
863
|
class NgxsUnhandledActionsLogger {
|
|
864
|
+
/**
|
|
865
|
+
* These actions should be ignored by default; the user can increase this
|
|
866
|
+
* list in the future via the `ignoreActions` method.
|
|
867
|
+
*/
|
|
868
|
+
_ignoredActions = new Set([InitState.type, UpdateState.type]);
|
|
985
869
|
constructor() {
|
|
986
|
-
/**
|
|
987
|
-
* These actions should be ignored by default; the user can increase this
|
|
988
|
-
* list in the future via the `ignoreActions` method.
|
|
989
|
-
*/
|
|
990
|
-
this._ignoredActions = new Set([InitState.type, UpdateState.type]);
|
|
991
870
|
const options = inject(NGXS_DEVELOPMENT_OPTIONS);
|
|
992
871
|
if (typeof options.warnOnUnhandledActions === 'object') {
|
|
993
872
|
this.ignoreActions(...options.warnOnUnhandledActions.ignore);
|
|
@@ -1013,122 +892,37 @@ class NgxsUnhandledActionsLogger {
|
|
|
1013
892
|
: action.type;
|
|
1014
893
|
console.warn(`The ${action} action has been dispatched but hasn't been handled. This may happen if the state with an action handler for this action is not registered.`);
|
|
1015
894
|
}
|
|
1016
|
-
/** @nocollapse */ static
|
|
1017
|
-
/** @nocollapse */ static
|
|
895
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledActionsLogger, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
896
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledActionsLogger });
|
|
1018
897
|
}
|
|
1019
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
898
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledActionsLogger, decorators: [{
|
|
1020
899
|
type: Injectable
|
|
1021
900
|
}], ctorParameters: () => [] });
|
|
1022
|
-
|
|
1023
|
-
class NgxsUnhandledErrorHandler {
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
*
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
//
|
|
1035
|
-
// the
|
|
1036
|
-
//
|
|
1037
|
-
//
|
|
1038
|
-
|
|
1039
|
-
// `handleError` (see `_callAndReportToErrorHandler`).
|
|
1040
|
-
this._ngZone.runOutsideAngular(() => this._errorHandler.handleError(error));
|
|
1041
|
-
}
|
|
1042
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsUnhandledErrorHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1043
|
-
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsUnhandledErrorHandler, providedIn: 'root' }); }
|
|
1044
|
-
}
|
|
1045
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsUnhandledErrorHandler, decorators: [{
|
|
1046
|
-
type: Injectable,
|
|
1047
|
-
args: [{ providedIn: 'root' }]
|
|
1048
|
-
}] });
|
|
1049
|
-
|
|
1050
|
-
function simplePatch(value) {
|
|
1051
|
-
return (existingState) => {
|
|
1052
|
-
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
1053
|
-
if (Array.isArray(value)) {
|
|
1054
|
-
throwPatchingArrayError();
|
|
1055
|
-
}
|
|
1056
|
-
else if (typeof value !== 'object') {
|
|
1057
|
-
throwPatchingPrimitiveError();
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
const newState = { ...existingState };
|
|
1061
|
-
for (const key in value) {
|
|
1062
|
-
// deep clone for patch compatibility
|
|
1063
|
-
newState[key] = value[key];
|
|
1064
|
-
}
|
|
1065
|
-
return newState;
|
|
1066
|
-
};
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
/**
|
|
1070
|
-
* State Context factory class
|
|
1071
|
-
* @ignore
|
|
1072
|
-
*/
|
|
1073
|
-
class StateContextFactory {
|
|
1074
|
-
constructor() {
|
|
1075
|
-
this._internalStateOperations = inject(InternalStateOperations);
|
|
1076
|
-
}
|
|
1077
|
-
/**
|
|
1078
|
-
* Create the state context
|
|
1079
|
-
*/
|
|
1080
|
-
createStateContext(path) {
|
|
1081
|
-
const root = this._internalStateOperations.getRootStateOperations();
|
|
1082
|
-
return {
|
|
1083
|
-
getState() {
|
|
1084
|
-
const currentAppState = root.getState();
|
|
1085
|
-
return getState(currentAppState, path);
|
|
1086
|
-
},
|
|
1087
|
-
patchState(val) {
|
|
1088
|
-
const currentAppState = root.getState();
|
|
1089
|
-
const patchOperator = simplePatch(val);
|
|
1090
|
-
setStateFromOperator(root, currentAppState, patchOperator, path);
|
|
1091
|
-
},
|
|
1092
|
-
setState(val) {
|
|
1093
|
-
const currentAppState = root.getState();
|
|
1094
|
-
if (isStateOperator(val)) {
|
|
1095
|
-
setStateFromOperator(root, currentAppState, val, path);
|
|
1096
|
-
}
|
|
1097
|
-
else {
|
|
1098
|
-
setStateValue(root, currentAppState, val, path);
|
|
1099
|
-
}
|
|
1100
|
-
},
|
|
1101
|
-
dispatch(actions) {
|
|
1102
|
-
return root.dispatch(actions);
|
|
1103
|
-
}
|
|
1104
|
-
};
|
|
901
|
+
|
|
902
|
+
class NgxsUnhandledErrorHandler {
|
|
903
|
+
_ngZone = inject(NgZone);
|
|
904
|
+
_errorHandler = inject(ErrorHandler);
|
|
905
|
+
/**
|
|
906
|
+
* The `_unhandledErrorContext` is left unused internally since we do not
|
|
907
|
+
* require it for internal operations. However, developers who wish to provide
|
|
908
|
+
* their own custom error handler may utilize this context information.
|
|
909
|
+
*/
|
|
910
|
+
handleError(error, _unhandledErrorContext) {
|
|
911
|
+
// In order to avoid duplicate error handling, it is necessary to leave
|
|
912
|
+
// the Angular zone to ensure that errors are not caught twice. The `handleError`
|
|
913
|
+
// method may contain a `throw error` statement, which is used to re-throw the error.
|
|
914
|
+
// If the error is re-thrown within the Angular zone, it will be caught again by the
|
|
915
|
+
// Angular zone. By default, `@angular/core` leaves the Angular zone when invoking
|
|
916
|
+
// `handleError` (see `_callAndReportToErrorHandler`).
|
|
917
|
+
this._ngZone.runOutsideAngular(() => this._errorHandler.handleError(error));
|
|
1105
918
|
}
|
|
1106
|
-
/** @nocollapse */ static
|
|
1107
|
-
/** @nocollapse */ static
|
|
919
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledErrorHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
920
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledErrorHandler, providedIn: 'root' });
|
|
1108
921
|
}
|
|
1109
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
922
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsUnhandledErrorHandler, decorators: [{
|
|
1110
923
|
type: Injectable,
|
|
1111
924
|
args: [{ providedIn: 'root' }]
|
|
1112
925
|
}] });
|
|
1113
|
-
function setStateValue(root, currentAppState, newValue, path) {
|
|
1114
|
-
const newAppState = setValue(currentAppState, path, newValue);
|
|
1115
|
-
root.setState(newAppState);
|
|
1116
|
-
return newAppState;
|
|
1117
|
-
// In doing this refactoring I noticed that there is a 'bug' where the
|
|
1118
|
-
// application state is returned instead of this state slice.
|
|
1119
|
-
// This has worked this way since the beginning see:
|
|
1120
|
-
// https://github.com/ngxs/store/blame/324c667b4b7debd8eb979006c67ca0ae347d88cd/src/state-factory.ts
|
|
1121
|
-
// This needs to be fixed, but is a 'breaking' change.
|
|
1122
|
-
// I will do this fix in a subsequent PR and we can decide how to handle it.
|
|
1123
|
-
}
|
|
1124
|
-
function setStateFromOperator(root, currentAppState, stateOperator, path) {
|
|
1125
|
-
const local = getState(currentAppState, path);
|
|
1126
|
-
const newValue = stateOperator(local);
|
|
1127
|
-
return setStateValue(root, currentAppState, newValue, path);
|
|
1128
|
-
}
|
|
1129
|
-
function getState(currentAppState, path) {
|
|
1130
|
-
return getValue(currentAppState, path);
|
|
1131
|
-
}
|
|
1132
926
|
|
|
1133
927
|
/**
|
|
1134
928
|
* RxJS operator for selecting out specific actions.
|
|
@@ -1144,7 +938,7 @@ function ofAction(...allowedTypes) {
|
|
|
1144
938
|
* This will ONLY grab actions that have just been dispatched
|
|
1145
939
|
*/
|
|
1146
940
|
function ofActionDispatched(...allowedTypes) {
|
|
1147
|
-
return ofActionOperator(allowedTypes, [
|
|
941
|
+
return ofActionOperator(allowedTypes, [ActionStatus.Dispatched]);
|
|
1148
942
|
}
|
|
1149
943
|
/**
|
|
1150
944
|
* RxJS operator for selecting out specific actions.
|
|
@@ -1152,7 +946,7 @@ function ofActionDispatched(...allowedTypes) {
|
|
|
1152
946
|
* This will ONLY grab actions that have just been successfully completed
|
|
1153
947
|
*/
|
|
1154
948
|
function ofActionSuccessful(...allowedTypes) {
|
|
1155
|
-
return ofActionOperator(allowedTypes, [
|
|
949
|
+
return ofActionOperator(allowedTypes, [ActionStatus.Successful]);
|
|
1156
950
|
}
|
|
1157
951
|
/**
|
|
1158
952
|
* RxJS operator for selecting out specific actions.
|
|
@@ -1160,7 +954,7 @@ function ofActionSuccessful(...allowedTypes) {
|
|
|
1160
954
|
* This will ONLY grab actions that have just been canceled
|
|
1161
955
|
*/
|
|
1162
956
|
function ofActionCanceled(...allowedTypes) {
|
|
1163
|
-
return ofActionOperator(allowedTypes, [
|
|
957
|
+
return ofActionOperator(allowedTypes, [ActionStatus.Canceled]);
|
|
1164
958
|
}
|
|
1165
959
|
/**
|
|
1166
960
|
* RxJS operator for selecting out specific actions.
|
|
@@ -1169,9 +963,9 @@ function ofActionCanceled(...allowedTypes) {
|
|
|
1169
963
|
*/
|
|
1170
964
|
function ofActionCompleted(...allowedTypes) {
|
|
1171
965
|
const allowedStatuses = [
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
966
|
+
ActionStatus.Successful,
|
|
967
|
+
ActionStatus.Canceled,
|
|
968
|
+
ActionStatus.Errored
|
|
1175
969
|
];
|
|
1176
970
|
return ofActionOperator(allowedTypes, allowedStatuses, mapActionResult);
|
|
1177
971
|
}
|
|
@@ -1181,7 +975,7 @@ function ofActionCompleted(...allowedTypes) {
|
|
|
1181
975
|
* This will ONLY grab actions that have just thrown an error
|
|
1182
976
|
*/
|
|
1183
977
|
function ofActionErrored(...allowedTypes) {
|
|
1184
|
-
return ofActionOperator(allowedTypes, [
|
|
978
|
+
return ofActionOperator(allowedTypes, [ActionStatus.Errored], mapActionResult);
|
|
1185
979
|
}
|
|
1186
980
|
function ofActionOperator(allowedTypes, statuses,
|
|
1187
981
|
// This could have been written as
|
|
@@ -1197,7 +991,7 @@ mapOperator = mapAction) {
|
|
|
1197
991
|
};
|
|
1198
992
|
}
|
|
1199
993
|
function filterStatus(allowedTypes, allowedStatuses) {
|
|
1200
|
-
return filter
|
|
994
|
+
return filter((ctx) => {
|
|
1201
995
|
const actionType = getActionTypeFromInstance(ctx.action);
|
|
1202
996
|
const typeMatch = allowedTypes[actionType];
|
|
1203
997
|
const statusMatch = allowedStatuses ? allowedStatuses[ctx.status] : true;
|
|
@@ -1209,8 +1003,8 @@ function mapActionResult() {
|
|
|
1209
1003
|
return {
|
|
1210
1004
|
action,
|
|
1211
1005
|
result: {
|
|
1212
|
-
successful:
|
|
1213
|
-
canceled:
|
|
1006
|
+
successful: ActionStatus.Successful === status,
|
|
1007
|
+
canceled: ActionStatus.Canceled === status,
|
|
1214
1008
|
error
|
|
1215
1009
|
}
|
|
1216
1010
|
};
|
|
@@ -1232,6 +1026,160 @@ function createAllowedStatusesMap(statuses) {
|
|
|
1232
1026
|
}, {});
|
|
1233
1027
|
}
|
|
1234
1028
|
|
|
1029
|
+
function simplePatch(value) {
|
|
1030
|
+
return (existingState) => {
|
|
1031
|
+
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
1032
|
+
if (Array.isArray(value)) {
|
|
1033
|
+
throwPatchingArrayError();
|
|
1034
|
+
}
|
|
1035
|
+
else if (typeof value !== 'object') {
|
|
1036
|
+
throwPatchingPrimitiveError();
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
const newState = { ...existingState };
|
|
1040
|
+
for (const key in value) {
|
|
1041
|
+
// deep clone for patch compatibility
|
|
1042
|
+
newState[key] = value[key];
|
|
1043
|
+
}
|
|
1044
|
+
return newState;
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
/**
|
|
1049
|
+
* State Context factory class
|
|
1050
|
+
* @ignore
|
|
1051
|
+
*/
|
|
1052
|
+
class StateContextFactory {
|
|
1053
|
+
_internalStateOperations = inject(InternalStateOperations);
|
|
1054
|
+
/**
|
|
1055
|
+
* Create the state context
|
|
1056
|
+
*/
|
|
1057
|
+
createStateContext(path) {
|
|
1058
|
+
const root = this._internalStateOperations.getRootStateOperations();
|
|
1059
|
+
return {
|
|
1060
|
+
getState() {
|
|
1061
|
+
const currentAppState = root.getState();
|
|
1062
|
+
return getState(currentAppState, path);
|
|
1063
|
+
},
|
|
1064
|
+
patchState(val) {
|
|
1065
|
+
const currentAppState = root.getState();
|
|
1066
|
+
const patchOperator = simplePatch(val);
|
|
1067
|
+
setStateFromOperator(root, currentAppState, patchOperator, path);
|
|
1068
|
+
},
|
|
1069
|
+
setState(val) {
|
|
1070
|
+
const currentAppState = root.getState();
|
|
1071
|
+
if (isStateOperator(val)) {
|
|
1072
|
+
setStateFromOperator(root, currentAppState, val, path);
|
|
1073
|
+
}
|
|
1074
|
+
else {
|
|
1075
|
+
setStateValue(root, currentAppState, val, path);
|
|
1076
|
+
}
|
|
1077
|
+
},
|
|
1078
|
+
dispatch(actions) {
|
|
1079
|
+
return root.dispatch(actions);
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateContextFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1084
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateContextFactory, providedIn: 'root' });
|
|
1085
|
+
}
|
|
1086
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateContextFactory, decorators: [{
|
|
1087
|
+
type: Injectable,
|
|
1088
|
+
args: [{ providedIn: 'root' }]
|
|
1089
|
+
}] });
|
|
1090
|
+
function setStateValue(root, currentAppState, newValue, path) {
|
|
1091
|
+
const newAppState = setValue(currentAppState, path, newValue);
|
|
1092
|
+
root.setState(newAppState);
|
|
1093
|
+
return newAppState;
|
|
1094
|
+
// In doing this refactoring I noticed that there is a 'bug' where the
|
|
1095
|
+
// application state is returned instead of this state slice.
|
|
1096
|
+
// This has worked this way since the beginning see:
|
|
1097
|
+
// https://github.com/ngxs/store/blame/324c667b4b7debd8eb979006c67ca0ae347d88cd/src/state-factory.ts
|
|
1098
|
+
// This needs to be fixed, but is a 'breaking' change.
|
|
1099
|
+
// I will do this fix in a subsequent PR and we can decide how to handle it.
|
|
1100
|
+
}
|
|
1101
|
+
function setStateFromOperator(root, currentAppState, stateOperator, path) {
|
|
1102
|
+
const local = getState(currentAppState, path);
|
|
1103
|
+
const newValue = stateOperator(local);
|
|
1104
|
+
return setStateValue(root, currentAppState, newValue, path);
|
|
1105
|
+
}
|
|
1106
|
+
function getState(currentAppState, path) {
|
|
1107
|
+
return getValue(currentAppState, path);
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
class InternalActionHandlerFactory {
|
|
1111
|
+
_actions = inject(InternalActions);
|
|
1112
|
+
_stateContextFactory = inject(StateContextFactory);
|
|
1113
|
+
createActionHandler(path, handlerFn, options) {
|
|
1114
|
+
const { dispatched$ } = this._actions;
|
|
1115
|
+
return (action) => {
|
|
1116
|
+
const stateContext = this._stateContextFactory.createStateContext(path);
|
|
1117
|
+
let result = handlerFn(stateContext, action);
|
|
1118
|
+
// We need to use `isPromise` instead of checking whether
|
|
1119
|
+
// `result instanceof Promise`. In zone.js patched environments, `global.Promise`
|
|
1120
|
+
// is the `ZoneAwarePromise`. Some APIs, which are likely not patched by zone.js
|
|
1121
|
+
// for certain reasons, might not work with `instanceof`. For instance, the dynamic
|
|
1122
|
+
// import returns a native promise (not a `ZoneAwarePromise`), causing this check to
|
|
1123
|
+
// be falsy.
|
|
1124
|
+
if (_isPromise(result)) {
|
|
1125
|
+
result = from(result);
|
|
1126
|
+
}
|
|
1127
|
+
if (isObservable(result)) {
|
|
1128
|
+
result = result.pipe(mergeMap(value => (_isPromise(value) || isObservable(value) ? value : of(value))),
|
|
1129
|
+
// If this observable has completed without emitting any values,
|
|
1130
|
+
// we wouldn't want to complete the entire chain of actions.
|
|
1131
|
+
// If any observable completes, then the action will be canceled.
|
|
1132
|
+
// For instance, if any action handler had a statement like
|
|
1133
|
+
// `handler(ctx) { return EMPTY; }`, then the action would be canceled.
|
|
1134
|
+
// See https://github.com/ngxs/store/issues/1568
|
|
1135
|
+
// Note that we actually don't care about the return type; we only care
|
|
1136
|
+
// about emission, and thus `undefined` is applicable by the framework.
|
|
1137
|
+
defaultIfEmpty(undefined));
|
|
1138
|
+
if (options.cancelUncompleted) {
|
|
1139
|
+
const canceled = dispatched$.pipe(ofActionDispatched(action));
|
|
1140
|
+
result = result.pipe(takeUntil(canceled));
|
|
1141
|
+
}
|
|
1142
|
+
result = result.pipe(
|
|
1143
|
+
// Note that we use the `finalize` operator only when the action handler
|
|
1144
|
+
// explicitly returns an observable (or a promise) to wait for. This means
|
|
1145
|
+
// the action handler is written in a "fire & wait" style. If the handler’s
|
|
1146
|
+
// result is unsubscribed (either because the observable has completed or
|
|
1147
|
+
// it was unsubscribed by `takeUntil` due to a new action being dispatched),
|
|
1148
|
+
// we prevent writing to the state context.
|
|
1149
|
+
finalize(() => {
|
|
1150
|
+
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
1151
|
+
function noopAndWarn() {
|
|
1152
|
+
console.warn(`"${action}" attempted to change the state, but the change was ignored because state updates are not allowed after the action handler has completed.`);
|
|
1153
|
+
}
|
|
1154
|
+
stateContext.setState = noopAndWarn;
|
|
1155
|
+
stateContext.patchState = noopAndWarn;
|
|
1156
|
+
}
|
|
1157
|
+
else {
|
|
1158
|
+
stateContext.setState = noop;
|
|
1159
|
+
stateContext.patchState = noop;
|
|
1160
|
+
}
|
|
1161
|
+
}));
|
|
1162
|
+
}
|
|
1163
|
+
else {
|
|
1164
|
+
// If the action handler is synchronous and returns nothing (`void`), we
|
|
1165
|
+
// still have to convert the result to a synchronous observable.
|
|
1166
|
+
result = of(undefined);
|
|
1167
|
+
}
|
|
1168
|
+
return result;
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActionHandlerFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1172
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActionHandlerFactory, providedIn: 'root' });
|
|
1173
|
+
}
|
|
1174
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InternalActionHandlerFactory, decorators: [{
|
|
1175
|
+
type: Injectable,
|
|
1176
|
+
args: [{ providedIn: 'root' }]
|
|
1177
|
+
}] });
|
|
1178
|
+
// This is used to replace `setState` and `patchState` once the action
|
|
1179
|
+
// handler has been unsubscribed or completed, to prevent writing
|
|
1180
|
+
// to the state context.
|
|
1181
|
+
function noop() { }
|
|
1182
|
+
|
|
1235
1183
|
function cloneDefaults(defaults) {
|
|
1236
1184
|
let value = defaults === undefined ? {} : defaults;
|
|
1237
1185
|
if (defaults) {
|
|
@@ -1256,57 +1204,55 @@ function cloneDefaults(defaults) {
|
|
|
1256
1204
|
* @ignore
|
|
1257
1205
|
*/
|
|
1258
1206
|
class StateFactory {
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
return getter;
|
|
1288
|
-
}
|
|
1289
|
-
return (...args) => {
|
|
1290
|
-
// Late loaded getter
|
|
1291
|
-
if (!getter) {
|
|
1292
|
-
getter = /*@__INLINE__*/ resolveGetter(key);
|
|
1293
|
-
}
|
|
1294
|
-
return getter ? getter(...args) : undefined;
|
|
1295
|
-
};
|
|
1296
|
-
},
|
|
1297
|
-
getSelectorOptions(localOptions) {
|
|
1298
|
-
const globalSelectorOptions = stateFactory._config.selectorOptions;
|
|
1299
|
-
return {
|
|
1300
|
-
...globalSelectorOptions,
|
|
1301
|
-
...(localOptions || {})
|
|
1302
|
-
};
|
|
1207
|
+
_injector = inject(Injector);
|
|
1208
|
+
_config = inject(NgxsConfig);
|
|
1209
|
+
_actionHandlerFactory = inject(InternalActionHandlerFactory);
|
|
1210
|
+
_actions = inject(InternalActions);
|
|
1211
|
+
_actionResults = inject(InternalDispatchedActionResults);
|
|
1212
|
+
_initialState = inject(_INITIAL_STATE_TOKEN, { optional: true });
|
|
1213
|
+
_actionRegistry = inject(_NgxsActionRegistry);
|
|
1214
|
+
_propGetter = inject(ɵPROP_GETTER);
|
|
1215
|
+
_actionsSubscription = null;
|
|
1216
|
+
_ngxsUnhandledErrorHandler = null;
|
|
1217
|
+
_states = [];
|
|
1218
|
+
_statesByName = {};
|
|
1219
|
+
_statePaths = {};
|
|
1220
|
+
getRuntimeSelectorContext = _memoize(() => {
|
|
1221
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1222
|
+
const stateFactory = this;
|
|
1223
|
+
const propGetter = stateFactory._propGetter;
|
|
1224
|
+
function resolveGetter(key) {
|
|
1225
|
+
const path = stateFactory._statePaths[key];
|
|
1226
|
+
return path ? propGetter(path.split('.')) : null;
|
|
1227
|
+
}
|
|
1228
|
+
const context = {
|
|
1229
|
+
getStateGetter(key) {
|
|
1230
|
+
// Use `@__INLINE__` annotation to forcely inline `resolveGetter`.
|
|
1231
|
+
// This is a Terser annotation, which will function only in the production mode.
|
|
1232
|
+
let getter = /*@__INLINE__*/ resolveGetter(key);
|
|
1233
|
+
if (getter) {
|
|
1234
|
+
return getter;
|
|
1303
1235
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1236
|
+
return (...args) => {
|
|
1237
|
+
// Late loaded getter
|
|
1238
|
+
if (!getter) {
|
|
1239
|
+
getter = /*@__INLINE__*/ resolveGetter(key);
|
|
1240
|
+
}
|
|
1241
|
+
return getter ? getter(...args) : undefined;
|
|
1242
|
+
};
|
|
1243
|
+
},
|
|
1244
|
+
getSelectorOptions(localOptions) {
|
|
1245
|
+
const globalSelectorOptions = stateFactory._config.selectorOptions;
|
|
1246
|
+
return {
|
|
1247
|
+
...globalSelectorOptions,
|
|
1248
|
+
...(localOptions || {})
|
|
1249
|
+
};
|
|
1250
|
+
}
|
|
1251
|
+
};
|
|
1252
|
+
return context;
|
|
1253
|
+
});
|
|
1254
|
+
constructor() {
|
|
1255
|
+
inject(DestroyRef).onDestroy(() => this._actionsSubscription?.unsubscribe());
|
|
1310
1256
|
}
|
|
1311
1257
|
/**
|
|
1312
1258
|
* Add a new state to the global defs.
|
|
@@ -1328,10 +1274,6 @@ class StateFactory {
|
|
|
1328
1274
|
const path = paths[name];
|
|
1329
1275
|
const meta = stateClass[_META_KEY];
|
|
1330
1276
|
this.addRuntimeInfoToMeta(meta, path);
|
|
1331
|
-
// Note: previously we called `ensureStateClassIsInjectable` within the
|
|
1332
|
-
// `State` decorator. This check is moved here because the `ɵprov` property
|
|
1333
|
-
// will not exist on the class in JIT mode (because it's set asynchronously
|
|
1334
|
-
// during JIT compilation through `Object.defineProperty`).
|
|
1335
1277
|
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
1336
1278
|
ensureStateClassIsInjectable(stateClass);
|
|
1337
1279
|
}
|
|
@@ -1365,15 +1307,15 @@ class StateFactory {
|
|
|
1365
1307
|
}
|
|
1366
1308
|
connectActionHandlers() {
|
|
1367
1309
|
this._actionsSubscription = this._actions
|
|
1368
|
-
.pipe(filter((ctx) => ctx.status ===
|
|
1310
|
+
.pipe(filter((ctx) => ctx.status === ActionStatus.Dispatched), mergeMap(ctx => {
|
|
1369
1311
|
const action = ctx.action;
|
|
1370
|
-
return this.invokeActions(action).pipe(map
|
|
1312
|
+
return this.invokeActions(action).pipe(map(() => ({ action, status: ActionStatus.Successful })), defaultIfEmpty({ action, status: ActionStatus.Canceled }), catchError(error => {
|
|
1371
1313
|
const ngxsUnhandledErrorHandler = (this._ngxsUnhandledErrorHandler ||=
|
|
1372
1314
|
this._injector.get(NgxsUnhandledErrorHandler));
|
|
1373
1315
|
const handleableError = assignUnhandledCallback(error, () => ngxsUnhandledErrorHandler.handleError(error, { action }));
|
|
1374
1316
|
return of({
|
|
1375
1317
|
action,
|
|
1376
|
-
status:
|
|
1318
|
+
status: ActionStatus.Errored,
|
|
1377
1319
|
error: handleableError
|
|
1378
1320
|
});
|
|
1379
1321
|
}));
|
|
@@ -1397,7 +1339,7 @@ class StateFactory {
|
|
|
1397
1339
|
result = actionHandler(action);
|
|
1398
1340
|
}
|
|
1399
1341
|
catch (e) {
|
|
1400
|
-
result =
|
|
1342
|
+
result = new Observable(subscriber => subscriber.error(e));
|
|
1401
1343
|
}
|
|
1402
1344
|
results.push(result);
|
|
1403
1345
|
actionHasBeenHandled = true;
|
|
@@ -1447,98 +1389,37 @@ class StateFactory {
|
|
|
1447
1389
|
return this._statesByName[name] && valueIsBootstrappedInInitialState;
|
|
1448
1390
|
}
|
|
1449
1391
|
hydrateActionMetasMap({ path, actions, instance }) {
|
|
1450
|
-
const { dispatched$ } = this._actions;
|
|
1451
1392
|
for (const actionType of Object.keys(actions)) {
|
|
1452
1393
|
const actionHandlers = actions[actionType].map(actionMeta => {
|
|
1453
|
-
const
|
|
1454
|
-
return (
|
|
1455
|
-
const stateContext = this._stateContextFactory.createStateContext(path);
|
|
1456
|
-
let result = instance[actionMeta.fn](stateContext, action);
|
|
1457
|
-
// We need to use `isPromise` instead of checking whether
|
|
1458
|
-
// `result instanceof Promise`. In zone.js patched environments, `global.Promise`
|
|
1459
|
-
// is the `ZoneAwarePromise`. Some APIs, which are likely not patched by zone.js
|
|
1460
|
-
// for certain reasons, might not work with `instanceof`. For instance, the dynamic
|
|
1461
|
-
// import returns a native promise (not a `ZoneAwarePromise`), causing this check to
|
|
1462
|
-
// be falsy.
|
|
1463
|
-
if (_isPromise(result)) {
|
|
1464
|
-
result = from(result);
|
|
1465
|
-
}
|
|
1466
|
-
if (isObservable(result)) {
|
|
1467
|
-
result = result.pipe(mergeMap$1((value) => {
|
|
1468
|
-
if (_isPromise(value)) {
|
|
1469
|
-
return from(value);
|
|
1470
|
-
}
|
|
1471
|
-
else if (isObservable(value)) {
|
|
1472
|
-
return value;
|
|
1473
|
-
}
|
|
1474
|
-
else {
|
|
1475
|
-
return of(value);
|
|
1476
|
-
}
|
|
1477
|
-
}),
|
|
1478
|
-
// If this observable has completed without emitting any values,
|
|
1479
|
-
// we wouldn't want to complete the entire chain of actions.
|
|
1480
|
-
// If any observable completes, then the action will be canceled.
|
|
1481
|
-
// For instance, if any action handler had a statement like
|
|
1482
|
-
// `handler(ctx) { return EMPTY; }`, then the action would be canceled.
|
|
1483
|
-
// See https://github.com/ngxs/store/issues/1568
|
|
1484
|
-
// Note that we actually don't care about the return type; we only care
|
|
1485
|
-
// about emission, and thus `undefined` is applicable by the framework.
|
|
1486
|
-
defaultIfEmpty(undefined));
|
|
1487
|
-
if (cancelable) {
|
|
1488
|
-
const notifier$ = dispatched$.pipe(ofActionDispatched(action));
|
|
1489
|
-
result = result.pipe(takeUntil(notifier$));
|
|
1490
|
-
}
|
|
1491
|
-
result = result.pipe(
|
|
1492
|
-
// Note that we use the `finalize` operator only when the action handler
|
|
1493
|
-
// returns an observable. If the action handler is synchronous, we do not
|
|
1494
|
-
// need to set the state context functions to `noop`, as the absence of a
|
|
1495
|
-
// return value indicates no asynchronous functionality. If the handler's
|
|
1496
|
-
// result is unsubscribed (either because the observable has completed or it
|
|
1497
|
-
// was unsubscribed by `takeUntil` due to a new action being dispatched),
|
|
1498
|
-
// we prevent writing to the state context.
|
|
1499
|
-
finalize(() => {
|
|
1500
|
-
stateContext.setState = noop;
|
|
1501
|
-
stateContext.patchState = noop;
|
|
1502
|
-
}));
|
|
1503
|
-
}
|
|
1504
|
-
else {
|
|
1505
|
-
// If the action handler is synchronous and returns nothing (`void`), we
|
|
1506
|
-
// still have to convert the result to a synchronous observable.
|
|
1507
|
-
result = of(undefined);
|
|
1508
|
-
}
|
|
1509
|
-
return result;
|
|
1510
|
-
};
|
|
1394
|
+
const handlerFn = (ctx, action) => instance[actionMeta.fn](ctx, action);
|
|
1395
|
+
return this._actionHandlerFactory.createActionHandler(path, handlerFn, actionMeta.options);
|
|
1511
1396
|
});
|
|
1512
1397
|
for (const actionHandler of actionHandlers) {
|
|
1513
1398
|
this._actionRegistry.register(actionType, actionHandler);
|
|
1514
1399
|
}
|
|
1515
1400
|
}
|
|
1516
1401
|
}
|
|
1517
|
-
/** @nocollapse */ static
|
|
1518
|
-
/** @nocollapse */ static
|
|
1402
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1403
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateFactory, providedIn: 'root' });
|
|
1519
1404
|
}
|
|
1520
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1405
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: StateFactory, decorators: [{
|
|
1521
1406
|
type: Injectable,
|
|
1522
1407
|
args: [{ providedIn: 'root' }]
|
|
1523
|
-
}] });
|
|
1524
|
-
// This is used to replace `setState` and `patchState` once the action
|
|
1525
|
-
// handler has been unsubscribed or completed, to prevent writing
|
|
1526
|
-
// to the state context.
|
|
1527
|
-
function noop() { }
|
|
1408
|
+
}], ctorParameters: () => [] });
|
|
1528
1409
|
|
|
1529
1410
|
class Store {
|
|
1411
|
+
_stateStream = inject(_StateStream);
|
|
1412
|
+
_internalStateOperations = inject(InternalStateOperations);
|
|
1413
|
+
_config = inject(NgxsConfig);
|
|
1414
|
+
_internalExecutionStrategy = inject(InternalNgxsExecutionStrategy);
|
|
1415
|
+
_stateFactory = inject(StateFactory);
|
|
1416
|
+
/**
|
|
1417
|
+
* This is a derived state stream that leaves NGXS execution strategy to emit state changes within the Angular zone,
|
|
1418
|
+
* because state is being changed actually within the `<root>` zone, see `InternalDispatcher#dispatchSingle`.
|
|
1419
|
+
* All selects would use this stream, and it would call leave only once for any state change across all active selectors.
|
|
1420
|
+
*/
|
|
1421
|
+
_selectableStateStream = this._stateStream.pipe(leaveNgxs(this._internalExecutionStrategy), shareReplay({ bufferSize: 1, refCount: true }));
|
|
1530
1422
|
constructor() {
|
|
1531
|
-
this._stateStream = inject(_StateStream);
|
|
1532
|
-
this._internalStateOperations = inject(InternalStateOperations);
|
|
1533
|
-
this._config = inject(NgxsConfig);
|
|
1534
|
-
this._internalExecutionStrategy = inject(InternalNgxsExecutionStrategy);
|
|
1535
|
-
this._stateFactory = inject(StateFactory);
|
|
1536
|
-
/**
|
|
1537
|
-
* This is a derived state stream that leaves NGXS execution strategy to emit state changes within the Angular zone,
|
|
1538
|
-
* because state is being changed actually within the `<root>` zone, see `InternalDispatcher#dispatchSingle`.
|
|
1539
|
-
* All selects would use this stream, and it would call leave only once for any state change across all active selectors.
|
|
1540
|
-
*/
|
|
1541
|
-
this._selectableStateStream = this._stateStream.pipe(leaveNgxs(this._internalExecutionStrategy), shareReplay$1({ bufferSize: 1, refCount: true }));
|
|
1542
1423
|
this.initStateStream();
|
|
1543
1424
|
}
|
|
1544
1425
|
/**
|
|
@@ -1552,7 +1433,7 @@ class Store {
|
|
|
1552
1433
|
// If a list of actions is dispatched and any of the actions are nullable.
|
|
1553
1434
|
(Array.isArray(actionOrActions) && actionOrActions.some(action => action == null))) {
|
|
1554
1435
|
const error = new Error('`dispatch()` was called without providing an action.');
|
|
1555
|
-
return
|
|
1436
|
+
return new Observable(subscriber => subscriber.error(error));
|
|
1556
1437
|
}
|
|
1557
1438
|
}
|
|
1558
1439
|
return this._internalStateOperations.getRootStateOperations().dispatch(actionOrActions);
|
|
@@ -1562,20 +1443,20 @@ class Store {
|
|
|
1562
1443
|
*/
|
|
1563
1444
|
select(selector) {
|
|
1564
1445
|
const selectorFn = this.getStoreBoundSelectorFn(selector);
|
|
1565
|
-
return this._selectableStateStream.pipe(map
|
|
1446
|
+
return this._selectableStateStream.pipe(map(selectorFn), catchError((error) => {
|
|
1566
1447
|
// if error is TypeError we swallow it to prevent usual errors with property access
|
|
1567
1448
|
if (this._config.selectorOptions.suppressErrors && error instanceof TypeError) {
|
|
1568
1449
|
return of(undefined);
|
|
1569
1450
|
}
|
|
1570
1451
|
// rethrow other errors
|
|
1571
|
-
|
|
1452
|
+
throw error;
|
|
1572
1453
|
}), distinctUntilChanged(), leaveNgxs(this._internalExecutionStrategy));
|
|
1573
1454
|
}
|
|
1574
1455
|
/**
|
|
1575
1456
|
* Select one slice of data from the store.
|
|
1576
1457
|
*/
|
|
1577
1458
|
selectOnce(selector) {
|
|
1578
|
-
return this.select(selector).pipe(take
|
|
1459
|
+
return this.select(selector).pipe(take(1));
|
|
1579
1460
|
}
|
|
1580
1461
|
/**
|
|
1581
1462
|
* Select a snapshot from the state.
|
|
@@ -1625,10 +1506,10 @@ class Store {
|
|
|
1625
1506
|
this._stateStream.next(initialStateValue);
|
|
1626
1507
|
}
|
|
1627
1508
|
}
|
|
1628
|
-
/** @nocollapse */ static
|
|
1629
|
-
/** @nocollapse */ static
|
|
1509
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Store, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1510
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Store, providedIn: 'root' });
|
|
1630
1511
|
}
|
|
1631
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1512
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: Store, decorators: [{
|
|
1632
1513
|
type: Injectable,
|
|
1633
1514
|
args: [{ providedIn: 'root' }]
|
|
1634
1515
|
}], ctorParameters: () => [] });
|
|
@@ -1663,40 +1544,24 @@ function withNgxsPreboot(prebootFn) {
|
|
|
1663
1544
|
]);
|
|
1664
1545
|
}
|
|
1665
1546
|
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
SelectFactory.store = store;
|
|
1675
|
-
SelectFactory.config = config;
|
|
1676
|
-
}
|
|
1677
|
-
ngOnDestroy() {
|
|
1678
|
-
SelectFactory.store = null;
|
|
1679
|
-
SelectFactory.config = null;
|
|
1547
|
+
const ROOT_STORE_GUARD = /* @__PURE__ */ new InjectionToken('ROOT_STORE_GUARD', {
|
|
1548
|
+
providedIn: 'root',
|
|
1549
|
+
factory: () => ({ initialized: false })
|
|
1550
|
+
});
|
|
1551
|
+
function assertRootStoreNotInitialized() {
|
|
1552
|
+
const rootStoreGuard = inject(ROOT_STORE_GUARD);
|
|
1553
|
+
if (rootStoreGuard.initialized) {
|
|
1554
|
+
throw new Error('provideStore() should only be called once.');
|
|
1680
1555
|
}
|
|
1681
|
-
|
|
1682
|
-
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SelectFactory, providedIn: 'root' }); }
|
|
1556
|
+
rootStoreGuard.initialized = true;
|
|
1683
1557
|
}
|
|
1684
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SelectFactory, decorators: [{
|
|
1685
|
-
type: Injectable,
|
|
1686
|
-
args: [{ providedIn: 'root' }]
|
|
1687
|
-
}], ctorParameters: () => [{ type: Store }, { type: NgxsConfig }] });
|
|
1688
1558
|
|
|
1689
1559
|
class LifecycleStateManager {
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
this._destroy$ = new ReplaySubject(1);
|
|
1696
|
-
}
|
|
1697
|
-
ngOnDestroy() {
|
|
1698
|
-
this._destroy$.next();
|
|
1699
|
-
}
|
|
1560
|
+
_store = inject(Store);
|
|
1561
|
+
_internalStateOperations = inject(InternalStateOperations);
|
|
1562
|
+
_stateContextFactory = inject(StateContextFactory);
|
|
1563
|
+
_appBootstrappedState = inject(_NgxsAppBootstrappedState);
|
|
1564
|
+
_initStateHasBeenDispatched;
|
|
1700
1565
|
ngxsBootstrap(action, results) {
|
|
1701
1566
|
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
1702
1567
|
if (action instanceof InitState) {
|
|
@@ -1713,21 +1578,45 @@ class LifecycleStateManager {
|
|
|
1713
1578
|
console.error(getInvalidInitializationOrderMessage(action.addedStates));
|
|
1714
1579
|
}
|
|
1715
1580
|
}
|
|
1581
|
+
// It does not need to unsubscribe because it is completed when the
|
|
1582
|
+
// root injector is destroyed.
|
|
1716
1583
|
this._internalStateOperations
|
|
1717
1584
|
.getRootStateOperations()
|
|
1718
1585
|
.dispatch(action)
|
|
1719
|
-
.pipe(
|
|
1720
|
-
|
|
1586
|
+
.pipe(mergeMap(() => {
|
|
1587
|
+
// If no states are provided, we safely complete the stream
|
|
1588
|
+
// and do not proceed further.
|
|
1589
|
+
if (!results) {
|
|
1590
|
+
return EMPTY;
|
|
1591
|
+
}
|
|
1592
|
+
this._invokeInitOnStates(results.states);
|
|
1593
|
+
return this._appBootstrappedState;
|
|
1594
|
+
}))
|
|
1595
|
+
.subscribe(appBootstrapped => {
|
|
1596
|
+
if (appBootstrapped) {
|
|
1597
|
+
this._invokeBootstrapOnStates(results.states);
|
|
1598
|
+
}
|
|
1599
|
+
});
|
|
1721
1600
|
}
|
|
1722
1601
|
_invokeInitOnStates(mappedStores) {
|
|
1723
1602
|
for (const mappedStore of mappedStores) {
|
|
1724
1603
|
const instance = mappedStore.instance;
|
|
1725
1604
|
if (instance.ngxsOnChanges) {
|
|
1605
|
+
// We are manually keeping track of the previous value
|
|
1606
|
+
// within the subscribe block in order to drop the `pairwise()` operator.
|
|
1607
|
+
let previousValue;
|
|
1608
|
+
// It does not need to unsubscribe because it is completed when the
|
|
1609
|
+
// root injector is destroyed.
|
|
1726
1610
|
this._store
|
|
1727
1611
|
.select(state => getValue(state, mappedStore.path))
|
|
1728
|
-
.pipe(
|
|
1729
|
-
|
|
1612
|
+
.pipe(
|
|
1613
|
+
// Ensure initial state is captured
|
|
1614
|
+
startWith(undefined),
|
|
1615
|
+
// `skip` is using `filter` internally.
|
|
1616
|
+
skip(1))
|
|
1617
|
+
.subscribe(currentValue => {
|
|
1730
1618
|
const change = new NgxsSimpleChange(previousValue, currentValue, !mappedStore.isInitialised);
|
|
1619
|
+
previousValue = currentValue;
|
|
1731
1620
|
instance.ngxsOnChanges(change);
|
|
1732
1621
|
});
|
|
1733
1622
|
}
|
|
@@ -1748,10 +1637,10 @@ class LifecycleStateManager {
|
|
|
1748
1637
|
_getStateContext(mappedStore) {
|
|
1749
1638
|
return this._stateContextFactory.createStateContext(mappedStore.path);
|
|
1750
1639
|
}
|
|
1751
|
-
/** @nocollapse */ static
|
|
1752
|
-
/** @nocollapse */ static
|
|
1640
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: LifecycleStateManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1641
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: LifecycleStateManager, providedIn: 'root' });
|
|
1753
1642
|
}
|
|
1754
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1643
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: LifecycleStateManager, decorators: [{
|
|
1755
1644
|
type: Injectable,
|
|
1756
1645
|
args: [{ providedIn: 'root' }]
|
|
1757
1646
|
}] });
|
|
@@ -1762,6 +1651,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
|
|
|
1762
1651
|
* same initialization functionality.
|
|
1763
1652
|
*/
|
|
1764
1653
|
function rootStoreInitializer() {
|
|
1654
|
+
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
1655
|
+
assertRootStoreNotInitialized();
|
|
1656
|
+
}
|
|
1765
1657
|
// Override the RxJS `config.onUnhandledError` within the root store initializer,
|
|
1766
1658
|
// but only after other code has already executed.
|
|
1767
1659
|
// If users have a custom `config.onUnhandledError`, we might overwrite it too
|
|
@@ -1772,7 +1664,6 @@ function rootStoreInitializer() {
|
|
|
1772
1664
|
const factory = inject(StateFactory);
|
|
1773
1665
|
const internalStateOperations = inject(InternalStateOperations);
|
|
1774
1666
|
inject(Store);
|
|
1775
|
-
inject(SelectFactory);
|
|
1776
1667
|
const states = inject(ROOT_STATE_TOKEN, { optional: true }) || [];
|
|
1777
1668
|
const lifecycleStateManager = inject(LifecycleStateManager);
|
|
1778
1669
|
// Add stores to the state graph and return their defaults.
|
|
@@ -1815,13 +1706,7 @@ const NGXS_ROOT_STORE_INITIALIZER = new InjectionToken(typeof ngDevMode !== 'und
|
|
|
1815
1706
|
const NGXS_FEATURE_STORE_INITIALIZER = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'NGXS_FEATURE_STORE_INITIALIZER' : '');
|
|
1816
1707
|
const NGXS_ROOT_ENVIRONMENT_INITIALIZER = [
|
|
1817
1708
|
{ provide: NGXS_ROOT_STORE_INITIALIZER, useFactory: rootStoreInitializer },
|
|
1818
|
-
|
|
1819
|
-
provide: ENVIRONMENT_INITIALIZER,
|
|
1820
|
-
multi: true,
|
|
1821
|
-
useFactory() {
|
|
1822
|
-
return () => inject(NGXS_ROOT_STORE_INITIALIZER);
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1709
|
+
provideEnvironmentInitializer(() => inject(NGXS_ROOT_STORE_INITIALIZER))
|
|
1825
1710
|
];
|
|
1826
1711
|
/**
|
|
1827
1712
|
* The `NGXS_FEATURE_ENVIRONMENT_INITIALIZER` functions as an environment initializer
|
|
@@ -1831,13 +1716,7 @@ const NGXS_ROOT_ENVIRONMENT_INITIALIZER = [
|
|
|
1831
1716
|
*/
|
|
1832
1717
|
const NGXS_FEATURE_ENVIRONMENT_INITIALIZER = [
|
|
1833
1718
|
{ provide: NGXS_FEATURE_STORE_INITIALIZER, useFactory: featureStatesInitializer },
|
|
1834
|
-
|
|
1835
|
-
provide: ENVIRONMENT_INITIALIZER,
|
|
1836
|
-
multi: true,
|
|
1837
|
-
useFactory() {
|
|
1838
|
-
return () => inject(NGXS_FEATURE_STORE_INITIALIZER);
|
|
1839
|
-
}
|
|
1840
|
-
}
|
|
1719
|
+
provideEnvironmentInitializer(() => inject(NGXS_FEATURE_STORE_INITIALIZER))
|
|
1841
1720
|
];
|
|
1842
1721
|
|
|
1843
1722
|
/**
|
|
@@ -1847,11 +1726,11 @@ class NgxsRootModule {
|
|
|
1847
1726
|
constructor() {
|
|
1848
1727
|
rootStoreInitializer();
|
|
1849
1728
|
}
|
|
1850
|
-
/** @nocollapse */ static
|
|
1851
|
-
/** @nocollapse */ static
|
|
1852
|
-
/** @nocollapse */ static
|
|
1729
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsRootModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1730
|
+
/** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: NgxsRootModule });
|
|
1731
|
+
/** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsRootModule });
|
|
1853
1732
|
}
|
|
1854
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1733
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsRootModule, decorators: [{
|
|
1855
1734
|
type: NgModule
|
|
1856
1735
|
}], ctorParameters: () => [] });
|
|
1857
1736
|
|
|
@@ -1862,11 +1741,11 @@ class NgxsFeatureModule {
|
|
|
1862
1741
|
constructor() {
|
|
1863
1742
|
featureStatesInitializer();
|
|
1864
1743
|
}
|
|
1865
|
-
/** @nocollapse */ static
|
|
1866
|
-
/** @nocollapse */ static
|
|
1867
|
-
/** @nocollapse */ static
|
|
1744
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsFeatureModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1745
|
+
/** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: NgxsFeatureModule });
|
|
1746
|
+
/** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsFeatureModule });
|
|
1868
1747
|
}
|
|
1869
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1748
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsFeatureModule, decorators: [{
|
|
1870
1749
|
type: NgModule
|
|
1871
1750
|
}], ctorParameters: () => [] });
|
|
1872
1751
|
|
|
@@ -1892,10 +1771,6 @@ function getRootProviders(states, options) {
|
|
|
1892
1771
|
{
|
|
1893
1772
|
provide: NGXS_OPTIONS,
|
|
1894
1773
|
useValue: options
|
|
1895
|
-
},
|
|
1896
|
-
{
|
|
1897
|
-
provide: CUSTOM_NGXS_EXECUTION_STRATEGY,
|
|
1898
|
-
useValue: options.executionStrategy
|
|
1899
1774
|
}
|
|
1900
1775
|
];
|
|
1901
1776
|
}
|
|
@@ -1929,11 +1804,11 @@ class NgxsModule {
|
|
|
1929
1804
|
providers: getFeatureProviders(states)
|
|
1930
1805
|
};
|
|
1931
1806
|
}
|
|
1932
|
-
/** @nocollapse */ static
|
|
1933
|
-
/** @nocollapse */ static
|
|
1934
|
-
/** @nocollapse */ static
|
|
1807
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1808
|
+
/** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: NgxsModule });
|
|
1809
|
+
/** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsModule });
|
|
1935
1810
|
}
|
|
1936
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1811
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsModule, decorators: [{
|
|
1937
1812
|
type: NgModule
|
|
1938
1813
|
}] });
|
|
1939
1814
|
|
|
@@ -1945,7 +1820,7 @@ function Action(actions, options) {
|
|
|
1945
1820
|
// This parameter ensures that the decorated method has a call signature that could be passed an instance of the given action(s).
|
|
1946
1821
|
_descriptor) => {
|
|
1947
1822
|
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
1948
|
-
const isStaticMethod = target
|
|
1823
|
+
const isStaticMethod = _hasOwnProperty(target, 'prototype');
|
|
1949
1824
|
if (isStaticMethod) {
|
|
1950
1825
|
throwActionDecoratorError();
|
|
1951
1826
|
}
|
|
@@ -1972,91 +1847,34 @@ function Action(actions, options) {
|
|
|
1972
1847
|
function State(options) {
|
|
1973
1848
|
return (target) => {
|
|
1974
1849
|
const stateClass = target;
|
|
1850
|
+
const inherited = Object.getPrototypeOf(stateClass);
|
|
1975
1851
|
const meta = _ensureStoreMetadata(stateClass);
|
|
1976
|
-
const
|
|
1977
|
-
|
|
1978
|
-
mutateMetaData(
|
|
1979
|
-
stateClass[_META_OPTIONS_KEY] =
|
|
1852
|
+
const mergedOptions = { ...(inherited[_META_OPTIONS_KEY] || {}), ...options };
|
|
1853
|
+
// Apply merged options to metadata.
|
|
1854
|
+
mutateMetaData(meta, inherited, mergedOptions);
|
|
1855
|
+
stateClass[_META_OPTIONS_KEY] = mergedOptions;
|
|
1980
1856
|
};
|
|
1981
1857
|
}
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
function mutateMetaData(params) {
|
|
1987
|
-
const { meta, inheritedStateClass, optionsWithInheritance } = params;
|
|
1988
|
-
const { children, defaults, name } = optionsWithInheritance;
|
|
1989
|
-
const stateName = typeof name === 'string' ? name : (name && name.getName()) || null;
|
|
1858
|
+
// Updates metadata using inherited and current options
|
|
1859
|
+
function mutateMetaData(meta, inherited, options) {
|
|
1860
|
+
const { name, defaults, children } = options;
|
|
1861
|
+
const stateName = typeof name === 'string' ? name : name?.getName?.() || null;
|
|
1990
1862
|
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
1991
1863
|
ensureStateNameIsValid(stateName);
|
|
1992
1864
|
}
|
|
1993
|
-
if (
|
|
1994
|
-
const inheritedMeta =
|
|
1865
|
+
if (_hasOwnProperty(inherited, _META_KEY)) {
|
|
1866
|
+
const inheritedMeta = inherited[_META_KEY] || {};
|
|
1995
1867
|
meta.actions = { ...meta.actions, ...inheritedMeta.actions };
|
|
1996
1868
|
}
|
|
1997
|
-
meta.children = children;
|
|
1998
|
-
meta.defaults = defaults;
|
|
1999
1869
|
meta.name = stateName;
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
const DOLLAR_CHAR_CODE = 36;
|
|
2003
|
-
function createSelectObservable(selector) {
|
|
2004
|
-
if (!SelectFactory.store) {
|
|
2005
|
-
throwSelectFactoryNotConnectedError();
|
|
2006
|
-
}
|
|
2007
|
-
return SelectFactory.store.select(selector);
|
|
2008
|
-
}
|
|
2009
|
-
function createSelectorFn(name, rawSelector, paths = []) {
|
|
2010
|
-
rawSelector = !rawSelector ? removeDollarAtTheEnd(name) : rawSelector;
|
|
2011
|
-
if (typeof rawSelector === 'string') {
|
|
2012
|
-
const propsArray = paths.length
|
|
2013
|
-
? [rawSelector, ...paths]
|
|
2014
|
-
: rawSelector.split('.');
|
|
2015
|
-
return propGetter(propsArray, SelectFactory.config);
|
|
2016
|
-
}
|
|
2017
|
-
return rawSelector;
|
|
2018
|
-
}
|
|
2019
|
-
/**
|
|
2020
|
-
* @example If `foo$` => make it just `foo`
|
|
2021
|
-
*/
|
|
2022
|
-
function removeDollarAtTheEnd(name) {
|
|
2023
|
-
const lastCharIndex = name.length - 1;
|
|
2024
|
-
const dollarAtTheEnd = name.charCodeAt(lastCharIndex) === DOLLAR_CHAR_CODE;
|
|
2025
|
-
return dollarAtTheEnd ? name.slice(0, lastCharIndex) : name;
|
|
2026
|
-
}
|
|
2027
|
-
|
|
2028
|
-
/**
|
|
2029
|
-
* Decorator for selecting a slice of state from the store.
|
|
2030
|
-
*
|
|
2031
|
-
* @deprecated
|
|
2032
|
-
* Read the deprecation notice at this link: https://ngxs.io/deprecations/select-decorator-deprecation.
|
|
2033
|
-
*/
|
|
2034
|
-
function Select(rawSelector, ...paths) {
|
|
2035
|
-
return function (target, key) {
|
|
2036
|
-
const name = key.toString();
|
|
2037
|
-
const selectorId = `__${name}__selector`;
|
|
2038
|
-
const selector = createSelectorFn(name, rawSelector, paths);
|
|
2039
|
-
Object.defineProperties(target, {
|
|
2040
|
-
[selectorId]: {
|
|
2041
|
-
writable: true,
|
|
2042
|
-
enumerable: false,
|
|
2043
|
-
configurable: true
|
|
2044
|
-
},
|
|
2045
|
-
[name]: {
|
|
2046
|
-
enumerable: true,
|
|
2047
|
-
configurable: true,
|
|
2048
|
-
get() {
|
|
2049
|
-
return this[selectorId] || (this[selectorId] = createSelectObservable(selector));
|
|
2050
|
-
}
|
|
2051
|
-
}
|
|
2052
|
-
});
|
|
2053
|
-
};
|
|
1870
|
+
meta.defaults = defaults;
|
|
1871
|
+
meta.children = children;
|
|
2054
1872
|
}
|
|
2055
1873
|
|
|
2056
1874
|
const SELECTOR_OPTIONS_META_KEY = 'NGXS_SELECTOR_OPTIONS_META';
|
|
2057
1875
|
const selectorOptionsMetaAccessor = {
|
|
2058
1876
|
getOptions: (target) => {
|
|
2059
|
-
return
|
|
1877
|
+
return target?.[SELECTOR_OPTIONS_META_KEY] || {};
|
|
2060
1878
|
},
|
|
2061
1879
|
defineOptions: (target, options) => {
|
|
2062
1880
|
if (!target)
|
|
@@ -2119,7 +1937,7 @@ function Selector(selectors) {
|
|
|
2119
1937
|
descriptor ||= Object.getOwnPropertyDescriptor(target, key);
|
|
2120
1938
|
const originalFn = descriptor?.value;
|
|
2121
1939
|
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
2122
|
-
if (
|
|
1940
|
+
if (typeof originalFn !== 'function') {
|
|
2123
1941
|
throwSelectorDecoratorError();
|
|
2124
1942
|
}
|
|
2125
1943
|
}
|
|
@@ -2141,6 +1959,21 @@ function Selector(selectors) {
|
|
|
2141
1959
|
};
|
|
2142
1960
|
}
|
|
2143
1961
|
|
|
1962
|
+
class ActionDirector {
|
|
1963
|
+
_registry = inject(_NgxsActionRegistry);
|
|
1964
|
+
_actionHandlerFactory = inject(InternalActionHandlerFactory);
|
|
1965
|
+
attachAction(stateToken, Action, handlerFn, options = {}) {
|
|
1966
|
+
const actionHandler = this._actionHandlerFactory.createActionHandler(stateToken.getName(), handlerFn, options);
|
|
1967
|
+
this._registry.register(Action.type, actionHandler);
|
|
1968
|
+
}
|
|
1969
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ActionDirector, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1970
|
+
/** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ActionDirector, providedIn: 'root' });
|
|
1971
|
+
}
|
|
1972
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ActionDirector, decorators: [{
|
|
1973
|
+
type: Injectable,
|
|
1974
|
+
args: [{ providedIn: 'root' }]
|
|
1975
|
+
}] });
|
|
1976
|
+
|
|
2144
1977
|
class NgxsDevelopmentModule {
|
|
2145
1978
|
static forRoot(options) {
|
|
2146
1979
|
return {
|
|
@@ -2151,11 +1984,11 @@ class NgxsDevelopmentModule {
|
|
|
2151
1984
|
]
|
|
2152
1985
|
};
|
|
2153
1986
|
}
|
|
2154
|
-
/** @nocollapse */ static
|
|
2155
|
-
/** @nocollapse */ static
|
|
2156
|
-
/** @nocollapse */ static
|
|
1987
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsDevelopmentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1988
|
+
/** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: NgxsDevelopmentModule });
|
|
1989
|
+
/** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsDevelopmentModule });
|
|
2157
1990
|
}
|
|
2158
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1991
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsDevelopmentModule, decorators: [{
|
|
2159
1992
|
type: NgModule
|
|
2160
1993
|
}] });
|
|
2161
1994
|
function withNgxsDevelopmentOptions(options) {
|
|
@@ -2276,19 +2109,60 @@ function createPropertySelectors(parentSelector) {
|
|
|
2276
2109
|
*/
|
|
2277
2110
|
function withNgxsPendingTasks() {
|
|
2278
2111
|
return withNgxsPreboot(() => {
|
|
2279
|
-
const pendingTasks = inject(PendingTasks);
|
|
2280
2112
|
const actions$ = inject(Actions);
|
|
2281
|
-
const
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2113
|
+
const appRef = inject(ApplicationRef);
|
|
2114
|
+
const pendingTasks = inject(PendingTasks);
|
|
2115
|
+
// Removing a pending task via the public API forces a scheduled tick, ensuring that
|
|
2116
|
+
// stability is async and delayed until there was at least an opportunity to run
|
|
2117
|
+
// app synchronization.
|
|
2118
|
+
// Adding a new task every time an action is dispatched drastically increases the
|
|
2119
|
+
// number of change detection cycles because removing a task schedules a new change
|
|
2120
|
+
// detection cycle.
|
|
2121
|
+
// If 10 actions are dispatched with synchronous action handlers, this would trigger
|
|
2122
|
+
// 10 change detection cycles in a row, potentially leading to an
|
|
2123
|
+
// `INFINITE_CHANGE_DETECTION` error.
|
|
2124
|
+
let removeTask = null;
|
|
2125
|
+
const executedActions = new Set();
|
|
2126
|
+
// If the app is forcely destroyed before all actions are completed,
|
|
2127
|
+
// we clean up the set of actions being executed to prevent memory leaks
|
|
2128
|
+
// and remove the pending task to stabilize the app.
|
|
2129
|
+
appRef.onDestroy(() => executedActions.clear());
|
|
2130
|
+
let isStable = false;
|
|
2131
|
+
appRef.whenStable().then(() => {
|
|
2132
|
+
isStable = true;
|
|
2133
|
+
});
|
|
2134
|
+
const subscription = actions$
|
|
2135
|
+
.pipe(filter(context => {
|
|
2136
|
+
if (context.status === ActionStatus.Dispatched) {
|
|
2137
|
+
executedActions.add(context.action);
|
|
2138
|
+
removeTask ||= pendingTasks.add();
|
|
2139
|
+
return false;
|
|
2286
2140
|
}
|
|
2287
2141
|
else {
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2142
|
+
return true;
|
|
2143
|
+
}
|
|
2144
|
+
}),
|
|
2145
|
+
// Every time an action is completed, we debounce the stream to ensure only one
|
|
2146
|
+
// task is removed, even if multiple synchronous actions are completed in a row.
|
|
2147
|
+
// We use `buffer` to collect action contexts because, if we only use
|
|
2148
|
+
// `debounceTime(0)`, we may lose action contexts that are never removed from the set.
|
|
2149
|
+
buffer(actions$.pipe(debounceTime(0))))
|
|
2150
|
+
.subscribe(contexts => {
|
|
2151
|
+
for (const context of contexts) {
|
|
2152
|
+
if (!executedActions.has(context.action)) {
|
|
2153
|
+
continue;
|
|
2154
|
+
}
|
|
2155
|
+
executedActions.delete(context.action);
|
|
2156
|
+
// Mark app as stable once all of the debounced actions have completed.
|
|
2157
|
+
if (executedActions.size === 0) {
|
|
2158
|
+
removeTask?.();
|
|
2159
|
+
removeTask = null;
|
|
2160
|
+
if (isStable) {
|
|
2161
|
+
// Stop contributing to stability once the application has become stable,
|
|
2162
|
+
// which may happen on the server before the platform is destroyed or in
|
|
2163
|
+
// the browser once hydration is complete.
|
|
2164
|
+
subscription.unsubscribe();
|
|
2165
|
+
}
|
|
2292
2166
|
}
|
|
2293
2167
|
}
|
|
2294
2168
|
});
|
|
@@ -2332,6 +2206,9 @@ function isEnvironmentProvider(target) {
|
|
|
2332
2206
|
* }
|
|
2333
2207
|
* ];
|
|
2334
2208
|
* ```
|
|
2209
|
+
*
|
|
2210
|
+
* To lazy-load feature states at the route level,
|
|
2211
|
+
* please refer to the `lazyProvider` utility function.
|
|
2335
2212
|
*/
|
|
2336
2213
|
function provideStates(states, ...features) {
|
|
2337
2214
|
return makeEnvironmentProviders([
|
|
@@ -2363,11 +2240,7 @@ function withNgxsPlugin(plugin) {
|
|
|
2363
2240
|
// We should inject the `PluginManager` to retrieve `NGXS_PLUGINS` and
|
|
2364
2241
|
// register those plugins. The plugin can be added from inside the child
|
|
2365
2242
|
// route, so the plugin manager should be re-injected.
|
|
2366
|
-
|
|
2367
|
-
provide: ENVIRONMENT_INITIALIZER,
|
|
2368
|
-
useValue: () => inject(PluginManager),
|
|
2369
|
-
multi: true
|
|
2370
|
-
}
|
|
2243
|
+
provideEnvironmentInitializer(() => inject(PluginManager))
|
|
2371
2244
|
]);
|
|
2372
2245
|
}
|
|
2373
2246
|
|
|
@@ -2396,24 +2269,79 @@ function dispatch(ActionType) {
|
|
|
2396
2269
|
function createSelectMap(selectorMap) {
|
|
2397
2270
|
const store = inject(Store);
|
|
2398
2271
|
return Object.entries(selectorMap).reduce((accumulator, [key, selector]) => {
|
|
2399
|
-
|
|
2400
|
-
enumerable: true,
|
|
2401
|
-
value: store.selectSignal(selector)
|
|
2402
|
-
});
|
|
2272
|
+
accumulator[key] = store.selectSignal(selector);
|
|
2403
2273
|
return accumulator;
|
|
2404
2274
|
}, {});
|
|
2405
2275
|
}
|
|
2406
2276
|
|
|
2407
2277
|
function createDispatchMap(actionMap) {
|
|
2408
2278
|
return Object.entries(actionMap).reduce((accumulator, [key, ActionType]) => {
|
|
2409
|
-
|
|
2410
|
-
enumerable: true,
|
|
2411
|
-
value: dispatch(ActionType)
|
|
2412
|
-
});
|
|
2279
|
+
accumulator[key] = dispatch(ActionType);
|
|
2413
2280
|
return accumulator;
|
|
2414
2281
|
}, {});
|
|
2415
2282
|
}
|
|
2416
2283
|
|
|
2284
|
+
function isWrappedDefaultExport(value) {
|
|
2285
|
+
return value && typeof value === 'object' && 'default' in value;
|
|
2286
|
+
}
|
|
2287
|
+
function maybeUnwrapDefaultExport(input) {
|
|
2288
|
+
return isWrappedDefaultExport(input) ? input['default'] : input;
|
|
2289
|
+
}
|
|
2290
|
+
const REGISTERED_PROVIDERS = new InjectionToken('', {
|
|
2291
|
+
providedIn: 'root',
|
|
2292
|
+
factory: () => {
|
|
2293
|
+
const registeredProviders = new Set();
|
|
2294
|
+
inject(ApplicationRef).onDestroy(() => registeredProviders.clear());
|
|
2295
|
+
return registeredProviders;
|
|
2296
|
+
}
|
|
2297
|
+
});
|
|
2298
|
+
/**
|
|
2299
|
+
* This function serves as a utility to lazy-load providers at the injection
|
|
2300
|
+
* context level — for example, at the route level. If the feature state needs
|
|
2301
|
+
* to be provided in more than one place, it might be indirectly included in
|
|
2302
|
+
* the main bundle, which we want to avoid. This function can be used at the
|
|
2303
|
+
* guard level to lazy-load the state provider before resolvers run and the
|
|
2304
|
+
* component is initialized:
|
|
2305
|
+
*
|
|
2306
|
+
* ```ts
|
|
2307
|
+
* const routes = [
|
|
2308
|
+
* {
|
|
2309
|
+
* path: 'home',
|
|
2310
|
+
* loadComponent: () => import(...),
|
|
2311
|
+
* canActivate: [
|
|
2312
|
+
* lazyProvider(async () => (await import('path-to-state-library')).invoicesStateProvider)
|
|
2313
|
+
* ]
|
|
2314
|
+
* }
|
|
2315
|
+
* ];
|
|
2316
|
+
* ```
|
|
2317
|
+
*
|
|
2318
|
+
* Where `invoicesStateProvider` is the following:
|
|
2319
|
+
*
|
|
2320
|
+
* ```ts
|
|
2321
|
+
* // path-to-state-library/index.ts
|
|
2322
|
+
*
|
|
2323
|
+
* export const invoicesStateProvider = provideStates([InvoicesState]);
|
|
2324
|
+
* ```
|
|
2325
|
+
*/
|
|
2326
|
+
function lazyProvider(factory) {
|
|
2327
|
+
return async () => {
|
|
2328
|
+
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
2329
|
+
assertInInjectionContext(lazyProvider);
|
|
2330
|
+
}
|
|
2331
|
+
const appRef = inject(ApplicationRef);
|
|
2332
|
+
const parentInjector = inject(EnvironmentInjector);
|
|
2333
|
+
const registeredProviders = inject(REGISTERED_PROVIDERS);
|
|
2334
|
+
const provider = maybeUnwrapDefaultExport(await factory());
|
|
2335
|
+
if (registeredProviders.has(provider)) {
|
|
2336
|
+
return true;
|
|
2337
|
+
}
|
|
2338
|
+
registeredProviders.add(provider);
|
|
2339
|
+
const injector = createEnvironmentInjector([provider], parentInjector);
|
|
2340
|
+
appRef.onDestroy(() => injector.destroy());
|
|
2341
|
+
return true;
|
|
2342
|
+
};
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2417
2345
|
// Backward compatibility is provided because these tokens are used by third-party
|
|
2418
2346
|
// libraries. We expose a separate function to allow tree-shaking of these tokens
|
|
2419
2347
|
// if they are not used in standard applications that do not rely on them.
|
|
@@ -2438,5 +2366,5 @@ function ɵprovideNgxsInternalStateTokens() {
|
|
|
2438
2366
|
* Generated bundle index. Do not edit.
|
|
2439
2367
|
*/
|
|
2440
2368
|
|
|
2441
|
-
export { Action, Actions, NgxsConfig, NgxsDevelopmentModule, NgxsModule, NgxsSimpleChange, NgxsUnhandledActionsLogger, NgxsUnhandledErrorHandler,
|
|
2369
|
+
export { Action, ActionDirector, ActionStatus, Actions, NgxsConfig, NgxsDevelopmentModule, NgxsModule, NgxsSimpleChange, NgxsUnhandledActionsLogger, NgxsUnhandledErrorHandler, Selector, SelectorOptions, State, Store, createDispatchMap, createModelSelector, createPickSelector, createPropertySelectors, createSelectMap, createSelector, dispatch, lazyProvider, ofAction, ofActionCanceled, ofActionCompleted, ofActionDispatched, ofActionErrored, ofActionSuccessful, provideStates, provideStore, select, withNgxsDevelopmentOptions, withNgxsPendingTasks, withNgxsPlugin, withNgxsPreboot, NgxsFeatureModule as ɵNgxsFeatureModule, NgxsRootModule as ɵNgxsRootModule, ɵprovideNgxsInternalStateTokens };
|
|
2442
2370
|
//# sourceMappingURL=ngxs-store.mjs.map
|