Socket
Socket
Sign inDemoInstall

sane

Package Overview
Dependencies
6
Maintainers
1
Versions
58
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.0 to 0.2.1

145

index.js

@@ -42,10 +42,16 @@ var fs = require('fs');

if (!Array.isArray(this.globs)) this.globs = [this.glob];
this.watchers = [];
this.watched = Object.create(null);
this.changeTimers = Object.create(null);
this.dir = dir
this.dirRegistery = Object.create(null);
this.root = path.resolve(dir);
this.watchdir = this.watchdir.bind(this);
this.register = this.register.bind(this);
this.stopWatching = this.stopWatching.bind(this);
this.watchdir(dir);
recReaddir(dir, this.watchdir, this.emit.bind(this, 'ready'));
recReaddir(
dir,
this.watchdir,
this.register,
this.emit.bind(this, 'ready')
);
}

@@ -56,2 +62,87 @@

/**
* Register files that matches our globs to know what to type of event to
* emit in the future.
*
* Registery looks like the following:
*
* dirRegister => Map {
* dirpath => Map {
* filename => true
* }
* }
*
* @param {string} filepath
* @return {boolean} whether or not we have registered the file.
* @private
*/
Watcher.prototype.register = function(filepath) {
var globs = this.globs;
var matched;
if (globs.length) {
for (var i = 0; i < globs.length; i++) {
if (minimatch(filepath, globs[i])) {
matched = true;
break;
}
}
} else {
matched = true;
}
if (!matched) return false;
var dir = path.dirname(filepath);
if (!this.dirRegistery[dir]) {
this.dirRegistery[dir] = Object.create(null);
}
var filename = path.basename(filepath);
this.dirRegistery[dir][filename] = true;
return true;
};
/**
* Removes a file from the registery.
*
* @param {string} filepath
* @private
*/
Watcher.prototype.unregister = function(filepath) {
var dir = path.dirname(filepath);
if (this.dirRegistery[dir]) {
var filename = path.basename(filepath);
this.dirRegistery[dir][filename] = null;
}
};
/**
* Removes a dir from the registery.
*
* @param {string} dirpath
* @private
*/
Watcher.prototype.unregisterDir = function(dirpath) {
if (this.dirRegistery[dirpath]) {
this.dirRegistery[dirpath] = null;
}
};
/**
* Checks if a file or directory exists in the registery.
*
* @param {string} fullpath
* @return {boolean}
* @private
*/
Watcher.prototype.registered = function(fullpath) {
var dir = path.dirname(fullpath);
return this.dirRegistery[fullpath] ||
this.dirRegistery[dir] && this.dirRegistery[dir][path.basename(fullpath)];
};
/**
* Watch a directory.

@@ -109,21 +200,25 @@ *

var fullPath = path.join(dir, file);
var relativePath = path.join(path.relative(this.dir, dir), file);
var relativePath = path.join(path.relative(this.root, dir), file);
fs.stat(fullPath, function(error, stat) {
if (error && error.code === 'ENOENT') {
this.stopWatching(fullPath);
return;
} else if (error) {
if (error && error.code !== 'ENOENT') {
this.emit('error', error);
return;
} else if (stat.isDirectory()) {
} else if (!error && stat.isDirectory()) {
this.watchdir(fullPath);
} else if (this.globs.length) {
var globs = this.globs;
for (var i = 0; i < globs.length; i++) {
if (minimatch(file, globs[i])) {
this.emitChange(relativePath);
this.emitEvent('add', relativePath);
} else {
var registered = this.registered(fullPath);
if (error && error.code === 'ENOENT') {
this.unregister(fullPath);
this.stopWatching(fullPath);
this.unregisterDir(fullPath);
if (registered) {
this.emitEvent('delete', relativePath);
}
} else if (registered) {
this.emitEvent('change', relativePath);
} else {
if (this.register(fullPath)) {
this.emitEvent('add', relativePath);
}
}
} else {
this.emitChange(relativePath);
}

@@ -140,7 +235,8 @@ }.bind(this));

Watcher.prototype.emitChange = function(file) {
clearTimeout(this.changeTimers[file]);
this.changeTimers[file] = setTimeout(function() {
this.changeTimers[file] = null;
this.emit('change', file);
Watcher.prototype.emitEvent = function(type, file) {
var key = type + '-' + file;
clearTimeout(this.changeTimers[key]);
this.changeTimers[key] = setTimeout(function() {
this.changeTimers[key] = null;
this.emit(type, file);
}.bind(this), 100);

@@ -158,6 +254,7 @@ };

function recReaddir(dir, callback, endCallback) {
function recReaddir(dir, dirCallback, fileCallback, endCallback) {
walker(dir)
.on('dir', callback)
.on('dir', dirCallback)
.on('file', fileCallback)
.on('end', endCallback);
}

5

package.json
{
"name": "sane",
"version": "0.1.0",
"version": "0.2.1",
"description": "Sane aims to be fast, small, and reliable file system watcher. No bells and whistles, just change events.",

@@ -26,3 +26,6 @@ "main": "index.js",

"rimraf": "~2.2.6"
},
"engines": {
"node": ">=0.10.0"
}
}

@@ -5,4 +5,12 @@ sane

I've been driven to insanity by node filesystem watcher wrappers.
Sane aims to be fast, small, and reliable file system watcher. No bells and whistles, just change events.
Sane aims to be fast, small, and reliable file system watcher.
## Install
Requires node >= v0.10.0.
```
$ npm install sane
```
## API

@@ -12,3 +20,4 @@

Shortcut for `new sane.Watcher(files, {globs: globs})`
Watches a directory and all it's descendant directorys for changes, deletions, and additions on files and directories.
Shortcut for `new sane.Watcher(files, {globs: globs})`.

@@ -19,2 +28,4 @@ ```js

watcher.on('change', function (filepath) { console.log('file changed', filepath); });
watcher.on('add', function (filepath) { console.log('file added', filepath); });
watcher.on('delete', function (filepath) { console.log('file deleted', filepath); });
// close

@@ -35,2 +46,12 @@ watcer.close();

### sane.Watcher events
Emits the following events:
All events are passed the file/dir path relative to the root directory
* `ready` when the program is ready to detect events in the directory
* `change` when a file changes
* `add` when a file or directory has been added
* `delete` when a file or directory has been deleted
Stops watching.

@@ -37,0 +58,0 @@

@@ -66,3 +66,3 @@ var os = require('os');

var testfile = jo(testdir, 'file_x' + Math.floor(Math.random() * 10000));
this.watcher.on('change', function(filepath) {
this.watcher.on('add', function(filepath) {
assert.equal(filepath, path.relative(testdir, testfile));

@@ -76,6 +76,5 @@ done();

it('adding in a new subdir will trigger a change', function(done) {
var subdir = jo(testdir, 'sub_x' + Math.floor(Math.random() * 10000));
var testfile = jo(subdir, 'file_x' + Math.floor(Math.random() * 10000));
this.watcher.on('change', function(filepath) {
it('removing a file will emit delete event', function(done) {
var testfile = jo(testdir, 'file_9');
this.watcher.on('delete', function(filepath) {
assert.equal(filepath, path.relative(testdir, testfile));

@@ -85,3 +84,46 @@ done();

this.watcher.on('ready', function() {
fs.unlink(testfile, 'wow');
});
});
it('removing a dir will emit delete event', function(done) {
var subdir = jo(testdir, 'sub_9');
this.watcher.on('delete', function(filepath) {
// Ignore delete events for files in the dir.
if (path.dirname(filepath) === path.relative(testdir, subdir)) {
return;
}
assert.equal(filepath, path.relative(testdir, subdir));
done();
});
this.watcher.on('ready', function() {
rimraf.sync(subdir);
});
});
it('adding a dir will emit an add event', function(done) {
var subdir = jo(testdir, 'sub_x' + Math.floor(Math.random() * 10000));
this.watcher.on('add', function(filepath) {
assert.equal(filepath, path.relative(testdir, subdir));
done();
});
this.watcher.on('ready', function() {
fs.mkdirSync(subdir);
});
});
it('adding in a new subdir will trigger an add event', function(done) {
var subdir = jo(testdir, 'sub_x' + Math.floor(Math.random() * 10000));
var testfile = jo(subdir, 'file_x' + Math.floor(Math.random() * 10000));
var i = 0;
this.watcher.on('add', function(filepath) {
if (++i === 1) {
assert.equal(filepath, path.relative(testdir, subdir));
} else {
assert.equal(filepath, path.relative(testdir, testfile));
done();
}
});
this.watcher.on('ready', function() {
fs.mkdirSync(subdir);
defer(function() {

@@ -96,5 +138,10 @@ fs.writeFileSync(testfile, 'wow');

var testfile = jo(subdir, 'file_1');
this.watcher.on('change', function(filepath) {
assert.equal(filepath, path.relative(testdir, testfile));
done();
var i = 0;
this.watcher.on('add', function(filepath) {
if (++i === 1) {
assert.equal(filepath, path.relative(testdir, subdir));
} else {
assert.equal(filepath, path.relative(testdir, testfile));
done();
}
});

@@ -111,2 +158,20 @@ this.watcher.on('ready', function() {

});
it('should be ok to remove and then add the same file', function(done) {
var testfile = jo(testdir, 'sub_8', 'file_1');
var i = 0;
this.watcher.on('add', function(filepath) {
assert.equal(filepath, path.relative(testdir, testfile));
});
this.watcher.on('delete', function(filepath) {
assert.equal(filepath, path.relative(testdir, testfile));
done();
});
this.watcher.on('ready', function() {
fs.unlink(testfile);
defer(function() {
fs.writeFileSync(testfile, 'wow');
});
});
});
});

@@ -113,0 +178,0 @@

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc