@dwtechs/errandler-express
v0.1.0
Published
Open source Error handler for Express.js services.
Downloads
8
Readme
- Synopsis
- Support
- Installation
- Error Flow
- Database Transaction Rollback
- Usage
- API Reference
- Logs
- Contributors
- Stack
Synopsis
Errandler-express.js is an open source Errandler gateway toolset for Express.js.
- 🪶 Very lightweight
- ⚡ High performance
- 🔧 Easy to use
- 📦 Only 1 dependency to log errors
- 🧪 Thoroughly tested
- 🚚 Shipped as ECMAScript Express module
- 📝 Written in TypeScript
Support
- node: 22
This is the oldest targeted version.
Installation
$ npm i @dwtechs/errandler-expressError Flow
┌─────────────────┐
│ Error Occurs │
│ next(error) │
└─────────┬───────┘
│
▼
┌──────────────────┐
│ Step 1: logError │
│ • Log stack │
│ • Log message │
│ • next(err) ─────┼──┐
└──────────────────┘ │
│
┌───────────┘
▼
┌───────────────────┐
│ Step 2: rollback │
│ • Check db client │
│ • ROLLBACK │
│ • Release conn │
│ • next(err) ──────┼─┐
└───────────────────┘ │
│
┌───────────┘
▼
┌───────────────────┐
│ Step 3: clientErr │
│ • Get status │
│ • Send response │
│ • END CHAIN │
└───────────────────┘
┌──────────────────┐
│ No route matches │
│ • Unmatched URL │
│ • Send 404 │
└──────────────────┘Database Transaction Rollback
The error handling pipeline automatically manages database transaction rollback when errors occur, ensuring data consistency and preventing connexion leaks.
The rollbackTransaction middleware automatically detects a database client stored in res.locals.dbClient and performs rollback operations when errors occur:
- Detects Active Transaction: Checks for database client in
res.locals.dbClient - Executes ROLLBACK: Runs
ROLLBACKcommand to undo pending changes - Releases Connection: Returns connection to pool preventing memory leaks
- Cleans Up: Sets
res.locals.dbClienttoundefined
Requirements
- Database client must be stored in
res.locals.dbClient - Client must have
query(sql)andrelease()methods - Transaction should be active (
BEGINalready executed)
Usage
Error Handler
// @ts-check
import express from "express";
// const cors = require("cors");
import { log } from '@dwtechs/winstan';
import { errorHandler } from "@dwtechs/errandler-express";
import { listen } from "@dwtechs/servpico-express";
const app = express();
app.disable("x-powered-by");
// Mandatory modules for any service
import health from "health";
// import services
// import middlewares
// import routes
app.use(express.json());
app.use("/health", health);
// Routes
app.use("/xx", ...);
app.use("/xxx", ...);
// Error handling
errorHandler(app);
// Init reference data
Promise.all([
data1.init(),
data2.init(),
])
.then(() => listen(app))
.catch((err) => log.error(`App cannot start: ${err.msg}`));
Error Codes
import {
EC_CLIENT_BAD_REQUEST,
EC_CLIENT_UNAUTHORIZED,
EC_CLIENT_FORBIDDEN,
EC_CLIENT_NOT_FOUND,
EC_CLIENT_CONFLICT,
EC_CLIENT_MALFORMED_SYNTAX,
EC_CLIENT_TOO_MANY_REQUESTS,
EC_SERVER_INTERNAL_ERROR,
EC_SERVER_SERVICE_UNAVAILABLE
} from '@dwtechs/errandler-express';
// Create custom errors with status codes
function createValidationError(message: string) {
const error = new Error(message);
error.statusCode = EC_CLIENT_BAD_REQUEST;
return error;
}
// Use in middleware
app.use('/api/protected', (req, res, next) => {
if (!req.user) {
return res.status(EC_CLIENT_UNAUTHORIZED)
.send('Authentication required');
}
next();
});
// Error handling in routes
app.get('/api/users/:id', async (req, res, next) => {
try {
const user = await getUserById(req.params.id);
if (!user) {
return res.status(EC_CLIENT_NOT_FOUND)
.send('User not found');
}
res.json(user);
} catch (error) {
error.statusCode = EC_SERVER_INTERNAL_ERROR;
next(error);
}
});
API Reference
/**
* Exported HTTP Error Status Codes grouped by category
* Client Error Responses (4xx)
* These errors indicate that the client made an error in the request
* Server Error Responses (5xx)
* These errors indicate that the server encountered an error
*/
const EC_CLIENT_BAD_REQUEST = 400; // 400 - The server cannot process the request due to client error
const EC_CLIENT_UNAUTHORIZED = 401; // 401 - Authentication is required and has failed or not been provided
const EC_CLIENT_FORBIDDEN = 403; // 403 - The client does not have access rights to the content
const EC_CLIENT_NOT_FOUND = 404; // 404 - The server cannot find the requested resource
const EC_CLIENT_CONFLICT = 409; // 409 - Request conflicts with the current state of the server
const EC_CLIENT_MALFORMED_SYNTAX = 422; // 422 - The request was well-formed but contains semantic errors
const EC_CLIENT_TOO_MANY_REQUESTS = 429; // 429 - The user has sent too many requests in a given time
const EC_SERVER_INTERNAL_ERROR = 500; // 500 - The server encountered an unexpected condition */
const EC_SERVER_SERVICE_UNAVAILABLE = 503; // 503 - The server is not ready to handle the request */
/**
* Sets up comprehensive error handling middleware for an Express application.
* This function configures a complete error handling pipeline that should be registered
* after all other middleware and routes to properly handle errors and invalid paths.
*
* The middleware stack is applied in the following order:
* 1. **Error Logging** - Logs error details for debugging and monitoring
* 2. **DB Transaction Rollback** - Rolls back database transactions on errors (PostgreSQL)
* 3. **Client Error Response** - Sends formatted HTTP error responses to clients
* 4. **Invalid Path Handling** - Handles 404 errors for undefined routes
*
* @param {Application} app - The Express application instance to configure with error handlers
*
* @returns {void} Configures the application with error handling middleware
*
* @example
* ```typescript
* import express from 'express';
* import { errorHandler } from './error';
*
* const app = express();
*
* // Configure your routes and middleware first
* app.use(express.json());
* app.get('/api/users', getUsersHandler);
* app.post('/api/users', createUserHandler);
*
* // Apply comprehensive error handling (should be last)
* errorHandler(app);
*
* app.listen(3000, () => {
* console.log('Server running with error handling configured');
* });
* ```
*
*/
function errorHandler(app) {}
Error Code Reference
| Code | Value | Description |
|------|-------|-------------|
| EC_CLIENT_BAD_REQUEST | 400 | The server cannot process the request due to Client error |
| EC_CLIENT_UNAUTHORIZED | 401 | Authentication is required and has failed or not been provided |
| EC_CLIENT_FORBIDDEN | 403 | The Client does not have access rights to the content |
| EC_CLIENT_NOT_FOUND | 404 | The server cannot find the requested resource |
| EC_CLIENT_CONFLICT | 409 | Request conflicts with the current state of the server |
| EC_CLIENT_MALFORMED_SYNTAX | 422 | The request was well-formed but contains semantic errors |
| EC_CLIENT_TOO_MANY_REQUESTS | 429 | The user has sent too many requests in a given time |
| EC_SERVER_INTERNAL_ERROR | 500 | The server encountered an unexpected condition |
| EC_SERVER_SERVICE_UNAVAILABLE | 503 | The server is not ready to handle the request |
Logs
Errandler-express.js uses @dwtechs/Winstan library for logging. All logs are in debug mode. Meaning they should not appear in production mode.
Contributors
Errandler-express.js is still in development and we would be glad to get all the help you can provide. To contribute please read contributor.md for detailed installation guide.
Stack
| Purpose | Choice | Motivation | | :-------------- | :------------------------------------------: | -------------------------------------------------------------: | | repository | Github | hosting for software development version control using Git | | package manager | npm | default node.js package manager | | language | TypeScript | static type checking along with the latest ECMAScript features | | module bundler | Rollup | advanced module bundler for ES6 modules | | unit testing | Jest | delightful testing with a focus on simplicity |
