@htyf-mp/cli 0.2.0-alpha.3 → 0.2.0-alpha.5
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.
- package/package.json +1 -1
- package/src/command-executor.mjs +60 -34
- package/src/config.mjs +7 -10
- package/src/constants.mjs +2 -3
- package/src/debug.mjs +27 -6
- package/src/file-system.mjs +18 -0
- package/src/index.mjs +50 -1
- package/src/project-initializer.mjs +82 -16
- package/src/template-processor.mjs +2 -2
package/package.json
CHANGED
package/src/command-executor.mjs
CHANGED
|
@@ -20,46 +20,72 @@ export class CommandExecutor {
|
|
|
20
20
|
const displayCommand = showCommand ? command : description;
|
|
21
21
|
const spinner = ora(displayCommand).start();
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
23
|
+
// 信号处理:当收到退出信号时,停止 spinner
|
|
24
|
+
const cleanup = () => {
|
|
25
|
+
spinner.stop();
|
|
26
|
+
};
|
|
27
|
+
process.once('SIGINT', cleanup);
|
|
28
|
+
process.once('SIGTERM', cleanup);
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
for (let attempt = 1; attempt <= retryCount; attempt++) {
|
|
32
|
+
try {
|
|
33
|
+
Logger.debug(`执行命令 (尝试 ${attempt}/${retryCount}): ${command}`);
|
|
34
|
+
|
|
35
|
+
const result = await new Promise((resolve, reject) => {
|
|
36
|
+
const timeoutId = setTimeout(() => {
|
|
37
|
+
reject(new Error(`命令执行超时 (${timeout}ms)`));
|
|
38
|
+
}, timeout);
|
|
39
|
+
|
|
40
|
+
shell.exec(command, {
|
|
41
|
+
silent: silent,
|
|
42
|
+
fatal: false,
|
|
43
|
+
async: false
|
|
44
|
+
}, (code, stdout, stderr) => {
|
|
45
|
+
clearTimeout(timeoutId);
|
|
46
|
+
resolve({ code, stdout, stderr });
|
|
47
|
+
});
|
|
39
48
|
});
|
|
40
|
-
});
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
if (result.code === 0) {
|
|
51
|
+
process.removeListener('SIGINT', cleanup);
|
|
52
|
+
process.removeListener('SIGTERM', cleanup);
|
|
53
|
+
spinner.succeed(`${description} 成功`);
|
|
54
|
+
Logger.debug(`命令输出: ${result.stdout}`);
|
|
55
|
+
return result;
|
|
56
|
+
} else {
|
|
57
|
+
throw new Error(`命令执行失败,退出码: ${result.code}, 错误: ${result.stderr}`);
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
// 如果是用户中断,直接退出
|
|
61
|
+
if (error.message && (error.message.includes('SIGINT') || error.message.includes('SIGTERM'))) {
|
|
62
|
+
process.removeListener('SIGINT', cleanup);
|
|
63
|
+
process.removeListener('SIGTERM', cleanup);
|
|
64
|
+
spinner.stop();
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
53
67
|
|
|
54
|
-
if (
|
|
55
|
-
process.
|
|
68
|
+
if (attempt === retryCount) {
|
|
69
|
+
process.removeListener('SIGINT', cleanup);
|
|
70
|
+
process.removeListener('SIGTERM', cleanup);
|
|
71
|
+
spinner.fail(`${description} 失败 (${retryCount} 次尝试后)`);
|
|
72
|
+
Logger.error(`命令执行失败: ${error.message}`);
|
|
73
|
+
|
|
74
|
+
if (fatal) {
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
throw error;
|
|
78
|
+
} else {
|
|
79
|
+
Logger.warn(`命令执行失败,准备重试 (${attempt}/${retryCount}): ${error.message}`);
|
|
80
|
+
await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); // 递增延迟
|
|
56
81
|
}
|
|
57
|
-
throw error;
|
|
58
|
-
} else {
|
|
59
|
-
Logger.warn(`命令执行失败,准备重试 (${attempt}/${retryCount}): ${error.message}`);
|
|
60
|
-
await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); // 递增延迟
|
|
61
82
|
}
|
|
62
83
|
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
process.removeListener('SIGINT', cleanup);
|
|
86
|
+
process.removeListener('SIGTERM', cleanup);
|
|
87
|
+
spinner.stop();
|
|
88
|
+
throw error;
|
|
63
89
|
}
|
|
64
90
|
}
|
|
65
91
|
|
package/src/config.mjs
CHANGED
|
@@ -13,17 +13,14 @@ export class ProjectConfig {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
this.templates = {
|
|
16
|
-
[CONSTANTS.TEMPLATE_TYPES.
|
|
17
|
-
name: '
|
|
18
|
-
tempPath: '
|
|
19
|
-
files: {
|
|
20
|
-
src: 'expo_src',
|
|
21
|
-
app: 'expo.App.tsx',
|
|
22
|
-
index: 'expo.index.js',
|
|
23
|
-
babel: 'expo.babel.config.js',
|
|
24
|
-
config: 'expo.project.dgz.json'
|
|
25
|
-
}
|
|
16
|
+
[CONSTANTS.TEMPLATE_TYPES.APP_TEMPLATE]: {
|
|
17
|
+
name: 'app-template',
|
|
18
|
+
tempPath: '_apps_temp_'
|
|
26
19
|
},
|
|
20
|
+
[CONSTANTS.TEMPLATE_TYPES.GAME_TEMPLATE]: {
|
|
21
|
+
name: 'game-template',
|
|
22
|
+
tempPath: '_games_temp_'
|
|
23
|
+
}
|
|
27
24
|
};
|
|
28
25
|
}
|
|
29
26
|
|
package/src/constants.mjs
CHANGED
|
@@ -25,9 +25,8 @@ export const CONSTANTS = {
|
|
|
25
25
|
CODING: 'https://e.coding.net/dagouzhi/hongtangyun_mobile/htyf-mp.git'
|
|
26
26
|
},
|
|
27
27
|
TEMPLATE_TYPES: {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
GAME_COCOS: 'game-cocos',
|
|
28
|
+
APP_TEMPLATE: 'app-template',
|
|
29
|
+
GAME_TEMPLATE: 'game-template',
|
|
31
30
|
}
|
|
32
31
|
};
|
|
33
32
|
|
package/src/debug.mjs
CHANGED
|
@@ -94,14 +94,35 @@ export async function mpDebugShell(newAppInfo) {
|
|
|
94
94
|
Logger.info('调试服务器已启动,按 Ctrl+C 停止');
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
-
// 优雅关闭
|
|
98
|
-
|
|
99
|
-
Logger.info('正在关闭调试服务器...');
|
|
97
|
+
// 优雅关闭 - 移除全局处理,添加专用的服务器关闭处理
|
|
98
|
+
const handleShutdown = () => {
|
|
99
|
+
Logger.info('\n正在关闭调试服务器...');
|
|
100
|
+
let isClosed = false;
|
|
101
|
+
|
|
100
102
|
server.close(() => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
if (!isClosed) {
|
|
104
|
+
isClosed = true;
|
|
105
|
+
Logger.success('调试服务器已关闭');
|
|
106
|
+
process.exit(0);
|
|
107
|
+
}
|
|
103
108
|
});
|
|
104
|
-
|
|
109
|
+
|
|
110
|
+
// 如果服务器在 3 秒内没有关闭,强制退出
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
if (!isClosed) {
|
|
113
|
+
isClosed = true;
|
|
114
|
+
Logger.warn('强制退出...');
|
|
115
|
+
process.exit(0);
|
|
116
|
+
}
|
|
117
|
+
}, 3000);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// 移除全局的信号处理,添加专用的服务器关闭处理
|
|
121
|
+
// 这样可以确保服务器能够正确关闭
|
|
122
|
+
process.removeAllListeners('SIGINT');
|
|
123
|
+
process.removeAllListeners('SIGTERM');
|
|
124
|
+
process.once('SIGINT', handleShutdown);
|
|
125
|
+
process.once('SIGTERM', handleShutdown);
|
|
105
126
|
|
|
106
127
|
} catch (error) {
|
|
107
128
|
Logger.error(`小程序调试失败: ${error.message}`);
|
package/src/file-system.mjs
CHANGED
|
@@ -62,6 +62,24 @@ export class FileSystemUtils {
|
|
|
62
62
|
return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* 检查目录是否为空
|
|
67
|
+
* @param {string} dirPath
|
|
68
|
+
* @returns {boolean}
|
|
69
|
+
*/
|
|
70
|
+
static isDirectoryEmpty(dirPath) {
|
|
71
|
+
if (!fs.existsSync(dirPath)) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const entries = fs.readdirSync(dirPath);
|
|
76
|
+
return entries.length === 0;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
Logger.warn(`读取目录内容失败: ${dirPath}`, error.message);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
65
83
|
static validatePath(path) {
|
|
66
84
|
// if (/[ - fa5]/gi.test(path)) {
|
|
67
85
|
// return { isValid: false, error: '路径中包含中文字符' };
|
package/src/index.mjs
CHANGED
|
@@ -27,6 +27,48 @@ import { incrementVersion, updateAppConfig } from './utils-functions.mjs';
|
|
|
27
27
|
|
|
28
28
|
const projectPath = getProjectRoot();
|
|
29
29
|
|
|
30
|
+
// 全局状态管理,用于优雅退出
|
|
31
|
+
let isExiting = false;
|
|
32
|
+
let currentProcess = null;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 优雅退出处理
|
|
36
|
+
*/
|
|
37
|
+
function handleGracefulExit() {
|
|
38
|
+
if (isExiting) {
|
|
39
|
+
// 如果已经在退出中,强制退出
|
|
40
|
+
Logger.warn('强制退出...');
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
isExiting = true;
|
|
45
|
+
Logger.info('\n正在退出...');
|
|
46
|
+
|
|
47
|
+
// 如果有正在运行的进程,尝试关闭
|
|
48
|
+
if (currentProcess) {
|
|
49
|
+
try {
|
|
50
|
+
if (typeof currentProcess.close === 'function') {
|
|
51
|
+
currentProcess.close();
|
|
52
|
+
} else if (typeof currentProcess.kill === 'function') {
|
|
53
|
+
currentProcess.kill('SIGTERM');
|
|
54
|
+
}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
Logger.debug(`关闭进程时出错: ${error.message}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 延迟退出,给清理操作一些时间
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
Logger.info('再见!');
|
|
63
|
+
process.exit(0);
|
|
64
|
+
}, 100);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 注册全局信号处理(使用 once 确保只注册一次)
|
|
68
|
+
// 注意:某些模块(如 debug.mjs)可能会移除这些监听器并添加自己的处理
|
|
69
|
+
process.on('SIGINT', handleGracefulExit);
|
|
70
|
+
process.on('SIGTERM', handleGracefulExit);
|
|
71
|
+
|
|
30
72
|
/**
|
|
31
73
|
* 主启动函数
|
|
32
74
|
* @param {string} action - 操作类型
|
|
@@ -250,6 +292,13 @@ inquirer
|
|
|
250
292
|
}
|
|
251
293
|
})
|
|
252
294
|
.catch((error) => {
|
|
295
|
+
// 如果是用户取消(Ctrl+C),不显示错误
|
|
296
|
+
if (error.isTtyError || error.name === 'AbortError') {
|
|
297
|
+
handleGracefulExit();
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
253
300
|
Logger.error(`程序启动失败: ${error.message}`);
|
|
254
|
-
|
|
301
|
+
if (!isExiting) {
|
|
302
|
+
process.exit(1);
|
|
303
|
+
}
|
|
255
304
|
});
|
|
@@ -26,7 +26,28 @@ export class ProjectInitializer {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
async initialize() {
|
|
29
|
-
const spinner = ora('正在初始化项目...')
|
|
29
|
+
const spinner = ora('正在初始化项目...');
|
|
30
|
+
let tmpdir = null;
|
|
31
|
+
let rootPath = null;
|
|
32
|
+
|
|
33
|
+
// 信号处理:清理临时文件并停止 spinner
|
|
34
|
+
const handleExit = () => {
|
|
35
|
+
spinner.stop();
|
|
36
|
+
Logger.info('\n正在清理临时文件...');
|
|
37
|
+
if (tmpdir && fs.existsSync(tmpdir)) {
|
|
38
|
+
try {
|
|
39
|
+
fse.removeSync(tmpdir);
|
|
40
|
+
Logger.info('临时文件已清理');
|
|
41
|
+
} catch (error) {
|
|
42
|
+
Logger.warn(`清理临时文件时出错: ${error.message}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
Logger.info('已取消项目初始化');
|
|
46
|
+
process.exit(0);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
process.once('SIGINT', handleExit);
|
|
50
|
+
process.once('SIGTERM', handleExit);
|
|
30
51
|
|
|
31
52
|
try {
|
|
32
53
|
// 1. 获取用户输入
|
|
@@ -35,26 +56,41 @@ export class ProjectInitializer {
|
|
|
35
56
|
// 2. 验证输入
|
|
36
57
|
const validation = this.validateInputs(userInputs);
|
|
37
58
|
if (!validation.isValid) {
|
|
59
|
+
process.removeListener('SIGINT', handleExit);
|
|
60
|
+
process.removeListener('SIGTERM', handleExit);
|
|
38
61
|
spinner.fail('输入验证失败');
|
|
39
62
|
Logger.error(validation.error);
|
|
40
63
|
return;
|
|
41
64
|
}
|
|
42
65
|
|
|
43
66
|
// 3. 检查目录
|
|
44
|
-
|
|
67
|
+
rootPath = path.join(process.cwd(), userInputs.appName);
|
|
45
68
|
if (fs.existsSync(rootPath)) {
|
|
69
|
+
process.removeListener('SIGINT', handleExit);
|
|
70
|
+
process.removeListener('SIGTERM', handleExit);
|
|
46
71
|
spinner.fail('目录已存在');
|
|
47
72
|
Logger.error(`目录已存在: ${rootPath}`);
|
|
48
73
|
return;
|
|
49
74
|
}
|
|
50
75
|
|
|
51
|
-
// 4.
|
|
52
|
-
|
|
76
|
+
// 4. 创建项目(在此之前启动 spinner)
|
|
77
|
+
spinner.start();
|
|
78
|
+
spinner.text = '正在初始化项目...';
|
|
79
|
+
// 传递 tmpdir 引用以便清理
|
|
80
|
+
await this.createProject(userInputs, rootPath, spinner, (dir) => {
|
|
81
|
+
tmpdir = dir;
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// 移除信号监听器
|
|
85
|
+
process.removeListener('SIGINT', handleExit);
|
|
86
|
+
process.removeListener('SIGTERM', handleExit);
|
|
53
87
|
|
|
54
88
|
// 5. 显示成功信息
|
|
55
|
-
this.showSuccessInfo(userInputs.appName, rootPath);
|
|
89
|
+
this.showSuccessInfo(userInputs.appName, rootPath, userInputs.templateType);
|
|
56
90
|
|
|
57
91
|
} catch (error) {
|
|
92
|
+
process.removeListener('SIGINT', handleExit);
|
|
93
|
+
process.removeListener('SIGTERM', handleExit);
|
|
58
94
|
spinner.fail('项目初始化失败');
|
|
59
95
|
Logger.error('初始化失败:', error.message);
|
|
60
96
|
if (error.exitCode === 128) {
|
|
@@ -106,7 +142,6 @@ export class ProjectInitializer {
|
|
|
106
142
|
message: '请选择模板镜像?',
|
|
107
143
|
choices: [
|
|
108
144
|
{ name: 'GitHub (最新)', value: CONSTANTS.TEMPLATE_REPOS.GITHUB },
|
|
109
|
-
{ name: 'Coding (最快)', value: CONSTANTS.TEMPLATE_REPOS.CODING }
|
|
110
145
|
]
|
|
111
146
|
});
|
|
112
147
|
|
|
@@ -122,13 +157,18 @@ export class ProjectInitializer {
|
|
|
122
157
|
return { isValid: true };
|
|
123
158
|
}
|
|
124
159
|
|
|
125
|
-
async createProject(userInputs, rootPath, spinner) {
|
|
160
|
+
async createProject(userInputs, rootPath, spinner, setTmpdirCallback = null) {
|
|
126
161
|
const { appName, displayName, templateType, repoType } = userInputs;
|
|
127
162
|
|
|
128
163
|
// 创建临时目录
|
|
129
164
|
spinner.text = '正在准备临时目录...';
|
|
130
165
|
const tmpdir = path.join(os.tmpdir(), md5('__HTYF__'), appName);
|
|
131
166
|
fse.emptyDirSync(tmpdir);
|
|
167
|
+
|
|
168
|
+
// 设置临时目录引用,以便在退出时清理
|
|
169
|
+
if (setTmpdirCallback) {
|
|
170
|
+
setTmpdirCallback(tmpdir);
|
|
171
|
+
}
|
|
132
172
|
|
|
133
173
|
try {
|
|
134
174
|
// 克隆仓库
|
|
@@ -153,7 +193,7 @@ export class ProjectInitializer {
|
|
|
153
193
|
const projectConfig = this.config.createProjectConfig(appName, displayName, appid);
|
|
154
194
|
|
|
155
195
|
// 写入配置文件
|
|
156
|
-
const configPath = path.join(appRootPath, '
|
|
196
|
+
const configPath = path.join(appRootPath, 'htyf.json');
|
|
157
197
|
fs.writeFileSync(configPath, JSON.stringify(projectConfig, undefined, 2));
|
|
158
198
|
|
|
159
199
|
// 清理临时文件
|
|
@@ -165,7 +205,19 @@ export class ProjectInitializer {
|
|
|
165
205
|
|
|
166
206
|
// 移动到目标目录
|
|
167
207
|
spinner.text = '正在创建项目目录...';
|
|
168
|
-
|
|
208
|
+
|
|
209
|
+
if (fs.existsSync(rootPath)) {
|
|
210
|
+
fse.ensureDirSync(rootPath);
|
|
211
|
+
const items = fs.readdirSync(appRootPath);
|
|
212
|
+
items.forEach((item) => {
|
|
213
|
+
const source = path.join(appRootPath, item);
|
|
214
|
+
const destination = path.join(rootPath, item);
|
|
215
|
+
fse.moveSync(source, destination, { overwrite: true });
|
|
216
|
+
});
|
|
217
|
+
fse.removeSync(appRootPath);
|
|
218
|
+
} else {
|
|
219
|
+
fse.moveSync(appRootPath, rootPath);
|
|
220
|
+
}
|
|
169
221
|
|
|
170
222
|
// 清理临时目录
|
|
171
223
|
fse.removeSync(tmpdir);
|
|
@@ -181,19 +233,33 @@ export class ProjectInitializer {
|
|
|
181
233
|
}
|
|
182
234
|
}
|
|
183
235
|
|
|
184
|
-
showSuccessInfo(appName, rootPath) {
|
|
236
|
+
showSuccessInfo(appName, rootPath, templateType) {
|
|
185
237
|
console.log('\n' + boxen(
|
|
186
238
|
gradient.rainbow('🎉 项目创建成功!') + '\n\n' +
|
|
187
239
|
chalk.cyan('项目名称: ') + chalk.white(appName) + '\n' +
|
|
188
240
|
chalk.cyan('项目路径: ') + chalk.white(rootPath) + '\n\n' +
|
|
189
241
|
chalk.yellow('下一步操作:') + '\n' +
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
242
|
+
(() => {
|
|
243
|
+
const relativePath = path.relative(process.cwd(), rootPath);
|
|
244
|
+
const commands = [];
|
|
245
|
+
if (relativePath) {
|
|
246
|
+
commands.push(chalk.white(` cd ${relativePath}`));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (templateType === CONSTANTS.TEMPLATE_TYPES.GAME_TEMPLATE) {
|
|
250
|
+
commands.push(chalk.white(' npm install'));
|
|
251
|
+
} else {
|
|
252
|
+
commands.push(
|
|
253
|
+
chalk.white(' npm install'),
|
|
254
|
+
chalk.white(' npm run ios'),
|
|
255
|
+
chalk.white(' npm run android')
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return commands.join('\n');
|
|
260
|
+
})() + '\n\n' +
|
|
193
261
|
chalk.blue('常用命令:') + '\n' +
|
|
194
|
-
chalk.white(' npm run
|
|
195
|
-
chalk.white(' npm run build:h5 # 构建H5版本') + '\n' +
|
|
196
|
-
chalk.white(' npm run build:rn # 构建React Native版本') + '\n\n' +
|
|
262
|
+
chalk.white(' npm run htyf # 构建红糖云服小程序') + '\n' +
|
|
197
263
|
chalk.gray('💡 提示: 使用 --debug 参数可以查看详细的调试信息'),
|
|
198
264
|
{
|
|
199
265
|
padding: 1,
|
|
@@ -89,7 +89,7 @@ export class TemplateProcessor {
|
|
|
89
89
|
// 复制模板文件
|
|
90
90
|
Object.entries(template.files).forEach(([key, fileName]) => {
|
|
91
91
|
const srcPath = path.join(tempPath, fileName);
|
|
92
|
-
const destPath = path.join(appRootPath, key === 'src' ? './src' : `./${key === 'app' ? 'App.tsx' : key === 'index' ? 'index.js' : key === 'babel' ? 'babel.config.js' : '
|
|
92
|
+
const destPath = path.join(appRootPath, key === 'src' ? './src' : `./${key === 'app' ? 'App.tsx' : key === 'index' ? 'index.js' : key === 'babel' ? 'babel.config.js' : 'htyf.json'}`);
|
|
93
93
|
|
|
94
94
|
if (fs.existsSync(srcPath)) {
|
|
95
95
|
fse.copySync(srcPath, destPath);
|
|
@@ -125,7 +125,7 @@ export class TemplateProcessor {
|
|
|
125
125
|
// 复制模板文件
|
|
126
126
|
Object.entries(template.files).forEach(([key, fileName]) => {
|
|
127
127
|
const srcPath = path.join(tempPath, fileName);
|
|
128
|
-
const destPath = path.join(appRootPath, key === 'src' ? './src' : `./${key === 'app' ? 'App.tsx' : key === 'index' ? 'index.js' : key === 'babel' ? 'babel.config.js' : '
|
|
128
|
+
const destPath = path.join(appRootPath, key === 'src' ? './src' : `./${key === 'app' ? 'App.tsx' : key === 'index' ? 'index.js' : key === 'babel' ? 'babel.config.js' : 'htyf.json'}`);
|
|
129
129
|
|
|
130
130
|
if (fs.existsSync(srcPath)) {
|
|
131
131
|
fse.copySync(srcPath, destPath);
|