#!/usr/bin/env node import Database from 'better-sqlite3'; import bcrypt from 'bcryptjs'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const db = new Database(join(__dirname, '..', 'bifrost.db')); db.pragma('journal_mode = WAL'); db.pragma('foreign_keys = ON'); // Verify schema exists try { db.prepare('SELECT id FROM users LIMIT 1').get(); } catch { console.error('Error: database tables not found. Run `pnpm db:migrate` first.'); process.exit(1); } // Wipe existing seed data (idempotent). Order matters: every table that // FK-references users (without ON DELETE CASCADE) must be cleared first. db.exec(` DELETE FROM activity; DELETE FROM votes; DELETE FROM dispatches; DELETE FROM events; DELETE FROM pulses; DELETE FROM roadmap_attributions; DELETE FROM reactions; DELETE FROM replies; DELETE FROM contributions; DELETE FROM attendance; DELETE FROM join_requests; DELETE FROM invites; DELETE FROM sessions; DELETE FROM users; `); const ROUNDS = 10; const users = [ { email: 'mette@virk1.dk', password: 'pilot123', name: 'Mette Hansen', organisation: 'Virksomhed 1', role: 'pilot', }, { email: 'lars@virk2.dk', password: 'cab123', name: 'Lars Thomsen', organisation: 'Virksomhed 2', role: 'cab', }, { email: 'jonathan@studio.test', password: 'fenja123', name: 'Jonathan', organisation: 'Fenja AI', role: 'fenja', }, ]; const insertUser = db.prepare(` INSERT INTO users (email, password_hash, name, organisation, role, bio, slug) VALUES (?, ?, ?, ?, ?, ?, ?) `); const userIds = {}; for (const u of users) { const hash = bcrypt.hashSync(u.password, ROUNDS); const slug = u.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''); const result = insertUser.run(u.email, hash, u.name, u.organisation, u.role, '', slug); userIds[u.role] = Number(result.lastInsertRowid); console.log(` created user: ${u.name} (${u.role}) — password: ${u.password}`); } // Sample contributions const insertContrib = db.prepare(` INSERT INTO contributions (user_id, type, body_md, created_at) VALUES (?, ?, ?, ?) `); const now = new Date(); const minus20 = new Date(now.getTime() - 20 * 60 * 1000).toISOString(); const minus2h = new Date(now.getTime() - 2 * 60 * 60 * 1000).toISOString(); const minus1d = new Date(now.getTime() - 24 * 60 * 60 * 1000).toISOString(); const minus3d = new Date(now.getTime() - 3 * 24 * 60 * 60 * 1000).toISOString(); const c1 = insertContrib.run( userIds['pilot'], 'idea', 'What if the system could **auto-summarise meetings** and link the summary back to the relevant roadmap item? Would save a lot of manual work after each CAB session.', minus1d ); const c2 = insertContrib.run( userIds['cab'], 'question', 'How will the system handle documents in **multiple languages**? Most of our operational docs are in Danish, but some legal references are in English or German.', minus2h ); const c3 = insertContrib.run( userIds['pilot'], 'inspiration', 'Came across this framing of knowledge management in regulated industries — the idea of an "institutional memory" that stays even when staff rotate. Feels very aligned with what Fenja is building.', minus3d ); const c4 = insertContrib.run( userIds['fenja'], 'idea', 'Consider department-level access scoping for v1.1 — some organisations may want certain documents visible only to specific teams, even within the pilot group.', minus20 ); // Reactions const insertReaction = db.prepare(` INSERT INTO reactions (user_id, contribution_id) VALUES (?, ?) `); insertReaction.run(userIds['cab'], c1.lastInsertRowid); insertReaction.run(userIds['fenja'], c1.lastInsertRowid); insertReaction.run(userIds['pilot'], c3.lastInsertRowid); // Fenja reply on c1 db.prepare(` INSERT INTO replies (contribution_id, user_id, body_md) VALUES (?, ?, ?) `).run( c1.lastInsertRowid, userIds['fenja'], 'Great idea — meeting summaries are on our Q3 roadmap. The link back to roadmap items is something we hadn\'t explicitly planned; adding it to the backlog now.' ); // Sample attendance const insertAttendance = db.prepare(` INSERT OR REPLACE INTO attendance (user_id, meeting_slug, status, updated_at) VALUES (?, ?, ?, datetime('now')) `); insertAttendance.run(userIds['pilot'], '2026-03-20-kickoff', 'yes'); insertAttendance.run(userIds['cab'], '2026-03-20-kickoff', 'yes'); insertAttendance.run(userIds['fenja'], '2026-03-20-kickoff', 'yes'); insertAttendance.run(userIds['pilot'], '2026-04-25-cab-q2-session', 'yes'); insertAttendance.run(userIds['cab'], '2026-04-25-cab-q2-session', 'no'); console.log('\n Seed complete.'); console.log('\n Test credentials:'); console.log(' mette@virk1.dk / pilot123 (pilot)'); console.log(' lars@virk2.dk / cab123 (cab)'); console.log(' jonathan@studio.test / fenja123 (fenja)'); db.close();