import { BehaviorSubject } from 'rxjs' ; import { skip } from 'rxjs/operators' ; import deepFreeze from 'deep-freeze-strict' ; import { PureTransitionsToTransitions , PureTransition , ReduxLikeStateContainer , PureSelectorsToSelectors , BaseState , } from './types' ; const $$observable = ( typeof Symbol === 'function' && ( Symbol as any ) . observable ) || '@@observable' ; const $$setActionType = '@@SET' ; const isProduction = typeof window === 'object' ? process . env . NODE_ENV === 'production' : ! process . env . NODE_ENV || process . env . NODE_ENV === 'production' ; const defaultFreeze = isProduction ? < T > ( value ) => value as T : < T > ( value ) : T => { const isFreezable = value !== null && typeof value === 'object' ; if ( isFreezable ) return deepFreeze ( value ) as T ; return value as T ; } ; public export interface CreateStateContainerOptions { example freeze ? : < T > ( state : T ) => T ; } param defaultState typeParam public export function createStateContainer < State extends BaseState > ( defaultState ) ; param defaultState param pureTransitions - state transitions configuration object. Map of  PureTransition .
 *  typeParam public export function createStateContainer < State extends BaseState , PureTransitions extends object > ( defaultState , pureTransitions ) ; param defaultState param pureTransitions - state transitions configuration object. Map of  PureTransition .
 *  param pureSelectors - state selectors configuration object. Map of  PureSelectors .
 *  param options - state container options  CreateStateContainerOptions typeParam public export function createStateContainer < State extends BaseState , PureTransitions extends object , PureSelectors extends object > ( defaultState , pureTransitions , pureSelectors , options ? ) ; internal export function createStateContainer < State extends BaseState , PureTransitions extends object , PureSelectors extends object > ( defaultState , pureTransitions = { } as PureTransitions , pureSelectors = { } as PureSelectors , options = { } ) { const { freeze = defaultFreeze } = options ; const data$ = new BehaviorSubject < State > ( freeze ( defaultState ) ) ; const state$ = data$ . pipe ( skip ( 1 ) ) ; const get = ( ) => data$ . getValue ( ) ; const container = { get , state$ , getState : ( ) => data$ . getValue ( ) , set : ( state ) => { container . dispatch ( { type : $$setActionType , args : [ state ] } ) ; } , reducer : ( state , action ) => { if ( action . type === $$setActionType ) { return freeze ( action . args [ 0 ] as State ) ; } const pureTransition = ( pureTransitions as Record < string , PureTransition < State , any [ ] > > ) [ action . type ] ; return pureTransition ? freeze ( pureTransition ( state ) ( ... action . args ) ) : state ; } , replaceReducer : ( nextReducer ) => ( container . reducer = nextReducer ) , dispatch : ( action ) => data$ . next ( container . reducer ( get ( ) , action ) ) , transitions : Object . keys ( pureTransitions ) . reduce < PureTransitionsToTransitions < PureTransitions > > ( ( acc , type ) => ( { ... acc , [ type ] : ( ... args ) => container . dispatch ( { type , args } ) } ) , { } as PureTransitionsToTransitions < PureTransitions > ) , selectors : Object . keys ( pureSelectors ) . reduce < PureSelectorsToSelectors < PureSelectors > > ( ( acc , selector ) => ( { ... acc , [ selector ] : ( ... args ) => ( pureSelectors as any ) [ selector ] ( get ( ) ) ( ... args ) , } ) , { } as PureSelectorsToSelectors < PureSelectors > ) , addMiddleware : ( middleware ) => ( container . dispatch = middleware ( container as any ) ( container . dispatch ) ) , subscribe : ( listener ) => { const subscription = state$ . subscribe ( listener ) ; return ( ) => subscription . unsubscribe ( ) ; } , [ $$observable ] : state$ , } ; return container ; }