Files
bilin/src/main/services/fts-sync.service.ts
T
bing aac51bf183 feat: deliver P2 v0.2.0 with unified editor, search, and snapshots
Implement schema v2 migration, outline/setting/inspiration CRUD, unified TipTap editing, reference panel with mentions, FTS global search, chapter version history, writing landmarks, word frequency analysis, light theme contrast fixes, and full unit/E2E test coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-06 14:13:27 +08:00

69 lines
2.1 KiB
TypeScript

import type { SearchSourceKind } from '../../shared/types'
import { stripHtml } from './word-count'
import type { SqliteDb } from '../db/types'
export class FtsSyncService {
upsert(db: SqliteDb, kind: SearchSourceKind, id: string, title: string, body: string): void {
const plainBody = stripHtml(body)
db.prepare('DELETE FROM search_fts WHERE source_kind = ? AND source_id = ?').run(kind, id)
db.prepare(
'INSERT INTO search_fts (source_kind, source_id, title, body) VALUES (?, ?, ?, ?)'
).run(kind, id, title, plainBody)
}
remove(db: SqliteDb, kind: SearchSourceKind, id: string): void {
db.prepare('DELETE FROM search_fts WHERE source_kind = ? AND source_id = ?').run(kind, id)
}
rebuildAll(db: SqliteDb): void {
db.exec('DELETE FROM search_fts')
const chapters = db.prepare('SELECT id, title, content FROM chapters').all() as {
id: string
title: string
content: string
}[]
for (const ch of chapters) {
this.upsert(db, 'chapter', ch.id, ch.title, ch.content)
}
const outlines = db.prepare('SELECT id, title, description FROM outline_items').all() as {
id: string
title: string
description: string
}[]
for (const o of outlines) {
this.upsert(db, 'outline', o.id, o.title, o.description)
}
const settings = db.prepare('SELECT id, name, description FROM settings').all() as {
id: string
name: string
description: string
}[]
for (const s of settings) {
this.upsert(db, 'setting', s.id, s.name, s.description)
}
const inspirations = db.prepare('SELECT id, title, content FROM inspiration').all() as {
id: string
title: string
content: string
}[]
for (const i of inspirations) {
this.upsert(db, 'inspiration', i.id, i.title, i.content)
}
const bookmarks = db.prepare('SELECT id, label, chapter_id FROM bookmarks').all() as {
id: string
label: string
chapter_id: string
}[]
for (const b of bookmarks) {
this.upsert(db, 'bookmark', b.id, b.label, b.label)
}
}
}
export const ftsSync = new FtsSyncService()