refactor(utils): extract describeError + ENOENT fs helpers into src/utils#171
Conversation
…tils The third and final slice of the parser/IO restructure (after #168, #169). Hoists two generic, domain-free helpers — repeated across the codebase — into the existing utils/ leaf. - utils/describe-error.ts: describeError(error) — the `instanceof Error ? .message : String(...)` idiom that appeared inline 12x across 8 files (and as a private helper in note-mover). All collapse onto it. - utils/fs.ts: readFileOrNull / readdirOrNull / fileExists — the ENOENT-to- null/false fs wrappers, previously private in vault-filesystem and note-mover. memory-store's readMemoryFileOrNull now delegates to readFileOrNull. No behavior change. New unit tests for both modules (incl. the non-ENOENT rethrow contract). 927 tests, build + lint green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Qodo found 1 finding(s) but none met the |
|
✅ Action performedReview finished.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (14)
📝 WalkthroughWalkthroughIntroduces two new shared utility modules — ChangesShared Utility Extraction and Consumer Migration
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…ort conventions (#172) ## What Capstone to the parser/IO restructure (#168, #169, #171). Adds a **Module layering** section to `AGENTS.md` so the structure those PRs built is durable and enforceable — recorded as rules, not just implied by the file tree. Also lands the structure-polish follow-ups (folder rename + boundary clarifications) agreed during review. It documents: - **What each folder is for** (`obsidian-markdown/` · `vault-operations/` · `mcp-core/` · `search/` · `oauth/` · `utils/`), and that a module's folder follows **what it depends on**, not just its topic. - **Dependency direction** — `obsidian-markdown/` and `utils/` are leaves; `vault-operations/` and `search/` build on them; `mcp-core/` and the wiring depend on everything — plus the "top level is wiring only" rule. - **The `vault-filesystem.ts` ↔ `utils/fs.ts` boundary** — **policy vs. adapter**: `utils/fs.ts` holds only policy-free `node:fs` wrappers, while the atomic-write strategy, path-safety, and the `vaultFs` data API stay in `vault-filesystem.ts`. "Mechanically generic" isn't enough to demote load-bearing vault-I/O policy. - **`utils/` admission** — generic with zero domain knowledge, clearing one of two bars: it consolidates real duplication (multi-consumer), or it is a self-contained, general-purpose primitive (`mapWithConcurrency`). - **Export style by module kind** — service/data-layer modules export a single namespace object (or a factory-closure when stateful: `createSearchIndex`/`createMemoryStore`); pure parsers/helpers use named exports; `links.ts` is the deliberate namespace exception (its `/g` `lastIndex` footgun). ### Structure polish (also in this PR) - Renamed `vault-mcp/auth/` → `vault-mcp/oauth/` so it no longer collides conceptually with the top-level `src/auth.ts` token utilities. Docs + a folder rename — no behavior change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
What
The third and final slice of the parser/IO restructure (after #168 and #169). Hoists two generic, domain-free helpers — each repeated across the codebase — into the existing
src/utils/leaf.utils/describe-error.tsdescribeError(error)— theerror instanceof Error ? error.message : String(error)idiom, which appeared inline 12× across 8 files (and as a private helper innote-mover). Every site now imports the one implementation.utils/fs.tsreadFileOrNull/readdirOrNull/fileExists— the ENOENT‑to‑null/falsefilesystem wrappers, previously private invault-filesystem(readFileOrNull,readdirOrNull) andnote-mover(fileExists).memory-store'sreadMemoryFileOrNullnow delegates toreadFileOrNulltoo, retiring another hand‑rolled ENOENT check.These clear the bar for
utils/: generic, zero domain knowledge, multi‑consumer. (isString/isDatewere deliberately left out — low value — per the plan.)Scope
No behavior change — pure extraction + call‑site rewiring. The only remaining
instanceof Errorinsrc/is the canonical one insidedescribe-error.ts.Tests
utils/__tests__/describe-error.test.tsandutils/__tests__/fs.test.ts, including the non‑ENOENT rethrow contract (reading a directory as a file must propagateEISDIR, not be masked as "missing").Verification
npm run build(tsc, server + cli) ✅npm test— 927 passed ✅npm run lint✅🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Tests