2.1.0 • Published 3 years ago

precise-watcher v2.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

Contents

  1. Status
  2. Installation
  3. Usage
    1. Posibilities
    2. Watch files using NPM scripts
      1. Setting options in a configuration file
    3. Watch files using your console
      1. Supported options
    4. Watch files using js
  4. Examples
    1. Run eslint --fix on 1 single file, when it changes
    2. Copy /static content to /public. On development, serve /public; on production, exit
  5. Supported options
  6. Credits
  7. License

Status

Linux & MacOS CI NPM version

Installation

Run npm i precise-watcher or yarn add precise-watcher.

Usage

Using precise-watcher is as simple as adding the following to your package.json and running npm run watch:

{
  "precise-watcher": {
    "src": [{
      "pattern": ["**/*"],
      "on": "change",
      "run": [{
        "cmd": "echo",
        "args": ["<file> changed."]
      }]
    }]
  },
  "scripts": {
    "watch": "precise-watcher"
  },
  "devDependency": {
    "precise-watcher": "^1.0.0"
  }
}

To run it, just modify any file not included in your .gitignore file...

Posibilities

This tool allows you to:

  • Run commands on 1 single file when it changes (by using "<file>" in src.run.args).
  • Call as many commands in parallel or serial as you want.
  • Watch not only for changes but errors, removals, addings, ...
  • Watch multiple sources and run multiple scoped commands.
  • Write complex solutions easily.
  • From v2.0: Run all your commands and exit. Useful for production!

Once you see what it does and why you need it, you can use it in any of the following ways: 1. NPM scripts 2. CLI 3. Javascript

Watch files using NPM scripts

Add precise-watcher to your package.json file in the following way:

{
  "precise-watcher": {
    // Your options go here.
  },
  "scripts": {
    // Replace "watch" with whatever you want.
    "watch": "precise-watcher"
  }
}

Then, run the NPM script (npm run watch in this case) and press ctrl + c, as normal, to stop watching files.

Addittionaly, you can remove the options from your package.json file and use a config. file to set your options:

Setting options in a configuration file

Create a config. file called precise-watcher.config.js (for example), and reference it using the --config option in the command you added before.

// precise-watcher.config.js
module.exports = {
  // Your options go here.
}
{
  "scripts": {
    "watch": "precise-watcher --config precise-watcher.config.js"
  }
}

As you can see, you no longer need the precise-watcher property anymore.

Watch files using your console

To start watching file changes: 1. Create a config file called precise-watcher.config.js, for example. 2. Run ./node_modules/.bin/precise-watcher --config precise-watcher.config.js.

To stop watching file changes:

  • Press ctrl + c.

Supported options

Below are a list of options that you can use with precise-watcher:

OptionDefaultsDescription
--cwdprocess.cwd()Directory for chokidar, config file, and child_process.spawn().
--configpackage.jsonPath to your config. file, relative to cwd.

Watch files using js

Should be as easy as:

const { start, stop, shutdown } = require('precise-watcher')

// Resolves to an array of chokidar.watch() instances:
start().then(async (watchers) => {
  // To remove some watchers:
  // Resolves to an array of each watcher.close() result.
  const closedWatchers = await stop(watchers)
  // To remove all watchers:
  const allClosedWatchers = await stop()

  // To exit:
  shutdow() // Calls stop() internally.
}) // ...

With async/await:

const { start, stop, shutdown } = require('precise-watcher')

(async () => {
  try {
    const watchers = await start()
    const closedWatchers = await stop(watchers)
    const allClosedWatchers = await stop()

    shutdown()
  } catch (error) {
    // Log error...
  }
})()

Examples

If you need more inspiration, you can check out these examples:

Run eslint --fix on 1 single file, when it changes

  1. Run npm install eslint --save-dev.
  2. Add the following to your package.json:
{
  "precise-watcher": {
    "src": [{
      "pattern": ["**/*.js"],
      "on": "change",
      "run": [{
        "cmd": "echo",
        "args": [
          "Running eslint <file> --fix"
        ],
        "callNext": "parallel"
      }, {
        "cmd": "eslint",
        "args": [
          "<file>",
          "--fix"
        ],
        "callNext": "serial"
      }, {
        "cmd": "echo",
        "args": ["Done"]
      }]
    }]
  },
  "scripts": {
    "watch": "precise-watcher"
  }
}
  1. Run npm run watch.
  2. Modify any .js file.

Copy /static content to /public. On development, serve /public; on production, exit.

  1. Install requirements: Run npm install live-server precise-watcher@^2.0 cpy-cli --save-dev.
  2. Create some files: /static/index.html and /static/img/favicon.svg, for example.
  3. Add the following to precise-watcher.config.js:
const {NODE_ENV} = process.env;
const isProduction = NODE_ENV === 'production';
const isDevelopment = !isProduction;

module.exports = {
    "src": [].concat(isDevelopment ? {
        "pattern": "public",
        "on": "ready",
        "run": [{
            // Start development server.
            "cmd": "live-server",
            "args": ["public"]
        }]
    } : {
        "pattern": "dist",
        // Empty the /dist dir.
        "run": [{
            "cmd": "rm",
            "args": ["dist -R"]
        }, {
            "cmd": "mkdir",
            "args": ["dist"]
        }]
    }).concat({
        "pattern": ["static/**/*.{jpg,jpeg,png,ico,svg,html}"],
        "baseDir": "static",
        "on": (isProduction
            ? null // Run as soon as possible.
            : ["ready", "change"] // Run when chokidar is ready and when it detects a change.
        )
        "run": {
            // Copy your static content (images and HTMLs), one by one.
            "cmd": "cpy",
            "args": `<file> ../${isDevelopment ? "public" : "dist"} --cwd=static --parents`.split(" ")
        }
    })
};
  1. Update your npm scripts (update your package.json):
"scripts": {
    "start": "precise-watcher --config precise-watcher.config.js",
    "dev": "NODE_ENV=development npm run start",
    "prod": "NODE_ENV=production npm run start"
}
  1. Run npm run dev and wait for your browser to start. Then, modify any file (e.g, static/index.html) and your changes should be visible right away.

  2. When you're done, hit ctrl + c and run npm run prod. Your /dist folder will now contain all your final files.

Supported options

{
  /** @type {?object} (Optional) chokidar options that will apply to all sources. Defaults to the following, as of chokidar@3.5: */
  "chokidar": {
    "persistent": true,
    // Concatenated with src.ignoreFrom sources.
    "ignored": [],
    "ignoreInitial": false,
    "followSymlinks": false,
    // Defaults to value passed via --cwd, "cwd" param in src/start.js' main function, or process.cwd()
    "cwd": "",
    "disableGlobbing": false,
    "usePolling": false,
    "useFsEvents": true,
    "alwaysStat": false,
    "depth": undefined,
    "awaitWriteFinish": false,
    "ignorePermissionErrors": false,
    "atomic": true
  },
  /** @type {object|object[]} Source(s) to watch. */
  "src": [{
    /** @type {string|RegExp|string[]|RegExp[]} Pattern(s) to watch. */
    "pattern": [],
    /** @type {?string} (Optional) Set "<file>" replacement relative to this value. Basically: path.relative(baseDir, watchedFile). Useful to convert /some/path/file to /file, for example */
    "baseDir": "",
    /** @type {?string} A path to a .gitignore-like file to ignore sources matched by src.pattern. Relative to cwd. */
    "ignoreFrom": ".gitignore",
    /** @type {object|object[]} An array of commands. */
    "run": [{
      /** @type {?string} The command to run. */
      "cmd": "",
      /**
       * @type {?string[]} List of arguments for cmd.
       *
       * Use "<file>" to replace it with the changed filepath if the event
       * supports it, or set each src.pattern value as default (and call
       * this command in parallel multiple times with each given pattern).
       */
      "args": [],
      /** @type {?string} Any of "serial" or "parallel". Defaults to "serial". */
      "callNext": "serial",
      /**
       * @type {?function} A function triggered before running the command.
       * @return {?boolean} If false is returned, the command won't run.
       */
      beforeRun (cmdInfo, eventInfo) {
        const {
          callNext,
          patterns,
          baseDir,
          commands
        } = this;
        const {
          cmd,
          args: cmdArgs,
          options: cmdOptions
        } = cmdInfo;
        const {
          name: eventName,
          args: eventArgs
        } = eventInfo;
        let keepRunning = true;

        return keepRunning;
      }
    }],
    /** @see https://github.com/paulmillr/chokidar */
    /** @type {?string[]|?string} One or many chokidar events: "add", "unlink", "addDir", "unlinkDir", "error", "ready", "raw". */
    "on": [],
    /** @see https://github.com/paulmillr/chokidar */
    /** @type {?object} Chokidar options that will apply to these sources only. Merged with global "chokidar" options. */
    "chokidar": {}
  }]
}

Credits

Thanks to Chokidar's author and contributors and this project's contributors.

License

This project is MIT Licensed.