UNPKG

13.4 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const fs = require('fs-extra');
4const path = require('path');
5const chalk = require('chalk');
6const cwd = process.cwd();
7const merge = require('lodash.mergewith');
8const shelljs = require('shelljs');
9const mergeDir = path.join(cwd, '.CACHE/nanachi');
10let mergeFilesQueue = require('./mergeFilesQueue');
11let diff = require('deep-diff').diff;
12function getMergedAppJsConent(appJsSrcPath, pages = []) {
13 let allRoutesStr = pages.map(function (pageRoute) {
14 if (!/^\.\//.test(pageRoute)) {
15 pageRoute = './' + pageRoute;
16 }
17 pageRoute = `import '${pageRoute}';\n`;
18 return pageRoute;
19 }).join('');
20 return new Promise(function (rel, rej) {
21 let appJsSrcContent = '';
22 let appJsDist = path.join(mergeDir, 'source', 'app.js');
23 try {
24 appJsSrcContent = fs.readFileSync(appJsSrcPath).toString();
25 }
26 catch (err) {
27 rej(err);
28 }
29 appJsSrcContent = allRoutesStr + appJsSrcContent;
30 rel({
31 content: appJsSrcContent,
32 dist: appJsDist
33 });
34 });
35}
36function getAppJsSourcePath(queue = []) {
37 let appJsSourcePath = queue.filter(function (file) {
38 file = file.replace(/\\/g, '/');
39 return /\/app\.js$/.test(file);
40 })[0];
41 return appJsSourcePath;
42}
43function getFilesMap(queue = []) {
44 let map = {};
45 let env = process.env.ANU_ENV;
46 queue.forEach(function (file) {
47 file = file.replace(/\\/g, '/');
48 if (/\/package\.json$/.test(file)) {
49 let { dependencies = {}, devDependencies = {} } = require(file);
50 if (dependencies) {
51 map['pkgDependencies'] = map['pkgDependencies'] || [];
52 map['pkgDependencies'].push({
53 id: file,
54 content: dependencies,
55 type: 'dependencies'
56 });
57 }
58 if (devDependencies) {
59 delete devDependencies['node-sass'];
60 map['pkgDevDep'] = map['pkgDevDep'] || [];
61 map['pkgDevDep'].push({
62 id: file,
63 content: devDependencies,
64 type: 'devDependencies'
65 });
66 }
67 return;
68 }
69 if (/\/app\.json$/.test(file)) {
70 var { alias = {}, pages = [], order = 0 } = require(file);
71 if (alias) {
72 map['alias'] = map['alias'] || [];
73 map['alias'].push({
74 id: file,
75 content: alias,
76 type: 'alias'
77 });
78 }
79 if (pages.length) {
80 let allInjectRoutes = pages.reduce(function (ret, route) {
81 let injectRoute = '';
82 if ('[object Object]' === Object.prototype.toString.call(route)) {
83 var supportPlat = route.platform.replace(/\s*/g, '').split(',');
84 if (supportPlat.includes(env)) {
85 injectRoute = route.route;
86 }
87 }
88 else {
89 injectRoute = route;
90 }
91 if (injectRoute) {
92 ret.add(injectRoute);
93 }
94 return ret;
95 }, new Set());
96 map['pages'] = map['pages'] || [];
97 map['pages'].push({
98 routes: Array.from(allInjectRoutes),
99 order: order
100 });
101 }
102 return;
103 }
104 if (/\/project\.config\.json$/.test(file)) {
105 map['projectConfigJson'] = map['projectConfigJson'] || [];
106 map['projectConfigJson'].push(file);
107 return;
108 }
109 var reg = new RegExp(env + 'Config.json$');
110 map['xconfig'] = map['xconfig'] || [];
111 if (reg.test(file)) {
112 try {
113 var config = require(file);
114 if (config) {
115 map['xconfig'].push({
116 id: file,
117 content: config
118 });
119 }
120 }
121 catch (err) {
122 }
123 }
124 });
125 map = orderRouteByOrder(map);
126 return map;
127}
128function orderRouteByOrder(map) {
129 map['pages'] = map['pages'].sort(function (a, b) {
130 return b.order - a.order;
131 });
132 map['pages'] = map['pages'].map(function (pageEl) {
133 return pageEl.routes;
134 });
135 map['pages'] = [].concat(...map['pages']);
136 return map;
137}
138function customizer(objValue, srcValue) {
139 if (Array.isArray(objValue)) {
140 return Array.from(new Set(objValue.concat(srcValue)));
141 }
142}
143function getMergedXConfigContent(config = {}) {
144 let env = process.env.ANU_ENV;
145 let xConfigJsonDist = path.join(mergeDir, 'source', `${env}Config.json`);
146 return Promise.resolve({
147 dist: xConfigJsonDist,
148 content: JSON.stringify(xDiff(config), null, 4)
149 });
150}
151function getMergedData(configList) {
152 return xDiff(configList);
153}
154function getValueByPath(path, data) {
155 path = path.slice(0);
156 var ret;
157 while (path.length) {
158 var key = path.shift();
159 if (!ret) {
160 ret = data[key] || '';
161 }
162 else {
163 ret = ret[key] || '';
164 }
165 }
166 return ret;
167}
168function xDiff(list) {
169 if (!list.length)
170 return {};
171 let first = list[0];
172 let confictQueue = [];
173 let other = list.slice(1);
174 let isConfict = false;
175 for (let i = 0; i < other.length; i++) {
176 let x = diff(first.content, other[i].content) || [];
177 x = x.filter(function (el) {
178 return el.kind === 'E';
179 });
180 if (x.length) {
181 isConfict = true;
182 confictQueue = [...x];
183 break;
184 }
185 }
186 if (isConfict) {
187 var errList = [];
188 confictQueue.forEach(function (confictEl) {
189 let kind = [];
190 list.forEach(function (el) {
191 let confictValue = getValueByPath(confictEl.path, el.content);
192 if (confictValue) {
193 let errorItem = {};
194 errorItem.confictFile = el.id.replace(/\\/g, '/').split(/\/download\//).pop();
195 errorItem.confictValue = confictValue || '';
196 if (el.type === 'dependencies') {
197 errorItem.confictKeyPath = ['dependencies', ...confictEl.path];
198 }
199 else if (el.type === 'devDependencies') {
200 errorItem.confictKeyPath = ['devDependencies', ...confictEl.path];
201 }
202 else if (el.type === 'alias') {
203 errorItem.confictKeyPath = ['nanachi', 'alias', ...confictEl.path];
204 }
205 else {
206 errorItem.confictKeyPath = confictEl.path;
207 }
208 errorItem.confictKeyPath = JSON.stringify(errorItem.confictKeyPath);
209 kind.push(errorItem);
210 }
211 });
212 errList.push(kind);
213 });
214 var msg = '';
215 errList.forEach(function (errEl) {
216 let kindErr = '';
217 errEl.forEach(function (errItem) {
218 var tpl = `
219冲突文件: ${(errItem.confictFile)}
220冲突路径 ${errItem.confictKeyPath}
221冲突详情:${JSON.stringify({ [JSON.parse(errItem.confictKeyPath).pop()]: errItem.confictValue }, null, 4)}
222`;
223 kindErr += tpl;
224 });
225 msg = msg + kindErr + '\n--------------------------------------------------\n';
226 });
227 console.log(chalk.bold.red('⚠️ 发现冲突! 请先解决冲突。\n\n' + msg));
228 process.exit(1);
229 }
230 isConfict = false;
231 if (!isConfict) {
232 return list.reduce(function (ret, el) {
233 return merge(ret, el.content, customizer);
234 }, {});
235 }
236 else {
237 return {};
238 }
239}
240function getMergedPkgJsonContent(alias) {
241 let currentPkg = require(path.join(cwd, 'package.json'));
242 let distContent = Object.assign({}, currentPkg, {
243 nanachi: {
244 alias: alias
245 }
246 });
247 let dist = path.join(mergeDir, 'package.json');
248 return {
249 dist: dist,
250 content: JSON.stringify(distContent, null, 4)
251 };
252}
253function getMiniAppProjectConfigJson(projectConfigQueue = []) {
254 let dist = path.join(mergeDir, 'project.config.json');
255 let distContent = '';
256 if (projectConfigQueue.length) {
257 distContent = JSON.stringify(require(projectConfigQueue[0]), null, 4);
258 }
259 return {
260 dist: dist,
261 content: distContent
262 };
263}
264function validateAppJsFileCount(queue) {
265 let appJsFileCount = queue
266 .filter(function (el) {
267 return /\/app\.js$/.test(el);
268 })
269 .map(function (el) {
270 return el.replace(/\\/g, '/').split('/download/').pop();
271 });
272 if (!appJsFileCount.length || appJsFileCount.length > 1) {
273 let msg = '';
274 if (!appJsFileCount.length) {
275 msg = '校验到无 app.js 文件的拆库工程,请检查是否安装了该包含 app.js 文件的拆库工程.';
276 }
277 else if (appJsFileCount.length > 1) {
278 msg = '校验到多个拆库仓库中存在app.js. 在业务线的拆库工程中,有且只能有一个拆库需要包含app.js' + '\n' + JSON.stringify(appJsFileCount, null, 4);
279 }
280 console.log(chalk.bold.red(msg));
281 process.exit(1);
282 }
283}
284function validateMiniAppProjectConfigJson(queue) {
285 let projectConfigJsonList = queue.filter(function (el) {
286 return /\/project\.config\.json$/.test(el);
287 });
288 if (projectConfigJsonList.length > 1) {
289 console.log(chalk.bold.red('校验到多个拆库仓库中存在project.config.json. 在业务线的拆库工程中,最多只能有一个拆库需要包含project.config.jon:'), chalk.bold.red('\n' + JSON.stringify(projectConfigJsonList, null, 4)));
290 process.exit(1);
291 }
292}
293function validateConfigFileCount(queue) {
294 let configFiles = queue.filter(function (el) {
295 return /Config\.json$/.test(el);
296 });
297 let errorFiles = [];
298 configFiles.forEach(function (el) {
299 el = el.replace(/\\/g, '/');
300 let projectName = el.replace(/\\/g, '/').split('/download/')[1].split('/')[0];
301 let reg = new RegExp(projectName + '/' + process.env.ANU_ENV + 'Config.json$');
302 let dir = path.dirname(el);
303 if (reg.test(el) && !fs.existsSync(path.join(dir, 'app.js'))) {
304 errorFiles.push(el);
305 }
306 });
307 if (errorFiles.length) {
308 console.log(chalk.bold.red('校验到拆库仓库中配置文件路径错误,请将该配置文件放到 source 目录中:\n'), chalk.bold.red(JSON.stringify(errorFiles, null, 4)));
309 process.exit(1);
310 }
311}
312function default_1() {
313 let queue = Array.from(mergeFilesQueue);
314 validateAppJsFileCount(queue);
315 validateConfigFileCount(queue);
316 validateMiniAppProjectConfigJson(queue);
317 let map = getFilesMap(queue);
318 let tasks = [
319 getMergedAppJsConent(getAppJsSourcePath(queue), map.pages),
320 getMergedXConfigContent(map.xconfig),
321 getMergedPkgJsonContent(getMergedData(map.alias)),
322 getMiniAppProjectConfigJson(map.projectConfigJson)
323 ];
324 function getNodeModulesList(config) {
325 let mergeData = getMergedData(config);
326 return Object.keys(mergeData).reduce(function (ret, key) {
327 ret.push(key + '@' + mergeData[key]);
328 return ret;
329 }, []);
330 }
331 var installList = [...getNodeModulesList(map.pkgDependencies), ...getNodeModulesList(map.pkgDevDep)];
332 var installPkgList = installList.reduce(function (needInstall, pkg) {
333 var pkgMeta = pkg.split('@');
334 var pkgName = pkgMeta[0] === '' ? '@' + pkgMeta[1] : pkgMeta[0];
335 var p = path.join(cwd, 'node_modules', pkgName, 'package.json');
336 var isExit = fs.existsSync(p);
337 if (!isExit) {
338 needInstall.push(pkg);
339 }
340 return needInstall;
341 }, []);
342 if (installPkgList.length) {
343 let installList = installPkgList.join(' ');
344 console.log(chalk.bold.green(`缺少各拆库依赖 ${installList}, 正在安装, 请稍候...`));
345 fs.ensureDir(path.join(cwd, 'node_modules'));
346 let cmd = `npm install ${installList} --no-save`;
347 let std = shelljs.exec(cmd, {
348 silent: true
349 });
350 if (/npm ERR!/.test(std.stderr)) {
351 console.log(chalk.red(std.stderr));
352 process.exit(1);
353 }
354 }
355 return Promise.all(tasks)
356 .then(function (queue) {
357 queue = queue.map(function ({ dist, content }) {
358 return new Promise(function (rel, rej) {
359 if (!content) {
360 rel(1);
361 return;
362 }
363 fs.ensureFileSync(dist);
364 fs.writeFile(dist, content, function (err) {
365 if (err) {
366 rej(err);
367 }
368 else {
369 rel(1);
370 }
371 });
372 });
373 });
374 return Promise.all(queue);
375 });
376}
377exports.default = default_1;
378;