bolt / src /db /seed.js
Abhinay
Deploy Bolt Run backend (Express + Firestore) as Docker Space
d3477e4
Raw
History Blame Contribute Delete
3.62 kB
const bcrypt = require('bcryptjs');
const { collections, FieldValue } = require('./firestore');
function slug(s) {
return s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
}
async function seed() {
try {
// Demo user
const demoEmail = 'demo@bolt.run';
const existing = await collections.users.where('email', '==', demoEmail).limit(1).get();
if (existing.empty) {
const hash = await bcrypt.hash('password123', 10);
const ref = collections.users.doc();
await ref.set({
name: 'Demo Runner',
email: demoEmail,
password_hash: hash,
avatar_url: null,
weight_kg: 70,
height_cm: 175,
date_of_birth: null,
total_runs: 0,
total_distance_km: 0,
total_duration_sec: 0,
total_calories: 0,
created_at: FieldValue.serverTimestamp(),
updated_at: FieldValue.serverTimestamp(),
});
console.log(' + demo user created');
} else {
console.log(' · demo user exists');
}
// Programs (deterministic doc IDs from title slug for idempotent seed)
const programs = [
{ title: '5K Beginner Plan', description: 'Go from couch to 5K in 8 weeks', coach_name: 'Eliud Kipchoge', duration_weeks: 8, sessions_per_week: 3, difficulty: 'beginner', category: '5K', is_featured: true },
{ title: '10K Speed Builder', description: 'Build speed and endurance for 10K', coach_name: 'Joshua Cheptegei', duration_weeks: 10, sessions_per_week: 4, difficulty: 'intermediate', category: '10K', is_featured: true },
{ title: 'Half Marathon Prep', description: 'Complete your first half marathon', coach_name: 'Brigid Kosgei', duration_weeks: 12, sessions_per_week: 5, difficulty: 'intermediate', category: 'Half Marathon', is_featured: false },
{ title: 'Marathon Masters', description: 'Advanced marathon training plan', coach_name: 'Kenenisa Bekele', duration_weeks: 16, sessions_per_week: 6, difficulty: 'advanced', category: 'Marathon', is_featured: false },
];
for (const p of programs) {
const id = slug(p.title);
const ref = collections.programs.doc(id);
const snap = await ref.get();
if (!snap.exists) {
await ref.set({
...p,
coach_avatar_url: null,
image_url: null,
total_enrolled: 0,
created_at: FieldValue.serverTimestamp(),
});
console.log(` + program "${p.title}"`);
}
}
// Clubs
const clubs = [
{ name: 'Morning Milers', description: 'Early birds who love the sunrise run', location: 'New York, NY', member_count: 124 },
{ name: 'Trail Blazers', description: 'Off-road and trail running enthusiasts', location: 'Denver, CO', member_count: 89 },
{ name: 'Speed Demons', description: 'Track and interval training focus', location: 'Los Angeles, CA', member_count: 203 },
{ name: 'Weekend Warriors', description: 'Casual runners, serious fun', location: 'Chicago, IL', member_count: 156 },
];
for (const c of clubs) {
const id = slug(c.name);
const ref = collections.clubs.doc(id);
const snap = await ref.get();
if (!snap.exists) {
await ref.set({
...c,
avatar_url: null,
cover_url: null,
is_public: true,
created_by: null,
created_at: FieldValue.serverTimestamp(),
});
console.log(` + club "${c.name}"`);
}
}
console.log('Seed complete.');
process.exit(0);
} catch (err) {
console.error('Seed failed:', err);
process.exit(1);
}
}
seed();