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