61 |
62 |
63 | ### Installation:
64 |
65 | `yarn add react-native-exception-handler`
66 |
67 | or
68 |
69 | `npm i react-native-exception-handler --save`
70 |
71 | ### Mostly automatic installation
72 |
73 | `react-native link react-native-exception-handler`
74 |
75 | ### For react-native@0.60.0 or above
76 |
77 | As [react-native@0.60.0](https://reactnative.dev/blog/2019/07/03/version-60) or above supports autolinking, so there is no need to run linking process.
78 | Read more about autolinking [here](https://github.com/react-native-picker/cli/blob/master/docs/autolinking.md).
79 |
80 | ### Manual installation
81 |
82 | #### iOS
83 |
84 | 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]`
85 | 2. Go to `node_modules` ➜ `react-native-exception-handler` and add `ReactNativeExceptionHandler.xcodeproj`
86 | 3. In XCode, in the project navigator, select your project. Add `libReactNativeExceptionHandler.a` to your project's `Build Phases` ➜ `Link Binary With Libraries`
87 | 4. Run your project (`Cmd+R`)<
88 |
89 | ##### Using Cocoapods
90 |
91 | 1. add `pod 'ReactNativeExceptionHandler', :podspec => '../node_modules/react-native-exception-handler/ReactNativeExceptionHandler.podspec'` to your Podfile
92 | 2. run `pod install`
93 |
94 | #### Android
95 |
96 | 1. Open up `android/app/src/main/java/[...]/MainApplication.java`
97 |
98 | - Add `import com.masteratul.exceptionhandler.ReactNativeExceptionHandlerPackage;` to the imports at the top of the file
99 | - Add `new ReactNativeExceptionHandlerPackage()` to the list returned by the `getPackages()` method
100 |
101 | 2. Append the following lines to `android/settings.gradle`:
102 | ```
103 | include ':react-native-exception-handler'
104 | project(':react-native-exception-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-exception-handler/android')
105 | ```
106 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`:
107 | ```
108 | compile project(':react-native-exception-handler')
109 | ```
110 |
111 | ### PLEASE READ BEFORE GOING TO USAGE SECTION
112 |
113 | Lets introduce you to the type of errors in a RN app.
114 |
115 | - Errors produced by your Javascript code (includes all your react code). We will refer to these errors as **JS_Exceptions** going forward.
116 |
117 | - Errors produced by Native Modules. We will refer to these as **Native_Exceptions** going forward.
118 |
119 | Unhandled exceptions leave the app in a critical state.
120 |
121 | In case of **JS_Exceptions** you can catch these unhandled exceptions and perform tasks like show alerts or popups, do cleanup or even hit an API to inform the dev teams before closing the app.
122 |
123 | In case of **Native_Exceptions** it becomes much worse. While you can catch these unhandled exceptions and perform tasks like cleanup or logout or even hit an API to inform the dev teams before closing the app,
124 | you CANNOT show a JS alert box or do any UI stuff via JS code. This has to be done via the native methods provided by this module in the respective NATIVE codebase for iOS and android. The module does provide default handlers though :P. So you will get default popups incase of errors. Obviously you can customise them. See CUSTOMIZATION section.
125 |
126 | ### Usage
127 |
128 | To catch **JS_Exceptions**
129 |
130 | ```js
131 | import {setJSExceptionHandler, getJSExceptionHandler} from 'react-native-exception-handler';
132 |
133 | .
134 | .
135 | // For most use cases:
136 | // registering the error handler (maybe u can do this in the index.android.js or index.ios.js)
137 | setJSExceptionHandler((error, isFatal) => {
138 | // This is your custom global error handler
139 | // You do stuff like show an error dialog
140 | // or hit google analytics to track crashes
141 | // or hit a custom api to inform the dev team.
142 | });
143 | //=================================================
144 | // ADVANCED use case:
145 | const exceptionhandler = (error, isFatal) => {
146 | // your error handler function
147 | };
148 | setJSExceptionHandler(exceptionhandler, allowInDevMode);
149 | // - exceptionhandler is the exception handler function
150 | // - allowInDevMode is an optional parameter is a boolean.
151 | // If set to true the handler to be called in place of RED screen
152 | // in development mode also.
153 |
154 | // getJSExceptionHandler gives the currently set JS exception handler
155 | const currentHandler = getJSExceptionHandler();
156 | ```
157 |
158 | To catch **Native_Exceptions**
159 |
160 | ```js
161 | import { setNativeExceptionHandler } from "react-native-exception-handler";
162 |
163 | //For most use cases:
164 | setNativeExceptionHandler((exceptionString) => {
165 | // This is your custom global error handler
166 | // You do stuff likehit google analytics to track crashes.
167 | // or hit a custom api to inform the dev team.
168 | //NOTE: alert or showing any UI change via JS
169 | //WILL NOT WORK in case of NATIVE ERRORS.
170 | });
171 | //====================================================
172 | // ADVANCED use case:
173 | const exceptionhandler = (exceptionString) => {
174 | // your exception handler code here
175 | };
176 | setNativeExceptionHandler(
177 | exceptionhandler,
178 | forceAppQuit,
179 | executeDefaultHandler
180 | );
181 | // - exceptionhandler is the exception handler function
182 | // - forceAppQuit is an optional ANDROID specific parameter that defines
183 | // if the app should be force quit on error. default value is true.
184 | // To see usecase check the common issues section.
185 | // - executeDefaultHandler is an optional boolean (both IOS, ANDROID)
186 | // It executes previous exception handlers if set by some other module.
187 | // It will come handy when you use any other crash analytics module along with this one
188 | // Default value is set to false. Set to true if you are using other analytics modules.
189 | ```
190 |
191 | It is recommended you set both the handlers.
192 | **NOTE: `setNativeExceptionHandler` only works in bundled mode - it will show the red screen when applied to dev mode.**
193 |
194 | **See the examples to know more**
195 |
196 | ### CUSTOMIZATION
197 |
198 | #### Customizing **setJSExceptionHandler**.
199 |
200 | In case of `setJSExceptionHandler` you can do everything that is possible. Hence there is not much to customize here.
201 |
202 | ```js
203 | const errorHandler = (error, isFatal) => {
204 | // This is your custom global error handler
205 | // You do stuff like show an error dialog
206 | // or hit google analytics to track crashes
207 | // or hit a custom api to inform the dev team.
208 | })
209 | //Second argument is a boolean with a default value of false if unspecified.
210 | //If set to true the handler to be called in place of RED screen
211 | //in development mode also.
212 | setJSExceptionHandler(errorHandler, true);
213 | ```
214 |
215 | #### Customizing **setNativeExceptionHandler**
216 |
217 | By default whenever a **Native_Exceptions** occurs if you have used `setNativeExceptionHandler`, **along with the callback specified** you would see a popup (this is the default native handler set by this module).
218 |
219 | In Android and iOS you will see something like
220 |
221 |
222 |
223 |
224 |
225 |
226 | **Modifying Android Native Exception handler (RECOMMENDED APPROACH)**
227 |
228 | (NATIVE CODE HAS TO BE WRITTEN) _recommended that you do this in android studio_
229 |
230 | - In the `android/app/src/main/java/[...]/MainApplication.java`
231 |
232 | ```java
233 | import com.masteratul.exceptionhandler.ReactNativeExceptionHandlerModule;
234 | import com.masteratul.exceptionhandler.NativeExceptionHandlerIfc
235 | ...
236 | ...
237 | ...
238 | public class MainApplication extends Application implements ReactApplication {
239 | ...
240 | ...
241 | @Override
242 | public void onCreate() {
243 | ....
244 | ....
245 | ....
246 | ReactNativeExceptionHandlerModule.setNativeExceptionHandler(new NativeExceptionHandlerIfc() {
247 | @Override
248 | public void handleNativeException(Thread thread, Throwable throwable, Thread.UncaughtExceptionHandler originalHandler) {
249 | // Put your error handling code here
250 | }
251 | });//This will override the default behaviour of displaying the recover activity.
252 | }
253 | ```
254 |
255 | **Modifying Android Native Exception handler UI (CUSTOM ACTIVITY APPROACH (OLD APPROACH).. LEAVING FOR BACKWARD COMPATIBILITY)**
256 |
257 | (NATIVE CODE HAS TO BE WRITTEN) _recommended that you do this in android studio_
258 |
259 | - Create an Empty Activity in the `android/app/src/main/java/[...]/`. For example lets say CustomErrorDialog.java
260 | - Customize your activity to look and behave however you need it to be.
261 | - In the `android/app/src/main/java/[...]/MainApplication.java`
262 |
263 | ```java
264 | import com.masteratul.exceptionhandler.ReactNativeExceptionHandlerModule;
265 | import .YourCustomActivity; //This is your CustomErrorDialog.java
266 | ...
267 | ...
268 | ...
269 | public class MainApplication extends Application implements ReactApplication {
270 | ...
271 | ...
272 | @Override
273 | public void onCreate() {
274 | ....
275 | ....
276 | ....
277 | ReactNativeExceptionHandlerModule.replaceErrorScreenActivityClass(YourCustomActivity.class); //This will replace the native error handler popup with your own custom activity.
278 | }
279 | ```
280 |
281 | **Modifying iOS Native Exception handler UI** (NATIVE CODE HAS TO BE WRITTEN) _recommended that you do this in XCode_
282 |
283 | Unlike Android, in the case of iOS, there is no way to restart the app if it has crashed. Also, during a **Native_Exceptions** the UI becomes quite unstable since the exception occured on the main UI thread. Hence, none of the click or press handlers would work either.
284 |
285 | Keeping in mind of these, at the most we can just show the user a dialog and inform the user to reopen the app.
286 |
287 | If you noticed the default native exception popup does exactly that. To customize the UI for the popup.
288 |
289 | - In XCode, open the file `AppDelegate.m`
290 |
291 | ```c
292 | #import "AppDelegate.h"
293 |
294 | #import
295 | #import
296 |
297 | //Add the header file
298 | #import "ReactNativeExceptionHandler.h"
299 | ...
300 | ...
301 | @implementation AppDelegate
302 |
303 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
304 | {
305 | ...
306 | ...
307 |
308 | [ReactNativeExceptionHandler replaceNativeExceptionHandlerBlock:^(NSException *exception, NSString *readeableException){
309 |
310 | // THE CODE YOU WRITE HERE WILL REPLACE THE EXISTING NATIVE POPUP THAT COMES WITH THIS MODULE.
311 | //We create an alert box
312 | UIAlertController* alert = [UIAlertController
313 | alertControllerWithTitle:@"Critical error occurred"
314 | message: [NSString stringWithFormat:@"%@\n%@",
315 | @"Apologies..The app will close now \nPlease restart the app\n",
316 | readeableException]
317 | preferredStyle:UIAlertControllerStyleAlert];
318 |
319 | // We show the alert box using the rootViewController
320 | [rootViewController presentViewController:alert animated:YES completion:nil];
321 |
322 | // THIS IS THE IMPORTANT PART
323 | // By default when an exception is raised we will show an alert box as per our code.
324 | // But since our buttons wont work because our click handlers wont work.
325 | // to close the app or to remove the UI lockup on exception.
326 | // we need to call this method
327 | // [ReactNativeExceptionHandler releaseExceptionHold]; // to release the lock and let the app crash.
328 |
329 | // Hence we set a timer of 4 secs and then call the method releaseExceptionHold to quit the app after
330 | // 4 secs of showing the popup
331 | [NSTimer scheduledTimerWithTimeInterval:4.0
332 | target:[ReactNativeExceptionHandler class]
333 | selector:@selector(releaseExceptionHold)
334 | userInfo:nil
335 | repeats:NO];
336 |
337 | // or you can call
338 | // [ReactNativeExceptionHandler releaseExceptionHold]; when you are done to release the UI lock.
339 | }];
340 |
341 | ...
342 | ...
343 | ...
344 |
345 | return YES;
346 | }
347 |
348 | @end
349 | ```
350 |
351 | What is this `[ReactNativeExceptionHandler releaseExceptionHold];`?
352 |
353 | In case of iOS we lock the UI thread after we show our popup to prevent the app from closing.
354 | Hence once we are done showing the popup we need to close our app after some time.
355 | But since our buttons wont work as our click handlers wont work (explained before).
356 | To close the app or to remove the UI lockup on exception, we need to call this method
357 | `[ReactNativeExceptionHandler releaseExceptionHold];`
358 |
359 | Hence we set a timer of 4 secs and then call the method releaseExceptionHold to quit the app after
360 | 4 secs of showing the popup
361 |
362 | ```c
363 | [NSTimer scheduledTimerWithTimeInterval:4.0
364 | target:[ReactNativeExceptionHandler class]
365 | selector:@selector(releaseExceptionHold)
366 | userInfo:nil
367 | repeats:NO];
368 | ```
369 |
370 | ### Examples
371 |
372 | ##### Restart on error example
373 |
374 | This example shows how to use this module show a graceful bug dialog to the user on crash and restart the app when the user presses ok !
375 |
376 | ```js
377 | import {Alert} from 'react-native';
378 | import RNRestart from 'react-native-restart';
379 | import {setJSExceptionHandler} from 'react-native-exception-handler';
380 |
381 | const errorHandler = (e, isFatal) => {
382 | if (isFatal) {
383 | Alert.alert(
384 | 'Unexpected error occurred',
385 | `
386 | Error: ${(isFatal) ? 'Fatal:' : ''} ${e.name} ${e.message}
387 |
388 | We will need to restart the app.
389 | `,
390 | [{
391 | text: 'Restart',
392 | onPress: () => {
393 | RNRestart.Restart();
394 | }
395 | }]
396 | );
397 | } else {
398 | console.log(e); // So that we can see it in the ADB logs in case of Android if needed
399 | }
400 | };
401 |
402 | setJSExceptionHandler(errorHandler);
403 |
404 | setNativeExceptionHandler((errorString) => {
405 | //You can do something like call an api to report to dev team here
406 | ...
407 | ...
408 | // When you call setNativeExceptionHandler, react-native-exception-handler sets a
409 | // Native Exception Handler popup which supports restart on error in case of android.
410 | // In case of iOS, it is not possible to restart the app programmatically, so we just show an error popup and close the app.
411 | // To customize the popup screen take a look at CUSTOMIZATION section.
412 | });
413 | ```
414 |
415 | #### Bug Capture to dev team example
416 |
417 | This example shows how to use this module to send global errors to the dev team and show a graceful bug dialog to the user on crash !
418 |
419 | ```js
420 | import { Alert } from "react-native";
421 | import { BackAndroid } from "react-native";
422 | import { setJSExceptionHandler } from "react-native-exception-handler";
423 |
424 | const reporter = (error) => {
425 | // Logic for reporting to devs
426 | // Example : Log issues to github issues using github apis.
427 | console.log(error); // sample
428 | };
429 |
430 | const errorHandler = (e, isFatal) => {
431 | if (isFatal) {
432 | reporter(e);
433 | Alert.alert(
434 | "Unexpected error occurred",
435 | `
436 | Error: ${isFatal ? "Fatal:" : ""} ${e.name} ${e.message}
437 |
438 | We have reported this to our team ! Please close the app and start again!
439 | `,
440 | [
441 | {
442 | text: "Close",
443 | onPress: () => {
444 | BackAndroid.exitApp();
445 | },
446 | },
447 | ]
448 | );
449 | } else {
450 | console.log(e); // So that we can see it in the ADB logs in case of Android if needed
451 | }
452 | };
453 |
454 | setJSExceptionHandler(errorHandler);
455 |
456 | setNativeExceptionHandler((errorString) => {
457 | //You can do something like call an api to report to dev team here
458 | //example
459 | // fetch('http://?error='+errorString);
460 | //
461 | });
462 | ```
463 |
464 | _More Examples can be found in the examples folder_
465 |
466 | - Preserving old handler (thanks to zeh)
467 |
468 | # Known issues and fixes:
469 |
470 | ### react-native-navigation (Wix)
471 |
472 | This is specifically occuring when you use [wix library](http://wix.github.io/react-native-navigation/) for navigation along with react-native-exception-handler. Whenever an error occurs, it will recreate the application above the crash screen.
473 |
474 | **Fix:**
475 |
476 | You need to set second parametera as _false_ while calling _setNativeExceptionHandler_.
477 | The second parameter is an android specific field which stands for forceQuitOnError.
478 | When set to false it doesnt quit the app forcefully on error. In short :
479 |
480 | Credit goes to **Gustavo Fão Valvassori**
481 |
482 | ```js
483 | setNativeExceptionHandler(nativeErrorCallback, false);
484 | ```
485 |
486 | ### Previously defined exception handlers are not executed anymore
487 |
488 | A lot of frameworks (especially analytics sdk's) implement global exception handlers. In order to keep these frameworks working while using react-native-exception-hanlder, you can pass a boolean value as third argument to `setNativeExceptionHandler(..., ..., true`) what will trigger the execution of the last global handler registered.
489 |
490 | ## CONTRIBUTORS
491 |
492 | - [Atul R](https://github.com/master-atul)
493 | - [Zeh Fernando](https://github.com/zeh)
494 | - [Fred Chasen](https://github.com/fchasen)
495 | - [Christoph Jerolimov](https://github.com/jerolimov)
496 | - [Peter Chow](https://github.com/peteroid)
497 | - [Gustavo Fão Valvassori](https://github.com/faogustavo)
498 | - [Alessandro Agosto](https://github.com/lexor90)
499 | - [robinxb](https://github.com/robinxb)
500 | - [Gant Laborde](https://github.com/GantMan)
501 | - [Himanshu Singh](https://github.com/himanshusingh2407)
502 | - [Paulus Esterhazy](https://github.com/pesterhazy)
503 | - [TomMahle](https://github.com/TomMahle)
504 | - [Sébastien Krafft](https://github.com/skrafft)
505 | - [Mark Friedman](https://github.com/mark-friedman)
506 | - [Damien Solimando](https://github.com/dsolimando)
507 | - [Jens Kuhr Jørgensen](https://github.com/jenskuhrjorgensen)
508 | - [Szabó Zsolt](https://github.com/alexovits)
509 | - [Andrew Vyazovoy](https://github.com/Vyazovoy)
510 | - [Pierre Segalen](https://github.com/psegalen)
511 | - [Denis Slávik](https://github.com/slavikdenis)
512 |
513 | ## TESTING NATIVE EXCEPTIONS/ERRORS
514 |
515 | To make sure this module works. You can generate a native exception using the module `rn-test-exception-handler`.
516 | [https://github.com/master-atul/rn-test-exception-handler](https://github.com/master-atul/rn-test-exception-handler)
517 |
518 | `rn-test-exception-handler` module does only one thing. It raises a **Native_Exceptions**.
519 | This will help you to verify your customizations or functionality of this module.
520 |
521 | Peace ! ✌🏻🍻
522 |
--------------------------------------------------------------------------------
/ReactNativeExceptionHandler.podspec:
--------------------------------------------------------------------------------
1 | require 'json'
2 |
3 | # Returns the version number for a package.json file
4 | pkg_version = lambda do |dir_from_root = '', version = 'version'|
5 | path = File.join(__dir__, dir_from_root, 'package.json')
6 | JSON.parse(File.read(path))[version]
7 | end
8 |
9 | # Let the main package.json decide the version number for the pod
10 | package_version = pkg_version.call
11 |
12 | Pod::Spec.new do |s|
13 | s.name = "ReactNativeExceptionHandler"
14 | s.version = package_version
15 | s.summary = "A react native module that lets you to register a global error handler that can capture fatal/non fatal uncaught exceptions"
16 | s.description = <<-DESC
17 | A react native module that lets you to register a global error handler that can capture fatal/non fatal uncaught exceptions.
18 | The module helps prevent abrupt crashing of RN Apps without a graceful message to the user.
19 | DESC
20 | s.homepage = "https://github.com/master-atul/react-native-exception-handler"
21 | s.license = "MIT"
22 | s.author = { "Atul R" => "atulanand94@gmail.com" }
23 | s.platform = :ios, "9.0"
24 | s.source = { :git => "https://github.com/master-atul/react-native-exception-handler.git", :tag => s.version.to_s }
25 | s.source_files = "ios/*.{h,m}"
26 |
27 | s.dependency "React-Core"
28 |
29 | end
30 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 |
2 | buildscript {
3 | repositories {
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 |
9 | }
10 | }
11 |
12 | apply plugin: 'com.android.library'
13 |
14 |
15 |
16 | def getExtValue(rootProject,key,defaultValue ) {
17 | if (rootProject.hasProperty('ext')) {
18 | if (rootProject.ext.has(key)) {
19 | return rootProject.ext[key]
20 | }
21 | }
22 | return defaultValue
23 | }
24 |
25 | android {
26 | compileSdkVersion getExtValue(rootProject,'compileSdkVersion',23)
27 | buildToolsVersion getExtValue(rootProject,'buildToolsVersion', "23.0.1")
28 |
29 | defaultConfig {
30 | minSdkVersion getExtValue(rootProject,'minSdkVersion', 16)
31 | targetSdkVersion getExtValue(rootProject,'targetSdkVersion', 22)
32 | versionCode 1
33 | versionName "1.0"
34 | }
35 | lintOptions {
36 | abortOnError false
37 | }
38 | }
39 |
40 | repositories {
41 | mavenCentral()
42 | }
43 |
44 | dependencies {
45 | implementation 'com.facebook.react:react-native:+'
46 | }
47 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/android/src/main/java/com/masteratul/exceptionhandler/DefaultErrorScreen.java:
--------------------------------------------------------------------------------
1 | package com.masteratul.exceptionhandler;
2 |
3 | import android.app.Activity;
4 | import android.app.AlarmManager;
5 | import android.app.PendingIntent;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.content.pm.PackageManager;
9 | import android.os.Bundle;
10 | import android.util.Log;
11 | import android.view.View;
12 | import android.widget.Button;
13 | import android.widget.TextView;
14 |
15 | public class DefaultErrorScreen extends Activity {
16 | private static String TAG = "RN_ERROR_HANDLER";
17 | private Button quitButton;
18 | private Button relaunchButton;
19 | private Button showDetailsButton;
20 | private TextView stackTraceView;
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | String stackTraceString = "StackTrace unavailable";
26 | try {
27 | stackTraceString = getIntent().getExtras().getString("stack_trace_string");
28 | }
29 | catch (Exception e) {
30 | Log.e(TAG, String.format("Was not able to get StackTrace: %s", e.getMessage()));
31 | }
32 | setContentView(R.layout.default_error_screen);
33 | quitButton = (Button) findViewById(R.id.eh_quit_button);
34 | relaunchButton = (Button) findViewById(R.id.eh_restart_button);
35 | showDetailsButton = (Button) findViewById(R.id.eh_show_details_button);
36 | stackTraceView = (TextView) findViewById(R.id.eh_stack_trace_text_view);
37 | stackTraceView.setText(stackTraceString);
38 |
39 | showDetailsButton.setOnClickListener(new View.OnClickListener() {
40 | @Override
41 | public void onClick(View view) {
42 | int stackTraceViewVisibility = stackTraceView.getVisibility();
43 | if(stackTraceViewVisibility == View.VISIBLE){
44 | stackTraceView.setVisibility(View.GONE);
45 | showDetailsButton.setText("SHOW DETAILS");
46 | }else{
47 | stackTraceView.setVisibility(View.VISIBLE);
48 | showDetailsButton.setText("HIDE DETAILS");
49 | }
50 | }
51 | });
52 |
53 | relaunchButton.setOnClickListener(new View.OnClickListener() {
54 | @Override
55 | public void onClick(View view) {
56 | doRestart(getApplicationContext());
57 | }
58 | });
59 |
60 | quitButton.setOnClickListener(new View.OnClickListener() {
61 | @Override
62 | public void onClick(View view) {
63 | System.exit(0);
64 | }
65 | });
66 | }
67 |
68 | public static void doRestart(Context c) {
69 | try {
70 | if (c != null) {
71 | PackageManager pm = c.getPackageManager();
72 | if (pm != null) {
73 | Intent mStartActivity = pm.getLaunchIntentForPackage(
74 | c.getPackageName()
75 | );
76 | if (mStartActivity != null) {
77 | mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
78 | int mPendingIntentId = 654311;
79 | PendingIntent mPendingIntent = PendingIntent
80 | .getActivity(c, mPendingIntentId, mStartActivity,
81 | PendingIntent.FLAG_CANCEL_CURRENT);
82 | AlarmManager mgr = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
83 | mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
84 | System.exit(0);
85 | } else {
86 | throw new Exception("Was not able to restart application, mStartActivity null");
87 | }
88 | } else {
89 | throw new Exception("Was not able to restart application, PM null");
90 | }
91 | } else {
92 | throw new Exception("Was not able to restart application, Context null");
93 | }
94 | } catch (Exception ex) {
95 | Log.e(TAG, "Was not able to restart application");
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/android/src/main/java/com/masteratul/exceptionhandler/NativeExceptionHandlerIfc.java:
--------------------------------------------------------------------------------
1 | package com.masteratul.exceptionhandler;
2 |
3 | public interface NativeExceptionHandlerIfc {
4 | void handleNativeException(Thread thread, Throwable throwable, Thread.UncaughtExceptionHandler originalHandler);
5 | }
6 |
--------------------------------------------------------------------------------
/android/src/main/java/com/masteratul/exceptionhandler/ReactNativeExceptionHandlerModule.java:
--------------------------------------------------------------------------------
1 |
2 | package com.masteratul.exceptionhandler;
3 |
4 | import android.app.Activity;
5 | import android.content.Intent;
6 | import android.util.Log;
7 |
8 | import com.facebook.react.bridge.Callback;
9 | import com.facebook.react.bridge.ReactApplicationContext;
10 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
11 | import com.facebook.react.bridge.ReactMethod;
12 |
13 | public class ReactNativeExceptionHandlerModule extends ReactContextBaseJavaModule {
14 |
15 | private ReactApplicationContext reactContext;
16 | private Activity activity;
17 | private static Class errorIntentTargetClass = DefaultErrorScreen.class;
18 | private static NativeExceptionHandlerIfc nativeExceptionHandler;
19 | private Callback callbackHolder;
20 | private Thread.UncaughtExceptionHandler originalHandler;
21 |
22 | public ReactNativeExceptionHandlerModule(ReactApplicationContext reactContext) {
23 | super(reactContext);
24 | this.reactContext = reactContext;
25 | }
26 |
27 | @Override
28 | public String getName() {
29 | return "ReactNativeExceptionHandler";
30 | }
31 |
32 |
33 | @ReactMethod
34 | public void setHandlerforNativeException(
35 | final boolean executeOriginalUncaughtExceptionHandler,
36 | final boolean forceToQuit,
37 | Callback customHandler) {
38 |
39 | callbackHolder = customHandler;
40 | originalHandler = Thread.getDefaultUncaughtExceptionHandler();
41 |
42 | Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
43 |
44 | @Override
45 | public void uncaughtException(Thread thread, Throwable throwable) {
46 |
47 | String stackTraceString = Log.getStackTraceString(throwable);
48 | callbackHolder.invoke(stackTraceString);
49 |
50 | if (nativeExceptionHandler != null) {
51 | nativeExceptionHandler.handleNativeException(thread, throwable, originalHandler);
52 | } else {
53 | activity = getCurrentActivity();
54 |
55 | Intent i = new Intent();
56 | i.setClass(activity, errorIntentTargetClass);
57 | i.putExtra("stack_trace_string",stackTraceString);
58 | i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
59 |
60 | activity.startActivity(i);
61 | activity.finish();
62 |
63 | if (executeOriginalUncaughtExceptionHandler && originalHandler != null) {
64 | originalHandler.uncaughtException(thread, throwable);
65 | }
66 |
67 | if (forceToQuit) {
68 | System.exit(0);
69 | }
70 | }
71 | }
72 | });
73 | }
74 |
75 | public static void replaceErrorScreenActivityClass(Class errorScreenActivityClass){
76 | errorIntentTargetClass = errorScreenActivityClass;
77 | }
78 |
79 | public static void setNativeExceptionHandler(NativeExceptionHandlerIfc nativeExceptionHandler) {
80 | ReactNativeExceptionHandlerModule.nativeExceptionHandler = nativeExceptionHandler;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/android/src/main/java/com/masteratul/exceptionhandler/ReactNativeExceptionHandlerPackage.java:
--------------------------------------------------------------------------------
1 |
2 | package com.masteratul.exceptionhandler;
3 |
4 | import java.util.Arrays;
5 | import java.util.Collections;
6 | import java.util.List;
7 |
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.bridge.NativeModule;
10 | import com.facebook.react.bridge.ReactApplicationContext;
11 | import com.facebook.react.uimanager.ViewManager;
12 | import com.facebook.react.bridge.JavaScriptModule;
13 | public class ReactNativeExceptionHandlerPackage implements ReactPackage {
14 | @Override
15 | public List createNativeModules(ReactApplicationContext reactContext) {
16 | return Arrays.asList(new ReactNativeExceptionHandlerModule(reactContext));
17 | }
18 |
19 | public List> createJSModules() {
20 | return Collections.emptyList();
21 | }
22 |
23 | @Override
24 | public List createViewManagers(ReactApplicationContext reactContext) {
25 | return Collections.emptyList();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/android/src/main/res/layout/default_error_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
15 |
24 |
33 |
34 |
42 |
47 |
53 |
59 |
60 |
69 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/android/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SHOW ERROR DETAILS
3 |
4 |
--------------------------------------------------------------------------------
/examples/bugCaptureOnError.js:
--------------------------------------------------------------------------------
1 | import {Alert} from 'react-native';
2 | import {BackAndroid} from 'react-native';
3 | import {setJSExceptionHandler} from 'react-native-exception-handler';
4 |
5 | const reporter = (error) => {
6 | // Logic for reporting to devs
7 | // Example : Log issues to github issues using github apis.
8 | console.log(error); // sample
9 | };
10 |
11 | const errorHandler = (e, isFatal) => {
12 | if (isFatal) {
13 | reporter(e);
14 | Alert.alert(
15 | 'Unexpected error occurred',
16 | `
17 | Error: ${(isFatal) ? 'Fatal:' : ''} ${e.name} ${e.message}
18 |
19 | We have reported this to our team ! Please close the app and start again!
20 | `,
21 | [{
22 | text: 'Close',
23 | onPress: () => {
24 | BackAndroid.exitApp();
25 | }
26 | }]
27 | );
28 | } else {
29 | console.log(e); // So that we can see it in the ADB logs in case of Android if needed
30 | }
31 | };
32 |
33 | setJSExceptionHandler(errorHandler);
34 |
--------------------------------------------------------------------------------
/examples/preservingOldHandler.js:
--------------------------------------------------------------------------------
1 | import {getJSExceptionHandler, setJSExceptionHandler} from 'react-native-exception-handler';
2 |
3 | const customErrorHandler = (error, isFatal) => {
4 | // Logic for reporting to devs
5 | // Example : Log issues to github issues using github apis.
6 | console.log(error, isFatal); // example
7 | };
8 |
9 | const previousErrorHandler = getJSExceptionHandler(); // by default u will get the red screen error handler here
10 |
11 | const errorHandler = (e, isFatal) => {
12 | customErrorHandler(e, isFatal);
13 | previousErrorHandler(e, isFatal);
14 | };
15 |
16 | // We will still see the error screen, but our customErrorHandler() function will be called
17 | setJSExceptionHandler(errorHandler);
18 |
--------------------------------------------------------------------------------
/examples/restartOnError.js:
--------------------------------------------------------------------------------
1 | import {Alert} from 'react-native';
2 | import RNRestart from 'react-native-restart';
3 | import {setJSExceptionHandler} from 'react-native-exception-handler';
4 |
5 | const errorHandler = (e, isFatal) => {
6 | if (isFatal) {
7 | Alert.alert(
8 | 'Unexpected error occurred',
9 | `
10 | Error: ${(isFatal) ? 'Fatal:' : ''} ${e.name} ${e.message}
11 |
12 | We will need to restart the app.
13 | `,
14 | [{
15 | text: 'Restart',
16 | onPress: () => {
17 | RNRestart.Restart();
18 | }
19 | }]
20 | );
21 | } else {
22 | console.log(e); // So that we can see it in the ADB logs in case of Android if needed
23 | }
24 | };
25 |
26 | setJSExceptionHandler(errorHandler);
27 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | export type JSExceptionHandler = (error: Error, isFatal: boolean) => void;
2 | export type NativeExceptionHandler = (exceptionMsg: string) => void;
3 |
4 | declare const getJSExceptionHandler: () => JSExceptionHandler;
5 |
6 | declare const setJSExceptionHandler: (handler: JSExceptionHandler, allowInDevMode?: boolean) => void;
7 |
8 | declare const setNativeExceptionHandler: (
9 | handler: NativeExceptionHandler,
10 | forceAppQuit?: boolean, // Android only
11 | executeDefaultHandler?: boolean,
12 | ) => void;
13 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import { NativeModules, Platform } from "react-native";
2 |
3 | const { ReactNativeExceptionHandler } = NativeModules;
4 |
5 | const noop = () => { };
6 |
7 | export const setJSExceptionHandler = (customHandler = noop, allowedInDevMode = false) => {
8 | if (typeof allowedInDevMode !== "boolean" || typeof customHandler !== "function") {
9 | console.log("setJSExceptionHandler is called with wrong argument types.. first argument should be callback function and second argument is optional should be a boolean");
10 | console.log("Not setting the JS handler .. please fix setJSExceptionHandler call");
11 | return;
12 | }
13 | const allowed = allowedInDevMode ? true : !__DEV__;
14 | if (allowed) {
15 | global.ErrorUtils.setGlobalHandler(customHandler);
16 | const consoleError = console.error;
17 | console.error = (...args) => {
18 | global.ErrorUtils.reportError(...args);
19 | consoleError(...args);
20 | };
21 | } else {
22 | console.log("Skipping setJSExceptionHandler: Reason: In DEV mode and allowedInDevMode = false");
23 | }
24 | };
25 |
26 | export const getJSExceptionHandler = () => global.ErrorUtils.getGlobalHandler();
27 |
28 | export const setNativeExceptionHandler = (customErrorHandler = noop, forceApplicationToQuit = true, executeDefaultHandler = false) => {
29 | if (typeof customErrorHandler !== "function" || typeof forceApplicationToQuit !== "boolean") {
30 | console.log("setNativeExceptionHandler is called with wrong argument types.. first argument should be callback function and second argument is optional should be a boolean");
31 | console.log("Not setting the native handler .. please fix setNativeExceptionHandler call");
32 | return;
33 | }
34 | if (Platform.OS === "ios") {
35 | ReactNativeExceptionHandler.setHandlerforNativeException(executeDefaultHandler, customErrorHandler);
36 | } else {
37 | ReactNativeExceptionHandler.setHandlerforNativeException(executeDefaultHandler, forceApplicationToQuit, customErrorHandler);
38 | }
39 | };
40 |
41 | export default {
42 | setJSExceptionHandler,
43 | getJSExceptionHandler,
44 | setNativeExceptionHandler
45 | };
46 |
--------------------------------------------------------------------------------
/ios/ReactNativeExceptionHandler.h:
--------------------------------------------------------------------------------
1 |
2 | #if __has_include()
3 | #import
4 | #else
5 | #import "RCTBridgeModule.h"
6 | #endif
7 |
8 | #import
9 | #include
10 | #include
11 |
12 | @interface ReactNativeExceptionHandler : NSObject
13 | + (void) replaceNativeExceptionHandlerBlock:(void (^)(NSException *exception, NSString *readeableException))nativeCallbackBlock;
14 | + (void) releaseExceptionHold;
15 | @end
16 |
17 |
18 |
--------------------------------------------------------------------------------
/ios/ReactNativeExceptionHandler.m:
--------------------------------------------------------------------------------
1 | #import "ReactNativeExceptionHandler.h"
2 |
3 |
4 | // CONSTANTS
5 | NSString * const RNUncaughtExceptionHandlerSignalExceptionName = @"RNUncaughtExceptionHandlerSignalExceptionName";
6 | NSString * const RNUncaughtExceptionHandlerSignalKey = @"RNUncaughtExceptionHandlerSignalKey";
7 | NSString * const RNUncaughtExceptionHandlerAddressesKey = @"RNUncaughtExceptionHandlerAddressesKey";
8 | volatile int32_t RNUncaughtExceptionCount = 0;
9 | const int32_t RNUncaughtExceptionMaximum = 10;
10 | const NSInteger RNUncaughtExceptionHandlerSkipAddressCount = 4;
11 | const NSInteger RNUncaughtExceptionHandlerReportAddressCount = 5;
12 |
13 |
14 | @implementation ReactNativeExceptionHandler
15 |
16 | - (dispatch_queue_t)methodQueue
17 | {
18 | return dispatch_get_main_queue();
19 | }
20 |
21 | // ======================
22 | // VARIABLE DECLARATIONS
23 | // ======================
24 |
25 | //variable which is used to track till when to keep the app running on exception.
26 | bool dismissApp = true;
27 |
28 | //variable to hold the custom error handler passed while customizing native handler
29 | void (^nativeErrorCallbackBlock)(NSException *exception, NSString *readeableException);
30 |
31 | // variable to hold the previously defined error handler
32 | NSUncaughtExceptionHandler* previousNativeErrorCallbackBlock;
33 |
34 | BOOL callPreviousNativeErrorCallbackBlock = false;
35 |
36 | //variable to hold the js error handler when setting up the error handler in RN.
37 | void (^jsErrorCallbackBlock)(NSException *exception, NSString *readeableException);
38 |
39 | //variable that holds the default native error handler
40 | void (^defaultNativeErrorCallbackBlock)(NSException *exception, NSString *readeableException) =
41 | ^(NSException *exception, NSString *readeableException){
42 |
43 | UIAlertController* alert = [UIAlertController
44 | alertControllerWithTitle:@"Unexpected error occured"
45 | message:[NSString stringWithFormat:@"%@\n%@",
46 | @"Apologies..The app will close now \nPlease restart the app\n",
47 | readeableException]
48 | preferredStyle:UIAlertControllerStyleAlert];
49 |
50 | UIApplication* app = [UIApplication sharedApplication];
51 | UIViewController * rootViewController = app.delegate.window.rootViewController;
52 | [rootViewController presentViewController:alert animated:YES completion:nil];
53 |
54 | [NSTimer scheduledTimerWithTimeInterval:5.0
55 | target:[ReactNativeExceptionHandler class]
56 | selector:@selector(releaseExceptionHold)
57 | userInfo:nil
58 | repeats:NO];
59 | };
60 |
61 | // ====================================
62 | // REACT NATIVE MODULE EXPOSED METHODS
63 | // ====================================
64 |
65 | RCT_EXPORT_MODULE();
66 |
67 | // METHOD TO INITIALIZE THE EXCEPTION HANDLER AND SET THE JS CALLBACK BLOCK
68 | RCT_EXPORT_METHOD(setHandlerforNativeException:(BOOL)callPreviouslyDefinedHandler withCallback: (RCTResponseSenderBlock)callback)
69 | {
70 | jsErrorCallbackBlock = ^(NSException *exception, NSString *readeableException){
71 | callback(@[readeableException]);
72 | };
73 |
74 | previousNativeErrorCallbackBlock = NSGetUncaughtExceptionHandler();
75 | callPreviousNativeErrorCallbackBlock = callPreviouslyDefinedHandler;
76 |
77 | NSSetUncaughtExceptionHandler(&HandleException);
78 | signal(SIGABRT, SignalHandler);
79 | signal(SIGILL, SignalHandler);
80 | signal(SIGSEGV, SignalHandler);
81 | signal(SIGFPE, SignalHandler);
82 | signal(SIGBUS, SignalHandler);
83 | //signal(SIGPIPE, SignalHandler);
84 | //Removing SIGPIPE as per https://github.com/master-atul/react-native-exception-handler/issues/32
85 | NSLog(@"REGISTERED RN EXCEPTION HANDLER");
86 | }
87 |
88 |
89 | // =====================================================
90 | // METHODS TO CUSTOMIZE THE DEFAULT NATIVE ERROR HANDLER
91 | // =====================================================
92 |
93 | + (void) replaceNativeExceptionHandlerBlock:(void (^)(NSException *exception, NSString *readeableException))nativeCallbackBlock{
94 | NSLog(@"SET THE CALLBACK HANDLER NATTTIVEEE");
95 | nativeErrorCallbackBlock = nativeCallbackBlock;
96 | }
97 |
98 | + (void) releaseExceptionHold {
99 | dismissApp = true;
100 | NSLog(@"RELEASING LOCKED RN EXCEPTION HANDLER");
101 | }
102 |
103 |
104 | // ================================================================
105 | // ACTUAL CUSTOM HANDLER called by the EXCEPTION AND SIGNAL HANDLER
106 | // WHICH KEEPS THE APP RUNNING ON EXCEPTION
107 | // ================================================================
108 |
109 | - (void)handleException:(NSException *)exception
110 | {
111 | NSString * readeableError = [NSString stringWithFormat:NSLocalizedString(@"%@\n%@", nil),
112 | [exception reason],
113 | [[exception userInfo] objectForKey:RNUncaughtExceptionHandlerAddressesKey]];
114 | dismissApp = false;
115 |
116 |
117 | if (callPreviousNativeErrorCallbackBlock && previousNativeErrorCallbackBlock) {
118 | previousNativeErrorCallbackBlock(exception);
119 | }
120 |
121 | if(nativeErrorCallbackBlock != nil){
122 | nativeErrorCallbackBlock(exception,readeableError);
123 | }else{
124 | defaultNativeErrorCallbackBlock(exception,readeableError);
125 | }
126 | jsErrorCallbackBlock(exception,readeableError);
127 |
128 | CFRunLoopRef runLoop = CFRunLoopGetCurrent();
129 | CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
130 | while (!dismissApp)
131 | {
132 | long count = CFArrayGetCount(allModes);
133 | long i = 0;
134 | while(i < count){
135 | NSString *mode = CFArrayGetValueAtIndex(allModes, i);
136 | if(![mode isEqualToString:@"kCFRunLoopCommonModes"]){
137 | CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
138 | }
139 | i++;
140 | }
141 | }
142 |
143 | CFRelease(allModes);
144 |
145 | NSSetUncaughtExceptionHandler(NULL);
146 | signal(SIGABRT, SIG_DFL);
147 | signal(SIGILL, SIG_DFL);
148 | signal(SIGSEGV, SIG_DFL);
149 | signal(SIGFPE, SIG_DFL);
150 | signal(SIGBUS, SIG_DFL);
151 | signal(SIGPIPE, SIG_DFL);
152 |
153 | kill(getpid(), [[[exception userInfo] objectForKey:RNUncaughtExceptionHandlerSignalKey] intValue]);
154 |
155 | }
156 |
157 |
158 | // ============================================================================
159 | // EXCEPTION AND SIGNAL HANDLERS to collect error and launch the custom handler
160 | // ============================================================================
161 |
162 | void HandleException(NSException *exception)
163 | {
164 | int32_t exceptionCount = OSAtomicIncrement32(&RNUncaughtExceptionCount);
165 | if (exceptionCount > RNUncaughtExceptionMaximum)
166 | {
167 | return;
168 | }
169 |
170 | NSArray *callStack = [ReactNativeExceptionHandler backtrace];
171 | NSMutableDictionary *userInfo =
172 | [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
173 | [userInfo
174 | setObject:callStack
175 | forKey:RNUncaughtExceptionHandlerAddressesKey];
176 |
177 | [[[ReactNativeExceptionHandler alloc] init]
178 | performSelectorOnMainThread:@selector(handleException:)
179 | withObject:
180 | [NSException
181 | exceptionWithName:[exception name]
182 | reason:[exception reason]
183 | userInfo:userInfo]
184 | waitUntilDone:YES];
185 | }
186 |
187 | void SignalHandler(int signal)
188 | {
189 | int32_t exceptionCount = OSAtomicIncrement32(&RNUncaughtExceptionCount);
190 | if (exceptionCount > RNUncaughtExceptionMaximum)
191 | {
192 | return;
193 | }
194 |
195 | NSMutableDictionary *userInfo =
196 | [NSMutableDictionary
197 | dictionaryWithObject:[NSNumber numberWithInt:signal]
198 | forKey:RNUncaughtExceptionHandlerSignalKey];
199 |
200 | NSArray *callStack = [ReactNativeExceptionHandler backtrace];
201 | [userInfo
202 | setObject:callStack
203 | forKey:RNUncaughtExceptionHandlerAddressesKey];
204 |
205 | [[[ReactNativeExceptionHandler alloc] init]
206 | performSelectorOnMainThread:@selector(handleException:)
207 | withObject:
208 | [NSException
209 | exceptionWithName:RNUncaughtExceptionHandlerSignalExceptionName
210 | reason:
211 | [NSString stringWithFormat:
212 | NSLocalizedString(@"Signal %d was raised.", nil),
213 | signal]
214 | userInfo:
215 | [NSDictionary
216 | dictionaryWithObject:[NSNumber numberWithInt:signal]
217 | forKey:RNUncaughtExceptionHandlerSignalKey]]
218 | waitUntilDone:YES];
219 | }
220 |
221 |
222 | // ====================================
223 | // UTILITY METHOD TO GET THE BACKTRACE
224 | // ====================================
225 |
226 | + (NSArray *)backtrace
227 | {
228 | void* callstack[128];
229 | int frames = backtrace(callstack, 128);
230 | char **strs = backtrace_symbols(callstack, frames);
231 |
232 | int i;
233 | NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
234 | for (
235 | i = RNUncaughtExceptionHandlerSkipAddressCount;
236 | i < RNUncaughtExceptionHandlerSkipAddressCount +
237 | RNUncaughtExceptionHandlerReportAddressCount;
238 | i++)
239 | {
240 | [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
241 | }
242 | free(strs);
243 |
244 | return backtrace;
245 | }
246 |
247 | @end
248 |
249 |
--------------------------------------------------------------------------------
/ios/ReactNativeExceptionHandler.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | B3E7B58A1CC2AC0600A0062D /* ReactNativeExceptionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* ReactNativeExceptionHandler.m */; };
11 | /* End PBXBuildFile section */
12 |
13 | /* Begin PBXCopyFilesBuildPhase section */
14 | 58B511D91A9E6C8500147676 /* CopyFiles */ = {
15 | isa = PBXCopyFilesBuildPhase;
16 | buildActionMask = 2147483647;
17 | dstPath = "include/$(PRODUCT_NAME)";
18 | dstSubfolderSpec = 16;
19 | files = (
20 | );
21 | runOnlyForDeploymentPostprocessing = 0;
22 | };
23 | /* End PBXCopyFilesBuildPhase section */
24 |
25 | /* Begin PBXFileReference section */
26 | 134814201AA4EA6300B7C361 /* libReactNativeExceptionHandler.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactNativeExceptionHandler.a; sourceTree = BUILT_PRODUCTS_DIR; };
27 | B3E7B5881CC2AC0600A0062D /* ReactNativeExceptionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReactNativeExceptionHandler.h; sourceTree = ""; };
28 | B3E7B5891CC2AC0600A0062D /* ReactNativeExceptionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReactNativeExceptionHandler.m; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 58B511D81A9E6C8500147676 /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 134814211AA4EA7D00B7C361 /* Products */ = {
43 | isa = PBXGroup;
44 | children = (
45 | 134814201AA4EA6300B7C361 /* libReactNativeExceptionHandler.a */,
46 | );
47 | name = Products;
48 | sourceTree = "";
49 | };
50 | 58B511D21A9E6C8500147676 = {
51 | isa = PBXGroup;
52 | children = (
53 | B3E7B5881CC2AC0600A0062D /* ReactNativeExceptionHandler.h */,
54 | B3E7B5891CC2AC0600A0062D /* ReactNativeExceptionHandler.m */,
55 | 134814211AA4EA7D00B7C361 /* Products */,
56 | );
57 | sourceTree = "";
58 | };
59 | /* End PBXGroup section */
60 |
61 | /* Begin PBXNativeTarget section */
62 | 58B511DA1A9E6C8500147676 /* ReactNativeExceptionHandler */ = {
63 | isa = PBXNativeTarget;
64 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "ReactNativeExceptionHandler" */;
65 | buildPhases = (
66 | 58B511D71A9E6C8500147676 /* Sources */,
67 | 58B511D81A9E6C8500147676 /* Frameworks */,
68 | 58B511D91A9E6C8500147676 /* CopyFiles */,
69 | );
70 | buildRules = (
71 | );
72 | dependencies = (
73 | );
74 | name = ReactNativeExceptionHandler;
75 | productName = RCTDataManager;
76 | productReference = 134814201AA4EA6300B7C361 /* libReactNativeExceptionHandler.a */;
77 | productType = "com.apple.product-type.library.static";
78 | };
79 | /* End PBXNativeTarget section */
80 |
81 | /* Begin PBXProject section */
82 | 58B511D31A9E6C8500147676 /* Project object */ = {
83 | isa = PBXProject;
84 | attributes = {
85 | LastUpgradeCheck = 0610;
86 | ORGANIZATIONNAME = Facebook;
87 | TargetAttributes = {
88 | 58B511DA1A9E6C8500147676 = {
89 | CreatedOnToolsVersion = 6.1.1;
90 | };
91 | };
92 | };
93 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "ReactNativeExceptionHandler" */;
94 | compatibilityVersion = "Xcode 3.2";
95 | developmentRegion = English;
96 | hasScannedForEncodings = 0;
97 | knownRegions = (
98 | en,
99 | );
100 | mainGroup = 58B511D21A9E6C8500147676;
101 | productRefGroup = 58B511D21A9E6C8500147676;
102 | projectDirPath = "";
103 | projectRoot = "";
104 | targets = (
105 | 58B511DA1A9E6C8500147676 /* ReactNativeExceptionHandler */,
106 | );
107 | };
108 | /* End PBXProject section */
109 |
110 | /* Begin PBXSourcesBuildPhase section */
111 | 58B511D71A9E6C8500147676 /* Sources */ = {
112 | isa = PBXSourcesBuildPhase;
113 | buildActionMask = 2147483647;
114 | files = (
115 | B3E7B58A1CC2AC0600A0062D /* ReactNativeExceptionHandler.m in Sources */,
116 | );
117 | runOnlyForDeploymentPostprocessing = 0;
118 | };
119 | /* End PBXSourcesBuildPhase section */
120 |
121 | /* Begin XCBuildConfiguration section */
122 | 58B511ED1A9E6C8500147676 /* Debug */ = {
123 | isa = XCBuildConfiguration;
124 | buildSettings = {
125 | ALWAYS_SEARCH_USER_PATHS = NO;
126 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
127 | CLANG_CXX_LIBRARY = "libc++";
128 | CLANG_ENABLE_MODULES = YES;
129 | CLANG_ENABLE_OBJC_ARC = YES;
130 | CLANG_WARN_BOOL_CONVERSION = YES;
131 | CLANG_WARN_CONSTANT_CONVERSION = YES;
132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
133 | CLANG_WARN_EMPTY_BODY = YES;
134 | CLANG_WARN_ENUM_CONVERSION = YES;
135 | CLANG_WARN_INT_CONVERSION = YES;
136 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
137 | CLANG_WARN_UNREACHABLE_CODE = YES;
138 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
139 | COPY_PHASE_STRIP = NO;
140 | ENABLE_STRICT_OBJC_MSGSEND = YES;
141 | GCC_C_LANGUAGE_STANDARD = gnu99;
142 | GCC_DYNAMIC_NO_PIC = NO;
143 | GCC_OPTIMIZATION_LEVEL = 0;
144 | GCC_PREPROCESSOR_DEFINITIONS = (
145 | "DEBUG=1",
146 | "$(inherited)",
147 | );
148 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
149 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
150 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
151 | GCC_WARN_UNDECLARED_SELECTOR = YES;
152 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
153 | GCC_WARN_UNUSED_FUNCTION = YES;
154 | GCC_WARN_UNUSED_VARIABLE = YES;
155 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
156 | MTL_ENABLE_DEBUG_INFO = YES;
157 | ONLY_ACTIVE_ARCH = YES;
158 | SDKROOT = iphoneos;
159 | };
160 | name = Debug;
161 | };
162 | 58B511EE1A9E6C8500147676 /* Release */ = {
163 | isa = XCBuildConfiguration;
164 | buildSettings = {
165 | ALWAYS_SEARCH_USER_PATHS = NO;
166 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
167 | CLANG_CXX_LIBRARY = "libc++";
168 | CLANG_ENABLE_MODULES = YES;
169 | CLANG_ENABLE_OBJC_ARC = YES;
170 | CLANG_WARN_BOOL_CONVERSION = YES;
171 | CLANG_WARN_CONSTANT_CONVERSION = YES;
172 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
173 | CLANG_WARN_EMPTY_BODY = YES;
174 | CLANG_WARN_ENUM_CONVERSION = YES;
175 | CLANG_WARN_INT_CONVERSION = YES;
176 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
177 | CLANG_WARN_UNREACHABLE_CODE = YES;
178 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
179 | COPY_PHASE_STRIP = YES;
180 | ENABLE_NS_ASSERTIONS = NO;
181 | ENABLE_STRICT_OBJC_MSGSEND = YES;
182 | GCC_C_LANGUAGE_STANDARD = gnu99;
183 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
184 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
185 | GCC_WARN_UNDECLARED_SELECTOR = YES;
186 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
187 | GCC_WARN_UNUSED_FUNCTION = YES;
188 | GCC_WARN_UNUSED_VARIABLE = YES;
189 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
190 | MTL_ENABLE_DEBUG_INFO = NO;
191 | SDKROOT = iphoneos;
192 | VALIDATE_PRODUCT = YES;
193 | };
194 | name = Release;
195 | };
196 | 58B511F01A9E6C8500147676 /* Debug */ = {
197 | isa = XCBuildConfiguration;
198 | buildSettings = {
199 | HEADER_SEARCH_PATHS = (
200 | "$(inherited)",
201 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
202 | "$(SRCROOT)/../../../React/**",
203 | "$(SRCROOT)/../../react-native/React/**",
204 | );
205 | LIBRARY_SEARCH_PATHS = "$(inherited)";
206 | OTHER_LDFLAGS = "-ObjC";
207 | PRODUCT_NAME = ReactNativeExceptionHandler;
208 | SKIP_INSTALL = YES;
209 | };
210 | name = Debug;
211 | };
212 | 58B511F11A9E6C8500147676 /* Release */ = {
213 | isa = XCBuildConfiguration;
214 | buildSettings = {
215 | HEADER_SEARCH_PATHS = (
216 | "$(inherited)",
217 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
218 | "$(SRCROOT)/../../../React/**",
219 | "$(SRCROOT)/../../react-native/React/**",
220 | );
221 | LIBRARY_SEARCH_PATHS = "$(inherited)";
222 | OTHER_LDFLAGS = "-ObjC";
223 | PRODUCT_NAME = ReactNativeExceptionHandler;
224 | SKIP_INSTALL = YES;
225 | };
226 | name = Release;
227 | };
228 | /* End XCBuildConfiguration section */
229 |
230 | /* Begin XCConfigurationList section */
231 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "ReactNativeExceptionHandler" */ = {
232 | isa = XCConfigurationList;
233 | buildConfigurations = (
234 | 58B511ED1A9E6C8500147676 /* Debug */,
235 | 58B511EE1A9E6C8500147676 /* Release */,
236 | );
237 | defaultConfigurationIsVisible = 0;
238 | defaultConfigurationName = Release;
239 | };
240 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "ReactNativeExceptionHandler" */ = {
241 | isa = XCConfigurationList;
242 | buildConfigurations = (
243 | 58B511F01A9E6C8500147676 /* Debug */,
244 | 58B511F11A9E6C8500147676 /* Release */,
245 | );
246 | defaultConfigurationIsVisible = 0;
247 | defaultConfigurationName = Release;
248 | };
249 | /* End XCConfigurationList section */
250 | };
251 | rootObject = 58B511D31A9E6C8500147676 /* Project object */;
252 | }
253 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-exception-handler",
3 | "version": "2.10.10",
4 | "description": "A react native module that lets you to register a global error handler that can capture fatal/non fatal uncaught exceptions.",
5 | "main": "index.js",
6 | "typings": "index.d.ts",
7 | "scripts": {
8 | "test": "echo no tests && exit 1",
9 | "lint": "eslint app/",
10 | "lint:fix": "eslint app/ --fix"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/a7ul/react-native-exception-handler"
15 | },
16 | "keywords": [
17 | "modal",
18 | "react",
19 | "native",
20 | "exception",
21 | "handler",
22 | "red",
23 | "screen",
24 | "production",
25 | "ios",
26 | "android",
27 | "bug",
28 | "capture"
29 | ],
30 | "peerDependencies": {
31 | "react": "*",
32 | "react-native": "*"
33 | },
34 | "author": "a7ul",
35 | "license": "MIT",
36 | "bugs": {
37 | "url": "https://github.com/a7ul/react-native-exception-handler/issues"
38 | },
39 | "homepage": "https://github.com/a7ul/react-native-exception-handler",
40 | "devDependencies": {
41 | "babel-eslint": "^7.2.3",
42 | "eslint": "^4.0.0",
43 | "eslint-plugin-react": "^7.1.0",
44 | "eslint-plugin-react-native": "^2.3.2"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/screens/WITHOUT_DEV.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7ul/react-native-exception-handler/50e736b0b2c39c2bf6f00f26a04d5073d69cf966/screens/WITHOUT_DEV.gif
--------------------------------------------------------------------------------
/screens/WITHOUT_PROD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7ul/react-native-exception-handler/50e736b0b2c39c2bf6f00f26a04d5073d69cf966/screens/WITHOUT_PROD.gif
--------------------------------------------------------------------------------
/screens/WITH_EH.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7ul/react-native-exception-handler/50e736b0b2c39c2bf6f00f26a04d5073d69cf966/screens/WITH_EH.gif
--------------------------------------------------------------------------------
/screens/android_native_exception.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7ul/react-native-exception-handler/50e736b0b2c39c2bf6f00f26a04d5073d69cf966/screens/android_native_exception.png
--------------------------------------------------------------------------------
/screens/ios_native_exception.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7ul/react-native-exception-handler/50e736b0b2c39c2bf6f00f26a04d5073d69cf966/screens/ios_native_exception.png
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | acorn-jsx@^3.0.0:
6 | version "3.0.1"
7 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
8 | dependencies:
9 | acorn "^3.0.4"
10 |
11 | acorn@^3.0.4:
12 | version "3.3.0"
13 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
14 |
15 | acorn@^5.0.1:
16 | version "5.0.3"
17 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d"
18 |
19 | ajv-keywords@^1.0.0:
20 | version "1.5.1"
21 | resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
22 |
23 | ajv@^4.7.0:
24 | version "4.11.8"
25 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
26 | dependencies:
27 | co "^4.6.0"
28 | json-stable-stringify "^1.0.1"
29 |
30 | ansi-escapes@^2.0.0:
31 | version "2.0.0"
32 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b"
33 |
34 | ansi-regex@^2.0.0:
35 | version "2.1.1"
36 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
37 |
38 | ansi-styles@^2.2.1:
39 | version "2.2.1"
40 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
41 |
42 | argparse@^1.0.7:
43 | version "1.0.9"
44 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
45 | dependencies:
46 | sprintf-js "~1.0.2"
47 |
48 | array-union@^1.0.1:
49 | version "1.0.2"
50 | resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
51 | dependencies:
52 | array-uniq "^1.0.1"
53 |
54 | array-uniq@^1.0.1:
55 | version "1.0.3"
56 | resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
57 |
58 | arrify@^1.0.0:
59 | version "1.0.1"
60 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
61 |
62 | babel-code-frame@^6.22.0:
63 | version "6.22.0"
64 | resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
65 | dependencies:
66 | chalk "^1.1.0"
67 | esutils "^2.0.2"
68 | js-tokens "^3.0.0"
69 |
70 | babel-eslint@^7.2.3:
71 | version "7.2.3"
72 | resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.3.tgz#b2fe2d80126470f5c19442dc757253a897710827"
73 | dependencies:
74 | babel-code-frame "^6.22.0"
75 | babel-traverse "^6.23.1"
76 | babel-types "^6.23.0"
77 | babylon "^6.17.0"
78 |
79 | babel-messages@^6.23.0:
80 | version "6.23.0"
81 | resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
82 | dependencies:
83 | babel-runtime "^6.22.0"
84 |
85 | babel-runtime@^6.22.0:
86 | version "6.23.0"
87 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b"
88 | dependencies:
89 | core-js "^2.4.0"
90 | regenerator-runtime "^0.10.0"
91 |
92 | babel-traverse@^6.23.1:
93 | version "6.25.0"
94 | resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1"
95 | dependencies:
96 | babel-code-frame "^6.22.0"
97 | babel-messages "^6.23.0"
98 | babel-runtime "^6.22.0"
99 | babel-types "^6.25.0"
100 | babylon "^6.17.2"
101 | debug "^2.2.0"
102 | globals "^9.0.0"
103 | invariant "^2.2.0"
104 | lodash "^4.2.0"
105 |
106 | babel-types@^6.23.0, babel-types@^6.25.0:
107 | version "6.25.0"
108 | resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e"
109 | dependencies:
110 | babel-runtime "^6.22.0"
111 | esutils "^2.0.2"
112 | lodash "^4.2.0"
113 | to-fast-properties "^1.0.1"
114 |
115 | babylon@^6.17.0, babylon@^6.17.2:
116 | version "6.17.4"
117 | resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a"
118 |
119 | balanced-match@^1.0.0:
120 | version "1.0.0"
121 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
122 |
123 | brace-expansion@^1.1.7:
124 | version "1.1.8"
125 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
126 | dependencies:
127 | balanced-match "^1.0.0"
128 | concat-map "0.0.1"
129 |
130 | caller-path@^0.1.0:
131 | version "0.1.0"
132 | resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
133 | dependencies:
134 | callsites "^0.2.0"
135 |
136 | callsites@^0.2.0:
137 | version "0.2.0"
138 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
139 |
140 | chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
141 | version "1.1.3"
142 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
143 | dependencies:
144 | ansi-styles "^2.2.1"
145 | escape-string-regexp "^1.0.2"
146 | has-ansi "^2.0.0"
147 | strip-ansi "^3.0.0"
148 | supports-color "^2.0.0"
149 |
150 | circular-json@^0.3.1:
151 | version "0.3.1"
152 | resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d"
153 |
154 | cli-cursor@^2.1.0:
155 | version "2.1.0"
156 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
157 | dependencies:
158 | restore-cursor "^2.0.0"
159 |
160 | cli-width@^2.0.0:
161 | version "2.1.0"
162 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a"
163 |
164 | co@^4.6.0:
165 | version "4.6.0"
166 | resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
167 |
168 | concat-map@0.0.1:
169 | version "0.0.1"
170 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
171 |
172 | concat-stream@^1.6.0:
173 | version "1.6.0"
174 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
175 | dependencies:
176 | inherits "^2.0.3"
177 | readable-stream "^2.2.2"
178 | typedarray "^0.0.6"
179 |
180 | core-js@^2.4.0:
181 | version "2.4.1"
182 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
183 |
184 | core-util-is@~1.0.0:
185 | version "1.0.2"
186 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
187 |
188 | debug@^2.2.0, debug@^2.6.8:
189 | version "2.6.8"
190 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
191 | dependencies:
192 | ms "2.0.0"
193 |
194 | deep-is@~0.1.3:
195 | version "0.1.3"
196 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
197 |
198 | del@^2.0.2:
199 | version "2.2.2"
200 | resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
201 | dependencies:
202 | globby "^5.0.0"
203 | is-path-cwd "^1.0.0"
204 | is-path-in-cwd "^1.0.0"
205 | object-assign "^4.0.1"
206 | pify "^2.0.0"
207 | pinkie-promise "^2.0.0"
208 | rimraf "^2.2.8"
209 |
210 | doctrine@^2.0.0:
211 | version "2.0.0"
212 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63"
213 | dependencies:
214 | esutils "^2.0.2"
215 | isarray "^1.0.0"
216 |
217 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
218 | version "1.0.5"
219 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
220 |
221 | eslint-plugin-react-native@^2.3.2:
222 | version "2.3.2"
223 | resolved "https://registry.yarnpkg.com/eslint-plugin-react-native/-/eslint-plugin-react-native-2.3.2.tgz#e1b2ba2d97fb46b16fe2dbb5bd4d0f47419f2859"
224 |
225 | eslint-plugin-react@^7.1.0:
226 | version "7.1.0"
227 | resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.1.0.tgz#27770acf39f5fd49cd0af4083ce58104eb390d4c"
228 | dependencies:
229 | doctrine "^2.0.0"
230 | has "^1.0.1"
231 | jsx-ast-utils "^1.4.1"
232 |
233 | eslint-scope@^3.7.1:
234 | version "3.7.1"
235 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
236 | dependencies:
237 | esrecurse "^4.1.0"
238 | estraverse "^4.1.1"
239 |
240 | eslint@^4.0.0:
241 | version "4.0.0"
242 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.0.0.tgz#7277c01437fdf41dccd168d5aa0e49b75ca1f260"
243 | dependencies:
244 | babel-code-frame "^6.22.0"
245 | chalk "^1.1.3"
246 | concat-stream "^1.6.0"
247 | debug "^2.6.8"
248 | doctrine "^2.0.0"
249 | eslint-scope "^3.7.1"
250 | espree "^3.4.3"
251 | esquery "^1.0.0"
252 | estraverse "^4.2.0"
253 | esutils "^2.0.2"
254 | file-entry-cache "^2.0.0"
255 | glob "^7.1.2"
256 | globals "^9.17.0"
257 | ignore "^3.3.3"
258 | imurmurhash "^0.1.4"
259 | inquirer "^3.0.6"
260 | is-my-json-valid "^2.16.0"
261 | is-resolvable "^1.0.0"
262 | js-yaml "^3.8.4"
263 | json-stable-stringify "^1.0.1"
264 | levn "^0.3.0"
265 | lodash "^4.17.4"
266 | mkdirp "^0.5.1"
267 | natural-compare "^1.4.0"
268 | optionator "^0.8.2"
269 | path-is-inside "^1.0.2"
270 | pluralize "^4.0.0"
271 | progress "^2.0.0"
272 | require-uncached "^1.0.3"
273 | strip-json-comments "~2.0.1"
274 | table "^4.0.1"
275 | text-table "~0.2.0"
276 |
277 | espree@^3.4.3:
278 | version "3.4.3"
279 | resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374"
280 | dependencies:
281 | acorn "^5.0.1"
282 | acorn-jsx "^3.0.0"
283 |
284 | esprima@^3.1.1:
285 | version "3.1.3"
286 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
287 |
288 | esquery@^1.0.0:
289 | version "1.0.0"
290 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa"
291 | dependencies:
292 | estraverse "^4.0.0"
293 |
294 | esrecurse@^4.1.0:
295 | version "4.2.0"
296 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163"
297 | dependencies:
298 | estraverse "^4.1.0"
299 | object-assign "^4.0.1"
300 |
301 | estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
302 | version "4.2.0"
303 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
304 |
305 | esutils@^2.0.2:
306 | version "2.0.2"
307 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
308 |
309 | external-editor@^2.0.4:
310 | version "2.0.4"
311 | resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972"
312 | dependencies:
313 | iconv-lite "^0.4.17"
314 | jschardet "^1.4.2"
315 | tmp "^0.0.31"
316 |
317 | fast-levenshtein@~2.0.4:
318 | version "2.0.6"
319 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
320 |
321 | figures@^2.0.0:
322 | version "2.0.0"
323 | resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
324 | dependencies:
325 | escape-string-regexp "^1.0.5"
326 |
327 | file-entry-cache@^2.0.0:
328 | version "2.0.0"
329 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
330 | dependencies:
331 | flat-cache "^1.2.1"
332 | object-assign "^4.0.1"
333 |
334 | flat-cache@^1.2.1:
335 | version "1.2.2"
336 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96"
337 | dependencies:
338 | circular-json "^0.3.1"
339 | del "^2.0.2"
340 | graceful-fs "^4.1.2"
341 | write "^0.2.1"
342 |
343 | fs.realpath@^1.0.0:
344 | version "1.0.0"
345 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
346 |
347 | function-bind@^1.0.2:
348 | version "1.1.0"
349 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
350 |
351 | generate-function@^2.0.0:
352 | version "2.0.0"
353 | resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74"
354 |
355 | generate-object-property@^1.1.0:
356 | version "1.2.0"
357 | resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
358 | dependencies:
359 | is-property "^1.0.0"
360 |
361 | glob@^7.0.3, glob@^7.0.5, glob@^7.1.2:
362 | version "7.1.2"
363 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
364 | dependencies:
365 | fs.realpath "^1.0.0"
366 | inflight "^1.0.4"
367 | inherits "2"
368 | minimatch "^3.0.4"
369 | once "^1.3.0"
370 | path-is-absolute "^1.0.0"
371 |
372 | globals@^9.0.0, globals@^9.17.0:
373 | version "9.18.0"
374 | resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
375 |
376 | globby@^5.0.0:
377 | version "5.0.0"
378 | resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
379 | dependencies:
380 | array-union "^1.0.1"
381 | arrify "^1.0.0"
382 | glob "^7.0.3"
383 | object-assign "^4.0.1"
384 | pify "^2.0.0"
385 | pinkie-promise "^2.0.0"
386 |
387 | graceful-fs@^4.1.2:
388 | version "4.1.11"
389 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
390 |
391 | has-ansi@^2.0.0:
392 | version "2.0.0"
393 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
394 | dependencies:
395 | ansi-regex "^2.0.0"
396 |
397 | has@^1.0.1:
398 | version "1.0.1"
399 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
400 | dependencies:
401 | function-bind "^1.0.2"
402 |
403 | iconv-lite@^0.4.17:
404 | version "0.4.18"
405 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2"
406 |
407 | ignore@^3.3.3:
408 | version "3.3.3"
409 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d"
410 |
411 | imurmurhash@^0.1.4:
412 | version "0.1.4"
413 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
414 |
415 | inflight@^1.0.4:
416 | version "1.0.6"
417 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
418 | dependencies:
419 | once "^1.3.0"
420 | wrappy "1"
421 |
422 | inherits@2, inherits@^2.0.3, inherits@~2.0.3:
423 | version "2.0.3"
424 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
425 |
426 | inquirer@^3.0.6:
427 | version "3.1.1"
428 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.1.1.tgz#87621c4fba4072f48a8dd71c9f9df6f100b2d534"
429 | dependencies:
430 | ansi-escapes "^2.0.0"
431 | chalk "^1.0.0"
432 | cli-cursor "^2.1.0"
433 | cli-width "^2.0.0"
434 | external-editor "^2.0.4"
435 | figures "^2.0.0"
436 | lodash "^4.3.0"
437 | mute-stream "0.0.7"
438 | run-async "^2.2.0"
439 | rx-lite "^4.0.8"
440 | rx-lite-aggregates "^4.0.8"
441 | string-width "^2.0.0"
442 | strip-ansi "^3.0.0"
443 | through "^2.3.6"
444 |
445 | invariant@^2.2.0:
446 | version "2.2.2"
447 | resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
448 | dependencies:
449 | loose-envify "^1.0.0"
450 |
451 | is-fullwidth-code-point@^2.0.0:
452 | version "2.0.0"
453 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
454 |
455 | is-my-json-valid@^2.16.0:
456 | version "2.16.0"
457 | resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693"
458 | dependencies:
459 | generate-function "^2.0.0"
460 | generate-object-property "^1.1.0"
461 | jsonpointer "^4.0.0"
462 | xtend "^4.0.0"
463 |
464 | is-path-cwd@^1.0.0:
465 | version "1.0.0"
466 | resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
467 |
468 | is-path-in-cwd@^1.0.0:
469 | version "1.0.0"
470 | resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc"
471 | dependencies:
472 | is-path-inside "^1.0.0"
473 |
474 | is-path-inside@^1.0.0:
475 | version "1.0.0"
476 | resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f"
477 | dependencies:
478 | path-is-inside "^1.0.1"
479 |
480 | is-promise@^2.1.0:
481 | version "2.1.0"
482 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
483 |
484 | is-property@^1.0.0:
485 | version "1.0.2"
486 | resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
487 |
488 | is-resolvable@^1.0.0:
489 | version "1.0.0"
490 | resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62"
491 | dependencies:
492 | tryit "^1.0.1"
493 |
494 | isarray@^1.0.0, isarray@~1.0.0:
495 | version "1.0.0"
496 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
497 |
498 | js-tokens@^3.0.0:
499 | version "3.0.1"
500 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
501 |
502 | js-yaml@^3.8.4:
503 | version "3.8.4"
504 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6"
505 | dependencies:
506 | argparse "^1.0.7"
507 | esprima "^3.1.1"
508 |
509 | jschardet@^1.4.2:
510 | version "1.4.2"
511 | resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.4.2.tgz#2aa107f142af4121d145659d44f50830961e699a"
512 |
513 | json-stable-stringify@^1.0.1:
514 | version "1.0.1"
515 | resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
516 | dependencies:
517 | jsonify "~0.0.0"
518 |
519 | jsonify@~0.0.0:
520 | version "0.0.0"
521 | resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
522 |
523 | jsonpointer@^4.0.0:
524 | version "4.0.1"
525 | resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
526 |
527 | jsx-ast-utils@^1.4.1:
528 | version "1.4.1"
529 | resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1"
530 |
531 | levn@^0.3.0, levn@~0.3.0:
532 | version "0.3.0"
533 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
534 | dependencies:
535 | prelude-ls "~1.1.2"
536 | type-check "~0.3.2"
537 |
538 | lodash@^4.0.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0:
539 | version "4.17.4"
540 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
541 |
542 | loose-envify@^1.0.0:
543 | version "1.3.1"
544 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
545 | dependencies:
546 | js-tokens "^3.0.0"
547 |
548 | mimic-fn@^1.0.0:
549 | version "1.1.0"
550 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18"
551 |
552 | minimatch@^3.0.4:
553 | version "3.0.4"
554 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
555 | dependencies:
556 | brace-expansion "^1.1.7"
557 |
558 | minimist@0.0.8:
559 | version "0.0.8"
560 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
561 |
562 | mkdirp@^0.5.1:
563 | version "0.5.1"
564 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
565 | dependencies:
566 | minimist "0.0.8"
567 |
568 | ms@2.0.0:
569 | version "2.0.0"
570 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
571 |
572 | mute-stream@0.0.7:
573 | version "0.0.7"
574 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
575 |
576 | natural-compare@^1.4.0:
577 | version "1.4.0"
578 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
579 |
580 | object-assign@^4.0.1:
581 | version "4.1.1"
582 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
583 |
584 | once@^1.3.0:
585 | version "1.4.0"
586 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
587 | dependencies:
588 | wrappy "1"
589 |
590 | onetime@^2.0.0:
591 | version "2.0.1"
592 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
593 | dependencies:
594 | mimic-fn "^1.0.0"
595 |
596 | optionator@^0.8.2:
597 | version "0.8.2"
598 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
599 | dependencies:
600 | deep-is "~0.1.3"
601 | fast-levenshtein "~2.0.4"
602 | levn "~0.3.0"
603 | prelude-ls "~1.1.2"
604 | type-check "~0.3.2"
605 | wordwrap "~1.0.0"
606 |
607 | os-tmpdir@~1.0.1:
608 | version "1.0.2"
609 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
610 |
611 | path-is-absolute@^1.0.0:
612 | version "1.0.1"
613 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
614 |
615 | path-is-inside@^1.0.1, path-is-inside@^1.0.2:
616 | version "1.0.2"
617 | resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
618 |
619 | pify@^2.0.0:
620 | version "2.3.0"
621 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
622 |
623 | pinkie-promise@^2.0.0:
624 | version "2.0.1"
625 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
626 | dependencies:
627 | pinkie "^2.0.0"
628 |
629 | pinkie@^2.0.0:
630 | version "2.0.4"
631 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
632 |
633 | pluralize@^4.0.0:
634 | version "4.0.0"
635 | resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762"
636 |
637 | prelude-ls@~1.1.2:
638 | version "1.1.2"
639 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
640 |
641 | process-nextick-args@~1.0.6:
642 | version "1.0.7"
643 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
644 |
645 | progress@^2.0.0:
646 | version "2.0.0"
647 | resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
648 |
649 | readable-stream@^2.2.2:
650 | version "2.3.2"
651 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.2.tgz#5a04df05e4f57fe3f0dc68fdd11dc5c97c7e6f4d"
652 | dependencies:
653 | core-util-is "~1.0.0"
654 | inherits "~2.0.3"
655 | isarray "~1.0.0"
656 | process-nextick-args "~1.0.6"
657 | safe-buffer "~5.1.0"
658 | string_decoder "~1.0.0"
659 | util-deprecate "~1.0.1"
660 |
661 | regenerator-runtime@^0.10.0:
662 | version "0.10.5"
663 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
664 |
665 | require-uncached@^1.0.3:
666 | version "1.0.3"
667 | resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
668 | dependencies:
669 | caller-path "^0.1.0"
670 | resolve-from "^1.0.0"
671 |
672 | resolve-from@^1.0.0:
673 | version "1.0.1"
674 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
675 |
676 | restore-cursor@^2.0.0:
677 | version "2.0.0"
678 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
679 | dependencies:
680 | onetime "^2.0.0"
681 | signal-exit "^3.0.2"
682 |
683 | rimraf@^2.2.8:
684 | version "2.6.1"
685 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
686 | dependencies:
687 | glob "^7.0.5"
688 |
689 | run-async@^2.2.0:
690 | version "2.3.0"
691 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
692 | dependencies:
693 | is-promise "^2.1.0"
694 |
695 | rx-lite-aggregates@^4.0.8:
696 | version "4.0.8"
697 | resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
698 | dependencies:
699 | rx-lite "*"
700 |
701 | rx-lite@*, rx-lite@^4.0.8:
702 | version "4.0.8"
703 | resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
704 |
705 | safe-buffer@~5.1.0:
706 | version "5.1.1"
707 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
708 |
709 | signal-exit@^3.0.2:
710 | version "3.0.2"
711 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
712 |
713 | slice-ansi@0.0.4:
714 | version "0.0.4"
715 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
716 |
717 | sprintf-js@~1.0.2:
718 | version "1.0.3"
719 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
720 |
721 | string-width@^2.0.0:
722 | version "2.0.0"
723 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e"
724 | dependencies:
725 | is-fullwidth-code-point "^2.0.0"
726 | strip-ansi "^3.0.0"
727 |
728 | string_decoder@~1.0.0:
729 | version "1.0.3"
730 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
731 | dependencies:
732 | safe-buffer "~5.1.0"
733 |
734 | strip-ansi@^3.0.0:
735 | version "3.0.1"
736 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
737 | dependencies:
738 | ansi-regex "^2.0.0"
739 |
740 | strip-json-comments@~2.0.1:
741 | version "2.0.1"
742 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
743 |
744 | supports-color@^2.0.0:
745 | version "2.0.0"
746 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
747 |
748 | table@^4.0.1:
749 | version "4.0.1"
750 | resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435"
751 | dependencies:
752 | ajv "^4.7.0"
753 | ajv-keywords "^1.0.0"
754 | chalk "^1.1.1"
755 | lodash "^4.0.0"
756 | slice-ansi "0.0.4"
757 | string-width "^2.0.0"
758 |
759 | text-table@~0.2.0:
760 | version "0.2.0"
761 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
762 |
763 | through@^2.3.6:
764 | version "2.3.8"
765 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
766 |
767 | tmp@^0.0.31:
768 | version "0.0.31"
769 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7"
770 | dependencies:
771 | os-tmpdir "~1.0.1"
772 |
773 | to-fast-properties@^1.0.1:
774 | version "1.0.3"
775 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
776 |
777 | tryit@^1.0.1:
778 | version "1.0.3"
779 | resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb"
780 |
781 | type-check@~0.3.2:
782 | version "0.3.2"
783 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
784 | dependencies:
785 | prelude-ls "~1.1.2"
786 |
787 | typedarray@^0.0.6:
788 | version "0.0.6"
789 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
790 |
791 | util-deprecate@~1.0.1:
792 | version "1.0.2"
793 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
794 |
795 | wordwrap@~1.0.0:
796 | version "1.0.0"
797 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
798 |
799 | wrappy@1:
800 | version "1.0.2"
801 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
802 |
803 | write@^0.2.1:
804 | version "0.2.1"
805 | resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
806 | dependencies:
807 | mkdirp "^0.5.1"
808 |
809 | xtend@^4.0.0:
810 | version "4.0.1"
811 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
812 |
--------------------------------------------------------------------------------