import { WebTypeDefinition, ButtonActionDefinition, RegistryEvent, RegistryEventListener, } from "./types"; /** * 웹타입 레지스트리 클래스 * 웹타입과 버튼 액션의 동적 등록/관리를 담당 */ export class WebTypeRegistry { private static webTypes = new Map(); private static buttonActions = new Map(); 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(); 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(); 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): 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 ): 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; } }