266 lines
6.0 KiB
TypeScript
266 lines
6.0 KiB
TypeScript
import {
|
|
WebTypeDefinition,
|
|
ButtonActionDefinition,
|
|
RegistryEvent,
|
|
RegistryEventListener,
|
|
} from "./types";
|
|
|
|
/**
|
|
* 웹타입 레지스트리 클래스
|
|
* 웹타입과 버튼 액션의 동적 등록/관리를 담당
|
|
*/
|
|
export class WebTypeRegistry {
|
|
private static webTypes = new Map<string, WebTypeDefinition>();
|
|
private static buttonActions = new Map<string, ButtonActionDefinition>();
|
|
private static listeners: RegistryEventListener[] = [];
|
|
|
|
// ===== 웹타입 관리 =====
|
|
|
|
/**
|
|
* 웹타입 등록
|
|
*/
|
|
static register(definition: WebTypeDefinition): void {
|
|
this.webTypes.set(definition.webType, definition);
|
|
this.notifyListeners({
|
|
type: "webtype_registered",
|
|
data: definition,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 웹타입 조회
|
|
*/
|
|
static get(webType: string): WebTypeDefinition | undefined {
|
|
return this.webTypes.get(webType);
|
|
}
|
|
|
|
/**
|
|
* 모든 웹타입 조회 (활성화된 것만, 정렬됨)
|
|
*/
|
|
static getAll(): WebTypeDefinition[] {
|
|
return Array.from(this.webTypes.values())
|
|
.filter((type) => type.isActive !== false)
|
|
.sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
|
|
}
|
|
|
|
/**
|
|
* 카테고리별 웹타입 조회
|
|
*/
|
|
static getByCategory(category: string): WebTypeDefinition[] {
|
|
return this.getAll().filter((type) => type.category === category);
|
|
}
|
|
|
|
/**
|
|
* 웹타입 등록 해제
|
|
*/
|
|
static unregister(webType: string): boolean {
|
|
const definition = this.webTypes.get(webType);
|
|
if (definition) {
|
|
this.webTypes.delete(webType);
|
|
this.notifyListeners({
|
|
type: "webtype_unregistered",
|
|
data: definition,
|
|
});
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 웹타입 존재 여부 확인
|
|
*/
|
|
static has(webType: string): boolean {
|
|
return this.webTypes.has(webType);
|
|
}
|
|
|
|
/**
|
|
* 모든 웹타입 카테고리 조회
|
|
*/
|
|
static getCategories(): string[] {
|
|
const categories = new Set<string>();
|
|
this.getAll().forEach((type) => categories.add(type.category));
|
|
return Array.from(categories).sort();
|
|
}
|
|
|
|
// ===== 버튼 액션 관리 =====
|
|
|
|
/**
|
|
* 버튼 액션 등록
|
|
*/
|
|
static registerAction(definition: ButtonActionDefinition): void {
|
|
this.buttonActions.set(definition.actionType, definition);
|
|
this.notifyListeners({
|
|
type: "action_registered",
|
|
data: definition,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 버튼 액션 조회
|
|
*/
|
|
static getAction(actionType: string): ButtonActionDefinition | undefined {
|
|
return this.buttonActions.get(actionType);
|
|
}
|
|
|
|
/**
|
|
* 모든 버튼 액션 조회 (활성화된 것만, 정렬됨)
|
|
*/
|
|
static getAllActions(): ButtonActionDefinition[] {
|
|
return Array.from(this.buttonActions.values())
|
|
.filter((action) => action.isActive !== false)
|
|
.sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
|
|
}
|
|
|
|
/**
|
|
* 카테고리별 버튼 액션 조회
|
|
*/
|
|
static getActionsByCategory(category: string): ButtonActionDefinition[] {
|
|
return this.getAllActions().filter(
|
|
(action) => action.category === category
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 버튼 액션 등록 해제
|
|
*/
|
|
static unregisterAction(actionType: string): boolean {
|
|
const definition = this.buttonActions.get(actionType);
|
|
if (definition) {
|
|
this.buttonActions.delete(actionType);
|
|
this.notifyListeners({
|
|
type: "action_unregistered",
|
|
data: definition,
|
|
});
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 버튼 액션 존재 여부 확인
|
|
*/
|
|
static hasAction(actionType: string): boolean {
|
|
return this.buttonActions.has(actionType);
|
|
}
|
|
|
|
/**
|
|
* 모든 버튼 액션 카테고리 조회
|
|
*/
|
|
static getActionCategories(): string[] {
|
|
const categories = new Set<string>();
|
|
this.getAllActions().forEach((action) => categories.add(action.category));
|
|
return Array.from(categories).sort();
|
|
}
|
|
|
|
// ===== 이벤트 관리 =====
|
|
|
|
/**
|
|
* 이벤트 리스너 등록
|
|
*/
|
|
static addEventListener(listener: RegistryEventListener): void {
|
|
this.listeners.push(listener);
|
|
}
|
|
|
|
/**
|
|
* 이벤트 리스너 제거
|
|
*/
|
|
static removeEventListener(listener: RegistryEventListener): void {
|
|
const index = this.listeners.indexOf(listener);
|
|
if (index > -1) {
|
|
this.listeners.splice(index, 1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 이벤트 알림
|
|
*/
|
|
private static notifyListeners(event: RegistryEvent): void {
|
|
this.listeners.forEach((listener) => {
|
|
try {
|
|
listener(event);
|
|
} catch (error) {
|
|
console.error("Registry event listener error:", error);
|
|
}
|
|
});
|
|
}
|
|
|
|
// ===== 유틸리티 메서드 =====
|
|
|
|
/**
|
|
* 레지스트리 상태 조회
|
|
*/
|
|
static getStats() {
|
|
return {
|
|
webTypes: {
|
|
total: this.webTypes.size,
|
|
active: this.getAll().length,
|
|
categories: this.getCategories().length,
|
|
},
|
|
buttonActions: {
|
|
total: this.buttonActions.size,
|
|
active: this.getAllActions().length,
|
|
categories: this.getActionCategories().length,
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 레지스트리 초기화 (테스트용)
|
|
*/
|
|
static clear(): void {
|
|
this.webTypes.clear();
|
|
this.buttonActions.clear();
|
|
this.listeners.length = 0;
|
|
}
|
|
|
|
/**
|
|
* 웹타입 정의 검증
|
|
*/
|
|
static validateWebType(definition: Partial<WebTypeDefinition>): string[] {
|
|
const errors: string[] = [];
|
|
|
|
if (!definition.webType) {
|
|
errors.push("webType is required");
|
|
}
|
|
|
|
if (!definition.name) {
|
|
errors.push("name is required");
|
|
}
|
|
|
|
if (!definition.category) {
|
|
errors.push("category is required");
|
|
}
|
|
|
|
if (!definition.component) {
|
|
errors.push("component is required");
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
/**
|
|
* 버튼 액션 정의 검증
|
|
*/
|
|
static validateButtonAction(
|
|
definition: Partial<ButtonActionDefinition>
|
|
): string[] {
|
|
const errors: string[] = [];
|
|
|
|
if (!definition.actionType) {
|
|
errors.push("actionType is required");
|
|
}
|
|
|
|
if (!definition.name) {
|
|
errors.push("name is required");
|
|
}
|
|
|
|
if (!definition.category) {
|
|
errors.push("category is required");
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
}
|
|
|
|
|