// src/main/ipc/cloud-sync-handlers.ts // Phase V2-4: CloudSync IPC 핸들러 import { ipcMain, BrowserWindow } from 'electron' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels' import { D3ROError, ErrorCode } from '@d3ro/core/errors' import type { IPCResult } from '@d3ro/core/errors' import { getCloudSyncService } from '../services/CloudSyncService' import { getLogger } from '../services/LoggerService' import { configSet } from '../services/ConfigService' const logger = getLogger('cloud-sync-handlers') interface SignInParams { provider: 'google' | 'github' } function ok(data: T): IPCResult { return { success: true, data } } function fail(error: unknown): IPCResult { if (error instanceof D3ROError) { return { success: false, error: { code: error.code, message: error.message } } } const message = error instanceof Error ? error.message : String(error) return { success: false, error: { code: ErrorCode.LLMProcessingFailed, message } } } export function registerCloudSyncHandlers(): void { const sync = getCloudSyncService() ipcMain.handle(IPC_CHANNELS.CLOUD_SYNC.GET_STATE, () => { try { return ok(sync.getState()) } catch (e) { return fail(e) } }) ipcMain.handle(IPC_CHANNELS.CLOUD_SYNC.SIGN_IN, async (_e, params: SignInParams) => { try { await sync.startSignIn(params.provider) return ok({ started: true }) } catch (e) { return fail(e) } }) ipcMain.handle(IPC_CHANNELS.CLOUD_SYNC.HANDLE_CALLBACK, async (_e, params: { code: string }) => { try { await sync.handleAuthCallback(params.code) return ok(sync.getState()) } catch (e) { return fail(e) } }) ipcMain.handle(IPC_CHANNELS.CLOUD_SYNC.SIGN_OUT, async () => { try { await sync.signOut() return ok(sync.getState()) } catch (e) { return fail(e) } }) ipcMain.handle(IPC_CHANNELS.CLOUD_SYNC.PUSH_ALL, async () => { try { const result = await sync.pushAll() configSet('cloudSyncLastAt', Date.now()) return ok(result) } catch (e) { return fail(e) } }) ipcMain.handle(IPC_CHANNELS.CLOUD_SYNC.PULL_ALL, async () => { try { const result = await sync.pullAll() configSet('cloudSyncLastAt', Date.now()) return ok(result) } catch (e) { return fail(e) } }) // 이벤트 → renderer 브로드캐스트 function broadcast(channel: string, payload: unknown): void { BrowserWindow.getAllWindows().forEach((win) => { if (!win.isDestroyed()) { win.webContents.send(channel, payload) } }) } sync.on('auth-changed', (payload) => { broadcast(IPC_CHANNELS.CLOUD_SYNC.AUTH_CHANGED, payload) }) sync.on('sync-progress', (payload) => { broadcast(IPC_CHANNELS.CLOUD_SYNC.SYNC_PROGRESS, payload) }) sync.on('sync-complete', (payload) => { broadcast(IPC_CHANNELS.CLOUD_SYNC.SYNC_COMPLETE, payload) }) sync.on('sync-error', (payload) => { broadcast(IPC_CHANNELS.CLOUD_SYNC.SYNC_ERROR, payload) }) logger.info('Cloud Sync IPC handlers registered') }