From ace6867259bc5811e1c3c97038fc286c8901e77f Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Nov 2025 06:35:25 +0000 Subject: [PATCH] feat(obsidian): build complete FMG ID index on startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: With hundreds/thousands of burgs and markers, building the FMG ID index one-by-one as you click each element is too slow. Users need instant lookups at scale. Solution: Build the complete index upfront on startup by reading ALL notes' frontmatter during the pre-warm phase. How it works: 1. On startup/connection test: Pre-warm cache runs 2. After scanning file list: buildCompleteIndex() runs 3. Reads frontmatter from ALL 13k+ files 4. Extracts fmg-id from each note 5. Builds complete fmg-id → path mapping 6. Saves to localStorage Benefits: - Day 1: All burgs/markers with notes have instant lookups - No gradual index building needed - Scales to thousands of elements - Index persists across page reloads Performance: - Initial build: One-time cost on startup (background, non-blocking) - All subsequent clicks: Instant O(1) lookup - Manual rebuild: ObsidianBridge.buildCompleteIndex() Console output shows: 'Complete FMG ID index built: X notes indexed, Y skipped' --- modules/io/obsidian-bridge.js | 44 ++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/modules/io/obsidian-bridge.js b/modules/io/obsidian-bridge.js index 6ed7c13d..f7f5ae45 100644 --- a/modules/io/obsidian-bridge.js +++ b/modules/io/obsidian-bridge.js @@ -99,12 +99,53 @@ const ObsidianBridge = (() => { INFO && console.log("Pre-warming vault file cache..."); await getVaultFiles(); INFO && console.log("Vault file cache pre-warmed successfully!"); + + // Also build the complete FMG ID index + await buildCompleteIndex(); } catch (error) { WARN && console.warn("Failed to pre-warm cache:", error); // Don't throw - this is just optimization } } + // Build complete index of all fmg-ids in the vault + async function buildCompleteIndex() { + try { + INFO && console.log("Building complete FMG ID index..."); + TIME && console.time("buildCompleteIndex"); + + const files = vaultFilesCache.files || await getVaultFiles(); + let indexed = 0; + let skipped = 0; + + for (const filePath of files) { + try { + const content = await getNote(filePath); + const {frontmatter} = parseFrontmatter(content); + + const fmgId = frontmatter["fmg-id"] || frontmatter.fmgId; + if (fmgId) { + fmgIdIndex[fmgId] = filePath; + indexed++; + } else { + skipped++; + } + } catch (error) { + DEBUG && console.debug(`Skipping file ${filePath}:`, error); + skipped++; + } + } + + // Save the complete index + saveFmgIdIndex(); + + TIME && console.timeEnd("buildCompleteIndex"); + INFO && console.log(`Complete FMG ID index built: ${indexed} notes indexed, ${skipped} skipped`); + } catch (error) { + ERROR && console.error("Failed to build complete index:", error); + } + } + // Recursively scan a directory and all subdirectories for .md files async function scanDirectory(path = "") { const response = await fetch(`${config.apiUrl}/vault/${encodeURIComponent(path)}`, { @@ -660,7 +701,8 @@ Add your lore here... listAllNotes, listAllNotePaths, addToFmgIdIndex, - getFromFmgIdIndex + getFromFmgIdIndex, + buildCompleteIndex }; })();