UNPKG

@masuidrive/bloom-local-rag

Version:

RAG (Retrieval-Augmented Generation) system for local directories - Index and search your documents with AI-powered answers

87 lines 3.02 kB
import { readFile, stat } from 'fs/promises'; import { join, relative, extname } from 'path'; import { glob } from 'glob'; import ignore from 'ignore'; import matter from 'gray-matter'; import yaml from 'js-yaml'; import createXXHash from 'xxhash-wasm'; import { DEFAULT_EXCLUDE_PATTERNS } from './constants.js'; import { createGitignoreChecker } from './gitignore.js'; let xxhash = null; async function getHasher() { if (!xxhash) { xxhash = await createXXHash(); } return xxhash; } export async function hashFile(content) { const hasher = await getHasher(); return hasher.h64(content).toString(16); } // Re-export from gitignore.ts for backward compatibility export { loadGitignore } from './gitignore.js'; export async function scanFiles(directory, extensions, excludePatterns = []) { const ig = ignore(); ig.add(DEFAULT_EXCLUDE_PATTERNS); ig.add(excludePatterns); // Create gitignore checker that respects hierarchy const isGitignored = await createGitignoreChecker(directory); const patterns = extensions.map(ext => `**/*${ext}`); const files = await glob(patterns, { cwd: directory, absolute: false, ignore: DEFAULT_EXCLUDE_PATTERNS.concat(excludePatterns), }); const fileInfos = []; for (const file of files) { const relativePath = relative(directory, join(directory, file)); if (ig.ignores(relativePath) || isGitignored(relativePath)) { continue; } try { const filePath = join(directory, file); const content = await readFile(filePath, 'utf-8'); const stats = await stat(filePath); const ext = extname(file); let metadata = { path: relativePath, modifiedAt: stats.mtime.getTime(), }; if (ext === '.md' || ext === '.mdx') { const { data, content: body } = matter(content); metadata = { ...metadata, ...data }; fileInfos.push({ path: relativePath, content: body, metadata, }); } else if (ext === '.yaml' || ext === '.yml') { try { const data = yaml.load(content); metadata = { ...metadata, ...data }; } catch { // If YAML parsing fails, treat as plain text } fileInfos.push({ path: relativePath, content, metadata, }); } else { fileInfos.push({ path: relativePath, content, metadata, }); } } catch (error) { console.error(`Error reading file ${file}:`, error); } } return fileInfos; } //# sourceMappingURL=fileScanner.js.map