glass/src/common/services/databaseInitializer.js
2025-07-05 22:00:36 +09:00

222 lines
8.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { app } = require('electron');
const path = require('path');
const fs = require('fs');
const sqliteClient = require('./sqliteClient');
const config = require('../config/config');
class DatabaseInitializer {
constructor() {
this.isInitialized = false;
// 최종적으로 사용될 DB 경로 (쓰기 가능한 위치)
const userDataPath = app.getPath('userData');
this.dbPath = path.join(userDataPath, 'pickleglass.db');
this.dataDir = userDataPath;
// 원본 DB 경로 (패키지 내 읽기 전용 위치)
this.sourceDbPath = app.isPackaged
? path.join(process.resourcesPath, 'data', 'pickleglass.db')
: path.join(app.getAppPath(), 'data', 'pickleglass.db');
}
ensureDatabaseExists() {
if (!fs.existsSync(this.dbPath)) {
console.log(`[DB] Database not found at ${this.dbPath}. Preparing to create new database...`);
// userData 디렉토리 생성 (없을 경우)
if (!fs.existsSync(this.dataDir)) {
fs.mkdirSync(this.dataDir, { recursive: true });
}
// 패키지에 번들된 초기 DB가 있으면 복사, 없으면 빈 파일을 생성하도록 둔다.
if (fs.existsSync(this.sourceDbPath)) {
try {
fs.copyFileSync(this.sourceDbPath, this.dbPath);
console.log(`[DB] Bundled database copied to ${this.dbPath}`);
} catch (error) {
console.error(`[DB] Failed to copy bundled database:`, error);
// 복사 실패 시에도 새 DB를 생성할 수 있도록 계속 진행
}
} else {
console.log('[DB] No bundled DB found a fresh database will be created.');
}
}
}
async initialize() {
if (this.isInitialized) {
console.log('[DB] Already initialized.');
return true;
}
try {
this.ensureDatabaseExists();
await sqliteClient.connect(this.dbPath); // DB 경로를 인자로 전달
// This single call will now synchronize the schema and then init default data.
await sqliteClient.initTables();
// Clean up any orphaned sessions from previous versions
await sqliteClient.cleanupEmptySessions();
this.isInitialized = true;
console.log('[DB] Database initialized successfully');
return true;
} catch (error) {
console.error('[DB] Database initialization failed:', error);
this.isInitialized = false;
throw error;
}
}
async ensureDataDirectory() {
try {
if (!fs.existsSync(this.dataDir)) {
fs.mkdirSync(this.dataDir, { recursive: true });
console.log('[DatabaseInitializer] Data directory created:', this.dataDir);
} else {
console.log('[DatabaseInitializer] Data directory exists:', this.dataDir);
}
} catch (error) {
console.error('[DatabaseInitializer] Failed to create data directory:', error);
throw error;
}
}
async checkDatabaseExists() {
try {
const exists = fs.existsSync(this.dbPath);
console.log('[DatabaseInitializer] Database file check:', { path: this.dbPath, exists });
return exists;
} catch (error) {
console.error('[DatabaseInitializer] Error checking database file:', error);
return false;
}
}
async createNewDatabase() {
console.log('[DatabaseInitializer] Creating new database...');
try {
await sqliteClient.connect(); // Connect and initialize tables/default data
const user = await sqliteClient.getUser(sqliteClient.defaultUserId);
if (!user) {
throw new Error('Default user was not created during initialization.');
}
console.log(`[DatabaseInitializer] Default user check successful, UID: ${user.uid}`);
return { success: true, user };
} catch (error) {
console.error('[DatabaseInitializer] Failed to create new database:', error);
throw error;
}
}
async connectToExistingDatabase() {
console.log('[DatabaseInitializer] Connecting to existing database...');
try {
await sqliteClient.connect();
const user = await sqliteClient.getUser(sqliteClient.defaultUserId);
if (!user) {
console.warn('[DatabaseInitializer] Default user not found in existing DB, attempting recovery.');
throw new Error('Default user missing');
}
console.log(`[DatabaseInitializer] Connection to existing DB successful for user: ${user.uid}`);
return { success: true, user };
} catch (error) {
console.error('[DatabaseInitializer] Failed to connect to existing database:', error);
throw error;
}
}
async validateAndRecoverData() {
console.log('[DatabaseInitializer] Validating database integrity...');
try {
console.log('[DatabaseInitializer] Validating database integrity...');
// The synchronizeSchema function handles table and column creation now.
// We just need to ensure default data is present.
await sqliteClient.synchronizeSchema();
const defaultUser = await sqliteClient.getUser(sqliteClient.defaultUserId);
if (!defaultUser) {
console.log('[DatabaseInitializer] Default user not found - creating...');
await sqliteClient.initDefaultData();
}
const presetTemplates = await sqliteClient.getPresets('default_user');
if (!presetTemplates || presetTemplates.length === 0) {
console.log('[DatabaseInitializer] Preset templates missing - creating...');
await sqliteClient.initDefaultData();
}
console.log('[DatabaseInitializer] Database validation completed');
return { success: true };
} catch (error) {
console.error('[DatabaseInitializer] Database validation failed:', error);
try {
await sqliteClient.initDefaultData();
console.log('[DatabaseInitializer] Default data recovered');
return { success: true };
} catch (error) {
console.error('[DatabaseInitializer] Database validation failed:', error);
throw error;
}
}
}
async getStatus() {
return {
isInitialized: this.isInitialized,
dbPath: this.dbPath,
dbExists: fs.existsSync(this.dbPath),
enableSQLiteStorage: config.get('enableSQLiteStorage'),
enableOfflineMode: config.get('enableOfflineMode')
};
}
async reset() {
try {
console.log('[DatabaseInitializer] Resetting database...');
sqliteClient.close();
if (fs.existsSync(this.dbPath)) {
fs.unlinkSync(this.dbPath);
console.log('[DatabaseInitializer] Database file deleted');
}
this.isInitialized = false;
await this.initialize();
console.log('[DatabaseInitializer] Database reset completed');
return true;
} catch (error) {
console.error('[DatabaseInitializer] Database reset failed:', error);
return false;
}
}
close() {
if (sqliteClient) {
sqliteClient.close();
}
this.isInitialized = false;
console.log('[DatabaseInitializer] Database connection closed');
}
getDatabasePath() {
return this.dbPath;
}
}
const databaseInitializer = new DatabaseInitializer();
module.exports = databaseInitializer;