@restnfeel/agentc-starter-kit
Version:
한국어 기업용 CMS 모듈 - Task Master AI와 함께 빠르게 웹사이트를 구현할 수 있는 재사용 가능한 컴포넌트 시스템
275 lines (239 loc) • 7.08 kB
text/typescript
/**
* Component Registry System
* 서비스 티어별 컴포넌트 관리 시스템
*/
import {
ComponentRegistry,
ComponentDefinition,
ComponentType,
ServiceTier,
BaseComponent,
ComponentSettings,
ComponentSchema,
} from "../../types/template-system";
export class TemplateComponentRegistry implements ComponentRegistry {
private components: Map<string, ComponentDefinition> = new Map();
private tierComponents: Map<ServiceTier, Set<ComponentType>> = new Map();
constructor() {
this.initializeTierMappings();
}
/**
* 서비스 티어별 사용 가능한 컴포넌트 초기화
*/
private initializeTierMappings(): void {
// Starter 티어 - 기본 컴포넌트만
this.tierComponents.set(
ServiceTier.STARTER,
new Set([
ComponentType.HERO,
ComponentType.ABOUT,
ComponentType.CONTACT,
ComponentType.FOOTER,
])
);
// Standard 티어 - Starter + 추가 컴포넌트
this.tierComponents.set(
ServiceTier.STANDARD,
new Set([
ComponentType.HERO,
ComponentType.ABOUT,
ComponentType.SERVICES,
ComponentType.TESTIMONIALS,
ComponentType.BLOG,
ComponentType.CONTACT,
ComponentType.FOOTER,
])
);
// Plus 티어 - 모든 컴포넌트
this.tierComponents.set(
ServiceTier.PLUS,
new Set([
ComponentType.HERO,
ComponentType.ABOUT,
ComponentType.SERVICES,
ComponentType.TESTIMONIALS,
ComponentType.BLOG,
ComponentType.CONTACT,
ComponentType.FOOTER,
ComponentType.TEAM,
ComponentType.GALLERY,
ComponentType.NEWSLETTER,
ComponentType.CASE_STUDIES,
])
);
}
/**
* 컴포넌트 등록
*/
register(component: ComponentDefinition): void {
const key = this.getComponentKey(component.type, component.tier);
this.components.set(key, component);
}
/**
* 특정 티어의 컴포넌트 조회
*/
get(type: ComponentType, tier: ServiceTier): ComponentDefinition | null {
// 요청된 티어에서 컴포넌트가 사용 가능한지 확인
if (!this.isComponentAvailableInTier(type, tier)) {
return null;
}
// 정확한 티어의 컴포넌트를 먼저 찾기
let key = this.getComponentKey(type, tier);
let component = this.components.get(key);
if (component) {
return component;
}
// 하위 호환성을 위해 낮은 티어의 컴포넌트 찾기
const tierHierarchy = [
ServiceTier.STARTER,
ServiceTier.STANDARD,
ServiceTier.PLUS,
];
const currentTierIndex = tierHierarchy.indexOf(tier);
for (let i = currentTierIndex - 1; i >= 0; i--) {
key = this.getComponentKey(type, tierHierarchy[i]);
component = this.components.get(key);
if (component) {
return component;
}
}
return null;
}
/**
* 특정 티어에서 사용 가능한 모든 컴포넌트 조회
*/
getAvailable(tier: ServiceTier): ComponentDefinition[] {
const availableTypes = this.tierComponents.get(tier) || new Set();
const components: ComponentDefinition[] = [];
availableTypes.forEach((type) => {
const component = this.get(type, tier);
if (component) {
components.push(component);
}
});
return components.sort((a, b) => a.name.localeCompare(b.name));
}
/**
* 컴포넌트가 특정 티어에서 유효한지 검증
*/
validate(component: BaseComponent, tier: ServiceTier): boolean {
// 컴포넌트가 해당 티어에서 사용 가능한지 확인
if (!this.isComponentAvailableInTier(component.type, tier)) {
return false;
}
// 컴포넌트가 등록되어 있는지 확인
const definition = this.get(component.type, tier);
if (!definition) {
return false;
}
// 컴포넌트 설정이 스키마에 맞는지 검증
return this.validateComponentSettings(
component.settings,
definition.schema
);
}
/**
* 컴포넌트가 특정 티어에서 사용 가능한지 확인
*/
private isComponentAvailableInTier(
type: ComponentType,
tier: ServiceTier
): boolean {
const availableComponents = this.tierComponents.get(tier);
return availableComponents ? availableComponents.has(type) : false;
}
/**
* 컴포넌트 키 생성
*/
private getComponentKey(type: ComponentType, tier: ServiceTier): string {
return `${type}-${tier}`;
}
/**
* 컴포넌트 설정이 스키마에 맞는지 검증
*/
private validateComponentSettings(
settings: ComponentSettings,
_schema: ComponentSchema
): boolean {
// 기본 필수 필드 확인
if (
typeof settings.enabled !== "boolean" ||
typeof settings.visible !== "boolean" ||
typeof settings.customizable !== "boolean"
) {
return false;
}
// 추가 스키마 검증 로직은 필요에 따라 구현
return true;
}
/**
* 등록된 모든 컴포넌트 조회
*/
getAllComponents(): ComponentDefinition[] {
return Array.from(this.components.values());
}
/**
* 특정 타입의 모든 티어 버전 조회
*/
getComponentVariants(type: ComponentType): ComponentDefinition[] {
const variants: ComponentDefinition[] = [];
[ServiceTier.STARTER, ServiceTier.STANDARD, ServiceTier.PLUS].forEach(
(tier) => {
const component = this.get(type, tier);
if (component) {
variants.push(component);
}
}
);
return variants;
}
/**
* 컴포넌트 등록 해제
*/
unregister(type: ComponentType, tier: ServiceTier): boolean {
const key = this.getComponentKey(type, tier);
return this.components.delete(key);
}
/**
* 레지스트리 초기화
*/
clear(): void {
this.components.clear();
}
/**
* 티어 업그레이드 시 사용 가능한 새로운 컴포넌트 조회
*/
getNewComponentsForTierUpgrade(
fromTier: ServiceTier,
toTier: ServiceTier
): ComponentType[] {
const fromComponents = this.tierComponents.get(fromTier) || new Set();
const toComponents = this.tierComponents.get(toTier) || new Set();
const newComponents: ComponentType[] = [];
toComponents.forEach((component) => {
if (!fromComponents.has(component)) {
newComponents.push(component);
}
});
return newComponents;
}
/**
* 티어별 컴포넌트 제한 확인
*/
getTierRestrictions(tier: ServiceTier): {
allowedComponents: ComponentType[];
restrictedComponents: ComponentType[];
} {
const allowedComponents = Array.from(this.tierComponents.get(tier) || []);
const allComponents = Object.values(ComponentType);
const restrictedComponents = allComponents.filter(
(comp) => !allowedComponents.includes(comp)
);
return {
allowedComponents,
restrictedComponents,
};
}
}
// 싱글톤 인스턴스 export
export const componentRegistry = new TemplateComponentRegistry();