UNPKG

@sentry/wizard

Version:

Sentry wizard helping you to configure your project

182 lines 7.08 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 */ const fs = __importStar(require("fs")); // @ts-expect-error - clack is ESM and TS complains about that. It works though const clack = __importStar(require("@clack/prompts")); const Sentry = __importStar(require("@sentry/node")); const templates_1 = require("./templates"); const xml_js_1 = __importDefault(require("xml-js")); const 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, enableLogs) { if (!fs.existsSync(manifestFile)) { clack.log.warn('AndroidManifest.xml not found.'); Sentry.captureException('No AndroidManifest file'); return false; } const 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; } const applicationMatch = /<\/application>/i.exec(manifestContent); if (!applicationMatch) { clack.log.warn('<application> tag not found within the manifest.'); Sentry.captureException('No <application> tag'); return false; } const insertionIndex = applicationMatch.index; const newContent = manifestContent.slice(0, insertionIndex) + (0, templates_1.manifest)(dsn, enableLogs) + manifestContent.slice(insertionIndex); fs.writeFileSync(manifestFile, newContent, 'utf8'); clack.log.success(chalk_1.default.greenBright(`Updated ${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) { if (!fs.existsSync(manifestFile)) { clack.log.warn('AndroidManifest.xml not found.'); Sentry.captureException('No AndroidManifest file'); return {}; } const manifestContent = fs.readFileSync(manifestFile, 'utf8'); const converted = xml_js_1.default.xml2js(manifestContent, { compact: true, }); const activities = converted.manifest?.application?.activity; const packageName = converted.manifest?._attributes?.['package']; if (!activities) { clack.log.warn('No activity found in AndroidManifest.'); Sentry.captureException('No Activity'); return {}; } let mainActivity; if (Array.isArray(activities)) { const withIntentFilter = activities.filter((a) => !!a['intent-filter']); mainActivity = withIntentFilter.find((a) => 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 {}; } const attrs = mainActivity._attributes; const activityName = attrs?.['android:name']; return { packageName: packageName, activityName: activityName }; } exports.getMainActivity = getMainActivity; function isMainActivity(activity) { const intentFilters = activity['intent-filter']; if (Array.isArray(intentFilters)) { return intentFilters.some((i) => { const action = i.action; return hasMainAction(action); }); } else { const action = intentFilters.action; return hasMainAction(action); } } function hasMainAction(action) { if (!action) { return false; } function isMain(attrs) { return attrs?.['android:name'] === 'android.intent.action.MAIN'; } if (Array.isArray(action)) { return action.some((c) => { return isMain(c._attributes); }); } else { return isMain(action._attributes); } } //# sourceMappingURL=manifest.js.map