(
@Inject(FIREBASE_OPTIONS) options: FirebaseOptions,
@Optional() @Inject(FIREBASE_APP_NAME) name: string|null|undefined,
// eslint-disable-next-line @typescript-eslint/ban-types
@Inject(PLATFORM_ID) platformId: Object,
zone: NgZone,
schedulers: ɵAngularFireSchedulers,
@Optional() @Inject(USE_EMULATOR) useEmulator: any, // can't use the tuple here
@Optional() @Inject(SETTINGS) settings: any, // can't use firebase.auth.AuthSettings here
@Optional() @Inject(TENANT_ID) tenantId: string | null,
@Optional() @Inject(LANGUAGE_CODE) languageCode: string | null,
@Optional() @Inject(USE_DEVICE_LANGUAGE) useDeviceLanguage: boolean | null,
@Optional() @Inject(PERSISTENCE) persistence: string | null,
@Optional() _appCheckInstances: AppCheckInstances,
)
| 85 | public readonly credential: Observable<Required<firebase.auth.UserCredential>|null>; |
| 86 | |
| 87 | constructor( |
| 88 | @Inject(FIREBASE_OPTIONS) options: FirebaseOptions, |
| 89 | @Optional() @Inject(FIREBASE_APP_NAME) name: string|null|undefined, |
| 90 | // eslint-disable-next-line @typescript-eslint/ban-types |
| 91 | @Inject(PLATFORM_ID) platformId: Object, |
| 92 | zone: NgZone, |
| 93 | schedulers: ɵAngularFireSchedulers, |
| 94 | @Optional() @Inject(USE_EMULATOR) useEmulator: any, // can't use the tuple here |
| 95 | @Optional() @Inject(SETTINGS) settings: any, // can't use firebase.auth.AuthSettings here |
| 96 | @Optional() @Inject(TENANT_ID) tenantId: string | null, |
| 97 | @Optional() @Inject(LANGUAGE_CODE) languageCode: string | null, |
| 98 | @Optional() @Inject(USE_DEVICE_LANGUAGE) useDeviceLanguage: boolean | null, |
| 99 | @Optional() @Inject(PERSISTENCE) persistence: string | null, |
| 100 | @Optional() _appCheckInstances: AppCheckInstances, |
| 101 | ) { |
| 102 | const logins = new Subject<Required<firebase.auth.UserCredential>>(); |
| 103 | |
| 104 | const auth = of(undefined).pipe( |
| 105 | observeOn(schedulers.outsideAngular), |
| 106 | switchMap(() => zone.runOutsideAngular(() => import('firebase/compat/auth'))), |
| 107 | map(() => ɵfirebaseAppFactory(options, zone, name)), |
| 108 | map(app => ɵauthFactory(app, zone, useEmulator, tenantId, languageCode, useDeviceLanguage, settings, persistence)), |
| 109 | shareReplay({ bufferSize: 1, refCount: false }), |
| 110 | ); |
| 111 | |
| 112 | if (isPlatformServer(platformId)) { |
| 113 | |
| 114 | this.authState = this.user = this.idToken = this.idTokenResult = this.credential = of(null); |
| 115 | |
| 116 | } else { |
| 117 | |
| 118 | // HACK, as we're exporting auth.Auth, rather than auth, developers importing firebase.auth |
| 119 | // (e.g, `import { auth } from 'firebase/compat/app'`) are getting an undefined auth object unexpectedly |
| 120 | // as we're completely lazy. Let's eagerly load the Auth SDK here. |
| 121 | // There could potentially be race conditions still... but this greatly decreases the odds while |
| 122 | // we reevaluate the API. |
| 123 | auth.pipe(first()).subscribe(); |
| 124 | |
| 125 | const redirectResult = auth.pipe( |
| 126 | switchMap(auth => auth.getRedirectResult().then(it => it, () => null)), |
| 127 | pendingUntilEvent(this.injector), |
| 128 | shareReplay({ bufferSize: 1, refCount: false }), |
| 129 | ); |
| 130 | |
| 131 | const authStateChanged = auth.pipe( |
| 132 | switchMap(auth => new Observable<firebase.User|null>(sub => |
| 133 | ({ unsubscribe: zone.runOutsideAngular(() => auth.onAuthStateChanged( |
| 134 | next => sub.next(next), |
| 135 | err => sub.error(err), |
| 136 | () => sub.complete() |
| 137 | ))}) |
| 138 | )), |
| 139 | ); |
| 140 | |
| 141 | const idTokenChanged = auth.pipe( |
| 142 | switchMap(auth => new Observable<firebase.User|null>(sub => |
| 143 | ({ unsubscribe: zone.runOutsideAngular(() => auth.onIdTokenChanged( |
| 144 | next => sub.next(next), |
nothing calls this directly
no test coverage detected