Skip to content

feat(plugins): add absolutePath to onFileSystemChange - #67

Open
shpaw415 wants to merge 1 commit into
mainfrom
feat/onfilesystemchange-absolute-path
Open

shpaw415 wants to merge 1 commit into
mainfrom
feat/onfilesystemchange-absolute-path

Conversation

@shpaw415

Copy link
Copy Markdown
Owner

Summary

onFileSystemChange now exposes a real OS absolute path without breaking existing plugins.

The third argument was named absolutePath / used as abs, but it was the path from the project root (cwd). That mismatch made ignore checks, HMR path mapping, and startsWith("src/") filters easy to get wrong — especially when fileSystemWatchDir was absolute vs relative.

New callback shape

onFileSystemChange(eventType, filePath, projectRootPath, absolutePath)
Arg Meaning
filePath Filename relative to the watched directory (unchanged)
projectRootPath Path from process.cwd(), posix-separated (was the 3rd arg)
absolutePath New. path.resolve(...) OS absolute path

Backward compatible: extra trailing argument. Existing 3-arg plugins still typecheck and still receive the project-root path in position 3.

DX / fail-safes

  • resolveFileChangePaths() never throws: skips null/empty/"."/".." filenames; posix-normalizes projectRootPath so startsWith("src/") works on Windows; files outside cwd become ../… instead of crashing.
  • File watches no longer join(file, filename) into a bogus nested path.
  • Watch root is resolved once so ignore/debounce do not mix relative and absolute bases.
  • dispatchFileChangeCallbacks() uses Promise.allSettled so one plugin throw (sync or async) cannot skip later plugins or leave an unhandled rejection.

Plugin DX

Plugin authors can keep 3-arg handlers:

onFileSystemChange(event, file, projectRootPath) { /* still works */ }

or opt into the OS path when they need Bun.file, existsSync, or apply-react-style resolve(cwd, path) without guessing:

onFileSystemChange(event, file, projectRootPath, absolutePath) {
  if (!projectRootPath.startsWith("src/")) return;
  await Bun.file(absolutePath).text();
}

Docs, README, debug watcher-change messages, and the docs-app dev plugin were updated to the new names.

Tests

  • test/watch-paths.test.ts — relative/.//trailing slash, absolute inside/outside cwd, posix separators, [id].tsx/spaces/unicode, skip invalid filenames, 3-arg assignability, file-watch fallback
  • test/watch-dispatch.test.ts — 4-arg delivery, 3-arg BC, sync throw and async reject isolation
  • test/watch.test.ts — nested file args, 3-arg live callback, throw-then-continue, ignore, debounce, stop()

bun test 301 pass; bun run typecheck pass.

Out of scope

frame-master-plugin-apply-react still works (resolve(cwd, 3rd)). It can switch to the 4th arg in a follow-up.

Rename the third callback argument to projectRootPath and append a
real OS absolutePath. Existing 3-arg plugins stay compatible. Isolate
per-plugin watcher errors so one throw cannot skip the rest.
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2be38317-019b-453f-b6ca-3cef2b12a171


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying frame-master-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: a890f28
Status:🚫  Build failed.

View logs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant