flu-cli 0.0.2 → 0.0.4
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 +106 -31
- package/index.js +68 -19
- package/lib/createProject.js +97 -64
- package/lib/flutterProjectCreator.js +63 -49
- package/lib/libCopier.js +183 -119
- package/lib/userInteraction.js +129 -61
- package/lib/utils.js +92 -44
- package/package.json +5 -2
- package/publish.sh +29 -0
- package/lib/desktopPath.js +0 -85
package/README.md
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Flu CLI 工具
|
|
2
2
|
|
|
3
3
|
火之夜工作室 Flutter 项目创建工具,基于 Node.js 实现的命令行工具,用于快速创建和配置 Flutter 项目。
|
|
4
4
|
|
|
5
5
|
## 功能特点
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
7
|
+
- **交互式命令行界面**:简化项目创建流程,引导用户完成各项配置
|
|
8
|
+
- **多项目类型支持**:可创建应用(app)、模块(module)、包(package)和插件(plugin)四种项目类型
|
|
9
|
+
- **丰富的模板选择**:提供四种模板类型,满足不同开发需求
|
|
10
|
+
- **仅基础项目(only)**:仅包含Flutter官方基础项目结构
|
|
11
|
+
- **最小模板(min)**:基础结构+路由管理+主题管理
|
|
12
|
+
- **标准模板(normal)**:最小模板+状态管理+工具集+UI组件库
|
|
13
|
+
- **高级模板(pro)**:标准模板+网络请求+数据缓存+示例模块
|
|
14
|
+
- **灵活的状态管理**:支持原生setState、GetX等多种状态管理方案
|
|
15
|
+
- **自动化配置**:自动处理包名替换、项目命名和依赖管理
|
|
16
|
+
- **开发环境集成**:自动配置VSCode开发环境(代码风格、调试配置、扩展推荐)
|
|
17
|
+
- **依赖包管理**:支持通过Git仓库自动集成常用工具库和网络请求库
|
|
18
|
+
- **IDE自动打开**:创建完成后可自动在VSCode或Android Studio中打开项目
|
|
19
|
+
- **跨平台支持**:兼容Windows、macOS和Linux操作系统
|
|
14
20
|
|
|
15
21
|
## 安装
|
|
16
22
|
|
|
@@ -32,7 +38,7 @@ npm install flu-cli
|
|
|
32
38
|
|
|
33
39
|
```bash
|
|
34
40
|
# 如果全局安装
|
|
35
|
-
|
|
41
|
+
flu-cli
|
|
36
42
|
|
|
37
43
|
# 或者使用 npx
|
|
38
44
|
npx flu-cli
|
|
@@ -44,13 +50,96 @@ npx flu-cli
|
|
|
44
50
|
flu-cli create
|
|
45
51
|
```
|
|
46
52
|
|
|
53
|
+
### 命令行参数示例
|
|
54
|
+
|
|
55
|
+
可以直接通过命令行参数指定所有配置,无需交互式输入:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# 创建应用项目(高级模板+GetX状态管理+VSCode)
|
|
59
|
+
flu-cli create --project-type app --template-type pro --state-manager GetX --project-name my_flutter_app --package-name com.example.myapp --parent-dir ~/your projects path --ide vscode
|
|
60
|
+
|
|
61
|
+
# 创建模块项目(标准模板+State状态管理 + Android Studio)
|
|
62
|
+
flu-cli create --project-type module --template-type normal --state-manager state --project-name my_flutter_module --package-name com.example.mymodule --parent-dir ~/your projects path --ide android_studio
|
|
63
|
+
|
|
64
|
+
# 最小化模板快速创建
|
|
65
|
+
flu-cli create --project-type app --template-type min --project-name quick_start --package-name com.example.quick --parent-dir ~/your projects path
|
|
66
|
+
|
|
67
|
+
# 仅仅创建一个flutter项目
|
|
68
|
+
flu-cli create --project-type app --template-type only --project-name quick_start --package-name com.example.quick --parent-dir ~/your projects path
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### 参数说明
|
|
72
|
+
|
|
73
|
+
| 参数 | 说明 | 可选值 |
|
|
74
|
+
| --project-type | 项目类型 | app, module, package, plugin |
|
|
75
|
+
| --template-type | 模板类型 | only, min, normal, pro |
|
|
76
|
+
| --state-manager | 状态管理方案 | state, GetX, |
|
|
77
|
+
| --project-name | 项目名称 | 小写字母、数字和下划线组合 |
|
|
78
|
+
| --package-name | 包名 | 类似Java包名格式,如com.example.app |
|
|
79
|
+
| --parent-dir | 存放目录 | 绝对路径或相对路径 |
|
|
80
|
+
| --ide | IDE选择 | vscode, android_studio, open_folder, manual |
|
|
81
|
+
| --flutter-sdk | Flutter SDK路径 | 默认为系统环境变量中的flutter |
|
|
82
|
+
|
|
47
83
|
按照提示完成以下步骤:
|
|
48
84
|
|
|
49
|
-
1.
|
|
50
|
-
2.
|
|
51
|
-
3.
|
|
52
|
-
4.
|
|
53
|
-
5.
|
|
85
|
+
1. **选择项目类型**:应用(app)、模块(module)、包(package)或插件(plugin)
|
|
86
|
+
2. **选择模板类型**:基础(only)、最小(min)、标准(normal)或高级(pro)
|
|
87
|
+
3. **选择状态管理**:根据模板类型选择合适的状态管理方案(高级模板需要)
|
|
88
|
+
4. **输入项目信息**:项目名称、包名和存放路径
|
|
89
|
+
5. **确认配置**:确认项目信息和覆盖选项
|
|
90
|
+
6. **选择IDE**:选择用于打开项目的IDE
|
|
91
|
+
|
|
92
|
+
## 模板详情
|
|
93
|
+
|
|
94
|
+
### 仅基础项目(only)
|
|
95
|
+
- 包含Flutter官方创建的基础项目结构
|
|
96
|
+
- 仅保留核心文件:`main.dart`、`pubspec.yaml`和基础目录结构
|
|
97
|
+
- 适用于快速测试或需要完全自定义项目结构的场景
|
|
98
|
+
|
|
99
|
+
### 最小模板(min)
|
|
100
|
+
- 基于基础项目扩展,增加以下功能:
|
|
101
|
+
- 路由管理:使用`auto_route`实现路由配置和导航
|
|
102
|
+
- 主题管理:支持亮色/暗色主题切换
|
|
103
|
+
- 基础工具类:包含常用字符串、日期处理方法
|
|
104
|
+
|
|
105
|
+
### 标准模板(normal)
|
|
106
|
+
- 基于最小模板扩展,增加以下功能:
|
|
107
|
+
- 状态管理:根据选择集成对应状态管理库
|
|
108
|
+
- UI组件库:基础按钮、输入框、列表项等常用组件
|
|
109
|
+
- 网络请求:基于`dio`的基础网络请求封装
|
|
110
|
+
- 本地存储:使用`shared_preferences`实现简单数据存储
|
|
111
|
+
|
|
112
|
+
### 高级模板(pro)
|
|
113
|
+
- 基于标准模板扩展,增加以下功能:
|
|
114
|
+
- 完整网络层:请求拦截、响应处理、错误统一管理
|
|
115
|
+
- 数据缓存:实现网络数据缓存策略
|
|
116
|
+
- 业务模块划分:按功能模块组织代码结构
|
|
117
|
+
- 示例功能:包含登录、列表等示例页面
|
|
118
|
+
- 依赖注入:使用`get_it`实现服务定位
|
|
119
|
+
|
|
120
|
+
## 项目结构
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
flutter-cli/
|
|
124
|
+
├── index.js # 主入口文件
|
|
125
|
+
├── package.json # 项目配置
|
|
126
|
+
├── README.md # 项目说明文档
|
|
127
|
+
└── lib/ # 核心功能模块
|
|
128
|
+
├── createProject.js # 项目创建主流程协调
|
|
129
|
+
├── userInteraction.js # 用户交互功能(输入、选择、确认)
|
|
130
|
+
├── flutterProjectCreator.js # Flutter项目创建(执行flutter create命令)
|
|
131
|
+
├── libCopier.js # 模板文件复制和处理
|
|
132
|
+
├── utils.js # 工具函数(验证、格式化、IDE打开等)
|
|
133
|
+
└── desktopPath.js # 桌面路径获取
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 核心模块说明
|
|
137
|
+
|
|
138
|
+
- **createProject.js**:协调整个项目创建流程,包括用户交互、项目初始化、模板复制和环境配置
|
|
139
|
+
- **userInteraction.js**:提供所有交互式功能,包括获取项目类型、模板类型、状态管理、项目信息等
|
|
140
|
+
- **flutterProjectCreator.js**:执行`flutter create`命令创建基础项目,处理不同项目类型参数
|
|
141
|
+
- **libCopier.js**:负责模板文件复制、占位符替换和Git仓库克隆操作
|
|
142
|
+
- **utils.js**:提供各种辅助功能,如名称验证、彩色输出、README生成和IDE自动打开
|
|
54
143
|
|
|
55
144
|
## 依赖项
|
|
56
145
|
|
|
@@ -58,27 +147,11 @@ flu-cli create
|
|
|
58
147
|
- chalk: 终端彩色输出
|
|
59
148
|
- commander: 命令行参数解析
|
|
60
149
|
- ora: 终端加载动画
|
|
61
|
-
- cli-progress: 进度条显示
|
|
62
150
|
- fs-extra: 文件系统操作增强
|
|
151
|
+
- child_process: 执行系统命令
|
|
63
152
|
|
|
64
153
|
## 开发
|
|
65
154
|
|
|
66
|
-
### 项目结构
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
flutter-cli/
|
|
70
|
-
├── index.js # 主入口文件
|
|
71
|
-
├── package.json # 项目配置
|
|
72
|
-
├── README.md # 项目说明
|
|
73
|
-
└── lib/ # 核心功能模块
|
|
74
|
-
├── createProject.js # 项目创建主流程
|
|
75
|
-
├── userInteraction.js # 用户交互功能
|
|
76
|
-
├── flutterProjectCreator.js # Flutter项目创建
|
|
77
|
-
├── libCopier.js # 项目模板复制
|
|
78
|
-
├── utils.js # 工具函数
|
|
79
|
-
└── desktopPath.js # 桌面路径获取
|
|
80
|
-
```
|
|
81
|
-
|
|
82
155
|
### 本地开发
|
|
83
156
|
|
|
84
157
|
```bash
|
|
@@ -101,6 +174,8 @@ flu-cli
|
|
|
101
174
|
- 确保系统已正确安装 Flutter SDK 并添加到环境变量
|
|
102
175
|
- 使用前可运行 `flutter doctor` 检查 Flutter 安装状态
|
|
103
176
|
- 项目创建过程中需要网络连接以从 Git 仓库获取模板
|
|
177
|
+
- 高级模板可能需要较长时间下载依赖,请耐心等待
|
|
178
|
+
- 如遇权限问题,在命令前添加`sudo`(macOS/Linux)或使用管理员权限运行终端(Windows)
|
|
104
179
|
|
|
105
180
|
## 许可证
|
|
106
181
|
|
package/index.js
CHANGED
|
@@ -6,35 +6,64 @@
|
|
|
6
6
|
* 主入口文件,处理命令行参数并调用相应功能
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
|
|
10
|
+
import { program } from 'commander'
|
|
11
|
+
import chalk from 'chalk';
|
|
12
|
+
import { createProject } from './lib/createProject.js';
|
|
13
|
+
import { readFileSync } from 'fs';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import { dirname, join } from 'path';
|
|
16
|
+
|
|
17
|
+
// 获取package.json内容
|
|
18
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const packageJson = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8'));
|
|
13
20
|
|
|
14
21
|
// 设置版本号和描述
|
|
15
22
|
program
|
|
16
23
|
.version(packageJson.version)
|
|
17
24
|
.description(chalk.cyan('火之夜工作室 Flutter 项目创建工具'));
|
|
18
25
|
|
|
26
|
+
//
|
|
27
|
+
|
|
19
28
|
// 创建项目命令
|
|
20
29
|
program
|
|
21
30
|
.command('create')
|
|
22
|
-
.description('
|
|
23
|
-
.option('-t, --project-type <type>', '项目类型: app
|
|
24
|
-
.option('-m, --template-type <type>', '模板类型:
|
|
25
|
-
.option('-
|
|
26
|
-
.option('-n, --project-name <name>', '项目名称
|
|
27
|
-
.option('-p, --package-name <name>', '包名
|
|
28
|
-
.option('-
|
|
29
|
-
.option('-i, --ide <type>', '使用的IDE: vscode, android_studio,
|
|
31
|
+
.description('创建新的Flutter项目')
|
|
32
|
+
.option('-t, --project-type <type>', '项目类型: app, module, package, plugin', 'app')
|
|
33
|
+
.option('-m, --template-type <type>', '模板类型: only, min, normal, pro', 'normal')
|
|
34
|
+
.option('-s, --state-manager <name>', '状态管理: state, GetX, Provider, MobX, Bloc, Riverpod', 'GetX')
|
|
35
|
+
.option('-n, --project-name <name>', '项目名称')
|
|
36
|
+
.option('-p, --package-name <name>', '包名(com.example.app)')
|
|
37
|
+
.option('-d, --parent-dir <path>', '项目存放目录')
|
|
38
|
+
.option('-i, --ide <type>', '使用的IDE: vscode, android_studio, open_folder , manual', 'vscode')
|
|
30
39
|
.option('-f, --flutter-sdk <path>', '自定义Flutter SDK路径')
|
|
40
|
+
.option('-h, --help', '显示创建命令帮助信息')
|
|
31
41
|
.action((options) => {
|
|
32
|
-
|
|
42
|
+
if (options.help) {
|
|
43
|
+
console.log(chalk.bold.greenBright('flu-cli create - 创建新的Flutter项目'));
|
|
44
|
+
console.log('用法: flu-cli create [选项]');
|
|
45
|
+
console.log('选项:');
|
|
46
|
+
console.log(' -t, --project-type <type> 项目类型 (app, module, package, plugin) [默认: app]');
|
|
47
|
+
console.log(' -m, --template-type <type> 模板类型 (only, min, normal, pro) [默认: pro]');
|
|
48
|
+
console.log(' -s, --state-manager <name> 状态管理方案 (state, GetX,) [默认: GetX]');
|
|
49
|
+
console.log(' -n, --project-name <name> 项目名称 [默认: hzy_example_${项目类型}]');
|
|
50
|
+
console.log(' -p, --package-name <name> 包名 [默认: com.example.${项目类型}]');
|
|
51
|
+
console.log(' -d, --parent-dir <path> 项目存放目录 [默认: 当前目录]');
|
|
52
|
+
console.log(' -i, --ide <choice> IDE选择 (vscode, android_studio, open_folder, manual) [默认: vscode]');
|
|
53
|
+
console.log(' -f, --flutter-sdk <path> 自定义Flutter SDK路径 [默认: 系统环境变量中的flutter]');
|
|
54
|
+
console.log(' -h, --help 显示本帮助信息');
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
console.log(chalk.bold.greenBright('欢迎使用 火之夜工作室 Flutter 项目创建工具'));
|
|
33
59
|
|
|
34
60
|
// 检查是否提供了命令行参数
|
|
35
|
-
const hasCommandLineArgs = options.projectName ||
|
|
36
|
-
options.
|
|
37
|
-
options.
|
|
61
|
+
const hasCommandLineArgs = options.projectName ||
|
|
62
|
+
options.packageName ||
|
|
63
|
+
options.projectType !== 'app' ||
|
|
64
|
+
options.templateType !== 'normal' ||
|
|
65
|
+
options.stateManager !== 'GetX' ||
|
|
66
|
+
options.parentDir || options.ide !== 'vscode' || options.flutterSdk;
|
|
38
67
|
|
|
39
68
|
// 如果提供了命令行参数,则直接使用这些参数创建项目
|
|
40
69
|
// 否则使用交互式方式获取参数
|
|
@@ -42,14 +71,34 @@ program
|
|
|
42
71
|
useCommandLineArgs: hasCommandLineArgs,
|
|
43
72
|
projectType: options.projectType,
|
|
44
73
|
templateType: options.templateType,
|
|
45
|
-
|
|
74
|
+
stateManager: options.stateManager,
|
|
46
75
|
projectName: options.projectName,
|
|
47
76
|
packageName: options.packageName,
|
|
48
|
-
parentDir: options.
|
|
49
|
-
ideChoice: options.ide
|
|
77
|
+
parentDir: options.parentDir,
|
|
78
|
+
ideChoice: options.ide,
|
|
79
|
+
flutterSdkPath: options.flutterSdk,
|
|
50
80
|
});
|
|
51
81
|
});
|
|
52
82
|
|
|
83
|
+
// 全局帮助处理
|
|
84
|
+
if (process.argv.includes('-h') || process.argv.includes('--help')) {
|
|
85
|
+
if (process.argv.length <= 3) {
|
|
86
|
+
console.log('flu-cli - 火之夜工作室Flutter项目创建工具');
|
|
87
|
+
console.log('版本: ' + packageJson.version);
|
|
88
|
+
console.log('用法: flu-cli [命令] [选项]\n');
|
|
89
|
+
console.log('命令:');
|
|
90
|
+
console.log(' create 创建新的Flutter项目\n');
|
|
91
|
+
console.log('全局选项:');
|
|
92
|
+
console.log(' -V, --version 显示版本号');
|
|
93
|
+
console.log(' -h, --help 显示全局帮助信息\n');
|
|
94
|
+
console.log('使用 "flu-cli [命令] --help" 查看特定命令的详细帮助');
|
|
95
|
+
process.exit(0);
|
|
96
|
+
}
|
|
97
|
+
program.parse(process.argv);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
53
102
|
// 如果没有提供命令,默认执行创建项目
|
|
54
103
|
if (process.argv.length === 2) {
|
|
55
104
|
console.log(chalk.bold.greenBright('欢迎使用 火之夜工作室 Flutter 项目创建工具\n'));
|
package/lib/createProject.js
CHANGED
|
@@ -1,60 +1,102 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 项目创建模块
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 负责协调整个Flutter项目的创建流程,包括用户交互、项目初始化、模板复制和环境配置
|
|
5
|
+
* 支持通过命令行参数或交互式方式创建不同类型和模板的Flutter项目
|
|
5
6
|
*/
|
|
6
7
|
|
|
8
|
+
import { execSync } from 'child_process';
|
|
9
|
+
import ora from 'ora';
|
|
10
|
+
import { dirname, join } from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
import fsExtra from 'fs-extra';
|
|
13
|
+
const { existsSync, mkdirSync, accessSync, constants, removeSync } = fsExtra;
|
|
14
|
+
import { getUserInteraction } from './userInteraction.js';
|
|
15
|
+
import { copyLibDirectory, copyVscode } from './libCopier.js';
|
|
16
|
+
import { runFlutterCreate } from './flutterProjectCreator.js';
|
|
17
|
+
import { printColored, updateReadme, openProjectInIde, getTemplateBranch } from './utils.js';
|
|
7
18
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
/**
|
|
20
|
+
* 生成默认项目名称
|
|
21
|
+
*
|
|
22
|
+
* 根据项目类型和当前日期生成唯一的默认项目名称,避免命名冲突
|
|
23
|
+
* 应用类型项目以'flutter_app_'为前缀,模块类型以'flutter_module_'为前缀
|
|
24
|
+
*
|
|
25
|
+
* @param {string} projectType - 项目类型 ('app' 或 'module')
|
|
26
|
+
* @returns {string} 带时间戳的默认项目名称
|
|
27
|
+
*/
|
|
28
|
+
function getDefaultProjectName (projectType) {
|
|
29
|
+
const date = new Date();
|
|
30
|
+
const timestamp = `${date.getFullYear()}${String(date.getMonth() + 1).padStart(2, '0')}${String(date.getDate()).padStart(2, '0')}`;
|
|
31
|
+
return projectType === 'app' ? `flutter_app_${timestamp}` : `flutter_module_${timestamp}`;
|
|
32
|
+
}
|
|
16
33
|
|
|
17
34
|
/**
|
|
18
35
|
* 创建项目的主函数
|
|
19
36
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* @param {
|
|
24
|
-
* @param {
|
|
25
|
-
* @param {
|
|
26
|
-
* @param {string} options.
|
|
27
|
-
* @param {string} options.
|
|
28
|
-
* @param {string} options.
|
|
29
|
-
* @param {string} options.
|
|
37
|
+
* 协调整个项目创建流程,包括获取用户输入、验证环境、创建Flutter项目、复制模板文件、
|
|
38
|
+
* 生成README和自动打开IDE等步骤。支持命令行参数和交互式两种模式
|
|
39
|
+
*
|
|
40
|
+
* @param {Object} [options={}] - 命令行参数选项
|
|
41
|
+
* @param {boolean} [options.useCommandLineArgs=false] - 是否使用命令行参数
|
|
42
|
+
* @param {string} [options.projectType] - 项目类型 ('app','module','package','plugin')
|
|
43
|
+
* @param {string} [options.templateType] - 模板类型 ('only', 'min', 'normal', 'pro')
|
|
44
|
+
* @param {string} [options.stateManager] - 状态管理 ('state', 'GetX', 'Provider', etc.)
|
|
45
|
+
* @param {string} [options.projectName] - 项目名称
|
|
46
|
+
* @param {string} [options.packageName] - 包名
|
|
47
|
+
* @param {string} [options.parentDir] - 项目存放路径
|
|
48
|
+
* @param {string} [options.ideChoice] - IDE选择 ('vscode', 'android_studio', etc.)
|
|
49
|
+
* @param {string} [options.flutterSdk] - Flutter SDK路径
|
|
50
|
+
* @example
|
|
51
|
+
* // 交互式创建项目
|
|
52
|
+
* createProject();
|
|
53
|
+
* // 命令行模式创建项目
|
|
54
|
+
* createProject({
|
|
55
|
+
* useCommandLineArgs: true,
|
|
56
|
+
* projectType: 'app',
|
|
57
|
+
* templateType: 'pro',
|
|
58
|
+
* projectName: 'my_app',
|
|
59
|
+
* packageName: 'com.example.myapp',
|
|
60
|
+
* parentDir: '/path/to/projects'
|
|
61
|
+
* });
|
|
30
62
|
*/
|
|
31
63
|
async function createProject (options = {}) {
|
|
32
64
|
try {
|
|
33
65
|
// 获取项目类型 - 从命令行参数或交互式输入
|
|
34
66
|
const projectType = options.useCommandLineArgs ? options.projectType : await getUserInteraction.getProjectType();
|
|
67
|
+
let templateType = '';
|
|
68
|
+
// 项目类型为app或module时,获取模板类型
|
|
69
|
+
if (projectType == "app" || projectType == "module") {
|
|
70
|
+
// 获取模板类型 - 从命令行参数或交互式输入
|
|
71
|
+
templateType = options.useCommandLineArgs ? options.templateType : await getUserInteraction.getTemplateType();
|
|
72
|
+
} else {
|
|
73
|
+
// 项目类型为package或plugin时,模板类型固定为only
|
|
74
|
+
templateType = 'only';
|
|
75
|
+
}
|
|
35
76
|
|
|
36
|
-
// 获取模板类型 - 从命令行参数或交互式输入
|
|
37
|
-
const templateType = options.useCommandLineArgs ? options.templateType : await getUserInteraction.getTemplateType();
|
|
38
77
|
|
|
39
|
-
//
|
|
40
|
-
|
|
78
|
+
// 获取状态管理 - 仅在非基础模板时需要
|
|
79
|
+
let stateManager = '';
|
|
80
|
+
if (templateType != 'only' && templateType != 'min') {
|
|
81
|
+
stateManager = options.useCommandLineArgs ? options.stateManager : await getUserInteraction.getStateManager();
|
|
82
|
+
}
|
|
41
83
|
|
|
42
84
|
// 获取当前脚本所在目录作为源目录
|
|
43
|
-
const sourceDir =
|
|
85
|
+
const sourceDir = dirname(fileURLToPath(import.meta.url));
|
|
44
86
|
|
|
45
87
|
// 获取项目信息 - 从命令行参数或交互式输入
|
|
46
88
|
let projectName, packageName, parentDir, targetDir, flutterSdkPath;
|
|
47
89
|
|
|
48
|
-
if (options.useCommandLineArgs && options.projectName && options.packageName && options.parentDir) {
|
|
90
|
+
if (options.useCommandLineArgs && options.projectName && options.packageName && options.parentDir && options.flutterSdk) {
|
|
49
91
|
// 使用命令行参数
|
|
50
92
|
projectName = options.projectName;
|
|
51
93
|
packageName = options.packageName;
|
|
52
94
|
parentDir = options.parentDir;
|
|
53
|
-
targetDir =
|
|
95
|
+
targetDir = join(parentDir, projectName);
|
|
54
96
|
flutterSdkPath = options.flutterSdk;
|
|
55
97
|
} else if (options.useCommandLineArgs) {
|
|
56
98
|
// 命令行参数不完整,使用交互式输入,但预填充已提供的参数
|
|
57
|
-
const defaultName = projectType
|
|
99
|
+
const defaultName = getDefaultProjectName(projectType);
|
|
58
100
|
const projectInfo = await getUserInteraction.getProjectInfo(
|
|
59
101
|
projectType,
|
|
60
102
|
options.projectName || defaultName,
|
|
@@ -69,8 +111,11 @@ async function createProject (options = {}) {
|
|
|
69
111
|
} else {
|
|
70
112
|
// 完全使用交互式输入
|
|
71
113
|
const projectInfo = await getUserInteraction.getProjectInfo(projectType);
|
|
114
|
+
// 项目名字
|
|
72
115
|
projectName = projectInfo.projectName;
|
|
116
|
+
// 包名
|
|
73
117
|
packageName = projectInfo.packageName;
|
|
118
|
+
// 项目存放地址
|
|
74
119
|
parentDir = projectInfo.parentDir;
|
|
75
120
|
targetDir = projectInfo.targetDir;
|
|
76
121
|
flutterSdkPath = projectInfo.flutterSdkPath;
|
|
@@ -78,9 +123,9 @@ async function createProject (options = {}) {
|
|
|
78
123
|
|
|
79
124
|
console.log('flutterSdkPath:', flutterSdkPath);
|
|
80
125
|
// 验证目标目录是否存在并具有写权限
|
|
81
|
-
if (!
|
|
126
|
+
if (!existsSync(parentDir)) {
|
|
82
127
|
try {
|
|
83
|
-
|
|
128
|
+
mkdirSync(parentDir, { recursive: true });
|
|
84
129
|
} catch (e) {
|
|
85
130
|
printColored(`错误: 无法创建目录 ${parentDir}: ${e.message}`, 'red');
|
|
86
131
|
return;
|
|
@@ -89,14 +134,14 @@ async function createProject (options = {}) {
|
|
|
89
134
|
|
|
90
135
|
// 检查目标目录是否具有写权限
|
|
91
136
|
try {
|
|
92
|
-
|
|
137
|
+
accessSync(parentDir, constants.W_OK);
|
|
93
138
|
} catch (e) {
|
|
94
139
|
printColored(`错误: 目录 ${parentDir} 没有写权限`, 'red');
|
|
95
140
|
return;
|
|
96
141
|
}
|
|
97
142
|
|
|
98
143
|
// 检查目标目录是否已存在
|
|
99
|
-
if (
|
|
144
|
+
if (existsSync(targetDir)) {
|
|
100
145
|
const overwrite = await getUserInteraction.confirmOverwrite(targetDir);
|
|
101
146
|
if (!overwrite) {
|
|
102
147
|
printColored("操作已取消", 'yellow');
|
|
@@ -104,7 +149,7 @@ async function createProject (options = {}) {
|
|
|
104
149
|
}
|
|
105
150
|
|
|
106
151
|
// 删除已存在的目录
|
|
107
|
-
|
|
152
|
+
removeSync(targetDir);
|
|
108
153
|
}
|
|
109
154
|
|
|
110
155
|
// 使用flutter create创建新项目
|
|
@@ -116,40 +161,25 @@ async function createProject (options = {}) {
|
|
|
116
161
|
}
|
|
117
162
|
flutterCreateSpinner.succeed('Flutter项目创建成功');
|
|
118
163
|
|
|
119
|
-
// 根据模板类型选择Git分支和是否需要demo分支
|
|
120
|
-
let templateBranch = 'master';
|
|
121
|
-
|
|
122
|
-
switch (templateType) {
|
|
123
|
-
case '0':
|
|
124
|
-
// 基础模版
|
|
125
|
-
templateBranch = 'master';
|
|
126
|
-
break;
|
|
127
|
-
case '1':
|
|
128
|
-
// State模板
|
|
129
|
-
templateBranch = 'depend';
|
|
130
|
-
break;
|
|
131
|
-
case '2':
|
|
132
|
-
// GetX模板
|
|
133
|
-
templateBranch = 'depend-get';
|
|
134
|
-
break;
|
|
135
|
-
default:
|
|
136
|
-
break;
|
|
137
|
-
}
|
|
138
164
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
165
|
+
|
|
166
|
+
if (templateType != 'only') {
|
|
167
|
+
// 获取模板分支名称
|
|
168
|
+
const templateBranch = getTemplateBranch(templateType, stateManager);
|
|
169
|
+
// 复制项目文件
|
|
170
|
+
const copySpinner = ora('正在复制项目模板...').start();
|
|
171
|
+
const copyResult = await copyLibDirectory(sourceDir, targetDir, projectName, projectType, templateType, packageName, templateBranch);
|
|
172
|
+
if (!copyResult) {
|
|
173
|
+
copySpinner.fail('项目模板复制失败');
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
copySpinner.succeed('项目模板复制成功');
|
|
177
|
+
// 更新README.md
|
|
178
|
+
updateReadme(targetDir, projectName, packageName);
|
|
148
179
|
}
|
|
149
|
-
copySpinner.succeed('项目模板复制成功');
|
|
150
180
|
|
|
151
|
-
|
|
152
|
-
|
|
181
|
+
|
|
182
|
+
|
|
153
183
|
|
|
154
184
|
// 打印完成信息
|
|
155
185
|
printColored("\n新项目已创建成功!", 'green');
|
|
@@ -161,6 +191,9 @@ async function createProject (options = {}) {
|
|
|
161
191
|
|
|
162
192
|
// 获取用户选择的IDE类型 - 从命令行参数或交互式输入
|
|
163
193
|
const ideChoice = options.useCommandLineArgs ? options.ideChoice : await getUserInteraction.getIdeChoice();
|
|
194
|
+
if (ideChoice == 'vscode' && templateType != 'only') {
|
|
195
|
+
await copyVscode(targetDir);
|
|
196
|
+
}
|
|
164
197
|
if ((ideChoice == 'vscode' || ideChoice == 'android_studio') && flutterSdkPath === 'flutter') {
|
|
165
198
|
const pubGetSpinner = ora('正在获取Flutter依赖...').start();
|
|
166
199
|
try {
|
|
@@ -184,4 +217,4 @@ async function createProject (options = {}) {
|
|
|
184
217
|
}
|
|
185
218
|
}
|
|
186
219
|
|
|
187
|
-
|
|
220
|
+
export { createProject };
|