11import { merge , Observable , Subject , Subscription , NEVER } from 'rxjs'
2- import { map , catchError } from 'rxjs/operators'
2+ import { map , catchError , takeUntil , filter } from 'rxjs/operators'
33import { mapValues } from 'lodash'
44import produce from 'immer'
55
@@ -14,9 +14,11 @@ import {
1414 EffectActionFactories ,
1515} from './types'
1616import { Ayanami } from './ayanami'
17- import { BasicState , getEffectActionFactories , getOriginalFunctions } from './utils'
17+ import { createState , getEffectActionFactories , getOriginalFunctions } from './utils'
1818import { logStateAction } from '../redux-devtools-extension'
1919import { ikariSymbol } from './symbols'
20+ import { TERMINATE_ACTION } from '../ssr/terminate'
21+ import { isSSREnabled } from '../ssr/flag'
2022
2123interface Config < State > {
2224 nameForLog : string
@@ -74,13 +76,13 @@ export function destroyIkariFrom<S>(ayanami: Ayanami<S>): void {
7476}
7577
7678export 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 > {
7880 const createdIkari = this . getFrom ( target )
7981
8082 if ( createdIkari ) {
8183 return createdIkari
8284 } else {
83- const ikari = new Ikari ( config )
85+ const ikari = new Ikari ( target , config )
8486 Reflect . defineMetadata ( ikariSymbol , ikari , target )
8587 return ikari
8688 }
@@ -90,18 +92,18 @@ export class Ikari<State> {
9092 return Reflect . getMetadata ( ikariSymbol , target )
9193 }
9294
93- state : BasicState < State >
95+ state = createState ( this . config . defaultState )
9496
95- effectActionFactories : EffectActionFactories
97+ effectActionFactories = this . config . effectActionFactories
9698
9799 triggerActions : TriggerActions = { }
98100
99101 subscription = new Subscription ( )
100102
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 > ( )
104105
106+ constructor ( readonly ayanami : Ayanami < State > , private readonly config : Readonly < Config < State > > ) {
105107 const [ effectActions$ , effectActions ] = setupEffectActions (
106108 this . config . effects ,
107109 this . state . state$ ,
@@ -124,8 +126,18 @@ export class Ikari<State> {
124126 ...mapValues ( this . config . defineActions , ( { next } ) => next ) ,
125127 }
126128
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+
127139 this . subscription . add (
128- effectActions $. subscribe ( ( action ) => {
140+ effectActionsWithTerminate $. subscribe ( ( action ) => {
129141 this . log ( action )
130142 this . handleAction ( action )
131143 } ) ,
@@ -152,12 +164,10 @@ export class Ikari<State> {
152164 }
153165
154166 private log = ( { originalActionName, effectAction, reducerAction } : Action < State > ) => {
155- if ( effectAction ) {
167+ if ( effectAction && effectAction !== TERMINATE_ACTION ) {
156168 logStateAction ( this . config . nameForLog , {
157169 params : effectAction . params ,
158- actionName : `${ originalActionName } /👉${ effectAction . ayanami . constructor . name } /️${
159- effectAction . actionName
160- } `,
170+ actionName : `${ originalActionName } /👉${ effectAction . ayanami . constructor . name } /️${ effectAction . actionName } ` ,
161171 } )
162172 }
163173
@@ -172,8 +182,12 @@ export class Ikari<State> {
172182
173183 private handleAction = ( { effectAction, reducerAction } : Action < State > ) => {
174184 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+ }
177191 }
178192
179193 if ( reducerAction ) {
0 commit comments