feng3d-cli 0.0.5 → 0.0.7
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 +65 -61
- package/bin/cli.js +2 -79
- package/dist/index.js +223 -512
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +225 -512
- package/dist/index.umd.cjs.map +1 -1
- package/lib/commands/create.d.ts.map +1 -1
- package/lib/commands/update.d.ts +2 -20
- package/lib/commands/update.d.ts.map +1 -1
- package/lib/index.d.ts +0 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/templates.d.ts +13 -7
- package/lib/templates.d.ts.map +1 -1
- package/lib/versions.d.ts +5 -19
- package/lib/versions.d.ts.map +1 -1
- package/package.json +5 -9
- package/templates/.github/workflows/pages.yml +11 -41
- package/templates/.github/workflows/pull-request.yml +3 -3
- package/templates/.github/workflows/upload-oss.yml +100 -0
- package/templates/.husky/pre-commit +32 -1
- package/templates/gitignore +0 -13
- package/templates/package.json +71 -0
- package/templates/scripts/postdocs.js +46 -0
- package/templates/src/index.ts +6 -0
- package/templates/vite.config.js +1 -0
- package/templates/vitest.config.ts +14 -0
- package/lib/commands/oss.d.ts +0 -11
- package/lib/commands/oss.d.ts.map +0 -1
- package/lib/types/config.d.ts +0 -113
- package/lib/types/config.d.ts.map +0 -1
- package/schemas/feng3d.schema.json +0 -196
- package/templates/feng3d.json +0 -43
package/dist/index.js
CHANGED
|
@@ -1,59 +1,26 @@
|
|
|
1
1
|
import fs from "fs-extra";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
|
-
import OSS from "ali-oss";
|
|
5
|
-
import fs$1 from "fs";
|
|
6
4
|
import chalk from "chalk";
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"@typescript-eslint/parser": "8.32.1",
|
|
16
|
-
"typescript-eslint": "^8.32.1",
|
|
17
|
-
globals: "^14.0.0",
|
|
18
|
-
// 测试相关
|
|
19
|
-
vitest: "^3.1.3",
|
|
20
|
-
"@vitest/coverage-v8": "^3.2.4",
|
|
21
|
-
"happy-dom": "^20.0.11",
|
|
22
|
-
// 构建工具
|
|
23
|
-
vite: "^6.3.5",
|
|
24
|
-
rimraf: "6.0.1",
|
|
25
|
-
"cross-env": "7.0.3",
|
|
26
|
-
// 文档
|
|
27
|
-
typedoc: "^0.28.4",
|
|
28
|
-
// Git hooks
|
|
29
|
-
husky: "^9.1.7",
|
|
30
|
-
"lint-staged": "^15.2.10"
|
|
31
|
-
};
|
|
5
|
+
const __dirname$2 = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const TEMPLATES_DIR$1 = path.resolve(__dirname$2, "../templates");
|
|
7
|
+
function loadVersionsFromTemplate() {
|
|
8
|
+
const packageJsonPath = path.join(TEMPLATES_DIR$1, "package.json");
|
|
9
|
+
const packageJson = fs.readJsonSync(packageJsonPath);
|
|
10
|
+
return packageJson.devDependencies || {};
|
|
11
|
+
}
|
|
12
|
+
const VERSIONS = loadVersionsFromTemplate();
|
|
32
13
|
function getDevDependencies(options = {}) {
|
|
33
|
-
const deps = {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"@typescript-eslint/parser": VERSIONS["@typescript-eslint/parser"],
|
|
37
|
-
"cross-env": VERSIONS["cross-env"],
|
|
38
|
-
eslint: VERSIONS.eslint,
|
|
39
|
-
globals: VERSIONS.globals,
|
|
40
|
-
rimraf: VERSIONS.rimraf,
|
|
41
|
-
tslib: VERSIONS.tslib,
|
|
42
|
-
typescript: VERSIONS.typescript,
|
|
43
|
-
"typescript-eslint": VERSIONS["typescript-eslint"],
|
|
44
|
-
vite: VERSIONS.vite
|
|
45
|
-
};
|
|
46
|
-
if (options.includeVitest !== false) {
|
|
47
|
-
deps.vitest = VERSIONS.vitest;
|
|
14
|
+
const deps = { ...VERSIONS };
|
|
15
|
+
if (options.includeVitest === false) {
|
|
16
|
+
delete deps.vitest;
|
|
48
17
|
}
|
|
49
|
-
if (options.
|
|
50
|
-
deps
|
|
18
|
+
if (options.includeTypedoc === false) {
|
|
19
|
+
delete deps.typedoc;
|
|
51
20
|
}
|
|
52
|
-
if (options.
|
|
53
|
-
deps
|
|
21
|
+
if (options.includeCoverage && !deps["@vitest/coverage-v8"]) {
|
|
22
|
+
deps["@vitest/coverage-v8"] = "^3.2.4";
|
|
54
23
|
}
|
|
55
|
-
deps.husky = VERSIONS.husky;
|
|
56
|
-
deps["lint-staged"] = VERSIONS["lint-staged"];
|
|
57
24
|
return deps;
|
|
58
25
|
}
|
|
59
26
|
const __dirname$1 = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -95,6 +62,9 @@ function getPagesWorkflowTemplate() {
|
|
|
95
62
|
function getPullRequestWorkflowTemplate() {
|
|
96
63
|
return fs.readFileSync(path.join(TEMPLATES_DIR, ".github/workflows/pull-request.yml"), "utf-8");
|
|
97
64
|
}
|
|
65
|
+
function getUploadOssWorkflowTemplate() {
|
|
66
|
+
return fs.readFileSync(path.join(TEMPLATES_DIR, ".github/workflows/upload-oss.yml"), "utf-8");
|
|
67
|
+
}
|
|
98
68
|
function getHuskyPreCommitTemplate() {
|
|
99
69
|
return fs.readFileSync(path.join(TEMPLATES_DIR, ".husky/pre-commit"), "utf-8");
|
|
100
70
|
}
|
|
@@ -112,396 +82,95 @@ function getPrepublishScriptTemplate() {
|
|
|
112
82
|
function getPostpublishScriptTemplate() {
|
|
113
83
|
return fs.readFileSync(path.join(TEMPLATES_DIR, "scripts/postpublish.js"), "utf-8");
|
|
114
84
|
}
|
|
115
|
-
|
|
116
|
-
"
|
|
117
|
-
"./node_modules/feng3d-cli/schemas/feng3d.schema.json"
|
|
118
|
-
];
|
|
119
|
-
function detectSchemaPath(projectDir) {
|
|
120
|
-
for (const schemaPath of SCHEMA_PATHS) {
|
|
121
|
-
const fullPath = path.join(projectDir, schemaPath);
|
|
122
|
-
if (fs.existsSync(fullPath)) {
|
|
123
|
-
return schemaPath;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return SCHEMA_PATHS[1];
|
|
127
|
-
}
|
|
128
|
-
function getFeng3dConfigTemplate(options) {
|
|
129
|
-
const templateContent = fs.readFileSync(path.join(TEMPLATES_DIR, "feng3d.json"), "utf-8");
|
|
130
|
-
const content = templateContent.replace(/\{\{name\}\}/g, options.name);
|
|
131
|
-
const config = JSON.parse(content);
|
|
132
|
-
if (options.schemaPath) {
|
|
133
|
-
config.$schema = options.schemaPath;
|
|
134
|
-
}
|
|
135
|
-
return config;
|
|
136
|
-
}
|
|
137
|
-
const DEFAULT_UPDATE_CONFIG = {
|
|
138
|
-
config: true,
|
|
139
|
-
eslint: true,
|
|
140
|
-
gitignore: true,
|
|
141
|
-
cursorrules: true,
|
|
142
|
-
publish: true,
|
|
143
|
-
pages: true,
|
|
144
|
-
pullRequest: true,
|
|
145
|
-
typedoc: true,
|
|
146
|
-
test: true,
|
|
147
|
-
deps: true,
|
|
148
|
-
husky: true,
|
|
149
|
-
license: true,
|
|
150
|
-
vscode: true,
|
|
151
|
-
tsconfig: true,
|
|
152
|
-
vite: true
|
|
153
|
-
};
|
|
154
|
-
const DEFAULT_CONFIG = {
|
|
155
|
-
eslint: {
|
|
156
|
-
enabled: true,
|
|
157
|
-
ignores: [],
|
|
158
|
-
rules: {}
|
|
159
|
-
},
|
|
160
|
-
vitest: {
|
|
161
|
-
enabled: true,
|
|
162
|
-
testTimeout: 0
|
|
163
|
-
},
|
|
164
|
-
typedoc: {
|
|
165
|
-
enabled: true,
|
|
166
|
-
outDir: "public"
|
|
167
|
-
},
|
|
168
|
-
oss: {
|
|
169
|
-
localDir: "./public",
|
|
170
|
-
ossDir: ""
|
|
171
|
-
},
|
|
172
|
-
templates: {
|
|
173
|
-
examples: true,
|
|
174
|
-
test: true
|
|
175
|
-
},
|
|
176
|
-
update: DEFAULT_UPDATE_CONFIG
|
|
177
|
-
};
|
|
178
|
-
const configPath = "C:/Users/Administrator/oss_config.json";
|
|
179
|
-
async function ossUploadDir(localDirPath, ossDirPath) {
|
|
180
|
-
const config = readConfig(configPath);
|
|
181
|
-
if (!config) {
|
|
182
|
-
console.error("无法读取配置文件");
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
const client = initializeOSS(config);
|
|
186
|
-
const { files, failedFiles } = collectFiles(localDirPath, ossDirPath);
|
|
187
|
-
console.log(`总文件数: ${files.length}`);
|
|
188
|
-
const { successCount, failureCount } = await uploadFiles(files, client, failedFiles);
|
|
189
|
-
console.log(`上传完成: 成功 ${successCount} 个, 失败 ${failureCount} 个`);
|
|
190
|
-
if (failureCount > 0) {
|
|
191
|
-
console.log("上传失败的文件列表:");
|
|
192
|
-
failedFiles.forEach((file) => console.log(file));
|
|
193
|
-
}
|
|
194
|
-
if (successCount > 0) {
|
|
195
|
-
const baseUrl = config.baseUrl || `https://${config.bucket}.${config.region}.aliyuncs.com`;
|
|
196
|
-
const accessUrl = `${baseUrl}/${ossDirPath}/`;
|
|
197
|
-
console.log(`
|
|
198
|
-
📎 访问路径: ${accessUrl}`);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
function readConfig(filePath) {
|
|
202
|
-
try {
|
|
203
|
-
const fileContent = fs$1.readFileSync(filePath, "utf8");
|
|
204
|
-
const config = JSON.parse(fileContent);
|
|
205
|
-
return config;
|
|
206
|
-
} catch (error) {
|
|
207
|
-
console.error("读取或解析配置文件时出错:", error);
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
function initializeOSS(config) {
|
|
212
|
-
return new OSS({
|
|
213
|
-
region: config.region,
|
|
214
|
-
accessKeyId: config.accessKeyId,
|
|
215
|
-
accessKeySecret: config.accessKeySecret,
|
|
216
|
-
bucket: config.bucket
|
|
217
|
-
});
|
|
85
|
+
function getPostdocsScriptTemplate() {
|
|
86
|
+
return fs.readFileSync(path.join(TEMPLATES_DIR, "scripts/postdocs.js"), "utf-8");
|
|
218
87
|
}
|
|
219
|
-
function
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
function traverseDirectory(currentDirPath, currentOssPath) {
|
|
223
|
-
const items = fs$1.readdirSync(currentDirPath);
|
|
224
|
-
for (const item of items) {
|
|
225
|
-
const localFilePath = path.join(currentDirPath, item);
|
|
226
|
-
const ossFilePath = `${currentOssPath}/${item}`;
|
|
227
|
-
if (fs$1.statSync(localFilePath).isDirectory()) {
|
|
228
|
-
traverseDirectory(localFilePath, ossFilePath);
|
|
229
|
-
} else {
|
|
230
|
-
files.push({ localFilePath, ossFilePath });
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
traverseDirectory(dirPath, ossDirPath);
|
|
235
|
-
return { files, failedFiles };
|
|
236
|
-
}
|
|
237
|
-
function renderProgressBar(current, total, barLength = 30) {
|
|
238
|
-
const percent = current / total;
|
|
239
|
-
const filled = Math.round(barLength * percent);
|
|
240
|
-
const empty = barLength - filled;
|
|
241
|
-
const bar = "█".repeat(filled) + "░".repeat(empty);
|
|
242
|
-
const percentText = (percent * 100).toFixed(0).padStart(3, " ");
|
|
243
|
-
return `[${bar}] ${percentText}% (${current}/${total})`;
|
|
244
|
-
}
|
|
245
|
-
async function uploadFiles(files, client, failedFiles) {
|
|
246
|
-
let successCount = 0;
|
|
247
|
-
let failureCount = 0;
|
|
248
|
-
let uploadedCount = 0;
|
|
249
|
-
const total = files.length;
|
|
250
|
-
process.stdout.write(`上传进度: ${renderProgressBar(0, total)}`);
|
|
251
|
-
for (const { localFilePath, ossFilePath } of files) {
|
|
252
|
-
try {
|
|
253
|
-
await client.put(ossFilePath, localFilePath);
|
|
254
|
-
successCount++;
|
|
255
|
-
} catch (e) {
|
|
256
|
-
process.stdout.write("\n");
|
|
257
|
-
console.error(`文件上传失败: ${localFilePath}`, e);
|
|
258
|
-
failedFiles.push(localFilePath);
|
|
259
|
-
failureCount++;
|
|
260
|
-
}
|
|
261
|
-
uploadedCount++;
|
|
262
|
-
process.stdout.write(`\r上传进度: ${renderProgressBar(uploadedCount, total)}`);
|
|
263
|
-
}
|
|
264
|
-
process.stdout.write("\n");
|
|
265
|
-
return { successCount, failureCount, uploadedCount };
|
|
266
|
-
}
|
|
267
|
-
const AUTO_GENERATED_FILES = [
|
|
268
|
-
{ path: ".cursorrules", getTemplate: () => getCursorrrulesTemplate() },
|
|
269
|
-
{ path: "eslint.config.js", getTemplate: () => getEslintConfigTemplate() },
|
|
270
|
-
{ path: "typedoc.json", getTemplate: (ctx) => getTypedocConfigTemplate({ repoName: ctx.repoName }) },
|
|
271
|
-
{ path: "test/_.test.ts", getTemplate: (ctx) => getTestIndexTemplate({ name: ctx.name }) },
|
|
272
|
-
{ path: ".husky/pre-commit", getTemplate: () => getHuskyPreCommitTemplate() },
|
|
273
|
-
{ path: ".vscode/settings.json", getTemplate: () => getVscodeSettingsTemplate() },
|
|
274
|
-
{ path: "tsconfig.json", getTemplate: () => getTsconfigTemplateString() },
|
|
275
|
-
{ path: "vite.config.js", getTemplate: () => getViteConfigTemplate() },
|
|
276
|
-
{ path: "scripts/prepublish.js", getTemplate: () => getPrepublishScriptTemplate() },
|
|
277
|
-
{ path: "scripts/postpublish.js", getTemplate: () => getPostpublishScriptTemplate() }
|
|
278
|
-
];
|
|
279
|
-
async function isFileInGitignore(projectDir, filePath) {
|
|
280
|
-
const gitignorePath = path.join(projectDir, ".gitignore");
|
|
281
|
-
if (!await fs.pathExists(gitignorePath)) {
|
|
282
|
-
return false;
|
|
283
|
-
}
|
|
284
|
-
const gitignoreContent = await fs.readFile(gitignorePath, "utf-8");
|
|
285
|
-
const escapedPath = filePath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
286
|
-
const regex = new RegExp(`^${escapedPath}$`, "m");
|
|
287
|
-
return regex.test(gitignoreContent);
|
|
288
|
-
}
|
|
289
|
-
async function updateFeng3dConfig(projectDir) {
|
|
290
|
-
const configPath2 = path.join(projectDir, "feng3d.json");
|
|
291
|
-
const schemaPath = detectSchemaPath(projectDir);
|
|
292
|
-
const packageJsonPath = path.join(projectDir, "package.json");
|
|
293
|
-
const packageJson = await fs.readJson(packageJsonPath);
|
|
294
|
-
const name = packageJson.name || path.basename(projectDir);
|
|
295
|
-
const isInGitignore = await isFileInGitignore(projectDir, "feng3d.json");
|
|
296
|
-
if (!await fs.pathExists(configPath2) || isInGitignore) {
|
|
297
|
-
const configTemplate = getFeng3dConfigTemplate({ name, schemaPath });
|
|
298
|
-
await fs.writeJson(configPath2, configTemplate, { spaces: 4 });
|
|
299
|
-
console.log(chalk.gray(isInGitignore ? " 覆盖: feng3d.json(在忽略列表中)" : " 创建: feng3d.json"));
|
|
300
|
-
} else {
|
|
301
|
-
try {
|
|
302
|
-
const configData = await fs.readJson(configPath2);
|
|
303
|
-
let updated = false;
|
|
304
|
-
if (configData.$schema !== schemaPath) {
|
|
305
|
-
configData.$schema = schemaPath;
|
|
306
|
-
updated = true;
|
|
307
|
-
}
|
|
308
|
-
if (configData.name !== name) {
|
|
309
|
-
configData.name = name;
|
|
310
|
-
updated = true;
|
|
311
|
-
}
|
|
312
|
-
if (updated) {
|
|
313
|
-
await fs.writeJson(configPath2, configData, { spaces: 4 });
|
|
314
|
-
console.log(chalk.gray(" 更新: feng3d.json"));
|
|
315
|
-
} else {
|
|
316
|
-
console.log(chalk.gray(" 跳过: feng3d.json(无需更新)"));
|
|
317
|
-
}
|
|
318
|
-
} catch (error) {
|
|
319
|
-
const configTemplate = getFeng3dConfigTemplate({ name, schemaPath });
|
|
320
|
-
await fs.writeJson(configPath2, configTemplate, { spaces: 4 });
|
|
321
|
-
console.log(chalk.gray(" 重建: feng3d.json"));
|
|
322
|
-
}
|
|
323
|
-
}
|
|
88
|
+
function getSrcIndexTemplate(options) {
|
|
89
|
+
const template = fs.readFileSync(path.join(TEMPLATES_DIR, "src/index.ts"), "utf-8");
|
|
90
|
+
return template.replace(/\{\{name\}\}/g, options.name);
|
|
324
91
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
if (!await fs.pathExists(configPath2)) {
|
|
328
|
-
return DEFAULT_CONFIG;
|
|
329
|
-
}
|
|
330
|
-
try {
|
|
331
|
-
const configData = await fs.readJson(configPath2);
|
|
332
|
-
return { ...DEFAULT_CONFIG, ...configData };
|
|
333
|
-
} catch (error) {
|
|
334
|
-
console.log(chalk.yellow(` 警告: 无法加载 feng3d.json,使用默认配置 (${error})`));
|
|
335
|
-
return DEFAULT_CONFIG;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
function hasAnyUpdateOption(options) {
|
|
339
|
-
return !!(options.config || options.eslint || options.gitignore || options.cursorrules || options.publish || options.pages || options.pullRequest || options.typedoc || options.test || options.deps || options.husky || options.license || options.vscode || options.tsconfig);
|
|
340
|
-
}
|
|
341
|
-
function mergeUpdateOptions(cliOptions, configUpdate) {
|
|
342
|
-
if (cliOptions.all) {
|
|
343
|
-
return DEFAULT_UPDATE_CONFIG;
|
|
344
|
-
}
|
|
345
|
-
if (hasAnyUpdateOption(cliOptions)) {
|
|
346
|
-
return {
|
|
347
|
-
config: cliOptions.config || false,
|
|
348
|
-
eslint: cliOptions.eslint || false,
|
|
349
|
-
gitignore: cliOptions.gitignore || false,
|
|
350
|
-
cursorrules: cliOptions.cursorrules || false,
|
|
351
|
-
publish: cliOptions.publish || false,
|
|
352
|
-
pages: cliOptions.pages || false,
|
|
353
|
-
pullRequest: cliOptions.pullRequest || false,
|
|
354
|
-
typedoc: cliOptions.typedoc || false,
|
|
355
|
-
test: cliOptions.test || false,
|
|
356
|
-
deps: cliOptions.deps || false,
|
|
357
|
-
husky: cliOptions.husky || false,
|
|
358
|
-
license: cliOptions.license || false,
|
|
359
|
-
vscode: cliOptions.vscode || false,
|
|
360
|
-
tsconfig: cliOptions.tsconfig || false
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
return { ...DEFAULT_UPDATE_CONFIG, ...configUpdate };
|
|
92
|
+
function getVitestConfigTemplate() {
|
|
93
|
+
return fs.readFileSync(path.join(TEMPLATES_DIR, "vitest.config.ts"), "utf-8");
|
|
364
94
|
}
|
|
365
|
-
async function updateProject(
|
|
366
|
-
const projectDir = path.resolve(
|
|
95
|
+
async function updateProject(directory = ".") {
|
|
96
|
+
const projectDir = path.resolve(directory);
|
|
367
97
|
const packageJsonPath = path.join(projectDir, "package.json");
|
|
368
98
|
if (!await fs.pathExists(packageJsonPath)) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
99
|
+
await fs.ensureDir(projectDir);
|
|
100
|
+
const dirName = path.basename(projectDir);
|
|
101
|
+
const initialPackageJson = {
|
|
102
|
+
name: `@feng3d/${dirName}`,
|
|
103
|
+
version: "0.0.1",
|
|
104
|
+
description: ""
|
|
105
|
+
};
|
|
106
|
+
await fs.writeJson(packageJsonPath, initialPackageJson, { spaces: 4 });
|
|
107
|
+
console.log(chalk.gray(" 创建: package.json"));
|
|
108
|
+
const srcDir = path.join(projectDir, "src");
|
|
109
|
+
await fs.ensureDir(srcDir);
|
|
110
|
+
await fs.writeFile(path.join(srcDir, "index.ts"), getSrcIndexTemplate({ name: `@feng3d/${dirName}` }));
|
|
111
|
+
console.log(chalk.gray(" 创建: src/index.ts"));
|
|
375
112
|
}
|
|
376
113
|
const packageJson = await fs.readJson(packageJsonPath);
|
|
377
114
|
const name = packageJson.name || path.basename(projectDir);
|
|
378
115
|
const repoName = name.replace(/^@[^/]+\//, "");
|
|
379
|
-
const templateContext = { name, repoName };
|
|
380
|
-
if (updateConfig.gitignore) {
|
|
381
|
-
const gitignorePath = path.join(projectDir, ".gitignore");
|
|
382
|
-
if (!await fs.pathExists(gitignorePath)) {
|
|
383
|
-
await fs.writeFile(gitignorePath, getGitignoreTemplate());
|
|
384
|
-
console.log(chalk.gray(" 创建: .gitignore"));
|
|
385
|
-
} else {
|
|
386
|
-
console.log(chalk.gray(" 跳过: .gitignore(已存在)"));
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
if (updateConfig.cursorrules) {
|
|
390
|
-
await fs.writeFile(path.join(projectDir, ".cursorrules"), getCursorrrulesTemplate());
|
|
391
|
-
console.log(chalk.gray(" 更新: .cursorrules"));
|
|
392
|
-
}
|
|
393
|
-
if (updateConfig.eslint) {
|
|
394
|
-
if (config.eslint?.enabled !== false) {
|
|
395
|
-
await createEslintConfigFile(projectDir);
|
|
396
|
-
console.log(chalk.gray(" 更新: eslint.config.js"));
|
|
397
|
-
} else {
|
|
398
|
-
console.log(chalk.gray(" 跳过: eslint.config.js(配置中已禁用)"));
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
if (updateConfig.publish) {
|
|
402
|
-
await fs.ensureDir(path.join(projectDir, ".github/workflows"));
|
|
403
|
-
await fs.writeFile(path.join(projectDir, ".github/workflows/publish.yml"), getPublishWorkflowTemplate());
|
|
404
|
-
console.log(chalk.gray(" 更新: .github/workflows/publish.yml"));
|
|
405
|
-
}
|
|
406
|
-
if (updateConfig.pages) {
|
|
407
|
-
await fs.ensureDir(path.join(projectDir, ".github/workflows"));
|
|
408
|
-
await fs.writeFile(path.join(projectDir, ".github/workflows/pages.yml"), getPagesWorkflowTemplate());
|
|
409
|
-
console.log(chalk.gray(" 更新: .github/workflows/pages.yml"));
|
|
410
|
-
}
|
|
411
|
-
if (updateConfig.pullRequest) {
|
|
412
|
-
await fs.ensureDir(path.join(projectDir, ".github/workflows"));
|
|
413
|
-
await fs.writeFile(path.join(projectDir, ".github/workflows/pull-request.yml"), getPullRequestWorkflowTemplate());
|
|
414
|
-
console.log(chalk.gray(" 更新: .github/workflows/pull-request.yml"));
|
|
415
|
-
}
|
|
416
|
-
if (updateConfig.typedoc) {
|
|
417
|
-
if (config.typedoc?.enabled !== false) {
|
|
418
|
-
const typedocContent = getTypedocConfigTemplate({ repoName });
|
|
419
|
-
await fs.writeFile(path.join(projectDir, "typedoc.json"), typedocContent);
|
|
420
|
-
console.log(chalk.gray(" 更新: typedoc.json"));
|
|
421
|
-
} else {
|
|
422
|
-
console.log(chalk.gray(" 跳过: typedoc.json(配置中已禁用)"));
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
if (updateConfig.test) {
|
|
426
|
-
if (config.vitest?.enabled !== false) {
|
|
427
|
-
const testDir = path.join(projectDir, "test");
|
|
428
|
-
const testFilePath = path.join(testDir, "_.test.ts");
|
|
429
|
-
let hasOtherFiles = false;
|
|
430
|
-
if (await fs.pathExists(testDir)) {
|
|
431
|
-
const files = await fs.readdir(testDir);
|
|
432
|
-
hasOtherFiles = files.some((file) => file !== "_.test.ts");
|
|
433
|
-
}
|
|
434
|
-
if (!hasOtherFiles) {
|
|
435
|
-
await fs.ensureDir(testDir);
|
|
436
|
-
const testContent = getTestIndexTemplate();
|
|
437
|
-
await fs.writeFile(testFilePath, testContent);
|
|
438
|
-
console.log(chalk.gray(" 更新: test/_.test.ts"));
|
|
439
|
-
} else {
|
|
440
|
-
console.log(chalk.gray(" 跳过: test/_.test.ts(测试目录已有其他文件)"));
|
|
441
|
-
}
|
|
442
|
-
} else {
|
|
443
|
-
console.log(chalk.gray(" 跳过: test/_.test.ts(vitest 配置中已禁用)"));
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
if (updateConfig.deps) {
|
|
447
|
-
await updateDependencies(projectDir, config);
|
|
448
|
-
console.log(chalk.gray(" 更新: package.json devDependencies"));
|
|
449
|
-
}
|
|
450
|
-
if (updateConfig.husky) {
|
|
451
|
-
await fs.ensureDir(path.join(projectDir, ".husky"));
|
|
452
|
-
await fs.writeFile(path.join(projectDir, ".husky/pre-commit"), getHuskyPreCommitTemplate());
|
|
453
|
-
console.log(chalk.gray(" 更新: .husky/pre-commit"));
|
|
454
|
-
await updateHuskyConfig(projectDir);
|
|
455
|
-
}
|
|
456
|
-
if (updateConfig.license) {
|
|
457
|
-
const licensePath = path.join(projectDir, "LICENSE");
|
|
458
|
-
if (!await fs.pathExists(licensePath)) {
|
|
459
|
-
await fs.writeFile(licensePath, getLicenseTemplate());
|
|
460
|
-
console.log(chalk.gray(" 创建: LICENSE"));
|
|
461
|
-
} else {
|
|
462
|
-
console.log(chalk.gray(" 跳过: LICENSE(已存在)"));
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
if (updateConfig.vscode) {
|
|
466
|
-
await fs.ensureDir(path.join(projectDir, ".vscode"));
|
|
467
|
-
await fs.writeFile(path.join(projectDir, ".vscode/settings.json"), getVscodeSettingsTemplate());
|
|
468
|
-
console.log(chalk.gray(" 更新: .vscode/settings.json"));
|
|
469
|
-
}
|
|
470
116
|
const isFeng3dCli = name === "feng3d-cli";
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
117
|
+
await fs.writeFile(path.join(projectDir, ".gitignore"), getGitignoreTemplate());
|
|
118
|
+
console.log(chalk.gray(" 更新: .gitignore"));
|
|
119
|
+
await fs.writeFile(path.join(projectDir, ".cursorrules"), getCursorrrulesTemplate());
|
|
120
|
+
console.log(chalk.gray(" 更新: .cursorrules"));
|
|
121
|
+
await createEslintConfigFile(projectDir);
|
|
122
|
+
console.log(chalk.gray(" 更新: eslint.config.js"));
|
|
123
|
+
await fs.ensureDir(path.join(projectDir, ".github/workflows"));
|
|
124
|
+
await fs.writeFile(path.join(projectDir, ".github/workflows/publish.yml"), getPublishWorkflowTemplate());
|
|
125
|
+
console.log(chalk.gray(" 更新: .github/workflows/publish.yml"));
|
|
126
|
+
await fs.writeFile(path.join(projectDir, ".github/workflows/pages.yml"), getPagesWorkflowTemplate());
|
|
127
|
+
console.log(chalk.gray(" 更新: .github/workflows/pages.yml"));
|
|
128
|
+
await fs.writeFile(path.join(projectDir, ".github/workflows/pull-request.yml"), getPullRequestWorkflowTemplate());
|
|
129
|
+
console.log(chalk.gray(" 更新: .github/workflows/pull-request.yml"));
|
|
130
|
+
await fs.writeFile(path.join(projectDir, ".github/workflows/upload-oss.yml"), getUploadOssWorkflowTemplate());
|
|
131
|
+
console.log(chalk.gray(" 更新: .github/workflows/upload-oss.yml"));
|
|
132
|
+
const typedocContent = getTypedocConfigTemplate({ repoName });
|
|
133
|
+
await fs.writeFile(path.join(projectDir, "typedoc.json"), typedocContent);
|
|
134
|
+
console.log(chalk.gray(" 更新: typedoc.json"));
|
|
135
|
+
const testDir = path.join(projectDir, "test");
|
|
136
|
+
await fs.ensureDir(testDir);
|
|
137
|
+
const testContent = getTestIndexTemplate();
|
|
138
|
+
await fs.writeFile(path.join(testDir, "_.test.ts"), testContent);
|
|
139
|
+
console.log(chalk.gray(" 更新: test/_.test.ts"));
|
|
140
|
+
await updateDependencies(projectDir);
|
|
141
|
+
console.log(chalk.gray(" 更新: package.json devDependencies"));
|
|
142
|
+
await fs.ensureDir(path.join(projectDir, ".husky"));
|
|
143
|
+
await fs.writeFile(path.join(projectDir, ".husky/pre-commit"), getHuskyPreCommitTemplate());
|
|
144
|
+
console.log(chalk.gray(" 更新: .husky/pre-commit"));
|
|
145
|
+
await updateHuskyConfig(projectDir);
|
|
146
|
+
await fs.writeFile(path.join(projectDir, "LICENSE"), getLicenseTemplate());
|
|
147
|
+
console.log(chalk.gray(" 更新: LICENSE"));
|
|
148
|
+
await fs.ensureDir(path.join(projectDir, ".vscode"));
|
|
149
|
+
await fs.writeFile(path.join(projectDir, ".vscode/settings.json"), getVscodeSettingsTemplate());
|
|
150
|
+
console.log(chalk.gray(" 更新: .vscode/settings.json"));
|
|
151
|
+
if (!isFeng3dCli) {
|
|
152
|
+
await fs.writeFile(path.join(projectDir, "tsconfig.json"), getTsconfigTemplateString());
|
|
153
|
+
console.log(chalk.gray(" 更新: tsconfig.json"));
|
|
154
|
+
}
|
|
155
|
+
if (!isFeng3dCli) {
|
|
156
|
+
await fs.writeFile(path.join(projectDir, "vite.config.js"), getViteConfigTemplate());
|
|
157
|
+
console.log(chalk.gray(" 更新: vite.config.js"));
|
|
158
|
+
}
|
|
159
|
+
if (!isFeng3dCli) {
|
|
160
|
+
await fs.writeFile(path.join(projectDir, "vitest.config.ts"), getVitestConfigTemplate());
|
|
161
|
+
console.log(chalk.gray(" 更新: vitest.config.ts"));
|
|
490
162
|
}
|
|
491
163
|
const scriptsDir = path.join(projectDir, "scripts");
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
164
|
+
await fs.ensureDir(scriptsDir);
|
|
165
|
+
await fs.writeFile(path.join(scriptsDir, "prepublish.js"), getPrepublishScriptTemplate());
|
|
166
|
+
console.log(chalk.gray(" 更新: scripts/prepublish.js"));
|
|
167
|
+
await fs.writeFile(path.join(scriptsDir, "postpublish.js"), getPostpublishScriptTemplate());
|
|
168
|
+
console.log(chalk.gray(" 更新: scripts/postpublish.js"));
|
|
169
|
+
const examplesDir = path.join(projectDir, "examples");
|
|
170
|
+
if (await fs.pathExists(examplesDir)) {
|
|
171
|
+
await fs.writeFile(path.join(scriptsDir, "postdocs.js"), getPostdocsScriptTemplate());
|
|
172
|
+
console.log(chalk.gray(" 更新: scripts/postdocs.js"));
|
|
498
173
|
}
|
|
499
|
-
if (!await fs.pathExists(postpublishPath)) {
|
|
500
|
-
await fs.ensureDir(scriptsDir);
|
|
501
|
-
await fs.writeFile(postpublishPath, getPostpublishScriptTemplate());
|
|
502
|
-
console.log(chalk.gray(" 创建: scripts/postpublish.js"));
|
|
503
|
-
}
|
|
504
|
-
await syncGitignoreForModifiedFiles(projectDir, templateContext, name);
|
|
505
174
|
}
|
|
506
175
|
async function createEslintConfigFile(projectDir) {
|
|
507
176
|
await fs.writeFile(path.join(projectDir, "eslint.config.js"), getEslintConfigTemplate());
|
|
@@ -510,15 +179,74 @@ function detectIndent(content) {
|
|
|
510
179
|
const match = content.match(/^[ \t]+/m);
|
|
511
180
|
return match ? match[0] : " ";
|
|
512
181
|
}
|
|
513
|
-
|
|
182
|
+
const PACKAGE_JSON_FIELD_ORDER = [
|
|
183
|
+
"name",
|
|
184
|
+
"version",
|
|
185
|
+
"description",
|
|
186
|
+
"homepage",
|
|
187
|
+
"author",
|
|
188
|
+
"license",
|
|
189
|
+
"type",
|
|
190
|
+
"main",
|
|
191
|
+
"types",
|
|
192
|
+
"module",
|
|
193
|
+
"exports",
|
|
194
|
+
"bin",
|
|
195
|
+
"scripts",
|
|
196
|
+
"repository",
|
|
197
|
+
"publishConfig",
|
|
198
|
+
"files",
|
|
199
|
+
"devDependencies",
|
|
200
|
+
"dependencies",
|
|
201
|
+
"peerDependencies",
|
|
202
|
+
"lint-staged"
|
|
203
|
+
];
|
|
204
|
+
const SCRIPTS_ORDER = [
|
|
205
|
+
"examples:dev",
|
|
206
|
+
"test_web",
|
|
207
|
+
"postdocs",
|
|
208
|
+
"clean",
|
|
209
|
+
"build",
|
|
210
|
+
"watch",
|
|
211
|
+
"test",
|
|
212
|
+
"lint",
|
|
213
|
+
"lintfix",
|
|
214
|
+
"docs",
|
|
215
|
+
"prepublishOnly",
|
|
216
|
+
"release",
|
|
217
|
+
"postpublish",
|
|
218
|
+
"prepare"
|
|
219
|
+
];
|
|
220
|
+
function reorderObject(obj, order) {
|
|
221
|
+
const ordered = {};
|
|
222
|
+
for (const key of order) {
|
|
223
|
+
if (key in obj) {
|
|
224
|
+
ordered[key] = obj[key];
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
for (const key of Object.keys(obj)) {
|
|
228
|
+
if (!(key in ordered)) {
|
|
229
|
+
ordered[key] = obj[key];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return ordered;
|
|
233
|
+
}
|
|
234
|
+
function reorderPackageJson(packageJson) {
|
|
235
|
+
const ordered = reorderObject(packageJson, PACKAGE_JSON_FIELD_ORDER);
|
|
236
|
+
if (ordered.scripts && typeof ordered.scripts === "object") {
|
|
237
|
+
ordered.scripts = reorderObject(ordered.scripts, SCRIPTS_ORDER);
|
|
238
|
+
}
|
|
239
|
+
return ordered;
|
|
240
|
+
}
|
|
241
|
+
async function updateDependencies(projectDir) {
|
|
514
242
|
const packageJsonPath = path.join(projectDir, "package.json");
|
|
515
243
|
const originalContent = await fs.readFile(packageJsonPath, "utf-8");
|
|
516
244
|
const indent = detectIndent(originalContent);
|
|
517
245
|
const hasTrailingNewline = originalContent.endsWith("\n");
|
|
518
246
|
const packageJson = JSON.parse(originalContent);
|
|
519
247
|
const standardDeps = getDevDependencies({
|
|
520
|
-
includeVitest:
|
|
521
|
-
includeTypedoc:
|
|
248
|
+
includeVitest: true,
|
|
249
|
+
includeTypedoc: true
|
|
522
250
|
});
|
|
523
251
|
let updated = false;
|
|
524
252
|
if (!packageJson.devDependencies) {
|
|
@@ -541,23 +269,59 @@ async function updateDependencies(projectDir, config) {
|
|
|
541
269
|
const standardScripts = {
|
|
542
270
|
clean: "rimraf lib dist public",
|
|
543
271
|
build: "vite build && tsc",
|
|
272
|
+
watch: 'concurrently "vite build --watch" "tsc -w" "vitest"',
|
|
273
|
+
test: "vitest run",
|
|
544
274
|
lint: "eslint . --ext .js,.ts --max-warnings 0",
|
|
545
275
|
lintfix: "npm run lint -- --fix",
|
|
546
276
|
docs: "typedoc",
|
|
547
|
-
upload_oss: "npm run docs && npx feng3d-cli oss_upload_dir",
|
|
548
|
-
update: "npx feng3d-cli update && npm install",
|
|
549
277
|
prepublishOnly: "node scripts/prepublish.js",
|
|
278
|
+
release: "npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish",
|
|
550
279
|
postpublish: "node scripts/postpublish.js"
|
|
551
280
|
};
|
|
281
|
+
const examplesDir = path.join(projectDir, "examples");
|
|
282
|
+
if (await fs.pathExists(examplesDir)) {
|
|
283
|
+
standardScripts["examples:dev"] = "cd examples && npm run dev";
|
|
284
|
+
standardScripts.postdocs = "node scripts/postdocs.js && cd examples && vite build --outDir ../public";
|
|
285
|
+
}
|
|
552
286
|
for (const [key, value] of Object.entries(standardScripts)) {
|
|
553
|
-
if (
|
|
287
|
+
if (packageJson.scripts[key] !== value) {
|
|
554
288
|
packageJson.scripts[key] = value;
|
|
555
289
|
updated = true;
|
|
556
|
-
console.log(chalk.gray(`
|
|
290
|
+
console.log(chalk.gray(` 更新: scripts.${key}`));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (packageJson.type !== "module") {
|
|
294
|
+
packageJson.type = "module";
|
|
295
|
+
updated = true;
|
|
296
|
+
console.log(chalk.gray(' 更新: type = "module"'));
|
|
297
|
+
}
|
|
298
|
+
const entryPoints = {
|
|
299
|
+
main: "./src/index.ts",
|
|
300
|
+
types: "./src/index.ts",
|
|
301
|
+
module: "./src/index.ts"
|
|
302
|
+
};
|
|
303
|
+
for (const [key, value] of Object.entries(entryPoints)) {
|
|
304
|
+
if (packageJson[key] !== value) {
|
|
305
|
+
packageJson[key] = value;
|
|
306
|
+
updated = true;
|
|
307
|
+
console.log(chalk.gray(` 更新: ${key} = "${value}"`));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const standardExports = {
|
|
311
|
+
".": {
|
|
312
|
+
types: "./src/index.ts",
|
|
313
|
+
import: "./src/index.ts",
|
|
314
|
+
require: "./src/index.ts"
|
|
557
315
|
}
|
|
316
|
+
};
|
|
317
|
+
if (JSON.stringify(packageJson.exports) !== JSON.stringify(standardExports)) {
|
|
318
|
+
packageJson.exports = standardExports;
|
|
319
|
+
updated = true;
|
|
320
|
+
console.log(chalk.gray(" 更新: exports"));
|
|
558
321
|
}
|
|
559
322
|
if (updated) {
|
|
560
|
-
|
|
323
|
+
const orderedPackageJson = reorderPackageJson(packageJson);
|
|
324
|
+
let newContent = JSON.stringify(orderedPackageJson, null, indent);
|
|
561
325
|
if (hasTrailingNewline) {
|
|
562
326
|
newContent += "\n";
|
|
563
327
|
}
|
|
@@ -574,15 +338,15 @@ async function updateHuskyConfig(projectDir) {
|
|
|
574
338
|
if (!packageJson.devDependencies) {
|
|
575
339
|
packageJson.devDependencies = {};
|
|
576
340
|
}
|
|
577
|
-
if (
|
|
341
|
+
if (packageJson.devDependencies.husky !== VERSIONS.husky) {
|
|
578
342
|
packageJson.devDependencies.husky = VERSIONS.husky;
|
|
579
343
|
updated = true;
|
|
580
|
-
console.log(chalk.gray(`
|
|
344
|
+
console.log(chalk.gray(` 更新: devDependencies.husky = "${VERSIONS.husky}"`));
|
|
581
345
|
}
|
|
582
|
-
if (
|
|
346
|
+
if (packageJson.devDependencies["lint-staged"] !== VERSIONS["lint-staged"]) {
|
|
583
347
|
packageJson.devDependencies["lint-staged"] = VERSIONS["lint-staged"];
|
|
584
348
|
updated = true;
|
|
585
|
-
console.log(chalk.gray(`
|
|
349
|
+
console.log(chalk.gray(` 更新: devDependencies.lint-staged = "${VERSIONS["lint-staged"]}"`));
|
|
586
350
|
}
|
|
587
351
|
if (!packageJson.scripts) {
|
|
588
352
|
packageJson.scripts = {};
|
|
@@ -590,77 +354,25 @@ async function updateHuskyConfig(projectDir) {
|
|
|
590
354
|
if (packageJson.scripts.prepare !== "husky") {
|
|
591
355
|
packageJson.scripts.prepare = "husky";
|
|
592
356
|
updated = true;
|
|
593
|
-
console.log(chalk.gray('
|
|
357
|
+
console.log(chalk.gray(' 更新: scripts.prepare = "husky"'));
|
|
594
358
|
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
359
|
+
const standardLintStaged = {
|
|
360
|
+
"*.{js,ts}": ["eslint --fix --max-warnings 0"]
|
|
361
|
+
};
|
|
362
|
+
if (JSON.stringify(packageJson["lint-staged"]) !== JSON.stringify(standardLintStaged)) {
|
|
363
|
+
packageJson["lint-staged"] = standardLintStaged;
|
|
599
364
|
updated = true;
|
|
600
|
-
console.log(chalk.gray("
|
|
365
|
+
console.log(chalk.gray(" 更新: lint-staged 配置"));
|
|
601
366
|
}
|
|
602
367
|
if (updated) {
|
|
603
|
-
|
|
368
|
+
const orderedPackageJson = reorderPackageJson(packageJson);
|
|
369
|
+
let newContent = JSON.stringify(orderedPackageJson, null, indent);
|
|
604
370
|
if (hasTrailingNewline) {
|
|
605
371
|
newContent += "\n";
|
|
606
372
|
}
|
|
607
373
|
await fs.writeFile(packageJsonPath, newContent);
|
|
608
374
|
}
|
|
609
375
|
}
|
|
610
|
-
const AUTO_GENERATED_COMMENT = `# 以下文件可由 feng3d-cli 自动生成,无需提交
|
|
611
|
-
# 运行 \`feng3d-cli update\` 可重新生成`;
|
|
612
|
-
async function syncGitignoreForModifiedFiles(projectDir, _ctx, projectName) {
|
|
613
|
-
const gitignorePath = path.join(projectDir, ".gitignore");
|
|
614
|
-
if (!await fs.pathExists(gitignorePath)) {
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
let gitignoreContent = await fs.readFile(gitignorePath, "utf-8");
|
|
618
|
-
let modified = false;
|
|
619
|
-
const isFeng3dCli = projectName === "feng3d-cli";
|
|
620
|
-
const skipFiles = isFeng3dCli ? ["tsconfig.json", "vite.config.js"] : [];
|
|
621
|
-
const filesToAdd = [];
|
|
622
|
-
const feng3dConfigPath = "feng3d.json";
|
|
623
|
-
const escapedFeng3dPath = feng3dConfigPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
624
|
-
const feng3dRegex = new RegExp(`^${escapedFeng3dPath}$`, "m");
|
|
625
|
-
if (!feng3dRegex.test(gitignoreContent)) {
|
|
626
|
-
filesToAdd.push(feng3dConfigPath);
|
|
627
|
-
}
|
|
628
|
-
for (const file of AUTO_GENERATED_FILES) {
|
|
629
|
-
if (skipFiles.includes(file.path)) {
|
|
630
|
-
continue;
|
|
631
|
-
}
|
|
632
|
-
const escapedPath = file.path.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
633
|
-
const regex = new RegExp(`^${escapedPath}$`, "m");
|
|
634
|
-
if (!regex.test(gitignoreContent)) {
|
|
635
|
-
const filePath = path.join(projectDir, file.path);
|
|
636
|
-
if (await fs.pathExists(filePath)) {
|
|
637
|
-
const fileContent = await fs.readFile(filePath, "utf-8");
|
|
638
|
-
const templateContent = file.getTemplate(_ctx);
|
|
639
|
-
if (fileContent.trim() === templateContent.trim()) {
|
|
640
|
-
filesToAdd.push(file.path);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
if (filesToAdd.length > 0) {
|
|
646
|
-
const hasComment = gitignoreContent.includes("# 以下文件可由 feng3d-cli 自动生成");
|
|
647
|
-
if (!hasComment) {
|
|
648
|
-
gitignoreContent = gitignoreContent.trim() + "\n\n" + AUTO_GENERATED_COMMENT + "\n" + filesToAdd.join("\n") + "\n";
|
|
649
|
-
} else {
|
|
650
|
-
for (const filePath of filesToAdd) {
|
|
651
|
-
gitignoreContent = gitignoreContent.trim() + "\n" + filePath + "\n";
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
modified = true;
|
|
655
|
-
for (const filePath of filesToAdd) {
|
|
656
|
-
console.log(chalk.gray(` 添加到 .gitignore: ${filePath}`));
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
if (modified) {
|
|
660
|
-
gitignoreContent = gitignoreContent.replace(/\n\n+/g, "\n\n").trim() + "\n";
|
|
661
|
-
await fs.writeFile(gitignorePath, gitignoreContent);
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
376
|
async function createProject(name, options) {
|
|
665
377
|
const projectDir = path.join(options.directory, name);
|
|
666
378
|
if (await fs.pathExists(projectDir)) {
|
|
@@ -683,12 +395,7 @@ async function createProject(name, options) {
|
|
|
683
395
|
const typedocConfig = getTypedocConfig({ repoName: name });
|
|
684
396
|
await fs.writeJson(path.join(projectDir, "typedoc.json"), typedocConfig, { spaces: 4 });
|
|
685
397
|
console.log(chalk.gray(" 创建: typedoc.json"));
|
|
686
|
-
await fs.writeFile(path.join(projectDir, "src/index.ts"),
|
|
687
|
-
* @feng3d/${name}
|
|
688
|
-
*/
|
|
689
|
-
|
|
690
|
-
export {};
|
|
691
|
-
`);
|
|
398
|
+
await fs.writeFile(path.join(projectDir, "src/index.ts"), getSrcIndexTemplate({ name: `@feng3d/${name}` }));
|
|
692
399
|
console.log(chalk.gray(" 创建: src/index.ts"));
|
|
693
400
|
await fs.writeFile(path.join(projectDir, "README.md"), `# @feng3d/${name}
|
|
694
401
|
`);
|
|
@@ -709,12 +416,13 @@ export {};
|
|
|
709
416
|
await fs.writeFile(path.join(projectDir, "scripts/postpublish.js"), getPostpublishScriptTemplate());
|
|
710
417
|
console.log(chalk.gray(" 创建: scripts/prepublish.js"));
|
|
711
418
|
console.log(chalk.gray(" 创建: scripts/postpublish.js"));
|
|
712
|
-
|
|
713
|
-
|
|
419
|
+
if (options.examples !== false) {
|
|
420
|
+
await fs.writeFile(path.join(projectDir, "scripts/postdocs.js"), getPostdocsScriptTemplate());
|
|
421
|
+
console.log(chalk.gray(" 创建: scripts/postdocs.js"));
|
|
422
|
+
}
|
|
714
423
|
}
|
|
715
424
|
function createPackageJson(name, options) {
|
|
716
425
|
const scripts = {
|
|
717
|
-
dev: "cd examples && npm run dev",
|
|
718
426
|
clean: "rimraf lib dist public",
|
|
719
427
|
build: "vite build && tsc",
|
|
720
428
|
types: "tsc",
|
|
@@ -726,6 +434,10 @@ function createPackageJson(name, options) {
|
|
|
726
434
|
prepublishOnly: "node scripts/prepublish.js",
|
|
727
435
|
postpublish: "node scripts/postpublish.js"
|
|
728
436
|
};
|
|
437
|
+
if (options.examples !== false) {
|
|
438
|
+
scripts["examples:dev"] = "cd examples && npm run dev";
|
|
439
|
+
scripts.postdocs = "node scripts/postdocs.js && cd examples && vite build --outDir ../public";
|
|
440
|
+
}
|
|
729
441
|
if (options.vitest !== false) {
|
|
730
442
|
scripts.test = "vitest run";
|
|
731
443
|
scripts["test:watch"] = "vitest";
|
|
@@ -763,31 +475,30 @@ function createPackageJson(name, options) {
|
|
|
763
475
|
};
|
|
764
476
|
}
|
|
765
477
|
export {
|
|
766
|
-
DEFAULT_CONFIG,
|
|
767
|
-
DEFAULT_UPDATE_CONFIG,
|
|
768
478
|
VERSIONS,
|
|
769
479
|
createProject,
|
|
770
|
-
detectSchemaPath,
|
|
771
480
|
getCursorrrulesTemplate,
|
|
772
481
|
getDevDependencies,
|
|
773
482
|
getEslintConfigTemplate,
|
|
774
|
-
getFeng3dConfigTemplate,
|
|
775
483
|
getGitignoreTemplate,
|
|
776
484
|
getHuskyPreCommitTemplate,
|
|
777
485
|
getLicenseTemplate,
|
|
778
486
|
getPagesWorkflowTemplate,
|
|
487
|
+
getPostdocsScriptTemplate,
|
|
779
488
|
getPostpublishScriptTemplate,
|
|
780
489
|
getPrepublishScriptTemplate,
|
|
781
490
|
getPublishWorkflowTemplate,
|
|
782
491
|
getPullRequestWorkflowTemplate,
|
|
492
|
+
getSrcIndexTemplate,
|
|
783
493
|
getTestIndexTemplate,
|
|
784
494
|
getTsconfigTemplate,
|
|
785
495
|
getTsconfigTemplateString,
|
|
786
496
|
getTypedocConfig,
|
|
787
497
|
getTypedocConfigTemplate,
|
|
498
|
+
getUploadOssWorkflowTemplate,
|
|
788
499
|
getViteConfigTemplate,
|
|
500
|
+
getVitestConfigTemplate,
|
|
789
501
|
getVscodeSettingsTemplate,
|
|
790
|
-
ossUploadDir,
|
|
791
502
|
updateProject
|
|
792
503
|
};
|
|
793
504
|
//# sourceMappingURL=index.js.map
|