create-vue3-enterprise 1.0.0 → 1.0.20
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/dist/index.js +291 -130
- package/package.json +2 -4
- package/template/.husky/commit-msg +35 -0
- package/template/.husky/pre-commit +30 -0
- package/template/commitlint.config.js +28 -0
- package/template/lint-staged.config.js +8 -0
package/dist/index.js
CHANGED
|
@@ -1,48 +1,56 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import fs from
|
|
3
|
-
import path from
|
|
4
|
-
import { fileURLToPath } from
|
|
5
|
-
import minimist from
|
|
6
|
-
import prompts from
|
|
7
|
-
import { red, green, cyan } from
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import minimist from "minimist";
|
|
6
|
+
import prompts from "prompts";
|
|
7
|
+
import { red, green, cyan, yellow } from "kolorist";
|
|
8
8
|
const argv = minimist(process.argv.slice(2), {
|
|
9
|
-
string: [
|
|
10
|
-
boolean: [
|
|
9
|
+
string: ["_"],
|
|
10
|
+
boolean: ["help", "template", "force"],
|
|
11
11
|
alias: {
|
|
12
|
-
h:
|
|
13
|
-
t:
|
|
14
|
-
f:
|
|
15
|
-
}
|
|
12
|
+
h: "help",
|
|
13
|
+
t: "template",
|
|
14
|
+
f: "force",
|
|
15
|
+
},
|
|
16
16
|
});
|
|
17
17
|
const cwd = process.cwd();
|
|
18
18
|
const __filename = fileURLToPath(import.meta.url);
|
|
19
19
|
const __dirname = path.dirname(__filename);
|
|
20
20
|
function printHelp() {
|
|
21
21
|
console.log(`
|
|
22
|
-
${cyan(
|
|
22
|
+
${cyan("create-vue3-enterprise")}
|
|
23
23
|
|
|
24
|
-
${green(
|
|
25
|
-
npm create vue3-enterprise
|
|
24
|
+
${green("用法:")}
|
|
25
|
+
npm create vue3-enterprise <项目名称> [选项]
|
|
26
26
|
|
|
27
|
-
${green(
|
|
28
|
-
-h, --help
|
|
29
|
-
-
|
|
27
|
+
${green("选项:")}
|
|
28
|
+
-h, --help 显示帮助信息
|
|
29
|
+
-t, --template 指定模板(vue3-ts)
|
|
30
|
+
-f, --force 强制覆盖已存在的目录
|
|
30
31
|
|
|
31
|
-
${green(
|
|
32
|
+
${green("示例:")}
|
|
32
33
|
npm create vue3-enterprise my-project
|
|
34
|
+
npm create vue3-enterprise my-project --force
|
|
33
35
|
`);
|
|
34
36
|
}
|
|
35
37
|
function isValidPackageName(projectName) {
|
|
36
38
|
return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(projectName);
|
|
37
39
|
}
|
|
38
40
|
function toValidPackageName(projectName) {
|
|
39
|
-
return projectName
|
|
41
|
+
return projectName
|
|
42
|
+
.trim()
|
|
43
|
+
.toLowerCase()
|
|
44
|
+
.replace(/\s+/g, "-")
|
|
45
|
+
.replace(/^[._]/, "")
|
|
46
|
+
.replace(/[^a-z0-9-~]+/g, "-");
|
|
40
47
|
}
|
|
41
48
|
function emptyDir(dir) {
|
|
42
49
|
if (!fs.existsSync(dir))
|
|
43
50
|
return;
|
|
44
51
|
for (const file of fs.readdirSync(dir)) {
|
|
45
|
-
|
|
52
|
+
const filePath = path.resolve(dir, file);
|
|
53
|
+
fs.rmSync(filePath, { recursive: true, force: true });
|
|
46
54
|
}
|
|
47
55
|
}
|
|
48
56
|
function copyDir(srcDir, destDir) {
|
|
@@ -51,166 +59,319 @@ function copyDir(srcDir, destDir) {
|
|
|
51
59
|
const srcFile = path.resolve(srcDir, file);
|
|
52
60
|
const destFile = path.resolve(destDir, file);
|
|
53
61
|
const stat = fs.statSync(srcFile);
|
|
54
|
-
if (stat.isDirectory())
|
|
62
|
+
if (stat.isDirectory()) {
|
|
55
63
|
copyDir(srcFile, destFile);
|
|
56
|
-
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
57
66
|
fs.copyFileSync(srcFile, destFile);
|
|
67
|
+
}
|
|
58
68
|
}
|
|
59
69
|
}
|
|
60
|
-
function
|
|
61
|
-
const name = isValidPackageName(targetDir) ? targetDir : toValidPackageName(targetDir);
|
|
70
|
+
async function generatePackageJson(targetDir, options) {
|
|
62
71
|
const pkg = {
|
|
63
|
-
name
|
|
64
|
-
|
|
72
|
+
name: isValidPackageName(targetDir)
|
|
73
|
+
? targetDir
|
|
74
|
+
: toValidPackageName(targetDir),
|
|
75
|
+
version: "0.0.0",
|
|
65
76
|
private: true,
|
|
66
|
-
type:
|
|
77
|
+
type: "module",
|
|
67
78
|
scripts: {
|
|
68
|
-
dev:
|
|
69
|
-
build:
|
|
70
|
-
preview:
|
|
71
|
-
test:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
lint:
|
|
75
|
-
format:
|
|
76
|
-
|
|
79
|
+
dev: "vite",
|
|
80
|
+
build: "vue-tsc && vite build",
|
|
81
|
+
preview: "vite preview",
|
|
82
|
+
test: "vitest",
|
|
83
|
+
"test:e2e": "playwright test",
|
|
84
|
+
"test:perf": "playwright test --config=playwright.config.perf.ts",
|
|
85
|
+
lint: "eslint . --ext .vue,.ts,.tsx --fix",
|
|
86
|
+
format: "prettier --write .",
|
|
87
|
+
"type-check": "vue-tsc --noEmit",
|
|
88
|
+
prepare: "husky install",
|
|
89
|
+
"lint-staged": "lint-staged",
|
|
90
|
+
},
|
|
91
|
+
dependencies: {
|
|
92
|
+
vue: "^3.4.0",
|
|
77
93
|
},
|
|
78
|
-
dependencies: { vue: '^3.4.0' },
|
|
79
94
|
devDependencies: {
|
|
80
|
-
|
|
81
|
-
typescript:
|
|
82
|
-
vite:
|
|
83
|
-
|
|
84
|
-
}
|
|
95
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
96
|
+
typescript: "^5.3.0",
|
|
97
|
+
vite: "^5.0.0",
|
|
98
|
+
"vue-tsc": "^1.8.0",
|
|
99
|
+
},
|
|
85
100
|
};
|
|
86
|
-
if (
|
|
87
|
-
pkg.dependencies[
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
pkg.devDependencies[
|
|
110
|
-
}
|
|
111
|
-
if (features
|
|
112
|
-
pkg.devDependencies[
|
|
113
|
-
}
|
|
114
|
-
if (features
|
|
115
|
-
pkg.devDependencies[
|
|
101
|
+
if (options.needsRouter) {
|
|
102
|
+
pkg.dependencies["vue-router"] = "^4.2.0";
|
|
103
|
+
}
|
|
104
|
+
if (options.needsPinia) {
|
|
105
|
+
pkg.dependencies["pinia"] = "^2.1.0";
|
|
106
|
+
}
|
|
107
|
+
if (options.features?.includes("lint")) {
|
|
108
|
+
pkg.devDependencies["@typescript-eslint/eslint-plugin"] = "^6.21.0";
|
|
109
|
+
pkg.devDependencies["@typescript-eslint/parser"] = "^6.21.0";
|
|
110
|
+
pkg.devDependencies["@vue/eslint-config-prettier"] = "^9.0.0";
|
|
111
|
+
pkg.devDependencies["@vue/eslint-config-typescript"] = "^12.0.0";
|
|
112
|
+
pkg.devDependencies["eslint"] = "^8.57.0";
|
|
113
|
+
pkg.devDependencies["eslint-plugin-vue"] = "^9.21.0";
|
|
114
|
+
pkg.devDependencies["prettier"] = "^3.2.0";
|
|
115
|
+
// Git hooks
|
|
116
|
+
pkg.devDependencies["husky"] = "^9.0.0";
|
|
117
|
+
pkg.devDependencies["lint-staged"] = "^15.2.0";
|
|
118
|
+
pkg.devDependencies["@commitlint/cli"] = "^19.0.0";
|
|
119
|
+
pkg.devDependencies["@commitlint/config-conventional"] = "^19.0.0";
|
|
120
|
+
}
|
|
121
|
+
if (options.features?.includes("vitest")) {
|
|
122
|
+
pkg.devDependencies["@vue/test-utils"] = "^2.4.0";
|
|
123
|
+
pkg.devDependencies["happy-dom"] = "^13.0.0";
|
|
124
|
+
pkg.devDependencies["vitest"] = "^1.2.0";
|
|
125
|
+
}
|
|
126
|
+
if (options.features?.includes("playwright")) {
|
|
127
|
+
pkg.devDependencies["@playwright/test"] = "^1.41.0";
|
|
128
|
+
}
|
|
129
|
+
if (options.features?.includes("mcp")) {
|
|
130
|
+
pkg.devDependencies["vue3-enterprise-mcp"] = "^1.0.0";
|
|
131
|
+
}
|
|
132
|
+
if (options.features?.includes("ci")) {
|
|
133
|
+
pkg.devDependencies["vue3-enterprise-ci"] = "^1.0.0";
|
|
116
134
|
}
|
|
117
135
|
return pkg;
|
|
118
136
|
}
|
|
119
137
|
async function main() {
|
|
120
|
-
console.log(`\n${cyan(
|
|
138
|
+
console.log(`\n${cyan("Vue3 Enterprise Toolchain")}\n`);
|
|
121
139
|
if (argv.help) {
|
|
122
140
|
printHelp();
|
|
123
141
|
return;
|
|
124
142
|
}
|
|
125
143
|
let targetDir = argv._[0];
|
|
126
|
-
const
|
|
144
|
+
const promptResult = await prompts([
|
|
127
145
|
{
|
|
128
|
-
type: targetDir ? null :
|
|
129
|
-
name:
|
|
130
|
-
message:
|
|
131
|
-
initial:
|
|
132
|
-
onState: (
|
|
146
|
+
type: targetDir ? null : "text",
|
|
147
|
+
name: "projectName",
|
|
148
|
+
message: "项目名称:",
|
|
149
|
+
initial: "vue3-enterprise-project",
|
|
150
|
+
onState: (state) => {
|
|
151
|
+
targetDir = String(state.value).trim() || "vue3-enterprise-project";
|
|
152
|
+
},
|
|
133
153
|
},
|
|
134
154
|
{
|
|
135
|
-
type:
|
|
155
|
+
type: "select",
|
|
156
|
+
name: "template",
|
|
157
|
+
message: "选择模板:",
|
|
136
158
|
choices: [
|
|
137
|
-
{ title:
|
|
138
|
-
{ title:
|
|
139
|
-
{
|
|
140
|
-
|
|
159
|
+
{ title: "Vue3 + TypeScript + Vite (推荐)", value: "vue3-ts" },
|
|
160
|
+
{ title: "Vue3 + TypeScript + Vite + Pinia", value: "vue3-ts-pinia" },
|
|
161
|
+
{
|
|
162
|
+
title: "Vue3 + TypeScript + Vite + Pinia + Vue Router",
|
|
163
|
+
value: "vue3-ts-full",
|
|
164
|
+
},
|
|
165
|
+
],
|
|
141
166
|
},
|
|
142
167
|
{
|
|
143
|
-
type:
|
|
168
|
+
type: "multiselect",
|
|
169
|
+
name: "features",
|
|
170
|
+
message: "选择功能 (空格选择,回车确认):",
|
|
144
171
|
choices: [
|
|
145
|
-
{ title:
|
|
146
|
-
{ title:
|
|
147
|
-
{
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
172
|
+
{ title: "ESLint + Prettier", value: "lint", selected: true },
|
|
173
|
+
{ title: "Vitest (单元测试)", value: "vitest", selected: true },
|
|
174
|
+
{
|
|
175
|
+
title: "Playwright (E2E 测试)",
|
|
176
|
+
value: "playwright",
|
|
177
|
+
selected: true,
|
|
178
|
+
},
|
|
179
|
+
{ title: "Vue3 Enterprise MCP", value: "mcp", selected: true },
|
|
180
|
+
{ title: "CI/CD 工作流", value: "ci", selected: true },
|
|
181
|
+
{ title: "性能基准测试", value: "perf", selected: true },
|
|
182
|
+
],
|
|
152
183
|
},
|
|
153
184
|
{
|
|
154
|
-
type:
|
|
185
|
+
type: "confirm",
|
|
186
|
+
name: "needsTypeScript",
|
|
187
|
+
message: "使用 TypeScript?",
|
|
188
|
+
initial: true,
|
|
155
189
|
},
|
|
156
190
|
{
|
|
157
|
-
type:
|
|
191
|
+
type: "confirm",
|
|
192
|
+
name: "needsRouter",
|
|
193
|
+
message: "添加 Vue Router?",
|
|
194
|
+
initial: true,
|
|
158
195
|
},
|
|
159
196
|
{
|
|
160
|
-
type:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
initial:
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
197
|
+
type: "confirm",
|
|
198
|
+
name: "needsPinia",
|
|
199
|
+
message: "添加 Pinia (状态管理)?",
|
|
200
|
+
initial: true,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
type: "confirm",
|
|
204
|
+
name: "overwrite",
|
|
205
|
+
message: targetDir &&
|
|
206
|
+
fs.existsSync(targetDir) &&
|
|
207
|
+
fs.readdirSync(targetDir).length > 0
|
|
208
|
+
? `目录 "${targetDir}" 已存在且不为空。是否覆盖?`
|
|
209
|
+
: "",
|
|
210
|
+
initial: false,
|
|
211
|
+
},
|
|
212
|
+
], {
|
|
213
|
+
onCancel: () => {
|
|
214
|
+
console.log(red("✖ 操作已取消"));
|
|
215
|
+
process.exit(1);
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
if (promptResult.overwrite === false) {
|
|
219
|
+
console.log(red("✖ 操作已取消"));
|
|
168
220
|
process.exit(1);
|
|
169
221
|
}
|
|
170
222
|
const root = path.join(cwd, targetDir);
|
|
171
223
|
if (fs.existsSync(root)) {
|
|
172
|
-
if (argv.force ||
|
|
224
|
+
if (argv.force || promptResult.overwrite) {
|
|
173
225
|
emptyDir(root);
|
|
226
|
+
}
|
|
174
227
|
else {
|
|
175
|
-
console.log(red(`✖
|
|
228
|
+
console.log(red(`✖ 目录 "${targetDir}" 已存在`));
|
|
229
|
+
console.log(yellow("提示: 使用 --force 强制覆盖"));
|
|
176
230
|
process.exit(1);
|
|
177
231
|
}
|
|
178
232
|
}
|
|
179
|
-
else
|
|
233
|
+
else {
|
|
180
234
|
fs.mkdirSync(root, { recursive: true });
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
235
|
+
}
|
|
236
|
+
console.log(`\n${cyan("正在创建项目...")}\n`);
|
|
237
|
+
const templateDir = path.resolve(__dirname, "../template");
|
|
238
|
+
copyDir(templateDir, root);
|
|
239
|
+
const pkg = await generatePackageJson(targetDir, {
|
|
240
|
+
features: promptResult.features || [],
|
|
241
|
+
needsRouter: promptResult.needsRouter,
|
|
242
|
+
needsPinia: promptResult.needsPinia,
|
|
243
|
+
});
|
|
244
|
+
fs.writeFileSync(path.join(root, "package.json"), JSON.stringify(pkg, null, 2));
|
|
245
|
+
const featureDescriptions = {
|
|
246
|
+
lint: "- 🧹 ESLint + Prettier 代码规范 + Git Hooks 自动检查",
|
|
247
|
+
vitest: "- 🧪 Vitest 单元测试",
|
|
248
|
+
playwright: "- 🎭 Playwright E2E 测试",
|
|
249
|
+
mcp: "- 🔍 Vue3 Enterprise MCP 代码审查",
|
|
250
|
+
ci: "- ⚡ CI/CD 自动化",
|
|
251
|
+
perf: "- 📊 性能基准测试",
|
|
192
252
|
};
|
|
193
253
|
const readme = `# ${pkg.name}
|
|
194
254
|
|
|
195
|
-
|
|
255
|
+
使用 Vue3 Enterprise Toolchain 创建的项目
|
|
256
|
+
|
|
257
|
+
## 功能特性
|
|
196
258
|
|
|
197
|
-
|
|
198
|
-
|
|
259
|
+
${(promptResult.features || [])
|
|
260
|
+
.map((f) => featureDescriptions[f] || "")
|
|
261
|
+
.filter(Boolean)
|
|
262
|
+
.join("\n")}
|
|
263
|
+
|
|
264
|
+
## 快速开始
|
|
199
265
|
|
|
200
|
-
## Quick Start
|
|
201
266
|
\`\`\`bash
|
|
267
|
+
# 安装依赖
|
|
202
268
|
npm install
|
|
269
|
+
|
|
270
|
+
# 启动开发服务器
|
|
203
271
|
npm run dev
|
|
272
|
+
|
|
273
|
+
# 运行测试
|
|
274
|
+
npm test
|
|
275
|
+
|
|
276
|
+
# 构建生产版本
|
|
277
|
+
npm run build
|
|
204
278
|
\`\`\`
|
|
205
279
|
|
|
206
|
-
##
|
|
207
|
-
|
|
208
|
-
- \`npm run
|
|
209
|
-
- \`npm
|
|
280
|
+
## 可用脚本
|
|
281
|
+
|
|
282
|
+
- \`npm run dev\` - 启动开发服务器
|
|
283
|
+
- \`npm run build\` - 构建生产版本
|
|
284
|
+
- \`npm run preview\` - 预览生产版本
|
|
285
|
+
- \`npm test\` - 运行单元测试
|
|
286
|
+
- \`npm run test:e2e\` - 运行 E2E 测试
|
|
287
|
+
- \`npm run test:perf\` - 运行性能测试
|
|
288
|
+
- \`npm run lint\` - 运行 ESLint
|
|
289
|
+
- \`npm run format\` - 运行 Prettier
|
|
290
|
+
|
|
291
|
+
## 文档
|
|
292
|
+
|
|
293
|
+
- [Vue3 Enterprise MCP 使用指南](https://github.com/your-org/vue3-enterprise-toolchain/blob/main/docs/mcp.md)
|
|
294
|
+
- [CI 集成指南](https://github.com/your-org/vue3-enterprise-toolchain/blob/main/docs/ci.md)
|
|
210
295
|
`;
|
|
211
|
-
fs.writeFileSync(path.join(root,
|
|
212
|
-
const gitignore =
|
|
213
|
-
|
|
214
|
-
|
|
296
|
+
fs.writeFileSync(path.join(root, "README.md"), readme);
|
|
297
|
+
const gitignore = `# Logs
|
|
298
|
+
logs
|
|
299
|
+
*.log
|
|
300
|
+
npm-debug.log*
|
|
301
|
+
yarn-debug.log*
|
|
302
|
+
yarn-error.log*
|
|
303
|
+
pnpm-debug.log*
|
|
304
|
+
lerna-debug.log*
|
|
305
|
+
|
|
306
|
+
node_modules
|
|
307
|
+
.DS_Store
|
|
308
|
+
dist
|
|
309
|
+
dist-ssr
|
|
310
|
+
*.local
|
|
311
|
+
|
|
312
|
+
# Editor directories and files
|
|
313
|
+
.vscode/*
|
|
314
|
+
!.vscode/extensions.json
|
|
315
|
+
.idea
|
|
316
|
+
*.suo
|
|
317
|
+
*.ntvs*
|
|
318
|
+
*.njsproj
|
|
319
|
+
*.sln
|
|
320
|
+
*.sw?
|
|
321
|
+
|
|
322
|
+
# Testing
|
|
323
|
+
coverage
|
|
324
|
+
|
|
325
|
+
# Playwright
|
|
326
|
+
test-results/
|
|
327
|
+
playwright-report/
|
|
328
|
+
playwright/.cache/
|
|
329
|
+
|
|
330
|
+
# Performance baseline
|
|
331
|
+
.perf-baseline.json
|
|
332
|
+
`;
|
|
333
|
+
fs.writeFileSync(path.join(root, ".gitignore"), gitignore);
|
|
334
|
+
// Initialize git and husky if lint feature is enabled
|
|
335
|
+
if (promptResult.features?.includes("lint")) {
|
|
336
|
+
const { execSync } = require("child_process");
|
|
337
|
+
try {
|
|
338
|
+
execSync("git init", { cwd: root, stdio: "ignore" });
|
|
339
|
+
execSync("npm run prepare", { cwd: root, stdio: "ignore" });
|
|
340
|
+
}
|
|
341
|
+
catch (e) {
|
|
342
|
+
// Git may not be installed
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
console.log(`${green("✔")} 项目创建成功!\n`);
|
|
346
|
+
console.log(` cd ${cyan(targetDir)}`);
|
|
347
|
+
console.log(` npm install`);
|
|
348
|
+
console.log(` npm run dev\n`);
|
|
349
|
+
// Git hooks info
|
|
350
|
+
if (promptResult.features?.includes("lint")) {
|
|
351
|
+
console.log(`${cyan("Git Hooks 配置:")}`);
|
|
352
|
+
console.log(` • pre-commit: 自动检查格式和类型`);
|
|
353
|
+
console.log(` • commit-msg: 验证提交信息格式`);
|
|
354
|
+
console.log(` 提交时自动运行检查,无需手动触发\n`);
|
|
355
|
+
}
|
|
356
|
+
if (promptResult.features?.includes("mcp")) {
|
|
357
|
+
console.log(`${cyan("MCP Server 配置:")}`);
|
|
358
|
+
console.log(` 在 Claude Desktop 的 claude_desktop_config.json 中添加:\n`);
|
|
359
|
+
console.log(` {
|
|
360
|
+
"mcpServers": {
|
|
361
|
+
"vue3-enterprise": {
|
|
362
|
+
"command": "npx",
|
|
363
|
+
"args": ["-y", "vue3-enterprise-mcp", "${targetDir}"]
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}\n`);
|
|
367
|
+
}
|
|
368
|
+
if (promptResult.features?.includes("ci")) {
|
|
369
|
+
console.log(`${cyan("CI 配置:")}`);
|
|
370
|
+
console.log(` 已配置 GitHub Actions 工作流`);
|
|
371
|
+
console.log(` 提交代码后会自动运行测试和性能检查\n`);
|
|
372
|
+
}
|
|
215
373
|
}
|
|
216
|
-
main().catch((
|
|
374
|
+
main().catch((err) => {
|
|
375
|
+
console.error(err);
|
|
376
|
+
process.exit(1);
|
|
377
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-vue3-enterprise",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
4
4
|
"description": "Vue3 + TypeScript + Vite 企业级项目脚手架",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,9 +13,7 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "tsc",
|
|
15
15
|
"dev": "tsc --watch",
|
|
16
|
-
"prepublishOnly": "npm run build"
|
|
17
|
-
"test": "node ./dist/index.js --help",
|
|
18
|
-
"test:create": "node ./dist/index.js test-project --force"
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
19
17
|
},
|
|
20
18
|
"dependencies": {
|
|
21
19
|
"kolorist": "^1.8.0",
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
. "$(dirname -- "$0")/_/husky.sh"
|
|
3
|
+
|
|
4
|
+
# ============================================
|
|
5
|
+
# 📝 Commit Message Validation
|
|
6
|
+
# Uses Conventional Commits format
|
|
7
|
+
# ============================================
|
|
8
|
+
|
|
9
|
+
echo ""
|
|
10
|
+
echo "📝 Validating commit message..."
|
|
11
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
12
|
+
|
|
13
|
+
# Run commitlint
|
|
14
|
+
if ! npx commitlint --edit ${1}; then
|
|
15
|
+
echo ""
|
|
16
|
+
echo "❌ Commit message validation FAILED"
|
|
17
|
+
echo ""
|
|
18
|
+
echo "📖 Correct format:"
|
|
19
|
+
echo " <type>(<scope>): <subject>"
|
|
20
|
+
echo ""
|
|
21
|
+
echo " Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert"
|
|
22
|
+
echo ""
|
|
23
|
+
echo " Examples:"
|
|
24
|
+
echo " • feat: add user login button"
|
|
25
|
+
echo " • fix: resolve memory leak in component"
|
|
26
|
+
echo " • docs: update API documentation"
|
|
27
|
+
echo ""
|
|
28
|
+
echo " Run 'npm run commit' for interactive commit"
|
|
29
|
+
echo ""
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
echo ""
|
|
34
|
+
echo "✅ Commit message validated!"
|
|
35
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
. "$(dirname -- "$0")/_/husky.sh"
|
|
3
|
+
|
|
4
|
+
# ============================================
|
|
5
|
+
# 🧹 Pre-commit Checks
|
|
6
|
+
# - Code formatting (Prettier)
|
|
7
|
+
# - Type checking (vue-tsc)
|
|
8
|
+
# - Linting (ESLint)
|
|
9
|
+
# ============================================
|
|
10
|
+
|
|
11
|
+
echo ""
|
|
12
|
+
echo "🔍 Running pre-commit checks..."
|
|
13
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
14
|
+
|
|
15
|
+
# Run lint-staged
|
|
16
|
+
if ! npx lint-staged; then
|
|
17
|
+
echo ""
|
|
18
|
+
echo "❌ Pre-commit checks FAILED"
|
|
19
|
+
echo ""
|
|
20
|
+
echo "📖 Fix suggestions:"
|
|
21
|
+
echo " • Run 'npm run format' to fix formatting"
|
|
22
|
+
echo " • Run 'npm run lint' to fix linting errors"
|
|
23
|
+
echo " • Fix TypeScript errors manually"
|
|
24
|
+
echo ""
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
echo ""
|
|
29
|
+
echo "✅ Pre-commit checks passed!"
|
|
30
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
extends: ['@commitlint/config-conventional'],
|
|
3
|
+
rules: {
|
|
4
|
+
// Type envelope: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test
|
|
5
|
+
'type-enum': [
|
|
6
|
+
2,
|
|
7
|
+
'always',
|
|
8
|
+
[
|
|
9
|
+
'feat', // New feature
|
|
10
|
+
'fix', // Bug fix
|
|
11
|
+
'docs', // Documentation only changes
|
|
12
|
+
'style', // Changes that do not affect the meaning of the code (formatting)
|
|
13
|
+
'refactor', // Code change that neither fixes a bug nor adds a feature
|
|
14
|
+
'perf', // Performance improvement
|
|
15
|
+
'test', // Adding or correcting tests
|
|
16
|
+
'build', // Changes to build system or dependencies
|
|
17
|
+
'ci', // Changes to CI configuration
|
|
18
|
+
'chore', // Other changes that don't modify src or test files
|
|
19
|
+
'revert', // Reverts a previous commit
|
|
20
|
+
],
|
|
21
|
+
],
|
|
22
|
+
'type-case': [2, 'always', 'lower-case'],
|
|
23
|
+
'type-empty': [2, 'never'],
|
|
24
|
+
'subject-empty': [2, 'never'],
|
|
25
|
+
'subject-full-stop': [2, 'never', '.'],
|
|
26
|
+
'header-max-length': [2, 'always', 100],
|
|
27
|
+
},
|
|
28
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
// TypeScript and Vue files - check types
|
|
3
|
+
'*.ts': ['vue-tsc --noEmit', 'eslint --fix'],
|
|
4
|
+
'*.tsx': ['vue-tsc --noEmit', 'eslint --fix'],
|
|
5
|
+
'*.vue': ['vue-tsc --noEmit', 'eslint --fix'],
|
|
6
|
+
// Format all staged files
|
|
7
|
+
'**/*': ['prettier --write --ignore-unknown'],
|
|
8
|
+
}
|