From 06e9814925f0638906ead9b377d156d345ee43e9 Mon Sep 17 00:00:00 2001
From: James Daniels <jamesdaniels@google.com>
Date: Tue, 15 May 2018 15:10:17 -0700
Subject: [PATCH] fix(): allow initializeApp to be used with AOT

---
 src/auth/auth.spec.ts                   |  4 ++--
 src/auth/auth.ts                        |  7 +++----
 src/core/angularfire2.ts                |  3 +--
 src/core/firebase.app.module.ts         | 24 +++++++++---------------
 src/database-deprecated/database.ts     |  7 +++----
 src/database/database.spec.ts           |  6 +++---
 src/database/database.ts                |  7 +++----
 src/firestore/firestore.spec.ts         |  4 ++--
 src/firestore/firestore.ts              |  7 +++----
 src/storage/storage.spec.ts             |  4 ++--
 src/storage/storage.ts                  |  7 +++----
 test/ng-build/ng6/package.json          |  6 +++---
 test/ng-build/ng6/src/app/app.module.ts | 17 ++++++-----------
 test/ng-build/ng6/yarn.lock             |  2 +-
 14 files changed, 44 insertions(+), 61 deletions(-)

diff --git a/src/auth/auth.spec.ts b/src/auth/auth.spec.ts
index d8f16fb57..891b1e2b8 100644
--- a/src/auth/auth.spec.ts
+++ b/src/auth/auth.spec.ts
@@ -2,7 +2,7 @@ import { User } from '@firebase/auth-types';
 import { ReflectiveInjector, Provider } from '@angular/core';
 import { Observable, Subject } from 'rxjs'
 import { TestBed, inject } from '@angular/core/testing';
-import { FirebaseApp, FirebaseOptionsToken, AngularFireModule, FirebaseAppNameToken } from 'angularfire2';
+import { FirebaseApp, FirebaseOptionsToken, AngularFireModule, FirebaseNameOrConfigToken } from 'angularfire2';
 import { AngularFireAuth, AngularFireAuthModule } from 'angularfire2/auth';
 import { COMMON_CONFIG } from './test-config';
 import { take, skip } from 'rxjs/operators';
@@ -136,7 +136,7 @@ describe('AngularFireAuth with different app', () => {
         AngularFireAuthModule
       ],
       providers: [
-        { provide: FirebaseAppNameToken, useValue: FIREBASE_APP_NAME_TOO },
+        { provide: FirebaseNameOrConfigToken, useValue: FIREBASE_APP_NAME_TOO },
         { provide: FirebaseOptionsToken, useValue: COMMON_CONFIG }
       ]
     });
diff --git a/src/auth/auth.ts b/src/auth/auth.ts
index 9cbbf0bd7..41d4a1c35 100644
--- a/src/auth/auth.ts
+++ b/src/auth/auth.ts
@@ -4,7 +4,7 @@ import { Injectable, Inject, Optional, NgZone, PLATFORM_ID } from '@angular/core
 import { Observable, of, from } from 'rxjs';
 import { switchMap } from 'rxjs/operators';
 
-import { FirebaseOptionsToken, FirebaseAppConfigToken, FirebaseAppNameToken, _firebaseAppFactory, FirebaseZoneScheduler } from 'angularfire2';
+import { FirebaseOptionsToken, FirebaseNameOrConfigToken, _firebaseAppFactory, FirebaseZoneScheduler } from 'angularfire2';
 
 
 @Injectable()
@@ -39,14 +39,13 @@ export class AngularFireAuth {
 
   constructor(
     @Inject(FirebaseOptionsToken) options:FirebaseOptions,
-    @Optional() @Inject(FirebaseAppConfigToken) config:FirebaseAppConfig,
-    @Optional() @Inject(FirebaseAppNameToken) name:string,
+    @Optional() @Inject(FirebaseNameOrConfigToken) nameOrConfig:string|FirebaseAppConfig|undefined,
     @Inject(PLATFORM_ID) platformId: Object,
     private zone: NgZone
   ) {
     const scheduler = new FirebaseZoneScheduler(zone, platformId);
     this.auth = zone.runOutsideAngular(() => {
-      const app = _firebaseAppFactory(options, name, config);
+      const app = _firebaseAppFactory(options, nameOrConfig);
       return app.auth();
     });
 
diff --git a/src/core/angularfire2.ts b/src/core/angularfire2.ts
index 4c2345cd4..46cd1b65c 100644
--- a/src/core/angularfire2.ts
+++ b/src/core/angularfire2.ts
@@ -6,9 +6,8 @@ import { first } from 'rxjs/operators';
 import firebase from '@firebase/app';
 import { FirebaseApp, FirebaseOptions, FirebaseAppConfig } from '@firebase/app-types';
 
-export const FirebaseAppNameToken = new InjectionToken<string|undefined>('angularfire2.app.name');
 export const FirebaseOptionsToken = new InjectionToken<FirebaseOptions>('angularfire2.app.options');
-export const FirebaseAppConfigToken = new InjectionToken<FirebaseAppConfig|undefined>('angularfire2.app.config');
+export const FirebaseNameOrConfigToken = new InjectionToken<string|FirebaseAppConfig|undefined>('angularfire2.app.nameOrConfig')
 
 // Put in database.ts when we drop database-depreciated
 export const RealtimeDatabaseURL = new InjectionToken<string>('angularfire2.realtimeDatabaseURL');
diff --git a/src/core/firebase.app.module.ts b/src/core/firebase.app.module.ts
index 74d5d0b2f..2373419bb 100644
--- a/src/core/firebase.app.module.ts
+++ b/src/core/firebase.app.module.ts
@@ -1,6 +1,6 @@
 import { InjectionToken, NgZone, NgModule, Optional } from '@angular/core';
 
-import { FirebaseOptionsToken, FirebaseAppNameToken, FirebaseAppConfigToken } from './angularfire2';
+import { FirebaseOptionsToken, FirebaseNameOrConfigToken } from './angularfire2';
 
 import firebase from '@firebase/app';
 import { FirebaseApp as _FirebaseApp, FirebaseOptions, FirebaseAppConfig } from '@firebase/app-types';
@@ -22,12 +22,10 @@ export class FirebaseApp implements _FirebaseApp {
     firestore: () => FirebaseFirestore;
 }
 
-export function _firebaseAppFactory(options: FirebaseOptions, name?: string, appConfig?: FirebaseAppConfig): FirebaseApp {
-    const config = appConfig || {};
-    if (name && config.name && config.name !== name) {
-        console.warn('FirebaseAppNameToken and FirebaseAppConfigToken.name don\'t match, FirebaseAppNameToken takes precedence.');
-    }
-    config.name = name || config.name || '[DEFAULT]';
+export function _firebaseAppFactory(options: FirebaseOptions, nameOrConfig?: string | FirebaseAppConfig) {
+    const name = typeof nameOrConfig === 'string' && nameOrConfig || '[DEFAULT]';
+    const config = typeof nameOrConfig === 'object' && nameOrConfig || {};
+    config.name = config.name || name;
     const existingApp = firebase.apps.filter(app => app.name === config.name)[0];
     return (existingApp || firebase.initializeApp(options, config)) as FirebaseApp;
 }
@@ -37,8 +35,7 @@ const FirebaseAppProvider = {
     useFactory: _firebaseAppFactory,
     deps: [
         FirebaseOptionsToken,
-        [new Optional(), FirebaseAppNameToken],
-        [new Optional(), FirebaseAppConfigToken]
+        [new Optional(), FirebaseNameOrConfigToken]
     ]
 };
  
@@ -46,15 +43,12 @@ const FirebaseAppProvider = {
     providers: [ FirebaseAppProvider ],
 })
 export class AngularFireModule {
-    static initializeApp(options: FirebaseOptions, appNameOrConfig?: string | FirebaseAppConfig) {
-        const name   = typeof appNameOrConfig === 'string' && appNameOrConfig || undefined
-        const config = typeof appNameOrConfig === 'object' && appNameOrConfig || undefined
+    static initializeApp(options: FirebaseOptions, nameOrConfig?: string | FirebaseAppConfig) {
         return {
             ngModule: AngularFireModule,
             providers: [
-                { provide: FirebaseOptionsToken,   useValue: options },
-                { provide: FirebaseAppNameToken,   useValue: name    },
-                { provide: FirebaseAppConfigToken, useValue: config  }
+                { provide: FirebaseOptionsToken, useValue: options },
+                { provide: FirebaseNameOrConfigToken, useValue: nameOrConfig }
             ]
         }
     }
diff --git a/src/database-deprecated/database.ts b/src/database-deprecated/database.ts
index 8fcd18017..05e64acb4 100644
--- a/src/database-deprecated/database.ts
+++ b/src/database-deprecated/database.ts
@@ -7,7 +7,7 @@ import { FirebaseObjectFactory } from './firebase_object_factory';
 import { FirebaseObjectObservable } from './firebase_object_observable';
 import * as utils from './utils';
 import { FirebaseOptions, FirebaseAppConfig } from '@firebase/app-types';
-import { FirebaseAppConfigToken, FirebaseOptionsToken, FirebaseAppNameToken, RealtimeDatabaseURL, _firebaseAppFactory } from 'angularfire2';
+import { FirebaseOptionsToken, FirebaseNameOrConfigToken, RealtimeDatabaseURL, _firebaseAppFactory } from 'angularfire2';
 
 @Injectable()
 export class AngularFireDatabase {
@@ -19,13 +19,12 @@ export class AngularFireDatabase {
 
   constructor(
     @Inject(FirebaseOptionsToken) options:FirebaseOptions,
-    @Inject(FirebaseAppConfigToken) config:FirebaseAppConfig,
-    @Optional() @Inject(FirebaseAppNameToken) name:string,
+    @Inject(FirebaseNameOrConfigToken) nameOrConfig:string|FirebaseAppConfig|undefined,
     @Optional() @Inject(RealtimeDatabaseURL) databaseURL:string,
     zone: NgZone
   ) {
     this.database = zone.runOutsideAngular(() => {
-      const app = _firebaseAppFactory(options, name, config);
+      const app = _firebaseAppFactory(options, nameOrConfig);
       return app.database(databaseURL || undefined);
     });
   }
diff --git a/src/database/database.spec.ts b/src/database/database.spec.ts
index b51acb6cb..febb15f9e 100644
--- a/src/database/database.spec.ts
+++ b/src/database/database.spec.ts
@@ -1,4 +1,4 @@
-import { FirebaseApp, AngularFireModule, FirebaseOptionsToken, FirebaseAppNameToken } from 'angularfire2';
+import { FirebaseApp, AngularFireModule, FirebaseOptionsToken, FirebaseNameOrConfigToken } from 'angularfire2';
 import { AngularFireDatabase, AngularFireDatabaseModule, RealtimeDatabaseURL } from 'angularfire2/database';
 import { TestBed, inject } from '@angular/core/testing';
 import { COMMON_CONFIG } from './test-config';
@@ -42,7 +42,7 @@ describe('AngularFireDatabase', () => {
     });
 
     it('should accept a Firebase App in the constructor', () => {
-      const __db = new AngularFireDatabase(app.options, undefined!, app.name, undefined!, {}, zone);
+      const __db = new AngularFireDatabase(app.options, app.name, undefined!, {}, zone);
       expect(__db instanceof AngularFireDatabase).toEqual(true);
     });
 
@@ -69,7 +69,7 @@ describe('AngularFireDatabase w/options', () => {
         AngularFireDatabaseModule
       ],
       providers: [
-        { provide: FirebaseAppNameToken, useValue: FIREBASE_APP_NAME_TOO },
+        { provide: FirebaseNameOrConfigToken, useValue: FIREBASE_APP_NAME_TOO },
         { provide: FirebaseOptionsToken, useValue: COMMON_CONFIG },
         { provide: RealtimeDatabaseURL,  useValue: FIREBASE_DB_NAME }
       ]
diff --git a/src/database/database.ts b/src/database/database.ts
index 665023b7b..940d87be4 100644
--- a/src/database/database.ts
+++ b/src/database/database.ts
@@ -6,7 +6,7 @@ import { InjectionToken } from '@angular/core';
 import { FirebaseOptions, FirebaseAppConfig } from '@firebase/app-types';
 import { createListReference } from './list/create-reference';
 import { createObjectReference } from './object/create-reference';
-import { FirebaseOptionsToken, FirebaseAppConfigToken, FirebaseAppNameToken, RealtimeDatabaseURL, _firebaseAppFactory, FirebaseZoneScheduler } from 'angularfire2';
+import { FirebaseOptionsToken, FirebaseNameOrConfigToken, RealtimeDatabaseURL, _firebaseAppFactory, FirebaseZoneScheduler } from 'angularfire2';
 
 @Injectable()
 export class AngularFireDatabase {
@@ -15,15 +15,14 @@ export class AngularFireDatabase {
 
   constructor(
     @Inject(FirebaseOptionsToken) options:FirebaseOptions,
-    @Optional() @Inject(FirebaseAppConfigToken) config:FirebaseAppConfig,
-    @Optional() @Inject(FirebaseAppNameToken) name:string,
+    @Optional() @Inject(FirebaseNameOrConfigToken) nameOrConfig:string|FirebaseAppConfig|undefined,
     @Optional() @Inject(RealtimeDatabaseURL) databaseURL:string,
     @Inject(PLATFORM_ID) platformId: Object,
     zone: NgZone
   ) {
     this.scheduler = new FirebaseZoneScheduler(zone, platformId);
     this.database = zone.runOutsideAngular(() => {
-      const app = _firebaseAppFactory(options, name, config);
+      const app = _firebaseAppFactory(options, nameOrConfig);
       return app.database(databaseURL || undefined);
     });
   }
diff --git a/src/firestore/firestore.spec.ts b/src/firestore/firestore.spec.ts
index a9c193587..c6d0a5221 100644
--- a/src/firestore/firestore.spec.ts
+++ b/src/firestore/firestore.spec.ts
@@ -1,4 +1,4 @@
-import { FirebaseApp, FirebaseOptionsToken, AngularFireModule, FirebaseAppNameToken } from 'angularfire2';
+import { FirebaseApp, FirebaseOptionsToken, AngularFireModule, FirebaseNameOrConfigToken } from 'angularfire2';
 import { AngularFirestore } from './firestore';
 import { AngularFirestoreModule } from './firestore.module';
 import { AngularFirestoreDocument } from './document/document';
@@ -105,7 +105,7 @@ describe('AngularFirestore with different app', () => {
         AngularFirestoreModule
       ],
       providers: [
-        { provide: FirebaseAppNameToken, useValue: FIREBASE_APP_NAME_TOO },
+        { provide: FirebaseNameOrConfigToken, useValue: FIREBASE_APP_NAME_TOO },
         { provide: FirebaseOptionsToken, useValue: COMMON_CONFIG }
       ]
     });
diff --git a/src/firestore/firestore.ts b/src/firestore/firestore.ts
index c07fe5b7b..1d34584bc 100644
--- a/src/firestore/firestore.ts
+++ b/src/firestore/firestore.ts
@@ -9,7 +9,7 @@ import { QueryFn, AssociatedReference } from './interfaces';
 import { AngularFirestoreDocument } from './document/document';
 import { AngularFirestoreCollection } from './collection/collection';
 
-import { FirebaseAppConfigToken, FirebaseOptionsToken, FirebaseAppNameToken, _firebaseAppFactory, FirebaseZoneScheduler } from 'angularfire2';
+import { FirebaseOptionsToken, FirebaseNameOrConfigToken, _firebaseAppFactory, FirebaseZoneScheduler } from 'angularfire2';
 
 /**
  * The value of this token determines whether or not the firestore will have persistance enabled
@@ -106,8 +106,7 @@ export class AngularFirestore {
    */
   constructor(
     @Inject(FirebaseOptionsToken) options:FirebaseOptions,
-    @Optional() @Inject(FirebaseAppConfigToken) config:FirebaseAppConfig,
-    @Optional() @Inject(FirebaseAppNameToken) name:string,
+    @Optional() @Inject(FirebaseNameOrConfigToken) nameOrConfig:string|FirebaseAppConfig|undefined,
     @Optional() @Inject(EnablePersistenceToken) shouldEnablePersistence: boolean,
     @Optional() @Inject(FirestoreSettingsToken) settings: Settings,
     @Inject(PLATFORM_ID) platformId: Object,
@@ -115,7 +114,7 @@ export class AngularFirestore {
   ) {
     this.scheduler = new FirebaseZoneScheduler(zone, platformId);
     this.firestore = zone.runOutsideAngular(() => {
-      const app = _firebaseAppFactory(options, name, config);
+      const app = _firebaseAppFactory(options, nameOrConfig);
       const firestore = app.firestore();
       firestore.settings(settings || DefaultFirestoreSettings);
       return firestore;
diff --git a/src/storage/storage.spec.ts b/src/storage/storage.spec.ts
index cd88cbe3c..fd925a244 100644
--- a/src/storage/storage.spec.ts
+++ b/src/storage/storage.spec.ts
@@ -1,7 +1,7 @@
 import { Observable, forkJoin } from 'rxjs'
 import { map, mergeMap, tap } from 'rxjs/operators';
 import { TestBed, inject } from '@angular/core/testing';
-import { FirebaseApp, FirebaseOptionsToken, AngularFireModule, FirebaseAppNameToken } from 'angularfire2';
+import { FirebaseApp, FirebaseOptionsToken, AngularFireModule, FirebaseNameOrConfigToken } from 'angularfire2';
 import { AngularFireStorageModule, AngularFireStorage, AngularFireUploadTask, StorageBucket } from 'angularfire2/storage';
 import { COMMON_CONFIG } from './test-config';
 
@@ -140,7 +140,7 @@ describe('AngularFireStorage w/options', () => {
         AngularFireStorageModule
       ],
       providers: [
-        { provide: FirebaseAppNameToken, useValue: FIREBASE_APP_NAME_TOO },
+        { provide: FirebaseNameOrConfigToken, useValue: FIREBASE_APP_NAME_TOO },
         { provide: FirebaseOptionsToken, useValue:  COMMON_CONFIG },
         { provide: StorageBucket, useValue: FIREBASE_STORAGE_BUCKET }
       ]
diff --git a/src/storage/storage.ts b/src/storage/storage.ts
index de80842f9..5435bf62a 100644
--- a/src/storage/storage.ts
+++ b/src/storage/storage.ts
@@ -3,7 +3,7 @@ import { FirebaseStorage, UploadMetadata } from '@firebase/storage-types';
 import { createStorageRef, AngularFireStorageReference } from './ref';
 import { createUploadTask, AngularFireUploadTask } from './task';
 import { Observable } from 'rxjs';
-import { FirebaseAppConfigToken, FirebaseOptionsToken, FirebaseAppNameToken, FirebaseZoneScheduler, _firebaseAppFactory } from 'angularfire2';
+import { FirebaseOptionsToken, FirebaseNameOrConfigToken, FirebaseZoneScheduler, _firebaseAppFactory } from 'angularfire2';
 import { FirebaseOptions, FirebaseAppConfig } from '@firebase/app-types';
 
 export const StorageBucket = new InjectionToken<string>('angularfire2.storageBucket');
@@ -22,15 +22,14 @@ export class AngularFireStorage {
 
   constructor(
     @Inject(FirebaseOptionsToken) options:FirebaseOptions,
-    @Optional() @Inject(FirebaseAppConfigToken) config:FirebaseAppConfig,
-    @Optional() @Inject(FirebaseAppNameToken) name:string,
+    @Optional() @Inject(FirebaseNameOrConfigToken) nameOrConfig:string|FirebaseAppConfig|undefined,
     @Optional() @Inject(StorageBucket) storageBucket:string,
     @Inject(PLATFORM_ID) platformId: Object,
     zone: NgZone
   ) {
     this.scheduler = new FirebaseZoneScheduler(zone, platformId);
     this.storage = zone.runOutsideAngular(() => {
-      const app = _firebaseAppFactory(options, name, config);
+      const app = _firebaseAppFactory(options, nameOrConfig);
       return app.storage(storageBucket || undefined);
     });
   }
diff --git a/test/ng-build/ng6/package.json b/test/ng-build/ng6/package.json
index e381d904b..021b66633 100644
--- a/test/ng-build/ng6/package.json
+++ b/test/ng-build/ng6/package.json
@@ -22,16 +22,16 @@
     "@angular/platform-browser": "6.0.1",
     "@angular/platform-browser-dynamic": "6.0.1",
     "@angular/router": "6.0.1",
-    "angularfire2": "file:../../../dist/packages-dist",
+    "angularfire2": "../../../dist/packages-dist",
     "core-js": "^2.4.1",
     "rxjs": "^6.0.0",
     "zone.js": "^0.8.14"
   },
   "devDependencies": {
+    "@angular-devkit/build-angular": "~0.6.1",
     "@angular/cli": "6.0.1",
     "@angular/compiler-cli": "6.0.1",
     "@angular/language-service": "6.0.1",
-    "typescript": ">=2.7.2 <2.8.0",
-    "@angular-devkit/build-angular": "~0.6.1"
+    "typescript": ">=2.7.2 <2.8.0"
   }
 }
diff --git a/test/ng-build/ng6/src/app/app.module.ts b/test/ng-build/ng6/src/app/app.module.ts
index 08b2384c9..495803d7c 100644
--- a/test/ng-build/ng6/src/app/app.module.ts
+++ b/test/ng-build/ng6/src/app/app.module.ts
@@ -1,6 +1,6 @@
 import { BrowserModule } from '@angular/platform-browser';
 import { NgModule } from '@angular/core';
-import { FirebaseOptionsToken, AngularFireModule, FirebaseAppNameToken, FirebaseAppConfigToken } from 'angularfire2';
+import { FirebaseOptionsToken, AngularFireModule } from 'angularfire2';
 import { AngularFireDatabaseModule } from 'angularfire2/database';
 import { AngularFireAuthModule } from 'angularfire2/auth';
 import { AngularFirestoreModule } from 'angularfire2/firestore';
@@ -13,22 +13,17 @@ import { AppComponent } from './app.component';
   ],
   imports: [
     BrowserModule,
-    AngularFireModule,
-    AngularFireAuthModule,
-    AngularFireDatabaseModule,
-    AngularFirestoreModule
-  ],
-  providers: [
-    { provide: FirebaseOptionsToken, useValue: {
+    AngularFireModule.initializeApp({
       apiKey: "AIzaSyAwRrxjjft7KMdhwfLKPkd8PCBR3JFaLfo",
       authDomain: "angularfirestore.firebaseapp.com",
       databaseURL: "https://angularfirestore.firebaseio.com",
       projectId: "angularfirestore",
       storageBucket: "angularfirestore.appspot.com",
       messagingSenderId: "1039984584356"
-    } },
-    { provide: FirebaseAppNameToken, useValue: undefined },
-    { provide: FirebaseAppConfigToken, useValue: undefined }
+    }),
+    AngularFireAuthModule,
+    AngularFireDatabaseModule,
+    AngularFirestoreModule
   ],
   bootstrap: [AppComponent]
 })
diff --git a/test/ng-build/ng6/yarn.lock b/test/ng-build/ng6/yarn.lock
index 391c0458f..dc8d85fd7 100644
--- a/test/ng-build/ng6/yarn.lock
+++ b/test/ng-build/ng6/yarn.lock
@@ -283,7 +283,7 @@ amdefine@>=0.0.4:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
 
-"angularfire2@file:../../../dist/packages-dist":
+angularfire2@../../../dist/packages-dist:
   version "5.0.0-rc.8"
 
 ansi-html@0.0.7: