NestJS custom error
npm install @sklv-labs/ts-nestjs-errorA NestJS error handling package that provides a robust BaseError class for consistent error handling across HTTP, RPC, and WebSocket transports.
- 🎯 Type-Safe - Full TypeScript support with comprehensive type definitions
- 🚀 Transport-Aware - Automatic detection of HTTP/RPC/WS transport context
- 🛠️ NestJS Native - Built for NestJS with seamless integration
- 📦 Rich Metadata - Support for error metadata and context
- 🔒 Security - Control over error exposure and logging
- 🏭 Factory Methods - Convenient static methods for common HTTP errors
``bash`
npm install @sklv-labs/ts-nestjs-error
This package requires the following peer dependencies:
`bash`
npm install @nestjs/common@^11.1.11 @nestjs/core@^11.1.11
Note: This package requires Node.js 24 LTS or higher.
`typescript
import { BaseError } from '@sklv-labs/ts-nestjs-error';
// Basic usage
throw new BaseError('User not found', 'USER_NOT_FOUND', {
statusCode: 404,
metadata: { userId: '123' },
});
// Using factory methods
throw BaseError.notFound('User not found', 'USER_NOT_FOUND', { userId: '123' });
`
`typescript
import { BaseError } from '@sklv-labs/ts-nestjs-error';
// Simple error
throw new BaseError('Invalid input', 'VALIDATION_ERROR', {
statusCode: 400,
});
// Error with metadata
throw new BaseError('Payment failed', 'PAYMENT_FAILED', {
statusCode: 402,
metadata: {
orderId: 'order-123',
amount: 99.99,
},
});
`
`typescript
try {
await someAsyncOperation();
} catch (error) {
throw new BaseError('Operation failed', 'OPERATION_FAILED', {
statusCode: 500,
cause: error as Error,
});
}
// Or use the helper method
throw BaseError.fromError(error, 'OPERATION_FAILED', {
statusCode: 500,
});
`
`typescript
// Bad Request (400)
throw BaseError.badRequest('Invalid email format', 'INVALID_EMAIL');
// Unauthorized (401)
throw BaseError.unauthorized('Authentication required', 'AUTH_REQUIRED');
// Forbidden (403)
throw BaseError.forbidden('Insufficient permissions', 'INSUFFICIENT_PERMISSIONS');
// Not Found (404)
throw BaseError.notFound('Resource not found', 'RESOURCE_NOT_FOUND', {
resourceId: '123',
});
// Conflict (409)
throw BaseError.conflict('Email already exists', 'EMAIL_EXISTS');
// Internal Server Error (500)
throw BaseError.internalServerError('Database connection failed', 'DB_ERROR');
`
`typescript
// Error that should not be exposed to clients (e.g., internal errors)
throw new BaseError('Database connection failed', 'DB_ERROR', {
statusCode: 500,
exposeToClient: false, // Client will see "An error occurred"
loggable: true, // But it will be logged
});
// Error that should not be logged (e.g., validation errors)
throw new BaseError('Invalid input', 'VALIDATION_ERROR', {
statusCode: 400,
loggable: false, // Won't be logged
exposeToClient: true, // But will be shown to client
});
`
`typescript
const error = new BaseError('Something went wrong', 'ERROR_CODE', {
statusCode: 500,
metadata: { key: 'value' },
});
// Convert to JSON (without stack trace)
const json = error.toJSON();
console.log(json);
// {
// name: 'BaseError',
// code: 'ERROR_CODE',
// transport: 'unknown',
// message: 'Something went wrong',
// statusCode: 500,
// metadata: { key: 'value' },
// timestamp: '2024-01-01T00:00:00.000Z'
// }
// Convert to JSON (with stack trace)
const jsonWithStack = error.toJSON(true);
// Get client-safe error (for HTTP responses)
const clientError = error.getClientSafeError();
// {
// code: 'ERROR_CODE',
// message: 'Something went wrong',
// statusCode: 500,
// metadata: { key: 'value' }
// }
// Get RPC error (for RPC transport)
const rpcError = error.getRpcError();
// {
// code: 'ERROR_CODE',
// message: 'Something went wrong',
// metadata: { key: 'value' }
// }
`
The main error class that extends the native Error class.
#### Constructor
`typescript`
new BaseError(
message: string,
code: string,
options?: BaseErrorOptions
)
#### Properties
- code: string - Error code for programmatic identificationtransport: ErrorTransport
- - Transport context (auto-detected by exception filters)statusCode?: number
- - HTTP status code (if applicable)metadata?: Record
- - Additional error contexttimestamp: Date
- - When the error was createdloggable: boolean
- - Whether the error should be logged (default: true)exposeToClient: boolean
- - Whether the error should be exposed to clients (default: true)
#### Methods
- toJSON(includeStack?: boolean): Record - Convert error to plain objectgetClientSafeError(): {...}
- - Get error details safe for HTTP client exposuregetRpcError(): {...}
- - Get error payload for RPC transportsetTransportIfUnset(transport: ErrorTransport): void
- - Internal method used by exception filters
#### Static Factory Methods
- BaseError.fromError(error: Error, code: string, options?: BaseErrorOptions): BaseErrorBaseError.badRequest(message: string, code?: string, metadata?: Record
- BaseError.unauthorized(message: string, code?: string, metadata?: Record
- BaseError.forbidden(message: string, code?: string, metadata?: Record
- BaseError.notFound(message: string, code?: string, metadata?: Record
- BaseError.conflict(message: string, code?: string, metadata?: Record
- BaseError.internalServerError(message: string, code?: string, metadata?: Record
-
`typescript
type ErrorTransport = 'http' | 'rpc' | 'ws' | 'unknown';
interface BaseErrorOptions {
statusCode?: number;
metadata?: Record
cause?: Error;
loggable?: boolean;
exposeToClient?: boolean;
}
`
The BaseError class is designed to work with NestJS exception filters that automatically detect the transport context:
`typescript
import { Catch, ArgumentsHost } from '@nestjs/common';
import { BaseError } from '@sklv-labs/ts-nestjs-error';
@Catch(BaseError)
export class BaseErrorFilter implements ExceptionFilter {
catch(exception: BaseError, host: ArgumentsHost) {
const ctx = host.switchToHttpContext();
const request = ctx.getRequest();
// Auto-detect transport
if (ctx.getType() === 'http') {
exception.setTransportIfUnset('http');
// Handle HTTP error
} else if (ctx.getType() === 'rpc') {
exception.setTransportIfUnset('rpc');
// Handle RPC error
} else if (ctx.getType() === 'ws') {
exception.setTransportIfUnset('ws');
// Handle WebSocket error
}
// Use appropriate method based on transport
if (exception.transport === 'http') {
return exception.getClientSafeError();
} else {
return exception.getRpcError();
}
}
}
`
`bashBuild
npm run build
MIT © sklv-labs