@andre1502/react-utilities 0.9.7 → 1.0.1

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 (125) hide show
  1. package/dist/Config/Config.js +2 -4
  2. package/dist/Config/Config.js.map +1 -1
  3. package/dist/Config/GoogleAuth.js +1 -1
  4. package/dist/Config/GoogleAuth.js.map +1 -1
  5. package/dist/Config/Sitemap.js +1 -1
  6. package/dist/Config/Sitemap.js.map +1 -1
  7. package/dist/EnvironmentEnum-BjXsfSRZ.js.map +1 -1
  8. package/dist/EnvironmentEnum-UcQ6Il1O.js.map +1 -1
  9. package/dist/Format/NumberParser.js.map +1 -1
  10. package/dist/Hooks/useDevice.d.ts +3 -0
  11. package/dist/Hooks/useDevice.js +47 -0
  12. package/dist/Hooks/useDevice.js.map +1 -0
  13. package/dist/Hooks/useSEStore.d.ts +5 -0
  14. package/dist/Hooks/useSound.d.ts +9 -0
  15. package/dist/Hooks/useSound.js +47 -0
  16. package/dist/Hooks/useSound.js.map +1 -0
  17. package/dist/Hooks/useWebSocket.d.ts +9 -0
  18. package/dist/Hooks/useWebSocket.js +120 -0
  19. package/dist/Hooks/useWebSocket.js.map +1 -0
  20. package/dist/I18n/I18n.d.ts +1 -1
  21. package/dist/I18n/I18n.js +9 -5
  22. package/dist/I18n/I18n.js.map +1 -1
  23. package/dist/NumberFormat-CvvBWhHc.js.map +1 -1
  24. package/dist/NumberFormat-glmpbk7E.js.map +1 -1
  25. package/dist/React-BaJ1KfGF.js.map +1 -1
  26. package/dist/React-qUl0CBmE.js.map +1 -1
  27. package/dist/ReactNative-Ckbnh5vm.js +1770 -0
  28. package/dist/ReactNative-Ckbnh5vm.js.map +1 -0
  29. package/dist/ReactNative-DLA9Xwp4.js +1792 -0
  30. package/dist/ReactNative-DLA9Xwp4.js.map +1 -0
  31. package/dist/Sentry/Build.js +1 -1
  32. package/dist/Sentry/Build.js.map +1 -1
  33. package/dist/Sentry/React.js.map +1 -1
  34. package/dist/Sentry/ReactNative.js +3 -3
  35. package/dist/Sentry/ReactNative.js.map +1 -1
  36. package/dist/Utils/Array.d.ts +3 -0
  37. package/dist/Utils/Array.js +26 -0
  38. package/dist/Utils/Array.js.map +1 -0
  39. package/dist/Utils/Files.js +2 -2
  40. package/dist/Utils/Files.js.map +1 -1
  41. package/dist/Utils/Pagination.d.ts +3 -0
  42. package/dist/Utils/Pagination.js +32 -0
  43. package/dist/Utils/Pagination.js.map +1 -0
  44. package/dist/Utils/Utils.d.ts +10 -0
  45. package/dist/Utils/Utils.js +98 -0
  46. package/dist/Utils/Utils.js.map +1 -0
  47. package/dist/Utils-Bnk2KHAB.js +70 -0
  48. package/dist/Utils-Bnk2KHAB.js.map +1 -0
  49. package/dist/Utils-Cq948gfa.js.map +1 -1
  50. package/dist/Utils-DLJ3-s9J.js +61 -0
  51. package/dist/Utils-DLJ3-s9J.js.map +1 -0
  52. package/dist/Utils-Dilye04y.js.map +1 -1
  53. package/dist/config-cli.cjs +2 -3
  54. package/dist/config-cli.cjs.map +1 -1
  55. package/dist/config-cli.js +3 -3
  56. package/dist/config-cli.js.map +1 -1
  57. package/dist/config-cli.mjs +2 -2
  58. package/dist/config-cli.mjs.map +1 -1
  59. package/dist/enums/CurrencySymbolEnum.js +4 -2
  60. package/dist/enums/CurrencySymbolEnum.js.map +1 -1
  61. package/dist/enums/DeviceEnum.d.ts +4 -0
  62. package/dist/enums/DeviceEnum.js +12 -0
  63. package/dist/enums/DeviceEnum.js.map +1 -0
  64. package/dist/hooks.cjs +13 -0
  65. package/dist/hooks.cjs.map +1 -0
  66. package/dist/hooks.d.ts +9 -0
  67. package/dist/hooks.js +87 -0
  68. package/dist/hooks.js.map +1 -0
  69. package/dist/hooks.mjs +4 -0
  70. package/dist/hooks.mjs.map +1 -0
  71. package/dist/i18n.cjs +3104 -6
  72. package/dist/i18n.cjs.map +1 -1
  73. package/dist/i18n.mjs +3104 -2
  74. package/dist/i18n.mjs.map +1 -1
  75. package/dist/index-cli.cjs +1 -1
  76. package/dist/index-cli.mjs +1 -1
  77. package/dist/index-rn.cjs +5 -5
  78. package/dist/index-rn.mjs +3 -3
  79. package/dist/index.cjs +25 -4
  80. package/dist/index.cjs.map +1 -1
  81. package/dist/index.d.ts +2 -0
  82. package/dist/index.js +22 -0
  83. package/dist/index.js.map +1 -1
  84. package/dist/index.mjs +6 -2
  85. package/dist/index.mjs.map +1 -1
  86. package/dist/sentry-cli.cjs.map +1 -1
  87. package/dist/sentry-cli.js +1 -1
  88. package/dist/sentry-cli.js.map +1 -1
  89. package/dist/sentry-cli.mjs.map +1 -1
  90. package/dist/sentry-rn.cjs +1 -1
  91. package/dist/sentry-rn.mjs +1 -1
  92. package/dist/useWebSocket-GlUpioz3.js +168 -0
  93. package/dist/useWebSocket-GlUpioz3.js.map +1 -0
  94. package/dist/useWebSocket-vgu8TAsa.js +163 -0
  95. package/dist/useWebSocket-vgu8TAsa.js.map +1 -0
  96. package/dist/utils.cjs +58 -0
  97. package/dist/utils.cjs.map +1 -0
  98. package/dist/utils.d.ts +3 -0
  99. package/dist/utils.js +39 -0
  100. package/dist/utils.js.map +1 -0
  101. package/dist/utils.mjs +43 -0
  102. package/dist/utils.mjs.map +1 -0
  103. package/package.json +51 -40
  104. package/src/Config/Config.ts +2 -2
  105. package/src/Hooks/useDevice.ts +34 -0
  106. package/src/Hooks/useSEStore.tsx +29 -0
  107. package/src/Hooks/useSound.ts +44 -0
  108. package/src/Hooks/useWebSocket.ts +115 -0
  109. package/src/I18n/I18n.ts +1 -4
  110. package/src/Sentry/ReactNative.ts +2 -5
  111. package/src/Utils/Array.ts +23 -0
  112. package/src/Utils/Pagination.ts +42 -0
  113. package/src/Utils/Utils.ts +75 -0
  114. package/src/enums/DeviceEnum.ts +4 -0
  115. package/src/hooks.ts +11 -0
  116. package/src/index.ts +2 -0
  117. package/src/utils.ts +3 -0
  118. package/dist/I18n-BIBLVzaQ.js +0 -3313
  119. package/dist/I18n-BIBLVzaQ.js.map +0 -1
  120. package/dist/I18n-tdxuTc45.js +0 -3316
  121. package/dist/I18n-tdxuTc45.js.map +0 -1
  122. package/dist/ReactNative-CqUrY2ZJ.js +0 -3856
  123. package/dist/ReactNative-CqUrY2ZJ.js.map +0 -1
  124. package/dist/ReactNative-mNnws-b5.js +0 -3834
  125. package/dist/ReactNative-mNnws-b5.js.map +0 -1
@@ -0,0 +1,1792 @@
1
+ 'use strict';
2
+
3
+ var Sentry = require('@sentry/react-native');
4
+ var Utils = require('./Utils-Dilye04y.js');
5
+
6
+ function _interopNamespaceDefault(e) {
7
+ var n = Object.create(null);
8
+ if (e) {
9
+ Object.keys(e).forEach(function (k) {
10
+ if (k !== 'default') {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function () { return e[k]; }
15
+ });
16
+ }
17
+ });
18
+ }
19
+ n.default = e;
20
+ return Object.freeze(n);
21
+ }
22
+
23
+ var Sentry__namespace = /*#__PURE__*/_interopNamespaceDefault(Sentry);
24
+
25
+ // This is a magic string replaced by rollup
26
+
27
+ const SDK_VERSION = "8.54.0" ;
28
+
29
+ /** Get's the global object for the current JavaScript runtime */
30
+ const GLOBAL_OBJ = globalThis ;
31
+
32
+ /**
33
+ * Returns a global singleton contained in the global `__SENTRY__[]` object.
34
+ *
35
+ * If the singleton doesn't already exist in `__SENTRY__`, it will be created using the given factory
36
+ * function and added to the `__SENTRY__` object.
37
+ *
38
+ * @param name name of the global singleton on __SENTRY__
39
+ * @param creator creator Factory function to create the singleton if it doesn't already exist on `__SENTRY__`
40
+ * @param obj (Optional) The global object on which to look for `__SENTRY__`, if not `GLOBAL_OBJ`'s return value
41
+ * @returns the singleton
42
+ */
43
+ function getGlobalSingleton(name, creator, obj) {
44
+ const gbl = (obj || GLOBAL_OBJ) ;
45
+ const __SENTRY__ = (gbl.__SENTRY__ = gbl.__SENTRY__ || {});
46
+ const versionedCarrier = (__SENTRY__[SDK_VERSION] = __SENTRY__[SDK_VERSION] || {});
47
+ return versionedCarrier[name] || (versionedCarrier[name] = creator());
48
+ }
49
+
50
+ /**
51
+ * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.
52
+ *
53
+ * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking.
54
+ */
55
+ const DEBUG_BUILD = (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__);
56
+
57
+ /** Prefix for logging strings */
58
+ const PREFIX = 'Sentry Logger ';
59
+
60
+ const CONSOLE_LEVELS = [
61
+ 'debug',
62
+ 'info',
63
+ 'warn',
64
+ 'error',
65
+ 'log',
66
+ 'assert',
67
+ 'trace',
68
+ ] ;
69
+
70
+ /** This may be mutated by the console instrumentation. */
71
+ const originalConsoleMethods
72
+
73
+ = {};
74
+
75
+ /** JSDoc */
76
+
77
+ /**
78
+ * Temporarily disable sentry console instrumentations.
79
+ *
80
+ * @param callback The function to run against the original `console` messages
81
+ * @returns The results of the callback
82
+ */
83
+ function consoleSandbox(callback) {
84
+ if (!('console' in GLOBAL_OBJ)) {
85
+ return callback();
86
+ }
87
+
88
+ const console = GLOBAL_OBJ.console ;
89
+ const wrappedFuncs = {};
90
+
91
+ const wrappedLevels = Object.keys(originalConsoleMethods) ;
92
+
93
+ // Restore all wrapped console methods
94
+ wrappedLevels.forEach(level => {
95
+ const originalConsoleMethod = originalConsoleMethods[level] ;
96
+ wrappedFuncs[level] = console[level] ;
97
+ console[level] = originalConsoleMethod;
98
+ });
99
+
100
+ try {
101
+ return callback();
102
+ } finally {
103
+ // Revert restoration to wrapped state
104
+ wrappedLevels.forEach(level => {
105
+ console[level] = wrappedFuncs[level] ;
106
+ });
107
+ }
108
+ }
109
+
110
+ function makeLogger() {
111
+ let enabled = false;
112
+ const logger = {
113
+ enable: () => {
114
+ enabled = true;
115
+ },
116
+ disable: () => {
117
+ enabled = false;
118
+ },
119
+ isEnabled: () => enabled,
120
+ };
121
+
122
+ if (DEBUG_BUILD) {
123
+ CONSOLE_LEVELS.forEach(name => {
124
+ logger[name] = (...args) => {
125
+ if (enabled) {
126
+ consoleSandbox(() => {
127
+ GLOBAL_OBJ.console[name](`${PREFIX}[${name}]:`, ...args);
128
+ });
129
+ }
130
+ };
131
+ });
132
+ } else {
133
+ CONSOLE_LEVELS.forEach(name => {
134
+ logger[name] = () => undefined;
135
+ });
136
+ }
137
+
138
+ return logger ;
139
+ }
140
+
141
+ /**
142
+ * This is a logger singleton which either logs things or no-ops if logging is not enabled.
143
+ * The logger is a singleton on the carrier, to ensure that a consistent logger is used throughout the SDK.
144
+ */
145
+ const logger = getGlobalSingleton('logger', makeLogger);
146
+
147
+ const defaultFunctionName = '<anonymous>';
148
+
149
+ /**
150
+ * Safely extract function name from itself
151
+ */
152
+ function getFunctionName(fn) {
153
+ try {
154
+ if (!fn || typeof fn !== 'function') {
155
+ return defaultFunctionName;
156
+ }
157
+ return fn.name || defaultFunctionName;
158
+ } catch (e) {
159
+ // Just accessing custom props in some Selenium environments
160
+ // can cause a "Permission denied" exception (see raven-js#495).
161
+ return defaultFunctionName;
162
+ }
163
+ }
164
+
165
+ // We keep the handlers globally
166
+ const handlers = {};
167
+ const instrumented = {};
168
+
169
+ /** Add a handler function. */
170
+ function addHandler(type, handler) {
171
+ handlers[type] = handlers[type] || [];
172
+ (handlers[type] ).push(handler);
173
+ }
174
+
175
+ /** Maybe run an instrumentation function, unless it was already called. */
176
+ function maybeInstrument(type, instrumentFn) {
177
+ if (!instrumented[type]) {
178
+ instrumented[type] = true;
179
+ try {
180
+ instrumentFn();
181
+ } catch (e) {
182
+ DEBUG_BUILD && logger.error(`Error while instrumenting ${type}`, e);
183
+ }
184
+ }
185
+ }
186
+
187
+ /** Trigger handlers for a given instrumentation type. */
188
+ function triggerHandlers(type, data) {
189
+ const typeHandlers = handlers[type];
190
+ if (!typeHandlers) {
191
+ return;
192
+ }
193
+
194
+ for (const handler of typeHandlers) {
195
+ try {
196
+ handler(data);
197
+ } catch (e) {
198
+ DEBUG_BUILD &&
199
+ logger.error(
200
+ `Error while triggering instrumentation handler.\nType: ${type}\nName: ${getFunctionName(handler)}\nError:`,
201
+ e,
202
+ );
203
+ }
204
+ }
205
+ }
206
+
207
+ /**
208
+ * An object that contains globally accessible properties and maintains a scope stack.
209
+ * @hidden
210
+ */
211
+
212
+ /**
213
+ * Returns the global shim registry.
214
+ *
215
+ * FIXME: This function is problematic, because despite always returning a valid Carrier,
216
+ * it has an optional `__SENTRY__` property, which then in turn requires us to always perform an unnecessary check
217
+ * at the call-site. We always access the carrier through this function, so we can guarantee that `__SENTRY__` is there.
218
+ **/
219
+ function getMainCarrier() {
220
+ // This ensures a Sentry carrier exists
221
+ getSentryCarrier(GLOBAL_OBJ);
222
+ return GLOBAL_OBJ;
223
+ }
224
+
225
+ /** Will either get the existing sentry carrier, or create a new one. */
226
+ function getSentryCarrier(carrier) {
227
+ const __SENTRY__ = (carrier.__SENTRY__ = carrier.__SENTRY__ || {});
228
+
229
+ // For now: First SDK that sets the .version property wins
230
+ __SENTRY__.version = __SENTRY__.version || SDK_VERSION;
231
+
232
+ // Intentionally populating and returning the version of "this" SDK instance
233
+ // rather than what's set in .version so that "this" SDK always gets its carrier
234
+ return (__SENTRY__[SDK_VERSION] = __SENTRY__[SDK_VERSION] || {});
235
+ }
236
+
237
+ // eslint-disable-next-line @typescript-eslint/unbound-method
238
+ const objectToString = Object.prototype.toString;
239
+ /**
240
+ * Checks whether given value is an instance of the given built-in class.
241
+ *
242
+ * @param wat The value to be checked
243
+ * @param className
244
+ * @returns A boolean representing the result.
245
+ */
246
+ function isBuiltin(wat, className) {
247
+ return objectToString.call(wat) === `[object ${className}]`;
248
+ }
249
+
250
+ /**
251
+ * Checks whether given value's type is an object literal, or a class instance.
252
+ * {@link isPlainObject}.
253
+ *
254
+ * @param wat A value to be checked.
255
+ * @returns A boolean representing the result.
256
+ */
257
+ function isPlainObject(wat) {
258
+ return isBuiltin(wat, 'Object');
259
+ }
260
+
261
+ /**
262
+ * Checks whether given value has a then function.
263
+ * @param wat A value to be checked.
264
+ */
265
+ function isThenable(wat) {
266
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
267
+ return Boolean(wat && wat.then && typeof wat.then === 'function');
268
+ }
269
+
270
+ /**
271
+ * Checks whether given value's type is a Vue ViewModel.
272
+ *
273
+ * @param wat A value to be checked.
274
+ * @returns A boolean representing the result.
275
+ */
276
+ function isVueViewModel(wat) {
277
+ // Not using Object.prototype.toString because in Vue 3 it would read the instance's Symbol(Symbol.toStringTag) property.
278
+ return !!(typeof wat === 'object' && wat !== null && ((wat ).__isVue || (wat )._isVue));
279
+ }
280
+
281
+ /**
282
+ * Join values in array
283
+ * @param input array of values to be joined together
284
+ * @param delimiter string to be placed in-between values
285
+ * @returns Joined values
286
+ */
287
+ function safeJoin(input, delimiter) {
288
+ if (!Array.isArray(input)) {
289
+ return '';
290
+ }
291
+
292
+ const output = [];
293
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
294
+ for (let i = 0; i < input.length; i++) {
295
+ const value = input[i];
296
+ try {
297
+ // This is a hack to fix a Vue3-specific bug that causes an infinite loop of
298
+ // console warnings. This happens when a Vue template is rendered with
299
+ // an undeclared variable, which we try to stringify, ultimately causing
300
+ // Vue to issue another warning which repeats indefinitely.
301
+ // see: https://github.com/getsentry/sentry-javascript/pull/8981
302
+ if (isVueViewModel(value)) {
303
+ output.push('[VueViewModel]');
304
+ } else {
305
+ output.push(String(value));
306
+ }
307
+ } catch (e) {
308
+ output.push('[value cannot be serialized]');
309
+ }
310
+ }
311
+
312
+ return output.join(delimiter);
313
+ }
314
+
315
+ /**
316
+ * Replace a method in an object with a wrapped version of itself.
317
+ *
318
+ * @param source An object that contains a method to be wrapped.
319
+ * @param name The name of the method to be wrapped.
320
+ * @param replacementFactory A higher-order function that takes the original version of the given method and returns a
321
+ * wrapped version. Note: The function returned by `replacementFactory` needs to be a non-arrow function, in order to
322
+ * preserve the correct value of `this`, and the original method must be called using `origMethod.call(this, <other
323
+ * args>)` or `origMethod.apply(this, [<other args>])` (rather than being called directly), again to preserve `this`.
324
+ * @returns void
325
+ */
326
+ function fill(source, name, replacementFactory) {
327
+ if (!(name in source)) {
328
+ return;
329
+ }
330
+
331
+ const original = source[name] ;
332
+ const wrapped = replacementFactory(original) ;
333
+
334
+ // Make sure it's a function first, as we need to attach an empty prototype for `defineProperties` to work
335
+ // otherwise it'll throw "TypeError: Object.defineProperties called on non-object"
336
+ if (typeof wrapped === 'function') {
337
+ markFunctionWrapped(wrapped, original);
338
+ }
339
+
340
+ try {
341
+ source[name] = wrapped;
342
+ } catch (e) {
343
+ DEBUG_BUILD && logger.log(`Failed to replace method "${name}" in object`, source);
344
+ }
345
+ }
346
+
347
+ /**
348
+ * Defines a non-enumerable property on the given object.
349
+ *
350
+ * @param obj The object on which to set the property
351
+ * @param name The name of the property to be set
352
+ * @param value The value to which to set the property
353
+ */
354
+ function addNonEnumerableProperty(obj, name, value) {
355
+ try {
356
+ Object.defineProperty(obj, name, {
357
+ // enumerable: false, // the default, so we can save on bundle size by not explicitly setting it
358
+ value: value,
359
+ writable: true,
360
+ configurable: true,
361
+ });
362
+ } catch (o_O) {
363
+ DEBUG_BUILD && logger.log(`Failed to add non-enumerable property "${name}" to object`, obj);
364
+ }
365
+ }
366
+
367
+ /**
368
+ * Remembers the original function on the wrapped function and
369
+ * patches up the prototype.
370
+ *
371
+ * @param wrapped the wrapper function
372
+ * @param original the original function that gets wrapped
373
+ */
374
+ function markFunctionWrapped(wrapped, original) {
375
+ try {
376
+ const proto = original.prototype || {};
377
+ wrapped.prototype = original.prototype = proto;
378
+ addNonEnumerableProperty(wrapped, '__sentry_original__', original);
379
+ } catch (o_O) {} // eslint-disable-line no-empty
380
+ }
381
+
382
+ const ONE_SECOND_IN_MS = 1000;
383
+
384
+ /**
385
+ * A partial definition of the [Performance Web API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Performance}
386
+ * for accessing a high-resolution monotonic clock.
387
+ */
388
+
389
+ /**
390
+ * Returns a timestamp in seconds since the UNIX epoch using the Date API.
391
+ *
392
+ * TODO(v8): Return type should be rounded.
393
+ */
394
+ function dateTimestampInSeconds() {
395
+ return Date.now() / ONE_SECOND_IN_MS;
396
+ }
397
+
398
+ /**
399
+ * Returns a wrapper around the native Performance API browser implementation, or undefined for browsers that do not
400
+ * support the API.
401
+ *
402
+ * Wrapping the native API works around differences in behavior from different browsers.
403
+ */
404
+ function createUnixTimestampInSecondsFunc() {
405
+ const { performance } = GLOBAL_OBJ ;
406
+ if (!performance || !performance.now) {
407
+ return dateTimestampInSeconds;
408
+ }
409
+
410
+ // Some browser and environments don't have a timeOrigin, so we fallback to
411
+ // using Date.now() to compute the starting time.
412
+ const approxStartingTimeOrigin = Date.now() - performance.now();
413
+ const timeOrigin = performance.timeOrigin == undefined ? approxStartingTimeOrigin : performance.timeOrigin;
414
+
415
+ // performance.now() is a monotonic clock, which means it starts at 0 when the process begins. To get the current
416
+ // wall clock time (actual UNIX timestamp), we need to add the starting time origin and the current time elapsed.
417
+ //
418
+ // TODO: This does not account for the case where the monotonic clock that powers performance.now() drifts from the
419
+ // wall clock time, which causes the returned timestamp to be inaccurate. We should investigate how to detect and
420
+ // correct for this.
421
+ // See: https://github.com/getsentry/sentry-javascript/issues/2590
422
+ // See: https://github.com/mdn/content/issues/4713
423
+ // See: https://dev.to/noamr/when-a-millisecond-is-not-a-millisecond-3h6
424
+ return () => {
425
+ return (timeOrigin + performance.now()) / ONE_SECOND_IN_MS;
426
+ };
427
+ }
428
+
429
+ /**
430
+ * Returns a timestamp in seconds since the UNIX epoch using either the Performance or Date APIs, depending on the
431
+ * availability of the Performance API.
432
+ *
433
+ * BUG: Note that because of how browsers implement the Performance API, the clock might stop when the computer is
434
+ * asleep. This creates a skew between `dateTimestampInSeconds` and `timestampInSeconds`. The
435
+ * skew can grow to arbitrary amounts like days, weeks or months.
436
+ * See https://github.com/getsentry/sentry-javascript/issues/2590.
437
+ */
438
+ const timestampInSeconds = createUnixTimestampInSecondsFunc();
439
+
440
+ /**
441
+ * The number of milliseconds since the UNIX epoch. This value is only usable in a browser, and only when the
442
+ * performance API is available.
443
+ */
444
+ (() => {
445
+ // Unfortunately browsers may report an inaccurate time origin data, through either performance.timeOrigin or
446
+ // performance.timing.navigationStart, which results in poor results in performance data. We only treat time origin
447
+ // data as reliable if they are within a reasonable threshold of the current time.
448
+
449
+ const { performance } = GLOBAL_OBJ ;
450
+ if (!performance || !performance.now) {
451
+ return undefined;
452
+ }
453
+
454
+ const threshold = 3600 * 1000;
455
+ const performanceNow = performance.now();
456
+ const dateNow = Date.now();
457
+
458
+ // if timeOrigin isn't available set delta to threshold so it isn't used
459
+ const timeOriginDelta = performance.timeOrigin
460
+ ? Math.abs(performance.timeOrigin + performanceNow - dateNow)
461
+ : threshold;
462
+ const timeOriginIsReliable = timeOriginDelta < threshold;
463
+
464
+ // While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin
465
+ // is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.
466
+ // Also as of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always
467
+ // a valid fallback. In the absence of an initial time provided by the browser, fallback to the current time from the
468
+ // Date API.
469
+ // eslint-disable-next-line deprecation/deprecation
470
+ const navigationStart = performance.timing && performance.timing.navigationStart;
471
+ const hasNavigationStart = typeof navigationStart === 'number';
472
+ // if navigationStart isn't available set delta to threshold so it isn't used
473
+ const navigationStartDelta = hasNavigationStart ? Math.abs(navigationStart + performanceNow - dateNow) : threshold;
474
+ const navigationStartIsReliable = navigationStartDelta < threshold;
475
+
476
+ if (timeOriginIsReliable || navigationStartIsReliable) {
477
+ // Use the more reliable time origin
478
+ if (timeOriginDelta <= navigationStartDelta) {
479
+ return performance.timeOrigin;
480
+ } else {
481
+ return navigationStart;
482
+ }
483
+ }
484
+ return dateNow;
485
+ })();
486
+
487
+ /**
488
+ * UUID4 generator
489
+ *
490
+ * @returns string Generated UUID4.
491
+ */
492
+ function uuid4() {
493
+ const gbl = GLOBAL_OBJ ;
494
+ const crypto = gbl.crypto || gbl.msCrypto;
495
+
496
+ let getRandomByte = () => Math.random() * 16;
497
+ try {
498
+ if (crypto && crypto.randomUUID) {
499
+ return crypto.randomUUID().replace(/-/g, '');
500
+ }
501
+ if (crypto && crypto.getRandomValues) {
502
+ getRandomByte = () => {
503
+ // crypto.getRandomValues might return undefined instead of the typed array
504
+ // in old Chromium versions (e.g. 23.0.1235.0 (151422))
505
+ // However, `typedArray` is still filled in-place.
506
+ // @see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#typedarray
507
+ const typedArray = new Uint8Array(1);
508
+ crypto.getRandomValues(typedArray);
509
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
510
+ return typedArray[0];
511
+ };
512
+ }
513
+ } catch (_) {
514
+ // some runtimes can crash invoking crypto
515
+ // https://github.com/getsentry/sentry-javascript/issues/8935
516
+ }
517
+
518
+ // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
519
+ // Concatenating the following numbers as strings results in '10000000100040008000100000000000'
520
+ return (([1e7] ) + 1e3 + 4e3 + 8e3 + 1e11).replace(/[018]/g, c =>
521
+ // eslint-disable-next-line no-bitwise
522
+ ((c ) ^ ((getRandomByte() & 15) >> ((c ) / 4))).toString(16),
523
+ );
524
+ }
525
+
526
+ function getFirstException(event) {
527
+ return event.exception && event.exception.values ? event.exception.values[0] : undefined;
528
+ }
529
+
530
+ /**
531
+ * Adds exception mechanism data to a given event. Uses defaults if the second parameter is not passed.
532
+ *
533
+ * @param event The event to modify.
534
+ * @param newMechanism Mechanism data to add to the event.
535
+ * @hidden
536
+ */
537
+ function addExceptionMechanism(event, newMechanism) {
538
+ const firstException = getFirstException(event);
539
+ if (!firstException) {
540
+ return;
541
+ }
542
+
543
+ const defaultMechanism = { type: 'generic', handled: true };
544
+ const currentMechanism = firstException.mechanism;
545
+ firstException.mechanism = { ...defaultMechanism, ...currentMechanism, ...newMechanism };
546
+
547
+ if (newMechanism && 'data' in newMechanism) {
548
+ const mergedData = { ...(currentMechanism && currentMechanism.data), ...newMechanism.data };
549
+ firstException.mechanism.data = mergedData;
550
+ }
551
+ }
552
+
553
+ /**
554
+ * Updates a session object with the properties passed in the context.
555
+ *
556
+ * Note that this function mutates the passed object and returns void.
557
+ * (Had to do this instead of returning a new and updated session because closing and sending a session
558
+ * makes an update to the session after it was passed to the sending logic.
559
+ * @see BaseClient.captureSession )
560
+ *
561
+ * @param session the `Session` to update
562
+ * @param context the `SessionContext` holding the properties that should be updated in @param session
563
+ */
564
+ // eslint-disable-next-line complexity
565
+ function updateSession(session, context = {}) {
566
+ if (context.user) {
567
+ if (!session.ipAddress && context.user.ip_address) {
568
+ session.ipAddress = context.user.ip_address;
569
+ }
570
+
571
+ if (!session.did && !context.did) {
572
+ session.did = context.user.id || context.user.email || context.user.username;
573
+ }
574
+ }
575
+
576
+ session.timestamp = context.timestamp || timestampInSeconds();
577
+
578
+ if (context.abnormal_mechanism) {
579
+ session.abnormal_mechanism = context.abnormal_mechanism;
580
+ }
581
+
582
+ if (context.ignoreDuration) {
583
+ session.ignoreDuration = context.ignoreDuration;
584
+ }
585
+ if (context.sid) {
586
+ // Good enough uuid validation. — Kamil
587
+ session.sid = context.sid.length === 32 ? context.sid : uuid4();
588
+ }
589
+ if (context.init !== undefined) {
590
+ session.init = context.init;
591
+ }
592
+ if (!session.did && context.did) {
593
+ session.did = `${context.did}`;
594
+ }
595
+ if (typeof context.started === 'number') {
596
+ session.started = context.started;
597
+ }
598
+ if (session.ignoreDuration) {
599
+ session.duration = undefined;
600
+ } else if (typeof context.duration === 'number') {
601
+ session.duration = context.duration;
602
+ } else {
603
+ const duration = session.timestamp - session.started;
604
+ session.duration = duration >= 0 ? duration : 0;
605
+ }
606
+ if (context.release) {
607
+ session.release = context.release;
608
+ }
609
+ if (context.environment) {
610
+ session.environment = context.environment;
611
+ }
612
+ if (!session.ipAddress && context.ipAddress) {
613
+ session.ipAddress = context.ipAddress;
614
+ }
615
+ if (!session.userAgent && context.userAgent) {
616
+ session.userAgent = context.userAgent;
617
+ }
618
+ if (typeof context.errors === 'number') {
619
+ session.errors = context.errors;
620
+ }
621
+ if (context.status) {
622
+ session.status = context.status;
623
+ }
624
+ }
625
+
626
+ /**
627
+ * Generate a random, valid trace ID.
628
+ */
629
+ function generateTraceId() {
630
+ return uuid4();
631
+ }
632
+
633
+ /**
634
+ * Generate a random, valid span ID.
635
+ */
636
+ function generateSpanId() {
637
+ return uuid4().substring(16);
638
+ }
639
+
640
+ /**
641
+ * Shallow merge two objects.
642
+ * Does not mutate the passed in objects.
643
+ * Undefined/empty values in the merge object will overwrite existing values.
644
+ *
645
+ * By default, this merges 2 levels deep.
646
+ */
647
+ function merge(initialObj, mergeObj, levels = 2) {
648
+ // If the merge value is not an object, or we have no merge levels left,
649
+ // we just set the value to the merge value
650
+ if (!mergeObj || typeof mergeObj !== 'object' || levels <= 0) {
651
+ return mergeObj;
652
+ }
653
+
654
+ // If the merge object is an empty object, and the initial object is not undefined, we return the initial object
655
+ if (initialObj && mergeObj && Object.keys(mergeObj).length === 0) {
656
+ return initialObj;
657
+ }
658
+
659
+ // Clone object
660
+ const output = { ...initialObj };
661
+
662
+ // Merge values into output, resursively
663
+ for (const key in mergeObj) {
664
+ if (Object.prototype.hasOwnProperty.call(mergeObj, key)) {
665
+ output[key] = merge(output[key], mergeObj[key], levels - 1);
666
+ }
667
+ }
668
+
669
+ return output;
670
+ }
671
+
672
+ const SCOPE_SPAN_FIELD = '_sentrySpan';
673
+
674
+ /**
675
+ * Set the active span for a given scope.
676
+ * NOTE: This should NOT be used directly, but is only used internally by the trace methods.
677
+ */
678
+ function _setSpanForScope(scope, span) {
679
+ if (span) {
680
+ addNonEnumerableProperty(scope , SCOPE_SPAN_FIELD, span);
681
+ } else {
682
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
683
+ delete (scope )[SCOPE_SPAN_FIELD];
684
+ }
685
+ }
686
+
687
+ /**
688
+ * Get the active span for a given scope.
689
+ * NOTE: This should NOT be used directly, but is only used internally by the trace methods.
690
+ */
691
+ function _getSpanForScope(scope) {
692
+ return scope[SCOPE_SPAN_FIELD];
693
+ }
694
+
695
+ /**
696
+ * Default value for maximum number of breadcrumbs added to an event.
697
+ */
698
+ const DEFAULT_MAX_BREADCRUMBS = 100;
699
+
700
+ /**
701
+ * Holds additional event information.
702
+ */
703
+ class ScopeClass {
704
+ /** Flag if notifying is happening. */
705
+
706
+ /** Callback for client to receive scope changes. */
707
+
708
+ /** Callback list that will be called during event processing. */
709
+
710
+ /** Array of breadcrumbs. */
711
+
712
+ /** User */
713
+
714
+ /** Tags */
715
+
716
+ /** Extra */
717
+
718
+ /** Contexts */
719
+
720
+ /** Attachments */
721
+
722
+ /** Propagation Context for distributed tracing */
723
+
724
+ /**
725
+ * A place to stash data which is needed at some point in the SDK's event processing pipeline but which shouldn't get
726
+ * sent to Sentry
727
+ */
728
+
729
+ /** Fingerprint */
730
+
731
+ /** Severity */
732
+
733
+ /**
734
+ * Transaction Name
735
+ *
736
+ * IMPORTANT: The transaction name on the scope has nothing to do with root spans/transaction objects.
737
+ * It's purpose is to assign a transaction to the scope that's added to non-transaction events.
738
+ */
739
+
740
+ /** Session */
741
+
742
+ /** Request Mode Session Status */
743
+ // eslint-disable-next-line deprecation/deprecation
744
+
745
+ /** The client on this scope */
746
+
747
+ /** Contains the last event id of a captured event. */
748
+
749
+ // NOTE: Any field which gets added here should get added not only to the constructor but also to the `clone` method.
750
+
751
+ constructor() {
752
+ this._notifyingListeners = false;
753
+ this._scopeListeners = [];
754
+ this._eventProcessors = [];
755
+ this._breadcrumbs = [];
756
+ this._attachments = [];
757
+ this._user = {};
758
+ this._tags = {};
759
+ this._extra = {};
760
+ this._contexts = {};
761
+ this._sdkProcessingMetadata = {};
762
+ this._propagationContext = {
763
+ traceId: generateTraceId(),
764
+ spanId: generateSpanId(),
765
+ };
766
+ }
767
+
768
+ /**
769
+ * @inheritDoc
770
+ */
771
+ clone() {
772
+ const newScope = new ScopeClass();
773
+ newScope._breadcrumbs = [...this._breadcrumbs];
774
+ newScope._tags = { ...this._tags };
775
+ newScope._extra = { ...this._extra };
776
+ newScope._contexts = { ...this._contexts };
777
+ if (this._contexts.flags) {
778
+ // We need to copy the `values` array so insertions on a cloned scope
779
+ // won't affect the original array.
780
+ newScope._contexts.flags = {
781
+ values: [...this._contexts.flags.values],
782
+ };
783
+ }
784
+
785
+ newScope._user = this._user;
786
+ newScope._level = this._level;
787
+ newScope._session = this._session;
788
+ newScope._transactionName = this._transactionName;
789
+ newScope._fingerprint = this._fingerprint;
790
+ newScope._eventProcessors = [...this._eventProcessors];
791
+ newScope._requestSession = this._requestSession;
792
+ newScope._attachments = [...this._attachments];
793
+ newScope._sdkProcessingMetadata = { ...this._sdkProcessingMetadata };
794
+ newScope._propagationContext = { ...this._propagationContext };
795
+ newScope._client = this._client;
796
+ newScope._lastEventId = this._lastEventId;
797
+
798
+ _setSpanForScope(newScope, _getSpanForScope(this));
799
+
800
+ return newScope;
801
+ }
802
+
803
+ /**
804
+ * @inheritDoc
805
+ */
806
+ setClient(client) {
807
+ this._client = client;
808
+ }
809
+
810
+ /**
811
+ * @inheritDoc
812
+ */
813
+ setLastEventId(lastEventId) {
814
+ this._lastEventId = lastEventId;
815
+ }
816
+
817
+ /**
818
+ * @inheritDoc
819
+ */
820
+ getClient() {
821
+ return this._client ;
822
+ }
823
+
824
+ /**
825
+ * @inheritDoc
826
+ */
827
+ lastEventId() {
828
+ return this._lastEventId;
829
+ }
830
+
831
+ /**
832
+ * @inheritDoc
833
+ */
834
+ addScopeListener(callback) {
835
+ this._scopeListeners.push(callback);
836
+ }
837
+
838
+ /**
839
+ * @inheritDoc
840
+ */
841
+ addEventProcessor(callback) {
842
+ this._eventProcessors.push(callback);
843
+ return this;
844
+ }
845
+
846
+ /**
847
+ * @inheritDoc
848
+ */
849
+ setUser(user) {
850
+ // If null is passed we want to unset everything, but still define keys,
851
+ // so that later down in the pipeline any existing values are cleared.
852
+ this._user = user || {
853
+ email: undefined,
854
+ id: undefined,
855
+ ip_address: undefined,
856
+ username: undefined,
857
+ };
858
+
859
+ if (this._session) {
860
+ updateSession(this._session, { user });
861
+ }
862
+
863
+ this._notifyScopeListeners();
864
+ return this;
865
+ }
866
+
867
+ /**
868
+ * @inheritDoc
869
+ */
870
+ getUser() {
871
+ return this._user;
872
+ }
873
+
874
+ /**
875
+ * @inheritDoc
876
+ */
877
+ // eslint-disable-next-line deprecation/deprecation
878
+ getRequestSession() {
879
+ return this._requestSession;
880
+ }
881
+
882
+ /**
883
+ * @inheritDoc
884
+ */
885
+ // eslint-disable-next-line deprecation/deprecation
886
+ setRequestSession(requestSession) {
887
+ this._requestSession = requestSession;
888
+ return this;
889
+ }
890
+
891
+ /**
892
+ * @inheritDoc
893
+ */
894
+ setTags(tags) {
895
+ this._tags = {
896
+ ...this._tags,
897
+ ...tags,
898
+ };
899
+ this._notifyScopeListeners();
900
+ return this;
901
+ }
902
+
903
+ /**
904
+ * @inheritDoc
905
+ */
906
+ setTag(key, value) {
907
+ this._tags = { ...this._tags, [key]: value };
908
+ this._notifyScopeListeners();
909
+ return this;
910
+ }
911
+
912
+ /**
913
+ * @inheritDoc
914
+ */
915
+ setExtras(extras) {
916
+ this._extra = {
917
+ ...this._extra,
918
+ ...extras,
919
+ };
920
+ this._notifyScopeListeners();
921
+ return this;
922
+ }
923
+
924
+ /**
925
+ * @inheritDoc
926
+ */
927
+ setExtra(key, extra) {
928
+ this._extra = { ...this._extra, [key]: extra };
929
+ this._notifyScopeListeners();
930
+ return this;
931
+ }
932
+
933
+ /**
934
+ * @inheritDoc
935
+ */
936
+ setFingerprint(fingerprint) {
937
+ this._fingerprint = fingerprint;
938
+ this._notifyScopeListeners();
939
+ return this;
940
+ }
941
+
942
+ /**
943
+ * @inheritDoc
944
+ */
945
+ setLevel(level) {
946
+ this._level = level;
947
+ this._notifyScopeListeners();
948
+ return this;
949
+ }
950
+
951
+ /**
952
+ * Sets the transaction name on the scope so that the name of e.g. taken server route or
953
+ * the page location is attached to future events.
954
+ *
955
+ * IMPORTANT: Calling this function does NOT change the name of the currently active
956
+ * root span. If you want to change the name of the active root span, use
957
+ * `Sentry.updateSpanName(rootSpan, 'new name')` instead.
958
+ *
959
+ * By default, the SDK updates the scope's transaction name automatically on sensible
960
+ * occasions, such as a page navigation or when handling a new request on the server.
961
+ */
962
+ setTransactionName(name) {
963
+ this._transactionName = name;
964
+ this._notifyScopeListeners();
965
+ return this;
966
+ }
967
+
968
+ /**
969
+ * @inheritDoc
970
+ */
971
+ setContext(key, context) {
972
+ if (context === null) {
973
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
974
+ delete this._contexts[key];
975
+ } else {
976
+ this._contexts[key] = context;
977
+ }
978
+
979
+ this._notifyScopeListeners();
980
+ return this;
981
+ }
982
+
983
+ /**
984
+ * @inheritDoc
985
+ */
986
+ setSession(session) {
987
+ if (!session) {
988
+ delete this._session;
989
+ } else {
990
+ this._session = session;
991
+ }
992
+ this._notifyScopeListeners();
993
+ return this;
994
+ }
995
+
996
+ /**
997
+ * @inheritDoc
998
+ */
999
+ getSession() {
1000
+ return this._session;
1001
+ }
1002
+
1003
+ /**
1004
+ * @inheritDoc
1005
+ */
1006
+ update(captureContext) {
1007
+ if (!captureContext) {
1008
+ return this;
1009
+ }
1010
+
1011
+ const scopeToMerge = typeof captureContext === 'function' ? captureContext(this) : captureContext;
1012
+
1013
+ const [scopeInstance, requestSession] =
1014
+ scopeToMerge instanceof Scope
1015
+ ? // eslint-disable-next-line deprecation/deprecation
1016
+ [scopeToMerge.getScopeData(), scopeToMerge.getRequestSession()]
1017
+ : isPlainObject(scopeToMerge)
1018
+ ? [captureContext , (captureContext ).requestSession]
1019
+ : [];
1020
+
1021
+ const { tags, extra, user, contexts, level, fingerprint = [], propagationContext } = scopeInstance || {};
1022
+
1023
+ this._tags = { ...this._tags, ...tags };
1024
+ this._extra = { ...this._extra, ...extra };
1025
+ this._contexts = { ...this._contexts, ...contexts };
1026
+
1027
+ if (user && Object.keys(user).length) {
1028
+ this._user = user;
1029
+ }
1030
+
1031
+ if (level) {
1032
+ this._level = level;
1033
+ }
1034
+
1035
+ if (fingerprint.length) {
1036
+ this._fingerprint = fingerprint;
1037
+ }
1038
+
1039
+ if (propagationContext) {
1040
+ this._propagationContext = propagationContext;
1041
+ }
1042
+
1043
+ if (requestSession) {
1044
+ this._requestSession = requestSession;
1045
+ }
1046
+
1047
+ return this;
1048
+ }
1049
+
1050
+ /**
1051
+ * @inheritDoc
1052
+ */
1053
+ clear() {
1054
+ // client is not cleared here on purpose!
1055
+ this._breadcrumbs = [];
1056
+ this._tags = {};
1057
+ this._extra = {};
1058
+ this._user = {};
1059
+ this._contexts = {};
1060
+ this._level = undefined;
1061
+ this._transactionName = undefined;
1062
+ this._fingerprint = undefined;
1063
+ this._requestSession = undefined;
1064
+ this._session = undefined;
1065
+ _setSpanForScope(this, undefined);
1066
+ this._attachments = [];
1067
+ this.setPropagationContext({ traceId: generateTraceId() });
1068
+
1069
+ this._notifyScopeListeners();
1070
+ return this;
1071
+ }
1072
+
1073
+ /**
1074
+ * @inheritDoc
1075
+ */
1076
+ addBreadcrumb(breadcrumb, maxBreadcrumbs) {
1077
+ const maxCrumbs = typeof maxBreadcrumbs === 'number' ? maxBreadcrumbs : DEFAULT_MAX_BREADCRUMBS;
1078
+
1079
+ // No data has been changed, so don't notify scope listeners
1080
+ if (maxCrumbs <= 0) {
1081
+ return this;
1082
+ }
1083
+
1084
+ const mergedBreadcrumb = {
1085
+ timestamp: dateTimestampInSeconds(),
1086
+ ...breadcrumb,
1087
+ };
1088
+
1089
+ this._breadcrumbs.push(mergedBreadcrumb);
1090
+ if (this._breadcrumbs.length > maxCrumbs) {
1091
+ this._breadcrumbs = this._breadcrumbs.slice(-maxCrumbs);
1092
+ if (this._client) {
1093
+ this._client.recordDroppedEvent('buffer_overflow', 'log_item');
1094
+ }
1095
+ }
1096
+
1097
+ this._notifyScopeListeners();
1098
+
1099
+ return this;
1100
+ }
1101
+
1102
+ /**
1103
+ * @inheritDoc
1104
+ */
1105
+ getLastBreadcrumb() {
1106
+ return this._breadcrumbs[this._breadcrumbs.length - 1];
1107
+ }
1108
+
1109
+ /**
1110
+ * @inheritDoc
1111
+ */
1112
+ clearBreadcrumbs() {
1113
+ this._breadcrumbs = [];
1114
+ this._notifyScopeListeners();
1115
+ return this;
1116
+ }
1117
+
1118
+ /**
1119
+ * @inheritDoc
1120
+ */
1121
+ addAttachment(attachment) {
1122
+ this._attachments.push(attachment);
1123
+ return this;
1124
+ }
1125
+
1126
+ /**
1127
+ * @inheritDoc
1128
+ */
1129
+ clearAttachments() {
1130
+ this._attachments = [];
1131
+ return this;
1132
+ }
1133
+
1134
+ /** @inheritDoc */
1135
+ getScopeData() {
1136
+ return {
1137
+ breadcrumbs: this._breadcrumbs,
1138
+ attachments: this._attachments,
1139
+ contexts: this._contexts,
1140
+ tags: this._tags,
1141
+ extra: this._extra,
1142
+ user: this._user,
1143
+ level: this._level,
1144
+ fingerprint: this._fingerprint || [],
1145
+ eventProcessors: this._eventProcessors,
1146
+ propagationContext: this._propagationContext,
1147
+ sdkProcessingMetadata: this._sdkProcessingMetadata,
1148
+ transactionName: this._transactionName,
1149
+ span: _getSpanForScope(this),
1150
+ };
1151
+ }
1152
+
1153
+ /**
1154
+ * @inheritDoc
1155
+ */
1156
+ setSDKProcessingMetadata(newData) {
1157
+ this._sdkProcessingMetadata = merge(this._sdkProcessingMetadata, newData, 2);
1158
+ return this;
1159
+ }
1160
+
1161
+ /**
1162
+ * @inheritDoc
1163
+ */
1164
+ setPropagationContext(
1165
+ context,
1166
+ ) {
1167
+ this._propagationContext = {
1168
+ // eslint-disable-next-line deprecation/deprecation
1169
+ spanId: generateSpanId(),
1170
+ ...context,
1171
+ };
1172
+ return this;
1173
+ }
1174
+
1175
+ /**
1176
+ * @inheritDoc
1177
+ */
1178
+ getPropagationContext() {
1179
+ return this._propagationContext;
1180
+ }
1181
+
1182
+ /**
1183
+ * @inheritDoc
1184
+ */
1185
+ captureException(exception, hint) {
1186
+ const eventId = hint && hint.event_id ? hint.event_id : uuid4();
1187
+
1188
+ if (!this._client) {
1189
+ logger.warn('No client configured on scope - will not capture exception!');
1190
+ return eventId;
1191
+ }
1192
+
1193
+ const syntheticException = new Error('Sentry syntheticException');
1194
+
1195
+ this._client.captureException(
1196
+ exception,
1197
+ {
1198
+ originalException: exception,
1199
+ syntheticException,
1200
+ ...hint,
1201
+ event_id: eventId,
1202
+ },
1203
+ this,
1204
+ );
1205
+
1206
+ return eventId;
1207
+ }
1208
+
1209
+ /**
1210
+ * @inheritDoc
1211
+ */
1212
+ captureMessage(message, level, hint) {
1213
+ const eventId = hint && hint.event_id ? hint.event_id : uuid4();
1214
+
1215
+ if (!this._client) {
1216
+ logger.warn('No client configured on scope - will not capture message!');
1217
+ return eventId;
1218
+ }
1219
+
1220
+ const syntheticException = new Error(message);
1221
+
1222
+ this._client.captureMessage(
1223
+ message,
1224
+ level,
1225
+ {
1226
+ originalException: message,
1227
+ syntheticException,
1228
+ ...hint,
1229
+ event_id: eventId,
1230
+ },
1231
+ this,
1232
+ );
1233
+
1234
+ return eventId;
1235
+ }
1236
+
1237
+ /**
1238
+ * @inheritDoc
1239
+ */
1240
+ captureEvent(event, hint) {
1241
+ const eventId = hint && hint.event_id ? hint.event_id : uuid4();
1242
+
1243
+ if (!this._client) {
1244
+ logger.warn('No client configured on scope - will not capture event!');
1245
+ return eventId;
1246
+ }
1247
+
1248
+ this._client.captureEvent(event, { ...hint, event_id: eventId }, this);
1249
+
1250
+ return eventId;
1251
+ }
1252
+
1253
+ /**
1254
+ * This will be called on every set call.
1255
+ */
1256
+ _notifyScopeListeners() {
1257
+ // We need this check for this._notifyingListeners to be able to work on scope during updates
1258
+ // If this check is not here we'll produce endless recursion when something is done with the scope
1259
+ // during the callback.
1260
+ if (!this._notifyingListeners) {
1261
+ this._notifyingListeners = true;
1262
+ this._scopeListeners.forEach(callback => {
1263
+ callback(this);
1264
+ });
1265
+ this._notifyingListeners = false;
1266
+ }
1267
+ }
1268
+ }
1269
+
1270
+ /**
1271
+ * Holds additional event information.
1272
+ */
1273
+ const Scope = ScopeClass;
1274
+
1275
+ /** Get the default current scope. */
1276
+ function getDefaultCurrentScope() {
1277
+ return getGlobalSingleton('defaultCurrentScope', () => new Scope());
1278
+ }
1279
+
1280
+ /** Get the default isolation scope. */
1281
+ function getDefaultIsolationScope() {
1282
+ return getGlobalSingleton('defaultIsolationScope', () => new Scope());
1283
+ }
1284
+
1285
+ /**
1286
+ * This is an object that holds a stack of scopes.
1287
+ */
1288
+ class AsyncContextStack {
1289
+
1290
+ constructor(scope, isolationScope) {
1291
+ let assignedScope;
1292
+ if (!scope) {
1293
+ assignedScope = new Scope();
1294
+ } else {
1295
+ assignedScope = scope;
1296
+ }
1297
+
1298
+ let assignedIsolationScope;
1299
+ if (!isolationScope) {
1300
+ assignedIsolationScope = new Scope();
1301
+ } else {
1302
+ assignedIsolationScope = isolationScope;
1303
+ }
1304
+
1305
+ // scope stack for domains or the process
1306
+ this._stack = [{ scope: assignedScope }];
1307
+ this._isolationScope = assignedIsolationScope;
1308
+ }
1309
+
1310
+ /**
1311
+ * Fork a scope for the stack.
1312
+ */
1313
+ withScope(callback) {
1314
+ const scope = this._pushScope();
1315
+
1316
+ let maybePromiseResult;
1317
+ try {
1318
+ maybePromiseResult = callback(scope);
1319
+ } catch (e) {
1320
+ this._popScope();
1321
+ throw e;
1322
+ }
1323
+
1324
+ if (isThenable(maybePromiseResult)) {
1325
+ // @ts-expect-error - isThenable returns the wrong type
1326
+ return maybePromiseResult.then(
1327
+ res => {
1328
+ this._popScope();
1329
+ return res;
1330
+ },
1331
+ e => {
1332
+ this._popScope();
1333
+ throw e;
1334
+ },
1335
+ );
1336
+ }
1337
+
1338
+ this._popScope();
1339
+ return maybePromiseResult;
1340
+ }
1341
+
1342
+ /**
1343
+ * Get the client of the stack.
1344
+ */
1345
+ getClient() {
1346
+ return this.getStackTop().client ;
1347
+ }
1348
+
1349
+ /**
1350
+ * Returns the scope of the top stack.
1351
+ */
1352
+ getScope() {
1353
+ return this.getStackTop().scope;
1354
+ }
1355
+
1356
+ /**
1357
+ * Get the isolation scope for the stack.
1358
+ */
1359
+ getIsolationScope() {
1360
+ return this._isolationScope;
1361
+ }
1362
+
1363
+ /**
1364
+ * Returns the topmost scope layer in the order domain > local > process.
1365
+ */
1366
+ getStackTop() {
1367
+ return this._stack[this._stack.length - 1] ;
1368
+ }
1369
+
1370
+ /**
1371
+ * Push a scope to the stack.
1372
+ */
1373
+ _pushScope() {
1374
+ // We want to clone the content of prev scope
1375
+ const scope = this.getScope().clone();
1376
+ this._stack.push({
1377
+ client: this.getClient(),
1378
+ scope,
1379
+ });
1380
+ return scope;
1381
+ }
1382
+
1383
+ /**
1384
+ * Pop a scope from the stack.
1385
+ */
1386
+ _popScope() {
1387
+ if (this._stack.length <= 1) return false;
1388
+ return !!this._stack.pop();
1389
+ }
1390
+ }
1391
+
1392
+ /**
1393
+ * Get the global async context stack.
1394
+ * This will be removed during the v8 cycle and is only here to make migration easier.
1395
+ */
1396
+ function getAsyncContextStack() {
1397
+ const registry = getMainCarrier();
1398
+ const sentry = getSentryCarrier(registry);
1399
+
1400
+ return (sentry.stack = sentry.stack || new AsyncContextStack(getDefaultCurrentScope(), getDefaultIsolationScope()));
1401
+ }
1402
+
1403
+ function withScope$1(callback) {
1404
+ return getAsyncContextStack().withScope(callback);
1405
+ }
1406
+
1407
+ function withSetScope(scope, callback) {
1408
+ const stack = getAsyncContextStack() ;
1409
+ return stack.withScope(() => {
1410
+ stack.getStackTop().scope = scope;
1411
+ return callback(scope);
1412
+ });
1413
+ }
1414
+
1415
+ function withIsolationScope(callback) {
1416
+ return getAsyncContextStack().withScope(() => {
1417
+ return callback(getAsyncContextStack().getIsolationScope());
1418
+ });
1419
+ }
1420
+
1421
+ /**
1422
+ * Get the stack-based async context strategy.
1423
+ */
1424
+ function getStackAsyncContextStrategy() {
1425
+ return {
1426
+ withIsolationScope,
1427
+ withScope: withScope$1,
1428
+ withSetScope,
1429
+ withSetIsolationScope: (_isolationScope, callback) => {
1430
+ return withIsolationScope(callback);
1431
+ },
1432
+ getCurrentScope: () => getAsyncContextStack().getScope(),
1433
+ getIsolationScope: () => getAsyncContextStack().getIsolationScope(),
1434
+ };
1435
+ }
1436
+
1437
+ /**
1438
+ * Get the current async context strategy.
1439
+ * If none has been setup, the default will be used.
1440
+ */
1441
+ function getAsyncContextStrategy(carrier) {
1442
+ const sentry = getSentryCarrier(carrier);
1443
+
1444
+ if (sentry.acs) {
1445
+ return sentry.acs;
1446
+ }
1447
+
1448
+ // Otherwise, use the default one (stack)
1449
+ return getStackAsyncContextStrategy();
1450
+ }
1451
+
1452
+ /**
1453
+ * Get the currently active scope.
1454
+ */
1455
+ function getCurrentScope() {
1456
+ const carrier = getMainCarrier();
1457
+ const acs = getAsyncContextStrategy(carrier);
1458
+ return acs.getCurrentScope();
1459
+ }
1460
+
1461
+ /**
1462
+ * Creates a new scope with and executes the given operation within.
1463
+ * The scope is automatically removed once the operation
1464
+ * finishes or throws.
1465
+ */
1466
+
1467
+ /**
1468
+ * Either creates a new active scope, or sets the given scope as active scope in the given callback.
1469
+ */
1470
+ function withScope(
1471
+ ...rest
1472
+ ) {
1473
+ const carrier = getMainCarrier();
1474
+ const acs = getAsyncContextStrategy(carrier);
1475
+
1476
+ // If a scope is defined, we want to make this the active scope instead of the default one
1477
+ if (rest.length === 2) {
1478
+ const [scope, callback] = rest;
1479
+
1480
+ if (!scope) {
1481
+ return acs.withScope(callback);
1482
+ }
1483
+
1484
+ return acs.withSetScope(scope, callback);
1485
+ }
1486
+
1487
+ return acs.withScope(rest[0]);
1488
+ }
1489
+
1490
+ /**
1491
+ * Get the currently active client.
1492
+ */
1493
+ function getClient() {
1494
+ return getCurrentScope().getClient();
1495
+ }
1496
+
1497
+ /**
1498
+ * Parse either an `EventHint` directly, or convert a `CaptureContext` to an `EventHint`.
1499
+ * This is used to allow to update method signatures that used to accept a `CaptureContext` but should now accept an `EventHint`.
1500
+ */
1501
+ function parseEventHintOrCaptureContext(
1502
+ hint,
1503
+ ) {
1504
+ if (!hint) {
1505
+ return undefined;
1506
+ }
1507
+
1508
+ // If you pass a Scope or `() => Scope` as CaptureContext, we just return this as captureContext
1509
+ if (hintIsScopeOrFunction(hint)) {
1510
+ return { captureContext: hint };
1511
+ }
1512
+
1513
+ if (hintIsScopeContext(hint)) {
1514
+ return {
1515
+ captureContext: hint,
1516
+ };
1517
+ }
1518
+
1519
+ return hint;
1520
+ }
1521
+
1522
+ function hintIsScopeOrFunction(
1523
+ hint,
1524
+ ) {
1525
+ return hint instanceof Scope || typeof hint === 'function';
1526
+ }
1527
+
1528
+ const captureContextKeys = [
1529
+ 'user',
1530
+ 'level',
1531
+ 'extra',
1532
+ 'contexts',
1533
+ 'tags',
1534
+ 'fingerprint',
1535
+ 'requestSession',
1536
+ 'propagationContext',
1537
+ ] ;
1538
+
1539
+ function hintIsScopeContext(hint) {
1540
+ return Object.keys(hint).some(key => captureContextKeys.includes(key ));
1541
+ }
1542
+
1543
+ /**
1544
+ * Captures an exception event and sends it to Sentry.
1545
+ *
1546
+ * @param exception The exception to capture.
1547
+ * @param hint Optional additional data to attach to the Sentry event.
1548
+ * @returns the id of the captured Sentry event.
1549
+ */
1550
+ function captureException(exception, hint) {
1551
+ return getCurrentScope().captureException(exception, parseEventHintOrCaptureContext(hint));
1552
+ }
1553
+
1554
+ /**
1555
+ * Captures a message event and sends it to Sentry.
1556
+ *
1557
+ * @param message The message to send to Sentry.
1558
+ * @param captureContext Define the level of the message or pass in additional data to attach to the message.
1559
+ * @returns the id of the captured message.
1560
+ */
1561
+ function captureMessage(message, captureContext) {
1562
+ // This is necessary to provide explicit scopes upgrade, without changing the original
1563
+ // arity of the `captureMessage(message, level)` method.
1564
+ const level = typeof captureContext === 'string' ? captureContext : undefined;
1565
+ const context = typeof captureContext !== 'string' ? { captureContext } : undefined;
1566
+ return getCurrentScope().captureMessage(message, level, context);
1567
+ }
1568
+
1569
+ /**
1570
+ * Define an integration function that can be used to create an integration instance.
1571
+ * Note that this by design hides the implementation details of the integration, as they are considered internal.
1572
+ */
1573
+ function defineIntegration(fn) {
1574
+ return fn;
1575
+ }
1576
+
1577
+ /**
1578
+ * Add an instrumentation handler for when a console.xxx method is called.
1579
+ *
1580
+ * Use at your own risk, this might break without changelog notice, only used internally.
1581
+ * @hidden
1582
+ */
1583
+ function addConsoleInstrumentationHandler(handler) {
1584
+ const type = 'console';
1585
+ addHandler(type, handler);
1586
+ maybeInstrument(type, instrumentConsole);
1587
+ }
1588
+
1589
+ function instrumentConsole() {
1590
+ if (!('console' in GLOBAL_OBJ)) {
1591
+ return;
1592
+ }
1593
+
1594
+ CONSOLE_LEVELS.forEach(function (level) {
1595
+ if (!(level in GLOBAL_OBJ.console)) {
1596
+ return;
1597
+ }
1598
+
1599
+ fill(GLOBAL_OBJ.console, level, function (originalConsoleMethod) {
1600
+ originalConsoleMethods[level] = originalConsoleMethod;
1601
+
1602
+ return function (...args) {
1603
+ const handlerData = { args, level };
1604
+ triggerHandlers('console', handlerData);
1605
+
1606
+ const log = originalConsoleMethods[level];
1607
+ log && log.apply(GLOBAL_OBJ.console, args);
1608
+ };
1609
+ });
1610
+ });
1611
+ }
1612
+
1613
+ /**
1614
+ * @deprecated This variable has been deprecated and will be removed in the next major version.
1615
+ */
1616
+
1617
+ /**
1618
+ * Converts a string-based level into a `SeverityLevel`, normalizing it along the way.
1619
+ *
1620
+ * @param level String representation of desired `SeverityLevel`.
1621
+ * @returns The `SeverityLevel` corresponding to the given string, or 'log' if the string isn't a valid level.
1622
+ */
1623
+ function severityLevelFromString(level) {
1624
+ return (
1625
+ level === 'warn' ? 'warning' : ['fatal', 'error', 'warning', 'log', 'info', 'debug'].includes(level) ? level : 'log'
1626
+ ) ;
1627
+ }
1628
+
1629
+ const INTEGRATION_NAME = 'CaptureConsole';
1630
+
1631
+ const _captureConsoleIntegration = ((options = {}) => {
1632
+ const levels = options.levels || CONSOLE_LEVELS;
1633
+ // TODO(v9): Flip default value to `true`
1634
+ const handled = !!options.handled;
1635
+
1636
+ return {
1637
+ name: INTEGRATION_NAME,
1638
+ setup(client) {
1639
+ if (!('console' in GLOBAL_OBJ)) {
1640
+ return;
1641
+ }
1642
+
1643
+ addConsoleInstrumentationHandler(({ args, level }) => {
1644
+ if (getClient() !== client || !levels.includes(level)) {
1645
+ return;
1646
+ }
1647
+
1648
+ consoleHandler(args, level, handled);
1649
+ });
1650
+ },
1651
+ };
1652
+ }) ;
1653
+
1654
+ /**
1655
+ * Send Console API calls as Sentry Events.
1656
+ */
1657
+ const captureConsoleIntegration = defineIntegration(_captureConsoleIntegration);
1658
+
1659
+ function consoleHandler(args, level, handled) {
1660
+ const captureContext = {
1661
+ level: severityLevelFromString(level),
1662
+ extra: {
1663
+ arguments: args,
1664
+ },
1665
+ };
1666
+
1667
+ withScope(scope => {
1668
+ scope.addEventProcessor(event => {
1669
+ event.logger = 'console';
1670
+
1671
+ addExceptionMechanism(event, {
1672
+ handled,
1673
+ type: 'console',
1674
+ });
1675
+
1676
+ return event;
1677
+ });
1678
+
1679
+ if (level === 'assert') {
1680
+ if (!args[0]) {
1681
+ const message = `Assertion failed: ${safeJoin(args.slice(1), ' ') || 'console.assert'}`;
1682
+ scope.setExtra('arguments', args.slice(1));
1683
+ captureMessage(message, captureContext);
1684
+ }
1685
+ return;
1686
+ }
1687
+
1688
+ const error = args.find(arg => arg instanceof Error);
1689
+ if (error) {
1690
+ captureException(error, captureContext);
1691
+ return;
1692
+ }
1693
+
1694
+ const message = safeJoin(args, ' ');
1695
+ captureMessage(message, captureContext);
1696
+ });
1697
+ }
1698
+
1699
+ /**
1700
+ * Initialize Sentry for React Native.
1701
+ *
1702
+ * @param {InitOptionsRN} options
1703
+ * @return {void}
1704
+ */
1705
+ const initSentry = options => {
1706
+ let shouldSendToSentry = options?.requiredEnvForSendToSentry?.includes(options.env);
1707
+ let ignoreErrors = [/StallTracking/];
1708
+ if (options?.ignoreErrorsOptions) {
1709
+ ignoreErrors = ignoreErrors.concat(options.ignoreErrorsOptions);
1710
+ }
1711
+ if (options?.options?.ignoreErrors) {
1712
+ ignoreErrors = ignoreErrors.concat(options.options.ignoreErrors);
1713
+ delete options.options.ignoreErrors;
1714
+ }
1715
+ let integrations = [];
1716
+ if (options?.httpClientIntegrationOptions?.failedRequestStatusCodes && options?.httpClientIntegrationOptions?.failedRequestTargets) {
1717
+ integrations.push(Sentry__namespace.httpClientIntegration({
1718
+ failedRequestStatusCodes: options.httpClientIntegrationOptions.failedRequestStatusCodes,
1719
+ failedRequestTargets: options.httpClientIntegrationOptions.failedRequestTargets
1720
+ }));
1721
+ }
1722
+ if (options?.captureConsoleIntegrationOptions?.levels) {
1723
+ integrations.push(captureConsoleIntegration({
1724
+ levels: options.captureConsoleIntegrationOptions.levels
1725
+ }));
1726
+ }
1727
+ if (options?.options?.hasOwnProperty('integrations')) {
1728
+ options.options.integrations = [...options.options.integrations, ...integrations];
1729
+ } else {
1730
+ options.options = options.options || {};
1731
+ options.options.integrations = integrations;
1732
+ }
1733
+ let sentryOptions = {
1734
+ dsn: options.dsn,
1735
+ debug: options.debug,
1736
+ environment: options.env,
1737
+ ignoreErrors: ignoreErrors,
1738
+ sampleRate: 1.0,
1739
+ maxBreadcrumbs: 50,
1740
+ autoSessionTracking: true,
1741
+ attachScreenshot: true,
1742
+ enableCaptureFailedRequests: true,
1743
+ enableTracing: true,
1744
+ tracesSampleRate: 1.0,
1745
+ enableNative: true,
1746
+ autoInitializeNativeSdk: true,
1747
+ enableNativeCrashHandling: true,
1748
+ enableNativeNagger: true,
1749
+ enableAutoSessionTracking: true,
1750
+ enableNdkScopeSync: true,
1751
+ attachThreads: true,
1752
+ enableAutoPerformanceTracing: true,
1753
+ enableWatchdogTerminationTracking: true,
1754
+ enableAppHangTracking: true,
1755
+ appHangTimeoutInterval: 5,
1756
+ sendDefaultPii: true,
1757
+ beforeSend: event => {
1758
+ if (event?.message?.includes('StallTracking') || !shouldSendToSentry) {
1759
+ return null;
1760
+ }
1761
+ return event;
1762
+ }
1763
+ };
1764
+ if (options?.release) {
1765
+ sentryOptions.release = options.release;
1766
+ }
1767
+ if (options?.beforeSend) {
1768
+ sentryOptions.beforeSend = options.beforeSend;
1769
+ }
1770
+ if (options?.options) {
1771
+ sentryOptions = {
1772
+ ...sentryOptions,
1773
+ ...options.options
1774
+ };
1775
+ }
1776
+ Sentry__namespace.init(sentryOptions);
1777
+ };
1778
+ /**
1779
+ * Record additional http data for Sentry.
1780
+ *
1781
+ * @param {any | null} config
1782
+ * @param {any | null} request
1783
+ * @param {any | null} response
1784
+ * @return {void}
1785
+ */
1786
+ const recordAdditionalSentryHttp = (config, request, response) => {
1787
+ Utils.recordSentryHttp(Sentry__namespace, config, request, response);
1788
+ };
1789
+
1790
+ exports.initSentry = initSentry;
1791
+ exports.recordAdditionalSentryHttp = recordAdditionalSentryHttp;
1792
+ //# sourceMappingURL=ReactNative-DLA9Xwp4.js.map