1- import  {  getAnalytics ,  logEvent  }  from  "firebase/analytics" ; 
1+ import  { 
2+   Analytics , 
3+   getAnalytics , 
4+   isSupported , 
5+   logEvent , 
6+ }  from  "firebase/analytics" ; 
27import  {  FirebaseApp ,  initializeApp  }  from  "firebase/app" ; 
38import  {  child ,  getDatabase ,  onValue ,  ref  }  from  "firebase/database" ; 
49
@@ -13,99 +18,98 @@ type UUID = string;
1318
1419export  function  addLocationListener ( 
1520  pullKey : string , 
16-   callback : ( location : Location )  =>  void 
21+   callback : ( location : Location )  =>  void , 
1722)  { 
1823  return  forPullKey ( pullKey ) . addLocationListener ( callback ) ; 
1924} 
2025
2126export  function  addSpeedListener ( 
2227  pullKey : string , 
23-   callback : ( speed : MetersPerSecond )  =>  void 
28+   callback : ( speed : MetersPerSecond )  =>  void , 
2429)  { 
2530  return  forPullKey ( pullKey ) . addSpeedListener ( callback ) ; 
2631} 
2732
2833export  function  addHeadingListener ( 
2934  pullKey : string , 
30-   callback : ( heading : Degrees )  =>  void 
35+   callback : ( heading : Degrees )  =>  void , 
3136)  { 
3237  return  forPullKey ( pullKey ) . addHeadingListener ( callback ) ; 
3338} 
3439
3540export  function  addAltitudeListener ( 
3641  pullKey : string , 
37-   callback : ( altitude : Meters )  =>  void 
42+   callback : ( altitude : Meters )  =>  void , 
3843)  { 
3944  return  forPullKey ( pullKey ) . addAltitudeListener ( callback ) ; 
4045} 
4146
4247export  function  addSessionIdListener ( 
4348  pullKey : string , 
44-   callback : ( sessionId : UUID  |  null )  =>  void 
49+   callback : ( sessionId : UUID  |  null )  =>  void , 
4550)  { 
4651  return  forPullKey ( pullKey ) . addSessionIdListener ( callback ) ; 
4752} 
4853
4954/** Creates a listener source for a streamer's private data with a pull key. */ 
5055export  function  forPullKey ( pullKey : string )  { 
5156  const  db  =  getDatabase ( getApp ( ) ) ; 
52-   const  analytics  =  getAnalytics ( getApp ( ) ) ; 
5357  const  reference  =  child ( ref ( db ,  "pullables" ) ,  pullKey ) ; 
5458  return  { 
5559    addLocationListener ( callback : ( location : Location )  =>  void )  { 
56-       logEvent ( analytics ,   "listener" ,  {  type : "location" ,  pullKey } ) ; 
60+       safeLogEvent ( "listener" ,  {  type : "location" ,  pullKey } ) ; 
5761      return  onValue ( child ( reference ,  "location" ) ,  ( snapshot )  =>  { 
5862        callback ( snapshot . val ( ) ) ; 
59-         logEvent ( analytics ,   "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
63+         safeLogEvent ( "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
6064      } ) ; 
6165    } , 
6266    addSpeedListener ( callback : ( speed : MetersPerSecond )  =>  void )  { 
63-       logEvent ( analytics ,   "listener" ,  {  type : "speed" ,  pullKey } ) ; 
67+       safeLogEvent ( "listener" ,  {  type : "speed" ,  pullKey } ) ; 
6468      return  onValue ( child ( reference ,  "speed" ) ,  ( snapshot )  =>  { 
6569        callback ( snapshot . val ( ) ) ; 
66-         logEvent ( analytics ,   "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
70+         safeLogEvent ( "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
6771      } ) ; 
6872    } , 
6973    addHeadingListener ( callback : ( heading : Degrees )  =>  void )  { 
70-       logEvent ( analytics ,   "listener" ,  {  type : "heading" ,  pullKey } ) ; 
74+       safeLogEvent ( "listener" ,  {  type : "heading" ,  pullKey } ) ; 
7175      return  onValue ( child ( reference ,  "heading" ) ,  ( snapshot )  =>  { 
7276        callback ( snapshot . val ( ) ) ; 
73-         logEvent ( analytics ,   "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
77+         safeLogEvent ( "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
7478      } ) ; 
7579    } , 
7680    addAltitudeListener ( callback : ( altitude : Meters )  =>  void )  { 
77-       logEvent ( analytics ,   "listener" ,  {  type : "altitude" ,  pullKey } ) ; 
81+       safeLogEvent ( "listener" ,  {  type : "altitude" ,  pullKey } ) ; 
7882      return  onValue ( child ( reference ,  "altitude" ) ,  ( snapshot )  =>  { 
7983        callback ( snapshot . val ( ) ) ; 
80-         logEvent ( analytics ,   "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
84+         safeLogEvent ( "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
8185      } ) ; 
8286    } , 
8387    addHeartRateListener ( callback : ( altitude : BeatsPerMinute )  =>  void )  { 
84-       logEvent ( analytics ,   "listener" ,  {  type : "heartRate" ,  pullKey } ) ; 
88+       safeLogEvent ( "listener" ,  {  type : "heartRate" ,  pullKey } ) ; 
8589      return  onValue ( child ( reference ,  "heartRate" ) ,  ( snapshot )  =>  { 
8690        callback ( snapshot . val ( ) ) ; 
87-         logEvent ( analytics ,   "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
91+         safeLogEvent ( "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
8892      } ) ; 
8993    } , 
9094    addCyclingPowerListener ( callback : ( power : Watts )  =>  void )  { 
91-       logEvent ( analytics ,   "listener" ,  {  type : "cyclingPower" ,  pullKey } ) ; 
95+       safeLogEvent ( "listener" ,  {  type : "cyclingPower" ,  pullKey } ) ; 
9296      return  onValue ( child ( reference ,  "cyclingPower" ) ,  ( snapshot )  =>  { 
9397        callback ( snapshot . val ( ) ) ; 
94-         logEvent ( analytics ,   "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
98+         safeLogEvent ( "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
9599      } ) ; 
96100    } , 
97101    addCyclingCrankListener ( callback : ( power : Watts )  =>  void )  { 
98-       logEvent ( analytics ,   "listener" ,  {  type : "cyclingCrank" ,  pullKey } ) ; 
102+       safeLogEvent ( "listener" ,  {  type : "cyclingCrank" ,  pullKey } ) ; 
99103      return  onValue ( child ( reference ,  "cyclingCrank" ) ,  ( snapshot )  =>  { 
100104        callback ( snapshot . val ( ) ) ; 
101-         logEvent ( analytics ,   "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
105+         safeLogEvent ( "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
102106      } ) ; 
103107    } , 
104108    addCyclingWheelListener ( callback : ( power : Watts )  =>  void )  { 
105-       logEvent ( analytics ,   "listener" ,  {  type : "cyclingWheel" ,  pullKey } ) ; 
109+       safeLogEvent ( "listener" ,  {  type : "cyclingWheel" ,  pullKey } ) ; 
106110      return  onValue ( child ( reference ,  "cyclingWheel" ) ,  ( snapshot )  =>  { 
107111        callback ( snapshot . val ( ) ) ; 
108-         logEvent ( analytics ,   "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
112+         safeLogEvent ( "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
109113      } ) ; 
110114    } , 
111115    /** 
@@ -117,10 +121,10 @@ export function forPullKey(pullKey: string) {
117121     * for a given session id. 
118122     */ 
119123    addPedometerStepsListener ( callback : ( steps : Steps )  =>  void )  { 
120-       logEvent ( analytics ,   "listener" ,  {  type : "pedometerSteps" ,  pullKey } ) ; 
124+       safeLogEvent ( "listener" ,  {  type : "pedometerSteps" ,  pullKey } ) ; 
121125      return  onValue ( child ( reference ,  "pedometerSteps" ) ,  ( snapshot )  =>  { 
122126        callback ( snapshot . val ( ) ) ; 
123-         logEvent ( analytics ,   "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
127+         safeLogEvent ( "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
124128      } ) ; 
125129    } , 
126130    /** 
@@ -129,10 +133,10 @@ export function forPullKey(pullKey: string) {
129133     * as bluetooth heart rate or telemetry data. 
130134     */ 
131135    addListener ( callback : ( data : any )  =>  void )  { 
132-       logEvent ( analytics ,   "listener" ,  {  type : "root" ,  pullKey } ) ; 
136+       safeLogEvent ( "listener" ,  {  type : "root" ,  pullKey } ) ; 
133137      return  onValue ( reference ,  ( snapshot )  =>  { 
134138        callback ( snapshot . val ( ) ) ; 
135-         logEvent ( analytics ,   "data" ,  {  type : "root" ,  pullKey } ) ; 
139+         safeLogEvent ( "data" ,  {  type : "root" ,  pullKey } ) ; 
136140      } ) ; 
137141    } , 
138142    /** 
@@ -142,10 +146,10 @@ export function forPullKey(pullKey: string) {
142146     * possible for two sequential non-null sessionIds to be sent. 
143147     */ 
144148    addSessionIdListener ( callback : ( sessionId : UUID  |  null )  =>  void )  { 
145-       logEvent ( analytics ,   "listener" ,  {  type : "sessionId" ,  pullKey } ) ; 
149+       safeLogEvent ( "listener" ,  {  type : "sessionId" ,  pullKey } ) ; 
146150      return  onValue ( child ( reference ,  "sessionId" ) ,  ( snapshot )  =>  { 
147151        callback ( snapshot . val ( ) ) ; 
148-         logEvent ( analytics ,   "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
152+         safeLogEvent ( "data" ,  {  type : "sessionId" ,  pullKey } ) ; 
149153      } ) ; 
150154    } , 
151155  } ; 
@@ -154,21 +158,22 @@ export function forPullKey(pullKey: string) {
154158/** Creates a listener source for a streamer's public data. */ 
155159export  function  forStreamer ( provider : "twitch" ,  userId : string )  { 
156160  const  db  =  getDatabase ( getApp ( ) ) ; 
157-   const  analytics  =  getAnalytics ( getApp ( ) ) ; 
158161  const  reference  =  child ( ref ( db ,  "streamers" ) ,  `${ provider } ${ userId }  ) ; 
159162  return  { 
160163    /** If the public location is hidden (eg streamer is offline), null is passed. */ 
161164    addLocationListener ( callback : ( location : Location  |  null )  =>  void )  { 
162-       logEvent ( analytics ,   "listener" ,  {  type : "location" ,  provider,  userId } ) ; 
165+       safeLogEvent ( "listener" ,  {  type : "location" ,  provider,  userId } ) ; 
163166      return  onValue ( child ( reference ,  "location" ) ,  ( snapshot )  =>  { 
164167        callback ( snapshot . val ( ) ) ; 
165-         logEvent ( analytics ,   "data" ,  {  type : "location" ,  provider,  userId } ) ; 
168+         safeLogEvent ( "data" ,  {  type : "location" ,  provider,  userId } ) ; 
166169      } ) ; 
167170    } , 
168171  } ; 
169172} 
170173
171174let  app : FirebaseApp  |  null  =  null ; 
175+ let  analyticsInstance : Analytics  |  null  =  null ; 
176+ let  analyticsChecked  =  false ; 
172177
173178function  getApp ( )  { 
174179  if  ( ! app )  { 
@@ -180,8 +185,32 @@ function getApp() {
180185        appId : "1:684852107701:web:d77a8ed0ee5095279a61fc" , 
181186        measurementId : "G-TR97D81LT3" , 
182187      } , 
183-       "rtirl-api" 
188+       "rtirl-api" , 
184189    ) ; 
185190  } 
186191  return  app ; 
187192} 
193+ 
194+ async  function  getAnalyticsIfSupported ( ) : Promise < Analytics  |  null >  { 
195+   if  ( analyticsChecked )  { 
196+     return  analyticsInstance ; 
197+   } 
198+ 
199+   analyticsChecked  =  true ; 
200+   if  ( await  isSupported ( ) )  { 
201+     analyticsInstance  =  getAnalytics ( getApp ( ) ) ; 
202+   } 
203+   return  analyticsInstance ; 
204+ } 
205+ 
206+ function  safeLogEvent ( eventName : string ,  eventParams ?: any )  { 
207+   getAnalyticsIfSupported ( ) 
208+     . then ( ( analytics )  =>  { 
209+       if  ( analytics )  { 
210+         logEvent ( analytics ,  eventName ,  eventParams ) ; 
211+       } 
212+     } ) 
213+     . catch ( ( )  =>  { 
214+       // Silently ignore analytics errors 
215+     } ) ; 
216+ } 
0 commit comments