diff --git a/.craft.yml b/.craft.yml index 3ed70d0ad..43bc4eed8 100644 --- a/.craft.yml +++ b/.craft.yml @@ -1,4 +1,4 @@ -minVersion: '0.6.0' +minVersion: "0.6.0" github: owner: getsentry repo: react-native-sentry @@ -7,9 +7,3 @@ preReleaseCommand: bash scripts/craft-pre-release.sh targets: - name: npm - name: github - # - name: cocoapods - # specPath: Sentry.podspec - # - name: registry - # type: sdk - # config: - # canonical: 'cocoapods:sentry-cocoa' diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index e5f13e9fd..000000000 --- a/.editorconfig +++ /dev/null @@ -1,19 +0,0 @@ -root = true - -[*] -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true -charset = utf-8 - -[*.json] -indent_style = space -indent_size = 4 - -[*.js,*.jsx,*.ts] -indent_style = space -indent_size = 2 - -[{package.json,.travis.yml}] -indent_style = space -indent_size = 2 diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 48526abfd..000000000 --- a/.eslintrc +++ /dev/null @@ -1,187 +0,0 @@ -{ - "parser": "babel-eslint", - "parserOptions": { - "ecmaFeatures": { - "jsx": true, - "modules": true - } - }, - "globals": { - "require": false, - "console": false - }, - "plugins": [ - "react" - ], - "rules": { - /** - * Strict mode - */ - "strict": [ - 2, - "global" - ], // http://eslint.org/docs/rules/strict - /** - * ES6 - */ - "no-var": 2, // http://eslint.org/docs/rules/no-var - "prefer-const": 0, // http://eslint.org/docs/rules/prefer-const - /** - * Variables - */ - "no-shadow": 2, // http://eslint.org/docs/rules/no-shadow - "no-shadow-restricted-names": 2, // http://eslint.org/docs/rules/no-shadow-restricted-names - "no-undef": 2, // http://eslint.org/docs/rules/no-undef - "no-unused-vars": [ - 2, - { // http://eslint.org/docs/rules/no-unused-vars - "vars": "local", - "args": "none" - } - ], - "no-use-before-define": 2, // http://eslint.org/docs/rules/no-use-before-define - /** - * Possible errors - */ - "comma-dangle": [ - 0, - "always-multiline" - ], // http://eslint.org/docs/rules/comma-dangle - "no-cond-assign": [ - 2, - "always" - ], // http://eslint.org/docs/rules/no-cond-assign - "no-console": 1, // http://eslint.org/docs/rules/no-console - "no-debugger": 1, // http://eslint.org/docs/rules/no-debugger - "no-alert": 1, // http://eslint.org/docs/rules/no-alert - "no-constant-condition": 1, // http://eslint.org/docs/rules/no-constant-condition - "no-dupe-keys": 2, // http://eslint.org/docs/rules/no-dupe-keys - "no-duplicate-case": 2, // http://eslint.org/docs/rules/no-duplicate-case - "no-empty": 2, // http://eslint.org/docs/rules/no-empty - "no-ex-assign": 2, // http://eslint.org/docs/rules/no-ex-assign - "no-extra-boolean-cast": 0, // http://eslint.org/docs/rules/no-extra-boolean-cast - "no-extra-semi": 2, // http://eslint.org/docs/rules/no-extra-semi - "no-func-assign": 2, // http://eslint.org/docs/rules/no-func-assign - "no-inner-declarations": 2, // http://eslint.org/docs/rules/no-inner-declarations - "no-invalid-regexp": 2, // http://eslint.org/docs/rules/no-invalid-regexp - "no-irregular-whitespace": 2, // http://eslint.org/docs/rules/no-irregular-whitespace - "no-obj-calls": 2, // http://eslint.org/docs/rules/no-obj-calls - "no-sparse-arrays": 2, // http://eslint.org/docs/rules/no-sparse-arrays - "no-unreachable": 2, // http://eslint.org/docs/rules/no-unreachable - "semi": [ - 2, - "always" - ], // http://eslint.org/docs/rules/semi.html - "use-isnan": 2, // http://eslint.org/docs/rules/use-isnan - "block-scoped-var": 2, // http://eslint.org/docs/rules/block-scoped-var - /** - * Best practices - */ - "consistent-return": 2, // http://eslint.org/docs/rules/consistent-return - "curly": 0, // http://eslint.org/docs/rules/curly [REVISIT ME] - "default-case": 2, // http://eslint.org/docs/rules/default-case - "dot-notation": [ - 2, - { // http://eslint.org/docs/rules/dot-notation - "allowKeywords": true - } - ], - "eqeqeq": 0, // http://eslint.org/docs/rules/eqeqeq [REVISIT ME] - "guard-for-in": 0, // http://eslint.org/docs/rules/guard-for-in [REVISIT ME] - "jsx-quotes": [ - 2, - "prefer-double" - ], // http://eslint.org/docs/rules/jsx-quotes - "no-caller": 2, // http://eslint.org/docs/rules/no-caller - "no-else-return": 0, // http://eslint.org/docs/rules/no-else-return [REVISIT ME] - "no-eq-null": 2, // http://eslint.org/docs/rules/no-eq-null - "no-eval": 2, // http://eslint.org/docs/rules/no-eval - "no-extend-native": 2, // http://eslint.org/docs/rules/no-extend-native - "no-extra-bind": 2, // http://eslint.org/docs/rules/no-extra-bind - "no-fallthrough": 2, // http://eslint.org/docs/rules/no-fallthrough - "no-floating-decimal": 2, // http://eslint.org/docs/rules/no-floating-decimal - "no-implied-eval": 2, // http://eslint.org/docs/rules/no-implied-eval - "no-lone-blocks": 2, // http://eslint.org/docs/rules/no-lone-blocks - "no-loop-func": 2, // http://eslint.org/docs/rules/no-loop-func - "no-multi-str": 2, // http://eslint.org/docs/rules/no-multi-str - "no-native-reassign": 2, // http://eslint.org/docs/rules/no-native-reassign - "no-new": 2, // http://eslint.org/docs/rules/no-new - "no-new-func": 2, // http://eslint.org/docs/rules/no-new-func - "no-new-wrappers": 2, // http://eslint.org/docs/rules/no-new-wrappers - "no-octal": 2, // http://eslint.org/docs/rules/no-octal - "no-octal-escape": 2, // http://eslint.org/docs/rules/no-octal-escape - "no-param-reassign": 0, // http://eslint.org/docs/rules/no-param-reassign [REVISIT ME] - "no-proto": 2, // http://eslint.org/docs/rules/no-proto - "no-redeclare": 2, // http://eslint.org/docs/rules/no-redeclare - "no-return-assign": 2, // http://eslint.org/docs/rules/no-return-assign - "no-script-url": 2, // http://eslint.org/docs/rules/no-script-url - "no-self-compare": 2, // http://eslint.org/docs/rules/no-self-compare - "no-sequences": 2, // http://eslint.org/docs/rules/no-sequences - "no-throw-literal": 2, // http://eslint.org/docs/rules/no-throw-literal - "no-with": 2, // http://eslint.org/docs/rules/no-with - "quotes": [ - 2, - "single", - { - "avoidEscape": true - } - ], // http://eslint.org/docs/rules/quotes.html - "radix": 2, // http://eslint.org/docs/rules/radix - "computed-property-spacing": [ - 2, - "never" - ], // http://eslint.org/docs/rules/space-in-brackets.html - "array-bracket-spacing": [ - 2, - "never" - ], // http://eslint.org/docs/rules/space-in-brackets.html - "object-curly-spacing": [ - 2, - "never" - ], // http://eslint.org/docs/rules/space-in-brackets.html - "space-infix-ops": 2, // http://eslint.org/docs/rules/space-infix-ops.html - "vars-on-top": 0, // http://eslint.org/docs/rules/vars-on-top - "wrap-iife": [ - 2, - "any" - ], // http://eslint.org/docs/rules/wrap-iife - "yoda": 2, // http://eslint.org/docs/rules/yoda - /** - * React - */ - "react/display-name": 0, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md - "react/no-multi-comp": [ - 0, - { - "ignoreStateless": true - } - ], // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md - "react/jsx-key": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-key.md - "react/jsx-no-undef": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md - "react/jsx-no-duplicate-props": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-duplicate-props.md - "react/jsx-uses-react": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md - "react/jsx-uses-vars": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md - "react/no-did-mount-set-state": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md - "react/no-did-update-set-state": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md" - "react/no-unknown-property": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md - "react/prop-types": [ - 2, - { - "ignore": [ - "className", - "children", - "location", - "params" - ] - } - ], - "react/react-in-jsx-scope": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md - "react/self-closing-comp": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md - "react/sort-comp": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md - "react/jsx-wrap-multilines": 2, // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/wrap-multilines.md - /** - * Custom - */ - "getsentry/jsx-needs-il8n": 0, // highlights literals in JSX components w/o translation tags - } -} diff --git a/.gitignore b/.gitignore index 2ec5b9827..7b0483b8a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ node_modules ## Build generated build/ DerivedData +dist ## Various settings *.pbxuser diff --git a/.gitmodules b/.gitmodules index 5921e6724..9dc854294 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ -[submodule "ios/Sentry"] - path = ios/Sentry -url=https://github.com/getsentry/sentry-cocoa [submodule "examples"] path = examples url = https://github.com/getsentry/examples +[submodule "ios/Sentry"] + path = ios/Sentry + url=https://github.com/getsentry/sentry-cocoa diff --git a/.npmignore b/.npmignore index b2a9c4173..97efda3b6 100644 --- a/.npmignore +++ b/.npmignore @@ -7,6 +7,4 @@ appium .travis .github -# KSCrash -ios/Sentry/KSCrash -ios/Sentry/Sources/KSCrash +!/dist/**/* diff --git a/.vscode/.ropeproject/config.py b/.vscode/.ropeproject/config.py deleted file mode 100644 index d1e8f3df1..000000000 --- a/.vscode/.ropeproject/config.py +++ /dev/null @@ -1,100 +0,0 @@ -# The default ``config.py`` -# flake8: noqa - - -def set_prefs(prefs): - """This function is called before opening the project""" - - # Specify which files and folders to ignore in the project. - # Changes to ignored resources are not added to the history and - # VCSs. Also they are not returned in `Project.get_files()`. - # Note that ``?`` and ``*`` match all characters but slashes. - # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc' - # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc' - # '.svn': matches 'pkg/.svn' and all of its children - # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o' - # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o' - prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject', - '.hg', '.svn', '_svn', '.git', '.tox'] - - # Specifies which files should be considered python files. It is - # useful when you have scripts inside your project. Only files - # ending with ``.py`` are considered to be python files by - # default. - #prefs['python_files'] = ['*.py'] - - # Custom source folders: By default rope searches the project - # for finding source folders (folders that should be searched - # for finding modules). You can add paths to that list. Note - # that rope guesses project source folders correctly most of the - # time; use this if you have any problems. - # The folders should be relative to project root and use '/' for - # separating folders regardless of the platform rope is running on. - # 'src/my_source_folder' for instance. - #prefs.add('source_folders', 'src') - - # You can extend python path for looking up modules - #prefs.add('python_path', '~/python/') - - # Should rope save object information or not. - prefs['save_objectdb'] = True - prefs['compress_objectdb'] = False - - # If `True`, rope analyzes each module when it is being saved. - prefs['automatic_soa'] = True - # The depth of calls to follow in static object analysis - prefs['soa_followed_calls'] = 0 - - # If `False` when running modules or unit tests "dynamic object - # analysis" is turned off. This makes them much faster. - prefs['perform_doa'] = True - - # Rope can check the validity of its object DB when running. - prefs['validate_objectdb'] = True - - # How many undos to hold? - prefs['max_history_items'] = 32 - - # Shows whether to save history across sessions. - prefs['save_history'] = True - prefs['compress_history'] = False - - # Set the number spaces used for indenting. According to - # :PEP:`8`, it is best to use 4 spaces. Since most of rope's - # unit-tests use 4 spaces it is more reliable, too. - prefs['indent_size'] = 4 - - # Builtin and c-extension modules that are allowed to be imported - # and inspected by rope. - prefs['extension_modules'] = [] - - # Add all standard c-extensions to extension_modules list. - prefs['import_dynload_stdmods'] = True - - # If `True` modules with syntax errors are considered to be empty. - # The default value is `False`; When `False` syntax errors raise - # `rope.base.exceptions.ModuleSyntaxError` exception. - prefs['ignore_syntax_errors'] = False - - # If `True`, rope ignores unresolvable imports. Otherwise, they - # appear in the importing namespace. - prefs['ignore_bad_imports'] = False - - # If `True`, rope will insert new module imports as - # `from import ` by default. - prefs['prefer_module_from_imports'] = False - - # If `True`, rope will transform a comma list of imports into - # multiple separate import statements when organizing - # imports. - prefs['split_imports'] = False - - # If `True`, rope will sort imports alphabetically by module name - # instead of alphabetically by import statement, with from imports - # after normal imports. - prefs['sort_imports_alphabetically'] = False - - -def project_opened(project): - """This function is called after opening the project""" - # Do whatever you like here! diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 95b9c92ff..e1aafaae4 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,10 +1,8 @@ { - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format - "recommendations": [ - "dzannotti.vscode-babel-coloring", - "esbenp.prettier-vscode", - "dbaeumer.vscode-eslint", - "lextudio.restructuredtext" - ] + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "esbenp.prettier-vscode", + "ms-vscode.vscode-typescript-tslint-plugin" + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index faf327b08..d9bb89fb7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,15 +1,22 @@ { + "editor.formatOnType": true, + "editor.formatOnPaste": false, + "editor.formatOnSave": true, + "editor.rulers": [120], + "editor.tabSize": 2, + "files.autoSave": "onWindowChange", "files.trimTrailingWhitespace": true, - "files.ensureSingleFinalNewline": true, - - "python.linting.pylintEnabled": false, - - "prettier.bracketSpacing": false, - "prettier.singleQuote": true, - "prettier.printWidth": 90, - "prettier.jsxBracketSameLine": true, - - "[javascript]": { - "editor.formatOnSave": true + "files.insertFinalNewline": true, + "search.exclude": { + "**/node_modules/": true, + "**/build/": true, + "**/dist/": true + }, + "typescript.tsdk": "./node_modules/typescript/lib", + "tslint.autoFixOnSave": true, + "[json]": { + "editor.formatOnType": false, + "editor.formatOnPaste": false, + "editor.formatOnSave": false } -} + } diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bb6914e3..605751a1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## 1.0.0-beta + +This is a new major release of the Sentry's React Native SDK rewritten in TypeScript. +This SDK is now unified with the rest of our JavaScript SDKs and published under a new name `@sentry/react-native`. +It uses `@sentry/browser` and both `sentry-cocoa` and `sentry-android` for native handling. + +This release is a breaking change an code changes are necessary. + +New way to import and init the SDK: + +```js +import * as Sentry from "@sentry/react-native"; + +Sentry.init({ + dsn: "DSN" +}); +``` + ## 0.43.2 - Add a check for an empty stacktrace on Android (#594) @@ -53,12 +71,14 @@ - `react-native-sentry >= 0.39.0` requires `react-native >= 0.56.0` - [Android] Bumping of gradle deps + ``` compileSdkVersion 26 buildToolsVersion '26.0.3' ... targetSdkVersion 26 ``` + - [Android] Use `sentry-android` `1.7.5` - Bump `@sentry/wizard` `0.11.0` - Bump `sentry-cocoa` `4.1.0` @@ -162,7 +182,9 @@ The `Upload Debug Symbols to Sentry` build script looks like this: export SENTRY_PROPERTIES=sentry.properties ../node_modules/sentry-cli-binary/bin/sentry-cli upload-dsym ``` + should be changed to this: + ``` export SENTRY_PROPERTIES=sentry.properties ../node_modules/@sentry/cli/bin/sentry-cli upload-dsym @@ -210,16 +232,17 @@ Also squashed many little bugs on iOS. We had to rename `project.ext.sentry` to `project.ext.sentryCli` because our own proguard gradle plugin was conflicting with the name. The docs already reflect this change. + - #257 We now use the `mainThread` to report errors to `RNSentry`. This change is necessary in order for react-native to export constants. This change shouldn't impact anyone using `react-native-sentry` since most of the "heavy" load was handled by `sentry-cocoa` in its own background queue anyway. + - #259 - #244 Bump `sentry-cocoa` to `3.8.3` - ## v0.27.0 We decided to deactivate stack trace merging by default on iOS since it seems to unstable right now. @@ -227,7 +250,7 @@ To activate it set: ```js Sentry.config("___DSN___", { - deactivateStacktraceMerging: false + deactivateStacktraceMerging: false }); ``` @@ -358,7 +381,6 @@ Also added integration tests running on AWS Device Farm. - Updated to `sentry-cocoa` `3.1.2` - Fixed #156 - ## v0.14.11 - Fixed #166 diff --git a/SentryReactNative.podspec b/SentryReactNative.podspec index 4dbd553ff..1f7866ccd 100644 --- a/SentryReactNative.podspec +++ b/SentryReactNative.podspec @@ -18,8 +18,8 @@ Pod::Spec.new do |s| s.preserve_paths = '*.js' s.dependency 'React' - s.dependency 'Sentry', '~> 4.1.3' + s.dependency 'Sentry', '~> 4.3.4' - s.source_files = 'ios/RNSentry*.{h,m}' - s.public_header_files = 'ios/RNSentry.h' + s.source_files = 'src/ios/RNSentry*.{h,m}' + s.public_header_files = 'src/ios/RNSentry.h' end diff --git a/android/build.gradle b/android/build.gradle index bce751535..ba5ad91c8 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -28,5 +28,5 @@ android { dependencies { implementation 'com.facebook.react:react-native:+' - implementation 'io.sentry:sentry-android:1.7.5' + implementation 'io.sentry:sentry-android:1.7.23' } diff --git a/android/src/main/java/io/sentry/RNSentryEventEmitter.java b/android/src/main/java/io/sentry/RNSentryEventEmitter.java deleted file mode 100644 index d03c32440..000000000 --- a/android/src/main/java/io/sentry/RNSentryEventEmitter.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.sentry; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.modules.core.DeviceEventManagerModule; - -import java.util.HashMap; -import java.util.Map; - -public class RNSentryEventEmitter extends ReactContextBaseJavaModule { - - public static final String SENTRY_EVENT_SENT_SUCCESSFULLY = "Sentry/eventSentSuccessfully"; - public static final String SENTRY_EVENT_STORED = "Sentry/eventStored"; - - public RNSentryEventEmitter(ReactApplicationContext reactContext) { - super(reactContext); - } - - @Override - public String getName() { - return "RNSentryEventEmitter"; - } - - @Override - public Map getConstants() { - final Map constants = new HashMap<>(); - constants.put("EVENT_SENT_SUCCESSFULLY", SENTRY_EVENT_SENT_SUCCESSFULLY); - constants.put("EVENT_STORED", SENTRY_EVENT_STORED); - return constants; - } - - public static void sendEvent(ReactApplicationContext reactContext, String eventName, WritableMap params) { - reactContext - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) - .emit(eventName, params); - } - -} diff --git a/android/src/main/java/io/sentry/RNSentryModule.java b/android/src/main/java/io/sentry/RNSentryModule.java index bebccc467..2bdbf4720 100644 --- a/android/src/main/java/io/sentry/RNSentryModule.java +++ b/android/src/main/java/io/sentry/RNSentryModule.java @@ -16,17 +16,14 @@ import com.facebook.react.bridge.ReadableNativeMap; import com.facebook.react.bridge.ReadableType; import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.WritableNativeMap; import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Collections; import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; -import java.util.Random; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -35,9 +32,6 @@ import io.sentry.android.AndroidSentryClientFactory; import io.sentry.android.event.helper.AndroidEventBuilderHelper; -import io.sentry.connection.EventSendCallback; -import io.sentry.event.Breadcrumb; -import io.sentry.event.BreadcrumbBuilder; import io.sentry.event.Event; import io.sentry.event.EventBuilder; import io.sentry.event.Sdk; @@ -53,22 +47,15 @@ public class RNSentryModule extends ReactContextBaseJavaModule { private static final Pattern mJsModuleIdPattern = Pattern.compile("(?:^|[/\\\\])(\\d+\\.js)$"); - private static final String versionString = "0.43.2"; - private static final String sdkName = "sentry-react-native"; - - private final ReactApplicationContext reactContext; private static AndroidEventBuilderHelper androidHelper; - private static PackageInfo packageInfo; + final static Logger logger = Logger.getLogger("react-native-sentry"); - private static Map extra; - private static ReadableMap tags; private static SentryClient sentryClient; + private static PackageInfo packageInfo; public RNSentryModule(ReactApplicationContext reactContext) { super(reactContext); - this.reactContext = reactContext; - RNSentryModule.extra = new HashMap<>(); RNSentryModule.packageInfo = getPackageInfo(reactContext); } @@ -81,9 +68,11 @@ public String getName() { public Map getConstants() { final Map constants = new HashMap<>(); constants.put("nativeClientAvailable", true); + constants.put("nativeTransport", true); return constants; } + @ReactMethod public void startWithDsnString(String dsnString, final ReadableMap options, Promise promise) { if (sentryClient != null) { @@ -101,34 +90,7 @@ public void startWithDsnString(String dsnString, final ReadableMap options, Prom } androidHelper = new AndroidEventBuilderHelper(this.getReactApplicationContext()); - sentryClient.addEventSendCallback(new EventSendCallback() { - @Override - public void onFailure(Event event, Exception exception) { - // This needs to be there, otherwise in case of no internet the users app will not - // crash since we do not propagate the error further. The system needs to be - // overhauled to remove this "hack". - RNSentryEventEmitter.sendEvent(reactContext, RNSentryEventEmitter.SENTRY_EVENT_STORED, new WritableNativeMap()); - RNSentryEventEmitter.sendEvent(reactContext, RNSentryEventEmitter.SENTRY_EVENT_SENT_SUCCESSFULLY, new WritableNativeMap()); - } - @Override - public void onSuccess(Event event) { - WritableMap params = Arguments.createMap(); - params.putString("event_id", event.getId().toString()); - params.putString("level", event.getLevel().toString().toLowerCase()); - params.putString("message", event.getMessage()); - params.putString("release", event.getRelease()); - params.putString("dist", event.getDist()); - params.putMap("extra", MapUtil.toWritableMap(event.getExtra())); - params.putMap("tags", MapUtil.toWritableMap(Collections.unmodifiableMap(event.getTags()))); - if (event.getSentryInterfaces().containsKey(ExceptionInterface.EXCEPTION_INTERFACE)) { - ExceptionInterface exceptionInterface = ((ExceptionInterface)event.getSentryInterfaces().get(ExceptionInterface.EXCEPTION_INTERFACE)); - params.putString("message", exceptionInterface.getExceptions().getFirst().getExceptionMessage()); - } - RNSentryEventEmitter.sendEvent(reactContext, RNSentryEventEmitter.SENTRY_EVENT_STORED, new WritableNativeMap()); - RNSentryEventEmitter.sendEvent(reactContext, RNSentryEventEmitter.SENTRY_EVENT_SENT_SUCCESSFULLY, params); - } - }); sentryClient.addShouldSendEventCallback(new ShouldSendEventCallback() { @Override public boolean shouldSend(Event event) { @@ -140,12 +102,6 @@ public boolean shouldSend(Event event) { return false; } } - // Since we set shouldSendEvent for react-native we need to duplicate the code for sampling here - // I know you could add multiple shouldSendCallbacks but I want to be consistent with ios - if (options.hasKey("sampleRate")) { - double randomDouble = new Random().nextDouble(); - return options.getDouble("sampleRate") >= Math.abs(randomDouble); - } return true; } }); @@ -159,66 +115,45 @@ public void setLogLevel(int level) { } @ReactMethod - public void setExtra(ReadableMap extra) { - Map extraMap = MapUtil.toMap(extra); - RNSentryModule.extra.putAll(extraMap); - } - - @ReactMethod - public void addExtra(String key, String value) { - RNSentryModule.extra.put(key, value); - logger.info(String.format("addExtra '%s' '%s'", key, value)); - } - - @ReactMethod - public void setTags(ReadableMap tags) { - RNSentryModule.tags = tags; + public void crash() { + throw new RuntimeException("TEST - Sentry Client Crash"); } @ReactMethod - public void setUser(ReadableMap user) { - UserBuilder userBuilder = getUserBuilder(user); - User builtUser = userBuilder.build(); - Sentry.setUser(builtUser); + public void fetchRelease(Promise promise) { + WritableMap release = Arguments.createMap(); + release.putString("id", packageInfo.packageName); + release.putString("version", packageInfo.versionName); + release.putString("build", String.valueOf(packageInfo.versionCode)); + promise.resolve(release); } @ReactMethod - public void crash() { - throw new RuntimeException("TEST - Sentry Client Crash"); - } + public void deviceContexts(Promise promise) { + EventBuilder eventBuilder = new EventBuilder(); + androidHelper.helpBuildingEvent(eventBuilder); + Event event = eventBuilder.build(); - @ReactMethod - public void captureBreadcrumb(ReadableMap breadcrumb) { - logger.info(String.format("captureEvent '%s'", breadcrumb)); + WritableMap params = Arguments.createMap(); - BreadcrumbBuilder breadcrumbBuilder = new BreadcrumbBuilder(); - if (breadcrumb.hasKey("category")) { - breadcrumbBuilder.setCategory(breadcrumb.getString("category")); + for (Map.Entry> data : event.getContexts().entrySet()) { + params.putMap(data.getKey(), MapUtil.toWritableMap(data.getValue())); } - if (breadcrumb.hasKey("data") && breadcrumb.getMap("data") != null) { - Map newData = new HashMap<>(); - for (Map.Entry data : ((ReadableNativeMap)breadcrumb.getMap("data")).toHashMap().entrySet()) { - newData.put(data.getKey(), data.getValue() != null ? data.getValue().toString() : null); - } - breadcrumbBuilder.setData(newData); - } - breadcrumbBuilder.setLevel(breadcrumbLevel((ReadableNativeMap)breadcrumb)); - if (breadcrumb.hasKey("message")) { - breadcrumbBuilder.setMessage(breadcrumb.getString("message")); - } else { - breadcrumbBuilder.setMessage(""); - } - Sentry.record(breadcrumbBuilder.build()); + promise.resolve(params); } @ReactMethod - public void captureEvent(ReadableMap event) { + public void sendEvent(ReadableMap event, Promise promise) { ReadableNativeMap castEvent = (ReadableNativeMap)event; EventBuilder eventBuilder = new EventBuilder() .withLevel(eventLevel(castEvent)); + androidHelper.helpBuildingEvent(eventBuilder); + + eventBuilder.withBreadcrumbs(Sentry.getStoredClient().getContext().getBreadcrumbs()); + if (event.hasKey("message")) { eventBuilder.withMessage(event.getString("message")); } @@ -282,21 +217,36 @@ public void captureEvent(ReadableMap event) { eventBuilder.withEnvironment(event.getString("environment")); } - Sentry.capture(buildEvent(eventBuilder)); - } - @ReactMethod - public void clearContext() { - Sentry.clearContext(); - RNSentryModule.extra = new HashMap<>(); - RNSentryModule.tags = null; - } + if (event.hasKey("release")) { + eventBuilder.withRelease(event.getString("release")); + } else { + eventBuilder.withRelease(null); + } - @ReactMethod - public void activateStacktraceMerging(Promise promise) { - logger.info("TODO: implement activateStacktraceMerging"); -// promise.resolve(true); - promise.reject("Sentry", "Stacktrace merging not yet implemented"); + if (event.hasKey("dist")) { + eventBuilder.withDist(event.getString("dist")); + } else { + eventBuilder.withDist(null); + } + + Event builtEvent = eventBuilder.build(); + + if (event.hasKey("sdk")) { + ReadableNativeMap sdk = (ReadableNativeMap)event.getMap("sdk"); + Set sdkIntegrations = new HashSet<>(); + if (sdk.hasKey("integrations")) { + ReadableNativeArray integrations = (ReadableNativeArray)sdk.getArray("integrations"); + for(int i = 0; i < integrations.size(); ++i) { + sdkIntegrations.add(integrations.getString(i)); + } + } + builtEvent.setSdk(new Sdk(sdk.getString("name"), sdk.getString("version"), sdkIntegrations)); + } + + + Sentry.capture(builtEvent); + promise.resolve(true); } @NonNull @@ -321,33 +271,6 @@ private UserBuilder getUserBuilder(ReadableMap user) { return userBuilder; } - public static Event buildEvent(EventBuilder eventBuilder) { - androidHelper.helpBuildingEvent(eventBuilder); - - setRelease(eventBuilder); - eventBuilder.withBreadcrumbs(Sentry.getStoredClient().getContext().getBreadcrumbs()); - - if (extra != null) { - for (Map.Entry entry : extra.entrySet()) { - if (entry.getValue() != null) { - eventBuilder.withExtra(entry.getKey(), entry.getValue()); - logger.info(String.format("addExtra '%s' '%s'", entry.getKey(), entry.getValue())); - } - } - } - if (tags != null) { - for (Map.Entry entry : ((ReadableNativeMap)tags).toHashMap().entrySet()) { - eventBuilder.withExtra(entry.getKey(), entry.getValue()); - } - } - - Event event = eventBuilder.build(); - Set sdkIntegrations = new HashSet<>(); - sdkIntegrations.add("sentry-java"); - event.setSdk(new Sdk(sdkName, versionString, sdkIntegrations)); - return event; - } - private static void addExceptionInterface(EventBuilder eventBuilder, String type, String value, ReadableNativeArray stack) { StackTraceInterface stackTraceInterface = new StackTraceInterface(convertToNativeStacktrace(stack)); Deque exceptions = new ArrayDeque<>(); @@ -398,25 +321,7 @@ private static SentryStackTraceElement[] convertToNativeStacktrace(ReadableNativ column = frame.getInt("colno"); } - String[] lastFileNameSegments = fileName.split("\\?"); - String lastPathComponent = lastFileNameSegments[0]; - String[] fileNameSegments = lastPathComponent.split("/"); - String calculatedFileName = fileNameSegments[fileNameSegments.length-1]; - StringBuilder finalFileName = new StringBuilder("app:///").append(calculatedFileName); - - // We want to skip native code frames without function - if (methodName.equals("?") && calculatedFileName.equals("[native code]")) { - continue; - } - - // We remove the url and add native code the method name so its in the stacktrace - // but not - if (calculatedFileName.equals("[native code]")) { - finalFileName = new StringBuilder(""); - methodName = new StringBuilder("[native code] ").append(methodName).toString(); - } - - SentryStackTraceElement stackFrame = new SentryStackTraceElement("", methodName, stackFrameToModuleId(frame), lineNumber, column, finalFileName.toString(), "javascript"); + SentryStackTraceElement stackFrame = new SentryStackTraceElement("", methodName, stackFrameToModuleId(frame), lineNumber, column, fileName, "javascript"); frames.add(stackFrame); } SentryStackTraceElement[] synthStackTrace = new SentryStackTraceElement[frames.size()]; @@ -441,19 +346,6 @@ private static String stackFrameToModuleId(ReadableMap frame) { return ""; } - private static void setRelease(EventBuilder eventBuilder) { - if (extra.containsKey("__sentry_version")) { - eventBuilder.withRelease(packageInfo.packageName + "-" + extra.get("__sentry_version")); - eventBuilder.withDist(null); - } - if (extra.containsKey("__sentry_release")) { - eventBuilder.withRelease((String) extra.get("__sentry_release")); - } - if (extra.containsKey("__sentry_dist")) { - eventBuilder.withDist((String) extra.get("__sentry_dist")); - } - } - private static PackageInfo getPackageInfo(Context ctx) { try { return ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0); @@ -463,25 +355,6 @@ private static PackageInfo getPackageInfo(Context ctx) { } } - private Breadcrumb.Level breadcrumbLevel(ReadableNativeMap breadcrumb) { - String level = ""; - if (breadcrumb.hasKey("level")) { - level = breadcrumb.getString("level"); - } - switch (level) { - case "critical": - return Breadcrumb.Level.CRITICAL; - case "warning": - return Breadcrumb.Level.WARNING; - case "info": - return Breadcrumb.Level.INFO; - case "debug": - return Breadcrumb.Level.DEBUG; - default: - return Breadcrumb.Level.ERROR; - } - } - private Event.Level eventLevel(ReadableNativeMap event) { String level = ""; if (event.hasKey("level")) { diff --git a/android/src/main/java/io/sentry/RNSentryPackage.java b/android/src/main/java/io/sentry/RNSentryPackage.java index 76051c2f4..24748e20b 100644 --- a/android/src/main/java/io/sentry/RNSentryPackage.java +++ b/android/src/main/java/io/sentry/RNSentryPackage.java @@ -17,7 +17,7 @@ public RNSentryPackage() { @Override public List createNativeModules(ReactApplicationContext reactContext) { - return Arrays.asList(new RNSentryModule(reactContext), new RNSentryEventEmitter(reactContext)); + return Arrays.asList(new RNSentryModule(reactContext)); } public List> createJSModules() { diff --git a/index.js b/index.js deleted file mode 100644 index ea876336a..000000000 --- a/index.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; -export * from './lib/Sentry'; -import Sentry from './lib/Sentry'; - -export default Sentry; diff --git a/ios/RNSentry.h b/ios/RNSentry.h index be85de499..6f7df588a 100644 --- a/ios/RNSentry.h +++ b/ios/RNSentry.h @@ -3,15 +3,7 @@ #else #import "RCTBridge.h" #endif -#if __has_include() -#import -#else -#import "RCTRootView.h" -#endif @interface RNSentry : NSObject -+ (void)installWithRootView:(RCTRootView *)rootView; -+ (void)installWithBridge:(RCTBridge *)bridge; - @end diff --git a/ios/RNSentry.m b/ios/RNSentry.m index acd2e60e6..3192b1976 100644 --- a/ios/RNSentry.m +++ b/ios/RNSentry.m @@ -1,5 +1,5 @@ #import "RNSentry.h" -#import "RNSentryEventEmitter.h" + #if __has_include() #import #else @@ -8,13 +8,8 @@ #import -NSString *const RNSentryVersionString = @"0.43.2"; -NSString *const RNSentrySdkName = @"sentry.javascript.react-native"; - @interface RNSentry() -@property (nonatomic, strong) NSMutableDictionary *moduleMapping; - @end @@ -29,90 +24,11 @@ + (BOOL)requiresMainQueueSetup { return YES; } -+ (void)installWithBridge:(RCTBridge *)bridge { - // For now we don't need this anymore -} - -+ (void)installWithRootView:(RCTRootView *)rootView { - // For now we don't need this anymore -} - -- (NSInteger)indexOfReactNativeCallFrame:(NSArray *)frames nativeCallAddress:(NSUInteger)nativeCallAddress { - NSInteger smallestDiff = NSIntegerMax; - NSInteger index = -1; - NSUInteger counter = 0; - for (SentryFrame *frame in frames) { - NSUInteger instructionAddress; - // We skip js frames because they don't have an instructionAddress - if (frame.instructionAddress == nil) { - continue; - } - [[NSScanner scannerWithString:frame.instructionAddress] scanHexLongLong:&instructionAddress]; - if (instructionAddress < nativeCallAddress) { - continue; - } - NSInteger diff = instructionAddress - nativeCallAddress; - if (diff < smallestDiff) { - smallestDiff = diff; - index = counter; - } - counter++; - } - if (index > -1) { - return index + 1; - } - return index; -} - -- (void)injectReactNativeFrames:(SentryEvent *)event { - NSString *address = [[NSUserDefaults standardUserDefaults] objectForKey:@"RNSentry.__sentry_address"]; - if (nil == address) { - // We bail out here since __sentry_address is not set - return; - } - SentryThread *crashedThread = [event.exceptions objectAtIndex:0].thread; - NSArray *frames = crashedThread.stacktrace.frames; - NSInteger indexOfReactFrames = [self indexOfReactNativeCallFrame:frames - nativeCallAddress:[address integerValue]]; - if (indexOfReactFrames == -1) { - return; - } - - NSMutableArray *finalFrames = [NSMutableArray new]; - - NSString *stacktrace = [[NSUserDefaults standardUserDefaults] objectForKey:@"RNSentry.__sentry_stack"]; - NSArray *reactFrames = [SentryJavaScriptBridgeHelper convertReactNativeStacktrace:[SentryJavaScriptBridgeHelper parseJavaScriptStacktrace:stacktrace]]; - for (NSInteger i = 0; i < frames.count; i++) { - [finalFrames addObject:[frames objectAtIndex:i]]; - if (i == indexOfReactFrames) { - [finalFrames addObjectsFromArray:reactFrames]; - } - } - - crashedThread.stacktrace.frames = finalFrames; -} - -- (void)setReleaseVersionDist:(SentryEvent *)event { - if (event.extra[@"__sentry_version"]) { - NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; - event.releaseName = [NSString stringWithFormat:@"%@-%@", infoDict[@"CFBundleIdentifier"], event.extra[@"__sentry_version"]]; - } - if (event.extra[@"__sentry_release"]) { - event.releaseName = [NSString stringWithFormat:@"%@", event.extra[@"__sentry_release"]]; - } - if (event.extra[@"__sentry_dist"]) { - event.dist = [NSString stringWithFormat:@"%@", event.extra[@"__sentry_dist"]]; - } - event.sdk = @{@"name": RNSentrySdkName, - @"version": RNSentryVersionString, - @"integrations": @[@"sentry-cocoa"]}; -} - RCT_EXPORT_MODULE() - (NSDictionary *)constantsToExport { - return @{@"nativeClientAvailable": @YES}; + return @{@"nativeClientAvailable": @YES, @"nativeTransport": @YES}; } RCT_EXPORT_METHOD(crashedLastLaunch:(RCTPromiseResolveBlock)resolve @@ -130,12 +46,7 @@ - (void)setReleaseVersionDist:(SentryEvent *)event { rejecter:(RCTPromiseRejectBlock)reject) { NSError *error = nil; - self.moduleMapping = [[NSMutableDictionary alloc] init]; SentryClient *client = [[SentryClient alloc] initWithDsn:dsnString didFailWithError:&error]; - client.beforeSerializeEvent = ^(SentryEvent * _Nonnull event) { - [self injectReactNativeFrames:event]; - [self setReleaseVersionDist:event]; - }; client.shouldSendEvent = ^BOOL(SentryEvent * _Nonnull event) { // We don't want to send an event after startup that came from a Unhandled JS Exception of react native // Because we sent it already before the app crashed. @@ -144,14 +55,12 @@ - (void)setReleaseVersionDist:(SentryEvent *)event { NSLog(@"Unhandled JS Exception"); return NO; } - // Since we set shouldSendEvent for react-native we need to duplicate the code for sampling here - if (nil != options[@"sampleRate"]) { - return ([options[@"sampleRate"] floatValue] >= ((double)arc4random() / 0x100000000)); - } return YES; }; [SentryClient setSharedClient:client]; - [SentryClient.sharedClient startCrashHandlerWithError:&error]; + if ([[options objectForKey:@"enableNativeCrashHandling"] boolValue]) { + [SentryClient.sharedClient startCrashHandlerWithError:&error]; + } if (error) { reject(@"SentryReactNative", error.localizedDescription, error); return; @@ -159,142 +68,53 @@ - (void)setReleaseVersionDist:(SentryEvent *)event { resolve(@YES); } -RCT_EXPORT_METHOD(activateStacktraceMerging:(RCTPromiseResolveBlock)resolve +RCT_EXPORT_METHOD(deviceContexts:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - // React Native < 0.45 - if (NSClassFromString(@"RCTBatchedBridge")) { - [self swizzleCallNativeModule:NSClassFromString(@"RCTBatchedBridge")]; - } else { - [self swizzleInvokeWithBridge:NSClassFromString(@"RCTModuleMethod")]; - } - resolve(@YES); + resolve([[[SentryContext alloc] init] serialize]); } -- (void)swizzleInvokeWithBridge:(Class)class { - static const void *key = &key; - SEL selector = @selector(invokeWithBridge:module:arguments:); - uintptr_t callNativeModuleAddress = [class instanceMethodForSelector:selector]; - __block RNSentry *_self = self; - SentrySwizzleInstanceMethod(class, - selector, - SentrySWReturnType(id), - SentrySWArguments(RCTBridge *bridge, id module, NSArray *arguments), - SentrySWReplacement({ - // TODO: refactor this block, its used twice - NSMutableArray *newParams = [NSMutableArray array]; - if (arguments != nil && arguments.count > 0) { - for (id param in arguments) { - if ([param isKindOfClass:NSDictionary.class] && param[@"__sentry_stack"]) { - [_self.moduleMapping setValue:[NSString stringWithFormat:@"%@", [module class]] forKey:[NSString stringWithFormat:@"%@", param[@"__sentry_moduleID"]]]; - [RNSentryEventEmitter emitModuleTableUpdate:_self.moduleMapping.mutableCopy]; - [[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%lu", callNativeModuleAddress] forKey:@"RNSentry.__sentry_address"]; - [[NSUserDefaults standardUserDefaults] setObject:[RCTConvert NSString:param[@"__sentry_stack"]] forKey:@"RNSentry.__sentry_stack"]; - [[NSUserDefaults standardUserDefaults] synchronize]; - } else { - if (param != nil) { - [newParams addObject:param]; - } - } - } - } - return SentrySWCallOriginal(bridge, module, newParams); - }), SentrySwizzleModeOncePerClassAndSuperclasses, key); -} - -- (void)swizzleCallNativeModule:(Class)class { - static const void *key = &key; - SEL selctor = @selector(callNativeModule:method:params:); - uintptr_t callNativeModuleAddress = [class instanceMethodForSelector:selctor]; - - SentrySwizzleInstanceMethod(class, - selctor, - SentrySWReturnType(id), - SentrySWArguments(NSUInteger moduleID, NSUInteger methodID, NSArray *params), - SentrySWReplacement({ - // TODO: refactor this block, its used twice - NSMutableArray *newParams = [NSMutableArray array]; - if (params != nil && params.count > 0) { - for (id param in params) { - if ([param isKindOfClass:NSDictionary.class] && param[@"__sentry_stack"]) { - [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithUnsignedInteger:callNativeModuleAddress] forKey:@"RNSentry.__sentry_address"]; - [[NSUserDefaults standardUserDefaults] setObject:[RCTConvert NSString:param[@"__sentry_stack"]] forKey:@"RNSentry.__sentry_stack"]; - [[NSUserDefaults standardUserDefaults] synchronize]; - } else { - if (param != nil) { - [newParams addObject:param]; - } - } - } - } - return SentrySWCallOriginal(moduleID, methodID, newParams); - }), SentrySwizzleModeOncePerClassAndSuperclasses, key); -} - -RCT_EXPORT_METHOD(clearContext) +RCT_EXPORT_METHOD(fetchRelease:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^{ - [SentryClient.sharedClient clearContext]; - }); + NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; + resolve(@{ + @"id": infoDict[@"CFBundleIdentifier"], + @"version": infoDict[@"CFBundleShortVersionString"], + @"build": infoDict[@"CFBundleVersion"], + }); } + RCT_EXPORT_METHOD(setLogLevel:(int)level) { [SentryClient setLogLevel:[SentryJavaScriptBridgeHelper sentryLogLevelFromJavaScriptLevel:level]]; } -RCT_EXPORT_METHOD(setTags:(NSDictionary *_Nonnull)tags) -{ - SentryClient.sharedClient.tags = [SentryJavaScriptBridgeHelper sanitizeDictionary:tags]; -} - -RCT_EXPORT_METHOD(setExtra:(NSDictionary *_Nonnull)extra) -{ - SentryClient.sharedClient.extra = extra; -} - -RCT_EXPORT_METHOD(addExtra:(NSString *_Nonnull)key value:(id)value) -{ - NSMutableDictionary *prevExtra = SentryClient.sharedClient.extra.mutableCopy; - [prevExtra setValue:value forKey:key]; - SentryClient.sharedClient.extra = prevExtra; -} - -RCT_EXPORT_METHOD(setUser:(NSDictionary *_Nonnull)user) -{ - SentryUser *sentryUser = [SentryJavaScriptBridgeHelper createSentryUserFromJavaScriptUser:user]; - if (sentryUser) { - SentryClient.sharedClient.user = sentryUser; - } -} - -RCT_EXPORT_METHOD(captureBreadcrumb:(NSDictionary * _Nonnull)breadcrumb) -{ - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^{ - [SentryClient.sharedClient.breadcrumbs addBreadcrumb:[SentryJavaScriptBridgeHelper createSentryBreadcrumbFromJavaScriptBreadcrumb:breadcrumb]]; - }); -} - -RCT_EXPORT_METHOD(captureEvent:(NSDictionary * _Nonnull)event) +RCT_EXPORT_METHOD(sendEvent:(NSDictionary * _Nonnull)event + resolve:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^{ - SentryEvent *sentryEvent = [SentryJavaScriptBridgeHelper createSentryEventFromJavaScriptEvent:event]; - if (sentryEvent.exceptions) { -#if DEBUG - // We want to send the exception instead of storing it because in debug - // the app does not crash it will restart - [SentryClient.sharedClient sendEvent:sentryEvent withCompletionHandler:NULL]; -#else - [SentryClient.sharedClient storeEvent:sentryEvent]; -#endif + if ([NSJSONSerialization isValidJSONObject:event]) { + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:event + options:0 + error:nil]; + + SentryEvent *sentryEvent = [[SentryEvent alloc] initWithJSON:jsonData]; + [SentryClient.sharedClient sendEvent:sentryEvent withCompletionHandler:^(NSError * _Nullable error) { + if (nil != error) { + reject(@"SentryReactNative", error.localizedDescription, error); + } else { + resolve(@YES); + } + }]; } else { - [SentryClient.sharedClient sendEvent:sentryEvent withCompletionHandler:NULL]; + reject(@"SentryReactNative", @"Cannot serialize event", nil); } - [RNSentryEventEmitter emitStoredEvent]; }); } - RCT_EXPORT_METHOD(crash) { [SentryClient.sharedClient crash]; diff --git a/ios/RNSentry.xcodeproj/project.pbxproj b/ios/RNSentry.xcodeproj/project.pbxproj index 4ae55cdc4..0f79235dc 100644 --- a/ios/RNSentry.xcodeproj/project.pbxproj +++ b/ios/RNSentry.xcodeproj/project.pbxproj @@ -8,11 +8,9 @@ /* Begin PBXBuildFile section */ 274692BA21B4414400BF91A8 /* RNSentry.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNSentry.m */; }; - 274692BB21B4414400BF91A8 /* RNSentryEventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6378C6FA1EAF630500A1F1EE /* RNSentryEventEmitter.m */; }; 274692BD21B4414400BF91A8 /* libSentryStatic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6387B8561ED8520D0045A84C /* libSentryStatic.a */; }; 274692BF21B4414400BF91A8 /* RNSentry.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = B3E7B5881CC2AC0600A0062D /* RNSentry.h */; }; 6350257B1E1E845F00408AE7 /* RNSentry.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = B3E7B5881CC2AC0600A0062D /* RNSentry.h */; }; - 6378C6FB1EAF630500A1F1EE /* RNSentryEventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6378C6FA1EAF630500A1F1EE /* RNSentryEventEmitter.m */; }; 6387B8591ED8521B0045A84C /* libSentryStatic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6387B8561ED8520D0045A84C /* libSentryStatic.a */; }; B3E7B58A1CC2AC0600A0062D /* RNSentry.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNSentry.m */; }; /* End PBXBuildFile section */ @@ -83,8 +81,6 @@ /* Begin PBXFileReference section */ 134814201AA4EA6300B7C361 /* libRNSentry.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNSentry.a; sourceTree = BUILT_PRODUCTS_DIR; }; 274692C321B4414400BF91A8 /* libRNSentry-tvOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libRNSentry-tvOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 6378C6F91EAF630500A1F1EE /* RNSentryEventEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSentryEventEmitter.h; sourceTree = ""; }; - 6378C6FA1EAF630500A1F1EE /* RNSentryEventEmitter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSentryEventEmitter.m; sourceTree = ""; }; 6387B7971ED84BA70045A84C /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 6387B8441ED8520D0045A84C /* Sentry.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Sentry.xcodeproj; path = Sentry/Sentry.xcodeproj; sourceTree = ""; }; B3E7B5881CC2AC0600A0062D /* RNSentry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSentry.h; sourceTree = ""; }; @@ -126,8 +122,6 @@ 632232581E76C45800F58A1F /* Libraries */, B3E7B5881CC2AC0600A0062D /* RNSentry.h */, B3E7B5891CC2AC0600A0062D /* RNSentry.m */, - 6378C6F91EAF630500A1F1EE /* RNSentryEventEmitter.h */, - 6378C6FA1EAF630500A1F1EE /* RNSentryEventEmitter.m */, 134814211AA4EA7D00B7C361 /* Products */, 6387B7961ED84BA70045A84C /* Frameworks */, ); @@ -217,6 +211,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 58B511D21A9E6C8500147676; @@ -266,7 +261,6 @@ buildActionMask = 2147483647; files = ( 274692BA21B4414400BF91A8 /* RNSentry.m in Sources */, - 274692BB21B4414400BF91A8 /* RNSentryEventEmitter.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -275,7 +269,6 @@ buildActionMask = 2147483647; files = ( B3E7B58A1CC2AC0600A0062D /* RNSentry.m in Sources */, - 6378C6FB1EAF630500A1F1EE /* RNSentryEventEmitter.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/RNSentryEventEmitter.h b/ios/RNSentryEventEmitter.h deleted file mode 100644 index ddd60dbfa..000000000 --- a/ios/RNSentryEventEmitter.h +++ /dev/null @@ -1,17 +0,0 @@ -#if __has_include() -#import -#else -#import "RCTEventEmitter.h" -#endif -#if __has_include() -#import -#else -#import "RCTBridge.h" -#endif - -@interface RNSentryEventEmitter : RCTEventEmitter - -+ (void)emitStoredEvent; -+ (void)emitModuleTableUpdate:(NSDictionary *)moduleTable; - -@end diff --git a/ios/RNSentryEventEmitter.m b/ios/RNSentryEventEmitter.m deleted file mode 100644 index 924300997..000000000 --- a/ios/RNSentryEventEmitter.m +++ /dev/null @@ -1,78 +0,0 @@ -// -// RNSentryEventEmitter.m -// RNSentry -// -// Created by Daniel Griesser on 25/04/2017. -// Copyright © 2017 Facebook. All rights reserved. -// - -#import "RNSentryEventEmitter.h" - -NSString *const kEventSentSuccessfully = @"Sentry/eventSentSuccessfully"; -NSString *const kEventStored = @"Sentry/eventStored"; -NSString *const kModuleTable = @"Sentry/moduleTable"; - -@implementation RNSentryEventEmitter - -RCT_EXPORT_MODULE(); - -- (NSDictionary *)constantsToExport { - return @{ - @"EVENT_SENT_SUCCESSFULLY": kEventSentSuccessfully, - @"EVENT_STORED": kEventStored, - @"MODULE_TABLE": kModuleTable - }; -} - -+ (BOOL)requiresMainQueueSetup { - return YES; -} - -- (NSArray *)supportedEvents { - return @[kEventSentSuccessfully, kEventStored, kModuleTable]; -} - - -- (void)startObserving { - for (NSString *event in [self supportedEvents]) { - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleNotification:) - name:event - object:nil]; - } -} - -- (void)stopObserving { - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -+ (void)emitStoredEvent { - [self postNotificationName:kEventStored withPayload:@""]; -} - -+ (void)emitModuleTableUpdate:(NSDictionary *)moduleTable { - if (![NSJSONSerialization isValidJSONObject:moduleTable]) { - return; - } - NSError *error = nil; - NSData *jsonData = [NSJSONSerialization dataWithJSONObject:moduleTable - options:0 - error:&error]; - if (nil == error) { - [self postNotificationName:kModuleTable withPayload:[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]]; - } -} - -+ (void)postNotificationName:(NSString *)name withPayload:(NSObject *)object { - NSDictionary *payload = @{@"payload": object}; - - [[NSNotificationCenter defaultCenter] postNotificationName:name - object:self - userInfo:payload]; -} - -- (void)handleNotification:(NSNotification *)notification { - [self sendEventWithName:notification.name body:notification.userInfo]; -} - -@end diff --git a/ios/Sentry b/ios/Sentry index 6c7f2e23b..52f057f31 160000 --- a/ios/Sentry +++ b/ios/Sentry @@ -1 +1 @@ -Subproject commit 6c7f2e23b0401c099ebced56d22ccc96ffa71609 +Subproject commit 52f057f31cceb326cb68ca1212ea96c2f0ad53db diff --git a/lib/NativeClient.js b/lib/NativeClient.js deleted file mode 100644 index c79253615..000000000 --- a/lib/NativeClient.js +++ /dev/null @@ -1,190 +0,0 @@ -import {NativeModules, NativeEventEmitter} from 'react-native'; -const {RNSentry, RNSentryEventEmitter} = NativeModules; - -const DEFAULT_MODULE_IGNORES = [ - 'AccessibilityManager', - 'ActionSheetManager', - 'AlertManager', - 'AppState', - 'AsyncLocalStorage', - 'Clipboard', - 'DevLoadingView', - 'DevMenu', - 'ExceptionsManager', - 'I18nManager', - 'ImageEditingManager', - 'ImageStoreManager', - 'ImageViewManager', - 'IOSConstants', - 'JSCExecutor', - 'JSCSamplingProfiler', - 'KeyboardObserver', - 'LinkingManager', - 'LocationObserver', - 'NativeAnimatedModule', - 'NavigatorManager', - 'NetInfo', - 'Networking', - 'RedBox', - 'ScrollViewManager', - 'SettingsManager', - 'SourceCode', - 'StatusBarManager', - 'Timing', - 'UIManager', - 'Vibration', - 'WebSocketModule', - 'WebViewManager' -]; - -export class NativeClient { - constructor(dsn, options) { - if (dsn.constructor !== String) { - throw new Error('Sentry: A DSN must be provided'); - } - if (!RNSentry) { - throw new Error('Sentry: There is no native client installed.'); - } - - this._dsn = dsn; - this._activatedMerging = false; - this.options = { - ignoreModulesExclude: [], - ignoreModulesInclude: [], - deactivateStacktraceMerging: true - }; - Object.assign(this.options, options); - } - - async install() { - return RNSentry.startWithDsnString(this._dsn, this.options).then(() => { - if (this.options.deactivateStacktraceMerging === false) { - this._activateStacktraceMerging(); - const eventEmitter = new NativeEventEmitter(RNSentryEventEmitter); - eventEmitter.addListener(RNSentryEventEmitter.MODULE_TABLE, moduleTable => { - try { - this._updateIgnoredModules(JSON.parse(moduleTable.payload)); - } catch (e) { - // https://github.com/getsentry/react-native-sentry/issues/241 - // under some circumstances the the JSON is not valid - // the reason for this is yet to be found - } - }); - } - RNSentry.setLogLevel(this.options.logLevel); - }); - } - - _cloneObject(obj) { - return JSON.parse(JSON.stringify(obj)); - } - - nativeCrash() { - RNSentry.crash(); - } - - captureEvent(event) { - RNSentry.captureEvent(this._cloneObject(event)); - } - - setUserContext(user) { - RNSentry.setUser(this._cloneObject(user)); - } - - setTagsContext(tags) { - RNSentry.setTags(this._cloneObject(tags)); - } - - setExtraContext(extra) { - RNSentry.setExtra(this._cloneObject(extra)); - } - - addExtraContext(key, value) { - RNSentry.addExtra(key, value); - } - - captureBreadcrumb(breadcrumb) { - RNSentry.captureBreadcrumb(this._cloneObject(breadcrumb)); - } - - clearContext() { - RNSentry.clearContext(); - } - - _updateIgnoredModules(modules) { - const values = Object.values(modules); - const keys = Object.keys(modules); - for (let i = 0; i < values.length; i++) { - const moduleName = values[i].replace(/RCT/, ''); - const moduleID = keys[i]; - if (this._ignoredModules[moduleID]) { - continue; - } - this._addIgnoredModule(moduleID, moduleName); - } - } - - _addIgnoredModule(moduleID, moduleName) { - if ( - this.options.ignoreModulesExclude.indexOf(moduleName) === -1 && - (DEFAULT_MODULE_IGNORES.indexOf(moduleName) >= 0 || - this.options.ignoreModulesInclude.indexOf(moduleName) >= 0) - ) { - this._ignoredModules[moduleID] = true; - } - } - - _activateStacktraceMerging = async () => { - return RNSentry.activateStacktraceMerging() - .then(activated => { - if (this._activatedMerging) { - return; - } - this._ignoredModules = {}; - const BatchedBridge = require('react-native/Libraries/BatchedBridge/BatchedBridge'); - if (typeof __fbBatchedBridgeConfig !== 'undefined') { - /* global __fbBatchedBridgeConfig */ - __fbBatchedBridgeConfig.remoteModuleConfig.forEach((module, moduleID) => { - if (module !== null) { - this._addIgnoredModule(moduleID, module[0]); - } - }); - } else if (BatchedBridge._remoteModuleTable) { - for (let moduleID in BatchedBridge._remoteModuleTable) { - if (BatchedBridge._remoteModuleTable.hasOwnProperty(moduleID)) { - let moduleName = BatchedBridge._remoteModuleTable[moduleID]; - this._addIgnoredModule(moduleID, moduleName); - } - } - } - this._activatedMerging = true; - this._overwriteEnqueueNativeCall(); - }) - .catch(function(reason) { - // eslint-disable-next-line - console.log(reason); - }); - }; - - _overwriteEnqueueNativeCall() { - const BatchedBridge = require('react-native/Libraries/BatchedBridge/BatchedBridge'); - const original = BatchedBridge.enqueueNativeCall; - const that = this; - BatchedBridge.enqueueNativeCall = function( - moduleID: number, - methodID: number, - params: Array, - onFail: ?Function, - onSucc: ?Function - ) { - if (that._ignoredModules[moduleID]) { - return original.apply(this, arguments); - } - params.push({ - __sentry_stack: new Error().stack, - __sentry_moduleID: moduleID - }); - return original.apply(this, arguments); - }; - } -} diff --git a/lib/RavenClient.js b/lib/RavenClient.js deleted file mode 100644 index 02b600eb5..000000000 --- a/lib/RavenClient.js +++ /dev/null @@ -1,111 +0,0 @@ -import Raven from 'raven-js'; -import {Sentry, SentryLog} from './Sentry'; - -export class RavenClient { - constructor(dsn, options) { - if (dsn.constructor !== String) { - throw new Error('SentryClient: A DSN must be provided'); - } - this._dsn = dsn; - this.options = { - allowSecretKey: true, - allowDuplicates: Sentry.isNativeClientAvailable() - }; - Object.assign(this.options, options); - - Raven.config(dsn, this.options); - if (options.logLevel >= SentryLog.Debug) { - Raven.debug = true; - } - } - - install() { - // we have to remove the sampleRate if native client is available - // otherwise we will sample twice - if (Sentry.isNativeClientAvailable() && this.options.sampleRate !== undefined) { - Raven._globalOptions.sampleRate = 1; - } - - Raven.install(); - - Raven.addPlugin( - require('./raven-plugin'), - { - nativeClientAvailable: Sentry.isNativeClientAvailable(), - handlePromiseRejection: this.options.handlePromiseRejection - }, - data => { - if (Sentry.options.internal) { - data.dist = Sentry.options.internal.dist; - } - } - ); - - if (Sentry.isNativeClientAvailable()) { - // We overwrite the default transport handler when the native - // client is available, because we want to send the event with native - Raven.setTransport(transportOptions => { - // We don't need to send breadcrumbs over the bridge - // since we capture all breacrumbs when they get created - delete transportOptions.data.breadcrumbs; - Sentry._captureEvent(transportOptions.data); - }); - Raven.setBreadcrumbCallback(Sentry._breadcrumbCallback); - const oldCaptureBreadcrumb = Raven.captureBreadcrumb; - Raven.captureBreadcrumb = function(obj) { - if (obj.data && typeof obj.data === 'object') { - obj.data = Object.assign({}, obj.data); - } - return oldCaptureBreadcrumb.apply(this, arguments); - }; - } - } - - setDataCallback(callback) { - Raven.setDataCallback(callback); - } - - setShouldSendCallback(callback) { - Raven.setShouldSendCallback(callback); - } - - setUserContext(user) { - Raven.setUserContext(user); - } - - setTagsContext(tags) { - Raven.setTagsContext(tags); - } - - setExtraContext(extra) { - Raven.setExtraContext(extra); - } - - captureException(ex, options) { - Raven.captureException(ex, options); - } - - captureBreadcrumb(breadcrumb) { - Raven.captureBreadcrumb(breadcrumb); - } - - captureMessage(message, options) { - Raven.captureMessage(message, options); - } - - setRelease(release) { - Raven.setRelease(release); - } - - clearContext() { - return Raven.clearContext(); - } - - context(options, func, args) { - return Raven.context(options, func, args); - } - - wrap(options, func, _before) { - return Raven.wrap(options, func, _before); - } -} diff --git a/lib/Sentry.d.ts b/lib/Sentry.d.ts deleted file mode 100644 index 32a39948d..000000000 --- a/lib/Sentry.d.ts +++ /dev/null @@ -1,106 +0,0 @@ -// Type definitions for react-native-sentry -// Project: https://sentry.io -// Definitions by: Daniel Griesser -// Definitions: https://github.com/getsentry/react-native-sentry -// TypeScript Version: 2.3 - -import {RavenOptions} from 'raven-js'; - -type SentryBreadcrumbType = 'navigation' | 'http'; - -interface SentryBreadcrumb { - message?: string; - category?: string; - level?: SentrySeverity; - data?: object; - type?: SentryBreadcrumbType; -} - -export enum SentrySeverity { - Fatal = 'fatal', - Error = 'error', - Warning = 'warning', - Info = 'info', - Debug = 'debug', - Critical = 'critical' -} - -export enum SentryLog { - None = 0, - Error = 1, - Debug = 2, - Verbose = 3 -} - -interface SentryOptions { - /** Deactivates the stacktrace merging feature. Default: true */ - deactivateStacktraceMerging?: boolean; - /** Deactivates the native integration and only uses raven-js */ - disableNativeIntegration?: boolean; - /** Handle unhandled promise rejections. Default: true */ - handlePromiseRejection?: boolean; - ignoreModulesExclude?: string[]; - ignoreModulesInclude?: string[]; - instrument?: boolean; - /** Sentry log level. Default: SentryLog.None */ - logLevel?: SentryLog; -} - -export default Sentry; - -export class Sentry { - install(): Promise; - - static config(dsn: string, options?: SentryOptions): Sentry; - - static isNativeClientAvailable(): boolean; - - static crash(): void; - - static nativeCrash(): void; - - static setEventSentSuccessfully(callback: Function): void; - - static setShouldSendCallback(callback: Function): void; - - static setDataCallback(callback: Function): void; - - static setUserContext(user: { - id?: string; - username?: string; - email?: string; - extra?: object; - }): void; - - static setTagsContext(tags: object): void; - - static setExtraContext(extra: object): void; - - static captureMessage(message: string, options?: RavenOptions): void; - - static captureException(ex: Error, options?: RavenOptions): void; - - static captureBreadcrumb(breadcrumb: SentryBreadcrumb): void; - - static clearContext(): Promise; - - static context(func: Function, ...args: any[]): void; - static context(options: object, func: Function, ...args: any[]): void; - - static wrap(func: Function): Function; - static wrap(options: object, func: Function): Function; - static wrap(func: T): T; - static wrap(options: object, func: T): T; - - static lastException(): object; - static lastException(): null; - - static lastEventId(): object; - static lastEventId(): null; - - static setRelease(release: string): void; - - static setDist(dist: string): void; - - static setVersion(version: string): void; -} diff --git a/lib/Sentry.js b/lib/Sentry.js deleted file mode 100644 index 3f94e9dfb..000000000 --- a/lib/Sentry.js +++ /dev/null @@ -1,216 +0,0 @@ -import {NativeModules, NativeEventEmitter} from 'react-native'; -const {RNSentry, RNSentryEventEmitter} = NativeModules; - -import {RavenClient} from './RavenClient'; -import {NativeClient} from './NativeClient'; - -export const SentrySeverity = { - Fatal: 'fatal', - Error: 'error', - Warning: 'warning', - Info: 'info', - Debug: 'debug', - Critical: 'critical' -}; - -export const SentryLog = { - None: 0, - Error: 1, - Debug: 2, - Verbose: 3 -}; - -export const Sentry = { - async install() { - // We have to first setup raven otherwise react-native will freeze the options - // and some properties like ignoreErrors can not be mutated by raven-js - Sentry._ravenClient = new RavenClient(Sentry._dsn, Sentry.options); - if ( - RNSentry && - RNSentry.nativeClientAvailable && - Sentry.options.disableNativeIntegration === false - ) { - Sentry._nativeClient = new NativeClient(Sentry._dsn, Sentry.options); - Sentry.eventEmitter = new NativeEventEmitter(RNSentryEventEmitter); - Sentry.eventEmitter.addListener( - RNSentryEventEmitter.EVENT_SENT_SUCCESSFULLY, - event => { - Sentry._lastEvent = event; - if (Sentry._eventSentSuccessfully) Sentry._eventSentSuccessfully(event); - } - ); - Sentry.eventEmitter.addListener(RNSentryEventEmitter.EVENT_STORED, () => { - if (Sentry._internalEventStored) Sentry._internalEventStored(); - }); - } - if (Sentry._nativeClient) { - return Sentry._nativeClient.install().then(() => { - Sentry._ravenClient.install(); - }); - } else { - // We need to call install here since this add the callback for sending events - // over the native bridge - return Sentry._ravenClient.install(); - } - }, - - config(dsn, options) { - if (typeof dsn !== 'string') { - throw new Error('Sentry: A DSN must be provided'); - } - Sentry._dsn = dsn; - Sentry.options = { - logLevel: SentryLog.None, - instrument: false, - disableNativeIntegration: false, - handlePromiseRejection: true - }; - Object.assign(Sentry.options, options); - return Sentry; - }, - - isNativeClientAvailable() { - return ( - Sentry._nativeClient !== undefined && - Sentry.options.disableNativeIntegration === false - ); - }, - - _log(...args) { - if (Sentry.options && Sentry.options.logLevel >= 2) { - // eslint-disable-next-line - console.log.apply(null, args); - } - }, - - crash() { - throw new Error('Sentry: TEST crash'); - }, - - nativeCrash() { - if (Sentry.isNativeClientAvailable()) Sentry._nativeClient.nativeCrash(); - }, - - setEventSentSuccessfully(callback) { - Sentry._eventSentSuccessfully = callback; - }, - - setShouldSendCallback(callback) { - Sentry._log('react-native-sentry (setShouldSendCallback):', callback); - if (Sentry._ravenClient) Sentry._ravenClient.setShouldSendCallback(callback); - }, - - setDataCallback(callback) { - Sentry._log('react-native-sentry (setDataCallback):', callback); - if (Sentry._ravenClient) Sentry._ravenClient.setDataCallback(callback); - }, - - setUserContext(user) { - Sentry._log('react-native-sentry (setUserContext):', user); - if (Sentry._ravenClient) Sentry._ravenClient.setUserContext(user); - if (Sentry.isNativeClientAvailable()) Sentry._nativeClient.setUserContext(user); - }, - - setTagsContext(tags) { - Sentry._log('react-native-sentry (setTagsContext):', tags); - if (Sentry._ravenClient) Sentry._ravenClient.setTagsContext(tags); - if (Sentry.isNativeClientAvailable()) Sentry._nativeClient.setTagsContext(tags); - }, - - setExtraContext(extra) { - Sentry._log('react-native-sentry (setExtraContext):', extra); - if (Sentry._ravenClient) Sentry._ravenClient.setExtraContext(extra); - if (Sentry.isNativeClientAvailable()) Sentry._nativeClient.setExtraContext(extra); - }, - - captureMessage(message, options) { - Sentry._log('react-native-sentry (captureMessage):', message, options); - if (Sentry._ravenClient) Sentry._ravenClient.captureMessage(message, options); - }, - - captureException(ex, options) { - Sentry._log('react-native-sentry (captureException):', ex, options); - if (Sentry._ravenClient) Sentry._ravenClient.captureException(ex, options); - }, - - captureBreadcrumb(breadcrumb) { - Sentry._log('react-native-sentry (captureBreadcrumb):', breadcrumb); - if (Sentry._ravenClient) Sentry._ravenClient.captureBreadcrumb(breadcrumb); - }, - - async clearContext() { - Sentry._log('react-native-sentry (clearContext)'); - if (Sentry.isNativeClientAvailable()) Sentry._nativeClient.clearContext(); - if (Sentry._ravenClient) Sentry._ravenClient.clearContext(); - }, - - async crashedLastLaunch() { - return await RNSentry.crashedLastLaunch(); - }, - - context(options, func, args) { - Sentry._log('react-native-sentry (context)'); - if (Sentry._ravenClient) return Sentry._ravenClient.context(options, func, args); - return this; - }, - - wrap(options, func, _before) { - Sentry._log('react-native-sentry (wrap)'); - if (Sentry._ravenClient) return Sentry._ravenClient.wrap(options, func, _before); - return this; - }, - - lastException() { - if (Sentry._lastEvent) return Sentry._lastEvent; - return null; - }, - - lastEventId() { - if (Sentry._lastEvent) return Sentry._lastEvent.event_id; - return null; - }, - - setRelease(release) { - Sentry._log('react-native-sentry (setRelease)'); - Sentry._setInternalOption('release', release); - if (Sentry._ravenClient) Sentry._ravenClient.setRelease(release); - }, - - setDist(dist) { - Sentry._setInternalOption('dist', dist); - }, - - setVersion(version) { - Sentry._setInternalOption('version', version); - }, - - // Private helpers - - _setInternalOption(key, value) { - if (Sentry.isNativeClientAvailable()) { - Sentry._nativeClient.addExtraContext('__sentry_' + key, value); - } - if (undefined === Sentry.options.internal) { - Sentry.options.internal = {}; - } - Sentry.options.internal[key] = value; - }, - - _getInternalOption(key) { - return Sentry.options.internal[key]; - }, - - _breadcrumbCallback(crumb) { - if (Sentry.isNativeClientAvailable()) Sentry._nativeClient.captureBreadcrumb(crumb); - }, - - _captureEvent(event) { - if (Sentry.isNativeClientAvailable()) Sentry._nativeClient.captureEvent(event); - }, - - _setInternalEventStored(callback) { - Sentry._internalEventStored = callback; - } -}; - -export default Sentry; diff --git a/lib/raven-plugin.js b/lib/raven-plugin.js deleted file mode 100644 index e7554e764..000000000 --- a/lib/raven-plugin.js +++ /dev/null @@ -1,295 +0,0 @@ -/*global ErrorUtils:false*/ - -/** - * react-native plugin for Raven - * - * Usage: - * var Raven = require('raven-js'); - * Raven.addPlugin(require('raven-js/plugins/react-native')); - * - * Options: - * - * pathStrip: A RegExp that matches the portions of a file URI that should be - * removed from stacks prior to submission. - * - * onInitialize: A callback that fires once the plugin has fully initialized - * and checked for any previously thrown fatals. If there was a fatal, its - * data payload will be passed as the first argument of the callback. - * - */ -'use strict'; -import {NativeModules} from 'react-native'; -import {Sentry} from './Sentry'; - -function wrappedCallback(callback) { - function dataCallback(data, original) { - var normalizedData = callback(data) || data; - if (original) { - return original(normalizedData) || normalizedData; - } - return normalizedData; - } - return dataCallback; -} - -// Example React Native path format (iOS): -// /var/containers/Bundle/Application/{DEVICE_ID}/HelloWorld.app/main.jsbundle - -var PATH_STRIP_RE = /^.*\/[^\.]+(\.app|CodePush|.*(?=\/))/; -var FATAL_ERROR_KEY = '--rn-fatal--'; -var ASYNC_STORAGE_KEY = '--raven-js-global-error-payload--'; - -/** - * Strip device-specific IDs from React Native file:// paths - * Ensure path begins with / (after app://) to ensure source code and map path can be found - */ -function normalizeUrl(url, pathStripRe) { - const normUrl = url.replace(/^file\:\/\//, '').replace(pathStripRe, ''); - if (normUrl.indexOf('/') !== 0) { - return 'app:///' + normUrl; - } - return 'app://' + normUrl; -} - -/** - * Extract key/value pairs from an object and encode them for - * use in a query string - */ -function urlencode(obj) { - var pairs = []; - for (var key in obj) { - if ({}.hasOwnProperty.call(obj, key)) - pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])); - } - return pairs.join('&'); -} - -/** - * Initializes React Native plugin - */ -function reactNativePlugin(Raven, options, internalDataCallback) { - options = options || {}; - - // Use data callback to strip device-specific paths from stack traces - Raven.setDataCallback( - wrappedCallback(function(data) { - data = reactNativePlugin._normalizeData(data, options.pathStrip); - if (internalDataCallback) { - internalDataCallback(data); - } - }) - ); - - if (options.nativeClientAvailable === false) { - // react-native doesn't have a document, so can't use default Image - // transport - use XMLHttpRequest instead - Raven.setTransport(reactNativePlugin._transport); - - // Check for a previously persisted payload, and report it. - reactNativePlugin._restorePayload().then(function(payload) { - options.onInitialize && options.onInitialize(payload); - if (!payload) return; - Raven._sendProcessedPayload(payload, function(error) { - if (error) return; // Try again next launch. - reactNativePlugin._clearPayload(); - }); - })['catch'](function() {}); - - Raven.setShouldSendCallback(function(data, originalCallback) { - if (!(FATAL_ERROR_KEY in data)) { - // not a fatal (will not crash runtime), continue as planned - return originalCallback ? originalCallback.call(this, data) : true; - } - - var origError = data[FATAL_ERROR_KEY]; - delete data[FATAL_ERROR_KEY]; - - reactNativePlugin._persistPayload(data).then(function() { - defaultHandler(origError, true); - handlingFatal = false; // In case it isn't configured to crash. - return null; - })['catch'](function() {}); - - return false; // Do not continue. - }); - } - - // Make sure that if multiple fatals occur, we only persist the first one. - // - // The first error is probably the most important/interesting error, and we - // want to crash ASAP, rather than potentially queueing up multiple errors. - var handlingFatal = false; - - var defaultHandler = - (ErrorUtils.getGlobalHandler && ErrorUtils.getGlobalHandler()) || - ErrorUtils._globalHandler; - - if (options.handlePromiseRejection) { - // Track unhandled promise rejections - var tracking = require('promise/setimmediate/rejection-tracking'); - tracking.disable(); - tracking.enable({ - allRejections: true, - onUnhandled: function(id, error) { - var captureOptions = { - timestamp: new Date() / 1000, - type: 'Unhandled Promise Rejection' - }; - Raven.captureException(error, captureOptions); - }, - onHandled: function() {} - }); - } - - ErrorUtils.setGlobalHandler(function(error, isFatal) { - var captureOptions = { - timestamp: new Date() / 1000 - }; - var error = arguments[0]; - if (isFatal) { - captureOptions.level = 'fatal'; - } - // We want to handle fatals, but only in production mode. - var shouldHandleFatal = isFatal && !global.__DEV__; - if (shouldHandleFatal) { - if (handlingFatal) { - console.log('Encountered multiple fatals in a row. The latest:', error); - return; - } - handlingFatal = true; - // We need to preserve the original error so that it can be rethrown - // after it is persisted (see our shouldSendCallback above). - captureOptions[FATAL_ERROR_KEY] = error; - } - Raven.captureException(error, captureOptions); - if (options.nativeClientAvailable) { - // We always want to tunnel errors to the default handler - Sentry._setInternalEventStored(() => { - defaultHandler(error, isFatal); - }); - } else { - // if we don't have a native - defaultHandler(error, isFatal); - } - }); -} - -/** - * Saves the payload for a globally-thrown error, so that we can report it on - * next launch. - * - * Returns a promise that guarantees never to reject. - */ -reactNativePlugin._persistPayload = function(payload) { - var AsyncStorage = require('react-native').AsyncStorage; - return AsyncStorage.setItem(ASYNC_STORAGE_KEY, JSON.stringify(payload))[ - 'catch' - ](function() { - return null; - }); -}; - -/** - * Checks for any previously persisted errors (e.g. from last crash) - * - * Returns a promise that guarantees never to reject. - */ -reactNativePlugin._restorePayload = function() { - var AsyncStorage = require('react-native').AsyncStorage; - var promise = AsyncStorage.getItem(ASYNC_STORAGE_KEY).then(function(payload) { - return JSON.parse(payload); - })['catch'](function() { - return null; - }); - // Make sure that we fetch ASAP. - var RCTAsyncSQLiteStorage = NativeModules.AsyncSQLiteDBStorage; - var RCTAsyncRocksDBStorage = NativeModules.AsyncRocksDBStorage; - var RCTAsyncFileStorage = NativeModules.AsyncLocalStorage; - var RCTAsyncStorage = - RCTAsyncRocksDBStorage || RCTAsyncSQLiteStorage || RCTAsyncFileStorage; - if (RCTAsyncStorage.multiGet) { - AsyncStorage.flushGetRequests(); - } - - return promise; -}; - -/** - * Clears any persisted payloads. - */ -reactNativePlugin._clearPayload = function() { - var AsyncStorage = require('react-native').AsyncStorage; - return AsyncStorage.removeItem(ASYNC_STORAGE_KEY)['catch'](function() { - return null; - }); -}; - -/** - * Custom HTTP transport for use with React Native applications. - */ -reactNativePlugin._transport = function(options) { - var request = new XMLHttpRequest(); - request.onreadystatechange = function(e) { - if (request.readyState !== 4) { - return; - } - - if (request.status === 200) { - if (options.onSuccess) { - options.onSuccess(); - } - } else { - if (options.onError) { - var err = new Error('Sentry error code: ' + request.status); - err.request = request; - options.onError(err); - } - } - }; - - request.open('POST', options.url + '?' + urlencode(options.auth)); - - // NOTE: React Native ignores CORS and will NOT send a preflight - // request for application/json. - // See: https://facebook.github.io/react-native/docs/network.html#xmlhttprequest - request.setRequestHeader('Content-type', 'application/json'); - - // Sentry expects an Origin header when using HTTP POST w/ public DSN. - // Just set a phony Origin value; only matters if Sentry Project is configured - // to whitelist specific origins. - request.setRequestHeader('Origin', 'react-native://'); - request.send(JSON.stringify(options.data)); -}; - -/** - * Strip device-specific IDs found in transaction and frame filenames - * when running React Native applications on a physical device. - */ -reactNativePlugin._normalizeData = function(data, pathStripRe) { - if (!pathStripRe) { - pathStripRe = PATH_STRIP_RE; - } - - if (data.culprit) { - data.culprit = normalizeUrl(data.culprit, pathStripRe); - } - - if (data.transaction) { - data.transaction = normalizeUrl(data.transaction, pathStripRe); - } - - // NOTE: if data.exception exists, exception.values and exception.values[0] are - // guaranteed to exist - var stacktrace = - data.stacktrace || (data.exception && data.exception.values[0].stacktrace); - if (stacktrace) { - stacktrace.frames.forEach(function(frame) { - if (frame.filename !== '[native code]') { - frame.filename = normalizeUrl(frame.filename, pathStripRe); - } - }); - } - return data; -}; - -module.exports = reactNativePlugin; diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 270e30904..000000000 --- a/package-lock.json +++ /dev/null @@ -1,2640 +0,0 @@ -{ - "name": "react-native-sentry", - "version": "0.43.2", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@samverschueren/stream-to-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", - "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", - "dev": true, - "requires": { - "any-observable": "0.3.0" - } - }, - "@sentry/wizard": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@sentry/wizard/-/wizard-0.12.1.tgz", - "integrity": "sha512-kSqGcETUHR6n3DlyU/gcCwu+fcDVveEFXmLqGvib7c4nlV/ZwxT0J9TQi2u3Ux5EZQjYjTsdtvw6PYXvPXRPZA==", - "requires": { - "@sentry/cli": "1.37.0", - "chalk": "2.4.1", - "glob": "7.1.3", - "inquirer": "6.2.1", - "lodash": "4.17.11", - "opn": "5.4.0", - "r2": "2.0.1", - "read-env": "1.3.0", - "xcode": "git+https://github.com/apache/cordova-node-xcode.git#e7646f0680d509b590b839e567c217590451505b", - "yargs": "12.0.5" - }, - "dependencies": { - "@sentry/cli": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-1.37.0.tgz", - "integrity": "sha512-xNVclYfg/YkwAFA9Nv6dsvDYeZmH8vSA8I4sTZ8aRg8meAHxMyTCNv9ZwkfGlSYn2hQND9VlTiolx0od0LZ0Eg==", - "requires": { - "fs-copy-file-sync": "1.1.1", - "https-proxy-agent": "2.2.1", - "mkdirp": "0.5.1", - "node-fetch": "2.2.0", - "progress": "2.0.0", - "proxy-from-env": "1.0.0" - } - }, - "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==" - }, - "opn": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", - "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", - "requires": { - "is-wsl": "1.1.0" - } - }, - "read-env": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/read-env/-/read-env-1.3.0.tgz", - "integrity": "sha512-DbCgZ8oHwZreK/E2E27RGk3EUPapMhYGSGIt02k9sX6R3tCFc4u4tkltKvkCvzEQ3SOLUaiYHAnGb+TdsnPp0A==", - "requires": { - "camelcase": "5.0.0" - } - } - } - }, - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "requires": { - "es6-promisify": "5.0.0" - } - }, - "ansi-escapes": { - "version": "3.1.0", - "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "1.9.2" - } - }, - "any-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", - "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "1.0.3" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "base64-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.1.2.tgz", - "integrity": "sha1-1kAMrBxMZgl22Q0HoENR2JOV9eg=" - }, - "big-integer": { - "version": "1.6.23", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.23.tgz", - "integrity": "sha1-6F1QgiDHTj9DpM5y7tUfPaTblNE=" - }, - "bplist-creator": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.7.tgz", - "integrity": "sha1-N98VNgkoJLh8QvlXsBNEEXNyrkU=", - "requires": { - "stream-buffers": "2.2.0" - } - }, - "bplist-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.1.1.tgz", - "integrity": "sha1-1g1dzCDLptx+HymbNdPh+V2vuuY=", - "requires": { - "big-integer": "1.6.23" - } - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "repeat-element": "1.1.3", - "snapdragon": "0.8.2", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.2.1", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.0", - "to-object-path": "0.3.0", - "union-value": "1.0.0", - "unset-value": "1.0.0" - } - }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "requires": { - "callsites": "2.0.0" - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "requires": { - "caller-callsite": "2.0.0" - } - }, - "callsites": { - "version": "2.0.0", - "resolved": "http://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.5.0" - } - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - } - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "requires": { - "restore-cursor": "2.0.0" - } - }, - "cli-truncate": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", - "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", - "dev": true, - "requires": { - "slice-ansi": "0.0.4", - "string-width": "1.0.2" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "cli-width": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", - "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=" - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" - } - }, - "color-convert": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", - "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", - "requires": { - "color-name": "1.1.1" - } - }, - "color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" - }, - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "cosmiconfig": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz", - "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==", - "dev": true, - "requires": { - "import-fresh": "2.0.0", - "is-directory": "0.3.1", - "js-yaml": "3.12.0", - "parse-json": "4.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.2.14" - } - }, - "date-fns": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", - "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "elegant-spinner": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "0.2.1" - } - }, - "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "requires": { - "es6-promise": "4.2.4" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "external-editor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", - "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", - "requires": { - "chardet": "0.7.0", - "iconv-lite": "0.4.24", - "tmp": "0.0.33" - }, - "dependencies": { - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": "2.1.2" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "requires": { - "escape-string-regexp": "1.0.5" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "find-parent-dir": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "0.2.2" - } - }, - "fs-copy-file-sync": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz", - "integrity": "sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ==" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" - }, - "get-own-enumerable-property-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", - "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", - "requires": { - "agent-base": "4.2.1", - "debug": "3.1.0" - } - }, - "husky": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz", - "integrity": "sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA==", - "dev": true, - "requires": { - "is-ci": "1.2.1", - "normalize-path": "1.0.0", - "strip-indent": "2.0.0" - } - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "requires": { - "caller-path": "2.0.0", - "resolve-from": "3.0.0" - } - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "inquirer": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.1.tgz", - "integrity": "sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg==", - "requires": { - "ansi-escapes": "3.1.0", - "chalk": "2.4.1", - "cli-cursor": "2.1.0", - "cli-width": "2.1.0", - "external-editor": "3.0.3", - "figures": "2.0.0", - "lodash": "4.17.11", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rxjs": "6.3.3", - "string-width": "2.1.1", - "strip-ansi": "5.0.0", - "through": "2.3.8" - }, - "dependencies": { - "ansi-regex": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", - "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==" - }, - "strip-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", - "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", - "requires": { - "ansi-regex": "4.0.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "1.6.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-observable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", - "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", - "dev": true, - "requires": { - "symbol-observable": "1.2.0" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "jest-get-type": { - "version": "22.4.3", - "resolved": "http://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", - "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", - "dev": true - }, - "jest-validate": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz", - "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==", - "dev": true, - "requires": { - "chalk": "2.4.1", - "jest-get-type": "22.4.3", - "leven": "2.1.0", - "pretty-format": "23.6.0" - } - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "1.0.10", - "esprima": "4.0.1" - } - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", - "dev": true - }, - "lint-staged": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-7.3.0.tgz", - "integrity": "sha512-AXk40M9DAiPi7f4tdJggwuKIViUplYtVj1os1MVEteW7qOkU50EOehayCfO9TsoGK24o/EsWb41yrEgfJDDjCw==", - "dev": true, - "requires": { - "chalk": "2.4.1", - "commander": "2.19.0", - "cosmiconfig": "5.0.7", - "debug": "3.1.0", - "dedent": "0.7.0", - "execa": "0.9.0", - "find-parent-dir": "0.3.0", - "is-glob": "4.0.0", - "is-windows": "1.0.2", - "jest-validate": "23.6.0", - "listr": "0.14.3", - "lodash": "4.17.11", - "log-symbols": "2.2.0", - "micromatch": "3.1.10", - "npm-which": "3.0.1", - "p-map": "1.2.0", - "path-is-inside": "1.0.2", - "pify": "3.0.0", - "please-upgrade-node": "3.1.1", - "staged-git-files": "1.1.1", - "string-argv": "0.0.2", - "stringify-object": "3.3.0" - }, - "dependencies": { - "execa": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.9.0.tgz", - "integrity": "sha512-BbUMBiX4hqiHZUA5+JujIjNb6TyAlp2D5KLheMjMluwOuzcnylDL4AxZYLLn1n2AGB49eSWwyKvvEQoRpnAtmA==", - "dev": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - } - } - }, - "listr": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", - "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", - "dev": true, - "requires": { - "@samverschueren/stream-to-observable": "0.3.0", - "is-observable": "1.1.0", - "is-promise": "2.1.0", - "is-stream": "1.1.0", - "listr-silent-renderer": "1.1.1", - "listr-update-renderer": "0.5.0", - "listr-verbose-renderer": "0.5.0", - "p-map": "2.0.0", - "rxjs": "6.3.3" - }, - "dependencies": { - "p-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.0.0.tgz", - "integrity": "sha512-GO107XdrSUmtHxVoi60qc9tUl/KkNKm+X2CF4P9amalpGxv5YqVPJNfSb0wcA+syCopkZvYYIzW8OVTQW59x/w==", - "dev": true - } - } - }, - "listr-silent-renderer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", - "dev": true - }, - "listr-update-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", - "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", - "dev": true, - "requires": { - "chalk": "1.1.3", - "cli-truncate": "0.2.1", - "elegant-spinner": "1.0.1", - "figures": "1.7.0", - "indent-string": "3.2.0", - "log-symbols": "1.0.2", - "log-update": "2.3.0", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, - "requires": { - "chalk": "1.1.3" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "listr-verbose-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", - "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", - "dev": true, - "requires": { - "chalk": "2.4.1", - "cli-cursor": "2.1.0", - "date-fns": "1.29.0", - "figures": "2.0.0" - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "2.4.1" - } - }, - "log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", - "dev": true, - "requires": { - "ansi-escapes": "3.1.0", - "cli-cursor": "2.1.0", - "wrap-ansi": "3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", - "dev": true, - "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0" - } - } - } - }, - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "dev": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "requires": { - "p-defer": "1.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "1.0.1" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.13", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - } - }, - "mimic-fn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "1.1.8" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, - "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "fragment-cache": "0.2.1", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - } - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, - "node-fetch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.2.0.tgz", - "integrity": "sha512-OayFWziIxiHY8bCUyLX6sTpDH8Jsbp4FfYd1j1f7vZyfgkcOnAyM4oQR16f8a0s7Gl/viMGRey8eScYk4V4EZA==" - }, - "normalize-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", - "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", - "dev": true - }, - "npm-path": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", - "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", - "dev": true, - "requires": { - "which": "1.2.14" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "2.0.1" - } - }, - "npm-which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", - "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", - "dev": true, - "requires": { - "commander": "2.19.0", - "npm-path": "2.0.4", - "which": "1.2.14" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "requires": { - "mimic-fn": "1.1.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-is-promise": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" - }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true - }, - "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==" - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "1.3.2", - "json-parse-better-errors": "1.0.2" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "please-upgrade-node": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz", - "integrity": "sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==", - "dev": true, - "requires": { - "semver-compare": "1.0.0" - } - }, - "plist": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/plist/-/plist-2.0.1.tgz", - "integrity": "sha1-CjLKlIGxw2TpLhjcVch23p0B2os=", - "requires": { - "base64-js": "1.1.2", - "xmlbuilder": "8.2.2", - "xmldom": "0.1.27" - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "prettier": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.15.3.tgz", - "integrity": "sha512-gAU9AGAPMaKb3NNSUUuhhFAS7SCO4ALTN4nRIn6PJ075Qd28Yn2Ig2ahEJWdJwJmlEBTUfC7mMUSFy8MwsOCfg==", - "dev": true - }, - "pretty-format": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", - "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", - "dev": true, - "requires": { - "ansi-regex": "3.0.0", - "ansi-styles": "3.2.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - } - } - }, - "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" - }, - "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=" - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "r2": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/r2/-/r2-2.0.1.tgz", - "integrity": "sha512-EEmxoxYCe3LHzAUhRIRxdCKERpeRNmlLj6KLUSORqnK6dWl/K5ShmDGZqM2lRZQeqJgF+wyqk0s1M7SWUveNOQ==", - "requires": { - "caseless": "0.12.0", - "node-fetch": "2.2.0", - "typedarray-to-buffer": "3.1.5" - } - }, - "raven-js": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.27.0.tgz", - "integrity": "sha512-vChdOL+yzecfnGA+B5EhEZkJ3kY3KlMzxEhShKh6Vdtooyl0yZfYNFQfYzgMf2v4pyQa+OTZ5esTxxgOOZDHqw==" - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" - } - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-in-file": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-3.4.2.tgz", - "integrity": "sha512-wb2EU5MBBqUty+b1xSIqa0IKs5M2/a+4Ldw8KM5Gpe1btv16K0eii6nMxyNhAmRZhCEPrge0ss5Ij9f7vJEYcw==", - "dev": true, - "requires": { - "chalk": "2.4.1", - "glob": "7.1.3", - "yargs": "12.0.5" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "requires": { - "is-promise": "2.1.0" - } - }, - "rxjs": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", - "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", - "requires": { - "tslib": "1.9.3" - } - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "0.1.15" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "simple-plist": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-0.2.1.tgz", - "integrity": "sha1-cXZts1IyaSjPOoByQrp2IyJjZyM=", - "requires": { - "bplist-creator": "0.0.7", - "bplist-parser": "0.1.1", - "plist": "2.0.1" - } - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.2", - "use": "3.1.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "2.1.2", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "3.0.2" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "staged-git-files": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.1.tgz", - "integrity": "sha512-H89UNKr1rQJvI1c/PIR3kiAMBV23yvR7LItZiV74HWZwzt7f3YHuujJ9nJZlt58WlFox7XQsOahexwk7nTe69A==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - } - } - }, - "stream-buffers": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", - "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=" - }, - "string-argv": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz", - "integrity": "sha1-2sMECGkMIfPDYwo/86BYd73L1zY=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dev": true, - "requires": { - "get-own-enumerable-property-symbols": "3.0.0", - "is-obj": "1.0.1", - "is-regexp": "1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "3.0.0" - } - }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "1.0.2" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "regex-not": "1.0.2", - "safe-regex": "1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" - } - }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "requires": { - "is-typedarray": "1.0.0" - } - }, - "typescript": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", - "dev": true - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" - } - } - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "uuid": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", - "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=" - }, - "which": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", - "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", - "requires": { - "isexe": "2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "2.1.1", - "strip-ansi": "3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "xcode": { - "version": "git+https://github.com/apache/cordova-node-xcode.git#e7646f0680d509b590b839e567c217590451505b", - "requires": { - "simple-plist": "0.2.1", - "uuid": "3.0.1" - } - }, - "xmlbuilder": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", - "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=" - }, - "xmldom": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", - "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "requires": { - "cliui": "4.1.0", - "decamelize": "1.2.0", - "find-up": "3.0.0", - "get-caller-file": "1.0.2", - "os-locale": "3.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "11.1.1" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "1.0.5", - "path-key": "2.0.1", - "semver": "5.6.0", - "shebang-command": "1.2.0", - "which": "1.2.14" - } - }, - "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", - "requires": { - "cross-spawn": "6.0.5", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "3.0.0" - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "requires": { - "invert-kv": "2.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "3.0.0", - "path-exists": "3.0.0" - } - }, - "mem": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", - "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", - "requires": { - "map-age-cleaner": "0.1.3", - "mimic-fn": "1.1.0", - "p-is-promise": "1.1.0" - } - }, - "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", - "requires": { - "execa": "0.10.0", - "lcid": "2.0.0", - "mem": "4.0.0" - } - }, - "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", - "requires": { - "p-try": "2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "2.0.0" - } - } - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "requires": { - "camelcase": "5.0.0", - "decamelize": "1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==" - } - } - } - } -} diff --git a/package.json b/package.json index ebb843efa..9b8e4628e 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,19 @@ { - "name": "react-native-sentry", - "homepage": "https://github.com/getsentry/react-native-sentry", - "repository": "https://github.com/getsentry/react-native-sentry", - "version": "0.43.2", + "name": "@sentry/react-native", + "homepage": "https://github.com/getsentry/sentry-react-native", + "repository": "https://github.com/getsentry/sentry-react-native", + "version": "1.0.0", "description": "Official Sentry SDK for react-native", - "typings": "lib/Sentry.d.ts", - "types": "./lib/Sentry.d.ts", + "typings": "dist/js/index.d.ts", + "types": "dist/js/index.d.ts", "typescript": { - "definition": "lib/Sentry.d.ts" + "definition": "dist/js/index.d.ts" }, - "main": "index.js", + "main": "dist/js/index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "test:typescript": "node_modules/typescript/bin/tsc --noImplicitAny --allowJs typescript/Sentry-tests.ts" + "build": "tsc -p tsconfig.build.json", + "build:watch": "tsc -p tsconfig.build.json -w --preserveWatchOutput", + "clean": "rimraf dist coverage" }, "keywords": [ "react-native", @@ -26,8 +27,12 @@ "react-native": ">=0.56.0" }, "dependencies": { - "@sentry/wizard": "^0.13.0", - "raven-js": "^3.27.1" + "@sentry/browser": "^5.4.3", + "@sentry/core": "^5.4.3", + "@sentry/integrations": "^5.4.2", + "@sentry/types": "^5.4.2", + "@sentry/utils": "^5.4.2", + "@sentry/wizard": "^1.0.0" }, "rnpm": { "commands": { @@ -44,8 +49,11 @@ } }, "devDependencies": { - "prettier": "^1.12.1", - "replace-in-file": "^3.4.0", - "typescript": "^2.8.3" + "@sentry/typescript": "5.*", + "@types/react-native": "^0.57.57", + "prettier": "^1.17.0", + "replace-in-file": "^4.0.0", + "rimraf": "^2.6.3", + "typescript": "^3.4.5" } } diff --git a/scripts/version-bump.js b/scripts/version-bump.js index b1cd016cd..3618f7848 100644 --- a/scripts/version-bump.js +++ b/scripts/version-bump.js @@ -1,14 +1,14 @@ -const replace = require('replace-in-file'); -const pjson = require('../package.json'); +const replace = require("replace-in-file"); +const pjson = require("../package.json"); replace({ - files: ['ios/RNSentry.m', 'android/src/main/java/io/sentry/RNSentryModule.java'], + files: ["src/version.ts"], from: /\d+\.\d+.\d+/g, to: pjson.version }) .then(changedFiles => { - console.log('Modified files:', changedFiles.join(', ')); + console.log("Modified files:", changedFiles.join(", ")); }) .catch(error => { - console.error('Error occurred:', error); + console.error("Error occurred:", error); }); diff --git a/src/js/backend.ts b/src/js/backend.ts new file mode 100644 index 000000000..fd57b99b3 --- /dev/null +++ b/src/js/backend.ts @@ -0,0 +1,132 @@ +import { BrowserOptions, Transports } from "@sentry/browser"; +import { NoopTransport } from "@sentry/core"; +import { BrowserBackend } from "@sentry/browser/dist/backend"; +import { BaseBackend } from "@sentry/core"; +import { Event, EventHint, Severity, Transport } from "@sentry/types"; +import { SyncPromise } from "@sentry/utils"; +import { Alert, NativeModules, YellowBox } from "react-native"; + +import { NativeTransport } from "./transports/native"; + +const { RNSentry } = NativeModules; + +/** + * Configuration options for the Sentry ReactNative SDK. + * @see ReactNativeFrontend for more information. + */ +export interface ReactNativeOptions extends BrowserOptions { + /** + * Enables native transport + device info + offline caching. + * Be careful, disabling this also breaks automatic release setting. + * This means you have to manage setting the release yourself. + * Defaults to `true`. + */ + enableNative: boolean; + + /** + * Enables native crashHandling. This only works if `enableNative` is `true`. + * Defaults to `true`. + */ + enableNativeCrashHandling: boolean; + + /** Maximum time to wait to drain the request queue, before the process is allowed to exit. */ + shutdownTimeout?: number; +} + +/** The Sentry ReactNative SDK Backend. */ +export class ReactNativeBackend extends BaseBackend { + private readonly _browserBackend: BrowserBackend; + + /** Creates a new ReactNative backend instance. */ + public constructor(protected readonly _options: ReactNativeOptions) { + super(_options); + this._browserBackend = new BrowserBackend(_options); + + // This is a workaround for now using fetch on RN, this is a known issue in react-native and only generates a warning + YellowBox.ignoreWarnings(["Require cycle:"]); + + if ( + RNSentry && + RNSentry.nativeClientAvailable && + _options.enableNative !== false + ) { + RNSentry.startWithDsnString(_options.dsn, _options).then(() => { + RNSentry.setLogLevel(_options.debug ? 2 : 1); + }); + } else { + if (__DEV__) { + Alert.alert( + "Sentry", + "Warning, could not connect to Sentry native SDK.\nDid you forget to run \n`react-native link @sentry/react-native`?\nIf you do not want to use the native component please pass `enableNative: false` in the options.\nVisit: https://docs.sentry.io/clients/react-native/ for more details." + ); + } + } + } + + /** + * @inheritDoc + */ + protected _setupTransport(): Transport { + if (!this._options.dsn) { + // We return the noop transport here in case there is no Dsn. + return new NoopTransport(); + } + + const transportOptions = { + ...this._options.transportOptions, + dsn: this._options.dsn + }; + + if (this._options.transport) { + return new this._options.transport(transportOptions); + } + + if (this._isNativeTransportAvailable()) { + return new NativeTransport(); + } + + return new Transports.FetchTransport(transportOptions); + } + + /** + * If true, native client is availabe and active + */ + private _isNativeTransportAvailable(): boolean { + return ( + this._options.enableNative && + RNSentry.nativeClientAvailable && + RNSentry.nativeTransport + ); + } + + /** + * If native client is available it will trigger a native crash. + * Use this only for testing purposes. + */ + public nativeCrash(): void { + if (this._options.enableNative) { + RNSentry.crash(); + } + } + + /** + * @inheritDoc + */ + public eventFromException( + exception: any, + hint?: EventHint + ): SyncPromise { + return this._browserBackend.eventFromException(exception, hint); + } + + /** + * @inheritDoc + */ + public eventFromMessage( + message: string, + level: Severity = Severity.Info, + hint?: EventHint + ): SyncPromise { + return this._browserBackend.eventFromMessage(message, level, hint); + } +} diff --git a/src/js/client.ts b/src/js/client.ts new file mode 100644 index 000000000..15c74e3e1 --- /dev/null +++ b/src/js/client.ts @@ -0,0 +1,58 @@ +import { BaseClient, Scope } from "@sentry/core"; +import { Event, EventHint } from "@sentry/types"; +import { SyncPromise } from "@sentry/utils"; + +import { ReactNativeBackend, ReactNativeOptions } from "./backend"; +import { SDK_NAME, SDK_VERSION } from "./version"; + +/** + * The Sentry React Native SDK Client. + * + * @see ReactNativeOptions for documentation on configuration options. + * @see SentryClient for usage documentation. + */ +export class ReactNativeClient extends BaseClient< + ReactNativeBackend, + ReactNativeOptions +> { + /** + * Creates a new React Native SDK instance. + * @param options Configuration options for this SDK. + */ + public constructor(options: ReactNativeOptions) { + super(ReactNativeBackend, options); + } + + /** + * @inheritDoc + */ + protected _prepareEvent( + event: Event, + scope?: Scope, + hint?: EventHint + ): SyncPromise { + event.platform = event.platform || "javascript"; + event.sdk = { + ...event.sdk, + name: SDK_NAME, + packages: [ + ...((event.sdk && event.sdk.packages) || []), + { + name: "npm:@sentry/react-native", + version: SDK_VERSION + } + ], + version: SDK_VERSION + }; + + return super._prepareEvent(event, scope, hint); + } + + /** + * If native client is available it will trigger a native crash. + * Use this only for testing purposes. + */ + public nativeCrash(): void { + this._getBackend().nativeCrash(); + } +} diff --git a/src/js/index.ts b/src/js/index.ts new file mode 100644 index 000000000..529b3cddf --- /dev/null +++ b/src/js/index.ts @@ -0,0 +1,43 @@ +export { + Breadcrumb, + Request, + SdkInfo, + Event, + Exception, + Response, + Severity, + StackFrame, + Stacktrace, + Status, + Thread, + User +} from "@sentry/types"; + +export { + addGlobalEventProcessor, + addBreadcrumb, + captureException, + captureEvent, + captureMessage, + configureScope, + getHubFromCarrier, + getCurrentHub, + Hub, + Scope, + setContext, + setExtra, + setExtras, + setTag, + setTags, + setUser, + Span, + withScope +} from "@sentry/core"; + +export { ReactNativeBackend, ReactNativeOptions } from "./backend"; +export { ReactNativeClient } from "./client"; +export { init, setDist, setRelease } from "./sdk"; +export { SDK_NAME, SDK_VERSION } from "./version"; + +import * as Integrations from "./integrations"; +export { Integrations }; diff --git a/src/js/integrations/devicecontext.ts b/src/js/integrations/devicecontext.ts new file mode 100644 index 000000000..191d024e4 --- /dev/null +++ b/src/js/integrations/devicecontext.ts @@ -0,0 +1,38 @@ +import { addGlobalEventProcessor, getCurrentHub } from "@sentry/core"; +import { Event, Integration } from "@sentry/types"; +import { NativeModules } from "react-native"; + +const { RNSentry } = NativeModules; + +/** Load device context from native. */ +export class DeviceContext implements Integration { + /** + * @inheritDoc + */ + public name: string = DeviceContext.id; + /** + * @inheritDoc + */ + public static id: string = "DeviceContext"; + + /** + * @inheritDoc + */ + public setupOnce(): void { + addGlobalEventProcessor(async (event: Event) => { + const self = getCurrentHub().getIntegration(DeviceContext); + if (!self) { + return event; + } + + try { + const deviceContexts = await RNSentry.deviceContexts(); + event.contexts = { ...deviceContexts, ...event.contexts }; + } catch (_Oo) { + // Something went wrong, we just continue + } + + return event; + }); + } +} diff --git a/src/js/integrations/index.ts b/src/js/integrations/index.ts new file mode 100644 index 000000000..40e1e5dfd --- /dev/null +++ b/src/js/integrations/index.ts @@ -0,0 +1,3 @@ +export { DeviceContext } from "./devicecontext"; +export { ReactNativeErrorHandlers } from "./reactnativeerrorhandlers"; +export { Release } from "./release"; diff --git a/src/js/integrations/reactnativeerrorhandlers.ts b/src/js/integrations/reactnativeerrorhandlers.ts new file mode 100644 index 000000000..a21806c58 --- /dev/null +++ b/src/js/integrations/reactnativeerrorhandlers.ts @@ -0,0 +1,104 @@ +import { getCurrentHub } from "@sentry/core"; +import { Integration, Severity } from "@sentry/types"; +import { ReactNativeClient } from "../client"; + +/** ReactNativeErrorHandlers Options */ +interface ReactNativeErrorHandlersOptions { + onerror: boolean; + onunhandledrejection: boolean; +} + +declare const global: any; + +/** ReactNativeErrorHandlers Integration */ +export class ReactNativeErrorHandlers implements Integration { + /** + * @inheritDoc + */ + public name: string = ReactNativeErrorHandlers.id; + + /** + * @inheritDoc + */ + public static id: string = "ReactNative"; + + /** ReactNativeOptions */ + private readonly _options: ReactNativeErrorHandlersOptions; + + /** Constructor */ + public constructor(options?: ReactNativeErrorHandlersOptions) { + this._options = { + onerror: true, + onunhandledrejection: true, + ...options + }; + } + + /** + * @inheritDoc + */ + public setupOnce(): void { + this._handleUnhandledRejections(); + this._handleOnError(); + } + + private _handleUnhandledRejections(): void { + if (this._options.onunhandledrejection) { + const tracking = require("promise/setimmediate/rejection-tracking"); + tracking.disable(); + tracking.enable({ + allRejections: true, + onUnhandled: (id: any, error: any) => { + getCurrentHub().captureException(error, { + data: { id }, + originalException: error + }); + }, + onHandled: function() {} + }); + } + } + + private _handleOnError(): void { + if (this._options.onerror) { + let handlingFatal = false; + + let defaultHandler = + ErrorUtils.getGlobalHandler && ErrorUtils.getGlobalHandler(); + + ErrorUtils.setGlobalHandler((error: any, isFatal?: boolean) => { + // We want to handle fatals, but only in production mode. + const shouldHandleFatal = isFatal && !global.__DEV__; + if (shouldHandleFatal) { + if (handlingFatal) { + console.log( + "Encountered multiple fatals in a row. The latest:", + error + ); + return; + } + handlingFatal = true; + } + + getCurrentHub().withScope(scope => { + if (isFatal) { + scope.setLevel(Severity.Fatal); + } + getCurrentHub().captureException(error, { + originalException: error + }); + }); + + const client = getCurrentHub().getClient(); + if (client) { + client.flush(client.getOptions().shutdownTimeout || 2000).then(() => { + defaultHandler(error, isFatal); + }); + } else { + // If there is no client something is fishy, anyway we call the default handler + defaultHandler(error, isFatal); + } + }); + } + } +} diff --git a/src/js/integrations/release.ts b/src/js/integrations/release.ts new file mode 100644 index 000000000..93aded5e5 --- /dev/null +++ b/src/js/integrations/release.ts @@ -0,0 +1,54 @@ +import { addGlobalEventProcessor, getCurrentHub } from "@sentry/core"; +import { Event, Integration } from "@sentry/types"; +import { NativeModules } from "react-native"; + +const { RNSentry } = NativeModules; + +/** Release integration responsible to load release from file. */ +export class Release implements Integration { + /** + * @inheritDoc + */ + public name: string = Release.id; + /** + * @inheritDoc + */ + public static id: string = "Release"; + + /** + * @inheritDoc + */ + public setupOnce(): void { + addGlobalEventProcessor(async (event: Event) => { + const self = getCurrentHub().getIntegration(Release); + if (!self) { + return event; + } + + try { + const release = (await RNSentry.fetchRelease()) as { + build: string; + id: string; + version: string; + }; + if (release) { + event.release = `${release.id}-${release.version}`; + event.dist = `${release.build}`; + } + } catch (_Oo) { + // Something went wrong, we just continue + } + + // __sentry_release & __sentry_dist will be picked up by our native integration. + // It should live in extra, native will pick it up there and set it in the event. + if (event.extra && event.extra.__sentry_release && !event.release) { + event.release = `${event.extra.__sentry_release}`; + } + if (event.extra && event.extra.__sentry_dist && !event.dist) { + event.dist = `${event.extra.__sentry_dist}`; + } + + return event; + }); + } +} diff --git a/src/js/sdk.ts b/src/js/sdk.ts new file mode 100644 index 000000000..904740ee5 --- /dev/null +++ b/src/js/sdk.ts @@ -0,0 +1,91 @@ +import { + defaultIntegrations, + getCurrentHub, + Integrations +} from "@sentry/browser"; +import { RewriteFrames } from "@sentry/integrations"; +import { initAndBind } from "@sentry/core"; +import { setExtra } from "@sentry/minimal"; +import { StackFrame } from "@sentry/types"; + +import { ReactNativeOptions } from "./backend"; +import { ReactNativeClient } from "./client"; +import { + DeviceContext, + ReactNativeErrorHandlers, + Release +} from "./integrations"; + +const IGNORED_DEFAULT_INTEGRATIONS = [ + "GlobalHandlers", // We will use the react-native internal handlers + "Breadcrumbs", // We add it later, just not patching fetch + "TryCatch" // We don't need this +]; + +/** + * Inits the SDK + */ +export function init( + options: ReactNativeOptions = { + enableNative: true, + enableNativeCrashHandling: true + } +): void { + if (options.defaultIntegrations === undefined) { + options.defaultIntegrations = [ + new ReactNativeErrorHandlers(), + new Release(), + ...defaultIntegrations.filter( + i => !IGNORED_DEFAULT_INTEGRATIONS.includes(i.name) + ), + new Integrations.Breadcrumbs({ + fetch: false + }), + new RewriteFrames({ + iteratee: (frame: StackFrame) => { + if (frame.filename) { + frame.filename = + "app://" + + frame.filename + .replace(/^file\:\/\//, "") + .replace(/^.*\/[^\.]+(\.app|CodePush|.*(?=\/))/, ""); + } + return frame; + } + }), + new DeviceContext() + ]; + } + if (options.enableNative === undefined) { + options.enableNative = true; + } + if (options.enableNativeCrashHandling === undefined) { + options.enableNativeCrashHandling = true; + } + initAndBind(ReactNativeClient, options); +} + +/** + * Sets the release on the event. + */ +export function setRelease(release: string): void { + setExtra("__sentry_release", release); +} + +/** + * Sets the dist on the event. + */ +export function setDist(dist: string): void { + setExtra("__sentry_dist", dist); +} + +/** + * If native client is available it will trigger a native crash. + * Use this only for testing purposes. + */ +export function nativeCrash(): void { + const client = getCurrentHub().getClient(); + if (client) { + client.nativeCrash(); + } +} diff --git a/src/js/transports/native.ts b/src/js/transports/native.ts new file mode 100644 index 000000000..64de9a8ab --- /dev/null +++ b/src/js/transports/native.ts @@ -0,0 +1,26 @@ +import { Event, Response, Transport } from "@sentry/types"; +import { PromiseBuffer } from "@sentry/utils"; + +import { NativeModules } from "react-native"; + +const { RNSentry } = NativeModules; + +/** Native Transport class implementation */ +export class NativeTransport implements Transport { + /** A simple buffer holding all requests. */ + protected readonly _buffer: PromiseBuffer = new PromiseBuffer(30); + + /** + * @inheritDoc + */ + public sendEvent(event: Event): Promise { + return this._buffer.add(RNSentry.sendEvent(event)); + } + + /** + * @inheritDoc + */ + public close(timeout?: number): Promise { + return this._buffer.drain(timeout); + } +} diff --git a/src/js/version.ts b/src/js/version.ts new file mode 100644 index 000000000..57f3c0391 --- /dev/null +++ b/src/js/version.ts @@ -0,0 +1,2 @@ +export const SDK_NAME = 'sentry.javascript.react-native'; +export const SDK_VERSION = '1.0.0'; diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 000000000..599f6358f --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,14 @@ +{ + "extends": "./node_modules/@sentry/typescript/tsconfig.json", + "include": ["src/js/*.ts"], + "exclude": ["node_modules"], + "compilerOptions": { + "baseUrl": ".", + "outDir": "dist", + "rootDir": "src", + "lib": ["es7"], + "types": ["react-native"], + "target": "es6", + "module": "es6" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..2a7223602 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.build.json", + "include": ["src/js/*.ts", "test/**/*.ts"], + "exclude": ["dist"], + "compilerOptions": { + "rootDir": "." + } +} diff --git a/typescript/Sentry-tests.ts b/typescript/Sentry-tests.ts deleted file mode 100644 index 7ff3980f9..000000000 --- a/typescript/Sentry-tests.ts +++ /dev/null @@ -1,16 +0,0 @@ -import Sentry, {SentryLog, SentrySeverity} from '../lib/Sentry'; - -Sentry.config(null).install(); - -var options = { - logLevel: SentryLog.Verbose -}; -Sentry.config('https://public@sentry.io/1', options).install(); - -Sentry.captureMessage("test"); - -Sentry.clearContext(); - -Sentry.captureBreadcrumb({ - message: 'Message' -}); diff --git a/yarn.lock b/yarn.lock index e6b95a485..5a0ec4bb1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,39 @@ # yarn lockfile v1 -"@sentry/cli@^1.43.0": - version "1.43.0" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.43.0.tgz#c5d8cde88bf2b23882bcee7f1578edebd94d0abc" - integrity sha512-NnJTT0DjzZB8+CxaisVEEExtns5eHkIFy1nqbM8tzNZ6hREshGf5kFZPPTmHairvaVMk1KWa7w8EqNl7jg3KUA== +"@fimbul/bifrost@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@fimbul/bifrost/-/bifrost-0.17.0.tgz#f0383ba7e40992e3193dc87e2ddfde2ad62a9cf4" + integrity sha512-gVTkJAOef5HtN6LPmrtt5fAUmBywwlgmObsU3FBhPoNeXPLaIl2zywXkJEtvvVLQnaFmtff3x+wIj5lHRCDE3Q== + dependencies: + "@fimbul/ymir" "^0.17.0" + get-caller-file "^2.0.0" + tslib "^1.8.1" + tsutils "^3.5.0" + +"@fimbul/ymir@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@fimbul/ymir/-/ymir-0.17.0.tgz#4f28389b9f804d1cd202e11983af1743488b7815" + integrity sha512-xMXM9KTXRLHLVS6dnX1JhHNEkmWHcAVCQ/4+DA1KKwC/AFnGHzu/7QfQttEPgw3xplT+ILf9e3i64jrFwB3JtA== + dependencies: + inversify "^5.0.0" + reflect-metadata "^0.1.12" + tslib "^1.8.1" + +"@sentry/browser@^5.4.3": + version "5.4.3" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.4.3.tgz#c9b56611c6b7de624962d2ea3fc0a9318f44a853" + integrity sha512-5fPlco0/65RpyNy9LMURrZhX1RT1+CAoR06yU65ZB81N3oRuAGDYE85Hs62t0T3EEGTKrMundINHcq8UD1V0xw== + dependencies: + "@sentry/core" "5.4.3" + "@sentry/types" "5.4.2" + "@sentry/utils" "5.4.2" + tslib "^1.9.3" + +"@sentry/cli@^1.44.2": + version "1.46.0" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.46.0.tgz#04d69be114e84620d13c9c8cc90b4842de16913c" + integrity sha512-pZFW9U6XsbnD2pJPO5IyzN43k9wvp4sqshus22clb65mkEpa+vQ1QhL9bVAVuH4VRnu1xiEc5l9MlVlU+aeMvg== dependencies: fs-copy-file-sync "^1.1.1" https-proxy-agent "^2.2.1" @@ -14,12 +43,71 @@ progress "2.0.0" proxy-from-env "^1.0.0" -"@sentry/wizard@^0.13.0": - version "0.13.0" - resolved "https://registry.yarnpkg.com/@sentry/wizard/-/wizard-0.13.0.tgz#9eb2c2a9051f849815856293bca086725ecfc298" - integrity sha512-tI1B9NVIWZvAjgGOdI6JZuHVzIxOoO2JDNWJHD4voS4JyImko0zqGCDz15Nm4vh6RJKdHBUR841PTV2X3k2WaQ== +"@sentry/core@5.4.3", "@sentry/core@^5.4.3": + version "5.4.3" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.4.3.tgz#c9e3a6cc9f5e296c5a5e19a7a925d9ee9125a95f" + integrity sha512-VjRv9BXip2BtCSohi/WQra+Ep4B8ajer1nU1VpKy5tUCjpVfXRpitY23EdEl+MVJH7h6YPZ45JsuFiKGgrtaFQ== + dependencies: + "@sentry/hub" "5.4.3" + "@sentry/minimal" "5.4.3" + "@sentry/types" "5.4.2" + "@sentry/utils" "5.4.2" + tslib "^1.9.3" + +"@sentry/hub@5.4.3": + version "5.4.3" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.4.3.tgz#d6936f976435dd552e06a6a3e9f8cd643e9b9b3f" + integrity sha512-97bnk2dDuCdFv2xhujogqPiDDpKOsHxBXH1jOJ5ezr3/uZNsMRr450FDxxJJYDLuSx+qZ/+vUFfdVNjprBsuSg== + dependencies: + "@sentry/types" "5.4.2" + "@sentry/utils" "5.4.2" + tslib "^1.9.3" + +"@sentry/integrations@^5.4.2": + version "5.4.2" + resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-5.4.2.tgz#75312407571392badc40ee48b031fae701fee564" + integrity sha512-+nPaFdj8v2EBkZsQBF/pOIwqcf32//R3Iz37aMAWuutw0YOgJXJEaPe4GNMpk78bH3ZwVltGlW8RsDD6zgcc7A== + dependencies: + "@sentry/types" "5.4.2" + "@sentry/utils" "5.4.2" + tslib "^1.9.3" + +"@sentry/minimal@5.4.3": + version "5.4.3" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.4.3.tgz#afaa8f7a3b5074efa8d70a2edac920b2e0cdbe15" + integrity sha512-xSCcKDtVtlmJIGmnlNH2fL++4l7iORJ+pOOfTz1Yjm/Il7Tz9wLVodbEfplXmAbOvgG/x9oilbW0MBSnrwKPfQ== + dependencies: + "@sentry/hub" "5.4.3" + "@sentry/types" "5.4.2" + tslib "^1.9.3" + +"@sentry/types@5.4.2", "@sentry/types@^5.4.2": + version "5.4.2" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.4.2.tgz#4ab327bced2cfd961dc7a29f0ff43398f913f6a6" + integrity sha512-yh1fd7x5lLOIZ8W3A1I792B3jowJVCWp4HcTRikjTsjbF8lcURY62m+hiLYUFPTIX99AlFRIPiApDkWiwMGYMA== + +"@sentry/typescript@5.*": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@sentry/typescript/-/typescript-5.2.0.tgz#0741db715ef2580b351ead22fa82a923058d354f" + integrity sha512-9sAhk5Nwz+ZMNsClUJMITP0Iy80d1O8BNseS1xmhKQAc7qnfOYCqSOsNsSazQTo1QNkUBk0zOmQrHOwaU44cUA== + dependencies: + tslint-config-prettier "^1.18.0" + tslint-consistent-codestyle "^1.15.1" + +"@sentry/utils@5.4.2", "@sentry/utils@^5.4.2": + version "5.4.2" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.4.2.tgz#c88c6c08d635e1744a443cfefe9e2ed7fa250e4e" + integrity sha512-AW7/TGt2HiPQB8lJ8NgMgaFAIDQpKDF+wV8nENRbC1CP1zzcvb1QBF4zBL2auDT4fhkhVa817064s7vlDiJVLQ== + dependencies: + "@sentry/types" "5.4.2" + tslib "^1.9.3" + +"@sentry/wizard@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@sentry/wizard/-/wizard-1.0.0.tgz#6cfaf1d7622fedaba33ee3451bb0d01c4613d3bd" + integrity sha512-bxLuarABCtP1MO5dEzGBh+JH6PZenZBdnxc1neK2IKMIZ7wWsowpUzbjluECenbDqzOBPFlI2u6hAsw6dyyV6A== dependencies: - "@sentry/cli" "^1.43.0" + "@sentry/cli" "^1.44.2" chalk "^2.4.1" glob "^7.1.3" inquirer "^6.2.0" @@ -30,6 +118,27 @@ xcode "2.0.0" yargs "^12.0.2" +"@types/prop-types@*": + version "15.7.1" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.1.tgz#f1a11e7babb0c3cad68100be381d1e064c68f1f6" + integrity sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg== + +"@types/react-native@^0.57.57": + version "0.57.57" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.57.57.tgz#4b59068acf6e542ac8e1e02e8a639b47e3e02c02" + integrity sha512-OZyBlMyMeU3gXAmc1nnJhlWGihWUOiVR5Tj0y4TAA0rkKKHJwuNPPba6aaFmEaNcoZ9ejc3G30H+dneDOqICdg== + dependencies: + "@types/prop-types" "*" + "@types/react" "*" + +"@types/react@*": + version "16.8.17" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.17.tgz#f287b76a5badb93bc9aa3f54521a3eb53d6c2374" + integrity sha512-pln3mgc6VfkNg92WXODul/ONo140huK9OMsx62GlBlZ2lvjNK86PQJhYMPLO1i66aF5O9OPyZefogvNltBIszA== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + agent-base@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce" @@ -48,7 +157,12 @@ ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" -ansi-styles@^3.1.0: +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-styles@^3.1.0, ansi-styles@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" dependencies: @@ -100,6 +214,11 @@ camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + caseless@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -112,17 +231,18 @@ chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" -chalk@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.0.tgz#a060a297a6b57e15b61ca63ce84995daa0fe6e52" +chalk@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -150,6 +270,15 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -168,14 +297,6 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -186,15 +307,21 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" +csstype@^2.2.0: + version "2.6.4" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.4.tgz#d585a6062096e324e7187f80e04f92bd0f00e37f" + integrity sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg== + debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: ms "2.0.0" -decamelize@^1.1.1: +decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decamelize@^2.0.0: version "2.0.0" @@ -202,6 +329,18 @@ decamelize@^2.0.0: dependencies: xregexp "4.0.0" +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + dependencies: + once "^1.4.0" + es6-promise@^4.0.3: version "4.2.4" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" @@ -228,12 +367,13 @@ execa@^0.10.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" + cross-spawn "^6.0.0" + get-stream "^4.0.0" is-stream "^1.1.0" npm-run-path "^2.0.0" p-finally "^1.0.0" @@ -254,12 +394,6 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - dependencies: - locate-path "^2.0.0" - find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -279,20 +413,21 @@ get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" +get-caller-file@^2.0.0, get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" -glob@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" + pump "^3.0.0" glob@^7.1.3: version "7.1.3" @@ -355,9 +490,10 @@ inquirer@^6.2.0: strip-ansi "^4.0.0" through "^2.3.6" -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" +inversify@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/inversify/-/inversify-5.0.1.tgz#500d709b1434896ce5a0d58915c4a4210e34fb6e" + integrity sha512-Ieh06s48WnEYGcqHepdsJUIJUXpwH5o5vodAX+DK2JA/gjy4EbEcQZxw+uFfzysmKjiLXGYwNG3qDZsKVMcINQ== invert-kv@^2.0.0: version "2.0.0" @@ -393,25 +529,12 @@ isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - dependencies: - invert-kv "^1.0.0" - lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" dependencies: invert-kv "^2.0.0" -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -423,25 +546,12 @@ lodash@^4.17.10, lodash@^4.17.11: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" -lru-cache@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - map-age-cleaner@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz#098fb15538fd3dbe461f12745b0ca8568d4e3f74" dependencies: p-defer "^1.0.0" -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - dependencies: - mimic-fn "^1.0.0" - mem@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf" @@ -463,10 +573,12 @@ minimatch@^3.0.4: minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" @@ -500,7 +612,7 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -once@^1.3.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: @@ -518,14 +630,6 @@ opn@^5.4.0: dependencies: is-wsl "^1.1.0" -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - os-locale@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.0.1.tgz#3b014fbf01d87f60a1e5348d80fe870dc82c4620" @@ -534,6 +638,15 @@ os-locale@^3.0.0: lcid "^2.0.0" mem "^4.0.0" +os-locale@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -550,22 +663,12 @@ p-is-promise@^1.1.0: version "1.1.0" resolved "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" -p-limit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" - p-limit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" dependencies: p-try "^2.0.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - dependencies: - p-limit "^1.1.0" - p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -597,9 +700,10 @@ plist@^3.0.1: xmlbuilder "^9.0.7" xmldom "0.1.x" -prettier@^1.12.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325" +prettier@^1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.17.0.tgz#53b303676eed22cc14a9f0cec09b477b3026c008" + integrity sha512-sXe5lSt2WQlCbydGETgfm1YBShgOX4HxQkFPvbxkcwgDvGDeqVau8h+12+lmSVlP3rHPz0oavfddSZg/q+Szjw== progress@2.0.0: version "2.0.0" @@ -609,9 +713,13 @@ proxy-from-env@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" r2@^2.0.1: version "2.0.1" @@ -621,24 +729,25 @@ r2@^2.0.1: node-fetch "^2.0.0-alpha.8" typedarray-to-buffer "^3.1.2" -raven-js@^3.27.1: - version "3.27.1" - resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.27.1.tgz#e187a12982061908ccbf935af0640c9043d7d666" - integrity sha512-r/9CwSbaGfBFjo4hGR45DAmrukUKkQ4HdMu80PlVLDY1t8f9b4aaZzTsFegaafu7EGhEYougWDJ9/IcTdYdLXQ== - read-env@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/read-env/-/read-env-1.3.0.tgz#e26e1e446992b3216e9a3c6f6ac51064fe91fdff" dependencies: camelcase "5.0.0" -replace-in-file@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/replace-in-file/-/replace-in-file-3.4.0.tgz#b48c94567bbf4f44a2bc6fabdf21ab443e806851" +reflect-metadata@^0.1.12: + version "0.1.13" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" + integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== + +replace-in-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/replace-in-file/-/replace-in-file-4.0.0.tgz#824c04b453f8eaa617aa47f133e99dcbc8b19368" + integrity sha512-qbKJSOYMVSRzd10d0dOsGZoKQFMV17c2Vns9HH64pAYuPQO4xyDvwUOro2wYOk4kkerooTKbPSD6ETSdlHspuQ== dependencies: - chalk "^2.3.2" - glob "^7.1.2" - yargs "^11.0.0" + chalk "^2.4.2" + glob "^7.1.3" + yargs "^13.2.2" require-directory@^2.1.1: version "2.1.1" @@ -648,6 +757,11 @@ require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -655,6 +769,13 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +rimraf@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" @@ -721,6 +842,15 @@ string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" @@ -733,6 +863,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -759,19 +896,48 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -tslib@^1.9.0: +tslib@^1.7.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" +tslint-config-prettier@^1.18.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz#75f140bde947d35d8f0d238e0ebf809d64592c37" + integrity sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg== + +tslint-consistent-codestyle@^1.15.1: + version "1.15.1" + resolved "https://registry.yarnpkg.com/tslint-consistent-codestyle/-/tslint-consistent-codestyle-1.15.1.tgz#a0c5cd5a5860d40b659c490d8013c5732e02af8c" + integrity sha512-38Y3Dz4zcABe/PlPAQSGNEWPGVq0OzcIQR7SEU6dNujp/SgvhxhJOhIhI9gY4r0I3/TNtvVQwARWor9O9LPZWg== + dependencies: + "@fimbul/bifrost" "^0.17.0" + tslib "^1.7.1" + tsutils "^2.29.0" + +tsutils@^2.29.0: + version "2.29.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" + integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== + dependencies: + tslib "^1.8.1" + +tsutils@^3.5.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.10.0.tgz#6f1c95c94606e098592b0dff06590cf9659227d6" + integrity sha512-q20XSMq7jutbGB8luhKKsQldRKWvyBO2BGqni3p4yq8Ys9bEP/xQw3KepKmMRt9gJ4lvQSScrihJrcKdKoSU7Q== + dependencies: + tslib "^1.8.1" + typedarray-to-buffer@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.2.tgz#1017b32d984ff556eba100f501589aba1ace2e04" dependencies: is-typedarray "^1.0.0" -typescript@^2.8.3: - version "2.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.3.tgz#5d817f9b6f31bb871835f4edf0089f21abe6c170" +typescript@^3.4.5: + version "3.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99" + integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw== uuid@^3.3.2: version "3.3.2" @@ -795,6 +961,15 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -820,46 +995,23 @@ xregexp@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - -"y18n@^3.2.1 || ^4.0.0": +"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - yargs-parser@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" dependencies: camelcase "^4.1.0" -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" +yargs-parser@^13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.0.tgz#7016b6dd03e28e1418a510e258be4bff5a31138f" + integrity sha512-Yq+32PrijHRri0vVKQEm+ys8mbqWjLiwQkMFNXEENutzLPP0bE4Lcd4iA3OQY5HF+GD3xXxf0MEHb8E4/SA3AA== dependencies: - camelcase "^4.1.0" - -yargs@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.0.0.tgz#c052931006c5eee74610e5fc0354bedfd08a201b" - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" + camelcase "^5.0.0" + decamelize "^1.2.0" yargs@^12.0.2: version "12.0.2" @@ -877,3 +1029,20 @@ yargs@^12.0.2: which-module "^2.0.0" y18n "^3.2.1 || ^4.0.0" yargs-parser "^10.1.0" + +yargs@^13.2.2: + version "13.2.4" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" + integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + os-locale "^3.1.0" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.0"