Comparing version 0.3.4 to 0.4.0
314
lib/gaze.js
@@ -16,4 +16,4 @@ /* | ||
var path = require('path'); | ||
var fileset = require('fileset'); | ||
var minimatch = require('minimatch'); | ||
var globule = require('globule'); | ||
var helper = require('./helper'); | ||
@@ -25,4 +25,4 @@ // globals | ||
function Gaze(patterns, opts, done) { | ||
var _this = this; | ||
EE.call(_this); | ||
var self = this; | ||
EE.call(self); | ||
@@ -52,2 +52,5 @@ // If second arg is the callback | ||
// Store watchFile listeners | ||
this._pollers = Object.create(null); | ||
// Store patterns | ||
@@ -81,75 +84,6 @@ this._patterns = []; | ||
// Node v0.6 compat | ||
fs.existsSync = fs.existsSync || path.existsSync; | ||
path.sep = path.sep || path.normalize('/'); | ||
/** | ||
* Lo-Dash 1.0.1 <http://lodash.com/> | ||
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/> | ||
* Based on Underscore.js 1.4.4 <http://underscorejs.org/> | ||
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. | ||
* Available under MIT license <http://lodash.com/license> | ||
*/ | ||
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; } | ||
/** | ||
* Copyright (c) 2010 Caolan McMahon | ||
* Available under MIT license <https://raw.github.com/caolan/async/master/LICENSE> | ||
*/ | ||
function forEachSeries(arr, iterator, callback) { | ||
if (!arr.length) { return callback(); } | ||
var completed = 0; | ||
var iterate = function() { | ||
iterator(arr[completed], function (err) { | ||
if (err) { | ||
callback(err); | ||
callback = function() {}; | ||
} else { | ||
completed += 1; | ||
if (completed === arr.length) { | ||
callback(null); | ||
} else { | ||
iterate(); | ||
} | ||
} | ||
}); | ||
}; | ||
iterate(); | ||
} | ||
// other helpers | ||
// Returns boolean whether filepath is dir terminated | ||
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` | ||
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] = unique(obj[key]); | ||
} | ||
// Ensures the dir is marked with path.sep | ||
function _markDir(dir) { | ||
if (typeof dir === 'string' && | ||
dir.slice(-(path.sep.length)) !== path.sep && | ||
dir !== '.') { | ||
dir += path.sep; | ||
} | ||
return dir; | ||
} | ||
// Changes path.sep to unix ones for testing | ||
function _unixifyPathSep(filepath) { | ||
return (process.platform === 'win32') ? String(filepath).replace(/\\/g, '/') : filepath; | ||
} | ||
// Override the emit function to emit `all` events | ||
// and debounce on duplicate events per file | ||
Gaze.prototype.emit = function() { | ||
var _this = this; | ||
var self = this; | ||
var args = arguments; | ||
@@ -163,3 +97,3 @@ | ||
if (e.slice(-2) !== 'ed') { | ||
Gaze.super_.prototype.emit.apply(_this, args); | ||
Gaze.super_.prototype.emit.apply(self, args); | ||
return this; | ||
@@ -171,6 +105,6 @@ } | ||
Object.keys(this._cached).forEach(function(oldFile) { | ||
if (_this._cached[oldFile].indexOf('deleted') !== -1) { | ||
if (self._cached[oldFile].indexOf('deleted') !== -1) { | ||
args[0] = e = 'renamed'; | ||
[].push.call(args, oldFile); | ||
delete _this._cached[oldFile]; | ||
delete self._cached[oldFile]; | ||
return false; | ||
@@ -185,10 +119,10 @@ } | ||
if (cache.indexOf(e) === -1) { | ||
_objectPush(_this._cached, filepath, e); | ||
helper.objectPush(self._cached, filepath, e); | ||
clearTimeout(timeoutId); | ||
timeoutId = setTimeout(function() { | ||
delete _this._cached[filepath]; | ||
delete self._cached[filepath]; | ||
}, this.options.debounceDelay); | ||
// Emit the event and `all` event | ||
Gaze.super_.prototype.emit.apply(_this, args); | ||
Gaze.super_.prototype.emit.apply(_this, ['all', e].concat([].slice.call(args, 1))); | ||
Gaze.super_.prototype.emit.apply(self, args); | ||
Gaze.super_.prototype.emit.apply(self, ['all', e].concat([].slice.call(args, 1))); | ||
} | ||
@@ -201,22 +135,19 @@ | ||
Gaze.prototype.close = function(_reset) { | ||
var _this = this; | ||
var self = this; | ||
_reset = _reset === false ? false : true; | ||
Object.keys(_this._watchers).forEach(function(file) { | ||
_this._watchers[file].close(); | ||
Object.keys(self._watchers).forEach(function(file) { | ||
self._watchers[file].close(); | ||
}); | ||
_this._watchers = Object.create(null); | ||
self._watchers = Object.create(null); | ||
Object.keys(this._watched).forEach(function(dir) { | ||
fs.unwatchFile(dir); | ||
_this._watched[dir].forEach(function(uFile) { | ||
fs.unwatchFile(uFile); | ||
}); | ||
self._unpollDir(dir); | ||
}); | ||
if (_reset) { | ||
_this._watched = Object.create(null); | ||
self._watched = Object.create(null); | ||
setTimeout(function() { | ||
_this.emit('end'); | ||
_this.removeAllListeners(); | ||
}, delay + 100); | ||
self.emit('end'); | ||
self.removeAllListeners(); | ||
}, delay + 100); | ||
} | ||
return _this; | ||
return self; | ||
}; | ||
@@ -226,26 +157,25 @@ | ||
Gaze.prototype.add = function(files, done) { | ||
var _this = this; | ||
if (typeof files === 'string') { | ||
files = [files]; | ||
} | ||
this._patterns = unique.apply(null, [this._patterns, files]); | ||
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); | ||
}; | ||
var include = [], exclude = []; | ||
this._patterns.forEach(function(p) { | ||
if (p.slice(0, 1) === '!') { | ||
exclude.push(p.slice(1)); | ||
} else { | ||
include.push(p); | ||
// Dont increment patterns and dont call done if nothing added | ||
Gaze.prototype._internalAdd = function(file, done) { | ||
var files = []; | ||
if (helper.isDir(file)) { | ||
files = globule.find(this._patterns, this.options); | ||
} else { | ||
if (globule.isMatch(this._patterns, file, this.options)) { | ||
files = [file]; | ||
} | ||
}); | ||
fileset(include, exclude, _this.options, function(err, files) { | ||
if (err) { | ||
_this.emit('error', err); | ||
return done(err); | ||
} | ||
_this._addToWatched(files); | ||
_this.close(false); | ||
_this._initWatched(done); | ||
}); | ||
} | ||
if (files.length > 0) { | ||
this._addToWatched(files); | ||
this.close(false); | ||
this._initWatched(done); | ||
} | ||
}; | ||
@@ -255,7 +185,6 @@ | ||
Gaze.prototype.remove = function(file) { | ||
var _this = this; | ||
var self = this; | ||
if (this._watched[file]) { | ||
// is dir, remove all files | ||
fs.unwatchFile(file); | ||
this._watched[file].forEach(fs.unwatchFile); | ||
this._unpollDir(file); | ||
delete this._watched[file]; | ||
@@ -265,6 +194,6 @@ } else { | ||
Object.keys(this._watched).forEach(function(dir) { | ||
var index = _this._watched[dir].indexOf(file); | ||
if (index !== -1) { | ||
fs.unwatchFile(file); | ||
_this._watched[dir].splice(index, 1); | ||
var index = self._watched[dir].indexOf(file); | ||
if (index) { | ||
self._unpollFile(file); | ||
delete self._watched[dir][index]; | ||
return false; | ||
@@ -287,3 +216,3 @@ } | ||
Gaze.prototype.relative = function(dir, unixify) { | ||
var _this = this; | ||
var self = this; | ||
var relative = Object.create(null); | ||
@@ -293,3 +222,3 @@ var relDir, relFile, unixRelDir; | ||
if (dir === '') { dir = '.'; } | ||
dir = _markDir(dir); | ||
dir = helper.markDir(dir); | ||
unixify = unixify || false; | ||
@@ -299,10 +228,10 @@ Object.keys(this._watched).forEach(function(dir) { | ||
if (relDir === path.sep) { relDir = '.'; } | ||
unixRelDir = unixify ? _unixifyPathSep(relDir) : relDir; | ||
relative[unixRelDir] = _this._watched[dir].map(function(file) { | ||
relFile = path.relative(path.join(cwd, relDir), file); | ||
if (_isDir(file)) { | ||
relFile = _markDir(relFile); | ||
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); | ||
} | ||
if (unixify) { | ||
relFile = _unixifyPathSep(relFile); | ||
relFile = helper.unixifyPathSep(relFile); | ||
} | ||
@@ -313,3 +242,3 @@ return relFile; | ||
if (dir && unixify) { | ||
dir = _unixifyPathSep(dir); | ||
dir = helper.unixifyPathSep(dir); | ||
} | ||
@@ -321,41 +250,27 @@ return dir ? relative[dir] || [] : relative; | ||
Gaze.prototype._addToWatched = function(files) { | ||
var _this = this; | ||
files.forEach(function(file) { | ||
var filepath = path.resolve(_this.options.cwd, file); | ||
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 (file.slice(-1) === '/') { filepath += path.sep; } | ||
_objectPush(_this._watched, path.dirname(filepath) + path.sep, filepath); | ||
}); | ||
return this; | ||
}; | ||
helper.objectPush(this._watched, path.dirname(filepath) + path.sep, filepath); | ||
// Returns true if the file matches this._patterns | ||
Gaze.prototype._isMatch = function(file) { | ||
var include = [], exclude = []; | ||
this._patterns.forEach(function(p) { | ||
if (p.slice(0, 1) === '!') { | ||
exclude.push(p.slice(1)); | ||
} else { | ||
include.push(p); | ||
// 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.statSync(dirfile).isDirectory()) { | ||
helper.objectPush(this._watched, dirname, dirfile + path.sep); | ||
} | ||
} | ||
}); | ||
var matched = false, i = 0; | ||
for (i = 0; i < include.length; i++) { | ||
if (minimatch(file, include[i])) { | ||
matched = true; | ||
break; | ||
} | ||
} | ||
for (i = 0; i < exclude.length; i++) { | ||
if (minimatch(file, exclude[i])) { | ||
matched = false; | ||
break; | ||
} | ||
} | ||
return matched; | ||
return this; | ||
}; | ||
Gaze.prototype._watchDir = function(dir, done) { | ||
var _this = this; | ||
try { | ||
_this._watchers[dir] = fs.watch(dir, function(event) { | ||
this._watchers[dir] = fs.watch(dir, function(event) { | ||
// race condition. Let's give the fs a little time to settle down. so we | ||
@@ -375,12 +290,29 @@ // don't fire events on non existent files. | ||
Gaze.prototype._unpollFile = function(file) { | ||
if (this._pollers[file]) { | ||
fs.unwatchFile(file, this._pollers[file] ); | ||
delete this._pollers[file]; | ||
} | ||
return this; | ||
}; | ||
Gaze.prototype._unpollDir = function(dir) { | ||
this._unpollFile(dir); | ||
for (var i = 0; i < this._watched[dir].length; i++) { | ||
this._unpollFile(this._watched[dir][i]); | ||
} | ||
}; | ||
Gaze.prototype._pollFile = function(file, done) { | ||
var _this = this; | ||
var opts = { persistent: true, interval: _this.options.interval }; | ||
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, function(curr, prev) { | ||
done(null, file); | ||
}); | ||
fs.watchFile(file, opts, this._pollers[file]); | ||
} catch (err) { | ||
return this._handleError(err); | ||
} | ||
} | ||
return this; | ||
@@ -391,13 +323,15 @@ }; | ||
Gaze.prototype._initWatched = function(done) { | ||
var _this = this; | ||
var self = this; | ||
var cwd = this.options.cwd || process.cwd(); | ||
var curWatched = Object.keys(_this._watched); | ||
forEachSeries(curWatched, function(dir, next) { | ||
var files = _this._watched[dir]; | ||
var curWatched = Object.keys(self._watched); | ||
helper.forEachSeries(curWatched, function(dir, next) { | ||
dir = dir || ''; | ||
var files = self._watched[dir]; | ||
// Triggered when a watched dir has an event | ||
_this._watchDir(dir, function(event, dirpath) { | ||
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 _this.emit('error', err); } | ||
if (err) { return self.emit('error', err); } | ||
if (!current) { return; } | ||
@@ -419,3 +353,3 @@ | ||
// Get watched files for this dir | ||
var previous = _this.relative(relDir); | ||
var previous = self.relative(relDir); | ||
@@ -426,6 +360,6 @@ // If file was deleted | ||
}).forEach(function(file) { | ||
if (!_isDir(file)) { | ||
if (!helper.isDir(file)) { | ||
var filepath = path.join(dir, file); | ||
_this.remove(filepath); | ||
_this.emit('deleted', filepath); | ||
self.remove(filepath); | ||
self.emit('deleted', filepath); | ||
} | ||
@@ -440,10 +374,6 @@ }); | ||
var relFile = path.join(relDir, file); | ||
// TODO: this can be optimized more | ||
// we shouldnt need isMatch() and could just use add() | ||
if (_this._isMatch(relFile)) { | ||
// Add to watch then emit event | ||
_this.add(relFile, function() { | ||
_this.emit('added', path.join(dir, file)); | ||
}); | ||
} | ||
// Add to watch then emit event | ||
self._internalAdd(relFile, function() { | ||
self.emit('added', path.join(dir, file)); | ||
}); | ||
}); | ||
@@ -456,10 +386,8 @@ | ||
files.forEach(function(file) { | ||
if (_isDir(file)) { return; } | ||
_this._pollFile(file, function(err, filepath) { | ||
if (helper.isDir(file)) { return; } | ||
self._pollFile(file, function(err, filepath) { | ||
// Only emit changed if the file still exists | ||
// Prevents changed/deleted duplicate events | ||
// TODO: This ignores changed events on folders, maybe support this? | ||
// When a file is added, a folder changed event emits first | ||
if (fs.existsSync(filepath)) { | ||
_this.emit('changed', filepath); | ||
self.emit('changed', filepath); | ||
} | ||
@@ -475,4 +403,4 @@ }); | ||
setTimeout(function() { | ||
_this.emit('ready', _this); | ||
done.call(_this, null, _this); | ||
self.emit('ready', self); | ||
done.call(self, null, self); | ||
}, delay + 100); | ||
@@ -479,0 +407,0 @@ |
{ | ||
"name": "gaze", | ||
"description": "A globbing fs.watch wrapper built from the best parts of other fine watch libs.", | ||
"version": "0.3.4", | ||
"version": "0.4.0", | ||
"homepage": "https://github.com/shama/gaze", | ||
@@ -25,3 +25,3 @@ "author": { | ||
"engines": { | ||
"node": ">= 0.6.0" | ||
"node": ">= 0.8.0" | ||
}, | ||
@@ -32,10 +32,9 @@ "scripts": { | ||
"dependencies": { | ||
"minimatch": "~0.2.9", | ||
"fileset": "~0.1.5" | ||
"globule": "~0.1.0" | ||
}, | ||
"devDependencies": { | ||
"grunt": "~0.4.0rc7", | ||
"grunt-contrib-nodeunit": "~0.1.2rc6", | ||
"grunt-contrib-jshint": "~0.1.1rc6", | ||
"grunt-benchmark": "~0.1.1" | ||
"grunt": "~0.4.1", | ||
"grunt-contrib-nodeunit": "~0.2.0", | ||
"grunt-contrib-jshint": "~0.6.0", | ||
"grunt-benchmark": "~0.2.0" | ||
}, | ||
@@ -42,0 +41,0 @@ "keywords": [ |
@@ -5,3 +5,3 @@ # gaze [![Build Status](https://secure.travis-ci.org/shama/gaze.png?branch=master)](http://travis-ci.org/shama/gaze) | ||
Compatible with NodeJS v0.8/0.6, Windows, OSX and Linux. | ||
Compatible with Node.js 0.10/0.8, Windows, OSX and Linux. | ||
@@ -155,2 +155,3 @@ ## Usage | ||
## Release History | ||
* 0.4.0 - Drop support for node v0.6. Use globule for file matching. Avoid node v0.10 path.resolve/join errors. Register new files when added to non-existent folder. Multiple instances can now poll the same files (@jpommerening). | ||
* 0.3.4 - Code clean up. Fix path must be strings errors (@groner). Fix incorrect added events (@groner). | ||
@@ -157,0 +158,0 @@ * 0.3.3 - Fix for multiple patterns with negate. |
@@ -7,5 +7,7 @@ 'use strict'; | ||
var fixtures = path.resolve(__dirname, 'fixtures'); | ||
exports.add = { | ||
setUp: function(done) { | ||
process.chdir(path.resolve(__dirname, 'fixtures')); | ||
process.chdir(fixtures); | ||
done(); | ||
@@ -23,9 +25,9 @@ }, | ||
'nested/sub/two.js', | ||
'one.js' | ||
'one.js', | ||
]; | ||
var expected = { | ||
'Project (LO)/': ['one.js'], | ||
'.': ['Project (LO)/', 'nested/', 'one.js'], | ||
'nested/': ['one.js', 'three.js', 'sub/'], | ||
'nested/sub/': ['two.js'] | ||
'.': ['Project (LO)/', 'nested/', 'one.js', 'sub/'], | ||
'nested/': ['sub/', 'sub2/', 'one.js', 'three.js'], | ||
'nested/sub/': ['two.js'], | ||
}; | ||
@@ -32,0 +34,0 @@ var gaze = new Gaze('addnothingtowatch'); |
@@ -1,1 +0,1 @@ | ||
var test = true; | ||
var test = true; |
'use strict'; | ||
var gaze = require('../lib/gaze.js'); | ||
var grunt = require('grunt'); | ||
var path = require('path'); | ||
var fixtures = path.resolve(__dirname, 'fixtures'); | ||
function cleanUp(done) { | ||
[ | ||
'newfolder', | ||
].forEach(function(d) { | ||
var p = path.join(fixtures, d); | ||
if (grunt.file.exists(p)) { | ||
grunt.file.delete(p); | ||
} | ||
}); | ||
done(); | ||
} | ||
exports.matching = { | ||
setUp: function(done) { | ||
process.chdir(path.resolve(__dirname, 'fixtures')); | ||
done(); | ||
process.chdir(fixtures); | ||
cleanUp(done); | ||
}, | ||
tearDown: cleanUp, | ||
globAll: function(test) { | ||
@@ -33,3 +49,3 @@ test.expect(2); | ||
var result = this.relative(null, true); | ||
test.deepEqual(result['.'], ['one.js']); | ||
test.deepEqual(result['.'], ['one.js', 'Project (LO)/', 'nested/', 'sub/']); | ||
test.deepEqual(result['sub/'], ['one.js', 'two.js']); | ||
@@ -57,3 +73,20 @@ this.close(); | ||
}); | ||
} | ||
}, | ||
addedLater: function(test) { | ||
test.expect(2); | ||
var times = 0; | ||
gaze('**/*.js', function(err, watcher) { | ||
watcher.on('all', function(status, filepath) { | ||
times++; | ||
var result = watcher.relative(null, true); | ||
test.deepEqual(result['newfolder/'], ['added.js']); | ||
if (times > 1) { watcher.close(); } | ||
}); | ||
grunt.file.write(path.join(fixtures, 'newfolder', 'added.js'), 'var added = true;'); | ||
setTimeout(function() { | ||
grunt.file.write(path.join(fixtures, 'newfolder', 'added.js'), 'var added = true;'); | ||
}, 1000); | ||
watcher.on('end', test.done); | ||
}); | ||
}, | ||
}; |
@@ -25,5 +25,5 @@ 'use strict'; | ||
gaze._addToWatched(files); | ||
test.deepEqual(gaze.relative('.', true), ['Project (LO)/', 'nested/', 'one.js']); | ||
test.deepEqual(gaze.relative('.', true), ['Project (LO)/', 'nested/', 'one.js', 'sub/']); | ||
test.done(); | ||
} | ||
}; |
@@ -7,5 +7,2 @@ 'use strict'; | ||
// Node v0.6 compat | ||
fs.existsSync = fs.existsSync || path.existsSync; | ||
// Clean up helper to call in setUp and tearDown | ||
@@ -12,0 +9,0 @@ function cleanUp(done) { |
@@ -7,5 +7,2 @@ 'use strict'; | ||
// Node v0.6 compat | ||
fs.existsSync = fs.existsSync || path.existsSync; | ||
// Clean up helper to call in setUp and tearDown | ||
@@ -12,0 +9,0 @@ function cleanUp(done) { |
@@ -8,5 +8,2 @@ 'use strict'; | ||
// Node v0.6 compat | ||
fs.existsSync = fs.existsSync || path.existsSync; | ||
// Clean up helper to call in setUp and tearDown | ||
@@ -208,2 +205,42 @@ function cleanUp(done) { | ||
}, | ||
multipleWatchersSimultaneously: function(test) { | ||
test.expect(2); | ||
var did = 0; | ||
var ready = 0; | ||
var cwd = path.resolve(__dirname, 'fixtures', 'sub'); | ||
var watchers = []; | ||
var timeout = setTimeout(function() { | ||
test.ok(false, "Only " + did + " of " + ready + " watchers fired."); | ||
test.done(); | ||
watchers.forEach(function(watcher) { | ||
watcher.close(); | ||
}); | ||
}, 1000); | ||
function isReady() { | ||
ready++; | ||
if (ready > 1) { | ||
fs.writeFileSync(path.resolve(cwd, 'one.js'), 'var one = true;'); | ||
} | ||
} | ||
function isDone() { | ||
did++; | ||
if (did > 1) { | ||
clearTimeout(timeout); | ||
watchers.forEach(function(watcher) { | ||
watcher.close(); | ||
}); | ||
test.done(); | ||
} | ||
} | ||
function changed(filepath) { | ||
test.equal(path.join('sub', 'one.js'), path.relative(process.cwd(), filepath)); | ||
isDone(); | ||
} | ||
for (var i = 0; i < 2; i++) { | ||
watchers[i] = new gaze.Gaze('sub/one.js'); | ||
watchers[i].on('changed', changed); | ||
watchers[i].on('ready', isReady); | ||
} | ||
}, | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
41735
1
28
1042
174
+ Addedglobule@~0.1.0
+ Addedglob@3.1.21(transitive)
+ Addedglobule@0.1.0(transitive)
+ Addedgraceful-fs@1.2.3(transitive)
+ Addedinherits@1.0.2(transitive)
+ Addedlodash@1.0.2(transitive)
- Removedfileset@~0.1.5
- Removedminimatch@~0.2.9
- Removedfileset@0.1.8(transitive)
- Removedglob@3.2.11(transitive)
- Removedinherits@2.0.4(transitive)
- Removedminimatch@0.3.0(transitive)