tspm/ts/utils.errorhandler.ts

138 lines
3.4 KiB
TypeScript

/**
* Centralized error handling utility for TSPM
*/
// Define error types
export enum ErrorType {
CONFIG = 'ConfigError',
PROCESS = 'ProcessError',
RUNTIME = 'RuntimeError',
VALIDATION = 'ValidationError',
UNKNOWN = 'UnknownError'
}
// Base error class with type and code support
export class TspmError extends Error {
type: ErrorType;
code: string;
details?: Record<string, any>;
constructor(
message: string,
type: ErrorType = ErrorType.UNKNOWN,
code: string = 'ERR_UNKNOWN',
details?: Record<string, any>
) {
super(message);
this.name = type;
this.type = type;
this.code = code;
this.details = details;
// Preserve proper stack trace
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
toString(): string {
return `[${this.type}:${this.code}] ${this.message}`;
}
}
// Specific error classes
export class ConfigError extends TspmError {
constructor(message: string, code: string = 'ERR_CONFIG', details?: Record<string, any>) {
super(message, ErrorType.CONFIG, code, details);
}
}
export class ProcessError extends TspmError {
constructor(message: string, code: string = 'ERR_PROCESS', details?: Record<string, any>) {
super(message, ErrorType.PROCESS, code, details);
}
}
export class ValidationError extends TspmError {
constructor(message: string, code: string = 'ERR_VALIDATION', details?: Record<string, any>) {
super(message, ErrorType.VALIDATION, code, details);
}
}
// Utility for handling any error type
export const handleError = (error: Error | unknown): TspmError => {
if (error instanceof TspmError) {
return error;
}
if (error instanceof Error) {
return new TspmError(error.message, ErrorType.UNKNOWN, 'ERR_UNKNOWN', { originalError: error });
}
return new TspmError(String(error), ErrorType.UNKNOWN, 'ERR_UNKNOWN');
};
// Logger with different log levels
export enum LogLevel {
DEBUG = 0,
INFO = 1,
WARN = 2,
ERROR = 3,
NONE = 4
}
export class Logger {
private static instance: Logger;
private level: LogLevel = LogLevel.INFO;
private componentName: string;
constructor(componentName: string) {
this.componentName = componentName;
}
static getInstance(componentName: string): Logger {
if (!Logger.instance) {
Logger.instance = new Logger(componentName);
}
return Logger.instance;
}
setLevel(level: LogLevel): void {
this.level = level;
}
private formatMessage(message: string): string {
const timestamp = new Date().toISOString();
return `[${timestamp}] [${this.componentName}] ${message}`;
}
debug(message: string): void {
if (this.level <= LogLevel.DEBUG) {
console.log(this.formatMessage(`DEBUG: ${message}`));
}
}
info(message: string): void {
if (this.level <= LogLevel.INFO) {
console.log(this.formatMessage(message));
}
}
warn(message: string): void {
if (this.level <= LogLevel.WARN) {
console.warn(this.formatMessage(`WARNING: ${message}`));
}
}
error(error: Error | unknown): void {
if (this.level <= LogLevel.ERROR) {
const tspmError = handleError(error);
console.error(this.formatMessage(`ERROR: ${tspmError.toString()}`));
// In debug mode, also log stack trace
if (this.level === LogLevel.DEBUG && tspmError.stack) {
console.error(tspmError.stack);
}
}
}
}