@@ -13,7 +13,7 @@ type Payload = Record<string, unknown>;
13
13
14
14
type ActionFn <
15
15
Type extends string = string ,
16
- ActionPayload extends Payload = Payload
16
+ ActionPayload extends Payload = Payload ,
17
17
> = ( ( payload : ActionPayload ) => ActionPayload & { type : Type } ) & {
18
18
type : Type ;
19
19
} ;
@@ -24,7 +24,7 @@ export type ActionsFnSpecs = Record<string, Payload>;
24
24
25
25
type ActionFnCreator < Spec extends ActionsFnSpecs > = {
26
26
[ ActionName in keyof Spec ] : ( (
27
- payload : Spec [ ActionName ]
27
+ payload : Spec [ ActionName ] ,
28
28
) => Spec [ ActionName ] & { type : ActionName } ) & { type : ActionName & string } ;
29
29
} ;
30
30
@@ -55,34 +55,43 @@ export const noPayload = {};
55
55
56
56
type ReducerFunction < ReducerAction , State > = (
57
57
state : State ,
58
- action : ActionFnPayload < ReducerAction >
58
+ action : ActionFnPayload < ReducerAction > ,
59
59
) => void ;
60
60
61
61
type ReducerFactory < StateActionFns extends ActionFns , State > = (
62
62
actions : StateActionFns ,
63
63
on : < ReducerAction extends { type : string } > (
64
64
action : ReducerAction ,
65
- reducerFn : ReducerFunction < ReducerAction , State >
66
- ) => void
65
+ reducerFn : ReducerFunction < ReducerAction , State > ,
66
+ ) => void ,
67
67
) => void ;
68
68
69
69
/** Effect **/
70
70
71
71
type EffectsFactory < StateActionFns extends ActionFns > = (
72
72
actions : StateActionFns ,
73
73
create : < EffectAction extends { type : string } > (
74
- action : EffectAction
75
- ) => Observable < ActionFnPayload < EffectAction > >
74
+ action : EffectAction ,
75
+ ) => Observable < ActionFnPayload < EffectAction > > ,
76
76
) => Record < string , Observable < unknown > > ;
77
77
78
+ // internal types
79
+
80
+ /**
81
+ * Record which holds all effects for a specific action type.
82
+ * The values are Subject which the effect are subscribed to.
83
+ * `createActionFns` will call next on these subjects.
84
+ */
85
+ type EffectsRegistry = Record < string , Subject < ActionFnPayload < unknown > > [ ] > ;
86
+
78
87
function createActionFns < Spec extends ActionsFnSpecs > (
79
88
actionFnSpecs : Spec ,
80
89
reducerRegistry : Record <
81
90
string ,
82
91
( state : unknown , payload : ActionFnPayload < unknown > ) => void
83
92
> ,
84
- effectsRegistry : Record < string , Subject < ActionFnPayload < unknown > > > ,
85
- state : unknown
93
+ effectsRegistry : EffectsRegistry ,
94
+ state : unknown ,
86
95
) {
87
96
const actionFns : Record < string , ActionFn > = { } ;
88
97
@@ -93,12 +102,14 @@ function createActionFns<Spec extends ActionsFnSpecs>(
93
102
if ( reducer ) {
94
103
( reducer as ( state : unknown , payload : unknown ) => void ) (
95
104
state ,
96
- fullPayload as unknown
105
+ fullPayload as unknown ,
97
106
) ;
98
107
}
99
- const effectSubject = effectsRegistry [ type ] ;
100
- if ( effectSubject ) {
101
- ( effectSubject as unknown as Subject < unknown > ) . next ( fullPayload ) ;
108
+ const effectSubjects = effectsRegistry [ type ] ;
109
+ if ( effectSubjects ?. length ) {
110
+ for ( const effectSubject of effectSubjects ) {
111
+ ( effectSubject as unknown as Subject < unknown > ) . next ( fullPayload ) ;
112
+ }
102
113
}
103
114
return fullPayload ;
104
115
} ;
@@ -115,8 +126,8 @@ function createPublicAndAllActionsFns<Spec extends ActionsFnSpecs>(
115
126
string ,
116
127
( state : unknown , payload : ActionFnPayload < unknown > ) => void
117
128
> ,
118
- effectsRegistry : Record < string , Subject < ActionFnPayload < unknown > > > ,
119
- state : unknown
129
+ effectsRegistry : EffectsRegistry ,
130
+ state : unknown ,
120
131
) : { all : ActionFns ; publics : ActionFns } {
121
132
if ( 'public' in actionFnSpecs || 'private' in actionFnSpecs ) {
122
133
const privates = actionFnSpecs [ 'private' ] || { } ;
@@ -129,13 +140,13 @@ function createPublicAndAllActionsFns<Spec extends ActionsFnSpecs>(
129
140
privates ,
130
141
reducerRegistry ,
131
142
effectsRegistry ,
132
- state
143
+ state ,
133
144
) ;
134
145
const publicActionFns = createActionFns (
135
146
publics ,
136
147
reducerRegistry ,
137
148
effectsRegistry ,
138
- state
149
+ state ,
139
150
) ;
140
151
141
152
return {
@@ -148,7 +159,7 @@ function createPublicAndAllActionsFns<Spec extends ActionsFnSpecs>(
148
159
actionFnSpecs ,
149
160
reducerRegistry ,
150
161
effectsRegistry ,
151
- state
162
+ state ,
152
163
) ;
153
164
154
165
return { all : actionFns , publics : actionFns } ;
@@ -160,11 +171,11 @@ function fillReducerRegistry(
160
171
reducerRegistry : Record <
161
172
string ,
162
173
( state : unknown , payload : ActionFnPayload < unknown > ) => void
163
- >
174
+ > ,
164
175
) {
165
176
function on (
166
177
action : { type : string } ,
167
- reducerFn : ( state : unknown , payload : ActionFnPayload < unknown > ) => void
178
+ reducerFn : ( state : unknown , payload : ActionFnPayload < unknown > ) => void ,
168
179
) {
169
180
reducerRegistry [ action . type ] = reducerFn ;
170
181
}
@@ -177,11 +188,14 @@ function fillReducerRegistry(
177
188
function fillEffects (
178
189
effects : EffectsFactory < ActionFns > ,
179
190
actionFns : ActionFns ,
180
- effectsRegistry : Record < string , Subject < ActionFnPayload < unknown > > > = { }
191
+ effectsRegistry : EffectsRegistry = { } ,
181
192
) : Observable < unknown > [ ] {
182
193
function create ( action : { type : string } ) {
183
194
const subject = new Subject < ActionFnPayload < unknown > > ( ) ;
184
- effectsRegistry [ action . type ] = subject ;
195
+ if ( ! ( action . type in effectsRegistry ) ) {
196
+ effectsRegistry [ action . type ] = [ ] ;
197
+ }
198
+ effectsRegistry [ action . type ] . push ( subject ) ;
185
199
return subject . asObservable ( ) ;
186
200
}
187
201
@@ -197,18 +211,19 @@ function processRedux<Spec extends ActionsFnSpecs, ReturnType>(
197
211
actionFnSpecs : Spec ,
198
212
reducer : ReducerFactory < ActionFns , unknown > ,
199
213
effects : EffectsFactory < ActionFns > ,
200
- store : unknown
214
+ store : unknown ,
201
215
) {
202
216
const reducerRegistry : Record <
203
217
string ,
204
218
( state : unknown , payload : ActionFnPayload < unknown > ) => void
205
219
> = { } ;
206
- const effectsRegistry : Record < string , Subject < ActionFnPayload < unknown > > > = { } ;
220
+ const effectsRegistry : Record < string , Subject < ActionFnPayload < unknown > > [ ] > =
221
+ { } ;
207
222
const actionsMap = createPublicAndAllActionsFns (
208
223
actionFnSpecs ,
209
224
reducerRegistry ,
210
225
effectsRegistry ,
211
- store
226
+ store ,
212
227
) ;
213
228
const actionFns = actionsMap . all ;
214
229
const publicActionsFns = actionsMap . publics ;
@@ -237,7 +252,7 @@ export function withRedux<
237
252
Spec extends ActionsFnSpecs ,
238
253
Input extends SignalStoreFeatureResult ,
239
254
StateActionFns extends ActionFnsCreator < Spec > = ActionFnsCreator < Spec > ,
240
- PublicStoreActionFns extends PublicActionFns < Spec > = PublicActionFns < Spec >
255
+ PublicStoreActionFns extends PublicActionFns < Spec > = PublicActionFns < Spec > ,
241
256
> ( redux : {
242
257
actions : Spec ;
243
258
reducer : ReducerFactory < StateActionFns , StateSignal < Input [ 'state' ] > > ;
@@ -251,7 +266,7 @@ export function withRedux<
251
266
redux . actions ,
252
267
redux . reducer as ReducerFactory < ActionFns , unknown > ,
253
268
redux . effects as EffectsFactory < ActionFns > ,
254
- store
269
+ store ,
255
270
) ;
256
271
return {
257
272
...store ,
0 commit comments