From 983306e00416d093f7f189a070ffc869b1c34f9d Mon Sep 17 00:00:00 2001 From: altair823 Date: Tue, 5 May 2026 01:33:30 +0900 Subject: [PATCH] =?UTF-8?q?refactor(v026):=20#22=20NoteRepository=20hydrat?= =?UTF-8?q?e=20row=20type=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit db.prepare().all() 의 row type cast s any[] / s unknown[] → s Record[] 일괄 통일. hydrate() signature 도 동일 (이미 그렇거나 갱신). - TS strict 환경 친화 (any 보다 narrow) - 향후 explicit row interface 추가 시 base 형 명확 - runtime 동작 변경 0 Co-Authored-By: Claude Opus 4.7 (1M context) --- src/main/repository/NoteRepository.ts | 64 +++++++++++++-------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/main/repository/NoteRepository.ts b/src/main/repository/NoteRepository.ts index 291c4eb..3d47050 100644 --- a/src/main/repository/NoteRepository.ts +++ b/src/main/repository/NoteRepository.ts @@ -78,7 +78,7 @@ export class NoteRepository { } findById(id: string): Note | null { - const row = this.db.prepare('SELECT * FROM notes WHERE id=?').get(id) as any; + const row = this.db.prepare('SELECT * FROM notes WHERE id=?').get(id) as Record; if (!row) return null; return this.hydrate(row); } @@ -92,21 +92,21 @@ export class NoteRepository { WHERE deleted_at IS NULL AND created_at < ? ORDER BY created_at DESC, id DESC LIMIT ?` ) - .all(opts.cursor, limit) as any[]) + .all(opts.cursor, limit) as Record[]) : (this.db .prepare( `SELECT * FROM notes WHERE deleted_at IS NULL ORDER BY created_at DESC, id DESC LIMIT ?` ) - .all(limit) as any[]); + .all(limit) as Record[]); return rows.map((r) => this.hydrate(r)); } listAll(): Note[] { const rows = this.db .prepare(`SELECT * FROM notes WHERE deleted_at IS NULL ORDER BY created_at ASC, id ASC`) - .all() as any[]; + .all() as Record[]; return rows.map((r) => this.hydrate(r)); } @@ -453,7 +453,7 @@ export class NoteRepository { const limit = Math.max(1, Math.min(200, opts.limit)); const rows = this.db .prepare(`SELECT * FROM notes WHERE deleted_at IS NOT NULL ORDER BY deleted_at DESC, id DESC LIMIT ?`) - .all(limit) as any[]; + .all(limit) as Record[]; return rows.map((r) => this.hydrate(r)); } @@ -611,18 +611,18 @@ export class NoteRepository { AND ai_status = 'done' ORDER BY created_at DESC, id DESC` ) - .all(today) as any[]; + .all(today) as Record[]; return rows.map((r) => this.hydrate(r)); } getAllPendingJobs(): Array<{ noteId: string; attempts: number; nextRunAt: string }> { const rows = this.db .prepare(`SELECT note_id, attempts, next_run_at FROM pending_jobs`) - .all() as any[]; + .all() as Record[]; return rows.map((r) => ({ - noteId: r.note_id, - attempts: r.attempts, - nextRunAt: r.next_run_at + noteId: r.note_id as string, + attempts: r.attempts as number, + nextRunAt: r.next_run_at as string })); } @@ -638,39 +638,39 @@ export class NoteRepository { .run(nextRunAt, lastError.slice(0, 500), noteId); } - private hydrate(row: any): Note { + private hydrate(row: Record): Note { const tags = this.db .prepare( `SELECT t.name, nt.source FROM note_tags nt JOIN tags t ON t.id = nt.tag_id WHERE nt.note_id = ? ORDER BY t.name` ) - .all(row.id) as Array<{ name: string; source: 'ai' | 'user' }>; + .all(row.id as string) as Array<{ name: string; source: 'ai' | 'user' }>; const media = this.db .prepare( `SELECT id, kind, rel_path as relPath, mime, bytes FROM media WHERE note_id=?` ) - .all(row.id) as NoteMedia[]; + .all(row.id as string) as NoteMedia[]; return { - id: row.id, - rawText: row.raw_text, - aiTitle: row.ai_title, - aiSummary: row.ai_summary, - aiStatus: row.ai_status, - aiError: row.ai_error, - aiProvider: row.ai_provider, - aiGeneratedAt: row.ai_generated_at, - titleEditedByUser: row.title_edited_by_user === 1, - summaryEditedByUser: row.summary_edited_by_user === 1, - userIntent: row.user_intent, - intentPromptedAt: row.intent_prompted_at, - dueDate: row.due_date ?? null, - dueDateEditedByUser: row.due_date_edited_by_user === 1, - deletedAt: row.deleted_at ?? null, - lastRecalledAt: row.last_recalled_at ?? null, - recallDismissedAt: row.recall_dismissed_at ?? null, - createdAt: row.created_at, - updatedAt: row.updated_at, + id: row.id as string, + rawText: row.raw_text as string, + aiTitle: row.ai_title as string | null, + aiSummary: row.ai_summary as string | null, + aiStatus: row.ai_status as 'pending' | 'done' | 'failed', + aiError: row.ai_error as string | null, + aiProvider: row.ai_provider as string | null, + aiGeneratedAt: row.ai_generated_at as string | null, + titleEditedByUser: (row.title_edited_by_user as number) === 1, + summaryEditedByUser: (row.summary_edited_by_user as number) === 1, + userIntent: row.user_intent as string | null, + intentPromptedAt: row.intent_prompted_at as string | null, + dueDate: (row.due_date as string | null) ?? null, + dueDateEditedByUser: (row.due_date_edited_by_user as number) === 1, + deletedAt: (row.deleted_at as string | null) ?? null, + lastRecalledAt: (row.last_recalled_at as string | null) ?? null, + recallDismissedAt: (row.recall_dismissed_at as string | null) ?? null, + createdAt: row.created_at as string, + updatedAt: row.updated_at as string, tags: tags as NoteTag[], media };