cb6b4c3731
Co-authored-by: Cursor <cursoragent@cursor.com>
62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
import { randomUUID } from 'crypto'
|
|
import type { TimelineEntry } from '../../../shared/timeline'
|
|
import type { SqliteDb } from '../types'
|
|
|
|
function mapRow(row: Record<string, unknown>): TimelineEntry {
|
|
return {
|
|
id: row.id as string,
|
|
kind: 'manual',
|
|
title: row.title as string,
|
|
storyTime: (row.story_time as string) ?? null,
|
|
sortOrder: row.sort_order as number,
|
|
notes: (row.notes as string) ?? ''
|
|
}
|
|
}
|
|
|
|
export class TimelineRepository {
|
|
constructor(private db: SqliteDb) {}
|
|
|
|
listManual(): TimelineEntry[] {
|
|
return (
|
|
this.db
|
|
.prepare('SELECT * FROM timeline_events ORDER BY sort_order ASC, created_at ASC')
|
|
.all() as Record<string, unknown>[]
|
|
).map(mapRow)
|
|
}
|
|
|
|
upsert(input: {
|
|
id?: string
|
|
title: string
|
|
storyTime?: string | null
|
|
sortOrder?: number
|
|
notes?: string
|
|
}): TimelineEntry {
|
|
const id = input.id ?? randomUUID()
|
|
const existing = this.db.prepare('SELECT id FROM timeline_events WHERE id = ?').get(id)
|
|
if (existing) {
|
|
this.db
|
|
.prepare(
|
|
`UPDATE timeline_events SET title = ?, story_time = ?, sort_order = ?, notes = ? WHERE id = ?`
|
|
)
|
|
.run(
|
|
input.title,
|
|
input.storyTime ?? null,
|
|
input.sortOrder ?? 0,
|
|
input.notes ?? '',
|
|
id
|
|
)
|
|
} else {
|
|
this.db
|
|
.prepare(
|
|
`INSERT INTO timeline_events (id, title, story_time, sort_order, notes) VALUES (?, ?, ?, ?, ?)`
|
|
)
|
|
.run(id, input.title, input.storyTime ?? null, input.sortOrder ?? 0, input.notes ?? '')
|
|
}
|
|
return mapRow(this.db.prepare('SELECT * FROM timeline_events WHERE id = ?').get(id) as Record<string, unknown>)
|
|
}
|
|
|
|
delete(id: string): void {
|
|
this.db.prepare('DELETE FROM timeline_events WHERE id = ?').run(id)
|
|
}
|
|
}
|