(root: string)
| 2485 | * invisible, because notes are the only things we track per-file. |
| 2486 | */ |
| 2487 | export async function listFolders(root: string): Promise<FolderEntry[]> { |
| 2488 | const out: FolderEntry[] = [] |
| 2489 | for (const folder of FOLDERS) { |
| 2490 | const topAbs = await folderRoot(root, folder) |
| 2491 | const isPrimaryRoot = folder === 'inbox' && path.resolve(topAbs) === path.resolve(root) |
| 2492 | const topReal = await realpathOrResolve(topAbs) |
| 2493 | const ancestors = new Set<string>([topReal]) |
| 2494 | const walk = async (dirAbs: string, dirReal: string, subpath: string): Promise<void> => { |
| 2495 | let entries: Dirent[] |
| 2496 | try { |
| 2497 | entries = await fs.readdir(dirAbs, { withFileTypes: true }) |
| 2498 | } catch { |
| 2499 | return |
| 2500 | } |
| 2501 | for (const [index, e] of entries.entries()) { |
| 2502 | const full = path.join(dirAbs, e.name) |
| 2503 | const childReal = await resolveDirDescent(full, e, dirReal, ancestors) |
| 2504 | if (childReal === null) continue |
| 2505 | if (e.name.startsWith('.')) continue |
| 2506 | if (isPrimaryRoot && dirAbs === topAbs && shouldHidePrimaryRootEntry(e.name)) continue |
| 2507 | const nextSub = subpath ? `${subpath}/${e.name}` : e.name |
| 2508 | out.push({ folder, subpath: nextSub, siblingOrder: index, isSymlink: e.isSymbolicLink() }) |
| 2509 | // A `<Name>.base` database folder is listed (the renderer shows it as a |
| 2510 | // database), but we don't descend — its data.csv/schema.json internals |
| 2511 | // aren't folders, and its record-page notes are surfaced via listNotes. |
| 2512 | if (isFormDirName(e.name)) continue |
| 2513 | ancestors.add(childReal) |
| 2514 | await walk(full, childReal, nextSub) |
| 2515 | ancestors.delete(childReal) |
| 2516 | } |
| 2517 | } |
| 2518 | await walk(topAbs, topReal, '') |
| 2519 | } |
| 2520 | return out |
| 2521 | } |
| 2522 | |
| 2523 | export async function listNotes(root: string): Promise<NoteMeta[]> { |
| 2524 | const startedAt = performance.now() |
no test coverage detected