import db from './src/lib/db.js'; import initializeDatabase from './src/lib/init-db.js'; console.log('šŸš€ Migrating contact data from projects...\n'); try { // Run database initialization to ensure tables exist initializeDatabase(); console.log('āœ… Database tables verified\n'); // Get all projects with contact data const projectsWithContacts = db.prepare(` SELECT project_id, project_name, contact FROM projects WHERE contact IS NOT NULL AND contact != '' AND TRIM(contact) != '' `).all(); if (projectsWithContacts.length === 0) { console.log('ā„¹ļø No contact data found in projects to migrate.\n'); process.exit(0); } console.log(`šŸ“‹ Found ${projectsWithContacts.length} projects with contact information\n`); let created = 0; let linked = 0; let skipped = 0; const createContact = db.prepare(` INSERT INTO contacts (name, phone, email, contact_type, notes, is_active) VALUES (?, ?, ?, 'project', ?, 1) `); const linkContact = db.prepare(` INSERT OR IGNORE INTO project_contacts (project_id, contact_id, is_primary, relationship_type) VALUES (?, ?, 1, 'general') `); // Process each project for (const project of projectsWithContacts) { try { const contactText = project.contact.trim(); // Parse contact information - common formats: // "Jan Kowalski, tel. 123-456-789" // "Jan Kowalski 123-456-789" // "123-456-789" // "Jan Kowalski" let name = ''; let phone = ''; let email = ''; let notes = ''; // Try to extract email const emailPattern = /([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/; const emailMatch = contactText.match(emailPattern); if (emailMatch) { email = emailMatch[1].trim(); } // Try to extract phone number (various formats) const phonePatterns = [ /(?:\+?48)?[\s-]?(\d{3}[\s-]?\d{3}[\s-]?\d{3})/, // Polish: 123-456-789, 123 456 789, +48 123456789 /(?:\+?48)?[\s-]?(\d{9})/, // 9 digits /tel\.?\s*[:.]?\s*([+\d\s-]+)/i, // tel. 123-456-789 /phone\s*[:.]?\s*([+\d\s-]+)/i, // phone: 123-456-789 /(\d{3}[-\s]?\d{3}[-\s]?\d{3})/, // Generic phone pattern ]; for (const pattern of phonePatterns) { const match = contactText.match(pattern); if (match) { phone = match[1] || match[0]; phone = phone.replace(/\s+/g, ' ').trim(); break; } } // Extract name (text before phone/email or comma) let textForName = contactText; if (phone) { // Remove phone from text to get name textForName = textForName.replace(phone, ''); } if (email) { // Remove email from text to get name textForName = textForName.replace(email, ''); } // Remove common prefixes like "tel.", "phone:", "email:", commas, etc. name = textForName.replace(/tel\.?|phone:?|email:?|e-mail:?|,/gi, '').trim(); // Clean up name name = name.replace(/^[,\s-]+|[,\s-]+$/g, '').trim(); // If we couldn't extract structured data, use project name and put original text in notes if (!phone && !email) { // No structured contact info found, put everything in notes notes = `Original contact info: ${contactText}`; name = project.project_name; } else if (!name) { // We have phone/email but no clear name name = project.project_name; } // Check if this contact already exists (by name, phone, or email) let existingContact = null; if (phone) { existingContact = db.prepare(` SELECT contact_id FROM contacts WHERE phone LIKE ? OR phone LIKE ? `).get(`%${phone}%`, `%${phone.replace(/\s/g, '')}%`); } if (!existingContact && email) { existingContact = db.prepare(` SELECT contact_id FROM contacts WHERE LOWER(email) = LOWER(?) `).get(email); } if (!existingContact && name && name !== project.project_name) { existingContact = db.prepare(` SELECT contact_id FROM contacts WHERE LOWER(name) = LOWER(?) `).get(name); } let contactId; if (existingContact) { contactId = existingContact.contact_id; console.log(` ā™»ļø Using existing contact "${name}" for project "${project.project_name}"`); } else { // Create new contact const result = createContact.run( name, phone || null, email || null, notes || `Migrated from project: ${project.project_name}` ); contactId = result.lastInsertRowid; created++; const contactInfo = []; if (phone) contactInfo.push(`šŸ“ž ${phone}`); if (email) contactInfo.push(`šŸ“§ ${email}`); const infoStr = contactInfo.length > 0 ? ` (${contactInfo.join(', ')})` : ''; console.log(` ✨ Created contact "${name}"${infoStr} for project "${project.project_name}"`); } // Link contact to project linkContact.run(project.project_id, contactId); linked++; } catch (error) { console.error(` āŒ Error processing project "${project.project_name}":`, error.message); skipped++; } } console.log('\nšŸ“Š Migration Summary:'); console.log(` - Contacts created: ${created}`); console.log(` - Project-contact links created: ${linked}`); console.log(` - Projects skipped: ${skipped}`); console.log(` - Total projects processed: ${projectsWithContacts.length}`); // Show final statistics const contactsCount = db.prepare('SELECT COUNT(*) as count FROM contacts').get(); const projectContactsCount = db.prepare('SELECT COUNT(*) as count FROM project_contacts').get(); console.log('\nšŸ“ˆ Current Database Statistics:'); console.log(` - Total contacts: ${contactsCount.count}`); console.log(` - Total project-contact links: ${projectContactsCount.count}`); console.log('\n✨ Migration complete!'); console.log(' - Visit /contacts to view and manage your contacts'); console.log(' - Edit projects to see linked contacts'); console.log(' - The old contact text field is preserved for reference\n'); } catch (error) { console.error('āŒ Error during migration:', error); process.exit(1); }