@sentry/react-native 7.10.0 → 8.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/RNSentry.podspec +8 -4
  2. package/android/libs/replay-stubs.jar +0 -0
  3. package/android/src/main/java/io/sentry/react/RNSentryCompositeOptionsConfiguration.java +25 -0
  4. package/android/src/main/java/io/sentry/react/RNSentryJsonConverter.java +76 -0
  5. package/android/src/main/java/io/sentry/react/RNSentryJsonUtils.java +41 -0
  6. package/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +22 -398
  7. package/android/src/main/java/io/sentry/react/RNSentrySDK.java +68 -0
  8. package/android/src/main/java/io/sentry/react/RNSentryStart.java +417 -0
  9. package/android/src/main/java/io/sentry/react/RNSentryVersion.java +1 -1
  10. package/android/src/newarch/java/io/sentry/react/RNSentryModule.java +10 -0
  11. package/android/src/oldarch/java/io/sentry/react/RNSentryModule.java +15 -0
  12. package/dist/js/NativeRNSentry.d.ts +2 -0
  13. package/dist/js/NativeRNSentry.d.ts.map +1 -1
  14. package/dist/js/NativeRNSentry.js.map +1 -1
  15. package/dist/js/integrations/logEnricherIntegration.js +43 -3
  16. package/dist/js/integrations/logEnricherIntegration.js.map +1 -1
  17. package/dist/js/replay/mobilereplay.d.ts +0 -26
  18. package/dist/js/replay/mobilereplay.d.ts.map +1 -1
  19. package/dist/js/replay/mobilereplay.js.map +1 -1
  20. package/dist/js/scopeSync.d.ts.map +1 -1
  21. package/dist/js/scopeSync.js +21 -0
  22. package/dist/js/scopeSync.js.map +1 -1
  23. package/dist/js/sdk.d.ts.map +1 -1
  24. package/dist/js/sdk.js +21 -10
  25. package/dist/js/sdk.js.map +1 -1
  26. package/dist/js/tools/metroconfig.d.ts +9 -1
  27. package/dist/js/tools/metroconfig.d.ts.map +1 -1
  28. package/dist/js/tools/metroconfig.js +9 -2
  29. package/dist/js/tools/metroconfig.js.map +1 -1
  30. package/dist/js/tools/sentryMetroSerializer.d.ts.map +1 -1
  31. package/dist/js/tools/sentryMetroSerializer.js +1 -0
  32. package/dist/js/tools/sentryMetroSerializer.js.map +1 -1
  33. package/dist/js/tools/sentryOptionsSerializer.d.ts +6 -0
  34. package/dist/js/tools/sentryOptionsSerializer.d.ts.map +1 -0
  35. package/dist/js/tools/sentryOptionsSerializer.js +92 -0
  36. package/dist/js/tools/sentryOptionsSerializer.js.map +1 -0
  37. package/dist/js/tools/utils.d.ts +2 -1
  38. package/dist/js/tools/utils.d.ts.map +1 -1
  39. package/dist/js/tools/utils.js.map +1 -1
  40. package/dist/js/touchevents.d.ts +8 -0
  41. package/dist/js/touchevents.d.ts.map +1 -1
  42. package/dist/js/touchevents.js +33 -1
  43. package/dist/js/touchevents.js.map +1 -1
  44. package/dist/js/utils/worldwide.d.ts +2 -0
  45. package/dist/js/utils/worldwide.d.ts.map +1 -1
  46. package/dist/js/utils/worldwide.js.map +1 -1
  47. package/dist/js/version.d.ts +1 -1
  48. package/dist/js/version.d.ts.map +1 -1
  49. package/dist/js/version.js +1 -1
  50. package/dist/js/version.js.map +1 -1
  51. package/dist/js/wrapper.d.ts +2 -0
  52. package/dist/js/wrapper.d.ts.map +1 -1
  53. package/dist/js/wrapper.js +32 -0
  54. package/dist/js/wrapper.js.map +1 -1
  55. package/ios/RNSentry.h +3 -0
  56. package/ios/RNSentry.mm +28 -44
  57. package/ios/RNSentryDependencyContainer.h +2 -1
  58. package/ios/RNSentryDependencyContainer.m +1 -0
  59. package/ios/RNSentryEmitNewFrameEvent.h +3 -0
  60. package/ios/RNSentryExperimentalOptions.m +1 -1
  61. package/ios/RNSentryFramesTrackerListener.h +2 -2
  62. package/ios/RNSentryFramesTrackerListener.m +2 -0
  63. package/ios/RNSentryOnDrawReporter.h +2 -1
  64. package/ios/RNSentryOnDrawReporter.m +2 -0
  65. package/ios/RNSentryRNSScreen.m +3 -4
  66. package/ios/RNSentryReplay.mm +0 -5
  67. package/ios/RNSentryReplayBreadcrumbConverter.m +12 -12
  68. package/ios/RNSentrySDK.h +31 -0
  69. package/ios/RNSentrySDK.m +78 -0
  70. package/ios/RNSentryStart.h +25 -0
  71. package/ios/RNSentryStart.m +228 -0
  72. package/ios/RNSentryVersion.m +1 -1
  73. package/ios/SentryScreenFramesWrapper.h +14 -0
  74. package/ios/SentryScreenFramesWrapper.m +39 -0
  75. package/package.json +10 -10
  76. package/plugin/build/logger.d.ts +24 -0
  77. package/plugin/build/logger.js +44 -0
  78. package/plugin/build/utils.d.ts +0 -18
  79. package/plugin/build/utils.js +1 -34
  80. package/plugin/build/version.d.ts +2 -0
  81. package/plugin/build/version.js +6 -0
  82. package/plugin/build/withSentry.d.ts +1 -0
  83. package/plugin/build/withSentry.js +11 -10
  84. package/plugin/build/withSentryAndroid.d.ts +6 -1
  85. package/plugin/build/withSentryAndroid.js +52 -8
  86. package/plugin/build/withSentryAndroidGradlePlugin.d.ts +1 -1
  87. package/plugin/build/withSentryAndroidGradlePlugin.js +8 -8
  88. package/plugin/build/withSentryIOS.d.ts +6 -1
  89. package/plugin/build/withSentryIOS.js +55 -7
  90. package/scripts/sentry-xcode.sh +20 -0
  91. package/sentry.gradle +51 -0
  92. package/src/js/NativeRNSentry.ts +2 -0
  93. package/ts3.8/dist/js/NativeRNSentry.d.ts +2 -0
  94. package/ts3.8/dist/js/replay/mobilereplay.d.ts +0 -26
  95. package/ts3.8/dist/js/touchevents.d.ts +8 -0
  96. package/ts3.8/dist/js/utils/worldwide.d.ts +2 -0
  97. package/ts3.8/dist/js/version.d.ts +1 -1
  98. package/ts3.8/dist/js/wrapper.d.ts +2 -0
@@ -23,21 +23,23 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.modifyAppBuildGradle = exports.withSentryAndroid = void 0;
26
+ exports.modifyMainApplication = exports.modifyAppBuildGradle = exports.withSentryAndroid = void 0;
27
27
  const config_plugins_1 = require("expo/config-plugins");
28
28
  const path = __importStar(require("path"));
29
+ const logger_1 = require("./logger");
29
30
  const utils_1 = require("./utils");
30
- const withSentryAndroid = (config, sentryProperties) => {
31
- const cfg = (0, config_plugins_1.withAppBuildGradle)(config, appBuildGradle => {
32
- if (appBuildGradle.modResults.language === 'groovy') {
33
- appBuildGradle.modResults.contents = modifyAppBuildGradle(appBuildGradle.modResults.contents);
31
+ const withSentryAndroid = (config, { sentryProperties, useNativeInit = false }) => {
32
+ const appBuildGradleCfg = (0, config_plugins_1.withAppBuildGradle)(config, config => {
33
+ if (config.modResults.language === 'groovy') {
34
+ config.modResults.contents = modifyAppBuildGradle(config.modResults.contents);
34
35
  }
35
36
  else {
36
37
  throw new Error('Cannot configure Sentry in the app gradle because the build.gradle is not groovy');
37
38
  }
38
- return appBuildGradle;
39
+ return config;
39
40
  });
40
- return (0, config_plugins_1.withDangerousMod)(cfg, [
41
+ const mainApplicationCfg = useNativeInit ? modifyMainApplication(appBuildGradleCfg) : appBuildGradleCfg;
42
+ return (0, config_plugins_1.withDangerousMod)(mainApplicationCfg, [
41
43
  'android',
42
44
  dangerousMod => {
43
45
  (0, utils_1.writeSentryPropertiesTo)(path.resolve(dangerousMod.modRequest.projectRoot, 'android'), sentryProperties);
@@ -59,10 +61,52 @@ function modifyAppBuildGradle(buildGradle) {
59
61
  // See: https://github.com/getsentry/sentry-wizard/blob/e9b4522f27a852069c862bd458bdf9b07cab6e33/lib/Steps/Integrations/ReactNative.ts#L232
60
62
  const pattern = /^android {/m;
61
63
  if (!buildGradle.match(pattern)) {
62
- (0, utils_1.warnOnce)('Could not find `^android {` in `android/app/build.gradle`. Please open a bug report at https://github.com/getsentry/sentry-react-native.');
64
+ (0, logger_1.warnOnce)('Could not find `^android {` in `android/app/build.gradle`. Please open a bug report at https://github.com/getsentry/sentry-react-native.');
63
65
  return buildGradle;
64
66
  }
65
67
  const applyFrom = `apply from: new File(${resolveSentryReactNativePackageJsonPath}, "sentry.gradle")`;
66
68
  return buildGradle.replace(pattern, match => `${applyFrom}\n\n${match}`);
67
69
  }
68
70
  exports.modifyAppBuildGradle = modifyAppBuildGradle;
71
+ function modifyMainApplication(config) {
72
+ return (0, config_plugins_1.withMainApplication)(config, config => {
73
+ if (!config.modResults?.path) {
74
+ (0, logger_1.warnOnce)("Can't add 'RNSentrySDK.init' to Android MainApplication, because the file was not found.");
75
+ return config;
76
+ }
77
+ const fileName = path.basename(config.modResults.path);
78
+ if (config.modResults.contents.includes('RNSentrySDK.init')) {
79
+ (0, logger_1.warnOnce)(`Your '${fileName}' already contains 'RNSentrySDK.init', the native code won't be updated.`);
80
+ return config;
81
+ }
82
+ if (config.modResults.language === 'java') {
83
+ // Add RNSentrySDK.init
84
+ const originalContents = config.modResults.contents;
85
+ config.modResults.contents = config.modResults.contents.replace(/(super\.onCreate\(\)[;\n]*)([ \t]*)/, '$1\n$2RNSentrySDK.init(this);\n$2');
86
+ if (config.modResults.contents === originalContents) {
87
+ (0, logger_1.warnOnce)(`Failed to insert 'RNSentrySDK.init' in '${fileName}'.`);
88
+ }
89
+ else if (!config.modResults.contents.includes('import io.sentry.react.RNSentrySDK;')) {
90
+ // Insert import statement after package declaration
91
+ config.modResults.contents = config.modResults.contents.replace(/(package .*;\n\n?)/, '$1import io.sentry.react.RNSentrySDK;\n');
92
+ }
93
+ }
94
+ else if (config.modResults.language === 'kt') {
95
+ // Add RNSentrySDK.init
96
+ const originalContents = config.modResults.contents;
97
+ config.modResults.contents = config.modResults.contents.replace(/(super\.onCreate\(\)[;\n]*)([ \t]*)/, '$1\n$2RNSentrySDK.init(this)\n$2');
98
+ if (config.modResults.contents === originalContents) {
99
+ (0, logger_1.warnOnce)(`Failed to insert 'RNSentrySDK.init' in '${fileName}'.`);
100
+ }
101
+ else if (!config.modResults.contents.includes('import io.sentry.react.RNSentrySDK')) {
102
+ // Insert import statement after package declaration
103
+ config.modResults.contents = config.modResults.contents.replace(/(package .*\n\n?)/, '$1import io.sentry.react.RNSentrySDK\n');
104
+ }
105
+ }
106
+ else {
107
+ (0, logger_1.warnOnce)(`Unsupported language '${config.modResults.language}' detected in '${fileName}', the native code won't be updated.`);
108
+ }
109
+ return config;
110
+ });
111
+ }
112
+ exports.modifyMainApplication = modifyMainApplication;
@@ -9,7 +9,7 @@ export interface SentryAndroidGradlePluginOptions {
9
9
  includeNativeSources?: boolean;
10
10
  includeSourceContext?: boolean;
11
11
  }
12
- export declare const sentryAndroidGradlePluginVersion = "5.12.2";
12
+ export declare const sentryAndroidGradlePluginVersion = "6.0.0";
13
13
  /**
14
14
  * Adds the Sentry Android Gradle Plugin to the project.
15
15
  * https://docs.sentry.io/platforms/react-native/manual-setup/manual-setup/#enable-sentry-agp
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.withSentryAndroidGradlePlugin = exports.sentryAndroidGradlePluginVersion = void 0;
4
4
  const config_plugins_1 = require("@expo/config-plugins");
5
- const utils_1 = require("./utils");
6
- exports.sentryAndroidGradlePluginVersion = '5.12.2';
5
+ const logger_1 = require("./logger");
6
+ exports.sentryAndroidGradlePluginVersion = '6.0.0';
7
7
  /**
8
8
  * Adds the Sentry Android Gradle Plugin to the project.
9
9
  * https://docs.sentry.io/platforms/react-native/manual-setup/manual-setup/#enable-sentry-agp
@@ -13,29 +13,29 @@ function withSentryAndroidGradlePlugin(config, { includeProguardMapping = true,
13
13
  const withSentryProjectBuildGradle = (config) => {
14
14
  return (0, config_plugins_1.withProjectBuildGradle)(config, projectBuildGradle => {
15
15
  if (!projectBuildGradle.modResults?.contents) {
16
- (0, utils_1.warnOnce)('android/build.gradle content is missing or undefined.');
16
+ (0, logger_1.warnOnce)('android/build.gradle content is missing or undefined.');
17
17
  return projectBuildGradle;
18
18
  }
19
19
  if (projectBuildGradle.modResults.language !== 'groovy') {
20
- (0, utils_1.warnOnce)('Cannot configure Sentry in android/build.gradle because it is not in Groovy.');
20
+ (0, logger_1.warnOnce)('Cannot configure Sentry in android/build.gradle because it is not in Groovy.');
21
21
  return projectBuildGradle;
22
22
  }
23
23
  const dependency = `classpath("io.sentry:sentry-android-gradle-plugin:${exports.sentryAndroidGradlePluginVersion}")`;
24
24
  if (projectBuildGradle.modResults.contents.includes(dependency)) {
25
- (0, utils_1.warnOnce)('sentry-android-gradle-plugin dependency in already in android/build.gradle.');
25
+ (0, logger_1.warnOnce)('sentry-android-gradle-plugin dependency in already in android/build.gradle.');
26
26
  return projectBuildGradle;
27
27
  }
28
28
  try {
29
29
  const updatedContents = projectBuildGradle.modResults.contents.replace(/dependencies\s*{/, `dependencies {\n ${dependency}`);
30
30
  if (updatedContents === projectBuildGradle.modResults.contents) {
31
- (0, utils_1.warnOnce)('Failed to inject the dependency. Could not find `dependencies` in build.gradle.');
31
+ (0, logger_1.warnOnce)('Failed to inject the dependency. Could not find `dependencies` in build.gradle.');
32
32
  }
33
33
  else {
34
34
  projectBuildGradle.modResults.contents = updatedContents;
35
35
  }
36
36
  }
37
37
  catch (error) {
38
- (0, utils_1.warnOnce)('An error occurred while trying to modify build.gradle');
38
+ (0, logger_1.warnOnce)('An error occurred while trying to modify build.gradle');
39
39
  }
40
40
  return projectBuildGradle;
41
41
  });
@@ -44,7 +44,7 @@ function withSentryAndroidGradlePlugin(config, { includeProguardMapping = true,
44
44
  const withSentryAppBuildGradle = (config) => {
45
45
  return (0, config_plugins_1.withAppBuildGradle)(config, appBuildGradle => {
46
46
  if (appBuildGradle.modResults.language !== 'groovy') {
47
- (0, utils_1.warnOnce)('Cannot configure Sentry in android/app/build.gradle because it is not in Groovy.');
47
+ (0, logger_1.warnOnce)('Cannot configure Sentry in android/app/build.gradle because it is not in Groovy.');
48
48
  return appBuildGradle;
49
49
  }
50
50
  const sentryPlugin = 'apply plugin: "io.sentry.android.gradle"';
@@ -1,8 +1,13 @@
1
+ import type { ExpoConfig } from '@expo/config-types';
1
2
  import type { ConfigPlugin } from 'expo/config-plugins';
2
3
  type BuildPhase = {
3
4
  shellScript: string;
4
5
  };
5
- export declare const withSentryIOS: ConfigPlugin<string>;
6
+ export declare const withSentryIOS: ConfigPlugin<{
7
+ sentryProperties: string;
8
+ useNativeInit: boolean | undefined;
9
+ }>;
6
10
  export declare function modifyExistingXcodeBuildScript(script: BuildPhase): void;
7
11
  export declare function addSentryWithBundledScriptsToBundleShellScript(script: string): string;
12
+ export declare function modifyAppDelegate(config: ExpoConfig): ExpoConfig;
8
13
  export {};
@@ -23,14 +23,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.addSentryWithBundledScriptsToBundleShellScript = exports.modifyExistingXcodeBuildScript = exports.withSentryIOS = void 0;
26
+ exports.modifyAppDelegate = exports.addSentryWithBundledScriptsToBundleShellScript = exports.modifyExistingXcodeBuildScript = exports.withSentryIOS = void 0;
27
27
  const config_plugins_1 = require("expo/config-plugins");
28
28
  const path = __importStar(require("path"));
29
+ const logger_1 = require("./logger");
29
30
  const utils_1 = require("./utils");
30
31
  const SENTRY_REACT_NATIVE_XCODE_PATH = "`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode.sh'\"`";
31
32
  const SENTRY_REACT_NATIVE_XCODE_DEBUG_FILES_PATH = "`${NODE_BINARY:-node} --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode-debug-files.sh'\"`";
32
- const withSentryIOS = (config, sentryProperties) => {
33
- const cfg = (0, config_plugins_1.withXcodeProject)(config, config => {
33
+ const withSentryIOS = (config, { sentryProperties, useNativeInit = false }) => {
34
+ const xcodeProjectCfg = (0, config_plugins_1.withXcodeProject)(config, config => {
34
35
  const xcodeProject = config.modResults;
35
36
  const sentryBuildPhase = xcodeProject.pbxItemByComment('Upload Debug Symbols to Sentry', 'PBXShellScriptBuildPhase');
36
37
  if (!sentryBuildPhase) {
@@ -43,7 +44,8 @@ const withSentryIOS = (config, sentryProperties) => {
43
44
  modifyExistingXcodeBuildScript(bundleReactNativePhase);
44
45
  return config;
45
46
  });
46
- return (0, config_plugins_1.withDangerousMod)(cfg, [
47
+ const appDelegateCfc = useNativeInit ? modifyAppDelegate(xcodeProjectCfg) : xcodeProjectCfg;
48
+ return (0, config_plugins_1.withDangerousMod)(appDelegateCfc, [
47
49
  'ios',
48
50
  config => {
49
51
  (0, utils_1.writeSentryPropertiesTo)(path.resolve(config.modRequest.projectRoot, 'ios'), sentryProperties);
@@ -54,16 +56,16 @@ const withSentryIOS = (config, sentryProperties) => {
54
56
  exports.withSentryIOS = withSentryIOS;
55
57
  function modifyExistingXcodeBuildScript(script) {
56
58
  if (!script.shellScript.match(/(packager|scripts)\/react-native-xcode\.sh\b/)) {
57
- (0, utils_1.warnOnce)(`'react-native-xcode.sh' not found in 'Bundle React Native code and images'.
59
+ (0, logger_1.warnOnce)(`'react-native-xcode.sh' not found in 'Bundle React Native code and images'.
58
60
  Please open a bug report at https://github.com/getsentry/sentry-react-native`);
59
61
  return;
60
62
  }
61
63
  if (script.shellScript.includes('sentry-xcode.sh')) {
62
- (0, utils_1.warnOnce)("The latest 'sentry-xcode.sh' script already exists in 'Bundle React Native code and images'.");
64
+ (0, logger_1.warnOnce)("The latest 'sentry-xcode.sh' script already exists in 'Bundle React Native code and images'.");
63
65
  return;
64
66
  }
65
67
  if (script.shellScript.includes('@sentry')) {
66
- (0, utils_1.warnOnce)(`Outdated or custom Sentry script found in 'Bundle React Native code and images'.
68
+ (0, logger_1.warnOnce)(`Outdated or custom Sentry script found in 'Bundle React Native code and images'.
67
69
  Regenerate the native project to use the latest script.
68
70
  Run npx expo prebuild --clean`);
69
71
  return;
@@ -78,3 +80,49 @@ function addSentryWithBundledScriptsToBundleShellScript(script) {
78
80
  (match) => `/bin/sh ${SENTRY_REACT_NATIVE_XCODE_PATH} ${match}`);
79
81
  }
80
82
  exports.addSentryWithBundledScriptsToBundleShellScript = addSentryWithBundledScriptsToBundleShellScript;
83
+ function modifyAppDelegate(config) {
84
+ return (0, config_plugins_1.withAppDelegate)(config, async (config) => {
85
+ if (!config.modResults?.path) {
86
+ (0, logger_1.warnOnce)("Can't add 'RNSentrySDK.start()' to the iOS AppDelegate, because the file was not found.");
87
+ return config;
88
+ }
89
+ const fileName = path.basename(config.modResults.path);
90
+ if (config.modResults.language === 'swift') {
91
+ if (config.modResults.contents.includes('RNSentrySDK.start()')) {
92
+ (0, logger_1.warnOnce)(`Your '${fileName}' already contains 'RNSentrySDK.start()'.`);
93
+ return config;
94
+ }
95
+ // Add RNSentrySDK.start() at the beginning of application method
96
+ const originalContents = config.modResults.contents;
97
+ config.modResults.contents = config.modResults.contents.replace(/(func application\([^)]*\) -> Bool \{)\s*\n(\s*)/s, '$1\n$2RNSentrySDK.start()\n$2');
98
+ if (config.modResults.contents === originalContents) {
99
+ (0, logger_1.warnOnce)(`Failed to insert 'RNSentrySDK.start()' in '${fileName}'.`);
100
+ }
101
+ else if (!config.modResults.contents.includes('import RNSentry')) {
102
+ // Insert import statement after the first import (works for both UIKit and Expo imports)
103
+ config.modResults.contents = config.modResults.contents.replace(/(import \S+\n)/, '$1import RNSentry\n');
104
+ }
105
+ }
106
+ else if (['objcpp', 'objc'].includes(config.modResults.language)) {
107
+ if (config.modResults.contents.includes('[RNSentrySDK start]')) {
108
+ (0, logger_1.warnOnce)(`Your '${fileName}' already contains '[RNSentrySDK start]'.`);
109
+ return config;
110
+ }
111
+ // Add [RNSentrySDK start] at the beginning of application:didFinishLaunchingWithOptions method
112
+ const originalContents = config.modResults.contents;
113
+ config.modResults.contents = config.modResults.contents.replace(/(- \(BOOL\)application:[\s\S]*?didFinishLaunchingWithOptions:[\s\S]*?\{\n)(\s*)/s, '$1$2[RNSentrySDK start];\n$2');
114
+ if (config.modResults.contents === originalContents) {
115
+ (0, logger_1.warnOnce)(`Failed to insert '[RNSentrySDK start]' in '${fileName}.`);
116
+ }
117
+ else if (!config.modResults.contents.includes('#import <RNSentry/RNSentry.h>')) {
118
+ // Add import after AppDelegate.h
119
+ config.modResults.contents = config.modResults.contents.replace(/(#import "AppDelegate.h"\n)/, '$1#import <RNSentry/RNSentry.h>\n');
120
+ }
121
+ }
122
+ else {
123
+ (0, logger_1.warnOnce)(`Unsupported language '${config.modResults.language}' detected in '${fileName}', the native code won't be updated.`);
124
+ }
125
+ return config;
126
+ });
127
+ }
128
+ exports.modifyAppDelegate = modifyAppDelegate;
@@ -73,4 +73,24 @@ if [ -f "$SENTRY_COLLECT_MODULES" ]; then
73
73
  /bin/sh "$SENTRY_COLLECT_MODULES"
74
74
  fi
75
75
 
76
+ # sentry.options.json Block
77
+ SENTRY_OPTIONS_FILE_ERROR_MESSAGE_POSTFIX="Skipping options file copy. To disable this behavior, set SENTRY_COPY_OPTIONS_FILE=false in your environment variables."
78
+ SENTRY_OPTIONS_FILE_NAME="sentry.options.json"
79
+ SENTRY_OPTIONS_FILE_DESTINATION_PATH="$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/$SENTRY_OPTIONS_FILE_NAME"
80
+ [ -z "$SENTRY_OPTIONS_FILE_PATH" ] && SENTRY_OPTIONS_FILE_PATH="$RN_PROJECT_ROOT/$SENTRY_OPTIONS_FILE_NAME"
81
+ [ -z "$SENTRY_COPY_OPTIONS_FILE" ] && SENTRY_COPY_OPTIONS_FILE=true
82
+
83
+ if [ "$SENTRY_COPY_OPTIONS_FILE" = true ]; then
84
+ if [[ -z "$CONFIGURATION_BUILD_DIR" ]]; then
85
+ echo "[Sentry] CONFIGURATION_BUILD_DIR is not set. $SENTRY_OPTIONS_FILE_ERROR_MESSAGE_POSTFIX" 1>&2
86
+ elif [[ -z "$UNLOCALIZED_RESOURCES_FOLDER_PATH" ]]; then
87
+ echo "[Sentry] UNLOCALIZED_RESOURCES_FOLDER_PATH is not set. $SENTRY_OPTIONS_FILE_ERROR_MESSAGE_POSTFIX" 1>&2
88
+ elif [ ! -f "$SENTRY_OPTIONS_FILE_PATH" ]; then
89
+ echo "[Sentry] $SENTRY_OPTIONS_FILE_PATH not found. $SENTRY_OPTIONS_FILE_ERROR_MESSAGE_POSTFIX" 1>&2
90
+ else
91
+ cp "$SENTRY_OPTIONS_FILE_PATH" "$SENTRY_OPTIONS_FILE_DESTINATION_PATH"
92
+ echo "[Sentry] Copied $SENTRY_OPTIONS_FILE_PATH to $SENTRY_OPTIONS_FILE_DESTINATION_PATH"
93
+ fi
94
+ fi
95
+
76
96
  exit $exitCode
package/sentry.gradle CHANGED
@@ -20,8 +20,48 @@ interface InjectedExecOps {
20
20
  ExecOperations getExecOps()
21
21
  }
22
22
 
23
+ project.ext.shouldCopySentryOptionsFile = { -> // If not set, default to true
24
+ return System.getenv('SENTRY_COPY_OPTIONS_FILE') != 'false'
25
+ }
26
+
23
27
  def config = project.hasProperty("sentryCli") ? project.sentryCli : [];
24
28
 
29
+ def configFile = "sentry.options.json" // Sentry configuration file
30
+ def androidAssetsDir = new File("$rootDir/app/src/main/assets") // Path to Android assets folder
31
+
32
+ tasks.register("copySentryJsonConfiguration") {
33
+ onlyIf { shouldCopySentryOptionsFile() }
34
+ doLast {
35
+ def appRoot = project.rootDir.parentFile ?: project.rootDir
36
+ def sentryOptionsFile = new File(appRoot, configFile)
37
+ if (sentryOptionsFile.exists()) {
38
+ if (!androidAssetsDir.exists()) {
39
+ androidAssetsDir.mkdirs()
40
+ }
41
+
42
+ copy {
43
+ from sentryOptionsFile
44
+ into androidAssetsDir
45
+ rename { String fileName -> configFile }
46
+ }
47
+ logger.lifecycle("Copied ${configFile} to Android assets")
48
+ } else {
49
+ logger.warn("${configFile} not found in app root (${appRoot})")
50
+ }
51
+ }
52
+ }
53
+
54
+ tasks.register("cleanupTemporarySentryJsonConfiguration") {
55
+ onlyIf { shouldCopySentryOptionsFile() }
56
+ doLast {
57
+ def sentryOptionsFile = new File(androidAssetsDir, configFile)
58
+ if (sentryOptionsFile.exists()) {
59
+ logger.lifecycle("Deleting temporary file: ${sentryOptionsFile.path}")
60
+ sentryOptionsFile.delete()
61
+ }
62
+ }
63
+ }
64
+
25
65
  plugins.withId('com.android.application') {
26
66
  def androidComponents = extensions.getByName("androidComponents")
27
67
 
@@ -278,6 +318,17 @@ plugins.withId('com.android.application') {
278
318
  // gradle.projectsEvaluated doesn't work with --configure-on-demand
279
319
  // the task are create too late and not executed
280
320
  project.afterEvaluate {
321
+ // Add a task that copies the sentry.options.json file before the build starts
322
+ tasks.named("preBuild").configure {
323
+ dependsOn("copySentryJsonConfiguration")
324
+ }
325
+ // Cleanup sentry.options.json from assets after the build
326
+ tasks.matching { task ->
327
+ task.name == "build" || task.name.startsWith("assemble") || task.name.startsWith("install")
328
+ }.configureEach {
329
+ finalizedBy("cleanupTemporarySentryJsonConfiguration")
330
+ }
331
+
281
332
  if (config.flavorAware && config.sentryProperties) {
282
333
  throw new GradleException("Incompatible sentry configuration. " +
283
334
  "You cannot use both `flavorAware` and `sentryProperties`. " +
@@ -32,6 +32,8 @@ export interface Spec extends TurboModule {
32
32
  setContext(key: string, value: UnsafeObject | null): void;
33
33
  setExtra(key: string, value: string): void;
34
34
  setTag(key: string, value: string): void;
35
+ setAttribute(key: string, value: string): void;
36
+ setAttributes(attributes: UnsafeObject): void;
35
37
  enableNativeFramesTracking(): void;
36
38
  fetchModules(): Promise<string | undefined | null>;
37
39
  fetchViewHierarchy(): Promise<number[] | undefined | null>;
@@ -25,6 +25,8 @@ export interface Spec extends TurboModule {
25
25
  setContext(key: string, value: UnsafeObject | null): void;
26
26
  setExtra(key: string, value: string): void;
27
27
  setTag(key: string, value: string): void;
28
+ setAttribute(key: string, value: string): void;
29
+ setAttributes(attributes: UnsafeObject): void;
28
30
  enableNativeFramesTracking(): void;
29
31
  fetchModules(): Promise<string | undefined | null>;
30
32
  fetchViewHierarchy(): Promise<number[] | undefined | null>;
@@ -66,32 +66,6 @@ export interface MobileReplayOptions {
66
66
  * @platform ios
67
67
  */
68
68
  enableFastViewRendering?: boolean;
69
- /**
70
- * Array of view class names to include in subtree traversal during session replay and screenshot capture on iOS.
71
- *
72
- * Only views that are instances of these classes (or subclasses) will be traversed.
73
- * This helps prevent crashes when traversing problematic view hierarchies by allowing you to explicitly include only safe view classes.
74
- *
75
- * If both `includedViewClasses` and `excludedViewClasses` are set, `excludedViewClasses` takes precedence:
76
- * views matching excluded classes won't be traversed even if they match an included class.
77
- *
78
- * @default undefined
79
- * @platform ios
80
- */
81
- includedViewClasses?: string[];
82
- /**
83
- * Array of view class names to exclude from subtree traversal during session replay and screenshot capture on iOS.
84
- *
85
- * Views of these classes (or subclasses) will be skipped entirely, including all their children.
86
- * This helps prevent crashes when traversing problematic view hierarchies by allowing you to explicitly exclude problematic view classes.
87
- *
88
- * If both `includedViewClasses` and `excludedViewClasses` are set, `excludedViewClasses` takes precedence:
89
- * views matching excluded classes won't be traversed even if they match an included class.
90
- *
91
- * @default undefined
92
- * @platform ios
93
- */
94
- excludedViewClasses?: string[];
95
69
  /**
96
70
  * Sets the screenshot strategy used by the Session Replay integration on Android.
97
71
  *
@@ -1,3 +1,4 @@
1
+ import type { SpanAttributeValue } from '@sentry/core';
1
2
  import * as React from 'react';
2
3
  export type TouchEventBoundaryProps = {
3
4
  /**
@@ -30,6 +31,13 @@ export type TouchEventBoundaryProps = {
30
31
  * Label Name used to identify the touched element.
31
32
  */
32
33
  labelName?: string;
34
+ /**
35
+ * Custom attributes to add to user interaction spans.
36
+ * Accepts an object with string keys and values that are strings, numbers, booleans, or arrays.
37
+ *
38
+ * @experimental This API is experimental and may change in future releases.
39
+ */
40
+ spanAttributes?: Record<string, SpanAttributeValue>;
33
41
  };
34
42
  /**
35
43
  * Boundary to log breadcrumbs for interaction events.
@@ -1,6 +1,7 @@
1
1
  /// <reference types="react-native" />
2
2
  import type { InternalGlobal } from '@sentry/core';
3
3
  import type { ErrorUtils } from 'react-native/types';
4
+ import type { ReactNativeOptions } from '../options';
4
5
  import type { ExpoGlobalObject } from './expoglobalobject';
5
6
  export interface HermesPromiseRejectionTrackingOptions {
6
7
  allRejections: boolean;
@@ -32,6 +33,7 @@ export interface ReactNativeInternalGlobal extends InternalGlobal {
32
33
  nativePerformanceNow?: () => number;
33
34
  TextEncoder?: TextEncoder;
34
35
  alert?: (message: string) => void;
36
+ __SENTRY_OPTIONS__?: ReactNativeOptions;
35
37
  SENTRY_RELEASE?: {
36
38
  /** Used by Sentry Webpack Plugin, not used by RN, only to silence TS */
37
39
  id?: string;
@@ -1,4 +1,4 @@
1
1
  export declare const SDK_PACKAGE_NAME = "npm:@sentry/react-native";
2
2
  export declare const SDK_NAME = "sentry.javascript.react-native";
3
- export declare const SDK_VERSION = "7.10.0";
3
+ export declare const SDK_VERSION = "8.0.0-alpha.0";
4
4
  //# sourceMappingURL=version.d.ts.map
@@ -60,6 +60,8 @@ interface SentryNativeWrapper {
60
60
  setExtra(key: string, extra: unknown): void;
61
61
  setUser(user: User | null): void;
62
62
  setTag(key: string, value?: string): void;
63
+ setAttribute(key: string, value: string | number | boolean): void;
64
+ setAttributes(attributes: Record<string, string | number | boolean>): void;
63
65
  nativeCrash(): void;
64
66
  fetchModules(): Promise<Record<string, string> | null>;
65
67
  fetchViewHierarchy(): PromiseLike<Uint8Array | null>;