node-monocle-1.1.51+dfsg.orig/0000775000000000000000000000000012332203026014525 5ustar rootrootnode-monocle-1.1.51+dfsg.orig/test/0000775000000000000000000000000012235255531015516 5ustar rootrootnode-monocle-1.1.51+dfsg.orig/test/tester.js0000664000000000000000000002334412235255531017370 0ustar rootrootvar fs = require('fs'); var assert = require('assert'); var Monocle = require('../monocle'); // // setup // var monocle = null; var sample_dir = __dirname + '/sample_files'; before(function(){ monocle = Monocle(); }); after(function() { fs.unlinkSync(__dirname+"/sample_files/creation.txt"); fs.unlinkSync(__dirname+"/sample_files/creation2.txt"); fs.unlinkSync(__dirname+"/sample_files/creation3.txt"); fs.unlinkSync(__dirname+"/sample_files/creation4.txt"); fs.unlinkSync(__dirname+"/sample_files/creation5.txt"); fs.unlinkSync(__dirname+"/sample_files/nestedDir/creation3.txt"); }); // // file change tests // describe("file changes", function() { it("should detect a change", function(complete) { monocle.watchDirectory({ root: sample_dir, listener: function(f){ cb_helper('foo.txt', f, complete); }, complete: function(){ complete_helper("/sample_files/foo.txt"); } }); }); it("should detect a change in a nested dir file", function(complete) { monocle.watchDirectory({ root: sample_dir, listener: function(f) { cb_helper('servent.txt', f, complete); }, complete: function() { complete_helper("/sample_files/nestedDir/servent.txt"); } }); }); it("should detect a change", function(complete) { monocle.watchDirectory({ root: sample_dir, listener: function(f) { cb_helper('longbow.js', f, complete); }, complete: function() { complete_helper('/sample_files/longbow.js'); } }); }); it("should detect a change", function(complete) { // since we debounce every 1000 setTimeout(function() { monocle.watchPaths({ path: sample_dir, listener: function(f) { cb_helper('longbow.js', f, complete); }, complete: function() { complete_helper('/sample_files/longbow.js'); } }); }, 1500); }); }); // // file add tests // describe("file added", function() { it("should detect a file added", function(complete) { monocle.watchDirectory({ root: sample_dir, listener: function(f) { cb_helper("creation.txt", f, complete) }, complete: function() { complete_helper('/sample_files/creation.txt'); } }); }); it("should detect another file added", function(complete) { monocle.watchDirectory({ root: sample_dir, listener: function(f) { cb_helper("creation2.txt", f, complete); }, complete: function() { complete_helper('/sample_files/creation2.txt'); } }); }); it("should detect another file added in a nested folder", function(complete) { monocle.watchDirectory({ root: sample_dir, listener: function(f) { cb_helper("creation3.txt", f, complete); }, complete: function() { complete_helper('/sample_files/nestedDir/creation3.txt'); } }); }); it("should detect another file added", function(complete) { monocle.watchPaths({ path: sample_dir, listener: function(f) { cb_helper("creation2.txt", f, complete); }, complete: function() { complete_helper('/sample_files/creation2.txt'); } }); }); it("should detect another file added but passed as list", function(complete) { monocle.watchPaths({ path: [sample_dir], listener: function(f) { cb_helper("creation2.txt", f, complete); }, complete: function() { complete_helper('/sample_files/creation2.txt'); } }); }); }); // // watch an array of files // describe("files watched", function() { it("should detect a file changed of multiple", function(complete) { complete_helper('/sample_files/creation.txt'); complete_helper('/sample_files/creation2.txt'); complete_helper('/sample_files/creation3.txt'); monocle.watchFiles({ files: [__dirname+"/sample_files/creation.txt", __dirname+"/sample_files/creation2.txt"], listener: function(f) { cb_helper("creation2.txt", f, complete) }, complete: function() { complete_helper('/sample_files/creation2.txt'); } }); }); it("should detect a file changed (delayed)", function(complete) { complete_helper('/sample_files/creation3.txt'); monocle.watchFiles({ files: [__dirname+"/sample_files/creation3.txt"], listener: function(f) { setTimeout(function() { cb_helper('creation3.txt', f, complete); }, 400); }, complete: function() { complete_helper('/sample_files/creation3.txt'); } }); }); it("should detect a file changed (short delayed)", function(complete) { complete_helper('/sample_files/creation4.txt'); monocle.watchFiles({ files: [__dirname+"/sample_files/creation4.txt"], listener: function(f) { setTimeout(function() { cb_helper('creation4.txt', f, complete); }, 100); }, complete: function() { complete_helper('/sample_files/creation4.txt'); } }); }); it("should detect a file changed", function(complete) { complete_helper('/sample_files/creation.txt'); monocle.watchFiles({ files: [__dirname+"/sample_files/creation.txt"], listener: function(f) { cb_helper("creation.txt", f, complete) }, complete: function() { complete_helper('/sample_files/creation.txt'); } }); }); it("should not bomb when no callback is passed", function(complete) { complete_helper('/sample_files/creation5.txt'); monocle.watchFiles({ files: [__dirname+"/sample_files/creation5.txt"], complete: function() { complete_helper('/sample_files/creation5.txt'); } }); setTimeout(function() { complete(); }, 300) }); }); // // watch an array of paths // describe("paths watched", function() { it("should detect a file changed of multiple", function(complete) { complete_helper('/sample_files/creation.txt'); complete_helper('/sample_files/creation2.txt'); complete_helper('/sample_files/creation3.txt'); monocle.watchPaths({ path: [__dirname+"/sample_files/creation.txt", __dirname+"/sample_files/creation2.txt"], listener: function(f) { cb_helper("creation2.txt", f, complete) }, complete: function() { complete_helper('/sample_files/creation2.txt'); } }); }); it("should detect a file changed (delayed)", function(complete) { complete_helper('/sample_files/creation3.txt'); monocle.watchPaths({ path: [__dirname+"/sample_files/creation3.txt"], listener: function(f) { setTimeout(function() { cb_helper('creation3.txt', f, complete); }, 400); }, complete: function() { complete_helper('/sample_files/creation3.txt'); } }); }); it("should detect a file changed (short delayed)", function(complete) { complete_helper('/sample_files/creation4.txt'); monocle.watchPaths({ path: [__dirname+"/sample_files/creation4.txt"], listener: function(f) { setTimeout(function() { cb_helper('creation4.txt', f, complete); }, 100); }, complete: function() { complete_helper('/sample_files/creation4.txt'); } }); }); it("should detect a file changed", function(complete) { complete_helper('/sample_files/creation.txt'); monocle.watchPaths({ path: [__dirname+"/sample_files/creation.txt"], listener: function(f) { cb_helper("creation.txt", f, complete) }, complete: function() { complete_helper('/sample_files/creation.txt'); } }); }); it("should not bomb when no callback is passed", function(complete) { complete_helper('/sample_files/creation5.txt'); monocle.watchPaths({ path: [__dirname+"/sample_files/creation5.txt"], complete: function() { complete_helper('/sample_files/creation5.txt'); } }); setTimeout(function() { complete(); }, 300) }); }); // // watchPaths should accept a string or an array // describe("different parameters of watchPaths", function() { it("can be a file", function(complete) { monocle.watchPaths({ path: sample_dir + "/foo.txt", listener: function(f) { cb_helper("foo.txt", f, complete); }, complete: function() { complete_helper('/sample_files/foo.txt'); } }); }); it("can be a directory", function(complete) { monocle.watchPaths({ path: sample_dir, listener: function(f) { cb_helper("foo.txt", f, complete); }, complete: function() { complete_helper('/sample_files/foo.txt'); } }); }); it("can be a list of directories", function(complete) { monocle.watchPaths({ path: [sample_dir], listener: function(f) { cb_helper("foo.txt", f, complete); }, complete: function() { complete_helper('/sample_files/foo.txt'); } }); }); it("can be a list of directories and a file", function(complete) { monocle.watchPaths({ path: [sample_dir + "/nestedDir", sample_dir + "/foo.txt"], listener: function(f) { cb_helper("foo.txt", f, complete); }, complete: function() { complete_helper('/sample_files/foo.txt'); } }); }); it("can be a list of files and a directory", function(complete) { monocle.watchPaths({ path: [sample_dir + "/foo.txt", sample_dir + "/nestedDir"], listener: function(f) { cb_helper("servent.txt", f, complete); }, complete: function() { complete_helper('/sample_files/nestedDir/servent.txt'); } }); }); }); // // helpers // function cb_helper(name, file, done){ if (file.name === name) { monocle.unwatchAll(); done(); } } function complete_helper(path){ fs.writeFile(__dirname + path, (new Date).getTime() + "\n"); } node-monocle-1.1.51+dfsg.orig/test/sample_files/0000775000000000000000000000000012235255531020161 5ustar rootrootnode-monocle-1.1.51+dfsg.orig/test/sample_files/zap.bat0000664000000000000000000000066212235255531021447 0ustar rootroot1361223315286 1361223316535 1361223345247 1361223392495 1361223394521 1361223401023 1361223431160 1361223432160 1361223437177 1361223438592 1361223466645 1361223467719 1361223594858 1361223614308 1361223643429 1361223647989 1361223649211 1361223650605 1361223651566 1361223663051 1361223664917 1361223665860 1361223777758 1361223779174 1361223780023 1361223780769 1361223783122 1361223784141 1361223791305 1361223795551 1361223797217 node-monocle-1.1.51+dfsg.orig/test/sample_files/nestedDir/0000775000000000000000000000000012235255531022102 5ustar rootrootnode-monocle-1.1.51+dfsg.orig/test/sample_files/nestedDir/servent.txt0000664000000000000000000000001612235255531024326 0ustar rootroot1367293460783 node-monocle-1.1.51+dfsg.orig/test/sample_files/longbow.js0000664000000000000000000000001612235255531022163 0ustar rootroot1367293461094 node-monocle-1.1.51+dfsg.orig/test/sample_files/foo.txt0000664000000000000000000000001612235255531021502 0ustar rootroot1367293460624 node-monocle-1.1.51+dfsg.orig/package.json0000664000000000000000000000117212235255531017026 0ustar rootroot{ "name": "monocle", "version": "1.1.51", "description": "a tool for watching directories for file changes", "main": "monocle.js", "directories": { "test": "test" }, "dependencies": { "readdirp": "~0.2.3" }, "devDependencies": { "mocha": "1.8.1" }, "scripts": { "test": "mocha test -R spec -t 2000" }, "repository": { "type": "git", "url": "https://github.com/samccone/monocle.git" }, "bugs": { "url": "https://github.com/samccone/monocle/issues" }, "keywords": [ "watch", "filesystem", "folders", "fs" ], "author": "Sam Saccone", "license": "BSD" } node-monocle-1.1.51+dfsg.orig/monocle.js0000664000000000000000000001326412235255531016537 0ustar rootrootvar path = require('path'); var fs = require('fs'); var readdirp = require('readdirp'); var use_fs_watch = process.platform === 'win32' || process.env.USE_FS_WATCH; module.exports = function() { var watched_files = {}; var watched_directories = {}; var check_dir_pause = 1000; var checkInterval = undefined; // @api public // Watches the directory passed and its contained files // accepts args as an object. // @param root(string): the root directory to watch // @param fileFilter(array): ignore these files // @param directoryFilter(array): ignore these files // @param listener(fn(file)): on file change event this will be called // @param complete(fn): on complete of file watching setup function watchDirectory(args) { readdirp({ root: args.root, fileFilter: args.fileFilter, directoryFilter: args.directoryFilter }, function(err, res) { res.files.forEach(function(file) { watchFile(file, args.listener, args.partial); }); typeof args.complete == "function" && args.complete(); }); !args.partial && (checkInterval = setInterval(function() {checkDirectory(args)}, check_dir_pause)); } // @api public // Watches the files passed // accepts args as an object. // @param files(array): a list of files to watch // @param listener(fn(file)): on file change event this will be called // @param complete(fn): on complete of file watching setup function watchFiles(args) { args.files.forEach(function(file) { var o = { fullPath: fs.realpathSync(file), name: fs.realpathSync(file).split('/').pop() }; o.fullParentDir = o.fullPath.split('/').slice(0, o.fullPath.split('/').length - 1).join('/') watchFile(o, args.listener); }); typeof args.complete == "function" && args.complete(); } function unwatchAll() { if (use_fs_watch) { Object.keys(watched_files).forEach(function(key) { watched_files[key].close(); }); } else { Object.keys(watched_files).forEach(function(key) { fs.unwatchFile(key); }); } clearInterval(checkInterval); watched_files = {}; watched_directories = {}; } // Checks to see if something in the directory has changed function checkDirectory(args) { Object.keys(watched_directories).forEach(function(path) { var lastModified = watched_directories[path]; fs.stat(path, function(err, stats) { var stats_stamp = lastModified; if (!err) { stats_stamp = (new Date(stats.mtime)).getTime(); } if (stats_stamp != lastModified) { watched_directories[path] = stats_stamp; watchDirectory({ root: path, listener: args.listener, fileFilter: args.fileFilter, directoryFilter: args.directoryFilter, partial: true }); } }); }); } // sets the absolute path to the file from the current working dir function setAbsolutePath(file) { file.absolutePath = path.resolve(process.cwd(), file.fullPath); return file.absolutePath; } // Watches the file passed and its containing directory // on change calls given listener with file object function watchFile(file, cb, partial) { setAbsolutePath(file); storeDirectory(file); if (!watched_files[file.fullPath]) { if (use_fs_watch) { (function() { watched_files[file.fullPath] = fs.watch(file.fullPath, function() { typeof cb === "function" && cb(file); }); partial && cb(file); })(file, cb); } else { (function(file, cb) { watched_files[file.fullPath] = true; fs.watchFile(file.fullPath, {interval: 150}, function() { typeof cb === "function" && cb(file); }); partial && cb(file); })(file, cb); } } } // Sets up a store of the folders being watched // and saves the last modification timestamp for it function storeDirectory(file) { var directory = file.fullParentDir; if (!watched_directories[directory]) { fs.stat(directory, function(err, stats) { if (err) { watched_directories[directory] = (new Date).getTime(); } else { watched_directories[directory] = (new Date(stats.mtime)).getTime(); } }); } } // distinguish between files and directories // @returns {Object} contains directories and files array function distinguishPaths(paths) { paths = Array.isArray(paths) ? paths : [paths]; var result = { directories: [], files: [] }; paths.forEach(function(name) { if (fs.statSync(name).isDirectory()) { result.directories.push(name); } else { result.files.push(name); } }); return result; }; // for functions accepts an object as paramter // copy the object and modify with attributes function extend(prototype, attributes) { var object = {}; Object.keys(prototype).forEach(function(key) { object[key] = prototype[key]; }); Object.keys(attributes).forEach(function(key) { object[key] = attributes[key]; }); return object; }; // watch files if the paths refer to files, or directories function watchPaths(args) { var result = distinguishPaths(args.path) if (result.directories.length) { result.directories.forEach(function(directory) { watchDirectory(extend(args, {root: directory})); }); } if (result.files.length) watchFiles(extend(args, {files: result.files})); } return { watchDirectory: watchDirectory, watchFiles: watchFiles, watchPaths: watchPaths, unwatchAll: unwatchAll }; } node-monocle-1.1.51+dfsg.orig/README.md0000664000000000000000000000453012235255531016020 0ustar rootroot[![Build Status](https://travis-ci.org/samccone/monocle.png?branch=master)](https://travis-ci.org/samccone/monocle) # Monocle -- a tool for watching things [![logo](https://raw.github.com/samccone/monocle/master/logo.png)](https://raw.github.com/samccone/monocle/master/logo.png) Have you ever wanted to watch a folder and all of its files/nested folders for changes. well now you can! ## Installation ``` npm install monocle ``` ## Usage ### Watch a directory: ```js var monocle = require('monocle')() monocle.watchDirectory({ root: , fileFilter: , directoryFilter: , listener: fn(fs.stat+ object), //triggered on file change / addition complete: //file watching all set up }); ``` The listener will recive an object with the following ```js name: , path: , fullPath: , parentDir: , fullParentDir: , stat: ``` [fs.stats](http://nodejs.org/api/fs.html#fs_class_fs_stats) When a new file is added to the directoy it triggers a file change and thus will be passed to your specified listener. The two filters are passed through to `readdirp`. More documentation can be found [here](https://github.com/thlorenz/readdirp#filters) ### Watch a list of files: ```js Monocle.watchFiles({ files: [], //path of file(s) listener: , //triggered on file / addition complete: //file watching all set up }); ``` ### Just watch path Just an alias of `watchFiles` and `watchDirectory` so you don't need to tell if that's a file or a directory by yourself. Parameter passed to `path` can be a `string` or a `array` of `string`. ```js Monocle.watchPaths({ path: [], //list of paths, or a string of path fileFilter: , // `*.js` for example listener: , //triggered on file / addition complete: //file watching all set up }); ``` ### Force to use fs.watch You can use the USE_FS_WATCH env variable set to true, to force this behavior regardless of platform. ## Why not just use fs.watch ? - file watching is really bad cross platforms in node - you need to be smart when using fs.watch as compared to fs.watchFile - Monocle takes care of this logic for you! - windows systems use fs.watch - osx and linux uses fs.watchFile ## License BSD node-monocle-1.1.51+dfsg.orig/LICENSE0000664000000000000000000000237712235255531015555 0ustar rootrootCopyright (c) 2013, Sam Saccone All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. node-monocle-1.1.51+dfsg.orig/.travis.yml0000664000000000000000000000006112235255531016645 0ustar rootrootlanguage: node_js node_js: - "0.11" - "0.10" node-monocle-1.1.51+dfsg.orig/.npmignore0000664000000000000000000000003212235255531016531 0ustar rootroottest/ logo.png .travis.ymlnode-monocle-1.1.51+dfsg.orig/.gitignore0000664000000000000000000000002612235255531016525 0ustar rootrootnode_modules .DS_Store