import { PrismaClient } from '../src/generated/prisma/client.js'; import { PrismaLibSql } from '@prisma/adapter-libsql'; import bcrypt from 'bcryptjs'; import { randomBytes } from 'crypto'; import path from 'path'; const dbPath = path.resolve(process.cwd(), 'prisma', 'lootah.db'); const adapter = new PrismaLibSql({ url: `file:${dbPath}` }); const prisma = new PrismaClient({ adapter } as ConstructorParameters[0]); async function main() { console.log('Seeding database...'); // Create default admin user const existingAdmin = await prisma.adminUser.findUnique({ where: { username: 'admin' }, }); if (!existingAdmin) { const passwordHash = await bcrypt.hash('admin123', 12); await prisma.adminUser.create({ data: { username: 'admin', passwordHash, }, }); console.log('✓ Created admin user (username: admin, password: admin123)'); console.log(' ⚠️ Change the password after first login!'); } else { console.log('✓ Admin user already exists, skipping.'); } // Generate and store JWT secret const existingSecret = await prisma.appSettings.findUnique({ where: { key: 'jwt_secret' }, }); if (!existingSecret) { const jwtSecret = randomBytes(64).toString('hex'); await prisma.appSettings.upsert({ where: { key: 'jwt_secret' }, update: { value: jwtSecret }, create: { key: 'jwt_secret', value: jwtSecret }, }); console.log('✓ Generated JWT secret and stored in database.'); } else { console.log('✓ JWT secret already exists, skipping.'); } // Pricing items upserted on every deploy so the code is the source of truth. // Prices in AED. USD → AED at 3.6725 (CBUAE peg). // Basic = Unitree G1 retail ($16k) + $5k markup = $21k ≈ 77,125 AED. // EDU = $40k flat ≈ 146,900 AED. // All persona attire = 5,000 AED each. // Note: any prior admin-UI edits to these item prices/labels will be reset on each deploy. const defaultItems = [ { id: 'base', label: 'G1 Robot Basic', price: 77125, sortOrder: 0 }, { id: 'edu', label: 'G1 Robot EDU', price: 146900, sortOrder: 1 }, { id: 'emarati-kandura', label: 'Emarati Kandura', price: 5000, sortOrder: 2 }, { id: 'industrial-vest', label: 'Industrial Vest', price: 5000, sortOrder: 3 }, { id: 'business-suit', label: 'Business Suit', price: 5000, sortOrder: 4 }, { id: 'custom-color', label: 'Custom Color', price: 3500, sortOrder: 5 }, { id: 'robot-doctor', label: 'Robot Doctor', price: 5000, sortOrder: 6 }, { id: 'security-guard', label: 'Security Guard', price: 5000, sortOrder: 7 }, ]; for (const item of defaultItems) { await prisma.pricingItem.upsert({ where: { id: item.id }, create: item, update: { label: item.label, price: item.price, sortOrder: item.sortOrder }, }); } console.log(`✓ Upserted ${defaultItems.length} pricing items from code defaults.`); console.log('Seeding complete!'); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });