@relayfile/local-mount 0.6.13 → 0.6.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,7 +29,7 @@ Behavior:
29
29
  - Copies regular files into the mount
30
30
  - Applies ignore rules from `ignoredPatterns`
31
31
  - Marks read-only matches as mode `0o444`
32
- - Excludes `.git` and `node_modules` by default. Pass `includeGit: true` to opt the project's `.git` directory back in (see [Including `.git`](#including-git))
32
+ - Excludes `.git`, `node_modules`, and `.npm-cache` by default. Pass `includeGit: true` to opt the project's `.git` directory back in (see [Including `.git`](#including-git))
33
33
  - Writes `_MOUNT_README.md` and `.relayfile-local-mount` into the mount
34
34
  - Skips syncing `_MOUNT_README.md`, `.relayfile-local-mount`, ignored files, read-only files, and symlinks back to the source project
35
35
 
@@ -2,6 +2,15 @@ export interface AutoSyncContext {
2
2
  realMountDir: string;
3
3
  realProjectDir: string;
4
4
  isExcluded: (relPosix: string) => boolean;
5
+ /**
6
+ * The exact set of normalized directory names/prefixes that drive
7
+ * `isExcluded` (i.e., {@link MountOptions.excludeDirs} merged with the
8
+ * library defaults). Used purely to hint `@parcel/watcher` which subtrees
9
+ * to skip subscribing to. The in-handler `isSyncCandidate` filter remains
10
+ * authoritative; this is just a perf hint that keeps the watcher from
11
+ * recursing into heavy trees like `node_modules` or `.npm-cache`.
12
+ */
13
+ excludedNames: readonly string[];
5
14
  /**
6
15
  * Directory-only ignore patterns (ending in `/`) must only match when the
7
16
  * path is a directory. Callers that know the path's type pass `isDirectory`;
package/dist/auto-sync.js CHANGED
@@ -80,7 +80,6 @@ export function startAutoSync(ctx, opts = {}) {
80
80
  }, debounceMs);
81
81
  pendingDebounces.set(absPath, t);
82
82
  };
83
- const ignoreGlobs = buildIgnoreGlobs(ctx);
84
83
  const subscribeTo = (root) => watcher.subscribe(root, (err, events) => {
85
84
  if (err) {
86
85
  onError(err);
@@ -89,7 +88,7 @@ export function startAutoSync(ctx, opts = {}) {
89
88
  for (const ev of events) {
90
89
  schedulePathSync(root, ev.path);
91
90
  }
92
- }, { ignore: ignoreGlobs });
91
+ }, { ignore: buildIgnoreGlobs(ctx, root) });
93
92
  let mountSub;
94
93
  let projectSub;
95
94
  // Subscribe in parallel but track each outcome independently. With
@@ -163,18 +162,29 @@ export function startAutoSync(ctx, opts = {}) {
163
162
  },
164
163
  };
165
164
  }
166
- function buildIgnoreGlobs(ctx) {
167
- // @parcel/watcher matches globs against absolute paths via globset. For each
168
- // excluded directory name, ignore both the directory itself and everything
169
- // beneath it, anywhere under the watched root. The `isExcluded` predicate is
170
- // driven by a Set of directory names, so we probe a small set of common
171
- // exclusions rather than introspecting it. The in-handler `isSyncCandidate`
172
- // filter is authoritative this is just a perf hint so the watcher doesn't
173
- // recurse into heavy trees like node_modules or .git.
165
+ function buildIgnoreGlobs(ctx, watchRoot) {
166
+ // @parcel/watcher's wrapper splits each ignore entry by is-glob: globs are
167
+ // compiled by picomatch and matched as regexes against absolute event paths;
168
+ // non-globs are resolved as literal absolute paths. For each excluded entry
169
+ // (library defaults + user-supplied excludeDirs) we emit shapes that mirror
170
+ // `isExcludedPath`'s semantics, so a watcher-suppressed event never differs
171
+ // from what the in-handler filter would have rejected.
172
+ //
173
+ // - Bare directory names (e.g. `node_modules`) match at any depth, so
174
+ // emit `**/<name>` plus `**/<name>/**`. picomatch turns both into
175
+ // depth-agnostic regexes that catch the dir and its descendants.
176
+ // - Path-style entries (e.g. `build/cache`) are root-anchored prefixes
177
+ // in `isExcludedPath` — they only match `<root>/build/cache`, NOT
178
+ // `<root>/src/build/cache`. Emit absolute patterns rooted at the
179
+ // watch dir so the watcher hides the same set: a literal absolute
180
+ // path (which the wrapper routes to ignorePaths) plus an anchored
181
+ // descendant glob.
174
182
  const globs = [];
175
- const candidates = ['.git', 'node_modules', 'dist', 'build', '.next', '.cache'];
176
- for (const name of candidates) {
177
- if (ctx.isExcluded(name)) {
183
+ for (const name of ctx.excludedNames) {
184
+ if (name.includes('/')) {
185
+ globs.push(`${watchRoot}/${name}`, `${watchRoot}/${name}/**`);
186
+ }
187
+ else {
178
188
  globs.push(`**/${name}`, `**/${name}/**`);
179
189
  }
180
190
  }
package/dist/mount.js CHANGED
@@ -2,7 +2,7 @@ import { chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync,
2
2
  import ignore from 'ignore';
3
3
  import path from 'node:path';
4
4
  import { startAutoSync, } from './auto-sync.js';
5
- const DEFAULT_EXCLUDED_DIRS = ['.git', 'node_modules'];
5
+ const DEFAULT_EXCLUDED_DIRS = ['.git', 'node_modules', '.npm-cache'];
6
6
  const MOUNT_README_FILENAME = '_MOUNT_README.md';
7
7
  const MOUNT_MARKER_FILENAME = '.relayfile-local-mount';
8
8
  const MOUNT_MARKER_CONTENT = 'This directory is managed by @relayfile/local-mount. Do not place unrelated files here; the directory will be deleted when the mount is torn down.\n';
@@ -50,6 +50,7 @@ export function createMount(projectDir, mountDir, options) {
50
50
  realMountDir,
51
51
  realProjectDir: resolvedProjectDir,
52
52
  isExcluded: (relPosix) => isExcludedPath(relPosix, excludeSet),
53
+ excludedNames: [...excludeSet],
53
54
  isIgnored: (relPosix, isDir) => isPathMatched(relPosix, ignoredMatcher, isDir),
54
55
  isReadonly: (relPosix) => isPathMatched(relPosix, readonlyMatcher),
55
56
  isNoSyncBack: (relPosix) => isPathMatched(relPosix, noSyncBackMatcher),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relayfile/local-mount",
3
- "version": "0.6.13",
3
+ "version": "0.6.14",
4
4
  "description": "Create a symlink/copy mount of a project directory with .agentignore/.agentreadonly semantics, then launch a CLI inside it and sync writable changes back on exit",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",