@open-kingdom/shared-frontend-feature-error-autologger 0.0.2-14 → 0.0.2-16

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/README.md CHANGED
@@ -1,7 +1,152 @@
1
1
  # @open-kingdom/shared-frontend-feature-error-autologger
2
2
 
3
- This library was generated with [Nx](https://nx.dev).
3
+ React feature library that automatically captures uncaught errors, unhandled promise rejections, and RTK Query rejected actions, routing them to configurable logger and notification callbacks.
4
4
 
5
- ## Running unit tests
5
+ ---
6
6
 
7
- Run `nx test @open-kingdom/shared-frontend-feature-error-autologger` to execute the unit tests via [Vitest](https://vitest.dev/).
7
+ ## Exports
8
+
9
+ | Export | Type | Description |
10
+ | ------------------------------- | ------------------ | --------------------------------------------------------------------------------------------- |
11
+ | `ErrorBoundary` | `class Component` | React error boundary — catches render errors and calls logger/notification handlers |
12
+ | `useGlobalErrorListener` | hook | Attaches `window.error` and `unhandledrejection` listeners on mount; cleans up on unmount |
13
+ | `useErrorReporter` | hook | Returns a stable `report(error, options?)` function for manual error reporting |
14
+ | `createReduxRTKErrorMiddleware` | middleware factory | Redux middleware that intercepts `/rejected` RTK actions and dispatches Redux action creators |
15
+ | `createRTKErrorMiddleware` | middleware factory | Redux middleware variant that calls plain callbacks instead of dispatching action creators |
16
+
17
+ ---
18
+
19
+ ## Configuration
20
+
21
+ ### `ErrorBoundaryProps`
22
+
23
+ | Property | Type | Required | Default | Description |
24
+ | --------------------- | ---------------------------------------------- | -------- | ------------------------------------------- | ------------------------------------------------------- |
25
+ | `children` | `ReactNode` | Yes | — | Content to render |
26
+ | `fallback` | `ReactNode \| ((error: Error) => ReactNode)` | No | — | Rendered when an error is caught; accepts a render prop |
27
+ | `logger` | `(message: string) => void` | No | — | Called with the error message on catch |
28
+ | `notificationHandler` | `(message: string) => void` | No | — | Called with the user-facing message on catch |
29
+ | `userMessage` | `string` | No | `'Something went wrong. Please try again.'` | Message passed to `notificationHandler` |
30
+ | `notify` | `boolean` | No | `true` | Whether to call `notificationHandler` |
31
+ | `log` | `boolean` | No | `true` | Whether to call `logger` |
32
+ | `onError` | `(error: Error, errorInfo: ErrorInfo) => void` | No | — | Additional callback after the error is reported |
33
+
34
+ ### `ErrorListenerConfig` (for `useGlobalErrorListener`)
35
+
36
+ | Property | Type | Required | Default | Description |
37
+ | --------------------- | --------------------------- | -------- | -------------------------------- | -------------------------------------- |
38
+ | `logger` | `(message: string) => void` | No | — | Called with the error message |
39
+ | `notificationHandler` | `(message: string) => void` | No | — | Called with the user-facing message |
40
+ | `notify` | `boolean` | No | `true` | Whether to call `notificationHandler` |
41
+ | `log` | `boolean` | No | `true` | Whether to call `logger` |
42
+ | `defaultMessage` | `string` | No | `'An unexpected error occurred'` | Fallback when the error has no message |
43
+
44
+ ### `HandleErrorOptions` (per-call options for `useErrorReporter`)
45
+
46
+ | Property | Type | Required | Default | Description |
47
+ | ------------- | ------------------------- | -------- | ------- | ---------------------------------------- |
48
+ | `notify` | `boolean` | No | `true` | Whether to call `notificationHandler` |
49
+ | `log` | `boolean` | No | `true` | Whether to call `logger` |
50
+ | `userMessage` | `string` | No | — | Override the user-facing message |
51
+ | `context` | `Record<string, unknown>` | No | — | Additional context attached to the error |
52
+
53
+ ### `ReduxRTKErrorMiddlewareConfig` (for `createReduxRTKErrorMiddleware`)
54
+
55
+ | Property | Type | Required | Default | Description |
56
+ | ---------------- | ---------------------------------------------------------- | -------- | ------- | ------------------------------------------------------ |
57
+ | `logAction` | `(payload: { message: string; level: 'error' }) => Action` | Yes | — | Action creator dispatched for logging |
58
+ | `notifyAction` | `(message: string) => Action` | Yes | — | Action creator dispatched for notifications |
59
+ | `notify` | `boolean` | No | `true` | Whether to dispatch `notifyAction` |
60
+ | `log` | `boolean` | No | `true` | Whether to dispatch `logAction` |
61
+ | `defaultMessage` | `string` | No | — | Fallback message for errors without one |
62
+ | `shouldHandle` | `(action: unknown) => boolean` | No | — | Predicate to filter which rejected actions are handled |
63
+
64
+ ---
65
+
66
+ ## Usage
67
+
68
+ ### ErrorBoundary
69
+
70
+ ```tsx
71
+ import { ErrorBoundary } from '@open-kingdom/shared-frontend-feature-error-autologger';
72
+
73
+ function App() {
74
+ const dispatch = useDispatch();
75
+ return (
76
+ <ErrorBoundary logger={(msg) => dispatch(logError(msg))} notificationHandler={(msg) => dispatch(showErrorNotification(msg))} fallback={(error) => <div>Something went wrong: {error.message}</div>}>
77
+ <YourAppContent />
78
+ </ErrorBoundary>
79
+ );
80
+ }
81
+ ```
82
+
83
+ ### useGlobalErrorListener
84
+
85
+ ```tsx
86
+ import { useGlobalErrorListener } from '@open-kingdom/shared-frontend-feature-error-autologger';
87
+
88
+ function AppRoot() {
89
+ const dispatch = useDispatch();
90
+ useGlobalErrorListener({
91
+ logger: (msg) => dispatch(logError(msg)),
92
+ notificationHandler: (msg) => dispatch(showErrorNotification(msg)),
93
+ });
94
+ return <App />;
95
+ }
96
+ ```
97
+
98
+ ### useErrorReporter
99
+
100
+ ```tsx
101
+ import { useErrorReporter } from '@open-kingdom/shared-frontend-feature-error-autologger';
102
+
103
+ function DataFetcher() {
104
+ const dispatch = useDispatch();
105
+ const report = useErrorReporter({
106
+ logger: (msg) => dispatch(logError(msg)),
107
+ });
108
+
109
+ const fetchData = async () => {
110
+ try {
111
+ await api.getData();
112
+ } catch (err) {
113
+ report(err, { notify: false, context: { component: 'DataFetcher' } });
114
+ }
115
+ };
116
+ }
117
+ ```
118
+
119
+ ### createReduxRTKErrorMiddleware (recommended for Redux apps)
120
+
121
+ ```typescript
122
+ import { createReduxRTKErrorMiddleware } from '@open-kingdom/shared-frontend-feature-error-autologger';
123
+
124
+ configureStore({
125
+ middleware: (getDefault) =>
126
+ getDefault().concat(
127
+ createReduxRTKErrorMiddleware({
128
+ logAction: ({ message }) => logError(message),
129
+ notifyAction: (message) => showErrorNotification(message),
130
+ })
131
+ ),
132
+ });
133
+ ```
134
+
135
+ ### createRTKErrorMiddleware (callback-based)
136
+
137
+ ```typescript
138
+ import { createRTKErrorMiddleware } from '@open-kingdom/shared-frontend-feature-error-autologger';
139
+
140
+ const middleware = createRTKErrorMiddleware({
141
+ logger: (msg) => console.error('[RTK Error]', msg),
142
+ notificationHandler: (msg) => alert(msg),
143
+ });
144
+ ```
145
+
146
+ ---
147
+
148
+ ## Testing
149
+
150
+ ```bash
151
+ nx test shared-frontend-feature-error-autologger
152
+ ```
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { Component as m, useMemo as y, useCallback as E, useEffect as w } from "react";
2
- class M {
1
+ import { Component as p, useMemo as h, useCallback as m, useEffect as y } from "react";
2
+ class E {
3
3
  adapt(e, r) {
4
4
  return e instanceof Error ? {
5
5
  message: e.message,
@@ -60,27 +60,27 @@ class M {
60
60
  return "Request failed";
61
61
  }
62
62
  }
63
- const j = (n) => console.error("[Error]", n), H = (n) => console.warn("[Notification]", n);
64
- class g {
63
+ const w = (n) => console.error("[Error]", n), M = (n) => console.warn("[Notification]", n);
64
+ class c {
65
65
  logger;
66
66
  notificationHandler;
67
67
  adapter;
68
68
  constructor(e = {}) {
69
- this.logger = e.logger ?? j, this.notificationHandler = e.notificationHandler ?? H, this.adapter = e.adapter ?? new M();
69
+ this.logger = e.logger ?? w, this.notificationHandler = e.notificationHandler ?? M, this.adapter = e.adapter ?? new E();
70
70
  }
71
71
  report(e, r = {}) {
72
- const { notify: t = !0, log: o = !0, userMessage: i, context: s } = r, u = this.adapter.adapt(e, s), l = i || u.message;
72
+ const { notify: t = !0, log: o = !0, userMessage: i, context: a } = r, l = this.adapter.adapt(e, a), s = i || l.message;
73
73
  if (o) {
74
- const a = s ? `${u.message} | Context: ${JSON.stringify(s)}` : u.message;
75
- this.logger(a);
74
+ const u = a ? `${l.message} | Context: ${JSON.stringify(a)}` : l.message;
75
+ this.logger(u);
76
76
  }
77
- t && this.notificationHandler(l);
77
+ t && this.notificationHandler(s);
78
78
  }
79
79
  }
80
- class A extends m {
80
+ class b extends p {
81
81
  reporter;
82
82
  constructor(e) {
83
- super(e), this.state = { hasError: !1, error: null }, this.reporter = new g({
83
+ super(e), this.state = { hasError: !1, error: null }, this.reporter = new c({
84
84
  logger: e.logger,
85
85
  notificationHandler: e.notificationHandler
86
86
  });
@@ -96,11 +96,11 @@ class A extends m {
96
96
  onError: t,
97
97
  userMessage: o = "Something went wrong. Please try again.",
98
98
  notify: i = !0,
99
- log: s = !0
99
+ log: a = !0
100
100
  } = this.props;
101
101
  this.reporter.report(e, {
102
102
  notify: i,
103
- log: s,
103
+ log: a,
104
104
  userMessage: o,
105
105
  context: {
106
106
  type: "error-boundary",
@@ -113,17 +113,17 @@ class A extends m {
113
113
  return e && r ? typeof o == "function" ? o(r) : o ?? null : t;
114
114
  }
115
115
  }
116
- function k(n = {}) {
117
- const { logger: e, notificationHandler: r, adapter: t } = n, o = y(
118
- () => new g({ logger: e, notificationHandler: r, adapter: t }),
116
+ function x(n = {}) {
117
+ const { logger: e, notificationHandler: r, adapter: t } = n, o = h(
118
+ () => new c({ logger: e, notificationHandler: r, adapter: t }),
119
119
  [e, r, t]
120
120
  );
121
- return E(
122
- (i, s = {}) => o.report(i, s),
121
+ return m(
122
+ (i, a = {}) => o.report(i, a),
123
123
  [o]
124
124
  );
125
125
  }
126
- class b {
126
+ class j {
127
127
  reporter;
128
128
  notify;
129
129
  log;
@@ -134,9 +134,9 @@ class b {
134
134
  notificationHandler: t,
135
135
  notify: o = !0,
136
136
  log: i = !0,
137
- defaultMessage: s = "An unexpected error occurred"
137
+ defaultMessage: a = "An unexpected error occurred"
138
138
  } = e;
139
- this.reporter = new g({ logger: r, notificationHandler: t }), this.notify = o, this.log = i, this.defaultMessage = s;
139
+ this.reporter = new c({ logger: r, notificationHandler: t }), this.notify = o, this.log = i, this.defaultMessage = a;
140
140
  }
141
141
  attach() {
142
142
  const e = (t) => {
@@ -164,8 +164,8 @@ class b {
164
164
  };
165
165
  }
166
166
  }
167
- function S(n = {}) {
168
- w(() => new b(n).attach(), [
167
+ function k(n = {}) {
168
+ y(() => new j(n).attach(), [
169
169
  n.logger,
170
170
  n.notificationHandler,
171
171
  n.notify,
@@ -173,20 +173,19 @@ function S(n = {}) {
173
173
  n.defaultMessage
174
174
  ]);
175
175
  }
176
- const d = "An error occurred while processing your request";
177
- function f(n) {
176
+ function g(n) {
178
177
  if (typeof n != "object" || n === null)
179
178
  return !1;
180
179
  const e = n;
181
180
  return typeof e.type == "string" && (e.type.endsWith("/rejected") || e.meta?.rejectedWithValue === !0);
182
181
  }
183
- function p(n) {
182
+ function d(n) {
184
183
  return {
185
184
  type: "rtk-query",
186
185
  endpoint: n.meta?.arg?.endpointName || "unknown"
187
186
  };
188
187
  }
189
- function h(n) {
188
+ function f(n) {
190
189
  return n.payload || n.error;
191
190
  }
192
191
  function R(n = {}) {
@@ -195,59 +194,55 @@ function R(n = {}) {
195
194
  notificationHandler: r,
196
195
  notify: t = !0,
197
196
  log: o = !0,
198
- defaultMessage: i = d,
199
- shouldHandle: s
200
- } = n, u = new g({ logger: e, notificationHandler: r });
201
- return () => (l) => (a) => {
202
- if (f(a)) {
203
- if (s && !s(a))
204
- return l(a);
205
- u.report(h(a), {
197
+ shouldHandle: i
198
+ } = n, a = new c({ logger: e, notificationHandler: r });
199
+ return () => (l) => (s) => {
200
+ if (g(s)) {
201
+ if (i && !i(s))
202
+ return l(s);
203
+ a.report(f(s), {
206
204
  notify: t,
207
205
  log: o,
208
- userMessage: i,
209
- context: p(a)
206
+ context: d(s)
210
207
  });
211
208
  }
212
- return l(a);
209
+ return l(s);
213
210
  };
214
211
  }
215
- function L(n) {
212
+ function A(n) {
216
213
  const {
217
214
  logAction: e,
218
215
  notifyAction: r,
219
216
  notify: t = !0,
220
217
  log: o = !0,
221
- defaultMessage: i = d,
222
- shouldHandle: s
218
+ shouldHandle: i
223
219
  } = n;
224
- return ({ dispatch: u }) => {
225
- const l = new g({
226
- logger: (a) => u(e({ message: a, level: "error" })),
227
- notificationHandler: (a) => u(r(a))
220
+ return ({ dispatch: a }) => {
221
+ const l = new c({
222
+ logger: (s) => a(e({ message: s, level: "error" })),
223
+ notificationHandler: (s) => a(r(s))
228
224
  });
229
- return (a) => (c) => {
230
- if (f(c)) {
231
- if (s && !s(c))
232
- return a(c);
233
- l.report(h(c), {
225
+ return (s) => (u) => {
226
+ if (g(u)) {
227
+ if (i && !i(u))
228
+ return s(u);
229
+ l.report(f(u), {
234
230
  notify: t,
235
231
  log: o,
236
- userMessage: i,
237
- context: p(c)
232
+ context: d(u)
238
233
  });
239
234
  }
240
- return a(c);
235
+ return s(u);
241
236
  };
242
237
  };
243
238
  }
244
239
  export {
245
- M as ErrorAdapter,
246
- A as ErrorBoundary,
247
- g as ErrorReporter,
248
- b as GlobalErrorListener,
240
+ E as ErrorAdapter,
241
+ b as ErrorBoundary,
242
+ c as ErrorReporter,
243
+ j as GlobalErrorListener,
249
244
  R as createRTKErrorMiddleware,
250
- L as createReduxRTKErrorMiddleware,
251
- k as useErrorReporter,
252
- S as useGlobalErrorListener
245
+ A as createReduxRTKErrorMiddleware,
246
+ x as useErrorReporter,
247
+ k as useGlobalErrorListener
253
248
  };
@@ -1 +1 @@
1
- {"version":3,"file":"rtk-error.middleware.d.ts","sourceRoot":"","sources":["../../../src/lib/middlewares/rtk-error.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EACV,wBAAwB,EACxB,6BAA6B,EAC9B,MAAM,2BAA2B,CAAC;AAwCnC,wBAAgB,wBAAwB,CACtC,MAAM,GAAE,wBAA6B,GACpC,UAAU,CA4BZ;AAGD,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,6BAA6B,GACpC,UAAU,CAiCZ"}
1
+ {"version":3,"file":"rtk-error.middleware.d.ts","sourceRoot":"","sources":["../../../src/lib/middlewares/rtk-error.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EACV,wBAAwB,EACxB,6BAA6B,EAC9B,MAAM,2BAA2B,CAAC;AAsCnC,wBAAgB,wBAAwB,CACtC,MAAM,GAAE,wBAA6B,GACpC,UAAU,CA0BZ;AAGD,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,6BAA6B,GACpC,UAAU,CA+BZ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-kingdom/shared-frontend-feature-error-autologger",
3
- "version": "0.0.2-14",
3
+ "version": "0.0.2-16",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -18,6 +18,7 @@
18
18
  }
19
19
  },
20
20
  "files": [
21
+ "README.md",
21
22
  "dist",
22
23
  "!**/*.tsbuildinfo"
23
24
  ],