create-vee-vue 1.0.0 → 1.0.1
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/bin/index.js +120 -14
- package/package.json +2 -1
package/bin/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
+
import { input, select } from "@inquirer/prompts";
|
|
2
3
|
import fs from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { fileURLToPath } from "node:url";
|
|
@@ -7,33 +8,138 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
7
8
|
|
|
8
9
|
const program = new Command();
|
|
9
10
|
|
|
11
|
+
function normalizePackageName(name) {
|
|
12
|
+
return (
|
|
13
|
+
name
|
|
14
|
+
.trim()
|
|
15
|
+
.toLowerCase()
|
|
16
|
+
// 空格和下划线替换为 -
|
|
17
|
+
.replace(/[\s_]+/g, "-")
|
|
18
|
+
// 移除不允许的字符
|
|
19
|
+
.replace(/[^a-z0-9.-]/g, "")
|
|
20
|
+
// 连续的 - 合并为一个
|
|
21
|
+
.replace(/-+/g, "-")
|
|
22
|
+
// 移除开头和结尾的 -
|
|
23
|
+
.replace(/^-+|-+$/g, "")
|
|
24
|
+
// npm 包名不能以 . 开头
|
|
25
|
+
.replace(/^\.+/, "")
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function updatePackageName(targetDir, projectName) {
|
|
30
|
+
const packageJsonPath = path.join(targetDir, "package.json");
|
|
31
|
+
|
|
32
|
+
// 读取 package.json
|
|
33
|
+
const packageJsonContent = fs.readFileSync(packageJsonPath, "utf-8");
|
|
34
|
+
|
|
35
|
+
// JSON 字符串转换成 JavaScript 对象
|
|
36
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
37
|
+
|
|
38
|
+
// 修改项目名称
|
|
39
|
+
packageJson.name = projectName;
|
|
40
|
+
|
|
41
|
+
// 将对象转换成 JSON 字符串并写入文件
|
|
42
|
+
fs.writeFileSync(
|
|
43
|
+
packageJsonPath,
|
|
44
|
+
JSON.stringify(packageJson, null, 2) + "\n",
|
|
45
|
+
"utf-8",
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
10
49
|
program
|
|
11
50
|
.name("create-vee-vue")
|
|
12
51
|
.description("Create a Vue 3 project using my template")
|
|
13
|
-
.
|
|
14
|
-
|
|
15
|
-
|
|
52
|
+
.version("1.0.0");
|
|
53
|
+
|
|
54
|
+
// 项目名称改为可选参数
|
|
55
|
+
program.argument("[project-name]", "项目名称").action(async (projectName) => {
|
|
56
|
+
try {
|
|
57
|
+
// 1. 用户没有输入项目名称时,弹出输入框
|
|
58
|
+
if (!projectName) {
|
|
59
|
+
projectName = await input({
|
|
60
|
+
message: "Project name:",
|
|
61
|
+
default: "my-vue-app",
|
|
62
|
+
validate(value) {
|
|
63
|
+
if (!value.trim()) {
|
|
64
|
+
return "项目名称不能为空";
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const packageName = normalizePackageName(value);
|
|
68
|
+
|
|
69
|
+
if (!packageName) {
|
|
70
|
+
return "请输入有效的项目名称";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (packageName.length > 214) {
|
|
74
|
+
return "项目名称不能超过 214 个字符";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return true;
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 去除项目名称首尾空格
|
|
83
|
+
projectName = projectName.trim();
|
|
84
|
+
|
|
85
|
+
// 生成合法的 npm 包名称
|
|
86
|
+
const packageName = normalizePackageName(projectName);
|
|
87
|
+
|
|
88
|
+
// 2. 选择项目模板
|
|
89
|
+
const templateName = await select({
|
|
90
|
+
message: "Select a template:",
|
|
91
|
+
choices: [
|
|
92
|
+
{
|
|
93
|
+
name: "Vue 3 + TypeScript",
|
|
94
|
+
value: "vue-ts",
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// 3. 计算项目路径
|
|
16
100
|
const targetDir = path.resolve(process.cwd(), projectName);
|
|
17
101
|
|
|
18
|
-
//
|
|
19
|
-
const templateDir = path.resolve(__dirname, "../templates
|
|
102
|
+
// 4. 计算模板路径
|
|
103
|
+
const templateDir = path.resolve(__dirname, "../templates", templateName);
|
|
20
104
|
|
|
21
|
-
//
|
|
105
|
+
// 5. 检查项目目录是否存在
|
|
22
106
|
if (fs.existsSync(targetDir)) {
|
|
23
107
|
console.error(`目录已存在:${targetDir}`);
|
|
24
|
-
process.
|
|
108
|
+
process.exitCode = 1;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 6. 检查模板是否存在
|
|
113
|
+
if (!fs.existsSync(templateDir)) {
|
|
114
|
+
console.error(`模板不存在:${templateDir}`);
|
|
115
|
+
process.exitCode = 1;
|
|
116
|
+
return;
|
|
25
117
|
}
|
|
26
118
|
|
|
27
|
-
//
|
|
119
|
+
// 7. 复制模板
|
|
120
|
+
console.log(`Scaffolding project in ${projectName}...`);
|
|
121
|
+
|
|
28
122
|
fs.cpSync(templateDir, targetDir, {
|
|
29
123
|
recursive: true,
|
|
30
124
|
});
|
|
31
125
|
|
|
32
|
-
|
|
126
|
+
updatePackageName(targetDir, packageName);
|
|
127
|
+
|
|
33
128
|
console.log("");
|
|
34
|
-
console.log(
|
|
35
|
-
console.log("
|
|
36
|
-
console.log(
|
|
37
|
-
|
|
129
|
+
console.log("Done!");
|
|
130
|
+
console.log("");
|
|
131
|
+
console.log(` cd ${projectName}`);
|
|
132
|
+
console.log(" pnpm install");
|
|
133
|
+
console.log(" pnpm dev");
|
|
134
|
+
} catch (error) {
|
|
135
|
+
if (error.name === "AbortPromptError") {
|
|
136
|
+
console.log("\n取消创建项目");
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
console.error(error);
|
|
141
|
+
process.exitCode = 1;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
38
144
|
|
|
39
|
-
program.
|
|
145
|
+
program.parseAsync();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-vee-vue",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "My custom Vue 3 scaffolding",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"dev": "node ./bin/index.js"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"@inquirer/prompts": "^8.7.5",
|
|
17
18
|
"commander": "^14.0.0"
|
|
18
19
|
}
|
|
19
20
|
}
|