#!/usr/bin/env tsx import { config } from 'dotenv'; import { drizzle } from 'drizzle-orm/postgres-js'; import postgres from 'postgres'; import * as schema from '../src/schemas/database/schema'; import { hashPassword } from '../src/lib/utils/passwordHash'; import { v4 as uuidv4 } from 'uuid'; // Load environment variables from .env file config(); async function seed() { const databaseUrl = process.env.DATABASE_URL; if (!databaseUrl) { throw new Error('DATABASE_URL environment variable is not set'); } console.log('🌱 Starting database seeding...'); const client = postgres(databaseUrl); const db = drizzle(client, { schema }); try { // Create admin user console.log('πŸ‘€ Creating admin user...'); const adminPasswordHash = await hashPassword('admin123'); const adminUser = await db .insert(schema.managementUsers) .values({ firstName: 'Admin', lastName: 'User', username: 'admin', passwordHash: adminPasswordHash, role: 'ADMIN', enabled: true }) .returning() .onConflictDoNothing(); if (adminUser.length > 0) { console.log('βœ… Admin user created with username: admin, password: admin123'); } else { console.log('ℹ️ Admin user already exists'); } // Create sample members console.log('πŸ‘₯ Creating sample members...'); const members = [ { firstName: 'Max', lastName: 'Mustermann', email: 'max.mustermann@example.com', membershipNumber: 'MEM001', phoneMobile: '+49123456789', joinedAt: new Date('2024-01-15') }, { firstName: 'Anna', lastName: 'Schmidt', email: 'anna.schmidt@example.com', membershipNumber: 'MEM002', phoneMobile: '+49987654321', joinedAt: new Date('2024-02-20') }, { firstName: 'Peter', lastName: 'MΓΌller', email: 'peter.mueller@example.com', membershipNumber: 'MEM003', phoneMobile: '+49555666777', joinedAt: new Date('2024-03-10') } ]; const createdMembers = []; for (const member of members) { const result = await db .insert(schema.members) .values(member) .returning() .onConflictDoNothing(); if (result.length > 0) { createdMembers.push(result[0]); console.log(`βœ… Created member: ${member.firstName} ${member.lastName}`); } } // Create sample RFID cards console.log('πŸ†” Creating sample RFID cards...'); const rfidCards = [ { rfidId: 'ABC123456789', status: 'NEW' as const }, { rfidId: 'DEF987654321', status: 'NEW' as const }, { rfidId: 'GHI456789123', status: 'ENGRAVED' as const }, { rfidId: 'JKL789123456', status: 'NEW' as const }, { rfidId: 'MNO321654987', status: 'NEW' as const } ]; const createdCards = []; for (const card of rfidCards) { const result = await db .insert(schema.rfidCards) .values(card) .returning() .onConflictDoNothing(); if (result.length > 0) { createdCards.push(result[0]); console.log(`βœ… Created RFID card: ${card.rfidId} (${card.status})`); } } // Create sample assignments console.log('πŸ”— Creating sample card assignments...'); const assignments = [ { memberId: createdMembers[0]?.id, cardId: createdCards[0]?.id, status: 'ASSIGNED' as const, issuedAt: new Date('2024-01-20') }, { memberId: createdMembers[1]?.id, cardId: createdCards[1]?.id, status: 'ASSIGNED' as const, issuedAt: new Date('2024-02-25') }, { memberId: createdMembers[2]?.id, cardId: createdCards[2]?.id, status: 'ASSIGNED' as const, issuedAt: new Date('2024-03-15') } ]; for (const assignment of assignments) { if (assignment.memberId && assignment.cardId) { const result = await db .insert(schema.memberRfidCards) .values(assignment) .returning() .onConflictDoNothing(); if (result.length > 0) { console.log( `βœ… Assigned card ${createdCards.find((c) => c.id === assignment.cardId)?.rfidId} to ${createdMembers.find((m) => m.id === assignment.memberId)?.firstName} ${createdMembers.find((m) => m.id === assignment.memberId)?.lastName}` ); } } } // Create sample devices console.log('πŸ“± Creating sample devices...'); const devices = [ { name: 'Main Entrance Scanner', apiKey: 'dev_' + uuidv4().replace(/-/g, ''), type: 'RFID_SCANNER' as const }, { name: 'Office Door Lock', apiKey: 'dev_' + uuidv4().replace(/-/g, ''), type: 'LOCK_SYSTEM' as const } ]; const createdDevices = []; for (const device of devices) { const result = await db .insert(schema.devices) .values(device) .returning() .onConflictDoNothing(); if (result.length > 0) { createdDevices.push(result[0]); console.log(`βœ… Created device: ${device.name} (${device.type})`); } } // Get all members and devices for access logs const allMembers = await db.select().from(schema.members); const allDevices = await db.select().from(schema.devices); if (allMembers.length === 0 || allDevices.length === 0) { console.log('⚠️ No members or devices found, skipping access log creation'); } else { // Create sample access logs for the last 30 days console.log('πŸ“Š Creating sample access logs...'); const accessLogs = []; const now = new Date(); const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); for (let i = 0; i < 30; i++) { const date = new Date(thirtyDaysAgo.getTime() + i * 24 * 60 * 60 * 1000); // Random number of accesses per day (5-50) const accessesPerDay = Math.floor(Math.random() * 46) + 5; for (let j = 0; j < accessesPerDay; j++) { const randomMember = allMembers[Math.floor(Math.random() * allMembers.length)]; const randomDevice = allDevices[Math.floor(Math.random() * allDevices.length)]; const randomHour = Math.floor(Math.random() * 24); const randomMinute = Math.floor(Math.random() * 60); const accessedAt = new Date(date); accessedAt.setHours(randomHour, randomMinute, 0, 0); accessLogs.push({ memberId: randomMember.id, deviceId: randomDevice.id, accessedAt, accessGranted: Math.random() > 0.05 // 95% success rate }); } } for (const log of accessLogs) { await db.insert(schema.accessLogs).values(log).onConflictDoNothing(); } console.log(`βœ… Created ${accessLogs.length} sample access logs over the last 30 days`); } console.log('πŸŽ‰ Database seeding completed successfully!'); console.log('\nπŸ“‹ Summary:'); console.log('- Admin user: admin / admin123'); console.log('- Sample members, RFID cards, and assignments created'); console.log('- Sample devices created'); if (allMembers.length > 0 && allDevices.length > 0) { console.log('- Sample access logs created for chart testing'); } } catch (error) { console.error('❌ Error during seeding:', error); process.exit(1); } finally { await client.end(); } } seed().catch((error) => { console.error('❌ Seeding failed:', error); process.exit(1); });