@bugwatch/react 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,6 @@ var react = require('react');
|
|
|
4
4
|
var core = require('@bugwatch/core');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
|
|
7
|
-
// src/index.tsx
|
|
8
7
|
var DEFAULT_REACT_OPTIONS = {
|
|
9
8
|
captureGlobalErrors: true,
|
|
10
9
|
captureUnhandledRejections: true,
|
|
@@ -32,9 +31,16 @@ function BugwatchProvider({
|
|
|
32
31
|
fallback,
|
|
33
32
|
onError
|
|
34
33
|
}) {
|
|
34
|
+
const optionsKey = react.useMemo(
|
|
35
|
+
() => options ? JSON.stringify(options) : "",
|
|
36
|
+
[options]
|
|
37
|
+
);
|
|
38
|
+
const optionsRef = react.useRef(options);
|
|
39
|
+
optionsRef.current = options;
|
|
35
40
|
react.useEffect(() => {
|
|
41
|
+
const currentOptions = optionsRef.current;
|
|
36
42
|
const envConfig = core.getEnvConfig();
|
|
37
|
-
const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...
|
|
43
|
+
const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...currentOptions };
|
|
38
44
|
if (!mergedOptions.apiKey) {
|
|
39
45
|
if (process.env.NODE_ENV === "development") {
|
|
40
46
|
console.warn("[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey");
|
|
@@ -108,7 +114,7 @@ function BugwatchProvider({
|
|
|
108
114
|
}
|
|
109
115
|
}
|
|
110
116
|
};
|
|
111
|
-
}, [
|
|
117
|
+
}, [optionsKey]);
|
|
112
118
|
const captureException2 = react.useCallback(
|
|
113
119
|
(error, context) => {
|
|
114
120
|
return core.captureException(error, context);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx"],"names":["createContext","useContext","captureException","captureMessage","useEffect","getEnvConfig","coreInit","getClient","coreCaptureException","coreAddBreadcrumb","useCallback","coreCaptureMessage","addBreadcrumb","setUser","coreSetUser","setTag","coreSetTag","setExtra","coreSetExtra","useMemo","jsx","Component","jsxs"],"mappings":"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","file":"index.js","sourcesContent":["import React, {\n Component,\n createContext,\n useContext,\n useEffect,\n useCallback,\n useMemo,\n type ReactNode,\n type ErrorInfo,\n} from \"react\";\nimport {\n init as coreInit,\n getClient,\n getEnvConfig,\n captureException as coreCaptureException,\n captureMessage as coreCaptureMessage,\n addBreadcrumb as coreAddBreadcrumb,\n setUser as coreSetUser,\n setTag as coreSetTag,\n setExtra as coreSetExtra,\n type BugwatchOptions,\n type BugwatchClient,\n type UserContext,\n type Breadcrumb,\n type ErrorEvent,\n} from \"@bugwatch/core\";\n\n// Re-export types\nexport type { BugwatchOptions, UserContext, ErrorEvent, Breadcrumb } from \"@bugwatch/core\";\n\n/**\n * React-specific SDK options\n */\nexport interface ReactOptions extends BugwatchOptions {\n /** Capture window.onerror events */\n captureGlobalErrors?: boolean;\n /** Capture unhandled promise rejections */\n captureUnhandledRejections?: boolean;\n /** Capture console.error as breadcrumbs */\n captureConsoleBreadcrumbs?: boolean;\n}\n\nconst DEFAULT_REACT_OPTIONS: Partial<ReactOptions> = {\n captureGlobalErrors: true,\n captureUnhandledRejections: true,\n captureConsoleBreadcrumbs: true,\n};\n\n/**\n * Bugwatch context\n */\ninterface BugwatchContextValue {\n client: BugwatchClient | null;\n captureException: (error: Error, context?: Partial<ErrorEvent>) => string;\n captureMessage: (message: string, level?: ErrorEvent[\"level\"]) => string;\n addBreadcrumb: (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => void;\n setUser: (user: UserContext | null) => void;\n setTag: (key: string, value: string) => void;\n setExtra: (key: string, value: unknown) => void;\n}\n\nconst BugwatchContext = createContext<BugwatchContextValue | null>(null);\n\n/**\n * Hook to access Bugwatch SDK\n */\nexport function useBugwatch(): BugwatchContextValue {\n const context = useContext(BugwatchContext);\n if (!context) {\n throw new Error(\"useBugwatch must be used within a BugwatchProvider\");\n }\n return context;\n}\n\n/**\n * Hook to capture exceptions\n */\nexport function useCaptureException(): (\n error: Error,\n context?: Partial<ErrorEvent>\n) => string {\n const { captureException } = useBugwatch();\n return captureException;\n}\n\n/**\n * Hook to capture messages\n */\nexport function useCaptureMessage(): (\n message: string,\n level?: ErrorEvent[\"level\"]\n) => string {\n const { captureMessage } = useBugwatch();\n return captureMessage;\n}\n\n/**\n * Props for BugwatchProvider\n */\ninterface BugwatchProviderProps {\n /**\n * SDK configuration options.\n * Optional - if not provided, reads from environment variables:\n * - `BUGWATCH_API_KEY` - API key (required unless passed explicitly)\n * - `BUGWATCH_ENVIRONMENT` - Environment tag\n * - `BUGWATCH_RELEASE` - Release version\n * - `BUGWATCH_DEBUG` - Enable debug mode ('true')\n */\n options?: ReactOptions;\n /** Child components */\n children: ReactNode;\n /** Optional fallback UI for error boundary */\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Called when an error is caught by the error boundary */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\n/**\n * Bugwatch Provider component\n * Initializes the SDK and provides context to child components\n *\n * @example\n * ```tsx\n * // With BUGWATCH_API_KEY env var set\n * <BugwatchProvider>\n * <App />\n * </BugwatchProvider>\n *\n * // With explicit options\n * <BugwatchProvider options={{ apiKey: \"bw_live_xxxxx\" }}>\n * <App />\n * </BugwatchProvider>\n * ```\n */\nexport function BugwatchProvider({\n options,\n children,\n fallback,\n onError,\n}: BugwatchProviderProps): JSX.Element {\n useEffect(() => {\n // Merge env config with explicit options (explicit takes precedence)\n const envConfig = getEnvConfig();\n const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...options };\n\n // Skip initialization if no API key is available\n if (!mergedOptions.apiKey) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey');\n }\n return;\n }\n\n // Wrap initialization in try-catch for graceful degradation\n try {\n coreInit(mergedOptions);\n } catch (err) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Bugwatch] Initialization failed:', err);\n }\n return;\n }\n\n // Add React-specific tags\n const client = getClient();\n if (client) {\n client.setTag(\"framework\", \"react\");\n }\n\n // Store original handlers for cleanup\n let originalOnError: typeof window.onerror | null = null;\n let originalConsoleError: typeof console.error | null = null;\n let unhandledRejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;\n\n // Set up global error handlers\n if (typeof window !== \"undefined\") {\n if (mergedOptions.captureGlobalErrors) {\n originalOnError = window.onerror;\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n coreCaptureException(error, {\n tags: { mechanism: \"window.onerror\" },\n });\n }\n if (originalOnError) {\n return originalOnError(message, source, lineno, colno, error);\n }\n return false;\n };\n }\n\n if (mergedOptions.captureUnhandledRejections) {\n unhandledRejectionHandler = (event: PromiseRejectionEvent) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n coreCaptureException(error, {\n tags: { mechanism: \"unhandledrejection\" },\n });\n };\n window.addEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n if (mergedOptions.captureConsoleBreadcrumbs) {\n originalConsoleError = console.error;\n console.error = (...args: unknown[]) => {\n coreAddBreadcrumb({\n category: \"console\",\n message: args.map(String).join(\" \"),\n level: \"error\",\n });\n originalConsoleError!(...args);\n };\n }\n }\n\n if (mergedOptions.debug) {\n console.log(\"[Bugwatch] React SDK initialized\");\n }\n\n // Cleanup function to prevent memory leaks\n return () => {\n if (typeof window !== \"undefined\") {\n // Restore original window.onerror\n if (originalOnError !== null && mergedOptions.captureGlobalErrors) {\n window.onerror = originalOnError;\n }\n\n // Remove unhandled rejection listener\n if (unhandledRejectionHandler && mergedOptions.captureUnhandledRejections) {\n window.removeEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n // Restore original console.error\n if (originalConsoleError !== null && mergedOptions.captureConsoleBreadcrumbs) {\n console.error = originalConsoleError;\n }\n }\n };\n }, [options]);\n\n const captureException = useCallback(\n (error: Error, context?: Partial<ErrorEvent>) => {\n return coreCaptureException(error, context);\n },\n []\n );\n\n const captureMessage = useCallback(\n (message: string, level?: ErrorEvent[\"level\"]) => {\n return coreCaptureMessage(message, level);\n },\n []\n );\n\n const addBreadcrumb = useCallback(\n (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => {\n coreAddBreadcrumb(breadcrumb);\n },\n []\n );\n\n const setUser = useCallback((user: UserContext | null) => {\n coreSetUser(user);\n }, []);\n\n const setTag = useCallback((key: string, value: string) => {\n coreSetTag(key, value);\n }, []);\n\n const setExtra = useCallback((key: string, value: unknown) => {\n coreSetExtra(key, value);\n }, []);\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue = useMemo<BugwatchContextValue>(\n () => ({\n client: getClient(),\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n }),\n [captureException, captureMessage, addBreadcrumb, setUser, setTag, setExtra]\n );\n\n return (\n <BugwatchContext.Provider value={contextValue}>\n <ErrorBoundary fallback={fallback} onError={onError}>\n {children}\n </ErrorBoundary>\n </BugwatchContext.Provider>\n );\n}\n\n/**\n * Error Boundary Props\n */\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error Boundary component\n */\nclass ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n // Capture to Bugwatch\n coreCaptureException(error, {\n tags: { mechanism: \"react.errorBoundary\" },\n extra: {\n componentStack: errorInfo.componentStack,\n },\n });\n\n // Call custom handler\n this.props.onError?.(error, errorInfo);\n }\n\n reset = (): void => {\n this.setState({ hasError: false, error: null });\n };\n\n render(): ReactNode {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n\n if (typeof fallback === \"function\") {\n return fallback(this.state.error, this.reset);\n }\n\n if (fallback) {\n return fallback;\n }\n\n return (\n <div style={{ padding: \"20px\", fontFamily: \"sans-serif\" }}>\n <h2>Something went wrong</h2>\n <p>{this.state.error.message}</p>\n <button onClick={this.reset}>Try again</button>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\n/**\n * Standalone Error Boundary for custom use\n */\nexport { ErrorBoundary as BugwatchErrorBoundary };\n\n/**\n * Higher-order component for error boundary\n */\nexport function withBugwatchErrorBoundary<P extends object>(\n WrappedComponent: React.ComponentType<P>,\n options?: {\n fallback?: ErrorBoundaryProps[\"fallback\"];\n onError?: ErrorBoundaryProps[\"onError\"];\n }\n): React.ComponentType<P> {\n const WithErrorBoundary = (props: P) => (\n <ErrorBoundary fallback={options?.fallback} onError={options?.onError}>\n <WrappedComponent {...props} />\n </ErrorBoundary>\n );\n\n WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${\n WrappedComponent.displayName || WrappedComponent.name || \"Component\"\n })`;\n\n return WithErrorBoundary;\n}\n\n// Re-export core functions for convenience\nexport {\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n getClient,\n init,\n} from \"@bugwatch/core\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"names":["createContext","useContext","captureException","captureMessage","useMemo","useRef","useEffect","getEnvConfig","coreInit","getClient","coreCaptureException","coreAddBreadcrumb","useCallback","coreCaptureMessage","addBreadcrumb","setUser","coreSetUser","setTag","coreSetTag","setExtra","coreSetExtra","jsx","Component","jsxs"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\n\nimport React, {\n Component,\n createContext,\n useContext,\n useEffect,\n useCallback,\n useRef,\n useMemo,\n type ReactNode,\n type ErrorInfo,\n} from \"react\";\nimport {\n init as coreInit,\n getClient,\n getEnvConfig,\n captureException as coreCaptureException,\n captureMessage as coreCaptureMessage,\n addBreadcrumb as coreAddBreadcrumb,\n setUser as coreSetUser,\n setTag as coreSetTag,\n setExtra as coreSetExtra,\n type BugwatchOptions,\n type BugwatchClient,\n type UserContext,\n type Breadcrumb,\n type ErrorEvent,\n} from \"@bugwatch/core\";\n\n// Re-export types\nexport type { BugwatchOptions, UserContext, ErrorEvent, Breadcrumb } from \"@bugwatch/core\";\n\n/**\n * React-specific SDK options\n */\nexport interface ReactOptions extends BugwatchOptions {\n /** Capture window.onerror events */\n captureGlobalErrors?: boolean;\n /** Capture unhandled promise rejections */\n captureUnhandledRejections?: boolean;\n /** Capture console.error as breadcrumbs */\n captureConsoleBreadcrumbs?: boolean;\n}\n\nconst DEFAULT_REACT_OPTIONS: Partial<ReactOptions> = {\n captureGlobalErrors: true,\n captureUnhandledRejections: true,\n captureConsoleBreadcrumbs: true,\n};\n\n/**\n * Bugwatch context\n */\ninterface BugwatchContextValue {\n client: BugwatchClient | null;\n captureException: (error: Error, context?: Partial<ErrorEvent>) => string;\n captureMessage: (message: string, level?: ErrorEvent[\"level\"]) => string;\n addBreadcrumb: (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => void;\n setUser: (user: UserContext | null) => void;\n setTag: (key: string, value: string) => void;\n setExtra: (key: string, value: unknown) => void;\n}\n\nconst BugwatchContext = createContext<BugwatchContextValue | null>(null);\n\n/**\n * Hook to access Bugwatch SDK\n */\nexport function useBugwatch(): BugwatchContextValue {\n const context = useContext(BugwatchContext);\n if (!context) {\n throw new Error(\"useBugwatch must be used within a BugwatchProvider\");\n }\n return context;\n}\n\n/**\n * Hook to capture exceptions\n */\nexport function useCaptureException(): (\n error: Error,\n context?: Partial<ErrorEvent>\n) => string {\n const { captureException } = useBugwatch();\n return captureException;\n}\n\n/**\n * Hook to capture messages\n */\nexport function useCaptureMessage(): (\n message: string,\n level?: ErrorEvent[\"level\"]\n) => string {\n const { captureMessage } = useBugwatch();\n return captureMessage;\n}\n\n/**\n * Props for BugwatchProvider\n */\ninterface BugwatchProviderProps {\n /**\n * SDK configuration options.\n * Optional - if not provided, reads from environment variables:\n * - `BUGWATCH_API_KEY` - API key (required unless passed explicitly)\n * - `BUGWATCH_ENVIRONMENT` - Environment tag\n * - `BUGWATCH_RELEASE` - Release version\n * - `BUGWATCH_DEBUG` - Enable debug mode ('true')\n */\n options?: ReactOptions;\n /** Child components */\n children: ReactNode;\n /** Optional fallback UI for error boundary */\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Called when an error is caught by the error boundary */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\n/**\n * Bugwatch Provider component\n * Initializes the SDK and provides context to child components\n *\n * @example\n * ```tsx\n * // With BUGWATCH_API_KEY env var set\n * <BugwatchProvider>\n * <App />\n * </BugwatchProvider>\n *\n * // With explicit options\n * <BugwatchProvider options={{ apiKey: \"bw_live_xxxxx\" }}>\n * <App />\n * </BugwatchProvider>\n * ```\n */\nexport function BugwatchProvider({\n options,\n children,\n fallback,\n onError,\n}: BugwatchProviderProps): JSX.Element {\n // Serialize options to a stable string so useEffect doesn't re-run on every render.\n // Object identity of `options` changes every render if passed inline.\n const optionsKey = useMemo(\n () => (options ? JSON.stringify(options) : \"\"),\n [options]\n );\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n useEffect(() => {\n const currentOptions = optionsRef.current;\n\n // Merge env config with explicit options (explicit takes precedence)\n const envConfig = getEnvConfig();\n const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...currentOptions };\n\n // Skip initialization if no API key is available\n if (!mergedOptions.apiKey) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey');\n }\n return;\n }\n\n // Wrap initialization in try-catch for graceful degradation\n try {\n coreInit(mergedOptions);\n } catch (err) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Bugwatch] Initialization failed:', err);\n }\n return;\n }\n\n // Add React-specific tags\n const client = getClient();\n if (client) {\n client.setTag(\"framework\", \"react\");\n }\n\n // Store original handlers for cleanup\n let originalOnError: typeof window.onerror | null = null;\n let originalConsoleError: typeof console.error | null = null;\n let unhandledRejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;\n\n // Set up global error handlers\n if (typeof window !== \"undefined\") {\n if (mergedOptions.captureGlobalErrors) {\n originalOnError = window.onerror;\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n coreCaptureException(error, {\n tags: { mechanism: \"window.onerror\" },\n });\n }\n if (originalOnError) {\n return originalOnError(message, source, lineno, colno, error);\n }\n return false;\n };\n }\n\n if (mergedOptions.captureUnhandledRejections) {\n unhandledRejectionHandler = (event: PromiseRejectionEvent) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n coreCaptureException(error, {\n tags: { mechanism: \"unhandledrejection\" },\n });\n };\n window.addEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n if (mergedOptions.captureConsoleBreadcrumbs) {\n originalConsoleError = console.error;\n console.error = (...args: unknown[]) => {\n coreAddBreadcrumb({\n category: \"console\",\n message: args.map(String).join(\" \"),\n level: \"error\",\n });\n originalConsoleError!(...args);\n };\n }\n }\n\n if (mergedOptions.debug) {\n console.log(\"[Bugwatch] React SDK initialized\");\n }\n\n // Cleanup function to prevent memory leaks\n return () => {\n if (typeof window !== \"undefined\") {\n // Restore original window.onerror\n if (originalOnError !== null && mergedOptions.captureGlobalErrors) {\n window.onerror = originalOnError;\n }\n\n // Remove unhandled rejection listener\n if (unhandledRejectionHandler && mergedOptions.captureUnhandledRejections) {\n window.removeEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n // Restore original console.error\n if (originalConsoleError !== null && mergedOptions.captureConsoleBreadcrumbs) {\n console.error = originalConsoleError;\n }\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [optionsKey]);\n\n const captureException = useCallback(\n (error: Error, context?: Partial<ErrorEvent>) => {\n return coreCaptureException(error, context);\n },\n []\n );\n\n const captureMessage = useCallback(\n (message: string, level?: ErrorEvent[\"level\"]) => {\n return coreCaptureMessage(message, level);\n },\n []\n );\n\n const addBreadcrumb = useCallback(\n (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => {\n coreAddBreadcrumb(breadcrumb);\n },\n []\n );\n\n const setUser = useCallback((user: UserContext | null) => {\n coreSetUser(user);\n }, []);\n\n const setTag = useCallback((key: string, value: string) => {\n coreSetTag(key, value);\n }, []);\n\n const setExtra = useCallback((key: string, value: unknown) => {\n coreSetExtra(key, value);\n }, []);\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue = useMemo<BugwatchContextValue>(\n () => ({\n client: getClient(),\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n }),\n [captureException, captureMessage, addBreadcrumb, setUser, setTag, setExtra]\n );\n\n return (\n <BugwatchContext.Provider value={contextValue}>\n <ErrorBoundary fallback={fallback} onError={onError}>\n {children}\n </ErrorBoundary>\n </BugwatchContext.Provider>\n );\n}\n\n/**\n * Error Boundary Props\n */\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error Boundary component\n */\nclass ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n // Capture to Bugwatch\n coreCaptureException(error, {\n tags: { mechanism: \"react.errorBoundary\" },\n extra: {\n componentStack: errorInfo.componentStack,\n },\n });\n\n // Call custom handler\n this.props.onError?.(error, errorInfo);\n }\n\n reset = (): void => {\n this.setState({ hasError: false, error: null });\n };\n\n render(): ReactNode {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n\n if (typeof fallback === \"function\") {\n return fallback(this.state.error, this.reset);\n }\n\n if (fallback) {\n return fallback;\n }\n\n return (\n <div style={{ padding: \"20px\", fontFamily: \"sans-serif\" }}>\n <h2>Something went wrong</h2>\n <p>{this.state.error.message}</p>\n <button onClick={this.reset}>Try again</button>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\n/**\n * Standalone Error Boundary for custom use\n */\nexport { ErrorBoundary as BugwatchErrorBoundary };\n\n/**\n * Higher-order component for error boundary\n */\nexport function withBugwatchErrorBoundary<P extends object>(\n WrappedComponent: React.ComponentType<P>,\n options?: {\n fallback?: ErrorBoundaryProps[\"fallback\"];\n onError?: ErrorBoundaryProps[\"onError\"];\n }\n): React.ComponentType<P> {\n const WithErrorBoundary = (props: P) => (\n <ErrorBoundary fallback={options?.fallback} onError={options?.onError}>\n <WrappedComponent {...props} />\n </ErrorBoundary>\n );\n\n WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${\n WrappedComponent.displayName || WrappedComponent.name || \"Component\"\n })`;\n\n return WithErrorBoundary;\n}\n\n// Re-export core functions for convenience\nexport {\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n getClient,\n init,\n} from \"@bugwatch/core\";\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { createContext, useContext, useEffect, useCallback,
|
|
1
|
+
import { createContext, useContext, useMemo, useRef, useEffect, useCallback, Component } from 'react';
|
|
2
2
|
import { getEnvConfig, init, getClient, captureException, addBreadcrumb, captureMessage, setUser, setTag, setExtra } from '@bugwatch/core';
|
|
3
3
|
export { addBreadcrumb, captureException, captureMessage, getClient, init, setExtra, setTag, setUser } from '@bugwatch/core';
|
|
4
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
|
-
// src/index.tsx
|
|
7
6
|
var DEFAULT_REACT_OPTIONS = {
|
|
8
7
|
captureGlobalErrors: true,
|
|
9
8
|
captureUnhandledRejections: true,
|
|
@@ -31,9 +30,16 @@ function BugwatchProvider({
|
|
|
31
30
|
fallback,
|
|
32
31
|
onError
|
|
33
32
|
}) {
|
|
33
|
+
const optionsKey = useMemo(
|
|
34
|
+
() => options ? JSON.stringify(options) : "",
|
|
35
|
+
[options]
|
|
36
|
+
);
|
|
37
|
+
const optionsRef = useRef(options);
|
|
38
|
+
optionsRef.current = options;
|
|
34
39
|
useEffect(() => {
|
|
40
|
+
const currentOptions = optionsRef.current;
|
|
35
41
|
const envConfig = getEnvConfig();
|
|
36
|
-
const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...
|
|
42
|
+
const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...currentOptions };
|
|
37
43
|
if (!mergedOptions.apiKey) {
|
|
38
44
|
if (process.env.NODE_ENV === "development") {
|
|
39
45
|
console.warn("[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey");
|
|
@@ -107,7 +113,7 @@ function BugwatchProvider({
|
|
|
107
113
|
}
|
|
108
114
|
}
|
|
109
115
|
};
|
|
110
|
-
}, [
|
|
116
|
+
}, [optionsKey]);
|
|
111
117
|
const captureException2 = useCallback(
|
|
112
118
|
(error, context) => {
|
|
113
119
|
return captureException(error, context);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx"],"names":["captureException","captureMessage","coreInit","coreCaptureException","coreAddBreadcrumb","coreCaptureMessage","addBreadcrumb","setUser","coreSetUser","setTag","coreSetTag","setExtra","coreSetExtra"],"mappings":"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","file":"index.mjs","sourcesContent":["import React, {\n Component,\n createContext,\n useContext,\n useEffect,\n useCallback,\n useMemo,\n type ReactNode,\n type ErrorInfo,\n} from \"react\";\nimport {\n init as coreInit,\n getClient,\n getEnvConfig,\n captureException as coreCaptureException,\n captureMessage as coreCaptureMessage,\n addBreadcrumb as coreAddBreadcrumb,\n setUser as coreSetUser,\n setTag as coreSetTag,\n setExtra as coreSetExtra,\n type BugwatchOptions,\n type BugwatchClient,\n type UserContext,\n type Breadcrumb,\n type ErrorEvent,\n} from \"@bugwatch/core\";\n\n// Re-export types\nexport type { BugwatchOptions, UserContext, ErrorEvent, Breadcrumb } from \"@bugwatch/core\";\n\n/**\n * React-specific SDK options\n */\nexport interface ReactOptions extends BugwatchOptions {\n /** Capture window.onerror events */\n captureGlobalErrors?: boolean;\n /** Capture unhandled promise rejections */\n captureUnhandledRejections?: boolean;\n /** Capture console.error as breadcrumbs */\n captureConsoleBreadcrumbs?: boolean;\n}\n\nconst DEFAULT_REACT_OPTIONS: Partial<ReactOptions> = {\n captureGlobalErrors: true,\n captureUnhandledRejections: true,\n captureConsoleBreadcrumbs: true,\n};\n\n/**\n * Bugwatch context\n */\ninterface BugwatchContextValue {\n client: BugwatchClient | null;\n captureException: (error: Error, context?: Partial<ErrorEvent>) => string;\n captureMessage: (message: string, level?: ErrorEvent[\"level\"]) => string;\n addBreadcrumb: (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => void;\n setUser: (user: UserContext | null) => void;\n setTag: (key: string, value: string) => void;\n setExtra: (key: string, value: unknown) => void;\n}\n\nconst BugwatchContext = createContext<BugwatchContextValue | null>(null);\n\n/**\n * Hook to access Bugwatch SDK\n */\nexport function useBugwatch(): BugwatchContextValue {\n const context = useContext(BugwatchContext);\n if (!context) {\n throw new Error(\"useBugwatch must be used within a BugwatchProvider\");\n }\n return context;\n}\n\n/**\n * Hook to capture exceptions\n */\nexport function useCaptureException(): (\n error: Error,\n context?: Partial<ErrorEvent>\n) => string {\n const { captureException } = useBugwatch();\n return captureException;\n}\n\n/**\n * Hook to capture messages\n */\nexport function useCaptureMessage(): (\n message: string,\n level?: ErrorEvent[\"level\"]\n) => string {\n const { captureMessage } = useBugwatch();\n return captureMessage;\n}\n\n/**\n * Props for BugwatchProvider\n */\ninterface BugwatchProviderProps {\n /**\n * SDK configuration options.\n * Optional - if not provided, reads from environment variables:\n * - `BUGWATCH_API_KEY` - API key (required unless passed explicitly)\n * - `BUGWATCH_ENVIRONMENT` - Environment tag\n * - `BUGWATCH_RELEASE` - Release version\n * - `BUGWATCH_DEBUG` - Enable debug mode ('true')\n */\n options?: ReactOptions;\n /** Child components */\n children: ReactNode;\n /** Optional fallback UI for error boundary */\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Called when an error is caught by the error boundary */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\n/**\n * Bugwatch Provider component\n * Initializes the SDK and provides context to child components\n *\n * @example\n * ```tsx\n * // With BUGWATCH_API_KEY env var set\n * <BugwatchProvider>\n * <App />\n * </BugwatchProvider>\n *\n * // With explicit options\n * <BugwatchProvider options={{ apiKey: \"bw_live_xxxxx\" }}>\n * <App />\n * </BugwatchProvider>\n * ```\n */\nexport function BugwatchProvider({\n options,\n children,\n fallback,\n onError,\n}: BugwatchProviderProps): JSX.Element {\n useEffect(() => {\n // Merge env config with explicit options (explicit takes precedence)\n const envConfig = getEnvConfig();\n const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...options };\n\n // Skip initialization if no API key is available\n if (!mergedOptions.apiKey) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey');\n }\n return;\n }\n\n // Wrap initialization in try-catch for graceful degradation\n try {\n coreInit(mergedOptions);\n } catch (err) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Bugwatch] Initialization failed:', err);\n }\n return;\n }\n\n // Add React-specific tags\n const client = getClient();\n if (client) {\n client.setTag(\"framework\", \"react\");\n }\n\n // Store original handlers for cleanup\n let originalOnError: typeof window.onerror | null = null;\n let originalConsoleError: typeof console.error | null = null;\n let unhandledRejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;\n\n // Set up global error handlers\n if (typeof window !== \"undefined\") {\n if (mergedOptions.captureGlobalErrors) {\n originalOnError = window.onerror;\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n coreCaptureException(error, {\n tags: { mechanism: \"window.onerror\" },\n });\n }\n if (originalOnError) {\n return originalOnError(message, source, lineno, colno, error);\n }\n return false;\n };\n }\n\n if (mergedOptions.captureUnhandledRejections) {\n unhandledRejectionHandler = (event: PromiseRejectionEvent) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n coreCaptureException(error, {\n tags: { mechanism: \"unhandledrejection\" },\n });\n };\n window.addEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n if (mergedOptions.captureConsoleBreadcrumbs) {\n originalConsoleError = console.error;\n console.error = (...args: unknown[]) => {\n coreAddBreadcrumb({\n category: \"console\",\n message: args.map(String).join(\" \"),\n level: \"error\",\n });\n originalConsoleError!(...args);\n };\n }\n }\n\n if (mergedOptions.debug) {\n console.log(\"[Bugwatch] React SDK initialized\");\n }\n\n // Cleanup function to prevent memory leaks\n return () => {\n if (typeof window !== \"undefined\") {\n // Restore original window.onerror\n if (originalOnError !== null && mergedOptions.captureGlobalErrors) {\n window.onerror = originalOnError;\n }\n\n // Remove unhandled rejection listener\n if (unhandledRejectionHandler && mergedOptions.captureUnhandledRejections) {\n window.removeEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n // Restore original console.error\n if (originalConsoleError !== null && mergedOptions.captureConsoleBreadcrumbs) {\n console.error = originalConsoleError;\n }\n }\n };\n }, [options]);\n\n const captureException = useCallback(\n (error: Error, context?: Partial<ErrorEvent>) => {\n return coreCaptureException(error, context);\n },\n []\n );\n\n const captureMessage = useCallback(\n (message: string, level?: ErrorEvent[\"level\"]) => {\n return coreCaptureMessage(message, level);\n },\n []\n );\n\n const addBreadcrumb = useCallback(\n (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => {\n coreAddBreadcrumb(breadcrumb);\n },\n []\n );\n\n const setUser = useCallback((user: UserContext | null) => {\n coreSetUser(user);\n }, []);\n\n const setTag = useCallback((key: string, value: string) => {\n coreSetTag(key, value);\n }, []);\n\n const setExtra = useCallback((key: string, value: unknown) => {\n coreSetExtra(key, value);\n }, []);\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue = useMemo<BugwatchContextValue>(\n () => ({\n client: getClient(),\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n }),\n [captureException, captureMessage, addBreadcrumb, setUser, setTag, setExtra]\n );\n\n return (\n <BugwatchContext.Provider value={contextValue}>\n <ErrorBoundary fallback={fallback} onError={onError}>\n {children}\n </ErrorBoundary>\n </BugwatchContext.Provider>\n );\n}\n\n/**\n * Error Boundary Props\n */\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error Boundary component\n */\nclass ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n // Capture to Bugwatch\n coreCaptureException(error, {\n tags: { mechanism: \"react.errorBoundary\" },\n extra: {\n componentStack: errorInfo.componentStack,\n },\n });\n\n // Call custom handler\n this.props.onError?.(error, errorInfo);\n }\n\n reset = (): void => {\n this.setState({ hasError: false, error: null });\n };\n\n render(): ReactNode {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n\n if (typeof fallback === \"function\") {\n return fallback(this.state.error, this.reset);\n }\n\n if (fallback) {\n return fallback;\n }\n\n return (\n <div style={{ padding: \"20px\", fontFamily: \"sans-serif\" }}>\n <h2>Something went wrong</h2>\n <p>{this.state.error.message}</p>\n <button onClick={this.reset}>Try again</button>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\n/**\n * Standalone Error Boundary for custom use\n */\nexport { ErrorBoundary as BugwatchErrorBoundary };\n\n/**\n * Higher-order component for error boundary\n */\nexport function withBugwatchErrorBoundary<P extends object>(\n WrappedComponent: React.ComponentType<P>,\n options?: {\n fallback?: ErrorBoundaryProps[\"fallback\"];\n onError?: ErrorBoundaryProps[\"onError\"];\n }\n): React.ComponentType<P> {\n const WithErrorBoundary = (props: P) => (\n <ErrorBoundary fallback={options?.fallback} onError={options?.onError}>\n <WrappedComponent {...props} />\n </ErrorBoundary>\n );\n\n WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${\n WrappedComponent.displayName || WrappedComponent.name || \"Component\"\n })`;\n\n return WithErrorBoundary;\n}\n\n// Re-export core functions for convenience\nexport {\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n getClient,\n init,\n} from \"@bugwatch/core\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"names":["captureException","captureMessage","coreInit","coreCaptureException","coreAddBreadcrumb","coreCaptureMessage","addBreadcrumb","setUser","coreSetUser","setTag","coreSetTag","setExtra","coreSetExtra"],"mappings":"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","file":"index.mjs","sourcesContent":["\"use client\";\n\nimport React, {\n Component,\n createContext,\n useContext,\n useEffect,\n useCallback,\n useRef,\n useMemo,\n type ReactNode,\n type ErrorInfo,\n} from \"react\";\nimport {\n init as coreInit,\n getClient,\n getEnvConfig,\n captureException as coreCaptureException,\n captureMessage as coreCaptureMessage,\n addBreadcrumb as coreAddBreadcrumb,\n setUser as coreSetUser,\n setTag as coreSetTag,\n setExtra as coreSetExtra,\n type BugwatchOptions,\n type BugwatchClient,\n type UserContext,\n type Breadcrumb,\n type ErrorEvent,\n} from \"@bugwatch/core\";\n\n// Re-export types\nexport type { BugwatchOptions, UserContext, ErrorEvent, Breadcrumb } from \"@bugwatch/core\";\n\n/**\n * React-specific SDK options\n */\nexport interface ReactOptions extends BugwatchOptions {\n /** Capture window.onerror events */\n captureGlobalErrors?: boolean;\n /** Capture unhandled promise rejections */\n captureUnhandledRejections?: boolean;\n /** Capture console.error as breadcrumbs */\n captureConsoleBreadcrumbs?: boolean;\n}\n\nconst DEFAULT_REACT_OPTIONS: Partial<ReactOptions> = {\n captureGlobalErrors: true,\n captureUnhandledRejections: true,\n captureConsoleBreadcrumbs: true,\n};\n\n/**\n * Bugwatch context\n */\ninterface BugwatchContextValue {\n client: BugwatchClient | null;\n captureException: (error: Error, context?: Partial<ErrorEvent>) => string;\n captureMessage: (message: string, level?: ErrorEvent[\"level\"]) => string;\n addBreadcrumb: (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => void;\n setUser: (user: UserContext | null) => void;\n setTag: (key: string, value: string) => void;\n setExtra: (key: string, value: unknown) => void;\n}\n\nconst BugwatchContext = createContext<BugwatchContextValue | null>(null);\n\n/**\n * Hook to access Bugwatch SDK\n */\nexport function useBugwatch(): BugwatchContextValue {\n const context = useContext(BugwatchContext);\n if (!context) {\n throw new Error(\"useBugwatch must be used within a BugwatchProvider\");\n }\n return context;\n}\n\n/**\n * Hook to capture exceptions\n */\nexport function useCaptureException(): (\n error: Error,\n context?: Partial<ErrorEvent>\n) => string {\n const { captureException } = useBugwatch();\n return captureException;\n}\n\n/**\n * Hook to capture messages\n */\nexport function useCaptureMessage(): (\n message: string,\n level?: ErrorEvent[\"level\"]\n) => string {\n const { captureMessage } = useBugwatch();\n return captureMessage;\n}\n\n/**\n * Props for BugwatchProvider\n */\ninterface BugwatchProviderProps {\n /**\n * SDK configuration options.\n * Optional - if not provided, reads from environment variables:\n * - `BUGWATCH_API_KEY` - API key (required unless passed explicitly)\n * - `BUGWATCH_ENVIRONMENT` - Environment tag\n * - `BUGWATCH_RELEASE` - Release version\n * - `BUGWATCH_DEBUG` - Enable debug mode ('true')\n */\n options?: ReactOptions;\n /** Child components */\n children: ReactNode;\n /** Optional fallback UI for error boundary */\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Called when an error is caught by the error boundary */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\n/**\n * Bugwatch Provider component\n * Initializes the SDK and provides context to child components\n *\n * @example\n * ```tsx\n * // With BUGWATCH_API_KEY env var set\n * <BugwatchProvider>\n * <App />\n * </BugwatchProvider>\n *\n * // With explicit options\n * <BugwatchProvider options={{ apiKey: \"bw_live_xxxxx\" }}>\n * <App />\n * </BugwatchProvider>\n * ```\n */\nexport function BugwatchProvider({\n options,\n children,\n fallback,\n onError,\n}: BugwatchProviderProps): JSX.Element {\n // Serialize options to a stable string so useEffect doesn't re-run on every render.\n // Object identity of `options` changes every render if passed inline.\n const optionsKey = useMemo(\n () => (options ? JSON.stringify(options) : \"\"),\n [options]\n );\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n useEffect(() => {\n const currentOptions = optionsRef.current;\n\n // Merge env config with explicit options (explicit takes precedence)\n const envConfig = getEnvConfig();\n const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...currentOptions };\n\n // Skip initialization if no API key is available\n if (!mergedOptions.apiKey) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey');\n }\n return;\n }\n\n // Wrap initialization in try-catch for graceful degradation\n try {\n coreInit(mergedOptions);\n } catch (err) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Bugwatch] Initialization failed:', err);\n }\n return;\n }\n\n // Add React-specific tags\n const client = getClient();\n if (client) {\n client.setTag(\"framework\", \"react\");\n }\n\n // Store original handlers for cleanup\n let originalOnError: typeof window.onerror | null = null;\n let originalConsoleError: typeof console.error | null = null;\n let unhandledRejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;\n\n // Set up global error handlers\n if (typeof window !== \"undefined\") {\n if (mergedOptions.captureGlobalErrors) {\n originalOnError = window.onerror;\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n coreCaptureException(error, {\n tags: { mechanism: \"window.onerror\" },\n });\n }\n if (originalOnError) {\n return originalOnError(message, source, lineno, colno, error);\n }\n return false;\n };\n }\n\n if (mergedOptions.captureUnhandledRejections) {\n unhandledRejectionHandler = (event: PromiseRejectionEvent) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n coreCaptureException(error, {\n tags: { mechanism: \"unhandledrejection\" },\n });\n };\n window.addEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n if (mergedOptions.captureConsoleBreadcrumbs) {\n originalConsoleError = console.error;\n console.error = (...args: unknown[]) => {\n coreAddBreadcrumb({\n category: \"console\",\n message: args.map(String).join(\" \"),\n level: \"error\",\n });\n originalConsoleError!(...args);\n };\n }\n }\n\n if (mergedOptions.debug) {\n console.log(\"[Bugwatch] React SDK initialized\");\n }\n\n // Cleanup function to prevent memory leaks\n return () => {\n if (typeof window !== \"undefined\") {\n // Restore original window.onerror\n if (originalOnError !== null && mergedOptions.captureGlobalErrors) {\n window.onerror = originalOnError;\n }\n\n // Remove unhandled rejection listener\n if (unhandledRejectionHandler && mergedOptions.captureUnhandledRejections) {\n window.removeEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n // Restore original console.error\n if (originalConsoleError !== null && mergedOptions.captureConsoleBreadcrumbs) {\n console.error = originalConsoleError;\n }\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [optionsKey]);\n\n const captureException = useCallback(\n (error: Error, context?: Partial<ErrorEvent>) => {\n return coreCaptureException(error, context);\n },\n []\n );\n\n const captureMessage = useCallback(\n (message: string, level?: ErrorEvent[\"level\"]) => {\n return coreCaptureMessage(message, level);\n },\n []\n );\n\n const addBreadcrumb = useCallback(\n (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => {\n coreAddBreadcrumb(breadcrumb);\n },\n []\n );\n\n const setUser = useCallback((user: UserContext | null) => {\n coreSetUser(user);\n }, []);\n\n const setTag = useCallback((key: string, value: string) => {\n coreSetTag(key, value);\n }, []);\n\n const setExtra = useCallback((key: string, value: unknown) => {\n coreSetExtra(key, value);\n }, []);\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue = useMemo<BugwatchContextValue>(\n () => ({\n client: getClient(),\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n }),\n [captureException, captureMessage, addBreadcrumb, setUser, setTag, setExtra]\n );\n\n return (\n <BugwatchContext.Provider value={contextValue}>\n <ErrorBoundary fallback={fallback} onError={onError}>\n {children}\n </ErrorBoundary>\n </BugwatchContext.Provider>\n );\n}\n\n/**\n * Error Boundary Props\n */\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error Boundary component\n */\nclass ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n // Capture to Bugwatch\n coreCaptureException(error, {\n tags: { mechanism: \"react.errorBoundary\" },\n extra: {\n componentStack: errorInfo.componentStack,\n },\n });\n\n // Call custom handler\n this.props.onError?.(error, errorInfo);\n }\n\n reset = (): void => {\n this.setState({ hasError: false, error: null });\n };\n\n render(): ReactNode {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n\n if (typeof fallback === \"function\") {\n return fallback(this.state.error, this.reset);\n }\n\n if (fallback) {\n return fallback;\n }\n\n return (\n <div style={{ padding: \"20px\", fontFamily: \"sans-serif\" }}>\n <h2>Something went wrong</h2>\n <p>{this.state.error.message}</p>\n <button onClick={this.reset}>Try again</button>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\n/**\n * Standalone Error Boundary for custom use\n */\nexport { ErrorBoundary as BugwatchErrorBoundary };\n\n/**\n * Higher-order component for error boundary\n */\nexport function withBugwatchErrorBoundary<P extends object>(\n WrappedComponent: React.ComponentType<P>,\n options?: {\n fallback?: ErrorBoundaryProps[\"fallback\"];\n onError?: ErrorBoundaryProps[\"onError\"];\n }\n): React.ComponentType<P> {\n const WithErrorBoundary = (props: P) => (\n <ErrorBoundary fallback={options?.fallback} onError={options?.onError}>\n <WrappedComponent {...props} />\n </ErrorBoundary>\n );\n\n WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${\n WrappedComponent.displayName || WrappedComponent.name || \"Component\"\n })`;\n\n return WithErrorBoundary;\n}\n\n// Re-export core functions for convenience\nexport {\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n getClient,\n init,\n} from \"@bugwatch/core\";\n"]}
|