@sentry/wizard
Version:
Sentry wizard helping you to configure your project
183 lines • 7.37 kB
JavaScript
;
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