-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreate-arenapro-vite.cjs
More file actions
executable file
·200 lines (172 loc) · 5.27 KB
/
create-arenapro-vite.cjs
File metadata and controls
executable file
·200 lines (172 loc) · 5.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
// 模板复制时需要忽略的文件/目录(包内部用,不会复制到目标项目)
// 其余的目录与文件一律按层级递归复制
const INTERNAL_IGNORE = new Set([
'node_modules',
'.git',
'.turbo',
'.idea',
'.DS_Store',
'dist',
'coverage',
'npm-debug.log',
'create-arenapro-vite.cjs',
'pnpm-lock.yaml',
'bun.lock',
'LICENSE',
'.husky',
'cli',
]);
// 当前一次执行时的目标目录,用于避免把历史生成结果再次当作模板复制
let CURRENT_TARGET_DIR = '';
// 校验 npm 包名是否符合规范
function isValidPackageName(name) {
const pkgNamePattern =
/^(?:(?:@(?:[a-z0-9-*~][a-z0-9-*._~]*)?\/[a-z0-9-._~])|[a-z0-9-~])[a-z0-9-._~]*$/;
return pkgNamePattern.test(name);
}
function resolveTemplateRoot() {
// 当前包根目录即模板根目录
return path.resolve(__dirname);
}
function ensureDir(dir) {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
}
function copyDirRecursive(srcDir, destDir) {
if (!fs.existsSync(srcDir)) {
return;
}
// 避免把已经生成过的目标目录当成模板再次复制,造成无限嵌套
if (CURRENT_TARGET_DIR && srcDir.startsWith(CURRENT_TARGET_DIR)) {
return;
}
ensureDir(destDir);
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
for (const entry of entries) {
const srcPath = path.join(srcDir, entry.name);
const destPath = path.join(destDir, entry.name);
if (INTERNAL_IGNORE.has(entry.name)) {
continue;
}
// 同样避免进入目标目录下的任何内容
if (CURRENT_TARGET_DIR && srcPath.startsWith(CURRENT_TARGET_DIR)) {
continue;
}
if (entry.isDirectory()) {
copyDirRecursive(srcPath, destPath);
} else if (entry.isFile()) {
fs.copyFileSync(srcPath, destPath);
}
}
}
function adjustPackageJson(targetDir, projectName) {
const targetPkgPath = path.join(targetDir, 'package.json');
if (!fs.existsSync(targetPkgPath)) {
return;
}
try {
const raw = fs.readFileSync(targetPkgPath, 'utf8');
const pkg = JSON.parse(raw);
pkg.name = projectName;
// 生成的项目不再作为 CLI 包发布,移除 bin 字段
if (pkg.bin) {
delete pkg.bin;
}
pkg.dependencies = {
i18next: '^25.8.0',
};
if (pkg.keywords) {
delete pkg.keywords;
}
if (pkg.author) {
delete pkg.author;
}
// 为生成的项目补充 npm 包导出配置,暴露 dist 下的 client/server bundle
pkg.exports = {
'.': {
import: './dist/server/src/App.js',
types: './dist/server/src/App.d.ts',
},
'./client': {
import: './dist/client/src/App.js',
types: './dist/client/src/App.d.ts',
},
'./server': {
import: './dist/server/src/App.js',
types: './dist/server/src/App.d.ts',
},
'./shares': {
import: './dist/shares/src/App.js',
types: './dist/shares/src/App.d.ts',
},
};
pkg.files = ['dist/**/*'];
fs.writeFileSync(
targetPkgPath,
`${JSON.stringify(pkg, null, 2)}\n`,
'utf8'
);
} catch (err) {
console.warn('调整目标 package.json 失败:', err);
}
}
function writeGitignore(targetDir) {
const gitignorePath = path.join(targetDir, '.gitignore');
const content = [
'node_modules/',
'**/.log/',
'**/dist/',
'.env',
'.env.*',
'!.env.example',
'.DS_Store',
'*.tmp',
'*.swp',
'',
].join('\n');
fs.writeFileSync(gitignorePath, content, 'utf8');
}
function main() {
const args = process.argv.slice(2);
const projectName = args[0];
if (!projectName) {
console.error('\n[创建中止] 未指定项目目录。');
process.exit(1);
}
const cwd = process.cwd();
const targetDir = path.resolve(cwd, projectName);
// if (fs.existsSync(targetDir)) {
// console.error('\n[创建失败] 目标目录已存在');
// console.error(`- 目录名称:${projectName}`);
// console.error(`- 目录路径:${targetDir}`);
// console.error('\n请尝试:');
// console.error('1. 更换一个项目名称重新执行命令;');
// console.error('2. 或者先删除/备份该目录后再重新创建。\n');
// process.exit(1);
// }
CURRENT_TARGET_DIR = targetDir;
// 对 package.json 中的 name 字段做校验,不合规时回退为 my-arena-project
const packageName = isValidPackageName(projectName)
? projectName
: 'my-arena-project';
console.log('\n==========================================');
console.log(' ArenaPro Vite 项目创建向导');
console.log('==========================================');
console.log(`项目名称:${packageName}`);
console.log(`目标目录:${targetDir}`);
console.log('------------------------------------------');
const templateRoot = resolveTemplateRoot();
copyDirRecursive(templateRoot, targetDir);
adjustPackageJson(targetDir, packageName);
writeGitignore(targetDir);
console.log('\n项目文件已生成并完成基础配置。');
console.log('\n下一步操作建议:');
console.log(` 1. 进入项目目录:cd ${projectName}`);
console.log(' 2. 安装依赖:npm install');
console.log(' 3. 启动开发服务器:npm run dev');
}
main();