1
1
import { merge , Observable , Subject , Subscription , NEVER } from 'rxjs'
2
- import { map , catchError } from 'rxjs/operators'
2
+ import { map , catchError , takeUntil , filter } from 'rxjs/operators'
3
3
import { mapValues } from 'lodash'
4
4
import produce from 'immer'
5
5
@@ -14,9 +14,11 @@ import {
14
14
EffectActionFactories ,
15
15
} from './types'
16
16
import { Ayanami } from './ayanami'
17
- import { BasicState , getEffectActionFactories , getOriginalFunctions } from './utils'
17
+ import { createState , getEffectActionFactories , getOriginalFunctions } from './utils'
18
18
import { logStateAction } from '../redux-devtools-extension'
19
19
import { ikariSymbol } from './symbols'
20
+ import { TERMINATE_ACTION } from '../ssr/terminate'
21
+ import { isSSREnabled } from '../ssr/flag'
20
22
21
23
interface Config < State > {
22
24
nameForLog : string
@@ -74,13 +76,13 @@ export function destroyIkariFrom<S>(ayanami: Ayanami<S>): void {
74
76
}
75
77
76
78
export class Ikari < State > {
77
- static createAndBindAt < S > ( target : { defaultState : S } , config : Config < S > ) : Ikari < S > {
79
+ static createAndBindAt < S > ( target : Ayanami < S > , config : Config < S > ) : Ikari < S > {
78
80
const createdIkari = this . getFrom ( target )
79
81
80
82
if ( createdIkari ) {
81
83
return createdIkari
82
84
} else {
83
- const ikari = new Ikari ( config )
85
+ const ikari = new Ikari ( target , config )
84
86
Reflect . defineMetadata ( ikariSymbol , ikari , target )
85
87
return ikari
86
88
}
@@ -90,18 +92,18 @@ export class Ikari<State> {
90
92
return Reflect . getMetadata ( ikariSymbol , target )
91
93
}
92
94
93
- state : BasicState < State >
95
+ state = createState ( this . config . defaultState )
94
96
95
- effectActionFactories : EffectActionFactories
97
+ effectActionFactories = this . config . effectActionFactories
96
98
97
99
triggerActions : TriggerActions = { }
98
100
99
101
subscription = new Subscription ( )
100
102
101
- constructor ( private readonly config : Readonly < Config < State > > ) {
102
- this . effectActionFactories = config . effectActionFactories
103
- this . state = new BasicState < State > ( config . defaultState )
103
+ // @internal
104
+ terminate$ = new Subject < typeof TERMINATE_ACTION | null > ( )
104
105
106
+ constructor ( readonly ayanami : Ayanami < State > , private readonly config : Readonly < Config < State > > ) {
105
107
const [ effectActions$ , effectActions ] = setupEffectActions (
106
108
this . config . effects ,
107
109
this . state . state$ ,
@@ -124,8 +126,18 @@ export class Ikari<State> {
124
126
...mapValues ( this . config . defineActions , ( { next } ) => next ) ,
125
127
}
126
128
129
+ let effectActionsWithTerminate$ : Observable < Action < any > >
130
+
131
+ if ( ! isSSREnabled ( ) ) {
132
+ effectActionsWithTerminate$ = effectActions$
133
+ } else {
134
+ effectActionsWithTerminate$ = effectActions$ . pipe (
135
+ takeUntil ( this . terminate$ . pipe ( filter ( ( action ) => action === null ) ) ) ,
136
+ )
137
+ }
138
+
127
139
this . subscription . add (
128
- effectActions $. subscribe ( ( action ) => {
140
+ effectActionsWithTerminate $. subscribe ( ( action ) => {
129
141
this . log ( action )
130
142
this . handleAction ( action )
131
143
} ) ,
@@ -152,12 +164,10 @@ export class Ikari<State> {
152
164
}
153
165
154
166
private log = ( { originalActionName, effectAction, reducerAction } : Action < State > ) => {
155
- if ( effectAction ) {
167
+ if ( effectAction && effectAction !== TERMINATE_ACTION ) {
156
168
logStateAction ( this . config . nameForLog , {
157
169
params : effectAction . params ,
158
- actionName : `${ originalActionName } /👉${ effectAction . ayanami . constructor . name } /️${
159
- effectAction . actionName
160
- } `,
170
+ actionName : `${ originalActionName } /👉${ effectAction . ayanami . constructor . name } /️${ effectAction . actionName } ` ,
161
171
} )
162
172
}
163
173
@@ -172,8 +182,12 @@ export class Ikari<State> {
172
182
173
183
private handleAction = ( { effectAction, reducerAction } : Action < State > ) => {
174
184
if ( effectAction ) {
175
- const { ayanami, actionName, params } = effectAction
176
- combineWithIkari ( ayanami ) . triggerActions [ actionName ] ( params )
185
+ if ( effectAction !== TERMINATE_ACTION ) {
186
+ const { ayanami, actionName, params } = effectAction
187
+ combineWithIkari ( ayanami ) . triggerActions [ actionName ] ( params )
188
+ } else {
189
+ this . terminate$ . next ( effectAction )
190
+ }
177
191
}
178
192
179
193
if ( reducerAction ) {
0 commit comments