Skip to content

Commit 20a16e8

Browse files
committed
lib: support glob on --watch-path
1 parent 650f51f commit 20a16e8

File tree

3 files changed

+81
-5
lines changed

3 files changed

+81
-5
lines changed

lib/internal/fs/glob.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,4 +798,5 @@ module.exports = {
798798
__proto__: null,
799799
Glob,
800800
matchGlobPattern,
801+
createMatcher,
801802
};

lib/internal/main/watch_mode.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22
const {
3+
ArrayPrototypeFlatMap,
34
ArrayPrototypeForEach,
45
ArrayPrototypeIncludes,
56
ArrayPrototypeJoin,
@@ -28,17 +29,32 @@ const { inspect } = require('util');
2829
const { setTimeout, clearTimeout } = require('timers');
2930
const { resolve } = require('path');
3031
const { once } = require('events');
32+
const { createMatcher } = require('internal/fs/glob');
33+
const { globSync } = require('fs');
3134

3235
prepareMainThreadExecution(false, false);
3336
markBootstrapComplete();
3437

38+
function hasGlobPattern(path) {
39+
return createMatcher(path).hasMagic();
40+
}
41+
42+
function handleWatchedPath(path) {
43+
if (hasGlobPattern(path)) {
44+
const matchedFilesFromGlob = globSync(path);
45+
const resolvedMatchedFiles = ArrayPrototypeMap(matchedFilesFromGlob, (path) => resolve(path));
46+
return resolvedMatchedFiles;
47+
}
48+
return resolve(path);
49+
}
50+
3551
const kKillSignal = convertToValidSignal(getOptionValue('--watch-kill-signal'));
3652
const kShouldFilterModules = getOptionValue('--watch-path').length === 0;
3753
const kEnvFiles = [
3854
...getOptionValue('--env-file'),
3955
...getOptionValue('--env-file-if-exists'),
4056
];
41-
const kWatchedPaths = ArrayPrototypeMap(getOptionValue('--watch-path'), (path) => resolve(path));
57+
const kWatchedPaths = ArrayPrototypeFlatMap(getOptionValue('--watch-path'), (path) => handleWatchedPath(path));
4258
const kPreserveOutput = getOptionValue('--watch-preserve-output');
4359
const kCommand = ArrayPrototypeSlice(process.argv, 1);
4460
const kCommandStr = inspect(ArrayPrototypeJoin(kCommand, ' '));

test/sequential/test-watch-mode.mjs

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,21 @@ async function runWriteSucceed({
108108
let stderr = '';
109109
const stdout = [];
110110

111+
let watchedFiles = [];
112+
let currentWatchedFileIndex = 0;
113+
const isWatchingMultpileFiles = Array.isArray(watchedFile) && watchedFile.length > 1;
114+
const isWatchingSingleFile = !isWatchingMultpileFiles;
115+
116+
if (isWatchingMultpileFiles) {
117+
watchedFiles = watchedFile;
118+
restarts = watchedFiles.length + 1;
119+
}
120+
111121
child.stderr.on('data', (data) => {
112122
stderr += data;
113123
});
114124

125+
115126
try {
116127
// Break the chunks into lines
117128
for await (const data of createInterface({ input: child.stdout })) {
@@ -120,14 +131,16 @@ async function runWriteSucceed({
120131
}
121132
if (data.startsWith(completed)) {
122133
completes++;
123-
if (completes === restarts) {
134+
if (completes === restarts)
124135
break;
125-
}
126-
if (completes === 1) {
136+
if (isWatchingSingleFile && completes === 1)
127137
cancelRestarts = restart(watchedFile);
138+
if (isWatchingMultpileFiles && completes < restarts) {
139+
cancelRestarts();
140+
const currentlyWatchedFile = watchedFiles[currentWatchedFileIndex++];
141+
cancelRestarts = restart(currentlyWatchedFile);
128142
}
129143
}
130-
131144
if (!shouldFail && data.startsWith('Failed running')) {
132145
break;
133146
}
@@ -884,4 +897,50 @@ process.on('message', (message) => {
884897
await done();
885898
}
886899
});
900+
901+
it('should watch files from a given glob pattern --watch-path=./**/*.js', async () => {
902+
903+
const tmpDirForGlobTest = tmpdir.resolve('glob-test-dir');
904+
mkdirSync(tmpDirForGlobTest);
905+
906+
const globPattern = path.resolve(tmpDirForGlobTest, '**/*.js');
907+
908+
const directory1 = path.join(tmpDirForGlobTest, 'directory1');
909+
const directory2 = path.join(tmpDirForGlobTest, 'directory2');
910+
911+
mkdirSync(directory1);
912+
mkdirSync(directory2);
913+
914+
const tmpJsFile1 = createTmpFile('', '.js', directory1);
915+
const tmpJsFile2 = createTmpFile('', '.js', directory1);
916+
const tmpJsFile3 = createTmpFile('', '.js', directory2);
917+
const tmpJsFile4 = createTmpFile('', '.js', directory2);
918+
const tmpJsFile5 = createTmpFile('', '.js', directory2);
919+
920+
const mainJsFile = createTmpFile('console.log(\'running\')', '.js', tmpDirForGlobTest);
921+
922+
const args = ['--watch-path', globPattern, mainJsFile];
923+
const watchedFiles = [tmpJsFile1, tmpJsFile2, tmpJsFile3, tmpJsFile4, tmpJsFile5];
924+
925+
const { stderr, stdout } = await runWriteSucceed({
926+
args,
927+
watchedFile: watchedFiles,
928+
});
929+
930+
function expectRepeatedCompletes(n) {
931+
const expectedStdout = [];
932+
for (let i = 0; i < n; i++) {
933+
if (i !== 0) {
934+
expectedStdout.push(`Restarting ${inspect((mainJsFile))}`);
935+
}
936+
expectedStdout.push('running');
937+
expectedStdout.push(`Completed running ${inspect(mainJsFile)}. Waiting for file changes before restarting...`);
938+
}
939+
return expectedStdout;
940+
}
941+
942+
assert.strictEqual(stderr, '');
943+
assert.deepStrictEqual(stdout, expectRepeatedCompletes(6));
944+
945+
});
887946
});

0 commit comments

Comments
 (0)