11import { catchError , take , tap , map } from 'rxjs/operators'
2- import { AngularFireDatabase } from 'angularfire2/database'
3- import { Inject , Injectable , Optional } from '@angular/core'
4- import { HttpClient , HttpParams , HttpResponse } from '@angular/common/http'
52import {
6- FIREBASE_USER_AUTH_TOKEN ,
7- LRU_CACHE ,
8- LruCache
9- } from './server.firebase.module'
3+ AngularFireDatabase ,
4+ QueryFn ,
5+ PathReference
6+ } from 'angularfire2/database'
7+ import { Inject , Injectable , InjectionToken , Optional } from '@angular/core'
8+ import { HttpClient , HttpParams , HttpResponse } from '@angular/common/http'
9+ import { LRU_CACHE , LruCache } from './server.firebase.module'
1010import { Observable , of } from 'rxjs'
1111import { IUniversalRtdbService } from './rtdb.interface'
1212import { createHash } from 'crypto'
1313import { TransferState , StateKey } from '@angular/platform-browser'
1414import { makeRtDbStateTransferKey } from './common'
15+ import { makeStateKey } from '@angular/platform-browser'
16+
17+ export const FIREBASE_USER_AUTH_TOKEN = new InjectionToken < string > (
18+ 'fng.fb.svr.usr.auth'
19+ )
1520
1621function sha256 ( data : string ) {
1722 return createHash ( 'sha256' )
@@ -29,39 +34,49 @@ function getFullUrl(base: string, params: HttpParams) {
2934 return stringifiedParams ? `${ base } ?${ params . toString ( ) } ` : base
3035}
3136
32- function getParams ( fromObject = { } ) {
37+ function getParams ( fromObject = { } as any ) {
3338 return new HttpParams ( {
34- fromObject
39+ fromObject : Object . keys ( fromObject ) . reduce ( ( acc , curr ) => {
40+ return fromObject [ curr ]
41+ ? {
42+ ...acc ,
43+ [ curr ] : fromObject [ curr ]
44+ }
45+ : { ...acc }
46+ } , { } )
3547 } )
3648}
3749
3850function mapUndefined ( err : any ) {
3951 return of ( undefined )
4052}
4153
54+ function mapEmptyList < T > ( err : any ) {
55+ return of ( [ ] as ReadonlyArray < T > )
56+ }
57+
4258function attemptToCacheInLru ( key : string , lru ?: LruCache ) {
4359 return function ( response ?: any ) {
4460 lru && response && lru . set ( sha256 ( key ) , response )
4561 }
4662}
4763
48- function httpResponseToValue < T > ( value : HttpResponse < T > ) : T | undefined {
49- return ( value && value . body ) || undefined
50- }
51-
5264function attemptToGetCachedValue < T > ( key : string , lru ?: LruCache ) {
5365 return lru && lru . get < T > ( sha256 ( key ) )
5466}
5567
56- function writeLruCacheToTransferState < T > (
57- ts : TransferState ,
58- key : StateKey < string >
59- ) {
68+ function cacheInStateTransfer < T > ( ts : TransferState , key : StateKey < string > ) {
6069 return function ( val : T ) {
6170 ts . set ( key , val )
6271 }
6372}
6473
74+ function removeHttpInterceptorCache < T > ( ts : TransferState , key : string ) {
75+ return function ( val : T ) {
76+ ts . remove ( makeStateKey < string > ( `G.${ key } ` ) )
77+ }
78+ }
79+
6580// tslint:disable:no-this
6681// tslint:disable-next-line:no-class
6782@Injectable ( )
@@ -84,18 +99,52 @@ export class ServerUniversalRtDbService implements IUniversalRtdbService {
8499 const cacheKey = getFullUrl ( url , params )
85100 const cachedValue = attemptToGetCachedValue < T > ( cacheKey , this . lru )
86101 const tsKey = makeRtDbStateTransferKey ( url )
87-
88- const baseObs = this . authToken
89- ? this . http . get < HttpResponse < T > > ( url , { params } )
90- : this . http . get < HttpResponse < T > > ( url )
102+ const baseObs = this . http . get < HttpResponse < T > > ( url , { params } )
91103
92104 return cachedValue
93- ? of ( cachedValue ) . pipe ( tap ( writeLruCacheToTransferState ( this . ts , tsKey ) ) )
105+ ? of ( cachedValue ) . pipe ( tap ( cacheInStateTransfer ( this . ts , tsKey ) ) )
94106 : baseObs . pipe (
95107 take ( 1 ) ,
96- map ( httpResponseToValue ) ,
108+ tap ( removeHttpInterceptorCache ( this . ts , cacheKey ) ) ,
109+ tap ( cacheInStateTransfer ( this . ts , tsKey ) ) ,
97110 tap ( attemptToCacheInLru ( cacheKey , this . lru ) ) ,
98111 catchError ( mapUndefined )
99112 )
100113 }
114+
115+ universalList < T > (
116+ path : PathReference ,
117+ queryFn ?: QueryFn
118+ ) : Observable < ReadonlyArray < T > > {
119+ const query =
120+ ( queryFn && queryFn ( this . afdb . database . ref ( path . toString ( ) ) ) ) ||
121+ this . afdb . database . ref ( path . toString ( ) )
122+ const internalQueryParams = ( query as any ) . queryParams_
123+ const paramsFromString = internalQueryParams . toRestQueryStringParameters ( )
124+ const url = `${ query . toString ( ) } .json`
125+ const params = getParams ( { ...paramsFromString , auth : this . authToken } )
126+ const cacheKey = getFullUrl ( url , params )
127+ const tsKey = makeRtDbStateTransferKey ( url )
128+ const baseObs = this . http . get < ReadonlyArray < T > > ( url , { params } )
129+ const cachedValue = attemptToGetCachedValue < ReadonlyArray < T > > (
130+ cacheKey ,
131+ this . lru
132+ )
133+
134+ return cachedValue
135+ ? of ( cachedValue ) . pipe ( tap ( cacheInStateTransfer ( this . ts , tsKey ) ) )
136+ : baseObs . pipe (
137+ take ( 1 ) ,
138+ tap ( removeHttpInterceptorCache ( this . ts , url ) ) ,
139+ map ( ( val : any ) => {
140+ return Array . isArray ( val )
141+ ? val . filter ( Boolean )
142+ : Object . keys ( val ) . map ( key => val [ key ] )
143+ } ) ,
144+ tap ( cacheInStateTransfer ( this . ts , tsKey ) ) ,
145+ tap ( attemptToCacheInLru ( cacheKey , this . lru ) ) ,
146+
147+ catchError ( mapEmptyList )
148+ )
149+ }
101150}
0 commit comments