import { Inject , Injectable , InjectionToken , NgZone , Optional , PLATFORM_ID } from '@angular/core' ; import { from , Observable , of } from 'rxjs' ; import { AssociatedReference , CollectionReference , DocumentReference , PersistenceSettings , Query , QueryFn , QueryGroupFn , Settings } from './interfaces' ; import { AngularFirestoreDocument } from './document/document' ; import { AngularFirestoreCollection } from './collection/collection' ; import { AngularFirestoreCollectionGroup } from './collection-group/collection-group' ; import { ɵAngularFireSchedulers } from '@angular/fire' ; import { FirebaseApp , ɵfirebaseAppFactory , FIREBASE_APP_NAME , FIREBASE_OPTIONS , ɵcacheInstance } from '@angular/fire/compat' ; import { FirebaseOptions } from 'firebase/app' ; import { isPlatformServer } from '@angular/common' ; import firebase from 'firebase/compat/app' ; import 'firebase/compat/auth' ; import 'firebase/compat/firestore' ; import { AngularFireAuth , USE_EMULATOR as USE_AUTH_EMULATOR , SETTINGS as AUTH_SETTINGS , TENANT_ID , LANGUAGE_CODE , USE_DEVICE_LANGUAGE , PERSISTENCE , ɵauthFactory , } from '@angular/fire/compat/auth' ; import { AppCheckInstances } from '@angular/fire/app-check' ; /**
 * The value of this token determines whether or not the firestore will have persistance enabled
 */ export const ENABLE_PERSISTENCE = new InjectionToken < boolean > ( 'angularfire2.enableFirestorePersistence' ) ; export const PERSISTENCE_SETTINGS = new InjectionToken < PersistenceSettings | undefined > ( 'angularfire2.firestore.persistenceSettings' ) ; export const SETTINGS = new InjectionToken < Settings > ( 'angularfire2.firestore.settings' ) ; type UseEmulatorArguments = Parameters < firebase . firestore . Firestore [ 'useEmulator' ] > ; export const USE_EMULATOR = new InjectionToken < UseEmulatorArguments > ( 'angularfire2.firestore.use-emulator' ) ; param collectionRef param queryFn export function associateQuery < T > ( collectionRef , queryFn = ref => ref ) { const query = queryFn ( collectionRef ) ; const ref = collectionRef ; return { query , ref } ; } type InstanceCache = Map < FirebaseApp , [ firebase . firestore . Firestore , firebase . firestore . Settings | null , UseEmulatorArguments | null , boolean | null ] > ; Component @ Injectable ( { providedIn : 'any' } ) export class AngularFirestore { public readonly firestore : firebase . firestore . Firestore ; public readonly persistenceEnabled$ : Observable < boolean > ; /**
     * Each Feature of AngularFire has a FirebaseApp injected. This way we
     * don't rely on the main Firebase App instance and we can create named
     * apps and use multiple apps.
     */ constructor ( @ Inject ( FIREBASE_OPTIONS ) options , @ Optional ( ) @ Inject ( FIREBASE_APP_NAME ) name , @ Optional ( ) @ Inject ( ENABLE_PERSISTENCE ) shouldEnablePersistence , @ Optional ( ) @ Inject ( SETTINGS ) settings , @ Inject ( PLATFORM_ID ) platformId , zone , public schedulers , @ Optional ( ) @ Inject ( PERSISTENCE_SETTINGS ) persistenceSettings , @ Optional ( ) @ Inject ( USE_EMULATOR ) _useEmulator , @ Optional ( ) auth , @ Optional ( ) @ Inject ( USE_AUTH_EMULATOR ) useAuthEmulator , @ Optional ( ) @ Inject ( AUTH_SETTINGS ) authSettings , @ Optional ( ) @ Inject ( TENANT_ID ) tenantId , @ Optional ( ) @ Inject ( LANGUAGE_CODE ) languageCode , @ Optional ( ) @ Inject ( USE_DEVICE_LANGUAGE ) useDeviceLanguage , @ Optional ( ) @ Inject ( PERSISTENCE ) persistence , @ Optional ( ) _appCheckInstances ) { const app = ɵfirebaseAppFactory ( options , zone , name ) ; const useEmulator = _useEmulator ; if ( auth ) { ɵauthFactory ( app , zone , useAuthEmulator , tenantId , languageCode , useDeviceLanguage , authSettings , persistence ) ; } [ this . firestore , this . persistenceEnabled$ ] = ɵcacheInstance ( `${ app . name }.firestore` , 'AngularFirestore' , app . name , ( ) => { const firestore = zone . runOutsideAngular ( ( ) => app . firestore ( ) ) ; if ( settings ) { firestore . settings ( settings ) ; } if ( useEmulator ) { firestore . useEmulator ( ... useEmulator ) ; } if ( shouldEnablePersistence && ! isPlatformServer ( platformId ) ) { const enablePersistence = ( ) => { try { return from ( firestore . enablePersistence ( persistenceSettings || undefined ) . then ( ( ) => true , ( ) => false ) ) ; } catch ( e ) { if ( typeof console !== 'undefined' ) { console . warn ( e ) ; } return of ( false ) ; } } ; return [ firestore , zone . runOutsideAngular ( enablePersistence ) ] ; } else { return [ firestore , of ( false ) ] ; } } , [ settings , useEmulator , shouldEnablePersistence ] ) ; } /**
     * Create a reference to a Firestore Collection based on a path or
     * CollectionReference and an optional query function to narrow the result
     * set.
     */ collection < T > ( path , queryFn ? ) ; collection < T > ( ref , queryFn ? ) ; collection < T > ( pathOrRef , queryFn ? ) { let collectionRef ; if ( typeof pathOrRef === 'string' ) { collectionRef = this . firestore . collection ( pathOrRef ) as firebase . firestore . CollectionReference < T > ; } else { collectionRef = pathOrRef ; } const { ref , query } = associateQuery < T > ( collectionRef , queryFn ) ; const refInZone = this . schedulers . ngZone . run ( ( ) => ref ) ; return new AngularFirestoreCollection < T > ( refInZone , query , this ) ; } /**
     * Create a reference to a Firestore Collection Group based on a collectionId
     * and an optional query function to narrow the result
     * set.
     */ collectionGroup < T > ( collectionId , queryGroupFn ? ) { const queryFn = queryGroupFn || ( ref => ref ) ; const collectionGroup = this . firestore . collectionGroup ( collectionId ) as firebase . firestore . Query < T > ; return new AngularFirestoreCollectionGroup < T > ( queryFn ( collectionGroup ) , this ) ; } /**
     * Create a reference to a Firestore Document based on a path or
     * DocumentReference. Note that documents are not queryable because they are
     * simply objects. However, documents have sub-collections that return a
     * Collection reference and can be queried.
     */ doc < T > ( path ) ; doc < T > ( ref ) ; doc < T > ( pathOrRef ) { let ref ; if ( typeof pathOrRef === 'string' ) { ref = this . firestore . doc ( pathOrRef ) as firebase . firestore . DocumentReference < T > ; } else { ref = pathOrRef ; } const refInZone = this . schedulers . ngZone . run ( ( ) => ref ) ; return new AngularFirestoreDocument < T > ( refInZone , this ) ; } /**
     * Returns a generated Firestore Document Id.
     */ createId ( ) { return this . firestore . collection ( '_' ) . doc ( ) . id ; } }