#!/usr/bin/env node /** * Database initialization script for container startup * Automatically sets up database on first run or when database doesn't exist */ const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); const { DATA_ROOT, DB_PATH, KEY_FILE } = require('../src/database/config'); const DATABASE_PATH = DB_PATH; const USE_JSON_DATABASE = process.env.USE_JSON_DATABASE === '1' || process.env.USE_JSON_DATABASE === 'true'; async function initializeDatabase() { // Skip if using JSON mode if (USE_JSON_DATABASE) { console.log('📁 Using JSON database mode (backward compatibility)'); return; } console.log('🔍 Checking database status...'); // Ensure data directory exists const dataDir = path.dirname(DATABASE_PATH); if (!fs.existsSync(dataDir)) { console.log('📁 Creating data directory:', dataDir); fs.mkdirSync(dataDir, { recursive: true }); } // Check if database exists const dbExists = fs.existsSync(DATABASE_PATH); if (dbExists) { console.log('✅ Database already exists:', DATABASE_PATH); if (!process.env.DATABASE_ENCRYPTION_KEY && KEY_FILE && fs.existsSync(KEY_FILE)) { const persistedKey = fs.readFileSync(KEY_FILE, 'utf8').trim(); if (persistedKey) { process.env.DATABASE_ENCRYPTION_KEY = persistedKey; console.log('✅ Loaded encryption key from file'); } } // Verify encryption key is set if (!process.env.DATABASE_ENCRYPTION_KEY) { console.error('❌ DATABASE_ENCRYPTION_KEY not set!'); console.error(' Database exists but encryption key is missing.'); console.error(' Set DATABASE_ENCRYPTION_KEY to the key used when creating the database.'); process.exit(1); } return; } console.log('🔧 Database not found, setting up new database...'); // Generate encryption key if not provided if (!process.env.DATABASE_ENCRYPTION_KEY && KEY_FILE && fs.existsSync(KEY_FILE)) { const persistedKey = fs.readFileSync(KEY_FILE, 'utf8').trim(); if (persistedKey) { process.env.DATABASE_ENCRYPTION_KEY = persistedKey; console.log('✅ Loaded encryption key from file'); } } if (!process.env.DATABASE_ENCRYPTION_KEY) { const generatedKey = crypto.randomBytes(32).toString('hex'); process.env.DATABASE_ENCRYPTION_KEY = generatedKey; console.log('⚠️ Generated new encryption key (save this!)'); console.log('⚠️ DATABASE_ENCRYPTION_KEY=' + generatedKey); console.log('⚠️ Add this to your environment configuration to persist it!'); // Save to a file for persistence const keyFile = KEY_FILE || path.join(dataDir, '.encryption_key'); fs.writeFileSync(keyFile, generatedKey, { mode: 0o600 }); console.log('⚠️ Saved to:', keyFile); } // Generate JWT secret if not provided if (!process.env.JWT_SECRET && !process.env.SESSION_SECRET) { const jwtSecret = crypto.randomBytes(32).toString('hex'); process.env.JWT_SECRET = jwtSecret; console.log('⚠️ Generated new JWT secret (save this!)'); console.log('⚠️ JWT_SECRET=' + jwtSecret); // Save to a file for persistence const jwtFile = path.join(dataDir, '.jwt_secret'); fs.writeFileSync(jwtFile, jwtSecret, { mode: 0o600 }); console.log('⚠️ Saved to:', jwtFile); } // Run setup script try { const setupScript = require('./setup-database.js'); console.log('✅ Database setup complete'); } catch (error) { console.error('❌ Failed to setup database:', error.message); throw error; } // Check if there are JSON files to migrate const usersFile = path.join(path.join(DATA_ROOT, '.opencode-chat'), 'users.json'); const sessionsFile = path.join(path.join(DATA_ROOT, '.opencode-chat'), 'user-sessions.json'); const hasJsonData = fs.existsSync(usersFile) || fs.existsSync(sessionsFile); if (hasJsonData) { console.log('📦 Found existing JSON data files'); console.log(' To migrate data, run: node scripts/migrate-to-database.js'); console.log(' Or set USE_JSON_DATABASE=1 to continue using JSON files'); } } // Auto-initialize if called directly if (require.main === module) { initializeDatabase() .then(() => { console.log('✅ Database initialization complete'); process.exit(0); }) .catch(error => { console.error('❌ Database initialization failed:', error); process.exit(1); }); } module.exports = { initializeDatabase };