refactor(v026): #22 NoteRepository hydrate row type 통일
db.prepare().all() 의 row type cast s any[] / s unknown[] → s Record<string, unknown>[] 일괄 통일. hydrate() signature 도 동일 (이미 그렇거나 갱신). - TS strict 환경 친화 (any 보다 narrow) - 향후 explicit row interface 추가 시 base 형 명확 - runtime 동작 변경 0 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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<string, unknown>;
|
||||
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<string, unknown>[])
|
||||
: (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<string, unknown>[]);
|
||||
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<string, unknown>[];
|
||||
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<string, unknown>[];
|
||||
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<string, unknown>[];
|
||||
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<string, unknown>[];
|
||||
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<string, unknown>): 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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user