You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openNG/build/core/watch.js

99 lines
2.8 KiB
JavaScript

"use strict";
const Promise = require("bluebird");
const chokidar = require("chokidar");
const createFileSource = require("./file-source");
const fs = Promise.promisifyAll(require("fs"));
const path = require("path");
const splitPath = require("./split-path");
/* FIXME: Add deletion propagation support, based on correlating input files to output files */
module.exports = function watch(pattern, options = {}) {
let watcher;
let basePath;
if (options.basePath != null) {
/* FIXME: Verify that, if an explicit basePath is specified, it's not deeper in the path than the automatically-determined one (for any of the specified patterns); otherwise file-paths-relative-to-the-base-path no longer make any sense. */
basePath = options.basePath;
} else {
if (typeof pattern === "string") {
let pathSegments = splitPath(pattern);
let firstWildcardSegment = pathSegments.findIndex((segment) => {
return segment.includes("*");
});
if (firstWildcardSegment === -1) {
/* Assume an exact file path, and treat its folder as the base folder */
basePath = path.dirname(pattern);
} else {
/* Assume a path containing a wildcard, and treat the last non-wildcard segment as the base folder */
basePath = pathSegments.slice(0, firstWildcardSegment).join(path.sep);
}
} else {
throw new Error("When specifying multiple patterns to watch, you must explicitly specify a basePath in the options");
}
}
return createFileSource({
displayName: `Watch for changes (${pattern})`,
supportsTeardown: true,
basePath: basePath,
initialize: ({options, resolvePath, pushFile, reportError}) => {
function push(filePath, stats) {
return Promise.try(() => {
/* FIXME: Define more sensible resolvePath semantics */
let resolvedPath = resolvePath(filePath);
let metadata = {
isVirtual: false,
path: resolvedPath,
lastModified: stats.mtime
};
/* FIXME: File object format validation */
if (options.supportsStreams) {
pushFile({
metadata: {
isStream: true,
... metadata
},
stream: fs.createReadStream(resolvedPath)
});
} else {
return Promise.try(() => {
return fs.readFileAsync(resolvedPath);
}).then((contents) => {
pushFile({
metadata: {
isStream: false,
... metadata
},
contents: contents
});
});
}
}).catch((err) => {
reportError(err, false);
});
}
watcher = chokidar.watch(pattern, {alwaysStat: true})
.on("add", (path, stats) => {
push(path, stats);
})
.on("change", (path, stats) => {
push(path, stats);
})
.on("error", (err) => {
/* FIXME: Determine whether the error is fatal */
reportError(err, false);
});
},
teardown: function () {
watcher.close();
}
});
};