import { Inject , Injectable , PLATFORM_ID } from '@angular/core' ; import { AngularFireLiteApp } from '../core.service' ; import { HttpClient } from '@angular/common/http' ; import { makeStateKey , TransferState } from '@angular/platform-browser' ; import { isPlatformBrowser , isPlatformServer } from '@angular/common' ; import { BehaviorSubject , from , Observable } from 'rxjs' ; import { map } from 'rxjs/operators' ; import { FirebaseDatabase } from '@firebase/database-types' ; import 'firebase/database' ; @ Injectable ( ) export class AngularFireLiteDatabase { private readonly database : FirebaseDatabase ; private readonly config ; private readonly server = isPlatformServer ( this . platformId ) ; private readonly browser = isPlatformBrowser ( this . platformId ) ; private readonly ref = ( ref ) => this . database . ref ( ref ) ; constructor ( private app , private http , private state , @ Inject ( PLATFORM_ID ) private platformId ) { this . database = app . instance ( ) . database ( ) ; this . config = app . config ( ) ; } read ( ref ) { const dataStateKey = makeStateKey < Object | Array < any > > ( ref + 'rtd:read' ) ; if ( this . server ) { return this . SRH ( ref , dataStateKey ) ; } if ( this . browser ) { return this . BRH ( ref , 'value' , dataStateKey ) ; } } childAdded ( ref ) { const dataStateKey = makeStateKey < Object > ( ref + 'rtd:child_added' ) ; if ( this . server ) { return this . SRH ( ref , dataStateKey ) ; } if ( this . browser ) { return this . BRH ( ref , 'child_added' , dataStateKey ) ; } } childChanged ( ref ) { const dataStateKey = makeStateKey < Object > ( ref + 'rtd:child_changed' ) ; if ( this . server ) { return this . SRH ( ref , dataStateKey ) ; } if ( this . browser ) { return this . BRH ( ref , 'child_changed' , dataStateKey ) ; } } childRemoved ( ref ) { const dataStateKey = makeStateKey < Object > ( ref + 'rtd:child_removed' ) ; if ( this . server ) { return this . SRH ( ref , dataStateKey ) ; } if ( this . browser ) { return this . BRH ( ref , 'child_removed' , dataStateKey ) ; } } childMoved ( ref ) { const dataStateKey = makeStateKey < Object > ( ref + 'rtd:child_moved' ) ; if ( this . server ) { return this . SRH ( ref , dataStateKey ) ; } if ( this . browser ) { return this . BRH ( ref , 'child_moved' , dataStateKey ) ; } } write ( ref , data ) { if ( this . server ) { return this . http . put ( `https://${ this . config . projectId }.firebaseio.com/${ ref }.json?print=silent` , data ) ; } if ( this . browser ) { return from ( this . ref ( ref ) . set ( data ) ) ; } } push ( ref , data ) { if ( this . server ) { return this . http . post ( `https://${ this . config . projectId }.firebaseio.com/${ ref }.json?print=silent` , data ) ; } if ( this . browser ) { return from ( this . ref ( ref ) . push ( data ) ) ; } } update ( ref , data ) { if ( this . server ) { return this . http . patch ( `https://${ this . config . projectId }.firebaseio.com/${ ref }.json?print=silent` , data ) ; } if ( this . browser ) { return from ( this . ref ( ref ) . update ( data ) ) ; } } remove ( ref ) { if ( this . server ) { return this . http . delete ( `https://${ this . config . projectId }.firebaseio.com/${ ref }.json` ) ; } if ( this . browser ) { return from ( this . ref ( ref ) . remove ( ) ) ; } } query ( ref ) { const PID = this . platformId ; const state = this . state ; const db = this . database ; const http = this . http ; const config = this . config ; const SQH = function ( REF , FSQ , DSK ) { return http . get ( `https://${ config . projectId }.firebaseio.com/${ REF }.json?${ FSQ }` ) . pipe ( map ( ( payload ) => { if ( ! ! payload && typeof payload === 'object' ) { const result = [ ] ; Object . keys ( payload ) . forEach ( ( key ) => { result . push ( payload [ key ] ) ; } ) ; state . set ( DSK , result ) ; return result ; } else { state . set ( DSK , payload ) ; return payload ; } } ) ) ; } ; const BQH = function ( BS ) { return ( snapshot ) => { if ( ! ! snapshot . val ( ) && typeof snapshot . val ( ) === 'object' ) { const result = Object . keys ( snapshot . val ( ) ) . map ( function ( key ) { return [ snapshot . val ( ) [ key ] ] ; } ) ; BS . next ( result ) ; } else { BS . next ( snapshot . val ( ) ) ; } } ; } ; let SQ = '' ; let BQ = this . ref ( ref ) as any ; return { startAt ( value ) { SQ += `&startAt=${ value }` ; BQ = BQ . startAt ( value ) ; return this ; } , endAt ( value ) { SQ += `&endAt=${ value }` ; BQ = BQ . endAt ( value ) ; return this ; } , equalTo ( value ) { SQ += `&equalTo=${ value }` ; BQ = BQ . equalTo ( value ) ; return this ; } , isEqual ( query ) { if ( isPlatformBrowser ( PID ) ) { return db . ref ( ref ) . isEqual ( query ) ; } } , limitToFirst ( limit ) { SQ += `&limitToFirst=${ limit }` ; BQ = BQ . limitToFirst ( limit ) ; return this ; } , limitToLast ( limit ) { SQ += `&limitToLast=${ limit }` ; BQ = BQ . limitToLast ( limit ) ; return this ; } , orderByChild ( path ) { SQ += `&orderBy="${ path }"` ; BQ = BQ . orderByChild ( path ) ; return this ; } , orderByKey ( ) { SQ += `&orderBy="$key"` ; BQ = BQ . orderByKey ( ) ; return this ; } , orderByPriority ( ) { SQ += `&orderBy="$priority"` ; BQ = BQ . orderByPriority ( ) ; return this ; } , orderByValue ( ) { SQ += `&orderBy="$value"` ; BQ = BQ . orderByValue ( ) ; return this ; } , on ( event ) { const dataStateKey = makeStateKey < Object | Array < any > > ( ref + 'rtd' ) ; if ( isPlatformServer ( PID ) ) { return SQH ( ref , SQ , dataStateKey ) ; } if ( isPlatformBrowser ( PID ) ) { const SSRedValue = state . get ( dataStateKey , [ ] ) ; const VALUE = new BehaviorSubject < any > ( SSRedValue ) ; BQ . on ( event , BQH ( VALUE ) ) ; return VALUE ; } } , once ( event ) { const dataStateKey = makeStateKey < Object | Array < any > > ( ref + 'rtd' ) ; if ( isPlatformServer ( PID ) ) { return SQH ( ref , SQ , dataStateKey ) ; } if ( isPlatformBrowser ( PID ) ) { const SSRedValue = state . get ( dataStateKey , [ ] ) ; const VALUE = new BehaviorSubject < any > ( SSRedValue ) ; BQ . once ( event , BQH ( VALUE ) ) ; return VALUE ; } } } ; } private SRH ( ref , DSK ) { if ( this . server ) { return this . http . get ( `https://${ this . config . projectId }.firebaseio.com/${ ref }.json` ) . pipe ( map ( ( payload ) => { if ( ! ! payload && typeof payload === 'object' ) { const result = Object . keys ( payload ) . map ( ( key ) => { return [ payload [ key ] ] ; } ) ; this . state . set ( DSK , result ) ; return result ; } else { this . state . set ( DSK , payload ) ; return payload ; } } ) ) ; } } private BRH ( ref , event , DSK ) { if ( this . browser ) { const SSRedValue = this . state . get ( DSK , [ ] ) ; const DATA = new BehaviorSubject < any > ( SSRedValue ) ; this . ref ( ref ) . on ( event , ( snapshot ) => { if ( ! ! snapshot . val ( ) && typeof snapshot . val ( ) === 'object' ) { const result = Object . keys ( snapshot . val ( ) ) . map ( function ( key ) { return [ snapshot . val ( ) [ key ] ] ; } ) ; DATA . next ( result ) ; } else { DATA . next ( snapshot . val ( ) ) ; } } ) ; return DATA ; } } } export interface RDQuery { startAt ( value ) : RDQuery ; endAt ( value ) : RDQuery ; equalTo ( value ) : RDQuery ; isEqual ( other ) : boolean ; limitToFirst ( limit ) : RDQuery ; limitToLast ( limit ) : RDQuery ; orderByChild ( path ) : RDQuery ; orderByKey ( ) : RDQuery ; orderByPriority ( ) : RDQuery ; orderByValue ( ) : RDQuery ; on ( eventType ) : Observable < any > | any ; once ( eventType ) : Observable < any > | any ; }