UNPKG

jsm-exceptions

Version:

A comprehensive TypeScript exception library with HTTP status code support, detailed JSDoc documentation, and backward compatibility. Provides structured error handling for web applications and APIs.

261 lines (199 loc) 7.74 kB
# JSM Exceptions [![npm version](https://badge.fury.io/js/jsm-exceptions.svg)](https://badge.fury.io/js/jsm-exceptions) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) A comprehensive TypeScript exception library with HTTP status code support, detailed JSDoc documentation, and backward compatibility. Provides structured error handling for web applications and APIs. ## ✨ Features - 🎯 **HTTP Status Code Alignment**: Each exception corresponds to appropriate HTTP status codes - 📝 **Comprehensive JSDoc**: Detailed documentation with examples for every exception - 🔄 **Backward Compatibility**: Maintains compatibility with existing code using `@deprecated` annotations - 🏗️ **TypeScript Support**: Full TypeScript support with proper type definitions - 🧩 **Modular Design**: Import only what you need - 🔍 **Rich Context**: Support for additional context and metadata in exceptions - ⏰ **Timestamps**: Automatic timestamp tracking for debugging - 🎨 **Validation Support**: Built-in support for Joi validation errors ## 📦 Installation ```bash npm install jsm-exceptions ``` ## 🚀 Quick Start ### Basic Usage ```typescript import { BadRequestException, ValidationException, ItemNotFoundException } from 'jsm-exceptions'; // Simple usage throw new BadRequestException('Invalid request format'); // With additional context throw new ItemNotFoundException('User not found', { userId: '12345' }); // Validation with field errors throw new ValidationException('Validation failed', { email: { value: 'invalid-email', message: 'Email format is invalid' }, age: { value: -1, message: 'Age must be positive' } }); ``` ### Using the Base Exception ```typescript import { BaseException } from 'jsm-exceptions'; // Custom exception extending BaseException class CustomBusinessException extends BaseException { constructor(message: string, context?: Record<string, any>) { super(message, 422, context); // HTTP 422 Unprocessable Entity } } throw new CustomBusinessException('Business rule violation', { rule: 'maximum-orders-per-day', limit: 10, current: 11 }); ``` ## 📚 Available Exceptions ### 4xx Client Errors | Exception | HTTP Code | Description | |-----------|-----------|-------------| | `BadRequestException` | 400 | Malformed or invalid requests | | `UnauthorizedException` | 401 | Authentication required or invalid | | `InvalidPasswordException` | 401 | Password authentication failures | | `JWTTokenExpiredException` | 401 | Expired JWT tokens | | `ForbiddenException` | 403 | Insufficient permissions | | `ItemNotFoundException` | 404 | Resource not found | | `NoItemsFoundException` | 404 | Search returned no results | | `MethodNotAllowedException` | 405 | HTTP method not supported | | `RequestTimeoutException` | 408 | Request timeouts | | `ValueAlreadyExistsException` | 409 | Resource conflicts | | `ValidationException` | 422 | Input validation failures | | `UnprocessableEntityException` | 422 | Semantic errors | | `TooManyRequestsException` | 429 | Rate limiting | ### 5xx Server Errors | Exception | HTTP Code | Description | |-----------|-----------|-------------| | `InternalServerErrorException` | 500 | Unexpected server errors | | `NotImplementedException` | 501 | Unimplemented features | | `ServiceUnavailableException` | 503 | Temporary service unavailability | ### Special Cases | Exception | HTTP Code | Description | |-----------|-----------|-------------| | `NoContentException` | 204 | Valid request with no response body | ## 🔧 Advanced Usage ### Validation with Joi ```typescript import Joi from 'joi'; import { ValidationException } from 'jsm-exceptions'; const schema = Joi.object({ email: Joi.string().email().required(), age: Joi.number().min(0).required() }); try { const { error } = schema.validate(data); if (error) { throw new ValidationException('Validation failed', error); } } catch (joiError) { // ValidationException automatically handles Joi.ValidationError throw new ValidationException('Input validation failed', joiError); } ``` ### Error Handling in Express.js ```typescript import express from 'express'; import { BaseException, InternalServerErrorException } from 'jsm-exceptions'; const app = express(); // Error handling middleware app.use((error: Error, req: express.Request, res: express.Response, next: express.NextFunction) => { if (error instanceof BaseException) { return res.status(error.status).json({ success: false, error: { name: error.name, message: error.message, context: error.context, timestamp: error.timestamp } }); } // Handle unexpected errors const internalError = new InternalServerErrorException('Unexpected error occurred'); res.status(500).json({ success: false, error: internalError.toJSON() }); }); ``` ### Rate Limiting Example ```typescript import { TooManyRequestsException } from 'jsm-exceptions'; class RateLimiter { checkLimit(userId: string, limit: number, windowMs: number) { const requests = this.getUserRequests(userId, windowMs); if (requests.length >= limit) { throw new TooManyRequestsException('Rate limit exceeded', { userId, limit, windowMs, requestCount: requests.length, retryAfter: this.getRetryAfter(requests[0], windowMs) }); } } } ``` ## 🔄 Migration from v1.x The library maintains backward compatibility, but we recommend migrating to the new exception names: ```typescript // ❌ Old (deprecated) import { JsmException, InternalServerError, JWTTokenExpired } from 'jsm-exceptions'; // ✅ New (recommended) import { BaseException, InternalServerErrorException, JWTTokenExpiredException } from 'jsm-exceptions'; ``` Deprecated exports will show warnings in TypeScript and include `@deprecated` JSDoc annotations. ## 🎛️ Exception Properties All exceptions extend `BaseException` and include: ```typescript interface ExceptionProperties { name: string; // Exception class name message: string; // Error message status: number; // HTTP status code context?: Record<string, any>; // Additional context timestamp: Date; // When the exception was created stack?: string; // Stack trace } ``` ### JSON Serialization ```typescript const exception = new BadRequestException('Invalid input', { field: 'email' }); console.log(exception.toJSON()); // Output: // { // name: 'BadRequestException', // message: 'Invalid input', // status: 400, // context: { field: 'email' }, // timestamp: '2025-07-22T10:30:00.000Z', // stack: '...' // } ``` ## 📋 API Reference ### BaseException The foundation class for all exceptions. ```typescript class BaseException extends Error { constructor(message?: string, status?: number, context?: Record<string, any>) toJSON(): object toString(): string } ``` ### ValidationException Special handling for validation errors with field-specific information. ```typescript class ValidationException extends BaseException { fields: ErrorFields; isJoi: boolean; isMongoose: boolean; isCelebrate: boolean; } ``` ## 🤝 Contributing Contributions are welcome! Please read our contributing guidelines and submit pull requests for any improvements. ## 📄 License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## 🔗 Links - [GitHub Repository](https://github.com/reevosolutions/jsm-exceptions) - [npm Package](https://www.npmjs.com/package/jsm-exceptions) - [Issue Tracker](https://github.com/reevosolutions/jsm-exceptions/issues)