JSPM

@ticatec/node-exception

1.0.5
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 10
  • Score
    100M100P100Q51370F
  • License MIT

A comprehensive, production-ready error handling library for Node.js Express applications. Provides standardized error types, centralized error handling middleware, and consistent response formats with flexible content negotiation support.

Package Exports

  • @ticatec/node-exception
  • @ticatec/node-exception/lib/ErrorResponse
  • @ticatec/node-exception/lib/HttpError
  • @ticatec/node-exception/lib/utils
  • @ticatec/node-exception/package.json

Readme

@ticatec/node-exception

δΈ­ζ–‡ | English

Version License: MIT Node.js TypeScript

A comprehensive, production-ready error handling library for Node.js Express applications. This library provides standardized error types, centralized error handling middleware, and consistent response formats with flexible content negotiation support.

πŸš€ Features

  • 🎯 Standardized Error Types: Eight predefined error classes covering common HTTP scenarios
  • πŸ”§ Express Middleware: Drop-in error handling middleware with zero configuration
  • πŸ“‹ Consistent Response Format: Uniform error responses with comprehensive request context
  • 🎨 Content Negotiation: Automatic response formatting (JSON, HTML, plain text)
  • πŸ” Development Support: Stack trace inclusion in development environments
  • πŸ“˜ TypeScript First: Full TypeScript support with complete type definitions
  • πŸ“Š Logging Integration: Built-in log4js integration for comprehensive error tracking
  • 🌐 IP Detection: Automatic client and server IP address detection
  • ⚑ Zero Dependencies: Minimal runtime footprint with only essential dependencies

πŸ“¦ Installation

npm install @ticatec/node-exception

Peer Dependencies

npm install log4js

πŸ”§ Quick Start

import express from 'express';
import { handleError, AppError, UnauthenticatedError } from '@ticatec/node-exception';

const app = express();

// Your API routes
app.get('/api/protected', (req, res, next) => {
    try {
        if (!req.headers.authorization) {
            throw new UnauthenticatedError();
        }
        res.json({ message: 'Success!' });
    } catch (error) {
        next(error);
    }
});

// Error handling middleware (must be the last middleware)
app.use((err, req, res, next) => {
    handleError(err, req, res);
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});

πŸ“š Error Types & Usage

πŸ”‘ AppError

Generic application error with custom error codes for business logic errors.

// Database errors
throw new AppError(1001, "Database connection failed");

// Business logic errors
throw new AppError(2001, "Insufficient account balance");

// Validation errors
throw new AppError(3001, "User email already exists");

🚫 UnauthenticatedError

For authentication failures (HTTP 401).

// Missing authentication
if (!req.headers.authorization) {
    throw new UnauthenticatedError();
}

// Invalid token
if (!isValidToken(token)) {
    throw new UnauthenticatedError();
}

πŸ”’ InsufficientPermissionError

For authorization failures (HTTP 403).

// Role-based access control
if (!user.hasRole('admin')) {
    throw new InsufficientPermissionError();
}

// Resource ownership
if (resource.ownerId !== user.id) {
    throw new InsufficientPermissionError();
}

❌ IllegalParameterError

For input validation failures (HTTP 400).

// Email validation
if (!isValidEmail(email)) {
    throw new IllegalParameterError("Invalid email format");
}

// Required field validation
if (!userId) {
    throw new IllegalParameterError("User ID is required");
}

// Range validation
if (age < 0 || age > 150) {
    throw new IllegalParameterError("Age must be between 0 and 150");
}

πŸ” ActionNotFoundError

For non-existent routes or resources (HTTP 404).

// Route not found
if (!routeExists(req.path)) {
    throw new ActionNotFoundError();
}

// Resource not found
if (!user) {
    throw new ActionNotFoundError();
}

⏱️ TimeoutError

For request timeouts (HTTP 408).

// Database query timeout
if (Date.now() - startTime > TIMEOUT_LIMIT) {
    throw new TimeoutError();
}

// API request timeout
const timeoutPromise = new Promise((_, reject) => {
    setTimeout(() => reject(new TimeoutError()), 5000);
});

🌐 ProxyError

For proxy server issues (HTTP 502).

// Proxy server failure
if (!proxyResponse.ok) {
    throw new ProxyError();
}

// Gateway error
if (!upstreamServer.isHealthy()) {
    throw new ProxyError();
}

🚫 ServiceUnavailableError

For service unavailability (HTTP 503).

// Service maintenance
if (isMaintenanceMode()) {
    throw new ServiceUnavailableError();
}

// Server overload
if (activeConnections > maxConnections) {
    throw new ServiceUnavailableError();
}

🎨 Response Format & Content Negotiation

The library automatically handles content negotiation based on the Accept header:

JSON Response (Default)

{
    "code": -1,
    "client": "192.168.1.50",
    "path": "/api/users",
    "method": "GET",
    "timestamp": 1699123456789,
    "message": "Unauthenticated user is accessing the system.",
    "stack": "Error: ... (development only)"
}

HTML Response

When Accept: text/html is requested:

<h1>Error</h1>
<p><strong>Code:</strong> -1</p>
<p><strong>Message:</strong> Unauthenticated user is accessing the system.</p>
<p><strong>Path:</strong> /api/users</p>
<p><strong>Method:</strong> GET</p>
<p><strong>Timestamp:</strong> 1699123456789</p>

Plain Text Response

When Accept: text/plain is requested:

Error Code: -1
Message: Unauthenticated user is accessing the system.
Path: /api/users
Method: GET
Timestamp: 1699123456789

πŸ“Š Response Fields

Field Type Description
code number Application-specific error code (-1 for generic errors)
client string Client IP address
path string Full request path (baseUrl + path)
method string HTTP method (GET, POST, PUT, DELETE, etc.)
timestamp number Unix timestamp in milliseconds
message string | null Human-readable error message
stack string Stack trace (development environments only)

πŸ” Development vs Production

Stack traces are automatically included in development environments:

// Enable development mode by setting request header
fetch('/api/users', {
    headers: {
        'env': 'development' // or 'dev'
    }
});

🚦 HTTP Status Code Mapping

Error Type HTTP Status Use Case
UnauthenticatedError 401 Unauthorized Missing or invalid authentication
InsufficientPermissionError 403 Forbidden Insufficient permissions/authorization
IllegalParameterError 400 Bad Request Invalid input parameters or validation
ActionNotFoundError 404 Not Found Non-existent routes or resources
TimeoutError 408 Request Timeout Network requests or operations timeout
AppError 500 Internal Server Error Business logic or application errors
ProxyError 502 Bad Gateway Proxy server or gateway issues
ServiceUnavailableError 503 Service Unavailable Service maintenance or overload
Other errors 500 Internal Server Error Unexpected system errors

πŸ’‘ Advanced Usage

Custom HTTP Container

Create custom HTTP adapters for different frameworks:

import { setHttpContainer, HttpContainer } from '@ticatec/node-exception';

class CustomContainer implements HttpContainer {
    getRemoteIp(req) {
        return req.connection.remoteAddress;
    }
    
    getPath(req) {
        return req.originalUrl;
    }
    
    sendError(req, res, statusCode, data) {
        res.status(statusCode).json(data);
    }
}

setHttpContainer(new CustomContainer());

Error Code Conventions

Organize your error codes systematically:

// Authentication errors: 1000-1999
const AUTH_ERRORS = {
    INVALID_TOKEN: 1001,
    EXPIRED_TOKEN: 1002,
    MISSING_TOKEN: 1003
};

// Validation errors: 2000-2999
const VALIDATION_ERRORS = {
    INVALID_EMAIL: 2001,
    WEAK_PASSWORD: 2002,
    REQUIRED_FIELD: 2003
};

// Business logic errors: 3000-3999
const BUSINESS_ERRORS = {
    INSUFFICIENT_BALANCE: 3001,
    DUPLICATE_EMAIL: 3002,
    LIMIT_EXCEEDED: 3003
};

throw new AppError(AUTH_ERRORS.INVALID_TOKEN, "Authentication token is invalid");

πŸ”§ TypeScript Integration

Full TypeScript support with comprehensive type definitions:

import {
    AppError,
    UnauthenticatedError,
    InsufficientPermissionError,
    IllegalParameterError,
    ActionNotFoundError,
    handleError
} from '@ticatec/node-exception';
import { Request, Response, NextFunction } from 'express';

// Type-safe error middleware
const errorHandler = (
    err: AppError | Error,
    req: Request,
    res: Response,
    next: NextFunction
): void => {
    handleError(err, req, res);
};

// Custom error with proper typing
class CustomValidationError extends IllegalParameterError {
    constructor(field: string, value: any) {
        super(`Invalid ${field}: ${value}`);
    }
}

πŸ—οΈ Architecture

The library uses a modular architecture with clear separation of concerns:

  • Error Classes (Errors.ts): Standardized error types with global registration
  • Error Handler (handleError.ts): Central error processing and response logic
  • HTTP Container (HttpContainer.ts): Framework-agnostic HTTP abstraction
  • Response Types (ErrorResponse.ts): Standardized response structure
  • Utilities (utils.ts): Response formatting helpers

πŸ“‹ Requirements

  • Node.js: β‰₯14.0.0
  • npm: β‰₯6.0.0
  • log4js: ^6.7.0 (peer dependency)

🀝 Contributing

We welcome contributions! Please see our Contributing Guidelines for details.

Development Setup

git clone https://github.com/ticatec/node-exception.git
cd node-exception
npm install
npm run dev  # Start development mode
npm run build  # Build the library
npm run typecheck  # Type checking

πŸ“„ License

MIT Β© Henry Feng