UNPKG

@diagramers/api

Version:

Diagramers API - A comprehensive Node.js API template with TypeScript, Firebase Functions, and Socket.io

291 lines (255 loc) 8.45 kB
import { DatabaseConfig } from '../config/interfaces'; import { logger } from '../logging'; import { DatabaseManager } from './connection'; import { UserModel } from '../../modules/users/schemas/user.schema'; import * as bcrypt from 'bcryptjs'; export interface SeedData { users?: any[]; roles?: any[]; permissions?: any[]; [key: string]: any[]; } export interface SeederOptions { force?: boolean; // Force reseed even if data exists truncate?: boolean; // Truncate tables before seeding environment?: string; // Environment-specific seeding } export class DatabaseSeeder { private dbManager: DatabaseManager; private config: DatabaseConfig; constructor(dbManager: DatabaseManager, config: DatabaseConfig) { this.dbManager = dbManager; this.config = config; } /** * Run database seeding */ async seed(options: SeederOptions = {}): Promise<void> { try { logger.info('[DatabaseSeeder] Starting database seeding...'); // Check if seeding is needed if (!options.force && await this.hasData()) { logger.info('[DatabaseSeeder] Database already has data, skipping seeding'); return; } // Truncate if requested if (options.truncate) { await this.truncate(); } // Load seed data based on environment const seedData = await this.loadSeedData(options.environment); // Seed data await this.seedUsers(seedData.users || []); await this.seedRoles(seedData.roles || []); await this.seedPermissions(seedData.permissions || []); logger.info('[DatabaseSeeder] Database seeding completed successfully'); } catch (error) { logger.error('[DatabaseSeeder] Failed to seed database:', error); throw error; } } /** * Check if database already has data */ private async hasData(): Promise<boolean> { try { if (this.config.dialect === 'mongodb') { const userCount = await UserModel.countDocuments(); return userCount > 0; } else { // For SQL databases, you'd check the users table // This is a placeholder for SQL implementation return false; } } catch (error) { logger.warn('[DatabaseSeeder] Could not check existing data:', error); return false; } } /** * Truncate all tables/collections */ private async truncate(): Promise<void> { try { logger.info('[DatabaseSeeder] Truncating database...'); if (this.config.dialect === 'mongodb') { await UserModel.deleteMany({}); // Add other collections as needed } else { // For SQL databases, you'd truncate tables // This is a placeholder for SQL implementation } logger.info('[DatabaseSeeder] Database truncated successfully'); } catch (error) { logger.error('[DatabaseSeeder] Failed to truncate database:', error); throw error; } } /** * Load seed data based on environment */ private async loadSeedData(environment?: string): Promise<SeedData> { const env = environment || process.env.NODE_ENV || 'development'; // Default seed data const defaultData: SeedData = { users: [ { email: 'admin@diagramers.com', username: 'admin', password: '12345678@', firstName: 'Admin', lastName: 'User', role: 'admin', isActive: true, emailVerified: true, phoneVerified: false, permissions: ['*'] }, { email: 'user@diagramers.com', username: 'user', password: 'user123', firstName: 'Regular', lastName: 'User', role: 'user', isActive: true, emailVerified: true, phoneVerified: false, permissions: ['read:own', 'write:own'] } ], roles: [ { name: 'admin', description: 'Administrator with full access' }, { name: 'moderator', description: 'Moderator with limited admin access' }, { name: 'user', description: 'Regular user' } ], permissions: [ { name: '*', description: 'All permissions' }, { name: 'read:own', description: 'Read own data' }, { name: 'write:own', description: 'Write own data' }, { name: 'read:all', description: 'Read all data' }, { name: 'write:all', description: 'Write all data' } ] }; // Environment-specific overrides if (env === 'production') { // Production should have minimal seed data or none return { users: [], roles: defaultData.roles, permissions: defaultData.permissions }; } if (env === 'testing') { // Testing environment with test data return { users: [ { email: 'test@diagramers.com', username: 'testuser', password: 'test123', firstName: 'Test', lastName: 'User', role: 'user', isActive: true, emailVerified: true, phoneVerified: false, permissions: ['read:own'] } ], roles: defaultData.roles, permissions: defaultData.permissions }; } return defaultData; } /** * Seed users */ private async seedUsers(users: any[]): Promise<void> { if (users.length === 0) return; logger.info(`[DatabaseSeeder] Seeding ${users.length} users...`); for (const userData of users) { try { // Check if user already exists const existingUser = await UserModel.findOne({ $or: [ { email: userData.email }, { username: userData.username } ] }); if (existingUser) { logger.info(`[DatabaseSeeder] User ${userData.email} already exists, skipping`); continue; } // Hash password const saltRounds = 10; const hashedPassword = await bcrypt.hash(userData.password, saltRounds); // Create user const user = new UserModel({ ...userData, password: hashedPassword, email: userData.email.toLowerCase(), status: 1 }); await user.save(); logger.info(`[DatabaseSeeder] Created user: ${userData.email}`); } catch (error) { logger.error(`[DatabaseSeeder] Failed to create user ${userData.email}:`, error); } } } /** * Seed roles (placeholder for role-based system) */ private async seedRoles(roles: any[]): Promise<void> { if (roles.length === 0) return; logger.info(`[DatabaseSeeder] Seeding ${roles.length} roles...`); // This would create roles in a roles collection/table // For now, just log the roles for (const role of roles) { logger.info(`[DatabaseSeeder] Role: ${role.name} - ${role.description}`); } } /** * Seed permissions (placeholder for permission-based system) */ private async seedPermissions(permissions: any[]): Promise<void> { if (permissions.length === 0) return; logger.info(`[DatabaseSeeder] Seeding ${permissions.length} permissions...`); // This would create permissions in a permissions collection/table // For now, just log the permissions for (const permission of permissions) { logger.info(`[DatabaseSeeder] Permission: ${permission.name} - ${permission.description}`); } } /** * Create custom seed data */ async createSeedData(data: SeedData): Promise<void> { try { logger.info('[DatabaseSeeder] Creating custom seed data...'); await this.seedUsers(data.users || []); await this.seedRoles(data.roles || []); await this.seedPermissions(data.permissions || []); logger.info('[DatabaseSeeder] Custom seed data created successfully'); } catch (error) { logger.error('[DatabaseSeeder] Failed to create custom seed data:', error); throw error; } } /** * Reset database (truncate and reseed) */ async reset(): Promise<void> { try { logger.info('[DatabaseSeeder] Resetting database...'); await this.truncate(); await this.seed({ force: true }); logger.info('[DatabaseSeeder] Database reset completed'); } catch (error) { logger.error('[DatabaseSeeder] Failed to reset database:', error); throw error; } } }