UNPKG

57.1 kBJavaScriptView Raw
1import * as i0 from '@angular/core';
2import { Injectable, InjectionToken, Inject, isDevMode, inject, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, NgModule, Optional } from '@angular/core';
3import { BehaviorSubject, Observable, Subject, queueScheduler } from 'rxjs';
4import { observeOn, withLatestFrom, scan, pluck, map, distinctUntilChanged } from 'rxjs/operators';
5
6const REGISTERED_ACTION_TYPES = {};
7function resetRegisteredActionTypes() {
8 for (const key of Object.keys(REGISTERED_ACTION_TYPES)) {
9 delete REGISTERED_ACTION_TYPES[key];
10 }
11}
12
13/**
14 * @description
15 * Creates a configured `Creator` function that, when called, returns an object in the shape of the `Action` interface.
16 *
17 * Action creators reduce the explicitness of class-based action creators.
18 *
19 * @param type Describes the action that will be dispatched
20 * @param config Additional metadata needed for the handling of the action. See {@link createAction#usage-notes Usage Notes}.
21 *
22 * @usageNotes
23 *
24 * **Declaring an action creator**
25 *
26 * Without additional metadata:
27 * ```ts
28 * export const increment = createAction('[Counter] Increment');
29 * ```
30 * With additional metadata:
31 * ```ts
32 * export const loginSuccess = createAction(
33 * '[Auth/API] Login Success',
34 * props<{ user: User }>()
35 * );
36 * ```
37 * With a function:
38 * ```ts
39 * export const loginSuccess = createAction(
40 * '[Auth/API] Login Success',
41 * (response: Response) => response.user
42 * );
43 * ```
44 *
45 * **Dispatching an action**
46 *
47 * Without additional metadata:
48 * ```ts
49 * store.dispatch(increment());
50 * ```
51 * With additional metadata:
52 * ```ts
53 * store.dispatch(loginSuccess({ user: newUser }));
54 * ```
55 *
56 * **Referencing an action in a reducer**
57 *
58 * Using a switch statement:
59 * ```ts
60 * switch (action.type) {
61 * // ...
62 * case AuthApiActions.loginSuccess.type: {
63 * return {
64 * ...state,
65 * user: action.user
66 * };
67 * }
68 * }
69 * ```
70 * Using a reducer creator:
71 * ```ts
72 * on(AuthApiActions.loginSuccess, (state, { user }) => ({ ...state, user }))
73 * ```
74 *
75 * **Referencing an action in an effect**
76 * ```ts
77 * effectName$ = createEffect(
78 * () => this.actions$.pipe(
79 * ofType(AuthApiActions.loginSuccess),
80 * // ...
81 * )
82 * );
83 * ```
84 */
85function createAction(type, config) {
86 REGISTERED_ACTION_TYPES[type] = (REGISTERED_ACTION_TYPES[type] || 0) + 1;
87 if (typeof config === 'function') {
88 return defineType(type, (...args) => ({
89 ...config(...args),
90 type,
91 }));
92 }
93 const as = config ? config._as : 'empty';
94 switch (as) {
95 case 'empty':
96 return defineType(type, () => ({ type }));
97 case 'props':
98 return defineType(type, (props) => ({
99 ...props,
100 type,
101 }));
102 default:
103 throw new Error('Unexpected config.');
104 }
105}
106function props() {
107 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
108 return { _as: 'props', _p: undefined };
109}
110function union(creators) {
111 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
112 return undefined;
113}
114function defineType(type, creator) {
115 return Object.defineProperty(creator, 'type', {
116 value: type,
117 writable: false,
118 });
119}
120
121function capitalize(text) {
122 return (text.charAt(0).toUpperCase() + text.substring(1));
123}
124
125/**
126 * @description
127 * A function that creates a group of action creators with the same source.
128 *
129 * @param config An object that contains a source and dictionary of events.
130 * An event is a key-value pair of an event name and event props.
131 * @returns A dictionary of action creators.
132 * The name of each action creator is created by camel casing the event name.
133 * The type of each action is created using the "[Source] Event Name" pattern.
134 *
135 * @usageNotes
136 *
137 * ```ts
138 * const authApiActions = createActionGroup({
139 * source: 'Auth API',
140 * events: {
141 * // defining events with payload using the `props` function
142 * 'Login Success': props<{ userId: number; token: string }>(),
143 * 'Login Failure': props<{ error: string }>(),
144 *
145 * // defining an event without payload using the `emptyProps` function
146 * 'Logout Success': emptyProps(),
147 *
148 * // defining an event with payload using the props factory
149 * 'Logout Failure': (error: Error) => ({ error }),
150 * },
151 * });
152 *
153 * // action type: "[Auth API] Login Success"
154 * authApiActions.loginSuccess({ userId: 10, token: 'ngrx' });
155 *
156 * // action type: "[Auth API] Login Failure"
157 * authApiActions.loginFailure({ error: 'Login Failure!' });
158 *
159 * // action type: "[Auth API] Logout Success"
160 * authApiActions.logoutSuccess();
161 *
162 * // action type: "[Auth API] Logout Failure";
163 * authApiActions.logoutFailure(new Error('Logout Failure!'));
164 * ```
165 */
166function createActionGroup(config) {
167 const { source, events } = config;
168 return Object.keys(events).reduce((actionGroup, eventName) => ({
169 ...actionGroup,
170 [toActionName(eventName)]: createAction(toActionType(source, eventName), events[eventName]),
171 }), {});
172}
173function emptyProps() {
174 return props();
175}
176function toActionName(eventName) {
177 return eventName
178 .trim()
179 .toLowerCase()
180 .split(' ')
181 .map((word, i) => (i === 0 ? word : capitalize(word)))
182 .join('');
183}
184function toActionType(source, eventName) {
185 return `[${source}] ${eventName}`;
186}
187
188const INIT = '@ngrx/store/init';
189class ActionsSubject extends BehaviorSubject {
190 constructor() {
191 super({ type: INIT });
192 }
193 next(action) {
194 if (typeof action === 'function') {
195 throw new TypeError(`
196 Dispatch expected an object, instead it received a function.
197 If you're using the createAction function, make sure to invoke the function
198 before dispatching the action. For example, someAction should be someAction().`);
199 }
200 else if (typeof action === 'undefined') {
201 throw new TypeError(`Actions must be objects`);
202 }
203 else if (typeof action.type === 'undefined') {
204 throw new TypeError(`Actions must have a type property`);
205 }
206 super.next(action);
207 }
208 complete() {
209 /* noop */
210 }
211 ngOnDestroy() {
212 super.complete();
213 }
214}
215/** @nocollapse */ ActionsSubject.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ActionsSubject, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
216/** @nocollapse */ ActionsSubject.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ActionsSubject });
217i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ActionsSubject, decorators: [{
218 type: Injectable
219 }], ctorParameters: function () { return []; } });
220const ACTIONS_SUBJECT_PROVIDERS = [ActionsSubject];
221
222const _ROOT_STORE_GUARD = new InjectionToken('@ngrx/store Internal Root Guard');
223const _INITIAL_STATE = new InjectionToken('@ngrx/store Internal Initial State');
224const INITIAL_STATE = new InjectionToken('@ngrx/store Initial State');
225const REDUCER_FACTORY = new InjectionToken('@ngrx/store Reducer Factory');
226const _REDUCER_FACTORY = new InjectionToken('@ngrx/store Internal Reducer Factory Provider');
227const INITIAL_REDUCERS = new InjectionToken('@ngrx/store Initial Reducers');
228const _INITIAL_REDUCERS = new InjectionToken('@ngrx/store Internal Initial Reducers');
229const STORE_FEATURES = new InjectionToken('@ngrx/store Store Features');
230const _STORE_REDUCERS = new InjectionToken('@ngrx/store Internal Store Reducers');
231const _FEATURE_REDUCERS = new InjectionToken('@ngrx/store Internal Feature Reducers');
232const _FEATURE_CONFIGS = new InjectionToken('@ngrx/store Internal Feature Configs');
233const _STORE_FEATURES = new InjectionToken('@ngrx/store Internal Store Features');
234const _FEATURE_REDUCERS_TOKEN = new InjectionToken('@ngrx/store Internal Feature Reducers Token');
235const FEATURE_REDUCERS = new InjectionToken('@ngrx/store Feature Reducers');
236/**
237 * User-defined meta reducers from StoreModule.forRoot()
238 */
239const USER_PROVIDED_META_REDUCERS = new InjectionToken('@ngrx/store User Provided Meta Reducers');
240/**
241 * Meta reducers defined either internally by @ngrx/store or by library authors
242 */
243const META_REDUCERS = new InjectionToken('@ngrx/store Meta Reducers');
244/**
245 * Concats the user provided meta reducers and the meta reducers provided on the multi
246 * injection token
247 */
248const _RESOLVED_META_REDUCERS = new InjectionToken('@ngrx/store Internal Resolved Meta Reducers');
249/**
250 * Runtime checks defined by the user via an InjectionToken
251 * Defaults to `_USER_RUNTIME_CHECKS`
252 */
253const USER_RUNTIME_CHECKS = new InjectionToken('@ngrx/store User Runtime Checks Config');
254/**
255 * Runtime checks defined by the user via forRoot()
256 */
257const _USER_RUNTIME_CHECKS = new InjectionToken('@ngrx/store Internal User Runtime Checks Config');
258/**
259 * Runtime checks currently in use
260 */
261const ACTIVE_RUNTIME_CHECKS = new InjectionToken('@ngrx/store Internal Runtime Checks');
262const _ACTION_TYPE_UNIQUENESS_CHECK = new InjectionToken('@ngrx/store Check if Action types are unique');
263/**
264 * InjectionToken that registers the global Store.
265 * Mainly used to provide a hook that can be injected
266 * to ensure the root state is loaded before something
267 * that depends on it.
268 */
269const ROOT_STORE_PROVIDER = new InjectionToken('@ngrx/store Root Store Provider');
270/**
271 * InjectionToken that registers feature states.
272 * Mainly used to provide a hook that can be injected
273 * to ensure feature state is loaded before something
274 * that depends on it.
275 */
276const FEATURE_STATE_PROVIDER = new InjectionToken('@ngrx/store Feature State Provider');
277
278/**
279 * @description
280 * Combines reducers for individual features into a single reducer.
281 *
282 * You can use this function to delegate handling of state transitions to multiple reducers, each acting on their
283 * own sub-state within the root state.
284 *
285 * @param reducers An object mapping keys of the root state to their corresponding feature reducer.
286 * @param initialState Provides a state value if the current state is `undefined`, as it is initially.
287 * @returns A reducer function.
288 *
289 * @usageNotes
290 *
291 * **Example combining two feature reducers into one "root" reducer**
292 *
293 * ```ts
294 * export const reducer = combineReducers({
295 * featureA: featureAReducer,
296 * featureB: featureBReducer
297 * });
298 * ```
299 *
300 * You can also override the initial states of the sub-features:
301 * ```ts
302 * export const reducer = combineReducers({
303 * featureA: featureAReducer,
304 * featureB: featureBReducer
305 * }, {
306 * featureA: { counterA: 13 },
307 * featureB: { counterB: 37 }
308 * });
309 * ```
310 */
311function combineReducers(reducers, initialState = {}) {
312 const reducerKeys = Object.keys(reducers);
313 const finalReducers = {};
314 for (let i = 0; i < reducerKeys.length; i++) {
315 const key = reducerKeys[i];
316 if (typeof reducers[key] === 'function') {
317 finalReducers[key] = reducers[key];
318 }
319 }
320 const finalReducerKeys = Object.keys(finalReducers);
321 return function combination(state, action) {
322 state = state === undefined ? initialState : state;
323 let hasChanged = false;
324 const nextState = {};
325 for (let i = 0; i < finalReducerKeys.length; i++) {
326 const key = finalReducerKeys[i];
327 const reducer = finalReducers[key];
328 const previousStateForKey = state[key];
329 const nextStateForKey = reducer(previousStateForKey, action);
330 nextState[key] = nextStateForKey;
331 hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
332 }
333 return hasChanged ? nextState : state;
334 };
335}
336function omit(object, keyToRemove) {
337 return Object.keys(object)
338 .filter((key) => key !== keyToRemove)
339 .reduce((result, key) => Object.assign(result, { [key]: object[key] }), {});
340}
341function compose(...functions) {
342 return function (arg) {
343 if (functions.length === 0) {
344 return arg;
345 }
346 const last = functions[functions.length - 1];
347 const rest = functions.slice(0, -1);
348 return rest.reduceRight((composed, fn) => fn(composed), last(arg));
349 };
350}
351function createReducerFactory(reducerFactory, metaReducers) {
352 if (Array.isArray(metaReducers) && metaReducers.length > 0) {
353 reducerFactory = compose.apply(null, [
354 ...metaReducers,
355 reducerFactory,
356 ]);
357 }
358 return (reducers, initialState) => {
359 const reducer = reducerFactory(reducers);
360 return (state, action) => {
361 state = state === undefined ? initialState : state;
362 return reducer(state, action);
363 };
364 };
365}
366function createFeatureReducerFactory(metaReducers) {
367 const reducerFactory = Array.isArray(metaReducers) && metaReducers.length > 0
368 ? compose(...metaReducers)
369 : (r) => r;
370 return (reducer, initialState) => {
371 reducer = reducerFactory(reducer);
372 return (state, action) => {
373 state = state === undefined ? initialState : state;
374 return reducer(state, action);
375 };
376 };
377}
378
379class ReducerObservable extends Observable {
380}
381class ReducerManagerDispatcher extends ActionsSubject {
382}
383const UPDATE = '@ngrx/store/update-reducers';
384class ReducerManager extends BehaviorSubject {
385 constructor(dispatcher, initialState, reducers, reducerFactory) {
386 super(reducerFactory(reducers, initialState));
387 this.dispatcher = dispatcher;
388 this.initialState = initialState;
389 this.reducers = reducers;
390 this.reducerFactory = reducerFactory;
391 }
392 get currentReducers() {
393 return this.reducers;
394 }
395 addFeature(feature) {
396 this.addFeatures([feature]);
397 }
398 addFeatures(features) {
399 const reducers = features.reduce((reducerDict, { reducers, reducerFactory, metaReducers, initialState, key }) => {
400 const reducer = typeof reducers === 'function'
401 ? createFeatureReducerFactory(metaReducers)(reducers, initialState)
402 : createReducerFactory(reducerFactory, metaReducers)(reducers, initialState);
403 reducerDict[key] = reducer;
404 return reducerDict;
405 }, {});
406 this.addReducers(reducers);
407 }
408 removeFeature(feature) {
409 this.removeFeatures([feature]);
410 }
411 removeFeatures(features) {
412 this.removeReducers(features.map((p) => p.key));
413 }
414 addReducer(key, reducer) {
415 this.addReducers({ [key]: reducer });
416 }
417 addReducers(reducers) {
418 this.reducers = { ...this.reducers, ...reducers };
419 this.updateReducers(Object.keys(reducers));
420 }
421 removeReducer(featureKey) {
422 this.removeReducers([featureKey]);
423 }
424 removeReducers(featureKeys) {
425 featureKeys.forEach((key) => {
426 this.reducers = omit(this.reducers, key) /*TODO(#823)*/;
427 });
428 this.updateReducers(featureKeys);
429 }
430 updateReducers(featureKeys) {
431 this.next(this.reducerFactory(this.reducers, this.initialState));
432 this.dispatcher.next({
433 type: UPDATE,
434 features: featureKeys,
435 });
436 }
437 ngOnDestroy() {
438 this.complete();
439 }
440}
441/** @nocollapse */ ReducerManager.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ReducerManager, deps: [{ token: ReducerManagerDispatcher }, { token: INITIAL_STATE }, { token: INITIAL_REDUCERS }, { token: REDUCER_FACTORY }], target: i0.ɵɵFactoryTarget.Injectable });
442/** @nocollapse */ ReducerManager.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ReducerManager });
443i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ReducerManager, decorators: [{
444 type: Injectable
445 }], ctorParameters: function () { return [{ type: ReducerManagerDispatcher }, { type: undefined, decorators: [{
446 type: Inject,
447 args: [INITIAL_STATE]
448 }] }, { type: undefined, decorators: [{
449 type: Inject,
450 args: [INITIAL_REDUCERS]
451 }] }, { type: undefined, decorators: [{
452 type: Inject,
453 args: [REDUCER_FACTORY]
454 }] }]; } });
455const REDUCER_MANAGER_PROVIDERS = [
456 ReducerManager,
457 { provide: ReducerObservable, useExisting: ReducerManager },
458 { provide: ReducerManagerDispatcher, useExisting: ActionsSubject },
459];
460
461class ScannedActionsSubject extends Subject {
462 ngOnDestroy() {
463 this.complete();
464 }
465}
466/** @nocollapse */ ScannedActionsSubject.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ScannedActionsSubject, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
467/** @nocollapse */ ScannedActionsSubject.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ScannedActionsSubject });
468i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ScannedActionsSubject, decorators: [{
469 type: Injectable
470 }] });
471const SCANNED_ACTIONS_SUBJECT_PROVIDERS = [
472 ScannedActionsSubject,
473];
474
475class StateObservable extends Observable {
476}
477class State extends BehaviorSubject {
478 constructor(actions$, reducer$, scannedActions, initialState) {
479 super(initialState);
480 const actionsOnQueue$ = actions$.pipe(observeOn(queueScheduler));
481 const withLatestReducer$ = actionsOnQueue$.pipe(withLatestFrom(reducer$));
482 const seed = { state: initialState };
483 const stateAndAction$ = withLatestReducer$.pipe(scan(reduceState, seed));
484 this.stateSubscription = stateAndAction$.subscribe(({ state, action }) => {
485 this.next(state);
486 scannedActions.next(action);
487 });
488 }
489 ngOnDestroy() {
490 this.stateSubscription.unsubscribe();
491 this.complete();
492 }
493}
494State.INIT = INIT;
495/** @nocollapse */ State.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: State, deps: [{ token: ActionsSubject }, { token: ReducerObservable }, { token: ScannedActionsSubject }, { token: INITIAL_STATE }], target: i0.ɵɵFactoryTarget.Injectable });
496/** @nocollapse */ State.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: State });
497i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: State, decorators: [{
498 type: Injectable
499 }], ctorParameters: function () { return [{ type: ActionsSubject }, { type: ReducerObservable }, { type: ScannedActionsSubject }, { type: undefined, decorators: [{
500 type: Inject,
501 args: [INITIAL_STATE]
502 }] }]; } });
503function reduceState(stateActionPair = { state: undefined }, [action, reducer]) {
504 const { state } = stateActionPair;
505 return { state: reducer(state, action), action };
506}
507const STATE_PROVIDERS = [
508 State,
509 { provide: StateObservable, useExisting: State },
510];
511
512// disabled because we have lowercase generics for `select`
513class Store extends Observable {
514 constructor(state$, actionsObserver, reducerManager) {
515 super();
516 this.actionsObserver = actionsObserver;
517 this.reducerManager = reducerManager;
518 this.source = state$;
519 }
520 select(pathOrMapFn, ...paths) {
521 return select.call(null, pathOrMapFn, ...paths)(this);
522 }
523 lift(operator) {
524 const store = new Store(this, this.actionsObserver, this.reducerManager);
525 store.operator = operator;
526 return store;
527 }
528 dispatch(action) {
529 this.actionsObserver.next(action);
530 }
531 next(action) {
532 this.actionsObserver.next(action);
533 }
534 error(err) {
535 this.actionsObserver.error(err);
536 }
537 complete() {
538 this.actionsObserver.complete();
539 }
540 addReducer(key, reducer) {
541 this.reducerManager.addReducer(key, reducer);
542 }
543 removeReducer(key) {
544 this.reducerManager.removeReducer(key);
545 }
546}
547/** @nocollapse */ Store.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: Store, deps: [{ token: StateObservable }, { token: ActionsSubject }, { token: ReducerManager }], target: i0.ɵɵFactoryTarget.Injectable });
548/** @nocollapse */ Store.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: Store });
549i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: Store, decorators: [{
550 type: Injectable
551 }], ctorParameters: function () { return [{ type: StateObservable }, { type: ActionsSubject }, { type: ReducerManager }]; } });
552const STORE_PROVIDERS = [Store];
553function select(pathOrMapFn, propsOrPath, ...paths) {
554 return function selectOperator(source$) {
555 let mapped$;
556 if (typeof pathOrMapFn === 'string') {
557 const pathSlices = [propsOrPath, ...paths].filter(Boolean);
558 mapped$ = source$.pipe(pluck(pathOrMapFn, ...pathSlices));
559 }
560 else if (typeof pathOrMapFn === 'function') {
561 mapped$ = source$.pipe(map((source) => pathOrMapFn(source, propsOrPath)));
562 }
563 else {
564 throw new TypeError(`Unexpected type '${typeof pathOrMapFn}' in select operator,` +
565 ` expected 'string' or 'function'`);
566 }
567 return mapped$.pipe(distinctUntilChanged());
568 };
569}
570
571const RUNTIME_CHECK_URL = 'https://ngrx.io/guide/store/configuration/runtime-checks';
572function isUndefined(target) {
573 return target === undefined;
574}
575function isNull(target) {
576 return target === null;
577}
578function isArray(target) {
579 return Array.isArray(target);
580}
581function isString(target) {
582 return typeof target === 'string';
583}
584function isBoolean(target) {
585 return typeof target === 'boolean';
586}
587function isNumber(target) {
588 return typeof target === 'number';
589}
590function isObjectLike(target) {
591 return typeof target === 'object' && target !== null;
592}
593function isObject(target) {
594 return isObjectLike(target) && !isArray(target);
595}
596function isPlainObject(target) {
597 if (!isObject(target)) {
598 return false;
599 }
600 const targetPrototype = Object.getPrototypeOf(target);
601 return targetPrototype === Object.prototype || targetPrototype === null;
602}
603function isFunction(target) {
604 return typeof target === 'function';
605}
606function isComponent(target) {
607 return isFunction(target) && target.hasOwnProperty('ɵcmp');
608}
609function hasOwnProperty(target, propertyName) {
610 return Object.prototype.hasOwnProperty.call(target, propertyName);
611}
612
613let _ngrxMockEnvironment = false;
614function setNgrxMockEnvironment(value) {
615 _ngrxMockEnvironment = value;
616}
617function isNgrxMockEnvironment() {
618 return _ngrxMockEnvironment;
619}
620
621function isEqualCheck(a, b) {
622 return a === b;
623}
624function isArgumentsChanged(args, lastArguments, comparator) {
625 for (let i = 0; i < args.length; i++) {
626 if (!comparator(args[i], lastArguments[i])) {
627 return true;
628 }
629 }
630 return false;
631}
632function resultMemoize(projectionFn, isResultEqual) {
633 return defaultMemoize(projectionFn, isEqualCheck, isResultEqual);
634}
635function defaultMemoize(projectionFn, isArgumentsEqual = isEqualCheck, isResultEqual = isEqualCheck) {
636 let lastArguments = null;
637 // eslint-disable-next-line @typescript-eslint/no-explicit-any, , , , ,
638 let lastResult = null;
639 let overrideResult;
640 function reset() {
641 lastArguments = null;
642 lastResult = null;
643 }
644 function setResult(result = undefined) {
645 overrideResult = { result };
646 }
647 function clearResult() {
648 overrideResult = undefined;
649 }
650 /* eslint-disable prefer-rest-params, prefer-spread */
651 // disabled because of the use of `arguments`
652 function memoized() {
653 if (overrideResult !== undefined) {
654 return overrideResult.result;
655 }
656 if (!lastArguments) {
657 lastResult = projectionFn.apply(null, arguments);
658 lastArguments = arguments;
659 return lastResult;
660 }
661 if (!isArgumentsChanged(arguments, lastArguments, isArgumentsEqual)) {
662 return lastResult;
663 }
664 const newResult = projectionFn.apply(null, arguments);
665 lastArguments = arguments;
666 if (isResultEqual(lastResult, newResult)) {
667 return lastResult;
668 }
669 lastResult = newResult;
670 return newResult;
671 }
672 return { memoized, reset, setResult, clearResult };
673}
674function createSelector(...input) {
675 return createSelectorFactory(defaultMemoize)(...input);
676}
677function defaultStateFn(state, selectors, props, memoizedProjector) {
678 if (props === undefined) {
679 const args = selectors.map((fn) => fn(state));
680 return memoizedProjector.memoized.apply(null, args);
681 }
682 const args = selectors.map((fn) => fn(state, props));
683 return memoizedProjector.memoized.apply(null, [...args, props]);
684}
685/**
686 *
687 * @param memoize The function used to memoize selectors
688 * @param options Config Object that may include a `stateFn` function defining how to return the selector's value, given the entire `Store`'s state, parent `Selector`s, `Props`, and a `MemoizedProjection`
689 *
690 * @usageNotes
691 *
692 * **Creating a Selector Factory Where Array Order Does Not Matter**
693 *
694 * ```ts
695 * function removeMatch(arr: string[], target: string): string[] {
696 * const matchIndex = arr.indexOf(target);
697 * return [...arr.slice(0, matchIndex), ...arr.slice(matchIndex + 1)];
698 * }
699 *
700 * function orderDoesNotMatterComparer(a: any, b: any): boolean {
701 * if (!Array.isArray(a) || !Array.isArray(b)) {
702 * return a === b;
703 * }
704 * if (a.length !== b.length) {
705 * return false;
706 * }
707 * let tempB = [...b];
708 * function reduceToDetermineIfArraysContainSameContents(
709 * previousCallResult: boolean,
710 * arrayMember: any
711 * ): boolean {
712 * if (previousCallResult === false) {
713 * return false;
714 * }
715 * if (tempB.includes(arrayMember)) {
716 * tempB = removeMatch(tempB, arrayMember);
717 * return true;
718 * }
719 * return false;
720 * }
721 * return a.reduce(reduceToDetermineIfArraysContainSameContents, true);
722 * }
723 *
724 * export const createOrderDoesNotMatterSelector = createSelectorFactory(
725 * (projectionFun) => defaultMemoize(
726 * projectionFun,
727 * orderDoesNotMatterComparer,
728 * orderDoesNotMatterComparer
729 * )
730 * );
731 * ```
732 *
733 * **Creating an Alternative Memoization Strategy**
734 *
735 * ```ts
736 * function serialize(x: any): string {
737 * return JSON.stringify(x);
738 * }
739 *
740 * export const createFullHistorySelector = createSelectorFactory(
741 * (projectionFunction) => {
742 * const cache = {};
743 *
744 * function memoized() {
745 * const serializedArguments = serialize(...arguments);
746 * if (cache[serializedArguments] != null) {
747 * cache[serializedArguments] = projectionFunction.apply(null, arguments);
748 * }
749 * return cache[serializedArguments];
750 * }
751 * return {
752 * memoized,
753 * reset: () => {},
754 * setResult: () => {},
755 * clearResult: () => {},
756 * };
757 * }
758 * );
759 * ```
760 */
761function createSelectorFactory(memoize, options = {
762 stateFn: defaultStateFn,
763}) {
764 return function (...input) {
765 let args = input;
766 if (Array.isArray(args[0])) {
767 const [head, ...tail] = args;
768 args = [...head, ...tail];
769 }
770 else if (args.length === 1 && isSelectorsDictionary(args[0])) {
771 args = extractArgsFromSelectorsDictionary(args[0]);
772 }
773 const selectors = args.slice(0, args.length - 1);
774 const projector = args[args.length - 1];
775 const memoizedSelectors = selectors.filter((selector) => selector.release && typeof selector.release === 'function');
776 const memoizedProjector = memoize(function (...selectors) {
777 return projector.apply(null, selectors);
778 });
779 const memoizedState = defaultMemoize(function (state, props) {
780 return options.stateFn.apply(null, [
781 state,
782 selectors,
783 props,
784 memoizedProjector,
785 ]);
786 });
787 function release() {
788 memoizedState.reset();
789 memoizedProjector.reset();
790 memoizedSelectors.forEach((selector) => selector.release());
791 }
792 return Object.assign(memoizedState.memoized, {
793 release,
794 projector: memoizedProjector.memoized,
795 setResult: memoizedState.setResult,
796 clearResult: memoizedState.clearResult,
797 });
798 };
799}
800function createFeatureSelector(featureName) {
801 return createSelector((state) => {
802 const featureState = state[featureName];
803 if (!isNgrxMockEnvironment() && isDevMode() && !(featureName in state)) {
804 console.warn(`@ngrx/store: The feature name "${featureName}" does ` +
805 'not exist in the state, therefore createFeatureSelector ' +
806 'cannot access it. Be sure it is imported in a loaded module ' +
807 `using StoreModule.forRoot('${featureName}', ...) or ` +
808 `StoreModule.forFeature('${featureName}', ...). If the default ` +
809 'state is intended to be undefined, as is the case with router ' +
810 'state, this development-only warning message can be ignored.');
811 }
812 return featureState;
813 }, (featureState) => featureState);
814}
815function isSelectorsDictionary(selectors) {
816 return (!!selectors &&
817 typeof selectors === 'object' &&
818 Object.values(selectors).every((selector) => typeof selector === 'function'));
819}
820function extractArgsFromSelectorsDictionary(selectorsDictionary) {
821 const selectors = Object.values(selectorsDictionary);
822 const resultKeys = Object.keys(selectorsDictionary);
823 const projector = (...selectorResults) => resultKeys.reduce((result, key, index) => ({
824 ...result,
825 [key]: selectorResults[index],
826 }), {});
827 return [...selectors, projector];
828}
829
830/**
831 * @description
832 * A function that accepts a feature name and a feature reducer, and creates
833 * a feature selector and a selector for each feature state property.
834 * This function also provides the ability to add extra selectors to
835 * the feature object.
836 *
837 * @param featureConfig An object that contains a feature name and a feature
838 * reducer as required, and extra selectors factory as an optional argument.
839 * @returns An object that contains a feature name, a feature reducer,
840 * a feature selector, a selector for each feature state property, and extra
841 * selectors.
842 *
843 * @usageNotes
844 *
845 * ```ts
846 * interface ProductsState {
847 * products: Product[];
848 * selectedId: string | null;
849 * }
850 *
851 * const initialState: ProductsState = {
852 * products: [],
853 * selectedId: null,
854 * };
855 *
856 * const productsFeature = createFeature({
857 * name: 'products',
858 * reducer: createReducer(
859 * initialState,
860 * on(ProductsApiActions.loadSuccess(state, { products }) => ({
861 * ...state,
862 * products,
863 * }),
864 * ),
865 * });
866 *
867 * const {
868 * name,
869 * reducer,
870 * // feature selector
871 * selectProductsState, // type: MemoizedSelector<Record<string, any>, ProductsState>
872 * // feature state properties selectors
873 * selectProducts, // type: MemoizedSelector<Record<string, any>, Product[]>
874 * selectSelectedId, // type: MemoizedSelector<Record<string, any>, string | null>
875 * } = productsFeature;
876 * ```
877 *
878 * **Creating Feature with Extra Selectors**
879 *
880 * ```ts
881 * type CallState = 'init' | 'loading' | 'loaded' | { error: string };
882 *
883 * interface State extends EntityState<Product> {
884 * callState: CallState;
885 * }
886 *
887 * const adapter = createEntityAdapter<Product>();
888 * const initialState: State = adapter.getInitialState({
889 * callState: 'init',
890 * });
891 *
892 * export const productsFeature = createFeature({
893 * name: 'products',
894 * reducer: createReducer(initialState),
895 * extraSelectors: ({ selectProductsState, selectCallState }) => ({
896 * ...adapter.getSelectors(selectBooksState),
897 * ...getCallStateSelectors(selectCallState)
898 * }),
899 * });
900 *
901 * const {
902 * name,
903 * reducer,
904 * // feature selector
905 * selectProductsState,
906 * // feature state properties selectors
907 * selectIds,
908 * selectEntities,
909 * selectCallState,
910 * // selectors returned by `adapter.getSelectors`
911 * selectAll,
912 * selectTotal,
913 * // selectors returned by `getCallStateSelectors`
914 * selectIsLoading,
915 * selectIsLoaded,
916 * selectError,
917 * } = productsFeature;
918 * ```
919 */
920function createFeature(featureConfig) {
921 const { name, reducer, extraSelectors: extraSelectorsFactory, } = featureConfig;
922 const featureSelector = createFeatureSelector(name);
923 const nestedSelectors = createNestedSelectors(featureSelector, reducer);
924 const baseSelectors = {
925 [`select${capitalize(name)}State`]: featureSelector,
926 ...nestedSelectors,
927 };
928 const extraSelectors = extraSelectorsFactory
929 ? extraSelectorsFactory(baseSelectors)
930 : {};
931 return {
932 name,
933 reducer,
934 ...baseSelectors,
935 ...extraSelectors,
936 };
937}
938function createNestedSelectors(featureSelector, reducer) {
939 const initialState = getInitialState(reducer);
940 const nestedKeys = (isPlainObject(initialState) ? Object.keys(initialState) : []);
941 return nestedKeys.reduce((nestedSelectors, nestedKey) => ({
942 ...nestedSelectors,
943 [`select${capitalize(nestedKey)}`]: createSelector(featureSelector, (parentState) => parentState?.[nestedKey]),
944 }), {});
945}
946function getInitialState(reducer) {
947 return reducer(undefined, { type: '@ngrx/feature/init' });
948}
949
950function _createStoreReducers(reducers) {
951 return reducers instanceof InjectionToken ? inject(reducers) : reducers;
952}
953function _createFeatureStore(configs, featureStores) {
954 return featureStores.map((feat, index) => {
955 if (configs[index] instanceof InjectionToken) {
956 const conf = inject(configs[index]);
957 return {
958 key: feat.key,
959 reducerFactory: conf.reducerFactory
960 ? conf.reducerFactory
961 : combineReducers,
962 metaReducers: conf.metaReducers ? conf.metaReducers : [],
963 initialState: conf.initialState,
964 };
965 }
966 return feat;
967 });
968}
969function _createFeatureReducers(reducerCollection) {
970 return reducerCollection.map((reducer) => {
971 return reducer instanceof InjectionToken ? inject(reducer) : reducer;
972 });
973}
974function _initialStateFactory(initialState) {
975 if (typeof initialState === 'function') {
976 return initialState();
977 }
978 return initialState;
979}
980function _concatMetaReducers(metaReducers, userProvidedMetaReducers) {
981 return metaReducers.concat(userProvidedMetaReducers);
982}
983function _provideForRootGuard() {
984 const store = inject(Store, { optional: true, skipSelf: true });
985 if (store) {
986 throw new TypeError(`The root Store has been provided more than once. Feature modules should provide feature states instead.`);
987 }
988 return 'guarded';
989}
990
991function immutabilityCheckMetaReducer(reducer, checks) {
992 return function (state, action) {
993 const act = checks.action(action) ? freeze(action) : action;
994 const nextState = reducer(state, act);
995 return checks.state() ? freeze(nextState) : nextState;
996 };
997}
998function freeze(target) {
999 Object.freeze(target);
1000 const targetIsFunction = isFunction(target);
1001 Object.getOwnPropertyNames(target).forEach((prop) => {
1002 // Ignore Ivy properties, ref: https://github.com/ngrx/platform/issues/2109#issuecomment-582689060
1003 if (prop.startsWith('ɵ')) {
1004 return;
1005 }
1006 if (hasOwnProperty(target, prop) &&
1007 (targetIsFunction
1008 ? prop !== 'caller' && prop !== 'callee' && prop !== 'arguments'
1009 : true)) {
1010 const propValue = target[prop];
1011 if ((isObjectLike(propValue) || isFunction(propValue)) &&
1012 !Object.isFrozen(propValue)) {
1013 freeze(propValue);
1014 }
1015 }
1016 });
1017 return target;
1018}
1019
1020function serializationCheckMetaReducer(reducer, checks) {
1021 return function (state, action) {
1022 if (checks.action(action)) {
1023 const unserializableAction = getUnserializable(action);
1024 throwIfUnserializable(unserializableAction, 'action');
1025 }
1026 const nextState = reducer(state, action);
1027 if (checks.state()) {
1028 const unserializableState = getUnserializable(nextState);
1029 throwIfUnserializable(unserializableState, 'state');
1030 }
1031 return nextState;
1032 };
1033}
1034function getUnserializable(target, path = []) {
1035 // Guard against undefined and null, e.g. a reducer that returns undefined
1036 if ((isUndefined(target) || isNull(target)) && path.length === 0) {
1037 return {
1038 path: ['root'],
1039 value: target,
1040 };
1041 }
1042 const keys = Object.keys(target);
1043 return keys.reduce((result, key) => {
1044 if (result) {
1045 return result;
1046 }
1047 const value = target[key];
1048 // Ignore Ivy components
1049 if (isComponent(value)) {
1050 return result;
1051 }
1052 if (isUndefined(value) ||
1053 isNull(value) ||
1054 isNumber(value) ||
1055 isBoolean(value) ||
1056 isString(value) ||
1057 isArray(value)) {
1058 return false;
1059 }
1060 if (isPlainObject(value)) {
1061 return getUnserializable(value, [...path, key]);
1062 }
1063 return {
1064 path: [...path, key],
1065 value,
1066 };
1067 }, false);
1068}
1069function throwIfUnserializable(unserializable, context) {
1070 if (unserializable === false) {
1071 return;
1072 }
1073 const unserializablePath = unserializable.path.join('.');
1074 const error = new Error(`Detected unserializable ${context} at "${unserializablePath}". ${RUNTIME_CHECK_URL}#strict${context}serializability`);
1075 error.value = unserializable.value;
1076 error.unserializablePath = unserializablePath;
1077 throw error;
1078}
1079
1080function inNgZoneAssertMetaReducer(reducer, checks) {
1081 return function (state, action) {
1082 if (checks.action(action) && !i0.NgZone.isInAngularZone()) {
1083 throw new Error(`Action '${action.type}' running outside NgZone. ${RUNTIME_CHECK_URL}#strictactionwithinngzone`);
1084 }
1085 return reducer(state, action);
1086 };
1087}
1088
1089function createActiveRuntimeChecks(runtimeChecks) {
1090 if (isDevMode()) {
1091 return {
1092 strictStateSerializability: false,
1093 strictActionSerializability: false,
1094 strictStateImmutability: true,
1095 strictActionImmutability: true,
1096 strictActionWithinNgZone: false,
1097 strictActionTypeUniqueness: false,
1098 ...runtimeChecks,
1099 };
1100 }
1101 return {
1102 strictStateSerializability: false,
1103 strictActionSerializability: false,
1104 strictStateImmutability: false,
1105 strictActionImmutability: false,
1106 strictActionWithinNgZone: false,
1107 strictActionTypeUniqueness: false,
1108 };
1109}
1110function createSerializationCheckMetaReducer({ strictActionSerializability, strictStateSerializability, }) {
1111 return (reducer) => strictActionSerializability || strictStateSerializability
1112 ? serializationCheckMetaReducer(reducer, {
1113 action: (action) => strictActionSerializability && !ignoreNgrxAction(action),
1114 state: () => strictStateSerializability,
1115 })
1116 : reducer;
1117}
1118function createImmutabilityCheckMetaReducer({ strictActionImmutability, strictStateImmutability, }) {
1119 return (reducer) => strictActionImmutability || strictStateImmutability
1120 ? immutabilityCheckMetaReducer(reducer, {
1121 action: (action) => strictActionImmutability && !ignoreNgrxAction(action),
1122 state: () => strictStateImmutability,
1123 })
1124 : reducer;
1125}
1126function ignoreNgrxAction(action) {
1127 return action.type.startsWith('@ngrx');
1128}
1129function createInNgZoneCheckMetaReducer({ strictActionWithinNgZone, }) {
1130 return (reducer) => strictActionWithinNgZone
1131 ? inNgZoneAssertMetaReducer(reducer, {
1132 action: (action) => strictActionWithinNgZone && !ignoreNgrxAction(action),
1133 })
1134 : reducer;
1135}
1136function provideRuntimeChecks(runtimeChecks) {
1137 return [
1138 {
1139 provide: _USER_RUNTIME_CHECKS,
1140 useValue: runtimeChecks,
1141 },
1142 {
1143 provide: USER_RUNTIME_CHECKS,
1144 useFactory: _runtimeChecksFactory,
1145 deps: [_USER_RUNTIME_CHECKS],
1146 },
1147 {
1148 provide: ACTIVE_RUNTIME_CHECKS,
1149 deps: [USER_RUNTIME_CHECKS],
1150 useFactory: createActiveRuntimeChecks,
1151 },
1152 {
1153 provide: META_REDUCERS,
1154 multi: true,
1155 deps: [ACTIVE_RUNTIME_CHECKS],
1156 useFactory: createImmutabilityCheckMetaReducer,
1157 },
1158 {
1159 provide: META_REDUCERS,
1160 multi: true,
1161 deps: [ACTIVE_RUNTIME_CHECKS],
1162 useFactory: createSerializationCheckMetaReducer,
1163 },
1164 {
1165 provide: META_REDUCERS,
1166 multi: true,
1167 deps: [ACTIVE_RUNTIME_CHECKS],
1168 useFactory: createInNgZoneCheckMetaReducer,
1169 },
1170 ];
1171}
1172function checkForActionTypeUniqueness() {
1173 return [
1174 {
1175 provide: _ACTION_TYPE_UNIQUENESS_CHECK,
1176 multi: true,
1177 deps: [ACTIVE_RUNTIME_CHECKS],
1178 useFactory: _actionTypeUniquenessCheck,
1179 },
1180 ];
1181}
1182function _runtimeChecksFactory(runtimeChecks) {
1183 return runtimeChecks;
1184}
1185function _actionTypeUniquenessCheck(config) {
1186 if (!config.strictActionTypeUniqueness) {
1187 return;
1188 }
1189 const duplicates = Object.entries(REGISTERED_ACTION_TYPES)
1190 .filter(([, registrations]) => registrations > 1)
1191 .map(([type]) => type);
1192 if (duplicates.length) {
1193 throw new Error(`Action types are registered more than once, ${duplicates
1194 .map((type) => `"${type}"`)
1195 .join(', ')}. ${RUNTIME_CHECK_URL}#strictactiontypeuniqueness`);
1196 }
1197}
1198
1199/**
1200 * Provides additional slices of state in the Store.
1201 * These providers cannot be used at the component level.
1202 *
1203 * @usageNotes
1204 *
1205 * ### Providing Store Features
1206 *
1207 * ```ts
1208 * const booksRoutes: Route[] = [
1209 * {
1210 * path: '',
1211 * providers: [provideState('books', booksReducer)],
1212 * children: [
1213 * { path: '', component: BookListComponent },
1214 * { path: ':id', component: BookDetailsComponent },
1215 * ],
1216 * },
1217 * ];
1218 * ```
1219 */
1220function provideState(featureNameOrSlice, reducers, config = {}) {
1221 return makeEnvironmentProviders([
1222 ..._provideState(featureNameOrSlice, reducers, config),
1223 ENVIRONMENT_STATE_PROVIDER,
1224 ]);
1225}
1226function _provideStore(reducers = {}, config = {}) {
1227 return [
1228 {
1229 provide: _ROOT_STORE_GUARD,
1230 useFactory: _provideForRootGuard,
1231 },
1232 { provide: _INITIAL_STATE, useValue: config.initialState },
1233 {
1234 provide: INITIAL_STATE,
1235 useFactory: _initialStateFactory,
1236 deps: [_INITIAL_STATE],
1237 },
1238 { provide: _INITIAL_REDUCERS, useValue: reducers },
1239 {
1240 provide: _STORE_REDUCERS,
1241 useExisting: reducers instanceof InjectionToken ? reducers : _INITIAL_REDUCERS,
1242 },
1243 {
1244 provide: INITIAL_REDUCERS,
1245 deps: [_INITIAL_REDUCERS, [new Inject(_STORE_REDUCERS)]],
1246 useFactory: _createStoreReducers,
1247 },
1248 {
1249 provide: USER_PROVIDED_META_REDUCERS,
1250 useValue: config.metaReducers ? config.metaReducers : [],
1251 },
1252 {
1253 provide: _RESOLVED_META_REDUCERS,
1254 deps: [META_REDUCERS, USER_PROVIDED_META_REDUCERS],
1255 useFactory: _concatMetaReducers,
1256 },
1257 {
1258 provide: _REDUCER_FACTORY,
1259 useValue: config.reducerFactory ? config.reducerFactory : combineReducers,
1260 },
1261 {
1262 provide: REDUCER_FACTORY,
1263 deps: [_REDUCER_FACTORY, _RESOLVED_META_REDUCERS],
1264 useFactory: createReducerFactory,
1265 },
1266 ACTIONS_SUBJECT_PROVIDERS,
1267 REDUCER_MANAGER_PROVIDERS,
1268 SCANNED_ACTIONS_SUBJECT_PROVIDERS,
1269 STATE_PROVIDERS,
1270 STORE_PROVIDERS,
1271 provideRuntimeChecks(config.runtimeChecks),
1272 checkForActionTypeUniqueness(),
1273 ];
1274}
1275function rootStoreProviderFactory() {
1276 inject(ActionsSubject);
1277 inject(ReducerObservable);
1278 inject(ScannedActionsSubject);
1279 inject(Store);
1280 inject(_ROOT_STORE_GUARD, { optional: true });
1281 inject(_ACTION_TYPE_UNIQUENESS_CHECK, { optional: true });
1282}
1283/**
1284 * Environment Initializer used in the root
1285 * providers to initialize the Store
1286 */
1287const ENVIRONMENT_STORE_PROVIDER = [
1288 { provide: ROOT_STORE_PROVIDER, useFactory: rootStoreProviderFactory },
1289 {
1290 provide: ENVIRONMENT_INITIALIZER,
1291 multi: true,
1292 useFactory() {
1293 return () => inject(ROOT_STORE_PROVIDER);
1294 },
1295 },
1296];
1297/**
1298 * Provides the global Store providers and initializes
1299 * the Store.
1300 * These providers cannot be used at the component level.
1301 *
1302 * @usageNotes
1303 *
1304 * ### Providing the Global Store
1305 *
1306 * ```ts
1307 * bootstrapApplication(AppComponent, {
1308 * providers: [provideStore()],
1309 * });
1310 * ```
1311 */
1312function provideStore(reducers, config) {
1313 return makeEnvironmentProviders([
1314 ..._provideStore(reducers, config),
1315 ENVIRONMENT_STORE_PROVIDER,
1316 ]);
1317}
1318function featureStateProviderFactory() {
1319 inject(ROOT_STORE_PROVIDER);
1320 const features = inject(_STORE_FEATURES);
1321 const featureReducers = inject(FEATURE_REDUCERS);
1322 const reducerManager = inject(ReducerManager);
1323 inject(_ACTION_TYPE_UNIQUENESS_CHECK, { optional: true });
1324 const feats = features.map((feature, index) => {
1325 const featureReducerCollection = featureReducers.shift();
1326 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1327 const reducers = featureReducerCollection /*TODO(#823)*/[index];
1328 return {
1329 ...feature,
1330 reducers,
1331 initialState: _initialStateFactory(feature.initialState),
1332 };
1333 });
1334 reducerManager.addFeatures(feats);
1335}
1336/**
1337 * Environment Initializer used in the feature
1338 * providers to register state features
1339 */
1340const ENVIRONMENT_STATE_PROVIDER = [
1341 {
1342 provide: FEATURE_STATE_PROVIDER,
1343 useFactory: featureStateProviderFactory,
1344 },
1345 {
1346 provide: ENVIRONMENT_INITIALIZER,
1347 multi: true,
1348 useFactory() {
1349 return () => inject(FEATURE_STATE_PROVIDER);
1350 },
1351 },
1352];
1353function _provideState(featureNameOrSlice, reducers, config = {}) {
1354 return [
1355 {
1356 provide: _FEATURE_CONFIGS,
1357 multi: true,
1358 useValue: featureNameOrSlice instanceof Object ? {} : config,
1359 },
1360 {
1361 provide: STORE_FEATURES,
1362 multi: true,
1363 useValue: {
1364 key: featureNameOrSlice instanceof Object
1365 ? featureNameOrSlice.name
1366 : featureNameOrSlice,
1367 reducerFactory: !(config instanceof InjectionToken) && config.reducerFactory
1368 ? config.reducerFactory
1369 : combineReducers,
1370 metaReducers: !(config instanceof InjectionToken) && config.metaReducers
1371 ? config.metaReducers
1372 : [],
1373 initialState: !(config instanceof InjectionToken) && config.initialState
1374 ? config.initialState
1375 : undefined,
1376 },
1377 },
1378 {
1379 provide: _STORE_FEATURES,
1380 deps: [_FEATURE_CONFIGS, STORE_FEATURES],
1381 useFactory: _createFeatureStore,
1382 },
1383 {
1384 provide: _FEATURE_REDUCERS,
1385 multi: true,
1386 useValue: featureNameOrSlice instanceof Object
1387 ? featureNameOrSlice.reducer
1388 : reducers,
1389 },
1390 {
1391 provide: _FEATURE_REDUCERS_TOKEN,
1392 multi: true,
1393 useExisting: reducers instanceof InjectionToken ? reducers : _FEATURE_REDUCERS,
1394 },
1395 {
1396 provide: FEATURE_REDUCERS,
1397 multi: true,
1398 deps: [_FEATURE_REDUCERS, [new Inject(_FEATURE_REDUCERS_TOKEN)]],
1399 useFactory: _createFeatureReducers,
1400 },
1401 checkForActionTypeUniqueness(),
1402 ];
1403}
1404
1405class StoreRootModule {
1406 constructor(actions$, reducer$, scannedActions$, store, guard, actionCheck) { }
1407}
1408/** @nocollapse */ StoreRootModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: StoreRootModule, deps: [{ token: ActionsSubject }, { token: ReducerObservable }, { token: ScannedActionsSubject }, { token: Store }, { token: _ROOT_STORE_GUARD, optional: true }, { token: _ACTION_TYPE_UNIQUENESS_CHECK, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
1409/** @nocollapse */ StoreRootModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.0.0", ngImport: i0, type: StoreRootModule });
1410/** @nocollapse */ StoreRootModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: StoreRootModule });
1411i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: StoreRootModule, decorators: [{
1412 type: NgModule,
1413 args: [{}]
1414 }], ctorParameters: function () { return [{ type: ActionsSubject }, { type: ReducerObservable }, { type: ScannedActionsSubject }, { type: Store }, { type: undefined, decorators: [{
1415 type: Optional
1416 }, {
1417 type: Inject,
1418 args: [_ROOT_STORE_GUARD]
1419 }] }, { type: undefined, decorators: [{
1420 type: Optional
1421 }, {
1422 type: Inject,
1423 args: [_ACTION_TYPE_UNIQUENESS_CHECK]
1424 }] }]; } });
1425class StoreFeatureModule {
1426 constructor(features, featureReducers, reducerManager, root, actionCheck) {
1427 this.features = features;
1428 this.featureReducers = featureReducers;
1429 this.reducerManager = reducerManager;
1430 const feats = features.map((feature, index) => {
1431 const featureReducerCollection = featureReducers.shift();
1432 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1433 const reducers = featureReducerCollection /*TODO(#823)*/[index];
1434 return {
1435 ...feature,
1436 reducers,
1437 initialState: _initialStateFactory(feature.initialState),
1438 };
1439 });
1440 reducerManager.addFeatures(feats);
1441 }
1442 // eslint-disable-next-line @angular-eslint/contextual-lifecycle
1443 ngOnDestroy() {
1444 this.reducerManager.removeFeatures(this.features);
1445 }
1446}
1447/** @nocollapse */ StoreFeatureModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: StoreFeatureModule, deps: [{ token: _STORE_FEATURES }, { token: FEATURE_REDUCERS }, { token: ReducerManager }, { token: StoreRootModule }, { token: _ACTION_TYPE_UNIQUENESS_CHECK, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
1448/** @nocollapse */ StoreFeatureModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.0.0", ngImport: i0, type: StoreFeatureModule });
1449/** @nocollapse */ StoreFeatureModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: StoreFeatureModule });
1450i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: StoreFeatureModule, decorators: [{
1451 type: NgModule,
1452 args: [{}]
1453 }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1454 type: Inject,
1455 args: [_STORE_FEATURES]
1456 }] }, { type: undefined, decorators: [{
1457 type: Inject,
1458 args: [FEATURE_REDUCERS]
1459 }] }, { type: ReducerManager }, { type: StoreRootModule }, { type: undefined, decorators: [{
1460 type: Optional
1461 }, {
1462 type: Inject,
1463 args: [_ACTION_TYPE_UNIQUENESS_CHECK]
1464 }] }]; } });
1465class StoreModule {
1466 static forRoot(reducers, config) {
1467 return {
1468 ngModule: StoreRootModule,
1469 providers: [..._provideStore(reducers, config)],
1470 };
1471 }
1472 static forFeature(featureNameOrSlice, reducers, config = {}) {
1473 return {
1474 ngModule: StoreFeatureModule,
1475 providers: [..._provideState(featureNameOrSlice, reducers, config)],
1476 };
1477 }
1478}
1479/** @nocollapse */ StoreModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: StoreModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1480/** @nocollapse */ StoreModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.0.0", ngImport: i0, type: StoreModule });
1481/** @nocollapse */ StoreModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: StoreModule });
1482i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: StoreModule, decorators: [{
1483 type: NgModule,
1484 args: [{}]
1485 }] });
1486
1487/**
1488 * @description
1489 * Associates actions with a given state change function.
1490 * A state change function must be provided as the last parameter.
1491 *
1492 * @param args `ActionCreator`'s followed by a state change function.
1493 *
1494 * @returns an association of action types with a state change function.
1495 *
1496 * @usageNotes
1497 * ```ts
1498 * on(AuthApiActions.loginSuccess, (state, { user }) => ({ ...state, user }))
1499 * ```
1500 */
1501function on(...args) {
1502 const reducer = args.pop();
1503 const types = args.map((creator) => creator.type);
1504 return { reducer, types };
1505}
1506/**
1507 * @description
1508 * Creates a reducer function to handle state transitions.
1509 *
1510 * Reducer creators reduce the explicitness of reducer functions with switch statements.
1511 *
1512 * @param initialState Provides a state value if the current state is `undefined`, as it is initially.
1513 * @param ons Associations between actions and state changes.
1514 * @returns A reducer function.
1515 *
1516 * @usageNotes
1517 *
1518 * - Must be used with `ActionCreator`'s (returned by `createAction`). Cannot be used with class-based action creators.
1519 * - The returned `ActionReducer` does not require being wrapped with another function.
1520 *
1521 * **Declaring a reducer creator**
1522 *
1523 * ```ts
1524 * export const reducer = createReducer(
1525 * initialState,
1526 * on(
1527 * featureActions.actionOne,
1528 * featureActions.actionTwo,
1529 * (state, { updatedValue }) => ({ ...state, prop: updatedValue })
1530 * ),
1531 * on(featureActions.actionThree, () => initialState);
1532 * );
1533 * ```
1534 */
1535function createReducer(initialState, ...ons) {
1536 const map = new Map();
1537 for (const on of ons) {
1538 for (const type of on.types) {
1539 const existingReducer = map.get(type);
1540 if (existingReducer) {
1541 const newReducer = (state, action) => on.reducer(existingReducer(state, action), action);
1542 map.set(type, newReducer);
1543 }
1544 else {
1545 map.set(type, on.reducer);
1546 }
1547 }
1548 }
1549 return function (state = initialState, action) {
1550 const reducer = map.get(action.type);
1551 return reducer ? reducer(state, action) : state;
1552 };
1553}
1554
1555/**
1556 * DO NOT EDIT
1557 *
1558 * This file is automatically generated at build
1559 */
1560
1561/**
1562 * Generated bundle index. Do not edit.
1563 */
1564
1565export { ACTIVE_RUNTIME_CHECKS, ActionsSubject, FEATURE_REDUCERS, FEATURE_STATE_PROVIDER, INIT, INITIAL_REDUCERS, INITIAL_STATE, META_REDUCERS, REDUCER_FACTORY, ROOT_STORE_PROVIDER, ReducerManager, ReducerManagerDispatcher, ReducerObservable, STORE_FEATURES, ScannedActionsSubject, State, StateObservable, Store, StoreFeatureModule, StoreModule, StoreRootModule, UPDATE, USER_PROVIDED_META_REDUCERS, USER_RUNTIME_CHECKS, combineReducers, compose, createAction, createActionGroup, createFeature, createFeatureSelector, createReducer, createReducerFactory, createSelector, createSelectorFactory, defaultMemoize, defaultStateFn, emptyProps, isNgrxMockEnvironment, on, props, provideState, provideStore, reduceState, resultMemoize, select, setNgrxMockEnvironment, union };
1566//# sourceMappingURL=ngrx-store.mjs.map
1567//# sourceMappingURL=ngrx-store.mjs.map