import { Inject , Injectable , InjectionToken , NgZone , Optional , PLATFORM_ID } from '@angular/core' ; import { EMPTY , Observable , of , Subscription } from 'rxjs' ; import { map , shareReplay , switchMap , tap } from 'rxjs/operators' ; import firebase from 'firebase/compat/app' ; import { ɵapplyMixins , ɵlazySDKProxy , ɵPromiseProxy , ɵcacheInstance } from '@angular/fire/compat' ; import { FirebaseApp } from '@angular/fire/compat' ; import { isPlatformBrowser } from '@angular/common' ; import { proxyPolyfillCompat } from './base' ; export const INSTRUMENTATION_ENABLED = new InjectionToken < boolean > ( 'angularfire2.performance.instrumentationEnabled' ) ; export const DATA_COLLECTION_ENABLED = new InjectionToken < boolean > ( 'angularfire2.performance.dataCollectionEnabled' ) ; export interface AngularFirePerformance extends ɵPromiseProxy < firebase . performance . Performance > { } @ Injectable ( { providedIn : 'any' } ) export class AngularFirePerformance { private readonly performance : Observable < firebase . performance . Performance > ; constructor ( app , @ Optional ( ) @ Inject ( INSTRUMENTATION_ENABLED ) instrumentationEnabled , @ Optional ( ) @ Inject ( DATA_COLLECTION_ENABLED ) dataCollectionEnabled , private zone , @ Inject ( PLATFORM_ID ) platformId ) { this . performance = of ( undefined ) . pipe ( switchMap ( ( ) => isPlatformBrowser ( platformId ) ? zone . runOutsideAngular ( ( ) => import ( 'firebase/compat/performance' ) ) : EMPTY ) , map ( ( ) => ɵcacheInstance ( `performance` , 'AngularFirePerformance' , app . name , ( ) => { const performance = zone . runOutsideAngular ( ( ) => app . performance ( ) ) ; if ( instrumentationEnabled === false ) { performance . instrumentationEnabled = false ; } if ( dataCollectionEnabled === false ) { performance . dataCollectionEnabled = false ; } return performance ; } , [ instrumentationEnabled , dataCollectionEnabled ] ) ) , shareReplay ( { bufferSize : 1 , refCount : false } ) ) ; return ɵlazySDKProxy ( this , this . performance , zone ) ; } } const trace$ = ( traceId ) => { if ( typeof window !== 'undefined' && window . performance ?. mark ) { const entries = window . performance . getEntriesByName ( traceId , 'measure' ) || [ ] ; const startMarkName = `_${ traceId }Start[${ entries . length }]` ; const endMarkName = `_${ traceId }End[${ entries . length }]` ; return new Observable < void > ( emitter => { window . performance . mark ( startMarkName ) ; emitter . next ( ) ; return { unsubscribe : ( ) => { window . performance . mark ( endMarkName ) ; window . performance . measure ( traceId , startMarkName , endMarkName ) ; } } ; } ) ; } else { return EMPTY ; } } ; export const traceUntil = < T = any > ( name , test , options ? ) => ( source$ ) => new Observable < T > ( subscriber => { const traceSubscription = trace$ ( name ) . subscribe ( ) ; return source$ . pipe ( tap ( a => test ( a ) && traceSubscription . unsubscribe ( ) , ( ) => { } , ( ) => options && options . orComplete && traceSubscription . unsubscribe ( ) ) ) . subscribe ( subscriber ) ; } ) ; export const traceWhile = < T = any > ( name , test , options ? ) => ( source$ ) => new Observable < T > ( subscriber => { let traceSubscription ; return source$ . pipe ( tap ( a => { if ( test ( a ) ) { traceSubscription = traceSubscription || trace$ ( name ) . subscribe ( ) ; } else { if ( traceSubscription ) { traceSubscription . unsubscribe ( ) ; } traceSubscription = undefined ; } } , ( ) => { } , ( ) => options && options . orComplete && traceSubscription && traceSubscription . unsubscribe ( ) ) ) . subscribe ( subscriber ) ; } ) ; export const traceUntilComplete = < T = any > ( name ) => ( source$ ) => new Observable < T > ( subscriber => { const traceSubscription = trace$ ( name ) . subscribe ( ) ; return source$ . pipe ( tap ( ( ) => { } , ( ) => { } , ( ) => traceSubscription . unsubscribe ( ) ) ) . subscribe ( subscriber ) ; } ) ; export const traceUntilFirst = < T = any > ( name ) => ( source$ ) => new Observable < T > ( subscriber => { const traceSubscription = trace$ ( name ) . subscribe ( ) ; return source$ . pipe ( tap ( ( ) => traceSubscription . unsubscribe ( ) , ( ) => { } , ( ) => { } ) ) . subscribe ( subscriber ) ; } ) ; export const trace = < T = any > ( name ) => ( source$ ) => new Observable < T > ( subscriber => { const traceSubscription = trace$ ( name ) . subscribe ( ) ; return source$ . pipe ( tap ( ( ) => traceSubscription . unsubscribe ( ) , ( ) => { } , ( ) => traceSubscription . unsubscribe ( ) ) ) . subscribe ( subscriber ) ; } ) ; ɵapplyMixins ( AngularFirePerformance , [ proxyPolyfillCompat ] ) ;