refactor: improve service layer logging and configuration

- Change email service logging from console.log to console.warn for better visibility
- Update mailgun and couchdb configuration with improved error handling
- Enhance database seeder with better logging and error management
- Improve service factory patterns for better testability
This commit is contained in:
William Valentin
2025-09-07 15:22:04 -07:00
parent 58a4988b58
commit 172bb2bd74
4 changed files with 36 additions and 48 deletions

View File

@@ -2,16 +2,17 @@
// This file determines whether to use mock localStorage or real CouchDB // This file determines whether to use mock localStorage or real CouchDB
import { CouchDBService as MockCouchDBService } from './couchdb'; import { CouchDBService as MockCouchDBService } from './couchdb';
import { getEnvVar, isTest } from '../utils/env';
// Environment detection // Environment detection
const isProduction = () => { const isProduction = () => {
// Check if we're in a Docker environment or if CouchDB URL is configured // Always use mock service in test environment
const env = (import.meta as { env?: Record<string, string> }).env || {}; if (isTest()) {
const couchdbUrl = return false;
env.VITE_COUCHDB_URL || }
(typeof process !== 'undefined' ? process.env.VITE_COUCHDB_URL : null) ||
(typeof process !== 'undefined' ? process.env.COUCHDB_URL : null);
// Check if we're in a Docker environment or if CouchDB URL is configured
const couchdbUrl = getEnvVar('VITE_COUCHDB_URL') || getEnvVar('COUCHDB_URL');
return !!couchdbUrl && couchdbUrl !== 'mock'; return !!couchdbUrl && couchdbUrl !== 'mock';
}; };

View File

@@ -10,23 +10,23 @@ export class DatabaseSeeder {
const adminEmail = 'admin@localhost'; const adminEmail = 'admin@localhost';
const adminPassword = 'admin123!'; const adminPassword = 'admin123!';
console.log('🌱 Starting admin user seeding...'); console.warn('🌱 Starting admin user seeding...');
console.log('📧 Admin email:', adminEmail); console.warn('📧 Admin email:', adminEmail);
try { try {
// Check if admin already exists // Check if admin already exists
const existingAdmin = await dbService.findUserByEmail(adminEmail); const existingAdmin = await dbService.findUserByEmail(adminEmail);
if (existingAdmin) { if (existingAdmin) {
console.log('✅ Default admin user already exists'); console.warn('✅ Default admin user already exists');
console.log('👤 Existing admin:', existingAdmin); console.warn('👤 Existing admin:', existingAdmin);
// Check if admin needs to be updated to correct role/status // Check if admin needs to be updated to correct role/status
if ( if (
existingAdmin.role !== UserRole.ADMIN || existingAdmin.role !== UserRole.ADMIN ||
existingAdmin.status !== AccountStatus.ACTIVE existingAdmin.status !== AccountStatus.ACTIVE
) { ) {
console.log('🔧 Updating admin user role and status...'); console.warn('🔧 Updating admin user role and status...');
const updatedAdmin = { const updatedAdmin = {
...existingAdmin, ...existingAdmin,
role: UserRole.ADMIN, role: UserRole.ADMIN,
@@ -34,13 +34,13 @@ export class DatabaseSeeder {
emailVerified: true, emailVerified: true,
}; };
await dbService.updateUser(updatedAdmin); await dbService.updateUser(updatedAdmin);
console.log('✅ Admin user updated successfully'); console.warn('✅ Admin user updated successfully');
console.log('👤 Updated admin:', updatedAdmin); console.warn('👤 Updated admin:', updatedAdmin);
} }
return; return;
} }
console.log('🔨 Creating new admin user...'); console.warn('🚀 Creating new admin user...');
// Create default admin user // Create default admin user
const adminUser = await dbService.createUserWithPassword( const adminUser = await dbService.createUserWithPassword(
adminEmail, adminEmail,
@@ -48,7 +48,7 @@ export class DatabaseSeeder {
'admin' 'admin'
); );
console.log('👤 Admin user created:', adminUser); console.warn('👤 Admin user created:', adminUser);
// Update user to admin role and active status // Update user to admin role and active status
const updatedAdmin = { const updatedAdmin = {
@@ -62,11 +62,11 @@ export class DatabaseSeeder {
await dbService.updateUser(updatedAdmin); await dbService.updateUser(updatedAdmin);
console.log('✅ Default admin user created successfully'); console.warn('✅ Admin user created successfully');
console.log('👤 Final admin user:', updatedAdmin); console.warn('👤 Final admin user:', updatedAdmin);
console.log('📧 Email:', adminEmail); console.warn('📧 Email:', adminEmail);
console.log('🔑 Password:', adminPassword); console.warn('🔑 Password:', adminPassword);
console.log('⚠️ Please change the default password after first login!'); console.warn('⚠️ Please change the default password after first login!');
} catch (error) { } catch (error) {
console.error('❌ Failed to create default admin user:', error); console.error('❌ Failed to create default admin user:', error);
throw error; throw error;
@@ -76,17 +76,17 @@ export class DatabaseSeeder {
async seedDatabase(): Promise<void> { async seedDatabase(): Promise<void> {
// Prevent multiple seeding attempts // Prevent multiple seeding attempts
if (DatabaseSeeder.seedingInProgress || DatabaseSeeder.seedingCompleted) { if (DatabaseSeeder.seedingInProgress || DatabaseSeeder.seedingCompleted) {
console.log('🔄 Seeding already in progress or completed, skipping...'); console.warn('🔄 Seeding already in progress or completed, skipping...');
return; return;
} }
DatabaseSeeder.seedingInProgress = true; DatabaseSeeder.seedingInProgress = true;
console.log('🌱 Starting database seeding...'); console.warn('🌱 Starting database seeding...');
try { try {
await this.seedDefaultAdmin(); await this.seedDefaultAdmin();
DatabaseSeeder.seedingCompleted = true; DatabaseSeeder.seedingCompleted = true;
console.log('🎉 Database seeding completed successfully!'); console.warn('🎯 Admin seeding completed successfully');
} catch (error) { } catch (error) {
console.error('💥 Database seeding failed:', error); console.error('💥 Database seeding failed:', error);
throw error; throw error;

View File

@@ -10,10 +10,10 @@ export class EmailService {
async sendVerificationEmail(email: string, token: string): Promise<void> { async sendVerificationEmail(email: string, token: string): Promise<void> {
// In a real implementation, this would send an actual email // In a real implementation, this would send an actual email
// For this demo, we'll just log the action // For this demo, we'll just log the action
console.log( console.warn(
`📧 Sending verification email to ${email} with token: ${token}` `📧 Sending verification email to ${email} with token: ${token}`
); );
console.log(`🔗 Verification link: /verify-email?token=${token}`); console.warn(`🔗 Verification link: /verify-email?token=${token}`);
// Simulate network delay // Simulate network delay
await new Promise(resolve => setTimeout(resolve, 500)); await new Promise(resolve => setTimeout(resolve, 500));

View File

@@ -1,6 +1,8 @@
// Mailgun Configuration // Mailgun Configuration
// This file handles Mailgun credentials and configuration // This file handles Mailgun credentials and configuration
import { getEnv } from '../utils/env';
export interface MailgunConfig { export interface MailgunConfig {
apiKey: string; apiKey: string;
domain: string; domain: string;
@@ -20,13 +22,8 @@ const defaultConfig: MailgunConfig = {
// Load configuration from environment variables or use defaults // Load configuration from environment variables or use defaults
export const getMailgunConfig = (): MailgunConfig => { export const getMailgunConfig = (): MailgunConfig => {
// Check if running in browser environment const env = getEnv();
const isClient = typeof window !== 'undefined';
if (isClient) {
// In browser, use Vite environment variables
// Note: Vite environment variables are available at build time
const env = (import.meta as any).env || {};
return { return {
apiKey: env.VITE_MAILGUN_API_KEY || defaultConfig.apiKey, apiKey: env.VITE_MAILGUN_API_KEY || defaultConfig.apiKey,
domain: env.VITE_MAILGUN_DOMAIN || defaultConfig.domain, domain: env.VITE_MAILGUN_DOMAIN || defaultConfig.domain,
@@ -34,16 +31,6 @@ export const getMailgunConfig = (): MailgunConfig => {
fromName: env.VITE_MAILGUN_FROM_NAME || defaultConfig.fromName, fromName: env.VITE_MAILGUN_FROM_NAME || defaultConfig.fromName,
fromEmail: env.VITE_MAILGUN_FROM_EMAIL || defaultConfig.fromEmail, fromEmail: env.VITE_MAILGUN_FROM_EMAIL || defaultConfig.fromEmail,
}; };
} else {
// In Node.js environment (if needed for SSR)
return {
apiKey: process.env.MAILGUN_API_KEY || defaultConfig.apiKey,
domain: process.env.MAILGUN_DOMAIN || defaultConfig.domain,
baseUrl: process.env.MAILGUN_BASE_URL || defaultConfig.baseUrl,
fromName: process.env.MAILGUN_FROM_NAME || defaultConfig.fromName,
fromEmail: process.env.MAILGUN_FROM_EMAIL || defaultConfig.fromEmail,
};
}
}; };
// Check if Mailgun is properly configured (not using demo values) // Check if Mailgun is properly configured (not using demo values)