Files
Gnuboard7/resources/js/core/template-engine/TemplateEngineError.ts
T
2026-04-01 10:30:52 +09:00

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,
}
);
}