-
-
Notifications
You must be signed in to change notification settings - Fork 359
Expand file tree
/
Copy pathwithSentry.ts
More file actions
119 lines (103 loc) · 4.66 KB
/
withSentry.ts
File metadata and controls
119 lines (103 loc) · 4.66 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
import type { ExpoConfig } from '@expo/config-types';
import type { ConfigPlugin } from 'expo/config-plugins';
import { createRunOncePlugin, withDangerousMod } from 'expo/config-plugins';
import type { SentryAndroidGradlePluginOptions } from './withSentryAndroidGradlePlugin';
import { bold, warnOnce } from './logger';
import { writeSentryOptions } from './utils';
import { PLUGIN_NAME, PLUGIN_VERSION } from './version';
import { withSentryAndroid } from './withSentryAndroid';
import { withSentryAndroidGradlePlugin } from './withSentryAndroidGradlePlugin';
import { withSentryIOS } from './withSentryIOS';
interface PluginProps {
organization?: string;
project?: string;
authToken?: string;
url?: string;
useNativeInit?: boolean;
options?: Record<string, unknown>;
experimental_android?: SentryAndroidGradlePluginOptions;
}
const withSentryPlugin: ConfigPlugin<PluginProps | void> = (config, props) => {
const sentryProperties = getSentryProperties(props);
if (props?.authToken) {
// If not removed, the plugin config with the authToken will be written to the application package
delete props.authToken;
}
let cfg = config;
const pluginOptions = props?.options ? { ...props.options } : {};
// oxlint-disable-next-line typescript-eslint(no-unsafe-member-access)
const environment = process.env.SENTRY_ENVIRONMENT;
if (environment) {
pluginOptions.environment = environment;
}
if (Object.keys(pluginOptions).length > 0) {
cfg = withSentryOptionsFile(cfg, pluginOptions);
}
if (sentryProperties !== null) {
try {
cfg = withSentryAndroid(cfg, { sentryProperties, useNativeInit: props?.useNativeInit });
} catch (e) {
warnOnce(`There was a problem with configuring your native Android project: ${e}`);
}
// if `enableAndroidGradlePlugin` is provided configure the Sentry Android Gradle Plugin
if (props?.experimental_android?.enableAndroidGradlePlugin) {
try {
cfg = withSentryAndroidGradlePlugin(cfg, props.experimental_android);
} catch (e) {
warnOnce(`There was a problem with configuring Sentry Android Gradle Plugin: ${e}`);
}
}
try {
cfg = withSentryIOS(cfg, { sentryProperties, useNativeInit: props?.useNativeInit });
} catch (e) {
warnOnce(`There was a problem with configuring your native iOS project: ${e}`);
}
}
return cfg;
};
const missingProjectMessage = '# no project found, falling back to SENTRY_PROJECT environment variable';
const missingOrgMessage = '# no org found, falling back to SENTRY_ORG environment variable';
const existingAuthTokenMessage =
'# DO NOT COMMIT the auth token, use SENTRY_AUTH_TOKEN instead, see https://docs.sentry.io/platforms/react-native/manual-setup/';
const missingAuthTokenMessage = '# Using SENTRY_AUTH_TOKEN environment variable';
export function getSentryProperties(props: PluginProps | void): string | null {
const { organization, project, authToken, url = 'https://sentry.io/' } = props ?? {};
const missingProperties = ['organization', 'project'].filter(each => !props?.hasOwnProperty(each));
if (missingProperties.length) {
const missingPropertiesString = bold(missingProperties.join(', '));
const warningMessage = `Missing config for ${missingPropertiesString}. Environment variables will be used as a fallback during the build. https://docs.sentry.io/platforms/react-native/manual-setup/`;
warnOnce(warningMessage);
}
if (authToken) {
warnOnce(
`Detected unsecure use of 'authToken' in Sentry plugin configuration. To avoid exposing the token use ${bold(
'SENTRY_AUTH_TOKEN',
)} environment variable instead. https://docs.sentry.io/platforms/react-native/manual-setup/`,
);
}
return `defaults.url=${url}
${organization ? `defaults.org=${organization}` : missingOrgMessage}
${project ? `defaults.project=${project}` : missingProjectMessage}
${authToken ? `${existingAuthTokenMessage}\nauth.token=${authToken}` : missingAuthTokenMessage}`;
}
function withSentryOptionsFile(config: ExpoConfig, pluginOptions: Record<string, unknown>): ExpoConfig {
// withDangerousMod requires a platform key, but sentry.options.json is at the project root.
// We apply to both platforms so it works with `expo prebuild --platform ios` or `--platform android`.
let cfg = withDangerousMod(config, [
'android',
mod => {
writeSentryOptions(mod.modRequest.projectRoot, pluginOptions);
return mod;
},
]);
cfg = withDangerousMod(cfg, [
'ios',
mod => {
writeSentryOptions(mod.modRequest.projectRoot, pluginOptions);
return mod;
},
]);
return cfg;
}
const withSentry = createRunOncePlugin(withSentryPlugin, PLUGIN_NAME, PLUGIN_VERSION);
export { withSentry };