@angular-architects/ngrx-toolkit 19.3.0 → 19.4.0

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.
Files changed (126) hide show
  1. package/eslint.config.cjs +43 -0
  2. package/jest.config.ts +22 -0
  3. package/ng-package.json +7 -0
  4. package/package.json +4 -21
  5. package/project.json +37 -0
  6. package/redux-connector/docs/README.md +131 -0
  7. package/redux-connector/index.ts +6 -0
  8. package/redux-connector/ng-package.json +5 -0
  9. package/redux-connector/src/lib/create-redux.ts +102 -0
  10. package/redux-connector/src/lib/model.ts +89 -0
  11. package/redux-connector/src/lib/rxjs-interop/redux-method.ts +66 -0
  12. package/redux-connector/src/lib/signal-redux-store.ts +59 -0
  13. package/redux-connector/src/lib/util.ts +22 -0
  14. package/{index.d.ts → src/index.ts} +35 -6
  15. package/src/lib/assertions/assertions.ts +9 -0
  16. package/{lib/devtools/features/with-disabled-name-indicies.d.ts → src/lib/devtools/features/with-disabled-name-indicies.ts} +5 -1
  17. package/{lib/devtools/features/with-glitch-tracking.d.ts → src/lib/devtools/features/with-glitch-tracking.ts} +6 -1
  18. package/{lib/devtools/features/with-mapper.d.ts → src/lib/devtools/features/with-mapper.ts} +7 -1
  19. package/src/lib/devtools/internal/current-action-names.ts +1 -0
  20. package/src/lib/devtools/internal/default-tracker.ts +60 -0
  21. package/src/lib/devtools/internal/devtools-feature.ts +37 -0
  22. package/src/lib/devtools/internal/devtools-syncer.service.ts +202 -0
  23. package/src/lib/devtools/internal/glitch-tracker.service.ts +61 -0
  24. package/src/lib/devtools/internal/models.ts +29 -0
  25. package/{lib/devtools/provide-devtools-config.d.ts → src/lib/devtools/provide-devtools-config.ts} +16 -4
  26. package/src/lib/devtools/rename-devtools-name.ts +21 -0
  27. package/src/lib/devtools/tests/action-name.spec.ts +48 -0
  28. package/src/lib/devtools/tests/basic.spec.ts +111 -0
  29. package/src/lib/devtools/tests/connecting.spec.ts +37 -0
  30. package/src/lib/devtools/tests/helpers.spec.ts +43 -0
  31. package/src/lib/devtools/tests/naming.spec.ts +216 -0
  32. package/src/lib/devtools/tests/provide-devtools-config.spec.ts +25 -0
  33. package/src/lib/devtools/tests/types.spec.ts +19 -0
  34. package/src/lib/devtools/tests/update-state.spec.ts +29 -0
  35. package/src/lib/devtools/tests/with-devtools.spec.ts +5 -0
  36. package/src/lib/devtools/tests/with-glitch-tracking.spec.ts +272 -0
  37. package/src/lib/devtools/tests/with-mapper.spec.ts +69 -0
  38. package/src/lib/devtools/update-state.ts +38 -0
  39. package/{lib/devtools/with-dev-tools-stub.d.ts → src/lib/devtools/with-dev-tools-stub.ts} +2 -1
  40. package/src/lib/devtools/with-devtools.ts +81 -0
  41. package/src/lib/flattening-operator.ts +42 -0
  42. package/src/lib/immutable-state/deep-freeze.ts +43 -0
  43. package/src/lib/immutable-state/is-dev-mode.ts +6 -0
  44. package/src/lib/immutable-state/tests/with-immutable-state.spec.ts +260 -0
  45. package/src/lib/immutable-state/with-immutable-state.ts +115 -0
  46. package/src/lib/mutation/http-mutation.spec.ts +473 -0
  47. package/src/lib/mutation/http-mutation.ts +172 -0
  48. package/src/lib/mutation/mutation.ts +26 -0
  49. package/src/lib/mutation/rx-mutation.spec.ts +594 -0
  50. package/src/lib/mutation/rx-mutation.ts +208 -0
  51. package/src/lib/shared/prettify.ts +3 -0
  52. package/{lib/shared/signal-store-models.d.ts → src/lib/shared/signal-store-models.ts} +8 -4
  53. package/src/lib/shared/throw-if-null.ts +7 -0
  54. package/src/lib/storage-sync/features/with-indexed-db.ts +81 -0
  55. package/src/lib/storage-sync/features/with-local-storage.ts +58 -0
  56. package/src/lib/storage-sync/internal/indexeddb.service.ts +124 -0
  57. package/src/lib/storage-sync/internal/local-storage.service.ts +19 -0
  58. package/src/lib/storage-sync/internal/models.ts +62 -0
  59. package/src/lib/storage-sync/internal/session-storage.service.ts +18 -0
  60. package/src/lib/storage-sync/tests/indexeddb.service.spec.ts +99 -0
  61. package/src/lib/storage-sync/tests/with-storage-async.spec.ts +308 -0
  62. package/src/lib/storage-sync/tests/with-storage-sync.spec.ts +268 -0
  63. package/src/lib/storage-sync/with-storage-sync.ts +233 -0
  64. package/src/lib/with-call-state.spec.ts +42 -0
  65. package/src/lib/with-call-state.ts +195 -0
  66. package/src/lib/with-conditional.spec.ts +125 -0
  67. package/{lib/with-conditional.d.ts → src/lib/with-conditional.ts} +31 -7
  68. package/src/lib/with-data-service.spec.ts +564 -0
  69. package/src/lib/with-data-service.ts +433 -0
  70. package/src/lib/with-feature-factory.spec.ts +69 -0
  71. package/{lib/with-feature-factory.d.ts → src/lib/with-feature-factory.ts} +32 -4
  72. package/src/lib/with-mutations.spec.ts +537 -0
  73. package/src/lib/with-mutations.ts +146 -0
  74. package/src/lib/with-pagination.spec.ts +90 -0
  75. package/src/lib/with-pagination.ts +353 -0
  76. package/src/lib/with-redux.spec.ts +258 -0
  77. package/src/lib/with-redux.ts +387 -0
  78. package/src/lib/with-reset.spec.ts +112 -0
  79. package/src/lib/with-reset.ts +62 -0
  80. package/src/lib/with-undo-redo.spec.ts +287 -0
  81. package/src/lib/with-undo-redo.ts +199 -0
  82. package/src/test-setup.ts +8 -0
  83. package/tsconfig.json +29 -0
  84. package/tsconfig.lib.json +17 -0
  85. package/tsconfig.lib.prod.json +9 -0
  86. package/tsconfig.spec.json +17 -0
  87. package/fesm2022/angular-architects-ngrx-toolkit-redux-connector.mjs +0 -119
  88. package/fesm2022/angular-architects-ngrx-toolkit-redux-connector.mjs.map +0 -1
  89. package/fesm2022/angular-architects-ngrx-toolkit.mjs +0 -1967
  90. package/fesm2022/angular-architects-ngrx-toolkit.mjs.map +0 -1
  91. package/lib/assertions/assertions.d.ts +0 -2
  92. package/lib/devtools/internal/current-action-names.d.ts +0 -1
  93. package/lib/devtools/internal/default-tracker.d.ts +0 -13
  94. package/lib/devtools/internal/devtools-feature.d.ts +0 -24
  95. package/lib/devtools/internal/devtools-syncer.service.d.ts +0 -35
  96. package/lib/devtools/internal/glitch-tracker.service.d.ts +0 -18
  97. package/lib/devtools/internal/models.d.ts +0 -24
  98. package/lib/devtools/rename-devtools-name.d.ts +0 -7
  99. package/lib/devtools/update-state.d.ts +0 -15
  100. package/lib/devtools/with-devtools.d.ts +0 -24
  101. package/lib/flattening-operator.d.ts +0 -14
  102. package/lib/immutable-state/deep-freeze.d.ts +0 -11
  103. package/lib/immutable-state/is-dev-mode.d.ts +0 -1
  104. package/lib/immutable-state/with-immutable-state.d.ts +0 -60
  105. package/lib/rx-mutation.d.ts +0 -58
  106. package/lib/shared/throw-if-null.d.ts +0 -1
  107. package/lib/storage-sync/features/with-indexed-db.d.ts +0 -2
  108. package/lib/storage-sync/features/with-local-storage.d.ts +0 -3
  109. package/lib/storage-sync/internal/indexeddb.service.d.ts +0 -29
  110. package/lib/storage-sync/internal/local-storage.service.d.ts +0 -8
  111. package/lib/storage-sync/internal/models.d.ts +0 -45
  112. package/lib/storage-sync/internal/session-storage.service.d.ts +0 -8
  113. package/lib/storage-sync/with-storage-sync.d.ts +0 -45
  114. package/lib/with-call-state.d.ts +0 -58
  115. package/lib/with-data-service.d.ts +0 -109
  116. package/lib/with-mutations.d.ts +0 -66
  117. package/lib/with-pagination.d.ts +0 -98
  118. package/lib/with-redux.d.ts +0 -147
  119. package/lib/with-reset.d.ts +0 -29
  120. package/lib/with-undo-redo.d.ts +0 -31
  121. package/redux-connector/index.d.ts +0 -2
  122. package/redux-connector/src/lib/create-redux.d.ts +0 -13
  123. package/redux-connector/src/lib/model.d.ts +0 -40
  124. package/redux-connector/src/lib/rxjs-interop/redux-method.d.ts +0 -14
  125. package/redux-connector/src/lib/signal-redux-store.d.ts +0 -11
  126. package/redux-connector/src/lib/util.d.ts +0 -5
@@ -1,147 +0,0 @@
1
- import { EmptyFeatureResult, SignalStoreFeature, SignalStoreFeatureResult, WritableStateSource } from '@ngrx/signals';
2
- import { Observable } from 'rxjs';
3
- /** Actions **/
4
- type Payload = Record<string, unknown>;
5
- type ActionFn<Type extends string = string, ActionPayload extends Payload = Payload> = ((payload: ActionPayload) => ActionPayload & {
6
- type: Type;
7
- }) & {
8
- type: Type;
9
- };
10
- type ActionFns = Record<string, ActionFn>;
11
- export type ActionsFnSpecs = Record<string, Payload>;
12
- type ActionFnCreator<Spec extends ActionsFnSpecs> = {
13
- [ActionName in keyof Spec]: (Record<never, never> extends Spec[ActionName] ? () => Spec[ActionName] & {
14
- type: ActionName;
15
- } : (payload: Spec[ActionName]) => Spec[ActionName] & {
16
- type: ActionName;
17
- }) & {
18
- type: ActionName & string;
19
- };
20
- };
21
- type ActionFnPayload<Action> = Action extends (payload: infer Payload) => void ? Payload : never;
22
- type ActionFnsCreator<Spec extends ActionsFnSpecs> = Spec extends {
23
- private: Record<string, Payload>;
24
- public: Record<string, Payload>;
25
- } ? ActionFnCreator<Spec['private']> & ActionFnCreator<Spec['public']> : ActionFnCreator<Spec>;
26
- type PublicActionFns<Spec extends ActionsFnSpecs> = Spec extends {
27
- public: Record<string, Payload>;
28
- } ? ActionFnCreator<Spec['public']> : ActionFnCreator<Spec>;
29
- export declare function payload<Type extends Payload>(): Type;
30
- export declare const noPayload: {};
31
- /** Reducer **/
32
- type ReducerFunction<ReducerAction, State> = (state: State, action: ActionFnPayload<ReducerAction>) => void;
33
- type ReducerFactory<StateActionFns extends ActionFns, State> = (actions: StateActionFns, on: <ReducerAction extends {
34
- type: string;
35
- }>(action: ReducerAction, reducerFn: ReducerFunction<ReducerAction, State>) => void) => void;
36
- /**
37
- * Creates a reducer function to separate the reducer logic into another file.
38
- *
39
- * ```typescript
40
- * interface FlightState {
41
- * flights: Flight[];
42
- * effect1: boolean;
43
- * effect2: boolean;
44
- * }
45
- *
46
- * const initialState: FlightState = {
47
- * flights: [],
48
- * effect1: false,
49
- * effect2: false,
50
- * };
51
- *
52
- * const actions = {
53
- * init: noPayload,
54
- * updateEffect1: payload<{ value: boolean }>(),
55
- * updateEffect2: payload<{ value: boolean }>(),
56
- * };
57
- *
58
- * const reducer = createReducer<FlightState, typeof actions>((actions, on) => {
59
- * on(actions.updateEffect1, (state, { value }) => {
60
- * patchState(state, { effect1: value });
61
- * });
62
- *
63
- * on(actions.updateEffect2, (state, { value }) => {
64
- * patchState(state, { effect2: value });
65
- * });
66
- * });
67
- *
68
- * signalStore(
69
- * withState(initialState),
70
- * withRedux({
71
- * actions,
72
- * reducer,
73
- * })
74
- * );
75
- * ```
76
- * @param reducerFactory
77
- */
78
- export declare function createReducer<State extends object, Actions extends ActionsFnSpecs>(reducerFactory: ReducerFactory<ActionFnsCreator<Actions>, WritableStateSource<State>>): ReducerFactory<ActionFnsCreator<Actions>, WritableStateSource<State>>;
79
- /** Effect **/
80
- type EffectsFactory<StateActionFns extends ActionFns> = (actions: StateActionFns, create: <EffectAction extends {
81
- type: string;
82
- }>(action: EffectAction) => Observable<ActionFnPayload<EffectAction>>) => Record<string, Observable<unknown>>;
83
- /**
84
- * @deprecated Use NgRx's `@ngrx/signals/events` starting in 19.2
85
- *
86
- * Creates the effects function to separate the effects logic into another file.
87
- *
88
- * ```typescript
89
- * interface FlightState {
90
- * flights: Flight[];
91
- * effect1: boolean;
92
- * effect2: boolean;
93
- * }
94
- *
95
- * const initialState: FlightState = {
96
- * flights: [],
97
- * effect1: false,
98
- * effect2: false,
99
- * };
100
- *
101
- * const actions = {
102
- * init: noPayload,
103
- * updateEffect1: payload<{ value: boolean }>(),
104
- * updateEffect2: payload<{ value: boolean }>(),
105
- * };
106
- *
107
- * const effects = createEffects(actions, (actions, create) => {
108
- * return {
109
- * init1$: create(actions.init).pipe(
110
- * map(() => actions.updateEffect1({ value: true }))
111
- * ),
112
- * init2$: create(actions.init).pipe(
113
- * map(() => actions.updateEffect2({ value: true }))
114
- * ),
115
- * };
116
- * });
117
- *
118
- * signalStore(
119
- * withState(initialState),
120
- * withRedux({
121
- * actions,
122
- * effects,
123
- * })
124
- * );
125
- * ```
126
- * @param actions
127
- * @param effectsFactory
128
- */
129
- export declare function createEffects<Actions extends ActionsFnSpecs>(actions: Actions, effectsFactory: EffectsFactory<ActionFnsCreator<Actions>>): EffectsFactory<ActionFnsCreator<Actions>>;
130
- /**
131
- * @param redux redux
132
- *
133
- * properties do not start with `with` since they are not extension functions on their own.
134
- *
135
- * no dependency to NgRx
136
- *
137
- * actions are passed to reducer and effects, but it is also possible to use other actions.
138
- * effects provide forAction and do not return anything. that is important because effects should stay inaccessible
139
- */
140
- export declare function withRedux<Spec extends ActionsFnSpecs, Input extends SignalStoreFeatureResult, StateActionFns extends ActionFnsCreator<Spec> = ActionFnsCreator<Spec>, PublicStoreActionFns extends PublicActionFns<Spec> = PublicActionFns<Spec>>(redux: {
141
- actions: Spec;
142
- reducer: ReducerFactory<StateActionFns, WritableStateSource<Input['state']>>;
143
- effects: EffectsFactory<StateActionFns>;
144
- }): SignalStoreFeature<Input, EmptyFeatureResult & {
145
- methods: PublicStoreActionFns;
146
- }>;
147
- export {};
@@ -1,29 +0,0 @@
1
- import { StateSource } from '@ngrx/signals';
2
- export type PublicMethods = {
3
- resetState(): void;
4
- };
5
- /**
6
- * Adds a `resetState` method to the store, which resets the state
7
- * to the initial state.
8
- *
9
- * If you want to set a custom initial state, you can use {@link setResetState}.
10
- */
11
- export declare function withReset(): import("@ngrx/signals").SignalStoreFeature<import("@ngrx/signals").EmptyFeatureResult, {
12
- state: {};
13
- props: {
14
- _resetState: {
15
- value: {};
16
- };
17
- };
18
- methods: {
19
- resetState: () => void;
20
- };
21
- }>;
22
- /**
23
- * Sets the reset state of the store to the given state.
24
- *
25
- * Throws an error if the store is not configured with {@link withReset}.
26
- * @param store the instance of a SignalStore
27
- * @param state the state to set as the reset state
28
- */
29
- export declare function setResetState<State extends object>(store: StateSource<State>, state: State): void;
@@ -1,31 +0,0 @@
1
- import { Signal } from '@angular/core';
2
- import { EmptyFeatureResult, SignalStoreFeature, SignalStoreFeatureResult } from '@ngrx/signals';
3
- export type StackItem = Record<string, unknown>;
4
- export type NormalizedUndoRedoOptions = {
5
- maxStackSize: number;
6
- collections?: string[];
7
- keys: string[];
8
- skip: number;
9
- };
10
- export declare function getUndoRedoKeys(collections?: string[]): string[];
11
- type NonNever<T> = T extends never ? never : T;
12
- type ExtractEntityCollection<T> = T extends `${infer U}Entities` ? U : never;
13
- type ExtractEntityCollections<Store extends SignalStoreFeatureResult> = NonNever<{
14
- [K in keyof Store['props']]: ExtractEntityCollection<K>;
15
- }[keyof Store['props']]>;
16
- type OptionsForState<Store extends SignalStoreFeatureResult> = Partial<Omit<NormalizedUndoRedoOptions, 'collections' | 'keys'>> & {
17
- collections?: ExtractEntityCollections<Store>[];
18
- keys?: (keyof Store['state'])[];
19
- };
20
- export declare function withUndoRedo<Input extends EmptyFeatureResult>(options?: OptionsForState<Input>): SignalStoreFeature<Input, EmptyFeatureResult & {
21
- props: {
22
- canUndo: Signal<boolean>;
23
- canRedo: Signal<boolean>;
24
- };
25
- methods: {
26
- undo: () => void;
27
- redo: () => void;
28
- clearStack: () => void;
29
- };
30
- }>;
31
- export {};
@@ -1,2 +0,0 @@
1
- export { createReduxState, mapAction, withActionMappers, } from './src/lib/create-redux';
2
- export { reduxMethod } from './src/lib/rxjs-interop/redux-method';
@@ -1,13 +0,0 @@
1
- import { ActionCreator, ActionType } from '@ngrx/store/src/models';
2
- import { CreateReduxState, MapperTypes, Store } from './model';
3
- export declare function mapAction<Creators extends readonly ActionCreator[]>(...args: [
4
- ...creators: Creators,
5
- storeMethod: (action: ActionType<Creators[number]>) => unknown
6
- ]): MapperTypes<Creators>;
7
- export declare function mapAction<Creators extends readonly ActionCreator[], T>(...args: [
8
- ...creators: Creators,
9
- storeMethod: (action: ActionType<Creators[number]>, resultMethod: (input: T) => unknown) => unknown,
10
- resultMethod: (input: T) => unknown
11
- ]): MapperTypes<Creators>;
12
- export declare function withActionMappers(...mappers: MapperTypes<ActionCreator[]>[]): MapperTypes<ActionCreator[]>[];
13
- export declare function createReduxState<StoreName extends string, STORE extends Store>(storeName: StoreName, signalStore: STORE, withActionMappers: (store: InstanceType<STORE>) => MapperTypes<ActionCreator[]>[]): CreateReduxState<StoreName, STORE>;
@@ -1,40 +0,0 @@
1
- import { EnvironmentProviders, Signal, Type } from '@angular/core';
2
- import { DeepSignal } from '@ngrx/signals/src/deep-signal';
3
- import { SignalStoreFeatureResult, StateSignals } from '@ngrx/signals/src/signal-store-models';
4
- import { Action, ActionCreator, ActionType, Prettify } from '@ngrx/store/src/models';
5
- import { Observable, Unsubscribable } from 'rxjs';
6
- export type IncludePropType<T, V, WithNevers = {
7
- [K in keyof T]: Exclude<T[K], undefined> extends V ? T[K] extends Record<string, unknown> ? IncludePropType<T[K], V> : T[K] : never;
8
- }> = Prettify<Pick<WithNevers, {
9
- [K in keyof WithNevers]: WithNevers[K] extends never ? never : K extends string ? K : never;
10
- }[keyof WithNevers]>>;
11
- export type Store = Type<Record<string, unknown> & StateSignals<SignalStoreFeatureResult['state']>>;
12
- export type CreateReduxState<StoreName extends string, STORE extends Store> = {
13
- [K in StoreName as `provide${Capitalize<K>}Store`]: (connectReduxDevtools?: boolean) => EnvironmentProviders;
14
- } & {
15
- [K in StoreName as `inject${Capitalize<K>}Store`]: () => InjectableReduxSlice<STORE>;
16
- };
17
- export type Selectors<STORE extends Store> = IncludePropType<InstanceType<STORE>, Signal<unknown> | DeepSignal<unknown>>;
18
- export type Dispatch = {
19
- dispatch: (input: Action | Observable<Action> | Signal<Action>) => Unsubscribable;
20
- };
21
- export type InjectableReduxSlice<STORE extends Store> = Selectors<STORE> & Dispatch;
22
- export type ExtractActionTypes<Creators extends readonly ActionCreator[]> = {
23
- [Key in keyof Creators]: Creators[Key] extends ActionCreator<infer T> ? T : never;
24
- };
25
- export interface ActionMethod<T, V extends Action = Action> {
26
- (action: V): T;
27
- }
28
- export interface StoreMethod<Creators extends readonly ActionCreator[], ResultState = unknown> {
29
- (action: ActionType<Creators[number]>): ResultState;
30
- }
31
- export interface MapperTypes<Creators extends readonly ActionCreator[]> {
32
- types: ExtractActionTypes<Creators>;
33
- storeMethod: StoreMethod<Creators>;
34
- resultMethod?: (...args: unknown[]) => unknown;
35
- }
36
- export type ServiceWithDecorator = {
37
- ɵprov?: {
38
- providedIn?: string;
39
- };
40
- };
@@ -1,14 +0,0 @@
1
- import { Injector, Signal } from '@angular/core';
2
- import { Observable } from 'rxjs';
3
- type RxMethodInput<Input> = Input | Observable<Input> | Signal<Input>;
4
- type RxMethodRef = {
5
- destroy: () => void;
6
- };
7
- type RxMethod<Input, MethodInput = Input, MethodResult = unknown> = ((input: RxMethodInput<Input>, resultMethod: (input: MethodInput) => MethodResult) => RxMethodRef) & RxMethodRef;
8
- export declare function reduxMethod<Input, MethodInput = Input>(generator: (source$: Observable<Input>) => Observable<MethodInput>, config?: {
9
- injector?: Injector;
10
- }): RxMethod<Input, MethodInput>;
11
- export declare function reduxMethod<Input, MethodInput = Input, MethodResult = unknown>(generator: (source$: Observable<Input>) => Observable<MethodInput>, resultMethod: (input: MethodInput) => MethodResult, config?: {
12
- injector?: Injector;
13
- }): RxMethod<Input, MethodInput, MethodResult>;
14
- export {};
@@ -1,11 +0,0 @@
1
- import { Action, ActionCreator } from '@ngrx/store';
2
- import { MapperTypes } from './model';
3
- import * as i0 from "@angular/core";
4
- export declare class SignalReduxStore {
5
- private mapperDict;
6
- dispatch: import("@ngrx/signals/rxjs-interop").RxMethod<Action<string>>;
7
- connectFeatureStore(mappers: MapperTypes<ActionCreator<any, any>[]>[]): void;
8
- static ɵfac: i0.ɵɵFactoryDeclaration<SignalReduxStore, never>;
9
- static ɵprov: i0.ɵɵInjectableDeclaration<SignalReduxStore>;
10
- }
11
- export declare function injectReduxDispatch(): import("@ngrx/signals/rxjs-interop").RxMethod<Action<string>>;
@@ -1,5 +0,0 @@
1
- import { ActionCreator } from '@ngrx/store';
2
- import { Unsubscribable } from 'rxjs';
3
- export declare function isUnsubscribable<F extends (...args: unknown[]) => unknown>(fn: F | (F & Unsubscribable)): fn is F & Unsubscribable;
4
- export declare function capitalize(str: string): string;
5
- export declare function isActionCreator(action: unknown): action is ActionCreator;