@@ -50,26 +50,40 @@ + (NSRegularExpression *)frameRegex {
5050 NSRange searchedRange = NSMakeRange (0 , [line length ]);
5151 NSArray *matches = [[RNSentry frameRegex ] matchesInString: line options: 0 range: searchedRange];
5252 for (NSTextCheckingResult *match in matches) {
53- NSString *matchText = [line substringWithRange: [match range ]];
5453 [frames addObject: @{
5554 @" methodName" : [line substringWithRange: [match rangeAtIndex: 1 ]],
5655 @" column" : [formatter numberFromString: [line substringWithRange: [match rangeAtIndex: 4 ]]],
57- @" lineNumber" : [formatter numberFromString: [line substringWithRange: [match rangeAtIndex: 3 ]]],
56+ @" lineNumber" : [formatter numberFromString: [line substringWithRange: [match rangeAtIndex: 3 ]]],
5857 @" file" : [line substringWithRange: [match rangeAtIndex: 2 ]]
5958 }];
6059 }
6160 }
6261 return frames;
6362}
6463
64+ NSArray *SentryParseRavenFrames (NSArray *ravenFrames) {
65+ NSNumberFormatter *formatter = [RNSentry numberFormatter ];
66+ NSMutableArray *frames = [NSMutableArray array ];
67+ for (NSDictionary *ravenFrame in ravenFrames) {
68+ if (ravenFrame[@" lineno" ] != NSNull .null ) {
69+ [frames addObject: @{
70+ @" methodName" : ravenFrame[@" function" ],
71+ @" column" : [formatter numberFromString: [NSString stringWithFormat: @" %@ " , ravenFrame[@" colno" ]]],
72+ @" lineNumber" : [formatter numberFromString: [NSString stringWithFormat: @" %@ " , ravenFrame[@" lineno" ]]],
73+ @" file" : ravenFrame[@" filename" ]
74+ }];
75+ }
76+ }
77+ return frames;
78+ }
79+
6580RCT_EXPORT_MODULE ()
6681
6782- (NSDictionary <NSString *, id > *)constantsToExport
6883{
6984 return @{@" nativeClientAvailable" : @YES };
7085}
7186
72-
7387RCT_EXPORT_METHOD (startWithDsnString:(NSString * _Nonnull)dsnString)
7488{
7589 [SentryClient setShared: [[SentryClient alloc ] initWithDsnString: dsnString]];
@@ -109,24 +123,26 @@ + (NSRegularExpression *)frameRegex {
109123 resolve (@YES );
110124}
111125
112- RCT_EXPORT_METHOD (captureMessage:( NSString * _Nonnull)message level:( int )level )
126+ RCT_EXPORT_METHOD (clearContext )
113127{
114- [[SentryClient shared ] captureMessage: message level: level];
128+ [SentryClient shared ].tags = @{};
129+ [SentryClient shared ].extra = @{};
130+ [SentryClient shared ].user = nil ;
115131}
116132
117133RCT_EXPORT_METHOD (setLogLevel:(int )level)
118134{
119135 [SentryClient setLogLevel: level];
120136}
121137
122- RCT_EXPORT_METHOD (setExtras :(NSDictionary * _Nonnull)extras )
138+ RCT_EXPORT_METHOD (setTags :(NSDictionary * _Nonnull)tags )
123139{
124- [SentryClient shared ].extra = extras ;
140+ [SentryClient shared ].tags = [ self sanitizeDictionary: tags] ;
125141}
126142
127- RCT_EXPORT_METHOD (setTags :(NSDictionary * _Nonnull)tags )
143+ RCT_EXPORT_METHOD (setExtra :(NSDictionary * _Nonnull)extra )
128144{
129- [SentryClient shared ].tags = [ self sanitizeDictionary: tags] ;
145+ [SentryClient shared ].extra = extra ;
130146}
131147
132148RCT_EXPORT_METHOD (setUser:(NSDictionary * _Nonnull)user)
@@ -137,11 +153,76 @@ + (NSRegularExpression *)frameRegex {
137153 extra: [RCTConvert NSDictionary: user[@" extra" ]]];
138154}
139155
156+ RCT_EXPORT_METHOD (captureBreadcrumb:(NSDictionary * _Nonnull)breadcrumb)
157+ {
158+ SentryBreadcrumb *crumb = [[SentryBreadcrumb alloc ] initWithCategory: breadcrumb[@" category" ]
159+ timestamp: [NSDate dateWithTimeIntervalSince1970: [breadcrumb[@" timestamp" ] integerValue ]]
160+ message: breadcrumb[@" message" ]
161+ type: nil
162+ level: [self sentrySeverityFromLevel: [breadcrumb[@" level" ] integerValue ]]
163+ data: nil ];
164+ [[SentryClient shared ].breadcrumbs add: crumb];
165+ }
166+
167+ RCT_EXPORT_METHOD (captureEvent:(NSDictionary * _Nonnull)event)
168+ {
169+ SentrySeverity level = [self sentrySeverityFromLevel: [event[@" level" ] integerValue ]];
170+
171+ SentryUser *user = nil ;
172+ if (event[@" user" ] != nil ) {
173+ user = [[SentryUser alloc ] initWithId: [RCTConvert NSString: event[@" user" ][@" userID" ]]
174+ email: [RCTConvert NSString: event[@" user" ][@" email" ]]
175+ username: [RCTConvert NSString: event[@" user" ][@" username" ]]
176+ extra: [RCTConvert NSDictionary: event[@" user" ][@" extra" ]]];
177+ }
178+
179+ if (event[@" message" ]) {
180+ SentryEvent *sentryEvent = [[SentryEvent alloc ] init: event[@" message" ]
181+ timestamp: [NSDate date ]
182+ level: level
183+ logger: event[@" logger" ]
184+ culprit: nil
185+ serverName: nil
186+ release: nil
187+ buildNumber: nil
188+ tags: [self sanitizeDictionary: event[@" tags" ]]
189+ modules: nil
190+ extra: event[@" extra" ]
191+ fingerprint: nil
192+ user: user
193+ exceptions: nil
194+ stacktrace: nil ];
195+ [[SentryClient shared ] captureEvent: sentryEvent];
196+ } else if (event[@" exception" ]) {
197+ // TODO what do we do here with extra/tags/users that are not global?
198+ [self handleSoftJSExceptionWithMessage: [NSString stringWithFormat: @" Unhandled JS Exception: %@ " , event[@" exception" ][@" values" ][0 ][@" value" ]]
199+ stack: SentryParseRavenFrames (event[@" exception" ][@" values" ][0 ][@" stacktrace" ][@" frames" ])
200+ exceptionId: @99 ];
201+ }
202+
203+ }
204+
140205RCT_EXPORT_METHOD (crash)
141206{
142207 [[SentryClient shared ] crash ];
143208}
144209
210+ - (SentrySeverity)sentrySeverityFromLevel : (NSInteger )level {
211+ switch (level) {
212+ case 0 :
213+ return SentrySeverityFatal;
214+ case 2 :
215+ return SentrySeverityWarning;
216+ case 3 :
217+ return SentrySeverityInfo;
218+ case 4 :
219+ return SentrySeverityDebug;
220+ default :
221+ return SentrySeverityError;
222+ }
223+ return level;
224+ }
225+
145226- (NSDictionary *)sanitizeDictionary : (NSDictionary *)dictionary {
146227 NSMutableDictionary *dict = [NSMutableDictionary dictionary ];
147228 for (NSString *key in dictionary.allKeys ) {
0 commit comments