forked from mxmul/closure-loader
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdependencyMapBuilder.js
More file actions
97 lines (89 loc) · 2.76 KB
/
dependencyMapBuilder.js
File metadata and controls
97 lines (89 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
var _ = require('lodash'),
path = require('path'),
chokidar = require('chokidar'),
Promise = require('bluebird'),
cache = {},
glob = Promise.promisify(require('glob')),
fs = require('graceful-fs'),
lstat = Promise.promisify(fs.lstat),
readFile = Promise.promisify(fs.readFile),
provideRegExp = /goog\.provide\((['"])(([^.)]+)[^)]*)\1\)/g;
/**
* Fulfills in an object wich maps namespaces to file paths found in given
* directories.
*
* @param {string[]} directories Directories to be processed
* @param {boolean} watch Watch for changes is mapped files to invalidate cache
* @returns {Promise}
*/
module.exports = function (directories, watch) {
return Promise.map(directories, function(dir) {
return resolveAndCacheDirectory(dir, watch)
}).then(function(results) {
return _.assign.apply(_, results);
})
};
/**
* Promisified watch
*
* Resolves promise after watcher is ready to prevent `add` events during
* initializations wich repeatedly deletes our cache.
*
* @returns {Promise}
*/
function createWatchPromise(directory) {
return new Promise(function(resolve, reject) {
var watcher = chokidar.watch(directory)
.on('ready', function() {
watcher.on('all', function() {
delete cache[directory];
});
resolve(watcher);
});
});
}
/**
* Fulfills in an object wich maps namespace to file path. The result will be
* cached by the given directory name. A file watcher watches for any changes
* in this directory and deletes the cached object.
*
* @param {string} directory
* @returns {Promise}
*/
function resolveAndCacheDirectory(directory, watch) {
if (cache[directory]) {
return cache[directory];
}
cache[directory] = (watch ? createWatchPromise(directory) : Promise.resolve())
.then(function() {
return glob(path.join(directory, '/**/*.js'));
})
.map(function(filePath) {
return findProvideCalls(filePath);
})
.then(function(results) {
return _.assign.apply(_, results);
});
return cache[directory];
}
/**
* Scans the given file path for occurences of `goog.provide()` and fulfills
* in an object wich mapps each namespace to the file path
*
* @param {string} filePath
* @returns {Promise}
*/
function findProvideCalls(filePath) {
return lstat(filePath).then(function (stats) {
if (!stats.isFile()) {
return {};
}
return readFile(filePath).then(function(fileContent) {
var result = {};
while (matches = provideRegExp.exec(fileContent)) {
result[matches[2]] = filePath;
}
return result;
});
});
}