import dotenv from 'dotenv'; dotenv.config(); import prisma from '../src/utils/db'; const INITIAL_VERTICALS = [ { name: 'Cybersecurity', slug: 'cybersecurity', icon: 'Shield', color: '#ef4444', description: 'OT, Infrastructure & Data Defense' }, { name: 'AI & ML', slug: 'ai-ml', icon: 'Cpu', color: '#8b5cf6', description: 'Artificial Intelligence & Machine Learning' }, { name: 'Healthcare & Pharma', slug: 'healthcare-pharma', icon: 'Activity', color: '#ec4899', description: 'Medical, Diagnostics & BioTech' }, { name: 'Finance & Banking', slug: 'finance-banking', icon: 'Landmark', color: '#10b981', description: 'FinTech, Payments & Risk Analytics' }, { name: 'Insurance', slug: 'insurance', icon: 'FileCheck', color: '#3b82f6', description: 'InsurTech, Claims & Underwriting' }, { name: 'Energy & Utilities', slug: 'energy-utilities', icon: 'Zap', color: '#f59e0b', description: 'Smart Grid, Power & Renewables' }, { name: 'Agriculture', slug: 'agriculture', icon: 'Leaf', color: '#84cc16', description: 'AgriTech, Precision Farming & Supply' }, { name: 'Education', slug: 'education', icon: 'GraduationCap', color: '#06b6d4', description: 'EdTech, LMS & Institutional Tools' }, { name: 'Manufacturing & IoT', slug: 'manufacturing-iot', icon: 'Factory', color: '#6366f1', description: 'Industrial Automation & Edge IoT' }, { name: 'Automotive', slug: 'automotive', icon: 'Car', color: '#14b8a6', description: 'Connected Vehicles & Telematics' }, { name: 'Retail & Supply Chain', slug: 'retail-supply-chain', icon: 'ShoppingBag', color: '#d97706', description: 'E-Commerce, Logistics & Smart Retail' }, { name: 'Blockchain', slug: 'blockchain', icon: 'Link', color: '#0284c7', description: 'Smart Contracts & Web3 Infrastructure' }, ]; function inferContentType(type: string, subcategory?: string | null): string { const sub = (subcategory || '').toLowerCase().trim(); if (sub === 'case study') return 'case_study'; if (sub === 'showcase') return 'showcase'; if (sub === 'news letter' || sub === 'marketing milestone') return 'newsletter'; if (sub === 'portfolio' || sub === 'company deck' || sub === 'product showcase' || sub === 'rnd innovation') return 'portfolio'; if (sub === 'mvp') return 'mvp'; if (sub === 'workflow automation' || sub === 'worlflow automation') return 'workflow'; if (sub === 'use case') return 'use_case'; if (sub === 'test drive resources') return 'test_drive'; if (type === 'case_study') return 'case_study'; if (type === 'url') return 'showcase'; if (type.includes('pdf') || type.includes('document') || type.includes('word')) return 'document'; if (type.includes('sheet') || type.includes('csv') || type.includes('excel')) return 'spreadsheet'; if (type.includes('presentation') || type.includes('powerpoint')) return 'presentation'; if (type.includes('image')) return 'image'; return 'document'; } function matchVerticalSlugs(title: string, description?: string | null): string[] { const text = `${title} ${description || ''}`.toLowerCase(); const matched = new Set(); if (/cybersecurity|security|threat|ot |defence|defense|ransomware|audit|hacker|firewall|fpga|compliance|kyc|aml/.test(text)) { matched.add('cybersecurity'); } if (/ai|machine learning|resnet|densenet|nlp|chatbot|genai|deep learning|prediction|predictive|forecasting|gpt|n8n|rag|speech/.test(text)) { matched.add('ai-ml'); } if (/health|medical|pharma|drug|cancer|hospital|patient|doctor|eye|blood|hematology|x-ray|brain tumor|bio|biotech|wearable|ventilator|ct scan/.test(text)) { matched.add('healthcare-pharma'); } if (/bank|fintech|payment|fraud|credit|loan|financial|accounting|cash|revenue|investor|audit|trade|b2b/.test(text)) { matched.add('finance-banking'); } if (/insurance|claims|underwriting|insurtech|policy|catastrophe|actuary/.test(text)) { matched.add('insurance'); } if (/energy|grid|power|renewable|ev |electric vehicle|utility|utilities|battery|charging|power plant|oms|ems|metering|solar|wind/.test(text)) { matched.add('energy-utilities'); } if (/agri|farm|crop|livestock|soil|aqua|pest|aquaponics|harvest|yield/.test(text)) { matched.add('agriculture'); } if (/education|student|learning|lms|classroom|exam|academic|textbook|proctoring|university|school/.test(text)) { matched.add('education'); } if (/manufactur|industrial|iot|edge|predictive maintenance|digital twin|esp32|ble board|pcb|robotics|factory|plc/.test(text)) { matched.add('manufacturing-iot'); } if (/vehicle|automotive|fleet|telematics|adas|car|driving|mobility|maas/.test(text)) { matched.add('automotive'); } if (/retail|e-commerce|supply chain|inventory|mall|store|basket|procurement|logistics|fmcg|pos/.test(text)) { matched.add('retail-supply-chain'); } if (/blockchain|smart contract|credentialing|traceability/.test(text)) { matched.add('blockchain'); } return Array.from(matched); } async function main() { console.log('🚀 Starting Data Normalization & Taxonomy Seeding...'); // 1. Seed Verticals const verticalMap = new Map(); // slug -> id for (const v of INITIAL_VERTICALS) { const upserted = await prisma.vertical.upsert({ where: { slug: v.slug }, update: { name: v.name, icon: v.icon, color: v.color, description: v.description }, create: v, }); verticalMap.set(v.slug, upserted.id); } console.log(`✅ ${verticalMap.size} Verticals ready.`); // 2. Fix typos in Subcategories await prisma.asset.updateMany({ where: { subcategory: { in: ['Showcaase', 'showcase'] } }, data: { subcategory: 'Showcase' }, }); await prisma.asset.updateMany({ where: { subcategory: 'Worlflow Automation' }, data: { subcategory: 'Workflow Automation' }, }); await prisma.asset.updateMany({ where: { subcategory: 'Use Case', categoryId: 'Marketing' }, data: { categoryId: 'Technical' }, }); await prisma.asset.updateMany({ where: { subcategory: 'MVP', categoryId: 'Presentations' }, data: { categoryId: 'Resources' }, }); console.log('✅ Subcategory typos & category alignments fixed.'); // 3. Process all assets const assets = await prisma.asset.findMany(); let updatedCount = 0; for (const asset of assets) { const contentType = inferContentType(asset.type, asset.subcategory); const matchedSlugs = matchVerticalSlugs(asset.title, asset.description); const verticalIds = matchedSlugs.map(slug => verticalMap.get(slug)).filter(Boolean) as string[]; await prisma.asset.update({ where: { id: asset.id }, data: { contentType, verticals: { set: verticalIds.map(id => ({ id })), }, }, }); updatedCount++; } console.log(`🎉 Successfully normalized ${updatedCount} assets with content types & vertical tags!`); } main() .catch(err => { console.error('❌ Migration failed:', err); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });