Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

commoner

Package Overview
Dependencies
Maintainers
1
Versions
55
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

commoner - npm Package Compare versions

Comparing version 0.8.2 to 0.8.3

11

lib/util.js

@@ -193,8 +193,13 @@ var assert = require("assert");

function openExclusiveP(file) {
function openFileP(file, mode) {
return makePromise(function(callback) {
// The 'x' in "wx+" means the file must be newly created.
fs.open(file, "wx+", callback);
fs.open(file, mode || "w+", callback);
});
}
exports.openFileP = openFileP;
function openExclusiveP(file) {
// The 'x' in "wx+" means the file must be newly created.
return openFileP(file, "wx+");
}
exports.openExclusiveP = openExclusiveP;

@@ -201,0 +206,0 @@

@@ -9,2 +9,3 @@ var assert = require("assert");

var util = require("./util");
var hasOwn = Object.prototype.hasOwnProperty;

@@ -21,5 +22,18 @@ function Watcher(sourceDir, persistent) {

sourceCache: { value: {} },
watched: { value: {} },
persistent: { value: !!persistent }
dirWatcher: { value: new DirWatcher(sourceDir, persistent) }
});
function handle(event, relativePath) {
if (self.dirWatcher.ready) {
self.getFileHandler(relativePath)(event);
}
}
self.dirWatcher.on("added", function(relativePath) {
handle("added", relativePath);
}).on("deleted", function(relativePath) {
handle("deleted", relativePath);
}).on("changed", function(relativePath) {
handle("changed", relativePath);
});
}

@@ -30,2 +44,7 @@

Wp.watch = function(relativePath) {
this.dirWatcher.add(path.dirname(path.join(
this.sourceDir, relativePath)));
};
Wp.readFileP = function(relativePath) {

@@ -50,37 +69,188 @@ relativePath = path.normalize(relativePath);

Wp.watch = function(relativePath) {
Wp.getFileHandler = util.cachedMethod(function(relativePath) {
var self = this;
var watched = self.watched;
return function handler(event) {
Q.all([
self.readFileP(relativePath).catch(orNull),
self.noCacheReadFileP(relativePath).catch(orNull)
]).spread(function(oldData, newData) {
if (oldData !== newData)
self.emit("changed", relativePath);
}).done();
};
});
if (!self.persistent)
function orNull(err) {
return null;
}
Wp.close = function() {
this.dirWatcher.close();
};
/**
* DirWatcher code adapted from Jeffrey Lin's original implementation:
* https://github.com/jeffreylin/jsx_transformer_fun/blob/master/dirWatcher.js
*
* Invariant: this only watches the dir inode, not the actual path.
* That means the dir can't be renamed and swapped with another dir.
*/
function DirWatcher(inputPath, persistent) {
assert.ok(this instanceof DirWatcher);
var self = this;
var absPath = path.resolve(inputPath);
if (!fs.statSync(absPath).isDirectory()) {
throw new Error(inputPath + "is not a directory!");
}
EventEmitter.call(self);
self.ready = false;
self.on("ready", function(){
self.ready = true;
});
Object.defineProperties(self, {
// Map of absDirPaths to fs.FSWatcher objects from fs.watch().
watchers: { value: {} },
dirContents: { value: {} },
rootPath: { value: absPath },
persistent: { value: !!persistent }
});
process.nextTick(function() {
self.add(absPath);
self.emit("ready");
});
}
util.inherits(DirWatcher, EventEmitter);
var DWp = DirWatcher.prototype;
DWp.add = function(absDirPath) {
var self = this;
if (hasOwn.call(self.watchers, absDirPath)) {
return;
}
relativePath = path.normalize(relativePath);
if (!watched.hasOwnProperty(relativePath)) {
var fullPath = path.join(self.sourceDir, relativePath);
var options = { persistent: self.persistent };
self.watchers[absDirPath] = fs.watch(absDirPath, {
persistent: self.persistent
}).on("change", function(event, filename) {
self.updateDirContents(absDirPath, event, filename);
});
function handler(event) {
var oldP = self.readFileP(relativePath);
var newP = self.noCacheReadFileP(relativePath);
// Update internal dir contents.
self.updateDirContents(absDirPath);
Q.all([oldP, newP]).spread(function(oldData, newData) {
if (oldData !== newData)
self.emit("changed", relativePath);
}).done();
// Since we've never seen this path before, recursively add child
// directories of this path. TODO: Don't do fs.readdirSync on the
// same dir twice in a row. We already do an fs.statSync in
// this.updateDirContents() and we're just going to do another one
// here...
fs.readdirSync(absDirPath).forEach(function(filename) {
var filepath = path.join(absDirPath, filename);
// Look for directories.
if (fs.statSync(filepath).isDirectory()) {
self.add(filepath);
}
});
};
try {
fs.watch(fullPath, options, handler);
// Don't mark the file as watched if fs.watch threw an exception.
watched[relativePath] = true;
} catch (e) {
util.log.err(
"unable to watch file " + relativePath +
" (" + e + ")",
"yellow");
DWp.updateDirContents = function(absDirPath, event, fsWatchReportedFilename) {
var self = this;
if (!hasOwn.call(self.dirContents, absDirPath)) {
self.dirContents[absDirPath] = [];
}
var oldContents = self.dirContents[absDirPath];
var newContents = fs.readdirSync(absDirPath);
var deleted = {};
var added = {};
oldContents.forEach(function(filename) {
deleted[filename] = true;
});
newContents.forEach(function(filename) {
if (hasOwn.call(deleted, filename)) {
delete deleted[filename];
} else {
added[filename] = true;
}
});
var deletedNames = Object.keys(deleted);
deletedNames.forEach(function(filename) {
self.emit(
"deleted",
path.relative(
self.rootPath,
path.join(absDirPath, filename)
)
);
});
var addedNames = Object.keys(added);
addedNames.forEach(function(filename) {
self.emit(
"added",
path.relative(
self.rootPath,
path.join(absDirPath, filename)
)
);
});
// So changed is not deleted or added?
if (fsWatchReportedFilename &&
!hasOwn.call(deleted, fsWatchReportedFilename) &&
!hasOwn.call(added, fsWatchReportedFilename))
{
self.emit(
"changed",
path.relative(
self.rootPath,
path.join(absDirPath, fsWatchReportedFilename)
)
);
}
// If any of the things removed were directories, remove their watchers.
// If a dir was moved, hopefully two changed events fired?
// 1) event in dir where it was removed
// 2) event in dir where it was moved to (added)
deletedNames.forEach(function(filename) {
var filepath = path.join(absDirPath, filename);
delete self.dirContents[filepath];
delete self.watchers[filepath];
});
// if any of the things added were directories, recursively deal with them
addedNames.forEach(function(filename) {
var filepath = path.join(absDirPath, filename);
if (fs.existsSync(filepath) &&
fs.statSync(filepath).isDirectory())
{
self.add(filepath);
// mighttttttt need a self.updateDirContents() here in case
// we're somehow adding a path that replaces another one...?
}
});
// Update state of internal dir contents.
self.dirContents[absDirPath] = newContents;
};
DWp.close = function() {
var watchers = this.watchers;
Object.keys(watchers).forEach(function(filename) {
watchers[filename].close();
});
};
function run(cmd, args) {

@@ -87,0 +257,0 @@ return spawn(cmd, args, {

@@ -17,3 +17,3 @@ {

],
"version": "0.8.2",
"version": "0.8.3",
"license": "MIT",

@@ -20,0 +20,0 @@ "homepage": "http://github.com/benjamn/commoner",

@@ -391,1 +391,79 @@ var Watcher = require("../lib/watcher").Watcher;

};
exports.testWatcherBasic = function(t, assert) {
var watcher = new Watcher(sourceDir);
var dummy = "dummy.js";
var dummyFile = path.join(sourceDir, dummy);
function waitForChangeP() {
return util.makePromise(function(callback) {
watcher.on("changed", function(path) {
callback(null, path);
});
});
}
util.unlinkP(dummyFile).then(function() {
return util.openExclusiveP(dummyFile).then(function(fd) {
return util.writeFdP(fd, "dummy");
});
}).then(function() {
return Q.all([
watcher.readFileP("home.js"),
watcher.readFileP(dummy)
]);
}).then(function() {
return Q.all([
util.unlinkP(dummyFile),
waitForChangeP()
]);
}).done(function() {
watcher.close();
t.finish();
});
};
exports.testWatchDirectory = function(t, assert) {
var watcher = new Watcher(sourceDir);
var watchMe = "watchMe.js";
var fullPath = path.join(watcher.sourceDir, watchMe);
function waitForChangeP() {
return util.makePromise(function(callback) {
watcher.once("changed", function(path) {
callback(null, path);
});
});
}
function write(content) {
return util.openFileP(fullPath).then(function(fd) {
var promise = waitForChangeP();
util.writeFdP(fd, content);
return promise;
});
}
util.unlinkP(fullPath).then(function() {
return watcher.readFileP(watchMe).then(function(source) {
assert.ok(false, "readFileP should have failed");
}, function(err) {
assert.strictEqual(err.code, "ENOENT");
});
}).then(function() {
return write("first");
}).then(function() {
return write("second");
}).then(function() {
var promise = waitForChangeP();
util.unlinkP(fullPath);
return promise;
}).then(function() {
return write("third");
}).fin(function() {
return util.unlinkP(fullPath);
}).done(function() {
watcher.close();
t.finish();
});
};
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc