import { NgZone , Type } from '@angular/core' ; import { ReplaySubject } from 'rxjs' ; import { ReduxStateDecorator } from '@harmowatch/redux-decorators' ; import { ReduxRegistry } from './providers/redux-registry' ; import { ReduxRootState } from './interfaces/redux-root-state.interface' ; import { ReduxStateProvider } from './providers/redux-state.provider' ; export class ReduxSelector < T > extends ReplaySubject < T > { private static readonly DELIMITER = '/' ; constructor ( zone , selector = '/' , stateProvider ? ) { if ( ! selector . startsWith ( ReduxSelector . DELIMITER ) && ! stateProvider ) { throw new Error ( 'You need to provide a state provider, if you use relative selectors' ) ; } super ( 1 ) ; ReduxRegistry . getStore ( ) . then ( store => { const next = ( ) => { zone . run ( ( ) => { this . next ( ReduxSelector . getValueByState ( store . getState ( ) , selector , stateProvider ) ) ; } ) ; } ; store . subscribe ( ( ) => next ( ) ) ; next ( ) ; } ) ; } public static normalize ( selector , stateProvider ? ) { if ( ! selector . startsWith ( ReduxSelector . DELIMITER ) ) { const stateName = ReduxStateDecorator . get ( stateProvider ) . name ; return `${ ReduxSelector . DELIMITER }${ stateName }${ ReduxSelector . DELIMITER }${ selector }` ; } return selector ; } public static getValueByState < S > ( state , selector , stateProvider ? ) { const value = ReduxSelector . normalize ( selector , stateProvider ) . split ( ReduxSelector . DELIMITER ) . filter ( propertyKey => propertyKey !== '' ) . reduce ( ( previousValue , propertyKey ) => { if ( ! previousValue || ! previousValue . hasOwnProperty ( propertyKey ) ) { return null ; } return previousValue [ propertyKey ] ; } , state as { } ) ; return value ; } }