fix(dictionary): let an edit clear the pronunciation and report duplicate renames
This commit is contained in:
parent
9d5d043e8b
commit
de1e8a82a4
6 changed files with 350 additions and 24 deletions
|
|
@ -12,6 +12,12 @@ import { getLogger } from './LoggerService'
|
|||
import { getCloudSyncService } from './CloudSyncService'
|
||||
import { getMainWindow } from '../windows/WindowManager'
|
||||
import { D3ROError, ErrorCode } from '@d3ro/core/errors'
|
||||
import {
|
||||
buildDictionaryUpdatePatch,
|
||||
isUniqueConstraintViolation,
|
||||
normalizeDictionaryPronunciation,
|
||||
normalizeDictionaryWord
|
||||
} from '@d3ro/core/dictionary-policy'
|
||||
import type {
|
||||
DictionaryEntry,
|
||||
DictionaryQueryParams,
|
||||
|
|
@ -114,7 +120,7 @@ function normalizeCategory(value: string | null): DictionaryEntry['category'] {
|
|||
|
||||
class DictionaryService {
|
||||
add(params: DictionaryAddParams): DictionaryEntry {
|
||||
const word = params.word.trim()
|
||||
const word = normalizeDictionaryWord(params.word)
|
||||
if (!word) {
|
||||
throw new D3ROError(ErrorCode.DictionaryImportInvalidFormat, 'Dictionary word is empty')
|
||||
}
|
||||
|
|
@ -126,7 +132,7 @@ class DictionaryService {
|
|||
const entry: NewDictionary = {
|
||||
id,
|
||||
word,
|
||||
pronunciation: params.pronunciation ?? null,
|
||||
pronunciation: normalizeDictionaryPronunciation(params.pronunciation) ?? null,
|
||||
category: params.category ?? 'user',
|
||||
usageCount: 0,
|
||||
lastUsedAt: null,
|
||||
|
|
@ -137,8 +143,7 @@ class DictionaryService {
|
|||
try {
|
||||
db.insert(dictionary).values(entry).run()
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err)
|
||||
if (message.includes('UNIQUE') || message.includes('unique')) {
|
||||
if (isUniqueConstraintViolation(err)) {
|
||||
throw new D3ROError(ErrorCode.DictionaryDuplicate, `Duplicate word: ${word}`)
|
||||
}
|
||||
throw err
|
||||
|
|
@ -150,16 +155,27 @@ class DictionaryService {
|
|||
}
|
||||
|
||||
update(params: DictionaryUpdateParams): DictionaryEntry | null {
|
||||
const result = buildDictionaryUpdatePatch(params)
|
||||
if (!result.ok) {
|
||||
throw new D3ROError(ErrorCode.DictionaryImportInvalidFormat, 'Dictionary word is empty')
|
||||
}
|
||||
|
||||
const db = getDatabase()
|
||||
const existing = db.select().from(dictionary).where(eq(dictionary.id, params.id)).get()
|
||||
if (!existing) return null
|
||||
|
||||
const updates: Partial<NewDictionary> = { updatedAt: Date.now() }
|
||||
if (params.word !== undefined) updates.word = params.word
|
||||
if (params.pronunciation !== undefined) updates.pronunciation = params.pronunciation
|
||||
if (params.category !== undefined) updates.category = params.category
|
||||
|
||||
db.update(dictionary).set(updates).where(eq(dictionary.id, params.id)).run()
|
||||
const updates: Partial<NewDictionary> = { ...result.patch, updatedAt: Date.now() }
|
||||
try {
|
||||
db.update(dictionary).set(updates).where(eq(dictionary.id, params.id)).run()
|
||||
} catch (err) {
|
||||
if (isUniqueConstraintViolation(err)) {
|
||||
throw new D3ROError(
|
||||
ErrorCode.DictionaryDuplicate,
|
||||
`Duplicate word: ${result.patch.word ?? existing.word}`
|
||||
)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
|
||||
const updated = db.select().from(dictionary).where(eq(dictionary.id, params.id)).get()
|
||||
// Phase 3.3: 자동 push (fire-and-forget)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue