feat(V2-1b): packages/core 추출 — 공유 타입/에러/채널/유틸 분리
packages/core (@d3ro/core) 신규 생성:
- types.ts, errors.ts, ipc-channels.ts, constants.ts (shared에서 이동)
- utils/meeting-markdown.ts, utils/markdown-to-docx.ts (main/utils에서 이동)
- subpath exports 정의 (./types, ./errors, ./ipc-channels, ./constants,
./utils/meeting-markdown, ./utils/markdown-to-docx)
- src/index.ts barrel export 추가
- docx를 core 자체 dependency로 선언
apps/desktop 연결:
- package.json에 @d3ro/core: '*' dep 추가
- tsconfig.node/web.json paths에 @d3ro/core/* 추가
- electron.vite.config.ts 3개 섹션 alias 추가 (main/preload/renderer)
- externalizeDepsPlugin exclude에 @d3ro/core (workspace 소스 번들 대상)
- vitest.config.ts alias 추가
일괄 치환 (79 파일, 167건):
- @shared/{types,errors,ipc-channels,constants} → @d3ro/core/*
- static/dynamic import + type expression import 모두 포함
- MeetingModeService.ts의 ../utils/* 상대 경로 → @d3ro/core/utils/*
- @shared/theme-vars는 V2-1c 범위로 남김 (WindowManager만 사용)
M1 수정 포함:
- electron.vite.config.ts의 resolve('src/shared') → resolve(__dirname, ...)
CWD 독립적으로 동작하도록 견고화
검증:
- typecheck 통과
- build 통과 (main+preload+renderer)
- dev 런타임 → DB/핫키/Ollama 모두 정상, 기존 데이터 연속성 유지
This commit is contained in:
parent
a4cb4c0805
commit
3b0eb3393b
95 changed files with 315 additions and 212 deletions
256
packages/core/src/errors.ts
Normal file
256
packages/core/src/errors.ts
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
// src/shared/errors.ts
|
||||
|
||||
export enum ErrorCode {
|
||||
// === Success ===
|
||||
Success = 0,
|
||||
|
||||
// === STT (100-199) ===
|
||||
STTEngineNotInstalled = 100,
|
||||
STTModelNotFound = 101,
|
||||
STTModelNotLoaded = 102,
|
||||
STTModelLoadFailed = 103,
|
||||
STTModelDownloadFailed = 104,
|
||||
STTModelDownloadCancelled = 105,
|
||||
STTTranscriptionFailed = 110,
|
||||
STTTranscriptionTimeout = 111,
|
||||
STTTranscriptionCancelled = 112,
|
||||
STTNoAudioData = 113,
|
||||
STTAudioTooShort = 114,
|
||||
STTLanguageNotSupported = 120,
|
||||
STTSidecarSpawnFailed = 130,
|
||||
STTSidecarCrashed = 131,
|
||||
STTSidecarCommunicationFailed = 132,
|
||||
STTGPUNotAvailable = 140,
|
||||
|
||||
// === TTS (200-299) ===
|
||||
TTSEngineNotInstalled = 200,
|
||||
TTSVoiceNotFound = 201,
|
||||
TTSVoiceNotLoaded = 202,
|
||||
TTSVoiceLoadFailed = 203,
|
||||
TTSVoiceDownloadFailed = 204,
|
||||
TTSSynthesisFailed = 210,
|
||||
TTSPlaybackFailed = 211,
|
||||
TTSPlaybackInterrupted = 212,
|
||||
TTSTextTooLong = 220,
|
||||
TTSTextEmpty = 221,
|
||||
|
||||
// === LLM / Ollama (300-399) ===
|
||||
LLMServerUnreachable = 300,
|
||||
LLMServerConnectionFailed = 301,
|
||||
LLMServerTimeout = 302,
|
||||
LLMModelNotFound = 310,
|
||||
LLMModelNotLoaded = 311,
|
||||
LLMModelLoadFailed = 312,
|
||||
LLMModelPullFailed = 313,
|
||||
LLMModelPullCancelled = 314,
|
||||
LLMProcessingFailed = 320,
|
||||
LLMProcessingTimeout = 321,
|
||||
LLMProcessingCancelled = 322,
|
||||
LLMResponseParseFailed = 323,
|
||||
LLMInvalidAction = 330,
|
||||
LLMPromptTooLong = 331,
|
||||
|
||||
// === Audio (400-499) ===
|
||||
AudioDeviceNotFound = 400,
|
||||
AudioDeviceAccessDenied = 401,
|
||||
AudioDeviceBusy = 402,
|
||||
AudioCaptureStartFailed = 410,
|
||||
AudioCaptureStopFailed = 411,
|
||||
AudioCaptureFailed = 412,
|
||||
AudioNoPermission = 420,
|
||||
AudioStreamError = 430,
|
||||
AudioBufferOverflow = 431,
|
||||
|
||||
// === Hotkey (500-599) ===
|
||||
HotkeyRegistrationFailed = 500,
|
||||
HotkeyConflict = 501,
|
||||
HotkeySystemReserved = 502,
|
||||
HotkeyHookInitFailed = 510,
|
||||
HotkeyHookCrashed = 511,
|
||||
|
||||
// === TextInsert (600-699) ===
|
||||
TextInsertFailed = 600,
|
||||
TextInsertClipboardSaveFailed = 601,
|
||||
TextInsertClipboardRestoreFailed = 602,
|
||||
TextInsertKeySimulationFailed = 603,
|
||||
TextInsertNoActiveWindow = 610,
|
||||
TextInsertTargetAppNotResponding = 611,
|
||||
|
||||
// === History / Dictionary / DB (700-799) ===
|
||||
DBOpenFailed = 700,
|
||||
DBMigrationFailed = 701,
|
||||
DBQueryFailed = 702,
|
||||
DBWriteFailed = 703,
|
||||
HistoryNotFound = 710,
|
||||
HistoryExportFailed = 711,
|
||||
DictionaryNotFound = 720,
|
||||
DictionaryDuplicate = 721,
|
||||
DictionaryImportFailed = 722,
|
||||
DictionaryExportFailed = 723,
|
||||
DictionaryImportInvalidFormat = 724,
|
||||
|
||||
// === Phase 10: Memo Tags (730-739) ===
|
||||
MemoTagDuplicate = 730,
|
||||
MemoTagNotFound = 731,
|
||||
MemoExportFailed = 732,
|
||||
|
||||
// === Phase 10: Voice Commands (740-749) ===
|
||||
VoiceCommandMatchFailed = 740,
|
||||
VoiceCommandNotFound = 741,
|
||||
|
||||
// === Phase 10: Screen Context (750-759) ===
|
||||
ContextCaptureFailed = 750,
|
||||
ContextSelectedTextFailed = 751,
|
||||
|
||||
// === Phase 10: LLM Chain (760-769) ===
|
||||
ChainNotFound = 760,
|
||||
ChainExecutionFailed = 761,
|
||||
ChainStepFailed = 762,
|
||||
ChainCancelled = 763,
|
||||
|
||||
// === Phase 10: Live Caption (770-779) ===
|
||||
CaptionStartFailed = 770,
|
||||
CaptionAlreadyActive = 771,
|
||||
CaptionSTTFailed = 772,
|
||||
|
||||
// === Phase 12: File Transcription (780-784) ===
|
||||
FileTranscriptionFFmpegFailed = 780,
|
||||
FileTranscriptionInvalidFormat = 781,
|
||||
FileTranscriptionChunkFailed = 782,
|
||||
FileTranscriptionCancelled = 783,
|
||||
FileTranscriptionFileTooLarge = 784,
|
||||
|
||||
// === Phase 12: Meeting Summary (785-789) ===
|
||||
MeetingSummaryGenerationFailed = 785,
|
||||
MeetingSummaryNoTranscript = 786,
|
||||
MeetingSummaryExportFailed = 787,
|
||||
|
||||
// === Phase 12: Dictation Template (790-794) ===
|
||||
TemplateNotFound = 790,
|
||||
TemplateSessionAlreadyActive = 791,
|
||||
TemplateSessionNotActive = 792,
|
||||
TemplateFieldRecordingFailed = 793,
|
||||
TemplateInvalidFormat = 794,
|
||||
|
||||
// === Phase 13: Voice Conversation (795-799) ===
|
||||
ConversationSessionAlreadyActive = 795,
|
||||
ConversationNoActiveSession = 796,
|
||||
ConversationTTSFailed = 797,
|
||||
ConversationLLMFailed = 798,
|
||||
|
||||
// === Phase 13: Local RAG (870-874) ===
|
||||
RAGDocumentNotFound = 870,
|
||||
RAGIndexingFailed = 871,
|
||||
RAGEmbeddingFailed = 872,
|
||||
RAGQueryFailed = 873,
|
||||
RAGUnsupportedFormat = 874,
|
||||
|
||||
// === Phase 13: Voice Action (875-879) ===
|
||||
VoiceActionPlanFailed = 875,
|
||||
VoiceActionExecutionFailed = 876,
|
||||
VoiceActionBlocked = 877,
|
||||
VoiceActionInvalidPlan = 878,
|
||||
|
||||
// === Phase 14: Meeting Mode (880-889) ===
|
||||
MeetingAlreadyRecording = 880,
|
||||
MeetingNotRecording = 881,
|
||||
MeetingProcessingFailed = 882,
|
||||
MeetingSessionNotFound = 883,
|
||||
MeetingExportFailed = 884,
|
||||
MeetingPdfFailed = 885,
|
||||
MeetingDocumentNotFound = 886,
|
||||
MeetingDocGenerationFailed = 887,
|
||||
MeetingDocExportFailed = 888,
|
||||
MeetingTranscriptUpdateFailed = 889,
|
||||
MeetingDocTemplateNotFound = 890,
|
||||
MeetingDocTemplateBuiltinDelete = 891,
|
||||
MeetingDocxExportFailed = 892,
|
||||
MeetingPolishFailed = 893,
|
||||
MeetingChatFailed = 894,
|
||||
DiarizationFailed = 895,
|
||||
DiarizationModelNotLoaded = 896,
|
||||
DiarizationTokenRequired = 897,
|
||||
|
||||
// === Config (800-849) ===
|
||||
ConfigReadFailed = 800,
|
||||
ConfigWriteFailed = 801,
|
||||
ConfigInvalidValue = 802,
|
||||
ConfigKeyNotFound = 803,
|
||||
ConfigResetFailed = 804,
|
||||
ConfigMigrationFailed = 810,
|
||||
|
||||
// === License (850-869) ===
|
||||
LicenseKeyInvalid = 850,
|
||||
LicenseKeyExpired = 851,
|
||||
LicenseActivationFailed = 852,
|
||||
LicenseDeactivationFailed = 853,
|
||||
LicenseMachineIdMismatch = 854,
|
||||
LicenseOfflineGraceExpired = 855,
|
||||
LicenseVerificationFailed = 856,
|
||||
FeatureNotAvailable = 860,
|
||||
QuotaExceeded = 861,
|
||||
TierRequired = 862,
|
||||
|
||||
// === System / Window (900-999) ===
|
||||
WindowCreationFailed = 900,
|
||||
WindowNotFound = 901,
|
||||
TrayCreationFailed = 910,
|
||||
NotificationFailed = 920,
|
||||
PermissionDenied = 930,
|
||||
ExternalOpenFailed = 940,
|
||||
SoundPlayFailed = 950,
|
||||
AppAlreadyRunning = 960,
|
||||
UnknownError = 999
|
||||
}
|
||||
|
||||
/**
|
||||
* D3RO-VOICE 표준 에러 객체 (Speakly NXError 패턴)
|
||||
*/
|
||||
export class D3ROError extends Error {
|
||||
readonly code: ErrorCode
|
||||
readonly details?: Record<string, unknown>
|
||||
|
||||
constructor(code: ErrorCode, message: string, details?: Record<string, unknown>) {
|
||||
super(message)
|
||||
this.name = 'D3ROError'
|
||||
this.code = code
|
||||
this.details = details
|
||||
}
|
||||
|
||||
toJSON(): D3ROErrorJSON {
|
||||
return {
|
||||
code: this.code,
|
||||
message: this.message,
|
||||
details: this.details
|
||||
}
|
||||
}
|
||||
|
||||
static fromJSON(json: D3ROErrorJSON): D3ROError {
|
||||
return new D3ROError(json.code, json.message, json.details)
|
||||
}
|
||||
}
|
||||
|
||||
export interface D3ROErrorJSON {
|
||||
code: ErrorCode
|
||||
message: string
|
||||
details?: Record<string, unknown>
|
||||
}
|
||||
|
||||
/**
|
||||
* IPC 핸들러에서 사용하는 표준 응답 래퍼.
|
||||
*/
|
||||
export type IPCResult<T> =
|
||||
| { success: true; data: T }
|
||||
| { success: false; error: D3ROErrorJSON }
|
||||
|
||||
export function ipcSuccess<T>(data: T): IPCResult<T> {
|
||||
return { success: true, data }
|
||||
}
|
||||
|
||||
export function ipcError<T>(
|
||||
code: ErrorCode,
|
||||
message: string,
|
||||
details?: Record<string, unknown>
|
||||
): IPCResult<T> {
|
||||
return { success: false, error: { code, message, details } }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue