UNPKG

@fab33/fab-errors

Version:

Modern error handling library with typed contexts, Error.cause chains, and ErrorSpecs

105 lines 4.91 kB
/** * @file src/fab-error.ts * @description Основной класс ошибок FabError для библиотеки @fab33/fab-errors. * @version 1.0.2 * @date 2025-05-30 * @updated Заменен тип 'any' на 'unknown' в дженерике TContext. Исправлены пробелы, eol-last. * * HISTORY: * v1.0.2 (2025-05-30): Заменен 'any' на 'unknown' в TContext, исправления ESLint. * v1.0.1 (2025-05-29): Добавлен интерфейс FabErrorJSON и обновлена сигнатура toJSON. * v1.0.0 (2025-05-29): Первая реализация FabError с поддержкой Error.cause и типизированного контекста. */ import { formatMessage } from './utils.js'; /** * Базовый класс для всех ошибок, создаваемых библиотекой `@fab33/fab-errors`. * Расширяет стандартный `Error`, добавляя структурированные метаданные: * код ошибки, спецификацию ошибки, типизированный контекст и использует * нативное свойство `Error.cause` для построения цепочек ошибок. * * @template TContext Тип объекта контекста, связанного с ошибкой. */ export class FabError extends Error { /** * Уникальный код ошибки, определенный в `ErrorSpec`. * @example 'USER_SERVICE_USER_NOT_FOUND' */ code; /** * Объект контекста, содержащий дополнительные данные об ошибке. * Типизируется через дженерик `TContext`. */ context; /** * Ссылка на спецификацию (`ErrorSpec`), по которой была создана эта ошибка. * Содержит `code`, `messageTemplate`, `defaultContext` (если есть) и `docs`. */ spec; /** * Опциональная ссылка на документацию по этой ошибке, из `ErrorSpec`. */ docs; /** * Создает экземпляр `FabError`. * * @param spec Спецификация ошибки (`ErrorSpec`), содержащая `code`, `messageTemplate` и др. * @param context Объект контекста, соответствующий `TContext` и дополняющий `spec.defaultContext`. * @param cause Оригинальная ошибка, которая привела к возникновению текущей (для `Error.cause`). */ constructor(spec, context, cause) { const fullContext = { ...spec.defaultContext, ...context }; const formattedMessage = formatMessage(spec.messageTemplate, fullContext); super(formattedMessage); this.name = this.constructor.name; // 'FabError' this.code = spec.code; this.spec = spec; this.context = Object.freeze(fullContext); // Делаем контекст неизменяемым this.docs = spec.docs; if (cause instanceof Error) { this.cause = cause; } } /** * Сериализует ошибку в JSON-совместимый объект для логирования или передачи. * Включает все ключевые свойства ошибки и рекурсивно сериализует `cause`. * * @returns Сериализованное представление ошибки, соответствующее интерфейсу `FabErrorJSON`. */ toJSON() { let causeJSON; if (this.cause) { if (this.cause instanceof FabError) { causeJSON = this.cause.toJSON(); } else if (this.cause instanceof Error) { causeJSON = { name: this.cause.name, message: this.cause.message, stack: this.cause.stack }; } else if (typeof this.cause === 'object' && this.cause !== null) { causeJSON = { ...this.cause }; } else if (this.cause !== undefined) { causeJSON = { value: String(this.cause) }; } } return { name: this.name, code: this.code, message: this.message, context: this.context, docs: this.docs, stack: this.stack, spec: { code: this.spec.code, messageTemplate: this.spec.messageTemplate, docs: this.spec.docs }, cause: causeJSON }; } } // END OF: src/fab-error.ts //# sourceMappingURL=fab-error.js.map