UNPKG

@sentry/wizard

Version:

Sentry wizard helping you to configure your project

183 lines 7.37 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.getMainActivity = exports.addManifestSnippet = void 0; /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ var fs = __importStar(require("fs")); // @ts-ignore - clack is ESM and TS complains about that. It works though var clack = __importStar(require("@clack/prompts")); var Sentry = __importStar(require("@sentry/node")); var templates_1 = require("./templates"); var xml_js_1 = __importDefault(require("xml-js")); var chalk_1 = __importDefault(require("chalk")); /** * Looks for the closing </application> tag in the manifest and adds the Sentry config after it. * * For example: * ```xml * <manifest xmlns:android="http://schemas.android.com/apk/res/android" * xmlns:tools="http://schemas.android.com/tools"> * * <application> * ... * // this is what we add and more * <meta-data android:name="io.sentry.dsn" android:value="__dsn__" /> * </application> <!-- we are looking for this one * </manifest> * ``` * * @param manifestFile the path to the main AndroidManifest.xml file * @param dsn * @returns true if successfully patched the manifest, false otherwise */ function addManifestSnippet(manifestFile, dsn) { if (!fs.existsSync(manifestFile)) { clack.log.warn('AndroidManifest.xml not found.'); Sentry.captureException('No AndroidManifest file'); return false; } var manifestContent = fs.readFileSync(manifestFile, 'utf8'); if (/android:name="io\.sentry[^"]*"/i.test(manifestContent)) { // sentry is already configured clack.log.success(chalk_1.default.greenBright('Sentry SDK is already configured.')); return true; } var applicationMatch = /<\/application>/i.exec(manifestContent); if (!applicationMatch) { clack.log.warn('<application> tag not found within the manifest.'); Sentry.captureException('No <application> tag'); return false; } var insertionIndex = applicationMatch.index; var newContent = manifestContent.slice(0, insertionIndex) + (0, templates_1.manifest)(dsn) + manifestContent.slice(insertionIndex); fs.writeFileSync(manifestFile, newContent, 'utf8'); clack.log.success(chalk_1.default.greenBright("Updated ".concat(chalk_1.default.bold('AndroidManifest.xml'), " with the Sentry SDK configuration."))); return true; } exports.addManifestSnippet = addManifestSnippet; /** * There might be multiple <activity> in the manifest, as well as multiple <activity-alias> with category LAUNCHER, * but only one main activity with action MAIN. We are looking for this one by parsing xml and walking it. * * In addition, older Android versions required to specify the packag name in the manifest, * while the new ones - in the Gradle config. So we are just sanity checking if the package name * is in the manifest and returning it as well. * * For example: * * ```xml * <manifest xmlns:android="http://schemas.android.com/apk/res/android" * xmlns:tools="http://schemas.android.com/tools" * package="com.example.sample"> * * <application> * <activity * android:name="ui.MainActivity" * ...other props> * <intent-filter> * <action android:name="android.intent.action.MAIN" /> <!-- we are looking for this one * * <category android:name="android.intent.category.LAUNCHER" /> * </intent-filter> * </activity> * </application> * </manifest> * ``` * * @param manifestFile path to the AndroidManifest.xml file * @returns package name (if available in the manifest) + the main activity name */ function getMainActivity(manifestFile) { var _a, _b, _c, _d; if (!fs.existsSync(manifestFile)) { clack.log.warn('AndroidManifest.xml not found.'); Sentry.captureException('No AndroidManifest file'); return {}; } var manifestContent = fs.readFileSync(manifestFile, 'utf8'); var converted = xml_js_1.default.xml2js(manifestContent, { compact: true, }); var activities = (_b = (_a = converted.manifest) === null || _a === void 0 ? void 0 : _a.application) === null || _b === void 0 ? void 0 : _b.activity; var packageName = (_d = (_c = converted.manifest) === null || _c === void 0 ? void 0 : _c._attributes) === null || _d === void 0 ? void 0 : _d['package']; if (!activities) { clack.log.warn('No activity found in AndroidManifest.'); Sentry.captureException('No Activity'); return {}; } var mainActivity; if (Array.isArray(activities)) { var withIntentFilter = activities.filter(function (a) { return !!a['intent-filter']; }); mainActivity = withIntentFilter.find(function (a) { return isMainActivity(a); }); } else if (isMainActivity(activities)) { mainActivity = activities; } if (!mainActivity) { clack.log.warn('No main activity found in AndroidManifest.'); Sentry.captureException('No Main Activity'); return {}; } var attrs = mainActivity._attributes; var activityName = attrs === null || attrs === void 0 ? void 0 : attrs['android:name']; return { packageName: packageName, activityName: activityName }; } exports.getMainActivity = getMainActivity; function isMainActivity(activity) { var intentFilters = activity['intent-filter']; if (Array.isArray(intentFilters)) { return intentFilters.some(function (i) { var action = i.action; return hasMainAction(action); }); } else { var action = intentFilters.action; return hasMainAction(action); } } function hasMainAction(action) { if (!action) { return false; } function isMain(attrs) { return (attrs === null || attrs === void 0 ? void 0 : attrs['android:name']) === 'android.intent.action.MAIN'; } if (Array.isArray(action)) { return action.some(function (c) { return isMain(c._attributes); }); } else { return isMain(action._attributes); } } //# sourceMappingURL=manifest.js.map