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