UNPKG

appcenter-crashes

Version:
188 lines (160 loc) 6.51 kB
// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. const ReactNative = require('react-native'); const AppCenterLog = require('appcenter/appcenter-log'); const { AppCenterReactNativeCrashes } = ReactNative.NativeModules; const crashesEventEmitter = new ReactNative.NativeEventEmitter(AppCenterReactNativeCrashes); const LOG_TAG = 'AppCenterCrashes'; const EVENT_BEFORE_SENDING = 'AppCenterErrorReportOnBeforeSending'; const EVENT_SENDING_SUCCEEDED = 'AppCenterErrorReportOnSendingSucceeded'; const EVENT_SENDING_FAILED = 'AppCenterErrorReportOnSendingFailed'; // This is set later if and when the user provides a value for the getErrorAttachments callback let getErrorAttachmentsMethod = () => { }; const filteredReports = []; const UserConfirmation = { DONT_SEND: 0, SEND: 1, ALWAYS_SEND: 2 }; const ErrorAttachmentLog = { // Create text attachment for an error report attachmentWithText(text, fileName) { return { text, fileName }; }, // Create binary attachment for an error report, binary must be passed as a base64 string attachmentWithBinary(data, fileName, contentType) { return { data, fileName, contentType }; } }; const Crashes = { // async - returns a Promise generateTestCrash() { return AppCenterReactNativeCrashes.generateTestCrash(); }, // async - returns a Promise hasCrashedInLastSession() { return AppCenterReactNativeCrashes.hasCrashedInLastSession(); }, // async - returns a Promise lastSessionCrashReport() { return AppCenterReactNativeCrashes.lastSessionCrashReport(); }, // async - returns a Promise hasReceivedMemoryWarningInLastSession() { return AppCenterReactNativeCrashes.hasReceivedMemoryWarningInLastSession(); }, // async - returns a Promise isEnabled() { return AppCenterReactNativeCrashes.isEnabled(); }, // async - returns a Promise setEnabled(shouldEnable) { return AppCenterReactNativeCrashes.setEnabled(shouldEnable); }, // Error value should have type `ExceptionModel`. trackError(error, properties, attachments) { return AppCenterReactNativeCrashes.trackException(error, sanitizeProperties(properties), sanitizeProperties(attachments)); }, notifyUserConfirmation(userConfirmation) { switch (userConfirmation) { case UserConfirmation.DONT_SEND: case UserConfirmation.SEND: case UserConfirmation.ALWAYS_SEND: AppCenterReactNativeCrashes.notifyWithUserConfirmation(userConfirmation); break; default: AppCenterLog.error(LOG_TAG, 'Crashes.notifyUserConfirmation: Invalid parameter value.'); return; } if (userConfirmation !== UserConfirmation.DONT_SEND) { Helper.sendErrorAttachments(); } }, setListener(listenerMap) { crashesEventEmitter.removeAllListeners(EVENT_BEFORE_SENDING); crashesEventEmitter.removeAllListeners(EVENT_SENDING_SUCCEEDED); crashesEventEmitter.removeAllListeners(EVENT_SENDING_FAILED); if (!listenerMap) { return; } if (listenerMap.onBeforeSending) { crashesEventEmitter.addListener(EVENT_BEFORE_SENDING, listenerMap.onBeforeSending); } if (listenerMap.onSendingSucceeded) { crashesEventEmitter.addListener(EVENT_SENDING_SUCCEEDED, listenerMap.onSendingSucceeded); } if (listenerMap.onSendingFailed) { crashesEventEmitter.addListener(EVENT_SENDING_FAILED, listenerMap.onSendingFailed); } getErrorAttachmentsMethod = listenerMap.getErrorAttachments; Crashes.isEnabled() .then((isEnabled) => { if (isEnabled) { return AppCenterReactNativeCrashes.getUnprocessedCrashReports(); } throw new Error('Crashes service is not enabled.'); }) .then((reports) => { if (reports.length > 0) { const filteredReportIds = []; reports.forEach((report) => { if (!listenerMap.shouldProcess || listenerMap.shouldProcess(report)) { filteredReports.push(report); filteredReportIds.push(report.id); } }); return AppCenterReactNativeCrashes.sendCrashReportsOrAwaitUserConfirmationForFilteredIds(filteredReportIds); } throw new Error('No unprocessed crash reports found.'); }) .then((alwaysSend) => { if (alwaysSend) { Helper.sendErrorAttachments(); } else if (!listenerMap.shouldAwaitUserConfirmation || !listenerMap.shouldAwaitUserConfirmation()) { Crashes.notifyUserConfirmation(UserConfirmation.SEND); } }) .catch((error) => console.log(error.message)); } }; const Helper = { sendErrorAttachments() { if (!getErrorAttachmentsMethod) { return; } filteredReports.forEach((report) => { Promise.resolve(getErrorAttachmentsMethod(report)) .then((attachments) => AppCenterReactNativeCrashes.sendErrorAttachments(attachments, report.id)) .catch((error) => AppCenterLog.error(LOG_TAG, `Could not send error attachments. Error: ${error}`)); }); // Prevent multipe calls if shouldAwaitUserConfirmation is false and user calling notifyUserConfirmation for some reason filteredReports.length = 0; } }; // Exports with "curly braces". Crashes.UserConfirmation = UserConfirmation; Crashes.ErrorAttachmentLog = ErrorAttachmentLog; Crashes.ExceptionModel = class { wrapperSdkName = 'appcenter.react-native'; constructor(type, message, stack) { this.type = type; this.message = message; this.stackTrace = stack; } // Error value should have Error type. static createFromError(error) { return new this(error.name, error.message, error.stack); } static createFromTypeAndMessage(type, message, stacktrace) { return new this(type, message, stacktrace); } }; // Export main class without "curly braces". module.exports = Crashes; function sanitizeProperties(props) { if (props === null) { return undefined; } return props; }