wyt-cli 1.0.19 → 1.0.21

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,7 +1,7 @@
1
1
  // commands/create.js
2
2
 
3
3
  import path from 'path';
4
- import { log_error, log_success, getPlainText, getInquirerOperationText } from '../lib/logger.js';
4
+ import { log_error, getInquirerOperationText } from '../lib/logger.js';
5
5
 
6
6
  // 外部依赖
7
7
  import { Command } from 'commander';
@@ -10,6 +10,7 @@ import { glob } from 'glob';
10
10
  import fs from 'fs-extra';
11
11
  // import ora from 'ora';
12
12
  import inquirer from 'inquirer';
13
+ import chalk from 'chalk';
13
14
  import ejs from 'ejs';
14
15
  import { checkTargetDir, getModuleMenuConfig, getProjectConfig } from '../lib/dir.js';
15
16
 
@@ -66,8 +67,14 @@ async function createProjectAction(projectName, options) {
66
67
 
67
68
  // 创建项目模版
68
69
  await createProject(projectName, options);
69
- log_success(
70
- `项目 ${projectName} 创建成功!\n\n${getPlainText('项目运行步骤:\n1. 请自行安装依赖 pnpm i\n2. 启动测试服务器 pnpm run dev')}\n\n`
70
+ console.log(
71
+ `\n\n${chalk.bgGreen.black(' 项目创建成功 ')} ${chalk.greenBright(projectName)}\n\n` +
72
+ `${chalk.cyan.bold('━━━━ 运行步骤 ━━━━')}\n` +
73
+ `${chalk.blue('1. 安装依赖')} ${chalk.yellow('pnpm install')}\n` +
74
+ `${chalk.blue('2. 启动开发服务器')} ${chalk.yellow('wyt-cli run')}\n\n` +
75
+ `${chalk.hex('#FFA500').bold('💡 注意事项:')}\n` +
76
+ `• 确保本地 ${chalk.yellow('Node.js >= 16.0 && pnpm 7.x+')} 版本\n` +
77
+ `• 建议使用 ${chalk.yellow('wyt-cli')} 命令行工具\n`
71
78
  );
72
79
  } catch (error) {
73
80
  log_error(error.message);
@@ -189,124 +196,3 @@ async function updateRootProjectJson(projectName, options) {
189
196
  return false;
190
197
  }
191
198
  }
192
-
193
- // 询问 -> 创建项目
194
- // const inquirerAnswers = await inquirer.prompt([
195
- // {
196
- // type: 'input',
197
- // name: 'projectName',
198
- // message: '请输入项目名称:',
199
- // validate: (input) => {
200
- // // 校验规则
201
- // if (!input) return '项目名称不能为空!';
202
- // if (!/^[a-zA-Z0-9-]{1,50}$/.test(input)) {
203
- // return '名称只能包含字母、数字和中划线,且不超过50字符';
204
- // }
205
- // if (glob_projectInfo.map((item) => item.name).includes(input.toLowerCase())) {
206
- // return `项目名称 "${input}" 已存在,请重新输入`;
207
- // }
208
- // return true;
209
- // },
210
- // // 当命令行已传入名称时自动跳过
211
- // when: !projectName,
212
- // },
213
- // {
214
- // type: 'input',
215
- // name: 'devServerPort',
216
- // message: '请输入测试服务器端口号:',
217
- // validate: (input) => {
218
- // // 校验规则
219
- // if (!input) return '测试服务器端口号不能为空!';
220
- // if (!/^\d+$/.test(input)) {
221
- // return '测试服务器端口号必须为纯数字';
222
- // }
223
- // if (glob_projectInfo.map((item) => item.port).includes(input)) {
224
- // return `测试服务器端口号 "${input}" 已存在,请重新输入`;
225
- // }
226
- // return true;
227
- // },
228
- // },
229
- // ]);
230
- // if (!options.force) {
231
- // throw new Error(`项目 ${projectName} 已存在,使用 --force 强制覆盖`);
232
- // }
233
- // inquirer
234
- // .prompt([
235
- // {
236
- // type: 'confirm',
237
- // name: 'confirmOverwrite',
238
- // message: `项目 ${projectName} 已存在,是否覆盖?`,
239
- // default: true,
240
- // },
241
- // ])
242
- // .then((answers) => {
243
- // if (answers.confirmOverwrite) {
244
- // fs.emptyDirSync(targetDir);
245
- // createProject(projectName, options);
246
- // log_success(`项目 ${projectName} 强制创建成功!`);
247
- // } else {
248
- // log_info('操作已取消');
249
- // process.exit(1);
250
- // }
251
- // });
252
-
253
- // 检测已有项目信息
254
- // async function checkProjectInfo(options) {
255
- // const files = await glob(['**/package.json'], {
256
- // cwd: path.resolve(options.dir, 'apps'), // 以项目根目录为基准
257
- // absolute: true, // 返回绝对路径
258
- // ignore: [
259
- // // 添加排除规则
260
- // '**/node_modules/**', // 排除 node_modules
261
- // '**/src/**', // 排除测试目录
262
- // '**/.*', // 排除隐藏文件/目录
263
- // ],
264
- // });
265
-
266
- // let results = await Promise.all(
267
- // files.map(async (file) => {
268
- // // 识别文件类型
269
- // const isPkg = file.endsWith('package.json');
270
-
271
- // try {
272
- // // 读取文件内容
273
- // const content = await fs.promises.readFile(file, 'utf-8');
274
-
275
- // if (isPkg) {
276
- // // 解析 package.json
277
- // const pkg = JSON.parse(content);
278
- // return { port: pkg.devServer && pkg.devServer.port, name: pkg.name };
279
- // }
280
- // } catch (err) {
281
- // console.error(`文件处理失败: ${file}`, err);
282
- // return null;
283
- // }
284
- // })
285
- // );
286
- // // 排序逻辑
287
- // results = results.sort((a, b) => {
288
- // // 处理 undefined 端口为最大值
289
- // const portA = a.port ? parseInt(a.port) : Infinity;
290
- // const portB = b.port ? parseInt(b.port) : Infinity;
291
- // // 优先级 1: 端口号升序
292
- // if (portA !== portB) {
293
- // return portA - portB;
294
- // }
295
-
296
- // // 优先级 2: 名称字母序
297
- // return a.name.localeCompare(b.name);
298
- // });
299
-
300
- // // 组合项目信息
301
- // const projectList = results.map((item, index) => ({
302
- // 序号: index + 1,
303
- // 项目名称: item.name,
304
- // 'DevServer 端口号': item.port || '未配置',
305
- // }));
306
- // // // 格式化输出
307
- // if (options.list) {
308
- // console.log('\n\n====== 已存在的项目列表,请不要重复 ======');
309
- // console.table(projectList, ['序号', '项目名称', 'DevServer 端口号']);
310
- // }
311
- // return results;
312
- // }
@@ -20,59 +20,75 @@ const startTime = Date.now(); // 计时器
20
20
  export default function () {
21
21
  const command = new Command('deploy');
22
22
 
23
- command.description('部署项目').action(async () => {
24
- try {
25
- // 校验项目目录
26
- if (!checkTargetDir(process.cwd())) {
27
- log_error('请在 HRP3.0 项目根目录运行此命令!');
28
- return;
29
- }
23
+ command
24
+ .description('部署项目')
25
+ .option('-f, --filter <name>', '部署指定项目')
26
+ .action(async (options) => {
27
+ try {
28
+ // 校验项目目录
29
+ if (!checkTargetDir(process.cwd())) {
30
+ log_error('请在 HRP3.0 项目根目录运行此命令!');
31
+ return;
32
+ }
30
33
 
31
- // 项目根目录
32
- const appsDir = path.resolve(process.cwd(), 'apps');
33
-
34
- // 获取项目列表
35
- const projects = await getProjects(appsDir);
36
-
37
- // 交互选择项目
38
- const answer = await inquirer.prompt([
39
- {
40
- type: 'rawlist',
41
- name: 'deploystyle',
42
- message: `请选择部署项目的方式:` + getInquirerOperationText('list'),
43
- default: 0,
44
- choices: [
45
- { name: '方式1:部署所有项目', value: 0 },
46
- { name: '方式2:部署指定项目', value: 1 },
47
- ],
48
- },
49
- {
50
- type: 'checkbox',
51
- name: 'project',
52
- message: '请选择要部署的项目:' + getInquirerOperationText('checkbox'),
53
- when: (answers) => answers.deploystyle == 1,
54
- choices: projects.map((p) => ({
55
- name: p.name,
56
- })),
57
- },
58
- ]);
59
-
60
- // 准备部署目录
61
- await initDeployDir();
62
-
63
- // 构建并部署
64
- if (answer.deploystyle === 0) {
65
- await buildAndDeploy(projects.map((p) => p.name));
66
- }
34
+ // 项目根目录
35
+ const appsDir = path.resolve(process.cwd(), 'apps');
36
+
37
+ // 获取项目列表
38
+ const projects = await getProjects(appsDir);
39
+
40
+ if (options.filter) {
41
+ const filtered = projects.filter((p) => p.name.includes(options.filter));
42
+ if (filtered.length === 0) {
43
+ log_error(`找不到包含"${options.filter}"的项目`);
44
+ return;
45
+ }
46
+ // 准备部署目录
47
+ await initDeployDir();
67
48
 
68
- if (answer.deploystyle === 1 && answer.project) {
69
- await buildAndDeploy(answer.project);
49
+ // 构建并部署
50
+ await buildAndDeploy(filtered.map((p) => p.name));
51
+ } else {
52
+ // 交互选择项目
53
+ const answer = await inquirer.prompt([
54
+ {
55
+ type: 'rawlist',
56
+ name: 'deploystyle',
57
+ message: `请选择部署项目的方式:` + getInquirerOperationText('list'),
58
+ default: 0,
59
+ choices: [
60
+ { name: '方式1:部署所有项目', value: 0 },
61
+ { name: '方式2:部署指定项目', value: 1 },
62
+ ],
63
+ },
64
+ {
65
+ type: 'checkbox',
66
+ name: 'project',
67
+ message: '请选择要部署的项目:' + getInquirerOperationText('checkbox'),
68
+ when: (answers) => answers.deploystyle == 1,
69
+ choices: projects.map((p) => ({
70
+ name: p.name,
71
+ })),
72
+ },
73
+ ]);
74
+
75
+ // 准备部署目录
76
+ await initDeployDir();
77
+
78
+ // 构建并部署
79
+ if (answer.deploystyle === 0) {
80
+ await buildAndDeploy(projects.map((p) => p.name));
81
+ }
82
+
83
+ if (answer.deploystyle === 1 && answer.project) {
84
+ await buildAndDeploy(answer.project);
85
+ }
86
+ }
87
+ } catch (error) {
88
+ log_error(`部署失败: ${error.message}`);
89
+ process.exit(1);
70
90
  }
71
- } catch (error) {
72
- log_error(`部署失败: ${error.message}`);
73
- process.exit(1);
74
- }
75
- });
91
+ });
76
92
 
77
93
  return command;
78
94
  }
@@ -10,66 +10,72 @@ import { checkTargetDir, getProjects } from '../lib/dir.js';
10
10
  export default function () {
11
11
  const command = new Command('run');
12
12
 
13
- command.description('运行项目').action(async () => {
14
- try {
15
- // 校验项目根目录是否合法
16
- if (!checkTargetDir(process.cwd())) {
17
- log_error('请在 HRP3.0 项目根目录下运行此命令!');
18
- return;
13
+ command
14
+ .description('运行项目')
15
+ .option('-f, --filter <name>', '运行指定项目')
16
+ .action(async (options) => {
17
+ try {
18
+ // 校验项目根目录是否合法
19
+ if (!checkTargetDir(process.cwd())) {
20
+ log_error('请在 HRP3.0 项目根目录下运行此命令!');
21
+ return;
22
+ }
23
+
24
+ // 项目根目录
25
+ const appsDir = path.resolve(process.cwd(), 'apps');
26
+
27
+ // 获取项目列表
28
+ const projects = await getProjects(appsDir);
29
+
30
+ // 运行指定项目
31
+ if (options.filter) {
32
+ const filtered = projects.filter((p) => p.name.includes(options.filter));
33
+ if (filtered.length === 0) {
34
+ log_error(`找不到包含"${options.filter}"的项目`);
35
+ return;
36
+ }
37
+ runProject([{ name: 'core' }, { name: filtered[0].name }], appsDir);
38
+ } else {
39
+ // 交互选择项目
40
+ const answer = await inquirer.prompt([
41
+ {
42
+ type: 'rawlist',
43
+ name: 'runstyle',
44
+ message: `请选择项目运行方式:` + getInquirerOperationText('list'),
45
+ default: 0,
46
+ choices: [
47
+ { name: '方式1:运行所有项目', value: 0 },
48
+ { name: '方式2:运行指定项目', value: 1 },
49
+ ],
50
+ },
51
+ {
52
+ type: 'checkbox',
53
+ name: 'project',
54
+ message: '请选择要运行的项目:' + getInquirerOperationText('checkbox'),
55
+ when: (answers) => answers.runstyle == 1,
56
+ choices: projects.map((p) => ({
57
+ checked: p.name === 'core',
58
+ name: `${p.name} (端口号: ${p.port || '未配置'}) ${p.description || ''}`,
59
+ value: p,
60
+ })),
61
+ },
62
+ ]);
63
+
64
+ // 运行项目
65
+ if (answer.runstyle === 0) runProject(projects, appsDir);
66
+ if (answer.runstyle === 1 && answer.project) runProject(answer.project, appsDir);
67
+ }
68
+ } catch (error) {
69
+ log_error(error.message);
70
+ process.exit(1);
19
71
  }
20
-
21
- // 项目根目录
22
- const appsDir = path.resolve(process.cwd(), 'apps');
23
-
24
- // 获取项目列表
25
- const projects = await getProjects(appsDir);
26
-
27
- // 交互选择项目
28
- const answer = await inquirer.prompt([
29
- {
30
- type: 'rawlist',
31
- name: 'runstyle',
32
- message: `请选择项目运行方式:` + getInquirerOperationText('list'),
33
- default: 0,
34
- choices: [
35
- { name: '方式1:运行所有项目', value: 0 },
36
- { name: '方式2:运行指定项目', value: 1 },
37
- ],
38
- },
39
- {
40
- type: 'checkbox',
41
- name: 'project',
42
- message: '请选择要运行的项目:' + getInquirerOperationText('checkbox'),
43
- when: (answers) => answers.runstyle == 1,
44
- choices: projects.map((p) => ({
45
- checked: p.name === 'core',
46
- name: `${p.name} (端口号: ${p.port || '未配置'})`,
47
- value: p,
48
- })),
49
- },
50
- ]);
51
-
52
- // 运行项目
53
- if (answer.runstyle === 0) runProject(projects, appsDir);
54
- if (answer.runstyle === 1 && answer.project) runProject(answer.project, appsDir);
55
- } catch (error) {
56
- log_error(error.message);
57
- process.exit(1);
58
- }
59
- });
72
+ });
60
73
 
61
74
  return command;
62
75
  }
63
76
 
64
77
  // 运行项目
65
78
  async function runProject(projects = [], appsDir) {
66
- // 更新 packages 最新版本
67
- log_info(`🔄 检查并更新 packages 最新版本...`);
68
- await execa('pnpm', ['install'], {
69
- cwd: process.cwd(),
70
- stdio: 'inherit',
71
- });
72
-
73
79
  // 运行命令
74
80
  const command = 'npm run dev';
75
81
  const commandEnv = {
@@ -77,6 +83,17 @@ async function runProject(projects = [], appsDir) {
77
83
  NODE_ENV: 'development',
78
84
  PROJECT_RUN_MODE: 'wyt-cli',
79
85
  };
86
+ // 更新 packages 最新版本
87
+ log_info(`🔄 检查并更新 packages 最新版本...`);
88
+ await execa('pnpm', ['install'], {
89
+ cwd: process.cwd(),
90
+ stdio: 'inherit',
91
+ });
92
+ await execa('pnpm', ['check:dist'], {
93
+ cwd: process.cwd(),
94
+ stdio: 'inherit',
95
+ env: commandEnv,
96
+ });
80
97
 
81
98
  // 运行项目文档
82
99
  log_info(`🚀 启动项目文档...`);
@@ -97,7 +114,7 @@ async function runProject(projects = [], appsDir) {
97
114
  // 初始化
98
115
  config.apps.forEach((app, index) => {
99
116
  config.apps[index] = {
100
- ...app,
117
+ name: app.name,
101
118
  lastRun: false,
102
119
  };
103
120
  });
@@ -136,5 +153,7 @@ async function runProject(projects = [], appsDir) {
136
153
  }
137
154
  });
138
155
 
139
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
156
+ // 运行时配置更新
157
+ const runtimeConfigPath = path.join(process.cwd(), 'runtime.config.json');
158
+ fs.writeFileSync(runtimeConfigPath, JSON.stringify({ runtime_apps: config.apps }, null, 2));
140
159
  }
package/bin/lib/dir.js CHANGED
@@ -16,7 +16,7 @@ export async function getProjects(appsDir) {
16
16
  return {
17
17
  name,
18
18
  port: pkg.devServer?.port || 3000,
19
- scripts: pkg.scripts || {},
19
+ description: pkg.description || {},
20
20
  };
21
21
  });
22
22
  }
package/bin/main.js CHANGED
@@ -33,7 +33,7 @@ main();
33
33
  // 处理 CLI 命令
34
34
  function handleProgramCommand() {
35
35
  // 基本信息
36
- program.name('cli-test').description(`这是 hrp3.0 项目的命令行工具,当前版本为${version}`);
36
+ program.name('wyt-cli').description(`这是 hrp3.0 项目的命令行工具,当前版本为${version}`);
37
37
  program.version(version, '-v, --version', '显示版本信息');
38
38
  program.helpOption('-h, --help', '显示帮助信息').helpCommand(false);
39
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wyt-cli",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "HRP3.0 项目命令行工具",
5
5
  "main": "index.js",
6
6
  "bin": {