UNPKG

2.04 kBJavaScriptView Raw
1var chokidar = require("chokidar");
2var ReadableStream = require("stream").Readable;
3var isWindowsCI = require("is-appveyor");
4var globby = require("globby");
5
6var ignored = /node_modules/;
7
8module.exports = function(graphStream){
9 var watcher, addresses, allNodes;
10 var stream = new ReadableStream({ objectMode: true });
11 stream._read = function(){};
12
13 function updateWatch(data){
14 allNodes = collectGraphNodes(data.graph);
15 addresses = Object.keys(allNodes);
16
17 watcher.add(addresses);
18 }
19
20 function changed(event, address){
21 if(isWindowsCI && address && ignored.test(address)) {
22 return;
23 }
24
25 var nodes = allNodes ? allNodes[address] : [];
26
27 var moduleNames = (nodes || []).map(function(node){
28 return node.load.name;
29 });
30
31 stream.push(moduleNames);
32 }
33
34 var watchOptions = { ignoreInitial: true, usePolling: true };
35 // Use this to prevent false positives on AppVeyor
36 if(isWindowsCI) {
37 watchOptions.awaitWriteFinish = true;
38 }
39
40 watcher = chokidar.watch(null, watchOptions);
41 watcher.on("all", changed);
42
43 graphStream.on("data", updateWatch);
44
45 function onGraphStreamError() {
46 globby(["**/*"], {gitignore: true})
47 .then(function(paths){
48 watcher.add(paths);
49 graphStream.emit("watch-added");
50 })
51 .catch(() => {});
52 }
53
54 graphStream.once("error", onGraphStreamError);
55
56 graphStream.once("data", function(){
57 graphStream.removeListener("error", onGraphStreamError);
58 });
59
60 graphStream.on("end", function(){
61 watcher.close();
62 });
63
64 return stream;
65};
66
67function collectGraphNodes(graph){
68 var out = {};
69
70 Object.keys(graph).forEach(function(moduleName){
71 function addToLookup(address) {
72 var addy = address.replace("file:", "");
73 var nodes = out[addy];
74 if(!nodes) {
75 nodes = out[addy] = [];
76 }
77
78 nodes.push(node);
79 }
80
81 var node = graph[moduleName];
82 if(node.load.address) {
83 addToLookup(node.load.address, node);
84 }
85 if(Array.isArray(node.load.metadata.includedDeps)) {
86 node.load.metadata.includedDeps.forEach(function(address){
87 addToLookup(address, node);
88 });
89 }
90 });
91
92 return out;
93}