import { PrismaClient } from '@prisma/client'; import bcrypt from 'bcryptjs'; const prisma = new PrismaClient(); async function main() { console.log('Seeding database...'); // --- System Settings --- const settings = await prisma.systemSettings.upsert({ where: { id: 'singleton' }, update: {}, create: { id: 'singleton', authMode: 'local', registrationEnabled: true, defaultTheme: 'dark', defaultPrimaryColor: '#6366f1', healthcheckDefaults: JSON.stringify({ interval: 300, timeout: 5000, method: 'GET', expectedStatus: 200 }) } }); console.log(' Created system settings:', settings.id); // --- Admin User --- const adminPassword = await bcrypt.hash('admin123', 12); const admin = await prisma.user.upsert({ where: { email: 'admin@localhost' }, update: {}, create: { email: 'admin@localhost', password: adminPassword, displayName: 'Administrator', role: 'admin', authProvider: 'local' } }); console.log(' Created admin user:', admin.email); // --- Groups --- const adminGroup = await prisma.group.upsert({ where: { name: 'admin' }, update: {}, create: { name: 'admin', description: 'Administrators with full system access', isDefault: false } }); console.log(' Created group:', adminGroup.name); const userGroup = await prisma.group.upsert({ where: { name: 'user' }, update: {}, create: { name: 'user', description: 'Default group for all registered users', isDefault: true } }); console.log(' Created group:', userGroup.name); // --- User-Group memberships --- await prisma.userGroup.upsert({ where: { userId_groupId: { userId: admin.id, groupId: adminGroup.id } }, update: {}, create: { userId: admin.id, groupId: adminGroup.id } }); await prisma.userGroup.upsert({ where: { userId_groupId: { userId: admin.id, groupId: userGroup.id } }, update: {}, create: { userId: admin.id, groupId: userGroup.id } }); console.log(' Added admin to groups'); // --- Sample Apps --- const apps = [ { name: 'Plex', url: 'http://plex.local:32400', icon: 'plex', iconType: 'simple', description: 'Media server for streaming movies, TV shows, and music', category: 'Media', tags: 'media,streaming,movies,tv', healthcheckEnabled: true }, { name: 'Nextcloud', url: 'http://nextcloud.local', icon: 'nextcloud', iconType: 'simple', description: 'Self-hosted file sync, sharing, and collaboration platform', category: 'Productivity', tags: 'files,sync,cloud,office', healthcheckEnabled: true }, { name: 'Gitea', url: 'http://gitea.local:3000', icon: 'gitea', iconType: 'simple', description: 'Lightweight self-hosted Git service', category: 'Development', tags: 'git,code,development,ci', healthcheckEnabled: true }, { name: 'Home Assistant', url: 'http://homeassistant.local:8123', icon: 'homeassistant', iconType: 'simple', description: 'Open-source home automation platform', category: 'Home Automation', tags: 'home,automation,iot,smart-home', healthcheckEnabled: true }, { name: 'Grafana', url: 'http://grafana.local:3000', icon: 'grafana', iconType: 'simple', description: 'Analytics and monitoring dashboards', category: 'Monitoring', tags: 'monitoring,analytics,dashboards,metrics', healthcheckEnabled: true } ]; const createdApps = []; for (const appData of apps) { const app = await prisma.app.upsert({ where: { id: appData.name.toLowerCase().replace(/\s+/g, '-') }, update: {}, create: { ...appData, createdById: admin.id } }); createdApps.push(app); console.log(' Created app:', app.name); } // --- Default Board --- const board = await prisma.board.upsert({ where: { id: 'default-board' }, update: {}, create: { id: 'default-board', name: 'Dashboard', icon: 'layout-dashboard', description: 'Default application dashboard', isDefault: true, isGuestAccessible: true, createdById: admin.id } }); console.log(' Created board:', board.name); // --- Sections --- const mediaSection = await prisma.section.upsert({ where: { id: 'section-media' }, update: {}, create: { id: 'section-media', boardId: board.id, title: 'Media & Entertainment', icon: 'tv', order: 0, isExpandedByDefault: true } }); console.log(' Created section:', mediaSection.title); const infraSection = await prisma.section.upsert({ where: { id: 'section-infra' }, update: {}, create: { id: 'section-infra', boardId: board.id, title: 'Infrastructure & Tools', icon: 'server', order: 1, isExpandedByDefault: true } }); console.log(' Created section:', infraSection.title); // --- Widgets --- // Plex widget in media section await prisma.widget.upsert({ where: { id: 'widget-plex' }, update: {}, create: { id: 'widget-plex', sectionId: mediaSection.id, type: 'app', order: 0, appId: createdApps[0].id, config: JSON.stringify({ showStatus: true, openInNewTab: true }) } }); // Nextcloud widget in infra section await prisma.widget.upsert({ where: { id: 'widget-nextcloud' }, update: {}, create: { id: 'widget-nextcloud', sectionId: infraSection.id, type: 'app', order: 0, appId: createdApps[1].id, config: JSON.stringify({ showStatus: true, openInNewTab: true }) } }); // Gitea widget in infra section await prisma.widget.upsert({ where: { id: 'widget-gitea' }, update: {}, create: { id: 'widget-gitea', sectionId: infraSection.id, type: 'app', order: 1, appId: createdApps[2].id, config: JSON.stringify({ showStatus: true, openInNewTab: true }) } }); // Home Assistant widget in infra section await prisma.widget.upsert({ where: { id: 'widget-homeassistant' }, update: {}, create: { id: 'widget-homeassistant', sectionId: infraSection.id, type: 'app', order: 2, appId: createdApps[3].id, config: JSON.stringify({ showStatus: true, openInNewTab: true }) } }); // Grafana widget in infra section await prisma.widget.upsert({ where: { id: 'widget-grafana' }, update: {}, create: { id: 'widget-grafana', sectionId: infraSection.id, type: 'app', order: 3, appId: createdApps[4].id, config: JSON.stringify({ showStatus: true, openInNewTab: true }) } }); console.log(' Created widgets for all apps'); console.log('Seeding complete!'); } main() .catch((e) => { console.error('Seed error:', e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });