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
Markdown
# JSM Exceptions
[](https://badge.fury.io/js/jsm-exceptions)
[](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)