@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.
Files changed (2) hide show
  1. package/bin/cli.js +175 -15
  2. 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(" 3. 启动项目"),
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
- projectTemplate = templates[toolType][appDirection].find(
333
+ const foundTemplate = templates[toolType][appDirection].find(
189
334
  (template) => template.name === options.template
190
- )?.value;
191
- if (projectTemplate) {
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 { template } = await inquirer.prompt({
200
- type: "list",
201
- name: "template",
202
- message: chalk.cyan("📋 请选择模版:"),
203
- choices: templates[toolType][appDirection].map((t) => ({
204
- name: `${chalk.white(t.name)}`,
205
- value: t.value,
206
- })),
207
- });
208
- projectTemplate = template;
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4399ywkf/cli",
3
- "version": "0.0.4",
3
+ "version": "0.0.7",
4
4
  "description": "运维开发部脚手架",
5
5
  "main": "index.js",
6
6
  "bin": {