-
Notifications
You must be signed in to change notification settings - Fork 41
/
get-dependency-list.js
124 lines (103 loc) · 3.69 KB
/
get-dependency-list.js
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
'use strict';
const path = require('path');
const { paperwork } = require('precinct');
const resolve = require('resolve');
const readPkgUp = require('read-pkg-up');
const requirePackageName = require('require-package-name');
const glob = require('glob');
function ignoreMissing(dependency, optional, peerDependenciesMeta) {
return optional && dependency in optional
|| peerDependenciesMeta && dependency in peerDependenciesMeta && peerDependenciesMeta[dependency].optional;
}
module.exports = function(filename, serverless, cache) {
const servicePath = serverless.config.servicePath;
const modulePaths = new Set();
const filePaths = new Set();
const modulesToProcess = [];
const localFilesToProcess = [filename];
function handle(name, basedir, optionalDependencies, peerDependenciesMeta) {
const moduleName = requirePackageName(name.replace(/\\/, '/'));
const cacheKey = `${basedir}:${name}`;
if (cache && cache.has(cacheKey)) {
return;
}
try {
const pathToModule = resolve.sync(path.join(moduleName, 'package.json'), { basedir });
const pkg = readPkgUp.sync({ cwd: pathToModule });
if (pkg) {
modulesToProcess.push(pkg);
if (cache) {
cache.add(cacheKey);
}
} else {
// TODO: should we warn here?
}
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND') {
if (ignoreMissing(moduleName, optionalDependencies, peerDependenciesMeta)) {
serverless.cli.log(`[serverless-plugin-include-dependencies]: WARNING missing optional dependency: ${moduleName}`);
return null;
}
try {
// this resolves the requested import also against any set up NODE_PATH extensions, etc.
const resolved = require.resolve(name);
localFilesToProcess.push(resolved);
if (cache) {
cache.add(cacheKey);
}
return;
} catch(e) {
throw new Error(`[serverless-plugin-include-dependencies]: Could not find npm package: ${moduleName}`);
}
}
throw e;
}
}
while (localFilesToProcess.length) {
const currentLocalFile = localFilesToProcess.pop();
if (filePaths.has(currentLocalFile)) {
continue;
}
filePaths.add(currentLocalFile);
paperwork(currentLocalFile, { includeCore: false }).forEach(dependency => {
if (dependency.indexOf('.') === 0) {
filePaths.add(dependency);
const abs = resolve.sync(dependency, {
basedir: path.dirname(currentLocalFile)
});
localFilesToProcess.push(abs);
} else {
handle(dependency, servicePath);
}
});
}
while (modulesToProcess.length) {
const currentModule = modulesToProcess.pop();
const currentModulePath = path.join(currentModule.path, '..');
if (modulePaths.has(currentModulePath)) {
continue;
}
modulePaths.add(currentModulePath);
const { packageJson } = currentModule;
['dependencies', 'peerDependencies', 'optionalDependencies'].forEach(key => {
const dependencies = packageJson[key];
if (dependencies) {
Object.keys(dependencies).forEach(dependency => {
handle(dependency, currentModulePath, packageJson.optionalDependencies, packageJson.peerDependenciesMeta);
});
}
});
}
modulePaths.forEach(modulePath => {
const moduleFilePaths = glob.sync(path.join(modulePath, '**'), {
nodir: true,
ignore: path.join(modulePath, 'node_modules', '**'),
absolute: true,
windowsPathsNoEscape: true,
});
moduleFilePaths.forEach(moduleFilePath => {
filePaths.add(moduleFilePath);
});
});
return Array.from(filePaths).map(file => file.replace(/\\/, '/'));
};