11import { merge , Observable , Subject , Subscription , NEVER } from 'rxjs'
22import { map , catchError } from 'rxjs/operators'
33import { mapValues } from 'lodash'
4+ import produce from 'immer'
45
56import {
67 EffectAction ,
78 ReducerAction ,
89 OriginalEffectActions ,
910 OriginalReducerActions ,
11+ OriginalImmerReducerActions ,
1012 OriginalDefineActions ,
1113 TriggerActions ,
1214 EffectActionFactories ,
@@ -21,6 +23,7 @@ interface Config<State> {
2123 defaultState : State
2224 effects : OriginalEffectActions < State >
2325 reducers : OriginalReducerActions < State >
26+ immerReducers : OriginalImmerReducerActions < State >
2427 defineActions : OriginalDefineActions
2528 effectActionFactories : EffectActionFactories
2629}
@@ -45,7 +48,7 @@ export function combineWithIkari<S>(ayanami: Ayanami<S>): Ikari<S> {
4548 if ( ikari ) {
4649 return ikari
4750 } else {
48- const { effects, reducers, defineActions } = getOriginalFunctions ( ayanami )
51+ const { effects, reducers, immerReducers , defineActions } = getOriginalFunctions ( ayanami )
4952
5053 Object . assign ( ayanami , mapValues ( defineActions , ( { observable } ) => observable ) )
5154
@@ -54,6 +57,7 @@ export function combineWithIkari<S>(ayanami: Ayanami<S>): Ikari<S> {
5457 defaultState : ayanami . defaultState ,
5558 effects,
5659 reducers,
60+ immerReducers,
5761 defineActions,
5862 effectActionFactories : getEffectActionFactories ( ayanami ) ,
5963 } )
@@ -108,9 +112,15 @@ export class Ikari<State> {
108112 this . state . getState ,
109113 )
110114
115+ const [ immerReducerActions$ , immerReducerActions ] = setupImmerReducerActions (
116+ this . config . immerReducers ,
117+ this . state . getState ,
118+ )
119+
111120 this . triggerActions = {
112121 ...effectActions ,
113122 ...reducerActions ,
123+ ...immerReducerActions ,
114124 ...mapValues ( this . config . defineActions , ( { next } ) => next ) ,
115125 }
116126
@@ -127,6 +137,13 @@ export class Ikari<State> {
127137 this . handleAction ( action )
128138 } ) ,
129139 )
140+
141+ this . subscription . add (
142+ immerReducerActions$ . subscribe ( ( action ) => {
143+ this . log ( action )
144+ this . handleAction ( action )
145+ } ) ,
146+ )
130147 }
131148
132149 destroy ( ) {
@@ -218,3 +235,31 @@ function setupReducerActions<State>(
218235
219236 return [ merge ( ...reducers ) , actions ]
220237}
238+
239+ function setupImmerReducerActions < State > (
240+ immerReducerActions : OriginalImmerReducerActions < State > ,
241+ getState : ( ) => State ,
242+ ) : [ Observable < Action < State > > , TriggerActions ] {
243+ const actions : TriggerActions = { }
244+ const immerReducers : Observable < Action < State > > [ ] = [ ]
245+
246+ Object . keys ( immerReducerActions ) . forEach ( ( actionName ) => {
247+ const immerReducer$ = new Subject < Action < State > > ( )
248+ immerReducers . push ( immerReducer$ )
249+
250+ const immerReducer = immerReducerActions [ actionName ]
251+
252+ actions [ actionName ] = ( params : any ) => {
253+ const nextState = produce ( getState ( ) , ( draft ) => {
254+ immerReducer ( draft , params )
255+ } )
256+
257+ immerReducer$ . next ( {
258+ reducerAction : { params, actionName, nextState } ,
259+ originalActionName : actionName ,
260+ } )
261+ }
262+ } )
263+
264+ return [ merge ( ...immerReducers ) , actions ]
265+ }
0 commit comments