1- import type { DeviceContext , Event , Integration , OsContext } from '@sentry/core' ;
1+ import { type DeviceContext , type Event , type Integration , type OsContext , logger } from '@sentry/core' ;
22
3- import { getExpoDevice } from '../utils/expomodules' ;
3+ import { isExpo , isExpoGo } from '../utils/environment' ;
4+ import { getExpoDevice , getExpoUpdates } from '../utils/expomodules' ;
5+ import { NATIVE } from '../wrapper' ;
46
57const INTEGRATION_NAME = 'ExpoContext' ;
68
9+ export const EXPO_UPDATES_CONTEXT_KEY = 'expo_updates' ;
10+
711/** Load device context from expo modules. */
812export const expoContextIntegration = ( ) : Integration => {
13+ let _expoUpdatesContextCached : ExpoUpdatesContext | undefined ;
14+
15+ function setup ( ) : void {
16+ setExpoUpdatesNativeContext ( ) ;
17+ }
18+
19+ function setExpoUpdatesNativeContext ( ) : void {
20+ if ( ! isExpo ( ) || isExpoGo ( ) ) {
21+ return ;
22+ }
23+
24+ const expoUpdates = getExpoUpdatesContextCached ( ) ;
25+
26+ try {
27+ // Ensures native errors and crashes have the same context as JS errors
28+ NATIVE . setContext ( EXPO_UPDATES_CONTEXT_KEY , expoUpdates ) ;
29+ } catch ( error ) {
30+ logger . error ( 'Error setting Expo updates context:' , error ) ;
31+ }
32+ }
33+
34+ function processEvent ( event : Event ) : Event {
35+ if ( ! isExpo ( ) ) {
36+ return event ;
37+ }
38+
39+ addExpoGoContext ( event ) ;
40+ addExpoUpdatesContext ( event ) ;
41+ return event ;
42+ }
43+
44+ function addExpoUpdatesContext ( event : Event ) : void {
45+ event . contexts = event . contexts || { } ;
46+ event . contexts [ EXPO_UPDATES_CONTEXT_KEY ] = {
47+ ...getExpoUpdatesContextCached ( ) ,
48+ } ;
49+ }
50+
51+ function getExpoUpdatesContextCached ( ) : ExpoUpdatesContext {
52+ if ( _expoUpdatesContextCached ) {
53+ return _expoUpdatesContextCached ;
54+ }
55+
56+ return ( _expoUpdatesContextCached = getExpoUpdatesContext ( ) ) ;
57+ }
58+
959 return {
1060 name : INTEGRATION_NAME ,
11- setupOnce : ( ) => {
12- // noop
13- } ,
61+ setup,
1462 processEvent,
1563 } ;
1664} ;
1765
18- function processEvent ( event : Event ) : Event {
66+ function getExpoUpdatesContext ( ) : ExpoUpdatesContext {
67+ const expoUpdates = getExpoUpdates ( ) ;
68+ if ( ! expoUpdates ) {
69+ return {
70+ is_enabled : false ,
71+ } ;
72+ }
73+
74+ const updatesContext : ExpoUpdatesContext = {
75+ is_enabled : ! ! expoUpdates . isEnabled ,
76+ is_embedded_launch : ! ! expoUpdates . isEmbeddedLaunch ,
77+ is_emergency_launch : ! ! expoUpdates . isEmergencyLaunch ,
78+ is_using_embedded_assets : ! ! expoUpdates . isUsingEmbeddedAssets ,
79+ } ;
80+
81+ if ( typeof expoUpdates . updateId === 'string' ) {
82+ updatesContext . update_id = expoUpdates . updateId ;
83+ }
84+ if ( typeof expoUpdates . channel === 'string' ) {
85+ updatesContext . channel = expoUpdates . channel ;
86+ }
87+ if ( typeof expoUpdates . runtimeVersion === 'string' ) {
88+ updatesContext . runtime_version = expoUpdates . runtimeVersion ;
89+ }
90+ if ( typeof expoUpdates . checkAutomatically === 'string' ) {
91+ updatesContext . check_automatically = expoUpdates . checkAutomatically ;
92+ }
93+ if ( typeof expoUpdates . emergencyLaunchReason === 'string' ) {
94+ updatesContext . emergency_launch_reason = expoUpdates . emergencyLaunchReason ;
95+ }
96+ if ( typeof expoUpdates . launchDuration === 'number' ) {
97+ updatesContext . launch_duration = expoUpdates . launchDuration ;
98+ }
99+ if ( expoUpdates . createdAt instanceof Date ) {
100+ updatesContext . created_at = expoUpdates . createdAt . toISOString ( ) ;
101+ }
102+ return updatesContext ;
103+ }
104+
105+ function addExpoGoContext ( event : Event ) : void {
106+ if ( ! isExpoGo ( ) ) {
107+ return ;
108+ }
109+
19110 const expoDeviceContext = getExpoDeviceContext ( ) ;
20111 if ( expoDeviceContext ) {
21112 event . contexts = event . contexts || { } ;
@@ -27,8 +118,6 @@ function processEvent(event: Event): Event {
27118 event . contexts = event . contexts || { } ;
28119 event . contexts . os = { ...expoOsContext , ...event . contexts . os } ;
29120 }
30-
31- return event ;
32121}
33122
34123/**
@@ -66,3 +155,17 @@ function getExpoOsContext(): OsContext | undefined {
66155 name : expoDevice . osName ,
67156 } ;
68157}
158+
159+ type ExpoUpdatesContext = Partial < {
160+ is_enabled : boolean ;
161+ is_embedded_launch : boolean ;
162+ is_emergency_launch : boolean ;
163+ is_using_embedded_assets : boolean ;
164+ update_id : string ;
165+ channel : string ;
166+ runtime_version : string ;
167+ check_automatically : string ;
168+ emergency_launch_reason : string ;
169+ launch_duration : number ;
170+ created_at : string ;
171+ } > ;
0 commit comments