feat(seed): split seed scripts into production and development
- Create seed.production.js with admin user, divisions, and competition types only - Rename seed.js to seed.development.js with all test data - Add admin@spotlight.cam account with isAdmin flag and COMFORT tier - Update test users to use @spotlight.cam domain and SUPPORTER tier - Remove wsdcId from test users - Add npm scripts: prisma:seed:dev and prisma:seed:prod - Add Makefile targets: seed-dev and seed-prod
This commit is contained in:
378
backend/prisma/seed.development.js
Normal file
378
backend/prisma/seed.development.js
Normal file
@@ -0,0 +1,378 @@
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const bcrypt = require('bcryptjs');
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
console.log('🌱 Seeding database...');
|
||||
|
||||
// Create admin user
|
||||
const adminUser = await prisma.user.upsert({
|
||||
where: { email: 'admin@spotlight.cam' },
|
||||
update: {},
|
||||
create: {
|
||||
username: 'spotlight_admin',
|
||||
email: 'admin@spotlight.cam',
|
||||
passwordHash: '$2b$10$yYiA7KDB2fjTykDWIMVvvus8Ra8wKxKeLipAxiZYMnklyT3UnVSWK',
|
||||
firstName: 'Admin',
|
||||
lastName: 'User',
|
||||
emailVerified: true,
|
||||
isAdmin: true,
|
||||
accountTier: 'COMFORT',
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`✅ Created admin user: ${adminUser.username}`);
|
||||
|
||||
// Create test users
|
||||
const testUsers = await Promise.all([
|
||||
prisma.user.upsert({
|
||||
where: { email: 'john@spotlight.cam' },
|
||||
update: {},
|
||||
create: {
|
||||
username: 'john_dancer',
|
||||
email: 'john@spotlight.cam',
|
||||
passwordHash: await bcrypt.hash('Dance123!', 10),
|
||||
firstName: 'John',
|
||||
lastName: 'Smith',
|
||||
emailVerified: true,
|
||||
accountTier: 'SUPPORTER',
|
||||
country: 'United States',
|
||||
city: 'Los Angeles',
|
||||
instagramUrl: 'https://instagram.com/johndancer',
|
||||
youtubeUrl: 'https://youtube.com/@johndancer',
|
||||
},
|
||||
}),
|
||||
prisma.user.upsert({
|
||||
where: { email: 'sarah@spotlight.cam' },
|
||||
update: {},
|
||||
create: {
|
||||
username: 'sarah_swings',
|
||||
email: 'sarah@spotlight.cam',
|
||||
passwordHash: await bcrypt.hash('Swing456!', 10),
|
||||
firstName: 'Sarah',
|
||||
lastName: 'Johnson',
|
||||
emailVerified: true,
|
||||
accountTier: 'SUPPORTER',
|
||||
country: 'United Kingdom',
|
||||
city: 'London',
|
||||
tiktokUrl: 'https://tiktok.com/@sarahswings',
|
||||
facebookUrl: 'https://facebook.com/sarah.swings',
|
||||
},
|
||||
}),
|
||||
prisma.user.upsert({
|
||||
where: { email: 'mike@spotlight.cam' },
|
||||
update: {},
|
||||
create: {
|
||||
username: 'mike_blues',
|
||||
email: 'mike@spotlight.cam',
|
||||
passwordHash: await bcrypt.hash('Blues789!', 10),
|
||||
firstName: 'Mike',
|
||||
lastName: 'Williams',
|
||||
emailVerified: true,
|
||||
accountTier: 'SUPPORTER',
|
||||
country: 'Sweden',
|
||||
city: 'Stockholm',
|
||||
instagramUrl: 'https://instagram.com/mikeblues',
|
||||
youtubeUrl: 'https://youtube.com/@mikeblues',
|
||||
tiktokUrl: 'https://tiktok.com/@mikeblues',
|
||||
facebookUrl: 'https://facebook.com/mike.blues',
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log(`✅ Created ${testUsers.length} test users`);
|
||||
|
||||
// Create divisions
|
||||
const divisions = await Promise.all([
|
||||
prisma.division.upsert({
|
||||
where: { name: 'Newcomer' },
|
||||
update: {},
|
||||
create: { name: 'Newcomer', abbreviation: 'NEW', displayOrder: 1 },
|
||||
}),
|
||||
prisma.division.upsert({
|
||||
where: { name: 'Novice' },
|
||||
update: {},
|
||||
create: { name: 'Novice', abbreviation: 'NOV', displayOrder: 2 },
|
||||
}),
|
||||
prisma.division.upsert({
|
||||
where: { name: 'Intermediate' },
|
||||
update: {},
|
||||
create: { name: 'Intermediate', abbreviation: 'INT', displayOrder: 3 },
|
||||
}),
|
||||
prisma.division.upsert({
|
||||
where: { name: 'Advanced' },
|
||||
update: {},
|
||||
create: { name: 'Advanced', abbreviation: 'ADV', displayOrder: 4 },
|
||||
}),
|
||||
prisma.division.upsert({
|
||||
where: { name: 'All-Star' },
|
||||
update: {},
|
||||
create: { name: 'All-Star', abbreviation: 'ALL', displayOrder: 5 },
|
||||
}),
|
||||
prisma.division.upsert({
|
||||
where: { name: 'Champion' },
|
||||
update: {},
|
||||
create: { name: 'Champion', abbreviation: 'CHA', displayOrder: 6 },
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log(`✅ Created ${divisions.length} divisions`);
|
||||
|
||||
// Create competition types
|
||||
const competitionTypes = await Promise.all([
|
||||
prisma.competitionType.upsert({
|
||||
where: { name: 'Jack & Jill' },
|
||||
update: {},
|
||||
create: { name: 'Jack & Jill', abbreviation: 'J&J' },
|
||||
}),
|
||||
prisma.competitionType.upsert({
|
||||
where: { name: 'Strictly' },
|
||||
update: {},
|
||||
create: { name: 'Strictly', abbreviation: 'STR' },
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log(`✅ Created ${competitionTypes.length} competition types`);
|
||||
|
||||
// Create events (slug will be auto-generated as cuid for security)
|
||||
const events = await Promise.all([
|
||||
prisma.event.upsert({
|
||||
where: { worldsdcId: 'wdf-2025' },
|
||||
update: {},
|
||||
create: {
|
||||
name: 'Warsaw Dance Festival 2025',
|
||||
location: 'Warsaw, Poland',
|
||||
startDate: new Date('2025-03-15'),
|
||||
endDate: new Date('2025-03-17'),
|
||||
worldsdcId: 'wdf-2025',
|
||||
participantsCount: 156,
|
||||
description: 'The biggest West Coast Swing event in Central Europe',
|
||||
},
|
||||
}),
|
||||
prisma.event.upsert({
|
||||
where: { worldsdcId: 'scb-2025' },
|
||||
update: {},
|
||||
create: {
|
||||
name: 'Swing Camp Barcelona 2025',
|
||||
location: 'Barcelona, Spain',
|
||||
startDate: new Date('2025-04-20'),
|
||||
endDate: new Date('2025-04-23'),
|
||||
worldsdcId: 'scb-2025',
|
||||
participantsCount: 203,
|
||||
description: 'International swing dance camp with workshops and socials',
|
||||
},
|
||||
}),
|
||||
prisma.event.upsert({
|
||||
where: { worldsdcId: 'bwh-2025' },
|
||||
update: {},
|
||||
create: {
|
||||
name: 'Blues Week Herräng 2025',
|
||||
location: 'Herräng, Sweden',
|
||||
startDate: new Date('2025-07-14'),
|
||||
endDate: new Date('2025-07-20'),
|
||||
worldsdcId: 'bwh-2025',
|
||||
participantsCount: 89,
|
||||
description: 'Week-long blues dance intensive in the heart of Sweden',
|
||||
},
|
||||
}),
|
||||
prisma.event.upsert({
|
||||
where: { worldsdcId: 'ksc-2025' },
|
||||
update: {},
|
||||
create: {
|
||||
name: 'Krakow Swing Connection 2025',
|
||||
location: 'Krakow, Poland',
|
||||
startDate: new Date('2025-05-10'),
|
||||
endDate: new Date('2025-05-12'),
|
||||
worldsdcId: 'ksc-2025',
|
||||
participantsCount: 127,
|
||||
description: 'Three days of swing dancing in historic Krakow',
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log(`✅ Created ${events.length} events`);
|
||||
|
||||
// Create event chat rooms for each event
|
||||
const chatRooms = await Promise.all(
|
||||
events.map((event) =>
|
||||
prisma.chatRoom.create({
|
||||
data: {
|
||||
eventId: event.id,
|
||||
type: 'event',
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
console.log(`✅ Created ${chatRooms.length} event chat rooms`);
|
||||
|
||||
// Add test users as event participants (check-in)
|
||||
const warsawEvent = events[0]; // Warsaw Dance Festival
|
||||
const barcelonaEvent = events[1]; // Swing Camp Barcelona
|
||||
|
||||
const eventParticipants = await Promise.all([
|
||||
// John participates in Warsaw
|
||||
prisma.eventParticipant.upsert({
|
||||
where: {
|
||||
userId_eventId: {
|
||||
userId: testUsers[0].id,
|
||||
eventId: warsawEvent.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
userId: testUsers[0].id,
|
||||
eventId: warsawEvent.id,
|
||||
},
|
||||
}),
|
||||
// Sarah participates in Warsaw
|
||||
prisma.eventParticipant.upsert({
|
||||
where: {
|
||||
userId_eventId: {
|
||||
userId: testUsers[1].id,
|
||||
eventId: warsawEvent.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
userId: testUsers[1].id,
|
||||
eventId: warsawEvent.id,
|
||||
},
|
||||
}),
|
||||
// Mike participates in Warsaw
|
||||
prisma.eventParticipant.upsert({
|
||||
where: {
|
||||
userId_eventId: {
|
||||
userId: testUsers[2].id,
|
||||
eventId: warsawEvent.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
userId: testUsers[2].id,
|
||||
eventId: warsawEvent.id,
|
||||
},
|
||||
}),
|
||||
// John also in Barcelona
|
||||
prisma.eventParticipant.upsert({
|
||||
where: {
|
||||
userId_eventId: {
|
||||
userId: testUsers[0].id,
|
||||
eventId: barcelonaEvent.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
userId: testUsers[0].id,
|
||||
eventId: barcelonaEvent.id,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log(`✅ Added ${eventParticipants.length} event participants`);
|
||||
|
||||
// Create sample heats for test users in Warsaw event
|
||||
const jjType = competitionTypes[0]; // Jack & Jill
|
||||
const strType = competitionTypes[1]; // Strictly
|
||||
const novDiv = divisions[1]; // Novice
|
||||
const intDiv = divisions[2]; // Intermediate
|
||||
const advDiv = divisions[3]; // Advanced
|
||||
|
||||
const heats = await Promise.all([
|
||||
// John: J&J Novice Heat 1 (Leader), Strictly Intermediate Heat 2 (Leader)
|
||||
prisma.eventUserHeat.create({
|
||||
data: {
|
||||
userId: testUsers[0].id,
|
||||
eventId: warsawEvent.id,
|
||||
divisionId: novDiv.id,
|
||||
competitionTypeId: jjType.id,
|
||||
heatNumber: 1,
|
||||
role: 'Leader',
|
||||
},
|
||||
}),
|
||||
prisma.eventUserHeat.create({
|
||||
data: {
|
||||
userId: testUsers[0].id,
|
||||
eventId: warsawEvent.id,
|
||||
divisionId: intDiv.id,
|
||||
competitionTypeId: strType.id,
|
||||
heatNumber: 2,
|
||||
role: 'Leader',
|
||||
},
|
||||
}),
|
||||
// Sarah: J&J Novice Heat 1 (Follower), J&J Advanced Heat 3
|
||||
prisma.eventUserHeat.create({
|
||||
data: {
|
||||
userId: testUsers[1].id,
|
||||
eventId: warsawEvent.id,
|
||||
divisionId: novDiv.id,
|
||||
competitionTypeId: jjType.id,
|
||||
heatNumber: 1,
|
||||
role: 'Follower',
|
||||
},
|
||||
}),
|
||||
prisma.eventUserHeat.create({
|
||||
data: {
|
||||
userId: testUsers[1].id,
|
||||
eventId: warsawEvent.id,
|
||||
divisionId: advDiv.id,
|
||||
competitionTypeId: jjType.id,
|
||||
heatNumber: 3,
|
||||
role: null,
|
||||
},
|
||||
}),
|
||||
// Mike: J&J Intermediate Heat 5 (Leader), Strictly Advanced Heat 1 (Follower)
|
||||
prisma.eventUserHeat.create({
|
||||
data: {
|
||||
userId: testUsers[2].id,
|
||||
eventId: warsawEvent.id,
|
||||
divisionId: intDiv.id,
|
||||
competitionTypeId: jjType.id,
|
||||
heatNumber: 5,
|
||||
role: 'Leader',
|
||||
},
|
||||
}),
|
||||
prisma.eventUserHeat.create({
|
||||
data: {
|
||||
userId: testUsers[2].id,
|
||||
eventId: warsawEvent.id,
|
||||
divisionId: advDiv.id,
|
||||
competitionTypeId: strType.id,
|
||||
heatNumber: 1,
|
||||
role: 'Follower',
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log(`✅ Created ${heats.length} sample heats`);
|
||||
|
||||
console.log('🎉 Seeding completed successfully!');
|
||||
console.log('');
|
||||
console.log('Created:');
|
||||
console.log(` - 1 admin user`);
|
||||
console.log(` - ${testUsers.length} test users`);
|
||||
console.log(` - ${divisions.length} divisions`);
|
||||
console.log(` - ${competitionTypes.length} competition types`);
|
||||
console.log(` - ${events.length} events`);
|
||||
console.log(` - ${chatRooms.length} chat rooms`);
|
||||
console.log(` - ${eventParticipants.length} event participants`);
|
||||
console.log(` - ${heats.length} sample heats`);
|
||||
console.log('');
|
||||
console.log('Admin account:');
|
||||
console.log(' - admin@spotlight.cam / spotlight_admin (COMFORT tier)');
|
||||
console.log('');
|
||||
console.log('Test accounts:');
|
||||
console.log(' 1. john_dancer / Dance123!');
|
||||
console.log(' 2. sarah_swings / Swing456!');
|
||||
console.log(' 3. mike_blues / Blues789!');
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error('❌ Seeding failed:', e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user