@indigoai-us/hq-cloud 6.18.19 → 6.18.20-alpha.732c
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/dist/cli/push-scan-exclusions.test.js +12 -0
- package/dist/cli/push-scan-exclusions.test.js.map +1 -1
- package/dist/watch-roots.d.ts +14 -12
- package/dist/watch-roots.d.ts.map +1 -1
- package/dist/watch-roots.js +35 -22
- package/dist/watch-roots.js.map +1 -1
- package/dist/watch-roots.test.js +64 -2
- package/dist/watch-roots.test.js.map +1 -1
- package/dist/watcher.d.ts +30 -3
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +50 -9
- package/dist/watcher.js.map +1 -1
- package/dist/watcher.test.js +130 -3
- package/dist/watcher.test.js.map +1 -1
- package/package.json +1 -1
package/dist/watcher.js
CHANGED
|
@@ -356,8 +356,9 @@ function errorPath(err) {
|
|
|
356
356
|
* Which backend a platform gets.
|
|
357
357
|
*
|
|
358
358
|
* - macOS (FSEvents) and Windows (ReadDirectoryChangesW) watch a directory
|
|
359
|
-
* recursively with ONE OS handle
|
|
360
|
-
*
|
|
359
|
+
* recursively with ONE OS handle. Windows uses the exact scoped plan;
|
|
360
|
+
* macOS uses a depth-bounded plan to keep its shared FSEvents stream's
|
|
361
|
+
* registered path set small while the event filter preserves upload scope.
|
|
361
362
|
* - Linux has no recursive handle: a directory watch reports only its own
|
|
362
363
|
* direct contents. The same scoped backend runs with one shallow inotify
|
|
363
364
|
* watch per in-scope directory instead — and NONE per file, because the
|
|
@@ -370,7 +371,9 @@ function errorPath(err) {
|
|
|
370
371
|
export function selectTreeWatchBackend(platform, forcePolling) {
|
|
371
372
|
if (forcePolling)
|
|
372
373
|
return "polling";
|
|
373
|
-
if (platform === "darwin"
|
|
374
|
+
if (platform === "darwin")
|
|
375
|
+
return "native-coarse";
|
|
376
|
+
if (platform === "win32")
|
|
374
377
|
return "native-recursive";
|
|
375
378
|
if (platform === "linux")
|
|
376
379
|
return "native-shallow";
|
|
@@ -390,6 +393,12 @@ function startChokidarTreeWatch(hqRoot, shouldEmit, onEvent, onError, maxWatched
|
|
|
390
393
|
const readyListeners = new Set();
|
|
391
394
|
try {
|
|
392
395
|
cw = watch(hqRoot, {
|
|
396
|
+
// Push walkers record a directory symlink as a link entry and never
|
|
397
|
+
// traverse its target. Keep polling discovery on the same boundary so
|
|
398
|
+
// aliased trees do not consume the path budget or produce events for
|
|
399
|
+
// content that cannot upload. Chokidar still reports changes to the
|
|
400
|
+
// symlink entry itself.
|
|
401
|
+
followSymlinks: false,
|
|
393
402
|
// On Linux chokidar adds one fs.watch/inotify watch per descended dir.
|
|
394
403
|
// The predicate therefore enforces both scope and the hard per-runner cap.
|
|
395
404
|
ignored: toChokidarIgnored(shouldEmit, hqRoot, budget),
|
|
@@ -642,7 +651,7 @@ export function startScopedRecursiveWatch(hqRoot, shouldEmit, onEvent, onError,
|
|
|
642
651
|
const openedOn = directoryIdentity(dir);
|
|
643
652
|
let handle;
|
|
644
653
|
try {
|
|
645
|
-
handle = fs.watch(dir, { recursive, persistent: true }, (eventType, filename) => {
|
|
654
|
+
handle = (opts.watchDirectory ?? fs.watch)(dir, { recursive, persistent: true }, (eventType, filename) => {
|
|
646
655
|
// `filename` is relative to THIS watch's directory (or null/empty if
|
|
647
656
|
// the platform couldn't provide it — nothing actionable then).
|
|
648
657
|
// `String()` coerces both the string and (older @types/node) Buffer
|
|
@@ -680,6 +689,11 @@ export function startScopedRecursiveWatch(hqRoot, shouldEmit, onEvent, onError,
|
|
|
680
689
|
}
|
|
681
690
|
handle.on("error", (err) => {
|
|
682
691
|
onError(err);
|
|
692
|
+
// TreeWatcher handles systemic watch exhaustion by closing this backend
|
|
693
|
+
// and moving to polling. Reopening the failed path before that transition
|
|
694
|
+
// runs only repeats the same EMFILE/ENFILE failure.
|
|
695
|
+
if (isSystemicWatchError(err))
|
|
696
|
+
return;
|
|
683
697
|
// A handle a re-plan already replaced (retiring) must not tear down its
|
|
684
698
|
// replacement at the same path.
|
|
685
699
|
if (closed || watchers.get(dir) !== handle)
|
|
@@ -730,6 +744,7 @@ export function startScopedRecursiveWatch(hqRoot, shouldEmit, onEvent, onError,
|
|
|
730
744
|
}
|
|
731
745
|
: onDirectorySeen,
|
|
732
746
|
recursiveWatches,
|
|
747
|
+
maxDepth: opts.maxDepth,
|
|
733
748
|
listChildDirs: opts.listChildDirs,
|
|
734
749
|
}));
|
|
735
750
|
}
|
|
@@ -1002,13 +1017,39 @@ export function startScopedRecursiveWatch(hqRoot, shouldEmit, onEvent, onError,
|
|
|
1002
1017
|
* ancestor-descent pruning that the chokidar backend needs
|
|
1003
1018
|
* {@link toChokidarIgnored} to avoid.
|
|
1004
1019
|
*/
|
|
1005
|
-
|
|
1020
|
+
/** @internal Exported for backend-level regression tests. */
|
|
1021
|
+
export function startTreeWatch(hqRoot, shouldEmit, onEvent, onError, maxWatchedPaths, onWatchBudgetExceeded, onDirectorySeen, forcePolling = false) {
|
|
1022
|
+
// Resolve the root once before the backend starts. Chokidar with
|
|
1023
|
+
// followSymlinks:false treats descendant links as leaf entries, but an
|
|
1024
|
+
// explicitly supplied root may itself be a symlink. Watch its real tree and
|
|
1025
|
+
// map observed paths back to the caller's root spelling so the caller's
|
|
1026
|
+
// filter and path routing retain their existing contract.
|
|
1027
|
+
const displayRoot = path.resolve(hqRoot);
|
|
1028
|
+
const root = fs.realpathSync(displayRoot);
|
|
1029
|
+
const displayPath = (absolutePath) => root === displayRoot
|
|
1030
|
+
? absolutePath
|
|
1031
|
+
: path.join(displayRoot, path.relative(root, absolutePath));
|
|
1032
|
+
const watchFilter = root === displayRoot
|
|
1033
|
+
? shouldEmit
|
|
1034
|
+
: (absolutePath, isDir) => shouldEmit(displayPath(absolutePath), isDir);
|
|
1035
|
+
const watchEvent = root === displayRoot
|
|
1036
|
+
? onEvent
|
|
1037
|
+
: (absolutePath, kind) => onEvent(displayPath(absolutePath), kind);
|
|
1038
|
+
const watchDirectorySeen = onDirectorySeen
|
|
1039
|
+
? root === displayRoot
|
|
1040
|
+
? onDirectorySeen
|
|
1041
|
+
: (absolutePath) => onDirectorySeen(displayPath(absolutePath))
|
|
1042
|
+
: undefined;
|
|
1006
1043
|
const choice = selectTreeWatchBackend(process.platform, forcePolling);
|
|
1007
|
-
if (choice === "native-recursive" ||
|
|
1044
|
+
if (choice === "native-recursive" ||
|
|
1045
|
+
choice === "native-coarse" ||
|
|
1046
|
+
choice === "native-shallow") {
|
|
1008
1047
|
try {
|
|
1009
|
-
const scoped = startScopedRecursiveWatch(
|
|
1048
|
+
const scoped = startScopedRecursiveWatch(root, watchFilter, watchEvent, onError, watchDirectorySeen, choice === "native-shallow"
|
|
1010
1049
|
? { recursiveWatches: false, maxWatchedPaths, onWatchBudgetExceeded }
|
|
1011
|
-
:
|
|
1050
|
+
: choice === "native-coarse"
|
|
1051
|
+
? { maxDepth: 2 }
|
|
1052
|
+
: {});
|
|
1012
1053
|
// Partial coverage is worse than a different backend: a planned root we
|
|
1013
1054
|
// could not attach is silently unwatched forever, and the operator only
|
|
1014
1055
|
// sees it as "instant sync stopped working for that subtree". Accept the
|
|
@@ -1024,7 +1065,7 @@ function startTreeWatch(hqRoot, shouldEmit, onEvent, onError, maxWatchedPaths, o
|
|
|
1024
1065
|
onError(err);
|
|
1025
1066
|
}
|
|
1026
1067
|
}
|
|
1027
|
-
return startChokidarTreeWatch(
|
|
1068
|
+
return startChokidarTreeWatch(root, watchFilter, watchEvent, onError, maxWatchedPaths, onWatchBudgetExceeded, forcePolling);
|
|
1028
1069
|
}
|
|
1029
1070
|
/**
|
|
1030
1071
|
* Build the composite emit-decision predicate. Returns true when a change to
|