@uncaughtdev/react 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Uncaught Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # @uncaughtdev/react
2
+
3
+ React and Next.js SDK for [Uncaught](https://github.com/AjeeshDevops/uncaught) error monitoring.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npx uncaught init
9
+ ```
10
+
11
+ Or manually:
12
+
13
+ ```bash
14
+ npm install @uncaughtdev/react
15
+ ```
16
+
17
+ ## What's included
18
+
19
+ - `<UncaughtProvider>` — wraps your app, auto-captures errors
20
+ - React Error Boundary with componentStack capture
21
+ - Global error and unhandled rejection handlers
22
+ - DOM breadcrumbs (clicks, navigation, fetch tracking)
23
+ - Next.js App Router and Pages Router support
24
+
25
+ ## License
26
+
27
+ MIT
@@ -0,0 +1,219 @@
1
+ import * as React$1 from 'react';
2
+ import React__default, { ReactNode, Component } from 'react';
3
+ import { UncaughtClient, UncaughtEvent, UncaughtConfig, Breadcrumb } from '@uncaughtdev/core';
4
+ export { Breadcrumb, EnvironmentInfo, UncaughtClient, UncaughtConfig, UncaughtEvent, getClient, initUncaught } from '@uncaughtdev/core';
5
+
6
+ /**
7
+ * Value provided by the UncaughtContext to descendant components.
8
+ */
9
+ interface UncaughtContextValue {
10
+ /** The initialized UncaughtClient instance, or null if not yet initialized. */
11
+ client: UncaughtClient | null;
12
+ }
13
+ /**
14
+ * Props for the UncaughtProvider component.
15
+ * Extends UncaughtConfig so all core configuration can be passed directly.
16
+ */
17
+ interface UncaughtProviderProps extends UncaughtConfig {
18
+ /** React children to render inside the provider. */
19
+ children: ReactNode;
20
+ /**
21
+ * Fallback UI to render when an error is caught by the built-in error boundary.
22
+ * Can be a ReactNode or a render function receiving the caught error.
23
+ */
24
+ fallback?: ReactNode | ((error: Error) => ReactNode);
25
+ /**
26
+ * When true, show a default error dialog when an error is caught.
27
+ * Only applies if no custom fallback is provided.
28
+ * @default false
29
+ */
30
+ showDialog?: boolean;
31
+ }
32
+ /**
33
+ * Props for the UncaughtErrorBoundary component.
34
+ */
35
+ interface UncaughtErrorBoundaryProps {
36
+ /** React children to render when no error has occurred. */
37
+ children: ReactNode;
38
+ /**
39
+ * Fallback UI to render when an error is caught.
40
+ * Can be a ReactNode or a render function receiving the caught error.
41
+ */
42
+ fallback?: ReactNode | ((error: Error) => ReactNode);
43
+ /**
44
+ * When true, show a default error dialog when an error is caught
45
+ * and no custom fallback is provided.
46
+ * @default false
47
+ */
48
+ showDialog?: boolean;
49
+ /**
50
+ * Callback invoked when an error is caught, after it has been reported.
51
+ */
52
+ onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
53
+ /**
54
+ * Callback invoked before the error is captured, allowing mutation
55
+ * of the event data before it is sent.
56
+ */
57
+ beforeCapture?: (event: UncaughtEvent, error: Error) => UncaughtEvent | void;
58
+ }
59
+ /**
60
+ * Internal state for the UncaughtErrorBoundary component.
61
+ */
62
+ interface ErrorBoundaryState {
63
+ hasError: boolean;
64
+ error: Error | null;
65
+ }
66
+
67
+ /**
68
+ * UncaughtProvider initializes the Uncaught error monitoring client and
69
+ * provides it to all descendant components via React context.
70
+ *
71
+ * It automatically:
72
+ * - Initializes the UncaughtClient with the provided configuration
73
+ * - Sets up global error handlers (window.onerror, unhandledrejection)
74
+ * - Sets up DOM breadcrumb tracking (clicks, navigation, fetch)
75
+ * - Detects and integrates with Next.js routing if present
76
+ * - Wraps children in an error boundary
77
+ * - Cleans up all listeners on unmount
78
+ *
79
+ * Usage:
80
+ * ```tsx
81
+ * <UncaughtProvider dsn="your-dsn" environment="production">
82
+ * <App />
83
+ * </UncaughtProvider>
84
+ * ```
85
+ *
86
+ * @param props - Configuration props extending UncaughtConfig plus children, fallback, and showDialog.
87
+ */
88
+ declare function UncaughtProvider({ children, fallback, showDialog, ...config }: UncaughtProviderProps): React__default.ReactElement;
89
+
90
+ /**
91
+ * React context that provides the UncaughtClient instance to descendant components.
92
+ * The context value is null when no UncaughtProvider is present in the tree.
93
+ */
94
+ declare const UncaughtContext: React$1.Context<UncaughtContextValue>;
95
+
96
+ /**
97
+ * React Error Boundary that captures errors and reports them to Uncaught.
98
+ *
99
+ * Must be a class component as React does not support error boundaries
100
+ * via function components / hooks.
101
+ *
102
+ * Usage:
103
+ * ```tsx
104
+ * <UncaughtErrorBoundary fallback={<div>Something went wrong</div>}>
105
+ * <MyApp />
106
+ * </UncaughtErrorBoundary>
107
+ * ```
108
+ */
109
+ declare class UncaughtErrorBoundary extends Component<UncaughtErrorBoundaryProps, ErrorBoundaryState> {
110
+ static contextType: React__default.Context<UncaughtContextValue>;
111
+ context: React__default.ContextType<typeof UncaughtContext>;
112
+ private removePopstateListener;
113
+ constructor(props: UncaughtErrorBoundaryProps);
114
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
115
+ componentDidCatch(error: Error, errorInfo: React__default.ErrorInfo): void;
116
+ componentDidMount(): void;
117
+ componentWillUnmount(): void;
118
+ /**
119
+ * Reset the error boundary state, allowing children to re-render.
120
+ */
121
+ resetError: () => void;
122
+ render(): React__default.ReactNode;
123
+ }
124
+
125
+ /**
126
+ * Returns the UncaughtClient instance from context.
127
+ * Must be called within an UncaughtProvider.
128
+ *
129
+ * @throws {Error} If called outside of an UncaughtProvider.
130
+ * @returns The UncaughtClient instance.
131
+ */
132
+ declare function useUncaught(): UncaughtClient;
133
+ /**
134
+ * Returns a function that reports an error to Uncaught.
135
+ * Safe to call even if the client is not yet initialized (will silently no-op).
136
+ *
137
+ * @returns A function `(error: Error, context?: Record<string, unknown>) => void`
138
+ */
139
+ declare function useReportError(): (error: Error, context?: Record<string, unknown>) => void;
140
+ /**
141
+ * Returns a function that adds a breadcrumb to the current Uncaught session.
142
+ * Safe to call even if the client is not yet initialized (will silently no-op).
143
+ *
144
+ * @returns A function `(breadcrumb: Partial<Breadcrumb>) => void`
145
+ */
146
+ declare function useBreadcrumb(): (breadcrumb: Partial<Breadcrumb>) => void;
147
+
148
+ /**
149
+ * Result of Next.js environment detection.
150
+ */
151
+ interface NextJsDetection {
152
+ /** Whether the app appears to be running in a Next.js context */
153
+ isNextJs: boolean;
154
+ /** Whether the App Router is detected */
155
+ isAppRouter: boolean;
156
+ /** Whether the Pages Router is detected */
157
+ isPagesRouter: boolean;
158
+ }
159
+ /**
160
+ * Detect if the current environment is a Next.js application,
161
+ * and which router (App Router vs Pages Router) is being used.
162
+ *
163
+ * This detection is best-effort and relies on undocumented
164
+ * but stable Next.js window properties.
165
+ *
166
+ * @returns Detection result with router type information.
167
+ */
168
+ declare function detectNextJs(): NextJsDetection;
169
+ /**
170
+ * Set up navigation tracking specifically for Next.js routing.
171
+ *
172
+ * For the Pages Router, hooks into Next.js router events (routeChangeStart,
173
+ * routeChangeComplete, routeChangeError).
174
+ *
175
+ * For the App Router, navigation is tracked via the general DOM breadcrumbs
176
+ * (history.pushState monkey-patch), so this function primarily adds
177
+ * Next.js-specific context.
178
+ *
179
+ * @param client - The UncaughtClient instance.
180
+ * @returns A cleanup function that removes the event listeners.
181
+ */
182
+ declare function setupNextJsNavigation(client: UncaughtClient): () => void;
183
+ /**
184
+ * Higher-order function for wrapping Next.js App Router layouts.
185
+ *
186
+ * Returns the configuration object needed to initialize UncaughtProvider
187
+ * with Next.js-specific defaults applied.
188
+ *
189
+ * Usage in layout.tsx:
190
+ * ```tsx
191
+ * import { UncaughtProvider } from '@uncaughtdev/react';
192
+ * import { withUncaught } from '@uncaughtdev/react';
193
+ *
194
+ * const uncaughtConfig = withUncaught({
195
+ * dsn: 'your-dsn-here',
196
+ * environment: 'production',
197
+ * });
198
+ *
199
+ * export default function RootLayout({ children }) {
200
+ * return (
201
+ * <html>
202
+ * <body>
203
+ * <UncaughtProvider {...uncaughtConfig}>
204
+ * {children}
205
+ * </UncaughtProvider>
206
+ * </body>
207
+ * </html>
208
+ * );
209
+ * }
210
+ * ```
211
+ *
212
+ * @param config - Base UncaughtConfig to extend with Next.js defaults.
213
+ * @returns Configuration object with Next.js-specific settings applied.
214
+ */
215
+ declare function withUncaught(config: UncaughtConfig): UncaughtConfig & {
216
+ __nextjs: boolean;
217
+ };
218
+
219
+ export { type ErrorBoundaryState, type NextJsDetection, UncaughtContext, type UncaughtContextValue, UncaughtErrorBoundary, type UncaughtErrorBoundaryProps, UncaughtProvider, type UncaughtProviderProps, detectNextJs, setupNextJsNavigation, useBreadcrumb, useReportError, useUncaught, withUncaught };
@@ -0,0 +1,219 @@
1
+ import * as React$1 from 'react';
2
+ import React__default, { ReactNode, Component } from 'react';
3
+ import { UncaughtClient, UncaughtEvent, UncaughtConfig, Breadcrumb } from '@uncaughtdev/core';
4
+ export { Breadcrumb, EnvironmentInfo, UncaughtClient, UncaughtConfig, UncaughtEvent, getClient, initUncaught } from '@uncaughtdev/core';
5
+
6
+ /**
7
+ * Value provided by the UncaughtContext to descendant components.
8
+ */
9
+ interface UncaughtContextValue {
10
+ /** The initialized UncaughtClient instance, or null if not yet initialized. */
11
+ client: UncaughtClient | null;
12
+ }
13
+ /**
14
+ * Props for the UncaughtProvider component.
15
+ * Extends UncaughtConfig so all core configuration can be passed directly.
16
+ */
17
+ interface UncaughtProviderProps extends UncaughtConfig {
18
+ /** React children to render inside the provider. */
19
+ children: ReactNode;
20
+ /**
21
+ * Fallback UI to render when an error is caught by the built-in error boundary.
22
+ * Can be a ReactNode or a render function receiving the caught error.
23
+ */
24
+ fallback?: ReactNode | ((error: Error) => ReactNode);
25
+ /**
26
+ * When true, show a default error dialog when an error is caught.
27
+ * Only applies if no custom fallback is provided.
28
+ * @default false
29
+ */
30
+ showDialog?: boolean;
31
+ }
32
+ /**
33
+ * Props for the UncaughtErrorBoundary component.
34
+ */
35
+ interface UncaughtErrorBoundaryProps {
36
+ /** React children to render when no error has occurred. */
37
+ children: ReactNode;
38
+ /**
39
+ * Fallback UI to render when an error is caught.
40
+ * Can be a ReactNode or a render function receiving the caught error.
41
+ */
42
+ fallback?: ReactNode | ((error: Error) => ReactNode);
43
+ /**
44
+ * When true, show a default error dialog when an error is caught
45
+ * and no custom fallback is provided.
46
+ * @default false
47
+ */
48
+ showDialog?: boolean;
49
+ /**
50
+ * Callback invoked when an error is caught, after it has been reported.
51
+ */
52
+ onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
53
+ /**
54
+ * Callback invoked before the error is captured, allowing mutation
55
+ * of the event data before it is sent.
56
+ */
57
+ beforeCapture?: (event: UncaughtEvent, error: Error) => UncaughtEvent | void;
58
+ }
59
+ /**
60
+ * Internal state for the UncaughtErrorBoundary component.
61
+ */
62
+ interface ErrorBoundaryState {
63
+ hasError: boolean;
64
+ error: Error | null;
65
+ }
66
+
67
+ /**
68
+ * UncaughtProvider initializes the Uncaught error monitoring client and
69
+ * provides it to all descendant components via React context.
70
+ *
71
+ * It automatically:
72
+ * - Initializes the UncaughtClient with the provided configuration
73
+ * - Sets up global error handlers (window.onerror, unhandledrejection)
74
+ * - Sets up DOM breadcrumb tracking (clicks, navigation, fetch)
75
+ * - Detects and integrates with Next.js routing if present
76
+ * - Wraps children in an error boundary
77
+ * - Cleans up all listeners on unmount
78
+ *
79
+ * Usage:
80
+ * ```tsx
81
+ * <UncaughtProvider dsn="your-dsn" environment="production">
82
+ * <App />
83
+ * </UncaughtProvider>
84
+ * ```
85
+ *
86
+ * @param props - Configuration props extending UncaughtConfig plus children, fallback, and showDialog.
87
+ */
88
+ declare function UncaughtProvider({ children, fallback, showDialog, ...config }: UncaughtProviderProps): React__default.ReactElement;
89
+
90
+ /**
91
+ * React context that provides the UncaughtClient instance to descendant components.
92
+ * The context value is null when no UncaughtProvider is present in the tree.
93
+ */
94
+ declare const UncaughtContext: React$1.Context<UncaughtContextValue>;
95
+
96
+ /**
97
+ * React Error Boundary that captures errors and reports them to Uncaught.
98
+ *
99
+ * Must be a class component as React does not support error boundaries
100
+ * via function components / hooks.
101
+ *
102
+ * Usage:
103
+ * ```tsx
104
+ * <UncaughtErrorBoundary fallback={<div>Something went wrong</div>}>
105
+ * <MyApp />
106
+ * </UncaughtErrorBoundary>
107
+ * ```
108
+ */
109
+ declare class UncaughtErrorBoundary extends Component<UncaughtErrorBoundaryProps, ErrorBoundaryState> {
110
+ static contextType: React__default.Context<UncaughtContextValue>;
111
+ context: React__default.ContextType<typeof UncaughtContext>;
112
+ private removePopstateListener;
113
+ constructor(props: UncaughtErrorBoundaryProps);
114
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
115
+ componentDidCatch(error: Error, errorInfo: React__default.ErrorInfo): void;
116
+ componentDidMount(): void;
117
+ componentWillUnmount(): void;
118
+ /**
119
+ * Reset the error boundary state, allowing children to re-render.
120
+ */
121
+ resetError: () => void;
122
+ render(): React__default.ReactNode;
123
+ }
124
+
125
+ /**
126
+ * Returns the UncaughtClient instance from context.
127
+ * Must be called within an UncaughtProvider.
128
+ *
129
+ * @throws {Error} If called outside of an UncaughtProvider.
130
+ * @returns The UncaughtClient instance.
131
+ */
132
+ declare function useUncaught(): UncaughtClient;
133
+ /**
134
+ * Returns a function that reports an error to Uncaught.
135
+ * Safe to call even if the client is not yet initialized (will silently no-op).
136
+ *
137
+ * @returns A function `(error: Error, context?: Record<string, unknown>) => void`
138
+ */
139
+ declare function useReportError(): (error: Error, context?: Record<string, unknown>) => void;
140
+ /**
141
+ * Returns a function that adds a breadcrumb to the current Uncaught session.
142
+ * Safe to call even if the client is not yet initialized (will silently no-op).
143
+ *
144
+ * @returns A function `(breadcrumb: Partial<Breadcrumb>) => void`
145
+ */
146
+ declare function useBreadcrumb(): (breadcrumb: Partial<Breadcrumb>) => void;
147
+
148
+ /**
149
+ * Result of Next.js environment detection.
150
+ */
151
+ interface NextJsDetection {
152
+ /** Whether the app appears to be running in a Next.js context */
153
+ isNextJs: boolean;
154
+ /** Whether the App Router is detected */
155
+ isAppRouter: boolean;
156
+ /** Whether the Pages Router is detected */
157
+ isPagesRouter: boolean;
158
+ }
159
+ /**
160
+ * Detect if the current environment is a Next.js application,
161
+ * and which router (App Router vs Pages Router) is being used.
162
+ *
163
+ * This detection is best-effort and relies on undocumented
164
+ * but stable Next.js window properties.
165
+ *
166
+ * @returns Detection result with router type information.
167
+ */
168
+ declare function detectNextJs(): NextJsDetection;
169
+ /**
170
+ * Set up navigation tracking specifically for Next.js routing.
171
+ *
172
+ * For the Pages Router, hooks into Next.js router events (routeChangeStart,
173
+ * routeChangeComplete, routeChangeError).
174
+ *
175
+ * For the App Router, navigation is tracked via the general DOM breadcrumbs
176
+ * (history.pushState monkey-patch), so this function primarily adds
177
+ * Next.js-specific context.
178
+ *
179
+ * @param client - The UncaughtClient instance.
180
+ * @returns A cleanup function that removes the event listeners.
181
+ */
182
+ declare function setupNextJsNavigation(client: UncaughtClient): () => void;
183
+ /**
184
+ * Higher-order function for wrapping Next.js App Router layouts.
185
+ *
186
+ * Returns the configuration object needed to initialize UncaughtProvider
187
+ * with Next.js-specific defaults applied.
188
+ *
189
+ * Usage in layout.tsx:
190
+ * ```tsx
191
+ * import { UncaughtProvider } from '@uncaughtdev/react';
192
+ * import { withUncaught } from '@uncaughtdev/react';
193
+ *
194
+ * const uncaughtConfig = withUncaught({
195
+ * dsn: 'your-dsn-here',
196
+ * environment: 'production',
197
+ * });
198
+ *
199
+ * export default function RootLayout({ children }) {
200
+ * return (
201
+ * <html>
202
+ * <body>
203
+ * <UncaughtProvider {...uncaughtConfig}>
204
+ * {children}
205
+ * </UncaughtProvider>
206
+ * </body>
207
+ * </html>
208
+ * );
209
+ * }
210
+ * ```
211
+ *
212
+ * @param config - Base UncaughtConfig to extend with Next.js defaults.
213
+ * @returns Configuration object with Next.js-specific settings applied.
214
+ */
215
+ declare function withUncaught(config: UncaughtConfig): UncaughtConfig & {
216
+ __nextjs: boolean;
217
+ };
218
+
219
+ export { type ErrorBoundaryState, type NextJsDetection, UncaughtContext, type UncaughtContextValue, UncaughtErrorBoundary, type UncaughtErrorBoundaryProps, UncaughtProvider, type UncaughtProviderProps, detectNextJs, setupNextJsNavigation, useBreadcrumb, useReportError, useUncaught, withUncaught };
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ 'use strict';var $=require('react'),core=require('@uncaughtdev/core'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var $__default=/*#__PURE__*/_interopDefault($);var f=$.createContext({client:null});f.displayName="UncaughtContext";var h=class extends $.Component{constructor(n){super(n);this.removePopstateListener=null;this.resetError=()=>{this.setState({hasError:false,error:null});};this.state={hasError:false,error:null};}static getDerivedStateFromError(n){return {hasError:true,error:n}}componentDidCatch(n,r){try{let a=this.context?.client??null,{onError:s,beforeCapture:o}=this.props,i=r.componentStack??void 0;a&&(a.captureError(n,{componentStack:i}),a.addBreadcrumb({type:"custom",category:"react.error_boundary",message:`Error boundary caught: ${n.message}`,level:"error"})),s&&s(n,r);}catch(a){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Error in componentDidCatch handler:",a);}}componentDidMount(){if(typeof window<"u"){let n=()=>{this.state.hasError&&this.resetError();};window.addEventListener("popstate",n),this.removePopstateListener=()=>{window.removeEventListener("popstate",n);};}}componentWillUnmount(){this.removePopstateListener&&(this.removePopstateListener(),this.removePopstateListener=null);}render(){let{hasError:n,error:r}=this.state,{children:a,fallback:s,showDialog:o}=this.props;if(!n||!r)return a;if(typeof s=="function")try{return s(r)}catch(i){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Fallback render function threw:",i);}return s!==void 0&&typeof s!="function"?s:o?jsxRuntime.jsx("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",minHeight:"100vh",padding:"20px",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',backgroundColor:"#f8f9fa"},children:jsxRuntime.jsxs("div",{style:{maxWidth:"480px",width:"100%",backgroundColor:"#ffffff",borderRadius:"12px",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)",padding:"32px",textAlign:"center"},children:[jsxRuntime.jsx("div",{style:{width:"48px",height:"48px",borderRadius:"50%",backgroundColor:"#fee2e2",display:"flex",alignItems:"center",justifyContent:"center",margin:"0 auto 16px",fontSize:"24px",color:"#dc2626"},children:"!"}),jsxRuntime.jsx("h2",{style:{margin:"0 0 8px",fontSize:"20px",fontWeight:600,color:"#111827"},children:"Something went wrong"}),jsxRuntime.jsx("p",{style:{margin:"0 0 24px",fontSize:"14px",color:"#6b7280",lineHeight:1.5},children:"An unexpected error occurred. Our team has been notified and is working on a fix."}),process.env.NODE_ENV==="development"&&jsxRuntime.jsxs("pre",{style:{textAlign:"left",backgroundColor:"#f3f4f6",padding:"12px",borderRadius:"8px",fontSize:"12px",color:"#dc2626",overflow:"auto",maxHeight:"120px",marginBottom:"24px",whiteSpace:"pre-wrap",wordBreak:"break-word"},children:[r.message,r.stack&&`
2
+
3
+ ${r.stack}`]}),jsxRuntime.jsx("button",{onClick:()=>{try{typeof window<"u"&&window.location.reload();}catch{}},style:{backgroundColor:"#3b82f6",color:"#ffffff",border:"none",borderRadius:"8px",padding:"10px 24px",fontSize:"14px",fontWeight:500,cursor:"pointer",transition:"background-color 0.15s ease"},onMouseOver:i=>{i.target.style.backgroundColor="#2563eb";},onMouseOut:i=>{i.target.style.backgroundColor="#3b82f6";},children:"Reload Page"})]})}):null}};h.contextType=f;var B=[/ResizeObserver loop/i,/^Script error\.?$/i,/chrome-extension:\/\//i,/moz-extension:\/\//i,/safari-extension:\/\//i,/safari-web-extension:\/\//i,/extension:\/\//i];function b(e){return B.some(t=>t.test(e))}function N(e,t){return !t||t.length===0?false:t.some(n=>typeof n=="string"?e.includes(n):n.test(e))}function A(e){if(e instanceof Error)return e;if(typeof e=="string")return new Error(e);if(e!=null)try{return new Error(JSON.stringify(e))}catch{return new Error(String(e))}return new Error("Unhandled promise rejection with no reason")}function C(e){if(typeof window>"u")return ()=>{};let n=(e.getConfig?.()??{}).ignoreErrors,r=s=>{try{let{error:o,message:i,filename:u}=s;if(!o&&(!i||i==="Script error.")&&!u)return;let c=o?.message??i??"Unknown error";if(b(c)||N(c,n))return;let l=o instanceof Error?o:new Error(c);e.captureError(l,{tags:{source:"window.onerror"},extra:{filename:u??void 0,lineno:s.lineno??void 0,colno:s.colno??void 0}});}catch(o){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Error in global error handler:",o);}},a=s=>{try{let o=A(s.reason),i=o.message;if(b(i)||N(i,n))return;e.captureError(o,{tags:{source:"unhandledrejection",unhandled:"true"}});}catch(o){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Error in unhandled rejection handler:",o);}};return window.addEventListener("error",r),window.addEventListener("unhandledrejection",a),()=>{window.removeEventListener("error",r),window.removeEventListener("unhandledrejection",a);}}function y(e,t){return e.length<=t?e:e.slice(0,t-3)+"..."}function O(e){let t=e.tagName?.toLowerCase()??"unknown",n=t==="input"?e.type?.toLowerCase():void 0;if(n==="password")return "password input";let r;t==="button"||e.getAttribute("role")==="button"?r="button":t==="a"?r="link":t==="input"?r=`${n??"text"} input`:t==="select"?r="dropdown":t==="textarea"?r="textarea":r=t;let a=null,s=e.getAttribute("aria-label");if(s)a=s;else if(t==="button"||t==="a"){let u=e.innerText?.trim();u&&(a=u.split(`
4
+ `)[0]);}else if(t==="input"||t==="textarea"){let u=e.placeholder,c=e.getAttribute("name");a=u||c||null;}let o=e.id?`#${e.id}`:"";return `Clicked${a?` '${y(a,50)}'`:""} ${r}${o}`}function T(e){let t=n=>{try{let r=n.target;if(!r||!r.tagName||r.tagName.toLowerCase()==="input"&&r.type?.toLowerCase()==="password")return;let a=O(r);e.addBreadcrumb({timestamp:new Date().toISOString(),type:"click",category:"ui.click",message:y(a,200),level:"info",data:{tag:r.tagName.toLowerCase(),id:r.id||void 0,className:typeof r.className=="string"?y(r.className,100):void 0}});}catch{}};return document.addEventListener("click",t,true),()=>document.removeEventListener("click",t,true)}function M(e){let t=window.location.href,n=o=>{try{let i=t;t=o,e.addBreadcrumb({timestamp:new Date().toISOString(),type:"navigation",category:"navigation",message:`Navigated to ${o}`,level:"info",data:{from:i,to:o}});}catch{}},r=()=>{n(window.location.href);};window.addEventListener("popstate",r);let a=history.pushState.bind(history),s=history.replaceState.bind(history);return history.pushState=function(o,i,u){if(a(o,i,u),u)try{let c=new URL(String(u),window.location.href).href;n(c);}catch{n(String(u));}},history.replaceState=function(o,i,u){if(s(o,i,u),u)try{let c=new URL(String(u),window.location.href).href;n(c);}catch{n(String(u));}},()=>{window.removeEventListener("popstate",r),history.pushState=a,history.replaceState=s;}}function V(e){let t=window.fetch.bind(window),n=e.getConfig?.()??{},r=n.endpoint??n.dsn??"",a=[];if(typeof r=="string"&&r)try{let o=new URL(r);a.push(o.hostname);}catch{a.push(r);}a.push("uncaught.dev"),a.push("api.uncaught");let s=o=>a.some(i=>i&&o.includes(i));return window.fetch=async function(o,i){let u=o instanceof Request?o.url:o instanceof URL?o.href:String(o),c=(i?.method??(o instanceof Request?o.method:"GET")).toUpperCase();if(s(u))return t(o,i);let l=Date.now();try{let d=await t(o,i),m=Date.now()-l,g=d.status>=400;try{let p=y(u,150);e.addBreadcrumb({timestamp:new Date().toISOString(),type:"api_call",category:"fetch",message:`${c} ${p} [${d.status}]`,level:g?"error":"info",data:{method:c,url:p,status:d.status,statusText:d.statusText,duration:m}});}catch{}return d}catch(d){let m=Date.now()-l;try{let g=y(u,150);e.addBreadcrumb({timestamp:new Date().toISOString(),type:"api_call",category:"fetch",message:`${c} ${g} [Network Error]`,level:"error",data:{method:c,url:g,status:0,error:d instanceof Error?d.message:"Network error",duration:m}});}catch{}throw d}},()=>{window.fetch=t;}}function R(e){if(typeof window>"u")return ()=>{};let t=[];try{t.push(T(e));}catch(n){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up click tracking:",n);}try{t.push(M(e));}catch(n){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up navigation tracking:",n);}try{t.push(V(e));}catch(n){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up fetch tracking:",n);}return ()=>{t.forEach(n=>{try{n();}catch{}});}}function w(){if(typeof window>"u")return {isNextJs:false,isAppRouter:false,isPagesRouter:false};let e=window,t=e.__NEXT_DATA__!==void 0,n=e.__next_f!==void 0,r=false;try{r=document.querySelector('meta[name="next-size-adjust"]')!==null;}catch{}return {isNextJs:t||n||r,isAppRouter:n,isPagesRouter:t&&!n}}function x(e){if(typeof window>"u")return ()=>{};let t=w(),n=[];try{e.addBreadcrumb({type:"navigation",category:"nextjs",message:`Next.js detected: ${t.isAppRouter?"App Router":t.isPagesRouter?"Pages Router":"Unknown Router"}`,level:"info",data:{isAppRouter:t.isAppRouter,isPagesRouter:t.isPagesRouter}});}catch{}if(t.isPagesRouter)try{let a=window.next?.router?.events;if(a){let s=0,o=c=>{try{s=Date.now(),e.addBreadcrumb({type:"navigation",category:"nextjs.route",message:`Route change started: ${String(c)}`,level:"info",data:{to:String(c)}});}catch{}},i=c=>{try{let l=s>0?Date.now()-s:void 0;e.addBreadcrumb({type:"navigation",category:"nextjs.route",message:`Route change completed: ${String(c)}`,level:"info",data:{to:String(c),duration:l}});}catch{}},u=(c,l)=>{try{let d=s>0?Date.now()-s:void 0;e.addBreadcrumb({type:"navigation",category:"nextjs.route",message:`Route change error: ${String(l)}`,level:"error",data:{to:String(l),error:c instanceof Error?c.message:String(c),duration:d}});}catch{}};a.on("routeChangeStart",o),a.on("routeChangeComplete",i),a.on("routeChangeError",u),n.push(()=>{try{a.off("routeChangeStart",o),a.off("routeChangeComplete",i),a.off("routeChangeError",u);}catch{}});}}catch(r){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up Next.js Pages Router navigation:",r);}return ()=>{n.forEach(r=>{try{r();}catch{}});}}function j(e){return {...e,__nextjs:true}}function J({children:e,fallback:t,showDialog:n,...r}){let[a,s]=$.useState(null),o=$.useRef([]),i=$.useRef(false);$.useEffect(()=>{if(i.current)return;i.current=true;let c=true,l=[];try{let{__nextjs:d,...m}=r,g=core.initUncaught(m);if(!g){process.env.NODE_ENV==="development"&&console.warn("[Uncaught] initUncaught returned null/undefined. Error monitoring is disabled.");return}try{let p=C(g);l.push(p);}catch(p){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up global handlers:",p);}try{let p=R(g);l.push(p);}catch(p){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up DOM breadcrumbs:",p);}if(typeof window<"u")try{if(w().isNextJs||d){let D=x(g);l.push(D);}}catch(p){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up Next.js integration:",p);}o.current=l,c&&s(g);}catch(d){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to initialize:",d);}return ()=>{c=false,o.current.forEach(d=>{try{d();}catch{}}),o.current=[],i.current=false;}},[]);let u=$__default.default.useMemo(()=>({client:a}),[a]);return jsxRuntime.jsx(f.Provider,{value:u,children:jsxRuntime.jsx(h,{fallback:t,showDialog:n,children:e})})}function z(){let{client:e}=$.useContext(f);if(!e)throw new Error("useUncaught must be used within an <UncaughtProvider>. Wrap your application in <UncaughtProvider> to use this hook.");return e}function W(){let{client:e}=$.useContext(f);return $.useCallback((t,n)=>{try{if(!e){process.env.NODE_ENV==="development"&&console.warn("[Uncaught] useReportError called but no UncaughtClient is available. Make sure <UncaughtProvider> is mounted.");return}e.captureError(t);}catch(r){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to report error:",r);}},[e])}function G(){let{client:e}=$.useContext(f);return $.useCallback(t=>{try{if(!e){process.env.NODE_ENV==="development"&&console.warn("[Uncaught] useBreadcrumb called but no UncaughtClient is available. Make sure <UncaughtProvider> is mounted.");return}e.addBreadcrumb({type:t.type??"custom",category:t.category??"custom",message:t.message??"",level:t.level??"info",data:t.data});}catch(n){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to add breadcrumb:",n);}},[e])}Object.defineProperty(exports,"getClient",{enumerable:true,get:function(){return core.getClient}});Object.defineProperty(exports,"initUncaught",{enumerable:true,get:function(){return core.initUncaught}});exports.UncaughtContext=f;exports.UncaughtErrorBoundary=h;exports.UncaughtProvider=J;exports.detectNextJs=w;exports.setupNextJsNavigation=x;exports.useBreadcrumb=G;exports.useReportError=W;exports.useUncaught=z;exports.withUncaught=j;//# sourceMappingURL=index.js.map
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.ts","../src/error-boundary.tsx","../src/global-handlers.ts","../src/dom-breadcrumbs.ts","../src/next-integration.ts","../src/provider.tsx","../src/hooks.ts"],"names":["UncaughtContext","createContext","UncaughtErrorBoundary","Component","props","error","errorInfo","client","onError","beforeCapture","componentStack","e","handlePopState","hasError","children","fallback","showDialog","jsx","jsxs","NOISE_PATTERNS","isNoiseError","message","pattern","isIgnoredByConfig","ignoreErrors","normalizeRejectionReason","reason","setupGlobalHandlers","handleError","event","filename","errorMessage","errorObj","handleRejection","truncate","str","maxLen","describeElement","element","tag","type","role","text","ariaLabel","innerText","placeholder","name","id","setupClickTracking","handleClick","target","setupNavigationTracking","currentUrl","recordNavigation","to","from","originalPushState","originalReplaceState","data","unused","url","resolvedUrl","setupFetchTracking","originalFetch","config","apiEndpoint","uncaughtEndpoints","isUncaughtRequest","endpoint","input","init","method","startTime","response","duration","isError","displayUrl","setupDomBreadcrumbs","cleanups","cleanup","detectNextJs","win","hasPagesData","hasAppRouterData","hasNextMeta","setupNextJsNavigation","detection","routerEvents","navigationStartTime","handleRouteChangeStart","handleRouteChangeComplete","handleRouteChangeError","err","withUncaught","UncaughtProvider","setClient","useState","cleanupRef","useRef","initializedRef","useEffect","mounted","__nextjs","coreConfig","uncaughtClient","initUncaught","cleanupGlobal","cleanupDom","cleanupNext","contextValue","React","useUncaught","useContext","useReportError","useCallback","context","useBreadcrumb","breadcrumb"],"mappings":"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","file":"index.js","sourcesContent":["'use client';\n\nimport { createContext } from 'react';\nimport type { UncaughtContextValue } from './types';\n\n/**\n * React context that provides the UncaughtClient instance to descendant components.\n * The context value is null when no UncaughtProvider is present in the tree.\n */\nexport const UncaughtContext = createContext<UncaughtContextValue>({\n client: null,\n});\n\nUncaughtContext.displayName = 'UncaughtContext';\n","'use client';\n\nimport React, { Component } from 'react';\nimport type { UncaughtClient } from '@uncaughtdev/core';\nimport { UncaughtContext } from './context';\nimport type { UncaughtErrorBoundaryProps, ErrorBoundaryState } from './types';\n\n/**\n * React Error Boundary that captures errors and reports them to Uncaught.\n *\n * Must be a class component as React does not support error boundaries\n * via function components / hooks.\n *\n * Usage:\n * ```tsx\n * <UncaughtErrorBoundary fallback={<div>Something went wrong</div>}>\n * <MyApp />\n * </UncaughtErrorBoundary>\n * ```\n */\nexport class UncaughtErrorBoundary extends Component<\n UncaughtErrorBoundaryProps,\n ErrorBoundaryState\n> {\n static contextType = UncaughtContext;\n declare context: React.ContextType<typeof UncaughtContext>;\n\n private removePopstateListener: (() => void) | null = null;\n\n constructor(props: UncaughtErrorBoundaryProps) {\n super(props);\n this.state = {\n hasError: false,\n error: null,\n };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return {\n hasError: true,\n error,\n };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n try {\n const client: UncaughtClient | null = this.context?.client ?? null;\n const { onError, beforeCapture } = this.props;\n\n // Extract component stack for richer error context\n const componentStack = errorInfo.componentStack ?? undefined;\n\n if (client) {\n client.captureError(error, {\n componentStack,\n });\n\n // Add a breadcrumb noting the error boundary source\n client.addBreadcrumb({\n type: 'custom',\n category: 'react.error_boundary',\n message: `Error boundary caught: ${error.message}`,\n level: 'error',\n });\n }\n\n // Invoke the user's onError callback if provided\n if (onError) {\n onError(error, errorInfo);\n }\n } catch (e) {\n // Never crash the host app from error reporting itself\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Error in componentDidCatch handler:', e);\n }\n }\n }\n\n componentDidMount(): void {\n // Auto-reset the error boundary when the user navigates via browser back/forward\n if (typeof window !== 'undefined') {\n const handlePopState = (): void => {\n if (this.state.hasError) {\n this.resetError();\n }\n };\n\n window.addEventListener('popstate', handlePopState);\n this.removePopstateListener = () => {\n window.removeEventListener('popstate', handlePopState);\n };\n }\n }\n\n componentWillUnmount(): void {\n if (this.removePopstateListener) {\n this.removePopstateListener();\n this.removePopstateListener = null;\n }\n }\n\n /**\n * Reset the error boundary state, allowing children to re-render.\n */\n resetError = (): void => {\n this.setState({\n hasError: false,\n error: null,\n });\n };\n\n render(): React.ReactNode {\n const { hasError, error } = this.state;\n const { children, fallback, showDialog } = this.props;\n\n if (!hasError || !error) {\n return children;\n }\n\n // Custom fallback: render function\n if (typeof fallback === 'function') {\n try {\n return fallback(error);\n } catch (e) {\n // If the fallback itself throws, fall through to default\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Fallback render function threw:', e);\n }\n }\n }\n\n // Custom fallback: ReactNode\n if (fallback !== undefined && typeof fallback !== 'function') {\n return fallback;\n }\n\n // Default dialog UI\n if (showDialog) {\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '100vh',\n padding: '20px',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n backgroundColor: '#f8f9fa',\n }}\n >\n <div\n style={{\n maxWidth: '480px',\n width: '100%',\n backgroundColor: '#ffffff',\n borderRadius: '12px',\n boxShadow:\n '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',\n padding: '32px',\n textAlign: 'center',\n }}\n >\n <div\n style={{\n width: '48px',\n height: '48px',\n borderRadius: '50%',\n backgroundColor: '#fee2e2',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n margin: '0 auto 16px',\n fontSize: '24px',\n color: '#dc2626',\n }}\n >\n !\n </div>\n <h2\n style={{\n margin: '0 0 8px',\n fontSize: '20px',\n fontWeight: 600,\n color: '#111827',\n }}\n >\n Something went wrong\n </h2>\n <p\n style={{\n margin: '0 0 24px',\n fontSize: '14px',\n color: '#6b7280',\n lineHeight: 1.5,\n }}\n >\n An unexpected error occurred. Our team has been notified and is\n working on a fix.\n </p>\n {process.env.NODE_ENV === 'development' && (\n <pre\n style={{\n textAlign: 'left',\n backgroundColor: '#f3f4f6',\n padding: '12px',\n borderRadius: '8px',\n fontSize: '12px',\n color: '#dc2626',\n overflow: 'auto',\n maxHeight: '120px',\n marginBottom: '24px',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n >\n {error.message}\n {error.stack && `\\n\\n${error.stack}`}\n </pre>\n )}\n <button\n onClick={() => {\n try {\n if (typeof window !== 'undefined') {\n window.location.reload();\n }\n } catch {\n // Silently ignore reload failures\n }\n }}\n style={{\n backgroundColor: '#3b82f6',\n color: '#ffffff',\n border: 'none',\n borderRadius: '8px',\n padding: '10px 24px',\n fontSize: '14px',\n fontWeight: 500,\n cursor: 'pointer',\n transition: 'background-color 0.15s ease',\n }}\n onMouseOver={(e) => {\n (e.target as HTMLButtonElement).style.backgroundColor =\n '#2563eb';\n }}\n onMouseOut={(e) => {\n (e.target as HTMLButtonElement).style.backgroundColor =\n '#3b82f6';\n }}\n >\n Reload Page\n </button>\n </div>\n </div>\n );\n }\n\n // No fallback and no dialog: render nothing (transparent failure)\n return null;\n }\n}\n","import type { UncaughtClient } from '@uncaughtdev/core';\n\n/**\n * Patterns for errors that are typically noise and should be ignored.\n * These are errors produced by the browser, extensions, or third-party scripts\n * that provide no actionable information.\n */\nconst NOISE_PATTERNS: RegExp[] = [\n // ResizeObserver loop errors are benign and happen in many apps\n /ResizeObserver loop/i,\n // \"Script error.\" with no useful info (cross-origin scripts without CORS headers)\n /^Script error\\.?$/i,\n // Browser extension errors\n /chrome-extension:\\/\\//i,\n /moz-extension:\\/\\//i,\n /safari-extension:\\/\\//i,\n /safari-web-extension:\\/\\//i,\n // Edge extension errors\n /extension:\\/\\//i,\n];\n\n/**\n * Check if an error message matches any of the known noise patterns.\n */\nfunction isNoiseError(message: string): boolean {\n return NOISE_PATTERNS.some((pattern) => pattern.test(message));\n}\n\n/**\n * Check if an error matches any user-defined ignoreErrors patterns.\n */\nfunction isIgnoredByConfig(\n message: string,\n ignoreErrors?: Array<string | RegExp>\n): boolean {\n if (!ignoreErrors || ignoreErrors.length === 0) {\n return false;\n }\n\n return ignoreErrors.some((pattern) => {\n if (typeof pattern === 'string') {\n return message.includes(pattern);\n }\n return pattern.test(message);\n });\n}\n\n/**\n * Normalize a promise rejection reason into a proper Error object.\n */\nfunction normalizeRejectionReason(reason: unknown): Error {\n if (reason instanceof Error) {\n return reason;\n }\n\n if (typeof reason === 'string') {\n return new Error(reason);\n }\n\n if (reason !== null && reason !== undefined) {\n try {\n return new Error(JSON.stringify(reason));\n } catch {\n return new Error(String(reason));\n }\n }\n\n return new Error('Unhandled promise rejection with no reason');\n}\n\n/**\n * Set up global error handlers to capture uncaught exceptions and\n * unhandled promise rejections.\n *\n * @param client - The UncaughtClient instance to report errors to.\n * @returns A cleanup function that removes the event listeners.\n */\nexport function setupGlobalHandlers(client: UncaughtClient): () => void {\n // Guard for SSR environments\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const config = client.getConfig?.() ?? {};\n const ignoreErrors = (config as Record<string, unknown>)\n .ignoreErrors as Array<string | RegExp> | undefined;\n\n /**\n * Handle uncaught exceptions via window.onerror / 'error' event.\n */\n const handleError = (event: ErrorEvent): void => {\n try {\n const { error, message, filename } = event;\n\n // \"Script error.\" with no stack and no filename is cross-origin noise\n if (\n !error &&\n (!message || message === 'Script error.') &&\n !filename\n ) {\n return;\n }\n\n const errorMessage =\n error?.message ?? message ?? 'Unknown error';\n\n // Filter out noise errors\n if (isNoiseError(errorMessage)) {\n return;\n }\n\n // Filter out user-configured ignored errors\n if (isIgnoredByConfig(errorMessage, ignoreErrors)) {\n return;\n }\n\n // Build the error object\n const errorObj =\n error instanceof Error ? error : new Error(errorMessage);\n\n client.captureError(errorObj, {\n tags: { source: 'window.onerror' },\n extra: {\n filename: filename ?? undefined,\n lineno: event.lineno ?? undefined,\n colno: event.colno ?? undefined,\n },\n });\n\n // Do NOT call event.preventDefault() - let the browser still log the error\n } catch (e) {\n // Never crash the host app from our error handler\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Error in global error handler:', e);\n }\n }\n };\n\n /**\n * Handle unhandled promise rejections.\n */\n const handleRejection = (event: PromiseRejectionEvent): void => {\n try {\n const error = normalizeRejectionReason(event.reason);\n const errorMessage = error.message;\n\n // Filter out noise errors\n if (isNoiseError(errorMessage)) {\n return;\n }\n\n // Filter out user-configured ignored errors\n if (isIgnoredByConfig(errorMessage, ignoreErrors)) {\n return;\n }\n\n client.captureError(error, {\n tags: {\n source: 'unhandledrejection',\n unhandled: 'true',\n },\n });\n\n // Do NOT call event.preventDefault() - let the browser still log\n } catch (e) {\n // Never crash the host app from our error handler\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Error in unhandled rejection handler:',\n e\n );\n }\n }\n };\n\n window.addEventListener('error', handleError);\n window.addEventListener('unhandledrejection', handleRejection);\n\n // Return cleanup function\n return () => {\n window.removeEventListener('error', handleError);\n window.removeEventListener('unhandledrejection', handleRejection);\n };\n}\n","import type { UncaughtClient } from '@uncaughtdev/core';\n\n/**\n * Maximum length for breadcrumb messages to avoid excessively large payloads.\n */\nconst MAX_MESSAGE_LENGTH = 200;\n\n/**\n * Truncate a string to a maximum length, appending \"...\" if truncated.\n */\nfunction truncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n return str.slice(0, maxLen - 3) + '...';\n}\n\n/**\n * Extract a human-readable description of a clicked element.\n */\nfunction describeElement(element: HTMLElement): string {\n const tag = element.tagName?.toLowerCase() ?? 'unknown';\n const type =\n tag === 'input'\n ? (element as HTMLInputElement).type?.toLowerCase()\n : undefined;\n\n // Don't record anything from password inputs\n if (type === 'password') {\n return 'password input';\n }\n\n // Determine element role for description\n let role: string;\n if (tag === 'button' || element.getAttribute('role') === 'button') {\n role = 'button';\n } else if (tag === 'a') {\n role = 'link';\n } else if (tag === 'input') {\n role = `${type ?? 'text'} input`;\n } else if (tag === 'select') {\n role = 'dropdown';\n } else if (tag === 'textarea') {\n role = 'textarea';\n } else {\n role = tag;\n }\n\n // Get meaningful text content\n let text: string | null = null;\n\n // aria-label is highest priority for meaningful text\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel) {\n text = ariaLabel;\n }\n // For buttons and links, try innerText\n else if (tag === 'button' || tag === 'a') {\n const innerText = element.innerText?.trim();\n if (innerText) {\n text = innerText.split('\\n')[0]; // First line only\n }\n }\n // For inputs, use placeholder or name\n else if (tag === 'input' || tag === 'textarea') {\n const placeholder = (element as HTMLInputElement).placeholder;\n const name = element.getAttribute('name');\n text = placeholder || name || null;\n }\n\n // Build description\n const id = element.id ? `#${element.id}` : '';\n const textPart = text ? ` '${truncate(text, 50)}'` : '';\n\n return `Clicked${textPart} ${role}${id}`;\n}\n\n/**\n * Set up click tracking as breadcrumbs.\n * Uses capture phase to intercept clicks before they may be stopped.\n */\nfunction setupClickTracking(client: UncaughtClient): () => void {\n const handleClick = (event: MouseEvent): void => {\n try {\n const target = event.target as HTMLElement | null;\n if (!target || !target.tagName) return;\n\n // Don't record clicks on password inputs\n if (\n target.tagName.toLowerCase() === 'input' &&\n (target as HTMLInputElement).type?.toLowerCase() === 'password'\n ) {\n return;\n }\n\n const message = describeElement(target);\n\n client.addBreadcrumb({\n timestamp: new Date().toISOString(),\n type: 'click',\n category: 'ui.click',\n message: truncate(message, MAX_MESSAGE_LENGTH),\n level: 'info',\n data: {\n tag: target.tagName.toLowerCase(),\n id: target.id || undefined,\n className:\n typeof target.className === 'string'\n ? truncate(target.className, 100)\n : undefined,\n },\n });\n } catch {\n // Silently ignore - never crash the host app\n }\n };\n\n document.addEventListener('click', handleClick, true); // capture phase\n return () => document.removeEventListener('click', handleClick, true);\n}\n\n/**\n * Set up navigation tracking as breadcrumbs.\n * Tracks popstate events and monkey-patches history.pushState / replaceState.\n */\nfunction setupNavigationTracking(client: UncaughtClient): () => void {\n let currentUrl = window.location.href;\n\n const recordNavigation = (to: string): void => {\n try {\n const from = currentUrl;\n currentUrl = to;\n\n client.addBreadcrumb({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Navigated to ${to}`,\n level: 'info',\n data: {\n from,\n to,\n },\n });\n } catch {\n // Silently ignore\n }\n };\n\n // popstate fires on back/forward\n const handlePopState = (): void => {\n recordNavigation(window.location.href);\n };\n\n window.addEventListener('popstate', handlePopState);\n\n // Monkey-patch pushState and replaceState\n const originalPushState = history.pushState.bind(history);\n const originalReplaceState = history.replaceState.bind(history);\n\n history.pushState = function (\n data: unknown,\n unused: string,\n url?: string | URL | null\n ): void {\n originalPushState(data, unused, url);\n if (url) {\n try {\n const resolvedUrl = new URL(\n String(url),\n window.location.href\n ).href;\n recordNavigation(resolvedUrl);\n } catch {\n recordNavigation(String(url));\n }\n }\n };\n\n history.replaceState = function (\n data: unknown,\n unused: string,\n url?: string | URL | null\n ): void {\n originalReplaceState(data, unused, url);\n if (url) {\n try {\n const resolvedUrl = new URL(\n String(url),\n window.location.href\n ).href;\n recordNavigation(resolvedUrl);\n } catch {\n recordNavigation(String(url));\n }\n }\n };\n\n return () => {\n window.removeEventListener('popstate', handlePopState);\n history.pushState = originalPushState;\n history.replaceState = originalReplaceState;\n };\n}\n\n/**\n * Set up fetch tracking as breadcrumbs.\n * Monkey-patches window.fetch to record API calls with method, URL, status, and duration.\n * Does NOT record request/response bodies. Skips requests to the Uncaught API.\n */\nfunction setupFetchTracking(client: UncaughtClient): () => void {\n const originalFetch = window.fetch.bind(window);\n\n // Get the Uncaught API endpoint to exclude self-reporting requests\n const config = client.getConfig?.() ?? {};\n const apiEndpoint =\n (config as Record<string, unknown>).endpoint ??\n (config as Record<string, unknown>).dsn ??\n '';\n const uncaughtEndpoints: string[] = [];\n\n if (typeof apiEndpoint === 'string' && apiEndpoint) {\n try {\n const url = new URL(apiEndpoint);\n uncaughtEndpoints.push(url.hostname);\n } catch {\n uncaughtEndpoints.push(apiEndpoint);\n }\n }\n\n // Also exclude common Uncaught API patterns\n uncaughtEndpoints.push('uncaught.dev');\n uncaughtEndpoints.push('api.uncaught');\n\n const isUncaughtRequest = (url: string): boolean => {\n return uncaughtEndpoints.some(\n (endpoint) => endpoint && url.includes(endpoint)\n );\n };\n\n window.fetch = async function (\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n const url =\n input instanceof Request\n ? input.url\n : input instanceof URL\n ? input.href\n : String(input);\n\n const method = (\n init?.method ??\n (input instanceof Request ? input.method : 'GET')\n ).toUpperCase();\n\n // Skip Uncaught's own requests to prevent infinite loops\n if (isUncaughtRequest(url)) {\n return originalFetch(input, init);\n }\n\n const startTime = Date.now();\n\n try {\n const response = await originalFetch(input, init);\n const duration = Date.now() - startTime;\n const isError = response.status >= 400;\n\n try {\n // Truncate URL for the breadcrumb to avoid huge payloads\n const displayUrl = truncate(url, 150);\n\n client.addBreadcrumb({\n timestamp: new Date().toISOString(),\n type: 'api_call',\n category: 'fetch',\n message: `${method} ${displayUrl} [${response.status}]`,\n level: isError ? 'error' : 'info',\n data: {\n method,\n url: displayUrl,\n status: response.status,\n statusText: response.statusText,\n duration,\n },\n });\n } catch {\n // Silently ignore breadcrumb failures\n }\n\n return response;\n } catch (error) {\n const duration = Date.now() - startTime;\n\n try {\n const displayUrl = truncate(url, 150);\n\n client.addBreadcrumb({\n timestamp: new Date().toISOString(),\n type: 'api_call',\n category: 'fetch',\n message: `${method} ${displayUrl} [Network Error]`,\n level: 'error',\n data: {\n method,\n url: displayUrl,\n status: 0,\n error:\n error instanceof Error\n ? error.message\n : 'Network error',\n duration,\n },\n });\n } catch {\n // Silently ignore breadcrumb failures\n }\n\n throw error; // Re-throw so the app's error handling still works\n }\n };\n\n return () => {\n window.fetch = originalFetch;\n };\n}\n\n/**\n * Set up automatic DOM breadcrumb tracking including clicks,\n * navigation changes, and fetch API calls.\n *\n * @param client - The UncaughtClient instance to add breadcrumbs to.\n * @returns A cleanup function that removes all listeners and restores patched functions.\n */\nexport function setupDomBreadcrumbs(client: UncaughtClient): () => void {\n // Guard for SSR environments\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const cleanups: Array<() => void> = [];\n\n try {\n cleanups.push(setupClickTracking(client));\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Failed to set up click tracking:', e);\n }\n }\n\n try {\n cleanups.push(setupNavigationTracking(client));\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Failed to set up navigation tracking:',\n e\n );\n }\n }\n\n try {\n cleanups.push(setupFetchTracking(client));\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Failed to set up fetch tracking:', e);\n }\n }\n\n return () => {\n cleanups.forEach((cleanup) => {\n try {\n cleanup();\n } catch {\n // Silently ignore cleanup failures\n }\n });\n };\n}\n","import type { UncaughtClient, UncaughtConfig } from '@uncaughtdev/core';\n\n/**\n * Augmented Window interface to access Next.js internals.\n * These are undocumented but stable properties Next.js sets on the window.\n */\ninterface NextWindow extends Window {\n /** Present in Pages Router - contains build-time page data */\n __NEXT_DATA__?: {\n page?: string;\n query?: Record<string, unknown>;\n buildId?: string;\n props?: Record<string, unknown>;\n };\n /** Present in App Router - contains flight response data */\n __next_f?: unknown[];\n /** Next.js router instance (Pages Router) */\n next?: {\n router?: {\n events?: {\n on: (event: string, handler: (...args: unknown[]) => void) => void;\n off: (event: string, handler: (...args: unknown[]) => void) => void;\n };\n };\n };\n}\n\n/**\n * Result of Next.js environment detection.\n */\nexport interface NextJsDetection {\n /** Whether the app appears to be running in a Next.js context */\n isNextJs: boolean;\n /** Whether the App Router is detected */\n isAppRouter: boolean;\n /** Whether the Pages Router is detected */\n isPagesRouter: boolean;\n}\n\n/**\n * Detect if the current environment is a Next.js application,\n * and which router (App Router vs Pages Router) is being used.\n *\n * This detection is best-effort and relies on undocumented\n * but stable Next.js window properties.\n *\n * @returns Detection result with router type information.\n */\nexport function detectNextJs(): NextJsDetection {\n if (typeof window === 'undefined') {\n return {\n isNextJs: false,\n isAppRouter: false,\n isPagesRouter: false,\n };\n }\n\n const win = window as NextWindow;\n\n const hasPagesData = win.__NEXT_DATA__ !== undefined;\n const hasAppRouterData = win.__next_f !== undefined;\n\n // Check for Next.js meta tag as an additional signal\n let hasNextMeta = false;\n try {\n const nextMeta = document.querySelector('meta[name=\"next-size-adjust\"]');\n hasNextMeta = nextMeta !== null;\n } catch {\n // Ignore DOM query errors\n }\n\n const isPagesRouter = hasPagesData && !hasAppRouterData;\n const isAppRouter = hasAppRouterData;\n const isNextJs = hasPagesData || hasAppRouterData || hasNextMeta;\n\n return {\n isNextJs,\n isAppRouter,\n isPagesRouter,\n };\n}\n\n/**\n * Set up navigation tracking specifically for Next.js routing.\n *\n * For the Pages Router, hooks into Next.js router events (routeChangeStart,\n * routeChangeComplete, routeChangeError).\n *\n * For the App Router, navigation is tracked via the general DOM breadcrumbs\n * (history.pushState monkey-patch), so this function primarily adds\n * Next.js-specific context.\n *\n * @param client - The UncaughtClient instance.\n * @returns A cleanup function that removes the event listeners.\n */\nexport function setupNextJsNavigation(client: UncaughtClient): () => void {\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const detection = detectNextJs();\n const cleanups: Array<() => void> = [];\n\n // Add Next.js context to the client\n try {\n client.addBreadcrumb({\n\n type: 'navigation',\n category: 'nextjs',\n message: `Next.js detected: ${\n detection.isAppRouter\n ? 'App Router'\n : detection.isPagesRouter\n ? 'Pages Router'\n : 'Unknown Router'\n }`,\n level: 'info',\n data: {\n isAppRouter: detection.isAppRouter,\n isPagesRouter: detection.isPagesRouter,\n },\n });\n } catch {\n // Silently ignore\n }\n\n // Pages Router: hook into router events\n if (detection.isPagesRouter) {\n try {\n const win = window as NextWindow;\n const routerEvents = win.next?.router?.events;\n\n if (routerEvents) {\n let navigationStartTime = 0;\n\n const handleRouteChangeStart = (url: unknown): void => {\n try {\n navigationStartTime = Date.now();\n client.addBreadcrumb({\n \n type: 'navigation',\n category: 'nextjs.route',\n message: `Route change started: ${String(url)}`,\n level: 'info',\n data: {\n to: String(url),\n },\n });\n } catch {\n // Silently ignore\n }\n };\n\n const handleRouteChangeComplete = (url: unknown): void => {\n try {\n const duration =\n navigationStartTime > 0\n ? Date.now() - navigationStartTime\n : undefined;\n\n client.addBreadcrumb({\n \n type: 'navigation',\n category: 'nextjs.route',\n message: `Route change completed: ${String(url)}`,\n level: 'info',\n data: {\n to: String(url),\n duration,\n },\n });\n } catch {\n // Silently ignore\n }\n };\n\n const handleRouteChangeError = (\n err: unknown,\n url: unknown\n ): void => {\n try {\n const duration =\n navigationStartTime > 0\n ? Date.now() - navigationStartTime\n : undefined;\n\n client.addBreadcrumb({\n \n type: 'navigation',\n category: 'nextjs.route',\n message: `Route change error: ${String(url)}`,\n level: 'error',\n data: {\n to: String(url),\n error:\n err instanceof Error\n ? err.message\n : String(err),\n duration,\n },\n });\n } catch {\n // Silently ignore\n }\n };\n\n routerEvents.on('routeChangeStart', handleRouteChangeStart);\n routerEvents.on(\n 'routeChangeComplete',\n handleRouteChangeComplete\n );\n routerEvents.on('routeChangeError', handleRouteChangeError);\n\n cleanups.push(() => {\n try {\n routerEvents.off(\n 'routeChangeStart',\n handleRouteChangeStart\n );\n routerEvents.off(\n 'routeChangeComplete',\n handleRouteChangeComplete\n );\n routerEvents.off(\n 'routeChangeError',\n handleRouteChangeError\n );\n } catch {\n // Silently ignore\n }\n });\n }\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Failed to set up Next.js Pages Router navigation:',\n e\n );\n }\n }\n }\n\n return () => {\n cleanups.forEach((cleanup) => {\n try {\n cleanup();\n } catch {\n // Silently ignore cleanup failures\n }\n });\n };\n}\n\n/**\n * Higher-order function for wrapping Next.js App Router layouts.\n *\n * Returns the configuration object needed to initialize UncaughtProvider\n * with Next.js-specific defaults applied.\n *\n * Usage in layout.tsx:\n * ```tsx\n * import { UncaughtProvider } from '@uncaughtdev/react';\n * import { withUncaught } from '@uncaughtdev/react';\n *\n * const uncaughtConfig = withUncaught({\n * dsn: 'your-dsn-here',\n * environment: 'production',\n * });\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html>\n * <body>\n * <UncaughtProvider {...uncaughtConfig}>\n * {children}\n * </UncaughtProvider>\n * </body>\n * </html>\n * );\n * }\n * ```\n *\n * @param config - Base UncaughtConfig to extend with Next.js defaults.\n * @returns Configuration object with Next.js-specific settings applied.\n */\nexport function withUncaught(\n config: UncaughtConfig\n): UncaughtConfig & { __nextjs: boolean } {\n return {\n ...config,\n __nextjs: true,\n };\n}\n","'use client';\n\nimport React, { useEffect, useRef, useState } from 'react';\nimport { initUncaught } from '@uncaughtdev/core';\nimport type { UncaughtClient } from '@uncaughtdev/core';\nimport { UncaughtContext } from './context';\nimport { UncaughtErrorBoundary } from './error-boundary';\nimport { setupGlobalHandlers } from './global-handlers';\nimport { setupDomBreadcrumbs } from './dom-breadcrumbs';\nimport { setupNextJsNavigation, detectNextJs } from './next-integration';\nimport type { UncaughtProviderProps } from './types';\n\n/**\n * UncaughtProvider initializes the Uncaught error monitoring client and\n * provides it to all descendant components via React context.\n *\n * It automatically:\n * - Initializes the UncaughtClient with the provided configuration\n * - Sets up global error handlers (window.onerror, unhandledrejection)\n * - Sets up DOM breadcrumb tracking (clicks, navigation, fetch)\n * - Detects and integrates with Next.js routing if present\n * - Wraps children in an error boundary\n * - Cleans up all listeners on unmount\n *\n * Usage:\n * ```tsx\n * <UncaughtProvider dsn=\"your-dsn\" environment=\"production\">\n * <App />\n * </UncaughtProvider>\n * ```\n *\n * @param props - Configuration props extending UncaughtConfig plus children, fallback, and showDialog.\n */\nexport function UncaughtProvider({\n children,\n fallback,\n showDialog,\n ...config\n}: UncaughtProviderProps): React.ReactElement {\n const [client, setClient] = useState<UncaughtClient | null>(null);\n const cleanupRef = useRef<Array<() => void>>([]);\n const initializedRef = useRef(false);\n\n useEffect(() => {\n // Prevent double-initialization in React StrictMode\n if (initializedRef.current) {\n return;\n }\n initializedRef.current = true;\n\n let mounted = true;\n const cleanups: Array<() => void> = [];\n\n try {\n // Strip React-specific props before passing to core\n const { __nextjs, ...coreConfig } = config as Record<string, unknown> & {\n __nextjs?: boolean;\n };\n\n // Initialize the core client\n const uncaughtClient = initUncaught(\n coreConfig as Parameters<typeof initUncaught>[0]\n );\n\n if (!uncaughtClient) {\n if (process.env.NODE_ENV === 'development') {\n console.warn(\n '[Uncaught] initUncaught returned null/undefined. Error monitoring is disabled.'\n );\n }\n return;\n }\n\n // Set up global error handlers\n try {\n const cleanupGlobal = setupGlobalHandlers(uncaughtClient);\n cleanups.push(cleanupGlobal);\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Failed to set up global handlers:',\n e\n );\n }\n }\n\n // Set up DOM breadcrumbs\n try {\n const cleanupDom = setupDomBreadcrumbs(uncaughtClient);\n cleanups.push(cleanupDom);\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Failed to set up DOM breadcrumbs:',\n e\n );\n }\n }\n\n // Set up Next.js integration if detected or explicitly configured\n if (typeof window !== 'undefined') {\n try {\n const nextDetection = detectNextJs();\n if (nextDetection.isNextJs || __nextjs) {\n const cleanupNext = setupNextJsNavigation(uncaughtClient);\n cleanups.push(cleanupNext);\n }\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Failed to set up Next.js integration:',\n e\n );\n }\n }\n }\n\n // Store cleanups for unmount\n cleanupRef.current = cleanups;\n\n // Only update state if still mounted\n if (mounted) {\n setClient(uncaughtClient);\n }\n } catch (e) {\n // Never crash the host app during initialization\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Failed to initialize:', e);\n }\n }\n\n return () => {\n mounted = false;\n // Run all cleanup functions\n cleanupRef.current.forEach((cleanup) => {\n try {\n cleanup();\n } catch {\n // Silently ignore cleanup failures\n }\n });\n cleanupRef.current = [];\n initializedRef.current = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []); // Initialize once on mount - config changes require remounting\n\n const contextValue = React.useMemo(() => ({ client }), [client]);\n\n return (\n <UncaughtContext.Provider value={contextValue}>\n <UncaughtErrorBoundary fallback={fallback} showDialog={showDialog}>\n {children}\n </UncaughtErrorBoundary>\n </UncaughtContext.Provider>\n );\n}\n","'use client';\n\nimport { useContext, useCallback } from 'react';\nimport type { UncaughtClient, Breadcrumb } from '@uncaughtdev/core';\nimport { UncaughtContext } from './context';\n\n/**\n * Returns the UncaughtClient instance from context.\n * Must be called within an UncaughtProvider.\n *\n * @throws {Error} If called outside of an UncaughtProvider.\n * @returns The UncaughtClient instance.\n */\nexport function useUncaught(): UncaughtClient {\n const { client } = useContext(UncaughtContext);\n\n if (!client) {\n throw new Error(\n 'useUncaught must be used within an <UncaughtProvider>. ' +\n 'Wrap your application in <UncaughtProvider> to use this hook.'\n );\n }\n\n return client;\n}\n\n/**\n * Returns a function that reports an error to Uncaught.\n * Safe to call even if the client is not yet initialized (will silently no-op).\n *\n * @returns A function `(error: Error, context?: Record<string, unknown>) => void`\n */\nexport function useReportError(): (\n error: Error,\n context?: Record<string, unknown>\n) => void {\n const { client } = useContext(UncaughtContext);\n\n return useCallback(\n (error: Error, context?: Record<string, unknown>) => {\n try {\n if (!client) {\n if (process.env.NODE_ENV === 'development') {\n console.warn(\n '[Uncaught] useReportError called but no UncaughtClient is available. ' +\n 'Make sure <UncaughtProvider> is mounted.'\n );\n }\n return;\n }\n\n client.captureError(error);\n } catch (e) {\n // Never crash the host app\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Failed to report error:', e);\n }\n }\n },\n [client]\n );\n}\n\n/**\n * Returns a function that adds a breadcrumb to the current Uncaught session.\n * Safe to call even if the client is not yet initialized (will silently no-op).\n *\n * @returns A function `(breadcrumb: Partial<Breadcrumb>) => void`\n */\nexport function useBreadcrumb(): (breadcrumb: Partial<Breadcrumb>) => void {\n const { client } = useContext(UncaughtContext);\n\n return useCallback(\n (breadcrumb: Partial<Breadcrumb>) => {\n try {\n if (!client) {\n if (process.env.NODE_ENV === 'development') {\n console.warn(\n '[Uncaught] useBreadcrumb called but no UncaughtClient is available. ' +\n 'Make sure <UncaughtProvider> is mounted.'\n );\n }\n return;\n }\n\n client.addBreadcrumb({\n type: breadcrumb.type ?? 'custom',\n category: breadcrumb.category ?? 'custom',\n message: breadcrumb.message ?? '',\n level: breadcrumb.level ?? 'info',\n data: breadcrumb.data,\n });\n } catch (e) {\n // Never crash the host app\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Failed to add breadcrumb:', e);\n }\n }\n },\n [client]\n );\n}\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,5 @@
1
+ import $,{createContext,Component,useState,useRef,useEffect,useContext,useCallback}from'react';import {initUncaught}from'@uncaughtdev/core';export{getClient,initUncaught}from'@uncaughtdev/core';import {jsx,jsxs}from'react/jsx-runtime';var f=createContext({client:null});f.displayName="UncaughtContext";var h=class extends Component{constructor(n){super(n);this.removePopstateListener=null;this.resetError=()=>{this.setState({hasError:false,error:null});};this.state={hasError:false,error:null};}static getDerivedStateFromError(n){return {hasError:true,error:n}}componentDidCatch(n,r){try{let a=this.context?.client??null,{onError:s,beforeCapture:o}=this.props,i=r.componentStack??void 0;a&&(a.captureError(n,{componentStack:i}),a.addBreadcrumb({type:"custom",category:"react.error_boundary",message:`Error boundary caught: ${n.message}`,level:"error"})),s&&s(n,r);}catch(a){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Error in componentDidCatch handler:",a);}}componentDidMount(){if(typeof window<"u"){let n=()=>{this.state.hasError&&this.resetError();};window.addEventListener("popstate",n),this.removePopstateListener=()=>{window.removeEventListener("popstate",n);};}}componentWillUnmount(){this.removePopstateListener&&(this.removePopstateListener(),this.removePopstateListener=null);}render(){let{hasError:n,error:r}=this.state,{children:a,fallback:s,showDialog:o}=this.props;if(!n||!r)return a;if(typeof s=="function")try{return s(r)}catch(i){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Fallback render function threw:",i);}return s!==void 0&&typeof s!="function"?s:o?jsx("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",minHeight:"100vh",padding:"20px",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',backgroundColor:"#f8f9fa"},children:jsxs("div",{style:{maxWidth:"480px",width:"100%",backgroundColor:"#ffffff",borderRadius:"12px",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)",padding:"32px",textAlign:"center"},children:[jsx("div",{style:{width:"48px",height:"48px",borderRadius:"50%",backgroundColor:"#fee2e2",display:"flex",alignItems:"center",justifyContent:"center",margin:"0 auto 16px",fontSize:"24px",color:"#dc2626"},children:"!"}),jsx("h2",{style:{margin:"0 0 8px",fontSize:"20px",fontWeight:600,color:"#111827"},children:"Something went wrong"}),jsx("p",{style:{margin:"0 0 24px",fontSize:"14px",color:"#6b7280",lineHeight:1.5},children:"An unexpected error occurred. Our team has been notified and is working on a fix."}),process.env.NODE_ENV==="development"&&jsxs("pre",{style:{textAlign:"left",backgroundColor:"#f3f4f6",padding:"12px",borderRadius:"8px",fontSize:"12px",color:"#dc2626",overflow:"auto",maxHeight:"120px",marginBottom:"24px",whiteSpace:"pre-wrap",wordBreak:"break-word"},children:[r.message,r.stack&&`
2
+
3
+ ${r.stack}`]}),jsx("button",{onClick:()=>{try{typeof window<"u"&&window.location.reload();}catch{}},style:{backgroundColor:"#3b82f6",color:"#ffffff",border:"none",borderRadius:"8px",padding:"10px 24px",fontSize:"14px",fontWeight:500,cursor:"pointer",transition:"background-color 0.15s ease"},onMouseOver:i=>{i.target.style.backgroundColor="#2563eb";},onMouseOut:i=>{i.target.style.backgroundColor="#3b82f6";},children:"Reload Page"})]})}):null}};h.contextType=f;var B=[/ResizeObserver loop/i,/^Script error\.?$/i,/chrome-extension:\/\//i,/moz-extension:\/\//i,/safari-extension:\/\//i,/safari-web-extension:\/\//i,/extension:\/\//i];function b(e){return B.some(t=>t.test(e))}function N(e,t){return !t||t.length===0?false:t.some(n=>typeof n=="string"?e.includes(n):n.test(e))}function A(e){if(e instanceof Error)return e;if(typeof e=="string")return new Error(e);if(e!=null)try{return new Error(JSON.stringify(e))}catch{return new Error(String(e))}return new Error("Unhandled promise rejection with no reason")}function C(e){if(typeof window>"u")return ()=>{};let n=(e.getConfig?.()??{}).ignoreErrors,r=s=>{try{let{error:o,message:i,filename:u}=s;if(!o&&(!i||i==="Script error.")&&!u)return;let c=o?.message??i??"Unknown error";if(b(c)||N(c,n))return;let l=o instanceof Error?o:new Error(c);e.captureError(l,{tags:{source:"window.onerror"},extra:{filename:u??void 0,lineno:s.lineno??void 0,colno:s.colno??void 0}});}catch(o){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Error in global error handler:",o);}},a=s=>{try{let o=A(s.reason),i=o.message;if(b(i)||N(i,n))return;e.captureError(o,{tags:{source:"unhandledrejection",unhandled:"true"}});}catch(o){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Error in unhandled rejection handler:",o);}};return window.addEventListener("error",r),window.addEventListener("unhandledrejection",a),()=>{window.removeEventListener("error",r),window.removeEventListener("unhandledrejection",a);}}function y(e,t){return e.length<=t?e:e.slice(0,t-3)+"..."}function O(e){let t=e.tagName?.toLowerCase()??"unknown",n=t==="input"?e.type?.toLowerCase():void 0;if(n==="password")return "password input";let r;t==="button"||e.getAttribute("role")==="button"?r="button":t==="a"?r="link":t==="input"?r=`${n??"text"} input`:t==="select"?r="dropdown":t==="textarea"?r="textarea":r=t;let a=null,s=e.getAttribute("aria-label");if(s)a=s;else if(t==="button"||t==="a"){let u=e.innerText?.trim();u&&(a=u.split(`
4
+ `)[0]);}else if(t==="input"||t==="textarea"){let u=e.placeholder,c=e.getAttribute("name");a=u||c||null;}let o=e.id?`#${e.id}`:"";return `Clicked${a?` '${y(a,50)}'`:""} ${r}${o}`}function T(e){let t=n=>{try{let r=n.target;if(!r||!r.tagName||r.tagName.toLowerCase()==="input"&&r.type?.toLowerCase()==="password")return;let a=O(r);e.addBreadcrumb({timestamp:new Date().toISOString(),type:"click",category:"ui.click",message:y(a,200),level:"info",data:{tag:r.tagName.toLowerCase(),id:r.id||void 0,className:typeof r.className=="string"?y(r.className,100):void 0}});}catch{}};return document.addEventListener("click",t,true),()=>document.removeEventListener("click",t,true)}function M(e){let t=window.location.href,n=o=>{try{let i=t;t=o,e.addBreadcrumb({timestamp:new Date().toISOString(),type:"navigation",category:"navigation",message:`Navigated to ${o}`,level:"info",data:{from:i,to:o}});}catch{}},r=()=>{n(window.location.href);};window.addEventListener("popstate",r);let a=history.pushState.bind(history),s=history.replaceState.bind(history);return history.pushState=function(o,i,u){if(a(o,i,u),u)try{let c=new URL(String(u),window.location.href).href;n(c);}catch{n(String(u));}},history.replaceState=function(o,i,u){if(s(o,i,u),u)try{let c=new URL(String(u),window.location.href).href;n(c);}catch{n(String(u));}},()=>{window.removeEventListener("popstate",r),history.pushState=a,history.replaceState=s;}}function V(e){let t=window.fetch.bind(window),n=e.getConfig?.()??{},r=n.endpoint??n.dsn??"",a=[];if(typeof r=="string"&&r)try{let o=new URL(r);a.push(o.hostname);}catch{a.push(r);}a.push("uncaught.dev"),a.push("api.uncaught");let s=o=>a.some(i=>i&&o.includes(i));return window.fetch=async function(o,i){let u=o instanceof Request?o.url:o instanceof URL?o.href:String(o),c=(i?.method??(o instanceof Request?o.method:"GET")).toUpperCase();if(s(u))return t(o,i);let l=Date.now();try{let d=await t(o,i),m=Date.now()-l,g=d.status>=400;try{let p=y(u,150);e.addBreadcrumb({timestamp:new Date().toISOString(),type:"api_call",category:"fetch",message:`${c} ${p} [${d.status}]`,level:g?"error":"info",data:{method:c,url:p,status:d.status,statusText:d.statusText,duration:m}});}catch{}return d}catch(d){let m=Date.now()-l;try{let g=y(u,150);e.addBreadcrumb({timestamp:new Date().toISOString(),type:"api_call",category:"fetch",message:`${c} ${g} [Network Error]`,level:"error",data:{method:c,url:g,status:0,error:d instanceof Error?d.message:"Network error",duration:m}});}catch{}throw d}},()=>{window.fetch=t;}}function R(e){if(typeof window>"u")return ()=>{};let t=[];try{t.push(T(e));}catch(n){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up click tracking:",n);}try{t.push(M(e));}catch(n){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up navigation tracking:",n);}try{t.push(V(e));}catch(n){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up fetch tracking:",n);}return ()=>{t.forEach(n=>{try{n();}catch{}});}}function w(){if(typeof window>"u")return {isNextJs:false,isAppRouter:false,isPagesRouter:false};let e=window,t=e.__NEXT_DATA__!==void 0,n=e.__next_f!==void 0,r=false;try{r=document.querySelector('meta[name="next-size-adjust"]')!==null;}catch{}return {isNextJs:t||n||r,isAppRouter:n,isPagesRouter:t&&!n}}function x(e){if(typeof window>"u")return ()=>{};let t=w(),n=[];try{e.addBreadcrumb({type:"navigation",category:"nextjs",message:`Next.js detected: ${t.isAppRouter?"App Router":t.isPagesRouter?"Pages Router":"Unknown Router"}`,level:"info",data:{isAppRouter:t.isAppRouter,isPagesRouter:t.isPagesRouter}});}catch{}if(t.isPagesRouter)try{let a=window.next?.router?.events;if(a){let s=0,o=c=>{try{s=Date.now(),e.addBreadcrumb({type:"navigation",category:"nextjs.route",message:`Route change started: ${String(c)}`,level:"info",data:{to:String(c)}});}catch{}},i=c=>{try{let l=s>0?Date.now()-s:void 0;e.addBreadcrumb({type:"navigation",category:"nextjs.route",message:`Route change completed: ${String(c)}`,level:"info",data:{to:String(c),duration:l}});}catch{}},u=(c,l)=>{try{let d=s>0?Date.now()-s:void 0;e.addBreadcrumb({type:"navigation",category:"nextjs.route",message:`Route change error: ${String(l)}`,level:"error",data:{to:String(l),error:c instanceof Error?c.message:String(c),duration:d}});}catch{}};a.on("routeChangeStart",o),a.on("routeChangeComplete",i),a.on("routeChangeError",u),n.push(()=>{try{a.off("routeChangeStart",o),a.off("routeChangeComplete",i),a.off("routeChangeError",u);}catch{}});}}catch(r){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up Next.js Pages Router navigation:",r);}return ()=>{n.forEach(r=>{try{r();}catch{}});}}function j(e){return {...e,__nextjs:true}}function J({children:e,fallback:t,showDialog:n,...r}){let[a,s]=useState(null),o=useRef([]),i=useRef(false);useEffect(()=>{if(i.current)return;i.current=true;let c=true,l=[];try{let{__nextjs:d,...m}=r,g=initUncaught(m);if(!g){process.env.NODE_ENV==="development"&&console.warn("[Uncaught] initUncaught returned null/undefined. Error monitoring is disabled.");return}try{let p=C(g);l.push(p);}catch(p){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up global handlers:",p);}try{let p=R(g);l.push(p);}catch(p){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up DOM breadcrumbs:",p);}if(typeof window<"u")try{if(w().isNextJs||d){let D=x(g);l.push(D);}}catch(p){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to set up Next.js integration:",p);}o.current=l,c&&s(g);}catch(d){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to initialize:",d);}return ()=>{c=false,o.current.forEach(d=>{try{d();}catch{}}),o.current=[],i.current=false;}},[]);let u=$.useMemo(()=>({client:a}),[a]);return jsx(f.Provider,{value:u,children:jsx(h,{fallback:t,showDialog:n,children:e})})}function z(){let{client:e}=useContext(f);if(!e)throw new Error("useUncaught must be used within an <UncaughtProvider>. Wrap your application in <UncaughtProvider> to use this hook.");return e}function W(){let{client:e}=useContext(f);return useCallback((t,n)=>{try{if(!e){process.env.NODE_ENV==="development"&&console.warn("[Uncaught] useReportError called but no UncaughtClient is available. Make sure <UncaughtProvider> is mounted.");return}e.captureError(t);}catch(r){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to report error:",r);}},[e])}function G(){let{client:e}=useContext(f);return useCallback(t=>{try{if(!e){process.env.NODE_ENV==="development"&&console.warn("[Uncaught] useBreadcrumb called but no UncaughtClient is available. Make sure <UncaughtProvider> is mounted.");return}e.addBreadcrumb({type:t.type??"custom",category:t.category??"custom",message:t.message??"",level:t.level??"info",data:t.data});}catch(n){process.env.NODE_ENV==="development"&&console.error("[Uncaught] Failed to add breadcrumb:",n);}},[e])}export{f as UncaughtContext,h as UncaughtErrorBoundary,J as UncaughtProvider,w as detectNextJs,x as setupNextJsNavigation,G as useBreadcrumb,W as useReportError,z as useUncaught,j as withUncaught};//# sourceMappingURL=index.mjs.map
5
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.ts","../src/error-boundary.tsx","../src/global-handlers.ts","../src/dom-breadcrumbs.ts","../src/next-integration.ts","../src/provider.tsx","../src/hooks.ts"],"names":["UncaughtContext","createContext","UncaughtErrorBoundary","Component","props","error","errorInfo","client","onError","beforeCapture","componentStack","e","handlePopState","hasError","children","fallback","showDialog","jsx","jsxs","NOISE_PATTERNS","isNoiseError","message","pattern","isIgnoredByConfig","ignoreErrors","normalizeRejectionReason","reason","setupGlobalHandlers","handleError","event","filename","errorMessage","errorObj","handleRejection","truncate","str","maxLen","describeElement","element","tag","type","role","text","ariaLabel","innerText","placeholder","name","id","setupClickTracking","handleClick","target","setupNavigationTracking","currentUrl","recordNavigation","to","from","originalPushState","originalReplaceState","data","unused","url","resolvedUrl","setupFetchTracking","originalFetch","config","apiEndpoint","uncaughtEndpoints","isUncaughtRequest","endpoint","input","init","method","startTime","response","duration","isError","displayUrl","setupDomBreadcrumbs","cleanups","cleanup","detectNextJs","win","hasPagesData","hasAppRouterData","hasNextMeta","setupNextJsNavigation","detection","routerEvents","navigationStartTime","handleRouteChangeStart","handleRouteChangeComplete","handleRouteChangeError","err","withUncaught","UncaughtProvider","setClient","useState","cleanupRef","useRef","initializedRef","useEffect","mounted","__nextjs","coreConfig","uncaughtClient","initUncaught","cleanupGlobal","cleanupDom","cleanupNext","contextValue","React","useUncaught","useContext","useReportError","useCallback","context","useBreadcrumb","breadcrumb"],"mappings":"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","file":"index.mjs","sourcesContent":["'use client';\n\nimport { createContext } from 'react';\nimport type { UncaughtContextValue } from './types';\n\n/**\n * React context that provides the UncaughtClient instance to descendant components.\n * The context value is null when no UncaughtProvider is present in the tree.\n */\nexport const UncaughtContext = createContext<UncaughtContextValue>({\n client: null,\n});\n\nUncaughtContext.displayName = 'UncaughtContext';\n","'use client';\n\nimport React, { Component } from 'react';\nimport type { UncaughtClient } from '@uncaughtdev/core';\nimport { UncaughtContext } from './context';\nimport type { UncaughtErrorBoundaryProps, ErrorBoundaryState } from './types';\n\n/**\n * React Error Boundary that captures errors and reports them to Uncaught.\n *\n * Must be a class component as React does not support error boundaries\n * via function components / hooks.\n *\n * Usage:\n * ```tsx\n * <UncaughtErrorBoundary fallback={<div>Something went wrong</div>}>\n * <MyApp />\n * </UncaughtErrorBoundary>\n * ```\n */\nexport class UncaughtErrorBoundary extends Component<\n UncaughtErrorBoundaryProps,\n ErrorBoundaryState\n> {\n static contextType = UncaughtContext;\n declare context: React.ContextType<typeof UncaughtContext>;\n\n private removePopstateListener: (() => void) | null = null;\n\n constructor(props: UncaughtErrorBoundaryProps) {\n super(props);\n this.state = {\n hasError: false,\n error: null,\n };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return {\n hasError: true,\n error,\n };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n try {\n const client: UncaughtClient | null = this.context?.client ?? null;\n const { onError, beforeCapture } = this.props;\n\n // Extract component stack for richer error context\n const componentStack = errorInfo.componentStack ?? undefined;\n\n if (client) {\n client.captureError(error, {\n componentStack,\n });\n\n // Add a breadcrumb noting the error boundary source\n client.addBreadcrumb({\n type: 'custom',\n category: 'react.error_boundary',\n message: `Error boundary caught: ${error.message}`,\n level: 'error',\n });\n }\n\n // Invoke the user's onError callback if provided\n if (onError) {\n onError(error, errorInfo);\n }\n } catch (e) {\n // Never crash the host app from error reporting itself\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Error in componentDidCatch handler:', e);\n }\n }\n }\n\n componentDidMount(): void {\n // Auto-reset the error boundary when the user navigates via browser back/forward\n if (typeof window !== 'undefined') {\n const handlePopState = (): void => {\n if (this.state.hasError) {\n this.resetError();\n }\n };\n\n window.addEventListener('popstate', handlePopState);\n this.removePopstateListener = () => {\n window.removeEventListener('popstate', handlePopState);\n };\n }\n }\n\n componentWillUnmount(): void {\n if (this.removePopstateListener) {\n this.removePopstateListener();\n this.removePopstateListener = null;\n }\n }\n\n /**\n * Reset the error boundary state, allowing children to re-render.\n */\n resetError = (): void => {\n this.setState({\n hasError: false,\n error: null,\n });\n };\n\n render(): React.ReactNode {\n const { hasError, error } = this.state;\n const { children, fallback, showDialog } = this.props;\n\n if (!hasError || !error) {\n return children;\n }\n\n // Custom fallback: render function\n if (typeof fallback === 'function') {\n try {\n return fallback(error);\n } catch (e) {\n // If the fallback itself throws, fall through to default\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Fallback render function threw:', e);\n }\n }\n }\n\n // Custom fallback: ReactNode\n if (fallback !== undefined && typeof fallback !== 'function') {\n return fallback;\n }\n\n // Default dialog UI\n if (showDialog) {\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '100vh',\n padding: '20px',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n backgroundColor: '#f8f9fa',\n }}\n >\n <div\n style={{\n maxWidth: '480px',\n width: '100%',\n backgroundColor: '#ffffff',\n borderRadius: '12px',\n boxShadow:\n '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',\n padding: '32px',\n textAlign: 'center',\n }}\n >\n <div\n style={{\n width: '48px',\n height: '48px',\n borderRadius: '50%',\n backgroundColor: '#fee2e2',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n margin: '0 auto 16px',\n fontSize: '24px',\n color: '#dc2626',\n }}\n >\n !\n </div>\n <h2\n style={{\n margin: '0 0 8px',\n fontSize: '20px',\n fontWeight: 600,\n color: '#111827',\n }}\n >\n Something went wrong\n </h2>\n <p\n style={{\n margin: '0 0 24px',\n fontSize: '14px',\n color: '#6b7280',\n lineHeight: 1.5,\n }}\n >\n An unexpected error occurred. Our team has been notified and is\n working on a fix.\n </p>\n {process.env.NODE_ENV === 'development' && (\n <pre\n style={{\n textAlign: 'left',\n backgroundColor: '#f3f4f6',\n padding: '12px',\n borderRadius: '8px',\n fontSize: '12px',\n color: '#dc2626',\n overflow: 'auto',\n maxHeight: '120px',\n marginBottom: '24px',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n >\n {error.message}\n {error.stack && `\\n\\n${error.stack}`}\n </pre>\n )}\n <button\n onClick={() => {\n try {\n if (typeof window !== 'undefined') {\n window.location.reload();\n }\n } catch {\n // Silently ignore reload failures\n }\n }}\n style={{\n backgroundColor: '#3b82f6',\n color: '#ffffff',\n border: 'none',\n borderRadius: '8px',\n padding: '10px 24px',\n fontSize: '14px',\n fontWeight: 500,\n cursor: 'pointer',\n transition: 'background-color 0.15s ease',\n }}\n onMouseOver={(e) => {\n (e.target as HTMLButtonElement).style.backgroundColor =\n '#2563eb';\n }}\n onMouseOut={(e) => {\n (e.target as HTMLButtonElement).style.backgroundColor =\n '#3b82f6';\n }}\n >\n Reload Page\n </button>\n </div>\n </div>\n );\n }\n\n // No fallback and no dialog: render nothing (transparent failure)\n return null;\n }\n}\n","import type { UncaughtClient } from '@uncaughtdev/core';\n\n/**\n * Patterns for errors that are typically noise and should be ignored.\n * These are errors produced by the browser, extensions, or third-party scripts\n * that provide no actionable information.\n */\nconst NOISE_PATTERNS: RegExp[] = [\n // ResizeObserver loop errors are benign and happen in many apps\n /ResizeObserver loop/i,\n // \"Script error.\" with no useful info (cross-origin scripts without CORS headers)\n /^Script error\\.?$/i,\n // Browser extension errors\n /chrome-extension:\\/\\//i,\n /moz-extension:\\/\\//i,\n /safari-extension:\\/\\//i,\n /safari-web-extension:\\/\\//i,\n // Edge extension errors\n /extension:\\/\\//i,\n];\n\n/**\n * Check if an error message matches any of the known noise patterns.\n */\nfunction isNoiseError(message: string): boolean {\n return NOISE_PATTERNS.some((pattern) => pattern.test(message));\n}\n\n/**\n * Check if an error matches any user-defined ignoreErrors patterns.\n */\nfunction isIgnoredByConfig(\n message: string,\n ignoreErrors?: Array<string | RegExp>\n): boolean {\n if (!ignoreErrors || ignoreErrors.length === 0) {\n return false;\n }\n\n return ignoreErrors.some((pattern) => {\n if (typeof pattern === 'string') {\n return message.includes(pattern);\n }\n return pattern.test(message);\n });\n}\n\n/**\n * Normalize a promise rejection reason into a proper Error object.\n */\nfunction normalizeRejectionReason(reason: unknown): Error {\n if (reason instanceof Error) {\n return reason;\n }\n\n if (typeof reason === 'string') {\n return new Error(reason);\n }\n\n if (reason !== null && reason !== undefined) {\n try {\n return new Error(JSON.stringify(reason));\n } catch {\n return new Error(String(reason));\n }\n }\n\n return new Error('Unhandled promise rejection with no reason');\n}\n\n/**\n * Set up global error handlers to capture uncaught exceptions and\n * unhandled promise rejections.\n *\n * @param client - The UncaughtClient instance to report errors to.\n * @returns A cleanup function that removes the event listeners.\n */\nexport function setupGlobalHandlers(client: UncaughtClient): () => void {\n // Guard for SSR environments\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const config = client.getConfig?.() ?? {};\n const ignoreErrors = (config as Record<string, unknown>)\n .ignoreErrors as Array<string | RegExp> | undefined;\n\n /**\n * Handle uncaught exceptions via window.onerror / 'error' event.\n */\n const handleError = (event: ErrorEvent): void => {\n try {\n const { error, message, filename } = event;\n\n // \"Script error.\" with no stack and no filename is cross-origin noise\n if (\n !error &&\n (!message || message === 'Script error.') &&\n !filename\n ) {\n return;\n }\n\n const errorMessage =\n error?.message ?? message ?? 'Unknown error';\n\n // Filter out noise errors\n if (isNoiseError(errorMessage)) {\n return;\n }\n\n // Filter out user-configured ignored errors\n if (isIgnoredByConfig(errorMessage, ignoreErrors)) {\n return;\n }\n\n // Build the error object\n const errorObj =\n error instanceof Error ? error : new Error(errorMessage);\n\n client.captureError(errorObj, {\n tags: { source: 'window.onerror' },\n extra: {\n filename: filename ?? undefined,\n lineno: event.lineno ?? undefined,\n colno: event.colno ?? undefined,\n },\n });\n\n // Do NOT call event.preventDefault() - let the browser still log the error\n } catch (e) {\n // Never crash the host app from our error handler\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Error in global error handler:', e);\n }\n }\n };\n\n /**\n * Handle unhandled promise rejections.\n */\n const handleRejection = (event: PromiseRejectionEvent): void => {\n try {\n const error = normalizeRejectionReason(event.reason);\n const errorMessage = error.message;\n\n // Filter out noise errors\n if (isNoiseError(errorMessage)) {\n return;\n }\n\n // Filter out user-configured ignored errors\n if (isIgnoredByConfig(errorMessage, ignoreErrors)) {\n return;\n }\n\n client.captureError(error, {\n tags: {\n source: 'unhandledrejection',\n unhandled: 'true',\n },\n });\n\n // Do NOT call event.preventDefault() - let the browser still log\n } catch (e) {\n // Never crash the host app from our error handler\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Error in unhandled rejection handler:',\n e\n );\n }\n }\n };\n\n window.addEventListener('error', handleError);\n window.addEventListener('unhandledrejection', handleRejection);\n\n // Return cleanup function\n return () => {\n window.removeEventListener('error', handleError);\n window.removeEventListener('unhandledrejection', handleRejection);\n };\n}\n","import type { UncaughtClient } from '@uncaughtdev/core';\n\n/**\n * Maximum length for breadcrumb messages to avoid excessively large payloads.\n */\nconst MAX_MESSAGE_LENGTH = 200;\n\n/**\n * Truncate a string to a maximum length, appending \"...\" if truncated.\n */\nfunction truncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n return str.slice(0, maxLen - 3) + '...';\n}\n\n/**\n * Extract a human-readable description of a clicked element.\n */\nfunction describeElement(element: HTMLElement): string {\n const tag = element.tagName?.toLowerCase() ?? 'unknown';\n const type =\n tag === 'input'\n ? (element as HTMLInputElement).type?.toLowerCase()\n : undefined;\n\n // Don't record anything from password inputs\n if (type === 'password') {\n return 'password input';\n }\n\n // Determine element role for description\n let role: string;\n if (tag === 'button' || element.getAttribute('role') === 'button') {\n role = 'button';\n } else if (tag === 'a') {\n role = 'link';\n } else if (tag === 'input') {\n role = `${type ?? 'text'} input`;\n } else if (tag === 'select') {\n role = 'dropdown';\n } else if (tag === 'textarea') {\n role = 'textarea';\n } else {\n role = tag;\n }\n\n // Get meaningful text content\n let text: string | null = null;\n\n // aria-label is highest priority for meaningful text\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel) {\n text = ariaLabel;\n }\n // For buttons and links, try innerText\n else if (tag === 'button' || tag === 'a') {\n const innerText = element.innerText?.trim();\n if (innerText) {\n text = innerText.split('\\n')[0]; // First line only\n }\n }\n // For inputs, use placeholder or name\n else if (tag === 'input' || tag === 'textarea') {\n const placeholder = (element as HTMLInputElement).placeholder;\n const name = element.getAttribute('name');\n text = placeholder || name || null;\n }\n\n // Build description\n const id = element.id ? `#${element.id}` : '';\n const textPart = text ? ` '${truncate(text, 50)}'` : '';\n\n return `Clicked${textPart} ${role}${id}`;\n}\n\n/**\n * Set up click tracking as breadcrumbs.\n * Uses capture phase to intercept clicks before they may be stopped.\n */\nfunction setupClickTracking(client: UncaughtClient): () => void {\n const handleClick = (event: MouseEvent): void => {\n try {\n const target = event.target as HTMLElement | null;\n if (!target || !target.tagName) return;\n\n // Don't record clicks on password inputs\n if (\n target.tagName.toLowerCase() === 'input' &&\n (target as HTMLInputElement).type?.toLowerCase() === 'password'\n ) {\n return;\n }\n\n const message = describeElement(target);\n\n client.addBreadcrumb({\n timestamp: new Date().toISOString(),\n type: 'click',\n category: 'ui.click',\n message: truncate(message, MAX_MESSAGE_LENGTH),\n level: 'info',\n data: {\n tag: target.tagName.toLowerCase(),\n id: target.id || undefined,\n className:\n typeof target.className === 'string'\n ? truncate(target.className, 100)\n : undefined,\n },\n });\n } catch {\n // Silently ignore - never crash the host app\n }\n };\n\n document.addEventListener('click', handleClick, true); // capture phase\n return () => document.removeEventListener('click', handleClick, true);\n}\n\n/**\n * Set up navigation tracking as breadcrumbs.\n * Tracks popstate events and monkey-patches history.pushState / replaceState.\n */\nfunction setupNavigationTracking(client: UncaughtClient): () => void {\n let currentUrl = window.location.href;\n\n const recordNavigation = (to: string): void => {\n try {\n const from = currentUrl;\n currentUrl = to;\n\n client.addBreadcrumb({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Navigated to ${to}`,\n level: 'info',\n data: {\n from,\n to,\n },\n });\n } catch {\n // Silently ignore\n }\n };\n\n // popstate fires on back/forward\n const handlePopState = (): void => {\n recordNavigation(window.location.href);\n };\n\n window.addEventListener('popstate', handlePopState);\n\n // Monkey-patch pushState and replaceState\n const originalPushState = history.pushState.bind(history);\n const originalReplaceState = history.replaceState.bind(history);\n\n history.pushState = function (\n data: unknown,\n unused: string,\n url?: string | URL | null\n ): void {\n originalPushState(data, unused, url);\n if (url) {\n try {\n const resolvedUrl = new URL(\n String(url),\n window.location.href\n ).href;\n recordNavigation(resolvedUrl);\n } catch {\n recordNavigation(String(url));\n }\n }\n };\n\n history.replaceState = function (\n data: unknown,\n unused: string,\n url?: string | URL | null\n ): void {\n originalReplaceState(data, unused, url);\n if (url) {\n try {\n const resolvedUrl = new URL(\n String(url),\n window.location.href\n ).href;\n recordNavigation(resolvedUrl);\n } catch {\n recordNavigation(String(url));\n }\n }\n };\n\n return () => {\n window.removeEventListener('popstate', handlePopState);\n history.pushState = originalPushState;\n history.replaceState = originalReplaceState;\n };\n}\n\n/**\n * Set up fetch tracking as breadcrumbs.\n * Monkey-patches window.fetch to record API calls with method, URL, status, and duration.\n * Does NOT record request/response bodies. Skips requests to the Uncaught API.\n */\nfunction setupFetchTracking(client: UncaughtClient): () => void {\n const originalFetch = window.fetch.bind(window);\n\n // Get the Uncaught API endpoint to exclude self-reporting requests\n const config = client.getConfig?.() ?? {};\n const apiEndpoint =\n (config as Record<string, unknown>).endpoint ??\n (config as Record<string, unknown>).dsn ??\n '';\n const uncaughtEndpoints: string[] = [];\n\n if (typeof apiEndpoint === 'string' && apiEndpoint) {\n try {\n const url = new URL(apiEndpoint);\n uncaughtEndpoints.push(url.hostname);\n } catch {\n uncaughtEndpoints.push(apiEndpoint);\n }\n }\n\n // Also exclude common Uncaught API patterns\n uncaughtEndpoints.push('uncaught.dev');\n uncaughtEndpoints.push('api.uncaught');\n\n const isUncaughtRequest = (url: string): boolean => {\n return uncaughtEndpoints.some(\n (endpoint) => endpoint && url.includes(endpoint)\n );\n };\n\n window.fetch = async function (\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n const url =\n input instanceof Request\n ? input.url\n : input instanceof URL\n ? input.href\n : String(input);\n\n const method = (\n init?.method ??\n (input instanceof Request ? input.method : 'GET')\n ).toUpperCase();\n\n // Skip Uncaught's own requests to prevent infinite loops\n if (isUncaughtRequest(url)) {\n return originalFetch(input, init);\n }\n\n const startTime = Date.now();\n\n try {\n const response = await originalFetch(input, init);\n const duration = Date.now() - startTime;\n const isError = response.status >= 400;\n\n try {\n // Truncate URL for the breadcrumb to avoid huge payloads\n const displayUrl = truncate(url, 150);\n\n client.addBreadcrumb({\n timestamp: new Date().toISOString(),\n type: 'api_call',\n category: 'fetch',\n message: `${method} ${displayUrl} [${response.status}]`,\n level: isError ? 'error' : 'info',\n data: {\n method,\n url: displayUrl,\n status: response.status,\n statusText: response.statusText,\n duration,\n },\n });\n } catch {\n // Silently ignore breadcrumb failures\n }\n\n return response;\n } catch (error) {\n const duration = Date.now() - startTime;\n\n try {\n const displayUrl = truncate(url, 150);\n\n client.addBreadcrumb({\n timestamp: new Date().toISOString(),\n type: 'api_call',\n category: 'fetch',\n message: `${method} ${displayUrl} [Network Error]`,\n level: 'error',\n data: {\n method,\n url: displayUrl,\n status: 0,\n error:\n error instanceof Error\n ? error.message\n : 'Network error',\n duration,\n },\n });\n } catch {\n // Silently ignore breadcrumb failures\n }\n\n throw error; // Re-throw so the app's error handling still works\n }\n };\n\n return () => {\n window.fetch = originalFetch;\n };\n}\n\n/**\n * Set up automatic DOM breadcrumb tracking including clicks,\n * navigation changes, and fetch API calls.\n *\n * @param client - The UncaughtClient instance to add breadcrumbs to.\n * @returns A cleanup function that removes all listeners and restores patched functions.\n */\nexport function setupDomBreadcrumbs(client: UncaughtClient): () => void {\n // Guard for SSR environments\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const cleanups: Array<() => void> = [];\n\n try {\n cleanups.push(setupClickTracking(client));\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Failed to set up click tracking:', e);\n }\n }\n\n try {\n cleanups.push(setupNavigationTracking(client));\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Failed to set up navigation tracking:',\n e\n );\n }\n }\n\n try {\n cleanups.push(setupFetchTracking(client));\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Failed to set up fetch tracking:', e);\n }\n }\n\n return () => {\n cleanups.forEach((cleanup) => {\n try {\n cleanup();\n } catch {\n // Silently ignore cleanup failures\n }\n });\n };\n}\n","import type { UncaughtClient, UncaughtConfig } from '@uncaughtdev/core';\n\n/**\n * Augmented Window interface to access Next.js internals.\n * These are undocumented but stable properties Next.js sets on the window.\n */\ninterface NextWindow extends Window {\n /** Present in Pages Router - contains build-time page data */\n __NEXT_DATA__?: {\n page?: string;\n query?: Record<string, unknown>;\n buildId?: string;\n props?: Record<string, unknown>;\n };\n /** Present in App Router - contains flight response data */\n __next_f?: unknown[];\n /** Next.js router instance (Pages Router) */\n next?: {\n router?: {\n events?: {\n on: (event: string, handler: (...args: unknown[]) => void) => void;\n off: (event: string, handler: (...args: unknown[]) => void) => void;\n };\n };\n };\n}\n\n/**\n * Result of Next.js environment detection.\n */\nexport interface NextJsDetection {\n /** Whether the app appears to be running in a Next.js context */\n isNextJs: boolean;\n /** Whether the App Router is detected */\n isAppRouter: boolean;\n /** Whether the Pages Router is detected */\n isPagesRouter: boolean;\n}\n\n/**\n * Detect if the current environment is a Next.js application,\n * and which router (App Router vs Pages Router) is being used.\n *\n * This detection is best-effort and relies on undocumented\n * but stable Next.js window properties.\n *\n * @returns Detection result with router type information.\n */\nexport function detectNextJs(): NextJsDetection {\n if (typeof window === 'undefined') {\n return {\n isNextJs: false,\n isAppRouter: false,\n isPagesRouter: false,\n };\n }\n\n const win = window as NextWindow;\n\n const hasPagesData = win.__NEXT_DATA__ !== undefined;\n const hasAppRouterData = win.__next_f !== undefined;\n\n // Check for Next.js meta tag as an additional signal\n let hasNextMeta = false;\n try {\n const nextMeta = document.querySelector('meta[name=\"next-size-adjust\"]');\n hasNextMeta = nextMeta !== null;\n } catch {\n // Ignore DOM query errors\n }\n\n const isPagesRouter = hasPagesData && !hasAppRouterData;\n const isAppRouter = hasAppRouterData;\n const isNextJs = hasPagesData || hasAppRouterData || hasNextMeta;\n\n return {\n isNextJs,\n isAppRouter,\n isPagesRouter,\n };\n}\n\n/**\n * Set up navigation tracking specifically for Next.js routing.\n *\n * For the Pages Router, hooks into Next.js router events (routeChangeStart,\n * routeChangeComplete, routeChangeError).\n *\n * For the App Router, navigation is tracked via the general DOM breadcrumbs\n * (history.pushState monkey-patch), so this function primarily adds\n * Next.js-specific context.\n *\n * @param client - The UncaughtClient instance.\n * @returns A cleanup function that removes the event listeners.\n */\nexport function setupNextJsNavigation(client: UncaughtClient): () => void {\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const detection = detectNextJs();\n const cleanups: Array<() => void> = [];\n\n // Add Next.js context to the client\n try {\n client.addBreadcrumb({\n\n type: 'navigation',\n category: 'nextjs',\n message: `Next.js detected: ${\n detection.isAppRouter\n ? 'App Router'\n : detection.isPagesRouter\n ? 'Pages Router'\n : 'Unknown Router'\n }`,\n level: 'info',\n data: {\n isAppRouter: detection.isAppRouter,\n isPagesRouter: detection.isPagesRouter,\n },\n });\n } catch {\n // Silently ignore\n }\n\n // Pages Router: hook into router events\n if (detection.isPagesRouter) {\n try {\n const win = window as NextWindow;\n const routerEvents = win.next?.router?.events;\n\n if (routerEvents) {\n let navigationStartTime = 0;\n\n const handleRouteChangeStart = (url: unknown): void => {\n try {\n navigationStartTime = Date.now();\n client.addBreadcrumb({\n \n type: 'navigation',\n category: 'nextjs.route',\n message: `Route change started: ${String(url)}`,\n level: 'info',\n data: {\n to: String(url),\n },\n });\n } catch {\n // Silently ignore\n }\n };\n\n const handleRouteChangeComplete = (url: unknown): void => {\n try {\n const duration =\n navigationStartTime > 0\n ? Date.now() - navigationStartTime\n : undefined;\n\n client.addBreadcrumb({\n \n type: 'navigation',\n category: 'nextjs.route',\n message: `Route change completed: ${String(url)}`,\n level: 'info',\n data: {\n to: String(url),\n duration,\n },\n });\n } catch {\n // Silently ignore\n }\n };\n\n const handleRouteChangeError = (\n err: unknown,\n url: unknown\n ): void => {\n try {\n const duration =\n navigationStartTime > 0\n ? Date.now() - navigationStartTime\n : undefined;\n\n client.addBreadcrumb({\n \n type: 'navigation',\n category: 'nextjs.route',\n message: `Route change error: ${String(url)}`,\n level: 'error',\n data: {\n to: String(url),\n error:\n err instanceof Error\n ? err.message\n : String(err),\n duration,\n },\n });\n } catch {\n // Silently ignore\n }\n };\n\n routerEvents.on('routeChangeStart', handleRouteChangeStart);\n routerEvents.on(\n 'routeChangeComplete',\n handleRouteChangeComplete\n );\n routerEvents.on('routeChangeError', handleRouteChangeError);\n\n cleanups.push(() => {\n try {\n routerEvents.off(\n 'routeChangeStart',\n handleRouteChangeStart\n );\n routerEvents.off(\n 'routeChangeComplete',\n handleRouteChangeComplete\n );\n routerEvents.off(\n 'routeChangeError',\n handleRouteChangeError\n );\n } catch {\n // Silently ignore\n }\n });\n }\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Failed to set up Next.js Pages Router navigation:',\n e\n );\n }\n }\n }\n\n return () => {\n cleanups.forEach((cleanup) => {\n try {\n cleanup();\n } catch {\n // Silently ignore cleanup failures\n }\n });\n };\n}\n\n/**\n * Higher-order function for wrapping Next.js App Router layouts.\n *\n * Returns the configuration object needed to initialize UncaughtProvider\n * with Next.js-specific defaults applied.\n *\n * Usage in layout.tsx:\n * ```tsx\n * import { UncaughtProvider } from '@uncaughtdev/react';\n * import { withUncaught } from '@uncaughtdev/react';\n *\n * const uncaughtConfig = withUncaught({\n * dsn: 'your-dsn-here',\n * environment: 'production',\n * });\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html>\n * <body>\n * <UncaughtProvider {...uncaughtConfig}>\n * {children}\n * </UncaughtProvider>\n * </body>\n * </html>\n * );\n * }\n * ```\n *\n * @param config - Base UncaughtConfig to extend with Next.js defaults.\n * @returns Configuration object with Next.js-specific settings applied.\n */\nexport function withUncaught(\n config: UncaughtConfig\n): UncaughtConfig & { __nextjs: boolean } {\n return {\n ...config,\n __nextjs: true,\n };\n}\n","'use client';\n\nimport React, { useEffect, useRef, useState } from 'react';\nimport { initUncaught } from '@uncaughtdev/core';\nimport type { UncaughtClient } from '@uncaughtdev/core';\nimport { UncaughtContext } from './context';\nimport { UncaughtErrorBoundary } from './error-boundary';\nimport { setupGlobalHandlers } from './global-handlers';\nimport { setupDomBreadcrumbs } from './dom-breadcrumbs';\nimport { setupNextJsNavigation, detectNextJs } from './next-integration';\nimport type { UncaughtProviderProps } from './types';\n\n/**\n * UncaughtProvider initializes the Uncaught error monitoring client and\n * provides it to all descendant components via React context.\n *\n * It automatically:\n * - Initializes the UncaughtClient with the provided configuration\n * - Sets up global error handlers (window.onerror, unhandledrejection)\n * - Sets up DOM breadcrumb tracking (clicks, navigation, fetch)\n * - Detects and integrates with Next.js routing if present\n * - Wraps children in an error boundary\n * - Cleans up all listeners on unmount\n *\n * Usage:\n * ```tsx\n * <UncaughtProvider dsn=\"your-dsn\" environment=\"production\">\n * <App />\n * </UncaughtProvider>\n * ```\n *\n * @param props - Configuration props extending UncaughtConfig plus children, fallback, and showDialog.\n */\nexport function UncaughtProvider({\n children,\n fallback,\n showDialog,\n ...config\n}: UncaughtProviderProps): React.ReactElement {\n const [client, setClient] = useState<UncaughtClient | null>(null);\n const cleanupRef = useRef<Array<() => void>>([]);\n const initializedRef = useRef(false);\n\n useEffect(() => {\n // Prevent double-initialization in React StrictMode\n if (initializedRef.current) {\n return;\n }\n initializedRef.current = true;\n\n let mounted = true;\n const cleanups: Array<() => void> = [];\n\n try {\n // Strip React-specific props before passing to core\n const { __nextjs, ...coreConfig } = config as Record<string, unknown> & {\n __nextjs?: boolean;\n };\n\n // Initialize the core client\n const uncaughtClient = initUncaught(\n coreConfig as Parameters<typeof initUncaught>[0]\n );\n\n if (!uncaughtClient) {\n if (process.env.NODE_ENV === 'development') {\n console.warn(\n '[Uncaught] initUncaught returned null/undefined. Error monitoring is disabled.'\n );\n }\n return;\n }\n\n // Set up global error handlers\n try {\n const cleanupGlobal = setupGlobalHandlers(uncaughtClient);\n cleanups.push(cleanupGlobal);\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Failed to set up global handlers:',\n e\n );\n }\n }\n\n // Set up DOM breadcrumbs\n try {\n const cleanupDom = setupDomBreadcrumbs(uncaughtClient);\n cleanups.push(cleanupDom);\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Failed to set up DOM breadcrumbs:',\n e\n );\n }\n }\n\n // Set up Next.js integration if detected or explicitly configured\n if (typeof window !== 'undefined') {\n try {\n const nextDetection = detectNextJs();\n if (nextDetection.isNextJs || __nextjs) {\n const cleanupNext = setupNextJsNavigation(uncaughtClient);\n cleanups.push(cleanupNext);\n }\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n '[Uncaught] Failed to set up Next.js integration:',\n e\n );\n }\n }\n }\n\n // Store cleanups for unmount\n cleanupRef.current = cleanups;\n\n // Only update state if still mounted\n if (mounted) {\n setClient(uncaughtClient);\n }\n } catch (e) {\n // Never crash the host app during initialization\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Failed to initialize:', e);\n }\n }\n\n return () => {\n mounted = false;\n // Run all cleanup functions\n cleanupRef.current.forEach((cleanup) => {\n try {\n cleanup();\n } catch {\n // Silently ignore cleanup failures\n }\n });\n cleanupRef.current = [];\n initializedRef.current = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []); // Initialize once on mount - config changes require remounting\n\n const contextValue = React.useMemo(() => ({ client }), [client]);\n\n return (\n <UncaughtContext.Provider value={contextValue}>\n <UncaughtErrorBoundary fallback={fallback} showDialog={showDialog}>\n {children}\n </UncaughtErrorBoundary>\n </UncaughtContext.Provider>\n );\n}\n","'use client';\n\nimport { useContext, useCallback } from 'react';\nimport type { UncaughtClient, Breadcrumb } from '@uncaughtdev/core';\nimport { UncaughtContext } from './context';\n\n/**\n * Returns the UncaughtClient instance from context.\n * Must be called within an UncaughtProvider.\n *\n * @throws {Error} If called outside of an UncaughtProvider.\n * @returns The UncaughtClient instance.\n */\nexport function useUncaught(): UncaughtClient {\n const { client } = useContext(UncaughtContext);\n\n if (!client) {\n throw new Error(\n 'useUncaught must be used within an <UncaughtProvider>. ' +\n 'Wrap your application in <UncaughtProvider> to use this hook.'\n );\n }\n\n return client;\n}\n\n/**\n * Returns a function that reports an error to Uncaught.\n * Safe to call even if the client is not yet initialized (will silently no-op).\n *\n * @returns A function `(error: Error, context?: Record<string, unknown>) => void`\n */\nexport function useReportError(): (\n error: Error,\n context?: Record<string, unknown>\n) => void {\n const { client } = useContext(UncaughtContext);\n\n return useCallback(\n (error: Error, context?: Record<string, unknown>) => {\n try {\n if (!client) {\n if (process.env.NODE_ENV === 'development') {\n console.warn(\n '[Uncaught] useReportError called but no UncaughtClient is available. ' +\n 'Make sure <UncaughtProvider> is mounted.'\n );\n }\n return;\n }\n\n client.captureError(error);\n } catch (e) {\n // Never crash the host app\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Failed to report error:', e);\n }\n }\n },\n [client]\n );\n}\n\n/**\n * Returns a function that adds a breadcrumb to the current Uncaught session.\n * Safe to call even if the client is not yet initialized (will silently no-op).\n *\n * @returns A function `(breadcrumb: Partial<Breadcrumb>) => void`\n */\nexport function useBreadcrumb(): (breadcrumb: Partial<Breadcrumb>) => void {\n const { client } = useContext(UncaughtContext);\n\n return useCallback(\n (breadcrumb: Partial<Breadcrumb>) => {\n try {\n if (!client) {\n if (process.env.NODE_ENV === 'development') {\n console.warn(\n '[Uncaught] useBreadcrumb called but no UncaughtClient is available. ' +\n 'Make sure <UncaughtProvider> is mounted.'\n );\n }\n return;\n }\n\n client.addBreadcrumb({\n type: breadcrumb.type ?? 'custom',\n category: breadcrumb.category ?? 'custom',\n message: breadcrumb.message ?? '',\n level: breadcrumb.level ?? 'info',\n data: breadcrumb.data,\n });\n } catch (e) {\n // Never crash the host app\n if (process.env.NODE_ENV === 'development') {\n console.error('[Uncaught] Failed to add breadcrumb:', e);\n }\n }\n },\n [client]\n );\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@uncaughtdev/react",
3
+ "version": "0.1.0",
4
+ "description": "React and Next.js SDK for Uncaught error monitoring",
5
+ "license": "MIT",
6
+ "author": "Uncaught",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/AjeeshDevops/uncaught.git",
10
+ "directory": "packages/react"
11
+ },
12
+ "homepage": "https://github.com/AjeeshDevops/uncaught#readme",
13
+ "keywords": [
14
+ "react",
15
+ "error-boundary",
16
+ "error-monitoring",
17
+ "nextjs",
18
+ "debugging",
19
+ "vibe-coding"
20
+ ],
21
+ "main": "./dist/index.js",
22
+ "module": "./dist/index.mjs",
23
+ "types": "./dist/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "import": "./dist/index.mjs",
28
+ "require": "./dist/index.js"
29
+ }
30
+ },
31
+ "sideEffects": false,
32
+ "files": [
33
+ "dist"
34
+ ],
35
+ "peerDependencies": {
36
+ "react": ">=17.0.0",
37
+ "react-dom": ">=17.0.0",
38
+ "@uncaughtdev/core": "0.1.0"
39
+ },
40
+ "dependencies": {
41
+ "@uncaughtdev/core": "0.1.0"
42
+ },
43
+ "devDependencies": {
44
+ "react": "^18.3.0",
45
+ "react-dom": "^18.3.0",
46
+ "@types/react": "^18.3.0",
47
+ "tsup": "^8.0.0",
48
+ "typescript": "^5.4.0",
49
+ "vitest": "^1.6.0",
50
+ "@testing-library/react": "^15.0.0"
51
+ },
52
+ "scripts": {
53
+ "build": "tsup",
54
+ "dev": "tsup --watch",
55
+ "test": "vitest run",
56
+ "lint": "eslint src/",
57
+ "typecheck": "tsc --noEmit",
58
+ "clean": "rm -rf dist"
59
+ }
60
+ }