import { call , put , select , take , cancel , all , race } from 'redux-saga/effects' ; import { Action , ActionCreator , PollActionCreator } from './actionCreatorFactory' ; import * as warning from 'warning' ; import { History } from 'history' ; import { Dispatch } from 'redux' ; export * from './actionCreatorFactory' ; export interface SubscriptionAPI { history : History ; dispatch : Dispatch < any > ; } export type Subscription = ( api : SubscriptionAPI , done : Function ) => void ; export interface SubscriptionsMapObject { [ key ] : Subscription ; } export type Handler < InS extends OutS , OutS , P > = ( state : InS , payload : P ) => OutS ; export type ImmerHandler < InS , P > = ( state : InS , payload : P ) => void ; interface Model < T > { namespace : string ; state ? : T ; reducers ? : any ; effects ? : any ; subscriptions ? : any ; } export interface EffectsCommandMap { put : typeof put ; call : typeof call ; select : typeof select ; take : typeof take ; cancel : typeof cancel ; all : typeof all ; race : typeof race ; } export type EffectsHandler < P > = ( payload : P , effects : EffectsCommandMap ) => any ; export type EffectsHandlerWithAction < P > = ( payload : Action < P > , effects : EffectsCommandMap ) => any ; export type EffectsWatcher = ( effects : EffectsCommandMap ) => any ; export class DvaModelBuilder < InS extends OutS , OutS = InS > { private model : Model < OutS > ; constructor ( initState , namespace ? ) { this . model = { state : initState , namespace , effects : { } , reducers : { } , subscriptions : { } , } ; } immer = < P > ( actionCreator , handler ) => { this . checkType ( actionCreator . type ) ; this . model . reducers [ actionCreator . originType ] = ( state , action ) => handler ( state , action . payload ) ; return this ; } ; immerWithAction = < P > ( actionCreator , handler ) => { this . checkType ( actionCreator . type ) ; this . model . reducers [ actionCreator . originType ] = handler ; return this ; } ; case = < P > ( actionCreator , handler ) => { this . checkType ( actionCreator . type ) ; this . model . reducers [ actionCreator . originType ] = ( state , action ) => handler ( state , action . payload ) ; return this ; } ; caseWithAction = < P > ( actionCreator , handler ) => { this . checkType ( actionCreator . type ) ; this . model . reducers [ actionCreator . originType ] = handler ; return this ; } ; takeEvery = < P > ( actionCreator , handler ) => { return this . setEffects ( actionCreator , function * ( { payload } , effects ) { return yield handler ( payload , effects ) ; } ) ; } ; takeEveryWithAction = < P > ( actionCreator , handler ) => { return this . setEffects ( actionCreator , handler ) ; } ; takeLatest = < P > ( actionCreator , handler ) => { return this . setEffects ( actionCreator , [ function * ( { payload } , effects ) { return yield handler ( payload , effects ) ; } , { type : 'takeLatest' } , ] ) ; } ; takeLatestWithAction = < P > ( actionCreator , handler ) => { return this . setEffects ( actionCreator , [ handler , { type : 'takeLatest' } ] ) ; } ; throttle = < P > ( actionCreator , handler , ms ? ) => { return this . setEffects ( actionCreator , [ function * ( { payload } , effects ) { return yield handler ( payload , effects ) ; } , { type : 'throttle' , ms } , ] ) ; } ; throttleWithAction = < P > ( actionCreator , handler , ms ? ) => { return this . setEffects ( actionCreator , [ handler , { type : 'throttle' , ms } ] ) ; } ; watcher = < P > ( actionCreator , handler ) => { return this . setEffects ( actionCreator , [ handler , { type : 'watcher' } ] ) ; } ; poll = < P > ( pollActionCreator , handler , delay ) => { return this . setEffectsWithPollActionCreator ( pollActionCreator , [ function * ( { payload } , effects ) { return yield handler ( payload , effects ) ; } , { type : 'poll' , delay } , ] ) ; } ; subscript = ( func ) => { let funcName = func . name ; warning ( ! ! funcName , `some subscriptions in model ${ this . model . namespace } don't have name` ) ; warning ( ! this . model . subscriptions [ funcName ] , `duplicate  subscript function name ${ funcName }` ) ; this . model . subscriptions [ funcName ] = func ; return this ; } ; build = ( ) => { return this . model ; } ; private setEffects = < P > ( actionCreator , data ) => { this . checkType ( actionCreator . type ) ; this . model . effects [ actionCreator . originType ] = data ; return this ; } ; private setEffectsWithPollActionCreator = < P > ( pollActionCreator , data ) => { this . checkType ( pollActionCreator . type ) ; this . model . effects [ pollActionCreator . originType ] = data ; return this ; } ; private checkType ( type ) { const { namespace } = this . model ; if ( namespace ) { const action = type . split ( '/' ) ; warning ( action . length === 2 , `action ${ type } in model "${ namespace }" should have namespace` ) ; if ( action . length === 2 ) { warning ( action [ 0 ] === namespace , `action "${ type }" can't be effects or reducers in model "${ namespace }"` ) ; } } } }