@4399ywkf/cli 0.0.4 → 0.0.7
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/bin/cli.js +175 -15
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -52,9 +52,11 @@ function printFinalInstructions(projectName) {
|
|
|
52
52
|
chalk.cyan("接下来的步骤:"),
|
|
53
53
|
chalk.gray(" 1. 进入项目目录"),
|
|
54
54
|
chalk.white(` cd ${projectName}`),
|
|
55
|
-
chalk.gray(" 2.
|
|
55
|
+
chalk.gray(" 2. 切换Node版本"),
|
|
56
|
+
chalk.white(" nvm use"),
|
|
57
|
+
chalk.gray(" 3. 安装依赖"),
|
|
56
58
|
chalk.white(" pnpm i"),
|
|
57
|
-
chalk.gray("
|
|
59
|
+
chalk.gray(" 4. 启动项目"),
|
|
58
60
|
chalk.white(" pnpm start"),
|
|
59
61
|
"",
|
|
60
62
|
chalk.magenta("🚀 开始你的开发之旅吧!"),
|
|
@@ -84,6 +86,148 @@ function cloneRepository(repoUrl, destination) {
|
|
|
84
86
|
});
|
|
85
87
|
}
|
|
86
88
|
|
|
89
|
+
// 新添加:更新环境模板文件
|
|
90
|
+
async function updateEnvTemplate(filePath, config) {
|
|
91
|
+
try {
|
|
92
|
+
// 读取模板文件内容
|
|
93
|
+
let templateContent = await fs.readFile(filePath, "utf8");
|
|
94
|
+
|
|
95
|
+
// 替换模板变量
|
|
96
|
+
const replacements = {
|
|
97
|
+
"{{APP_CNAME}}": `${config.appCname}`,
|
|
98
|
+
"{{APP_NAME}}": `${config.appName}`,
|
|
99
|
+
"{{SENTRY_ENABLED}}": `${config.sentryEnabled ? "true" : "false"}`,
|
|
100
|
+
"{{SENTRY_DSN}}": `${config.sentryDsn}`,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// 执行替换
|
|
104
|
+
for (const [placeholder, value] of Object.entries(replacements)) {
|
|
105
|
+
templateContent = templateContent.replace(
|
|
106
|
+
new RegExp(placeholder, "g"),
|
|
107
|
+
value
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 写回文件
|
|
112
|
+
await fs.writeFile(filePath, templateContent, "utf8");
|
|
113
|
+
} catch (error) {
|
|
114
|
+
throw new Error(`更新模板文件失败: ${error.message}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 配置 webpack 子应用的环境变量(填充模板)
|
|
119
|
+
async function configureWebpackSubApp(projectPath, projectName) {
|
|
120
|
+
printInfo("正在配置 Webpack 子应用环境变量...");
|
|
121
|
+
|
|
122
|
+
const envFilePath = path.join(projectPath, "config", "env", ".env.public");
|
|
123
|
+
|
|
124
|
+
// 检查模板文件是否存在
|
|
125
|
+
if (!fs.existsSync(envFilePath)) {
|
|
126
|
+
printWarning("未找到 .env.public 模板文件,跳过配置");
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// 询问用户配置选项
|
|
131
|
+
const { configureEnv } = await inquirer.prompt({
|
|
132
|
+
type: "confirm",
|
|
133
|
+
name: "configureEnv",
|
|
134
|
+
message: chalk.cyan("🔧 是否要自定义应用配置?"),
|
|
135
|
+
default: true,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (!configureEnv) {
|
|
139
|
+
// 如果不配置,使用默认值填充模板
|
|
140
|
+
const defaultConfig = {
|
|
141
|
+
appCname: projectName.toLowerCase().replace(/[^a-z0-9-]/g, "-"),
|
|
142
|
+
appName: projectName
|
|
143
|
+
.toLowerCase()
|
|
144
|
+
.replace(/[^a-z0-9-]/g, "-")
|
|
145
|
+
.split("-")
|
|
146
|
+
.map((word, index) =>
|
|
147
|
+
index === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1)
|
|
148
|
+
)
|
|
149
|
+
.join(""),
|
|
150
|
+
outputPath: "dist",
|
|
151
|
+
publicPath: "/",
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
await updateEnvTemplate(envFilePath, defaultConfig);
|
|
155
|
+
printInfo("已使用默认配置填充模板");
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 获取用户输入的配置
|
|
160
|
+
const config = await inquirer.prompt([
|
|
161
|
+
{
|
|
162
|
+
type: "input",
|
|
163
|
+
name: "appName",
|
|
164
|
+
message: chalk.cyan("📝 请输入应用代码名称(APP_NAME):"),
|
|
165
|
+
default: projectName.toLowerCase().replace(/[^a-z0-9-_]/g, "-"),
|
|
166
|
+
validate: (input) => {
|
|
167
|
+
if (!input.trim()) {
|
|
168
|
+
return "应用代码名称不能为空!";
|
|
169
|
+
}
|
|
170
|
+
if (!/^[a-z0-9-_]+$/.test(input)) {
|
|
171
|
+
return "应用代码名称只能包含小写字母、数字、横线和下划线!";
|
|
172
|
+
}
|
|
173
|
+
return true;
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
type: "input",
|
|
178
|
+
name: "appCname",
|
|
179
|
+
message: chalk.cyan("📝 请输入应用名称 (APP_CNAME):"),
|
|
180
|
+
default: projectName.toLowerCase().replace(/[^a-z0-9-_]/g, "-"),
|
|
181
|
+
validate: (input) => {
|
|
182
|
+
if (!input.trim()) {
|
|
183
|
+
return "应用名称不能为空!";
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// 支持中文、英文、数字、横线、下划线,必须以字母或中文开头
|
|
187
|
+
if (
|
|
188
|
+
!/^[\u4e00-\u9fff\u3400-\u4dbfa-zA-Z][\u4e00-\u9fff\u3400-\u4dbfa-zA-Z0-9_-]*$/.test(
|
|
189
|
+
input
|
|
190
|
+
)
|
|
191
|
+
) {
|
|
192
|
+
return "应用名称必须以中文或字母开头,可包含中文、字母、数字、横线和下划线!";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return true;
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
type: "confirm",
|
|
200
|
+
name: "sentryEnabled",
|
|
201
|
+
message: chalk.cyan("📝 是否开启 Sentry?"),
|
|
202
|
+
default: true,
|
|
203
|
+
},
|
|
204
|
+
// 如果开启 sentry 则需要输入 sentry 的 dsn
|
|
205
|
+
{
|
|
206
|
+
type: "input",
|
|
207
|
+
name: "sentryDsn",
|
|
208
|
+
message: chalk.cyan("📝 请输入 Sentry 的 DSN:"),
|
|
209
|
+
default: "https://207b65a59562963635abde2cfce82651@sentry.gz4399.com/28",
|
|
210
|
+
when: (answers) => answers.sentryEnabled,
|
|
211
|
+
},
|
|
212
|
+
]);
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
// 更新模板文件
|
|
216
|
+
await updateEnvTemplate(envFilePath, config);
|
|
217
|
+
printSuccess(`已更新环境配置文件:${chalk.bold(".env.public")}`);
|
|
218
|
+
|
|
219
|
+
// 显示配置信息
|
|
220
|
+
console.log();
|
|
221
|
+
printInfo("应用配置信息:");
|
|
222
|
+
console.log(chalk.gray(` 应用代码名称: ${chalk.white(config.appCname)}`));
|
|
223
|
+
console.log(chalk.gray(` 应用名称: ${chalk.white(config.appName)}`));
|
|
224
|
+
console.log();
|
|
225
|
+
} catch (error) {
|
|
226
|
+
printError(`更新环境配置文件失败:${error.message}`);
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
87
231
|
program
|
|
88
232
|
.command("create [projectName]")
|
|
89
233
|
.description("创建模版")
|
|
@@ -184,11 +328,13 @@ program
|
|
|
184
328
|
|
|
185
329
|
// 4. 选择模版
|
|
186
330
|
let projectTemplate;
|
|
331
|
+
|
|
187
332
|
if (options.template) {
|
|
188
|
-
|
|
333
|
+
const foundTemplate = templates[toolType][appDirection].find(
|
|
189
334
|
(template) => template.name === options.template
|
|
190
|
-
)
|
|
191
|
-
if (
|
|
335
|
+
);
|
|
336
|
+
if (foundTemplate) {
|
|
337
|
+
projectTemplate = foundTemplate.value;
|
|
192
338
|
printSuccess(`使用指定模版:${chalk.bold(options.template)}`);
|
|
193
339
|
} else {
|
|
194
340
|
printWarning(`未找到指定模版 "${options.template}",请重新选择`);
|
|
@@ -196,16 +342,24 @@ program
|
|
|
196
342
|
}
|
|
197
343
|
|
|
198
344
|
if (!projectTemplate) {
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
|
|
345
|
+
const availableTemplates = templates[toolType][appDirection];
|
|
346
|
+
|
|
347
|
+
// 如果只有一个模版,直接使用它
|
|
348
|
+
if (availableTemplates.length === 1) {
|
|
349
|
+
projectTemplate = availableTemplates[0].value;
|
|
350
|
+
} else {
|
|
351
|
+
// 多个模版时让用户选择
|
|
352
|
+
const { template } = await inquirer.prompt({
|
|
353
|
+
type: "list",
|
|
354
|
+
name: "template",
|
|
355
|
+
message: chalk.cyan("📋 请选择模版:"),
|
|
356
|
+
choices: availableTemplates.map((t) => ({
|
|
357
|
+
name: `${chalk.white(t.name)}`,
|
|
358
|
+
value: t.value,
|
|
359
|
+
})),
|
|
360
|
+
});
|
|
361
|
+
projectTemplate = template;
|
|
362
|
+
}
|
|
209
363
|
}
|
|
210
364
|
|
|
211
365
|
console.log(); // 空行
|
|
@@ -250,6 +404,12 @@ program
|
|
|
250
404
|
printSuccess("已清理 .git 文件夹");
|
|
251
405
|
}
|
|
252
406
|
|
|
407
|
+
// 新添加:如果是 webpack 子应用,进行环境配置
|
|
408
|
+
if (toolType === "webpack" && appDirection === "sub") {
|
|
409
|
+
console.log(); // 空行
|
|
410
|
+
await configureWebpackSubApp(dest, projectName);
|
|
411
|
+
}
|
|
412
|
+
|
|
253
413
|
console.log(); // 空行
|
|
254
414
|
printFinalInstructions(projectName);
|
|
255
415
|
} catch (error) {
|