diff --git a/src/watch/index.ts b/src/watch/index.ts index fcc25ac09..b798ad1ae 100644 --- a/src/watch/index.ts +++ b/src/watch/index.ts @@ -36,6 +36,10 @@ const flags = { type: [String], description: 'Paths & globs to exclude from being watched', }, + include: { + type: [String], + description: 'Additional paths & globs to watch', + }, } as const; export const watchCommand = command({ @@ -60,6 +64,7 @@ export const watchCommand = command({ tsconfigPath: argv.flags.tsconfig, clearScreen: argv.flags.clearScreen, ignore: argv.flags.ignore, + include: argv.flags.include, ipc: true, }; @@ -195,7 +200,10 @@ export const watchCommand = command({ * As an alternative, we watch cwd and all run-time dependencies */ const watcher = watch( - argv._, + [ + ...argv._, + ...options.include, + ], { cwd: process.cwd(), ignoreInitial: true, diff --git a/tests/specs/watch.ts b/tests/specs/watch.ts index 4f55134f3..47d562b85 100644 --- a/tests/specs/watch.ts +++ b/tests/specs/watch.ts @@ -300,5 +300,64 @@ export default testSuite(async ({ describe }, { tsx }: NodeApis) => { expect(p.stderr).toBe(''); }, 10_000); }); + + describe('watch additional files', ({ test }) => { + test('file path & glob', async () => { + const entryFile = 'index.js'; + const fileA = 'file-a'; + const fileB = 'directory/file-b'; + await using fixture = await createFixture({ + [entryFile]: ` + import fs from 'fs/promises'; + Promise.all([ + fs.readFile('./${fileA}', 'utf8'), + fs.readFile('./${fileB}', 'utf8') + ]).then(console.log, console.error); + `.trim(), + [fileA]: 'content-a', + [fileB]: 'content-b', + }); + + const tsxProcess = tsx( + [ + 'watch', + '--clear-screen=false', + `--include=${fileA}`, + '--include=directory/*', + entryFile, + ], + fixture.path, + ); + + await processInteract( + tsxProcess.stdout!, + [ + (data) => { + if (data.includes("'content-a', 'content-b'")) { + fixture.writeFile(fileA, 'update-a'); + return true; + } + }, + (data) => { + if (data.includes("'update-a', 'content-b'")) { + fixture.writeFile(fileB, 'update-b'); + return true; + } + }, + (data) => { + if (data.includes("'update-a', 'update-b'")) { + return true; + } + }, + ], + 9000, + ); + + tsxProcess.kill(); + + const tsxProcessResolved = await tsxProcess; + expect(tsxProcessResolved.stderr).toBe(''); + }, 10_000); + }); }); });