125 lines
3.3 KiB
JavaScript
125 lines
3.3 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
var chokidar = require('chokidar');
|
|
var runSequence = require('run-sequence');
|
|
var path = require('path');
|
|
|
|
function watch(globs, opts, tasks) {
|
|
if (typeof opts !== 'object' || Array.isArray(opts)) {
|
|
tasks = opts;
|
|
opts = {};
|
|
}
|
|
|
|
var triggerCount = 0;
|
|
var useRunSequence = typeof tasks !== 'function';
|
|
var runTasks;
|
|
|
|
if (useRunSequence) {
|
|
if (!Array.isArray(tasks)) tasks = [tasks];
|
|
tasks = tasks.slice();
|
|
tasks.push(tasksDone);
|
|
runTasks = function runTaskSequence() { runSequence.apply(null, tasks); };
|
|
} else {
|
|
var sync = tasks.length === 0;
|
|
runTasks = function runCallback() {
|
|
try {
|
|
tasks(tasksDone);
|
|
if (sync) tasksDone();
|
|
} catch (e) {
|
|
return tasksDone(e);
|
|
}
|
|
};
|
|
}
|
|
|
|
var events = opts.events = opts.events || ['add', 'change', 'unlink'];
|
|
|
|
// Don't let chokidar call us while initializing because on large trees it might take too long for
|
|
// all the add events to be emitted which causes the initial callback to be triggered more than
|
|
// once. Instead, we call handleEvent directly.
|
|
var ignoreInitial = opts.ignoreInitial;
|
|
opts.ignoreInitial = true;
|
|
|
|
var delay = opts.delay;
|
|
if (delay === undefined) delay = 100;
|
|
|
|
var watcher =
|
|
chokidar.watch(globs, opts).on('all', handleEvent).on('error', function(err) { throw err; });
|
|
|
|
var log = function watchLogger(triggerCount) {
|
|
// Don't report change for initial event
|
|
if (!ignoreInitial && !--triggerCount) return;
|
|
|
|
process.stdout.write([
|
|
'',
|
|
'==================================================',
|
|
' WATCH TRIGGERED BY FILE CHANGE #' + triggerCount,
|
|
' On: ' + prettyTime(),
|
|
'==================================================\n',
|
|
].join('\n'));
|
|
|
|
function prettyTime() {
|
|
var now = new Date();
|
|
return now.toLocaleDateString() + ' at ' + now.toLocaleTimeString();
|
|
}
|
|
};
|
|
|
|
if (opts.log !== undefined && !opts.log) {
|
|
log = function noopLog(triggerCount) {};
|
|
}
|
|
|
|
var close = watcher.close.bind(watcher);
|
|
watcher.close = function() {
|
|
if (timeoutId !== null) clearTimeout(timeoutId);
|
|
close();
|
|
};
|
|
|
|
var eventsRecorded = 0; // Number of events recorded
|
|
var timeoutId = null; // If non-null, event capture window is open
|
|
|
|
if (!ignoreInitial) {
|
|
// synthetic event to kick off the first task run
|
|
timeoutId = setTimeout(invokeCallback, delay);
|
|
}
|
|
|
|
return watcher;
|
|
|
|
function handleEvent(event, filepath) {
|
|
// Ignore unwatched events
|
|
if (events.indexOf(event) < 0) return;
|
|
|
|
// Increment number of events captured in this window
|
|
++eventsRecorded;
|
|
|
|
if (timeoutId === null) {
|
|
timeoutId = setTimeout(invokeCallback, delay);
|
|
}
|
|
}
|
|
|
|
function invokeCallback() {
|
|
eventsRecorded = 0;
|
|
log(++triggerCount);
|
|
runTasks();
|
|
}
|
|
|
|
function tasksDone(err) {
|
|
if (eventsRecorded) {
|
|
// eventsRecorded has increased during the run, run again on the next turn
|
|
timeoutId = setTimeout(invokeCallback, 0);
|
|
} else {
|
|
timeoutId = null;
|
|
}
|
|
if (!useRunSequence && err) {
|
|
// tslint:disable-next-line:no-console
|
|
console.log('Watch task error:', err.toString());
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = watch;
|