import { Cmd , CmdType , Sub } from './cmd' ; import { ActionType } from './types' ; import { set } from './utils' ; export function inject < S , A > ( s ? , a ? ) { let ctx = dispatcher . getContext ( ) ; return ctx ; } export namespace dispatcher { export let getResult = ( ) => { let ctx = contextStack [ contextStack . length - 1 ] ; if ( ! ctx ) return ; return { state : ctx . _internals . newState , cmd : ctx . _internals . cmd , } ; } ; export let getContext = ( ) => { checkActive ( ) ; return contextStack [ contextStack . length - 1 ] ; } ; let checkActive = ( ) => { if ( ! contextStack . length ) { throw new RangeError ( `inject is called out of scope, please ensure it is called in a synchronized action.` ) ; } } ; export type Mapper < A , SubA > = ( ( a : A ) => SubA ) | null ; export class CmdHelper < S = any , A = any > { none = Cmd . none ; constructor ( public readonly setState , private readonly _mapper ? ) { } map < SubA > ( mapper ) { return new CmdHelper ( this . setState , mapper ) ; } addSub ( ... subs ) { return this . addBatch ( subs ) ; } addBatch ( subs ) { this . _addCmd ( Cmd . ofSub , subs ) ; return this ; } addFn < Arg , T > ( task ? , succeedAction ? , failedAction ? ) ; addFn < Arg , T > ( task ? , args ? , succeedAction ? , failedAction ? ) { this . _addCmd ( Cmd . ofFn , arguments ) ; return this ; } addPromise < Arg , T > ( task , args , succeedAction ? , failedAction ? ) ; addPromise < Arg , T > ( task , succeedAction ? , failedAction ? ) ; addPromise < Arg , T > ( task , args ? , succeedAction ? , failedAction ? ) { this . _addCmd ( Cmd . ofPromise , arguments ) ; return this ; } private _addCmd ( fn , args ) { let ctx = getContext ( ) ; let cmd = ( fn as any ) ( ... args ) ; if ( this . _mapper ) { cmd = cmd . map ( c => a => c ( this . _mapper ! ( a ) ) ) ; } ctx . _internals . cmd . push ( ... cmd ) ; return cmd ; } } let contextStack = [ ] ; export interface ActiveProps { state : any ; actions : any ; parentState : any ; parentActions : any ; setState : ( s : any , callback ? : any ) => any ; } export class InjectContext < S , A = any > extends CmdHelper < S , A > { state : S ; actions : A ; setState : ( s : Partial < S > , callback ? : ( ) => void ) => InjectContext < S , A > ; parentState : any ; parentActions : any ; Cmd : CmdHelper < S , A > ; internal _internals : { newState : S ; cmd : CmdType < any > ; } ; constructor ( props , setState ) { super ( setState ) ; set ( this as InjectContext < any , any > , props ) ; this . _internals = { newState : props . state , cmd : [ ] , } ; this . setState = setState ; this . Cmd = new CmdHelper ( setState ) ; } } function makeContext ( props ) { let setState = ( state , callback ) => { ctx . _internals . newState = state ; props . setState ( state , callback ) ; return ctx ; } ; let ctx = new InjectContext ( props , setState ) ; return ctx ; } export function active < S > ( props ) { contextStack . push ( makeContext ( props ) ) ; } export function deactive ( ) { contextStack . pop ( ) ; } }