182 lines
5.4 KiB
TypeScript
182 lines
5.4 KiB
TypeScript
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);
|
||
});
|