backend-error 1.0.4 → 1.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.
package/README.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  BackendError is a lightweight utility for structured and user-aware error handling in Node.js backends. It helps distinguish operational errors from unexpected crashes, and supports standardized error responses across services.
4
4
 
5
+ > ⚠️ Note: backend-error is not a middleware — it's a flexible utility for throwing and formatting structured errors. It works seamlessly with Express, Cloud Functions, and any other Node.js-based backend environment where you want standardized, user-aware error responses.
6
+
7
+ > 💬 Tip: This package doesn't handle headers or CORS. If you're building an API for browsers, remember to configure CORS separately.
8
+
5
9
  [![GitHub package.json version (master)](https://img.shields.io/github/package-json/v/eriksturesson/backendError/master)](https://github.com/eriksturesson/backendError)
6
10
  [![npm](https://img.shields.io/npm/dy/backend-error?label=npm%20downloads)](https://www.npmjs.com/package/backend-error)
7
11
 
@@ -106,7 +110,32 @@ export interface BackendErrorOptions {
106
110
  }
107
111
  ```
108
112
 
109
- > 💬 Tip: This package doesn't handle headers or CORS. If you're building an API for browsers, remember to configure CORS separately.
113
+ ## 🎨 Works well with [error-drawings](https://www.npmjs.com/package/error-drawings)
114
+
115
+ ![GitHub package.json version (master)](https://img.shields.io/github/package-json/v/eriksturesson/errorDrawings/master)
116
+ ![npm downloads](https://img.shields.io/npm/dy/error-drawings?label=npm%20downloads)
117
+
118
+ `npm install error-drawings`
119
+
120
+ If you want fun and visual error output during development, you can combine backend-error with error-drawings. Both libraries support the same severity field ("info" | "warning" | "error" | "critical"), making them plug-and-play together.
121
+
122
+ ```ts
123
+ import { BackendError } from "backend-error";
124
+ import drawLog from "error-drawings";
125
+
126
+ try {
127
+ throw BackendError.Forbidden("No access to resource");
128
+ } catch (err) {
129
+ const isCritical = !(err instanceof BackendError && err.isOperational) || err.code >= 500;
130
+ if (isCritical) {
131
+ // 🔥 Draw dramatic error output to highlight critical issues during development
132
+ // 🧠 Important: log BEFORE formatting, since the formatter may hide details if showUser is false
133
+ drawLog(err);
134
+ }
135
+ const { status, body } = await httpErrorFormatter(err); //Use the formatter as always
136
+ res.status(status).json(body);
137
+ }
138
+ ```
110
139
 
111
140
  ---
112
141
 
@@ -1,8 +1,6 @@
1
- export declare function httpErrorFormatter({ err, }: {
2
- err: unknown;
3
- }): Promise<{
1
+ export declare function httpErrorFormatter(err: unknown): {
4
2
  status: number;
5
3
  body: Record<string, any>;
6
4
  showUser: boolean;
7
5
  message: string;
8
- }>;
6
+ };
@@ -10,81 +10,43 @@ var __assign = (this && this.__assign) || function () {
10
10
  };
11
11
  return __assign.apply(this, arguments);
12
12
  };
13
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
- return new (P || (P = Promise))(function (resolve, reject) {
16
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
- step((generator = generator.apply(thisArg, _arguments || [])).next());
20
- });
21
- };
22
- var __generator = (this && this.__generator) || function (thisArg, body) {
23
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
- function verb(n) { return function (v) { return step([n, v]); }; }
26
- function step(op) {
27
- if (f) throw new TypeError("Generator is already executing.");
28
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
- if (y = 0, t) op = [op[0] & 2, t.value];
31
- switch (op[0]) {
32
- case 0: case 1: t = op; break;
33
- case 4: _.label++; return { value: op[1], done: false };
34
- case 5: _.label++; y = op[1]; op = [0]; continue;
35
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
- default:
37
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
- if (t[2]) _.ops.pop();
42
- _.trys.pop(); continue;
43
- }
44
- op = body.call(thisArg, _);
45
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
- }
48
- };
49
13
  Object.defineProperty(exports, "__esModule", { value: true });
50
14
  exports.httpErrorFormatter = void 0;
51
15
  var BackendError_1 = require("./BackendError");
52
16
  function isValidStatusCode(code) {
53
17
  return typeof code === "number" && Number.isInteger(code) && code >= 100 && code <= 599;
54
18
  }
55
- function httpErrorFormatter(_a) {
56
- var err = _a.err;
57
- return __awaiter(this, void 0, void 0, function () {
58
- var status_1, showUser_1, message_1, body_1, status, message, showUser, maybeStatus, body;
59
- return __generator(this, function (_b) {
60
- // Handle your custom BackendError type
61
- if (err instanceof BackendError_1.BackendError) {
62
- status_1 = isValidStatusCode(err.code) ? err.code : 400;
63
- showUser_1 = typeof err.showUser === "boolean" ? err.showUser : status_1 < 500;
64
- message_1 = err.message || "Error";
65
- body_1 = showUser_1
66
- ? __assign(__assign({ message: message_1 }, (err.data !== undefined && { data: err.data })), { code: status_1, severity: err.severity }) : { message: "Internal Server Error" };
67
- return [2 /*return*/, { status: status_1, body: body_1, showUser: showUser_1, message: message_1 }];
68
- }
69
- status = 500;
70
- message = "Internal Server Error";
71
- showUser = false;
72
- if (err instanceof Error) {
73
- message = err.message;
74
- maybeStatus = err.status || err.code;
75
- if (isValidStatusCode(maybeStatus)) {
76
- status = maybeStatus;
77
- showUser = status < 500; // show message for 4xx errors by default
78
- }
79
- }
80
- else if (typeof err === "string") {
81
- message = err;
82
- status = 400;
83
- showUser = true;
84
- }
85
- body = showUser ? { message: message } : { message: "Internal Server Error" };
86
- return [2 /*return*/, { status: status, body: body, showUser: showUser, message: message }];
87
- });
88
- });
19
+ function httpErrorFormatter(err) {
20
+ // Handle your custom BackendError type
21
+ if (err instanceof BackendError_1.BackendError) {
22
+ var status_1 = isValidStatusCode(err.code) ? err.code : 400;
23
+ // If developer explicitly set showUser, trust that; otherwise default: true for 4xx, false for 5xx
24
+ var showUser_1 = typeof err.showUser === "boolean" ? err.showUser : status_1 < 500;
25
+ var message_1 = err.message || "Error";
26
+ // If showUser is true, return detailed info including data, code, severity; else generic message
27
+ var body_1 = showUser_1
28
+ ? __assign(__assign({ message: message_1 }, (err.data !== undefined && { data: err.data })), { code: status_1, severity: err.severity }) : { message: "Internal Server Error" };
29
+ return { status: status_1, body: body_1, showUser: showUser_1, message: message_1 };
30
+ }
31
+ // Handle generic Error or string or unknown
32
+ var status = 500;
33
+ var message = "Internal Server Error";
34
+ var showUser = false;
35
+ if (err instanceof Error) {
36
+ message = err.message;
37
+ // Try to extract HTTP status code from common fields 'status' or 'code'
38
+ var maybeStatus = err.status || err.code;
39
+ if (isValidStatusCode(maybeStatus)) {
40
+ status = maybeStatus;
41
+ showUser = status < 500; // show message for 4xx errors by default
42
+ }
43
+ }
44
+ else if (typeof err === "string") {
45
+ message = err;
46
+ status = 400;
47
+ showUser = true;
48
+ }
49
+ var body = showUser ? { message: message } : { message: "Internal Server Error" };
50
+ return { status: status, body: body, showUser: showUser, message: message };
89
51
  }
90
52
  exports.httpErrorFormatter = httpErrorFormatter;
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "email": "hej@eriksturesson.se",
10
10
  "url": "https://eriksturesson.se"
11
11
  },
12
- "version": "1.0.4",
12
+ "version": "1.1.0",
13
13
  "description": "Simple Error handling library.",
14
14
  "keywords": [
15
15
  "error",