SPB Git

spb/drive Public

SPB Drive — self-hosted personal cloud drive (files, previews, sharing) on the MacLustr cluster.

JavaScript 82.7% CSS 10.6% Nunjucks 3.6% Shell 1.8% SQL 1.3%
2.6 KB · 63 lines javascript
Raw Blame History
1/**2 * ─────────────────────────────────────────────3 *  SPB Drive — Personal Cloud Drive4 * ─────────────────────────────────────────────5 *  Author  : Simon-Pierre Boucher6 *  Contact : contact@spboucher.ai7 *  File    : src/search/index-sync.mjs8 *  Purpose : Keep the FTS5 index in sync with node names/tags/content9 *  License : MIT © Simon-Pierre Boucher10 * ─────────────────────────────────────────────11 */1213import { getDb } from '../db/db.mjs';1415/** Current tag names for a node, space-joined for the FTS tags column. */16function tagsText(nodeId) {17  return getDb()18    .prepare(19      `SELECT GROUP_CONCAT(t.name, ' ') AS tags FROM node_tags nt20       JOIN tags t ON t.id = nt.tag_id WHERE nt.node_id = ?`,21    )22    .get(nodeId)?.tags ?? '';23}2425/** Insert or refresh the FTS row for a node's name (keeps existing content). */26export function upsertFtsName(nodeId, name) {27  const db = getDb();28  const existing = db.prepare('SELECT content FROM fts WHERE rowid = ?').get(nodeId);29  db.prepare('DELETE FROM fts WHERE rowid = ?').run(nodeId);30  db.prepare('INSERT INTO fts (rowid, name, tags, content) VALUES (?, ?, ?, ?)').run(31    nodeId, name, tagsText(nodeId), existing?.content ?? '',32  );33}3435/** Refresh only the tags column for a node. */36export function updateFtsTags(nodeId) {37  const db = getDb();38  const node = db.prepare('SELECT name FROM nodes WHERE id = ?').get(nodeId);39  if (node) upsertFtsName(nodeId, node.name);40}4142/** Store extracted text content for a node (search-inside-files). */43export function setFtsContent(nodeId, content, contentSha) {44  const db = getDb();45  const node = db.prepare('SELECT name FROM nodes WHERE id = ?').get(nodeId);46  if (!node) return;47  db.prepare('DELETE FROM fts WHERE rowid = ?').run(nodeId);48  db.prepare('INSERT INTO fts (rowid, name, tags, content) VALUES (?, ?, ?, ?)').run(49    nodeId, node.name, tagsText(nodeId), (content ?? '').slice(0, 1_000_000),50  );51  db.prepare(52    `INSERT INTO fts_state (node_id, content_sha) VALUES (?, ?)53     ON CONFLICT(node_id) DO UPDATE SET content_sha = excluded.content_sha`,54  ).run(nodeId, contentSha ?? null);55}5657/** Remove a node from the index entirely. */58export function deleteFtsEntry(nodeId) {59  const db = getDb();60  db.prepare('DELETE FROM fts WHERE rowid = ?').run(nodeId);61  db.prepare('DELETE FROM fts_state WHERE node_id = ?').run(nodeId);62}63