@bugwatch/react 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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
@@ -4,7 +4,6 @@ var react = require('react');
4
4
  var core = require('@bugwatch/core');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
7
- // src/index.tsx
8
7
  var DEFAULT_REACT_OPTIONS = {
9
8
  captureGlobalErrors: true,
10
9
  captureUnhandledRejections: true,
@@ -32,28 +31,90 @@ function BugwatchProvider({
32
31
  fallback,
33
32
  onError
34
33
  }) {
34
+ const optionsKey = react.useMemo(
35
+ () => options ? JSON.stringify(options) : "",
36
+ [options]
37
+ );
38
+ const optionsRef = react.useRef(options);
39
+ optionsRef.current = options;
35
40
  react.useEffect(() => {
36
- const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...options };
37
- core.init(mergedOptions);
41
+ const currentOptions = optionsRef.current;
42
+ const envConfig = core.getEnvConfig();
43
+ const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...currentOptions };
44
+ if (!mergedOptions.apiKey) {
45
+ if (process.env.NODE_ENV === "development") {
46
+ console.warn("[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey");
47
+ }
48
+ return;
49
+ }
50
+ try {
51
+ core.init(mergedOptions);
52
+ } catch (err) {
53
+ if (process.env.NODE_ENV === "development") {
54
+ console.error("[Bugwatch] Initialization failed:", err);
55
+ }
56
+ return;
57
+ }
38
58
  const client = core.getClient();
39
59
  if (client) {
40
60
  client.setTag("framework", "react");
41
61
  }
62
+ let originalOnError = null;
63
+ let originalConsoleError = null;
64
+ let unhandledRejectionHandler = null;
42
65
  if (typeof window !== "undefined") {
43
66
  if (mergedOptions.captureGlobalErrors) {
44
- setupGlobalErrorHandler();
67
+ originalOnError = window.onerror;
68
+ window.onerror = (message, source, lineno, colno, error) => {
69
+ if (error) {
70
+ core.captureException(error, {
71
+ tags: { mechanism: "window.onerror" }
72
+ });
73
+ }
74
+ if (originalOnError) {
75
+ return originalOnError(message, source, lineno, colno, error);
76
+ }
77
+ return false;
78
+ };
45
79
  }
46
80
  if (mergedOptions.captureUnhandledRejections) {
47
- setupUnhandledRejectionHandler();
81
+ unhandledRejectionHandler = (event) => {
82
+ const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
83
+ core.captureException(error, {
84
+ tags: { mechanism: "unhandledrejection" }
85
+ });
86
+ };
87
+ window.addEventListener("unhandledrejection", unhandledRejectionHandler);
48
88
  }
49
89
  if (mergedOptions.captureConsoleBreadcrumbs) {
50
- setupConsoleBreadcrumbs();
90
+ originalConsoleError = console.error;
91
+ console.error = (...args) => {
92
+ core.addBreadcrumb({
93
+ category: "console",
94
+ message: args.map(String).join(" "),
95
+ level: "error"
96
+ });
97
+ originalConsoleError(...args);
98
+ };
51
99
  }
52
100
  }
53
101
  if (mergedOptions.debug) {
54
102
  console.log("[Bugwatch] React SDK initialized");
55
103
  }
56
- }, [options]);
104
+ return () => {
105
+ if (typeof window !== "undefined") {
106
+ if (originalOnError !== null && mergedOptions.captureGlobalErrors) {
107
+ window.onerror = originalOnError;
108
+ }
109
+ if (unhandledRejectionHandler && mergedOptions.captureUnhandledRejections) {
110
+ window.removeEventListener("unhandledrejection", unhandledRejectionHandler);
111
+ }
112
+ if (originalConsoleError !== null && mergedOptions.captureConsoleBreadcrumbs) {
113
+ console.error = originalConsoleError;
114
+ }
115
+ }
116
+ };
117
+ }, [optionsKey]);
57
118
  const captureException2 = react.useCallback(
58
119
  (error, context) => {
59
120
  return core.captureException(error, context);
@@ -81,15 +142,18 @@ function BugwatchProvider({
81
142
  const setExtra2 = react.useCallback((key, value) => {
82
143
  core.setExtra(key, value);
83
144
  }, []);
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
- };
145
+ const contextValue = react.useMemo(
146
+ () => ({
147
+ client: core.getClient(),
148
+ captureException: captureException2,
149
+ captureMessage: captureMessage2,
150
+ addBreadcrumb: addBreadcrumb2,
151
+ setUser: setUser2,
152
+ setTag: setTag2,
153
+ setExtra: setExtra2
154
+ }),
155
+ [captureException2, captureMessage2, addBreadcrumb2, setUser2, setTag2, setExtra2]
156
+ );
93
157
  return /* @__PURE__ */ jsxRuntime.jsx(BugwatchContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { fallback, onError, children }) });
94
158
  }
95
159
  var ErrorBoundary = class extends react.Component {
@@ -135,39 +199,6 @@ function withBugwatchErrorBoundary(WrappedComponent, options) {
135
199
  WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name || "Component"})`;
136
200
  return WithErrorBoundary;
137
201
  }
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
202
 
172
203
  Object.defineProperty(exports, "addBreadcrumb", {
173
204
  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":";;;;;;;AAwCA,IAAM,qBAAA,GAA+C;AAAA,EACnD,mBAAA,EAAqB,IAAA;AAAA,EACrB,0BAAA,EAA4B,IAAA;AAAA,EAC5B,yBAAA,EAA2B;AAC7B,CAAA;AAeA,IAAM,eAAA,GAAkBA,oBAA2C,IAAI,CAAA;AAKhE,SAAS,WAAA,GAAoC;AAClD,EAAA,MAAM,OAAA,GAAUC,iBAAW,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,EAAAC,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,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,aAAA,GAAgB,EAAE,GAAG,qBAAA,EAAuB,GAAG,OAAA,EAAQ;AAC7D,IAAAC,SAAA,CAAS,aAAa,CAAA;AAGtB,IAAA,MAAM,SAASC,cAAA,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,MAAMJ,iBAAAA,GAAmBK,iBAAA;AAAA,IACvB,CAAC,OAAc,OAAA,KAAkC;AAC/C,MAAA,OAAOC,qBAAA,CAAqB,OAAO,OAAO,CAAA;AAAA,IAC5C,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAML,eAAAA,GAAiBI,iBAAA;AAAA,IACrB,CAAC,SAAiB,KAAA,KAAgC;AAChD,MAAA,OAAOE,mBAAA,CAAmB,SAAS,KAAK,CAAA;AAAA,IAC1C,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAMC,cAAAA,GAAgBH,iBAAA;AAAA,IACpB,CAAC,UAAA,KAA8C;AAC7C,MAAAI,kBAAA,CAAkB,UAAU,CAAA;AAAA,IAC9B,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAMC,QAAAA,GAAUL,iBAAA,CAAY,CAAC,IAAA,KAA6B;AACxD,IAAAM,YAAA,CAAY,IAAI,CAAA;AAAA,EAClB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAMC,OAAAA,GAASP,iBAAA,CAAY,CAAC,GAAA,EAAa,KAAA,KAAkB;AACzD,IAAAQ,WAAA,CAAW,KAAK,KAAK,CAAA;AAAA,EACvB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAMC,SAAAA,GAAWT,iBAAA,CAAY,CAAC,GAAA,EAAa,KAAA,KAAmB;AAC5D,IAAAU,aAAA,CAAa,KAAK,KAAK,CAAA;AAAA,EACzB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,YAAA,GAAqC;AAAA,IACzC,QAAQX,cAAA,EAAU;AAAA,IAClB,gBAAA,EAAAJ,iBAAAA;AAAA,IACA,cAAA,EAAAC,eAAAA;AAAA,IACA,aAAA,EAAAO,cAAAA;AAAA,IACA,OAAA,EAAAE,QAAAA;AAAA,IACA,MAAA,EAAAE,OAAAA;AAAA,IACA,QAAA,EAAAE;AAAA,GACF;AAEA,EAAA,uBACEE,cAAA,CAAC,eAAA,CAAgB,QAAA,EAAhB,EAAyB,KAAA,EAAO,YAAA,EAC/B,QAAA,kBAAAA,cAAA,CAAC,aAAA,EAAA,EAAc,QAAA,EAAoB,OAAA,EAChC,QAAA,EACH,CAAA,EACF,CAAA;AAEJ;AAmBA,IAAM,aAAA,GAAN,cAA4BC,eAAA,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,IAAAX,qBAAA,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,uBACEY,eAAA,CAAC,SAAI,KAAA,EAAO,EAAE,SAAS,MAAA,EAAQ,UAAA,EAAY,cAAa,EACtD,QAAA,EAAA;AAAA,wBAAAF,cAAA,CAAC,QAAG,QAAA,EAAA,sBAAA,EAAoB,CAAA;AAAA,wBACxBA,cAAA,CAAC,GAAA,EAAA,EAAG,QAAA,EAAA,IAAA,CAAK,KAAA,CAAM,MAAM,OAAA,EAAQ,CAAA;AAAA,wBAC7BA,cAAA,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,qBACzBA,cAAA,CAAC,iBAAc,QAAA,EAAU,OAAA,EAAS,QAAA,EAAU,OAAA,EAAS,SAAS,OAAA,EAC5D,QAAA,kBAAAA,cAAA,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,MAAAV,qBAAA,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,qBAAA,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,kBAAA,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.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","useMemo","useRef","useEffect","getEnvConfig","coreInit","getClient","coreCaptureException","coreAddBreadcrumb","useCallback","coreCaptureMessage","addBreadcrumb","setUser","coreSetUser","setTag","coreSetTag","setExtra","coreSetExtra","jsx","Component","jsxs"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\n\nimport React, {\n Component,\n createContext,\n useContext,\n useEffect,\n useCallback,\n useRef,\n useMemo,\n type ReactNode,\n type ErrorInfo,\n} from \"react\";\nimport {\n init as coreInit,\n getClient,\n getEnvConfig,\n captureException as coreCaptureException,\n captureMessage as coreCaptureMessage,\n addBreadcrumb as coreAddBreadcrumb,\n setUser as coreSetUser,\n setTag as coreSetTag,\n setExtra as coreSetExtra,\n type BugwatchOptions,\n type BugwatchClient,\n type UserContext,\n type Breadcrumb,\n type ErrorEvent,\n} from \"@bugwatch/core\";\n\n// Re-export types\nexport type { BugwatchOptions, UserContext, ErrorEvent, Breadcrumb } from \"@bugwatch/core\";\n\n/**\n * React-specific SDK options\n */\nexport interface ReactOptions extends BugwatchOptions {\n /** Capture window.onerror events */\n captureGlobalErrors?: boolean;\n /** Capture unhandled promise rejections */\n captureUnhandledRejections?: boolean;\n /** Capture console.error as breadcrumbs */\n captureConsoleBreadcrumbs?: boolean;\n}\n\nconst DEFAULT_REACT_OPTIONS: Partial<ReactOptions> = {\n captureGlobalErrors: true,\n captureUnhandledRejections: true,\n captureConsoleBreadcrumbs: true,\n};\n\n/**\n * Bugwatch context\n */\ninterface BugwatchContextValue {\n client: BugwatchClient | null;\n captureException: (error: Error, context?: Partial<ErrorEvent>) => string;\n captureMessage: (message: string, level?: ErrorEvent[\"level\"]) => string;\n addBreadcrumb: (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => void;\n setUser: (user: UserContext | null) => void;\n setTag: (key: string, value: string) => void;\n setExtra: (key: string, value: unknown) => void;\n}\n\nconst BugwatchContext = createContext<BugwatchContextValue | null>(null);\n\n/**\n * Hook to access Bugwatch SDK\n */\nexport function useBugwatch(): BugwatchContextValue {\n const context = useContext(BugwatchContext);\n if (!context) {\n throw new Error(\"useBugwatch must be used within a BugwatchProvider\");\n }\n return context;\n}\n\n/**\n * Hook to capture exceptions\n */\nexport function useCaptureException(): (\n error: Error,\n context?: Partial<ErrorEvent>\n) => string {\n const { captureException } = useBugwatch();\n return captureException;\n}\n\n/**\n * Hook to capture messages\n */\nexport function useCaptureMessage(): (\n message: string,\n level?: ErrorEvent[\"level\"]\n) => string {\n const { captureMessage } = useBugwatch();\n return captureMessage;\n}\n\n/**\n * Props for BugwatchProvider\n */\ninterface BugwatchProviderProps {\n /**\n * SDK configuration options.\n * Optional - if not provided, reads from environment variables:\n * - `BUGWATCH_API_KEY` - API key (required unless passed explicitly)\n * - `BUGWATCH_ENVIRONMENT` - Environment tag\n * - `BUGWATCH_RELEASE` - Release version\n * - `BUGWATCH_DEBUG` - Enable debug mode ('true')\n */\n options?: ReactOptions;\n /** Child components */\n children: ReactNode;\n /** Optional fallback UI for error boundary */\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Called when an error is caught by the error boundary */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\n/**\n * Bugwatch Provider component\n * Initializes the SDK and provides context to child components\n *\n * @example\n * ```tsx\n * // With BUGWATCH_API_KEY env var set\n * <BugwatchProvider>\n * <App />\n * </BugwatchProvider>\n *\n * // With explicit options\n * <BugwatchProvider options={{ apiKey: \"bw_live_xxxxx\" }}>\n * <App />\n * </BugwatchProvider>\n * ```\n */\nexport function BugwatchProvider({\n options,\n children,\n fallback,\n onError,\n}: BugwatchProviderProps): JSX.Element {\n // Serialize options to a stable string so useEffect doesn't re-run on every render.\n // Object identity of `options` changes every render if passed inline.\n const optionsKey = useMemo(\n () => (options ? JSON.stringify(options) : \"\"),\n [options]\n );\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n useEffect(() => {\n const currentOptions = optionsRef.current;\n\n // Merge env config with explicit options (explicit takes precedence)\n const envConfig = getEnvConfig();\n const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...currentOptions };\n\n // Skip initialization if no API key is available\n if (!mergedOptions.apiKey) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey');\n }\n return;\n }\n\n // Wrap initialization in try-catch for graceful degradation\n try {\n coreInit(mergedOptions);\n } catch (err) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Bugwatch] Initialization failed:', err);\n }\n return;\n }\n\n // Add React-specific tags\n const client = getClient();\n if (client) {\n client.setTag(\"framework\", \"react\");\n }\n\n // Store original handlers for cleanup\n let originalOnError: typeof window.onerror | null = null;\n let originalConsoleError: typeof console.error | null = null;\n let unhandledRejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;\n\n // Set up global error handlers\n if (typeof window !== \"undefined\") {\n if (mergedOptions.captureGlobalErrors) {\n originalOnError = window.onerror;\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n coreCaptureException(error, {\n tags: { mechanism: \"window.onerror\" },\n });\n }\n if (originalOnError) {\n return originalOnError(message, source, lineno, colno, error);\n }\n return false;\n };\n }\n\n if (mergedOptions.captureUnhandledRejections) {\n unhandledRejectionHandler = (event: PromiseRejectionEvent) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n coreCaptureException(error, {\n tags: { mechanism: \"unhandledrejection\" },\n });\n };\n window.addEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n if (mergedOptions.captureConsoleBreadcrumbs) {\n originalConsoleError = console.error;\n console.error = (...args: unknown[]) => {\n coreAddBreadcrumb({\n category: \"console\",\n message: args.map(String).join(\" \"),\n level: \"error\",\n });\n originalConsoleError!(...args);\n };\n }\n }\n\n if (mergedOptions.debug) {\n console.log(\"[Bugwatch] React SDK initialized\");\n }\n\n // Cleanup function to prevent memory leaks\n return () => {\n if (typeof window !== \"undefined\") {\n // Restore original window.onerror\n if (originalOnError !== null && mergedOptions.captureGlobalErrors) {\n window.onerror = originalOnError;\n }\n\n // Remove unhandled rejection listener\n if (unhandledRejectionHandler && mergedOptions.captureUnhandledRejections) {\n window.removeEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n // Restore original console.error\n if (originalConsoleError !== null && mergedOptions.captureConsoleBreadcrumbs) {\n console.error = originalConsoleError;\n }\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [optionsKey]);\n\n const captureException = useCallback(\n (error: Error, context?: Partial<ErrorEvent>) => {\n return coreCaptureException(error, context);\n },\n []\n );\n\n const captureMessage = useCallback(\n (message: string, level?: ErrorEvent[\"level\"]) => {\n return coreCaptureMessage(message, level);\n },\n []\n );\n\n const addBreadcrumb = useCallback(\n (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => {\n coreAddBreadcrumb(breadcrumb);\n },\n []\n );\n\n const setUser = useCallback((user: UserContext | null) => {\n coreSetUser(user);\n }, []);\n\n const setTag = useCallback((key: string, value: string) => {\n coreSetTag(key, value);\n }, []);\n\n const setExtra = useCallback((key: string, value: unknown) => {\n coreSetExtra(key, value);\n }, []);\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue = useMemo<BugwatchContextValue>(\n () => ({\n client: getClient(),\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n }),\n [captureException, captureMessage, addBreadcrumb, setUser, setTag, setExtra]\n );\n\n return (\n <BugwatchContext.Provider value={contextValue}>\n <ErrorBoundary fallback={fallback} onError={onError}>\n {children}\n </ErrorBoundary>\n </BugwatchContext.Provider>\n );\n}\n\n/**\n * Error Boundary Props\n */\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error Boundary component\n */\nclass ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n // Capture to Bugwatch\n coreCaptureException(error, {\n tags: { mechanism: \"react.errorBoundary\" },\n extra: {\n componentStack: errorInfo.componentStack,\n },\n });\n\n // Call custom handler\n this.props.onError?.(error, errorInfo);\n }\n\n reset = (): void => {\n this.setState({ hasError: false, error: null });\n };\n\n render(): ReactNode {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n\n if (typeof fallback === \"function\") {\n return fallback(this.state.error, this.reset);\n }\n\n if (fallback) {\n return fallback;\n }\n\n return (\n <div style={{ padding: \"20px\", fontFamily: \"sans-serif\" }}>\n <h2>Something went wrong</h2>\n <p>{this.state.error.message}</p>\n <button onClick={this.reset}>Try again</button>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\n/**\n * Standalone Error Boundary for custom use\n */\nexport { ErrorBoundary as BugwatchErrorBoundary };\n\n/**\n * Higher-order component for error boundary\n */\nexport function withBugwatchErrorBoundary<P extends object>(\n WrappedComponent: React.ComponentType<P>,\n options?: {\n fallback?: ErrorBoundaryProps[\"fallback\"];\n onError?: ErrorBoundaryProps[\"onError\"];\n }\n): React.ComponentType<P> {\n const WithErrorBoundary = (props: P) => (\n <ErrorBoundary fallback={options?.fallback} onError={options?.onError}>\n <WrappedComponent {...props} />\n </ErrorBoundary>\n );\n\n WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${\n WrappedComponent.displayName || WrappedComponent.name || \"Component\"\n })`;\n\n return WithErrorBoundary;\n}\n\n// Re-export core functions for convenience\nexport {\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n getClient,\n init,\n} from \"@bugwatch/core\";\n"]}
package/dist/index.mjs CHANGED
@@ -1,9 +1,8 @@
1
- import { createContext, useContext, useEffect, useCallback, Component } from 'react';
2
- import { init, getClient, captureException, captureMessage, addBreadcrumb, setUser, setTag, setExtra } from '@bugwatch/core';
1
+ import { createContext, useContext, useMemo, useRef, useEffect, useCallback, 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
 
6
- // src/index.tsx
7
6
  var DEFAULT_REACT_OPTIONS = {
8
7
  captureGlobalErrors: true,
9
8
  captureUnhandledRejections: true,
@@ -31,28 +30,90 @@ function BugwatchProvider({
31
30
  fallback,
32
31
  onError
33
32
  }) {
33
+ const optionsKey = useMemo(
34
+ () => options ? JSON.stringify(options) : "",
35
+ [options]
36
+ );
37
+ const optionsRef = useRef(options);
38
+ optionsRef.current = options;
34
39
  useEffect(() => {
35
- const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...options };
36
- init(mergedOptions);
40
+ const currentOptions = optionsRef.current;
41
+ const envConfig = getEnvConfig();
42
+ const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...currentOptions };
43
+ if (!mergedOptions.apiKey) {
44
+ if (process.env.NODE_ENV === "development") {
45
+ console.warn("[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey");
46
+ }
47
+ return;
48
+ }
49
+ try {
50
+ init(mergedOptions);
51
+ } catch (err) {
52
+ if (process.env.NODE_ENV === "development") {
53
+ console.error("[Bugwatch] Initialization failed:", err);
54
+ }
55
+ return;
56
+ }
37
57
  const client = getClient();
38
58
  if (client) {
39
59
  client.setTag("framework", "react");
40
60
  }
61
+ let originalOnError = null;
62
+ let originalConsoleError = null;
63
+ let unhandledRejectionHandler = null;
41
64
  if (typeof window !== "undefined") {
42
65
  if (mergedOptions.captureGlobalErrors) {
43
- setupGlobalErrorHandler();
66
+ originalOnError = window.onerror;
67
+ window.onerror = (message, source, lineno, colno, error) => {
68
+ if (error) {
69
+ captureException(error, {
70
+ tags: { mechanism: "window.onerror" }
71
+ });
72
+ }
73
+ if (originalOnError) {
74
+ return originalOnError(message, source, lineno, colno, error);
75
+ }
76
+ return false;
77
+ };
44
78
  }
45
79
  if (mergedOptions.captureUnhandledRejections) {
46
- setupUnhandledRejectionHandler();
80
+ unhandledRejectionHandler = (event) => {
81
+ const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
82
+ captureException(error, {
83
+ tags: { mechanism: "unhandledrejection" }
84
+ });
85
+ };
86
+ window.addEventListener("unhandledrejection", unhandledRejectionHandler);
47
87
  }
48
88
  if (mergedOptions.captureConsoleBreadcrumbs) {
49
- setupConsoleBreadcrumbs();
89
+ originalConsoleError = console.error;
90
+ console.error = (...args) => {
91
+ addBreadcrumb({
92
+ category: "console",
93
+ message: args.map(String).join(" "),
94
+ level: "error"
95
+ });
96
+ originalConsoleError(...args);
97
+ };
50
98
  }
51
99
  }
52
100
  if (mergedOptions.debug) {
53
101
  console.log("[Bugwatch] React SDK initialized");
54
102
  }
55
- }, [options]);
103
+ return () => {
104
+ if (typeof window !== "undefined") {
105
+ if (originalOnError !== null && mergedOptions.captureGlobalErrors) {
106
+ window.onerror = originalOnError;
107
+ }
108
+ if (unhandledRejectionHandler && mergedOptions.captureUnhandledRejections) {
109
+ window.removeEventListener("unhandledrejection", unhandledRejectionHandler);
110
+ }
111
+ if (originalConsoleError !== null && mergedOptions.captureConsoleBreadcrumbs) {
112
+ console.error = originalConsoleError;
113
+ }
114
+ }
115
+ };
116
+ }, [optionsKey]);
56
117
  const captureException2 = useCallback(
57
118
  (error, context) => {
58
119
  return captureException(error, context);
@@ -80,15 +141,18 @@ function BugwatchProvider({
80
141
  const setExtra2 = useCallback((key, value) => {
81
142
  setExtra(key, value);
82
143
  }, []);
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
- };
144
+ const contextValue = useMemo(
145
+ () => ({
146
+ client: getClient(),
147
+ captureException: captureException2,
148
+ captureMessage: captureMessage2,
149
+ addBreadcrumb: addBreadcrumb2,
150
+ setUser: setUser2,
151
+ setTag: setTag2,
152
+ setExtra: setExtra2
153
+ }),
154
+ [captureException2, captureMessage2, addBreadcrumb2, setUser2, setTag2, setExtra2]
155
+ );
92
156
  return /* @__PURE__ */ jsx(BugwatchContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(ErrorBoundary, { fallback, onError, children }) });
93
157
  }
94
158
  var ErrorBoundary = class extends Component {
@@ -134,39 +198,6 @@ function withBugwatchErrorBoundary(WrappedComponent, options) {
134
198
  WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name || "Component"})`;
135
199
  return WithErrorBoundary;
136
200
  }
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
201
 
171
202
  export { ErrorBoundary as BugwatchErrorBoundary, BugwatchProvider, useBugwatch, useCaptureException, useCaptureMessage, withBugwatchErrorBoundary };
172
203
  //# 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":"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","file":"index.mjs","sourcesContent":["\"use client\";\n\nimport React, {\n Component,\n createContext,\n useContext,\n useEffect,\n useCallback,\n useRef,\n useMemo,\n type ReactNode,\n type ErrorInfo,\n} from \"react\";\nimport {\n init as coreInit,\n getClient,\n getEnvConfig,\n captureException as coreCaptureException,\n captureMessage as coreCaptureMessage,\n addBreadcrumb as coreAddBreadcrumb,\n setUser as coreSetUser,\n setTag as coreSetTag,\n setExtra as coreSetExtra,\n type BugwatchOptions,\n type BugwatchClient,\n type UserContext,\n type Breadcrumb,\n type ErrorEvent,\n} from \"@bugwatch/core\";\n\n// Re-export types\nexport type { BugwatchOptions, UserContext, ErrorEvent, Breadcrumb } from \"@bugwatch/core\";\n\n/**\n * React-specific SDK options\n */\nexport interface ReactOptions extends BugwatchOptions {\n /** Capture window.onerror events */\n captureGlobalErrors?: boolean;\n /** Capture unhandled promise rejections */\n captureUnhandledRejections?: boolean;\n /** Capture console.error as breadcrumbs */\n captureConsoleBreadcrumbs?: boolean;\n}\n\nconst DEFAULT_REACT_OPTIONS: Partial<ReactOptions> = {\n captureGlobalErrors: true,\n captureUnhandledRejections: true,\n captureConsoleBreadcrumbs: true,\n};\n\n/**\n * Bugwatch context\n */\ninterface BugwatchContextValue {\n client: BugwatchClient | null;\n captureException: (error: Error, context?: Partial<ErrorEvent>) => string;\n captureMessage: (message: string, level?: ErrorEvent[\"level\"]) => string;\n addBreadcrumb: (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => void;\n setUser: (user: UserContext | null) => void;\n setTag: (key: string, value: string) => void;\n setExtra: (key: string, value: unknown) => void;\n}\n\nconst BugwatchContext = createContext<BugwatchContextValue | null>(null);\n\n/**\n * Hook to access Bugwatch SDK\n */\nexport function useBugwatch(): BugwatchContextValue {\n const context = useContext(BugwatchContext);\n if (!context) {\n throw new Error(\"useBugwatch must be used within a BugwatchProvider\");\n }\n return context;\n}\n\n/**\n * Hook to capture exceptions\n */\nexport function useCaptureException(): (\n error: Error,\n context?: Partial<ErrorEvent>\n) => string {\n const { captureException } = useBugwatch();\n return captureException;\n}\n\n/**\n * Hook to capture messages\n */\nexport function useCaptureMessage(): (\n message: string,\n level?: ErrorEvent[\"level\"]\n) => string {\n const { captureMessage } = useBugwatch();\n return captureMessage;\n}\n\n/**\n * Props for BugwatchProvider\n */\ninterface BugwatchProviderProps {\n /**\n * SDK configuration options.\n * Optional - if not provided, reads from environment variables:\n * - `BUGWATCH_API_KEY` - API key (required unless passed explicitly)\n * - `BUGWATCH_ENVIRONMENT` - Environment tag\n * - `BUGWATCH_RELEASE` - Release version\n * - `BUGWATCH_DEBUG` - Enable debug mode ('true')\n */\n options?: ReactOptions;\n /** Child components */\n children: ReactNode;\n /** Optional fallback UI for error boundary */\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Called when an error is caught by the error boundary */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\n/**\n * Bugwatch Provider component\n * Initializes the SDK and provides context to child components\n *\n * @example\n * ```tsx\n * // With BUGWATCH_API_KEY env var set\n * <BugwatchProvider>\n * <App />\n * </BugwatchProvider>\n *\n * // With explicit options\n * <BugwatchProvider options={{ apiKey: \"bw_live_xxxxx\" }}>\n * <App />\n * </BugwatchProvider>\n * ```\n */\nexport function BugwatchProvider({\n options,\n children,\n fallback,\n onError,\n}: BugwatchProviderProps): JSX.Element {\n // Serialize options to a stable string so useEffect doesn't re-run on every render.\n // Object identity of `options` changes every render if passed inline.\n const optionsKey = useMemo(\n () => (options ? JSON.stringify(options) : \"\"),\n [options]\n );\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n useEffect(() => {\n const currentOptions = optionsRef.current;\n\n // Merge env config with explicit options (explicit takes precedence)\n const envConfig = getEnvConfig();\n const mergedOptions = { ...DEFAULT_REACT_OPTIONS, ...envConfig, ...currentOptions };\n\n // Skip initialization if no API key is available\n if (!mergedOptions.apiKey) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[Bugwatch] No API key provided. Set BUGWATCH_API_KEY env var or pass options.apiKey');\n }\n return;\n }\n\n // Wrap initialization in try-catch for graceful degradation\n try {\n coreInit(mergedOptions);\n } catch (err) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Bugwatch] Initialization failed:', err);\n }\n return;\n }\n\n // Add React-specific tags\n const client = getClient();\n if (client) {\n client.setTag(\"framework\", \"react\");\n }\n\n // Store original handlers for cleanup\n let originalOnError: typeof window.onerror | null = null;\n let originalConsoleError: typeof console.error | null = null;\n let unhandledRejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;\n\n // Set up global error handlers\n if (typeof window !== \"undefined\") {\n if (mergedOptions.captureGlobalErrors) {\n originalOnError = window.onerror;\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n coreCaptureException(error, {\n tags: { mechanism: \"window.onerror\" },\n });\n }\n if (originalOnError) {\n return originalOnError(message, source, lineno, colno, error);\n }\n return false;\n };\n }\n\n if (mergedOptions.captureUnhandledRejections) {\n unhandledRejectionHandler = (event: PromiseRejectionEvent) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n coreCaptureException(error, {\n tags: { mechanism: \"unhandledrejection\" },\n });\n };\n window.addEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n if (mergedOptions.captureConsoleBreadcrumbs) {\n originalConsoleError = console.error;\n console.error = (...args: unknown[]) => {\n coreAddBreadcrumb({\n category: \"console\",\n message: args.map(String).join(\" \"),\n level: \"error\",\n });\n originalConsoleError!(...args);\n };\n }\n }\n\n if (mergedOptions.debug) {\n console.log(\"[Bugwatch] React SDK initialized\");\n }\n\n // Cleanup function to prevent memory leaks\n return () => {\n if (typeof window !== \"undefined\") {\n // Restore original window.onerror\n if (originalOnError !== null && mergedOptions.captureGlobalErrors) {\n window.onerror = originalOnError;\n }\n\n // Remove unhandled rejection listener\n if (unhandledRejectionHandler && mergedOptions.captureUnhandledRejections) {\n window.removeEventListener(\"unhandledrejection\", unhandledRejectionHandler);\n }\n\n // Restore original console.error\n if (originalConsoleError !== null && mergedOptions.captureConsoleBreadcrumbs) {\n console.error = originalConsoleError;\n }\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [optionsKey]);\n\n const captureException = useCallback(\n (error: Error, context?: Partial<ErrorEvent>) => {\n return coreCaptureException(error, context);\n },\n []\n );\n\n const captureMessage = useCallback(\n (message: string, level?: ErrorEvent[\"level\"]) => {\n return coreCaptureMessage(message, level);\n },\n []\n );\n\n const addBreadcrumb = useCallback(\n (breadcrumb: Omit<Breadcrumb, \"timestamp\">) => {\n coreAddBreadcrumb(breadcrumb);\n },\n []\n );\n\n const setUser = useCallback((user: UserContext | null) => {\n coreSetUser(user);\n }, []);\n\n const setTag = useCallback((key: string, value: string) => {\n coreSetTag(key, value);\n }, []);\n\n const setExtra = useCallback((key: string, value: unknown) => {\n coreSetExtra(key, value);\n }, []);\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue = useMemo<BugwatchContextValue>(\n () => ({\n client: getClient(),\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n }),\n [captureException, captureMessage, addBreadcrumb, setUser, setTag, setExtra]\n );\n\n return (\n <BugwatchContext.Provider value={contextValue}>\n <ErrorBoundary fallback={fallback} onError={onError}>\n {children}\n </ErrorBoundary>\n </BugwatchContext.Provider>\n );\n}\n\n/**\n * Error Boundary Props\n */\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error Boundary component\n */\nclass ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n // Capture to Bugwatch\n coreCaptureException(error, {\n tags: { mechanism: \"react.errorBoundary\" },\n extra: {\n componentStack: errorInfo.componentStack,\n },\n });\n\n // Call custom handler\n this.props.onError?.(error, errorInfo);\n }\n\n reset = (): void => {\n this.setState({ hasError: false, error: null });\n };\n\n render(): ReactNode {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n\n if (typeof fallback === \"function\") {\n return fallback(this.state.error, this.reset);\n }\n\n if (fallback) {\n return fallback;\n }\n\n return (\n <div style={{ padding: \"20px\", fontFamily: \"sans-serif\" }}>\n <h2>Something went wrong</h2>\n <p>{this.state.error.message}</p>\n <button onClick={this.reset}>Try again</button>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\n/**\n * Standalone Error Boundary for custom use\n */\nexport { ErrorBoundary as BugwatchErrorBoundary };\n\n/**\n * Higher-order component for error boundary\n */\nexport function withBugwatchErrorBoundary<P extends object>(\n WrappedComponent: React.ComponentType<P>,\n options?: {\n fallback?: ErrorBoundaryProps[\"fallback\"];\n onError?: ErrorBoundaryProps[\"onError\"];\n }\n): React.ComponentType<P> {\n const WithErrorBoundary = (props: P) => (\n <ErrorBoundary fallback={options?.fallback} onError={options?.onError}>\n <WrappedComponent {...props} />\n </ErrorBoundary>\n );\n\n WithErrorBoundary.displayName = `withBugwatchErrorBoundary(${\n WrappedComponent.displayName || WrappedComponent.name || \"Component\"\n })`;\n\n return WithErrorBoundary;\n}\n\n// Re-export core functions for convenience\nexport {\n captureException,\n captureMessage,\n addBreadcrumb,\n setUser,\n setTag,\n setExtra,\n getClient,\n init,\n} from \"@bugwatch/core\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bugwatch/react",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Bugwatch SDK for React applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",