create-unibest 3.3.0 → 4.0.0
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 +60 -44
- package/bin/index.js +0 -1
- package/dist/index.js +594 -121
- package/package.json +9 -10
- package/dist/index.d.ts +0 -1
package/README.md
CHANGED
|
@@ -1,63 +1,79 @@
|
|
|
1
|
-
|
|
1
|
+
# create-unibest
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
<a href="https://www.npmjs.com/package/create-unibest"><img src="https://img.shields.io/npm/dm/create-unibest?colorA=363a4f&colorB=f5a97f&style=for-the-badge"></a>
|
|
5
|
-
<a href="https://www.npmjs.com/package/create-unibest"><img src="https://img.shields.io/npm/v/create-unibest?colorA=363a4f&colorB=a6da95&style=for-the-badge"></a>
|
|
6
|
-
</p>
|
|
3
|
+
跨平台 uniapp 项目脚手架工具。
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
<sub>>_ Easy to use create unibest</sub>
|
|
10
|
-
</h2>
|
|
5
|
+
## 功能特性
|
|
11
6
|
|
|
12
|
-
|
|
7
|
+
- 🚀 **快速创建** - 通过命令行快速生成 unibest 项目
|
|
8
|
+
- 🎯 **灵活配置** - 支持选择平台、UI库、Feature
|
|
9
|
+
- 🔧 **Feature 注入** - 创建后可动态添加 i18n、login 等功能
|
|
10
|
+
- 📦 **多平台支持** - H5、小程序、App 一键生成
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
## 使用方式
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
### 安装
|
|
17
15
|
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
pnpm create unibest -v # 查看版本信息
|
|
22
|
-
pnpm create unibest -h # 查看帮助信息
|
|
23
|
-
```
|
|
16
|
+
```bash
|
|
17
|
+
# 全局安装(可选)
|
|
18
|
+
npm i -g create-unibest
|
|
24
19
|
|
|
25
|
-
|
|
20
|
+
# 或直接使用
|
|
21
|
+
pnpm create unibest
|
|
22
|
+
```
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
### 创建项目
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
```bash
|
|
27
|
+
# 交互式创建
|
|
28
|
+
pnpm create unibest my-project
|
|
29
|
+
|
|
30
|
+
# 命令行参数创建
|
|
31
|
+
pnpm create unibest my-project \
|
|
32
|
+
--platform h5,mp-weixin \
|
|
33
|
+
--ui none \
|
|
34
|
+
--i18n \
|
|
35
|
+
--login
|
|
36
|
+
```
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
### 添加 Feature
|
|
37
39
|
|
|
38
40
|
```bash
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
cd my-project
|
|
42
|
+
|
|
43
|
+
# 添加多语言
|
|
44
|
+
pnpm create unibest add i18n
|
|
41
45
|
|
|
42
|
-
#
|
|
43
|
-
pnpm create unibest
|
|
46
|
+
# 添加登录策略
|
|
47
|
+
pnpm create unibest add login
|
|
44
48
|
|
|
45
|
-
#
|
|
46
|
-
pnpm create unibest
|
|
49
|
+
# 强制重新注入(覆盖已有配置)
|
|
50
|
+
pnpm create unibest add i18n --force
|
|
47
51
|
```
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
## 参数说明
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
npm i -g create-unibest # 全局安装,得到 best 命令
|
|
53
|
-
npm update -g create-unibest # 更新 create-unibest 包
|
|
54
|
-
```
|
|
55
|
+
### 创建项目参数
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
| 参数 | 说明 |
|
|
58
|
+
|------|------|
|
|
59
|
+
| `-p, --platform` | 平台类型,支持 `h5`, `mp-weixin`, `app`, `mp-alipay`, `mp-toutiao` |
|
|
60
|
+
| `-u, --ui` | UI 库,支持 `none`, `wot-ui`, `uview-pro`, `sard-uniapp`, `uv-ui`, `uview-plus` |
|
|
61
|
+
| `-l, --login` | 启用登录策略 |
|
|
62
|
+
| `-i, --i18n` | 启用多语言 |
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
### 添加 Feature 参数
|
|
65
|
+
|
|
66
|
+
| 参数 | 说明 |
|
|
67
|
+
|------|------|
|
|
68
|
+
| `--path` | 项目路径,默认当前目录 |
|
|
69
|
+
| `--force` | 强制重新注入 Feature |
|
|
70
|
+
|
|
71
|
+
## 与 unibest 模板版本对应关系
|
|
72
|
+
|
|
73
|
+
| create-unibest 版本 | unibest 模板版本 |
|
|
74
|
+
|---------------------|------------------|
|
|
75
|
+
| 4.0.0 | 4.3.0+ |
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
package/bin/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,11 +1,254 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import
|
|
4
|
+
import process6 from "process";
|
|
5
|
+
import { green as green6, yellow as yellow5 } from "kolorist";
|
|
5
6
|
import minimist from "minimist";
|
|
6
7
|
|
|
7
|
-
//
|
|
8
|
-
|
|
8
|
+
// package.json
|
|
9
|
+
var version = "4.0.0";
|
|
10
|
+
var package_default = {
|
|
11
|
+
name: "create-unibest",
|
|
12
|
+
type: "module",
|
|
13
|
+
version,
|
|
14
|
+
packageManager: "pnpm@10.10.0",
|
|
15
|
+
description: "\u5FEB\u901F\u521B\u5EFA unibest \u9879\u76EE\u7684\u811A\u624B\u67B6\u5DE5\u5177",
|
|
16
|
+
author: "feige996",
|
|
17
|
+
license: "MIT",
|
|
18
|
+
homepage: "https://unibest.tech",
|
|
19
|
+
bin: {
|
|
20
|
+
best: "bin/index.js",
|
|
21
|
+
"create-unibest": "bin/index.js",
|
|
22
|
+
unibest: "bin/index.js"
|
|
23
|
+
},
|
|
24
|
+
files: [
|
|
25
|
+
"bin",
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
scripts: {
|
|
29
|
+
dev: "cross-env NODE_ENV=development tsup --watch",
|
|
30
|
+
build: "cross-env NODE_ENV=production tsup",
|
|
31
|
+
prepare: "pnpm build",
|
|
32
|
+
start: "cross-env NODE_ENV=development node bin/index.js"
|
|
33
|
+
},
|
|
34
|
+
dependencies: {
|
|
35
|
+
"@clack/prompts": "^0.11.0",
|
|
36
|
+
dayjs: "^1.11.18",
|
|
37
|
+
ejs: "^3.1.10",
|
|
38
|
+
"fs-extra": "^11.3.0",
|
|
39
|
+
kolorist: "^1.8.0",
|
|
40
|
+
minimist: "^1.2.8",
|
|
41
|
+
"node-fetch": "^3.3.2"
|
|
42
|
+
},
|
|
43
|
+
devDependencies: {
|
|
44
|
+
"@types/ejs": "^3.1.5",
|
|
45
|
+
"@types/fs-extra": "^11.0.4",
|
|
46
|
+
"@types/minimist": "^1.2.5",
|
|
47
|
+
"@types/node": "^24.5.0",
|
|
48
|
+
"cross-env": "^7.0.3",
|
|
49
|
+
tsup: "^8.5.0",
|
|
50
|
+
typescript: "^5.9.0"
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// src/commands/add.ts
|
|
55
|
+
import fs4 from "fs";
|
|
56
|
+
import path3 from "path";
|
|
57
|
+
import process2 from "process";
|
|
58
|
+
import { cancel, intro, isCancel, log, multiselect } from "@clack/prompts";
|
|
59
|
+
import { bold as bold2, green as green2 } from "kolorist";
|
|
60
|
+
|
|
61
|
+
// src/features/interface.ts
|
|
62
|
+
var AVAILABLE_FEATURES = [
|
|
63
|
+
{
|
|
64
|
+
name: "i18n",
|
|
65
|
+
description: "\u591A\u8BED\u8A00\u652F\u6301",
|
|
66
|
+
dependencies: {
|
|
67
|
+
"vue-i18n": "^9.0.0",
|
|
68
|
+
"dayjs": "^1.11.0"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "login",
|
|
73
|
+
description: "\u767B\u5F55\u7B56\u7565\uFF08\u9ED1\u767D\u540D\u5355\u3001\u767B\u5F55\u62E6\u622A\u7B49\uFF09",
|
|
74
|
+
dependencies: {}
|
|
75
|
+
}
|
|
76
|
+
];
|
|
77
|
+
function getFeatureByName(name) {
|
|
78
|
+
return AVAILABLE_FEATURES.find((f) => f.name === name);
|
|
79
|
+
}
|
|
80
|
+
function getSelectedFeatures(options) {
|
|
81
|
+
const features = [];
|
|
82
|
+
if (options.i18n) {
|
|
83
|
+
const feature = getFeatureByName("i18n");
|
|
84
|
+
if (feature) features.push(feature);
|
|
85
|
+
}
|
|
86
|
+
if (options.loginStrategy) {
|
|
87
|
+
const feature = getFeatureByName("login");
|
|
88
|
+
if (feature) features.push(feature);
|
|
89
|
+
}
|
|
90
|
+
return features;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/features/loader.ts
|
|
94
|
+
import fs from "fs";
|
|
95
|
+
import path from "path";
|
|
96
|
+
var FEATURES_DIR = path.resolve(process.cwd(), "../../features");
|
|
97
|
+
async function loadFeatureHooks(featureName) {
|
|
98
|
+
const hooksPath = path.join(FEATURES_DIR, featureName, "hooks.ts");
|
|
99
|
+
if (!fs.existsSync(hooksPath)) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const module = await import(hooksPath);
|
|
103
|
+
return module;
|
|
104
|
+
}
|
|
105
|
+
function getAvailableFeatureNames() {
|
|
106
|
+
if (!fs.existsSync(FEATURES_DIR)) {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
const entries = fs.readdirSync(FEATURES_DIR, { withFileTypes: true });
|
|
110
|
+
return entries.filter((e) => e.isDirectory() && fs.existsSync(path.join(FEATURES_DIR, e.name, "files"))).map((e) => e.name);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/utils/injector.ts
|
|
114
|
+
import fs2 from "fs";
|
|
115
|
+
import path2 from "path";
|
|
116
|
+
import { dirname } from "path";
|
|
117
|
+
import { fileURLToPath } from "url";
|
|
118
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
119
|
+
var __dirname = dirname(__filename);
|
|
120
|
+
var FEATURES_PATH = path2.join(__dirname, "..", "..", "..", "features");
|
|
121
|
+
var FeatureInjector = class {
|
|
122
|
+
constructor(projectPath) {
|
|
123
|
+
this.projectPath = projectPath;
|
|
124
|
+
}
|
|
125
|
+
injectFile(targetPath, featureCode, placeholder) {
|
|
126
|
+
const fullPath = path2.join(this.projectPath, targetPath);
|
|
127
|
+
if (!fs2.existsSync(fullPath)) {
|
|
128
|
+
return { success: false, message: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${targetPath}` };
|
|
129
|
+
}
|
|
130
|
+
const content = fs2.readFileSync(fullPath, "utf-8");
|
|
131
|
+
if (!content.includes(placeholder)) {
|
|
132
|
+
return { success: false, message: `\u5360\u4F4D\u7B26\u4E0D\u5B58\u5728: ${placeholder}` };
|
|
133
|
+
}
|
|
134
|
+
const newContent = content.replace(placeholder, featureCode);
|
|
135
|
+
fs2.writeFileSync(fullPath, newContent);
|
|
136
|
+
return { success: true, message: `\u6CE8\u5165\u6210\u529F: ${targetPath}` };
|
|
137
|
+
}
|
|
138
|
+
replaceFile(targetPath, featureFilePath) {
|
|
139
|
+
const targetFullPath = path2.join(this.projectPath, targetPath);
|
|
140
|
+
const featureFullPath = path2.join(FEATURES_PATH, featureFilePath);
|
|
141
|
+
if (!fs2.existsSync(featureFullPath)) {
|
|
142
|
+
return { success: false, message: `Feature \u6587\u4EF6\u4E0D\u5B58\u5728: ${featureFilePath}` };
|
|
143
|
+
}
|
|
144
|
+
const featureContent = fs2.readFileSync(featureFullPath, "utf-8");
|
|
145
|
+
fs2.writeFileSync(targetFullPath, featureContent);
|
|
146
|
+
return { success: true, message: `\u66FF\u6362\u6210\u529F: ${targetPath}` };
|
|
147
|
+
}
|
|
148
|
+
createFile(relativePath, featureFilePath) {
|
|
149
|
+
const targetFullPath = path2.join(this.projectPath, relativePath);
|
|
150
|
+
const featureFullPath = path2.join(FEATURES_PATH, featureFilePath);
|
|
151
|
+
if (!fs2.existsSync(featureFullPath)) {
|
|
152
|
+
return { success: false, message: `Feature \u6587\u4EF6\u4E0D\u5B58\u5728: ${featureFilePath}` };
|
|
153
|
+
}
|
|
154
|
+
const dir = path2.dirname(targetFullPath);
|
|
155
|
+
if (!fs2.existsSync(dir)) {
|
|
156
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
157
|
+
}
|
|
158
|
+
const featureContent = fs2.readFileSync(featureFullPath, "utf-8");
|
|
159
|
+
fs2.writeFileSync(targetFullPath, featureContent);
|
|
160
|
+
return { success: true, message: `\u521B\u5EFA\u6210\u529F: ${relativePath}` };
|
|
161
|
+
}
|
|
162
|
+
appendAfter(targetPath, marker, code) {
|
|
163
|
+
const fullPath = path2.join(this.projectPath, targetPath);
|
|
164
|
+
if (!fs2.existsSync(fullPath)) {
|
|
165
|
+
return { success: false, message: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${targetPath}` };
|
|
166
|
+
}
|
|
167
|
+
const content = fs2.readFileSync(fullPath, "utf-8");
|
|
168
|
+
if (!content.includes(marker)) {
|
|
169
|
+
return { success: false, message: `\u6807\u8BB0\u4E0D\u5B58\u5728: ${marker}` };
|
|
170
|
+
}
|
|
171
|
+
const newContent = content.replace(marker, `${marker}
|
|
172
|
+
${code}`);
|
|
173
|
+
fs2.writeFileSync(fullPath, newContent);
|
|
174
|
+
return { success: true, message: `\u8FFD\u52A0\u6210\u529F: ${targetPath}` };
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
async function injectI18n(projectPath) {
|
|
178
|
+
const results = [];
|
|
179
|
+
const injector = new FeatureInjector(projectPath);
|
|
180
|
+
results.push(injector.appendAfter(
|
|
181
|
+
"src/main.ts",
|
|
182
|
+
`import 'virtual:uno.css'`,
|
|
183
|
+
`import i18n from './locale/index'`
|
|
184
|
+
));
|
|
185
|
+
results.push(injector.appendAfter(
|
|
186
|
+
"src/main.ts",
|
|
187
|
+
` app.use(requestInterceptor)`,
|
|
188
|
+
` app.use(i18n)`
|
|
189
|
+
));
|
|
190
|
+
results.push(injector.replaceFile(
|
|
191
|
+
"src/tabbar/config.ts",
|
|
192
|
+
"i18n/files/src/tabbar/config.ts"
|
|
193
|
+
));
|
|
194
|
+
results.push(injector.replaceFile(
|
|
195
|
+
"src/tabbar/index.vue",
|
|
196
|
+
"i18n/files/src/tabbar/index.vue"
|
|
197
|
+
));
|
|
198
|
+
results.push(injector.replaceFile(
|
|
199
|
+
"src/tabbar/TabbarItem.vue",
|
|
200
|
+
"i18n/files/src/tabbar/TabbarItem.vue"
|
|
201
|
+
));
|
|
202
|
+
results.push(injector.replaceFile(
|
|
203
|
+
"src/utils/index.ts",
|
|
204
|
+
"i18n/files/src/utils/index.ts"
|
|
205
|
+
));
|
|
206
|
+
results.push(injector.replaceFile(
|
|
207
|
+
"src/store/token.ts",
|
|
208
|
+
"i18n/files/src/store/token.ts"
|
|
209
|
+
));
|
|
210
|
+
const i18nFiles = [
|
|
211
|
+
"src/locale/index.ts",
|
|
212
|
+
"src/locale/en.json",
|
|
213
|
+
"src/locale/zh-Hans.json",
|
|
214
|
+
"src/locale/README.md",
|
|
215
|
+
"src/utils/i18n.ts",
|
|
216
|
+
"src/types/i18n.d.ts",
|
|
217
|
+
"src/tabbar/i18n.ts",
|
|
218
|
+
"src/pages/i18n/index.vue"
|
|
219
|
+
];
|
|
220
|
+
for (const file of i18nFiles) {
|
|
221
|
+
const featurePath = `i18n/files/${file}`;
|
|
222
|
+
results.push(injector.createFile(file, featurePath));
|
|
223
|
+
}
|
|
224
|
+
return results;
|
|
225
|
+
}
|
|
226
|
+
async function injectLogin(projectPath) {
|
|
227
|
+
const results = [];
|
|
228
|
+
const injector = new FeatureInjector(projectPath);
|
|
229
|
+
results.push(injector.replaceFile(
|
|
230
|
+
"src/router/interceptor.ts",
|
|
231
|
+
"login/files/src/router/interceptor.ts"
|
|
232
|
+
));
|
|
233
|
+
results.push(injector.replaceFile(
|
|
234
|
+
"src/router/config.ts",
|
|
235
|
+
"login/files/src/router/config.ts"
|
|
236
|
+
));
|
|
237
|
+
results.push(injector.replaceFile(
|
|
238
|
+
"src/pages/me/me.vue",
|
|
239
|
+
"login/files/src/pages/me.vue"
|
|
240
|
+
));
|
|
241
|
+
const loginFiles = [
|
|
242
|
+
"src/pages/auth/login.vue",
|
|
243
|
+
"src/pages/auth/register.vue",
|
|
244
|
+
"src/pages/auth/README.md"
|
|
245
|
+
];
|
|
246
|
+
for (const file of loginFiles) {
|
|
247
|
+
const featurePath = `login/files/${file}`;
|
|
248
|
+
results.push(injector.createFile(file, featurePath));
|
|
249
|
+
}
|
|
250
|
+
return results;
|
|
251
|
+
}
|
|
9
252
|
|
|
10
253
|
// src/utils/logger.ts
|
|
11
254
|
import { bold, green, red, yellow, cyan } from "kolorist";
|
|
@@ -32,6 +275,178 @@ var logger = {
|
|
|
32
275
|
}
|
|
33
276
|
};
|
|
34
277
|
|
|
278
|
+
// src/utils/readPackageJson.ts
|
|
279
|
+
import fs3 from "fs";
|
|
280
|
+
function readPackageJson(pkgPath) {
|
|
281
|
+
if (!fs3.existsSync(pkgPath)) {
|
|
282
|
+
throw new Error(`package.json not found: ${pkgPath}`);
|
|
283
|
+
}
|
|
284
|
+
const content = fs3.readFileSync(pkgPath, "utf-8");
|
|
285
|
+
return JSON.parse(content);
|
|
286
|
+
}
|
|
287
|
+
function writePackageJson(pkgPath, pkg) {
|
|
288
|
+
fs3.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
289
|
+
`);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// src/commands/add.ts
|
|
293
|
+
function getFeatureStatusFromPackageJson(pkgPath) {
|
|
294
|
+
try {
|
|
295
|
+
const pkg = readPackageJson(pkgPath);
|
|
296
|
+
return {
|
|
297
|
+
i18n: pkg.unibest?.i18n === true,
|
|
298
|
+
login: pkg.unibest?.loginStrategy === true
|
|
299
|
+
};
|
|
300
|
+
} catch {
|
|
301
|
+
return { i18n: false, login: false };
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function updatePackageJsonForFeature(pkgPath, featureName) {
|
|
305
|
+
const pkg = readPackageJson(pkgPath);
|
|
306
|
+
if (!pkg.unibest) {
|
|
307
|
+
pkg.unibest = {};
|
|
308
|
+
}
|
|
309
|
+
switch (featureName) {
|
|
310
|
+
case "i18n":
|
|
311
|
+
pkg.unibest.i18n = true;
|
|
312
|
+
break;
|
|
313
|
+
case "login":
|
|
314
|
+
pkg.unibest.loginStrategy = true;
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
writePackageJson(pkgPath, pkg);
|
|
318
|
+
}
|
|
319
|
+
async function checkFeatureStatus(projectPath) {
|
|
320
|
+
const pkgPath = path3.join(projectPath, "package.json");
|
|
321
|
+
const statusFromPkg = getFeatureStatusFromPackageJson(pkgPath);
|
|
322
|
+
return [
|
|
323
|
+
{ name: "i18n", enabled: statusFromPkg.i18n },
|
|
324
|
+
{ name: "login", enabled: statusFromPkg.login }
|
|
325
|
+
];
|
|
326
|
+
}
|
|
327
|
+
async function addFeature(featureName, projectPath, options = {}) {
|
|
328
|
+
const feature = getFeatureByName(featureName);
|
|
329
|
+
if (!feature) {
|
|
330
|
+
logger.error(`\u672A\u77E5\u7684 Feature: ${featureName}`);
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
const pkgPath = path3.join(projectPath, "package.json");
|
|
334
|
+
const pkg = readPackageJson(pkgPath);
|
|
335
|
+
let alreadyAdded = false;
|
|
336
|
+
if (featureName === "i18n" && pkg.unibest?.i18n === true) {
|
|
337
|
+
alreadyAdded = true;
|
|
338
|
+
} else if (featureName === "login" && pkg.unibest?.loginStrategy === true) {
|
|
339
|
+
alreadyAdded = true;
|
|
340
|
+
}
|
|
341
|
+
if (alreadyAdded && !options.force) {
|
|
342
|
+
logger.warn(`Feature ${featureName} \u5DF2\u6DFB\u52A0\u8FC7\uFF0C\u5982\u9700\u91CD\u65B0\u6CE8\u5165\u8BF7\u4F7F\u7528 --force \u53C2\u6570`);
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
log.info(`\u6B63\u5728\u6DFB\u52A0 Feature: ${green2(featureName)} - ${feature.description}`);
|
|
346
|
+
try {
|
|
347
|
+
let results;
|
|
348
|
+
switch (featureName) {
|
|
349
|
+
case "i18n":
|
|
350
|
+
results = await injectI18n(projectPath);
|
|
351
|
+
break;
|
|
352
|
+
case "login":
|
|
353
|
+
results = await injectLogin(projectPath);
|
|
354
|
+
break;
|
|
355
|
+
default:
|
|
356
|
+
logger.error(`\u4E0D\u652F\u6301\u7684 Feature: ${featureName}`);
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
for (const result of results) {
|
|
360
|
+
if (result.success) {
|
|
361
|
+
logger.success(result.message);
|
|
362
|
+
} else {
|
|
363
|
+
logger.warn(result.message);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const hooks = await loadFeatureHooks(featureName);
|
|
367
|
+
if (hooks?.postApply) {
|
|
368
|
+
await hooks.postApply({
|
|
369
|
+
options: { projectName: "", platforms: [], uiLibrary: "none", i18n: true, loginStrategy: true },
|
|
370
|
+
projectPath,
|
|
371
|
+
featureName
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
updatePackageJsonForFeature(pkgPath, featureName);
|
|
375
|
+
logger.success(`\u5DF2\u66F4\u65B0 package.json \u7684 unibest \u914D\u7F6E`);
|
|
376
|
+
if (feature.dependencies && Object.keys(feature.dependencies).length > 0) {
|
|
377
|
+
logger.info(`\u5B89\u88C5\u4F9D\u8D56: ${Object.keys(feature.dependencies).join(", ")}`);
|
|
378
|
+
}
|
|
379
|
+
logger.success(`Feature ${featureName} \u6DFB\u52A0\u6210\u529F\uFF01`);
|
|
380
|
+
return true;
|
|
381
|
+
} catch (error) {
|
|
382
|
+
logger.error(`\u6DFB\u52A0 Feature \u5931\u8D25: ${error.message}`);
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
async function addCommand(args) {
|
|
387
|
+
const options = {
|
|
388
|
+
path: args.path || args.p || ".",
|
|
389
|
+
feature: args._[1] || args.feature || args.f,
|
|
390
|
+
force: args.force || args.f
|
|
391
|
+
};
|
|
392
|
+
intro(bold2(green2(`create-unibest@v${version} \u6DFB\u52A0 Feature`)));
|
|
393
|
+
const projectPath = path3.isAbsolute(options.path) ? options.path : path3.join(process2.cwd(), options.path);
|
|
394
|
+
const pkgPath = path3.join(projectPath, "package.json");
|
|
395
|
+
if (!fs4.existsSync(pkgPath)) {
|
|
396
|
+
logger.error(`\u9879\u76EE\u4E0D\u5B58\u5728: ${projectPath}`);
|
|
397
|
+
process2.exit(1);
|
|
398
|
+
}
|
|
399
|
+
const pkg = readPackageJson(pkgPath);
|
|
400
|
+
if (pkg.name !== "unibest") {
|
|
401
|
+
logger.warn(`\u5F53\u524D\u9879\u76EE\u53EF\u80FD\u4E0D\u662F unibest \u9879\u76EE: ${pkg.name}`);
|
|
402
|
+
}
|
|
403
|
+
const availableFeatures = getAvailableFeatureNames();
|
|
404
|
+
try {
|
|
405
|
+
if (!options.feature) {
|
|
406
|
+
const detected = await checkFeatureStatus(projectPath);
|
|
407
|
+
const available = availableFeatures.filter((f) => !detected.find((d) => d.name === f && d.enabled));
|
|
408
|
+
if (available.length === 0) {
|
|
409
|
+
logger.info("\u6240\u6709\u53EF\u7528 Feature \u5DF2\u542F\u7528");
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
const selectedFeatures = await multiselect({
|
|
413
|
+
message: `\u8BF7\u9009\u62E9\u8981\u6DFB\u52A0\u7684 Feature`,
|
|
414
|
+
options: available.map((name) => {
|
|
415
|
+
const feature = getFeatureByName(name);
|
|
416
|
+
return {
|
|
417
|
+
value: name,
|
|
418
|
+
label: feature?.name || name,
|
|
419
|
+
hint: feature?.description || ""
|
|
420
|
+
};
|
|
421
|
+
}),
|
|
422
|
+
required: false
|
|
423
|
+
});
|
|
424
|
+
if (isCancel(selectedFeatures)) {
|
|
425
|
+
cancel("\u64CD\u4F5C\u5DF2\u53D6\u6D88");
|
|
426
|
+
process2.exit(0);
|
|
427
|
+
}
|
|
428
|
+
if (!Array.isArray(selectedFeatures) || selectedFeatures.length === 0) {
|
|
429
|
+
logger.info("\u672A\u9009\u62E9\u4EFB\u4F55 Feature");
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
for (const featureName of selectedFeatures) {
|
|
433
|
+
await addFeature(featureName, projectPath, options);
|
|
434
|
+
}
|
|
435
|
+
} else {
|
|
436
|
+
const features = Array.isArray(options.feature) ? options.feature : [options.feature];
|
|
437
|
+
for (const featureName of features) {
|
|
438
|
+
await addFeature(featureName, projectPath, options);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
} catch (error) {
|
|
442
|
+
logger.error(`\u6DFB\u52A0 Feature \u5931\u8D25: ${error.message}`);
|
|
443
|
+
process2.exit(1);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// src/commands/create/prompts.ts
|
|
448
|
+
import { text, multiselect as multiselect2, select, confirm, cancel as cancel2, isCancel as isCancel2 } from "@clack/prompts";
|
|
449
|
+
|
|
35
450
|
// src/utils/validate.ts
|
|
36
451
|
import { existsSync } from "fs";
|
|
37
452
|
import { yellow as yellow2 } from "kolorist";
|
|
@@ -58,8 +473,8 @@ function checkProjectNameExistAndValidate(_projectName) {
|
|
|
58
473
|
}
|
|
59
474
|
|
|
60
475
|
// src/commands/create/prompts.ts
|
|
61
|
-
import { green as
|
|
62
|
-
import
|
|
476
|
+
import { green as green3, red as red2 } from "kolorist";
|
|
477
|
+
import process3 from "process";
|
|
63
478
|
var VALID_PLATFORMS = ["h5", "mp-weixin", "app", "mp-alipay", "mp-toutiao"];
|
|
64
479
|
var VALID_UI_LIBRARIES = ["none", "wot-ui", "uview-pro", "sard-uniapp", "uv-ui", "uview-plus"];
|
|
65
480
|
async function promptUser(projectName, argv = {}) {
|
|
@@ -79,7 +494,7 @@ async function promptUser(projectName, argv = {}) {
|
|
|
79
494
|
if (invalidPlatforms.length > 0) {
|
|
80
495
|
console.error(red2(`\u65E0\u6548\u7684\u5E73\u53F0\u53C2\u6570: ${invalidPlatforms.join(", ")}`));
|
|
81
496
|
console.error(red2(`\u53EF\u9009\u503C: ${VALID_PLATFORMS.join(", ")}`));
|
|
82
|
-
|
|
497
|
+
process3.exit(1);
|
|
83
498
|
}
|
|
84
499
|
platforms = parsedPlatforms;
|
|
85
500
|
}
|
|
@@ -88,20 +503,26 @@ async function promptUser(projectName, argv = {}) {
|
|
|
88
503
|
if (!VALID_UI_LIBRARIES.includes(uiArg)) {
|
|
89
504
|
console.error(red2(`\u65E0\u6548\u7684UI\u5E93\u53C2\u6570: ${uiArg}`));
|
|
90
505
|
console.error(red2(`\u53EF\u9009\u503C: ${VALID_UI_LIBRARIES.join(", ")}`));
|
|
91
|
-
|
|
506
|
+
process3.exit(1);
|
|
92
507
|
}
|
|
93
508
|
uiLibrary = uiArg;
|
|
94
509
|
}
|
|
95
|
-
|
|
510
|
+
const loginArg = argv.l ?? argv.login;
|
|
511
|
+
if (loginArg === true || loginArg === "true") {
|
|
96
512
|
loginStrategy = true;
|
|
513
|
+
} else if (loginArg === false || loginArg === "false") {
|
|
514
|
+
loginStrategy = false;
|
|
97
515
|
}
|
|
98
|
-
|
|
516
|
+
const i18nArg = argv.i ?? argv.i18n;
|
|
517
|
+
if (i18nArg === true || i18nArg === "true") {
|
|
99
518
|
i18n = true;
|
|
519
|
+
} else if (i18nArg === false || i18nArg === "false") {
|
|
520
|
+
i18n = false;
|
|
100
521
|
}
|
|
101
522
|
try {
|
|
102
523
|
if (!projectName) {
|
|
103
524
|
const inputProjectName = await text({
|
|
104
|
-
message: `\u8BF7\u8F93\u5165\u9879\u76EE\u540D\u79F0${
|
|
525
|
+
message: `\u8BF7\u8F93\u5165\u9879\u76EE\u540D\u79F0${green3("[\u9879\u76EE\u540D\u79F0\u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\u548C\u77ED\u6A2A\u7EBF\uFF0C\u5343\u4E07\u522B\u5199\u4E2D\u6587]")}`,
|
|
105
526
|
initialValue: "",
|
|
106
527
|
validate: (value) => {
|
|
107
528
|
if (!value.trim()) return "\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A";
|
|
@@ -110,15 +531,15 @@ async function promptUser(projectName, argv = {}) {
|
|
|
110
531
|
return;
|
|
111
532
|
}
|
|
112
533
|
});
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
534
|
+
if (isCancel2(inputProjectName)) {
|
|
535
|
+
cancel2("\u64CD\u4F5C\u5DF2\u53D6\u6D88");
|
|
536
|
+
process3.exit(0);
|
|
116
537
|
}
|
|
117
538
|
projectName = inputProjectName;
|
|
118
539
|
}
|
|
119
540
|
if (!platforms) {
|
|
120
|
-
const selectedPlatforms = await
|
|
121
|
-
message: `\u8BF7\u9009\u62E9\u9700\u8981\u652F\u6301\u7684\u5E73\u53F0\uFF08\u591A\u9009\uFF09${
|
|
541
|
+
const selectedPlatforms = await multiselect2({
|
|
542
|
+
message: `\u8BF7\u9009\u62E9\u9700\u8981\u652F\u6301\u7684\u5E73\u53F0\uFF08\u591A\u9009\uFF09${green3("[\u811A\u624B\u67B6\u5C06\u6839\u636E\u6240\u9009\u5E73\u53F0\u751F\u6210\u5BF9\u5E94\u7684\u5E73\u53F0\u4EE3\u7801\uFF0C\u8BF7\u6839\u636E\u5B9E\u9645\u60C5\u51B5\u9009\u62E9]")}`,
|
|
122
543
|
options: [
|
|
123
544
|
{ value: "h5", label: "H5" },
|
|
124
545
|
{ value: "mp-weixin", label: "\u5FAE\u4FE1\u5C0F\u7A0B\u5E8F" },
|
|
@@ -130,9 +551,9 @@ async function promptUser(projectName, argv = {}) {
|
|
|
130
551
|
// 默认选择 H5
|
|
131
552
|
required: true
|
|
132
553
|
});
|
|
133
|
-
if (
|
|
134
|
-
|
|
135
|
-
|
|
554
|
+
if (isCancel2(selectedPlatforms)) {
|
|
555
|
+
cancel2("\u64CD\u4F5C\u5DF2\u53D6\u6D88");
|
|
556
|
+
process3.exit(0);
|
|
136
557
|
}
|
|
137
558
|
platforms = selectedPlatforms;
|
|
138
559
|
}
|
|
@@ -149,20 +570,20 @@ async function promptUser(projectName, argv = {}) {
|
|
|
149
570
|
],
|
|
150
571
|
initialValue: "none"
|
|
151
572
|
});
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
|
|
573
|
+
if (isCancel2(selectedUiLibrary)) {
|
|
574
|
+
cancel2("\u64CD\u4F5C\u5DF2\u53D6\u6D88");
|
|
575
|
+
process3.exit(0);
|
|
155
576
|
}
|
|
156
577
|
uiLibrary = selectedUiLibrary;
|
|
157
578
|
}
|
|
158
579
|
if (loginStrategy === void 0) {
|
|
159
580
|
const selectedLoginStrategy = await confirm({
|
|
160
|
-
message: `\u662F\u5426\u9700\u8981\u767B\u5F55\u7B56\u7565\uFF08\u9ED1\u767D\u540D\u5355\u3001\u767B\u5F55\u62E6\u622A\u7B49\uFF09\uFF1F${
|
|
581
|
+
message: `\u662F\u5426\u9700\u8981\u767B\u5F55\u7B56\u7565\uFF08\u9ED1\u767D\u540D\u5355\u3001\u767B\u5F55\u62E6\u622A\u7B49\uFF09\uFF1F${green3("[\u6682\u4E0D\u77E5\u9053\u7684\uFF0C\u9009No\u5373\u53EF\uFF0C\u9879\u76EE\u751F\u6210\u540E\u4E5F\u53EF\u4EE5\u52A0\u8BE5\u7B56\u7565]")}`,
|
|
161
582
|
initialValue: false
|
|
162
583
|
});
|
|
163
|
-
if (
|
|
164
|
-
|
|
165
|
-
|
|
584
|
+
if (isCancel2(selectedLoginStrategy)) {
|
|
585
|
+
cancel2("\u64CD\u4F5C\u5DF2\u53D6\u6D88");
|
|
586
|
+
process3.exit(0);
|
|
166
587
|
}
|
|
167
588
|
loginStrategy = selectedLoginStrategy;
|
|
168
589
|
}
|
|
@@ -171,9 +592,9 @@ async function promptUser(projectName, argv = {}) {
|
|
|
171
592
|
message: "\u662F\u5426\u9700\u8981\u591A\u8BED\u8A00i18n\uFF1F",
|
|
172
593
|
initialValue: false
|
|
173
594
|
});
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
|
|
595
|
+
if (isCancel2(selectedI18n)) {
|
|
596
|
+
cancel2("\u64CD\u4F5C\u5DF2\u53D6\u6D88");
|
|
597
|
+
process3.exit(0);
|
|
177
598
|
}
|
|
178
599
|
i18n = selectedI18n;
|
|
179
600
|
}
|
|
@@ -189,73 +610,25 @@ async function promptUser(projectName, argv = {}) {
|
|
|
189
610
|
};
|
|
190
611
|
} catch (error) {
|
|
191
612
|
logger.error(`\u8BE2\u95EE\u8FC7\u7A0B\u51FA\u9519: ${error.message}`);
|
|
192
|
-
|
|
613
|
+
process3.exit(1);
|
|
193
614
|
}
|
|
194
615
|
}
|
|
195
616
|
|
|
196
617
|
// src/commands/create/generate.ts
|
|
197
|
-
import
|
|
198
|
-
import { log } from "@clack/prompts";
|
|
618
|
+
import process5 from "process";
|
|
619
|
+
import { log as log2 } from "@clack/prompts";
|
|
199
620
|
|
|
200
621
|
// src/utils/cloneRepo.ts
|
|
201
622
|
import { exec } from "child_process";
|
|
202
|
-
import { promises as
|
|
203
|
-
import { join as join3 } from "path";
|
|
204
|
-
import
|
|
623
|
+
import { promises as fsPromises } from "fs";
|
|
624
|
+
import { join as join3, dirname as dirname2 } from "path";
|
|
625
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
626
|
+
import process4 from "process";
|
|
205
627
|
import { red as red3 } from "kolorist";
|
|
206
628
|
|
|
207
629
|
// src/utils/replacePackageJson.ts
|
|
208
630
|
import { readFileSync, writeFileSync } from "fs";
|
|
209
631
|
import { join as join2 } from "path";
|
|
210
|
-
|
|
211
|
-
// package.json
|
|
212
|
-
var version = "3.3.0";
|
|
213
|
-
var package_default = {
|
|
214
|
-
name: "create-unibest",
|
|
215
|
-
type: "module",
|
|
216
|
-
version,
|
|
217
|
-
updateTime: "2026-01-19",
|
|
218
|
-
packageManager: "pnpm@9.0.0",
|
|
219
|
-
description: "\u5FEB\u901F\u521B\u5EFAunibest\u9879\u76EE\u7684\u811A\u624B\u67B6\u5DE5\u5177",
|
|
220
|
-
author: "",
|
|
221
|
-
license: "ISC",
|
|
222
|
-
keywords: [],
|
|
223
|
-
main: "dist/index.js",
|
|
224
|
-
bin: {
|
|
225
|
-
best: "bin/index.js",
|
|
226
|
-
"create-unibest": "bin/index.js"
|
|
227
|
-
},
|
|
228
|
-
files: [
|
|
229
|
-
"bin",
|
|
230
|
-
"dist"
|
|
231
|
-
],
|
|
232
|
-
scripts: {
|
|
233
|
-
dev: "cross-env NODE_ENV=development tsup --watch",
|
|
234
|
-
build: "cross-env NODE_ENV=production tsup",
|
|
235
|
-
prepare: "cross-env NODE_ENV=production npm run build",
|
|
236
|
-
start: "cross-env NODE_ENV=development node bin/index.js"
|
|
237
|
-
},
|
|
238
|
-
dependencies: {
|
|
239
|
-
"@clack/prompts": "^0.11.0",
|
|
240
|
-
dayjs: "^1.11.18",
|
|
241
|
-
ejs: "^3.1.10",
|
|
242
|
-
"fs-extra": "^11.3.0",
|
|
243
|
-
kolorist: "^1.8.0",
|
|
244
|
-
minimist: "^1.2.8",
|
|
245
|
-
"node-fetch": "^3.3.2"
|
|
246
|
-
},
|
|
247
|
-
devDependencies: {
|
|
248
|
-
"@types/ejs": "^3.1.5",
|
|
249
|
-
"@types/fs-extra": "^11.0.4",
|
|
250
|
-
"@types/minimist": "^1.2.5",
|
|
251
|
-
"@types/node": "^24.5.0",
|
|
252
|
-
"cross-env": "^7.0.3",
|
|
253
|
-
tsup: "^8.5.0",
|
|
254
|
-
typescript: "^5.9.0"
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
// src/utils/replacePackageJson.ts
|
|
259
632
|
import dayjs from "dayjs";
|
|
260
633
|
function replaceContent(filePath, projectName, version2, options) {
|
|
261
634
|
const fileContent = JSON.parse(readFileSync(filePath, "utf8"));
|
|
@@ -267,6 +640,21 @@ function replaceContent(filePath, projectName, version2, options) {
|
|
|
267
640
|
delete fileContent.name;
|
|
268
641
|
delete fileContent.version;
|
|
269
642
|
const { projectName: _, ...restOptions } = options;
|
|
643
|
+
const selectedFeatures = getSelectedFeatures(options);
|
|
644
|
+
const featureDeps = {};
|
|
645
|
+
for (const feature of selectedFeatures) {
|
|
646
|
+
if (feature.dependencies) {
|
|
647
|
+
Object.assign(featureDeps, feature.dependencies);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
if (!fileContent.dependencies) {
|
|
651
|
+
fileContent.dependencies = {};
|
|
652
|
+
}
|
|
653
|
+
for (const [pkg, ver] of Object.entries(featureDeps)) {
|
|
654
|
+
if (!fileContent.dependencies[pkg]) {
|
|
655
|
+
fileContent.dependencies[pkg] = ver;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
270
658
|
const newContent = {
|
|
271
659
|
name: projectName,
|
|
272
660
|
type: fileContent.type,
|
|
@@ -291,9 +679,28 @@ function replacePackageJson(root2, name, version2, options) {
|
|
|
291
679
|
}
|
|
292
680
|
|
|
293
681
|
// src/utils/cloneRepo.ts
|
|
682
|
+
var __filename2 = fileURLToPath2(import.meta.url);
|
|
683
|
+
var __dirname2 = dirname2(__filename2);
|
|
684
|
+
var USE_LOCAL_TEMPLATE = process4.env.LOCAL_TEMPLATE === "true";
|
|
685
|
+
var TEMPLATE_BASE_PATH = null;
|
|
686
|
+
async function getTemplateBasePath() {
|
|
687
|
+
if (TEMPLATE_BASE_PATH) return TEMPLATE_BASE_PATH;
|
|
688
|
+
const candidates = [
|
|
689
|
+
join3(__dirname2, "..", "..", "..", "packages", "template-base"),
|
|
690
|
+
join3(__dirname2, "..", "..", "packages", "template-base")
|
|
691
|
+
];
|
|
692
|
+
const { existsSync: existsSync3 } = await import("fs");
|
|
693
|
+
for (const candidate of candidates) {
|
|
694
|
+
if (existsSync3(candidate)) {
|
|
695
|
+
TEMPLATE_BASE_PATH = candidate;
|
|
696
|
+
return candidate;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
throw new Error("\u65E0\u6CD5\u627E\u5230 template-base \u76EE\u5F55");
|
|
700
|
+
}
|
|
294
701
|
async function removeGitFolder(localPath) {
|
|
295
702
|
const gitFolderPath = join3(localPath, ".git");
|
|
296
|
-
await
|
|
703
|
+
await fsPromises.rm(gitFolderPath, { recursive: true, force: true });
|
|
297
704
|
}
|
|
298
705
|
var REPO_URL = "https://gitee.com/feige996/unibest.git";
|
|
299
706
|
async function cloneRepo(projectName, branch) {
|
|
@@ -320,12 +727,33 @@ async function cloneRepo(projectName, branch) {
|
|
|
320
727
|
throw new Error("cloneRepo error");
|
|
321
728
|
}
|
|
322
729
|
}
|
|
730
|
+
async function copyLocalTemplate(projectName) {
|
|
731
|
+
const projectPath = join3(process4.cwd(), projectName);
|
|
732
|
+
const sourcePath = await getTemplateBasePath();
|
|
733
|
+
await new Promise((resolve, reject) => {
|
|
734
|
+
const execStr = `cp -r "${sourcePath}/." "${projectPath}/"`;
|
|
735
|
+
exec(execStr, (error) => {
|
|
736
|
+
if (error) {
|
|
737
|
+
reject(error);
|
|
738
|
+
} else {
|
|
739
|
+
resolve();
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
});
|
|
743
|
+
return projectPath;
|
|
744
|
+
}
|
|
323
745
|
async function cloneRepoByBranch(root2, name, branch, options) {
|
|
324
746
|
try {
|
|
325
|
-
|
|
747
|
+
if (USE_LOCAL_TEMPLATE) {
|
|
748
|
+
console.log("\u4F7F\u7528\u672C\u5730\u6A21\u677F\u6D4B\u8BD5...");
|
|
749
|
+
await copyLocalTemplate(name);
|
|
750
|
+
} else {
|
|
751
|
+
console.log("\u4ECE Git \u514B\u9686\u57FA\u7840\u6A21\u677F...");
|
|
752
|
+
await cloneRepo(name, "base");
|
|
753
|
+
}
|
|
326
754
|
} catch (error) {
|
|
327
|
-
console.error(`${red3(`\u6A21\u677F\
|
|
328
|
-
|
|
755
|
+
console.error(`${red3(`\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25\uFF01`)} ${error}`);
|
|
756
|
+
process4.exit(1);
|
|
329
757
|
}
|
|
330
758
|
const projectPath = join3(root2, name);
|
|
331
759
|
replacePackageJson(projectPath, name, "1.0.0", options);
|
|
@@ -687,25 +1115,36 @@ function debug(...args) {
|
|
|
687
1115
|
}
|
|
688
1116
|
|
|
689
1117
|
// src/commands/create/generate.ts
|
|
690
|
-
import
|
|
691
|
-
var root =
|
|
1118
|
+
import path4 from "path";
|
|
1119
|
+
var root = process5.cwd();
|
|
692
1120
|
async function generateProject(options) {
|
|
693
1121
|
debug("generateProject options", options);
|
|
694
1122
|
const { projectName, platforms, uiLibrary, loginStrategy, i18n } = options;
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
debug("\
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
1123
|
+
const projectPath = path4.join(root, projectName);
|
|
1124
|
+
debug("\u62C9\u53D6 base \u5206\u652F");
|
|
1125
|
+
await cloneRepoByBranch(root, projectName, "base", options);
|
|
1126
|
+
if (i18n) {
|
|
1127
|
+
debug("\u6CE8\u5165 i18n feature");
|
|
1128
|
+
const results = await injectI18n(projectPath);
|
|
1129
|
+
for (const result of results) {
|
|
1130
|
+
if (result.success) {
|
|
1131
|
+
debug(result.message);
|
|
1132
|
+
} else {
|
|
1133
|
+
logger.warn(result.message);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
if (loginStrategy) {
|
|
1138
|
+
debug("\u6CE8\u5165 login feature");
|
|
1139
|
+
const results = await injectLogin(projectPath);
|
|
1140
|
+
for (const result of results) {
|
|
1141
|
+
if (result.success) {
|
|
1142
|
+
debug(result.message);
|
|
1143
|
+
} else {
|
|
1144
|
+
logger.warn(result.message);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
709
1148
|
if (uiLibrary === "none") {
|
|
710
1149
|
debug("\u4E0D\u5F15\u5165\u4EFB\u4F55UI\u5E93");
|
|
711
1150
|
} else {
|
|
@@ -718,8 +1157,18 @@ async function generateProject(options) {
|
|
|
718
1157
|
logger.info("\u60A8\u53EF\u4EE5\u5728\u9879\u76EE\u521B\u5EFA\u540E\u624B\u52A8\u914D\u7F6E UI \u5E93");
|
|
719
1158
|
}
|
|
720
1159
|
}
|
|
1160
|
+
const selectedFeatures = getSelectedFeatures(options);
|
|
1161
|
+
const allDeps = {};
|
|
1162
|
+
for (const feature of selectedFeatures) {
|
|
1163
|
+
if (feature.dependencies) {
|
|
1164
|
+
Object.assign(allDeps, feature.dependencies);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
if (Object.keys(allDeps).length > 0) {
|
|
1168
|
+
logger.info(`Feature \u4F9D\u8D56: ${Object.keys(allDeps).join(", ")}`);
|
|
1169
|
+
}
|
|
721
1170
|
try {
|
|
722
|
-
|
|
1171
|
+
log2.success(`\u9879\u76EE${projectName}\u521B\u5EFA\u6210\u529F\uFF01`);
|
|
723
1172
|
logger.info("\u4E0B\u4E00\u6B65:");
|
|
724
1173
|
logger.info(` cd ${projectName}`);
|
|
725
1174
|
logger.info(" pnpm i");
|
|
@@ -733,8 +1182,8 @@ async function generateProject(options) {
|
|
|
733
1182
|
}
|
|
734
1183
|
|
|
735
1184
|
// src/commands/create.ts
|
|
736
|
-
import { intro, log as
|
|
737
|
-
import { bold as
|
|
1185
|
+
import { intro as intro2, log as log3 } from "@clack/prompts";
|
|
1186
|
+
import { bold as bold3, yellow as yellow3, green as green4 } from "kolorist";
|
|
738
1187
|
|
|
739
1188
|
// src/utils/unibestVersion.ts
|
|
740
1189
|
import fetch from "node-fetch";
|
|
@@ -811,11 +1260,11 @@ function generateDeviceIdentifier() {
|
|
|
811
1260
|
async function createCommand(args) {
|
|
812
1261
|
const projectName = args._[1] || args._[0];
|
|
813
1262
|
const versionUnibest = await getUnibestVersionFromGitee() || "4.0.0";
|
|
814
|
-
|
|
1263
|
+
intro2(bold3(green4(`create-unibest@v${version} \u5FEB\u901F\u521B\u5EFA ${yellow3(`unibest@v${versionUnibest}`)} \u9879\u76EE`)));
|
|
815
1264
|
if (projectName) {
|
|
816
1265
|
const errorMessage = checkProjectNameExistAndValidate(projectName);
|
|
817
1266
|
if (errorMessage) {
|
|
818
|
-
|
|
1267
|
+
log3.error(errorMessage);
|
|
819
1268
|
process.exit(1);
|
|
820
1269
|
}
|
|
821
1270
|
}
|
|
@@ -824,16 +1273,16 @@ async function createCommand(args) {
|
|
|
824
1273
|
await generateProject(projectOptions);
|
|
825
1274
|
beacon(projectOptions);
|
|
826
1275
|
} catch (error) {
|
|
827
|
-
|
|
1276
|
+
log3.error(`\u521B\u5EFA\u9879\u76EE\u5931\u8D25: ${error.message}`);
|
|
828
1277
|
process.exit(1);
|
|
829
1278
|
}
|
|
830
1279
|
}
|
|
831
1280
|
|
|
832
1281
|
// src/utils/color.ts
|
|
833
|
-
import { blue, green as
|
|
1282
|
+
import { blue, green as green5, magenta as magenta2, red as red4, yellow as yellow4 } from "kolorist";
|
|
834
1283
|
var color = {
|
|
835
1284
|
blue,
|
|
836
|
-
green:
|
|
1285
|
+
green: green5,
|
|
837
1286
|
magenta: magenta2,
|
|
838
1287
|
red: red4,
|
|
839
1288
|
yellow: yellow4
|
|
@@ -846,33 +1295,54 @@ function printHelp() {
|
|
|
846
1295
|
console.log(color.blue("\u5FEB\u901F\u4F7F\u7528:"));
|
|
847
1296
|
console.log(color.green(" pnpm create unibest <command> [options]"));
|
|
848
1297
|
console.log(color.green(" pnpm create unibest my-project \u521B\u5EFA\u65B0\u7684unibest\u9879\u76EE"));
|
|
1298
|
+
console.log(color.green(" pnpm create unibest add i18n \u4E3A\u5DF2\u6709\u9879\u76EE\u6DFB\u52A0i18n\u7279\u6027"));
|
|
1299
|
+
console.log(color.green(" pnpm create unibest add login \u4E3A\u5DF2\u6709\u9879\u76EE\u6DFB\u52A0login\u7279\u6027"));
|
|
849
1300
|
console.log(color.green(" pnpm create unibest -v \u67E5\u770B\u7248\u672C\u4FE1\u606F"));
|
|
850
1301
|
console.log(color.green(" pnpm create unibest -h \u67E5\u770B\u5E2E\u52A9\u4FE1\u606F"));
|
|
851
1302
|
console.log("");
|
|
852
|
-
console.log(color.blue("\
|
|
1303
|
+
console.log(color.blue("\u53EF\u7528\u547D\u4EE4:"));
|
|
1304
|
+
console.log(" <projectName> \u521B\u5EFA\u9879\u76EE\uFF08\u4E0D\u7528 new \u5173\u952E\u5B57\uFF09");
|
|
1305
|
+
console.log(" create <projectName> \u521B\u5EFA\u9879\u76EE");
|
|
1306
|
+
console.log(" add <feature> \u4E3A\u5DF2\u6709\u9879\u76EE\u6DFB\u52A0 Feature");
|
|
1307
|
+
console.log("");
|
|
1308
|
+
console.log(color.blue("\u521B\u5EFA\u9879\u76EE\u9009\u9879:"));
|
|
853
1309
|
console.log(" -p, --platform <type> \u6307\u5B9A\u5E73\u53F0 (h5, mp-weixin, app, mp-alipay, mp-toutiao)");
|
|
854
1310
|
console.log(" \u652F\u6301\u591A\u9009: -p h5,mp-weixin \u6216 -p h5 -p mp-weixin");
|
|
855
1311
|
console.log(" -u, --ui <library> \u6307\u5B9AUI\u5E93 (wot-ui, uview-pro, sard-uniapp, uv-ui, uview-plus, none)");
|
|
856
1312
|
console.log(" -l, --login \u662F\u5426\u9700\u8981\u767B\u5F55\u7B56\u7565");
|
|
857
1313
|
console.log(" -i, --i18n \u662F\u5426\u9700\u8981\u591A\u8BED\u8A00");
|
|
858
1314
|
console.log("");
|
|
1315
|
+
console.log(color.blue("\u6DFB\u52A0Feature\u9009\u9879:"));
|
|
1316
|
+
console.log(" <feature> \u8981\u6DFB\u52A0\u7684 Feature (i18n, login)");
|
|
1317
|
+
console.log(" --path <path> \u9879\u76EE\u8DEF\u5F84 (\u9ED8\u8BA4\u5F53\u524D\u76EE\u5F55)");
|
|
1318
|
+
console.log(" --force \u5F3A\u5236\u91CD\u65B0\u6CE8\u5165\uFF08\u8986\u76D6\u5DF2\u6709\u914D\u7F6E\uFF09");
|
|
1319
|
+
console.log("");
|
|
1320
|
+
console.log(color.blue("\u53EF\u7528Feature:"));
|
|
1321
|
+
console.log(" i18n \u591A\u8BED\u8A00\u652F\u6301");
|
|
1322
|
+
console.log(" login \u767B\u5F55\u7B56\u7565\uFF08\u9ED1\u767D\u540D\u5355\u3001\u767B\u5F55\u62E6\u622A\u7B49\uFF09");
|
|
1323
|
+
console.log("");
|
|
859
1324
|
console.log(color.blue("\u793A\u4F8B:"));
|
|
1325
|
+
console.log(" # \u521B\u5EFA\u9879\u76EE");
|
|
860
1326
|
console.log(" pnpm create unibest my-project -u wot-ui -p h5,mp-weixin");
|
|
861
1327
|
console.log(" pnpm create unibest my-project -u uview-plus -l -i");
|
|
862
1328
|
console.log(" pnpm create unibest my-project -u none -p h5,app,mp-weixin");
|
|
863
1329
|
console.log("");
|
|
864
|
-
console.log(
|
|
865
|
-
console.log(
|
|
866
|
-
console.log(
|
|
867
|
-
console.log(
|
|
1330
|
+
console.log(" # \u6DFB\u52A0 Feature");
|
|
1331
|
+
console.log(" cd my-project && pnpm create unibest add i18n");
|
|
1332
|
+
console.log(" pnpm create unibest add login --path /path/to/project");
|
|
1333
|
+
console.log(" pnpm create unibest add i18n login");
|
|
1334
|
+
console.log(" pnpm create unibest add i18n --force # \u91CD\u65B0\u6CE8\u5165");
|
|
1335
|
+
console.log("");
|
|
1336
|
+
console.log(" # \u5168\u5C40\u5B89\u88C5");
|
|
1337
|
+
console.log(" npm i -g create-unibest");
|
|
1338
|
+
console.log(" best my-project");
|
|
1339
|
+
console.log(" best add i18n");
|
|
868
1340
|
console.log("");
|
|
869
1341
|
}
|
|
870
1342
|
|
|
871
1343
|
// src/index.ts
|
|
872
|
-
import { green as green5 } from "kolorist";
|
|
873
|
-
import { yellow as yellow5 } from "kolorist";
|
|
874
1344
|
function main() {
|
|
875
|
-
const args = minimist(
|
|
1345
|
+
const args = minimist(process6.argv.slice(2));
|
|
876
1346
|
const command = args._[0];
|
|
877
1347
|
debug("command:", command);
|
|
878
1348
|
debug("args:", args);
|
|
@@ -889,6 +1359,9 @@ function main() {
|
|
|
889
1359
|
case "new":
|
|
890
1360
|
createCommand(args);
|
|
891
1361
|
break;
|
|
1362
|
+
case "add":
|
|
1363
|
+
addCommand(args);
|
|
1364
|
+
break;
|
|
892
1365
|
case "-h":
|
|
893
1366
|
case "--help":
|
|
894
1367
|
printHelp();
|
|
@@ -906,8 +1379,8 @@ async function printVersion() {
|
|
|
906
1379
|
const cliVersion = version;
|
|
907
1380
|
const latestVersion = await getUnibestVersionFromGitee();
|
|
908
1381
|
if (latestVersion && latestVersion !== cliVersion) {
|
|
909
|
-
console.log(`unibest-cli ${cliVersion} ${yellow5(`->`)} ${
|
|
910
|
-
console.log(`\u4F7F\u7528 ${
|
|
1382
|
+
console.log(`unibest-cli ${cliVersion} ${yellow5(`->`)} ${green6(`\u6700\u65B0\u7248\u672C: ${latestVersion}`)}`);
|
|
1383
|
+
console.log(`\u4F7F\u7528 ${green6(`npm update -g create-unibest`)} \u6216 ${green6(`pnpm add -g create-unibest`)} \u66F4\u65B0`);
|
|
911
1384
|
console.log();
|
|
912
1385
|
} else {
|
|
913
1386
|
console.log(`unibest-cli ${cliVersion}`);
|
package/package.json
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-unibest",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"keywords": [],
|
|
11
|
-
"main": "dist/index.js",
|
|
4
|
+
"version": "4.0.0",
|
|
5
|
+
"packageManager": "pnpm@10.10.0",
|
|
6
|
+
"description": "快速创建 unibest 项目的脚手架工具",
|
|
7
|
+
"author": "feige996",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"homepage": "https://unibest.tech",
|
|
12
10
|
"bin": {
|
|
13
11
|
"best": "bin/index.js",
|
|
14
|
-
"create-unibest": "bin/index.js"
|
|
12
|
+
"create-unibest": "bin/index.js",
|
|
13
|
+
"unibest": "bin/index.js"
|
|
15
14
|
},
|
|
16
15
|
"files": [
|
|
17
16
|
"bin",
|
|
@@ -20,7 +19,7 @@
|
|
|
20
19
|
"scripts": {
|
|
21
20
|
"dev": "cross-env NODE_ENV=development tsup --watch",
|
|
22
21
|
"build": "cross-env NODE_ENV=production tsup",
|
|
23
|
-
"prepare": "
|
|
22
|
+
"prepare": "pnpm build",
|
|
24
23
|
"start": "cross-env NODE_ENV=development node bin/index.js"
|
|
25
24
|
},
|
|
26
25
|
"dependencies": {
|
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|