-
-
Notifications
You must be signed in to change notification settings - Fork 358
Expand file tree
/
Copy pathwithSentryAndroid.ts
More file actions
128 lines (112 loc) · 5.18 KB
/
withSentryAndroid.ts
File metadata and controls
128 lines (112 loc) · 5.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import type { ExpoConfig } from '@expo/config-types';
import type { ConfigPlugin } from 'expo/config-plugins';
import { withAppBuildGradle, withDangerousMod, withMainApplication } from 'expo/config-plugins';
import * as path from 'path';
import { warnOnce } from './logger';
import { writeSentryPropertiesTo } from './utils';
export const withSentryAndroid: ConfigPlugin<{
sentryProperties: string;
useNativeInit: boolean | undefined;
disableAutoUpload: boolean | undefined;
}> = (config, { sentryProperties, useNativeInit = false, disableAutoUpload = false }) => {
const appBuildGradleCfg = withAppBuildGradle(config, config => {
if (config.modResults.language === 'groovy') {
config.modResults.contents = modifyAppBuildGradle(config.modResults.contents, disableAutoUpload);
} else {
throw new Error('Cannot configure Sentry in the app gradle because the build.gradle is not groovy');
}
return config;
});
const mainApplicationCfg = useNativeInit ? modifyMainApplication(appBuildGradleCfg) : appBuildGradleCfg;
return withDangerousMod(mainApplicationCfg, [
'android',
dangerousMod => {
// oxlint-disable-next-line typescript-eslint(no-unsafe-member-access)
writeSentryPropertiesTo(path.resolve(dangerousMod.modRequest.projectRoot, 'android'), sentryProperties);
return dangerousMod;
},
]);
};
const resolveSentryReactNativePackageJsonPath =
'["node", "--print", "require(\'path\').dirname(require.resolve(\'@sentry/react-native/package.json\'))"].execute().text.trim()';
/**
* Writes to projectDirectory/android/app/build.gradle,
* adding the relevant @sentry/react-native script.
*/
export function modifyAppBuildGradle(buildGradle: string, disableAutoUpload: boolean = false): string {
if (buildGradle.includes('sentry.gradle')) {
if (disableAutoUpload && !buildGradle.includes('shouldSentryAutoUploadGeneral')) {
return buildGradle.replace(
/^(apply from:.*sentry\.gradle.*)$/m,
`$1\nproject.ext.shouldSentryAutoUploadGeneral = { -> return false }`,
);
}
return buildGradle;
}
// Use the same location that sentry-wizard uses
// See: https://github.com/getsentry/sentry-wizard/blob/e9b4522f27a852069c862bd458bdf9b07cab6e33/lib/Steps/Integrations/ReactNative.ts#L232
const pattern = /^android {/m;
if (!buildGradle.match(pattern)) {
warnOnce(
'Could not find `^android {` in `android/app/build.gradle`. Please open a bug report at https://github.com/getsentry/sentry-react-native.',
);
return buildGradle;
}
const applyFrom = `apply from: new File(${resolveSentryReactNativePackageJsonPath}, "sentry.gradle")`;
const disableUploadOverride = disableAutoUpload
? `\nproject.ext.shouldSentryAutoUploadGeneral = { -> return false }`
: '';
return buildGradle.replace(pattern, match => `${applyFrom}${disableUploadOverride}\n\n${match}`);
}
export function modifyMainApplication(config: ExpoConfig): ExpoConfig {
return withMainApplication(config, config => {
if (!config.modResults?.path) {
warnOnce("Can't add 'RNSentrySDK.init' to Android MainApplication, because the file was not found.");
return config;
}
// oxlint-disable-next-line typescript-eslint(no-unsafe-member-access)
const fileName = path.basename(config.modResults.path);
if (config.modResults.contents.includes('RNSentrySDK.init')) {
warnOnce(`Your '${fileName}' already contains 'RNSentrySDK.init', the native code won't be updated.`);
return config;
}
if (config.modResults.language === 'java') {
// Add RNSentrySDK.init
const originalContents = config.modResults.contents;
config.modResults.contents = config.modResults.contents.replace(
/(super\.onCreate\(\)[;\n]*)([ \t]*)/,
'$1\n$2RNSentrySDK.init(this);\n$2',
);
if (config.modResults.contents === originalContents) {
warnOnce(`Failed to insert 'RNSentrySDK.init' in '${fileName}'.`);
} else if (!config.modResults.contents.includes('import io.sentry.react.RNSentrySDK;')) {
// Insert import statement after package declaration
config.modResults.contents = config.modResults.contents.replace(
/(package .*;\n\n?)/,
'$1import io.sentry.react.RNSentrySDK;\n',
);
}
} else if (config.modResults.language === 'kt') {
// Add RNSentrySDK.init
const originalContents = config.modResults.contents;
config.modResults.contents = config.modResults.contents.replace(
/(super\.onCreate\(\)[;\n]*)([ \t]*)/,
'$1\n$2RNSentrySDK.init(this)\n$2',
);
if (config.modResults.contents === originalContents) {
warnOnce(`Failed to insert 'RNSentrySDK.init' in '${fileName}'.`);
} else if (!config.modResults.contents.includes('import io.sentry.react.RNSentrySDK')) {
// Insert import statement after package declaration
config.modResults.contents = config.modResults.contents.replace(
/(package .*\n\n?)/,
'$1import io.sentry.react.RNSentrySDK\n',
);
}
} else {
warnOnce(
`Unsupported language '${config.modResults.language}' detected in '${fileName}', the native code won't be updated.`,
);
}
return config;
});
}