// db/seeds/menu-v2-seed.ts import { mainNav, additionalNav, mainNavVendor, additionalNavVendor, MenuSection, MenuItem } from "@/config/menuConfig"; import koMenu from '@/i18n/locales/ko/menu.json'; import enMenu from '@/i18n/locales/en/menu.json'; import db from "@/db/db"; import { menuTreeNodes } from "@/db/schema/menu-v2"; import type { MenuDomain } from "@/lib/menu-v2/types"; type TranslationObject = { [key: string]: string | TranslationObject }; // 중첩 키로 번역 값 가져오기 function getTranslation(key: string, locale: 'ko' | 'en'): string { const translations: TranslationObject = locale === 'ko' ? koMenu : enMenu; const keys = key.split('.'); let value: string | TranslationObject | undefined = translations; for (const k of keys) { if (typeof value === 'object' && value !== null) { value = value[k]; } else { return key; } if (value === undefined) return key; } return typeof value === 'string' ? value : key; } export async function seedMenuTree() { console.log('🌱 Starting menu tree seeding...'); // 기존 데이터 삭제 await db.delete(menuTreeNodes); console.log('✅ Cleared existing menu tree data'); // evcp 도메인 seed await seedDomainMenus('evcp', mainNav, additionalNav); console.log('✅ Seeded evcp menu tree'); // partners 도메인 seed await seedDomainMenus('partners', mainNavVendor, additionalNavVendor); console.log('✅ Seeded partners menu tree'); console.log('🎉 Menu tree seeding completed!'); } async function seedDomainMenus( domain: MenuDomain, navConfig: MenuSection[], additionalConfig: MenuItem[] ) { // 최상위 sortOrder (메뉴그룹과 최상위 메뉴 모두 같은 레벨에서 정렬) let topLevelSortOrder = 0; // 메인 네비게이션 (메뉴그룹 → 그룹 → 메뉴) for (const section of navConfig) { // 1단계: 메뉴그룹 생성 const [menuGroup] = await db.insert(menuTreeNodes).values({ domain, parentId: null, nodeType: 'menu_group', titleKo: getTranslation(section.titleKey, 'ko'), titleEn: getTranslation(section.titleKey, 'en'), sortOrder: topLevelSortOrder++, isActive: true, }).returning(); // groupKey별로 그룹화 const groupedItems = new Map(); section.items.forEach(item => { const groupKey = item.groupKey || '__default__'; if (!groupedItems.has(groupKey)) { groupedItems.set(groupKey, []); } groupedItems.get(groupKey)!.push(item); }); let groupSortOrder = 0; for (const [groupKey, items] of groupedItems) { let parentId = menuGroup.id; // groupKey가 있으면 2단계 그룹 생성 if (groupKey !== '__default__') { const [group] = await db.insert(menuTreeNodes).values({ domain, parentId: menuGroup.id, nodeType: 'group', titleKo: getTranslation(groupKey, 'ko'), titleEn: getTranslation(groupKey, 'en'), sortOrder: groupSortOrder++, isActive: true, }).returning(); parentId = group.id; } // 3단계: 메뉴 생성 let menuSortOrder = 0; for (const item of items) { await db.insert(menuTreeNodes).values({ domain, parentId, nodeType: 'menu', titleKo: getTranslation(item.titleKey, 'ko'), titleEn: getTranslation(item.titleKey, 'en'), descriptionKo: item.descriptionKey ? getTranslation(item.descriptionKey, 'ko') : null, descriptionEn: item.descriptionKey ? getTranslation(item.descriptionKey, 'en') : null, menuPath: item.href, icon: item.icon || null, sortOrder: menuSortOrder++, isActive: true, }); } } } // 최상위 단일 링크 메뉴 (기존 additional) // nodeType을 'menu'로 설정하고 parentId를 null로 유지 for (const item of additionalConfig) { await db.insert(menuTreeNodes).values({ domain, parentId: null, nodeType: 'menu', // 'additional' 대신 'menu' 사용 titleKo: getTranslation(item.titleKey, 'ko'), titleEn: getTranslation(item.titleKey, 'en'), descriptionKo: item.descriptionKey ? getTranslation(item.descriptionKey, 'ko') : null, descriptionEn: item.descriptionKey ? getTranslation(item.descriptionKey, 'en') : null, menuPath: item.href, sortOrder: topLevelSortOrder++, // 메뉴그룹 다음 순서 isActive: true, }); } } // CLI에서 직접 실행 가능하도록 if (require.main === module) { seedMenuTree() .then(() => { console.log('Seed completed successfully'); process.exit(0); }) .catch((error) => { console.error('Seed failed:', error); process.exit(1); }); }