import { Inject, Injectable, InjectionToken, NgZone, Optional, PLATFORM_ID } from '@angular/core'; import { AngularFireList, AngularFireObject, DatabaseQuery, PathReference, QueryFn } from './interfaces'; import { getRef } from './utils'; import { createListReference } from './list/create-reference'; import { createObjectReference } from './object/create-reference'; import { FIREBASE_APP_NAME, FIREBASE_OPTIONS, FirebaseAppConfig, FirebaseOptions, ɵAngularFireSchedulers, ɵfirebaseAppFactory, ɵkeepUnstableUntilFirstFactory, } from '@angular/fire'; import { Observable } from 'rxjs'; import 'firebase/database'; import { USE_EMULATOR as USE_AUTH_EMULATOR } from '@angular/fire/auth'; import firebase from 'firebase/app'; import { ɵfetchInstance, ɵlogAuthEmulatorError } from '@angular/fire'; export const URL = new InjectionToken('angularfire2.realtimeDatabaseURL'); // SEMVER(7): use Parameters to detirmine the useEmulator arguments // TODO(jamesdaniels): don't hardcode, but having tyepscript issues with firebase.database.Database // type UseEmulatorArguments = Parameters; type UseEmulatorArguments = [string, number]; export const USE_EMULATOR = new InjectionToken('angularfire2.database.use-emulator'); @Injectable({ providedIn: 'any' }) export class AngularFireDatabase { public readonly database: firebase.database.Database; public readonly schedulers: ɵAngularFireSchedulers; public readonly keepUnstableUntilFirst: (obs$: Observable) => Observable; constructor( @Inject(FIREBASE_OPTIONS) options: FirebaseOptions, @Optional() @Inject(FIREBASE_APP_NAME) nameOrConfig: string | FirebaseAppConfig | null | undefined, @Optional() @Inject(URL) databaseURL: string | null, // tslint:disable-next-line:ban-types @Inject(PLATFORM_ID) platformId: Object, zone: NgZone, @Optional() @Inject(USE_EMULATOR) _useEmulator: any, // tuple isn't working here @Optional() @Inject(USE_AUTH_EMULATOR) useAuthEmulator: any, ) { this.schedulers = new ɵAngularFireSchedulers(zone); this.keepUnstableUntilFirst = ɵkeepUnstableUntilFirstFactory(this.schedulers); const useEmulator: UseEmulatorArguments | null = _useEmulator; const app = ɵfirebaseAppFactory(options, zone, nameOrConfig); if (!firebase.auth && useAuthEmulator) { ɵlogAuthEmulatorError(); } this.database = ɵfetchInstance(`${app.name}.database.${databaseURL}`, 'AngularFireDatabase', app, () => { const database = zone.runOutsideAngular(() => app.database(databaseURL || undefined)); if (useEmulator) { database.useEmulator(...useEmulator); } return database; }, [useEmulator]); } list(pathOrRef: PathReference, queryFn?: QueryFn): AngularFireList { const ref = this.schedulers.ngZone.runOutsideAngular(() => getRef(this.database, pathOrRef)); let query: DatabaseQuery = ref; if (queryFn) { query = queryFn(ref); } return createListReference(query, this); } object(pathOrRef: PathReference): AngularFireObject { const ref = this.schedulers.ngZone.runOutsideAngular(() => getRef(this.database, pathOrRef)); return createObjectReference(ref, this); } createPushId() { const ref = this.schedulers.ngZone.runOutsideAngular(() => this.database.ref()); return ref.push().key; } } export { PathReference, DatabaseSnapshot, ChildEvent, ListenEvent, QueryFn, AngularFireList, AngularFireObject, AngularFireAction, Action, SnapshotAction } from './interfaces';