Integrate local database management and IPC handlers into Electron
- Add comprehensive IPC handlers for database operations like books, chapters, characters, and conversations. - Implement local database initialization and user data encryption. - Update preload script paths for consistent environment handling. - Modify `page.tsx` to initialize local database within Electron environment. - Add new dependencies including `node-sqlite3-wasm` and `electron-rebuild`.
This commit is contained in:
251
electron/main.ts
251
electron/main.ts
@@ -4,6 +4,7 @@ import * as url from 'url';
|
||||
import { fileURLToPath } from 'url';
|
||||
import Store from 'electron-store';
|
||||
import * as fs from 'fs';
|
||||
import { getDatabaseService } from './database/database.service.js';
|
||||
|
||||
// Fix pour __dirname en ES modules
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
@@ -29,10 +30,8 @@ if (!isDev) {
|
||||
// Définir le nom de l'application
|
||||
app.setName('ERitors Scribe');
|
||||
|
||||
// En dev, __dirname pointe vers electron/, en prod vers dist/electron/
|
||||
const preloadPath = isDev
|
||||
? path.join(__dirname, '../dist/electron/preload.js')
|
||||
: path.join(__dirname, 'preload.js');
|
||||
// En dev et prod, __dirname pointe vers dist/electron/
|
||||
const preloadPath = path.join(__dirname, 'preload.js');
|
||||
|
||||
// Icône de l'application
|
||||
const iconPath = isDev
|
||||
@@ -143,6 +142,10 @@ ipcMain.on('login-success', (_event, token: string) => {
|
||||
ipcMain.on('logout', () => {
|
||||
store.delete('authToken');
|
||||
|
||||
// Close database connection
|
||||
const db = getDatabaseService();
|
||||
db.close();
|
||||
|
||||
if (mainWindow) {
|
||||
mainWindow.close();
|
||||
}
|
||||
@@ -150,6 +153,246 @@ ipcMain.on('logout', () => {
|
||||
createLoginWindow();
|
||||
});
|
||||
|
||||
// ========== DATABASE IPC HANDLERS ==========
|
||||
|
||||
/**
|
||||
* Generate user encryption key
|
||||
*/
|
||||
ipcMain.handle('generate-encryption-key', async (_event, userId: string) => {
|
||||
try {
|
||||
// Import encryption module dynamically
|
||||
const { generateUserEncryptionKey } = await import('./database/encryption.js');
|
||||
const key = generateUserEncryptionKey(userId);
|
||||
return { success: true, key };
|
||||
} catch (error) {
|
||||
console.error('Failed to generate encryption key:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get or generate user encryption key
|
||||
*/
|
||||
ipcMain.handle('get-user-encryption-key', (_event, userId: string) => {
|
||||
const key = store.get(`encryptionKey-${userId}`, null);
|
||||
return key;
|
||||
});
|
||||
|
||||
/**
|
||||
* Store user encryption key
|
||||
*/
|
||||
ipcMain.handle('set-user-encryption-key', (_event, userId: string, encryptionKey: string) => {
|
||||
store.set(`encryptionKey-${userId}`, encryptionKey);
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
* Initialize database for user
|
||||
*/
|
||||
ipcMain.handle('db-initialize', (_event, userId: string, encryptionKey: string) => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
db.initialize(userId, encryptionKey);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize database:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get all books
|
||||
*/
|
||||
ipcMain.handle('db-get-books', () => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
const books = db.getBooks();
|
||||
return { success: true, data: books };
|
||||
} catch (error) {
|
||||
console.error('Failed to get books:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get single book with all data
|
||||
*/
|
||||
ipcMain.handle('db-get-book', (_event, bookId: string) => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
const book = db.getBook(bookId);
|
||||
return { success: true, data: book };
|
||||
} catch (error) {
|
||||
console.error('Failed to get book:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Save book
|
||||
*/
|
||||
ipcMain.handle('db-save-book', (_event, book: any, authorId?: string) => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
db.saveBook(book, authorId);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('Failed to save book:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Delete book
|
||||
*/
|
||||
ipcMain.handle('db-delete-book', (_event, bookId: string) => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
db.deleteBook(bookId);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('Failed to delete book:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Save chapter
|
||||
*/
|
||||
ipcMain.handle('db-save-chapter', (_event, chapter: any, bookId: string, contentId?: string) => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
db.saveChapter(chapter, bookId, contentId);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('Failed to save chapter:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get characters for a book
|
||||
*/
|
||||
ipcMain.handle('db-get-characters', (_event, bookId: string) => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
const characters = db.getCharacters(bookId);
|
||||
return { success: true, data: characters };
|
||||
} catch (error) {
|
||||
console.error('Failed to get characters:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Save character
|
||||
*/
|
||||
ipcMain.handle('db-save-character', (_event, character: any, bookId: string) => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
db.saveCharacter(character, bookId);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('Failed to save character:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get AI conversations for a book
|
||||
*/
|
||||
ipcMain.handle('db-get-conversations', (_event, bookId: string) => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
const conversations = db.getConversations(bookId);
|
||||
return { success: true, data: conversations };
|
||||
} catch (error) {
|
||||
console.error('Failed to get conversations:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Save AI conversation
|
||||
*/
|
||||
ipcMain.handle('db-save-conversation', (_event, conversation: any, bookId: string) => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
db.saveConversation(conversation, bookId);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('Failed to save conversation:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get sync status
|
||||
*/
|
||||
ipcMain.handle('db-get-sync-status', () => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
const status = db.getSyncStatus();
|
||||
return { success: true, data: status };
|
||||
} catch (error) {
|
||||
console.error('Failed to get sync status:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get pending changes
|
||||
*/
|
||||
ipcMain.handle('db-get-pending-changes', (_event, limit: number = 100) => {
|
||||
try {
|
||||
const db = getDatabaseService();
|
||||
const changes = db.getPendingChanges(limit);
|
||||
return { success: true, data: changes };
|
||||
} catch (error) {
|
||||
console.error('Failed to get pending changes:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
app.whenReady().then(() => {
|
||||
console.log('App ready, isDev:', isDev);
|
||||
console.log('resourcesPath:', process.resourcesPath);
|
||||
|
||||
Reference in New Issue
Block a user