From c4645074e491d1fbbc670b25370d252bae767d9f Mon Sep 17 00:00:00 2001 From: Roman Lamsal Date: Wed, 5 Oct 2022 12:50:05 +0200 Subject: [PATCH 1/7] feat: add --ignored flag to watch --- README.md | 9 ++++++ src/watch/index.ts | 10 ++++++- tests/specs/watch.ts | 65 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7af1fdb7..2b15b70b 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,15 @@ tsx watch ./file.ts All imported files are watched except from the following directories: `node_modules`, `bower_components`, `vendor`, `dist`, and `.*` (hidden directories). +#### Ignore files from being watched + +If you wish to exclude files from being watched, you can pass `--ignored` multiple times: +```sh +tsx watch --ignored ./ignore-me.js --ignored ./ignore-me-too.js ./file.ts +``` + +This flag is passed to [chokidar](https://github.com/paulmillr/chokidar) thus glob patterns also work here. + #### Tips - Press Return to manually rerun - Pass in `--clear-screen=false` to disable clearing the screen on rerun diff --git a/src/watch/index.ts b/src/watch/index.ts index aaba93ba..a19c6e87 100644 --- a/src/watch/index.ts +++ b/src/watch/index.ts @@ -27,7 +27,12 @@ const flags = { description: 'Clearing the screen on rerun', default: true, }, -}; + ignored: { + type: [String], + description: 'Defines files/paths to be ignored', + default: [], + }, +} as const; export const watchCommand = command({ name: 'watch', @@ -47,6 +52,7 @@ export const watchCommand = command({ noCache: argv.flags.noCache, tsconfigPath: argv.flags.tsconfig, clearScreen: argv.flags.clearScreen, + ignored: argv.flags.ignored, ipc: true, }; @@ -123,6 +129,8 @@ export const watchCommand = command({ // Distribution files '**/dist/**', + + ...options.ignored, ], ignorePermissionErrors: true, }, diff --git a/tests/specs/watch.ts b/tests/specs/watch.ts index 6d83f7d3..353832dc 100644 --- a/tests/specs/watch.ts +++ b/tests/specs/watch.ts @@ -141,5 +141,70 @@ export default testSuite(async ({ describe }, fixturePath: string) => { // await tsxProcess; // }, 2000); }); + + describe('ignore', ({ test }) => { + test('multiple files ignored', async () => { + // given + const initialValue = 'first round'; + const alteredValue = 'second round'; + const includedFilename = 'included.js'; + const ignoredFilenames = ['ignored-1.js', 'ignored-2.js']; + + const fixtures = await createFixture({ + [includedFilename]: ` + import { value as value1 } from './ignored-1'; + import { value as value2 } from './ignored-2'; + console.log(value1 + value2); + `.trim(), + [ignoredFilenames[0]]: `export const value = '${initialValue}';`, + [ignoredFilenames[1]]: `export const value = '${initialValue}';`, + }); + + const tsxProcess = tsx({ + args: [ + 'watch', + '--clear-screen=false', + `--ignored=${path.join(fixtures.path, ignoredFilenames[0])}`, + `--ignored=${path.join(fixtures.path, ignoredFilenames[1])}`, + path.join(fixtures.path, includedFilename), + ], + }); + + let aggregatedOutput = ''; + async function onStdOut(data: Buffer) { + const chunkString = data.toString(); + aggregatedOutput += chunkString; + + if (new RegExp(`${initialValue}\n`).test(chunkString)) { + await Promise.all(ignoredFilenames.map(ignoredFilename => fixtures.writeFile(ignoredFilename, `export const value = '${alteredValue}';`))); + // make sure to wait for chokidar to pick up changes + // in the ignored file before manually triggering a rerun + setTimeout(async () => { + await fixtures.writeFile(includedFilename, 'console.log(\'TERMINATE\');'); + }, 500); + } else if (chunkString.match('TERMINATE\n')) { + // cleanup + await fixtures.rm(); + tsxProcess.kill(); + } + } + tsxProcess.stdout?.on('data', onStdOut); + + let error = false; + tsxProcess.stderr?.on('data', () => { + error = true; + }); + + // when + await tsxProcess; + + // then + if (error) { + // manten does not come with a fail() utility. + expect('No error throwing').toEqual('but was thrown.'); + } + expect(aggregatedOutput).not.toMatch(alteredValue); + }); + }); }); }); From bd0927b91db76ca8f0958d7a4da32dc7151a318e Mon Sep 17 00:00:00 2001 From: Roman Lamsal Date: Thu, 6 Oct 2022 09:54:59 +0200 Subject: [PATCH 2/7] Update `watch --ignored` description Co-authored-by: hiroki osame --- src/watch/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/watch/index.ts b/src/watch/index.ts index a19c6e87..33e101d1 100644 --- a/src/watch/index.ts +++ b/src/watch/index.ts @@ -29,7 +29,7 @@ const flags = { }, ignored: { type: [String], - description: 'Defines files/paths to be ignored', + description: 'Paths & globs to exclude from being watched', default: [], }, } as const; From c5eb83d086196412ae8b5e22b6fb91020602b339 Mon Sep 17 00:00:00 2001 From: Roman Lamsal Date: Thu, 6 Oct 2022 10:00:39 +0200 Subject: [PATCH 3/7] rename flag ignored->ignore --- README.md | 4 ++-- src/watch/index.ts | 6 +++--- tests/specs/watch.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2b15b70b..930c2c7e 100644 --- a/README.md +++ b/README.md @@ -99,9 +99,9 @@ All imported files are watched except from the following directories: #### Ignore files from being watched -If you wish to exclude files from being watched, you can pass `--ignored` multiple times: +If you wish to exclude files from being watched, you can pass `--ignore` multiple times: ```sh -tsx watch --ignored ./ignore-me.js --ignored ./ignore-me-too.js ./file.ts +tsx watch --ignore ./ignore-me.js --ignore ./ignore-me-too.js ./file.ts ``` This flag is passed to [chokidar](https://github.com/paulmillr/chokidar) thus glob patterns also work here. diff --git a/src/watch/index.ts b/src/watch/index.ts index 33e101d1..7246838d 100644 --- a/src/watch/index.ts +++ b/src/watch/index.ts @@ -27,7 +27,7 @@ const flags = { description: 'Clearing the screen on rerun', default: true, }, - ignored: { + ignore: { type: [String], description: 'Paths & globs to exclude from being watched', default: [], @@ -52,7 +52,7 @@ export const watchCommand = command({ noCache: argv.flags.noCache, tsconfigPath: argv.flags.tsconfig, clearScreen: argv.flags.clearScreen, - ignored: argv.flags.ignored, + ignore: argv.flags.ignore, ipc: true, }; @@ -130,7 +130,7 @@ export const watchCommand = command({ // Distribution files '**/dist/**', - ...options.ignored, + ...options.ignore, ], ignorePermissionErrors: true, }, diff --git a/tests/specs/watch.ts b/tests/specs/watch.ts index 353832dc..9a56d872 100644 --- a/tests/specs/watch.ts +++ b/tests/specs/watch.ts @@ -164,8 +164,8 @@ export default testSuite(async ({ describe }, fixturePath: string) => { args: [ 'watch', '--clear-screen=false', - `--ignored=${path.join(fixtures.path, ignoredFilenames[0])}`, - `--ignored=${path.join(fixtures.path, ignoredFilenames[1])}`, + `--ignore=${path.join(fixtures.path, ignoredFilenames[0])}`, + `--ignore=${path.join(fixtures.path, ignoredFilenames[1])}`, path.join(fixtures.path, includedFilename), ], }); From e428072b77789a7c7b24c584fc8908660d0a5c64 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Thu, 6 Oct 2022 19:02:47 +0900 Subject: [PATCH 4/7] docs: wording --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 930c2c7e..7788dafa 100644 --- a/README.md +++ b/README.md @@ -97,15 +97,13 @@ tsx watch ./file.ts All imported files are watched except from the following directories: `node_modules`, `bower_components`, `vendor`, `dist`, and `.*` (hidden directories). -#### Ignore files from being watched +#### Ignore files from watch -If you wish to exclude files from being watched, you can pass `--ignore` multiple times: +To exclude files from being watched, pass in a path or glob to the `--ignore` flag: ```sh tsx watch --ignore ./ignore-me.js --ignore ./ignore-me-too.js ./file.ts ``` -This flag is passed to [chokidar](https://github.com/paulmillr/chokidar) thus glob patterns also work here. - #### Tips - Press Return to manually rerun - Pass in `--clear-screen=false` to disable clearing the screen on rerun From 31e4afc53254025781df4c42c099d9e04259cd01 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Thu, 6 Oct 2022 22:15:32 +0900 Subject: [PATCH 5/7] test: refactor --- tests/specs/watch.ts | 79 +++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 45 deletions(-) diff --git a/tests/specs/watch.ts b/tests/specs/watch.ts index 9a56d872..fa6cd9cd 100644 --- a/tests/specs/watch.ts +++ b/tests/specs/watch.ts @@ -1,4 +1,5 @@ import path from 'path'; +import { setTimeout } from 'timers/promises'; import { testSuite, expect } from 'manten'; import { createFixture } from 'fs-fixture'; import { tsx } from '../utils/tsx'; @@ -144,67 +145,55 @@ export default testSuite(async ({ describe }, fixturePath: string) => { describe('ignore', ({ test }) => { test('multiple files ignored', async () => { - // given - const initialValue = 'first round'; - const alteredValue = 'second round'; - const includedFilename = 'included.js'; - const ignoredFilenames = ['ignored-1.js', 'ignored-2.js']; - - const fixtures = await createFixture({ - [includedFilename]: ` - import { value as value1 } from './ignored-1'; - import { value as value2 } from './ignored-2'; - console.log(value1 + value2); + const entryFile = 'index.js'; + const fileA = 'file-a.js'; + const fileB = 'directory/file-b.js'; + let value = Date.now(); + + const fixture = await createFixture({ + [entryFile]: ` + import valueA from './${fileA}' + import valueB from './${fileB}' + console.log(valueA, valueB) `.trim(), - [ignoredFilenames[0]]: `export const value = '${initialValue}';`, - [ignoredFilenames[1]]: `export const value = '${initialValue}';`, + [fileA]: `export default ${value}`, + [fileB]: `export default ${value}`, }); const tsxProcess = tsx({ args: [ 'watch', '--clear-screen=false', - `--ignore=${path.join(fixtures.path, ignoredFilenames[0])}`, - `--ignore=${path.join(fixtures.path, ignoredFilenames[1])}`, - path.join(fixtures.path, includedFilename), + `--ignore=${path.join(fixture.path, fileA)}`, + `--ignore=${path.join(fixture.path, 'directory/*')}`, + path.join(fixture.path, entryFile), ], }); - let aggregatedOutput = ''; - async function onStdOut(data: Buffer) { + tsxProcess.stdout!.on('data', async (data: Buffer) => { const chunkString = data.toString(); - aggregatedOutput += chunkString; - - if (new RegExp(`${initialValue}\n`).test(chunkString)) { - await Promise.all(ignoredFilenames.map(ignoredFilename => fixtures.writeFile(ignoredFilename, `export const value = '${alteredValue}';`))); - // make sure to wait for chokidar to pick up changes - // in the ignored file before manually triggering a rerun - setTimeout(async () => { - await fixtures.writeFile(includedFilename, 'console.log(\'TERMINATE\');'); - }, 500); - } else if (chunkString.match('TERMINATE\n')) { - // cleanup - await fixtures.rm(); - tsxProcess.kill(); + if (chunkString === `${value} ${value}\n`) { + value = Date.now(); + await Promise.all([ + fixture.writeFile(fileA, `export default ${value}`), + fixture.writeFile(fileB, `export default ${value}`), + ]); + + await setTimeout(500); + await fixture.writeFile(entryFile, 'console.log("TERMINATE")'); } - } - tsxProcess.stdout?.on('data', onStdOut); - let error = false; - tsxProcess.stderr?.on('data', () => { - error = true; + if (chunkString === 'TERMINATE\n') { + tsxProcess.kill(); + } }); - // when - await tsxProcess; + const tsxProcessResolved = await tsxProcess; + await fixture.rm(); - // then - if (error) { - // manten does not come with a fail() utility. - expect('No error throwing').toEqual('but was thrown.'); - } - expect(aggregatedOutput).not.toMatch(alteredValue); - }); + expect(tsxProcessResolved.stdout).not.toMatch(`${value} ${value}`); + expect(tsxProcessResolved.stderr).toBe(''); + }, 5000); }); }); }); From f66ce492217988238e8d18e230119d40dca5bf4e Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Thu, 6 Oct 2022 22:20:31 +0900 Subject: [PATCH 6/7] refactor: remove default on ignore flag --- src/watch/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/watch/index.ts b/src/watch/index.ts index 7246838d..3eb2504e 100644 --- a/src/watch/index.ts +++ b/src/watch/index.ts @@ -30,7 +30,6 @@ const flags = { ignore: { type: [String], description: 'Paths & globs to exclude from being watched', - default: [], }, } as const; From e003f87bb15f39e046c32b762de30b3d7b8067f1 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Thu, 6 Oct 2022 22:21:35 +0900 Subject: [PATCH 7/7] test: update test name --- tests/specs/watch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/specs/watch.ts b/tests/specs/watch.ts index fa6cd9cd..fe202250 100644 --- a/tests/specs/watch.ts +++ b/tests/specs/watch.ts @@ -144,7 +144,7 @@ export default testSuite(async ({ describe }, fixturePath: string) => { }); describe('ignore', ({ test }) => { - test('multiple files ignored', async () => { + test('file path & glob', async () => { const entryFile = 'index.js'; const fileA = 'file-a.js'; const fileB = 'directory/file-b.js';