@tmsfe/tmskit 0.0.5-beta.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,25 +1,23 @@
1
1
  const fs = require('fs');
2
- const { DEFAULT_MODULE_DIR, MODULE_CONFIG_FILENAME, MODULE_CONFIG_INVALID_KEY } = require('../config/constant');
2
+ const { MODULE_CONFIG_FILENAME, MODULE_CONFIG_INVALID_KEY } = require('../config/constant');
3
3
  const { fail } = require('./log');
4
4
  const { resolve, isObject, isArray } = require('./widgets');
5
+ const { handleError } = require('./handleError');
5
6
 
6
7
  /**
7
8
  * 获取每个模块下面的信息,并且收集,后续更新到appJson里面
8
9
  * @param { object } file 操作目录下面所有的文件
9
10
  * @param { string } appName 小程序的名称
10
11
  */
11
- function setModuleConfig(file, appName, moduleDir) {
12
+
13
+ function setModuleConfig(file, appName) {
12
14
  const content = file.contents ? JSON.parse(file.contents.toString()) : JSON.parse(file);
13
15
 
14
- if (isObject(content)) {
15
- content.root = content.root.indexOf(moduleDir) > -1 ? content.root : `${moduleDir}/${content.root}`;
16
- }
17
16
 
18
17
  if (isArray(content)) {
19
18
  let i = content.length - 1;
20
19
  while (i >= 0) {
21
20
  let current = content[i];
22
- current.root = current.root.indexOf(moduleDir) > -1 ? current.root : `${moduleDir}/${current.root}`;
23
21
 
24
22
  if (appName && current.mpConfig && current.mpConfig[appName]) {
25
23
  current = { ...current, ...current.mpConfig[appName] };
@@ -38,16 +36,17 @@ function setModuleConfig(file, appName, moduleDir) {
38
36
  /**
39
37
  * 递归获取本地所有模块的配置信息
40
38
  */
41
- function getLocalModuleConfig(modules = [], appName, moduleDir, moduleConfigFilename) {
39
+ function getLocalModuleConfig(modules = [], appName, moduleConfigFilename) {
42
40
  const modulesConfig = {};
43
41
 
44
42
  modules.forEach(({ path }) => {
45
43
  const moduleConfigPath = resolve(path, moduleConfigFilename);
46
44
  if (fs.existsSync(moduleConfigPath)) {
47
45
  const content = fs.readFileSync(moduleConfigPath, 'utf-8');
48
- modulesConfig[moduleConfigPath] = setModuleConfig(content, appName, moduleDir);
46
+ modulesConfig[moduleConfigPath] = setModuleConfig(content, appName);
49
47
  }
50
48
  });
49
+
51
50
  return modulesConfig;
52
51
  }
53
52
 
@@ -111,10 +110,22 @@ const updateSubpackages = (appJson, modulesConfig) => {
111
110
  // eslint-disable-next-line
112
111
  for (const name in modulesConfig) {
113
112
  const moduleInfo = isObject(modulesConfig[name]) ? [modulesConfig[name]] : modulesConfig[name];
113
+ // 过滤 pages 为空的情况
114
+ const validModules = getValidModules(moduleInfo);
114
115
  // eslint-disable-next-line
115
- appJson.subpackages = appJson.subpackages.concat(moduleInfo);
116
+ appJson.subpackages = appJson.subpackages.concat(validModules);
116
117
  }
117
118
  };
119
+ /**
120
+ * 过滤页面为空的分包
121
+ * @param {Array} moduleCfg 模块配置内容
122
+ * @returns pages不为空的分包
123
+ */
124
+ const getValidModules = (moduleCfg) => {
125
+ // 过滤 pages 为空的情况
126
+ const validModules = moduleCfg.filter(item => item.pages.length > 0);
127
+ return validModules;
128
+ };
118
129
 
119
130
  /**
120
131
  * 处理合并subpackages后的appjson, 整理重复不合法的地方
@@ -127,6 +138,11 @@ const processAppJson = (appJson) => {
127
138
  const subps = subpackages.map((subp) => {
128
139
  const invalidKeys = [];
129
140
  Object.keys(subp).forEach((key) => {
141
+ if (key === 'dependencies') {
142
+ // eslint-disable-next-line
143
+ delete subp.dependencies;
144
+ return;
145
+ }
130
146
  if (key === 'plugins') {
131
147
  Object.keys(subp.plugins).forEach((pk) => {
132
148
  pluginsMap[pk] ? pluginsMap[pk].push(`分包${subp.name}`) : pluginsMap[pk] = [`分包${subp.name}`];
@@ -164,7 +180,7 @@ const processAppJson = (appJson) => {
164
180
  })
165
181
  .reduce((pre, cur) => pre + cur, '');
166
182
  if (pluginsErrMsg) {
167
- fail(pluginsErrMsg);
183
+ fail(`plugins配置出现错误:${pluginsErrMsg}`);
168
184
  }
169
185
  // eslint-disable-next-line
170
186
  appJson.subpackages = subps;
@@ -177,24 +193,29 @@ const processAppJson = (appJson) => {
177
193
  * @param {array} modules
178
194
  * @returns
179
195
  */
180
- function buildOutputAppJson(tmsConfig, modules) {
181
- // 获取当前 modules 下的所有子模块的配置内容
182
- const modulesConfig = getLocalModuleConfig(modules, tmsConfig.appName, DEFAULT_MODULE_DIR, MODULE_CONFIG_FILENAME);
183
- // 获取app.json的配置
184
- const appJson = getAppJsonContent(resolve('./app.json'));
185
- // 更新app.json中的subpackages
186
- updateSubpackages(appJson, modulesConfig);
187
- // 处理appJson中重复||冲突的地方
188
- processAppJson(appJson);
189
- // 更新主包,需在subpackages处理完成后执行, pages/
190
- updateMainPackages(appJson, tmsConfig.mainPackages, DEFAULT_MODULE_DIR);
191
-
192
- fs.writeFileSync(resolve(`${tmsConfig.gulp.outputDir}/app.json`), JSON.stringify(appJson, null, 2), 'utf8');
193
-
194
- return appJson;
196
+ function buildOutputAppJson(tmsConfig, modules, isDev) {
197
+ try {
198
+ // 获取当前 modules 下的所有子模块的配置内容
199
+ const modulesConfig = getLocalModuleConfig(modules, tmsConfig.appName, MODULE_CONFIG_FILENAME);
200
+ // 获取app.json的配置
201
+ const appJson = getAppJsonContent(resolve('./app.json'));
202
+ // 更新app.json中的subpackages
203
+ updateSubpackages(appJson, modulesConfig);
204
+ // 处理appJson中重复||冲突的地方
205
+ processAppJson(appJson);
206
+ // 更新主包,需在subpackages处理完成后执行, pages/
207
+ updateMainPackages(appJson, tmsConfig.mainPackages);
208
+
209
+ fs.writeFileSync(resolve(`${tmsConfig.outputDir}/app.json`), JSON.stringify(appJson, null, 2), 'utf8');
210
+
211
+ return appJson;
212
+ } catch (e) {
213
+ handleError(`生成app.json出现错误: ${e}`, isDev);
214
+ }
195
215
  }
196
216
 
197
217
  module.exports = {
198
218
  setModuleConfig,
219
+ getValidModules,
199
220
  buildOutputAppJson,
200
221
  };
@@ -2,8 +2,8 @@ const fs = require('fs');
2
2
  const semver = require('semver');
3
3
  const { resolve } = require('./widgets');
4
4
  const path = require('path');
5
- const { fail } = require('./log');
6
5
  const shelljs = require('shelljs');
6
+ const { handleError } = require('./handleError');
7
7
 
8
8
  const getLatestVersion = (npmName) => {
9
9
  const data = shelljs.exec(`npm view ${npmName} version`);
@@ -17,7 +17,7 @@ const getLatestVersion = (npmName) => {
17
17
  * @param {*} outputDir 待检查node_modules存放的目录 (eg: dist/node_modules)
18
18
  * @returns
19
19
  */
20
- const checkDependencies = (modules, cwd, outputDir) => {
20
+ const checkDependencies = (modules, cwd, outputDir, isDev) => {
21
21
  // 步骤1. 收集package.json
22
22
  const packageJsonName = 'package.json'; // 查找文件名
23
23
  // 1.1根目录的package.json
@@ -41,12 +41,12 @@ const checkDependencies = (modules, cwd, outputDir) => {
41
41
  // 步骤2. 比较package.json的依赖与node_modules依赖的版本号
42
42
  for (const item of packageArr) {
43
43
  const packageJson = fs.readFileSync(item.srcPackageDir, 'utf-8');
44
- let dependencies;
44
+ let dependencies = {};
45
45
  try {
46
- dependencies = JSON.parse(packageJson).dependencies;
46
+ const json = JSON.parse(packageJson);
47
+ dependencies = json?.dependencies ? json?.dependencies : {};
47
48
  } catch (e) {
48
- fail(`解析${packageJson}报错,请检查是否是正确的json配置项`);
49
- process.exit(1);
49
+ handleError(`解析${item.srcPackageDir}报错,请检查是否是正确的json配置项`, isDev);
50
50
  }
51
51
  const dependenciesKeys = Object.keys(dependencies);
52
52
  for (const key of dependenciesKeys) {
@@ -1,9 +1,29 @@
1
1
  const MetalSmith = require('metalsmith');
2
2
  const { getGlobalInstance } = require('./global.js');
3
3
  const { downloadRepoForGit, resolve } = require('./widgets');
4
+ const { readTmsPrivateCf } = require('../utils/tkitUtils');
4
5
  const { fail } = require('./log');
5
6
  const fs = require('fs');
6
7
  const shelljs = require('shelljs');
8
+ const { handleError } = require('./handleError.js');
9
+
10
+ /**
11
+ * 处理用户没有clone git仓库权限问题——拼接账号信息
12
+ * @param {*} httpRepoUrl
13
+ * @param {*} moduleName
14
+ * @returns
15
+ */
16
+ function replaceGitUrlAccount(httpRepoUrl, moduleName, privateCf) {
17
+ let gitUrl = httpRepoUrl;
18
+ const { username = '', pass = '' } = privateCf?.gitAccout?.[moduleName] || {};
19
+
20
+ const urlPrefixReg = /http(s)?:\/\//;
21
+ if (username && pass && urlPrefixReg.test(gitUrl)) {
22
+ gitUrl = gitUrl.replace(urlPrefixReg, val => `${val}${encodeURIComponent(username)}:${pass}@`);
23
+ }
24
+
25
+ return gitUrl;
26
+ }
7
27
 
8
28
  /**
9
29
  * 对克隆下来的模块进行相应的文件处理操作,比如收集处理模块信息,进行信息缓存等操作
@@ -14,15 +34,15 @@ const shelljs = require('shelljs');
14
34
  */
15
35
  function moveFile(sourceDir, targetDir, ignore = []) {
16
36
  // 删除不是文件夹的文件
17
- return new Promise((resolve) => {
37
+ return new Promise((resolve, reject) => {
18
38
  MetalSmith(__dirname)
19
39
  .ignore(ignore)
20
40
  .source(sourceDir)
21
41
  .destination(targetDir)
22
42
  .build((e) => {
23
43
  if (e) {
24
- fail(e); // eslint-disable-line
25
- console.log('MetalSmith 详细的错误信息:', e);
44
+ fail(`${sourceDir} moveFile ${targetDir}出现错误: ${e}`);
45
+ reject(e);
26
46
  }
27
47
  resolve();
28
48
  });
@@ -33,13 +53,17 @@ function moveFile(sourceDir, targetDir, ignore = []) {
33
53
  * 下载目标模块
34
54
  * @param { string } sourceDir 缓存文件夹
35
55
  * @param { string } targetDir 目标文件夹
56
+ * @param { boolean } isDev 是否是dev
36
57
  * @returns { array } modules 描述模块的列表
37
58
  */
38
- async function cloneModules(sourceDir, targetDir, modules) {
59
+ async function cloneModules(sourceDir, targetDir, modules, isDev) {
60
+ // 用户本地的私有项目配置(用来配置环境\模块信息\账号信息)
61
+ const privateCf = readTmsPrivateCf();
62
+
39
63
  // 根据小程序的配置文件下载模块, 并且处理信息
40
- for (const moduleInfo of modules) { // eslint-disable-line
64
+ for (const moduleInfo of modules) {
41
65
  if (moduleInfo.repoInfo) {
42
- await downLoadAndMoveModule(sourceDir, targetDir, moduleInfo);
66
+ await downLoadAndMoveModule(sourceDir, targetDir, moduleInfo, privateCf, isDev);
43
67
  }
44
68
  }
45
69
  }
@@ -48,13 +72,14 @@ async function cloneModules(sourceDir, targetDir, modules) {
48
72
  * 下载模块信息并且将它移动到对应的位置
49
73
  * @param { string } sourceDir 代码缓存文件夹
50
74
  * @param { string } targetDir 代码要放到的目标文件夹
75
+ * @param { boolean } isDev 是否是dev
51
76
  * @returns { array } moduleInfo 描述模块的信息
52
77
  */
53
- async function downLoadAndMoveModule(sourceDir, targetDir, moduleInfo) {
54
- const { repoInfo: { buildGitTag, httpRepoUrl }, path } = moduleInfo;
78
+ async function downLoadAndMoveModule(sourceDir, targetDir, moduleInfo, privateCf, isDev) {
79
+ const { repoInfo: { buildGitTag, httpRepoUrl }, path, name } = moduleInfo;
55
80
 
56
81
  // 源码临时存在的源目录
57
- let sourcePath = resolve(sourceDir, path);
82
+ let sourcePath = resolve(sourceDir, name);
58
83
  // 源码要放到目标目录
59
84
  const targetPath = resolve(targetDir, path);
60
85
  // 设置模块的构建分支
@@ -66,22 +91,23 @@ async function downLoadAndMoveModule(sourceDir, targetDir, moduleInfo) {
66
91
 
67
92
  try {
68
93
  if (!moduleInCache) {
69
- await downloadRepoForGit(httpRepoUrl, sourcePath, cloneBranch);
94
+ // 处理仓库权限问题
95
+ const gitUrl = replaceGitUrlAccount(httpRepoUrl, name, privateCf);
96
+ await downloadRepoForGit(gitUrl, sourcePath, cloneBranch);
70
97
  globalInstance.setModuleCache(httpRepoUrl, cloneBranch, sourcePath);
71
98
  } else {
72
99
  sourcePath = globalInstance.getModuleCache(httpRepoUrl, cloneBranch).dest;
73
100
  }
74
101
 
75
102
  if (fs.existsSync(targetPath)) {
76
- shelljs.rm('-rf', targetPath);
103
+ shelljs.rm('-rf', `${targetPath}/*`);
77
104
  }
78
105
  await moveFile(sourcePath, targetPath, [
79
106
  'node_modules',
80
107
  '.git',
81
108
  ]);
82
109
  } catch (e) {
83
- fail(`downLoadAndMoveModule ${e}`); // eslint-disable-line
84
- process.exit(-1);
110
+ handleError(e, isDev);
85
111
  }
86
112
  }
87
113
 
@@ -0,0 +1,16 @@
1
+ const { fail } = require('./log');
2
+
3
+ function handleError(error, isDev = false) {
4
+ const errMsg = typeof error === 'object' ? error.message : error;
5
+ if (isDev) {
6
+ fail(errMsg);
7
+ } else {
8
+ fail(errMsg);
9
+ process.exit(1);
10
+ }
11
+ }
12
+
13
+ module.exports = {
14
+ handleError,
15
+ };
16
+
package/src/utils/io.js CHANGED
@@ -32,7 +32,7 @@ const copyFile = function (src, dest) {
32
32
  if (fs.existsSync(dest)) {
33
33
  fs.unlinkSync(dest);
34
34
  }
35
- const dir = dest.substr(0, dest.lastIndexOf('/'));
35
+ const dir = path.dirname(dest);
36
36
  ensureDirExist(dir);
37
37
  fs.copyFileSync(src, dest);
38
38
  };
@@ -1,4 +1,3 @@
1
- /* eslint-disable require-jsdoc */
2
1
  const ci = require('miniprogram-ci');
3
2
  const path = require('path');
4
3
 
@@ -2,55 +2,74 @@
2
2
  * 本文件主要负责项目或者分包依赖的npm的安装
3
3
  */
4
4
  const fs = require('fs');
5
+ const fsExtra = require('fs-extra');
6
+ const crypto = require('crypto');
5
7
  const path = require('path');
6
8
  const shell = require('shelljs');
7
9
  const glob = require('glob-ignore');
8
10
  const LOG = require('./log');
9
11
 
10
- const dirpath = process.cwd(); // 项目根目录
12
+ const shellJsOption = { async: false, silent: true };
13
+ const dirPath = process.cwd(); // 项目根目录
11
14
 
12
- const getTarNpmFilename = targetDir => `${targetDir.replace(/\//g, '-')}.tar.gz`;
15
+ const install = async (packageJsonPath = '', retry = true, cacheDir) => {
16
+ const obj = {};
17
+ const packageContent = fs.readFileSync(packageJsonPath);
18
+ const packageJson = JSON.parse(packageContent);
19
+ obj.dependencies = packageJson.dependencies || {};
20
+ // obj.devDependencies = packageJson.devDependencies || {};
13
21
 
14
- // 缓存npm
15
- const npmCache = function (targetDir, cacheDir) {
16
- if (!fs.existsSync(cacheDir)) {
17
- fs.mkdirSync(cacheDir);
22
+ // dependencies和devDependencies字段为空,没有需要安装的npm包,直接return
23
+ // if (Object.keys(obj.dependencies).length === 0 && Object.keys(obj.devDependencies).length === 0) {
24
+ if (Object.keys(obj.dependencies).length === 0) {
25
+ return;
18
26
  }
19
- const tarNpmFilename = getTarNpmFilename(targetDir);
20
- const tarNpmFilePath = `${cacheDir}/${tarNpmFilename}`;
21
- if (fs.existsSync(tarNpmFilePath)) {
22
- shell.rm('-rf', tarNpmFilePath);
23
- }
24
- const cmd = `tar -zcvf ${tarNpmFilePath} ./node_modules`;
25
- shell.exec(cmd, { async: true, silent: true });
26
- // tar -zcvf /Users/odile/.tmskit/node_modules.tar.gz ./node_modules
27
- };
28
27
 
29
- // 获取缓存npm包
30
- const getNpmCache = function (targetDir, cacheDir) {
31
- const tarNpmFilename = getTarNpmFilename(targetDir);
32
- const tarNpmFilePath = `${cacheDir}/${tarNpmFilename}`;
33
- if (fs.existsSync(tarNpmFilePath)) {
34
- const cmd = `tar -zxvf ${tarNpmFilePath} -C ./`;
35
- shell.exec(cmd, { async: false, silent: true });
28
+ // 以package.json中dependencies字段stringify后的md5值作为缓存key
29
+ // 任意包名或者版本号的差异,将导致md5后的差异,从而导致缓存失效,重新下载
30
+ // 如此来保证npm缓存的准确性
31
+ const str = JSON.stringify(obj);
32
+ const key = crypto.createHash('md5').update(str)
33
+ .digest('hex');
34
+ const keyPath = path.join(cacheDir, key);
35
+ const tarFile = path.join(keyPath, 'node_modules.tar.gz');
36
+
37
+ // npm缓存路径不存在
38
+ // 或者缓存的包大小小于512byte,认为缓存不合法
39
+ // 清空缓存目录,重新下载npm包缓存
40
+ const missCache = !fsExtra.pathExistsSync(keyPath)
41
+ || !fsExtra.existsSync(tarFile)
42
+ || fsExtra.statSync(tarFile).size < 512;
43
+ if (missCache) {
44
+ console.log(`未命中缓存,下载${packageJsonPath}依赖`);
45
+ fsExtra.emptydirSync(keyPath);
46
+ shell.cp('-f', packageJsonPath, keyPath);
47
+ shell.cd(keyPath);
48
+ try {
49
+ shell.exec('npx yarn --production --registry http://mirrors.tencent.com/npm/', shellJsOption);
50
+ } catch (err) {
51
+ console.log('err', err);
52
+ if (retry) {
53
+ return await install(packageJsonPath, false);
54
+ }
55
+ throw err;
56
+ }
57
+ shell.exec('tar -zcvf ./node_modules.tar.gz ./node_modules', shellJsOption);
58
+ shell.exec('rm -rf ./node_modules', shellJsOption);
36
59
  }
37
- // tar -zxvf /Users/odile/.tmskit/node_modules.tar.gz -C ./
60
+ shell.cp('-Rf', tarFile, `${path.dirname(packageJsonPath)}/`);
61
+ shell.cd(path.dirname(packageJsonPath));
62
+
63
+ shell.exec('tar -xzvf ./node_modules.tar.gz -C ./', shellJsOption);
64
+ shell.exec('rm -rf ./node_modules.tar.gz', shellJsOption);
65
+ return { missCache, key };
38
66
  };
39
67
 
40
68
 
41
69
  // 遍历安装指定目录下所有项目的npm依赖
42
70
  const mpNpmInstallAll = async (modules, contextDir, cacheDir) => {
43
71
  const packageJsonFiles = await findAllPackageJson(modules, contextDir);
44
- await Promise.all(packageJsonFiles.map(file => new Promise((resolve) => {
45
- const dir = path.dirname(file);
46
- shell.cd(dir);
47
- if (!fs.existsSync(`${dir}/node_modules`)) {
48
- getNpmCache(dir, cacheDir);
49
- }
50
- shell.exec('npx pnpm install --prod --registry http://mirrors.tencent.com/npm/', { silent: false });
51
- resolve();
52
- npmCache(dir, cacheDir);
53
- })));
72
+ await Promise.all(packageJsonFiles.map(file => install(file, true, cacheDir)));
54
73
  };
55
74
 
56
75
  /**
@@ -106,10 +125,9 @@ const findFilesByFilter = (startPath, filter) => {
106
125
  */
107
126
  const findAllPackageJson = (subRoots = [], contextDir) => {
108
127
  const packageJsonName = 'package.json'; // 查找文件名
109
- const cwd = contextDir || dirpath;
128
+ const cwd = contextDir || dirPath;
110
129
  const result = [path.join(cwd, packageJsonName)]; // 默认填充根目录下的package.json
111
130
 
112
-
113
131
  subRoots.forEach((subRoot) => {
114
132
  if (!subRoot.root) {
115
133
  LOG.fail(`请检查${subRoot.name}的module.config.json是否有root字段`);
@@ -1,13 +1,14 @@
1
1
  const loadash = require('lodash');
2
2
  const fs = require('fs');
3
- const { TMS_NAME, TMS_CONFIG_FILENAME, MODULE_CONFIG_FILENAME } = require('../config/constant');
3
+ const { TMS_NAME, TMS_CONFIG_FILENAME, MODULE_CONFIG_FILENAME, TMS_PRIVATE_FILENAME } = require('../config/constant');
4
4
  const { resolve, isObject } = require('./widgets');
5
- const { setModuleConfig } = require('./buildAppJson');
5
+ const { setModuleConfig, getValidModules } = require('./buildAppJson');
6
6
  const defaultTmsConfig = require('../config/defaultTmsConfig');
7
7
  const { fail } = require('./log');
8
+ const path = require('path');
8
9
 
9
10
  /**
10
- * 读取tms.config.json
11
+ * 读取tms.config.js
11
12
  * @param env {string} 环境变量
12
13
  */
13
14
  const readTmsConfig = function (env) {
@@ -22,9 +23,45 @@ const readTmsConfig = function (env) {
22
23
  });
23
24
  // 合并默认值
24
25
  loadash.mergeWith(tmsConfig, defaultTmsConfig);
26
+ // modules兼容处理
27
+ tmsConfig.modules = convertModules(tmsConfig.modules);
25
28
  return tmsConfig;
26
29
  };
27
30
 
31
+ // convertModules 处理默认值
32
+ const convertModules = (modules) => {
33
+ const newModules = [];
34
+ modules.forEach((module, index) => {
35
+ const newModule = {};
36
+ if (typeof module === 'string') {
37
+ // 路径字符串
38
+ Object.assign(newModule, {
39
+ name: path.basename(module),
40
+ path: module,
41
+ });
42
+ } else if (typeof module === 'object') {
43
+ Object.assign(newModule, module);
44
+ if (module.name === undefined) {
45
+ newModule.name = path.basename(module.path);
46
+ }
47
+ }
48
+ newModules.push(newModule);
49
+ });
50
+ return newModules;
51
+ };
52
+
53
+ /**
54
+ * 读取tms.private.js
55
+ */
56
+ const readTmsPrivateCf = function () {
57
+ let tmsPrivateCg;
58
+ const tmsPrivatePath = resolve(TMS_PRIVATE_FILENAME);
59
+ if (fs.existsSync(tmsPrivatePath)) {
60
+ tmsPrivateCg = require(tmsPrivatePath);
61
+ }
62
+ return tmsPrivateCg;
63
+ };
64
+
28
65
  /**
29
66
  * 从tms.config.json中检索用户传入的有效modules
30
67
  * @param { object } tmsConfig
@@ -32,7 +69,7 @@ const readTmsConfig = function (env) {
32
69
  * @returns
33
70
  */
34
71
  const checkModules = function (tmsConfig, modules) {
35
- const targetModules = [];
72
+ const targetModules = [];
36
73
  modules.forEach((moduleName) => {
37
74
  const module = tmsConfig.modules.find(module => module.name === moduleName);
38
75
  module && targetModules.push(module);
@@ -51,22 +88,29 @@ const checkModules = function (tmsConfig, modules) {
51
88
  * @param {string} moduleDir
52
89
  * @returns
53
90
  */
54
- const tmsModulesMergeLocalModuleCfg = (modules, appName, moduleDir) => {
91
+ const tmsModulesMergeLocalModuleCfg = (modules, appName) => {
55
92
  const newModules = [];
56
93
  modules.forEach(({ path: relativePath, name: moduleName }, moduleIndex) => {
57
94
  const moduleConfigPath = resolve(relativePath, MODULE_CONFIG_FILENAME);
58
95
  if (fs.existsSync(moduleConfigPath)) {
59
- let moduleConfigContent = fs.readFileSync(moduleConfigPath, 'utf-8');
60
- moduleConfigContent = setModuleConfig(moduleConfigContent, appName, moduleDir);
61
- const moduleContentArr = isObject(moduleConfigContent) ? [moduleConfigContent] : moduleConfigContent;
62
- moduleContentArr.forEach(({ name }, moduleContentArrIndex) => {
63
- if (name === moduleName) {
64
- newModules.push({
65
- ...modules[moduleIndex],
66
- ...moduleContentArr[moduleContentArrIndex],
67
- });
68
- }
69
- });
96
+ try {
97
+ let moduleConfigContent = fs.readFileSync(moduleConfigPath, 'utf-8');
98
+ moduleConfigContent = setModuleConfig(moduleConfigContent, appName);
99
+ const moduleContentArr = isObject(moduleConfigContent) ? [moduleConfigContent] : moduleConfigContent;
100
+ getValidModules(moduleContentArr).forEach(({ name }, moduleContentArrIndex) => {
101
+ if (name === moduleName) {
102
+ newModules.push({
103
+ ...modules[moduleIndex],
104
+ ...moduleContentArr[moduleContentArrIndex],
105
+ });
106
+ }
107
+ });
108
+ } catch (e) {
109
+ fail(`${moduleConfigPath}配置错误: ${e}`);
110
+ newModules.push({
111
+ ...modules[moduleIndex],
112
+ });
113
+ }
70
114
  } else {
71
115
  newModules.push({
72
116
  ...modules[moduleIndex],
@@ -76,9 +120,39 @@ const tmsModulesMergeLocalModuleCfg = (modules, appName, moduleDir) => {
76
120
  return newModules;
77
121
  };
78
122
 
123
+ /**
124
+ * 分包依赖了分包的模块 合并所依赖的modules
125
+ * @param { object } tmsConfig
126
+ * @param {array} modules
127
+ * @param {string} moduleDir
128
+ * @returns
129
+ */
130
+ const subModulesMergeDepModules = (tmsConfig, modules) => {
131
+ const moduleNames = [];
132
+ modules.forEach(({ name: moduleName }) => {
133
+ moduleNames.push(moduleName);
134
+ });
135
+ let mergeModules = modules;
136
+ let isOver = true;
137
+ modules.forEach(({ dependencies: dependencyModules }) => {
138
+ dependencyModules?.forEach((item) => {
139
+ // 如果所有模块的dep都在moduleNames内,则所有依赖都齐了
140
+ // 否则递归处理,根据name找到相关配置加到modules里
141
+ if (moduleNames.indexOf(item) === -1) {
142
+ isOver = false;
143
+ const tmpModules = checkModules(tmsConfig, [...new Set([item])]);
144
+ mergeModules = [...mergeModules, ...tmpModules];
145
+ mergeModules = tmsModulesMergeLocalModuleCfg(mergeModules, tmsConfig.appName);
146
+ }
147
+ });
148
+ });
149
+ return isOver ? mergeModules : subModulesMergeDepModules(tmsConfig, mergeModules);
150
+ };
79
151
 
80
152
  module.exports = {
81
153
  readTmsConfig,
154
+ readTmsPrivateCf,
82
155
  checkModules,
83
156
  tmsModulesMergeLocalModuleCfg,
157
+ subModulesMergeDepModules,
84
158
  };
@@ -7,7 +7,7 @@ const fs = require('fs');
7
7
  const shelljs = require('shelljs');
8
8
  const download = require('download-git-repo');
9
9
  const chalk = require('chalk');
10
- const shelljsOptons = { slient: true };
10
+ const shelljsOptions = { slient: true };
11
11
 
12
12
  // 获取当前目录
13
13
  const cwd = process.cwd();
@@ -96,7 +96,7 @@ function downloadRepo(dest, downloadOptions = { repoUrl: '', gitUrl: '', branch:
96
96
  function downloadRepoForGit(url, dest, branch) {
97
97
  const cwd = process.cwd();
98
98
 
99
- return new Promise((resolve) => {
99
+ return new Promise((resolve, reject) => {
100
100
  // 如果目标目录不存在
101
101
  if (fs.existsSync(dest)) {
102
102
  shelljs.rm('-rf', path.join(dest));
@@ -105,7 +105,10 @@ function downloadRepoForGit(url, dest, branch) {
105
105
  shelljs.mkdir('-p', dest);
106
106
  shelljs.cd(dest);
107
107
 
108
- shelljs.exec(`git clone ${url} ${dest} --branch ${branch} --depth 1`, shelljsOptons);
108
+ const gitCloneRes = shelljs.exec(`git clone ${url} ${dest} --branch ${branch} --depth 1`, shelljsOptions);
109
+ if (gitCloneRes.code !== 0) {
110
+ reject(gitCloneRes.stderr);
111
+ }
109
112
 
110
113
  shelljs.cd(cwd);
111
114
  resolve();
@@ -129,22 +132,16 @@ const cost = start => Date.now() - start;
129
132
  function createTask(task, startText, endText) {
130
133
  return async (...args) => {
131
134
  const start = Date.now();
132
- let result;
133
135
 
134
136
  const spinner = ora(startText);
137
+
135
138
  spinner.start();
139
+ console.log('\n');
136
140
 
137
- try {
138
- result = await task(...args);
139
- } catch (e) {
140
- result = e;
141
- console.log(chalk.red(e));
141
+ const result = await task(...args);
142
142
 
143
- process.exit(-1);
144
- } finally {
145
- endText && spinner.succeed(`${endText}, ${cost(start)}ms`);
146
- spinner.stop();
147
- }
143
+ endText && spinner.succeed(`${endText}, ${cost(start)}ms`);
144
+ spinner.stop();
148
145
 
149
146
  return result;
150
147
  };