refactor(main): ipcSuccess/ipcError 헬퍼 통일 + catch(error) 패턴 (WS-PATTERN)

- cloud-sync-handlers 수동 ok/fail -> ipcSuccess/ipcError 헬퍼 (6 핸들러)
- catch {} -> catch(error) 에러 메시지 보강 32건 (11 ipc handler 파일)
KEEP: template-handlers(주석 명시 에러 무시), license-handlers(이미 헬퍼 사용),
       audio-handlers stop().catch(() => {})(의도적 무시)
정책: docs/REFACTOR_POLICY.md DP2
This commit is contained in:
Yun Chan 2026-07-22 02:38:23 +09:00
parent 4c256202f7
commit 5b6e7aae6b
11 changed files with 133 additions and 93 deletions

View file

@ -39,8 +39,9 @@ export function registerAudioHandlers(): void {
try {
const devices = await getAudioCaptureService().getDevices()
return ipcSuccess(devices)
} catch {
return ipcError(ErrorCode.AudioDeviceNotFound, 'Failed to enumerate audio devices')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.AudioDeviceNotFound, `Failed to enumerate audio devices: ${message}`)
}
})
@ -52,8 +53,9 @@ export function registerAudioHandlers(): void {
try {
configSet('selectedDeviceId', params.deviceId)
return ipcSuccess(undefined)
} catch {
return ipcError(ErrorCode.AudioDeviceNotFound, 'Failed to set device')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.AudioDeviceNotFound, `Failed to set device: ${message}`)
}
})

View file

@ -3,8 +3,7 @@
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 { ipcSuccess, ipcError, ErrorCode, D3ROError } from '@d3ro/core/errors'
import { getCloudSyncService } from '../services/CloudSyncService'
import { getLogger } from '../services/LoggerService'
import { configSet } from '../services/ConfigService'
@ -15,56 +14,57 @@ interface SignInParams {
provider: 'google' | 'github'
}
function ok<T>(data: T): IPCResult<T> {
return { success: true, data }
}
function fail(error: unknown): IPCResult<never> {
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())
return ipcSuccess(sync.getState())
} catch (e) {
return fail(e)
if (e instanceof D3ROError) {
return ipcError(e.code, e.message)
}
const message = e instanceof Error ? e.message : String(e)
return ipcError(ErrorCode.LLMProcessingFailed, message)
}
})
ipcMain.handle(IPC_CHANNELS.CLOUD_SYNC.SIGN_IN, async (_e, params: SignInParams) => {
try {
await sync.startSignIn(params.provider)
return ok({ started: true })
return ipcSuccess({ started: true })
} catch (e) {
return fail(e)
if (e instanceof D3ROError) {
return ipcError(e.code, e.message)
}
const message = e instanceof Error ? e.message : String(e)
return ipcError(ErrorCode.LLMProcessingFailed, message)
}
})
ipcMain.handle(IPC_CHANNELS.CLOUD_SYNC.HANDLE_CALLBACK, async (_e, params: { code: string }) => {
try {
await sync.handleAuthCallback(params.code)
return ok(sync.getState())
return ipcSuccess(sync.getState())
} catch (e) {
return fail(e)
if (e instanceof D3ROError) {
return ipcError(e.code, e.message)
}
const message = e instanceof Error ? e.message : String(e)
return ipcError(ErrorCode.LLMProcessingFailed, message)
}
})
ipcMain.handle(IPC_CHANNELS.CLOUD_SYNC.SIGN_OUT, async () => {
try {
await sync.signOut()
return ok(sync.getState())
return ipcSuccess(sync.getState())
} catch (e) {
return fail(e)
if (e instanceof D3ROError) {
return ipcError(e.code, e.message)
}
const message = e instanceof Error ? e.message : String(e)
return ipcError(ErrorCode.LLMProcessingFailed, message)
}
})
@ -72,9 +72,13 @@ export function registerCloudSyncHandlers(): void {
try {
const result = await sync.pushAll()
configSet('cloudSyncLastAt', Date.now())
return ok(result)
return ipcSuccess(result)
} catch (e) {
return fail(e)
if (e instanceof D3ROError) {
return ipcError(e.code, e.message)
}
const message = e instanceof Error ? e.message : String(e)
return ipcError(ErrorCode.LLMProcessingFailed, message)
}
})
@ -82,9 +86,13 @@ export function registerCloudSyncHandlers(): void {
try {
const result = await sync.pullAll()
configSet('cloudSyncLastAt', Date.now())
return ok(result)
return ipcSuccess(result)
} catch (e) {
return fail(e)
if (e instanceof D3ROError) {
return ipcError(e.code, e.message)
}
const message = e instanceof Error ? e.message : String(e)
return ipcError(ErrorCode.LLMProcessingFailed, message)
}
})

View file

@ -28,8 +28,9 @@ export function registerConfigHandlers(): void {
ipcMain.handle(IPC_CHANNELS.CONFIG.GET, async (_event, params: ConfigGetParams) => {
try {
return ipcSuccess(configGet(params.key))
} catch {
return ipcError(ErrorCode.ConfigReadFailed, `Failed to read config key: ${params.key}`)
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.ConfigReadFailed, `Failed to read config key ${params.key}: ${message}`)
}
})
@ -39,8 +40,9 @@ export function registerConfigHandlers(): void {
configSet(params.key, params.value as AppConfig[typeof params.key])
broadcastConfigChanged(params.key, params.value, prev)
return ipcSuccess(undefined)
} catch {
return ipcError(ErrorCode.ConfigWriteFailed, `Failed to write config key: ${params.key}`)
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.ConfigWriteFailed, `Failed to write config key ${params.key}: ${message}`)
}
})
@ -52,8 +54,9 @@ export function registerConfigHandlers(): void {
try {
configReset(params.key)
return ipcSuccess(undefined)
} catch {
return ipcError(ErrorCode.ConfigResetFailed, 'Failed to reset config')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.ConfigResetFailed, `Failed to reset config: ${message}`)
}
})

View file

@ -16,24 +16,27 @@ export function registerDictionaryHandlers(): void {
ipcMain.handle(IPC_CHANNELS.DICTIONARY.GET_ALL, async (_event, params: DictionaryQueryParams) => {
try {
return ipcSuccess(getDictionaryService().list(params))
} catch {
return ipcError(ErrorCode.DBQueryFailed, 'Failed to get dictionary')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBQueryFailed, `Failed to get dictionary: ${message}`)
}
})
ipcMain.handle(IPC_CHANNELS.DICTIONARY.ADD, async (_event, params: DictionaryAddParams) => {
try {
return ipcSuccess(getDictionaryService().add(params))
} catch {
return ipcError(ErrorCode.DBWriteFailed, 'Failed to add dictionary entry')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBWriteFailed, `Failed to add dictionary entry: ${message}`)
}
})
ipcMain.handle(IPC_CHANNELS.DICTIONARY.UPDATE, async (_event, params: DictionaryUpdateParams) => {
try {
return ipcSuccess(getDictionaryService().update(params))
} catch {
return ipcError(ErrorCode.DBWriteFailed, 'Failed to update dictionary entry')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBWriteFailed, `Failed to update dictionary entry: ${message}`)
}
})
@ -41,16 +44,18 @@ export function registerDictionaryHandlers(): void {
try {
getDictionaryService().delete(params.id)
return ipcSuccess(undefined)
} catch {
return ipcError(ErrorCode.DBWriteFailed, 'Failed to delete dictionary entry')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBWriteFailed, `Failed to delete dictionary entry: ${message}`)
}
})
ipcMain.handle(IPC_CHANNELS.DICTIONARY.SEARCH, async (_event, params: DictionarySearchParams) => {
try {
return ipcSuccess(getDictionaryService().search(params))
} catch {
return ipcError(ErrorCode.DBQueryFailed, 'Failed to search dictionary')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBQueryFailed, `Failed to search dictionary: ${message}`)
}
})
}

View file

@ -15,16 +15,18 @@ export function registerHistoryHandlers(): void {
ipcMain.handle(IPC_CHANNELS.HISTORY.GET_ALL, async (_event, params: HistoryQueryParams) => {
try {
return ipcSuccess(getHistoryService().list(params))
} catch {
return ipcError(ErrorCode.DBQueryFailed, 'Failed to get history')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBQueryFailed, `Failed to get history: ${message}`)
}
})
ipcMain.handle(IPC_CHANNELS.HISTORY.GET_BY_ID, async (_event, params: HistoryGetByIdParams) => {
try {
return ipcSuccess(getHistoryService().getById(params.id))
} catch {
return ipcError(ErrorCode.DBQueryFailed, 'Failed to get history entry')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBQueryFailed, `Failed to get history entry: ${message}`)
}
})
@ -32,8 +34,9 @@ export function registerHistoryHandlers(): void {
try {
getHistoryService().delete(params.id)
return ipcSuccess(undefined)
} catch {
return ipcError(ErrorCode.DBWriteFailed, 'Failed to delete history entry')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBWriteFailed, `Failed to delete history entry: ${message}`)
}
})
@ -41,24 +44,27 @@ export function registerHistoryHandlers(): void {
try {
getHistoryService().deleteAll()
return ipcSuccess(undefined)
} catch {
return ipcError(ErrorCode.DBWriteFailed, 'Failed to delete all history')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBWriteFailed, `Failed to delete all history: ${message}`)
}
})
ipcMain.handle(IPC_CHANNELS.HISTORY.SEARCH, async (_event, params: HistorySearchParams) => {
try {
return ipcSuccess(getHistoryService().search(params))
} catch {
return ipcError(ErrorCode.DBQueryFailed, 'Failed to search history')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBQueryFailed, `Failed to search history: ${message}`)
}
})
ipcMain.handle(IPC_CHANNELS.STATS.GET_SUMMARY, async () => {
try {
return ipcSuccess(getHistoryService().getStats())
} catch {
return ipcError(ErrorCode.DBQueryFailed, 'Failed to get stats')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBQueryFailed, `Failed to get stats: ${message}`)
}
})
}

View file

@ -17,8 +17,9 @@ export function registerHotkeyHandlers(): void {
configSet('dictationShortcut', params.binding)
getHotkeyService().loadFromConfig()
return ipcSuccess(undefined)
} catch {
return ipcError(ErrorCode.HotkeyRegistrationFailed, 'Failed to set dictation shortcut')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.HotkeyRegistrationFailed, `Failed to set dictation shortcut: ${message}`)
}
})
@ -31,8 +32,9 @@ export function registerHotkeyHandlers(): void {
configSet('handsFreeShortcut', params.binding)
getHotkeyService().loadFromConfig()
return ipcSuccess(undefined)
} catch {
return ipcError(ErrorCode.HotkeyRegistrationFailed, 'Failed to set hands-free shortcut')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.HotkeyRegistrationFailed, `Failed to set hands-free shortcut: ${message}`)
}
})
@ -45,8 +47,9 @@ export function registerHotkeyHandlers(): void {
configSet('commandShortcut', params.binding)
getHotkeyService().loadFromConfig()
return ipcSuccess(undefined)
} catch {
return ipcError(ErrorCode.HotkeyRegistrationFailed, 'Failed to set command shortcut')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.HotkeyRegistrationFailed, `Failed to set command shortcut: ${message}`)
}
})
@ -59,8 +62,9 @@ export function registerHotkeyHandlers(): void {
configSet('captionShortcut', params.binding)
getHotkeyService().loadFromConfig()
return ipcSuccess(undefined)
} catch {
return ipcError(ErrorCode.HotkeyRegistrationFailed, 'Failed to set caption shortcut')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.HotkeyRegistrationFailed, `Failed to set caption shortcut: ${message}`)
}
})

View file

@ -24,8 +24,9 @@ export function registerInstructionHandlers(): void {
try {
const result = getCustomInstructionService().create(params)
return ipcSuccess(result)
} catch {
return ipcError(ErrorCode.ConfigWriteFailed, 'Failed to create instruction')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.ConfigWriteFailed, `Failed to create instruction: ${message}`)
}
}
)
@ -36,8 +37,9 @@ export function registerInstructionHandlers(): void {
try {
const result = getCustomInstructionService().update(params.id, params.data)
return ipcSuccess(result)
} catch {
return ipcError(ErrorCode.ConfigWriteFailed, 'Failed to update instruction')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.ConfigWriteFailed, `Failed to update instruction: ${message}`)
}
}
)

View file

@ -60,8 +60,9 @@ export function registerLLMHandlers(): void {
try {
const models = await getLocalLLMService().getModels()
return ipcSuccess(models)
} catch {
return ipcError(ErrorCode.LLMServerUnreachable, 'Failed to get models')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.LLMServerUnreachable, `Failed to get models: ${message}`)
}
})
@ -91,8 +92,9 @@ export function registerLLMHandlers(): void {
processingTimeMs: Math.round(performance.now() - start),
tokenCount: 0
})
} catch {
return ipcError(ErrorCode.LLMProcessingFailed, 'LLM processing failed')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.LLMProcessingFailed, `LLM processing failed: ${message}`)
}
})

View file

@ -17,8 +17,9 @@ export function registerMemoHandlers(): void {
ipcMain.handle(IPC_CHANNELS.MEMO.GET_TAGS, async (_event, params: GetTagsParams) => {
try {
return ipcSuccess(getMemoService().getTagsForEntry(params.historyId))
} catch {
return ipcError(ErrorCode.DBQueryFailed, 'Failed to get tags for history entry')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBQueryFailed, `Failed to get tags for history entry: ${message}`)
}
})
@ -48,16 +49,18 @@ export function registerMemoHandlers(): void {
ipcMain.handle(IPC_CHANNELS.MEMO.GET_ALL_TAGS, async () => {
try {
return ipcSuccess(getMemoService().getAllTags())
} catch {
return ipcError(ErrorCode.DBQueryFailed, 'Failed to get all tags')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBQueryFailed, `Failed to get all tags: ${message}`)
}
})
ipcMain.handle(IPC_CHANNELS.MEMO.SEARCH_BY_TAG, async (_event, params: SearchByTagParams) => {
try {
return ipcSuccess(getMemoService().searchByTag(params))
} catch {
return ipcError(ErrorCode.DBQueryFailed, 'Failed to search by tag')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.DBQueryFailed, `Failed to search by tag: ${message}`)
}
})

View file

@ -29,8 +29,9 @@ export function registerSTTHandlers(): void {
try {
const stt = getLocalSTTService()
return ipcSuccess(stt.getStatus())
} catch {
return ipcError(ErrorCode.STTSidecarCommunicationFailed, 'Failed to get STT status')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.STTSidecarCommunicationFailed, `Failed to get STT status: ${message}`)
}
})
@ -38,8 +39,9 @@ export function registerSTTHandlers(): void {
try {
const stt = getLocalSTTService()
return ipcSuccess(await stt.getModels())
} catch {
return ipcError(ErrorCode.STTModelNotFound, 'Failed to get models')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.STTModelNotFound, `Failed to get models: ${message}`)
}
})
@ -53,8 +55,9 @@ export function registerSTTHandlers(): void {
const stt = getLocalSTTService()
await stt.initialize(params.modelId)
return ipcSuccess(undefined)
} catch {
return ipcError(ErrorCode.STTModelLoadFailed, 'Failed to set STT model')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.STTModelLoadFailed, `Failed to set STT model: ${message}`)
}
})

View file

@ -34,8 +34,9 @@ export function registerVoiceHandlers(): void {
await voice.startSession('dictation')
const session = voice.currentSession
return ipcSuccess({ sessionId: session?.id ?? params.sessionId ?? '' })
} catch {
return ipcError(ErrorCode.AudioCaptureStartFailed, 'Failed to start recording')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.AudioCaptureStartFailed, `Failed to start recording: ${message}`)
}
})
@ -48,8 +49,9 @@ export function registerVoiceHandlers(): void {
text: voice.currentSession?.transcription ?? '',
durationMs: voice.currentSession ? Date.now() - voice.currentSession.startedAt : 0
})
} catch {
return ipcError(ErrorCode.STTTranscriptionFailed, 'Failed to stop recording')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
return ipcError(ErrorCode.STTTranscriptionFailed, `Failed to stop recording: ${message}`)
}
})