|
| 1 | +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ |
| 2 | +import type { ConfigPlugin, XcodeProject } from 'expo/config-plugins'; |
| 3 | +import { WarningAggregator, withDangerousMod, withXcodeProject } from 'expo/config-plugins'; |
| 4 | +import * as fs from 'fs'; |
| 5 | +import * as path from 'path'; |
| 6 | + |
| 7 | +const SENTRY_CLI = "`node --print \"require.resolve('@sentry/cli/package.json').slice(0, -13) + '/bin/sentry-cli'\"`"; |
| 8 | + |
| 9 | +export const withSentryIOS: ConfigPlugin<string> = (config, sentryProperties: string) => { |
| 10 | + const cfg = withXcodeProject(config, config => { |
| 11 | + const xcodeProject: XcodeProject = config.modResults; |
| 12 | + |
| 13 | + const sentryBuildPhase = xcodeProject.pbxItemByComment( |
| 14 | + 'Upload Debug Symbols to Sentry', |
| 15 | + 'PBXShellScriptBuildPhase', |
| 16 | + ); |
| 17 | + if (!sentryBuildPhase) { |
| 18 | + xcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, { |
| 19 | + shellPath: '/bin/sh', |
| 20 | + shellScript: ` |
| 21 | +export SENTRY_PROPERTIES=sentry.properties |
| 22 | +[[ $SENTRY_INCLUDE_NATIVE_SOURCES == "true" ]] && INCLUDE_SOURCES_FLAG="--include-sources" || INCLUDE_SOURCES_FLAG="" |
| 23 | +${SENTRY_CLI} debug-files upload --force-foreground "$INCLUDE_SOURCES_FLAG" "$DWARF_DSYM_FOLDER_PATH" |
| 24 | + `, |
| 25 | + }); |
| 26 | + } |
| 27 | + |
| 28 | + const bundleReactNativePhase = xcodeProject.pbxItemByComment( |
| 29 | + 'Bundle React Native code and images', |
| 30 | + 'PBXShellScriptBuildPhase', |
| 31 | + ); |
| 32 | + modifyExistingXcodeBuildScript(bundleReactNativePhase); |
| 33 | + |
| 34 | + return config; |
| 35 | + }); |
| 36 | + |
| 37 | + return withDangerousMod(cfg, [ |
| 38 | + 'ios', |
| 39 | + config => { |
| 40 | + writeSentryPropertiesTo(path.resolve(config.modRequest.projectRoot, 'ios'), sentryProperties); |
| 41 | + return config; |
| 42 | + }, |
| 43 | + ]); |
| 44 | +}; |
| 45 | + |
| 46 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 47 | +export function modifyExistingXcodeBuildScript(script: any): void { |
| 48 | + if ( |
| 49 | + !script.shellScript.match(/(packager|scripts)\/react-native-xcode\.sh\b/) || |
| 50 | + script.shellScript.match(/bin\/sentry-cli.*react-native[\s-]xcode/) |
| 51 | + ) { |
| 52 | + WarningAggregator.addWarningIOS( |
| 53 | + 'sentry-expo', |
| 54 | + "Unable to modify build script 'Bundle React Native code and images'. Please open a bug report at https://github.com/expo/sentry-expo.", |
| 55 | + ); |
| 56 | + return; |
| 57 | + } |
| 58 | + let code = JSON.parse(script.shellScript); |
| 59 | + code = `${ |
| 60 | + 'export SENTRY_PROPERTIES=sentry.properties\n' + |
| 61 | + 'export EXTRA_PACKAGER_ARGS="--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map"\n' |
| 62 | + }${code.replace( |
| 63 | + /^.*?(packager|scripts)\/react-native-xcode\.sh\s*(\\'\\\\")?/m, |
| 64 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 65 | + (match: any) => `${SENTRY_CLI} react-native xcode --force-foreground ${match}`, |
| 66 | + )}\n\n\`node --print "require.resolve('@sentry/react-native/package.json').slice(0, -13) + '/scripts/collect-modules.sh'"\``; |
| 67 | + |
| 68 | + script.shellScript = JSON.stringify(code); |
| 69 | +} |
| 70 | + |
| 71 | +export function writeSentryPropertiesTo(filepath: string, sentryProperties: string): void { |
| 72 | + if (!fs.existsSync(filepath)) { |
| 73 | + throw new Error(`Directory '${filepath}' does not exist.`); |
| 74 | + } |
| 75 | + |
| 76 | + fs.writeFileSync(path.resolve(filepath, 'sentry.properties'), sentryProperties); |
| 77 | +} |
0 commit comments