1 | # Watchr — better file system watching for Node.js
|
2 |
|
3 | [![Build Status](https://secure.travis-ci.org/bevry/watchr.png?branch=master)](http://travis-ci.org/bevry/watchr)
|
4 | [![NPM version](https://badge.fury.io/js/watchr.png)](https://npmjs.org/package/watchr)
|
5 | [![Flattr this project](https://raw.github.com/balupton/flattr-buttons/master/badge-89x18.gif)](http://flattr.com/thing/344188/balupton-on-Flattr)
|
6 |
|
7 | 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.
|
8 |
|
9 | You install it via `npm install watchr` and use it via `require('watchr').watch(config)`. Available configuration options are:
|
10 |
|
11 | - `path` a single path to watch
|
12 | - `paths` an array of paths to watch
|
13 | - `listener` a single change listener to fire when a change occurs
|
14 | - `listeners` an array of listeners to fire when a change occurs, overloaded to accept the following values:
|
15 | - `changeListener` a single change listener
|
16 | - `[changeListener]` an array of change listeners
|
17 | - `{eventName:eventListener}` an object keyed with the event names and valued with a single event listener
|
18 | - `{eventName:[eventListener]}` an object keyed with the event names and valued with an array of event listeners
|
19 | - `next` (optional, defaults to `null`) a completion callback to fire once the watchers have been setup, arguments are:
|
20 | - when using the `path` configuration option: `err, watcherInstance`
|
21 | - when using the `paths` configuration option: `err, [watcherInstance,...]`
|
22 | - `stat` (optional, defaults to `null`) a file stat object to use for the path, instead of fetching a new one
|
23 | - `interval` (optional, defaults to `5007`) for systems that poll to detect file changes, how often should it poll in millseconds
|
24 | - `persistent` (optional, defaults to `true`) whether or not we should keep the node process alive for as long as files are still being watched
|
25 | - `duplicateDelay` (optional, defaults to `1000`) sometimes events will fire really fast, this delay is set in place so we don't fire the same event within the timespan. Set to falsey to perform no duplicate detection.
|
26 | - `preferredMethods` (optional, defaults to `['watch','watchFile']`) which order should we prefer our watching methods to be tried?
|
27 | - `ignorePaths` (optional, defaults to `false`) an array of full paths to ignore
|
28 | - `ignoreHiddenFiles` (optional, defaults to `false`) whether or not to ignored files which filename starts with a `.`
|
29 | - `ignoreCommonPatterns` (optional, defaults to `true`) whether or not to ignore common undesirable file patterns (e.g. `.svn`, `.git`, `.DS_Store`, `thumbs.db`, etc)
|
30 | - `ignoreCustomPatterns` (optional, defaults to `null`) any custom ignore patterns that you would also like to ignore along with the common patterns
|
31 | - `followLinks` (optional, defaults to `true`) follow symlinks, i.e. use stat rather than lstat
|
32 |
|
33 | The following events are available to your via the listeners:
|
34 |
|
35 | - `log` for debugging, receives the arguments `logLevel ,args...`
|
36 | - `error` for gracefully listening to error events, receives the arguments `err`
|
37 | - 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)
|
38 | - `watching` for when watching of the path has completed, receives the arguments `err, isWatching`
|
39 | - `change` for listening to change events, receives the arguments `changeType, fullPath, currentStat, previousStat`, received arguments will be:
|
40 | - for updated files: `'update', fullPath, currentStat, previousStat`
|
41 | - for created files: `'create', fullPath, currentStat, null`
|
42 | - for deleted files: `'delete', fullPath, null, previousStat`
|
43 |
|
44 |
|
45 | To wrap it all together, it would look like this:
|
46 |
|
47 | ``` javascript
|
48 | // Require
|
49 | var watchr = require('watchr');
|
50 |
|
51 | // Watch a directory or file
|
52 | console.log('Watch our paths');
|
53 | watchr.watch({
|
54 | paths: ['path1','path2','path3'],
|
55 | listeners: {
|
56 | log: function(logLevel){
|
57 | console.log('a log message occured:', arguments);
|
58 | },
|
59 | error: function(err){
|
60 | console.log('an error occured:', err);
|
61 | },
|
62 | watching: function(err,watcherInstance,isWatching){
|
63 | if (err) {
|
64 | console.log("watching the path " + watcherInstance.path + " failed with error", err);
|
65 | } else {
|
66 | console.log("watching the path " + watcherInstance.path + " completed");
|
67 | }
|
68 | },
|
69 | change: function(changeType,filePath,fileCurrentStat,filePreviousStat){
|
70 | console.log('a change event occured:',arguments);
|
71 | }
|
72 | },
|
73 | next: function(err,watchers){
|
74 | if (err) {
|
75 | return console.log("watching everything failed with error", err);
|
76 | } else {
|
77 | console.log('watching everything completed', watchers);
|
78 | }
|
79 |
|
80 | // Close watchers after 60 seconds
|
81 | setTimeout(function(){
|
82 | var i;
|
83 | console.log('Stop watching our paths');
|
84 | for ( i=0; i<watchers.length; i++ ) {
|
85 | watchers[i].close();
|
86 | }
|
87 | },60*1000);
|
88 | }
|
89 | });
|
90 | ```
|
91 |
|
92 | You can test the above code snippet by running the following:
|
93 |
|
94 | ```
|
95 | npm install -g watchr
|
96 | watchr
|
97 | ```
|
98 |
|
99 |
|
100 |
|
101 | ## Known Issues
|
102 |
|
103 | - [Text Editor swap files on saving can throw it off.](https://github.com/bevry/watchr/issues/33)
|
104 | - We're working on it. Workaround for the meantime:
|
105 | - For Users:
|
106 | - TextMate: Turn off atomic saves. [Guide.](http://manual.macromates.com/en/saving_files.html)
|
107 | - Sublime Text 3: Add `"atomic_saves": false` to your user preferences
|
108 | - VIM: Disable the `set noswapfile` option and enable the `set nobackup` option
|
109 | - For Watchr implementations:
|
110 | - Set `preferredMethods` to `['watchFile','watch']` that will use the old polling mechanism (slower, but handles this use case)
|
111 |
|
112 | - [`ENOENT` errors are emitted when dead links a broken symlink is encountered](https://github.com/bevry/watchr/issues/42)
|
113 | - We're working on it. No known workaround.
|
114 |
|
115 |
|
116 |
|
117 | ## Support
|
118 | Support can be found in the [GitHub Issue Tracker](https://github.com/bevry/watchr/issues)
|
119 |
|
120 |
|
121 |
|
122 | ## History
|
123 | You can discover the history inside the [History.md](https://github.com/bevry/watchr/blob/master/History.md#files) file
|
124 |
|
125 |
|
126 |
|
127 | ## License
|
128 | Licensed under the incredibly [permissive](http://en.wikipedia.org/wiki/Permissive_free_software_licence) [MIT License](http://creativecommons.org/licenses/MIT/)
|
129 | <br/>Copyright © 2012+ [Bevry Pty Ltd](http://bevry.me)
|
130 | <br/>Copyright © 2011 [Benjamin Lupton](http://balupton.com)
|