JSPM

@thalorlabs/errors

1.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 20
  • Score
    100M100P100Q37147F
  • License ISC

Enhanced exception handling system for TypeScript applications with comprehensive error classes and debugging capabilities

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/errors

Features

  • 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 text
  • toJSON(): Complete JSON representation for logging
  • getErrorResponse(): 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_FAILED
  • QUERY_FAILED
  • TRANSACTION_FAILED
  • CONSTRAINT_VIOLATION
  • TIMEOUT
  • DEADLOCK
  • UNKNOWN

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:coverage

Test 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() and getErrorResponse() 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.