@bugwatch/react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,89 @@
1
+ import React, { Component, ReactNode, ErrorInfo } from 'react';
2
+ import { BugwatchOptions, BugwatchClient, ErrorEvent, Breadcrumb, UserContext } from '@bugwatch/core';
3
+ export { Breadcrumb, BugwatchOptions, ErrorEvent, UserContext, addBreadcrumb, captureException, captureMessage, getClient, init, setExtra, setTag, setUser } from '@bugwatch/core';
4
+
5
+ /**
6
+ * React-specific SDK options
7
+ */
8
+ interface ReactOptions extends BugwatchOptions {
9
+ /** Capture window.onerror events */
10
+ captureGlobalErrors?: boolean;
11
+ /** Capture unhandled promise rejections */
12
+ captureUnhandledRejections?: boolean;
13
+ /** Capture console.error as breadcrumbs */
14
+ captureConsoleBreadcrumbs?: boolean;
15
+ }
16
+ /**
17
+ * Bugwatch context
18
+ */
19
+ interface BugwatchContextValue {
20
+ client: BugwatchClient | null;
21
+ captureException: (error: Error, context?: Partial<ErrorEvent>) => string;
22
+ captureMessage: (message: string, level?: ErrorEvent["level"]) => string;
23
+ addBreadcrumb: (breadcrumb: Omit<Breadcrumb, "timestamp">) => void;
24
+ setUser: (user: UserContext | null) => void;
25
+ setTag: (key: string, value: string) => void;
26
+ setExtra: (key: string, value: unknown) => void;
27
+ }
28
+ /**
29
+ * Hook to access Bugwatch SDK
30
+ */
31
+ declare function useBugwatch(): BugwatchContextValue;
32
+ /**
33
+ * Hook to capture exceptions
34
+ */
35
+ declare function useCaptureException(): (error: Error, context?: Partial<ErrorEvent>) => string;
36
+ /**
37
+ * Hook to capture messages
38
+ */
39
+ declare function useCaptureMessage(): (message: string, level?: ErrorEvent["level"]) => string;
40
+ /**
41
+ * Props for BugwatchProvider
42
+ */
43
+ interface BugwatchProviderProps {
44
+ /** SDK configuration options */
45
+ options: ReactOptions;
46
+ /** Child components */
47
+ children: ReactNode;
48
+ /** Optional fallback UI for error boundary */
49
+ fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
50
+ /** Called when an error is caught by the error boundary */
51
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
52
+ }
53
+ /**
54
+ * Bugwatch Provider component
55
+ * Initializes the SDK and provides context to child components
56
+ */
57
+ declare function BugwatchProvider({ options, children, fallback, onError, }: BugwatchProviderProps): JSX.Element;
58
+ /**
59
+ * Error Boundary Props
60
+ */
61
+ interface ErrorBoundaryProps {
62
+ children: ReactNode;
63
+ fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
64
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
65
+ }
66
+ interface ErrorBoundaryState {
67
+ hasError: boolean;
68
+ error: Error | null;
69
+ }
70
+ /**
71
+ * Error Boundary component
72
+ */
73
+ declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
74
+ constructor(props: ErrorBoundaryProps);
75
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
76
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
77
+ reset: () => void;
78
+ render(): ReactNode;
79
+ }
80
+
81
+ /**
82
+ * Higher-order component for error boundary
83
+ */
84
+ declare function withBugwatchErrorBoundary<P extends object>(WrappedComponent: React.ComponentType<P>, options?: {
85
+ fallback?: ErrorBoundaryProps["fallback"];
86
+ onError?: ErrorBoundaryProps["onError"];
87
+ }): React.ComponentType<P>;
88
+
89
+ export { ErrorBoundary as BugwatchErrorBoundary, BugwatchProvider, type ReactOptions, useBugwatch, useCaptureException, useCaptureMessage, withBugwatchErrorBoundary };
@@ -0,0 +1,89 @@
1
+ import React, { Component, ReactNode, ErrorInfo } from 'react';
2
+ import { BugwatchOptions, BugwatchClient, ErrorEvent, Breadcrumb, UserContext } from '@bugwatch/core';
3
+ export { Breadcrumb, BugwatchOptions, ErrorEvent, UserContext, addBreadcrumb, captureException, captureMessage, getClient, init, setExtra, setTag, setUser } from '@bugwatch/core';
4
+
5
+ /**
6
+ * React-specific SDK options
7
+ */
8
+ interface ReactOptions extends BugwatchOptions {
9
+ /** Capture window.onerror events */
10
+ captureGlobalErrors?: boolean;
11
+ /** Capture unhandled promise rejections */
12
+ captureUnhandledRejections?: boolean;
13
+ /** Capture console.error as breadcrumbs */
14
+ captureConsoleBreadcrumbs?: boolean;
15
+ }
16
+ /**
17
+ * Bugwatch context
18
+ */
19
+ interface BugwatchContextValue {
20
+ client: BugwatchClient | null;
21
+ captureException: (error: Error, context?: Partial<ErrorEvent>) => string;
22
+ captureMessage: (message: string, level?: ErrorEvent["level"]) => string;
23
+ addBreadcrumb: (breadcrumb: Omit<Breadcrumb, "timestamp">) => void;
24
+ setUser: (user: UserContext | null) => void;
25
+ setTag: (key: string, value: string) => void;
26
+ setExtra: (key: string, value: unknown) => void;
27
+ }
28
+ /**
29
+ * Hook to access Bugwatch SDK
30
+ */
31
+ declare function useBugwatch(): BugwatchContextValue;
32
+ /**
33
+ * Hook to capture exceptions
34
+ */
35
+ declare function useCaptureException(): (error: Error, context?: Partial<ErrorEvent>) => string;
36
+ /**
37
+ * Hook to capture messages
38
+ */
39
+ declare function useCaptureMessage(): (message: string, level?: ErrorEvent["level"]) => string;
40
+ /**
41
+ * Props for BugwatchProvider
42
+ */
43
+ interface BugwatchProviderProps {
44
+ /** SDK configuration options */
45
+ options: ReactOptions;
46
+ /** Child components */
47
+ children: ReactNode;
48
+ /** Optional fallback UI for error boundary */
49
+ fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
50
+ /** Called when an error is caught by the error boundary */
51
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
52
+ }
53
+ /**
54
+ * Bugwatch Provider component
55
+ * Initializes the SDK and provides context to child components
56
+ */
57
+ declare function BugwatchProvider({ options, children, fallback, onError, }: BugwatchProviderProps): JSX.Element;
58
+ /**
59
+ * Error Boundary Props
60
+ */
61
+ interface ErrorBoundaryProps {
62
+ children: ReactNode;
63
+ fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
64
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
65
+ }
66
+ interface ErrorBoundaryState {
67
+ hasError: boolean;
68
+ error: Error | null;
69
+ }
70
+ /**
71
+ * Error Boundary component
72
+ */
73
+ declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
74
+ constructor(props: ErrorBoundaryProps);
75
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
76
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
77
+ reset: () => void;
78
+ render(): ReactNode;
79
+ }
80
+
81
+ /**
82
+ * Higher-order component for error boundary
83
+ */
84
+ declare function withBugwatchErrorBoundary<P extends object>(WrappedComponent: React.ComponentType<P>, options?: {
85
+ fallback?: ErrorBoundaryProps["fallback"];
86
+ onError?: ErrorBoundaryProps["onError"];
87
+ }): React.ComponentType<P>;
88
+
89
+ export { ErrorBoundary as BugwatchErrorBoundary, BugwatchProvider, type ReactOptions, useBugwatch, useCaptureException, useCaptureMessage, withBugwatchErrorBoundary };
package/dist/index.js ADDED
@@ -0,0 +1,211 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var core = require('@bugwatch/core');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ // src/index.tsx
8
+ var DEFAULT_REACT_OPTIONS = {
9
+ captureGlobalErrors: true,
10
+ captureUnhandledRejections: true,
11
+ captureConsoleBreadcrumbs: true
12
+ };
13
+ var BugwatchContext = react.createContext(null);
14
+ function useBugwatch() {
15
+ const context = react.useContext(BugwatchContext);
16
+ if (!context) {
17
+ throw new Error("useBugwatch must be used within a BugwatchProvider");
18
+ }
19
+ return context;
20
+ }
21
+ function useCaptureException() {
22
+ const { captureException: captureException2 } = useBugwatch();
23
+ return captureException2;
24
+ }
25
+ function useCaptureMessage() {
26
+ const { captureMessage: captureMessage2 } = useBugwatch();
27
+ return captureMessage2;
28
+ }
29
+ function BugwatchProvider({
30
+ options,
31
+ children,
32
+ fallback,
33
+ onError
34
+ }) {
35
+ react.useEffect(() => {
36
+ const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...options };
37
+ core.init(mergedOptions);
38
+ const client = core.getClient();
39
+ if (client) {
40
+ client.setTag("framework", "react");
41
+ }
42
+ if (typeof window !== "undefined") {
43
+ if (mergedOptions.captureGlobalErrors) {
44
+ setupGlobalErrorHandler();
45
+ }
46
+ if (mergedOptions.captureUnhandledRejections) {
47
+ setupUnhandledRejectionHandler();
48
+ }
49
+ if (mergedOptions.captureConsoleBreadcrumbs) {
50
+ setupConsoleBreadcrumbs();
51
+ }
52
+ }
53
+ if (mergedOptions.debug) {
54
+ console.log("[Bugwatch] React SDK initialized");
55
+ }
56
+ }, [options]);
57
+ const captureException2 = react.useCallback(
58
+ (error, context) => {
59
+ return core.captureException(error, context);
60
+ },
61
+ []
62
+ );
63
+ const captureMessage2 = react.useCallback(
64
+ (message, level) => {
65
+ return core.captureMessage(message, level);
66
+ },
67
+ []
68
+ );
69
+ const addBreadcrumb2 = react.useCallback(
70
+ (breadcrumb) => {
71
+ core.addBreadcrumb(breadcrumb);
72
+ },
73
+ []
74
+ );
75
+ const setUser2 = react.useCallback((user) => {
76
+ core.setUser(user);
77
+ }, []);
78
+ const setTag2 = react.useCallback((key, value) => {
79
+ core.setTag(key, value);
80
+ }, []);
81
+ const setExtra2 = react.useCallback((key, value) => {
82
+ core.setExtra(key, value);
83
+ }, []);
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
+ };
93
+ return /* @__PURE__ */ jsxRuntime.jsx(BugwatchContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { fallback, onError, children }) });
94
+ }
95
+ var ErrorBoundary = class extends react.Component {
96
+ constructor(props) {
97
+ super(props);
98
+ this.state = { hasError: false, error: null };
99
+ }
100
+ static getDerivedStateFromError(error) {
101
+ return { hasError: true, error };
102
+ }
103
+ componentDidCatch(error, errorInfo) {
104
+ core.captureException(error, {
105
+ tags: { mechanism: "react.errorBoundary" },
106
+ extra: {
107
+ componentStack: errorInfo.componentStack
108
+ }
109
+ });
110
+ this.props.onError?.(error, errorInfo);
111
+ }
112
+ reset = () => {
113
+ this.setState({ hasError: false, error: null });
114
+ };
115
+ render() {
116
+ if (this.state.hasError && this.state.error) {
117
+ const { fallback } = this.props;
118
+ if (typeof fallback === "function") {
119
+ return fallback(this.state.error, this.reset);
120
+ }
121
+ if (fallback) {
122
+ return fallback;
123
+ }
124
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "20px", fontFamily: "sans-serif" }, children: [
125
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { children: "Something went wrong" }),
126
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: this.state.error.message }),
127
+ /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: this.reset, children: "Try again" })
128
+ ] });
129
+ }
130
+ return this.props.children;
131
+ }
132
+ };
133
+ function withBugwatchErrorBoundary(WrappedComponent, options) {
134
+ const WithErrorBoundary = (props) => /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { fallback: options?.fallback, onError: options?.onError, children: /* @__PURE__ */ jsxRuntime.jsx(WrappedComponent, { ...props }) });
135
+ WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name || "Component"})`;
136
+ return WithErrorBoundary;
137
+ }
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
+
172
+ Object.defineProperty(exports, "addBreadcrumb", {
173
+ enumerable: true,
174
+ get: function () { return core.addBreadcrumb; }
175
+ });
176
+ Object.defineProperty(exports, "captureException", {
177
+ enumerable: true,
178
+ get: function () { return core.captureException; }
179
+ });
180
+ Object.defineProperty(exports, "captureMessage", {
181
+ enumerable: true,
182
+ get: function () { return core.captureMessage; }
183
+ });
184
+ Object.defineProperty(exports, "getClient", {
185
+ enumerable: true,
186
+ get: function () { return core.getClient; }
187
+ });
188
+ Object.defineProperty(exports, "init", {
189
+ enumerable: true,
190
+ get: function () { return core.init; }
191
+ });
192
+ Object.defineProperty(exports, "setExtra", {
193
+ enumerable: true,
194
+ get: function () { return core.setExtra; }
195
+ });
196
+ Object.defineProperty(exports, "setTag", {
197
+ enumerable: true,
198
+ get: function () { return core.setTag; }
199
+ });
200
+ Object.defineProperty(exports, "setUser", {
201
+ enumerable: true,
202
+ get: function () { return core.setUser; }
203
+ });
204
+ exports.BugwatchErrorBoundary = ErrorBoundary;
205
+ exports.BugwatchProvider = BugwatchProvider;
206
+ exports.useBugwatch = useBugwatch;
207
+ exports.useCaptureException = useCaptureException;
208
+ exports.useCaptureMessage = useCaptureMessage;
209
+ exports.withBugwatchErrorBoundary = withBugwatchErrorBoundary;
210
+ //# sourceMappingURL=index.js.map
211
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,173 @@
1
+ import { createContext, useContext, useEffect, useCallback, Component } from 'react';
2
+ import { init, getClient, captureException, captureMessage, addBreadcrumb, setUser, setTag, setExtra } from '@bugwatch/core';
3
+ export { addBreadcrumb, captureException, captureMessage, getClient, init, setExtra, setTag, setUser } from '@bugwatch/core';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ // src/index.tsx
7
+ var DEFAULT_REACT_OPTIONS = {
8
+ captureGlobalErrors: true,
9
+ captureUnhandledRejections: true,
10
+ captureConsoleBreadcrumbs: true
11
+ };
12
+ var BugwatchContext = createContext(null);
13
+ function useBugwatch() {
14
+ const context = useContext(BugwatchContext);
15
+ if (!context) {
16
+ throw new Error("useBugwatch must be used within a BugwatchProvider");
17
+ }
18
+ return context;
19
+ }
20
+ function useCaptureException() {
21
+ const { captureException: captureException2 } = useBugwatch();
22
+ return captureException2;
23
+ }
24
+ function useCaptureMessage() {
25
+ const { captureMessage: captureMessage2 } = useBugwatch();
26
+ return captureMessage2;
27
+ }
28
+ function BugwatchProvider({
29
+ options,
30
+ children,
31
+ fallback,
32
+ onError
33
+ }) {
34
+ useEffect(() => {
35
+ const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...options };
36
+ init(mergedOptions);
37
+ const client = getClient();
38
+ if (client) {
39
+ client.setTag("framework", "react");
40
+ }
41
+ if (typeof window !== "undefined") {
42
+ if (mergedOptions.captureGlobalErrors) {
43
+ setupGlobalErrorHandler();
44
+ }
45
+ if (mergedOptions.captureUnhandledRejections) {
46
+ setupUnhandledRejectionHandler();
47
+ }
48
+ if (mergedOptions.captureConsoleBreadcrumbs) {
49
+ setupConsoleBreadcrumbs();
50
+ }
51
+ }
52
+ if (mergedOptions.debug) {
53
+ console.log("[Bugwatch] React SDK initialized");
54
+ }
55
+ }, [options]);
56
+ const captureException2 = useCallback(
57
+ (error, context) => {
58
+ return captureException(error, context);
59
+ },
60
+ []
61
+ );
62
+ const captureMessage2 = useCallback(
63
+ (message, level) => {
64
+ return captureMessage(message, level);
65
+ },
66
+ []
67
+ );
68
+ const addBreadcrumb2 = useCallback(
69
+ (breadcrumb) => {
70
+ addBreadcrumb(breadcrumb);
71
+ },
72
+ []
73
+ );
74
+ const setUser2 = useCallback((user) => {
75
+ setUser(user);
76
+ }, []);
77
+ const setTag2 = useCallback((key, value) => {
78
+ setTag(key, value);
79
+ }, []);
80
+ const setExtra2 = useCallback((key, value) => {
81
+ setExtra(key, value);
82
+ }, []);
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
+ };
92
+ return /* @__PURE__ */ jsx(BugwatchContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(ErrorBoundary, { fallback, onError, children }) });
93
+ }
94
+ var ErrorBoundary = class extends Component {
95
+ constructor(props) {
96
+ super(props);
97
+ this.state = { hasError: false, error: null };
98
+ }
99
+ static getDerivedStateFromError(error) {
100
+ return { hasError: true, error };
101
+ }
102
+ componentDidCatch(error, errorInfo) {
103
+ captureException(error, {
104
+ tags: { mechanism: "react.errorBoundary" },
105
+ extra: {
106
+ componentStack: errorInfo.componentStack
107
+ }
108
+ });
109
+ this.props.onError?.(error, errorInfo);
110
+ }
111
+ reset = () => {
112
+ this.setState({ hasError: false, error: null });
113
+ };
114
+ render() {
115
+ if (this.state.hasError && this.state.error) {
116
+ const { fallback } = this.props;
117
+ if (typeof fallback === "function") {
118
+ return fallback(this.state.error, this.reset);
119
+ }
120
+ if (fallback) {
121
+ return fallback;
122
+ }
123
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "20px", fontFamily: "sans-serif" }, children: [
124
+ /* @__PURE__ */ jsx("h2", { children: "Something went wrong" }),
125
+ /* @__PURE__ */ jsx("p", { children: this.state.error.message }),
126
+ /* @__PURE__ */ jsx("button", { onClick: this.reset, children: "Try again" })
127
+ ] });
128
+ }
129
+ return this.props.children;
130
+ }
131
+ };
132
+ function withBugwatchErrorBoundary(WrappedComponent, options) {
133
+ const WithErrorBoundary = (props) => /* @__PURE__ */ jsx(ErrorBoundary, { fallback: options?.fallback, onError: options?.onError, children: /* @__PURE__ */ jsx(WrappedComponent, { ...props }) });
134
+ WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name || "Component"})`;
135
+ return WithErrorBoundary;
136
+ }
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
+
171
+ export { ErrorBoundary as BugwatchErrorBoundary, BugwatchProvider, useBugwatch, useCaptureException, useCaptureMessage, withBugwatchErrorBoundary };
172
+ //# sourceMappingURL=index.mjs.map
173
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.tsx"],"names":["captureException","captureMessage","coreInit","coreCaptureException","coreCaptureMessage","addBreadcrumb","coreAddBreadcrumb","setUser","coreSetUser","setTag","coreSetTag","setExtra","coreSetExtra"],"mappings":";;;;;;AAwCA,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;AAoBO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAAuC;AACrC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,aAAA,GAAgB,EAAE,GAAG,qBAAA,EAAuB,GAAG,OAAA,EAAQ;AAC7D,IAAAC,IAAA,CAAS,aAAa,CAAA;AAGtB,IAAA,MAAM,SAAS,SAAA,EAAU;AACzB,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,MAAA,CAAO,aAAa,OAAO,CAAA;AAAA,IACpC;AAGA,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,MAAA,IAAI,cAAc,mBAAA,EAAqB;AACrC,QAAA,uBAAA,EAAwB;AAAA,MAC1B;AACA,MAAA,IAAI,cAAc,0BAAA,EAA4B;AAC5C,QAAA,8BAAA,EAA+B;AAAA,MACjC;AACA,MAAA,IAAI,cAAc,yBAAA,EAA2B;AAC3C,QAAA,uBAAA,EAAwB;AAAA,MAC1B;AAAA,IACF;AAEA,IAAA,IAAI,cAAc,KAAA,EAAO;AACvB,MAAA,OAAA,CAAQ,IAAI,kCAAkC,CAAA;AAAA,IAChD;AAAA,EACF,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,MAAMF,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,OAAOG,cAAA,CAAmB,SAAS,KAAK,CAAA;AAAA,IAC1C,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAMC,cAAAA,GAAgB,WAAA;AAAA,IACpB,CAAC,UAAA,KAA8C;AAC7C,MAAAC,aAAA,CAAkB,UAAU,CAAA;AAAA,IAC9B,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAMC,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;AAEL,EAAA,MAAM,YAAA,GAAqC;AAAA,IACzC,QAAQ,SAAA,EAAU;AAAA,IAClB,gBAAA,EAAAZ,iBAAAA;AAAA,IACA,cAAA,EAAAC,eAAAA;AAAA,IACA,aAAA,EAAAI,cAAAA;AAAA,IACA,OAAA,EAAAE,QAAAA;AAAA,IACA,MAAA,EAAAE,OAAAA;AAAA,IACA,QAAA,EAAAE;AAAA,GACF;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;AAGA,SAAS,uBAAA,GAAgC;AACvC,EAAA,MAAM,kBAAkB,MAAA,CAAO,OAAA;AAE/B,EAAA,MAAA,CAAO,UAAU,CAAC,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ,OAAO,KAAA,KAAU;AAC1D,IAAA,IAAI,KAAA,EAAO;AACT,MAAAA,gBAAA,CAAqB,KAAA,EAAO;AAAA,QAC1B,IAAA,EAAM,EAAE,SAAA,EAAW,gBAAA;AAAiB,OACrC,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,OAAO,eAAA,CAAgB,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ,OAAO,KAAK,CAAA;AAAA,IAC9D;AAEA,IAAA,OAAO,KAAA;AAAA,EACT,CAAA;AACF;AAEA,SAAS,8BAAA,GAAuC;AAC9C,EAAA,MAAA,CAAO,gBAAA,CAAiB,oBAAA,EAAsB,CAAC,KAAA,KAAU;AACvD,IAAA,MAAM,KAAA,GACJ,KAAA,CAAM,MAAA,YAAkB,KAAA,GACpB,KAAA,CAAM,MAAA,GACN,IAAI,KAAA,CAAM,MAAA,CAAO,KAAA,CAAM,MAAM,CAAC,CAAA;AAEpC,IAAAA,gBAAA,CAAqB,KAAA,EAAO;AAAA,MAC1B,IAAA,EAAM,EAAE,SAAA,EAAW,oBAAA;AAAqB,KACzC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAEA,SAAS,uBAAA,GAAgC;AACvC,EAAA,MAAM,gBAAgB,OAAA,CAAQ,KAAA;AAE9B,EAAA,OAAA,CAAQ,KAAA,GAAQ,IAAI,IAAA,KAAoB;AACtC,IAAAG,aAAA,CAAkB;AAAA,MAChB,QAAA,EAAU,SAAA;AAAA,MACV,SAAS,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,MAClC,KAAA,EAAO;AAAA,KACR,CAAA;AACD,IAAA,aAAA,CAAc,GAAG,IAAI,CAAA;AAAA,EACvB,CAAA;AACF","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"]}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@bugwatch/react",
3
+ "version": "0.1.0",
4
+ "description": "Bugwatch SDK for React applications",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "dev": "tsup --watch",
21
+ "typecheck": "tsc --noEmit",
22
+ "clean": "rm -rf dist",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest"
25
+ },
26
+ "dependencies": {
27
+ "@bugwatch/core": "*"
28
+ },
29
+ "devDependencies": {
30
+ "@testing-library/jest-dom": "^6.9.1",
31
+ "@testing-library/react": "^16.3.1",
32
+ "@types/react": "^18.0.0",
33
+ "@types/react-dom": "^19.0.2",
34
+ "jsdom": "^27.4.0",
35
+ "react": "^18.0.0",
36
+ "react-dom": "^19.0.0",
37
+ "tsup": "^8.0.0",
38
+ "typescript": "^5.3.0"
39
+ },
40
+ "peerDependencies": {
41
+ "react": ">=17.0.0"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "https://github.com/bugwatch/bugwatch.git",
49
+ "directory": "packages/sdk/react"
50
+ },
51
+ "license": "MIT",
52
+ "keywords": [
53
+ "bugwatch",
54
+ "error-tracking",
55
+ "monitoring",
56
+ "react",
57
+ "sdk"
58
+ ]
59
+ }