@bugwatch/react 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -41,8 +41,15 @@ declare function useCaptureMessage(): (message: string, level?: ErrorEvent["leve
41
41
  * Props for BugwatchProvider
42
42
  */
43
43
  interface BugwatchProviderProps {
44
- /** SDK configuration options */
45
- options: ReactOptions;
44
+ /**
45
+ * SDK configuration options.
46
+ * Optional - if not provided, reads from environment variables:
47
+ * - `BUGWATCH_API_KEY` - API key (required unless passed explicitly)
48
+ * - `BUGWATCH_ENVIRONMENT` - Environment tag
49
+ * - `BUGWATCH_RELEASE` - Release version
50
+ * - `BUGWATCH_DEBUG` - Enable debug mode ('true')
51
+ */
52
+ options?: ReactOptions;
46
53
  /** Child components */
47
54
  children: ReactNode;
48
55
  /** Optional fallback UI for error boundary */
@@ -53,6 +60,19 @@ interface BugwatchProviderProps {
53
60
  /**
54
61
  * Bugwatch Provider component
55
62
  * Initializes the SDK and provides context to child components
63
+ *
64
+ * @example
65
+ * ```tsx
66
+ * // With BUGWATCH_API_KEY env var set
67
+ * <BugwatchProvider>
68
+ * <App />
69
+ * </BugwatchProvider>
70
+ *
71
+ * // With explicit options
72
+ * <BugwatchProvider options={{ apiKey: "bw_live_xxxxx" }}>
73
+ * <App />
74
+ * </BugwatchProvider>
75
+ * ```
56
76
  */
57
77
  declare function BugwatchProvider({ options, children, fallback, onError, }: BugwatchProviderProps): JSX.Element;
58
78
  /**
package/dist/index.d.ts CHANGED
@@ -41,8 +41,15 @@ declare function useCaptureMessage(): (message: string, level?: ErrorEvent["leve
41
41
  * Props for BugwatchProvider
42
42
  */
43
43
  interface BugwatchProviderProps {
44
- /** SDK configuration options */
45
- options: ReactOptions;
44
+ /**
45
+ * SDK configuration options.
46
+ * Optional - if not provided, reads from environment variables:
47
+ * - `BUGWATCH_API_KEY` - API key (required unless passed explicitly)
48
+ * - `BUGWATCH_ENVIRONMENT` - Environment tag
49
+ * - `BUGWATCH_RELEASE` - Release version
50
+ * - `BUGWATCH_DEBUG` - Enable debug mode ('true')
51
+ */
52
+ options?: ReactOptions;
46
53
  /** Child components */
47
54
  children: ReactNode;
48
55
  /** Optional fallback UI for error boundary */
@@ -53,6 +60,19 @@ interface BugwatchProviderProps {
53
60
  /**
54
61
  * Bugwatch Provider component
55
62
  * Initializes the SDK and provides context to child components
63
+ *
64
+ * @example
65
+ * ```tsx
66
+ * // With BUGWATCH_API_KEY env var set
67
+ * <BugwatchProvider>
68
+ * <App />
69
+ * </BugwatchProvider>
70
+ *
71
+ * // With explicit options
72
+ * <BugwatchProvider options={{ apiKey: "bw_live_xxxxx" }}>
73
+ * <App />
74
+ * </BugwatchProvider>
75
+ * ```
56
76
  */
57
77
  declare function BugwatchProvider({ options, children, fallback, onError, }: BugwatchProviderProps): JSX.Element;
58
78
  /**
package/dist/index.js CHANGED
@@ -33,26 +33,81 @@ function BugwatchProvider({
33
33
  onError
34
34
  }) {
35
35
  react.useEffect(() => {
36
- const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...options };
37
- core.init(mergedOptions);
36
+ const envConfig = core.getEnvConfig();
37
+ const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...options };
38
+ if (!mergedOptions.apiKey) {
39
+ if (process.env.NODE_ENV === "development") {
40
+ console.warn("[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey");
41
+ }
42
+ return;
43
+ }
44
+ try {
45
+ core.init(mergedOptions);
46
+ } catch (err) {
47
+ if (process.env.NODE_ENV === "development") {
48
+ console.error("[Bugwatch] Initialization failed:", err);
49
+ }
50
+ return;
51
+ }
38
52
  const client = core.getClient();
39
53
  if (client) {
40
54
  client.setTag("framework", "react");
41
55
  }
56
+ let originalOnError = null;
57
+ let originalConsoleError = null;
58
+ let unhandledRejectionHandler = null;
42
59
  if (typeof window !== "undefined") {
43
60
  if (mergedOptions.captureGlobalErrors) {
44
- setupGlobalErrorHandler();
61
+ originalOnError = window.onerror;
62
+ window.onerror = (message, source, lineno, colno, error) => {
63
+ if (error) {
64
+ core.captureException(error, {
65
+ tags: { mechanism: "window.onerror" }
66
+ });
67
+ }
68
+ if (originalOnError) {
69
+ return originalOnError(message, source, lineno, colno, error);
70
+ }
71
+ return false;
72
+ };
45
73
  }
46
74
  if (mergedOptions.captureUnhandledRejections) {
47
- setupUnhandledRejectionHandler();
75
+ unhandledRejectionHandler = (event) => {
76
+ const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
77
+ core.captureException(error, {
78
+ tags: { mechanism: "unhandledrejection" }
79
+ });
80
+ };
81
+ window.addEventListener("unhandledrejection", unhandledRejectionHandler);
48
82
  }
49
83
  if (mergedOptions.captureConsoleBreadcrumbs) {
50
- setupConsoleBreadcrumbs();
84
+ originalConsoleError = console.error;
85
+ console.error = (...args) => {
86
+ core.addBreadcrumb({
87
+ category: "console",
88
+ message: args.map(String).join(" "),
89
+ level: "error"
90
+ });
91
+ originalConsoleError(...args);
92
+ };
51
93
  }
52
94
  }
53
95
  if (mergedOptions.debug) {
54
96
  console.log("[Bugwatch] React SDK initialized");
55
97
  }
98
+ return () => {
99
+ if (typeof window !== "undefined") {
100
+ if (originalOnError !== null && mergedOptions.captureGlobalErrors) {
101
+ window.onerror = originalOnError;
102
+ }
103
+ if (unhandledRejectionHandler && mergedOptions.captureUnhandledRejections) {
104
+ window.removeEventListener("unhandledrejection", unhandledRejectionHandler);
105
+ }
106
+ if (originalConsoleError !== null && mergedOptions.captureConsoleBreadcrumbs) {
107
+ console.error = originalConsoleError;
108
+ }
109
+ }
110
+ };
56
111
  }, [options]);
57
112
  const captureException2 = react.useCallback(
58
113
  (error, context) => {
@@ -81,15 +136,18 @@ function BugwatchProvider({
81
136
  const setExtra2 = react.useCallback((key, value) => {
82
137
  core.setExtra(key, value);
83
138
  }, []);
84
- const contextValue = {
85
- client: core.getClient(),
86
- captureException: captureException2,
87
- captureMessage: captureMessage2,
88
- addBreadcrumb: addBreadcrumb2,
89
- setUser: setUser2,
90
- setTag: setTag2,
91
- setExtra: setExtra2
92
- };
139
+ const contextValue = react.useMemo(
140
+ () => ({
141
+ client: core.getClient(),
142
+ captureException: captureException2,
143
+ captureMessage: captureMessage2,
144
+ addBreadcrumb: addBreadcrumb2,
145
+ setUser: setUser2,
146
+ setTag: setTag2,
147
+ setExtra: setExtra2
148
+ }),
149
+ [captureException2, captureMessage2, addBreadcrumb2, setUser2, setTag2, setExtra2]
150
+ );
93
151
  return /* @__PURE__ */ jsxRuntime.jsx(BugwatchContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { fallback, onError, children }) });
94
152
  }
95
153
  var ErrorBoundary = class extends react.Component {
@@ -135,39 +193,6 @@ function withBugwatchErrorBoundary(WrappedComponent, options) {
135
193
  WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name || "Component"})`;
136
194
  return WithErrorBoundary;
137
195
  }
138
- function setupGlobalErrorHandler() {
139
- const originalOnError = window.onerror;
140
- window.onerror = (message, source, lineno, colno, error) => {
141
- if (error) {
142
- core.captureException(error, {
143
- tags: { mechanism: "window.onerror" }
144
- });
145
- }
146
- if (originalOnError) {
147
- return originalOnError(message, source, lineno, colno, error);
148
- }
149
- return false;
150
- };
151
- }
152
- function setupUnhandledRejectionHandler() {
153
- window.addEventListener("unhandledrejection", (event) => {
154
- const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
155
- core.captureException(error, {
156
- tags: { mechanism: "unhandledrejection" }
157
- });
158
- });
159
- }
160
- function setupConsoleBreadcrumbs() {
161
- const originalError = console.error;
162
- console.error = (...args) => {
163
- core.addBreadcrumb({
164
- category: "console",
165
- message: args.map(String).join(" "),
166
- level: "error"
167
- });
168
- originalError(...args);
169
- };
170
- }
171
196
 
172
197
  Object.defineProperty(exports, "addBreadcrumb", {
173
198
  enumerable: true,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx"],"names":["createContext","useContext","captureException","captureMessage","useEffect","coreInit","getClient","useCallback","coreCaptureException","coreCaptureMessage","addBreadcrumb","coreAddBreadcrumb","setUser","coreSetUser","setTag","coreSetTag","setExtra","coreSetExtra","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 type ReactNode,\n type ErrorInfo,\n} from \"react\";\nimport {\n init as coreInit,\n getClient,\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 /** SDK configuration options */\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 */\nexport function BugwatchProvider({\n options,\n children,\n fallback,\n onError,\n}: BugwatchProviderProps): JSX.Element {\n useEffect(() => {\n const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...options };\n coreInit(mergedOptions);\n\n // Add React-specific tags\n const client = getClient();\n if (client) {\n client.setTag(\"framework\", \"react\");\n }\n\n // Set up global error handlers\n if (typeof window !== \"undefined\") {\n if (mergedOptions.captureGlobalErrors) {\n setupGlobalErrorHandler();\n }\n if (mergedOptions.captureUnhandledRejections) {\n setupUnhandledRejectionHandler();\n }\n if (mergedOptions.captureConsoleBreadcrumbs) {\n setupConsoleBreadcrumbs();\n }\n }\n\n if (mergedOptions.debug) {\n console.log(\"[Bugwatch] React SDK initialized\");\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 const contextValue: BugwatchContextValue = {\n client: getClient(),\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n 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// Global error handler setup\nfunction setupGlobalErrorHandler(): void {\n const originalOnError = window.onerror;\n\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n coreCaptureException(error, {\n tags: { mechanism: \"window.onerror\" },\n });\n }\n\n if (originalOnError) {\n return originalOnError(message, source, lineno, colno, error);\n }\n\n return false;\n };\n}\n\nfunction setupUnhandledRejectionHandler(): void {\n window.addEventListener(\"unhandledrejection\", (event) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n\n coreCaptureException(error, {\n tags: { mechanism: \"unhandledrejection\" },\n });\n });\n}\n\nfunction setupConsoleBreadcrumbs(): void {\n const originalError = console.error;\n\n console.error = (...args: unknown[]) => {\n coreAddBreadcrumb({\n category: \"console\",\n message: args.map(String).join(\" \"),\n level: \"error\",\n });\n originalError(...args);\n };\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","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"]}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { createContext, useContext, useEffect, useCallback, Component } from 'react';
2
- import { init, getClient, captureException, captureMessage, addBreadcrumb, setUser, setTag, setExtra } from '@bugwatch/core';
1
+ import { createContext, useContext, useEffect, useCallback, useMemo, Component } from 'react';
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
 
@@ -32,26 +32,81 @@ function BugwatchProvider({
32
32
  onError
33
33
  }) {
34
34
  useEffect(() => {
35
- const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...options };
36
- init(mergedOptions);
35
+ const envConfig = getEnvConfig();
36
+ const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...options };
37
+ if (!mergedOptions.apiKey) {
38
+ if (process.env.NODE_ENV === "development") {
39
+ console.warn("[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey");
40
+ }
41
+ return;
42
+ }
43
+ try {
44
+ init(mergedOptions);
45
+ } catch (err) {
46
+ if (process.env.NODE_ENV === "development") {
47
+ console.error("[Bugwatch] Initialization failed:", err);
48
+ }
49
+ return;
50
+ }
37
51
  const client = getClient();
38
52
  if (client) {
39
53
  client.setTag("framework", "react");
40
54
  }
55
+ let originalOnError = null;
56
+ let originalConsoleError = null;
57
+ let unhandledRejectionHandler = null;
41
58
  if (typeof window !== "undefined") {
42
59
  if (mergedOptions.captureGlobalErrors) {
43
- setupGlobalErrorHandler();
60
+ originalOnError = window.onerror;
61
+ window.onerror = (message, source, lineno, colno, error) => {
62
+ if (error) {
63
+ captureException(error, {
64
+ tags: { mechanism: "window.onerror" }
65
+ });
66
+ }
67
+ if (originalOnError) {
68
+ return originalOnError(message, source, lineno, colno, error);
69
+ }
70
+ return false;
71
+ };
44
72
  }
45
73
  if (mergedOptions.captureUnhandledRejections) {
46
- setupUnhandledRejectionHandler();
74
+ unhandledRejectionHandler = (event) => {
75
+ const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
76
+ captureException(error, {
77
+ tags: { mechanism: "unhandledrejection" }
78
+ });
79
+ };
80
+ window.addEventListener("unhandledrejection", unhandledRejectionHandler);
47
81
  }
48
82
  if (mergedOptions.captureConsoleBreadcrumbs) {
49
- setupConsoleBreadcrumbs();
83
+ originalConsoleError = console.error;
84
+ console.error = (...args) => {
85
+ addBreadcrumb({
86
+ category: "console",
87
+ message: args.map(String).join(" "),
88
+ level: "error"
89
+ });
90
+ originalConsoleError(...args);
91
+ };
50
92
  }
51
93
  }
52
94
  if (mergedOptions.debug) {
53
95
  console.log("[Bugwatch] React SDK initialized");
54
96
  }
97
+ return () => {
98
+ if (typeof window !== "undefined") {
99
+ if (originalOnError !== null && mergedOptions.captureGlobalErrors) {
100
+ window.onerror = originalOnError;
101
+ }
102
+ if (unhandledRejectionHandler && mergedOptions.captureUnhandledRejections) {
103
+ window.removeEventListener("unhandledrejection", unhandledRejectionHandler);
104
+ }
105
+ if (originalConsoleError !== null && mergedOptions.captureConsoleBreadcrumbs) {
106
+ console.error = originalConsoleError;
107
+ }
108
+ }
109
+ };
55
110
  }, [options]);
56
111
  const captureException2 = useCallback(
57
112
  (error, context) => {
@@ -80,15 +135,18 @@ function BugwatchProvider({
80
135
  const setExtra2 = useCallback((key, value) => {
81
136
  setExtra(key, value);
82
137
  }, []);
83
- const contextValue = {
84
- client: getClient(),
85
- captureException: captureException2,
86
- captureMessage: captureMessage2,
87
- addBreadcrumb: addBreadcrumb2,
88
- setUser: setUser2,
89
- setTag: setTag2,
90
- setExtra: setExtra2
91
- };
138
+ const contextValue = useMemo(
139
+ () => ({
140
+ client: getClient(),
141
+ captureException: captureException2,
142
+ captureMessage: captureMessage2,
143
+ addBreadcrumb: addBreadcrumb2,
144
+ setUser: setUser2,
145
+ setTag: setTag2,
146
+ setExtra: setExtra2
147
+ }),
148
+ [captureException2, captureMessage2, addBreadcrumb2, setUser2, setTag2, setExtra2]
149
+ );
92
150
  return /* @__PURE__ */ jsx(BugwatchContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(ErrorBoundary, { fallback, onError, children }) });
93
151
  }
94
152
  var ErrorBoundary = class extends Component {
@@ -134,39 +192,6 @@ function withBugwatchErrorBoundary(WrappedComponent, options) {
134
192
  WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name || "Component"})`;
135
193
  return WithErrorBoundary;
136
194
  }
137
- function setupGlobalErrorHandler() {
138
- const originalOnError = window.onerror;
139
- window.onerror = (message, source, lineno, colno, error) => {
140
- if (error) {
141
- captureException(error, {
142
- tags: { mechanism: "window.onerror" }
143
- });
144
- }
145
- if (originalOnError) {
146
- return originalOnError(message, source, lineno, colno, error);
147
- }
148
- return false;
149
- };
150
- }
151
- function setupUnhandledRejectionHandler() {
152
- window.addEventListener("unhandledrejection", (event) => {
153
- const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
154
- captureException(error, {
155
- tags: { mechanism: "unhandledrejection" }
156
- });
157
- });
158
- }
159
- function setupConsoleBreadcrumbs() {
160
- const originalError = console.error;
161
- console.error = (...args) => {
162
- addBreadcrumb({
163
- category: "console",
164
- message: args.map(String).join(" "),
165
- level: "error"
166
- });
167
- originalError(...args);
168
- };
169
- }
170
195
 
171
196
  export { ErrorBoundary as BugwatchErrorBoundary, BugwatchProvider, useBugwatch, useCaptureException, useCaptureMessage, withBugwatchErrorBoundary };
172
197
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx"],"names":["captureException","captureMessage","coreInit","coreCaptureException","coreCaptureMessage","addBreadcrumb","coreAddBreadcrumb","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 type ReactNode,\n type ErrorInfo,\n} from \"react\";\nimport {\n init as coreInit,\n getClient,\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 /** SDK configuration options */\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 */\nexport function BugwatchProvider({\n options,\n children,\n fallback,\n onError,\n}: BugwatchProviderProps): JSX.Element {\n useEffect(() => {\n const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...options };\n coreInit(mergedOptions);\n\n // Add React-specific tags\n const client = getClient();\n if (client) {\n client.setTag(\"framework\", \"react\");\n }\n\n // Set up global error handlers\n if (typeof window !== \"undefined\") {\n if (mergedOptions.captureGlobalErrors) {\n setupGlobalErrorHandler();\n }\n if (mergedOptions.captureUnhandledRejections) {\n setupUnhandledRejectionHandler();\n }\n if (mergedOptions.captureConsoleBreadcrumbs) {\n setupConsoleBreadcrumbs();\n }\n }\n\n if (mergedOptions.debug) {\n console.log(\"[Bugwatch] React SDK initialized\");\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 const contextValue: BugwatchContextValue = {\n client: getClient(),\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n 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// Global error handler setup\nfunction setupGlobalErrorHandler(): void {\n const originalOnError = window.onerror;\n\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n coreCaptureException(error, {\n tags: { mechanism: \"window.onerror\" },\n });\n }\n\n if (originalOnError) {\n return originalOnError(message, source, lineno, colno, error);\n }\n\n return false;\n };\n}\n\nfunction setupUnhandledRejectionHandler(): void {\n window.addEventListener(\"unhandledrejection\", (event) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n\n coreCaptureException(error, {\n tags: { mechanism: \"unhandledrejection\" },\n });\n });\n}\n\nfunction setupConsoleBreadcrumbs(): void {\n const originalError = console.error;\n\n console.error = (...args: unknown[]) => {\n coreAddBreadcrumb({\n category: \"console\",\n message: args.map(String).join(\" \"),\n level: \"error\",\n });\n originalError(...args);\n };\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":";;;;;;AA0CA,IAAM,qBAAA,GAA+C;AAAA,EACnD,mBAAA,EAAqB,IAAA;AAAA,EACrB,0BAAA,EAA4B,IAAA;AAAA,EAC5B,yBAAA,EAA2B;AAC7B,CAAA;AAeA,IAAM,eAAA,GAAkB,cAA2C,IAAI,CAAA;AAKhE,SAAS,WAAA,GAAoC;AAClD,EAAA,MAAM,OAAA,GAAU,WAAW,eAAe,CAAA;AAC1C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,oDAAoD,CAAA;AAAA,EACtE;AACA,EAAA,OAAO,OAAA;AACT;AAKO,SAAS,mBAAA,GAGJ;AACV,EAAA,MAAM,EAAE,gBAAA,EAAAA,iBAAAA,EAAiB,GAAI,WAAA,EAAY;AACzC,EAAA,OAAOA,iBAAAA;AACT;AAKO,SAAS,iBAAA,GAGJ;AACV,EAAA,MAAM,EAAE,cAAA,EAAAC,eAAAA,EAAe,GAAI,WAAA,EAAY;AACvC,EAAA,OAAOA,eAAAA;AACT;AAwCO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAAuC;AACrC,EAAA,SAAA,CAAU,MAAM;AAEd,IAAA,MAAM,YAAY,YAAA,EAAa;AAC/B,IAAA,MAAM,gBAAgB,EAAE,GAAG,uBAAuB,GAAG,SAAA,EAAW,GAAG,OAAA,EAAQ;AAG3E,IAAA,IAAI,CAAC,cAAc,MAAA,EAAQ;AACzB,MAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,aAAA,EAAe;AAC1C,QAAA,OAAA,CAAQ,KAAK,qFAAqF,CAAA;AAAA,MACpG;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAI;AACF,MAAAC,IAAA,CAAS,aAAa,CAAA;AAAA,IACxB,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,aAAA,EAAe;AAC1C,QAAA,OAAA,CAAQ,KAAA,CAAM,qCAAqC,GAAG,CAAA;AAAA,MACxD;AACA,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,SAAS,SAAA,EAAU;AACzB,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,MAAA,CAAO,aAAa,OAAO,CAAA;AAAA,IACpC;AAGA,IAAA,IAAI,eAAA,GAAgD,IAAA;AACpD,IAAA,IAAI,oBAAA,GAAoD,IAAA;AACxD,IAAA,IAAI,yBAAA,GAA6E,IAAA;AAGjF,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,MAAA,IAAI,cAAc,mBAAA,EAAqB;AACrC,QAAA,eAAA,GAAkB,MAAA,CAAO,OAAA;AACzB,QAAA,MAAA,CAAO,UAAU,CAAC,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ,OAAO,KAAA,KAAU;AAC1D,UAAA,IAAI,KAAA,EAAO;AACT,YAAAC,gBAAA,CAAqB,KAAA,EAAO;AAAA,cAC1B,IAAA,EAAM,EAAE,SAAA,EAAW,gBAAA;AAAiB,aACrC,CAAA;AAAA,UACH;AACA,UAAA,IAAI,eAAA,EAAiB;AACnB,YAAA,OAAO,eAAA,CAAgB,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ,OAAO,KAAK,CAAA;AAAA,UAC9D;AACA,UAAA,OAAO,KAAA;AAAA,QACT,CAAA;AAAA,MACF;AAEA,MAAA,IAAI,cAAc,0BAAA,EAA4B;AAC5C,QAAA,yBAAA,GAA4B,CAAC,KAAA,KAAiC;AAC5D,UAAA,MAAM,KAAA,GACJ,KAAA,CAAM,MAAA,YAAkB,KAAA,GACpB,KAAA,CAAM,MAAA,GACN,IAAI,KAAA,CAAM,MAAA,CAAO,KAAA,CAAM,MAAM,CAAC,CAAA;AACpC,UAAAA,gBAAA,CAAqB,KAAA,EAAO;AAAA,YAC1B,IAAA,EAAM,EAAE,SAAA,EAAW,oBAAA;AAAqB,WACzC,CAAA;AAAA,QACH,CAAA;AACA,QAAA,MAAA,CAAO,gBAAA,CAAiB,sBAAsB,yBAAyB,CAAA;AAAA,MACzE;AAEA,MAAA,IAAI,cAAc,yBAAA,EAA2B;AAC3C,QAAA,oBAAA,GAAuB,OAAA,CAAQ,KAAA;AAC/B,QAAA,OAAA,CAAQ,KAAA,GAAQ,IAAI,IAAA,KAAoB;AACtC,UAAAC,aAAA,CAAkB;AAAA,YAChB,QAAA,EAAU,SAAA;AAAA,YACV,SAAS,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,YAClC,KAAA,EAAO;AAAA,WACR,CAAA;AACD,UAAA,oBAAA,CAAsB,GAAG,IAAI,CAAA;AAAA,QAC/B,CAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,cAAc,KAAA,EAAO;AACvB,MAAA,OAAA,CAAQ,IAAI,kCAAkC,CAAA;AAAA,IAChD;AAGA,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEjC,QAAA,IAAI,eAAA,KAAoB,IAAA,IAAQ,aAAA,CAAc,mBAAA,EAAqB;AACjE,UAAA,MAAA,CAAO,OAAA,GAAU,eAAA;AAAA,QACnB;AAGA,QAAA,IAAI,yBAAA,IAA6B,cAAc,0BAAA,EAA4B;AACzE,UAAA,MAAA,CAAO,mBAAA,CAAoB,sBAAsB,yBAAyB,CAAA;AAAA,QAC5E;AAGA,QAAA,IAAI,oBAAA,KAAyB,IAAA,IAAQ,aAAA,CAAc,yBAAA,EAA2B;AAC5E,UAAA,OAAA,CAAQ,KAAA,GAAQ,oBAAA;AAAA,QAClB;AAAA,MACF;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,MAAMJ,iBAAAA,GAAmB,WAAA;AAAA,IACvB,CAAC,OAAc,OAAA,KAAkC;AAC/C,MAAA,OAAOG,gBAAA,CAAqB,OAAO,OAAO,CAAA;AAAA,IAC5C,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAMF,eAAAA,GAAiB,WAAA;AAAA,IACrB,CAAC,SAAiB,KAAA,KAAgC;AAChD,MAAA,OAAOI,cAAA,CAAmB,SAAS,KAAK,CAAA;AAAA,IAC1C,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAMC,cAAAA,GAAgB,WAAA;AAAA,IACpB,CAAC,UAAA,KAA8C;AAC7C,MAAAF,aAAA,CAAkB,UAAU,CAAA;AAAA,IAC9B,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAMG,QAAAA,GAAU,WAAA,CAAY,CAAC,IAAA,KAA6B;AACxD,IAAAC,OAAA,CAAY,IAAI,CAAA;AAAA,EAClB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAMC,OAAAA,GAAS,WAAA,CAAY,CAAC,GAAA,EAAa,KAAA,KAAkB;AACzD,IAAAC,MAAA,CAAW,KAAK,KAAK,CAAA;AAAA,EACvB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAMC,SAAAA,GAAW,WAAA,CAAY,CAAC,GAAA,EAAa,KAAA,KAAmB;AAC5D,IAAAC,QAAA,CAAa,KAAK,KAAK,CAAA;AAAA,EACzB,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,YAAA,GAAe,OAAA;AAAA,IACnB,OAAO;AAAA,MACL,QAAQ,SAAA,EAAU;AAAA,MAClB,gBAAA,EAAAZ,iBAAAA;AAAA,MACA,cAAA,EAAAC,eAAAA;AAAA,MACA,aAAA,EAAAK,cAAAA;AAAA,MACA,OAAA,EAAAC,QAAAA;AAAA,MACA,MAAA,EAAAE,OAAAA;AAAA,MACA,QAAA,EAAAE;AAAA,KACF,CAAA;AAAA,IACA,CAACX,iBAAAA,EAAkBC,eAAAA,EAAgBK,cAAAA,EAAeC,QAAAA,EAASE,SAAQE,SAAQ;AAAA,GAC7E;AAEA,EAAA,uBACE,GAAA,CAAC,eAAA,CAAgB,QAAA,EAAhB,EAAyB,KAAA,EAAO,YAAA,EAC/B,QAAA,kBAAA,GAAA,CAAC,aAAA,EAAA,EAAc,QAAA,EAAoB,OAAA,EAChC,QAAA,EACH,CAAA,EACF,CAAA;AAEJ;AAmBA,IAAM,aAAA,GAAN,cAA4B,SAAA,CAAkD;AAAA,EAC5E,YAAY,KAAA,EAA2B;AACrC,IAAA,KAAA,CAAM,KAAK,CAAA;AACX,IAAA,IAAA,CAAK,KAAA,GAAQ,EAAE,QAAA,EAAU,KAAA,EAAO,OAAO,IAAA,EAAK;AAAA,EAC9C;AAAA,EAEA,OAAO,yBAAyB,KAAA,EAAkC;AAChE,IAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,KAAA,EAAM;AAAA,EACjC;AAAA,EAEA,iBAAA,CAAkB,OAAc,SAAA,EAA4B;AAE1D,IAAAR,gBAAA,CAAqB,KAAA,EAAO;AAAA,MAC1B,IAAA,EAAM,EAAE,SAAA,EAAW,qBAAA,EAAsB;AAAA,MACzC,KAAA,EAAO;AAAA,QACL,gBAAgB,SAAA,CAAU;AAAA;AAC5B,KACD,CAAA;AAGD,IAAA,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,KAAA,EAAO,SAAS,CAAA;AAAA,EACvC;AAAA,EAEA,QAAQ,MAAY;AAClB,IAAA,IAAA,CAAK,SAAS,EAAE,QAAA,EAAU,KAAA,EAAO,KAAA,EAAO,MAAM,CAAA;AAAA,EAChD,CAAA;AAAA,EAEA,MAAA,GAAoB;AAClB,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,QAAA,IAAY,IAAA,CAAK,MAAM,KAAA,EAAO;AAC3C,MAAA,MAAM,EAAE,QAAA,EAAS,GAAI,IAAA,CAAK,KAAA;AAE1B,MAAA,IAAI,OAAO,aAAa,UAAA,EAAY;AAClC,QAAA,OAAO,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,KAAA,EAAO,KAAK,KAAK,CAAA;AAAA,MAC9C;AAEA,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,OAAO,QAAA;AAAA,MACT;AAEA,MAAA,uBACE,IAAA,CAAC,SAAI,KAAA,EAAO,EAAE,SAAS,MAAA,EAAQ,UAAA,EAAY,cAAa,EACtD,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,QAAG,QAAA,EAAA,sBAAA,EAAoB,CAAA;AAAA,wBACxB,GAAA,CAAC,GAAA,EAAA,EAAG,QAAA,EAAA,IAAA,CAAK,KAAA,CAAM,MAAM,OAAA,EAAQ,CAAA;AAAA,wBAC7B,GAAA,CAAC,QAAA,EAAA,EAAO,OAAA,EAAS,IAAA,CAAK,OAAO,QAAA,EAAA,WAAA,EAAS;AAAA,OAAA,EACxC,CAAA;AAAA,IAEJ;AAEA,IAAA,OAAO,KAAK,KAAA,CAAM,QAAA;AAAA,EACpB;AACF;AAUO,SAAS,yBAAA,CACd,kBACA,OAAA,EAIwB;AACxB,EAAA,MAAM,iBAAA,GAAoB,CAAC,KAAA,qBACzB,GAAA,CAAC,iBAAc,QAAA,EAAU,OAAA,EAAS,QAAA,EAAU,OAAA,EAAS,SAAS,OAAA,EAC5D,QAAA,kBAAA,GAAA,CAAC,gBAAA,EAAA,EAAkB,GAAG,OAAO,CAAA,EAC/B,CAAA;AAGF,EAAA,iBAAA,CAAkB,cAAc,CAAA,0BAAA,EAC9B,gBAAA,CAAiB,WAAA,IAAe,gBAAA,CAAiB,QAAQ,WAC3D,CAAA,CAAA,CAAA;AAEA,EAAA,OAAO,iBAAA;AACT","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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bugwatch/react",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Bugwatch SDK for React applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",