@drakkar.software/sunglasses-react-native 0.10.0 → 0.12.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.
- package/dist/index.d.mts +115 -9
- package/dist/index.d.ts +115 -9
- package/dist/index.js +194 -18
- package/dist/index.mjs +192 -16
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import React$1 from 'react';
|
|
2
|
-
import { ISunglassesClient,
|
|
3
|
-
export { CaptureExceptionOptions, ConsentStatus, ISunglassesClient, ScreenTrackingOptions, SunglassesConfig, SunglassesCore, SunglassesEvent, captureException } from '@drakkar.software/sunglasses-core';
|
|
2
|
+
import { ISunglassesClient, AutoCaptureErrorsOptions, ScreenTrackingOptions, CaptureExceptionOptions } from '@drakkar.software/sunglasses-core';
|
|
3
|
+
export { AutoCaptureErrorsOptions, CaptureExceptionOptions, ConsentStatus, ConsoleCaptureOptions, GlobalErrorInfo, GlobalErrorListener, ISunglassesClient, ScreenTrackingOptions, SunglassesConfig, SunglassesCore, SunglassesEvent, captureException, patchConsole, publishGlobalError, subscribeGlobalError } from '@drakkar.software/sunglasses-core';
|
|
4
4
|
|
|
5
5
|
interface SunglassesProviderProps {
|
|
6
6
|
/** An initialized ISunglassesClient (from SunglassesCore.create()). */
|
|
7
7
|
client: ISunglassesClient;
|
|
8
8
|
/**
|
|
9
|
-
* Automatically capture unhandled
|
|
10
|
-
* (`$error_handled: false`)
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* invoked
|
|
9
|
+
* Automatically capture unhandled errors as `$error` events
|
|
10
|
+
* (`$error_handled: false`).
|
|
11
|
+
*
|
|
12
|
+
* - `true` installs a global `ErrorUtils` handler (the previous handler is
|
|
13
|
+
* preserved and still invoked) and an unhandled promise rejection handler.
|
|
14
|
+
* - An options object additionally lets you toggle `globalHandlers` and
|
|
15
|
+
* `unhandledRejections`, opt into `console` capture (`console.error` /
|
|
16
|
+
* `console.warn`), plus configure truncation / stack inclusion / ignore
|
|
17
|
+
* patterns.
|
|
18
|
+
*
|
|
19
|
+
* Default: off.
|
|
14
20
|
*/
|
|
15
|
-
autoCaptureErrors?: boolean |
|
|
21
|
+
autoCaptureErrors?: boolean | AutoCaptureErrorsOptions;
|
|
16
22
|
children: React$1.ReactNode;
|
|
17
23
|
}
|
|
18
24
|
/**
|
|
@@ -222,4 +228,104 @@ interface SunglassesErrorBoundaryProps {
|
|
|
222
228
|
*/
|
|
223
229
|
declare function SunglassesErrorBoundary(props: SunglassesErrorBoundaryProps): React$1.ReactElement;
|
|
224
230
|
|
|
225
|
-
|
|
231
|
+
interface SunglassesGlobalErrorBoundaryProps {
|
|
232
|
+
/**
|
|
233
|
+
* SunGlasses client. Optional — defaults to the client provided by the
|
|
234
|
+
* nearest `<SunglassesProvider>`.
|
|
235
|
+
*/
|
|
236
|
+
client?: ISunglassesClient;
|
|
237
|
+
/** Rendered when an error is caught. Defaults to rendering nothing. */
|
|
238
|
+
fallback?: React$1.ReactNode;
|
|
239
|
+
/** Error capture configuration forwarded to `captureException`. */
|
|
240
|
+
config?: CaptureExceptionOptions;
|
|
241
|
+
/**
|
|
242
|
+
* Also render the fallback for non-fatal global errors (e.g. `ErrorUtils`
|
|
243
|
+
* errors reported as non-fatal). Default: `false`.
|
|
244
|
+
*/
|
|
245
|
+
includeNonFatalGlobalErrors?: boolean;
|
|
246
|
+
/**
|
|
247
|
+
* Also render the fallback for unhandled promise rejections. Off by default
|
|
248
|
+
* because many apps prefer to surface rejections as toasts or inline errors
|
|
249
|
+
* rather than as a full-screen fallback. Default: `false`.
|
|
250
|
+
*/
|
|
251
|
+
includeUnhandledRejections?: boolean;
|
|
252
|
+
children: React$1.ReactNode;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* A superset of `SunglassesErrorBoundary` that renders a fallback UI for fatal
|
|
256
|
+
* non-render errors (uncaught `ErrorUtils` errors and, optionally, unhandled
|
|
257
|
+
* rejections) in addition to the render-phase errors a normal error boundary
|
|
258
|
+
* catches.
|
|
259
|
+
*
|
|
260
|
+
* Render-phase errors are captured here as `$error` events
|
|
261
|
+
* (`$error_handled: true`). Global errors are captured by the provider's
|
|
262
|
+
* `autoCaptureErrors` handlers and merely surfaced here as a fallback — so the
|
|
263
|
+
* global fallback requires `autoCaptureErrors` to be enabled on the
|
|
264
|
+
* `<SunglassesProvider>`. No event is captured twice.
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```tsx
|
|
268
|
+
* <SunglassesProvider client={client} autoCaptureErrors>
|
|
269
|
+
* <SunglassesGlobalErrorBoundary fallback={<ErrorScreen />}>
|
|
270
|
+
* <App />
|
|
271
|
+
* </SunglassesGlobalErrorBoundary>
|
|
272
|
+
* </SunglassesProvider>
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
declare function SunglassesGlobalErrorBoundary(props: SunglassesGlobalErrorBoundaryProps): React$1.ReactElement;
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Props Expo Router passes to a route-level `ErrorBoundary` export.
|
|
279
|
+
*/
|
|
280
|
+
interface ExpoRouterErrorBoundaryProps {
|
|
281
|
+
/** The render error caught by Expo Router for this route. */
|
|
282
|
+
error: Error;
|
|
283
|
+
/** Re-mounts the route's components to retry rendering. */
|
|
284
|
+
retry: () => Promise<void>;
|
|
285
|
+
}
|
|
286
|
+
interface WrapExpoRouterErrorBoundaryOptions {
|
|
287
|
+
/**
|
|
288
|
+
* SunGlasses client. Optional — defaults to the client provided by the
|
|
289
|
+
* nearest `<SunglassesProvider>`.
|
|
290
|
+
*/
|
|
291
|
+
client?: ISunglassesClient;
|
|
292
|
+
/** Error capture configuration forwarded to `captureException`. */
|
|
293
|
+
config?: CaptureExceptionOptions;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Wrap an Expo Router route-level `ErrorBoundary` so render errors that reach it
|
|
297
|
+
* are also captured as SunGlasses `$error` events (`$error_handled: true`) with
|
|
298
|
+
* route context (`$route_path`, `$route_name`). The original boundary still
|
|
299
|
+
* renders unchanged.
|
|
300
|
+
*
|
|
301
|
+
* The client is read from the nearest `<SunglassesProvider>` by default; pass
|
|
302
|
+
* `options.client` to override. Each distinct error is captured once.
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```tsx
|
|
306
|
+
* // app/_layout.tsx
|
|
307
|
+
* import { ErrorBoundary as ExpoErrorBoundary } from 'expo-router';
|
|
308
|
+
* import { wrapExpoRouterErrorBoundary } from '@drakkar.software/sunglasses-react-native';
|
|
309
|
+
*
|
|
310
|
+
* export const ErrorBoundary = wrapExpoRouterErrorBoundary(ExpoErrorBoundary);
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
declare function wrapExpoRouterErrorBoundary<P extends ExpoRouterErrorBoundaryProps>(Boundary: React$1.ComponentType<P>, options?: WrapExpoRouterErrorBoundaryOptions): React$1.ComponentType<P>;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Attach an unhandled promise rejection handler that captures rejections as
|
|
317
|
+
* `$error` events (`$error_handled: false`) and publishes them to the global
|
|
318
|
+
* error bus.
|
|
319
|
+
*
|
|
320
|
+
* Tries React Native's bundled rejection tracker first
|
|
321
|
+
* (`promise/setimmediate/rejection-tracking`, the same mechanism Sentry uses),
|
|
322
|
+
* then falls back to a global `unhandledrejection` listener / `onunhandledrejection`
|
|
323
|
+
* hook for engines that expose one. Never throws.
|
|
324
|
+
*
|
|
325
|
+
* @param client - SunGlasses client instance.
|
|
326
|
+
* @param options - Capture configuration forwarded to `captureException`.
|
|
327
|
+
* @returns A cleanup function that detaches the handler.
|
|
328
|
+
*/
|
|
329
|
+
declare function attachUnhandledRejectionHandler(client: ISunglassesClient, options?: CaptureExceptionOptions): () => void;
|
|
330
|
+
|
|
331
|
+
export { type ExpoRouterErrorBoundaryProps, SunglassesErrorBoundary, type SunglassesErrorBoundaryProps, SunglassesGlobalErrorBoundary, type SunglassesGlobalErrorBoundaryProps, SunglassesProvider, type SunglassesProviderProps, type WrapExpoRouterErrorBoundaryOptions, attachUnhandledRejectionHandler, captureDeepLinkUtmParams, useExpoRouterScreenTracking, useExpoRouterUtmCapture, useLinkingUtmCapture, useNavigationScreenTracking, useSunglasses, wrapExpoRouterErrorBoundary };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import React$1 from 'react';
|
|
2
|
-
import { ISunglassesClient,
|
|
3
|
-
export { CaptureExceptionOptions, ConsentStatus, ISunglassesClient, ScreenTrackingOptions, SunglassesConfig, SunglassesCore, SunglassesEvent, captureException } from '@drakkar.software/sunglasses-core';
|
|
2
|
+
import { ISunglassesClient, AutoCaptureErrorsOptions, ScreenTrackingOptions, CaptureExceptionOptions } from '@drakkar.software/sunglasses-core';
|
|
3
|
+
export { AutoCaptureErrorsOptions, CaptureExceptionOptions, ConsentStatus, ConsoleCaptureOptions, GlobalErrorInfo, GlobalErrorListener, ISunglassesClient, ScreenTrackingOptions, SunglassesConfig, SunglassesCore, SunglassesEvent, captureException, patchConsole, publishGlobalError, subscribeGlobalError } from '@drakkar.software/sunglasses-core';
|
|
4
4
|
|
|
5
5
|
interface SunglassesProviderProps {
|
|
6
6
|
/** An initialized ISunglassesClient (from SunglassesCore.create()). */
|
|
7
7
|
client: ISunglassesClient;
|
|
8
8
|
/**
|
|
9
|
-
* Automatically capture unhandled
|
|
10
|
-
* (`$error_handled: false`)
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* invoked
|
|
9
|
+
* Automatically capture unhandled errors as `$error` events
|
|
10
|
+
* (`$error_handled: false`).
|
|
11
|
+
*
|
|
12
|
+
* - `true` installs a global `ErrorUtils` handler (the previous handler is
|
|
13
|
+
* preserved and still invoked) and an unhandled promise rejection handler.
|
|
14
|
+
* - An options object additionally lets you toggle `globalHandlers` and
|
|
15
|
+
* `unhandledRejections`, opt into `console` capture (`console.error` /
|
|
16
|
+
* `console.warn`), plus configure truncation / stack inclusion / ignore
|
|
17
|
+
* patterns.
|
|
18
|
+
*
|
|
19
|
+
* Default: off.
|
|
14
20
|
*/
|
|
15
|
-
autoCaptureErrors?: boolean |
|
|
21
|
+
autoCaptureErrors?: boolean | AutoCaptureErrorsOptions;
|
|
16
22
|
children: React$1.ReactNode;
|
|
17
23
|
}
|
|
18
24
|
/**
|
|
@@ -222,4 +228,104 @@ interface SunglassesErrorBoundaryProps {
|
|
|
222
228
|
*/
|
|
223
229
|
declare function SunglassesErrorBoundary(props: SunglassesErrorBoundaryProps): React$1.ReactElement;
|
|
224
230
|
|
|
225
|
-
|
|
231
|
+
interface SunglassesGlobalErrorBoundaryProps {
|
|
232
|
+
/**
|
|
233
|
+
* SunGlasses client. Optional — defaults to the client provided by the
|
|
234
|
+
* nearest `<SunglassesProvider>`.
|
|
235
|
+
*/
|
|
236
|
+
client?: ISunglassesClient;
|
|
237
|
+
/** Rendered when an error is caught. Defaults to rendering nothing. */
|
|
238
|
+
fallback?: React$1.ReactNode;
|
|
239
|
+
/** Error capture configuration forwarded to `captureException`. */
|
|
240
|
+
config?: CaptureExceptionOptions;
|
|
241
|
+
/**
|
|
242
|
+
* Also render the fallback for non-fatal global errors (e.g. `ErrorUtils`
|
|
243
|
+
* errors reported as non-fatal). Default: `false`.
|
|
244
|
+
*/
|
|
245
|
+
includeNonFatalGlobalErrors?: boolean;
|
|
246
|
+
/**
|
|
247
|
+
* Also render the fallback for unhandled promise rejections. Off by default
|
|
248
|
+
* because many apps prefer to surface rejections as toasts or inline errors
|
|
249
|
+
* rather than as a full-screen fallback. Default: `false`.
|
|
250
|
+
*/
|
|
251
|
+
includeUnhandledRejections?: boolean;
|
|
252
|
+
children: React$1.ReactNode;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* A superset of `SunglassesErrorBoundary` that renders a fallback UI for fatal
|
|
256
|
+
* non-render errors (uncaught `ErrorUtils` errors and, optionally, unhandled
|
|
257
|
+
* rejections) in addition to the render-phase errors a normal error boundary
|
|
258
|
+
* catches.
|
|
259
|
+
*
|
|
260
|
+
* Render-phase errors are captured here as `$error` events
|
|
261
|
+
* (`$error_handled: true`). Global errors are captured by the provider's
|
|
262
|
+
* `autoCaptureErrors` handlers and merely surfaced here as a fallback — so the
|
|
263
|
+
* global fallback requires `autoCaptureErrors` to be enabled on the
|
|
264
|
+
* `<SunglassesProvider>`. No event is captured twice.
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```tsx
|
|
268
|
+
* <SunglassesProvider client={client} autoCaptureErrors>
|
|
269
|
+
* <SunglassesGlobalErrorBoundary fallback={<ErrorScreen />}>
|
|
270
|
+
* <App />
|
|
271
|
+
* </SunglassesGlobalErrorBoundary>
|
|
272
|
+
* </SunglassesProvider>
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
declare function SunglassesGlobalErrorBoundary(props: SunglassesGlobalErrorBoundaryProps): React$1.ReactElement;
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Props Expo Router passes to a route-level `ErrorBoundary` export.
|
|
279
|
+
*/
|
|
280
|
+
interface ExpoRouterErrorBoundaryProps {
|
|
281
|
+
/** The render error caught by Expo Router for this route. */
|
|
282
|
+
error: Error;
|
|
283
|
+
/** Re-mounts the route's components to retry rendering. */
|
|
284
|
+
retry: () => Promise<void>;
|
|
285
|
+
}
|
|
286
|
+
interface WrapExpoRouterErrorBoundaryOptions {
|
|
287
|
+
/**
|
|
288
|
+
* SunGlasses client. Optional — defaults to the client provided by the
|
|
289
|
+
* nearest `<SunglassesProvider>`.
|
|
290
|
+
*/
|
|
291
|
+
client?: ISunglassesClient;
|
|
292
|
+
/** Error capture configuration forwarded to `captureException`. */
|
|
293
|
+
config?: CaptureExceptionOptions;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Wrap an Expo Router route-level `ErrorBoundary` so render errors that reach it
|
|
297
|
+
* are also captured as SunGlasses `$error` events (`$error_handled: true`) with
|
|
298
|
+
* route context (`$route_path`, `$route_name`). The original boundary still
|
|
299
|
+
* renders unchanged.
|
|
300
|
+
*
|
|
301
|
+
* The client is read from the nearest `<SunglassesProvider>` by default; pass
|
|
302
|
+
* `options.client` to override. Each distinct error is captured once.
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```tsx
|
|
306
|
+
* // app/_layout.tsx
|
|
307
|
+
* import { ErrorBoundary as ExpoErrorBoundary } from 'expo-router';
|
|
308
|
+
* import { wrapExpoRouterErrorBoundary } from '@drakkar.software/sunglasses-react-native';
|
|
309
|
+
*
|
|
310
|
+
* export const ErrorBoundary = wrapExpoRouterErrorBoundary(ExpoErrorBoundary);
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
declare function wrapExpoRouterErrorBoundary<P extends ExpoRouterErrorBoundaryProps>(Boundary: React$1.ComponentType<P>, options?: WrapExpoRouterErrorBoundaryOptions): React$1.ComponentType<P>;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Attach an unhandled promise rejection handler that captures rejections as
|
|
317
|
+
* `$error` events (`$error_handled: false`) and publishes them to the global
|
|
318
|
+
* error bus.
|
|
319
|
+
*
|
|
320
|
+
* Tries React Native's bundled rejection tracker first
|
|
321
|
+
* (`promise/setimmediate/rejection-tracking`, the same mechanism Sentry uses),
|
|
322
|
+
* then falls back to a global `unhandledrejection` listener / `onunhandledrejection`
|
|
323
|
+
* hook for engines that expose one. Never throws.
|
|
324
|
+
*
|
|
325
|
+
* @param client - SunGlasses client instance.
|
|
326
|
+
* @param options - Capture configuration forwarded to `captureException`.
|
|
327
|
+
* @returns A cleanup function that detaches the handler.
|
|
328
|
+
*/
|
|
329
|
+
declare function attachUnhandledRejectionHandler(client: ISunglassesClient, options?: CaptureExceptionOptions): () => void;
|
|
330
|
+
|
|
331
|
+
export { type ExpoRouterErrorBoundaryProps, SunglassesErrorBoundary, type SunglassesErrorBoundaryProps, SunglassesGlobalErrorBoundary, type SunglassesGlobalErrorBoundaryProps, SunglassesProvider, type SunglassesProviderProps, type WrapExpoRouterErrorBoundaryOptions, attachUnhandledRejectionHandler, captureDeepLinkUtmParams, useExpoRouterScreenTracking, useExpoRouterUtmCapture, useLinkingUtmCapture, useNavigationScreenTracking, useSunglasses, wrapExpoRouterErrorBoundary };
|
package/dist/index.js
CHANGED
|
@@ -30,23 +30,29 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
SunglassesCore: () =>
|
|
33
|
+
SunglassesCore: () => import_sunglasses_core6.SunglassesCore,
|
|
34
34
|
SunglassesErrorBoundary: () => SunglassesErrorBoundary,
|
|
35
|
+
SunglassesGlobalErrorBoundary: () => SunglassesGlobalErrorBoundary,
|
|
35
36
|
SunglassesProvider: () => SunglassesProvider,
|
|
37
|
+
attachUnhandledRejectionHandler: () => attachUnhandledRejectionHandler,
|
|
36
38
|
captureDeepLinkUtmParams: () => captureDeepLinkUtmParams,
|
|
37
|
-
captureException: () =>
|
|
39
|
+
captureException: () => import_sunglasses_core6.captureException,
|
|
40
|
+
patchConsole: () => import_sunglasses_core6.patchConsole,
|
|
41
|
+
publishGlobalError: () => import_sunglasses_core6.publishGlobalError,
|
|
42
|
+
subscribeGlobalError: () => import_sunglasses_core6.subscribeGlobalError,
|
|
38
43
|
useExpoRouterScreenTracking: () => useExpoRouterScreenTracking,
|
|
39
44
|
useExpoRouterUtmCapture: () => useExpoRouterUtmCapture,
|
|
40
45
|
useLinkingUtmCapture: () => useLinkingUtmCapture,
|
|
41
46
|
useNavigationScreenTracking: () => useNavigationScreenTracking,
|
|
42
|
-
useSunglasses: () => useSunglasses
|
|
47
|
+
useSunglasses: () => useSunglasses,
|
|
48
|
+
wrapExpoRouterErrorBoundary: () => wrapExpoRouterErrorBoundary
|
|
43
49
|
});
|
|
44
50
|
module.exports = __toCommonJS(index_exports);
|
|
45
51
|
|
|
46
52
|
// src/SunglassesProvider.tsx
|
|
47
53
|
var import_react2 = require("react");
|
|
48
54
|
var import_react_native = require("react-native");
|
|
49
|
-
var
|
|
55
|
+
var import_sunglasses_core2 = require("@drakkar.software/sunglasses-core");
|
|
50
56
|
|
|
51
57
|
// src/context.ts
|
|
52
58
|
var import_react = require("react");
|
|
@@ -61,6 +67,68 @@ function useSunglasses() {
|
|
|
61
67
|
return client;
|
|
62
68
|
}
|
|
63
69
|
|
|
70
|
+
// src/unhandledRejections.ts
|
|
71
|
+
var import_sunglasses_core = require("@drakkar.software/sunglasses-core");
|
|
72
|
+
|
|
73
|
+
// src/rejectionTracking.ts
|
|
74
|
+
var _tracking = null;
|
|
75
|
+
try {
|
|
76
|
+
const required = require("promise/setimmediate/rejection-tracking");
|
|
77
|
+
const resolved = required.default ?? required;
|
|
78
|
+
if (resolved && typeof resolved.enable === "function") {
|
|
79
|
+
_tracking = resolved;
|
|
80
|
+
}
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
83
|
+
var rejectionTracking = _tracking;
|
|
84
|
+
|
|
85
|
+
// src/unhandledRejections.ts
|
|
86
|
+
function reasonOf(event) {
|
|
87
|
+
if (event && typeof event === "object" && "reason" in event) {
|
|
88
|
+
return event.reason;
|
|
89
|
+
}
|
|
90
|
+
return event;
|
|
91
|
+
}
|
|
92
|
+
function attachUnhandledRejectionHandler(client, options = {}) {
|
|
93
|
+
const onUnhandled = (error) => {
|
|
94
|
+
(0, import_sunglasses_core.captureException)(client, error, { handled: false, ...options });
|
|
95
|
+
(0, import_sunglasses_core.publishGlobalError)({ error, fatal: false, kind: "rejection" });
|
|
96
|
+
};
|
|
97
|
+
const tracking = rejectionTracking;
|
|
98
|
+
if (tracking) {
|
|
99
|
+
tracking.enable({
|
|
100
|
+
allRejections: true,
|
|
101
|
+
onUnhandled: (_id, error) => onUnhandled(error),
|
|
102
|
+
onHandled: () => {
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return () => {
|
|
106
|
+
try {
|
|
107
|
+
tracking.disable?.();
|
|
108
|
+
} catch {
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const g = globalThis;
|
|
113
|
+
if (typeof g.addEventListener === "function" && typeof g.removeEventListener === "function") {
|
|
114
|
+
const listener = (event) => onUnhandled(reasonOf(event));
|
|
115
|
+
g.addEventListener("unhandledrejection", listener);
|
|
116
|
+
return () => g.removeEventListener?.("unhandledrejection", listener);
|
|
117
|
+
}
|
|
118
|
+
if ("onunhandledrejection" in g) {
|
|
119
|
+
const previous = g.onunhandledrejection ?? null;
|
|
120
|
+
g.onunhandledrejection = (event) => {
|
|
121
|
+
onUnhandled(reasonOf(event));
|
|
122
|
+
previous?.(event);
|
|
123
|
+
};
|
|
124
|
+
return () => {
|
|
125
|
+
g.onunhandledrejection = previous;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return () => {
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
64
132
|
// src/SunglassesProvider.tsx
|
|
65
133
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
66
134
|
function SunglassesProvider({
|
|
@@ -76,15 +144,28 @@ function SunglassesProvider({
|
|
|
76
144
|
}, [client]);
|
|
77
145
|
(0, import_react2.useEffect)(() => {
|
|
78
146
|
if (!autoCaptureErrors) return;
|
|
79
|
-
if (typeof ErrorUtils === "undefined" || !ErrorUtils.setGlobalHandler) return;
|
|
80
147
|
const options = typeof autoCaptureErrors === "object" ? autoCaptureErrors : {};
|
|
81
|
-
const
|
|
82
|
-
ErrorUtils.setGlobalHandler
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
148
|
+
const cleanups = [];
|
|
149
|
+
if (options.globalHandlers !== false && typeof ErrorUtils !== "undefined" && ErrorUtils.setGlobalHandler) {
|
|
150
|
+
const previous = ErrorUtils.getGlobalHandler?.();
|
|
151
|
+
ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
152
|
+
(0, import_sunglasses_core2.captureException)(client, error, { handled: false, ...options });
|
|
153
|
+
(0, import_sunglasses_core2.publishGlobalError)({ error, fatal: isFatal !== false, kind: "error" });
|
|
154
|
+
previous?.(error, isFatal);
|
|
155
|
+
});
|
|
156
|
+
cleanups.push(() => {
|
|
157
|
+
if (previous) ErrorUtils.setGlobalHandler?.(previous);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (options.unhandledRejections !== false) {
|
|
161
|
+
cleanups.push(attachUnhandledRejectionHandler(client, options));
|
|
162
|
+
}
|
|
163
|
+
if (options.console) {
|
|
164
|
+
const consoleOptions = typeof options.console === "object" ? options.console : {};
|
|
165
|
+
cleanups.push((0, import_sunglasses_core2.patchConsole)(client, consoleOptions));
|
|
166
|
+
}
|
|
86
167
|
return () => {
|
|
87
|
-
|
|
168
|
+
for (const cleanup of cleanups) cleanup();
|
|
88
169
|
};
|
|
89
170
|
}, [client, autoCaptureErrors]);
|
|
90
171
|
(0, import_react2.useEffect)(() => {
|
|
@@ -104,8 +185,8 @@ var import_react3 = require("react");
|
|
|
104
185
|
function useExpoRouterScreenTracking(client, options = {}) {
|
|
105
186
|
let pathname;
|
|
106
187
|
try {
|
|
107
|
-
const { usePathname } = require("expo-router");
|
|
108
|
-
pathname =
|
|
188
|
+
const { usePathname: usePathname2 } = require("expo-router");
|
|
189
|
+
pathname = usePathname2();
|
|
109
190
|
} catch {
|
|
110
191
|
return;
|
|
111
192
|
}
|
|
@@ -199,11 +280,15 @@ var import_react6 = require("react");
|
|
|
199
280
|
|
|
200
281
|
// src/expoRouterCompat.ts
|
|
201
282
|
var _useGlobalSearchParams = null;
|
|
283
|
+
var _usePathname = null;
|
|
202
284
|
try {
|
|
203
|
-
|
|
285
|
+
const expoRouter = require("expo-router");
|
|
286
|
+
_useGlobalSearchParams = expoRouter.useGlobalSearchParams;
|
|
287
|
+
_usePathname = expoRouter.usePathname;
|
|
204
288
|
} catch {
|
|
205
289
|
}
|
|
206
290
|
var useGlobalSearchParams = _useGlobalSearchParams;
|
|
291
|
+
var usePathname = _usePathname;
|
|
207
292
|
|
|
208
293
|
// src/useExpoRouterUtmCapture.ts
|
|
209
294
|
function useExpoRouterUtmCapture(client) {
|
|
@@ -227,7 +312,7 @@ function useExpoRouterUtmCapture(client) {
|
|
|
227
312
|
|
|
228
313
|
// src/SunglassesErrorBoundary.tsx
|
|
229
314
|
var import_react7 = __toESM(require("react"));
|
|
230
|
-
var
|
|
315
|
+
var import_sunglasses_core3 = require("@drakkar.software/sunglasses-core");
|
|
231
316
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
232
317
|
var ErrorBoundaryInner = class extends import_react7.default.Component {
|
|
233
318
|
constructor() {
|
|
@@ -239,7 +324,7 @@ var ErrorBoundaryInner = class extends import_react7.default.Component {
|
|
|
239
324
|
}
|
|
240
325
|
componentDidCatch(error) {
|
|
241
326
|
const { client, config } = this.props;
|
|
242
|
-
(0,
|
|
327
|
+
(0, import_sunglasses_core3.captureException)(client, error, { handled: true, ...config });
|
|
243
328
|
}
|
|
244
329
|
render() {
|
|
245
330
|
if (this.state.hasError) return this.props.fallback ?? null;
|
|
@@ -257,18 +342,109 @@ function SunglassesErrorBoundary(props) {
|
|
|
257
342
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ErrorBoundaryInner, { ...props, client });
|
|
258
343
|
}
|
|
259
344
|
|
|
345
|
+
// src/SunglassesGlobalErrorBoundary.tsx
|
|
346
|
+
var import_react8 = __toESM(require("react"));
|
|
347
|
+
var import_sunglasses_core4 = require("@drakkar.software/sunglasses-core");
|
|
348
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
349
|
+
var GlobalErrorBoundaryInner = class extends import_react8.default.Component {
|
|
350
|
+
constructor() {
|
|
351
|
+
super(...arguments);
|
|
352
|
+
this.state = { hasError: false };
|
|
353
|
+
}
|
|
354
|
+
static getDerivedStateFromError() {
|
|
355
|
+
return { hasError: true };
|
|
356
|
+
}
|
|
357
|
+
componentDidMount() {
|
|
358
|
+
this.unsubscribe = (0, import_sunglasses_core4.subscribeGlobalError)((info) => this.handleGlobalError(info));
|
|
359
|
+
}
|
|
360
|
+
componentWillUnmount() {
|
|
361
|
+
this.unsubscribe?.();
|
|
362
|
+
}
|
|
363
|
+
componentDidCatch(error) {
|
|
364
|
+
const { client, config } = this.props;
|
|
365
|
+
(0, import_sunglasses_core4.captureException)(client, error, { handled: true, ...config });
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* React to a global error published by the provider's auto-capture handlers.
|
|
369
|
+
* The provider already captured it, so we only decide whether to show the
|
|
370
|
+
* fallback — we never re-capture here.
|
|
371
|
+
*/
|
|
372
|
+
handleGlobalError(info) {
|
|
373
|
+
if (this.state.hasError) return;
|
|
374
|
+
const { includeNonFatalGlobalErrors, includeUnhandledRejections } = this.props;
|
|
375
|
+
const shouldShow = info.kind === "rejection" ? includeUnhandledRejections === true : info.fatal || includeNonFatalGlobalErrors === true;
|
|
376
|
+
if (shouldShow) this.setState({ hasError: true });
|
|
377
|
+
}
|
|
378
|
+
render() {
|
|
379
|
+
if (this.state.hasError) return this.props.fallback ?? null;
|
|
380
|
+
return this.props.children;
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
function SunglassesGlobalErrorBoundary(props) {
|
|
384
|
+
const contextClient = (0, import_react8.useContext)(SunglassesContext);
|
|
385
|
+
const client = props.client ?? contextClient;
|
|
386
|
+
if (client === null) {
|
|
387
|
+
throw new Error(
|
|
388
|
+
"[SunGlasses] <SunglassesGlobalErrorBoundary> must be inside a <SunglassesProvider> or receive a `client` prop."
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GlobalErrorBoundaryInner, { ...props, client });
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// src/wrapExpoRouterErrorBoundary.tsx
|
|
395
|
+
var import_react9 = require("react");
|
|
396
|
+
var import_sunglasses_core5 = require("@drakkar.software/sunglasses-core");
|
|
397
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
398
|
+
function useExpoRouterPathname() {
|
|
399
|
+
if (!usePathname) return void 0;
|
|
400
|
+
return usePathname();
|
|
401
|
+
}
|
|
402
|
+
function wrapExpoRouterErrorBoundary(Boundary, options = {}) {
|
|
403
|
+
function WrappedExpoRouterErrorBoundary(props) {
|
|
404
|
+
const contextClient = (0, import_react9.useContext)(SunglassesContext);
|
|
405
|
+
const client = options.client ?? contextClient;
|
|
406
|
+
const pathname = useExpoRouterPathname();
|
|
407
|
+
const lastCaptured = (0, import_react9.useRef)(null);
|
|
408
|
+
const { error } = props;
|
|
409
|
+
(0, import_react9.useEffect)(() => {
|
|
410
|
+
if (!client || !error || lastCaptured.current === error) return;
|
|
411
|
+
lastCaptured.current = error;
|
|
412
|
+
const routeProps = {};
|
|
413
|
+
if (pathname) {
|
|
414
|
+
routeProps.$route_path = pathname;
|
|
415
|
+
routeProps.$route_name = pathname;
|
|
416
|
+
}
|
|
417
|
+
(0, import_sunglasses_core5.captureException)(client, error, {
|
|
418
|
+
handled: true,
|
|
419
|
+
...options.config,
|
|
420
|
+
properties: { ...routeProps, ...options.config?.properties }
|
|
421
|
+
});
|
|
422
|
+
}, [client, error, pathname]);
|
|
423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Boundary, { ...props });
|
|
424
|
+
}
|
|
425
|
+
const name = Boundary.displayName || Boundary.name || "ErrorBoundary";
|
|
426
|
+
WrappedExpoRouterErrorBoundary.displayName = `wrapExpoRouterErrorBoundary(${name})`;
|
|
427
|
+
return WrappedExpoRouterErrorBoundary;
|
|
428
|
+
}
|
|
429
|
+
|
|
260
430
|
// src/index.ts
|
|
261
|
-
var
|
|
431
|
+
var import_sunglasses_core6 = require("@drakkar.software/sunglasses-core");
|
|
262
432
|
// Annotate the CommonJS export names for ESM import in node:
|
|
263
433
|
0 && (module.exports = {
|
|
264
434
|
SunglassesCore,
|
|
265
435
|
SunglassesErrorBoundary,
|
|
436
|
+
SunglassesGlobalErrorBoundary,
|
|
266
437
|
SunglassesProvider,
|
|
438
|
+
attachUnhandledRejectionHandler,
|
|
267
439
|
captureDeepLinkUtmParams,
|
|
268
440
|
captureException,
|
|
441
|
+
patchConsole,
|
|
442
|
+
publishGlobalError,
|
|
443
|
+
subscribeGlobalError,
|
|
269
444
|
useExpoRouterScreenTracking,
|
|
270
445
|
useExpoRouterUtmCapture,
|
|
271
446
|
useLinkingUtmCapture,
|
|
272
447
|
useNavigationScreenTracking,
|
|
273
|
-
useSunglasses
|
|
448
|
+
useSunglasses,
|
|
449
|
+
wrapExpoRouterErrorBoundary
|
|
274
450
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -8,7 +8,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
8
8
|
// src/SunglassesProvider.tsx
|
|
9
9
|
import { useEffect } from "react";
|
|
10
10
|
import { AppState } from "react-native";
|
|
11
|
-
import { captureException } from "@drakkar.software/sunglasses-core";
|
|
11
|
+
import { captureException as captureException2, patchConsole, publishGlobalError as publishGlobalError2 } from "@drakkar.software/sunglasses-core";
|
|
12
12
|
|
|
13
13
|
// src/context.ts
|
|
14
14
|
import { createContext, useContext } from "react";
|
|
@@ -23,6 +23,68 @@ function useSunglasses() {
|
|
|
23
23
|
return client;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
// src/unhandledRejections.ts
|
|
27
|
+
import { captureException, publishGlobalError } from "@drakkar.software/sunglasses-core";
|
|
28
|
+
|
|
29
|
+
// src/rejectionTracking.ts
|
|
30
|
+
var _tracking = null;
|
|
31
|
+
try {
|
|
32
|
+
const required = __require("promise/setimmediate/rejection-tracking");
|
|
33
|
+
const resolved = required.default ?? required;
|
|
34
|
+
if (resolved && typeof resolved.enable === "function") {
|
|
35
|
+
_tracking = resolved;
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
}
|
|
39
|
+
var rejectionTracking = _tracking;
|
|
40
|
+
|
|
41
|
+
// src/unhandledRejections.ts
|
|
42
|
+
function reasonOf(event) {
|
|
43
|
+
if (event && typeof event === "object" && "reason" in event) {
|
|
44
|
+
return event.reason;
|
|
45
|
+
}
|
|
46
|
+
return event;
|
|
47
|
+
}
|
|
48
|
+
function attachUnhandledRejectionHandler(client, options = {}) {
|
|
49
|
+
const onUnhandled = (error) => {
|
|
50
|
+
captureException(client, error, { handled: false, ...options });
|
|
51
|
+
publishGlobalError({ error, fatal: false, kind: "rejection" });
|
|
52
|
+
};
|
|
53
|
+
const tracking = rejectionTracking;
|
|
54
|
+
if (tracking) {
|
|
55
|
+
tracking.enable({
|
|
56
|
+
allRejections: true,
|
|
57
|
+
onUnhandled: (_id, error) => onUnhandled(error),
|
|
58
|
+
onHandled: () => {
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
return () => {
|
|
62
|
+
try {
|
|
63
|
+
tracking.disable?.();
|
|
64
|
+
} catch {
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const g = globalThis;
|
|
69
|
+
if (typeof g.addEventListener === "function" && typeof g.removeEventListener === "function") {
|
|
70
|
+
const listener = (event) => onUnhandled(reasonOf(event));
|
|
71
|
+
g.addEventListener("unhandledrejection", listener);
|
|
72
|
+
return () => g.removeEventListener?.("unhandledrejection", listener);
|
|
73
|
+
}
|
|
74
|
+
if ("onunhandledrejection" in g) {
|
|
75
|
+
const previous = g.onunhandledrejection ?? null;
|
|
76
|
+
g.onunhandledrejection = (event) => {
|
|
77
|
+
onUnhandled(reasonOf(event));
|
|
78
|
+
previous?.(event);
|
|
79
|
+
};
|
|
80
|
+
return () => {
|
|
81
|
+
g.onunhandledrejection = previous;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return () => {
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
26
88
|
// src/SunglassesProvider.tsx
|
|
27
89
|
import { jsx } from "react/jsx-runtime";
|
|
28
90
|
function SunglassesProvider({
|
|
@@ -38,15 +100,28 @@ function SunglassesProvider({
|
|
|
38
100
|
}, [client]);
|
|
39
101
|
useEffect(() => {
|
|
40
102
|
if (!autoCaptureErrors) return;
|
|
41
|
-
if (typeof ErrorUtils === "undefined" || !ErrorUtils.setGlobalHandler) return;
|
|
42
103
|
const options = typeof autoCaptureErrors === "object" ? autoCaptureErrors : {};
|
|
43
|
-
const
|
|
44
|
-
ErrorUtils.setGlobalHandler
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
104
|
+
const cleanups = [];
|
|
105
|
+
if (options.globalHandlers !== false && typeof ErrorUtils !== "undefined" && ErrorUtils.setGlobalHandler) {
|
|
106
|
+
const previous = ErrorUtils.getGlobalHandler?.();
|
|
107
|
+
ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
108
|
+
captureException2(client, error, { handled: false, ...options });
|
|
109
|
+
publishGlobalError2({ error, fatal: isFatal !== false, kind: "error" });
|
|
110
|
+
previous?.(error, isFatal);
|
|
111
|
+
});
|
|
112
|
+
cleanups.push(() => {
|
|
113
|
+
if (previous) ErrorUtils.setGlobalHandler?.(previous);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
if (options.unhandledRejections !== false) {
|
|
117
|
+
cleanups.push(attachUnhandledRejectionHandler(client, options));
|
|
118
|
+
}
|
|
119
|
+
if (options.console) {
|
|
120
|
+
const consoleOptions = typeof options.console === "object" ? options.console : {};
|
|
121
|
+
cleanups.push(patchConsole(client, consoleOptions));
|
|
122
|
+
}
|
|
48
123
|
return () => {
|
|
49
|
-
|
|
124
|
+
for (const cleanup of cleanups) cleanup();
|
|
50
125
|
};
|
|
51
126
|
}, [client, autoCaptureErrors]);
|
|
52
127
|
useEffect(() => {
|
|
@@ -66,8 +141,8 @@ import { useEffect as useEffect2 } from "react";
|
|
|
66
141
|
function useExpoRouterScreenTracking(client, options = {}) {
|
|
67
142
|
let pathname;
|
|
68
143
|
try {
|
|
69
|
-
const { usePathname } = __require("expo-router");
|
|
70
|
-
pathname =
|
|
144
|
+
const { usePathname: usePathname2 } = __require("expo-router");
|
|
145
|
+
pathname = usePathname2();
|
|
71
146
|
} catch {
|
|
72
147
|
return;
|
|
73
148
|
}
|
|
@@ -161,11 +236,15 @@ import { useEffect as useEffect5 } from "react";
|
|
|
161
236
|
|
|
162
237
|
// src/expoRouterCompat.ts
|
|
163
238
|
var _useGlobalSearchParams = null;
|
|
239
|
+
var _usePathname = null;
|
|
164
240
|
try {
|
|
165
|
-
|
|
241
|
+
const expoRouter = __require("expo-router");
|
|
242
|
+
_useGlobalSearchParams = expoRouter.useGlobalSearchParams;
|
|
243
|
+
_usePathname = expoRouter.usePathname;
|
|
166
244
|
} catch {
|
|
167
245
|
}
|
|
168
246
|
var useGlobalSearchParams = _useGlobalSearchParams;
|
|
247
|
+
var usePathname = _usePathname;
|
|
169
248
|
|
|
170
249
|
// src/useExpoRouterUtmCapture.ts
|
|
171
250
|
function useExpoRouterUtmCapture(client) {
|
|
@@ -189,7 +268,7 @@ function useExpoRouterUtmCapture(client) {
|
|
|
189
268
|
|
|
190
269
|
// src/SunglassesErrorBoundary.tsx
|
|
191
270
|
import React2, { useContext as useContext2 } from "react";
|
|
192
|
-
import { captureException as
|
|
271
|
+
import { captureException as captureException3 } from "@drakkar.software/sunglasses-core";
|
|
193
272
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
194
273
|
var ErrorBoundaryInner = class extends React2.Component {
|
|
195
274
|
constructor() {
|
|
@@ -201,7 +280,7 @@ var ErrorBoundaryInner = class extends React2.Component {
|
|
|
201
280
|
}
|
|
202
281
|
componentDidCatch(error) {
|
|
203
282
|
const { client, config } = this.props;
|
|
204
|
-
|
|
283
|
+
captureException3(client, error, { handled: true, ...config });
|
|
205
284
|
}
|
|
206
285
|
render() {
|
|
207
286
|
if (this.state.hasError) return this.props.fallback ?? null;
|
|
@@ -219,17 +298,114 @@ function SunglassesErrorBoundary(props) {
|
|
|
219
298
|
return /* @__PURE__ */ jsx2(ErrorBoundaryInner, { ...props, client });
|
|
220
299
|
}
|
|
221
300
|
|
|
301
|
+
// src/SunglassesGlobalErrorBoundary.tsx
|
|
302
|
+
import React3, { useContext as useContext3 } from "react";
|
|
303
|
+
import { captureException as captureException4, subscribeGlobalError } from "@drakkar.software/sunglasses-core";
|
|
304
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
305
|
+
var GlobalErrorBoundaryInner = class extends React3.Component {
|
|
306
|
+
constructor() {
|
|
307
|
+
super(...arguments);
|
|
308
|
+
this.state = { hasError: false };
|
|
309
|
+
}
|
|
310
|
+
static getDerivedStateFromError() {
|
|
311
|
+
return { hasError: true };
|
|
312
|
+
}
|
|
313
|
+
componentDidMount() {
|
|
314
|
+
this.unsubscribe = subscribeGlobalError((info) => this.handleGlobalError(info));
|
|
315
|
+
}
|
|
316
|
+
componentWillUnmount() {
|
|
317
|
+
this.unsubscribe?.();
|
|
318
|
+
}
|
|
319
|
+
componentDidCatch(error) {
|
|
320
|
+
const { client, config } = this.props;
|
|
321
|
+
captureException4(client, error, { handled: true, ...config });
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* React to a global error published by the provider's auto-capture handlers.
|
|
325
|
+
* The provider already captured it, so we only decide whether to show the
|
|
326
|
+
* fallback — we never re-capture here.
|
|
327
|
+
*/
|
|
328
|
+
handleGlobalError(info) {
|
|
329
|
+
if (this.state.hasError) return;
|
|
330
|
+
const { includeNonFatalGlobalErrors, includeUnhandledRejections } = this.props;
|
|
331
|
+
const shouldShow = info.kind === "rejection" ? includeUnhandledRejections === true : info.fatal || includeNonFatalGlobalErrors === true;
|
|
332
|
+
if (shouldShow) this.setState({ hasError: true });
|
|
333
|
+
}
|
|
334
|
+
render() {
|
|
335
|
+
if (this.state.hasError) return this.props.fallback ?? null;
|
|
336
|
+
return this.props.children;
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
function SunglassesGlobalErrorBoundary(props) {
|
|
340
|
+
const contextClient = useContext3(SunglassesContext);
|
|
341
|
+
const client = props.client ?? contextClient;
|
|
342
|
+
if (client === null) {
|
|
343
|
+
throw new Error(
|
|
344
|
+
"[SunGlasses] <SunglassesGlobalErrorBoundary> must be inside a <SunglassesProvider> or receive a `client` prop."
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
return /* @__PURE__ */ jsx3(GlobalErrorBoundaryInner, { ...props, client });
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// src/wrapExpoRouterErrorBoundary.tsx
|
|
351
|
+
import { useContext as useContext4, useEffect as useEffect6, useRef as useRef2 } from "react";
|
|
352
|
+
import { captureException as captureException5 } from "@drakkar.software/sunglasses-core";
|
|
353
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
354
|
+
function useExpoRouterPathname() {
|
|
355
|
+
if (!usePathname) return void 0;
|
|
356
|
+
return usePathname();
|
|
357
|
+
}
|
|
358
|
+
function wrapExpoRouterErrorBoundary(Boundary, options = {}) {
|
|
359
|
+
function WrappedExpoRouterErrorBoundary(props) {
|
|
360
|
+
const contextClient = useContext4(SunglassesContext);
|
|
361
|
+
const client = options.client ?? contextClient;
|
|
362
|
+
const pathname = useExpoRouterPathname();
|
|
363
|
+
const lastCaptured = useRef2(null);
|
|
364
|
+
const { error } = props;
|
|
365
|
+
useEffect6(() => {
|
|
366
|
+
if (!client || !error || lastCaptured.current === error) return;
|
|
367
|
+
lastCaptured.current = error;
|
|
368
|
+
const routeProps = {};
|
|
369
|
+
if (pathname) {
|
|
370
|
+
routeProps.$route_path = pathname;
|
|
371
|
+
routeProps.$route_name = pathname;
|
|
372
|
+
}
|
|
373
|
+
captureException5(client, error, {
|
|
374
|
+
handled: true,
|
|
375
|
+
...options.config,
|
|
376
|
+
properties: { ...routeProps, ...options.config?.properties }
|
|
377
|
+
});
|
|
378
|
+
}, [client, error, pathname]);
|
|
379
|
+
return /* @__PURE__ */ jsx4(Boundary, { ...props });
|
|
380
|
+
}
|
|
381
|
+
const name = Boundary.displayName || Boundary.name || "ErrorBoundary";
|
|
382
|
+
WrappedExpoRouterErrorBoundary.displayName = `wrapExpoRouterErrorBoundary(${name})`;
|
|
383
|
+
return WrappedExpoRouterErrorBoundary;
|
|
384
|
+
}
|
|
385
|
+
|
|
222
386
|
// src/index.ts
|
|
223
|
-
import {
|
|
387
|
+
import {
|
|
388
|
+
SunglassesCore,
|
|
389
|
+
captureException as captureException6,
|
|
390
|
+
patchConsole as patchConsole2,
|
|
391
|
+
publishGlobalError as publishGlobalError3,
|
|
392
|
+
subscribeGlobalError as subscribeGlobalError2
|
|
393
|
+
} from "@drakkar.software/sunglasses-core";
|
|
224
394
|
export {
|
|
225
395
|
SunglassesCore,
|
|
226
396
|
SunglassesErrorBoundary,
|
|
397
|
+
SunglassesGlobalErrorBoundary,
|
|
227
398
|
SunglassesProvider,
|
|
399
|
+
attachUnhandledRejectionHandler,
|
|
228
400
|
captureDeepLinkUtmParams,
|
|
229
|
-
|
|
401
|
+
captureException6 as captureException,
|
|
402
|
+
patchConsole2 as patchConsole,
|
|
403
|
+
publishGlobalError3 as publishGlobalError,
|
|
404
|
+
subscribeGlobalError2 as subscribeGlobalError,
|
|
230
405
|
useExpoRouterScreenTracking,
|
|
231
406
|
useExpoRouterUtmCapture,
|
|
232
407
|
useLinkingUtmCapture,
|
|
233
408
|
useNavigationScreenTracking,
|
|
234
|
-
useSunglasses
|
|
409
|
+
useSunglasses,
|
|
410
|
+
wrapExpoRouterErrorBoundary
|
|
235
411
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drakkar.software/sunglasses-react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "React Native / Expo provider and hooks for SunGlasses event tracking",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@drakkar.software/sunglasses-core": "0.
|
|
19
|
+
"@drakkar.software/sunglasses-core": "0.12.0"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"expo-router": ">=3.0.0",
|