import * as Rx from "rxjs" ; import * as RxOps from "rxjs/operators" ; import * as A from "./atom" ; import * as L from "./lens" ; export type NativeProperty < T > = Rx . Observable < T > ; export type NativeAtom < T > = A . Atom < T > ; export type NativeEventStream < T > = Rx . Observable < T > ; export type Lens < A , B > = L . Lens < A , B > ; export type Scope = { start ( ) : void ; end ( ) : void ; } ; const mockScope = { start ( ) { } , end ( ) { } , } ; export function createScope ( ) { return mockScope ; } export function mkScope ( scopeFn ) { return mockScope ; } export type Predicate < A > = ( value : A ) => boolean ; export type Observable < T > = { } ; export type Atom < T > = { } ; export type Property < T > = { } ; export type EventStream < T > = { } ; export interface Bus < T > extends NativeEventStream < T > { } export type Unsub = ( ) => void ; export function bus < T > ( ) { return new Rx . Subject < T > ( ) ; } export function pushAndEnd < T > ( bus , value ) { const subject = bus as Rx . Subject < T > ; subject . next ( value ) ; subject . complete ( ) ; } export function get < A > ( prop ) { return getCurrentValue ( prop as Rx . Observable < A > ) ; } export function set < A > ( atom , value ) { ; ( atom as A . Atom < A > ) . set ( value ) ; } export function isAtom ( x ) { return A . isAtom ( x ) ; } export function isProperty ( x ) { return ! ! ( x && x . subscribe && x . forEach ) ; } export function forEach < V > ( x , fn ) { return _forEach ( x as Rx . Observable < V > , fn ) ; } export function view < A , K extends keyof A > ( a , key ) ; export function view < A , K extends keyof A > ( a , key ) ; export function view < A , B > ( a , fn ) ; export function view < A , K extends keyof A > ( a , key ) { if ( typeof key === "function" ) { const obs = a as Rx . Observable < A > ; return obs . pipe ( RxOps . map ( key ) , RxOps . distinctUntilChanged ( ) ) ; } else if ( A . isAtom ( a ) ) { return a . view ( key as any ) ; } else if ( isProperty ( a ) ) { const obs = a as Rx . Observable < A > ; if ( L . isLens ( key ) ) { return obs . pipe ( RxOps . map ( key . get ) ) ; } return obs . pipe ( RxOps . map ( ( x ) => x [ key ] ) ) ; } else { throw Error ( "Unknown observable: " + a ) ; } } export function filter < A > ( a , fn , scope ) ; export function filter < A > ( a , fn , scope ) ; export function filter < A > ( a , fn , scope ) { if ( A . isAtom ( a ) ) { return a . freezeUnless ( fn as any ) ; } else if ( isProperty ( a ) ) { return ( a as Rx . Observable < A > ) . pipe ( RxOps . filter ( fn ) ) ; } else { throw Error ( "Unknown observable: " + a ) ; } } export const valueMissing = { } ; export type ValueMissing = typeof valueMissing ; export function _forEach < V > ( x , fn ) { const subscription = x . pipe ( RxOps . tap ( ( value ) => { fn ( value ) ; } ) ) . subscribe ( ( ) => { } , ( error ) => { console . error ( "Caught error event" , error ) ; throw new Error ( `Got error from observable ${ x }: ${ error }. Harmaja does not handle errors.` ) ; } , ( ) => { } ) ; return ( ) => subscription . unsubscribe ( ) ; } export function getCurrentValue < A > ( observable ) { let currentV = valueMissing ; if ( ( observable as any ) . get ) { currentV = ( observable as any ) . get ( ) ; } else { _forEach ( observable . pipe ( RxOps . take ( 1 ) ) , ( v ) => ( currentV = v ) ) ; } if ( currentV === valueMissing ) { console . log ( "Current value not found!" , observable ) ; throw new Error ( "Current value missing. Cannot render. " + observable ) ; } return currentV ; } export const observablesImplementationName = "RxJs" ;