1
- import type { DeviceContext , Event , Integration , OsContext } from '@sentry/core' ;
1
+ import { type DeviceContext , type Event , type Integration , type OsContext , logger } from '@sentry/core' ;
2
2
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' ;
4
6
5
7
const INTEGRATION_NAME = 'ExpoContext' ;
6
8
9
+ export const EXPO_UPDATES_CONTEXT_KEY = 'expo_updates' ;
10
+
7
11
/** Load device context from expo modules. */
8
12
export 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
+
9
59
return {
10
60
name : INTEGRATION_NAME ,
11
- setupOnce : ( ) => {
12
- // noop
13
- } ,
61
+ setup,
14
62
processEvent,
15
63
} ;
16
64
} ;
17
65
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
+
19
110
const expoDeviceContext = getExpoDeviceContext ( ) ;
20
111
if ( expoDeviceContext ) {
21
112
event . contexts = event . contexts || { } ;
@@ -27,8 +118,6 @@ function processEvent(event: Event): Event {
27
118
event . contexts = event . contexts || { } ;
28
119
event . contexts . os = { ...expoOsContext , ...event . contexts . os } ;
29
120
}
30
-
31
- return event ;
32
121
}
33
122
34
123
/**
@@ -66,3 +155,17 @@ function getExpoOsContext(): OsContext | undefined {
66
155
name : expoDevice . osName ,
67
156
} ;
68
157
}
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