diff --git a/package.json b/package.json index 171a9d482..ba97634d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@angular/fire", - "version": "7.0.4", + "version": "7.1.0", "description": "The official Angular library for Firebase.", "private": true, "scripts": { diff --git a/samples/advanced/server.ts b/samples/advanced/server.ts index 6dca4a724..4c17d62d7 100644 --- a/samples/advanced/server.ts +++ b/samples/advanced/server.ts @@ -11,6 +11,11 @@ import { existsSync } from 'fs'; import '@angular/fire/firestore-protos'; +// These polyfills are for app-check Node.js +// @ts-ignore +globalThis.self = globalThis; +globalThis.fetch = require('node-fetch').default; + // The Express app is exported so that it can be used by serverless Functions. export function app(): express.Express { const server = express(); diff --git a/samples/advanced/src/app/app-check/app-check.component.spec.ts b/samples/advanced/src/app/app-check/app-check.component.spec.ts new file mode 100644 index 000000000..36be83bbb --- /dev/null +++ b/samples/advanced/src/app/app-check/app-check.component.spec.ts @@ -0,0 +1,25 @@ +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AppCheckComponent } from './app-check.component'; + +describe('RemoteConfigComponent', () => { + let component: AppCheckComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ AppCheckComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AppCheckComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/samples/advanced/src/app/app-check/app-check.component.ts b/samples/advanced/src/app/app-check/app-check.component.ts new file mode 100644 index 000000000..2840f3f40 --- /dev/null +++ b/samples/advanced/src/app/app-check/app-check.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { getToken, AppCheck } from '@angular/fire/app-check'; +import { traceUntilFirst } from '@angular/fire/performance'; +import { from, Observable } from 'rxjs'; +import { keepUnstableUntilFirst } from '@angular/fire'; +import { share, tap } from 'rxjs/operators'; + +@Component({ + selector: 'app-app-check', + template: ` +

+ App Check! + {{ (change$ | async)?.token | slice:0:12 }} +

+ `, + styles: [] +}) +export class AppCheckComponent implements OnInit { + + readonly change$: Observable; + + constructor(appCheck: AppCheck) { + this.change$ = from(getToken(appCheck)).pipe( + keepUnstableUntilFirst, + traceUntilFirst('app-check'), + share(), + ); + } + + ngOnInit(): void { + } + +} diff --git a/samples/advanced/src/app/app.module.ts b/samples/advanced/src/app/app.module.ts index a2ac5277e..be1eb4782 100644 --- a/samples/advanced/src/app/app.module.ts +++ b/samples/advanced/src/app/app.module.ts @@ -2,6 +2,7 @@ import { InjectionToken, NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { provideFirebaseApp, initializeApp } from '@angular/fire/app'; import { FunctionsModule } from '@angular/fire/functions'; +import { provideAppCheck, initializeAppCheck, ReCaptchaV3Provider, CustomProvider } from '@angular/fire/app-check'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -17,27 +18,37 @@ import { RemoteConfigComponent } from './remote-config/remote-config.component'; import { StorageComponent } from './storage/storage.component'; import type { app } from 'firebase-admin'; +import { AppCheckComponent } from './app-check/app-check.component'; + +const isNode = () => typeof process !== 'undefined' && process.versions?.node; export const FIREBASE_ADMIN = new InjectionToken('firebase-admin'); @NgModule({ declarations: [ AppComponent, - HomeComponent, - UpboatsComponent, + AppCheckComponent, AuthComponent, - FirestoreComponent, DatabaseComponent, + FirestoreComponent, FunctionsComponent, + HomeComponent, MessagingComponent, RemoteConfigComponent, StorageComponent, + UpboatsComponent, ], imports: [ BrowserModule.withServerTransition({ appId: 'serverApp' }), AppRoutingModule, FunctionsModule, provideFirebaseApp(() => initializeApp(environment.firebase)), + provideAppCheck(() => { + const provider = isNode() ? + new CustomProvider({ getToken: () => Promise.reject() }) : + new ReCaptchaV3Provider(environment.recaptcha3SiteKey); + return initializeAppCheck(undefined, { provider, isTokenAutoRefreshEnabled: true }); + }), ], providers: [ ], bootstrap: [ ], diff --git a/samples/advanced/src/app/auth/auth.component.ts b/samples/advanced/src/app/auth/auth.component.ts index 44ed5739a..951d5229d 100644 --- a/samples/advanced/src/app/auth/auth.component.ts +++ b/samples/advanced/src/app/auth/auth.component.ts @@ -10,7 +10,7 @@ import { Router } from '@angular/router'; template: `

Auth! - {{ (user | async)?.uid | json }} + {{ (user | async)?.uid }}

diff --git a/samples/advanced/src/app/database/database.component.ts b/samples/advanced/src/app/database/database.component.ts index 61a6b1786..022bea1d9 100644 --- a/samples/advanced/src/app/database/database.component.ts +++ b/samples/advanced/src/app/database/database.component.ts @@ -9,7 +9,7 @@ import { traceUntilFirst } from '@angular/fire/performance'; template: `

Database! - {{ testObjectValue$ | async | json }} + {{ testObjectValue$ | async | json }}

`, styles: [] diff --git a/samples/advanced/src/app/firestore/firestore.component.ts b/samples/advanced/src/app/firestore/firestore.component.ts index 1cd037c0d..b7948097c 100644 --- a/samples/advanced/src/app/firestore/firestore.component.ts +++ b/samples/advanced/src/app/firestore/firestore.component.ts @@ -6,11 +6,14 @@ import { traceUntilFirst } from '@angular/fire/performance'; @Component({ selector: 'app-firestore', - template: `

- Firestore! - {{ testDocValue$ | async | json }} - {{ persistenceEnabled | async }} -

`, + template: ` +

+ Firestore! + {{ testDocValue$ | async | json }} +
+ Persistence enabled: {{ (persistenceEnabled | async) ?? false }} +

+ `, styles: [``] }) export class FirestoreComponent implements OnInit { diff --git a/samples/advanced/src/app/functions/functions.component.ts b/samples/advanced/src/app/functions/functions.component.ts index 21b4f6830..590e55f77 100644 --- a/samples/advanced/src/app/functions/functions.component.ts +++ b/samples/advanced/src/app/functions/functions.component.ts @@ -7,7 +7,7 @@ import { EMPTY, Observable } from 'rxjs'; template: `

Functions! - {{ response$ | async | json }} + {{ response$ | async | json }}

`, diff --git a/samples/advanced/src/app/home/home.component.ts b/samples/advanced/src/app/home/home.component.ts index 51daeab6d..4d5242981 100644 --- a/samples/advanced/src/app/home/home.component.ts +++ b/samples/advanced/src/app/home/home.component.ts @@ -10,9 +10,11 @@ import { RESPONSE } from '@nguniversal/express-engine/tokens'; {{ firebaseApp.name }} + + `, diff --git a/samples/advanced/src/app/messaging/messaging.component.ts b/samples/advanced/src/app/messaging/messaging.component.ts index 6d7c9b3b3..6e617a809 100644 --- a/samples/advanced/src/app/messaging/messaging.component.ts +++ b/samples/advanced/src/app/messaging/messaging.component.ts @@ -1,6 +1,7 @@ import { Component, OnInit, Optional } from '@angular/core'; import { Messaging, getToken, onMessage } from '@angular/fire/messaging'; import { EMPTY, from, Observable } from 'rxjs'; +import { share, tap } from 'rxjs/operators'; import { environment } from 'src/environments/environment'; @Component({ @@ -8,8 +9,8 @@ import { environment } from 'src/environments/environment'; template: `

Messaging! - {{ token$ | async | json }} - {{ message$ | async | json }} + {{ token$ | async | slice:0:12 }} +  {{ message$ | async | json }}

`, @@ -30,8 +31,13 @@ export class MessagingComponent implements OnInit { serviceWorkerRegistration, vapidKey: environment.vapidKey, }) - )); - this.message$ = new Observable(sub => onMessage(messaging, it => sub.next(it))); + )).pipe( + tap(token => console.log('FCM', {token})), + share() + ); + this.message$ = new Observable(sub => onMessage(messaging, it => sub.next(it))).pipe( + tap(it => console.log('FCM', it)), + ); } } diff --git a/samples/advanced/src/app/remote-config/remote-config.component.ts b/samples/advanced/src/app/remote-config/remote-config.component.ts index 8c8bdbac9..b63faf012 100644 --- a/samples/advanced/src/app/remote-config/remote-config.component.ts +++ b/samples/advanced/src/app/remote-config/remote-config.component.ts @@ -1,24 +1,27 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, Optional } from '@angular/core'; import { RemoteConfig, getAllChanges } from '@angular/fire/remote-config'; import { traceUntilFirst } from '@angular/fire/performance'; -import { Observable } from 'rxjs'; +import { EMPTY, Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; @Component({ selector: 'app-remote-config', - template: ` -

- Remote Config! - {{ change$ | async | json }} -

- `, + template: ``, styles: [] }) export class RemoteConfigComponent implements OnInit { readonly change$: Observable; - constructor(public readonly remoteConfig: RemoteConfig) { - this.change$ = getAllChanges(this.remoteConfig).pipe(traceUntilFirst('remote-config')); + constructor(@Optional() remoteConfig: RemoteConfig) { + if (remoteConfig) { + this.change$ = getAllChanges(remoteConfig).pipe( + traceUntilFirst('remote-config'), + tap(it => console.log('REMOTE CONFIG', it)), + ); + } else { + this.change$ = EMPTY; + } } ngOnInit(): void { diff --git a/samples/advanced/src/environments/environment.prod.ts b/samples/advanced/src/environments/environment.prod.ts index 9177db4d9..9761fdd9a 100644 --- a/samples/advanced/src/environments/environment.prod.ts +++ b/samples/advanced/src/environments/environment.prod.ts @@ -11,5 +11,6 @@ export const environment = { appId: '1:480362569154:web:2fe6f75104cdfb82f50a5b', measurementId: 'G-CBRYER9PJR' }, - vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo' + vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo', + recaptcha3SiteKey: '6LeI1VocAAAAAEHdUR_I_p2dDBkes4Hu7c5utbKT', }; diff --git a/samples/advanced/src/environments/environment.ts b/samples/advanced/src/environments/environment.ts index e94ea98ba..74c35e22b 100644 --- a/samples/advanced/src/environments/environment.ts +++ b/samples/advanced/src/environments/environment.ts @@ -15,7 +15,8 @@ export const environment = { appId: '1:480362569154:web:2fe6f75104cdfb82f50a5b', measurementId: 'G-CBRYER9PJR' }, - vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo' + vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo', + recaptcha3SiteKey: '6LeI1VocAAAAAEHdUR_I_p2dDBkes4Hu7c5utbKT', }; /* diff --git a/samples/compat/src/app/app.module.ts b/samples/compat/src/app/app.module.ts index f6cfd2bcf..fb17f60b9 100644 --- a/samples/compat/src/app/app.module.ts +++ b/samples/compat/src/app/app.module.ts @@ -28,6 +28,8 @@ import { AngularFireFunctionsModule, USE_EMULATOR as USE_FUNCTIONS_EMULATOR, ORI import { AngularFireRemoteConfigModule, SETTINGS as REMOTE_CONFIG_SETTINGS, DEFAULTS as REMOTE_CONFIG_DEFAULTS } from '@angular/fire/compat/remote-config'; import { AngularFirePerformanceModule, PerformanceMonitoringService } from '@angular/fire/compat/performance'; import { AngularFireAuthGuardModule } from '@angular/fire/compat/auth-guard'; +import { provideAppCheck, initializeAppCheck, ReCaptchaV3Provider, CustomProvider } from '@angular/fire/app-check'; + import { DatabaseComponent } from './database/database.component'; import { StorageComponent } from './storage/storage.component'; import { RemoteConfigComponent } from './remote-config/remote-config.component'; @@ -36,6 +38,10 @@ import { AuthComponent } from './auth/auth.component'; import { MessagingComponent } from './messaging/messaging.component'; import { FunctionsComponent } from './functions/functions.component'; import { UpboatsComponent } from './upboats/upboats.component'; +import { initializeApp, provideFirebaseApp } from '@angular/fire/app'; + +// @ts-ignore +const isNode = () => typeof process !== 'undefined' && process.versions?.node; @NgModule({ declarations: [ @@ -65,6 +71,13 @@ import { UpboatsComponent } from './upboats/upboats.component'; AngularFireAnalyticsModule, AngularFireFunctionsModule, AngularFirePerformanceModule, + provideFirebaseApp(() => initializeApp(environment.firebase)), + provideAppCheck(() => { + const provider = isNode() ? + new CustomProvider({ getToken: () => Promise.reject() }) : + new ReCaptchaV3Provider(environment.recaptcha3SiteKey); + return initializeAppCheck(undefined, { provider, isTokenAutoRefreshEnabled: true }); + }), ], providers: [ UserTrackingService, @@ -78,7 +91,6 @@ import { UpboatsComponent } from './upboats/upboats.component'; { provide: USE_FIRESTORE_EMULATOR, useValue: environment.useEmulators ? ['localhost', 8080] : undefined }, { provide: USE_FUNCTIONS_EMULATOR, useValue: environment.useEmulators ? ['localhost', 5001] : undefined }, { provide: USE_STORAGE_EMULATOR, useValue: environment.useEmulators ? ['localhost', 9199] : undefined }, - { provide: FUNCTIONS_ORIGIN, useFactory: () => isDevMode() || typeof location === 'undefined' ? undefined : location.origin }, { provide: REMOTE_CONFIG_SETTINGS, useFactory: () => isDevMode() ? { minimumFetchIntervalMillis: 10_000 } : {} }, { provide: REMOTE_CONFIG_DEFAULTS, useValue: { background_color: 'red' } }, { provide: USE_DEVICE_LANGUAGE, useValue: true }, diff --git a/samples/compat/src/environments/environment.prod.ts b/samples/compat/src/environments/environment.prod.ts index 9177db4d9..9761fdd9a 100644 --- a/samples/compat/src/environments/environment.prod.ts +++ b/samples/compat/src/environments/environment.prod.ts @@ -11,5 +11,6 @@ export const environment = { appId: '1:480362569154:web:2fe6f75104cdfb82f50a5b', measurementId: 'G-CBRYER9PJR' }, - vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo' + vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo', + recaptcha3SiteKey: '6LeI1VocAAAAAEHdUR_I_p2dDBkes4Hu7c5utbKT', }; diff --git a/samples/compat/src/environments/environment.ts b/samples/compat/src/environments/environment.ts index 80d7965cd..9c6f760d1 100644 --- a/samples/compat/src/environments/environment.ts +++ b/samples/compat/src/environments/environment.ts @@ -3,7 +3,7 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - useEmulators: true, + useEmulators: false, production: false, firebase: { apiKey: 'AIzaSyA7CNE9aHbcSEbt9y03QReJ-Xr0nwKg7Yg', @@ -15,7 +15,8 @@ export const environment = { appId: '1:480362569154:web:2fe6f75104cdfb82f50a5b', measurementId: 'G-CBRYER9PJR' }, - vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo' + vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo', + recaptcha3SiteKey: '6LeI1VocAAAAAEHdUR_I_p2dDBkes4Hu7c5utbKT', }; /* diff --git a/samples/modular/src/app/app-check/app-check.component.spec.ts b/samples/modular/src/app/app-check/app-check.component.spec.ts new file mode 100644 index 000000000..36be83bbb --- /dev/null +++ b/samples/modular/src/app/app-check/app-check.component.spec.ts @@ -0,0 +1,25 @@ +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AppCheckComponent } from './app-check.component'; + +describe('RemoteConfigComponent', () => { + let component: AppCheckComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ AppCheckComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AppCheckComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/samples/modular/src/app/app-check/app-check.component.ts b/samples/modular/src/app/app-check/app-check.component.ts new file mode 100644 index 000000000..667ef913a --- /dev/null +++ b/samples/modular/src/app/app-check/app-check.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { getToken, AppCheck } from '@angular/fire/app-check'; +import { traceUntilFirst } from '@angular/fire/performance'; +import { from, Observable } from 'rxjs'; +import { keepUnstableUntilFirst } from '@angular/fire'; +import { share, tap } from 'rxjs/operators'; + +@Component({ + selector: 'app-app-check', + template: ` +

+ App Check! + {{ (change$ | async)?.token | slice:0:12 }} +

+ `, + styles: [] +}) +export class AppCheckComponent implements OnInit { + + readonly change$: Observable; + + constructor(appCheck: AppCheck) { + this.change$ = from(getToken(appCheck)).pipe( + traceUntilFirst('app-check'), + keepUnstableUntilFirst, + share(), + ); + } + + ngOnInit(): void { + } + +} diff --git a/samples/modular/src/app/app.module.ts b/samples/modular/src/app/app.module.ts index bf1dbd98d..bd12bd436 100644 --- a/samples/modular/src/app/app.module.ts +++ b/samples/modular/src/app/app.module.ts @@ -2,6 +2,10 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { provideFirebaseApp, initializeApp } from '@angular/fire/app'; import { connectFunctionsEmulator, FunctionsModule, getFunctions, provideFunctions } from '@angular/fire/functions'; +import { connectFirestoreEmulator, getFirestore, provideFirestore, enableMultiTabIndexedDbPersistence } from '@angular/fire/firestore'; +import { connectDatabaseEmulator, getDatabase, provideDatabase } from '@angular/fire/database'; +import { connectStorageEmulator, getStorage, provideStorage } from '@angular/fire/storage'; +import { provideAppCheck, CustomProvider, ReCaptchaV3Provider, initializeAppCheck } from '@angular/fire/app-check'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -15,9 +19,7 @@ import { FunctionsComponent } from './functions/functions.component'; import { MessagingComponent } from './messaging/messaging.component'; import { RemoteConfigComponent } from './remote-config/remote-config.component'; import { StorageComponent } from './storage/storage.component'; -import { connectFirestoreEmulator, getFirestore, provideFirestore, enableMultiTabIndexedDbPersistence } from '@angular/fire/firestore'; -import { connectDatabaseEmulator, getDatabase, provideDatabase } from '@angular/fire/database'; -import { connectStorageEmulator, getStorage, provideStorage } from '@angular/fire/storage'; +import { AppCheckComponent } from './app-check/app-check.component'; let resolvePersistenceEnabled: (enabled: boolean) => void; @@ -25,9 +27,12 @@ export const persistenceEnabled = new Promise(resolve => { resolvePersistenceEnabled = resolve; }); +const isNode = () => typeof process !== 'undefined' && process.versions?.node; + @NgModule({ declarations: [ AppComponent, + AppCheckComponent, HomeComponent, UpboatsComponent, AuthComponent, @@ -75,6 +80,12 @@ export const persistenceEnabled = new Promise(resolve => { } return functions; }), + provideAppCheck(() => { + const provider = isNode() ? + new CustomProvider({ getToken: () => Promise.reject() }) : + new ReCaptchaV3Provider(environment.recaptcha3SiteKey); + return initializeAppCheck(undefined, { provider, isTokenAutoRefreshEnabled: true }); + }), ], providers: [ ], bootstrap: [ ], diff --git a/samples/modular/src/app/auth/auth.component.ts b/samples/modular/src/app/auth/auth.component.ts index 93e9c8820..bb6013779 100644 --- a/samples/modular/src/app/auth/auth.component.ts +++ b/samples/modular/src/app/auth/auth.component.ts @@ -9,7 +9,7 @@ import { traceUntilFirst } from '@angular/fire/performance'; template: `

Auth! - {{ (user | async)?.uid | json }} + {{ (user | async)?.uid }} diff --git a/samples/modular/src/app/database/database.component.ts b/samples/modular/src/app/database/database.component.ts index 1c0c02515..4a58be9a3 100644 --- a/samples/modular/src/app/database/database.component.ts +++ b/samples/modular/src/app/database/database.component.ts @@ -8,7 +8,7 @@ import { Database, objectVal, ref } from '@angular/fire/database'; template: `

Database! - {{ testObjectValue$ | async | json }} + {{ testObjectValue$ | async | json }}

`, styles: [] diff --git a/samples/modular/src/app/firestore/firestore.component.ts b/samples/modular/src/app/firestore/firestore.component.ts index 46e014990..cb9d4a8f8 100644 --- a/samples/modular/src/app/firestore/firestore.component.ts +++ b/samples/modular/src/app/firestore/firestore.component.ts @@ -8,8 +8,9 @@ import { doc, docData, Firestore } from '@angular/fire/firestore'; selector: 'app-firestore', template: `

Firestore! - {{ testDocValue$ | async | json }} - {{ persistenceEnabled | async }} + {{ testDocValue$ | async | json }} +
+ Persistence enabled: {{ (persistenceEnabled | async) ?? false }}

`, styles: [``] }) diff --git a/samples/modular/src/app/functions/functions.component.ts b/samples/modular/src/app/functions/functions.component.ts index c5378186a..347de94de 100644 --- a/samples/modular/src/app/functions/functions.component.ts +++ b/samples/modular/src/app/functions/functions.component.ts @@ -7,7 +7,7 @@ import { EMPTY, Observable } from 'rxjs'; template: `

Functions! - {{ response$ | async | json }} + {{ response$ | async | json }}

`, diff --git a/samples/modular/src/app/home/home.component.ts b/samples/modular/src/app/home/home.component.ts index 51daeab6d..4d5242981 100644 --- a/samples/modular/src/app/home/home.component.ts +++ b/samples/modular/src/app/home/home.component.ts @@ -10,9 +10,11 @@ import { RESPONSE } from '@nguniversal/express-engine/tokens'; {{ firebaseApp.name }} + + `, diff --git a/samples/modular/src/app/messaging/messaging.component.ts b/samples/modular/src/app/messaging/messaging.component.ts index 6d7c9b3b3..047888c09 100644 --- a/samples/modular/src/app/messaging/messaging.component.ts +++ b/samples/modular/src/app/messaging/messaging.component.ts @@ -1,6 +1,7 @@ import { Component, OnInit, Optional } from '@angular/core'; import { Messaging, getToken, onMessage } from '@angular/fire/messaging'; import { EMPTY, from, Observable } from 'rxjs'; +import { share, tap } from 'rxjs/operators'; import { environment } from 'src/environments/environment'; @Component({ @@ -8,8 +9,8 @@ import { environment } from 'src/environments/environment'; template: `

Messaging! - {{ token$ | async | json }} - {{ message$ | async | json }} + {{ token$ | async | slice:0:12 }} +  {{ message$ | async | json }}

`, @@ -30,8 +31,13 @@ export class MessagingComponent implements OnInit { serviceWorkerRegistration, vapidKey: environment.vapidKey, }) - )); - this.message$ = new Observable(sub => onMessage(messaging, it => sub.next(it))); + )).pipe( + tap(token => console.log('FCM', {token})), + share(), + ); + this.message$ = new Observable(sub => onMessage(messaging, it => sub.next(it))).pipe( + tap(token => console.log('FCM', {token})), + ); } } diff --git a/samples/modular/src/app/remote-config/remote-config.component.ts b/samples/modular/src/app/remote-config/remote-config.component.ts index 8c8bdbac9..b63faf012 100644 --- a/samples/modular/src/app/remote-config/remote-config.component.ts +++ b/samples/modular/src/app/remote-config/remote-config.component.ts @@ -1,24 +1,27 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, Optional } from '@angular/core'; import { RemoteConfig, getAllChanges } from '@angular/fire/remote-config'; import { traceUntilFirst } from '@angular/fire/performance'; -import { Observable } from 'rxjs'; +import { EMPTY, Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; @Component({ selector: 'app-remote-config', - template: ` -

- Remote Config! - {{ change$ | async | json }} -

- `, + template: ``, styles: [] }) export class RemoteConfigComponent implements OnInit { readonly change$: Observable; - constructor(public readonly remoteConfig: RemoteConfig) { - this.change$ = getAllChanges(this.remoteConfig).pipe(traceUntilFirst('remote-config')); + constructor(@Optional() remoteConfig: RemoteConfig) { + if (remoteConfig) { + this.change$ = getAllChanges(remoteConfig).pipe( + traceUntilFirst('remote-config'), + tap(it => console.log('REMOTE CONFIG', it)), + ); + } else { + this.change$ = EMPTY; + } } ngOnInit(): void { diff --git a/samples/modular/src/environments/environment.prod.ts b/samples/modular/src/environments/environment.prod.ts index 9177db4d9..9761fdd9a 100644 --- a/samples/modular/src/environments/environment.prod.ts +++ b/samples/modular/src/environments/environment.prod.ts @@ -11,5 +11,6 @@ export const environment = { appId: '1:480362569154:web:2fe6f75104cdfb82f50a5b', measurementId: 'G-CBRYER9PJR' }, - vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo' + vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo', + recaptcha3SiteKey: '6LeI1VocAAAAAEHdUR_I_p2dDBkes4Hu7c5utbKT', }; diff --git a/samples/modular/src/environments/environment.ts b/samples/modular/src/environments/environment.ts index e94ea98ba..74c35e22b 100644 --- a/samples/modular/src/environments/environment.ts +++ b/samples/modular/src/environments/environment.ts @@ -15,7 +15,8 @@ export const environment = { appId: '1:480362569154:web:2fe6f75104cdfb82f50a5b', measurementId: 'G-CBRYER9PJR' }, - vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo' + vapidKey: 'BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo', + recaptcha3SiteKey: '6LeI1VocAAAAAEHdUR_I_p2dDBkes4Hu7c5utbKT', }; /* diff --git a/src/app-check/app-check.module.ts b/src/app-check/app-check.module.ts new file mode 100644 index 000000000..24f8f15a8 --- /dev/null +++ b/src/app-check/app-check.module.ts @@ -0,0 +1,73 @@ +import { NgModule, Optional, NgZone, InjectionToken, ModuleWithProviders, PLATFORM_ID, isDevMode } from '@angular/core'; +import { AppCheck as FirebaseAppCheck } from 'firebase/app-check'; +import { ɵgetDefaultInstanceOf, ɵmemoizeInstance, ɵAngularFireSchedulers, VERSION } from '@angular/fire'; +import { AppCheck, AppCheckInstances, APP_CHECK_PROVIDER_NAME } from './app-check'; +import { FirebaseApps, FirebaseApp } from '@angular/fire/app'; +import { registerVersion } from 'firebase/app'; + +export const PROVIDED_APP_CHECK_INSTANCES = new InjectionToken('angularfire2.app-check-instances'); +export const APP_CHECK_NAMESPACE_SYMBOL = Symbol('angularfire2.app-check.namespace'); + +export function defaultAppCheckInstanceFactory(provided: FirebaseAppCheck[]|undefined, defaultApp: FirebaseApp) { + const defaultAppCheck = ɵgetDefaultInstanceOf(APP_CHECK_PROVIDER_NAME, provided, defaultApp); + return new AppCheck(defaultAppCheck); +} + +export function appCheckInstanceFactory(fn: () => FirebaseAppCheck) { + return (zone: NgZone) => { + // This isn't supported by the JS SDK yet, I've put in the feature request + // for the time being I've written a hack in core.ts + /* if (typeof process !== 'undefined' && process.env?.FIREBASE_APPCHECK_DEBUG_TOKEN) { + globalThis.FIREBASE_APPCHECK_DEBUG_TOKEN ??= process.env.FIREBASE_APPCHECK_DEBUG_TOKEN; + } else if (isDevMode()) { + globalThis.FIREBASE_APPCHECK_DEBUG_TOKEN ??= true; + } */ + return ɵmemoizeInstance(fn, zone); + }; +} + +const APP_CHECK_INSTANCES_PROVIDER = { + provide: AppCheckInstances, + deps: [ + [new Optional(), PROVIDED_APP_CHECK_INSTANCES ], + ] +}; + +const DEFAULT_APP_CHECK_INSTANCE_PROVIDER = { + provide: AppCheck, + useFactory: defaultAppCheckInstanceFactory, + deps: [ + [new Optional(), PROVIDED_APP_CHECK_INSTANCES ], + FirebaseApp, + PLATFORM_ID, + ] +}; + +@NgModule({ + providers: [ + DEFAULT_APP_CHECK_INSTANCE_PROVIDER, + APP_CHECK_INSTANCES_PROVIDER, + ] +}) +export class AppCheckModule { + constructor() { + registerVersion('angularfire', VERSION.full, 'app-check'); + } +} + +export function provideAppCheck(fn: () => FirebaseAppCheck): ModuleWithProviders { + return { + ngModule: AppCheckModule, + providers: [{ + provide: PROVIDED_APP_CHECK_INSTANCES, + useFactory: appCheckInstanceFactory(fn), + multi: true, + deps: [ + NgZone, + PLATFORM_ID, + ɵAngularFireSchedulers, + FirebaseApps, + ] + }] + }; +} diff --git a/src/app-check/app-check.ts b/src/app-check/app-check.ts new file mode 100644 index 000000000..77050f853 --- /dev/null +++ b/src/app-check/app-check.ts @@ -0,0 +1,31 @@ +import { AppCheck as FirebaseAppCheck } from 'firebase/app-check'; +import { ɵgetAllInstancesOf } from '@angular/fire'; +import { from, timer } from 'rxjs'; +import { concatMap, distinct } from 'rxjs/operators'; + +export const APP_CHECK_PROVIDER_NAME = 'app-check'; + +// see notes in core/firebase.app.module.ts for why we're building the class like this +// tslint:disable-next-line:no-empty-interface +export interface AppCheck extends FirebaseAppCheck {} + +export class AppCheck { + constructor(appCheck: FirebaseAppCheck) { + return appCheck; + } +} + +// tslint:disable-next-line:no-empty-interface +export interface AppCheckInstances extends Array {} + +export class AppCheckInstances { + // tslint:disable-next-line:ban-types + constructor() { + return ɵgetAllInstancesOf(APP_CHECK_PROVIDER_NAME); + } +} + +export const appCheckInstance$ = timer(0, 300).pipe( + concatMap(() => from(ɵgetAllInstancesOf(APP_CHECK_PROVIDER_NAME))), + distinct(), +); diff --git a/src/app-check/firebase.ts b/src/app-check/firebase.ts new file mode 100644 index 000000000..59284be75 --- /dev/null +++ b/src/app-check/firebase.ts @@ -0,0 +1,14 @@ +// DO NOT MODIFY, this file is autogenerated by tools/build.ts +export * from 'firebase/app-check'; +import { ɵzoneWrap } from '@angular/fire'; +import { + getToken as _getToken, + initializeAppCheck as _initializeAppCheck, + onTokenChanged as _onTokenChanged, + setTokenAutoRefreshEnabled as _setTokenAutoRefreshEnabled +} from 'firebase/app-check'; + +export const getToken = ɵzoneWrap(_getToken, true); +export const initializeAppCheck = ɵzoneWrap(_initializeAppCheck, true); +export const onTokenChanged = ɵzoneWrap(_onTokenChanged, true); +export const setTokenAutoRefreshEnabled = ɵzoneWrap(_setTokenAutoRefreshEnabled, true); diff --git a/src/app-check/package.json b/src/app-check/package.json new file mode 100644 index 000000000..d21511d93 --- /dev/null +++ b/src/app-check/package.json @@ -0,0 +1,11 @@ +{ + "$schema": "../../node_modules/ng-packagr/package.schema.json", + "ngPackage": { + "lib": { + "umdModuleIds": { + "firebase/app-check": "firebase-app-check" + }, + "entryFile": "public_api.ts" + } + } +} \ No newline at end of file diff --git a/src/app-check/public_api.ts b/src/app-check/public_api.ts new file mode 100644 index 000000000..ff1a7d304 --- /dev/null +++ b/src/app-check/public_api.ts @@ -0,0 +1,3 @@ +export { AppCheck, AppCheckInstances, appCheckInstance$ } from './app-check'; +export { provideAppCheck, AppCheckModule } from './app-check.module'; +export * from './firebase'; diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index a0b50488f..31578eeb0 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -4,6 +4,7 @@ import { ɵgetDefaultInstanceOf, ɵmemoizeInstance, ɵAngularFireSchedulers, VER import { Auth, AuthInstances, AUTH_PROVIDER_NAME } from './auth'; import { FirebaseApps, FirebaseApp } from '@angular/fire/app'; import { registerVersion } from 'firebase/app'; +import { AppCheckInstances } from '@angular/fire/app-check'; export const PROVIDED_AUTH_INSTANCES = new InjectionToken('angularfire2.auth-instances'); @@ -59,6 +60,7 @@ export function provideAuth(fn: () => FirebaseAuth): ModuleWithProviders {} @@ -93,6 +94,7 @@ export class AngularFireAuth { @Optional() @Inject(LANGUAGE_CODE) languageCode: string | null, @Optional() @Inject(USE_DEVICE_LANGUAGE) useDeviceLanguage: boolean | null, @Optional() @Inject(PERSISTENCE) persistence: string | null, + @Optional() _appCheckInstances: AppCheckInstances, ) { const logins = new Subject>(); diff --git a/src/compat/database/database.spec.ts b/src/compat/database/database.spec.ts index d31531781..9e0f58773 100644 --- a/src/compat/database/database.spec.ts +++ b/src/compat/database/database.spec.ts @@ -48,7 +48,7 @@ describe('AngularFireDatabase', () => { const schedulers = new ɵAngularFireSchedulers(zone); const database = new AngularFireDatabase( app.options, rando(), undefined, {}, zone, schedulers, undefined, undefined, - undefined, undefined, undefined, undefined, undefined, undefined + undefined, undefined, undefined, undefined, undefined, undefined, undefined, ); expect(database instanceof AngularFireDatabase).toEqual(true); // try { database.database.app.delete().then(done, done); } catch(e) { done(); } diff --git a/src/compat/database/database.ts b/src/compat/database/database.ts index 20a06fd99..7fd725147 100644 --- a/src/compat/database/database.ts +++ b/src/compat/database/database.ts @@ -20,6 +20,7 @@ import { } from '@angular/fire/compat/auth'; import firebase from 'firebase/compat/app'; import { ɵcacheInstance } from '@angular/fire'; +import { AppCheckInstances } from '@angular/fire/app-check'; export const URL = new InjectionToken('angularfire2.realtimeDatabaseURL'); @@ -48,6 +49,7 @@ export class AngularFireDatabase { @Optional() @Inject(LANGUAGE_CODE) languageCode: string | null, @Optional() @Inject(USE_DEVICE_LANGUAGE) useDeviceLanguage: boolean | null, @Optional() @Inject(PERSISTENCE) persistence: string | null, + @Optional() _appCheckInstances: AppCheckInstances, ) { const useEmulator: UseEmulatorArguments | null = _useEmulator; diff --git a/src/compat/firestore/firestore.ts b/src/compat/firestore/firestore.ts index 7364330b4..d6bec8ac7 100644 --- a/src/compat/firestore/firestore.ts +++ b/src/compat/firestore/firestore.ts @@ -31,6 +31,7 @@ import { ɵauthFactory, } from '@angular/fire/compat/auth'; import { ɵcacheInstance } from '@angular/fire'; +import { AppCheckInstances } from '@angular/fire/app-check'; /** * The value of this token determines whether or not the firestore will have persistance enabled @@ -152,6 +153,7 @@ export class AngularFirestore { @Optional() @Inject(LANGUAGE_CODE) languageCode: string | null, @Optional() @Inject(USE_DEVICE_LANGUAGE) useDeviceLanguage: boolean | null, @Optional() @Inject(PERSISTENCE) persistence: string | null, + @Optional() _appCheckInstances: AppCheckInstances, ) { const app = ɵfirebaseAppFactory(options, zone, name); const useEmulator: UseEmulatorArguments | null = _useEmulator; diff --git a/src/compat/functions/functions.ts b/src/compat/functions/functions.ts index 6751f6f37..dedf6d2d4 100644 --- a/src/compat/functions/functions.ts +++ b/src/compat/functions/functions.ts @@ -9,6 +9,7 @@ import firebase from 'firebase/compat/app'; import { proxyPolyfillCompat } from './base'; import { HttpsCallableOptions } from '@firebase/functions-types'; import { ɵcacheInstance } from '@angular/fire'; +import { AppCheckInstances } from '@angular/fire/app-check'; export const ORIGIN = new InjectionToken('angularfire2.functions.origin'); export const REGION = new InjectionToken('angularfire2.functions.region'); @@ -35,6 +36,7 @@ export class AngularFireFunctions { @Optional() @Inject(REGION) region: string | null, @Optional() @Inject(ORIGIN) origin: string | null, @Optional() @Inject(USE_EMULATOR) _useEmulator: any, // can't use the tuple here + @Optional() _appCheckInstances: AppCheckInstances, ) { const useEmulator: UseEmulatorArguments | null = _useEmulator; diff --git a/src/compat/storage/storage.ts b/src/compat/storage/storage.ts index 12a69a8ba..21c732a45 100644 --- a/src/compat/storage/storage.ts +++ b/src/compat/storage/storage.ts @@ -1,12 +1,12 @@ import { Inject, Injectable, InjectionToken, NgZone, Optional, PLATFORM_ID } from '@angular/core'; import { createStorageRef } from './ref'; -import { Observable } from 'rxjs'; -import { ɵAngularFireSchedulers, ɵcacheInstance, keepUnstableUntilFirst } from '@angular/fire'; +import { ɵAngularFireSchedulers, ɵcacheInstance } from '@angular/fire'; import { FirebaseOptions } from 'firebase/app'; import { ɵfirebaseAppFactory, FIREBASE_APP_NAME, FIREBASE_OPTIONS } from '@angular/fire/compat'; import { UploadMetadata } from './interfaces'; import 'firebase/compat/storage'; import firebase from 'firebase/compat/app'; +import { AppCheckInstances } from '@angular/fire/app-check'; export const BUCKET = new InjectionToken('angularfire2.storageBucket'); export const MAX_UPLOAD_RETRY_TIME = new InjectionToken('angularfire2.storage.maxUploadRetryTime'); @@ -39,6 +39,7 @@ export class AngularFireStorage { @Optional() @Inject(MAX_UPLOAD_RETRY_TIME) maxUploadRetryTime: number | any, @Optional() @Inject(MAX_OPERATION_RETRY_TIME) maxOperationRetryTime: number | any, @Optional() @Inject(USE_EMULATOR) _useEmulator: any, + @Optional() _appCheckInstances: AppCheckInstances, ) { const app = ɵfirebaseAppFactory(options, zone, name); this.storage = ɵcacheInstance(`${app.name}.storage.${storageBucket}`, 'AngularFireStorage', app.name, () => { diff --git a/src/core.ts b/src/core.ts index 976155f6e..31cbf9ca9 100644 --- a/src/core.ts +++ b/src/core.ts @@ -1,5 +1,5 @@ import { isDevMode, NgZone, Version } from '@angular/core'; -import { FirebaseApp, getApp, getApps } from 'firebase/app'; +import { FirebaseApp, getApps } from 'firebase/app'; import { ComponentContainer } from '@firebase/component'; export const VERSION = new Version('ANGULARFIRE2_VERSION'); @@ -34,6 +34,16 @@ export function ɵcacheInstance(cacheKey: any, moduleName: string, appName: s globalThis.ɵAngularfireInstanceCache ||= []; +// HACK HACK HACK +// AppCheck stuff, here so we can get a jump on it. It's too late in the evaluation +// if we do this in the app-check module. globalThis.ngDevMode allows me to test if +// Angular is in DevMode before Angular initializes. +if (typeof process !== 'undefined' && process.env?.FIREBASE_APPCHECK_DEBUG_TOKEN) { + globalThis.FIREBASE_APPCHECK_DEBUG_TOKEN ??= process.env.FIREBASE_APPCHECK_DEBUG_TOKEN; +} else if (globalThis.ngDevMode) { + globalThis.FIREBASE_APPCHECK_DEBUG_TOKEN ??= true; +} + export function ɵmemoizeInstance(fn: () => T, zone: NgZone): T { const [, instance] = globalThis.ɵAngularfireInstanceCache.find((it: any) => matchDep(it[0], fn)) || []; if (instance) { diff --git a/src/database/database.module.ts b/src/database/database.module.ts index 1b73fa9be..4bb178f74 100644 --- a/src/database/database.module.ts +++ b/src/database/database.module.ts @@ -1,11 +1,11 @@ import { NgModule, Optional, NgZone, InjectionToken, ModuleWithProviders } from '@angular/core'; import { Database as FirebaseDatabase } from 'firebase/database'; - import { AuthInstances } from '@angular/fire/auth'; import { ɵgetDefaultInstanceOf, ɵmemoizeInstance, ɵAngularFireSchedulers, VERSION } from '@angular/fire'; import { Database, DatabaseInstances, DATABASE_PROVIDER_NAME } from './database'; import { FirebaseApps, FirebaseApp } from '@angular/fire/app'; import { registerVersion } from 'firebase/app'; +import { AppCheckInstances } from '@angular/fire/app-check'; export const PROVIDED_DATABASE_INSTANCES = new InjectionToken('angularfire2.database-instances'); @@ -62,6 +62,7 @@ export function provideDatabase(fn: () => FirebaseDatabase): ModuleWithProviders FirebaseApps, // Database+Auth work better if Auth is loaded first [new Optional(), AuthInstances ], + [new Optional(), AppCheckInstances ], ] }] }; diff --git a/src/firestore/firestore.module.ts b/src/firestore/firestore.module.ts index 5b67d0240..a55218ad0 100644 --- a/src/firestore/firestore.module.ts +++ b/src/firestore/firestore.module.ts @@ -5,6 +5,7 @@ import { ɵmemoizeInstance, ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VER import { Firestore, FirestoreInstances, FIRESTORE_PROVIDER_NAME } from './firestore'; import { FirebaseApps, FirebaseApp } from '@angular/fire/app'; import { registerVersion } from 'firebase/app'; +import { AppCheckInstances } from '@angular/fire/app-check'; export const PROVIDED_FIRESTORE_INSTANCES = new InjectionToken('angularfire2.firestore-instances'); @@ -63,6 +64,7 @@ export function provideFirestore(fn: () => FirebaseFirestore): ModuleWithProvide FirebaseApps, // Firestore+Auth work better if Auth is loaded first [new Optional(), AuthInstances ], + [new Optional(), AppCheckInstances ], ] }] }; diff --git a/src/functions/functions.module.ts b/src/functions/functions.module.ts index 7734a8673..8bccf163d 100644 --- a/src/functions/functions.module.ts +++ b/src/functions/functions.module.ts @@ -5,6 +5,7 @@ import { Functions, FunctionsInstances, FUNCTIONS_PROVIDER_NAME } from './functi import { FirebaseApps, FirebaseApp } from '@angular/fire/app'; import { AuthInstances } from '@angular/fire/auth'; import { registerVersion } from 'firebase/app'; +import { AppCheckInstances } from '@angular/fire/app-check'; export const PROVIDED_FUNCTIONS_INSTANCES = new InjectionToken('angularfire2.functions-instances'); @@ -61,6 +62,7 @@ export function provideFunctions(fn: () => FirebaseFunctions): ModuleWithProvide FirebaseApps, // Defensively load Auth first, if provided [new Optional(), AuthInstances ], + [new Optional(), AppCheckInstances ], ] }] }; diff --git a/src/storage/storage.module.ts b/src/storage/storage.module.ts index edccda138..b2c274bad 100644 --- a/src/storage/storage.module.ts +++ b/src/storage/storage.module.ts @@ -5,6 +5,7 @@ import { Storage, StorageInstances, STORAGE_PROVIDER_NAME } from './storage'; import { FirebaseApps, FirebaseApp } from '@angular/fire/app'; import { AuthInstances } from '@angular/fire/auth'; import { registerVersion } from 'firebase/app'; +import { AppCheckInstances } from '@angular/fire/app-check'; export const PROVIDED_STORAGE_INSTANCES = new InjectionToken('angularfire2.storage-instances'); @@ -61,6 +62,7 @@ export function provideStorage(fn: () => FirebaseStorage): ModuleWithProviders `export const ${exportName} = ɵ return Promise.all([ reexport('analytics', 'firebase', 'firebase/analytics', tsKeys()), reexport('app', 'firebase', 'firebase/app', tsKeys()), + reexport('app-check', 'firebase', 'firebase/app-check', tsKeys()), reexport('auth', 'rxfire', 'rxfire/auth', tsKeys()), reexport('auth', 'firebase', 'firebase/auth', tsKeys(), { debugErrorMap: null, diff --git a/tsconfig.base.json b/tsconfig.base.json index 198e922c8..091d06fae 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -23,27 +23,7 @@ ], "paths": { "@angular/fire": ["dist/packages-dist"], - "@angular/fire/auth": ["dist/packages-dist/auth"], - "@angular/fire/auth-guard": ["dist/packages-dist/auth-guard"], - "@angular/fire/analytics": ["dist/packages-dist/analytics"], - "@angular/fire/database": ["dist/packages-dist/database"], - "@angular/fire/firestore": ["dist/packages-dist/firestore"], - "@angular/fire/functions": ["dist/packages-dist/functions"], - "@angular/fire/messaging": ["dist/packages-dist/messaging"], - "@angular/fire/performance": ["dist/packages-dist/performance"], - "@angular/fire/remote-config": ["dist/packages-dist/remote-config"], - "@angular/fire/storage": ["dist/packages-dist/storage"], - "@angular/fire/compat": ["dist/packages-dist/compat"], - "@angular/fire/compat/auth-guard": ["dist/packages-dist/compat/auth-guard"], - "@angular/fire/compat/analytics": ["dist/packages-dist/compat/analytics"], - "@angular/fire/compat/auth": ["dist/packages-dist/compat/auth"], - "@angular/fire/compat/database": ["dist/packages-dist/compat/database"], - "@angular/fire/compat/firestore": ["dist/packages-dist/compat/firestore"], - "@angular/fire/compat/functions": ["dist/packages-dist/compat/functions"], - "@angular/fire/compat/messaging": ["dist/packages-dist/compat/messaging"], - "@angular/fire/compat/performance": ["dist/packages-dist/compat/performance"], - "@angular/fire/compat/remote-config": ["dist/packages-dist/compat/remote-config"], - "@angular/fire/compat/storage": ["dist/packages-dist/compat/storage"] + "@angular/fire/*": ["dist/packages-dist/*"] } } }