feat(V2-1a): Monorepo 구조 전환 — apps/desktop으로 V1 이동
- npm workspaces 루트 (apps/*, packages/*) 세팅 - V1 전체를 apps/desktop/으로 git mv (src, resources, tests, sidecar, scripts, electron.vite.config.ts, electron-builder.yml, vitest.config.ts, tsconfig.node.json, tsconfig.web.json) - apps/desktop/package.json 신규 (name=@d3ro/desktop) - productName: 'd3ro-voice' 명시 — app.getName()을 고정하여 userData 경로 %APPDATA%\d3ro-voice\ 그대로 유지 (기존 DB/설정 연속성 보장) - 루트 package.json을 workspace 루트로 재구성, 공통 devDep만 유지 (typescript, eslint, prettier) - turbo.json, tsconfig.base.json 추가 (Turborepo 자체 설치는 별도 sub-phase) - memory/project_status.md 생성 (규칙 13) 검증: - npm run typecheck 통과 - npm run build 통과 (electron-vite main+preload+renderer) - npm run dev 실제 실행 → DB/핫키/Ollama 자동 실행 모두 정상
This commit is contained in:
parent
3a160b9032
commit
45a580878a
178 changed files with 214 additions and 0 deletions
75
apps/desktop/tests/shared/errors.test.ts
Normal file
75
apps/desktop/tests/shared/errors.test.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
// tests/shared/errors.test.ts
|
||||
// D3ROError + IPCResult 헬퍼 테스트
|
||||
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { D3ROError, ErrorCode, ipcSuccess, ipcError } from '../../src/shared/errors'
|
||||
|
||||
describe('D3ROError', () => {
|
||||
it('code, message, details를 올바르게 설정한다', () => {
|
||||
const err = new D3ROError(ErrorCode.STTModelNotFound, 'Model not found', { modelId: 'large' })
|
||||
|
||||
expect(err.code).toBe(ErrorCode.STTModelNotFound)
|
||||
expect(err.message).toBe('Model not found')
|
||||
expect(err.details).toEqual({ modelId: 'large' })
|
||||
expect(err.name).toBe('D3ROError')
|
||||
expect(err instanceof Error).toBe(true)
|
||||
})
|
||||
|
||||
it('toJSON으로 직렬화할 수 있다', () => {
|
||||
const err = new D3ROError(ErrorCode.LLMServerUnreachable, 'Server down')
|
||||
const json = err.toJSON()
|
||||
|
||||
expect(json.code).toBe(300)
|
||||
expect(json.message).toBe('Server down')
|
||||
expect(json.details).toBeUndefined()
|
||||
})
|
||||
|
||||
it('fromJSON으로 역직렬화할 수 있다', () => {
|
||||
const json = { code: ErrorCode.AudioDeviceNotFound, message: 'No mic' }
|
||||
const err = D3ROError.fromJSON(json)
|
||||
|
||||
expect(err).toBeInstanceOf(D3ROError)
|
||||
expect(err.code).toBe(ErrorCode.AudioDeviceNotFound)
|
||||
expect(err.message).toBe('No mic')
|
||||
})
|
||||
})
|
||||
|
||||
describe('IPCResult helpers', () => {
|
||||
it('ipcSuccess는 success: true + data를 반환한다', () => {
|
||||
const result = ipcSuccess({ value: 42 })
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
if (result.success) {
|
||||
expect(result.data).toEqual({ value: 42 })
|
||||
}
|
||||
})
|
||||
|
||||
it('ipcError는 success: false + error를 반환한다', () => {
|
||||
const result = ipcError(ErrorCode.DBQueryFailed, 'Query failed', { table: 'history' })
|
||||
|
||||
expect(result.success).toBe(false)
|
||||
if (!result.success) {
|
||||
expect(result.error.code).toBe(ErrorCode.DBQueryFailed)
|
||||
expect(result.error.message).toBe('Query failed')
|
||||
expect(result.error.details).toEqual({ table: 'history' })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('ErrorCode', () => {
|
||||
it('에러 코드 범위가 올바르다', () => {
|
||||
// STT: 100-199
|
||||
expect(ErrorCode.STTEngineNotInstalled).toBe(100)
|
||||
expect(ErrorCode.STTGPUNotAvailable).toBe(140)
|
||||
|
||||
// LLM: 300-399
|
||||
expect(ErrorCode.LLMServerUnreachable).toBe(300)
|
||||
expect(ErrorCode.LLMPromptTooLong).toBe(331)
|
||||
|
||||
// Audio: 400-499
|
||||
expect(ErrorCode.AudioDeviceNotFound).toBe(400)
|
||||
|
||||
// System: 900-999
|
||||
expect(ErrorCode.UnknownError).toBe(999)
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue