flu-cli 0.0.2 → 0.0.5
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 +259 -63
- 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/lib/userInteraction.js
CHANGED
|
@@ -4,17 +4,20 @@
|
|
|
4
4
|
* 包含所有与用户交互相关的函数
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
|
|
8
|
+
import inquirer from 'inquirer';
|
|
9
|
+
const { prompt } = inquirer;
|
|
10
|
+
import { existsSync } from 'fs';
|
|
11
|
+
|
|
12
|
+
import { join } from 'path';
|
|
13
|
+
import { printColored, validatePackageName, validateProjectName } from './utils.js';
|
|
14
|
+
|
|
15
|
+
|
|
13
16
|
|
|
14
17
|
/**
|
|
15
18
|
* 用户交互功能集合
|
|
16
19
|
*/
|
|
17
|
-
const getUserInteraction = {
|
|
20
|
+
export const getUserInteraction = {
|
|
18
21
|
/**
|
|
19
22
|
* 获取项目类型
|
|
20
23
|
*
|
|
@@ -22,14 +25,16 @@ const getUserInteraction = {
|
|
|
22
25
|
*/
|
|
23
26
|
getProjectType: async () => {
|
|
24
27
|
|
|
25
|
-
const { projectType } = await
|
|
28
|
+
const { projectType } = await prompt([
|
|
26
29
|
{
|
|
27
30
|
type: 'list',
|
|
28
31
|
name: 'projectType',
|
|
29
32
|
message: '请选择项目类型:',
|
|
30
33
|
choices: [
|
|
31
|
-
{ name: '应用 (app)', value: 'app' },
|
|
32
|
-
{ name: '模块 (module)', value: 'module' }
|
|
34
|
+
{ name: '应用 (app)', value: 'app', },
|
|
35
|
+
{ name: '模块 (module)', value: 'module', },
|
|
36
|
+
{ name: '原生插件 (plugin)', value: 'plugin', },
|
|
37
|
+
{ name: '插件 (package)', value: 'package', }
|
|
33
38
|
],
|
|
34
39
|
default: 'app'
|
|
35
40
|
}
|
|
@@ -40,28 +45,52 @@ const getUserInteraction = {
|
|
|
40
45
|
/**
|
|
41
46
|
* 获取模板类型
|
|
42
47
|
*
|
|
43
|
-
* @returns {Promise<string>} '
|
|
48
|
+
* @returns {Promise<string>} 'only' 或 'min' 或 'normal' 或 'pro'
|
|
44
49
|
*/
|
|
45
50
|
getTemplateType: async () => {
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
const { templateType } = await prompt([
|
|
48
55
|
{
|
|
49
56
|
type: 'list',
|
|
50
57
|
name: 'templateType',
|
|
51
58
|
message: '请选择项目模版:',
|
|
52
59
|
choices: [
|
|
53
|
-
{ name: '
|
|
54
|
-
{ name: '
|
|
55
|
-
{ name: '
|
|
60
|
+
{ name: 'only (main.dart)', value: 'only' },
|
|
61
|
+
{ name: 'min (项目结构、路由管理、主题管理、状态管理、工具集)', value: 'min' },
|
|
62
|
+
{ name: 'normal (项目结构、路由管理、主题管理、状态管理、工具集、UI组件库)', value: 'normal' },
|
|
63
|
+
{ name: 'pro (项目结构、路由管理、主题管理、状态管理、工具集、UI组件库、网络请求、数据缓存、示例模块)', value: 'pro' }
|
|
56
64
|
],
|
|
57
|
-
default: '
|
|
65
|
+
default: 'pro'
|
|
58
66
|
}
|
|
59
67
|
]);
|
|
60
68
|
return templateType;
|
|
61
69
|
},
|
|
62
70
|
|
|
71
|
+
/**
|
|
72
|
+
* 获取状态管理
|
|
73
|
+
*
|
|
74
|
+
* @returns {Promise<string>} 'state' 或 'GetX'
|
|
75
|
+
*/
|
|
76
|
+
getStateManager: async () => {
|
|
77
|
+
const { stateManager } = await prompt([
|
|
78
|
+
{
|
|
79
|
+
type: 'list',
|
|
80
|
+
name: 'stateManager',
|
|
81
|
+
message: '请选择状态管理:',
|
|
82
|
+
choices: [
|
|
83
|
+
{ name: 'state (State)', value: 'state' },
|
|
84
|
+
{ name: 'get (GetX)', value: 'GetX' },
|
|
85
|
+
],
|
|
86
|
+
default: 'state'
|
|
87
|
+
}
|
|
88
|
+
]);
|
|
89
|
+
return stateManager;
|
|
90
|
+
},
|
|
91
|
+
|
|
63
92
|
getIsNeedDemo: async () => {
|
|
64
|
-
const { isNeedDemo } = await
|
|
93
|
+
const { isNeedDemo } = await prompt([
|
|
65
94
|
{
|
|
66
95
|
type: 'confirm',
|
|
67
96
|
name: 'isNeedDemo',
|
|
@@ -81,59 +110,69 @@ const getUserInteraction = {
|
|
|
81
110
|
* @param {string} defaultParentDir - 默认父目录
|
|
82
111
|
* @returns {Promise<Object>} 项目信息对象
|
|
83
112
|
*/
|
|
84
|
-
getProjectInfo: async (projectType, defaultProjectName, defaultPackageName, defaultParentDir) => {
|
|
85
|
-
// 设置默认值
|
|
86
|
-
if (!defaultProjectName) {
|
|
87
|
-
defaultProjectName = projectType === 'module' ? "hzy_example_module" : "hzy_example_project";
|
|
88
|
-
}
|
|
89
|
-
|
|
113
|
+
getProjectInfo: async (projectType, defaultProjectName, defaultPackageName, defaultParentDir, flutterSdkPath) => {
|
|
90
114
|
// 获取项目名称
|
|
91
|
-
|
|
115
|
+
let projectName = defaultProjectName;
|
|
116
|
+
if (!defaultProjectName) {
|
|
117
|
+
defaultProjectName = getDefaultProjectName(projectType);
|
|
118
|
+
const res = await prompt([
|
|
119
|
+
{
|
|
120
|
+
type: 'input',
|
|
121
|
+
name: 'projectName',
|
|
122
|
+
message: '请输入新项目名称(小写字母、数字和下划线):',
|
|
123
|
+
default: defaultProjectName,
|
|
124
|
+
validate: validateProjectName
|
|
125
|
+
}
|
|
92
126
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
name: 'projectName',
|
|
97
|
-
message: '请输入新项目名称(小写字母、数字和下划线):',
|
|
98
|
-
default: defaultProjectName,
|
|
99
|
-
validate: validateProjectName
|
|
100
|
-
}
|
|
101
|
-
]);
|
|
127
|
+
]);
|
|
128
|
+
projectName = res.projectName;
|
|
129
|
+
}
|
|
102
130
|
|
|
131
|
+
// 获取Flutter SDK路径
|
|
132
|
+
if (!flutterSdkPath) {
|
|
133
|
+
flutterSdkPath = await getFlutterSdkPath();
|
|
134
|
+
}
|
|
103
135
|
// 获取包名
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
136
|
+
let packageName = defaultPackageName;
|
|
137
|
+
if (!defaultPackageName) {
|
|
138
|
+
defaultPackageName = `com.example.${projectName}`;
|
|
139
|
+
const res = await prompt([
|
|
140
|
+
{
|
|
141
|
+
type: 'input',
|
|
142
|
+
name: 'packageName',
|
|
143
|
+
message: '请输入包名:',
|
|
144
|
+
default: defaultPackageName || `com.example.${projectName}`,
|
|
145
|
+
validate: validatePackageName
|
|
146
|
+
}
|
|
147
|
+
]);
|
|
148
|
+
packageName = res.packageName;
|
|
149
|
+
}
|
|
113
150
|
|
|
114
151
|
|
|
115
|
-
|
|
116
|
-
|
|
152
|
+
|
|
153
|
+
// 获取父目录
|
|
154
|
+
let parentDir = defaultParentDir;
|
|
117
155
|
if (!defaultParentDir) {
|
|
118
|
-
|
|
156
|
+
defaultParentDir = process.cwd();
|
|
157
|
+
const res = await prompt([
|
|
158
|
+
{
|
|
159
|
+
type: 'input',
|
|
160
|
+
name: 'parentDir',
|
|
161
|
+
message: '请输入项目存放路径:',
|
|
162
|
+
default: defaultParentDir
|
|
163
|
+
}
|
|
164
|
+
]);
|
|
165
|
+
parentDir = res.parentDir;
|
|
119
166
|
}
|
|
120
|
-
const { parentDir } = await inquirer.prompt([
|
|
121
|
-
{
|
|
122
|
-
type: 'input',
|
|
123
|
-
name: 'parentDir',
|
|
124
|
-
message: '请输入项目存放路径:',
|
|
125
|
-
default: defaultParentDir || desktopPath
|
|
126
|
-
}
|
|
127
|
-
]);
|
|
128
167
|
|
|
129
|
-
const targetDir =
|
|
130
|
-
console.log('flutterPath:',
|
|
168
|
+
const targetDir = join(parentDir, projectName);
|
|
169
|
+
console.log('flutterPath:', flutterSdkPath);
|
|
131
170
|
return {
|
|
132
171
|
projectName,
|
|
133
172
|
packageName,
|
|
134
173
|
parentDir,
|
|
135
174
|
targetDir,
|
|
136
|
-
flutterSdkPath
|
|
175
|
+
flutterSdkPath
|
|
137
176
|
};
|
|
138
177
|
},
|
|
139
178
|
|
|
@@ -146,7 +185,7 @@ const getUserInteraction = {
|
|
|
146
185
|
confirmOverwrite: async (targetDir) => {
|
|
147
186
|
printColored(`\n警告: 目标目录 ${targetDir} 已存在!`, 'yellow');
|
|
148
187
|
|
|
149
|
-
const { overwrite } = await
|
|
188
|
+
const { overwrite } = await prompt([
|
|
150
189
|
{
|
|
151
190
|
type: 'confirm',
|
|
152
191
|
name: 'overwrite',
|
|
@@ -170,7 +209,7 @@ const getUserInteraction = {
|
|
|
170
209
|
* @returns {Promise<string>} IDE类型
|
|
171
210
|
*/
|
|
172
211
|
getIdeChoice: async () => {
|
|
173
|
-
const { ideChoice } = await
|
|
212
|
+
const { ideChoice } = await prompt([
|
|
174
213
|
{
|
|
175
214
|
type: 'list',
|
|
176
215
|
name: 'ideChoice',
|
|
@@ -190,17 +229,46 @@ const getUserInteraction = {
|
|
|
190
229
|
};
|
|
191
230
|
|
|
192
231
|
async function getFlutterSdkPath () {
|
|
193
|
-
const { path: sdkPath } = await
|
|
232
|
+
const { path: sdkPath } = await prompt([{
|
|
194
233
|
type: 'input',
|
|
195
234
|
name: 'path',
|
|
196
235
|
|
|
197
236
|
message: '请输入Flutter SDK路径(留空使用系统默认):',
|
|
198
|
-
validate: input => !input ||
|
|
237
|
+
validate: input => !input || existsSync(join(input, 'bin/flutter'))
|
|
199
238
|
}]);
|
|
200
239
|
return sdkPath || 'flutter';
|
|
201
240
|
}
|
|
202
241
|
|
|
203
|
-
|
|
242
|
+
/**
|
|
243
|
+
* 获取默认项目名称
|
|
244
|
+
*
|
|
245
|
+
* @param {string} projectType - 项目类型 ('app'或'module')
|
|
246
|
+
* @returns {string} 默认项目名称
|
|
247
|
+
*/
|
|
248
|
+
function getDefaultProjectName (projectType) {
|
|
249
|
+
let defaultProjectName = 'project';
|
|
250
|
+
switch (projectType) {
|
|
251
|
+
case 'app':
|
|
252
|
+
defaultProjectName = 'project';
|
|
253
|
+
break;
|
|
254
|
+
case 'module':
|
|
255
|
+
defaultProjectName = 'module';
|
|
256
|
+
break;
|
|
257
|
+
case 'package':
|
|
258
|
+
defaultProjectName = 'package';
|
|
259
|
+
break;
|
|
260
|
+
case 'plugin':
|
|
261
|
+
defaultProjectName = 'plugin';
|
|
262
|
+
break;
|
|
263
|
+
default:
|
|
264
|
+
defaultProjectName = 'example';
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
return "hzy_example_" + defaultProjectName;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export default {
|
|
204
271
|
getFlutterSdkPath,
|
|
272
|
+
getDefaultProjectName,
|
|
205
273
|
getUserInteraction
|
|
206
274
|
};
|
package/lib/utils.js
CHANGED
|
@@ -1,40 +1,67 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 工具函数模块
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 包含项目创建过程中所需的各种实用工具函数,如模板分支计算、彩色输出、
|
|
5
|
+
* 验证函数、README生成和IDE打开等功能
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
const {
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
const { red: _red, green: _green, yellow: _yellow, blue: _blue, magenta, cyan: _cyan, bold } = chalk;
|
|
10
|
+
import fsExtra from 'fs-extra';
|
|
11
|
+
const { writeFileSync } = fsExtra;
|
|
12
|
+
import { join, resolve } from 'path';
|
|
13
|
+
import { exec } from 'child_process';
|
|
14
|
+
|
|
11
15
|
|
|
12
16
|
/**
|
|
13
|
-
*
|
|
17
|
+
* 计算模板分支名称
|
|
18
|
+
*
|
|
19
|
+
* 根据模板类型和状态管理组合生成Git仓库分支名称
|
|
20
|
+
* 用于从Git仓库获取对应类型的项目模板
|
|
21
|
+
*
|
|
22
|
+
* @param {string} templateType - 模板类型 (only, min, normal, pro)
|
|
23
|
+
* @param {string} stateManager - 状态管理类型 (state, GetX, Provider等)
|
|
24
|
+
* @returns {string} 组合后的模板分支名称
|
|
25
|
+
*/
|
|
26
|
+
export function getTemplateBranch (templateType, stateManager) {
|
|
27
|
+
if (stateManager == '') {
|
|
28
|
+
return templateType;
|
|
29
|
+
}
|
|
30
|
+
return templateType + "-" + stateManager;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 打印彩色文本到控制台
|
|
35
|
+
*
|
|
36
|
+
* 支持多种颜色输出,用于区分不同类型的提示信息(成功、错误、警告等)
|
|
37
|
+
* 使用chalk库实现颜色渲染,并自动添加粗体效果
|
|
14
38
|
*
|
|
15
|
-
* @param {string} text -
|
|
16
|
-
* @param {string} color -
|
|
39
|
+
* @param {string} text - 要打印的文本内容
|
|
40
|
+
* @param {string} color - 文本颜色,可选值: red, green, yellow, blue, purple, cyan
|
|
17
41
|
*/
|
|
18
|
-
function printColored (text, color) {
|
|
42
|
+
export function printColored (text, color) {
|
|
19
43
|
const colorMap = {
|
|
20
|
-
red:
|
|
21
|
-
green:
|
|
22
|
-
yellow:
|
|
23
|
-
blue:
|
|
24
|
-
purple:
|
|
25
|
-
cyan:
|
|
44
|
+
red: _red,
|
|
45
|
+
green: _green,
|
|
46
|
+
yellow: _yellow,
|
|
47
|
+
blue: _blue,
|
|
48
|
+
purple: magenta,
|
|
49
|
+
cyan: _cyan
|
|
26
50
|
};
|
|
27
51
|
|
|
28
|
-
console.log(
|
|
52
|
+
console.log(bold(colorMap[color] ? colorMap[color](text) : text));
|
|
29
53
|
}
|
|
30
54
|
|
|
31
55
|
/**
|
|
32
56
|
* 验证项目名称是否符合Flutter项目命名规范
|
|
33
57
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
58
|
+
* Flutter要求项目名称必须以小写字母开头,只能包含小写字母、数字和下划线
|
|
59
|
+
* 不符合规范时返回具体错误信息,符合时返回true
|
|
60
|
+
*
|
|
61
|
+
* @param {string} name - 待验证的项目名称
|
|
62
|
+
* @returns {boolean|string} 验证结果,true表示有效,字符串表示错误信息
|
|
36
63
|
*/
|
|
37
|
-
function validateProjectName (name) {
|
|
64
|
+
export function validateProjectName (name) {
|
|
38
65
|
if (!name.match(/^[a-z][a-z0-9_]*$/)) {
|
|
39
66
|
return '错误: 项目名称必须以小写字母开头,只能包含小写字母、数字和下划线';
|
|
40
67
|
}
|
|
@@ -44,10 +71,13 @@ function validateProjectName (name) {
|
|
|
44
71
|
/**
|
|
45
72
|
* 验证包名是否符合Java包名规范
|
|
46
73
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
74
|
+
* 包名必须以小写字母开头,可包含小写字母、数字、下划线和点号,点号用于分隔层级
|
|
75
|
+
* 不符合规范时返回具体错误信息,符合时返回true
|
|
76
|
+
*
|
|
77
|
+
* @param {string} name - 待验证的包名
|
|
78
|
+
* @returns {boolean|string} 验证结果,true表示有效,字符串表示错误信息
|
|
49
79
|
*/
|
|
50
|
-
function validatePackageName (name) {
|
|
80
|
+
export function validatePackageName (name) {
|
|
51
81
|
if (!name.match(/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$/)) {
|
|
52
82
|
return '错误: 包名必须符合Java包名规范,如com.example.myapp';
|
|
53
83
|
}
|
|
@@ -55,51 +85,76 @@ function validatePackageName (name) {
|
|
|
55
85
|
}
|
|
56
86
|
|
|
57
87
|
/**
|
|
58
|
-
*
|
|
88
|
+
* 生成并更新项目的README.md文件
|
|
89
|
+
*
|
|
90
|
+
* 创建包含项目基本信息和快速开始指南的README文件
|
|
91
|
+
* 包含项目名称、创建日期、包名和基本命令说明
|
|
59
92
|
*
|
|
60
|
-
* @param {string} targetDir -
|
|
93
|
+
* @param {string} targetDir - 项目根目录路径
|
|
61
94
|
* @param {string} projectName - 项目名称
|
|
62
|
-
|
|
95
|
+
* @param {string} packageName - 项目包名
|
|
63
96
|
*/
|
|
64
|
-
function updateReadme (targetDir, projectName) {
|
|
97
|
+
export function updateReadme (targetDir, projectName, packageName) {
|
|
65
98
|
const currentDate = new Date().toISOString().split('T')[0];
|
|
66
|
-
const readmePath =
|
|
99
|
+
const readmePath = join(targetDir, 'README.md');
|
|
67
100
|
|
|
68
|
-
const readmeContent = `#
|
|
101
|
+
const readmeContent = `# ${projectName}
|
|
69
102
|
|
|
70
|
-
基于火之夜工作室 Flutter
|
|
103
|
+
基于火之夜工作室 Flutter 通用项目框架创建的应用
|
|
71
104
|
|
|
72
105
|
## 项目信息
|
|
73
106
|
|
|
74
107
|
- 项目名称: ${projectName}
|
|
108
|
+
- 包名: ${packageName}
|
|
75
109
|
- 创建日期: ${currentDate}
|
|
76
110
|
|
|
111
|
+
## 项目结构
|
|
112
|
+
|
|
113
|
+
- lib/: 主要代码目录
|
|
114
|
+
- assets/: 静态资源目录
|
|
115
|
+
- pubspec.yaml: 项目依赖配置
|
|
116
|
+
|
|
77
117
|
## 快速开始
|
|
78
118
|
|
|
79
119
|
\`\`\`bash
|
|
80
120
|
# 安装依赖
|
|
81
121
|
flutter pub get
|
|
82
122
|
|
|
83
|
-
# 运行项目
|
|
123
|
+
# 运行项目 (默认调试模式)
|
|
84
124
|
flutter run
|
|
125
|
+
|
|
126
|
+
# 构建发布版本
|
|
127
|
+
flutter build appbundle
|
|
85
128
|
\`\`\`
|
|
129
|
+
|
|
130
|
+
## 功能特性
|
|
131
|
+
|
|
132
|
+
- 完整的项目结构
|
|
133
|
+
- 路由管理
|
|
134
|
+
- 主题管理
|
|
135
|
+
- 状态管理
|
|
136
|
+
- 网络请求封装
|
|
137
|
+
- 本地存储
|
|
86
138
|
`;
|
|
87
139
|
|
|
88
|
-
|
|
140
|
+
writeFileSync(readmePath, readmeContent, 'utf8');
|
|
89
141
|
}
|
|
90
142
|
|
|
91
143
|
/**
|
|
92
|
-
*
|
|
144
|
+
* 在指定IDE中自动打开项目
|
|
145
|
+
*
|
|
146
|
+
* 根据用户选择的IDE类型和当前操作系统,执行相应的命令打开项目
|
|
147
|
+
* 支持VS Code、Android Studio、文件管理器或手动打开
|
|
93
148
|
*
|
|
94
|
-
* @param {string} targetDir -
|
|
95
|
-
* @param {string} ideType - IDE
|
|
149
|
+
* @param {string} targetDir - 项目根目录绝对路径
|
|
150
|
+
* @param {string} [ideType="vscode"] - IDE类型,可选值: vscode, android_studio, open_folder, manual
|
|
96
151
|
*/
|
|
97
|
-
function openProjectInIde (targetDir, ideType = "vscode") {
|
|
152
|
+
export function openProjectInIde (targetDir, ideType = "vscode") {
|
|
98
153
|
const platform = process.platform;
|
|
99
154
|
let command = null;
|
|
100
155
|
|
|
101
156
|
// 确保路径是绝对路径
|
|
102
|
-
targetDir =
|
|
157
|
+
targetDir = resolve(targetDir);
|
|
103
158
|
|
|
104
159
|
switch (ideType) {
|
|
105
160
|
case 'vscode':
|
|
@@ -111,7 +166,7 @@ function openProjectInIde (targetDir, ideType = "vscode") {
|
|
|
111
166
|
} else if (platform === 'win32') { // Windows
|
|
112
167
|
// 在Windows上查找Android Studio路径会比较复杂
|
|
113
168
|
// 这里简化处理,实际应用中可能需要更复杂的逻辑
|
|
114
|
-
command =
|
|
169
|
+
command = '"C:\\Program Files\\Android\\Android Studio\\bin\\studio64.exe" "${targetDir}"';
|
|
115
170
|
} else if (platform === 'linux') { // Linux
|
|
116
171
|
command = `studio "${targetDir}"`;
|
|
117
172
|
}
|
|
@@ -143,10 +198,3 @@ function openProjectInIde (targetDir, ideType = "vscode") {
|
|
|
143
198
|
}
|
|
144
199
|
}
|
|
145
200
|
|
|
146
|
-
module.exports = {
|
|
147
|
-
printColored,
|
|
148
|
-
validateProjectName,
|
|
149
|
-
validatePackageName,
|
|
150
|
-
updateReadme,
|
|
151
|
-
openProjectInIde
|
|
152
|
-
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flu-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "火之夜工作室 Flutter 项目创建工具",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"bin": {
|
|
7
8
|
"flu-cli": "./index.js"
|
|
8
9
|
},
|
|
@@ -20,11 +21,13 @@
|
|
|
20
21
|
"license": "MIT",
|
|
21
22
|
"dependencies": {
|
|
22
23
|
"chalk": "^4.1.2",
|
|
23
|
-
"cli-progress": "^3.12.0",
|
|
24
24
|
"commander": "^11.1.0",
|
|
25
25
|
"fs-extra": "^11.2.0",
|
|
26
26
|
"inquirer": "^8.2.6",
|
|
27
27
|
"ora": "^5.4.1",
|
|
28
28
|
"path": "^0.12.7"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/fs-extra": "^11.0.4"
|
|
29
32
|
}
|
|
30
33
|
}
|
package/publish.sh
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
# 检查是否有未提交的更改
|
|
5
|
+
if [[ -n $(git status -s) ]]; then
|
|
6
|
+
echo "Error: There are uncommitted changes. Please commit or stash them first."
|
|
7
|
+
exit 1
|
|
8
|
+
fi
|
|
9
|
+
|
|
10
|
+
# 更新版本号 (patch版本,如需其他类型可改为minor或major)
|
|
11
|
+
npm version patch --no-git-tag-version -m "chore: bump version to %s"
|
|
12
|
+
|
|
13
|
+
# 获取版本号并创建git tag
|
|
14
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
15
|
+
git tag -a "v$VERSION" -m "Release v$VERSION"
|
|
16
|
+
|
|
17
|
+
# 获取当前分支名
|
|
18
|
+
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
|
|
19
|
+
if [[ -z "$BRANCH_NAME" ]]; then
|
|
20
|
+
echo "Error: Unable to determine current branch."
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# 推送提交和标签到当前分支对应的远程分支
|
|
25
|
+
# 使用双引号防止通配符扩展和单词分割
|
|
26
|
+
git push origin "$BRANCH_NAME" --tags
|
|
27
|
+
|
|
28
|
+
# 发布到npm
|
|
29
|
+
npm publish
|
package/lib/desktopPath.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 桌面路径获取模块
|
|
3
|
-
*
|
|
4
|
-
* 用于获取不同操作系统下的桌面路径
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const os = require('os');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const fs = require('fs-extra');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 获取用户桌面路径,支持多操作系统
|
|
13
|
-
*
|
|
14
|
-
* @returns {Promise<string>} 桌面路径
|
|
15
|
-
*/
|
|
16
|
-
async function getDesktopPath () {
|
|
17
|
-
const platform = process.platform;
|
|
18
|
-
let desktopPath = '';
|
|
19
|
-
|
|
20
|
-
if (platform === 'darwin') { // macOS
|
|
21
|
-
desktopPath = path.join(os.homedir(), 'Desktop');
|
|
22
|
-
} else if (platform === 'win32') { // Windows
|
|
23
|
-
try {
|
|
24
|
-
// 尝试从环境变量获取桌面路径
|
|
25
|
-
const userProfile = process.env.USERPROFILE || os.homedir();
|
|
26
|
-
desktopPath = path.join(userProfile, 'Desktop');
|
|
27
|
-
|
|
28
|
-
// 如果路径不存在,尝试其他可能的位置
|
|
29
|
-
if (!fs.existsSync(desktopPath)) {
|
|
30
|
-
desktopPath = path.join(os.homedir(), 'Desktop');
|
|
31
|
-
}
|
|
32
|
-
} catch (error) {
|
|
33
|
-
// 如果获取失败,使用默认路径
|
|
34
|
-
desktopPath = path.join(os.homedir(), 'Desktop');
|
|
35
|
-
}
|
|
36
|
-
} else if (platform === 'linux') { // Linux
|
|
37
|
-
// 首先尝试从环境变量获取
|
|
38
|
-
desktopPath = process.env.XDG_DESKTOP_DIR;
|
|
39
|
-
|
|
40
|
-
if (!desktopPath || !fs.existsSync(desktopPath)) {
|
|
41
|
-
// 尝试获取XDG_DESKTOP_DIR环境变量
|
|
42
|
-
const xdgConfig = path.join(os.homedir(), '.config/user-dirs.dirs');
|
|
43
|
-
|
|
44
|
-
if (fs.existsSync(xdgConfig)) {
|
|
45
|
-
try {
|
|
46
|
-
const content = fs.readFileSync(xdgConfig, 'utf8');
|
|
47
|
-
const lines = content.split('\n');
|
|
48
|
-
|
|
49
|
-
for (const line of lines) {
|
|
50
|
-
if (line.startsWith('XDG_DESKTOP_DIR=')) {
|
|
51
|
-
// 提取路径并处理引号和$HOME
|
|
52
|
-
let extractedPath = line.split('=')[1].trim().replace(/"/g, '');
|
|
53
|
-
extractedPath = extractedPath.replace('$HOME', os.homedir());
|
|
54
|
-
|
|
55
|
-
if (fs.existsSync(extractedPath)) {
|
|
56
|
-
desktopPath = extractedPath;
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
} catch (error) {
|
|
62
|
-
// 如果读取配置文件失败,使用默认路径
|
|
63
|
-
desktopPath = path.join(os.homedir(), 'Desktop');
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// 如果仍然没有找到,使用默认路径
|
|
68
|
-
if (!desktopPath || !fs.existsSync(desktopPath)) {
|
|
69
|
-
desktopPath = path.join(os.homedir(), 'Desktop');
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
} else {
|
|
73
|
-
// 其他操作系统,使用默认路径
|
|
74
|
-
desktopPath = path.join(os.homedir(), 'Desktop');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// 确保路径存在,如果不存在则使用用户主目录
|
|
78
|
-
if (!fs.existsSync(desktopPath)) {
|
|
79
|
-
desktopPath = os.homedir();
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return desktopPath;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
module.exports = { getDesktopPath };
|