import { createSelector } from 'reselect' ; import { ReplaySubject } from 'rxjs/ReplaySubject' ; import { Observable } from 'rxjs/Observable' ; import { ActionReducer } from '@ngrx/store' ; const tables = new Map < string , boolean > ( ) ; const reducers = { } ; const tableCreatedSubject$ = new ReplaySubject < string > ( 1 ) ; export interface Actions { } export const Actions = { } as any ; export interface State { } export const State = { } as any ; export interface Queries { } export const Queries = { } as any ; export interface Root { } export const Root = { } as any ; export namespace Model { const X = 15 ; } export interface Query < TTarget > { ( state ) : TTarget ; } export interface Type < T > { new ( ... args ) : T ; } namespace utils { export function generateQuery ( key ) { return ( state ) => state [ key ] ; } } export function safeQuery ( query , key ) { return typeof query === 'function' ? query : utils . generateQuery ( key ) ; } export function createDomain ( name , reducer ) { if ( tables . has ( name ) ) { throw new Error ( `Domain name "${ name }" already exists."` ) ; } tables . set ( name , true ) ; reducers [ name ] = reducer ; if ( ! Root [ name ] ) { setRootQuery ( name ) ; } tableCreatedSubject$ . next ( name ) ; } export function getReducers ( ) { return Object . assign ( { } , reducers ) as any ; } export const tableCreated$ = tableCreatedSubject$ . asObservable ( ) ; param base returns { ( selector : ( state : TState ) => TType ) => Selector < State , TOutput > } export function combineFactory < TState > ( base ) { return < TType > ( selector ) => createSelector ( base , selector ) ; } param domain param query returns { Query < TState > } export function setRootQuery < TState > ( domain , query ? ) { if ( Root [ domain ] ) { throw new Error ( `A root query for domain "${ domain }" is already defined` ) ; } const rootQuery = safeQuery ( query , domain ) ; Object . defineProperty ( Root , domain , { value : rootQuery } ) ; return rootQuery ; } param domain returns { ( selector : ( state : TState ) => TType ) => ( state : State ) => TType } export function combineRootFactory < TState > ( domain ) { const rootFn = Root [ domain ] || setRootQuery < TState > ( domain ) ; return combineFactory ( rootFn ) ; } param cls param name export function register ( cls , name ? ) { Model [ name || cls . name ] = cls ; } param ns export function registerNS ( ns ) { Object . keys ( ns ) . forEach ( key => register ( ns [ key ] ) ) ; }