레이아웃 추가기능
This commit is contained in:
174
frontend/lib/registry/utils/createLayoutDefinition.ts
Normal file
174
frontend/lib/registry/utils/createLayoutDefinition.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
"use client";
|
||||
|
||||
import { LayoutDefinition, LayoutType, LayoutCategory } from "@/types/layout";
|
||||
import React from "react";
|
||||
|
||||
/**
|
||||
* 레이아웃 정의를 생성하는 헬퍼 함수
|
||||
* 타입 안전성과 기본값을 보장합니다.
|
||||
*/
|
||||
export interface CreateLayoutDefinitionOptions {
|
||||
id: string;
|
||||
name: string;
|
||||
nameEng?: string;
|
||||
description: string;
|
||||
category: LayoutCategory;
|
||||
icon?: string;
|
||||
component: React.ComponentType<any>;
|
||||
defaultConfig?: Record<string, any>;
|
||||
defaultZones?: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
position?: Record<string, any>;
|
||||
size?: {
|
||||
width: number | string;
|
||||
height: number | string;
|
||||
minWidth?: number;
|
||||
minHeight?: number;
|
||||
maxWidth?: number;
|
||||
maxHeight?: number;
|
||||
};
|
||||
[key: string]: any;
|
||||
}>;
|
||||
tags?: string[];
|
||||
isActive?: boolean;
|
||||
version?: string;
|
||||
author?: string;
|
||||
documentation?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 레이아웃 정의를 생성합니다.
|
||||
*/
|
||||
export function createLayoutDefinition(options: CreateLayoutDefinitionOptions): LayoutDefinition {
|
||||
const {
|
||||
id,
|
||||
name,
|
||||
nameEng = name,
|
||||
description,
|
||||
category,
|
||||
icon = "layout",
|
||||
component,
|
||||
defaultConfig = {},
|
||||
defaultZones = [],
|
||||
tags = [],
|
||||
isActive = true,
|
||||
version = "1.0.0",
|
||||
author = "Developer",
|
||||
documentation = "",
|
||||
} = options;
|
||||
|
||||
// ID 유효성 검사
|
||||
if (!id || typeof id !== "string" || !/^[a-z][a-z0-9-]*$/.test(id)) {
|
||||
throw new Error(
|
||||
`Invalid layout ID: "${id}". ID must start with a letter and contain only lowercase letters, numbers, and hyphens.`,
|
||||
);
|
||||
}
|
||||
|
||||
// 필수 필드 검사
|
||||
if (!name.trim()) {
|
||||
throw new Error("Layout name is required");
|
||||
}
|
||||
|
||||
if (!description.trim()) {
|
||||
throw new Error("Layout description is required");
|
||||
}
|
||||
|
||||
if (!component) {
|
||||
throw new Error("Layout component is required");
|
||||
}
|
||||
|
||||
// 기본 태그 자동 추가
|
||||
const autoTags = [id, category, "layout"];
|
||||
const allTags = [...new Set([...autoTags, ...tags])];
|
||||
|
||||
const definition: LayoutDefinition = {
|
||||
id: id as LayoutType,
|
||||
name,
|
||||
nameEng,
|
||||
description,
|
||||
category,
|
||||
icon,
|
||||
component,
|
||||
defaultConfig,
|
||||
defaultZones,
|
||||
tags: allTags,
|
||||
isActive,
|
||||
metadata: {
|
||||
version,
|
||||
author,
|
||||
documentation,
|
||||
createdAt: new Date().toISOString(),
|
||||
lastUpdated: new Date().toISOString(),
|
||||
},
|
||||
};
|
||||
|
||||
console.log(`📦 레이아웃 정의 생성: ${id} (${name})`);
|
||||
return definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* 레이아웃 정의의 유효성을 검사합니다.
|
||||
*/
|
||||
export function validateLayoutDefinition(definition: LayoutDefinition): {
|
||||
isValid: boolean;
|
||||
errors: string[];
|
||||
warnings: string[];
|
||||
} {
|
||||
const errors: string[] = [];
|
||||
const warnings: string[] = [];
|
||||
|
||||
// 필수 필드 검사
|
||||
if (!definition.id) errors.push("ID is required");
|
||||
if (!definition.name) errors.push("Name is required");
|
||||
if (!definition.description) errors.push("Description is required");
|
||||
if (!definition.category) errors.push("Category is required");
|
||||
if (!definition.component) errors.push("Component is required");
|
||||
|
||||
// ID 형식 검사
|
||||
if (definition.id && !/^[a-z][a-z0-9-]*$/.test(definition.id)) {
|
||||
errors.push("ID must start with a letter and contain only lowercase letters, numbers, and hyphens");
|
||||
}
|
||||
|
||||
// defaultZones 검사
|
||||
if (definition.defaultZones) {
|
||||
definition.defaultZones.forEach((zone, index) => {
|
||||
if (!zone.id) errors.push(`Zone ${index}: ID is required`);
|
||||
if (!zone.name) errors.push(`Zone ${index}: Name is required`);
|
||||
});
|
||||
}
|
||||
|
||||
// 경고사항 검사
|
||||
if (!definition.nameEng) warnings.push("English name is recommended");
|
||||
if (!definition.icon || definition.icon === "layout") warnings.push("Custom icon is recommended");
|
||||
if (!definition.defaultZones || definition.defaultZones.length === 0) {
|
||||
warnings.push("Default zones are recommended for better UX");
|
||||
}
|
||||
|
||||
return {
|
||||
isValid: errors.length === 0,
|
||||
errors,
|
||||
warnings,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 레이아웃 정의를 디버그 정보와 함께 출력합니다.
|
||||
*/
|
||||
export function debugLayoutDefinition(definition: LayoutDefinition): void {
|
||||
console.group(`🔍 Layout Debug: ${definition.id}`);
|
||||
console.log("📋 Definition:", definition);
|
||||
|
||||
const validation = validateLayoutDefinition(definition);
|
||||
if (validation.errors.length > 0) {
|
||||
console.error("❌ Errors:", validation.errors);
|
||||
}
|
||||
if (validation.warnings.length > 0) {
|
||||
console.warn("⚠️ Warnings:", validation.warnings);
|
||||
}
|
||||
if (validation.isValid) {
|
||||
console.log("✅ Definition is valid");
|
||||
}
|
||||
|
||||
console.groupEnd();
|
||||
}
|
||||
Reference in New Issue
Block a user