@ysjdemo/umi-create-cli 0.0.2 → 0.0.3

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/README.md CHANGED
@@ -2,26 +2,45 @@
2
2
 
3
3
  一个用于创建Umi4项目的脚手架工具
4
4
 
5
- ## 安装
5
+ ## 使用方式(推荐npx)
6
6
 
7
7
  ```bash
8
- # 全局安装
9
- npm install -g @ysjdemo/umi-create-cli
8
+ # 🔥 推荐:使用 npx 直接创建(无需安装)
9
+ # 会自动提示选择模板,默认推荐 Ant Design Pro
10
+ npx @ysjdemo/umi-create-cli create my-project
10
11
 
11
- # 或使用 yarn
12
- yarn global add @ysjdemo/umi-create-cli
12
+ # 或直接指定模板
13
+ npx @ysjdemo/umi-create-cli create my-project -t antd
14
+ npx @ysjdemo/umi-create-cli create my-project -t basic
15
+
16
+ # 查看帮助
17
+ npx @ysjdemo/umi-create-cli --help
13
18
  ```
14
19
 
15
- ## 使用
20
+ ## 交互式模板选择
21
+
22
+ 当您运行创建命令时,会看到如下交互界面:
23
+
24
+ ```
25
+ 🚀 创建 Umi4 项目...
26
+ 📋 请选择项目模板:
27
+ ❯ 🎨 antd - Ant Design Pro 模板 (推荐)
28
+ 📦 basic - 基础模板
29
+ ```
30
+
31
+ ## 安装方式(可选)
32
+
33
+ 如果需要频繁使用,可以选择全局安装:
16
34
 
17
35
  ```bash
18
- # 创建新项目
19
- ysj-umi create my-project
36
+ # 全局安装
37
+ npm install -g @ysjdemo/umi-create-cli
20
38
 
21
- # 查看帮助
22
- ysj-umi --help
39
+ # 或使用 yarn
40
+ yarn global add @ysjdemo/umi-create-cli
23
41
 
24
- # 查看版本
42
+ # 安装后使用
43
+ ysj-umi create my-project
25
44
  ysj-umi --version
26
45
  ```
27
46
 
@@ -31,19 +50,33 @@ ysj-umi --version
31
50
  - 📦 内置常用配置模板
32
51
  - 🎨 支持TypeScript
33
52
  - 📱 支持多种UI库选择
53
+ - ⚡️ 支持npx直接使用,无需安装
54
+ - 🎯 交互式模板选择,默认推荐最佳实践
34
55
 
35
56
  ## 模板选项
36
57
 
37
- - 基础模板:包含基本的Umi4配置
38
- - TypeScript模板:包含TypeScript配置
39
- - Ant Design模板:集成Ant Design组件库
40
- - 移动端模板:适配移动端开发
58
+ - **🎨 Ant Design Pro 模板**(推荐):企业级后台管理系统
59
+ ```bash
60
+ npx @ysjdemo/umi-create-cli create my-admin -t antd
61
+ ```
62
+ - 集成 Ant Design 5.0
63
+ - Pro Components 组件库
64
+ - 完整的后台管理界面
65
+ - 仪表盘、用户管理、设置页面
66
+
67
+ - **📦 基础模板**:轻量级起始项目
68
+ ```bash
69
+ npx @ysjdemo/umi-create-cli create my-project -t basic
70
+ ```
71
+ - 基础 Umi 4 配置
72
+ - TypeScript 支持
73
+ - 简洁的项目结构
41
74
 
42
75
  ## 开发
43
76
 
44
77
  ```bash
45
78
  # 克隆项目
46
- git clone https://github.com/yourusername/ysj-cli.git
79
+ git clone https://github.com/Ivan-YangSj/umi-cli.git
47
80
 
48
81
  # 安装依赖
49
82
  npm install
package/bin/cli.js CHANGED
@@ -12,7 +12,7 @@ program
12
12
  program
13
13
  .command('create <project-name>')
14
14
  .description('创建一个新的 Umi4 项目')
15
- .option('-t, --template <template>', '使用指定模板 (basic, antd)', 'basic')
15
+ .option('-t, --template <template>', '使用指定模板 (basic, antd, qiankun)')
16
16
  .action(async (projectName, options) => {
17
17
  try {
18
18
  await createProject(projectName, options);
@@ -26,7 +26,7 @@ program
26
26
  program
27
27
  .command('init')
28
28
  .description('在当前目录初始化 Umi4 项目')
29
- .option('-t, --template <template>', '使用指定模板 (basic, antd)', 'basic')
29
+ .option('-t, --template <template>', '使用指定模板 (basic, antd, qiankun)')
30
30
  .action(async (options) => {
31
31
  try {
32
32
  await initProject(options);
package/lib/create.js CHANGED
@@ -1,146 +1,171 @@
1
- const fs = require('fs-extra');
2
- const path = require('path');
3
- const inquirer = require('inquirer');
4
- const chalk = require('chalk');
5
- const ora = require('ora');
6
- const { generateTemplate, getAvailableTemplates } = require('./templates');
1
+ const fs = require("fs-extra");
2
+ const path = require("path");
3
+ const inquirer = require("inquirer");
4
+ const chalk = require("chalk");
5
+ const ora = require("ora");
6
+ const { generateTemplate, getAvailableTemplates } = require("./templates");
7
+
8
+ // 默认选择的模板
9
+ const BASE_TEMPLATE = "qiankun";
10
+
11
+ const templateChoices = [
12
+ {
13
+ name: `🏗️ qiankun + antd + umi - 微前端模板 ${chalk.cyan("(推荐)")}`,
14
+ value: "qiankun",
15
+ short: "qiankun",
16
+ },
17
+ {
18
+ name: `🎨 antd + umi - Ant Design Pro 模板`,
19
+ value: "antd",
20
+ short: "antd",
21
+ },
22
+ {
23
+ name: `📦 umi - 基础模板`,
24
+ value: "umi",
25
+ short: "umi",
26
+ },
27
+ ];
7
28
 
8
29
  async function createProject(projectName, options) {
9
- const { template = 'basic' } = options;
10
-
30
+ const { template } = options;
31
+
11
32
  console.log(`🚀 创建 Umi4 项目...`);
12
-
33
+
13
34
  // 获取可用模板列表
14
35
  const availableTemplates = await getAvailableTemplates();
15
-
16
- // 如果指定的模板不存在,让用户选择
36
+
17
37
  let selectedTemplate = template;
18
- if (!availableTemplates.includes(template)) {
19
- console.log(chalk.yellow(`⚠️ 模板 "${template}" 不存在`));
20
- console.log(chalk.blue(`📋 可用模板: ${availableTemplates.join(', ')}`));
21
-
38
+
39
+ // 如果没有指定模板,或者指定的模板不存在,让用户选择
40
+ if (!template || !availableTemplates.includes(template)) {
41
+ if (template && !availableTemplates.includes(template)) {
42
+ console.log(chalk.yellow(`⚠️ 模板 "${template}" 不存在`));
43
+ }
44
+
45
+ console.log(chalk.blue(`📋 请选择项目模板:`));
46
+
22
47
  const { chosenTemplate } = await inquirer.prompt([
23
48
  {
24
- type: 'list',
25
- name: 'chosenTemplate',
26
- message: '请选择要使用的模板:',
27
- choices: availableTemplates.map(t => ({
28
- name: t === 'basic' ? `${t} (基础模板)` :
29
- t === 'antd' ? `${t} (Ant Design Pro)` : t,
30
- value: t
31
- }))
32
- }
49
+ type: "list",
50
+ name: "chosenTemplate",
51
+ message: "选择项目模板:",
52
+ choices: templateChoices,
53
+ default: BASE_TEMPLATE, // 默认选择antd
54
+ },
33
55
  ]);
34
56
  selectedTemplate = chosenTemplate;
35
57
  }
36
-
58
+
59
+ console.log(chalk.cyan(`📋 使用模板: ${selectedTemplate}`));
60
+
37
61
  const targetDir = path.resolve(projectName);
38
-
62
+
39
63
  // 检查目录是否已存在
40
64
  if (await fs.pathExists(targetDir)) {
41
65
  const { overwrite } = await inquirer.prompt([
42
66
  {
43
- type: 'confirm',
44
- name: 'overwrite',
67
+ type: "confirm",
68
+ name: "overwrite",
45
69
  message: `目录 ${projectName} 已存在,是否覆盖?`,
46
- default: false
47
- }
70
+ default: false,
71
+ },
48
72
  ]);
49
-
73
+
50
74
  if (!overwrite) {
51
- console.log(chalk.red('❌ 项目创建取消'));
75
+ console.log(chalk.red("❌ 项目创建取消"));
52
76
  return;
53
77
  }
54
-
78
+
55
79
  await fs.remove(targetDir);
56
80
  }
57
-
58
- const spinner = ora('正在创建项目...').start();
59
-
81
+
82
+ const spinner = ora("正在创建项目...").start();
83
+
60
84
  try {
61
85
  // 生成项目文件
62
86
  await generateTemplate(projectName, selectedTemplate, targetDir);
63
-
64
- spinner.succeed('项目文件生成完成');
65
-
66
- console.log(chalk.green('✅ 项目创建成功!'));
67
- console.log('');
87
+
88
+ spinner.succeed("项目文件生成完成");
89
+
90
+ console.log(chalk.green("✅ 项目创建成功!"));
91
+ console.log("");
68
92
  console.log(chalk.cyan(`📁 进入项目目录: cd ${projectName}`));
69
- console.log(chalk.cyan('📦 安装依赖: npm install 或 yarn'));
70
- console.log(chalk.cyan('🚀 启动项目: npm start 或 yarn start'));
71
-
93
+ console.log(chalk.cyan("📦 安装依赖: npm install 或 yarn"));
94
+ console.log(chalk.cyan("🚀 启动项目: npm start 或 yarn start"));
72
95
  } catch (error) {
73
- spinner.fail('项目创建失败');
96
+ spinner.fail("项目创建失败");
74
97
  console.error(chalk.red(error.message));
75
98
  process.exit(1);
76
99
  }
77
100
  }
78
101
 
79
102
  async function initProject(options) {
80
- const { template = 'basic' } = options;
103
+ const { template } = options;
81
104
  const projectName = path.basename(process.cwd());
82
-
105
+
83
106
  console.log(`🚀 初始化 Umi4 项目...`);
84
-
107
+
85
108
  // 获取可用模板列表
86
109
  const availableTemplates = await getAvailableTemplates();
87
-
88
- // 如果指定的模板不存在,让用户选择
110
+
89
111
  let selectedTemplate = template;
90
- if (!availableTemplates.includes(template)) {
91
- console.log(chalk.yellow(`⚠️ 模板 "${template}" 不存在`));
92
- console.log(chalk.blue(`📋 可用模板: ${availableTemplates.join(', ')}`));
93
-
112
+
113
+ // 如果没有指定模板,或者指定的模板不存在,让用户选择
114
+ if (!template || !availableTemplates.includes(template)) {
115
+ if (template && !availableTemplates.includes(template)) {
116
+ console.log(chalk.yellow(`⚠️ 模板 "${template}" 不存在`));
117
+ }
118
+
119
+ console.log(chalk.blue(`📋 请选择项目模板:`));
120
+
94
121
  const { chosenTemplate } = await inquirer.prompt([
95
122
  {
96
- type: 'list',
97
- name: 'chosenTemplate',
98
- message: '请选择要使用的模板:',
99
- choices: availableTemplates.map(t => ({
100
- name: t === 'basic' ? `${t} (基础模板)` :
101
- t === 'antd' ? `${t} (Ant Design Pro)` : t,
102
- value: t
103
- }))
104
- }
123
+ type: "list",
124
+ name: "chosenTemplate",
125
+ message: "选择项目模板:",
126
+ choices: templateChoices,
127
+ default: BASE_TEMPLATE, // 默认选择antd
128
+ },
105
129
  ]);
106
130
  selectedTemplate = chosenTemplate;
107
131
  }
108
-
132
+
133
+ console.log(chalk.cyan(`📋 使用模板: ${selectedTemplate}`));
134
+
109
135
  const targetDir = process.cwd();
110
-
136
+
111
137
  // 检查当前目录是否为空
112
138
  const files = await fs.readdir(targetDir);
113
139
  if (files.length > 0) {
114
140
  const { proceed } = await inquirer.prompt([
115
141
  {
116
- type: 'confirm',
117
- name: 'proceed',
118
- message: '当前目录不为空,是否继续?',
119
- default: false
120
- }
142
+ type: "confirm",
143
+ name: "proceed",
144
+ message: "当前目录不为空,是否继续?",
145
+ default: false,
146
+ },
121
147
  ]);
122
-
148
+
123
149
  if (!proceed) {
124
- console.log(chalk.red('❌ 项目初始化取消'));
150
+ console.log(chalk.red("❌ 项目初始化取消"));
125
151
  return;
126
152
  }
127
153
  }
128
-
129
- const spinner = ora('正在初始化项目...').start();
130
-
154
+
155
+ const spinner = ora("正在初始化项目...").start();
156
+
131
157
  try {
132
158
  // 生成项目文件
133
159
  await generateTemplate(projectName, selectedTemplate, targetDir);
134
-
135
- spinner.succeed('项目文件生成完成');
136
-
137
- console.log(chalk.green('✅ 项目初始化成功!'));
138
- console.log('');
139
- console.log(chalk.cyan('📦 安装依赖: npm install 或 yarn'));
140
- console.log(chalk.cyan('🚀 启动项目: npm start 或 yarn start'));
141
-
160
+
161
+ spinner.succeed("项目文件生成完成");
162
+
163
+ console.log(chalk.green("✅ 项目初始化成功!"));
164
+ console.log("");
165
+ console.log(chalk.cyan("📦 安装依赖: npm install 或 yarn"));
166
+ console.log(chalk.cyan("🚀 启动项目: npm start 或 yarn start"));
142
167
  } catch (error) {
143
- spinner.fail('项目初始化失败');
168
+ spinner.fail("项目初始化失败");
144
169
  console.error(chalk.red(error.message));
145
170
  process.exit(1);
146
171
  }
@@ -148,5 +173,5 @@ async function initProject(options) {
148
173
 
149
174
  module.exports = {
150
175
  createProject,
151
- initProject
152
- };
176
+ initProject,
177
+ };
@@ -28,7 +28,7 @@ const HomePage: React.FC = () => {
28
28
  <a href="https://umijs.org/" target="_blank" rel="noopener noreferrer">
29
29
  查看 Umi 文档
30
30
  </a>
31
- <a href="https://github.com/yourusername/ysj-cli" target="_blank" rel="noopener noreferrer">
31
+ <a href="https://github.com/Ivan-YangSj/umi-cli" target="_blank" rel="noopener noreferrer">
32
32
  GitHub 仓库
33
33
  </a>
34
34
  </div>
@@ -1,51 +1,81 @@
1
1
  const fs = require('fs-extra');
2
2
  const path = require('path');
3
3
 
4
- // 模板变量替换函数
4
+ /**
5
+ * 模板变量替换函数
6
+ * 将模板文件中的占位符(如{{projectName}})替换为实际的值
7
+ * @param {string} content - 文件内容
8
+ * @param {object} variables - 变量对象,包含要替换的键值对
9
+ * @returns {string} 替换后的内容
10
+ */
5
11
  function replaceTemplateVariables(content, variables) {
6
12
  let result = content;
13
+ // 遍历所有变量,逐一替换
7
14
  for (const [key, value] of Object.entries(variables)) {
15
+ // 创建占位符格式:{{变量名}}
8
16
  const placeholder = `{{${key}}}`;
17
+ // 全局替换所有匹配的占位符
9
18
  result = result.replace(new RegExp(placeholder, 'g'), value || '');
10
19
  }
11
20
  return result;
12
21
  }
13
22
 
14
- // 递归复制目录并替换模板变量
23
+ /**
24
+ * 递归复制目录并替换模板变量
25
+ * 这是核心函数,负责将模板目录完整复制到目标位置,并处理模板变量
26
+ * @param {string} srcDir - 源目录路径(模板目录)
27
+ * @param {string} destDir - 目标目录路径(项目生成位置)
28
+ * @param {object} variables - 模板变量对象
29
+ */
15
30
  async function copyTemplateDir(srcDir, destDir, variables) {
31
+ // 确保目标目录存在,如果不存在则创建
16
32
  await fs.ensureDir(destDir);
17
33
 
34
+ // 读取源目录下的所有文件和文件夹
18
35
  const items = await fs.readdir(srcDir);
19
36
 
37
+ // 遍历每个项目(文件或文件夹)
20
38
  for (const item of items) {
21
- const srcPath = path.join(srcDir, item);
22
- const destPath = path.join(destDir, item);
39
+ const srcPath = path.join(srcDir, item); // 源文件/文件夹的完整路径
40
+ const destPath = path.join(destDir, item); // 目标文件/文件夹的完整路径
23
41
 
42
+ // 获取文件/文件夹的统计信息
24
43
  const stat = await fs.stat(srcPath);
25
44
 
26
45
  if (stat.isDirectory()) {
27
- // 递归处理子目录
46
+ // 如果是目录,递归调用自己,复制整个子目录
28
47
  await copyTemplateDir(srcPath, destPath, variables);
29
48
  } else {
30
- // 处理文件
49
+ // 如果是文件,读取文件内容并处理模板变量
31
50
  const content = await fs.readFile(srcPath, 'utf8');
51
+ // 替换文件中的模板变量(如{{projectName}})
32
52
  const processedContent = replaceTemplateVariables(content, variables);
53
+ // 将处理后的内容写入目标文件
33
54
  await fs.writeFile(destPath, processedContent);
34
55
  }
35
56
  }
36
57
  }
37
58
 
59
+ /**
60
+ * 生成模板项目的主函数
61
+ * @param {string} projectName - 项目名称
62
+ * @param {string} templateType - 模板类型(如react、vue等)
63
+ * @param {string} targetDir - 目标生成目录
64
+ */
38
65
  async function generateTemplate(projectName, templateType, targetDir) {
66
+ // 获取模板根目录路径
39
67
  const templatesDir = path.join(__dirname, './');
68
+ // 构建特定模板目录路径
40
69
  const templateDir = path.join(templatesDir, templateType);
70
+ // 构建通用文件目录路径
41
71
  const commonDir = path.join(templatesDir, 'common');
42
72
 
43
- // 检查模板是否存在
73
+ // 检查指定的模板是否存在
44
74
  if (!await fs.pathExists(templateDir)) {
45
75
  throw new Error(`模板 "${templateType}" 不存在`);
46
76
  }
47
77
 
48
- // 模板变量
78
+ // 定义模板变量,这些变量会在模板文件中被替换
49
79
  const variables = {
50
80
  projectName: projectName || 'my-umi-app'
51
81
  };
@@ -53,17 +83,25 @@ async function generateTemplate(projectName, templateType, targetDir) {
53
83
  // 确保目标目录存在
54
84
  await fs.ensureDir(targetDir);
55
85
 
56
- // 首先创建基础目录结构
57
- const baseDirs = ['src/pages', 'src/components', 'src/services', 'src/utils'];
86
+ // 创建项目的基础目录结构
87
+ // 这些是前端项目常用的目录结构
88
+ const baseDirs = [
89
+ 'src/pages', // 页面组件目录
90
+ 'src/components', // 公共组件目录
91
+ 'src/services', // API服务目录
92
+ 'src/utils' // 工具函数目录
93
+ ];
94
+
95
+ // 遍历并创建所有基础目录
58
96
  for (const dir of baseDirs) {
59
97
  await fs.ensureDir(path.join(targetDir, dir));
60
98
  }
61
99
 
62
- // 复制模板特定的文件
100
+ // 复制模板特定的文件(如React模板、Vue模板等)
63
101
  console.log(`📂 正在复制模板文件...`);
64
102
  await copyTemplateDir(templateDir, targetDir, variables);
65
103
 
66
- // 复制通用文件
104
+ // 复制通用文件(如配置文件、README等,所有模板都需要的文件)
67
105
  if (await fs.pathExists(commonDir)) {
68
106
  console.log(`📄 正在复制通用配置文件...`);
69
107
  await copyTemplateDir(commonDir, targetDir, variables);
@@ -72,14 +110,20 @@ async function generateTemplate(projectName, templateType, targetDir) {
72
110
  console.log(`✅ 模板文件复制完成`);
73
111
  }
74
112
 
75
- // 获取可用的模板列表
113
+ /**
114
+ * 获取所有可用的模板列表
115
+ * 扫描模板目录,返回所有可用的模板类型
116
+ * @returns {Array<string>} 可用模板列表
117
+ */
76
118
  async function getAvailableTemplates() {
77
119
  const templatesDir = path.join(__dirname, './');
78
120
 
121
+ // 如果模板目录不存在,返回空数组
79
122
  if (!await fs.pathExists(templatesDir)) {
80
123
  return [];
81
124
  }
82
125
 
126
+ // 读取模板目录下的所有项目
83
127
  const items = await fs.readdir(templatesDir);
84
128
  const templates = [];
85
129
 
@@ -87,7 +131,8 @@ async function getAvailableTemplates() {
87
131
  const itemPath = path.join(templatesDir, item);
88
132
  const stat = await fs.stat(itemPath);
89
133
 
90
- // 排除common目录和index.js文件,只返回实际的模板目录
134
+ // 只返回目录类型的模板,排除common目录和index.js文件
135
+ // common目录是通用文件目录,不是模板类型
91
136
  if (stat.isDirectory() && item !== 'common') {
92
137
  templates.push(item);
93
138
  }
@@ -96,7 +141,8 @@ async function getAvailableTemplates() {
96
141
  return templates;
97
142
  }
98
143
 
144
+ // 导出主要功能函数
99
145
  module.exports = {
100
- generateTemplate,
101
- getAvailableTemplates
146
+ generateTemplate, // 生成模板项目
147
+ getAvailableTemplates // 获取可用模板列表
102
148
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ysjdemo/umi-create-cli",
3
3
  "author": "ysj <411367308@qq.com>",
4
- "version": "0.0.2",
4
+ "version": "0.0.3",
5
5
  "description": "一个用于创建Umi4项目的脚手架工具",
6
6
  "main": "index.js",
7
7
  "bin": {
@@ -11,7 +11,6 @@
11
11
  "start": "node bin/cli.js",
12
12
  "test": "echo \"Error: no test specified\" && exit 1",
13
13
  "prepublishOnly": "echo 'Preparing to publish...'",
14
- "publish:auto": "node scripts/publish.js",
15
14
  "version:patch": "npm version patch",
16
15
  "version:minor": "npm version minor",
17
16
  "version:major": "npm version major"