sync-notes.ts
1 /** 2 * Generate notes index from local notes directory. 3 * 4 * Scans ~/Development/personal/notes, filters notes tagged `public`, 5 * and writes a notes-index.json (array of relative paths) locally. 6 * 7 * Usage: bun scripts/sync-notes.ts 8 */ 9 10 import { readFile, writeFile } from "node:fs/promises"; 11 import { join, relative, sep } from "node:path"; 12 import { glob } from "glob"; 13 import matter from "gray-matter"; 14 15 const NOTES_DIR = join( 16 process.env.HOME ?? "", 17 "Development", 18 "personal", 19 "notes", 20 ); 21 22 const OUTPUT_PATH = join(process.cwd(), "notes-index.json"); 23 24 const PATTERNS = [ 25 "Articles/**/*.md", 26 "Vault/**/*.md", 27 "Music/*.md", 28 "People/*.md", 29 ]; 30 31 const EXCLUDE_PATTERNS = ["**/Archive/**", "**/Daily/**", "**/Inbox/**"]; 32 33 async function getPublicNotePaths(): Promise<string[]> { 34 const allFiles: string[] = []; 35 36 for (const pattern of PATTERNS) { 37 const files = await glob(pattern, { 38 cwd: NOTES_DIR, 39 absolute: true, 40 ignore: EXCLUDE_PATTERNS, 41 }); 42 allFiles.push(...files); 43 } 44 45 const publicPaths: string[] = []; 46 47 await Promise.all( 48 allFiles.map(async (filePath) => { 49 const content = await readFile(filePath, "utf-8"); 50 const { data } = matter(content); 51 const tags: string[] = data.tags ?? []; 52 if (tags.includes("public")) { 53 const rel = relative(NOTES_DIR, filePath).split(sep).join("/"); 54 publicPaths.push(rel); 55 } 56 }), 57 ); 58 59 return publicPaths.sort(); 60 } 61 62 async function writeIndexFile(paths: string[]) { 63 const content = JSON.stringify(paths, null, 2); 64 await writeFile(OUTPUT_PATH, content, "utf-8"); 65 } 66 67 async function main() { 68 console.log(`Scanning notes from: ${NOTES_DIR}`); 69 const paths = await getPublicNotePaths(); 70 console.log(`Found ${paths.length} public notes`); 71 console.log(`Writing index to ${OUTPUT_PATH}...`); 72 await writeIndexFile(paths); 73 console.log("Done ✓"); 74 } 75 76 main().catch((err) => { 77 console.error(err); 78 process.exit(1); 79 });