import "dotenv/config"; import bcrypt from "bcryptjs"; import { PrismaPg } from "@prisma/adapter-pg"; import { DemocraticInitiativeOrigin, PrismaClient } from "@prisma/client"; import { Pool } from "pg"; const connectionString = process.env.DATABASE_URL; if (!connectionString) { throw new Error("DATABASE_URL must be set for seeding"); } const pool = new Pool({ connectionString }); const adapter = new PrismaPg(pool); const prisma = new PrismaClient({ adapter }); async function main() { const email = "demo@local.dev"; const password = "demo1234"; const hash = await bcrypt.hash(password, 12); const user = await prisma.user.upsert({ where: { email }, update: { passwordHash: hash, name: "Demo Supporter", role: "USER", username: "portal_demo", }, create: { email, username: "portal_demo", name: "Demo Supporter", passwordHash: hash, role: "USER", }, }); await prisma.wallet.upsert({ where: { userId: user.id }, update: {}, create: { userId: user.id, balanceCredits: 0 }, }); const adminEmail = "drjones@admin.local"; const adminPassword = "czapiewski"; const adminHash = await bcrypt.hash(adminPassword, 12); const admin = await prisma.user.upsert({ where: { email: adminEmail }, update: { passwordHash: adminHash, name: "Dr Jones", role: "ADMIN", username: "portal_admin", }, create: { email: adminEmail, username: "portal_admin", name: "Dr Jones", passwordHash: adminHash, role: "ADMIN", }, }); await prisma.wallet.upsert({ where: { userId: admin.id }, update: { balanceCredits: 2_147_483_647 }, create: { userId: admin.id, balanceCredits: 2_147_483_647 }, }); await prisma.prizeSku.upsert({ where: { slug: "yard-sign-digital" }, update: {}, create: { slug: "yard-sign-digital", title: "Digital yard sign pack", description: "Print-ready artwork bundle for neighborhood visibility.", costCredits: 15, stockHint: "Digital download", }, }); await prisma.prizeSku.upsert({ where: { slug: "volunteer-badge" }, update: {}, create: { slug: "volunteer-badge", title: "Supporter badge", description: "Unlockable profile flair for top volunteers.", costCredits: 8, stockHint: "Profile flair", }, }); await prisma.raffle.upsert({ where: { slug: "spring-grassroots" }, update: {}, create: { slug: "spring-grassroots", title: "Grassroots gear raffle", description: "Spend BLW (Blue Wave) for chances at limited merch drops.", ticketCostCredits: 5, endsAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 30), }, }); const officialPriorities: Array<{ slug: string; sortOrder: number; title: string; description: string }> = [ { slug: "priority-voting-access", sortOrder: 0, title: "Voting access & fair elections", description: "Protect early voting, drop boxes where allowed, and nonpartisan election administration — signal BWT here if this is the lane you want organizers and messaging to emphasize first.", }, { slug: "priority-climate-jobs", sortOrder: 1, title: "Climate jobs & clean infrastructure", description: "Invest in union-scale clean energy, grid resilience, and communities transitioning off volatile fossil cycles — pledge BWT to raise the salience of green industrial policy in the program.", }, { slug: "priority-health-affordability", sortOrder: 2, title: "Healthcare affordability", description: "Expand coverage choices, cap out-of-pocket shocks for families, and defend access to care — use BWT totals here to show democratic demand for health-centered field work.", }, { slug: "priority-workers-rights", sortOrder: 3, title: "Workers’ rights & wages", description: "Stand with organizing, overtime fairness, and safety nets that reward work — pledges aggregate as a live scoreboard for how loud supporters want labor-forward priorities.", }, { slug: "priority-community-safety", sortOrder: 4, title: "Community safety & prevention", description: "Fund violence interruption, mental health first responders, and common-sense safety policy without scapegoating — BWT here steers narrative and volunteer energy toward prevention-first democracy.", }, ]; for (const p of officialPriorities) { await prisma.democraticInitiative.upsert({ where: { slug: p.slug }, update: { title: p.title, description: p.description, origin: DemocraticInitiativeOrigin.PLATFORM, sortOrder: p.sortOrder, creatorId: null, }, create: { slug: p.slug, title: p.title, description: p.description, origin: DemocraticInitiativeOrigin.PLATFORM, sortOrder: p.sortOrder, creatorId: null, }, }); } // eslint-disable-next-line no-console console.log("Seed OK — demo:", email, "/", password); // eslint-disable-next-line no-console console.log("Seed OK — admin:", adminEmail, "/", adminPassword, "(role ADMIN, max wallet)"); } main() .then(async () => { await prisma.$disconnect(); await pool.end(); }) .catch(async (e) => { console.error(e); await prisma.$disconnect(); await pool.end(); process.exit(1); });