UNPKG

@sentry/wizard

Version:

Sentry wizard helping you to configure your project

236 lines 11 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.Cordova = void 0; const fs = __importStar(require("node:fs")); const path = __importStar(require("node:path")); const xcode_1 = __importDefault(require("xcode")); const File_1 = require("../../Helper/File"); const Logging_1 = require("../../Helper/Logging"); const SentryCli_1 = require("../../Helper/SentryCli"); const BaseIntegration_1 = require("./BaseIntegration"); class Cordova extends BaseIntegration_1.BaseIntegration { _argv; _sentryCli; _folderPrefix = 'platforms'; _pluginFolder = ['.']; constructor(_argv) { super(_argv); this._argv = _argv; this._sentryCli = new SentryCli_1.SentryCli(this._argv); } async emit(answers) { if (this._argv.uninstall) { return this.uninstall(answers); } const sentryCliProperties = this._sentryCli.convertAnswersToProperties(answers); await (0, File_1.patchMatchingFile)(`${this._folderPrefix}/ios/*.xcodeproj/project.pbxproj`, (contents, filename) => this._patchXcodeProj(contents, filename)); await this._addSentryProperties(sentryCliProperties); (0, Logging_1.green)('Successfully set up for cordova'); return {}; } async uninstall(_answers) { await (0, File_1.patchMatchingFile)('**/*.xcodeproj/project.pbxproj', (_, filename) => this._unpatchXcodeProj(filename)); return {}; } async shouldConfigure(_answers) { // eslint-disable-next-line @typescript-eslint/no-misused-promises if (this._shouldConfigure) { return this._shouldConfigure; } let result = false; if (!(0, File_1.exists)(path.join('sentry.properties'))) { result = true; this.debug('sentry.properties not exists'); } if (!(0, File_1.matchesContent)('**/*.xcodeproj/project.pbxproj', /SENTRY_PROPERTIES/gi)) { result = true; this.debug('**/*.xcodeproj/project.pbxproj not matched'); } if (this._argv.uninstall) { // if we uninstall we need to invert the result so we remove already patched result = !result; } this._shouldConfigure = Promise.resolve({ cordova: result }); // eslint-disable-next-line @typescript-eslint/unbound-method return this.shouldConfigure; } _unpatchXcodeProj(filename) { const proj = xcode_1.default.project(filename); return new Promise((resolve, reject) => { proj.parse((err) => { if (err) { reject(err); return; } this._unpatchXcodeBuildScripts(proj); resolve(proj.writeSync()); }); }); } _unpatchXcodeBuildScripts(proj) { const scripts = proj.hash.project.objects.PBXShellScriptBuildPhase || {}; const firstTarget = proj.getFirstTarget()?.uuid || ''; const nativeTargets = proj.hash.project.objects.PBXNativeTarget; // scripts to kill entirely. for (const key of Object.keys(scripts)) { const script = scripts[key]; // ignore comments and keys that got deleted if (typeof script === 'string' || script === undefined) { continue; } if (script.shellScript?.match(/SENTRY_PROPERTIES/) || script.shellScript?.match(/SENTRY_FRAMEWORK_PATCH/)) { // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete scripts[key]; // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete scripts[`${key}_comment`]; const target = nativeTargets && nativeTargets[firstTarget]; const phases = typeof target === 'object' && target.buildPhases; if (phases) { for (let i = 0; i < phases.length; i++) { if (phases[i].value === key) { phases.splice(i, 1); break; } } } continue; } } } _patchXcodeProj(contents, filename) { const proj = xcode_1.default.project(filename); return new Promise((resolve, reject) => { proj.parse((err) => { if (err) { reject(err); return; } const xcodeSourceScriptPath = path.join(process.cwd(), 'plugins/sentry-cordova/scripts', 'xcode-upload-debug-files.sh'); if (!fs.existsSync(xcodeSourceScriptPath)) { this.debug(`file ${xcodeSourceScriptPath} not found.`); reject('This version of wizard requires Sentry Cordova 1.4.2 or higher, please use an older version of sentry wizard or upgrade sentry cordova.'); return; } const buildScripts = []; for (const val of Object.values(proj.hash.project.objects.PBXShellScriptBuildPhase || {})) { if (typeof val === 'object' && val.isa === 'PBXShellScriptBuildPhase') { buildScripts.push(val); } } this._addNewXcodeBuildPhaseForSymbols(buildScripts, proj, xcodeSourceScriptPath); this._addNewXcodeBuildPhaseForStripping(buildScripts, proj); // we always modify the xcode file in memory but we only want to save it // in case the user wants configuration for ios. This is why we check // here first if changes are made before we might prompt the platform // continue prompt. const newContents = proj.writeSync(); if (newContents === contents) { resolve(); } else { resolve(newContents); } }); }); } _addNewXcodeBuildPhaseForSymbols(buildScripts, proj, xcodeSymbolScriptPath) { for (const script of buildScripts) { if (typeof script === 'object' && script.shellScript?.match(/SENTRY_PROPERTIES/)) { return; } } const script = fs .readFileSync(xcodeSymbolScriptPath, 'utf8') .replace(/\\/g, '\\\\') .replace(/\n/g, '\\n'); proj.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, { shellPath: '/bin/sh', shellScript: script, }); } _addNewXcodeBuildPhaseForStripping(buildScripts, proj) { for (const script of buildScripts) { if (typeof script === 'object' && script.shellScript?.match(/SENTRY_FRAMEWORK_PATCH/)) { return; } } // http://ikennd.ac/blog/2015/02/stripping-unwanted-architectures-from-dynamic-libraries-in-xcode/ proj.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Sentry strip unused archs from Framework', null, { shellPath: '/bin/sh', shellScript: '# SENTRY_FRAMEWORK_PATCH \\n' + 'echo "warning: patching framework - set SENTRY_SKIP_FRAMEWORK_PATCH=true to skip this"\\n' + 'if [ -n "$SENTRY_SKIP_FRAMEWORK_PATCH" ]; then\\n' + ' echo "warning: skipping framework patch"\\n' + ' exit 0\\n' + 'fi\\n' + 'APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"\\n' + 'find "$APP_PATH" -name \'Sentry*.framework\' -type d | while read -r FRAMEWORK\\n' + 'do\\n' + 'FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)\\n' + 'FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"\\n' + 'echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"\\n' + 'EXTRACTED_ARCHS=()\\n' + 'for ARCH in $ARCHS\\n' + 'do\\n' + 'echo "Checking if $FRAMEWORK_EXECUTABLE_PATH needs to be stripped."\\n' + '# Do not skip if "Architectures in the fat file".\\n' + '# Skip if Non-fat file or if file not found. \\n' + 'if lipo -info "$FRAMEWORK_EXECUTABLE_PATH" | grep -v " fat "; then\\n' + ' echo "Strip not required, skipping the strip script."\\n' + ' exit 0\\n' + 'fi\\n' + 'echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"\\n' + 'lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"\\n' + 'EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")\\n' + 'done\\n' + 'echo "Merging extracted architectures: ${ARCHS}"\\n' + 'lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"\\n' + 'rm "${EXTRACTED_ARCHS[@]}"\\n' + 'echo "Replacing original executable with thinned version"\\n' + 'rm "$FRAMEWORK_EXECUTABLE_PATH"\\n' + 'mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"\\n' + 'done', }); } _addSentryProperties(properties) { let rv = Promise.resolve(); const fn = path.join('sentry.properties'); if ((0, File_1.exists)(fn)) { return rv; } rv = rv.then(() => fs.writeFileSync(fn, this._sentryCli.dumpProperties(properties))); return rv; } } exports.Cordova = Cordova; //# sourceMappingURL=Cordova.js.map