UNPKG

@sentry/wizard

Version:

Sentry wizard helping you to configure your project

158 lines 7.43 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSentryAppConfigJsonCodeSnippet = exports.addWithSentryToAppConfigJson = exports.patchExpoAppConfig = exports.printSentryExpoMigrationOutro = exports.SENTRY_PLUGIN_FUNCTION_NAME = exports.DEPRECATED_SENTRY_EXPO_PLUGIN_NAME = exports.SENTRY_EXPO_PLUGIN_NAME = void 0; // @ts-expect-error - clack is ESM and TS complains about that. It works though const clack = __importStar(require("@clack/prompts")); const chalk_1 = __importDefault(require("chalk")); const fs = __importStar(require("fs")); const os_1 = require("os"); const Sentry = __importStar(require("@sentry/node")); const clack_1 = require("../utils/clack"); const telemetry_1 = require("../telemetry"); exports.SENTRY_EXPO_PLUGIN_NAME = '@sentry/react-native/expo'; exports.DEPRECATED_SENTRY_EXPO_PLUGIN_NAME = 'sentry-expo'; exports.SENTRY_PLUGIN_FUNCTION_NAME = 'withSentry'; const APP_CONFIG_JSON = `app.json`; function printSentryExpoMigrationOutro() { clack.outro(`Deprecated ${chalk_1.default.cyan('sentry-expo')} package installed in your dependencies. Please follow the migration guide at ${chalk_1.default.cyan('https://docs.sentry.io/platforms/react-native/migration/sentry-expo/')}`); } exports.printSentryExpoMigrationOutro = printSentryExpoMigrationOutro; /** * Finds app.json in the project root and add Sentry Expo `withSentry` plugin. */ async function patchExpoAppConfig(options) { function showInstructions() { return (0, clack_1.showCopyPasteInstructions)({ filename: APP_CONFIG_JSON, codeSnippet: getSentryAppConfigJsonCodeSnippet(options), hint: 'This ensures auto upload of source maps during native app build.', }); } const appConfigJsonExists = fs.existsSync(APP_CONFIG_JSON); Sentry.setTag('app-config-file-status', appConfigJsonExists ? 'found' : 'not-found'); if (!appConfigJsonExists) { return await showInstructions(); } const patched = await patchAppConfigJson(APP_CONFIG_JSON, options); if (!patched) { Sentry.setTag('app-config-file-status', 'patch-error'); clack.log.error(`Unable to patch ${chalk_1.default.cyan('app.config.json')}.`); return await showInstructions(); } } exports.patchExpoAppConfig = patchExpoAppConfig; async function patchAppConfigJson(path, options) { const appConfigContent = (await fs.promises.readFile(path, { encoding: 'utf-8' })).toString(); const patchedContent = (0, telemetry_1.traceStep)('app-config-json-patch', () => addWithSentryToAppConfigJson(appConfigContent, options)); if (patchedContent === null) { return false; } try { await fs.promises.writeFile(path, patchedContent); } catch (error) { Sentry.setTag('app-config-file-status', 'json-write-error'); clack.log.error(`Unable to write ${chalk_1.default.cyan('app.config.json')}.`); Sentry.captureException(`Unable to write 'app.config.json'.`); return false; } Sentry.setTag('app-config-file-status', 'json-write-success'); clack.log.success(`Added Sentry Expo plugin to ${chalk_1.default.cyan('app.config.json')}.`); return true; } function addWithSentryToAppConfigJson(appConfigContent, options) { try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const parsedAppConfig = JSON.parse(appConfigContent); const includesWithSentry = appConfigContent.includes(exports.SENTRY_EXPO_PLUGIN_NAME) || appConfigContent.includes(exports.DEPRECATED_SENTRY_EXPO_PLUGIN_NAME); if (includesWithSentry) { Sentry.setTag('app-config-file-status', 'already-patched'); clack.log.warn(`Your ${chalk_1.default.cyan('app.config.json')} already includes the Sentry Expo plugin.`); return null; } if (parsedAppConfig.expo !== undefined && !isPlainObject(parsedAppConfig.expo)) { Sentry.setTag('app-config-file-status', 'invalid-json'); clack.log.error(`Unable to find expo in your ${chalk_1.default.cyan('app.config.json')}. Make sure it has a valid format!`); return null; } if (parsedAppConfig.expo && parsedAppConfig.expo.plugins !== undefined && !Array.isArray(parsedAppConfig.expo.plugins)) { Sentry.setTag('app-config-file-status', 'invalid-json'); clack.log.error(`Unable to find expo plugins in your ${chalk_1.default.cyan('app.config.json')}. Make sure it has a valid format!`); return null; } parsedAppConfig.expo = parsedAppConfig.expo ?? {}; parsedAppConfig.expo.plugins = parsedAppConfig.expo.plugins ?? []; parsedAppConfig.expo.plugins.push([ exports.SENTRY_EXPO_PLUGIN_NAME, { url: options.url, project: options.project, organization: options.org, }, ]); return JSON.stringify(parsedAppConfig, null, 2) + os_1.EOL; } catch (error) { Sentry.setTag('app-config-file-status', 'invalid-json'); clack.log.error(`Unable to parse your ${chalk_1.default.cyan('app.config.json')}. Make sure it has a valid format!`); Sentry.captureException(`Error to parsing 'app.config.json'`); return null; } } exports.addWithSentryToAppConfigJson = addWithSentryToAppConfigJson; function getSentryAppConfigJsonCodeSnippet({ url, project, org, }) { return (0, clack_1.makeCodeSnippet)(true, (unchanged, plus, _minus) => { return unchanged(`{ "name": "my app", "plugins": [ ${plus(`[ "@sentry/react-native/expo", { "url": "${url}", "project": "${project}", "organization": "${org}" } ]`)} ], }`); }); } exports.getSentryAppConfigJsonCodeSnippet = getSentryAppConfigJsonCodeSnippet; /** * Checks whether the given value is a plain object (as opposed to something like a class instance or a primitive). * vendored from @sentry/utils to avoid registering the dependency. */ function isPlainObject(what) { return Object.prototype.toString.call(what) === '[object Object]'; } //# sourceMappingURL=expo.js.map