1 | # Watchr — better file system watching for Node.js
|
2 |
|
3 |
|
4 |
|
5 | [![Build Status](http://img.shields.io/travis-ci/bevry/watchr.png?branch=master)](http://travis-ci.org/bevry/watchr "Check this project's build status on TravisCI")
|
6 | [![NPM version](http://badge.fury.io/js/watchr.png)](https://npmjs.org/package/watchr "View this project on NPM")
|
7 | [![Gittip donate button](http://img.shields.io/gittip/bevry.png)](https://www.gittip.com/bevry/ "Donate weekly to this project using Gittip")
|
8 | [![Flattr donate button](http://img.shields.io/flattr/donate.png?color=yellow)](http://flattr.com/thing/344188/balupton-on-Flattr "Donate monthly to this project using Flattr")
|
9 | [![PayPayl donate button](http://img.shields.io/paypal/donate.png?color=yellow)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QB8GQPZAH84N6 "Donate once-off to this project using Paypal")
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | Watchr provides a normalised API the file watching APIs of different node versions, nested/recursive file and directory watching, and accurate detailed events for file/directory creations, updates, and deletions.
|
15 |
|
16 | Watchr is made to be a module that other tools include. If you are looking for a command line tool to perform actions when files are changed, check out [Watchy](https://github.com/caseywebdev/watchy).
|
17 |
|
18 | You install it via `npm install watchr` and use it via `require('watchr').watch(config)`. Available configuration options are:
|
19 |
|
20 | - `path` a single path to watch
|
21 | - `paths` an array of paths to watch
|
22 | - `listener` a single change listener to fire when a change occurs
|
23 | - `listeners` an array of listeners to fire when a change occurs, overloaded to accept the following values:
|
24 | - `changeListener` a single change listener
|
25 | - `[changeListener]` an array of change listeners
|
26 | - `{eventName:eventListener}` an object keyed with the event names and valued with a single event listener
|
27 | - `{eventName:[eventListener]}` an object keyed with the event names and valued with an array of event listeners
|
28 | - `next` (optional, defaults to `null`) a completion callback to fire once the watchers have been setup, arguments are:
|
29 | - when using the `path` configuration option: `err, watcherInstance`
|
30 | - when using the `paths` configuration option: `err, [watcherInstance,...]`
|
31 | - `stat` (optional, defaults to `null`) a file stat object to use for the path, instead of fetching a new one
|
32 | - `interval` (optional, defaults to `5007`) for systems that poll to detect file changes, how often should it poll in millseconds
|
33 | - `persistent` (optional, defaults to `true`) whether or not we should keep the node process alive for as long as files are still being watched
|
34 | - `catchupDelay` (optional, defaults to `2000`) because swap files delete the original file, then rename a temporary file over-top of the original file, to ensure the change is reported correctly we must have a delay in place that waits until all change events for that file have finished, before starting the detection of what changed
|
35 | - `preferredMethods` (optional, defaults to `['watch','watchFile']`) which order should we prefer our watching methods to be tried?
|
36 | - `followLinks` (optional, defaults to `true`) follow symlinks, i.e. use stat rather than lstat
|
37 | - `ignorePaths` (optional, defaults to `false`) an array of full paths to ignore
|
38 | - `ignoreHiddenFiles` (optional, defaults to `false`) whether or not to ignored files which filename starts with a `.`
|
39 | - `ignoreCommonPatterns` (optional, defaults to `true`) whether or not to ignore common undesirable file patterns (e.g. `.svn`, `.git`, `.DS_Store`, `thumbs.db`, etc)
|
40 | - `ignoreCustomPatterns` (optional, defaults to `null`) any custom ignore patterns that you would also like to ignore along with the common patterns
|
41 |
|
42 | The following events are available to your via the listeners:
|
43 |
|
44 | - `log` for debugging, receives the arguments `logLevel ,args...`
|
45 | - `error` for gracefully listening to error events, receives the arguments `err`
|
46 | - you should always have an error listener, otherwise node.js's behavior is to throw the error and possibly crash your application, see [#40](https://github.com/bevry/watchr/issues/40)
|
47 | - `watching` for when watching of the path has completed, receives the arguments `err, isWatching`
|
48 | - `change` for listening to change events, receives the arguments `changeType, fullPath, currentStat, previousStat`, received arguments will be:
|
49 | - for updated files: `'update', fullPath, currentStat, previousStat`
|
50 | - for created files: `'create', fullPath, currentStat, null`
|
51 | - for deleted files: `'delete', fullPath, null, previousStat`
|
52 |
|
53 |
|
54 | To wrap it all together, it would look like this:
|
55 |
|
56 | ``` javascript
|
57 | // Require
|
58 | var watchr = require('watchr');
|
59 |
|
60 | // Watch a directory or file
|
61 | console.log('Watch our paths');
|
62 | watchr.watch({
|
63 | paths: ['path1','path2','path3'],
|
64 | listeners: {
|
65 | log: function(logLevel){
|
66 | console.log('a log message occured:', arguments);
|
67 | },
|
68 | error: function(err){
|
69 | console.log('an error occured:', err);
|
70 | },
|
71 | watching: function(err,watcherInstance,isWatching){
|
72 | if (err) {
|
73 | console.log("watching the path " + watcherInstance.path + " failed with error", err);
|
74 | } else {
|
75 | console.log("watching the path " + watcherInstance.path + " completed");
|
76 | }
|
77 | },
|
78 | change: function(changeType,filePath,fileCurrentStat,filePreviousStat){
|
79 | console.log('a change event occured:',arguments);
|
80 | }
|
81 | },
|
82 | next: function(err,watchers){
|
83 | if (err) {
|
84 | return console.log("watching everything failed with error", err);
|
85 | } else {
|
86 | console.log('watching everything completed', watchers);
|
87 | }
|
88 |
|
89 | // Close watchers after 60 seconds
|
90 | setTimeout(function(){
|
91 | var i;
|
92 | console.log('Stop watching our paths');
|
93 | for ( i=0; i<watchers.length; i++ ) {
|
94 | watchers[i].close();
|
95 | }
|
96 | },60*1000);
|
97 | }
|
98 | });
|
99 | ```
|
100 |
|
101 | You can test the above code snippet by running the following:
|
102 |
|
103 | ```
|
104 | npm install -g watchr
|
105 | watchr
|
106 | ```
|
107 |
|
108 |
|
109 |
|
110 |
|
111 | ## History
|
112 | [Discover the change history by heading on over to the `HISTORY.md` file.](https://github.com/bevry/watchr/blob/master/HISTORY.md#files)
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 | ## Contribute
|
120 |
|
121 | [Discover how you can contribute by heading on over to the `CONTRIBUTING.md` file.](https://github.com/bevry/watchr/blob/master/CONTRIBUTING.md#files)
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 | ## Backers
|
129 |
|
130 | ### Maintainers
|
131 |
|
132 | These amazing people are maintaining this project:
|
133 |
|
134 | - Benjamin Lupton <b@lupton.cc> (http://balupton.com)
|
135 |
|
136 | ### Sponsors
|
137 |
|
138 | No sponsors yet! Will you be the first?
|
139 |
|
140 | [![Gittip donate button](http://img.shields.io/gittip/bevry.png)](https://www.gittip.com/bevry/ "Donate weekly to this project using Gittip")
|
141 | [![Flattr donate button](http://img.shields.io/flattr/donate.png?color=yellow)](http://flattr.com/thing/344188/balupton-on-Flattr "Donate monthly to this project using Flattr")
|
142 | [![PayPayl donate button](http://img.shields.io/paypal/donate.png?color=yellow)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QB8GQPZAH84N6 "Donate once-off to this project using Paypal")
|
143 |
|
144 | ### Contributors
|
145 |
|
146 | These amazing people have contributed code to this project:
|
147 |
|
148 | - [adamsanderson](https://github.com/adamsanderson) — [view contributions](https://github.com/bevry/watchr/commits?author=adamsanderson)
|
149 | - [balupton](https://github.com/balupton) — [view contributions](https://github.com/bevry/watchr/commits?author=balupton)
|
150 | - [Casey Foster](https://github.com/caseywebdev) — [view contributions](https://github.com/bevry/watchr/commits?author=caseywebdev)
|
151 | - [FredrikNoren](https://github.com/FredrikNoren) — [view contributions](https://github.com/bevry/watchr/commits?author=FredrikNoren)
|
152 | - [Robson Roberto Souza Peixoto](https://github.com/robsonpeixoto) <robsonpeixoto@gmail.com> — [view contributions](https://github.com/bevry/watchr/commits?author=robsonpeixoto)
|
153 |
|
154 | [Become a contributor!](https://github.com/bevry/watchr/blob/master/CONTRIBUTING.md#files)
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 | ## License
|
162 |
|
163 | Licensed under the incredibly [permissive](http://en.wikipedia.org/wiki/Permissive_free_software_licence) [MIT license](http://creativecommons.org/licenses/MIT/)
|
164 |
|
165 | Copyright © 2012+ Bevry Pty Ltd <us@bevry.me> (http://bevry.me)
|
166 | <br/>Copyright © 2011 Benjamin Lupton <b@lupton.cc> (http://balupton.com)
|
167 |
|
168 |
|
169 |
|
170 |
|