UNPKG

@angular/fire

Version:
297 lines (289 loc) 15.1 kB
import { ɵgetAllInstancesOf as _getAllInstancesOf, ɵzoneWrap as _zoneWrap, VERSION, ɵgetDefaultInstanceOf as _getDefaultInstanceOf, ɵAngularFireSchedulers as _AngularFireSchedulers } from '@angular/fire'; import { timer, from, of } from 'rxjs'; import { concatMap, distinct, filter, switchMap, map, groupBy, mergeMap, distinctUntilChanged, startWith, pairwise } from 'rxjs/operators'; import { isPlatformBrowser } from '@angular/common'; import * as i0 from '@angular/core'; import { Injectable, Optional, InjectionToken, PLATFORM_ID, NgModule, makeEnvironmentProviders, NgZone, Injector } from '@angular/core'; import { FirebaseApp, FirebaseApps } from '@angular/fire/app'; import { registerVersion } from 'firebase/app'; import * as i2 from '@angular/platform-browser'; import * as i1$1 from '@angular/router'; import { ActivationEnd, ɵEmptyOutletComponent as _EmptyOutletComponent } from '@angular/router'; import { getAnalytics as getAnalytics$1, getGoogleAnalyticsClientId as getGoogleAnalyticsClientId$1, initializeAnalytics as initializeAnalytics$1, isSupported as isSupported$1, logEvent as logEvent$1, setAnalyticsCollectionEnabled as setAnalyticsCollectionEnabled$1, setConsent as setConsent$1, setCurrentScreen as setCurrentScreen$1, setDefaultEventParameters as setDefaultEventParameters$1, setUserId as setUserId$1, setUserProperties as setUserProperties$1, settings as settings$1 } from 'firebase/analytics'; export * from 'firebase/analytics'; import * as i1 from '@angular/fire/auth'; import { authState } from '@angular/fire/auth'; class Analytics { constructor(analytics) { return analytics; } } const ANALYTICS_PROVIDER_NAME = 'analytics'; class AnalyticsInstances { constructor() { return _getAllInstancesOf(ANALYTICS_PROVIDER_NAME); } } const analyticInstance$ = timer(0, 300).pipe(concatMap(() => from(_getAllInstancesOf(ANALYTICS_PROVIDER_NAME))), distinct()); // DO NOT MODIFY, this file is autogenerated by tools/build.ts const getAnalytics = _zoneWrap(getAnalytics$1, true); const getGoogleAnalyticsClientId = _zoneWrap(getGoogleAnalyticsClientId$1, true); const initializeAnalytics = _zoneWrap(initializeAnalytics$1, true); const isSupported = _zoneWrap(isSupported$1, false); const logEvent = _zoneWrap(logEvent$1, false, 2); const setAnalyticsCollectionEnabled = _zoneWrap(setAnalyticsCollectionEnabled$1, true, 2); const setConsent = _zoneWrap(setConsent$1, true, 2); const setCurrentScreen = _zoneWrap(setCurrentScreen$1, true, 2); const setDefaultEventParameters = _zoneWrap(setDefaultEventParameters$1, true, 2); const setUserId = _zoneWrap(setUserId$1, true, 2); const setUserProperties = _zoneWrap(setUserProperties$1, true, 2); const settings = _zoneWrap(settings$1, true); class UserTrackingService { initialized; disposables = []; constructor(auth, zone, injector) { registerVersion('angularfire', VERSION.full, 'user-tracking'); let resolveInitialized; this.initialized = zone.runOutsideAngular(() => new Promise(resolve => { resolveInitialized = resolve; })); // The APP_INITIALIZER that is making isSupported() sync for the sake of convenient DI // may not be done when services are initialized. Guard the functionality by first ensuring // that the (global) promise has resolved, then get Analytics from the injector. isSupported().then(() => { const analytics = injector.get(Analytics); if (analytics) { this.disposables = [ // TODO add credential tracking back in authState(auth).subscribe(user => { setUserId(analytics, user?.uid); resolveInitialized(); }), ]; } else { resolveInitialized(); } }); } ngOnDestroy() { this.disposables.forEach(it => it.unsubscribe()); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: UserTrackingService, deps: [{ token: i1.Auth }, { token: i0.NgZone }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: UserTrackingService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: UserTrackingService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.Auth }, { type: i0.NgZone }, { type: i0.Injector }] }); const FIREBASE_EVENT_ORIGIN_KEY = 'firebase_event_origin'; const FIREBASE_PREVIOUS_SCREEN_CLASS_KEY = 'firebase_previous_class'; const FIREBASE_PREVIOUS_SCREEN_INSTANCE_ID_KEY = 'firebase_previous_id'; const FIREBASE_PREVIOUS_SCREEN_NAME_KEY = 'firebase_previous_screen'; const FIREBASE_SCREEN_CLASS_KEY = 'firebase_screen_class'; const FIREBASE_SCREEN_INSTANCE_ID_KEY = 'firebase_screen_id'; const FIREBASE_SCREEN_NAME_KEY = 'firebase_screen'; const OUTLET_KEY = 'outlet'; const PAGE_PATH_KEY = 'page_path'; const PAGE_TITLE_KEY = 'page_title'; const SCREEN_CLASS_KEY = 'screen_class'; const SCREEN_NAME_KEY = 'screen_name'; const SCREEN_VIEW_EVENT = 'screen_view'; const EVENT_ORIGIN_AUTO = 'auto'; const SCREEN_INSTANCE_DELIMITER = '#'; // this is an INT64 in iOS/Android but use INT32 cause javascript let nextScreenInstanceID = Math.floor(Math.random() * (2 ** 32 - 1)) - 2 ** 31; const knownScreenInstanceIDs = {}; const getScreenInstanceID = (params) => { // unique the screen class against the outlet name const screenInstanceKey = [ params[SCREEN_CLASS_KEY], params[OUTLET_KEY] ].join(SCREEN_INSTANCE_DELIMITER); // eslint-disable-next-line no-prototype-builtins if (knownScreenInstanceIDs.hasOwnProperty(screenInstanceKey)) { return knownScreenInstanceIDs[screenInstanceKey]; } else { const ret = nextScreenInstanceID++; knownScreenInstanceIDs[screenInstanceKey] = ret; return ret; } }; const ɵscreenViewEvent = (router, title, componentFactoryResolver) => { const activationEndEvents = router.events.pipe(filter(e => e instanceof ActivationEnd)); return activationEndEvents.pipe(switchMap(activationEnd => { // router parseUrl is having trouble with outlets when they're empty // e.g, /asdf/1(bob://sally:asdf), so put another slash in when empty const urlTree = router.parseUrl(router.url.replace(/(?:\().+(?:\))/g, a => a.replace('://', ':///'))); const pagePath = urlTree.root.children[activationEnd.snapshot.outlet]?.toString() || ''; const actualSnapshot = router.routerState.root.children.map(it => it).find(it => it.outlet === activationEnd.snapshot.outlet); if (!actualSnapshot) { return of(null); } let actualDeep = actualSnapshot; while (actualDeep.firstChild) { actualDeep = actualDeep.firstChild; } const screenName = actualDeep.pathFromRoot.map(s => s.routeConfig?.path).filter(it => it).join('/') || '/'; const params = { [SCREEN_NAME_KEY]: screenName, [PAGE_PATH_KEY]: `/${pagePath}`, [FIREBASE_EVENT_ORIGIN_KEY]: EVENT_ORIGIN_AUTO, [FIREBASE_SCREEN_NAME_KEY]: screenName, [OUTLET_KEY]: activationEnd.snapshot.outlet }; if (title) { params[PAGE_TITLE_KEY] = title.getTitle(); } let component = actualSnapshot.component; if (component) { if (component === _EmptyOutletComponent) { let deepSnapshot = activationEnd.snapshot; // TODO when might there be mutple children, different outlets? explore while (deepSnapshot.firstChild) { deepSnapshot = deepSnapshot.firstChild; } component = deepSnapshot.component; } } else { component = activationEnd.snapshot.component; } if (typeof component === 'string') { return of({ ...params, [SCREEN_CLASS_KEY]: component }); } else if (component) { const componentFactory = componentFactoryResolver.resolveComponentFactory(component); return of({ ...params, [SCREEN_CLASS_KEY]: componentFactory.selector }); } // lazy loads cause extra activations, ignore return of(null); }), filter(it => !!it), map(params => ({ [FIREBASE_SCREEN_CLASS_KEY]: params[SCREEN_CLASS_KEY], [FIREBASE_SCREEN_INSTANCE_ID_KEY]: getScreenInstanceID(params), ...params })), groupBy(it => it[OUTLET_KEY]), mergeMap(it => it.pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)), startWith(undefined), pairwise(), map(([prior, current]) => prior ? { [FIREBASE_PREVIOUS_SCREEN_CLASS_KEY]: prior[SCREEN_CLASS_KEY], [FIREBASE_PREVIOUS_SCREEN_NAME_KEY]: prior[SCREEN_NAME_KEY], [FIREBASE_PREVIOUS_SCREEN_INSTANCE_ID_KEY]: prior[FIREBASE_SCREEN_INSTANCE_ID_KEY], ...current } : current)))); }; class ScreenTrackingService { disposable; constructor(router, title, componentFactoryResolver, zone, userTrackingService, injector) { registerVersion('angularfire', VERSION.full, 'screen-tracking'); // The APP_INITIALIZER that is making isSupported() sync for the sake of convenient DI // may not be done when services are initialized. Guard the functionality by first ensuring // that the (global) promise has resolved, then get Analytics from the injector. isSupported().then(() => { const analytics = injector.get(Analytics); if (!router || !analytics) { return; } zone.runOutsideAngular(() => { this.disposable = ɵscreenViewEvent(router, title, componentFactoryResolver).pipe(switchMap(async (params) => { if (userTrackingService) { await userTrackingService.initialized; } return logEvent(analytics, SCREEN_VIEW_EVENT, params); })).subscribe(); }); }); } ngOnDestroy() { if (this.disposable) { this.disposable.unsubscribe(); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ScreenTrackingService, deps: [{ token: i1$1.Router, optional: true }, { token: i2.Title, optional: true }, { token: i0.ComponentFactoryResolver }, { token: i0.NgZone }, { token: UserTrackingService, optional: true }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ScreenTrackingService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ScreenTrackingService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1$1.Router, decorators: [{ type: Optional }] }, { type: i2.Title, decorators: [{ type: Optional }] }, { type: i0.ComponentFactoryResolver }, { type: i0.NgZone }, { type: UserTrackingService, decorators: [{ type: Optional }] }, { type: i0.Injector }] }); const PROVIDED_ANALYTICS_INSTANCES = new InjectionToken('angularfire2.analytics-instances'); function defaultAnalyticsInstanceFactory(provided, defaultApp, platformId) { if (!isPlatformBrowser(platformId)) { return null; } const defaultAnalytics = _getDefaultInstanceOf(ANALYTICS_PROVIDER_NAME, provided, defaultApp); return defaultAnalytics && new Analytics(defaultAnalytics); } function analyticsInstanceFactory(fn) { return (zone, injector, platformId) => { if (!isPlatformBrowser(platformId)) { return null; } const analytics = zone.runOutsideAngular(() => fn(injector)); return new Analytics(analytics); }; } const ANALYTICS_INSTANCES_PROVIDER = { provide: AnalyticsInstances, deps: [ [new Optional(), PROVIDED_ANALYTICS_INSTANCES], ] }; const DEFAULT_ANALYTICS_INSTANCE_PROVIDER = { provide: Analytics, useFactory: defaultAnalyticsInstanceFactory, deps: [ [new Optional(), PROVIDED_ANALYTICS_INSTANCES], FirebaseApp, PLATFORM_ID, ] }; class AnalyticsModule { constructor(_screenTrackingService, _userTrackingService) { registerVersion('angularfire', VERSION.full, 'analytics'); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AnalyticsModule, deps: [{ token: ScreenTrackingService, optional: true }, { token: UserTrackingService, optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.0", ngImport: i0, type: AnalyticsModule }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AnalyticsModule, providers: [ DEFAULT_ANALYTICS_INSTANCE_PROVIDER, ANALYTICS_INSTANCES_PROVIDER ] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AnalyticsModule, decorators: [{ type: NgModule, args: [{ providers: [ DEFAULT_ANALYTICS_INSTANCE_PROVIDER, ANALYTICS_INSTANCES_PROVIDER ] }] }], ctorParameters: () => [{ type: ScreenTrackingService, decorators: [{ type: Optional }] }, { type: UserTrackingService, decorators: [{ type: Optional }] }] }); function provideAnalytics(fn, ...deps) { registerVersion('angularfire', VERSION.full, 'analytics'); return makeEnvironmentProviders([ DEFAULT_ANALYTICS_INSTANCE_PROVIDER, ANALYTICS_INSTANCES_PROVIDER, { provide: PROVIDED_ANALYTICS_INSTANCES, useFactory: analyticsInstanceFactory(fn), multi: true, deps: [ NgZone, Injector, PLATFORM_ID, _AngularFireSchedulers, FirebaseApps, ...deps, ], }, ]); } /** * Generated bundle index. Do not edit. */ export { Analytics, AnalyticsInstances, AnalyticsModule, ScreenTrackingService, UserTrackingService, analyticInstance$, getAnalytics, getGoogleAnalyticsClientId, initializeAnalytics, isSupported, logEvent, provideAnalytics, setAnalyticsCollectionEnabled, setConsent, setCurrentScreen, setDefaultEventParameters, setUserId, setUserProperties, settings, ɵscreenViewEvent }; //# sourceMappingURL=angular-fire-analytics.mjs.map