backend-error 0.0.5

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 ADDED
@@ -0,0 +1,146 @@
1
+ <center>
2
+
3
+ # Backend-error
4
+
5
+ Simple logging
6
+
7
+ <img alt="GitHub package.json version (master)" src="https://img.shields.io/github/package-json/v/eriksturesson/backendError/master">
8
+ <img alt="npm" src="https://img.shields.io/npm/dy/@eriksturesson/backend-error?label=npm%20downloads">
9
+
10
+ </center>
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @eriksturesson/backend-error
16
+ ```
17
+
18
+ ## πŸ”₯ Custom BackendError class
19
+
20
+ Use `BackendError` class for standardized backend error handling:
21
+
22
+ ## Usage
23
+
24
+ ```ts
25
+ import { BackendError } from "@eriksturesson/backend-error";
26
+
27
+ throw BackendError.BadRequest("Missing required field");
28
+ ```
29
+
30
+ Or construct it manually for full control:
31
+
32
+ ```ts
33
+ const error = new BackendError({
34
+ message: "Something went terribly wrong",
35
+ severity: "critical",
36
+ showUser: true,
37
+ code: 500,
38
+ data: { context: "PaymentService", id: 12345 },
39
+ });
40
+ ```
41
+
42
+ Properties available:
43
+
44
+ - `message`: The error message
45
+ - `code`: HTTP status code
46
+ - `isOperational`: Marks it as a handled error (vs. crash)
47
+ - `showUser`: Whether frontend should show the message
48
+ - `severity`: "info" | "warning" | "error" | "critical"
49
+ - `data`: Additional metadata (optional and anything accepted)
50
+
51
+ You can extend it for custom domains too.
52
+
53
+ ## 🧠 Example: With Express + showUser handling
54
+
55
+ ```ts
56
+ import { BackendError } from "@eriksturesson/backend-error";
57
+
58
+ app.get("/user/:id", async (req, res, next) => {
59
+ try {
60
+ const user = null;
61
+ if (!user) throw BackendError.NotFound("User not found");
62
+ res.json(user);
63
+ } catch (err) {
64
+ if (err instanceof BackendError && err.showUser) {
65
+ res.status(err.code ?? 400).json({ error: err.message });
66
+ } else {
67
+ res.status(500).json({ error: "Internal Server Error" });
68
+ }
69
+ next(err);
70
+ }
71
+ });
72
+ ```
73
+
74
+ ## Available static error constructors
75
+
76
+ - `BackendError.BadRequest(message: string)` // 400, showUser: true
77
+ - `BackendError.Unauthorized(message: string)` // 401, showUser: true
78
+ - `BackendError.Forbidden(message: string)` // 403, showUser: true
79
+ - `BackendError.NotFound(message: string)` // 404, showUser: true
80
+ - `BackendError.Conflict(message: string)` // 409, showUser: true
81
+ - `BackendError.UnprocessableEntity(message: string)`// 422, showUser: true
82
+ - `BackendError.Internal(message: string)` // 500, showUser: false
83
+ - `BackendError.ServiceUnavailable(message: string)` // 503, showUser: false
84
+
85
+ ## 🧩 httpErrorFormatter(error) – Format backend errors for HTTP responses
86
+
87
+ This helper takes an Error (or BackendError) and returns a plain object with:
88
+
89
+ βœ… status – an HTTP status code (number)
90
+
91
+ βœ… body – a JSON.stringify'd string representing the error (already parsed)
92
+
93
+ It’s designed to be simple and universal – you can use it with any framework (Azure Functions, Express, etc).
94
+
95
+ πŸ”§ Example usage
96
+
97
+ ```ts
98
+ import { BackendError, httpErrorFormatter } from "@eriksturesson/backend-error";
99
+
100
+ try {
101
+ throw BackendError.Internal("Something went very wrong."); // πŸ‘ˆ your static factory pattern
102
+ } catch (err) {
103
+ const { status, body } = await httpErrorFormatter(err);
104
+
105
+ return {
106
+ status,
107
+ headers: {
108
+ ...getCorsHeaders(request.headers.get("origin")), // Add CORS headers yourself
109
+ },
110
+ body,
111
+ };
112
+ }
113
+ ```
114
+
115
+ ⚠️ Important
116
+ This function does not include any HTTP headers – especially no CORS headers.
117
+ Why? Because every environment has different CORS rules.
118
+
119
+ If you're using Azure Functions, Express, or something else, you'll need to add CORS manually:
120
+
121
+ ## 🧩 Types
122
+
123
+ ```ts
124
+ export type Severity = "info" | "warning" | "error" | "critical";
125
+ ```
126
+
127
+ ```ts
128
+ export interface BackendErrorOptions {
129
+ message: string;
130
+ isOperational?: boolean;
131
+ showUser?: boolean;
132
+ severity?: Severity;
133
+ code?: number;
134
+ data?: any;
135
+ }
136
+ ```
137
+
138
+ ---
139
+
140
+ ## 🌐 Repo
141
+
142
+ [https://github.com/eriksturesson/backendError](https://github.com/eriksturesson/cloud-logger)
143
+
144
+ ---
145
+
146
+ Created by [@eriksturesson](https://eriksturesson.se)
@@ -0,0 +1,17 @@
1
+ import { BackendErrorOptions, Severity } from "../interfaces/Types";
2
+ export declare class BackendError extends Error {
3
+ isOperational: boolean;
4
+ showUser: boolean;
5
+ severity: Severity;
6
+ code?: number;
7
+ data?: any;
8
+ constructor(options: BackendErrorOptions);
9
+ static BadRequest(msg: string): BackendError;
10
+ static Unauthorized(msg: string): BackendError;
11
+ static Forbidden(msg: string): BackendError;
12
+ static NotFound(msg: string): BackendError;
13
+ static Conflict(msg: string): BackendError;
14
+ static UnprocessableEntity(msg: string): BackendError;
15
+ static Internal(msg: string): BackendError;
16
+ static ServiceUnavailable(msg: string): BackendError;
17
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.BackendError = void 0;
19
+ var BackendError = /** @class */ (function (_super) {
20
+ __extends(BackendError, _super);
21
+ function BackendError(options) {
22
+ var _this = this;
23
+ var _a, _b, _c;
24
+ _this = _super.call(this, options.message) || this;
25
+ _this.name = "BackendError";
26
+ _this.isOperational = (_a = options.isOperational) !== null && _a !== void 0 ? _a : true;
27
+ _this.showUser = (_b = options.showUser) !== null && _b !== void 0 ? _b : true;
28
+ _this.severity = (_c = options.severity) !== null && _c !== void 0 ? _c : "error";
29
+ _this.code = options.code;
30
+ _this.data = options.data;
31
+ Object.setPrototypeOf(_this, BackendError.prototype);
32
+ return _this;
33
+ }
34
+ BackendError.BadRequest = function (msg) {
35
+ return new BackendError({ message: msg, code: 400, severity: "warning", showUser: true });
36
+ };
37
+ BackendError.Unauthorized = function (msg) {
38
+ return new BackendError({ message: msg, code: 401, severity: "warning", showUser: true });
39
+ };
40
+ BackendError.Forbidden = function (msg) {
41
+ return new BackendError({ message: msg, code: 403, severity: "warning", showUser: true });
42
+ };
43
+ BackendError.NotFound = function (msg) {
44
+ return new BackendError({ message: msg, code: 404, severity: "warning", showUser: true });
45
+ };
46
+ BackendError.Conflict = function (msg) {
47
+ return new BackendError({ message: msg, code: 409, severity: "warning", showUser: true });
48
+ };
49
+ BackendError.UnprocessableEntity = function (msg) {
50
+ return new BackendError({ message: msg, code: 422, severity: "warning", showUser: true });
51
+ };
52
+ BackendError.Internal = function (msg) {
53
+ return new BackendError({ message: msg, code: 500, severity: "critical", showUser: false });
54
+ };
55
+ BackendError.ServiceUnavailable = function (msg) {
56
+ return new BackendError({ message: msg, code: 503, severity: "critical", showUser: false });
57
+ };
58
+ return BackendError;
59
+ }(Error));
60
+ exports.BackendError = BackendError;
@@ -0,0 +1,6 @@
1
+ export declare function httpErrorFormatter({ err }: {
2
+ err: unknown;
3
+ }): Promise<{
4
+ status: number;
5
+ body: string;
6
+ }>;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ 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;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.httpErrorFormatter = void 0;
40
+ var BackendError_1 = require("./BackendError");
41
+ function httpErrorFormatter(_a) {
42
+ var err = _a.err;
43
+ return __awaiter(this, void 0, void 0, function () {
44
+ var parsedCode, status_1, message;
45
+ return __generator(this, function (_b) {
46
+ if (err instanceof BackendError_1.BackendError && err.showUser) {
47
+ parsedCode = Number(err.code);
48
+ status_1 = Number.isInteger(parsedCode) ? parsedCode : 400;
49
+ return [2 /*return*/, {
50
+ status: status_1,
51
+ body: JSON.stringify(err),
52
+ }];
53
+ }
54
+ message = err instanceof Error ? err.message : typeof err === "string" ? err : "Internal Server Error";
55
+ return [2 /*return*/, {
56
+ status: 500,
57
+ body: JSON.stringify({ message: message }),
58
+ }];
59
+ });
60
+ });
61
+ }
62
+ exports.httpErrorFormatter = httpErrorFormatter;
@@ -0,0 +1,3 @@
1
+ export { BackendError } from "./core/BackendError";
2
+ export { httpErrorFormatter } from "./core/httpErrorFormatter";
3
+ export type { BackendErrorOptions, Severity } from "./interfaces/Types";
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.httpErrorFormatter = exports.BackendError = void 0;
4
+ var BackendError_1 = require("./core/BackendError");
5
+ Object.defineProperty(exports, "BackendError", { enumerable: true, get: function () { return BackendError_1.BackendError; } });
6
+ var httpErrorFormatter_1 = require("./core/httpErrorFormatter");
7
+ Object.defineProperty(exports, "httpErrorFormatter", { enumerable: true, get: function () { return httpErrorFormatter_1.httpErrorFormatter; } });
@@ -0,0 +1,9 @@
1
+ export type Severity = "info" | "warning" | "error" | "critical";
2
+ export interface BackendErrorOptions {
3
+ message: string;
4
+ isOperational?: boolean;
5
+ showUser?: boolean;
6
+ severity?: Severity;
7
+ code?: number;
8
+ data?: any;
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "backend-error",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "license": "MIT",
7
+ "maintainers": [
8
+ "Erik Sturesson"
9
+ ],
10
+ "author": {
11
+ "name": "Erik Sturesson",
12
+ "email": "hej@eriksturesson.se",
13
+ "url": "https://eriksturesson.se"
14
+ },
15
+ "version": "0.0.5",
16
+ "description": "Logger library supporting multiple cloud platforms with simple error handling.",
17
+ "keywords": [
18
+ "error",
19
+ "fail",
20
+ "drawing",
21
+ "drawings",
22
+ "summarized",
23
+ "help",
24
+ "fun"
25
+ ],
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/eriksturesson/backendError"
29
+ },
30
+ "bugs": {
31
+ "email": "hej@eriksturesson.se",
32
+ "url": "https://github.com/eriksturesson/backendError/issues"
33
+ },
34
+ "engines": {
35
+ "npm": "^10.0.0",
36
+ "node": "^22.0.0"
37
+ },
38
+ "main": "dist/index.js",
39
+ "types": "dist/index.d.ts",
40
+ "files": [
41
+ "dist"
42
+ ],
43
+ "scripts": {
44
+ "build": "tsc",
45
+ "test": "ts-node src/test/test.ts"
46
+ },
47
+ "dependencies": {
48
+ "dotenv": "^16.5.0",
49
+ "npm": "^11.4.1",
50
+ "typescript": "^4.7.4"
51
+ },
52
+ "exports": {
53
+ ".": "./dist/index.js"
54
+ },
55
+ "devDependencies": {
56
+ "@types/node": "^22.15.27"
57
+ }
58
+ }