()
| 739 | return dbInitPromise; |
| 740 | } |
| 741 | export async function initLocalDatabase(): Promise<void> { |
| 742 | if (localDbInitialized) return; |
| 743 | if (localDbInitPromise) return localDbInitPromise; |
| 744 | |
| 745 | localDbInitPromise = (async () => { |
| 746 | await runSerializedDbTask(async () => { |
| 747 | if (localDbInitialized) return; |
| 748 | |
| 749 | const database = await getLocalDB(); |
| 750 | |
| 751 | await database.execute(` |
| 752 | CREATE TABLE IF NOT EXISTS chunks ( |
| 753 | id TEXT PRIMARY KEY, |
| 754 | book_id TEXT NOT NULL, |
| 755 | chapter_index INTEGER NOT NULL, |
| 756 | chapter_title TEXT NOT NULL DEFAULT '', |
| 757 | content TEXT NOT NULL, |
| 758 | token_count INTEGER NOT NULL DEFAULT 0, |
| 759 | start_cfi TEXT, |
| 760 | end_cfi TEXT, |
| 761 | segment_cfis TEXT, |
| 762 | embedding BLOB, |
| 763 | updated_at INTEGER NOT NULL DEFAULT 0 |
| 764 | ) |
| 765 | `); |
| 766 | |
| 767 | try { |
| 768 | await database.execute( |
| 769 | "ALTER TABLE chunks ADD COLUMN updated_at INTEGER NOT NULL DEFAULT 0", |
| 770 | ); |
| 771 | } catch { |
| 772 | // Column already exists on upgraded installs. |
| 773 | } |
| 774 | |
| 775 | // Create indexes |
| 776 | await database.execute("CREATE INDEX IF NOT EXISTS idx_chunks_book ON chunks(book_id)"); |
| 777 | |
| 778 | localDbInitialized = true; |
| 779 | |
| 780 | // Migrate data from main DB to local DB on first run |
| 781 | await migrateDataToLocalDB(); |
| 782 | }); |
| 783 | })().finally(() => { |
| 784 | localDbInitPromise = null; |
| 785 | }); |
| 786 | |
| 787 | return localDbInitPromise; |
| 788 | } |
| 789 | |
| 790 | /** Migrate chunks from main DB to local DB (one-time) */ |
| 791 | async function migrateDataToLocalDB(): Promise<void> { |
no test coverage detected