feat(obsidian): build complete FMG ID index on startup

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'
This commit is contained in:
Claude 2025-11-14 06:35:25 +00:00
parent 69e69abb85
commit ace6867259
No known key found for this signature in database

View file

@ -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
};
})();