169 lines
4.9 KiB
TypeScript
169 lines
4.9 KiB
TypeScript
import type { TranslationContext } from '../template-engine/TranslationEngine';
|
|
|
|
/**
|
|
* 템플릿 엔진 에러 기본 클래스
|
|
*/
|
|
export class TemplateEngineError extends Error {
|
|
public readonly code: string;
|
|
public readonly userMessageKey: string;
|
|
public readonly showStack: boolean;
|
|
public readonly icon: string;
|
|
public readonly recoverable: boolean;
|
|
|
|
constructor(
|
|
code: string,
|
|
userMessageKey: string,
|
|
options: {
|
|
showStack?: boolean;
|
|
icon?: string;
|
|
recoverable?: boolean;
|
|
} = {}
|
|
) {
|
|
super(userMessageKey);
|
|
this.name = 'TemplateEngineError';
|
|
this.code = code;
|
|
this.userMessageKey = userMessageKey;
|
|
this.showStack = options.showStack ?? true;
|
|
this.icon = options.icon ?? 'fa-circle-exclamation';
|
|
this.recoverable = options.recoverable ?? true;
|
|
|
|
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 다국어가 적용된 사용자 메시지를 반환합니다.
|
|
*
|
|
* @param context 번역 컨텍스트
|
|
* @param translationEngine 번역 엔진 (선택)
|
|
*/
|
|
getUserMessage(
|
|
context?: TranslationContext,
|
|
translationEngine?: { translate: (key: string, context: TranslationContext) => string }
|
|
): string {
|
|
// 번역 엔진이 없거나 컨텍스트가 없으면 키를 그대로 반환
|
|
if (!translationEngine || !context) {
|
|
return this.userMessageKey;
|
|
}
|
|
|
|
try {
|
|
return translationEngine.translate(this.userMessageKey, context);
|
|
} catch (e) {
|
|
// 번역 실패 시 키를 그대로 반환
|
|
return this.userMessageKey;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 템플릿을 찾을 수 없을 때 발생하는 에러
|
|
*/
|
|
export class TemplateNotFoundError extends TemplateEngineError {
|
|
constructor() {
|
|
super(
|
|
'TEMPLATE_NOT_FOUND',
|
|
'$t:core.errors.template_not_found',
|
|
{
|
|
showStack: false,
|
|
icon: 'fa-paint-brush',
|
|
recoverable: false,
|
|
}
|
|
);
|
|
this.name = 'TemplateNotFoundError';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 레이아웃 로딩 실패 에러
|
|
*/
|
|
export class LayoutLoadError extends TemplateEngineError {
|
|
constructor(layoutId?: string) {
|
|
const messageKey = layoutId
|
|
? '$t:core.errors.layout_load_failed_with_id|layoutId=' + layoutId
|
|
: '$t:core.errors.layout_load_failed';
|
|
|
|
super('LAYOUT_LOAD_FAILED', messageKey, {
|
|
showStack: true,
|
|
icon: 'fa-file-circle-xmark',
|
|
recoverable: true,
|
|
});
|
|
this.name = 'LayoutLoadError';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 컴포넌트 레지스트리 에러
|
|
*/
|
|
export class ComponentRegistryError extends TemplateEngineError {
|
|
constructor(componentName?: string) {
|
|
const messageKey = componentName
|
|
? '$t:core.errors.component_load_failed_with_name|componentName=' + componentName
|
|
: '$t:core.errors.component_load_failed';
|
|
|
|
super('COMPONENT_REGISTRY_FAILED', messageKey, {
|
|
showStack: true,
|
|
icon: 'fa-cubes',
|
|
recoverable: true,
|
|
});
|
|
this.name = 'ComponentRegistryError';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 번역 파일 로딩 에러
|
|
*/
|
|
export class TranslationLoadError extends TemplateEngineError {
|
|
constructor(locale?: string) {
|
|
const messageKey = locale
|
|
? '$t:core.errors.translation_load_failed_with_locale|locale=' + locale
|
|
: '$t:core.errors.translation_load_failed';
|
|
|
|
super('TRANSLATION_LOAD_FAILED', messageKey, {
|
|
showStack: false,
|
|
icon: 'fa-language',
|
|
recoverable: true,
|
|
});
|
|
this.name = 'TranslationLoadError';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 일반 Error를 TemplateEngineError로 변환
|
|
*/
|
|
export function toTemplateEngineError(error: Error | unknown): TemplateEngineError {
|
|
// 이미 TemplateEngineError인 경우 그대로 반환
|
|
if (error instanceof TemplateEngineError) {
|
|
return error;
|
|
}
|
|
|
|
// Error 객체인 경우
|
|
if (error instanceof Error) {
|
|
// 원본 에러 메시지를 그대로 사용 (다국어 키가 아님)
|
|
const tempError = new TemplateEngineError(
|
|
'TEMPLATE_INIT_ERROR',
|
|
error.message || '$t:core.errors.template_init_error',
|
|
{
|
|
showStack: true,
|
|
icon: 'fa-circle-exclamation',
|
|
recoverable: true,
|
|
}
|
|
);
|
|
// 원본 스택을 보존
|
|
tempError.stack = error.stack;
|
|
return tempError;
|
|
}
|
|
|
|
// 기타 타입인 경우
|
|
return new TemplateEngineError(
|
|
'TEMPLATE_INIT_ERROR',
|
|
'$t:core.errors.template_init_error',
|
|
{
|
|
showStack: false,
|
|
icon: 'fa-circle-exclamation',
|
|
recoverable: true,
|
|
}
|
|
);
|
|
}
|