Package Exports
- @thalorlabs/errors
- @thalorlabs/errors/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@thalorlabs/errors) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@thalorlabs/errors
A comprehensive, production-ready exception handling system for TypeScript applications with enhanced features for debugging, monitoring, and API responses.
Installation
npm install @thalorlabs/errorsFeatures
- Base CustomError class with enhanced context and debugging capabilities
- HTTP-specific error classes for common API scenarios
- Specialized error classes for validation, rate limiting, and database operations
- Comprehensive test coverage (100% for all exception classes)
- TypeScript support with full type safety
- Structured error responses for consistent API responses
- Request tracking with requestId and context support
- Timestamp tracking for debugging and monitoring
Quick Start
import {
// Base error class
CustomError,
// 4xx Client Errors
BadRequestError,
UnauthorizedError,
ForbiddenError,
NotFoundError,
ConflictError,
UnprocessableEntityError,
TooManyRequestsError,
// 5xx Server Errors
InternalServerError,
NotImplementedError,
ServiceUnavailableError,
GatewayTimeoutError,
// Specialized error classes
ValidationError, // Alias for UnprocessableEntityError (422)
RateLimitError,
DatabaseError,
AuthenticationError, // Legacy alias for UnauthorizedError
// Optional/Nice-to-have errors
AuthenticationTimeoutError,
ThirdPartyServiceError,
PaymentRequiredError,
QuotaExceededError,
} from '@thalorlabs/errors';
// Basic usage
throw new BadRequestError('Invalid input data');
throw new UnauthorizedError('Invalid API key');
throw new ForbiddenError('Insufficient permissions');
// With context and request tracking
throw new ValidationError(
'Validation failed',
[{ field: 'email', message: 'Invalid email format' }],
'req-123',
{ userId: 'user-456' }
);
// Rate limiting with retry information
throw new TooManyRequestsError('Rate limit exceeded', 60, 100, 0, new Date());
// Database errors with detailed context
throw new DatabaseError(
'Connection failed',
'MongoDB',
'find',
DatabaseErrorType.CONNECTION_FAILED,
originalError,
'req-123',
{ collection: 'users' }
);Error Classes
CustomError (Base Class)
The foundation for all custom errors with enhanced debugging capabilities.
class CustomError extends Error {
statusCode: number;
status: 'success' | 'failure';
timestamp: Date;
requestId?: string;
context?: Record<string, any>;
}Methods:
getStatusText(): Returns human-readable status texttoJSON(): Complete JSON representation for logginggetErrorResponse(): API-friendly response format
HTTP Error Classes
4xx Client Errors
BadRequestError (400)
throw new BadRequestError('Malformed input data', 'invalid-json', 'req-123');UnauthorizedError (401)
throw new UnauthorizedError('Invalid API key', 'expired-token', 'req-123');ForbiddenError (403)
throw new ForbiddenError(
'Insufficient permissions',
'admin-required',
'req-123'
);NotFoundError (404)
throw new NotFoundError('User not found', 'user-id-123', 'req-123');ConflictError (409)
throw new ConflictError(
'Resource already exists',
'duplicate-email',
'req-123'
);UnprocessableEntityError (422)
throw new UnprocessableEntityError(
'Semantically invalid request',
'validation-failed',
'req-123'
);TooManyRequestsError (429)
throw new TooManyRequestsError(
'Rate limit exceeded',
60, // retryAfter seconds
100, // limit
0, // remaining
new Date('2024-01-01T13:00:00Z'), // resetTime
'req-123'
);5xx Server Errors
InternalServerError (500)
throw new InternalServerError(
'Unexpected server error',
'database-connection-failed',
'req-123'
);NotImplementedError (501)
throw new NotImplementedError(
'Endpoint not yet implemented',
'v2-api-missing',
'req-123'
);ServiceUnavailableError (503)
throw new ServiceUnavailableError(
'External service down',
'weather-api',
'req-123'
);GatewayTimeoutError (504)
throw new GatewayTimeoutError(
'Upstream service timeout',
'database-query-timeout',
'req-123'
);Specialized Error Classes
ValidationError (422)
For input validation errors with detailed field-level information.
const validationError = new ValidationError(
'Validation failed',
[
{ field: 'email', message: 'Invalid email format', value: 'invalid-email' },
{ field: 'password', message: 'Password too short', value: '123' },
],
'req-123'
);
// Add more validation errors dynamically
validationError.addValidationError('age', 'Must be 18 or older', 16, 'MIN_AGE');
throw validationError;Response Format:
{
"status": "failure",
"error": "Validation failed",
"timestamp": "2024-01-01T12:00:00.000Z",
"requestId": "req-123",
"errors": [
{
"field": "email",
"message": "Invalid email format",
"value": "invalid-email"
}
]
}RateLimitError (429)
For rate limiting scenarios with retry information.
throw new RateLimitError(
'Rate limit exceeded',
60, // retryAfter seconds
100, // limit
0, // remaining
new Date('2024-01-01T13:00:00Z'), // resetTime
'req-123'
);Response Format:
{
"status": "failure",
"error": "Rate limit exceeded",
"timestamp": "2024-01-01T12:00:00.000Z",
"requestId": "req-123",
"retryAfter": 60,
"limit": 100,
"remaining": 0,
"resetTime": "2024-01-01T13:00:00.000Z"
}DatabaseError (500)
For database-related errors with detailed context.
throw new DatabaseError(
'Connection timeout',
'MongoDB',
'find',
DatabaseErrorType.CONNECTION_FAILED,
originalError,
'req-123',
{ collection: 'users', query: { _id: '123' } }
);DatabaseErrorType enum:
CONNECTION_FAILEDQUERY_FAILEDTRANSACTION_FAILEDCONSTRAINT_VIOLATIONTIMEOUTDEADLOCKUNKNOWN
Optional/Nice-to-have Error Classes
AuthenticationTimeoutError (440)
For authentication timeout scenarios (custom status code).
throw new AuthenticationTimeoutError(
'Login session expired',
'jwt-expired',
'req-123'
);ThirdPartyServiceError (502/503)
For external service failures with detailed context.
throw new ThirdPartyServiceError(
'Payment gateway failed',
'stripe-api',
originalError,
'req-123',
{ endpoint: '/process-payment' }
);PaymentRequiredError (402)
For payment/subscription required scenarios.
throw new PaymentRequiredError(
'Premium feature requires payment',
'subscription-required',
'req-123'
);QuotaExceededError (429)
For quota/usage limit scenarios with detailed information.
throw new QuotaExceededError(
'Monthly API quota exceeded',
'api-calls',
1000, // current usage
1000, // max quota
new Date('2024-02-01T00:00:00Z'), // reset time
'req-123'
);Integration with Middleware
The exception system integrates seamlessly with your existing TryCatchMiddleware:
// In TryCatchMiddleware.ts
if (error instanceof CustomError) {
res.status(error.statusCode).json(error.getErrorResponse());
}Best Practices
1. Use Specific Error Types
// Good
throw new ValidationError('Invalid input', validationErrors);
// Avoid
throw new CustomError(422, 'Invalid input');2. Include Context for Debugging
throw new DatabaseError(
'Query failed',
'PostgreSQL',
'SELECT',
DatabaseErrorType.QUERY_FAILED,
originalError,
requestId,
{ table: 'users', query: 'SELECT * FROM users WHERE id = ?' }
);3. Use Request IDs for Tracing
// Extract request ID from request headers or generate one
const requestId = req.headers['x-request-id'] || generateRequestId();
throw new BadRequestError('Invalid data', 'field-name', requestId);4. Structured Error Responses
// For API responses
const response = error.getErrorResponse();
// For logging
const logData = error.toJSON();
logger.error('Error occurred', logData);Testing
All error classes have comprehensive test coverage:
npm test
npm run test:coverageTest Coverage:
- ✅ 100% statement coverage
- ✅ 97.36% branch coverage
- ✅ 100% function coverage
- ✅ 100% line coverage
Migration from Basic Errors
If you're upgrading from the basic error system:
// Before
throw new BadRequestError('Invalid input', 'field-name');
// After (backward compatible)
throw new BadRequestError('Invalid input', 'field-name');
// Enhanced (recommended)
throw new BadRequestError('Invalid input', 'field-name', requestId, {
field: 'email',
});Type Safety
The system is fully typed with TypeScript:
// All error classes extend CustomError
const error: CustomError = new ValidationError('Test');
// Type-safe error handling
if (error instanceof ValidationError) {
// TypeScript knows this is a ValidationError
console.log(error.validationErrors);
}Performance Considerations
- Minimal overhead: Base error class adds only essential properties
- Optional context: Context and requestId are optional to avoid unnecessary memory usage
- Efficient serialization:
toJSON()andgetErrorResponse()methods for different use cases - Stack trace preservation: Full Error inheritance maintains stack traces
Future Enhancements
The system is designed to be extensible:
- Add new specialized error types as needed
- Extend context with additional metadata
- Add error correlation IDs for distributed systems
- Implement error aggregation and reporting
- Add error recovery suggestions
Project Structure
src/
├── index.ts # Main exports
├── CustomError.ts # Base error class
├── AuthenticationError.ts # Legacy alias for UnauthorizedError
├── AuthenticationTimeoutError.ts
├── ConflictError.ts # 4xx Client Errors
├── ForbiddenError.ts
├── NotFoundError.ts
├── TooManyRequestsError.ts
├── UnauthorizedError.ts
├── UnprocessableEntityError.ts
├── GatewayTimeoutError.ts # 5xx Server Errors
├── InternalServerError.ts
├── NotImplementedError.ts
├── ServiceUnavailableError.ts
├── DatabaseError.ts # Specialized error classes
├── RateLimitError.ts
├── ValidationError.ts
├── ThirdPartyServiceError.ts # Optional error classes
├── PaymentRequiredError.ts
├── QuotaExceededError.ts
└── tests/ # Comprehensive test suite
├── CustomError.test.ts
├── AuthenticationError.test.ts
└── ... (all error classes)TypeScript Support
This package includes full TypeScript support with:
- Complete type definitions
- IntelliSense support
- Compile-time type checking
- Type-safe error handling
License
ISC
This enhanced exception system provides a solid foundation for robust error handling in production TypeScript applications.