├── .gitignore ├── index.js ├── package.json ├── README.md └── bin └── wait-run.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require("./bin/wait-run.js"); 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wait-run", 3 | "version": "1.2.0", 4 | "description": "Wait for a file or directory to change then run a command", 5 | "main": "index.js", 6 | "scripts": {}, 7 | "author": "Rick Wong", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/RickWong/wait-run.git" 11 | }, 12 | "bin": { 13 | "wait-run": "./bin/wait-run.js" 14 | }, 15 | "homepage": "https://github.com/RickWong/wait-run", 16 | "license": "BSD-3-Clause", 17 | "dependencies": { 18 | "commander": "2.9.0", 19 | "gaze": "0.5.2", 20 | "passthru": "0.4.0" 21 | }, 22 | "keywords": [ 23 | "wait", 24 | "file", 25 | "directory", 26 | "run", 27 | "command", 28 | "script", 29 | "cli" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wait-run 2 | 3 | [![version](https://img.shields.io/npm/v/wait-run.svg)](https://npmjs.org/package/wait-run) ![license](https://img.shields.io/npm/l/wait-run.svg) ![installs](https://img.shields.io/npm/dt/wait-run.svg) 4 | 5 | Wait for a file or directory to change or appear, then run a command once. The watched file or directory does not have to exist yet. 6 | 7 | Heavily based on the wonderful [watch-run](https://github.com/queckezz/watch-run) by [@queckezz](https://twitter.com/queckezz). 8 | 9 | Simply need to wait for a file/directory? Use [just-wait](https://github.com/download/just-wait) by [@Download](https://twitter.com/stijndewitt) which is a fork of wait-run. It allows you to chain `&&` commands. 10 | 11 | ## Installation 12 | 13 | ```bash 14 | npm install -g wait-run 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```bash 20 | wait-run --pattern '*.*' -- say hello # waits for any change in cwd then runs once. 21 | ``` 22 | 23 | ## License 24 | 25 | BSD 3-Clause license. Copyright © 2016, Rick Wong. All rights reserved. 26 | -------------------------------------------------------------------------------- /bin/wait-run.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | var passthru = require('passthru'); 7 | var program = require('commander'); 8 | var join = require('path').join; 9 | var Gaze = require('gaze').Gaze; 10 | var delay = 0; 11 | 12 | var list = function(val) { 13 | return val.split(',').map(function(val) { 14 | return val.trim() 15 | }) 16 | } 17 | 18 | /** 19 | * Options. 20 | */ 21 | program 22 | .usage('') 23 | .option('-p, --pattern ', 'glob pattern. "," separates multiple patterns.\n' + 24 | ' More info: https://github.com/isaacs/minimatch', list, '**') 25 | .option('-i, --initial', 'run on initial startup', false) 26 | .option('-d, --delay ', 'delay execution of for a number of milliseconds', parseInt) 27 | 28 | /** 29 | * Examples. 30 | */ 31 | program.on('--help', function() { 32 | console.log() 33 | console.log(' Examples:') 34 | console.log() 35 | console.log(' # watch dir and execute cmd') 36 | console.log(' $ wait-run -p \'lib/**\' cat package.json') 37 | console.log() 38 | console.log(' # watch dir "lib" and "src" and execute cmd') 39 | console.log(' $ wait-run -p \'lib/**,src/**\' cat package.json') 40 | console.log() 41 | }) 42 | 43 | /** 44 | * Parse argv. 45 | */ 46 | program.parse(process.argv); 47 | 48 | /** 49 | * Get command. 50 | */ 51 | var command = program.args.join(' '); 52 | var run = false; 53 | 54 | /** 55 | * Run initial execution if required. 56 | */ 57 | if (program.initial) { 58 | execute(); 59 | run = false; 60 | } 61 | 62 | /** 63 | * Set requested delay after initial execution. 64 | */ 65 | delay = program.delay || 0; 66 | 67 | /** 68 | * Watch. 69 | */ 70 | var watch = new Gaze(program.pattern); 71 | watch.on('all', execute); 72 | watch.on('nomatch', nomatch); 73 | 74 | /** 75 | * Execute command when file in dir changes. 76 | * 77 | * @param {String} event 78 | * @param {String} path 79 | */ 80 | function execute(event, path) { 81 | if (run) { 82 | return; 83 | } 84 | 85 | run = true; 86 | 87 | setTimeout(function() { 88 | passthru(command, [], function (err) { 89 | if (event) { 90 | process.exit(err); 91 | } 92 | }); 93 | }, delay); 94 | } 95 | 96 | /** 97 | * If the pattern couldn't be found, then keep globbing until a match is found. 98 | */ 99 | function nomatch() { 100 | watch.close(); 101 | 102 | if (run) { 103 | return; 104 | } 105 | 106 | setTimeout(function () { 107 | watch = new Gaze(program.pattern); 108 | watch.on('all', execute); 109 | watch.on('nomatch', nomatch); // Recursion 110 | watch.on('ready', function(watcher) { 111 | var keys = Object.keys(watcher._watched); 112 | if (keys && keys.length) { 113 | execute('added', watcher._watched[keys[0]]); 114 | } 115 | }); 116 | }, delay || 500); 117 | } 118 | --------------------------------------------------------------------------------