import * as Cmd from '../cmd' ; import { Init , normalize , Context , Component , CmdType } from '../index' ; export * from './hash' ; export * from './memoize' ; import { set , merge , setDeep , setDeepMutable , get , isFn , noop , isPojo , clone , OverrideLength , weakVal , } from '../utils' ; import { ActionReturn , ActionState , ActionCmdReturn , StandardActionReturn , ActionType , ActionsType , InitObjReturn , GeneralActionType , } from '../types' ; import { dispatcher } from '../dispatcher' ; export type Dt < T extends string , D = null > = { tag : T ; data : D ; } & { __tsTag : 'DateType' ; } ; /**
 * ADT Helper for TS
 * e.g.
 * ```ts
 * type Msg =
 * | Dt<'fetchBook', number>
 * | Dt<'updateBook', Book>
 *
 * let msg = dt('fetchBook', 1)
 * switch(msg.tag) {
 *   case 'fetchBook':
 *      //...
 *      break
 *   case 'updateBook':
 *      //...
 *      break
 *   default:
 *      never(msg) // incomplete check from TS
 *      break
 * }
 * ```
 */ export function dt < T extends string , D = null > ( tag , data = null as any ) { return { tag , data } as Dt < T , D > ; } public export const never = ( f ) => f ; public export function mkInit < S , A > ( state , cmd = Cmd . none ) { return { state , cmd } ; } export type Fn1 < T1 , R > = ( a1 : T1 ) => R ; public export function compose < T1 , T2 , R > ( fn1 , fn2 ) ; export function compose < T1 , T2 , T3 , R > ( fn1 , fn2 , fn3 ) ; export function compose < T1 , T2 , T3 , T4 , R > ( fn1 , fn2 , fn3 , fn4 ) ; export function compose < T1 , T2 , T3 , T4 , T5 , R > ( fn1 , fn2 , fn3 , fn4 , fn5 ) ; export function compose < T1 , T2 , T3 , T4 , T5 , T6 , R > ( fn1 , fn2 , fn3 , fn4 , fn5 , fn6 ) ; export function compose < T1 , T2 , T3 , T4 , T5 , T6 , T7 , R > ( fn1 , fn2 , fn3 , fn4 , fn5 , fn6 , fn7 ) ; export function compose < T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , R > ( fn1 , fn2 , fn3 , fn4 , fn5 , fn6 , fn7 , fn8 ) ; export function compose < T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , R > ( fn1 , fn2 , fn3 , fn4 , fn5 , fn6 , fn7 , fn8 , fn9 ) ; export function compose < R > ( ... fns ) { return arg => fns . reduce ( ( arg , fn ) => fn ( arg ) , arg ) ; } public export function defaults < T > ( value , defaults ) { return value == null ? defaults : value ; } export interface CombinedComps < T extends { [ k ] : [ Component , InitObjReturn < any , any > ] ; } , A extends { [ k ] : any ; } > { /** Combined state object for child components */ state : { [ k in keyof T ] : T [ k ] [ 1 ] [ 'state' ] ; } ; /** Combined and mapped cmd object for child components */ cmd : Cmd . Sub < A > [ ] ; /**
     * Splited mapped cmd object for child components, useful for router config, so you can call init cmd when each page routing.
     *
     */ cmds : { [ k in keyof T ] : Cmd . Sub < A > [ ] ; } ; /** Combined action object for child components */ actions : { [ k in keyof T ] : T [ k ] [ 0 ] [ 'actions' ] ; } ; /** Combined view function for child components */ views : { [ k in keyof T ] : T [ k ] [ 0 ] [ 'view' ] ; } ; /**
     * helper function for render routes views, so you can do
     * `subComps.render('somePage', state, actions)` instead of
     * `SomePage.views(state.somePage, actions.somePage)` or
     * `<SomePage.views
     *    state={state.somePage}
     *    actions={actions.somePage}
     *  />`
     */ render : < K extends Extract < keyof T , keyof S > , S > ( k : K , state : S , actions : ActionsType < S , any > ) => any ; } export function combine < T extends { [ k ] : [ Component , InitObjReturn < any , any > ] ; } , A extends { [ k ] : any ; } > ( arg , _acts = null as any ) { let state = { } as { [ k in keyof T ] : T [ k ] [ 1 ] [ 'state' ] ; } ; let cmd = Cmd . none as Cmd . CmdType < A > ; let cmds = { } as { [ k in keyof T ] : Cmd . CmdType < A > ; } ; let actions = { } as { [ k in keyof T ] : T [ k ] [ 0 ] [ 'actions' ] ; } ; let views = { } as { [ k in keyof T ] : T [ k ] [ 0 ] [ 'view' ] ; } ; for ( const key in arg ) { let comp = arg [ key ] [ 0 ] ; let init = normalize < any , any > ( arg [ key ] [ 1 ] ) ; state [ key ] = init . state ; actions [ key ] = comp . actions ; views [ key ] = comp . view ; cmds [ key ] = Cmd . map ( _ => _ [ key ] , init . cmd ) ; cmd = Cmd . batch ( cmd , cmds [ key ] ) ; } return { state , cmd , cmds , views , actions , render ( k , state , actions ) { let view = views [ k ] ; if ( view . length === 1 ) { return ( view as any ) ( { state : state [ k ] , actions : actions [ k ] } ) ; } else { return view ( state [ k ] , actions [ k ] ) ; } } , } ; } internal param result param state param actions export function runActionResult < S , A > ( result ) { let res = result ; let { state , actions , parentState , parentActions , } = dispatcher . getContext ( ) ; isFn ( res ) && ( res = res . call ( actions , state , actions , parentState , parentActions ) ) && isFn ( res ) && ( res = res . call ( actions , actions ) ) ; return normalize < S , A > ( res , state ) ; } internal export function withParents < S , A , PS , PA , A1 > ( action , wrapper ? ) ; export function withParents < S , A , PS , PA , A1 , A2 > ( action , wrapper ? ) ; export function withParents < S , A , PS , PA , A1 , A2 , A3 > ( action , wrapper ? ) ; export function withParents < S , A , PS , PA , A1 , A2 , A3 , A4 > ( action , wrapper ? ) ; export function withParents < S , A , PS , PA , A1 , A2 , A3 , A4 , A5 > ( action , wrapper ? ) ; internal deprecated param action param wrapper param parentState param parentActions export function withParents < S , A , PS , PA > ( action , wrapper ? ) { if ( ! wrapper ) { return action ; } const wrapped = ( state , actions , parentState , parentActions ) => { const nactions = ( ... args ) => runActionResult ( action ( ... args ) ) ; return wrapper ( nactions , parentState , parentActions , state , actions ) ; } ; return wrapped ; } deprecated internal export const wrapActions = withParents ; export function overrideAction < PS , PA , S , A , A1 > ( parentActions , getter , wrapper ? ) ; export function overrideAction < S , A , PS , PA , A1 , A2 > ( parentActions , getter , wrapper ? ) ; export function overrideAction < S , A , PS , PA , A1 , A2 , A3 > ( parentActions , getter , wrapper ? ) ; export function overrideAction < S , A , PS , PA , A1 , A2 , A3 , A4 > ( parentActions , getter , wrapper ? ) ; internal param action param wrapper param parentState param parentActions export function overrideAction < S , A , PS , PA > ( parentActions , getter , wrapper ? ) { if ( ! wrapper ) { return parentActions ; } let action = getter ( parentActions ) ; const wrapped = ( ... args ) => { const normalAction = ( ... args ) => { let ret = runActionResult ( action ( ... args ) ) ; return ret ; } ; let ctx = dispatcher . getContext ( ) ; return wrapper ( ... args ) ( normalAction , ctx . parentState , ctx . parentActions , ctx . state , ctx . actions ) ; } ; let keys = ( getter . toString ( ) . match ( /((?:[\w_$]+\.)+[\w_$]+)/ ) || [ ] ) [ 1 ] . split ( '.' ) . slice ( 1 ) ; let cursor = parentActions ; let replaced = false ; for ( let i = 0 ; i < keys . length ; i ++ ) { const key = keys [ i ] ; if ( cursor [ key ] === action ) { cursor [ key ] = wrapped ; replaced = true ; break ; } cursor = cursor [ key ] = { ... cursor [ key ] } ; } weakVal ( wrapped , OverrideLength , keys . length ) ; if ( ! replaced ) { console . error ( new Error ( `Cannot find action in parentActions` ) , parentActions , getter ) ; } return parentActions ; }