diff --git a/modules/io/obsidian-bridge.js b/modules/io/obsidian-bridge.js index bc02cc0e..d81b5598 100644 --- a/modules/io/obsidian-bridge.js +++ b/modules/io/obsidian-bridge.js @@ -61,6 +61,39 @@ const ObsidianBridge = (() => { } } + // Recursively scan a directory and all subdirectories for .md files + async function scanDirectory(path = "") { + const response = await fetch(`${config.apiUrl}/vault/${encodeURIComponent(path)}`, { + headers: { + Authorization: `Bearer ${config.apiKey}` + } + }); + + if (!response.ok) { + throw new Error(`Failed to fetch directory ${path}: ${response.status}`); + } + + const data = await response.json(); + const entries = data.files || []; + const mdFiles = []; + + for (const entry of entries) { + const fullPath = path ? `${path}${entry}` : entry; + + if (entry.endsWith("/")) { + // It's a directory - recurse into it + DEBUG && console.log(`Scanning directory: ${fullPath}`); + const subFiles = await scanDirectory(fullPath); + mdFiles.push(...subFiles); + } else if (entry.endsWith(".md")) { + // It's a markdown file - add it + mdFiles.push(fullPath); + } + } + + return mdFiles; + } + // Get all markdown files from vault (recursively) async function getVaultFiles() { if (!config.enabled) { @@ -68,62 +101,20 @@ const ObsidianBridge = (() => { } try { - // Try using the search endpoint to get all .md files recursively - // The /search/ endpoint with an empty query or wildcard should return all files - const searchResponse = await fetch(`${config.apiUrl}/search/?query=.md`, { - headers: { - Authorization: `Bearer ${config.apiKey}` - } - }); + TIME && console.time("getVaultFiles"); - if (searchResponse.ok) { - const searchData = await searchResponse.json(); - INFO && console.log("Using search endpoint, found:", searchData); + // Recursively scan all directories + const mdFiles = await scanDirectory(""); - // Extract file paths from search results - // The format might be different, check what we get - const files = searchData.files || searchData.results || searchData; - - if (Array.isArray(files)) { - const mdFiles = files - .filter(f => { - const path = typeof f === 'string' ? f : f.path || f.filename; - return path && path.endsWith(".md"); - }) - .map(f => typeof f === 'string' ? f : f.path || f.filename); - - INFO && console.log(`getVaultFiles (search): Found ${mdFiles.length} markdown files`); - DEBUG && console.log("Sample files:", mdFiles.slice(0, 10)); - - return mdFiles; - } - } - - // Fallback to /vault/ endpoint if search doesn't work - INFO && console.log("Search endpoint failed, falling back to /vault/"); - const response = await fetch(`${config.apiUrl}/vault/`, { - headers: { - Authorization: `Bearer ${config.apiKey}` - } - }); - - if (!response.ok) { - throw new Error(`Failed to fetch vault files: ${response.status}`); - } - - const data = await response.json(); - const files = data.files || []; - - // Filter to only .md files - const mdFiles = files.filter(f => f.endsWith(".md")); - - INFO && console.log(`getVaultFiles (vault): Found ${files.length} total files, ${mdFiles.length} markdown files`); + INFO && console.log(`getVaultFiles: Found ${mdFiles.length} markdown files (recursive scan)`); DEBUG && console.log("Sample files:", mdFiles.slice(0, 10)); - WARN && console.warn("Note: /vault/ endpoint may only return root-level files. Nested folders may not be visible."); + + TIME && console.timeEnd("getVaultFiles"); return mdFiles; } catch (error) { ERROR && console.error("Failed to get vault files:", error); + TIME && console.timeEnd("getVaultFiles"); throw error; } }