-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
156 lines (140 loc) · 4.14 KB
/
index.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
const fse = require("fs-extra");
const path = require("path");
const setValue = require("set-value");
function findAllPackages(projectDir, depth) {
const packagePathList = [];
function filterPath(list) {
var a = list.filter((item) => {
// 排除隐藏目录
if (/^\./.test(item)) {
return false;
}
// 排除重复包
if (/^\_/.test(item)) {
return false;
}
return true;
});
return a;
}
function findPackages(rootDir) {
const nodeModulesPath = path.join(rootDir, "node_modules");
const packagePath = path.join(rootDir, "package.json");
let basename = path.basename(rootDir);
let dirname = path.dirname(rootDir);
if (dirname.indexOf(`/node_modules/${basename}/`) > -1) {
return false;
}
const matchs = rootDir.match(/node_modules/g);
if (Array.isArray(matchs) && matchs.length > depth) {
return false;
}
if (fse.existsSync(packagePath)) {
packagePathList.push(packagePath);
}
const hasNodeModules = fse.existsSync(nodeModulesPath);
const isPernalPackagePrefix =
/node_modules$/.test(dirname) && /^\@/.test(basename);
if (hasNodeModules) {
let pathList = filterPath(fse.readdirSync(nodeModulesPath));
pathList.forEach((item) => {
findPackages(path.join(nodeModulesPath, item));
});
}
if (isPernalPackagePrefix) {
let pathList = filterPath(fse.readdirSync(rootDir));
pathList.forEach((item) => {
findPackages(path.join(rootDir, item));
});
}
}
findPackages(projectDir);
return packagePathList;
}
function readPackages(entries, projectDir) {
let tree = {};
let temp = null;
const placeholder = "{{BEE}}";
for (let i = 0; i < entries.length; i++) {
try {
let item = entries[i];
temp = require(item);
if (!temp.name) {
break;
}
// 去除工程目录前缀
item = item.replace(projectDir + "/", "").replace("/?package.json", "");
// 匹配 @ali/xx @babel/xx 等私有包,将/做特殊处理
let matchs = item.match(/\@.*?\//g);
if (Array.isArray(matchs)) {
matchs.forEach((match) => {
let excaped = match.replace("/", placeholder);
item = item.replace(match, excaped);
});
}
// 1、路径中的.转义;2、将/替换为.便于 setValue;3、还原私有包的/
item = item
.replace(/\./g, "\\.")
.replace(/\//g, ".")
.replace(new RegExp(placeholder, "g"), "/");
setValue(tree, item, {
name: temp.name,
version: temp.version,
});
temp = null;
} catch (e) {}
}
return tree;
}
function transformToSchema(tree, dependenciesKey) {
function tree2Schema(tree) {
let schema = {};
if (tree["node_modules"]) {
schema[dependenciesKey] = Object.keys(tree["node_modules"]).map(
(item) => {
return tree2Schema(tree["node_modules"][item]);
}
);
} else {
schema[dependenciesKey] = [];
}
if (tree["package.json"]) {
const item = tree["package.json"];
schema.name = item.name;
schema.version = item.version;
}
return schema;
}
return tree2Schema(tree);
}
/**
* traverse package from node_modules and return json schema
* @param {*} projectDir project directory
* @param {*} depth node_modules max depth
* @returns {
"dependencies": [
{
"name": "isexe",
"version": "2.0.0",
"dependencies": []
}
],
"name": "which",
"version": "2.0.2"
}
*/
function nodeModules2Schema(projectDir, options = {}) {
if (!projectDir) {
throw new Error("projectDir must be provided");
}
console.time("NodeModulesToSchemaTime");
const depth = options.depth || 8;
const dependenciesKey = options.dependenciesKey || "dependencies";
const absoluteDir = path.resolve(projectDir);
const packageList = findAllPackages(absoluteDir, depth);
const tree = readPackages(packageList, absoluteDir);
const schema = transformToSchema(tree, dependenciesKey);
console.timeEnd("NodeModulesToSchemaTime");
return schema;
}
module.exports = nodeModules2Schema;