Socket
Socket
Sign inDemoInstall

gaze

Package Overview
Dependencies
Maintainers
2
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gaze - npm Package Compare versions

Comparing version 0.6.4 to 1.0.0

482

lib/gaze.js

@@ -5,3 +5,3 @@ /*

*
* Copyright (c) 2014 Kyle Robinson Young
* Copyright (c) 2016 Kyle Robinson Young
* Licensed under the MIT license.

@@ -15,24 +15,22 @@ */

var EE = require('events').EventEmitter;
var fs = require('graceful-fs');
var fs = require('fs');
var path = require('path');
var globule = require('globule');
var nextback = require('nextback');
var helper = require('./helper');
var platform = require('./platform');
var isAbsolute = require('absolute-path');
// keep track of instances to call multiple times for backwards compatibility
var instances = [];
// shim setImmediate for node v0.8
var setImmediate = require('timers').setImmediate;
if (typeof setImmediate !== 'function') {
setImmediate = process.nextTick;
}
// globals
var delay = 10;
// `Gaze` EventEmitter object to return in the callback
function Gaze(patterns, opts, done) {
function Gaze (patterns, opts, done) {
var self = this;
EE.call(self);
// Optional arguments
if (typeof patterns === 'function') {
done = patterns;
patterns = null;
opts = {};
}
// If second arg is the callback
if (typeof opts === 'function') {

@@ -46,3 +44,3 @@ done = opts;

opts.mark = true;
opts.interval = opts.interval || 500;
opts.interval = opts.interval || 100;
opts.debounceDelay = opts.debounceDelay || 500;

@@ -52,17 +50,4 @@ opts.cwd = opts.cwd || process.cwd();

// Default error handler to prevent emit('error') throwing magically for us
this.on('error', function(error) {
if (self.listeners('error').length > 1) {
return self.removeListener('error', this);
}
nextback(function() {
done.call(self, error, self);
})();
});
// File watching mode to use when adding files to the platform
this._mode = opts.mode || 'auto';
// Default done callback
done = done || function() {};
done = done || function () {};

@@ -97,13 +82,4 @@ // Remember our watched dir:files

// keep the process alive
this._keepalive = setInterval(platform.tick.bind(platform), opts.interval);
this._keepalive = setInterval(function () {}, 200);
// Keep track of all instances created
this._instanceNum = instances.length;
instances.push(this);
// Keep track of safewriting and debounce timeouts
this._safewriting = null;
this._safewriteTimeout = null;
this._timeoutId = null;
return this;

@@ -114,3 +90,3 @@ }

// Main entry point. Start watching and call done when setup
module.exports = function gaze(patterns, opts, done) {
module.exports = function gaze (patterns, opts, done) {
return new Gaze(patterns, opts, done);

@@ -122,3 +98,3 @@ };

// and debounce on duplicate events per file
Gaze.prototype.emit = function() {
Gaze.prototype.emit = function () {
var self = this;

@@ -129,2 +105,3 @@ var args = arguments;

var filepath = args[1];
var timeoutId;

@@ -139,3 +116,3 @@ // If not added/deleted/changed/renamed then just emit the event

if (e === 'added') {
Object.keys(this._cached).forEach(function(oldFile) {
Object.keys(this._cached).forEach(function (oldFile) {
if (self._cached[oldFile].indexOf('deleted') !== -1) {

@@ -150,22 +127,2 @@ args[0] = e = 'renamed';

// Detect safewrite events, if file is deleted and then added/renamed, assume a safewrite happened
if (e === 'deleted' && this._safewriting == null) {
this._safewriting = filepath;
this._safewriteTimeout = setTimeout(function() {
// Just a normal delete, carry on
Gaze.super_.prototype.emit.apply(self, args);
Gaze.super_.prototype.emit.apply(self, ['all', e].concat([].slice.call(args, 1)));
self._safewriting = null;
}, this.options.debounceDelay);
return this;
} else if ((e === 'added' || e === 'renamed') && this._safewriting === filepath) {
clearTimeout(this._safewriteTimeout);
this._safewriteTimeout = setTimeout(function() {
self._safewriting = null;
}, this.options.debounceDelay);
args[0] = e = 'changed';
} else if (e === 'deleted' && this._safewriting === filepath) {
return this;
}
// If cached doesnt exist, create a delay before running the next

@@ -176,4 +133,4 @@ // then emit the event

helper.objectPush(self._cached, filepath, e);
clearTimeout(this._timeoutId);
this._timeoutId = setTimeout(function() {
clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
delete self._cached[filepath];

@@ -189,7 +146,7 @@ }, this.options.debounceDelay);

if (helper.isDir(filepath)) {
fs.readdirSync(filepath).map(function(file) {
fs.readdirSync(filepath).map(function (file) {
return path.join(filepath, file);
}).filter(function(file) {
}).filter(function (file) {
return globule.isMatch(self._patterns, file, self.options);
}).forEach(function(file) {
}).forEach(function (file) {
self.emit('added', file);

@@ -204,171 +161,292 @@ });

// Close watchers
Gaze.prototype.close = function(_reset) {
instances.splice(this._instanceNum, 1);
platform.closeAll();
this.emit('end');
Gaze.prototype.close = function (_reset) {
var self = this;
Object.keys(self._watchers).forEach(function (file) {
self._watchers[file].close();
});
self._watchers = Object.create(null);
Object.keys(this._watched).forEach(function (dir) {
self._unpollDir(dir);
});
if (_reset !== false) {
self._watched = Object.create(null);
setTimeout(function () {
self.emit('end');
self.removeAllListeners();
clearInterval(self._keepalive);
}, delay + 100);
}
return self;
};
// Add file patterns to be watched
Gaze.prototype.add = function(files, done) {
var self = this;
Gaze.prototype.add = function (files, done) {
if (typeof files === 'string') { files = [files]; }
this._patterns = helper.unique.apply(null, [this._patterns, files]);
files = globule.find(this._patterns, this.options);
this._addToWatched(files);
this.close(false);
this._initWatched(done);
};
// If no matching files
if (files.length < 1) {
// Defer to emitting to give a chance to attach event handlers.
nextback(function() {
self.emit('ready', self);
if (done) done.call(self, null, self);
self.emit('nomatch');
})();
return;
}
// Set the platform mode before adding files
platform.mode = self._mode;
helper.forEachSeries(files, function(file, next) {
try {
var filepath = (!isAbsolute(file)) ? path.join(self.options.cwd, file) : file;
platform(filepath, self._trigger.bind(self));
} catch (err) {
self.emit('error', err);
// Dont increment patterns and dont call done if nothing added
Gaze.prototype._internalAdd = function (file, done) {
var files = [];
if (helper.isDir(file)) {
files = [helper.markDir(file)].concat(globule.find(this._patterns, this.options));
} else {
if (globule.isMatch(this._patterns, file, this.options)) {
files = [file];
}
next();
}, function() {
// A little delay here for backwards compatibility, lol
setTimeout(function() {
self.emit('ready', self);
if (done) done.call(self, null, self);
}, 10);
});
};
// Call when the platform has triggered
Gaze.prototype._trigger = function(error, event, filepath, newFile) {
if (error) { return this.emit('error', error); }
// Set the platform mode before adding files
platform.mode = this._mode;
if (event === 'change' && helper.isDir(filepath)) {
this._wasAdded(filepath);
} else if (event === 'change') {
this._emitAll('changed', filepath);
} else if (event === 'delete') {
// Close out deleted filepaths (important to make safewrite detection work)
platform.close(filepath);
this._emitAll('deleted', filepath);
} else if (event === 'rename') {
// TODO: This occasionally throws, figure out why or use the old style rename detect
// The handle(26) returned by watching [filename] is the same with an already watched path([filename])
this._emitAll('renamed', newFile, filepath);
}
if (files.length > 0) {
this._addToWatched(files);
this.close(false);
this._initWatched(done);
}
};
// If a folder received a change event, investigate
Gaze.prototype._wasAdded = function(dir) {
// Remove file/dir from `watched`
Gaze.prototype.remove = function (file) {
var self = this;
var dirstat = fs.statSync(dir);
fs.readdir(dir, function(err, current) {
if (err) {
self.emit('error', err);
return;
}
helper.forEachSeries(current, function(file, next) {
var filepath = path.join(dir, file);
if (!fs.existsSync(filepath)) return next();
var stat = fs.lstatSync(filepath);
if ((dirstat.mtime - stat.mtime) <= 0) {
var relpath = path.relative(self.options.cwd, filepath);
if (stat.isDirectory()) {
// If it was a dir, watch the dir and emit that it was added
platform(filepath, self._trigger.bind(self));
if (globule.isMatch(self._patterns, relpath, self.options)) {
self._emitAll('added', filepath);
}
self._wasAddedSub(filepath);
} else if (globule.isMatch(self._patterns, relpath, self.options)) {
// Otherwise if the file matches, emit added
platform(filepath, self._trigger.bind(self));
if (globule.isMatch(self._patterns, relpath, self.options)) {
self._emitAll('added', filepath);
}
}
if (this._watched[file]) {
// is dir, remove all files
this._unpollDir(file);
delete this._watched[file];
} else {
// is a file, find and remove
Object.keys(this._watched).forEach(function (dir) {
var index = self._watched[dir].indexOf(file);
if (index !== -1) {
self._unpollFile(file);
self._watched[dir].splice(index, 1);
return false;
}
next();
});
});
}
if (this._watchers[file]) {
this._watchers[file].close();
}
return this;
};
// If a sub folder was added, investigate further
// Such as with grunt.file.write('new_dir/tmp.js', '') as it will create the folder and file simultaneously
Gaze.prototype._wasAddedSub = function(dir) {
// Return watched files
Gaze.prototype.watched = function () {
return this._watched;
};
// Returns `watched` files with relative paths to process.cwd()
Gaze.prototype.relative = function (dir, unixify) {
var self = this;
fs.readdir(dir, function(err, current) {
helper.forEachSeries(current, function(file, next) {
var filepath = path.join(dir, file);
var relpath = path.relative(self.options.cwd, filepath);
try {
if (fs.lstatSync(filepath).isDirectory()) {
self._wasAdded(filepath);
} else if (globule.isMatch(self._patterns, relpath, self.options)) {
// Make sure to watch the newly added sub file
platform(filepath, self._trigger.bind(self));
self._emitAll('added', filepath);
}
} catch (err) {
self.emit('error', err);
var relative = Object.create(null);
var relDir, relFile, unixRelDir;
var cwd = this.options.cwd || process.cwd();
if (dir === '') { dir = '.'; }
dir = helper.markDir(dir);
unixify = unixify || false;
Object.keys(this._watched).forEach(function (dir) {
relDir = path.relative(cwd, dir) + path.sep;
if (relDir === path.sep) { relDir = '.'; }
unixRelDir = unixify ? helper.unixifyPathSep(relDir) : relDir;
relative[unixRelDir] = self._watched[dir].map(function (file) {
relFile = path.relative(path.join(cwd, relDir) || '', file || '');
if (helper.isDir(file)) {
relFile = helper.markDir(relFile);
}
next();
if (unixify) {
relFile = helper.unixifyPathSep(relFile);
}
return relFile;
});
});
if (dir && unixify) {
dir = helper.unixifyPathSep(dir);
}
return dir ? relative[dir] || [] : relative;
};
// Wrapper for emit to ensure we emit on all instances
Gaze.prototype._emitAll = function() {
var args = Array.prototype.slice.call(arguments);
for (var i = 0; i < instances.length; i++) {
instances[i].emit.apply(instances[i], args);
// Adds files and dirs to watched
Gaze.prototype._addToWatched = function (files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var filepath = path.resolve(this.options.cwd, file);
var dirname = (helper.isDir(file)) ? filepath : path.dirname(filepath);
dirname = helper.markDir(dirname);
// If a new dir is added
if (helper.isDir(file) && !(filepath in this._watched)) {
helper.objectPush(this._watched, filepath, []);
}
if (file.slice(-1) === '/') { filepath += path.sep; }
helper.objectPush(this._watched, path.dirname(filepath) + path.sep, filepath);
// add folders into the mix
var readdir = fs.readdirSync(dirname);
for (var j = 0; j < readdir.length; j++) {
var dirfile = path.join(dirname, readdir[j]);
if (fs.lstatSync(dirfile).isDirectory()) {
helper.objectPush(this._watched, dirname, dirfile + path.sep);
}
}
}
return this;
};
// Remove file/dir from `watched`
Gaze.prototype.remove = function(file) {
platform.close(file);
Gaze.prototype._watchDir = function (dir, done) {
var self = this;
var timeoutId;
try {
this._watchers[dir] = fs.watch(dir, function (event) {
// race condition. Let's give the fs a little time to settle down. so we
// don't fire events on non existent files.
clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
// race condition. Ensure that this directory is still being watched
// before continuing.
if ((dir in self._watchers) && fs.existsSync(dir)) {
done(null, dir);
}
}, delay + 100);
});
} catch (err) {
return this._handleError(err);
}
return this;
};
// Return watched files
Gaze.prototype.watched = function(done) {
done = nextback(done || function() {});
helper.flatToTree(platform.getWatchedPaths(), this.options.cwd, false, false, done);
Gaze.prototype._unpollFile = function (file) {
if (this._pollers[file]) {
fs.unwatchFile(file, this._pollers[file]);
delete this._pollers[file];
}
return this;
};
// Returns `watched` files with relative paths to cwd
Gaze.prototype.relative = function(dir, unixify, done) {
if (typeof dir === 'function') {
done = dir;
dir = null;
unixify = false;
Gaze.prototype._unpollDir = function (dir) {
this._unpollFile(dir);
for (var i = 0; i < this._watched[dir].length; i++) {
this._unpollFile(this._watched[dir][i]);
}
if (typeof unixify === 'function') {
done = unixify;
unixify = false;
};
Gaze.prototype._pollFile = function (file, done) {
var opts = { persistent: true, interval: this.options.interval };
if (!this._pollers[file]) {
this._pollers[file] = function (curr, prev) {
done(null, file);
};
try {
fs.watchFile(file, opts, this._pollers[file]);
} catch (err) {
return this._handleError(err);
}
}
done = nextback(done || function() {});
helper.flatToTree(platform.getWatchedPaths(), this.options.cwd, true, unixify, function(err, relative) {
if (dir) {
if (unixify) {
dir = helper.unixifyPathSep(dir);
}
// Better guess what to return for backwards compatibility
return done(null, relative[dir] || relative[dir + (unixify ? '/' : path.sep)] || []);
}
return done(null, relative);
});
return this;
};
// Initialize the actual watch on `watched` files
Gaze.prototype._initWatched = function (done) {
var self = this;
var cwd = this.options.cwd || process.cwd();
var curWatched = Object.keys(self._watched);
// if no matching files
if (curWatched.length < 1) {
// Defer to emitting to give a chance to attach event handlers.
setImmediate(function () {
self.emit('ready', self);
if (done) { done.call(self, null, self); }
self.emit('nomatch');
});
return;
}
helper.forEachSeries(curWatched, function (dir, next) {
dir = dir || '';
var files = self._watched[dir];
// Triggered when a watched dir has an event
self._watchDir(dir, function (event, dirpath) {
var relDir = cwd === dir ? '.' : path.relative(cwd, dir);
relDir = relDir || '';
fs.readdir(dirpath, function (err, current) {
if (err) { return self.emit('error', err); }
if (!current) { return; }
try {
// append path.sep to directories so they match previous.
current = current.map(function (curPath) {
if (fs.existsSync(path.join(dir, curPath)) && fs.lstatSync(path.join(dir, curPath)).isDirectory()) {
return curPath + path.sep;
} else {
return curPath;
}
});
} catch (err) {
// race condition-- sometimes the file no longer exists
}
// Get watched files for this dir
var previous = self.relative(relDir);
// If file was deleted
previous.filter(function (file) {
return current.indexOf(file) < 0;
}).forEach(function (file) {
if (!helper.isDir(file)) {
var filepath = path.join(dir, file);
self.remove(filepath);
self.emit('deleted', filepath);
}
});
// If file was added
current.filter(function (file) {
return previous.indexOf(file) < 0;
}).forEach(function (file) {
// Is it a matching pattern?
var relFile = path.join(relDir, file);
// Add to watch then emit event
self._internalAdd(relFile, function () {
self.emit('added', path.join(dir, file));
});
});
});
});
// Watch for change/rename events on files
files.forEach(function (file) {
if (helper.isDir(file)) { return; }
self._pollFile(file, function (err, filepath) {
if (err) {
self.emit('error', err);
return;
}
// Only emit changed if the file still exists
// Prevents changed/deleted duplicate events
if (fs.existsSync(filepath)) {
self.emit('changed', filepath);
}
});
});
next();
}, function () {
// Return this instance of Gaze
// delay before ready solves a lot of issues
setTimeout(function () {
self.emit('ready', self);
if (done) { done.call(self, null, self); }
}, delay + 100);
});
};
// If an error, handle it here
Gaze.prototype._handleError = function (err) {
if (err.code === 'EMFILE') {
return this.emit('error', new Error('EMFILE: Too many opened files.'));
}
return this.emit('error', err);
};

@@ -1,9 +0,1 @@

/*
* gaze
* https://github.com/shama/gaze
*
* Copyright (c) 2014 Kyle Robinson Young
* Licensed under the MIT license.
*/
'use strict';

@@ -15,17 +7,25 @@

// Returns boolean whether filepath is dir terminated
helper.isDir = function isDir(dir) {
if (typeof dir !== 'string') { return false; }
return (dir.slice(-(path.sep.length)) === path.sep) || (dir.slice(-1) === '/');
helper.isDir = function isDir (dir) {
if (typeof dir !== 'string') {
return false;
}
return (dir.slice(-(path.sep.length)) === path.sep);
};
// Create a `key:[]` if doesnt exist on `obj` then push or concat the `val`
helper.objectPush = function objectPush(obj, key, val) {
if (obj[key] == null) { obj[key] = []; }
if (Array.isArray(val)) { obj[key] = obj[key].concat(val); }
else if (val) { obj[key].push(val); }
return obj[key] = helper.unique(obj[key]);
helper.objectPush = function objectPush (obj, key, val) {
if (obj[key] == null) {
obj[key] = [];
}
if (Array.isArray(val)) {
obj[key] = obj[key].concat(val);
} else if (val) {
obj[key].push(val);
}
obj[key] = helper.unique(obj[key]);
return obj[key];
};
// Ensures the dir is marked with path.sep
helper.markDir = function markDir(dir) {
helper.markDir = function markDir (dir) {
if (typeof dir === 'string' &&

@@ -40,49 +40,6 @@ dir.slice(-(path.sep.length)) !== path.sep &&

// Changes path.sep to unix ones for testing
helper.unixifyPathSep = function unixifyPathSep(filepath) {
helper.unixifyPathSep = function unixifyPathSep (filepath) {
return (process.platform === 'win32') ? String(filepath).replace(/\\/g, '/') : filepath;
};
// Converts a flat list of paths to the old style tree
helper.flatToTree = function flatToTree(files, cwd, relative, unixify, done) {
cwd = helper.markDir(cwd);
var tree = Object.create(null);
helper.forEachSeries(files, function(filepath, next) {
var parent = path.dirname(filepath) + path.sep;
// If parent outside cwd, ignore
if (path.relative(cwd, parent) === '..') {
return next();
}
// If we want relative paths
if (relative === true) {
if (path.resolve(parent) === path.resolve(cwd)) {
parent = './';
} else {
parent = path.relative(cwd, parent) + path.sep;
}
filepath = path.relative(path.join(cwd, parent), filepath) + (helper.isDir(filepath) ? path.sep : '');
}
// If we want to transform paths to unix seps
if (unixify === true) {
filepath = helper.unixifyPathSep(filepath);
if (parent !== './') {
parent = helper.unixifyPathSep(parent);
}
}
if (!parent) { return next(); }
if (!Array.isArray(tree[parent])) {
tree[parent] = [];
}
tree[parent].push(filepath);
next();
}, function() {
done(null, tree);
});
};
/**

@@ -95,3 +52,12 @@ * Lo-Dash 1.0.1 <http://lodash.com/>

*/
helper.unique = function unique() { var array = Array.prototype.concat.apply(Array.prototype, arguments); var result = []; for (var i = 0; i < array.length; i++) { if (result.indexOf(array[i]) === -1) { result.push(array[i]); } } return result; };
helper.unique = function unique () {
var array = Array.prototype.concat.apply(Array.prototype, arguments);
var result = [];
for (var i = 0; i < array.length; i++) {
if (result.indexOf(array[i]) === -1) {
result.push(array[i]);
}
}
return result;
};

@@ -102,7 +68,4 @@ /**

*/
helper.forEachSeries = function forEachSeries(arr, iterator, callback) {
callback = callback || function () {};
if (!arr.length) {
return callback();
}
helper.forEachSeries = function forEachSeries (arr, iterator, callback) {
if (!arr.length) { return callback(); }
var completed = 0;

@@ -114,6 +77,5 @@ var iterate = function () {

callback = function () {};
}
else {
} else {
completed += 1;
if (completed >= arr.length) {
if (completed === arr.length) {
callback(null);

@@ -120,0 +82,0 @@ } else {

{
"name": "gaze",
"description": "A globbing fs.watch wrapper built from the best parts of other fine watch libs.",
"version": "0.6.4",
"version": "1.0.0",
"homepage": "https://github.com/shama/gaze",

@@ -12,3 +12,3 @@ "author": {

"type": "git",
"url": "git://github.com/shama/gaze.git"
"url": "https://github.com/shama/gaze.git"
},

@@ -18,51 +18,39 @@ "bugs": {

},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/shama/gaze/blob/master/LICENSE-MIT"
}
],
"main": "index.js",
"license": "MIT",
"main": "lib/gaze",
"engines": {
"node": ">= 0.8.0"
"node": ">= 0.10.0"
},
"scripts": {
"test": "grunt nodeunit -v",
"install": "node-gyp rebuild"
"test": "semistandard && grunt nodeunit -v"
},
"dependencies": {
"globule": "~0.2.0",
"nextback": "~0.1.0",
"bindings": "~1.2.0",
"nan": "~0.8.0",
"absolute-path": "0.0.0",
"graceful-fs": "~2.0.3"
"globule": "^0.2.0"
},
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-nodeunit": "~0.3.3",
"grunt-contrib-jshint": "~0.9.2",
"async": "^1.5.2",
"grunt": "^0.4.5",
"grunt-benchmark": "~0.2.0",
"grunt-cli": "~0.1.13",
"async": "~0.2.10",
"rimraf": "~2.2.6",
"ascii-table": "0.0.4"
"grunt-contrib-jshint": "^1.0.0",
"grunt-contrib-nodeunit": "^1.0.0",
"rimraf": "^2.5.0",
"semistandard": "^7.0.5"
},
"keywords": [
"watch",
"watcher",
"watching",
"fs.watch",
"fswatcher",
"fs",
"glob",
"utility"
"glob"
],
"files": [
"index.js",
"lib",
"src",
"binding.gyp",
"AUTHORS",
"LICENSE-MIT"
]
],
"semistandard": {
"ignore": [
"benchmarks",
"experiments",
"build",
"test"
]
}
}

@@ -1,20 +0,10 @@

# gaze [![Build Status](http://img.shields.io/travis/shama/gaze.svg)](https://travis-ci.org/shama/gaze) [![gittip.com/shama](http://img.shields.io/gittip/shama.svg)](https://www.gittip.com/shama)
# gaze [![Build Status](http://img.shields.io/travis/shama/gaze.svg)](https://travis-ci.org/shama/gaze) [![Build status](https://ci.appveyor.com/api/projects/status/vtx65w9eg511tgo4)](https://ci.appveyor.com/project/shama/gaze)
A globbing fs.watch wrapper built from the best parts of other fine watch libs.
Compatible with Node.js 0.10/0.8, Windows, OSX and Linux.
Compatible with Node.js 4.x/0.12/0.10, Windows, OSX and Linux.
![gaze](http://dontkry.com/images/repos/gaze.png)
## Features
[![NPM](https://nodei.co/npm/gaze.png?downloads=true)](https://nodei.co/npm/gaze/)
* Consistent events on OSX, Linux and Windows
* Very fast start up and response time
* High test coverage
* Uses native OS events but falls back to stat polling
* Option to force stat polling with special file systems such as networked
* Downloaded over 400K times a month
* Used by [Grunt](http://gruntjs.com), [gulp](http://gulpjs.com), [Tower](http://tower.github.io/) and many others
## Usage

@@ -33,5 +23,3 @@ Install the module with: `npm install gaze` or place into your `package.json`

// Get all watched files
this.watched(function(watched) {
console.log(watched);
});
var watched = this.watched();

@@ -59,5 +47,3 @@ // On file changed

// Get watched files with relative paths
this.relative(function(err, files) {
console.log(files);
});
var files = this.relative();
});

@@ -103,10 +89,2 @@

#### `EMFILE` errors
By default, gaze will use native OS events and then fallback to slower stat polling when an `EMFILE` error is reached. Gaze will still emit or return the error as the first argument of the ready callback for you to handle.
It is recommended to advise your users to increase their file descriptor limits to utilize the faster native OS watching. Especially on OSX where the default descriptor limit is 256.
In some cases, native OS events will not work. Such as with networked file systems or vagrant. It is recommended to set the option `mode: 'poll'` to always stat poll for those situations.
### Minimatch / Glob

@@ -141,3 +119,3 @@

* `debounceDelay` {integer} Delay for events called in succession for the same
file/event
file/event in milliseconds
* `mode` {string} Force the watch mode. Either `'auto'` (default), `'watch'` (force native events), or `'poll'` (force stat polling).

@@ -166,19 +144,13 @@ * `cwd` {string} The current working directory to base file patterns from. Default is `process.cwd()`.

recurse directories.
* `watched([callback])` Returns the currently watched files.
* `callback` {function} Calls with `function(err, files)`.
* `relative([dir, unixify, callback])` Returns the currently watched files with relative paths.
* `watched()` Returns the currently watched files.
* `relative([dir, unixify])` Returns the currently watched files with relative paths.
* `dir` {string} Only return relative files for this directory.
* `unixify` {boolean} Return paths with `/` instead of `\\` if on Windows.
* `callback` {function} Calls with `function(err, files)`.
## FAQs
## Similar Projects
### Why Another `fs.watch` Wrapper?
I liked parts of other `fs.watch` wrappers but none had all the features I
needed when this library was originally written. This lib once combined the features I needed from other fine watch libs
but now has taken on a life of it's own (**gaze doesn't wrap `fs.watch` or `fs.watchFile` anymore**).
Other great watch libraries to try are:
* [paulmillr's chokidar](https://github.com/paulmillr/chokidar)
* [amasad's sane](https://github.com/amasad/sane)
* [mikeal's watch](https://github.com/mikeal/watch)

@@ -194,2 +166,3 @@ * [github's pathwatcher](https://github.com/atom/node-pathwatcher)

## Release History
* 1.0.0 - Revert back to 0.5.2. Drop support for Node.js v0.8. Fix for `maxListeners`. Update globule to `0.2.0`.
* 0.6.4 - Catch and emit error from readdir (@oconnore). Fix for 0 maxListeners. Use graceful-fs to avoid EMFILE errors in other places fs is used. Better method to determine if pathwatcher was built. Fix keeping process alive too much, only init pathwatcher if a file is being watched. Set min required to Windows Vista when building on Windows (@pvolok).

@@ -200,2 +173,3 @@ * 0.6.3 - Add support for node v0.11

* 0.6.0 - Uses native OS events (fork of pathwatcher) but can fall back to stat polling. Everything is async to avoid blocking, including `relative()` and `watched()`. Better error handling. Update to globule@0.2.0. No longer watches `cwd` by default. Added `mode` option. Better `EMFILE` message. Avoids `ENOENT` errors with symlinks. All constructor arguments are optional.
* 0.5.2 - Fix for ENOENT error with non-existent symlinks [BACKPORTED].
* 0.5.1 - Use setImmediate (process.nextTick for node v0.8) to defer ready/nomatch events (@amasad).

@@ -224,3 +198,3 @@ * 0.5.0 - Process is now kept alive while watching files. Emits a nomatch event when no files are matching.

## License
Copyright (c) 2014 Kyle Robinson Young
Copyright (c) 2015 Kyle Robinson Young
Licensed under the MIT license.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc