@sentry/react-native 8.3.0 → 8.4.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 (57) hide show
  1. package/RNSentry.podspec +1 -1
  2. package/android/libs/replay-stubs.jar +0 -0
  3. package/android/src/main/java/io/sentry/react/RNSentryStart.java +10 -0
  4. package/android/src/main/java/io/sentry/react/RNSentryVersion.java +1 -1
  5. package/dist/js/index.d.ts +2 -2
  6. package/dist/js/index.d.ts.map +1 -1
  7. package/dist/js/index.js +1 -1
  8. package/dist/js/index.js.map +1 -1
  9. package/dist/js/integrations/expocontext.d.ts.map +1 -1
  10. package/dist/js/integrations/expocontext.js +35 -1
  11. package/dist/js/integrations/expocontext.js.map +1 -1
  12. package/dist/js/sdk.d.ts.map +1 -1
  13. package/dist/js/sdk.js +3 -2
  14. package/dist/js/sdk.js.map +1 -1
  15. package/dist/js/tools/metroconfig.d.ts +4 -0
  16. package/dist/js/tools/metroconfig.d.ts.map +1 -1
  17. package/dist/js/tools/metroconfig.js +46 -1
  18. package/dist/js/tools/metroconfig.js.map +1 -1
  19. package/dist/js/tracing/expoAsset.d.ts +42 -0
  20. package/dist/js/tracing/expoAsset.d.ts.map +1 -0
  21. package/dist/js/tracing/expoAsset.js +60 -0
  22. package/dist/js/tracing/expoAsset.js.map +1 -0
  23. package/dist/js/tracing/expoImage.d.ts +61 -0
  24. package/dist/js/tracing/expoImage.d.ts.map +1 -0
  25. package/dist/js/tracing/expoImage.js +101 -0
  26. package/dist/js/tracing/expoImage.js.map +1 -0
  27. package/dist/js/tracing/index.d.ts +4 -0
  28. package/dist/js/tracing/index.d.ts.map +1 -1
  29. package/dist/js/tracing/index.js +2 -0
  30. package/dist/js/tracing/index.js.map +1 -1
  31. package/dist/js/tracing/origin.d.ts +2 -0
  32. package/dist/js/tracing/origin.d.ts.map +1 -1
  33. package/dist/js/tracing/origin.js +2 -0
  34. package/dist/js/tracing/origin.js.map +1 -1
  35. package/dist/js/tracing/reactnavigation.d.ts.map +1 -1
  36. package/dist/js/tracing/reactnavigation.js +9 -4
  37. package/dist/js/tracing/reactnavigation.js.map +1 -1
  38. package/dist/js/tracing/utils.d.ts +27 -1
  39. package/dist/js/tracing/utils.d.ts.map +1 -1
  40. package/dist/js/tracing/utils.js +66 -1
  41. package/dist/js/tracing/utils.js.map +1 -1
  42. package/dist/js/version.d.ts +1 -1
  43. package/dist/js/version.js +1 -1
  44. package/dist/js/version.js.map +1 -1
  45. package/ios/RNSentryVersion.m +1 -1
  46. package/package.json +9 -9
  47. package/plugin/build/utils.d.ts +1 -0
  48. package/plugin/build/utils.js +19 -1
  49. package/plugin/build/withSentry.d.ts +1 -0
  50. package/plugin/build/withSentry.js +28 -0
  51. package/ts3.8/dist/js/index.d.ts +2 -2
  52. package/ts3.8/dist/js/tracing/expoAsset.d.ts +42 -0
  53. package/ts3.8/dist/js/tracing/expoImage.d.ts +61 -0
  54. package/ts3.8/dist/js/tracing/index.d.ts +4 -0
  55. package/ts3.8/dist/js/tracing/origin.d.ts +2 -0
  56. package/ts3.8/dist/js/tracing/utils.d.ts +27 -1
  57. package/ts3.8/dist/js/version.d.ts +1 -1
@@ -1,4 +1,4 @@
1
- import { debug, dropUndefinedKeys, getSpanDescendants, SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT, SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, setMeasurement, spanToJSON, timestampInSeconds, uuid4, } from '@sentry/core';
1
+ import { debug, dropUndefinedKeys, getSpanDescendants, SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT, SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, setMeasurement, SPAN_STATUS_ERROR, SPAN_STATUS_OK, spanToJSON, startInactiveSpan, timestampInSeconds, uuid4, } from '@sentry/core';
2
2
  import { RN_GLOBAL_OBJ } from '../utils/worldwide';
3
3
  export const defaultTransactionSource = 'component';
4
4
  export const customTransactionSource = 'custom';
@@ -88,6 +88,71 @@ export function getBundleStartTimestampMs() {
88
88
  export function createSpanJSON(from) {
89
89
  return dropUndefinedKeys(Object.assign(Object.assign({ status: 'ok' }, from), { span_id: from.span_id ? from.span_id : uuid4().substring(16), trace_id: from.trace_id ? from.trace_id : uuid4(), data: dropUndefinedKeys(Object.assign({ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: from.op, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: from.origin }, (from.data ? from.data : {}))) }));
90
90
  }
91
+ /**
92
+ * Wraps a function call that returns a `Promise` with an inactive span that
93
+ * is automatically ended on success or failure (both sync throws and async
94
+ * rejections).
95
+ *
96
+ * This is the standard pattern for instrumenting async SDK operations such as
97
+ * `Image.loadAsync` and `Asset.loadAsync`.
98
+ *
99
+ * The span status is always set by this utility (`ok` on resolve, `error` on
100
+ * reject or sync throw). If you need custom status logic (e.g. inspecting the
101
+ * resolved value), handle span lifecycle manually instead.
102
+ *
103
+ * @param spanOptions Options forwarded to `startInactiveSpan`.
104
+ * @param fn The function to call.
105
+ * @returns Whatever `fn` returns (the original `Promise`).
106
+ */
107
+ export function traceAsyncOperation(spanOptions, fn) {
108
+ const span = startInactiveSpan(spanOptions);
109
+ try {
110
+ return fn()
111
+ .then(result => {
112
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SPAN_STATUS_OK });
113
+ span === null || span === void 0 ? void 0 : span.end();
114
+ return result;
115
+ })
116
+ .catch((error) => {
117
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SPAN_STATUS_ERROR, message: String(error) });
118
+ span === null || span === void 0 ? void 0 : span.end();
119
+ throw error;
120
+ });
121
+ }
122
+ catch (error) {
123
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SPAN_STATUS_ERROR, message: String(error) });
124
+ span === null || span === void 0 ? void 0 : span.end();
125
+ throw error;
126
+ }
127
+ }
128
+ /**
129
+ * Strips query string and fragment from a URL, preserving the scheme, host, and path.
130
+ */
131
+ export function sanitizeUrl(url) {
132
+ try {
133
+ const withoutQuery = url.split('?')[0] || url;
134
+ return withoutQuery.split('#')[0] || withoutQuery;
135
+ }
136
+ catch (_a) {
137
+ return url;
138
+ }
139
+ }
140
+ /**
141
+ * Extracts a short, human-readable description from a URL by stripping
142
+ * the query string, fragment, and path — returning only the filename.
143
+ */
144
+ export function describeUrl(url) {
145
+ try {
146
+ // Remove query string and fragment
147
+ const withoutQuery = url.split('?')[0] || url;
148
+ const withoutFragment = withoutQuery.split('#')[0] || withoutQuery;
149
+ const filename = withoutFragment.split('/').pop();
150
+ return filename || withoutFragment;
151
+ }
152
+ catch (_a) {
153
+ return url;
154
+ }
155
+ }
91
156
  const SENTRY_DEFAULT_ORIGIN = 'manual';
92
157
  /**
93
158
  *
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/js/tracing/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MeasurementUnit, Span, SpanJSON, TransactionSource } from '@sentry/core';\nimport {\n debug,\n dropUndefinedKeys,\n getSpanDescendants,\n SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT,\n SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n setMeasurement,\n spanToJSON,\n timestampInSeconds,\n uuid4,\n} from '@sentry/core';\nimport { RN_GLOBAL_OBJ } from '../utils/worldwide';\n\nexport const defaultTransactionSource: TransactionSource = 'component';\nexport const customTransactionSource: TransactionSource = 'custom';\n\n/**\n * A margin of error of 50ms is allowed for the async native bridge call.\n * Anything larger would reduce the accuracy of our frames measurements.\n */\nexport const MARGIN_OF_ERROR_SECONDS = 0.05;\n\nconst timeOriginMilliseconds = Date.now();\n\n/**\n * Returns the timestamp where the JS global scope was initialized.\n */\nexport function getTimeOriginMilliseconds(): number {\n return timeOriginMilliseconds;\n}\n\n/**\n * Determines if the timestamp is now or within the specified margin of error from now.\n */\nexport function isNearToNow(timestamp: number | undefined): boolean {\n if (!timestamp) {\n return false;\n }\n return Math.abs(timestampInSeconds() - timestamp) <= MARGIN_OF_ERROR_SECONDS;\n}\n\n/**\n * Sets the duration of the span as a measurement.\n * Uses `setMeasurement` function from @sentry/core.\n */\nexport function setSpanDurationAsMeasurement(name: string, span: Span): void {\n const { timestamp: spanEnd, start_timestamp: spanStart } = spanToJSON(span);\n if (!spanEnd || !spanStart) {\n return;\n }\n\n setMeasurement(name, (spanEnd - spanStart) * 1000, 'millisecond');\n}\n\n/**\n * Sets the duration of the span as a measurement.\n * Uses `setMeasurement` function from @sentry/core.\n */\nexport function setSpanDurationAsMeasurementOnSpan(name: string, span: Span, on: Span): void {\n const { timestamp: spanEnd, start_timestamp: spanStart } = spanToJSON(span);\n if (!spanEnd || !spanStart) {\n return;\n }\n\n setSpanMeasurement(on, name, (spanEnd - spanStart) * 1000, 'millisecond');\n}\n\n/**\n * Sets measurement on the give span.\n */\nexport function setSpanMeasurement(span: Span, key: string, value: number, unit: MeasurementUnit): void {\n span.addEvent(key, {\n [SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE]: value,\n [SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT]: unit as string,\n });\n}\n\n/**\n * Returns the latest end timestamp of the child spans of the given span.\n */\nexport function getLatestChildSpanEndTimestamp(span: Span): number | undefined {\n const childEndTimestamps = getSpanDescendants(span)\n .map(span => spanToJSON(span).timestamp)\n .filter(timestamp => !!timestamp) as number[];\n\n return childEndTimestamps.length ? Math.max(...childEndTimestamps) : undefined;\n}\n\n/**\n * Returns unix timestamp in ms of the bundle start time.\n *\n * If not available, returns undefined.\n */\nexport function getBundleStartTimestampMs(): number | undefined {\n const bundleStartTime = RN_GLOBAL_OBJ.__BUNDLE_START_TIME__;\n if (!bundleStartTime) {\n debug.warn('Missing the bundle start time on the global object.');\n return undefined;\n }\n\n if (!RN_GLOBAL_OBJ.nativePerformanceNow) {\n // bundleStartTime is Date.now() in milliseconds\n return bundleStartTime;\n }\n\n // nativePerformanceNow() is monotonic clock like performance.now()\n const approxStartingTimeOrigin = Date.now() - RN_GLOBAL_OBJ.nativePerformanceNow();\n return approxStartingTimeOrigin + bundleStartTime;\n}\n\n/**\n * Creates valid span JSON object from the given data.\n */\nexport function createSpanJSON(\n from: Partial<SpanJSON> & Pick<Required<SpanJSON>, 'description' | 'start_timestamp' | 'timestamp' | 'origin'>,\n): SpanJSON {\n return dropUndefinedKeys({\n status: 'ok',\n ...from,\n span_id: from.span_id ? from.span_id : uuid4().substring(16),\n trace_id: from.trace_id ? from.trace_id : uuid4(),\n data: dropUndefinedKeys({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: from.op,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: from.origin,\n ...(from.data ? from.data : {}),\n }),\n });\n}\n\nconst SENTRY_DEFAULT_ORIGIN = 'manual';\n\n/**\n *\n */\nexport function createChildSpanJSON(\n parent: SpanJSON,\n from: Partial<SpanJSON> & Pick<Required<SpanJSON>, 'description' | 'start_timestamp' | 'timestamp'>,\n): SpanJSON {\n return createSpanJSON({\n op: parent.op,\n trace_id: parent.trace_id,\n parent_span_id: parent.span_id,\n origin: parent.origin || SENTRY_DEFAULT_ORIGIN,\n ...from,\n });\n}\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/js/tracing/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MeasurementUnit, Span, SpanJSON, StartSpanOptions, TransactionSource } from '@sentry/core';\nimport {\n debug,\n dropUndefinedKeys,\n getSpanDescendants,\n SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT,\n SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n setMeasurement,\n SPAN_STATUS_ERROR,\n SPAN_STATUS_OK,\n spanToJSON,\n startInactiveSpan,\n timestampInSeconds,\n uuid4,\n} from '@sentry/core';\nimport { RN_GLOBAL_OBJ } from '../utils/worldwide';\n\nexport const defaultTransactionSource: TransactionSource = 'component';\nexport const customTransactionSource: TransactionSource = 'custom';\n\n/**\n * A margin of error of 50ms is allowed for the async native bridge call.\n * Anything larger would reduce the accuracy of our frames measurements.\n */\nexport const MARGIN_OF_ERROR_SECONDS = 0.05;\n\nconst timeOriginMilliseconds = Date.now();\n\n/**\n * Returns the timestamp where the JS global scope was initialized.\n */\nexport function getTimeOriginMilliseconds(): number {\n return timeOriginMilliseconds;\n}\n\n/**\n * Determines if the timestamp is now or within the specified margin of error from now.\n */\nexport function isNearToNow(timestamp: number | undefined): boolean {\n if (!timestamp) {\n return false;\n }\n return Math.abs(timestampInSeconds() - timestamp) <= MARGIN_OF_ERROR_SECONDS;\n}\n\n/**\n * Sets the duration of the span as a measurement.\n * Uses `setMeasurement` function from @sentry/core.\n */\nexport function setSpanDurationAsMeasurement(name: string, span: Span): void {\n const { timestamp: spanEnd, start_timestamp: spanStart } = spanToJSON(span);\n if (!spanEnd || !spanStart) {\n return;\n }\n\n setMeasurement(name, (spanEnd - spanStart) * 1000, 'millisecond');\n}\n\n/**\n * Sets the duration of the span as a measurement.\n * Uses `setMeasurement` function from @sentry/core.\n */\nexport function setSpanDurationAsMeasurementOnSpan(name: string, span: Span, on: Span): void {\n const { timestamp: spanEnd, start_timestamp: spanStart } = spanToJSON(span);\n if (!spanEnd || !spanStart) {\n return;\n }\n\n setSpanMeasurement(on, name, (spanEnd - spanStart) * 1000, 'millisecond');\n}\n\n/**\n * Sets measurement on the give span.\n */\nexport function setSpanMeasurement(span: Span, key: string, value: number, unit: MeasurementUnit): void {\n span.addEvent(key, {\n [SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE]: value,\n [SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT]: unit as string,\n });\n}\n\n/**\n * Returns the latest end timestamp of the child spans of the given span.\n */\nexport function getLatestChildSpanEndTimestamp(span: Span): number | undefined {\n const childEndTimestamps = getSpanDescendants(span)\n .map(span => spanToJSON(span).timestamp)\n .filter(timestamp => !!timestamp) as number[];\n\n return childEndTimestamps.length ? Math.max(...childEndTimestamps) : undefined;\n}\n\n/**\n * Returns unix timestamp in ms of the bundle start time.\n *\n * If not available, returns undefined.\n */\nexport function getBundleStartTimestampMs(): number | undefined {\n const bundleStartTime = RN_GLOBAL_OBJ.__BUNDLE_START_TIME__;\n if (!bundleStartTime) {\n debug.warn('Missing the bundle start time on the global object.');\n return undefined;\n }\n\n if (!RN_GLOBAL_OBJ.nativePerformanceNow) {\n // bundleStartTime is Date.now() in milliseconds\n return bundleStartTime;\n }\n\n // nativePerformanceNow() is monotonic clock like performance.now()\n const approxStartingTimeOrigin = Date.now() - RN_GLOBAL_OBJ.nativePerformanceNow();\n return approxStartingTimeOrigin + bundleStartTime;\n}\n\n/**\n * Creates valid span JSON object from the given data.\n */\nexport function createSpanJSON(\n from: Partial<SpanJSON> & Pick<Required<SpanJSON>, 'description' | 'start_timestamp' | 'timestamp' | 'origin'>,\n): SpanJSON {\n return dropUndefinedKeys({\n status: 'ok',\n ...from,\n span_id: from.span_id ? from.span_id : uuid4().substring(16),\n trace_id: from.trace_id ? from.trace_id : uuid4(),\n data: dropUndefinedKeys({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: from.op,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: from.origin,\n ...(from.data ? from.data : {}),\n }),\n });\n}\n\n/**\n * Wraps a function call that returns a `Promise` with an inactive span that\n * is automatically ended on success or failure (both sync throws and async\n * rejections).\n *\n * This is the standard pattern for instrumenting async SDK operations such as\n * `Image.loadAsync` and `Asset.loadAsync`.\n *\n * The span status is always set by this utility (`ok` on resolve, `error` on\n * reject or sync throw). If you need custom status logic (e.g. inspecting the\n * resolved value), handle span lifecycle manually instead.\n *\n * @param spanOptions Options forwarded to `startInactiveSpan`.\n * @param fn The function to call.\n * @returns Whatever `fn` returns (the original `Promise`).\n */\nexport function traceAsyncOperation<T>(spanOptions: StartSpanOptions, fn: () => Promise<T>): Promise<T> {\n const span = startInactiveSpan(spanOptions);\n\n try {\n return fn()\n .then(result => {\n span?.setStatus({ code: SPAN_STATUS_OK });\n span?.end();\n return result;\n })\n .catch((error: unknown) => {\n span?.setStatus({ code: SPAN_STATUS_ERROR, message: String(error) });\n span?.end();\n throw error;\n });\n } catch (error) {\n span?.setStatus({ code: SPAN_STATUS_ERROR, message: String(error) });\n span?.end();\n throw error;\n }\n}\n\n/**\n * Strips query string and fragment from a URL, preserving the scheme, host, and path.\n */\nexport function sanitizeUrl(url: string): string {\n try {\n const withoutQuery = url.split('?')[0] || url;\n return withoutQuery.split('#')[0] || withoutQuery;\n } catch {\n return url;\n }\n}\n\n/**\n * Extracts a short, human-readable description from a URL by stripping\n * the query string, fragment, and path — returning only the filename.\n */\nexport function describeUrl(url: string): string {\n try {\n // Remove query string and fragment\n const withoutQuery = url.split('?')[0] || url;\n const withoutFragment = withoutQuery.split('#')[0] || withoutQuery;\n const filename = withoutFragment.split('/').pop();\n return filename || withoutFragment;\n } catch {\n return url;\n }\n}\n\nconst SENTRY_DEFAULT_ORIGIN = 'manual';\n\n/**\n *\n */\nexport function createChildSpanJSON(\n parent: SpanJSON,\n from: Partial<SpanJSON> & Pick<Required<SpanJSON>, 'description' | 'start_timestamp' | 'timestamp'>,\n): SpanJSON {\n return createSpanJSON({\n op: parent.op,\n trace_id: parent.trace_id,\n parent_span_id: parent.span_id,\n origin: parent.origin || SENTRY_DEFAULT_ORIGIN,\n ...from,\n });\n}\n"]}
@@ -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 = "8.3.0";
3
+ export declare const SDK_VERSION = "8.4.0";
4
4
  //# sourceMappingURL=version.d.ts.map
@@ -3,5 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SDK_VERSION = exports.SDK_NAME = exports.SDK_PACKAGE_NAME = void 0;
4
4
  exports.SDK_PACKAGE_NAME = 'npm:@sentry/react-native';
5
5
  exports.SDK_NAME = 'sentry.javascript.react-native';
6
- exports.SDK_VERSION = '8.3.0';
6
+ exports.SDK_VERSION = '8.4.0';
7
7
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/js/version.ts"],"names":[],"mappings":";;;AAAa,QAAA,gBAAgB,GAAG,0BAA0B,CAAC;AAC9C,QAAA,QAAQ,GAAG,gCAAgC,CAAC;AAC5C,QAAA,WAAW,GAAG,OAAO,CAAC","sourcesContent":["export const SDK_PACKAGE_NAME = 'npm:@sentry/react-native';\nexport const SDK_NAME = 'sentry.javascript.react-native';\nexport const SDK_VERSION = '8.3.0';\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/js/version.ts"],"names":[],"mappings":";;;AAAa,QAAA,gBAAgB,GAAG,0BAA0B,CAAC;AAC9C,QAAA,QAAQ,GAAG,gCAAgC,CAAC;AAC5C,QAAA,WAAW,GAAG,OAAO,CAAC","sourcesContent":["export const SDK_PACKAGE_NAME = 'npm:@sentry/react-native';\nexport const SDK_NAME = 'sentry.javascript.react-native';\nexport const SDK_VERSION = '8.4.0';\n"]}
@@ -3,4 +3,4 @@
3
3
  NSString *const NATIVE_SDK_NAME = @"sentry.cocoa.react-native";
4
4
  NSString *const REACT_NATIVE_SDK_NAME = @"sentry.javascript.react-native";
5
5
  NSString *const REACT_NATIVE_SDK_PACKAGE_NAME = @"npm:@sentry/react-native";
6
- NSString *const REACT_NATIVE_SDK_PACKAGE_VERSION = @"8.3.0";
6
+ NSString *const REACT_NATIVE_SDK_PACKAGE_VERSION = @"8.4.0";
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@sentry/react-native",
3
3
  "homepage": "https://github.com/getsentry/sentry-react-native",
4
4
  "repository": "https://github.com/getsentry/sentry-react-native",
5
- "version": "8.3.0",
5
+ "version": "8.4.0",
6
6
  "description": "Official Sentry SDK for react-native",
7
7
  "typings": "dist/js/index.d.ts",
8
8
  "types": "dist/js/index.d.ts",
@@ -72,20 +72,20 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@sentry/babel-plugin-component-annotate": "5.1.1",
75
- "@sentry/browser": "10.42.0",
76
- "@sentry/cli": "3.3.0",
77
- "@sentry/core": "10.42.0",
78
- "@sentry/react": "10.42.0",
79
- "@sentry/types": "10.42.0"
75
+ "@sentry/browser": "10.43.0",
76
+ "@sentry/cli": "3.3.3",
77
+ "@sentry/core": "10.43.0",
78
+ "@sentry/react": "10.43.0",
79
+ "@sentry/types": "10.43.0"
80
80
  },
81
81
  "devDependencies": {
82
82
  "@babel/core": "^7.26.7",
83
83
  "@expo/metro-config": "~0.20.0",
84
84
  "@mswjs/interceptors": "^0.25.15",
85
85
  "@react-native/babel-preset": "0.80.0",
86
- "@sentry-internal/eslint-config-sdk": "10.42.0",
87
- "@sentry-internal/eslint-plugin-sdk": "10.42.0",
88
- "@sentry-internal/typescript": "10.42.0",
86
+ "@sentry-internal/eslint-config-sdk": "10.43.0",
87
+ "@sentry-internal/eslint-plugin-sdk": "10.43.0",
88
+ "@sentry-internal/typescript": "10.43.0",
89
89
  "@sentry/wizard": "6.12.0",
90
90
  "@testing-library/react-native": "^13.2.2",
91
91
  "@types/jest": "^29.5.13",
@@ -1 +1,2 @@
1
1
  export declare function writeSentryPropertiesTo(filepath: string, sentryProperties: string): void;
2
+ export declare function writeSentryOptions(projectRoot: string, pluginOptions: Record<string, unknown>): void;
@@ -23,9 +23,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.writeSentryPropertiesTo = void 0;
26
+ exports.writeSentryOptions = exports.writeSentryPropertiesTo = void 0;
27
27
  const fs = __importStar(require("fs"));
28
28
  const path = __importStar(require("path"));
29
+ const logger_1 = require("./logger");
29
30
  function writeSentryPropertiesTo(filepath, sentryProperties) {
30
31
  if (!fs.existsSync(filepath)) {
31
32
  throw new Error(`Directory '${filepath}' does not exist.`);
@@ -33,3 +34,20 @@ function writeSentryPropertiesTo(filepath, sentryProperties) {
33
34
  fs.writeFileSync(path.resolve(filepath, 'sentry.properties'), sentryProperties);
34
35
  }
35
36
  exports.writeSentryPropertiesTo = writeSentryPropertiesTo;
37
+ const SENTRY_OPTIONS_FILE_NAME = 'sentry.options.json';
38
+ function writeSentryOptions(projectRoot, pluginOptions) {
39
+ const optionsFilePath = path.resolve(projectRoot, SENTRY_OPTIONS_FILE_NAME);
40
+ let existingOptions = {};
41
+ if (fs.existsSync(optionsFilePath)) {
42
+ try {
43
+ existingOptions = JSON.parse(fs.readFileSync(optionsFilePath, 'utf8'));
44
+ }
45
+ catch (e) {
46
+ (0, logger_1.warnOnce)(`Failed to parse ${SENTRY_OPTIONS_FILE_NAME}: ${e}. These options will not be set.`);
47
+ return;
48
+ }
49
+ }
50
+ const mergedOptions = { ...existingOptions, ...pluginOptions };
51
+ fs.writeFileSync(optionsFilePath, `${JSON.stringify(mergedOptions, null, 2)}\n`);
52
+ }
53
+ exports.writeSentryOptions = writeSentryOptions;
@@ -6,6 +6,7 @@ interface PluginProps {
6
6
  authToken?: string;
7
7
  url?: string;
8
8
  useNativeInit?: boolean;
9
+ options?: Record<string, unknown>;
9
10
  experimental_android?: SentryAndroidGradlePluginOptions;
10
11
  }
11
12
  export declare function getSentryProperties(props: PluginProps | void): string | null;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.withSentry = exports.getSentryProperties = void 0;
4
4
  const config_plugins_1 = require("expo/config-plugins");
5
5
  const logger_1 = require("./logger");
6
+ const utils_1 = require("./utils");
6
7
  const version_1 = require("./version");
7
8
  const withSentryAndroid_1 = require("./withSentryAndroid");
8
9
  const withSentryAndroidGradlePlugin_1 = require("./withSentryAndroidGradlePlugin");
@@ -14,6 +15,14 @@ const withSentryPlugin = (config, props) => {
14
15
  delete props.authToken;
15
16
  }
16
17
  let cfg = config;
18
+ const pluginOptions = props?.options ? { ...props.options } : {};
19
+ const environment = process.env.SENTRY_ENVIRONMENT;
20
+ if (environment) {
21
+ pluginOptions.environment = environment;
22
+ }
23
+ if (Object.keys(pluginOptions).length > 0) {
24
+ cfg = withSentryOptionsFile(cfg, pluginOptions);
25
+ }
17
26
  if (sentryProperties !== null) {
18
27
  try {
19
28
  cfg = (0, withSentryAndroid_1.withSentryAndroid)(cfg, { sentryProperties, useNativeInit: props?.useNativeInit });
@@ -61,6 +70,25 @@ ${project ? `defaults.project=${project}` : missingProjectMessage}
61
70
  ${authToken ? `${existingAuthTokenMessage}\nauth.token=${authToken}` : missingAuthTokenMessage}`;
62
71
  }
63
72
  exports.getSentryProperties = getSentryProperties;
73
+ function withSentryOptionsFile(config, pluginOptions) {
74
+ // withDangerousMod requires a platform key, but sentry.options.json is at the project root.
75
+ // We apply to both platforms so it works with `expo prebuild --platform ios` or `--platform android`.
76
+ let cfg = (0, config_plugins_1.withDangerousMod)(config, [
77
+ 'android',
78
+ mod => {
79
+ (0, utils_1.writeSentryOptions)(mod.modRequest.projectRoot, pluginOptions);
80
+ return mod;
81
+ },
82
+ ]);
83
+ cfg = (0, config_plugins_1.withDangerousMod)(cfg, [
84
+ 'ios',
85
+ mod => {
86
+ (0, utils_1.writeSentryOptions)(mod.modRequest.projectRoot, pluginOptions);
87
+ return mod;
88
+ },
89
+ ]);
90
+ return cfg;
91
+ }
64
92
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
65
93
  const withSentry = (0, config_plugins_1.createRunOncePlugin)(withSentryPlugin, version_1.PLUGIN_NAME, version_1.PLUGIN_VERSION);
66
94
  exports.withSentry = withSentry;
@@ -9,8 +9,8 @@ export type { ReactNativeOptions, NativeLogEntry } from './options';
9
9
  export { ReactNativeClient } from './client';
10
10
  export { init, wrap, nativeCrash, flush, close, withScope, crashedLastRun } from './sdk';
11
11
  export { TouchEventBoundary, withTouchEventBoundary } from './touchevents';
12
- export { reactNativeTracingIntegration, getCurrentReactNativeTracingIntegration, getReactNativeTracingIntegration, reactNavigationIntegration, reactNativeNavigationIntegration, sentryTraceGesture, TimeToInitialDisplay, TimeToFullDisplay, startTimeToInitialDisplaySpan, startTimeToFullDisplaySpan, startIdleNavigationSpan, startIdleSpan, getDefaultIdleNavigationSpanOptions, createTimeToFullDisplay, createTimeToInitialDisplay, wrapExpoRouter, } from './tracing';
13
- export type { TimeToDisplayProps, ExpoRouter } from './tracing';
12
+ export { reactNativeTracingIntegration, getCurrentReactNativeTracingIntegration, getReactNativeTracingIntegration, reactNavigationIntegration, reactNativeNavigationIntegration, sentryTraceGesture, TimeToInitialDisplay, TimeToFullDisplay, startTimeToInitialDisplaySpan, startTimeToFullDisplaySpan, startIdleNavigationSpan, startIdleSpan, getDefaultIdleNavigationSpanOptions, createTimeToFullDisplay, createTimeToInitialDisplay, wrapExpoRouter, wrapExpoImage, wrapExpoAsset, } from './tracing';
13
+ export type { TimeToDisplayProps, ExpoRouter, ExpoImage, ExpoAsset } from './tracing';
14
14
  export { Mask, Unmask } from './replay/CustomMask';
15
15
  export { FeedbackButton } from './feedback/FeedbackButton';
16
16
  export { FeedbackWidget } from './feedback/FeedbackWidget';
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Internal interface for expo-asset's Asset instance.
3
+ * We define this to avoid a hard dependency on expo-asset.
4
+ */
5
+ export interface ExpoAssetInstance {
6
+ name: string;
7
+ type: string;
8
+ hash: string | null;
9
+ uri: string;
10
+ localUri: string | null;
11
+ width: number | null;
12
+ height: number | null;
13
+ downloaded: boolean;
14
+ downloadAsync(): Promise<ExpoAssetInstance>;
15
+ }
16
+ /**
17
+ * Represents the expo-asset `Asset` class with its static methods.
18
+ * We only describe the methods that we instrument.
19
+ */
20
+ export interface ExpoAsset {
21
+ loadAsync(moduleId: number | number[] | string | string[]): Promise<ExpoAssetInstance[]>;
22
+ fromModule(virtualAssetModule: number | string): ExpoAssetInstance;
23
+ }
24
+ /**
25
+ * Wraps expo-asset's `Asset` class to add automated performance monitoring.
26
+ *
27
+ * This function instruments `Asset.loadAsync` static method
28
+ * to create performance spans that measure how long asset loading takes.
29
+ *
30
+ * @param assetClass - The `Asset` class from `expo-asset`
31
+ * @returns The same class with instrumented static methods
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * import { Asset } from 'expo-asset';
36
+ * import * as Sentry from '@sentry/react-native';
37
+ *
38
+ * Sentry.wrapExpoAsset(Asset);
39
+ * ```
40
+ */
41
+ export declare function wrapExpoAsset<T extends ExpoAsset>(assetClass: T): T;
42
+ //# sourceMappingURL=expoAsset.d.ts.map
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Internal interface for expo-image's ImageSource.
3
+ * We define this to avoid a hard dependency on expo-image.
4
+ */
5
+ interface ExpoImageSource {
6
+ uri?: string;
7
+ headers?: Record<string, string>;
8
+ width?: number | null;
9
+ height?: number | null;
10
+ cacheKey?: string;
11
+ }
12
+ /**
13
+ * Internal interface for expo-image's ImageLoadOptions.
14
+ * We define this to avoid a hard dependency on expo-image.
15
+ */
16
+ interface ExpoImageLoadOptions {
17
+ maxWidth?: number;
18
+ maxHeight?: number;
19
+ onError?(error: Error, retry: () => void): void;
20
+ }
21
+ /**
22
+ * Internal interface for expo-image's ImageRef.
23
+ * We define this to avoid a hard dependency on expo-image.
24
+ */
25
+ interface ExpoImageRef {
26
+ readonly width: number;
27
+ readonly height: number;
28
+ readonly scale: number;
29
+ readonly mediaType: string | null;
30
+ readonly isAnimated?: boolean;
31
+ }
32
+ /**
33
+ * Represents the expo-image `Image` class with its static methods.
34
+ * We only describe the methods that we instrument.
35
+ */
36
+ export interface ExpoImage {
37
+ prefetch(urls: string | string[], cachePolicyOrOptions?: any): Promise<boolean>;
38
+ loadAsync(source: ExpoImageSource | string | number, options?: ExpoImageLoadOptions): Promise<ExpoImageRef>;
39
+ clearMemoryCache?(): Promise<boolean>;
40
+ clearDiskCache?(): Promise<boolean>;
41
+ }
42
+ /**
43
+ * Wraps expo-image's `Image` class to add automated performance monitoring.
44
+ *
45
+ * This function instruments `Image.prefetch` and `Image.loadAsync` static methods
46
+ * to create performance spans that measure how long image prefetching and loading take.
47
+ *
48
+ * @param imageClass - The `Image` class from `expo-image`
49
+ * @returns The same class with instrumented static methods
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * import { Image } from 'expo-image';
54
+ * import * as Sentry from '@sentry/react-native';
55
+ *
56
+ * Sentry.wrapExpoImage(Image);
57
+ * ```
58
+ */
59
+ export declare function wrapExpoImage<T extends ExpoImage>(imageClass: T): T;
60
+ export {};
61
+ //# sourceMappingURL=expoImage.d.ts.map
@@ -4,6 +4,10 @@ export { reactNavigationIntegration } from './reactnavigation';
4
4
  export { reactNativeNavigationIntegration } from './reactnativenavigation';
5
5
  export { wrapExpoRouter } from './expoRouter';
6
6
  export type { ExpoRouter } from './expoRouter';
7
+ export { wrapExpoImage } from './expoImage';
8
+ export type { ExpoImage } from './expoImage';
9
+ export { wrapExpoAsset } from './expoAsset';
10
+ export type { ExpoAsset } from './expoAsset';
7
11
  export { startIdleNavigationSpan, startIdleSpan, getDefaultIdleNavigationSpanOptions } from './span';
8
12
  export type { ReactNavigationCurrentRoute, ReactNavigationRoute } from './types';
9
13
  export { ReactNativeProfiler } from './reactnativeprofiler';
@@ -8,4 +8,6 @@ export declare const SPAN_ORIGIN_AUTO_NAVIGATION_CUSTOM = "auto.navigation.custo
8
8
  export declare const SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY = "auto.ui.time_to_display";
9
9
  export declare const SPAN_ORIGIN_MANUAL_UI_TIME_TO_DISPLAY = "manual.ui.time_to_display";
10
10
  export declare const SPAN_ORIGIN_AUTO_EXPO_ROUTER_PREFETCH = "auto.expo_router.prefetch";
11
+ export declare const SPAN_ORIGIN_AUTO_RESOURCE_EXPO_IMAGE = "auto.resource.expo_image";
12
+ export declare const SPAN_ORIGIN_AUTO_RESOURCE_EXPO_ASSET = "auto.resource.expo_asset";
11
13
  //# sourceMappingURL=origin.d.ts.map
@@ -1,4 +1,4 @@
1
- import type { MeasurementUnit, Span, SpanJSON, TransactionSource } from '@sentry/core';
1
+ import type { MeasurementUnit, Span, SpanJSON, StartSpanOptions, TransactionSource } from '@sentry/core';
2
2
  export declare const defaultTransactionSource: TransactionSource;
3
3
  export declare const customTransactionSource: TransactionSource;
4
4
  /**
@@ -42,6 +42,32 @@ export declare function getBundleStartTimestampMs(): number | undefined;
42
42
  * Creates valid span JSON object from the given data.
43
43
  */
44
44
  export declare function createSpanJSON(from: Partial<SpanJSON> & Pick<Required<SpanJSON>, 'description' | 'start_timestamp' | 'timestamp' | 'origin'>): SpanJSON;
45
+ /**
46
+ * Wraps a function call that returns a `Promise` with an inactive span that
47
+ * is automatically ended on success or failure (both sync throws and async
48
+ * rejections).
49
+ *
50
+ * This is the standard pattern for instrumenting async SDK operations such as
51
+ * `Image.loadAsync` and `Asset.loadAsync`.
52
+ *
53
+ * The span status is always set by this utility (`ok` on resolve, `error` on
54
+ * reject or sync throw). If you need custom status logic (e.g. inspecting the
55
+ * resolved value), handle span lifecycle manually instead.
56
+ *
57
+ * @param spanOptions Options forwarded to `startInactiveSpan`.
58
+ * @param fn The function to call.
59
+ * @returns Whatever `fn` returns (the original `Promise`).
60
+ */
61
+ export declare function traceAsyncOperation<T>(spanOptions: StartSpanOptions, fn: () => Promise<T>): Promise<T>;
62
+ /**
63
+ * Strips query string and fragment from a URL, preserving the scheme, host, and path.
64
+ */
65
+ export declare function sanitizeUrl(url: string): string;
66
+ /**
67
+ * Extracts a short, human-readable description from a URL by stripping
68
+ * the query string, fragment, and path — returning only the filename.
69
+ */
70
+ export declare function describeUrl(url: string): string;
45
71
  /**
46
72
  *
47
73
  */
@@ -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 = "8.3.0";
3
+ export declare const SDK_VERSION = "8.4.0";
4
4
  //# sourceMappingURL=version.d.ts.map