diff --git a/README.md b/README.md index edccfda..272467e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ _Automatically run Hardhat actions when files change_ npm install hardhat-watcher ``` -or +or ```bash yarn add hardhat-watcher @@ -17,18 +17,19 @@ yarn add hardhat-watcher Import the plugin in your `hardhat.config.js`: ```js -require("hardhat-watcher"); +require('hardhat-watcher') ``` Or if you are using TypeScript, in your `hardhat.config.ts`: ```ts -import "hardhat-watcher"; +import 'hardhat-watcher' ``` ## Tasks This plugin adds the _watch_ task to Hardhat: + ```bash npx hardhat watch ``` @@ -46,6 +47,7 @@ module.exports = { [key: string]: { // key is the name for the watcherTask tasks?: (string | { command: string, params?: { [key: string] => any } })[]; // Every task of the hardhat runtime is supported (including other plugins!) files?: string[]; // Files, directories or glob patterns to watch for changes. (defaults to `[config.paths.sources]`, which itself defaults to the `contracts` dir) + ignoredFiles?: string[]; // Files, directories or glob patterns that should *not* be watched. verbose?: boolean; // Turn on for extra logging } } @@ -60,8 +62,8 @@ The most basic use case, which is simply compiling your files on change, is acco module.exports = { watcher: { compilation: { - tasks: ["compile"], - } + tasks: ['compile'], + }, }, } ``` @@ -74,13 +76,18 @@ A bit more involved and showcasing the use of parameters for tasks and defining module.exports = { watcher: { compilation: { - tasks: ["compile"], - files: ["./contracts"], + tasks: ['compile'], + files: ['./contracts'], + ignoredFiles: ['**/.vscode'], verbose: true, }, ci: { - tasks: ["clean", { command: "compile", params: { quiet: true } }, { command: "test", params: { noCompile: true, testFiles: ["testfile.ts"] } } ], - } + tasks: [ + 'clean', + { command: 'compile', params: { quiet: true } }, + { command: 'test', params: { noCompile: true, testFiles: ['testfile.ts'] } }, + ], + }, }, } ``` @@ -93,14 +100,14 @@ Positional arguments are provided in the same way as "normal" arguments (check o In order to find the name of a positional argument, simply run `yarn hardhat --help`. This is an example output for the `test` command: -```` +``` Hardhat version 2.0.2 Usage: hardhat [GLOBAL OPTIONS] test [--no-compile] [...testFiles] OPTIONS: - --no-compile Don't compile before running this task + --no-compile Don't compile before running this task POSITIONAL ARGUMENTS: @@ -109,13 +116,15 @@ POSITIONAL ARGUMENTS: test: Runs mocha tests For global options help run: hardhat help -```` +``` + ### Changed file as argument The path of the changed file can be inserted into positional arguments using the template parameter `{path}`. This speeds up iteration in testing, especially if using single test isolation (for example, by using `it.only("test")` in mocha.) Example: -```` + +``` module.exports = { watcher: { test: { @@ -125,5 +134,4 @@ module.exports = { } } } -```` - +``` diff --git a/src/index.ts b/src/index.ts index b4c93a4..b65fea5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -25,6 +25,7 @@ extendConfig((config: HardhatConfig, userConfig: Readonly) => } }), files: task.files ?? [config.paths.sources], + ignoredFiles: task.ignoredFiles ?? [], verbose: task.verbose ?? false, } }) @@ -77,6 +78,7 @@ task('watch', 'Start the file watcher') chokidar .watch(taskConfig.files, { + ignored: taskConfig.ignoredFiles, ignoreInitial: true, usePolling: true, interval: 250, diff --git a/src/type-extensions.ts b/src/type-extensions.ts index 64624fb..74ba459 100644 --- a/src/type-extensions.ts +++ b/src/type-extensions.ts @@ -1,37 +1,39 @@ -import "hardhat/types/config"; -import "hardhat/types/runtime"; +import 'hardhat/types/config' +import 'hardhat/types/runtime' -declare module "hardhat/types/config" { - export type HardhatTask = string | ExpandedHardhatTask; +declare module 'hardhat/types/config' { + export type HardhatTask = string | ExpandedHardhatTask export type ExpandedHardhatTask = { - command: string; + command: string params?: { - [key: string]: any; - }; - }; + [key: string]: any + } + } export type WatcherTask = { - tasks?: HardhatTask[]; - files?: string[]; - verbose?: boolean; - }; + tasks?: HardhatTask[] + files?: string[] + ignoredFiles?: string[] + verbose?: boolean + } // User facing config export interface HardhatUserConfig { - watcher?: { [key: string]: WatcherTask }; + watcher?: { [key: string]: WatcherTask } } export type WatcherConfig = { [key: string]: { - tasks: Required[]; - files: string[]; - verbose: boolean; - }; - }; + tasks: Required[] + files: string[] + ignoredFiles: string[] + verbose: boolean + } + } // Fully resolved config export interface HardhatConfig { - watcher: WatcherConfig; + watcher: WatcherConfig } } diff --git a/test/dummyFiles/.editortest b/test/dummyFiles/.editortest new file mode 100644 index 0000000..a85ebf2 --- /dev/null +++ b/test/dummyFiles/.editortest @@ -0,0 +1 @@ +editor file \ No newline at end of file diff --git a/test/dummyFiles/.editortest2 b/test/dummyFiles/.editortest2 new file mode 100644 index 0000000..5e96e60 --- /dev/null +++ b/test/dummyFiles/.editortest2 @@ -0,0 +1 @@ +changed editor file test \ No newline at end of file diff --git a/test/fixture-projects/hardhat-project/contracts/.editortest b/test/fixture-projects/hardhat-project/contracts/.editortest new file mode 100644 index 0000000..5e96e60 --- /dev/null +++ b/test/fixture-projects/hardhat-project/contracts/.editortest @@ -0,0 +1 @@ +changed editor file test \ No newline at end of file diff --git a/test/fixture-projects/hardhat-project/hardhat.config.ts b/test/fixture-projects/hardhat-project/hardhat.config.ts index ed0d2f3..3a70257 100644 --- a/test/fixture-projects/hardhat-project/hardhat.config.ts +++ b/test/fixture-projects/hardhat-project/hardhat.config.ts @@ -9,6 +9,7 @@ const config: HardhatUserConfig = { compilation: { tasks: ['clean', { command: 'compile', params: { quiet: true } }], files: ['./contracts'], + ignoredFiles: ['**/.editortest'], verbose: true, }, }, diff --git a/test/project.test.ts b/test/project.test.ts index 8309fe3..5fffdf1 100644 --- a/test/project.test.ts +++ b/test/project.test.ts @@ -4,7 +4,7 @@ import { assert, expect } from 'chai' import { readContractJsonStat, sleep, useEnvironment, simulateFileChange } from './helpers' describe('Watcher tests', function () { - this.timeout(30000) + this.timeout(60000) useEnvironment('hardhat-project') beforeEach(async function () { @@ -15,19 +15,29 @@ describe('Watcher tests', function () { try { let lastTs = Date.now() simulateFileChange('Contract.sol') + simulateFileChange('.editortest', 'contracts/.editortest') this.hre.run('watch', { watcherTask: 'compilation' }) await sleep(1000) - console.log('=========== Simulating file change =============') + console.log('=========== Simulating Contract.sol change =============') simulateFileChange('Contract2.sol') await sleep(7500) expect(readContractJsonStat(this.hre).mtime.valueOf()).to.be.greaterThan(lastTs) lastTs = Date.now() - console.log('=========== Simulating file change =============') + console.log('=========== Simulating Contract.sol change =============') simulateFileChange('Contract3.sol') await sleep(7500) - expect(readContractJsonStat(this.hre).mtime.valueOf()).to.be.greaterThan(lastTs) + const lastModified = readContractJsonStat(this.hre).mtime.valueOf() + expect(lastModified).to.be.greaterThan(lastTs) + + lastTs = Date.now() + console.log('=========== Simulating .editortest change =============') + simulateFileChange('.editortest2', 'contracts/.editortest') + await sleep(7500) + + // File shouldn't change + expect(readContractJsonStat(this.hre).mtime.valueOf()).to.equal(lastModified) } catch (error: any) { assert.fail(error.message) }