Skip to content

Commit 9b35739

Browse files
committed
lib: support glob on --watch-path
1 parent e775989 commit 9b35739

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
@@ -800,4 +800,5 @@ module.exports = {
800800
__proto__: null,
801801
Glob,
802802
matchGlobPattern,
803+
createMatcher,
803804
};

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
@@ -117,10 +117,21 @@ async function runWriteSucceed({
117117
let stderr = '';
118118
const stdout = [];
119119

120+
let watchedFiles = [];
121+
let currentWatchedFileIndex = 0;
122+
const isWatchingMultpileFiles = Array.isArray(watchedFile) && watchedFile.length > 1;
123+
const isWatchingSingleFile = !isWatchingMultpileFiles;
124+
125+
if (isWatchingMultpileFiles) {
126+
watchedFiles = watchedFile;
127+
restarts = watchedFiles.length + 1;
128+
}
129+
120130
child.stderr.on('data', (data) => {
121131
stderr += data;
122132
});
123133

134+
124135
try {
125136
// Break the chunks into lines
126137
for await (const data of createInterface({ input: child.stdout })) {
@@ -129,14 +140,16 @@ async function runWriteSucceed({
129140
}
130141
if (data.startsWith(completed)) {
131142
completes++;
132-
if (completes === restarts) {
143+
if (completes === restarts)
133144
break;
134-
}
135-
if (completes === 1) {
145+
if (isWatchingSingleFile && completes === 1)
136146
cancelRestarts = restart(watchedFile);
147+
if (isWatchingMultpileFiles && completes < restarts) {
148+
cancelRestarts();
149+
const currentlyWatchedFile = watchedFiles[currentWatchedFileIndex++];
150+
cancelRestarts = restart(currentlyWatchedFile);
137151
}
138152
}
139-
140153
if (!shouldFail && data.startsWith('Failed running')) {
141154
break;
142155
}
@@ -922,4 +935,50 @@ process.on('message', (message) => {
922935
await done();
923936
}
924937
});
938+
939+
it('should watch files from a given glob pattern --watch-path=./**/*.js', async () => {
940+
941+
const tmpDirForGlobTest = tmpdir.resolve('glob-test-dir');
942+
mkdirSync(tmpDirForGlobTest);
943+
944+
const globPattern = path.resolve(tmpDirForGlobTest, '**/*.js');
945+
946+
const directory1 = path.join(tmpDirForGlobTest, 'directory1');
947+
const directory2 = path.join(tmpDirForGlobTest, 'directory2');
948+
949+
mkdirSync(directory1);
950+
mkdirSync(directory2);
951+
952+
const tmpJsFile1 = createTmpFile('', '.js', directory1);
953+
const tmpJsFile2 = createTmpFile('', '.js', directory1);
954+
const tmpJsFile3 = createTmpFile('', '.js', directory2);
955+
const tmpJsFile4 = createTmpFile('', '.js', directory2);
956+
const tmpJsFile5 = createTmpFile('', '.js', directory2);
957+
958+
const mainJsFile = createTmpFile('console.log(\'running\')', '.js', tmpDirForGlobTest);
959+
960+
const args = ['--watch-path', globPattern, mainJsFile];
961+
const watchedFiles = [tmpJsFile1, tmpJsFile2, tmpJsFile3, tmpJsFile4, tmpJsFile5];
962+
963+
const { stderr, stdout } = await runWriteSucceed({
964+
args,
965+
watchedFile: watchedFiles,
966+
});
967+
968+
function expectRepeatedCompletes(n) {
969+
const expectedStdout = [];
970+
for (let i = 0; i < n; i++) {
971+
if (i !== 0) {
972+
expectedStdout.push(`Restarting ${inspect((mainJsFile))}`);
973+
}
974+
expectedStdout.push('running');
975+
expectedStdout.push(`Completed running ${inspect(mainJsFile)}. Waiting for file changes before restarting...`);
976+
}
977+
return expectedStdout;
978+
}
979+
980+
assert.strictEqual(stderr, '');
981+
assert.deepStrictEqual(stdout, expectRepeatedCompletes(6));
982+
983+
});
925984
});

0 commit comments

Comments
 (0)