feng3d-cli 0.0.6 → 0.0.8

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 CHANGED
@@ -1,4 +1,4 @@
1
- feng3d 命令行工具,包含项目规范、配置模板、OSS 上传等功能。
1
+ feng3d 命令行工具,包含项目规范、配置模板等功能。
2
2
 
3
3
  ## 功能特性
4
4
 
@@ -6,8 +6,8 @@ feng3d 命令行工具,包含项目规范、配置模板、OSS 上传等功能
6
6
  - 📦 统一的依赖版本管理
7
7
  - 🛠️ CLI 工具支持创建和更新项目
8
8
  - 📝 项目模板(LICENSE, .gitignore, .cursorrules, tsconfig.json, vite.config.js 等)
9
- - 🔄 GitHub Actions 工作流模板
10
- - 📤 阿里云 OSS 文件上传
9
+ - 🔄 GitHub Actions 工作流模板(CI/CD、GitHub Pages 部署、OSS 上传)
10
+ - Git pre-commit 钩子(代码规范检查 + 单元测试)
11
11
 
12
12
  ## 使用方式
13
13
 
@@ -39,29 +39,7 @@ npx feng3d-cli update -d ./my-project # 指定项目目录
39
39
 
40
40
  更新项目的所有规范配置文件,包括 ESLint、TypeScript、Vite、GitHub Actions 等。
41
41
 
42
- ### 上传到阿里云 OSS
43
-
44
- ```bash
45
- npx feng3d-cli oss_upload_dir # 上传 ./public 目录
46
- npx feng3d-cli oss_upload_dir -l ./dist # 指定本地目录
47
- npx feng3d-cli oss_upload_dir -l ./public -o my-project # 指定 OSS 目录
48
- ```
49
-
50
- 选项:
51
- - `-l, --local_dir <dir>` - 本地目录(默认:./public)
52
- - `-o, --oss_dir <dir>` - OSS 目录(默认:从 package.json 的 name 获取)
53
-
54
- > 注意:需要在用户目录下创建 `oss_config.json` 配置 OSS 访问密钥(如 `~/oss_config.json`)
55
- >
56
- > 配置文件格式:
57
- > ```json
58
- > {
59
- > "region": "oss-cn-hangzhou",
60
- > "accessKeyId": "your-access-key-id",
61
- > "accessKeySecret": "your-access-key-secret",
62
- > "bucket": "your-bucket-name"
63
- > }
64
- > ```
42
+ > 注意:如果项目中存在 `examples` 目录,会自动添加 `examples:dev` 和 `postdocs` 脚本。
65
43
 
66
44
  ## 编程使用
67
45
 
@@ -81,7 +59,6 @@ import {
81
59
  // 项目操作
82
60
  createProject,
83
61
  updateProject,
84
- ossUploadDir,
85
62
  } from 'feng3d-cli';
86
63
  ```
87
64
 
@@ -97,10 +74,28 @@ import {
97
74
  | eslint.config.js | ESLint 配置 |
98
75
  | typedoc.json | TypeDoc 配置 |
99
76
  | .vscode/settings.json | VS Code 设置 |
100
- | .husky/pre-commit | Git pre-commit hook |
101
- | .github/workflows/*.yml | GitHub Actions 工作流 |
77
+ | .husky/pre-commit | Git pre-commit 钩子(代码规范 + 单元测试) |
102
78
  | scripts/prepublish.js | 发布前脚本 |
103
79
  | scripts/postpublish.js | 发布后脚本 |
80
+ | scripts/postdocs.js | 文档生成后处理脚本(移动到 public/doc) |
81
+
82
+ ## GitHub Actions 工作流
83
+
84
+ | 工作流文件 | 说明 |
85
+ |------|------|
86
+ | pull-request.yml | 代码检查和测试(PR 或推送时触发) |
87
+ | publish.yml | 发布到 npm(创建 Release 时触发) |
88
+ | pages.yml | 部署文档到 GitHub Pages(发布成功后或手动触发) |
89
+ | upload-oss.yml | 上传到阿里云 OSS(发布成功后或手动触发) |
90
+
91
+ ### OSS 上传配置
92
+
93
+ 要启用 OSS 上传功能,需要在 GitHub 仓库的 Settings > Secrets and variables > Actions 中配置以下密钥:
94
+
95
+ - `OSS_REGION` - OSS 区域(如 `oss-cn-hangzhou`)
96
+ - `OSS_ACCESS_KEY_ID` - 阿里云 AccessKey ID
97
+ - `OSS_ACCESS_KEY_SECRET` - 阿里云 AccessKey Secret
98
+ - `OSS_BUCKET` - OSS Bucket 名称
104
99
 
105
100
  ## 统一版本
106
101
 
@@ -130,6 +125,11 @@ import {
130
125
  - 遵循 Conventional Commits 格式
131
126
  - 类型:feat, fix, refactor, perf, style, docs, test, chore, build, ci
132
127
 
128
+ ### Pre-commit 检查
129
+ 提交代码前会自动执行:
130
+ 1. **代码规范检查** - 使用 ESLint 检查代码风格
131
+ 2. **单元测试** - 运行 vitest 确保测试通过
132
+
133
133
  ## 许可证
134
134
 
135
135
  MIT
package/dist/index.js CHANGED
@@ -89,6 +89,9 @@ function getSrcIndexTemplate(options) {
89
89
  const template = fs.readFileSync(path.join(TEMPLATES_DIR, "src/index.ts"), "utf-8");
90
90
  return template.replace(/\{\{name\}\}/g, options.name);
91
91
  }
92
+ function getVitestConfigTemplate() {
93
+ return fs.readFileSync(path.join(TEMPLATES_DIR, "vitest.config.ts"), "utf-8");
94
+ }
92
95
  async function updateProject(directory = ".") {
93
96
  const projectDir = path.resolve(directory);
94
97
  const packageJsonPath = path.join(projectDir, "package.json");
@@ -111,13 +114,8 @@ async function updateProject(directory = ".") {
111
114
  const name = packageJson.name || path.basename(projectDir);
112
115
  const repoName = name.replace(/^@[^/]+\//, "");
113
116
  const isFeng3dCli = name === "feng3d-cli";
114
- const gitignorePath = path.join(projectDir, ".gitignore");
115
- if (!await fs.pathExists(gitignorePath)) {
116
- await fs.writeFile(gitignorePath, getGitignoreTemplate());
117
- console.log(chalk.gray(" 创建: .gitignore"));
118
- } else {
119
- console.log(chalk.gray(" 跳过: .gitignore(已存在)"));
120
- }
117
+ await fs.writeFile(path.join(projectDir, ".gitignore"), getGitignoreTemplate());
118
+ console.log(chalk.gray(" 更新: .gitignore"));
121
119
  await fs.writeFile(path.join(projectDir, ".cursorrules"), getCursorrrulesTemplate());
122
120
  console.log(chalk.gray(" 更新: .cursorrules"));
123
121
  await createEslintConfigFile(projectDir);
@@ -135,75 +133,43 @@ async function updateProject(directory = ".") {
135
133
  await fs.writeFile(path.join(projectDir, "typedoc.json"), typedocContent);
136
134
  console.log(chalk.gray(" 更新: typedoc.json"));
137
135
  const testDir = path.join(projectDir, "test");
138
- const testFilePath = path.join(testDir, "_.test.ts");
139
- let hasOtherFiles = false;
140
- if (await fs.pathExists(testDir)) {
141
- const files = await fs.readdir(testDir);
142
- hasOtherFiles = files.some((file) => file !== "_.test.ts");
143
- }
144
- if (!hasOtherFiles) {
145
- await fs.ensureDir(testDir);
146
- const testContent = getTestIndexTemplate();
147
- await fs.writeFile(testFilePath, testContent);
148
- console.log(chalk.gray(" 更新: test/_.test.ts"));
149
- } else {
150
- console.log(chalk.gray(" 跳过: test/_.test.ts(测试目录已有其他文件)"));
151
- }
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"));
152
140
  await updateDependencies(projectDir);
153
141
  console.log(chalk.gray(" 更新: package.json devDependencies"));
154
142
  await fs.ensureDir(path.join(projectDir, ".husky"));
155
143
  await fs.writeFile(path.join(projectDir, ".husky/pre-commit"), getHuskyPreCommitTemplate());
156
144
  console.log(chalk.gray(" 更新: .husky/pre-commit"));
157
145
  await updateHuskyConfig(projectDir);
158
- const licensePath = path.join(projectDir, "LICENSE");
159
- if (!await fs.pathExists(licensePath)) {
160
- await fs.writeFile(licensePath, getLicenseTemplate());
161
- console.log(chalk.gray(" 创建: LICENSE"));
162
- } else {
163
- console.log(chalk.gray(" 跳过: LICENSE(已存在)"));
164
- }
146
+ await fs.writeFile(path.join(projectDir, "LICENSE"), getLicenseTemplate());
147
+ console.log(chalk.gray(" 更新: LICENSE"));
165
148
  await fs.ensureDir(path.join(projectDir, ".vscode"));
166
149
  await fs.writeFile(path.join(projectDir, ".vscode/settings.json"), getVscodeSettingsTemplate());
167
150
  console.log(chalk.gray(" 更新: .vscode/settings.json"));
168
151
  if (!isFeng3dCli) {
169
- const tsconfigPath = path.join(projectDir, "tsconfig.json");
170
- if (!await fs.pathExists(tsconfigPath)) {
171
- await fs.writeFile(tsconfigPath, getTsconfigTemplateString());
172
- console.log(chalk.gray(" 创建: tsconfig.json"));
173
- } else {
174
- console.log(chalk.gray(" 跳过: tsconfig.json(已存在)"));
175
- }
152
+ await fs.writeFile(path.join(projectDir, "tsconfig.json"), getTsconfigTemplateString());
153
+ console.log(chalk.gray(" 更新: tsconfig.json"));
176
154
  }
177
155
  if (!isFeng3dCli) {
178
- const viteConfigPath = path.join(projectDir, "vite.config.js");
179
- if (!await fs.pathExists(viteConfigPath)) {
180
- await fs.writeFile(viteConfigPath, getViteConfigTemplate());
181
- console.log(chalk.gray(" 创建: vite.config.js"));
182
- } else {
183
- console.log(chalk.gray(" 跳过: vite.config.js(已存在)"));
184
- }
156
+ await fs.writeFile(path.join(projectDir, "vite.config.js"), getViteConfigTemplate());
157
+ console.log(chalk.gray(" 更新: vite.config.js"));
185
158
  }
186
- const scriptsDir = path.join(projectDir, "scripts");
187
- const prepublishPath = path.join(scriptsDir, "prepublish.js");
188
- const postpublishPath = path.join(scriptsDir, "postpublish.js");
189
- if (!await fs.pathExists(prepublishPath)) {
190
- await fs.ensureDir(scriptsDir);
191
- await fs.writeFile(prepublishPath, getPrepublishScriptTemplate());
192
- console.log(chalk.gray(" 创建: scripts/prepublish.js"));
193
- }
194
- if (!await fs.pathExists(postpublishPath)) {
195
- await fs.ensureDir(scriptsDir);
196
- await fs.writeFile(postpublishPath, getPostpublishScriptTemplate());
197
- console.log(chalk.gray(" 创建: scripts/postpublish.js"));
159
+ if (!isFeng3dCli) {
160
+ await fs.writeFile(path.join(projectDir, "vitest.config.ts"), getVitestConfigTemplate());
161
+ console.log(chalk.gray(" 更新: vitest.config.ts"));
198
162
  }
163
+ const scriptsDir = path.join(projectDir, "scripts");
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"));
199
169
  const examplesDir = path.join(projectDir, "examples");
200
- const postdocsPath = path.join(scriptsDir, "postdocs.js");
201
170
  if (await fs.pathExists(examplesDir)) {
202
- if (!await fs.pathExists(postdocsPath)) {
203
- await fs.ensureDir(scriptsDir);
204
- await fs.writeFile(postdocsPath, getPostdocsScriptTemplate());
205
- console.log(chalk.gray(" 创建: scripts/postdocs.js"));
206
- }
171
+ await fs.writeFile(path.join(scriptsDir, "postdocs.js"), getPostdocsScriptTemplate());
172
+ console.log(chalk.gray(" 更新: scripts/postdocs.js"));
207
173
  }
208
174
  }
209
175
  async function createEslintConfigFile(projectDir) {
@@ -318,16 +284,16 @@ async function updateDependencies(projectDir) {
318
284
  standardScripts.postdocs = "node scripts/postdocs.js && cd examples && vite build --outDir ../public";
319
285
  }
320
286
  for (const [key, value] of Object.entries(standardScripts)) {
321
- if (!(key in packageJson.scripts)) {
287
+ if (packageJson.scripts[key] !== value) {
322
288
  packageJson.scripts[key] = value;
323
289
  updated = true;
324
- console.log(chalk.gray(` 添加: scripts.${key}`));
290
+ console.log(chalk.gray(` 更新: scripts.${key}`));
325
291
  }
326
292
  }
327
- if (!packageJson.type) {
293
+ if (packageJson.type !== "module") {
328
294
  packageJson.type = "module";
329
295
  updated = true;
330
- console.log(chalk.gray(' 添加: type = "module"'));
296
+ console.log(chalk.gray(' 更新: type = "module"'));
331
297
  }
332
298
  const entryPoints = {
333
299
  main: "./src/index.ts",
@@ -335,22 +301,23 @@ async function updateDependencies(projectDir) {
335
301
  module: "./src/index.ts"
336
302
  };
337
303
  for (const [key, value] of Object.entries(entryPoints)) {
338
- if (!(key in packageJson)) {
304
+ if (packageJson[key] !== value) {
339
305
  packageJson[key] = value;
340
306
  updated = true;
341
- console.log(chalk.gray(` 添加: ${key} = "${value}"`));
307
+ console.log(chalk.gray(` 更新: ${key} = "${value}"`));
342
308
  }
343
309
  }
344
- if (!packageJson.exports) {
345
- packageJson.exports = {
346
- ".": {
347
- types: "./src/index.ts",
348
- import: "./src/index.ts",
349
- require: "./src/index.ts"
350
- }
351
- };
310
+ const standardExports = {
311
+ ".": {
312
+ types: "./src/index.ts",
313
+ import: "./src/index.ts",
314
+ require: "./src/index.ts"
315
+ }
316
+ };
317
+ if (JSON.stringify(packageJson.exports) !== JSON.stringify(standardExports)) {
318
+ packageJson.exports = standardExports;
352
319
  updated = true;
353
- console.log(chalk.gray(" 添加: exports"));
320
+ console.log(chalk.gray(" 更新: exports"));
354
321
  }
355
322
  if (updated) {
356
323
  const orderedPackageJson = reorderPackageJson(packageJson);
@@ -371,15 +338,15 @@ async function updateHuskyConfig(projectDir) {
371
338
  if (!packageJson.devDependencies) {
372
339
  packageJson.devDependencies = {};
373
340
  }
374
- if (!packageJson.devDependencies.husky) {
341
+ if (packageJson.devDependencies.husky !== VERSIONS.husky) {
375
342
  packageJson.devDependencies.husky = VERSIONS.husky;
376
343
  updated = true;
377
- console.log(chalk.gray(` 添加: devDependencies.husky = "${VERSIONS.husky}"`));
344
+ console.log(chalk.gray(` 更新: devDependencies.husky = "${VERSIONS.husky}"`));
378
345
  }
379
- if (!packageJson.devDependencies["lint-staged"]) {
346
+ if (packageJson.devDependencies["lint-staged"] !== VERSIONS["lint-staged"]) {
380
347
  packageJson.devDependencies["lint-staged"] = VERSIONS["lint-staged"];
381
348
  updated = true;
382
- console.log(chalk.gray(` 添加: devDependencies.lint-staged = "${VERSIONS["lint-staged"]}"`));
349
+ console.log(chalk.gray(` 更新: devDependencies.lint-staged = "${VERSIONS["lint-staged"]}"`));
383
350
  }
384
351
  if (!packageJson.scripts) {
385
352
  packageJson.scripts = {};
@@ -387,14 +354,15 @@ async function updateHuskyConfig(projectDir) {
387
354
  if (packageJson.scripts.prepare !== "husky") {
388
355
  packageJson.scripts.prepare = "husky";
389
356
  updated = true;
390
- console.log(chalk.gray(' 添加: scripts.prepare = "husky"'));
357
+ console.log(chalk.gray(' 更新: scripts.prepare = "husky"'));
391
358
  }
392
- if (!packageJson["lint-staged"]) {
393
- packageJson["lint-staged"] = {
394
- "*.{js,ts}": ["eslint --fix --max-warnings 0"]
395
- };
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;
396
364
  updated = true;
397
- console.log(chalk.gray(" 添加: lint-staged 配置"));
365
+ console.log(chalk.gray(" 更新: lint-staged 配置"));
398
366
  }
399
367
  if (updated) {
400
368
  const orderedPackageJson = reorderPackageJson(packageJson);
@@ -529,6 +497,7 @@ export {
529
497
  getTypedocConfigTemplate,
530
498
  getUploadOssWorkflowTemplate,
531
499
  getViteConfigTemplate,
500
+ getVitestConfigTemplate,
532
501
  getVscodeSettingsTemplate,
533
502
  updateProject
534
503
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/versions.ts","../src/templates.ts","../src/commands/update.ts","../src/commands/create.ts"],"sourcesContent":["/**\n * feng3d 项目统一依赖版本\n * 从 templates/package.json 中读取\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\n/**\n * 模板目录路径\n */\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = path.resolve(__dirname, '../templates');\n\n/**\n * 从模板 package.json 中读取 devDependencies\n */\nfunction loadVersionsFromTemplate(): Record<string, string>\n{\n const packageJsonPath = path.join(TEMPLATES_DIR, 'package.json');\n const packageJson = fs.readJsonSync(packageJsonPath);\n\n return packageJson.devDependencies || {};\n}\n\n/**\n * 统一依赖版本(从 templates/package.json 读取)\n */\nexport const VERSIONS = loadVersionsFromTemplate();\n\n/**\n * 获取 devDependencies 配置\n */\nexport function getDevDependencies(options: {\n includeVitest?: boolean;\n includeTypedoc?: boolean;\n includeCoverage?: boolean;\n} = {}): Record<string, string>\n{\n // 从 VERSIONS 中复制所有依赖\n const deps: Record<string, string> = { ...VERSIONS };\n\n // 根据选项移除可选依赖\n if (options.includeVitest === false)\n {\n delete deps.vitest;\n }\n\n if (options.includeTypedoc === false)\n {\n delete deps.typedoc;\n }\n\n // 可选添加覆盖率依赖(默认不包含)\n if (options.includeCoverage && !deps['@vitest/coverage-v8'])\n {\n deps['@vitest/coverage-v8'] = '^3.2.4';\n }\n\n return deps;\n}\n","/**\n * 项目模板文件内容\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\n/**\n * 模板目录路径\n */\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = path.resolve(__dirname, '../templates');\n\n/**\n * 获取 .gitignore 模板内容\n */\nexport function getGitignoreTemplate(): string\n{\n // 模板文件命名为 gitignore(不带点),避免对 templates 目录生效\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'gitignore'), 'utf-8');\n}\n\n/**\n * 获取 .cursorrules 模板内容\n */\nexport function getCursorrrulesTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.cursorrules'), 'utf-8');\n}\n\n/**\n * 获取 tsconfig.json 模板内容(对象形式)\n */\nexport function getTsconfigTemplate(): object\n{\n return fs.readJsonSync(path.join(TEMPLATES_DIR, 'tsconfig.json'));\n}\n\n/**\n * 获取 tsconfig.json 模板内容(字符串形式)\n */\nexport function getTsconfigTemplateString(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'tsconfig.json'), 'utf-8');\n}\n\n/**\n * 获取 vite.config.js 模板内容\n */\nexport function getViteConfigTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'vite.config.js'), 'utf-8');\n}\n\n/**\n * 获取 eslint.config.js 模板内容\n */\nexport function getEslintConfigTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'eslint.config.js'), 'utf-8');\n}\n\n/**\n * 获取 typedoc.json 模板内容(返回对象)\n */\nexport function getTypedocConfig(options: {\n repoName: string;\n}): object\n{\n return JSON.parse(getTypedocConfigTemplate(options));\n}\n\n/**\n * 获取 typedoc.json 模板内容(返回字符串)\n */\nexport function getTypedocConfigTemplate(options: {\n repoName: string;\n}): string\n{\n const templateContent = fs.readFileSync(path.join(TEMPLATES_DIR, 'typedoc.json'), 'utf-8');\n\n return templateContent.replace(/\\{\\{repoName\\}\\}/g, options.repoName);\n}\n\n/**\n * 获取 test/_.test.ts 模板内容(空文件占位)\n */\nexport function getTestIndexTemplate(_options: { name: string }): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'test/_.test.ts'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions publish workflow 模板内容\n */\nexport function getPublishWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/publish.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions pages workflow 模板内容\n */\nexport function getPagesWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/pages.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions pull-request workflow 模板内容\n */\nexport function getPullRequestWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/pull-request.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions upload-oss workflow 模板内容\n */\nexport function getUploadOssWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/upload-oss.yml'), 'utf-8');\n}\n\n/**\n * 获取 .husky/pre-commit 模板内容\n */\nexport function getHuskyPreCommitTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.husky/pre-commit'), 'utf-8');\n}\n\n/**\n * 获取 LICENSE 模板内容\n */\nexport function getLicenseTemplate(ctx: { year?: number } = {}): string\n{\n const year = ctx.year || new Date().getFullYear();\n const template = fs.readFileSync(path.join(TEMPLATES_DIR, 'LICENSE'), 'utf-8');\n\n return template.replace('{{year}}', String(year));\n}\n\n/**\n * 获取 .vscode/settings.json 模板内容\n */\nexport function getVscodeSettingsTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.vscode/settings.json'), 'utf-8');\n}\n\n/**\n * 获取 scripts/prepublish.js 模板内容\n */\nexport function getPrepublishScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/prepublish.js'), 'utf-8');\n}\n\n/**\n * 获取 scripts/postpublish.js 模板内容\n */\nexport function getPostpublishScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/postpublish.js'), 'utf-8');\n}\n\n/**\n * 获取 scripts/postdocs.js 模板内容\n */\nexport function getPostdocsScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/postdocs.js'), 'utf-8');\n}\n\n/**\n * 获取 src/index.ts 模板内容\n */\nexport function getSrcIndexTemplate(options: { name: string }): string\n{\n const template = fs.readFileSync(path.join(TEMPLATES_DIR, 'src/index.ts'), 'utf-8');\n\n return template.replace(/\\{\\{name\\}\\}/g, options.name);\n}\n\n","/**\n * 更新项目规范命令\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport { getDevDependencies, VERSIONS } from '../versions.js';\nimport {\n getGitignoreTemplate,\n getCursorrrulesTemplate,\n getEslintConfigTemplate,\n getPublishWorkflowTemplate,\n getPagesWorkflowTemplate,\n getPullRequestWorkflowTemplate,\n getUploadOssWorkflowTemplate,\n getTypedocConfigTemplate,\n getTestIndexTemplate,\n getHuskyPreCommitTemplate,\n getLicenseTemplate,\n getVscodeSettingsTemplate,\n getTsconfigTemplateString,\n getViteConfigTemplate,\n getPrepublishScriptTemplate,\n getPostpublishScriptTemplate,\n getPostdocsScriptTemplate,\n getSrcIndexTemplate,\n} from '../templates.js';\n\n/**\n * 模板上下文\n */\ninterface TemplateContext {\n name: string;\n repoName: string;\n}\n\n/**\n * 更新项目的规范配置\n * @param directory 项目目录路径\n */\nexport async function updateProject(directory: string = '.'): Promise<void>\n{\n const projectDir = path.resolve(directory);\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 如果 package.json 不存在,创建基础 package.json\n if (!await fs.pathExists(packageJsonPath))\n {\n await fs.ensureDir(projectDir);\n const dirName = path.basename(projectDir);\n const initialPackageJson = {\n name: `@feng3d/${dirName}`,\n version: '0.0.1',\n description: '',\n };\n\n await fs.writeJson(packageJsonPath, initialPackageJson, { spaces: 4 });\n console.log(chalk.gray(' 创建: package.json'));\n\n // 创建 src/index.ts\n const srcDir = path.join(projectDir, 'src');\n\n await fs.ensureDir(srcDir);\n await fs.writeFile(path.join(srcDir, 'index.ts'), getSrcIndexTemplate({ name: `@feng3d/${dirName}` }));\n console.log(chalk.gray(' 创建: src/index.ts'));\n }\n\n // 获取项目信息用于模板\n const packageJson = await fs.readJson(packageJsonPath);\n const name = packageJson.name || path.basename(projectDir);\n const repoName = name.replace(/^@[^/]+\\//, ''); // 移除 scope 前缀\n const templateContext: TemplateContext = { name, repoName };\n\n // feng3d-cli 项目:不更新 tsconfig.json 和 vite.config.js(有自定义配置)\n const isFeng3dCli = name === 'feng3d-cli';\n\n // 更新 .gitignore(仅在文件不存在时创建)\n const gitignorePath = path.join(projectDir, '.gitignore');\n\n if (!await fs.pathExists(gitignorePath))\n {\n await fs.writeFile(gitignorePath, getGitignoreTemplate());\n console.log(chalk.gray(' 创建: .gitignore'));\n }\n else\n {\n console.log(chalk.gray(' 跳过: .gitignore(已存在)'));\n }\n\n // 更新 .cursorrules\n await fs.writeFile(path.join(projectDir, '.cursorrules'), getCursorrrulesTemplate());\n console.log(chalk.gray(' 更新: .cursorrules'));\n\n // 更新 eslint.config.js\n await createEslintConfigFile(projectDir);\n console.log(chalk.gray(' 更新: eslint.config.js'));\n\n // 更新 .github/workflows/publish.yml\n await fs.ensureDir(path.join(projectDir, '.github/workflows'));\n await fs.writeFile(path.join(projectDir, '.github/workflows/publish.yml'), getPublishWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/publish.yml'));\n\n // 更新 .github/workflows/pages.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/pages.yml'), getPagesWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/pages.yml'));\n\n // 更新 .github/workflows/pull-request.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/pull-request.yml'), getPullRequestWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/pull-request.yml'));\n\n // 更新 .github/workflows/upload-oss.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/upload-oss.yml'), getUploadOssWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/upload-oss.yml'));\n\n // 更新 typedoc.json\n const typedocContent = getTypedocConfigTemplate({ repoName });\n\n await fs.writeFile(path.join(projectDir, 'typedoc.json'), typedocContent);\n console.log(chalk.gray(' 更新: typedoc.json'));\n\n // 更新 test/_.test.ts\n const testDir = path.join(projectDir, 'test');\n const testFilePath = path.join(testDir, '_.test.ts');\n\n // 检查测试目录是否有其他文件\n let hasOtherFiles = false;\n\n if (await fs.pathExists(testDir))\n {\n const files = await fs.readdir(testDir);\n\n hasOtherFiles = files.some(file => file !== '_.test.ts');\n }\n\n if (!hasOtherFiles)\n {\n await fs.ensureDir(testDir);\n const testContent = getTestIndexTemplate({ name });\n\n await fs.writeFile(testFilePath, testContent);\n console.log(chalk.gray(' 更新: test/_.test.ts'));\n }\n else\n {\n console.log(chalk.gray(' 跳过: test/_.test.ts(测试目录已有其他文件)'));\n }\n\n // 更新依赖版本\n await updateDependencies(projectDir);\n console.log(chalk.gray(' 更新: package.json devDependencies'));\n\n // 更新 husky pre-commit hook\n await fs.ensureDir(path.join(projectDir, '.husky'));\n await fs.writeFile(path.join(projectDir, '.husky/pre-commit'), getHuskyPreCommitTemplate());\n console.log(chalk.gray(' 更新: .husky/pre-commit'));\n await updateHuskyConfig(projectDir);\n\n // 更新 LICENSE 文件(仅在不存在时创建)\n const licensePath = path.join(projectDir, 'LICENSE');\n\n if (!await fs.pathExists(licensePath))\n {\n await fs.writeFile(licensePath, getLicenseTemplate());\n console.log(chalk.gray(' 创建: LICENSE'));\n }\n else\n {\n console.log(chalk.gray(' 跳过: LICENSE(已存在)'));\n }\n\n // 更新 .vscode/settings.json\n await fs.ensureDir(path.join(projectDir, '.vscode'));\n await fs.writeFile(path.join(projectDir, '.vscode/settings.json'), getVscodeSettingsTemplate());\n console.log(chalk.gray(' 更新: .vscode/settings.json'));\n\n // 更新 tsconfig.json(仅在不存在时创建,feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n const tsconfigPath = path.join(projectDir, 'tsconfig.json');\n\n if (!await fs.pathExists(tsconfigPath))\n {\n await fs.writeFile(tsconfigPath, getTsconfigTemplateString());\n console.log(chalk.gray(' 创建: tsconfig.json'));\n }\n else\n {\n console.log(chalk.gray(' 跳过: tsconfig.json(已存在)'));\n }\n }\n\n // 更新 vite.config.js(仅在不存在时创建,feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n const viteConfigPath = path.join(projectDir, 'vite.config.js');\n\n if (!await fs.pathExists(viteConfigPath))\n {\n await fs.writeFile(viteConfigPath, getViteConfigTemplate());\n console.log(chalk.gray(' 创建: vite.config.js'));\n }\n else\n {\n console.log(chalk.gray(' 跳过: vite.config.js(已存在)'));\n }\n }\n\n // 更新发布脚本(仅在不存在时创建)\n const scriptsDir = path.join(projectDir, 'scripts');\n const prepublishPath = path.join(scriptsDir, 'prepublish.js');\n const postpublishPath = path.join(scriptsDir, 'postpublish.js');\n\n if (!await fs.pathExists(prepublishPath))\n {\n await fs.ensureDir(scriptsDir);\n await fs.writeFile(prepublishPath, getPrepublishScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/prepublish.js'));\n }\n\n if (!await fs.pathExists(postpublishPath))\n {\n await fs.ensureDir(scriptsDir);\n await fs.writeFile(postpublishPath, getPostpublishScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/postpublish.js'));\n }\n\n // 如果存在 examples 目录,创建 postdocs.js 脚本\n const examplesDir = path.join(projectDir, 'examples');\n const postdocsPath = path.join(scriptsDir, 'postdocs.js');\n\n if (await fs.pathExists(examplesDir))\n {\n if (!await fs.pathExists(postdocsPath))\n {\n await fs.ensureDir(scriptsDir);\n await fs.writeFile(postdocsPath, getPostdocsScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/postdocs.js'));\n }\n }\n}\n\n/**\n * 创建 ESLint 配置文件\n */\nexport async function createEslintConfigFile(projectDir: string): Promise<void>\n{\n await fs.writeFile(path.join(projectDir, 'eslint.config.js'), getEslintConfigTemplate());\n}\n\n/**\n * 检测 JSON 文件的缩进风格\n */\nfunction detectIndent(content: string): string\n{\n const match = content.match(/^[ \\t]+/m);\n\n return match ? match[0] : ' ';\n}\n\n/**\n * package.json 字段的标准顺序\n */\nconst PACKAGE_JSON_FIELD_ORDER = [\n 'name',\n 'version',\n 'description',\n 'homepage',\n 'author',\n 'license',\n 'type',\n 'main',\n 'types',\n 'module',\n 'exports',\n 'bin',\n 'scripts',\n 'repository',\n 'publishConfig',\n 'files',\n 'devDependencies',\n 'dependencies',\n 'peerDependencies',\n 'lint-staged',\n];\n\n/**\n * scripts 字段的标准顺序\n */\nconst SCRIPTS_ORDER = [\n 'examples:dev',\n 'test_web',\n 'postdocs',\n 'clean',\n 'build',\n 'watch',\n 'test',\n 'lint',\n 'lintfix',\n 'docs',\n 'prepublishOnly',\n 'release',\n 'postpublish',\n 'prepare',\n];\n\n/**\n * 按标准顺序重新排列对象字段\n */\nfunction reorderObject(obj: Record<string, unknown>, order: string[]): Record<string, unknown>\n{\n const ordered: Record<string, unknown> = {};\n\n // 先按标准顺序添加已存在的字段\n for (const key of order)\n {\n if (key in obj)\n {\n ordered[key] = obj[key];\n }\n }\n\n // 再添加其他未在标准顺序中的字段\n for (const key of Object.keys(obj))\n {\n if (!(key in ordered))\n {\n ordered[key] = obj[key];\n }\n }\n\n return ordered;\n}\n\n/**\n * 按标准顺序重新排列 package.json 字段\n */\nfunction reorderPackageJson(packageJson: Record<string, unknown>): Record<string, unknown>\n{\n const ordered = reorderObject(packageJson, PACKAGE_JSON_FIELD_ORDER);\n\n // 重新排列 scripts\n if (ordered.scripts && typeof ordered.scripts === 'object')\n {\n ordered.scripts = reorderObject(ordered.scripts as Record<string, unknown>, SCRIPTS_ORDER);\n }\n\n return ordered;\n}\n\n/**\n * 更新 package.json 中的 devDependencies 版本\n */\nasync function updateDependencies(projectDir: string): Promise<void>\n{\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 读取原始内容以检测缩进风格\n const originalContent = await fs.readFile(packageJsonPath, 'utf-8');\n const indent = detectIndent(originalContent);\n const hasTrailingNewline = originalContent.endsWith('\\n');\n\n const packageJson = JSON.parse(originalContent);\n\n const standardDeps = getDevDependencies({\n includeVitest: true,\n includeTypedoc: true,\n });\n\n // 添加或更新 devDependencies\n let updated = false;\n\n if (!packageJson.devDependencies)\n {\n packageJson.devDependencies = {};\n }\n\n for (const [key, value] of Object.entries(standardDeps))\n {\n if (!(key in packageJson.devDependencies))\n {\n packageJson.devDependencies[key] = value;\n updated = true;\n console.log(chalk.gray(` 添加: devDependencies.${key} = \"${value}\"`));\n }\n else if (packageJson.devDependencies[key] !== value)\n {\n packageJson.devDependencies[key] = value;\n updated = true;\n console.log(chalk.gray(` 更新: devDependencies.${key} = \"${value}\"`));\n }\n }\n\n // 添加标准 scripts\n if (!packageJson.scripts)\n {\n packageJson.scripts = {};\n }\n\n const standardScripts: Record<string, string> = {\n clean: 'rimraf lib dist public',\n build: 'vite build && tsc',\n watch: 'concurrently \"vite build --watch\" \"tsc -w\" \"vitest\"',\n test: 'vitest run',\n lint: 'eslint . --ext .js,.ts --max-warnings 0',\n lintfix: 'npm run lint -- --fix',\n docs: 'typedoc',\n prepublishOnly: 'node scripts/prepublish.js',\n release: 'npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish',\n postpublish: 'node scripts/postpublish.js',\n };\n\n // 检查是否存在 examples 目录,添加相关脚本\n const examplesDir = path.join(projectDir, 'examples');\n\n if (await fs.pathExists(examplesDir))\n {\n standardScripts['examples:dev'] = 'cd examples && npm run dev';\n standardScripts.postdocs = 'node scripts/postdocs.js && cd examples && vite build --outDir ../public';\n }\n\n for (const [key, value] of Object.entries(standardScripts))\n {\n if (!(key in packageJson.scripts))\n {\n packageJson.scripts[key] = value;\n updated = true;\n console.log(chalk.gray(` 添加: scripts.${key}`));\n }\n }\n\n // 设置标准入口点配置(配合 prepublish/postpublish 脚本使用,仅在不存在时添加)\n if (!packageJson.type)\n {\n packageJson.type = 'module';\n updated = true;\n console.log(chalk.gray(' 添加: type = \"module\"'));\n }\n\n const entryPoints = {\n main: './src/index.ts',\n types: './src/index.ts',\n module: './src/index.ts',\n };\n\n for (const [key, value] of Object.entries(entryPoints))\n {\n if (!(key in packageJson))\n {\n packageJson[key] = value;\n updated = true;\n console.log(chalk.gray(` 添加: ${key} = \"${value}\"`));\n }\n }\n\n // 设置 exports 配置(仅在不存在时添加)\n if (!packageJson.exports)\n {\n packageJson.exports = {\n '.': {\n types: './src/index.ts',\n import: './src/index.ts',\n require: './src/index.ts',\n },\n };\n updated = true;\n console.log(chalk.gray(' 添加: exports'));\n }\n\n // 只有在有更新时才写入文件\n if (updated)\n {\n const orderedPackageJson = reorderPackageJson(packageJson);\n let newContent = JSON.stringify(orderedPackageJson, null, indent);\n\n if (hasTrailingNewline)\n {\n newContent += '\\n';\n }\n await fs.writeFile(packageJsonPath, newContent);\n }\n}\n\n/**\n * 更新 package.json 添加 husky 配置\n */\nasync function updateHuskyConfig(projectDir: string): Promise<void>\n{\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 读取原始内容以检测缩进风格\n const originalContent = await fs.readFile(packageJsonPath, 'utf-8');\n const indent = detectIndent(originalContent);\n const hasTrailingNewline = originalContent.endsWith('\\n');\n\n const packageJson = JSON.parse(originalContent);\n let updated = false;\n\n // 添加 husky 和 lint-staged 依赖\n if (!packageJson.devDependencies)\n {\n packageJson.devDependencies = {};\n }\n if (!packageJson.devDependencies.husky)\n {\n packageJson.devDependencies.husky = VERSIONS.husky;\n updated = true;\n console.log(chalk.gray(` 添加: devDependencies.husky = \"${VERSIONS.husky}\"`));\n }\n if (!packageJson.devDependencies['lint-staged'])\n {\n packageJson.devDependencies['lint-staged'] = VERSIONS['lint-staged'];\n updated = true;\n console.log(chalk.gray(` 添加: devDependencies.lint-staged = \"${VERSIONS['lint-staged']}\"`));\n }\n\n // 添加 prepare 脚本\n if (!packageJson.scripts)\n {\n packageJson.scripts = {};\n }\n if (packageJson.scripts.prepare !== 'husky')\n {\n packageJson.scripts.prepare = 'husky';\n updated = true;\n console.log(chalk.gray(' 添加: scripts.prepare = \"husky\"'));\n }\n\n // 添加 lint-staged 配置\n if (!packageJson['lint-staged'])\n {\n packageJson['lint-staged'] = {\n '*.{js,ts}': ['eslint --fix --max-warnings 0'],\n };\n updated = true;\n console.log(chalk.gray(' 添加: lint-staged 配置'));\n }\n\n // 只有在有更新时才写入文件\n if (updated)\n {\n const orderedPackageJson = reorderPackageJson(packageJson);\n let newContent = JSON.stringify(orderedPackageJson, null, indent);\n\n if (hasTrailingNewline)\n {\n newContent += '\\n';\n }\n await fs.writeFile(packageJsonPath, newContent);\n }\n}\n","/**\n * 创建新项目命令\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport { getDevDependencies } from '../versions.js';\nimport {\n getGitignoreTemplate,\n getCursorrrulesTemplate,\n getTsconfigTemplate,\n getTypedocConfig,\n getPublishWorkflowTemplate,\n getPrepublishScriptTemplate,\n getPostpublishScriptTemplate,\n getPostdocsScriptTemplate,\n getSrcIndexTemplate,\n} from '../templates.js';\nimport { createEslintConfigFile } from './update.js';\n\nexport interface CreateOptions {\n directory: string;\n examples?: boolean;\n vitest?: boolean;\n}\n\n/**\n * 创建符合 feng3d 规范的新项目\n */\nexport async function createProject(name: string, options: CreateOptions): Promise<void>\n{\n const projectDir = path.join(options.directory, name);\n\n // 检查目录是否已存在\n if (await fs.pathExists(projectDir))\n {\n throw new Error(`目录 ${projectDir} 已存在`);\n }\n\n // 创建项目目录\n await fs.ensureDir(projectDir);\n await fs.ensureDir(path.join(projectDir, 'src'));\n\n console.log(chalk.gray(` 创建目录: ${projectDir}`));\n\n // 创建 package.json\n const packageJson = createPackageJson(name, options);\n\n await fs.writeJson(path.join(projectDir, 'package.json'), packageJson, { spaces: 4 });\n console.log(chalk.gray(' 创建: package.json'));\n\n // 创建 tsconfig.json\n await fs.writeJson(path.join(projectDir, 'tsconfig.json'), getTsconfigTemplate(), { spaces: 4 });\n console.log(chalk.gray(' 创建: tsconfig.json'));\n\n // 创建 .gitignore\n await fs.writeFile(path.join(projectDir, '.gitignore'), getGitignoreTemplate());\n console.log(chalk.gray(' 创建: .gitignore'));\n\n // 创建 .cursorrules\n await fs.writeFile(path.join(projectDir, '.cursorrules'), getCursorrrulesTemplate());\n console.log(chalk.gray(' 创建: .cursorrules'));\n\n // 创建 eslint.config.js\n await createEslintConfigFile(projectDir);\n console.log(chalk.gray(' 创建: eslint.config.js'));\n\n // 创建 typedoc.json\n const typedocConfig = getTypedocConfig({ repoName: name });\n\n await fs.writeJson(path.join(projectDir, 'typedoc.json'), typedocConfig, { spaces: 4 });\n console.log(chalk.gray(' 创建: typedoc.json'));\n\n // 创建 src/index.ts\n await fs.writeFile(path.join(projectDir, 'src/index.ts'), getSrcIndexTemplate({ name: `@feng3d/${name}` }));\n console.log(chalk.gray(' 创建: src/index.ts'));\n\n // 创建 README.md\n await fs.writeFile(path.join(projectDir, 'README.md'), `# @feng3d/${name}\\n`);\n console.log(chalk.gray(' 创建: README.md'));\n\n // 创建示例目录\n if (options.examples !== false)\n {\n await fs.ensureDir(path.join(projectDir, 'examples'));\n console.log(chalk.gray(' 创建: examples/'));\n }\n\n // 创建测试目录\n if (options.vitest !== false)\n {\n await fs.ensureDir(path.join(projectDir, 'test'));\n console.log(chalk.gray(' 创建: test/'));\n }\n\n // 创建 .github/workflows 目录和 publish.yml\n await fs.ensureDir(path.join(projectDir, '.github/workflows'));\n await fs.writeFile(path.join(projectDir, '.github/workflows/publish.yml'), getPublishWorkflowTemplate());\n console.log(chalk.gray(' 创建: .github/workflows/publish.yml'));\n\n // 创建 scripts 目录和发布脚本\n await fs.ensureDir(path.join(projectDir, 'scripts'));\n await fs.writeFile(path.join(projectDir, 'scripts/prepublish.js'), getPrepublishScriptTemplate());\n await fs.writeFile(path.join(projectDir, 'scripts/postpublish.js'), getPostpublishScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/prepublish.js'));\n console.log(chalk.gray(' 创建: scripts/postpublish.js'));\n\n // 如果创建了 examples 目录,添加 postdocs.js 脚本\n if (options.examples !== false)\n {\n await fs.writeFile(path.join(projectDir, 'scripts/postdocs.js'), getPostdocsScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/postdocs.js'));\n }\n}\n\n/**\n * 创建 package.json 内容\n */\nfunction createPackageJson(name: string, options: CreateOptions): object\n{\n const scripts: Record<string, string> = {\n clean: 'rimraf lib dist public',\n build: 'vite build && tsc',\n types: 'tsc',\n watch: 'tsc -w',\n lint: 'eslint . --ext .js,.ts --max-warnings 0',\n lintfix: 'npm run lint -- --fix',\n docs: 'typedoc',\n release: 'npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish',\n prepublishOnly: 'node scripts/prepublish.js',\n postpublish: 'node scripts/postpublish.js',\n };\n\n // 如果包含 examples 目录,添加相关脚本\n if (options.examples !== false)\n {\n scripts['examples:dev'] = 'cd examples && npm run dev';\n scripts.postdocs = 'node scripts/postdocs.js && cd examples && vite build --outDir ../public';\n }\n\n if (options.vitest !== false)\n {\n scripts.test = 'vitest run';\n scripts['test:watch'] = 'vitest';\n }\n\n return {\n name: `@feng3d/${name}`,\n version: '0.0.1',\n description: '',\n homepage: `https://feng3d.com/${name}/`,\n author: 'feng',\n type: 'module',\n main: './src/index.ts',\n types: './src/index.ts',\n module: './src/index.ts',\n exports: {\n '.': {\n types: './src/index.ts',\n import: './src/index.ts',\n require: './src/index.ts',\n },\n },\n scripts,\n repository: {\n type: 'git',\n url: `https://github.com/feng3d-labs/${name}.git`,\n },\n publishConfig: {\n access: 'public',\n },\n files: ['src', 'dist', 'lib'],\n devDependencies: getDevDependencies({\n includeVitest: options.vitest !== false,\n includeTypedoc: true,\n }),\n };\n}\n\n"],"names":["__dirname","TEMPLATES_DIR"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/versions.ts","../src/templates.ts","../src/commands/update.ts","../src/commands/create.ts"],"sourcesContent":["/**\n * feng3d 项目统一依赖版本\n * 从 templates/package.json 中读取\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\n/**\n * 模板目录路径\n */\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = path.resolve(__dirname, '../templates');\n\n/**\n * 从模板 package.json 中读取 devDependencies\n */\nfunction loadVersionsFromTemplate(): Record<string, string>\n{\n const packageJsonPath = path.join(TEMPLATES_DIR, 'package.json');\n const packageJson = fs.readJsonSync(packageJsonPath);\n\n return packageJson.devDependencies || {};\n}\n\n/**\n * 统一依赖版本(从 templates/package.json 读取)\n */\nexport const VERSIONS = loadVersionsFromTemplate();\n\n/**\n * 获取 devDependencies 配置\n */\nexport function getDevDependencies(options: {\n includeVitest?: boolean;\n includeTypedoc?: boolean;\n includeCoverage?: boolean;\n} = {}): Record<string, string>\n{\n // 从 VERSIONS 中复制所有依赖\n const deps: Record<string, string> = { ...VERSIONS };\n\n // 根据选项移除可选依赖\n if (options.includeVitest === false)\n {\n delete deps.vitest;\n }\n\n if (options.includeTypedoc === false)\n {\n delete deps.typedoc;\n }\n\n // 可选添加覆盖率依赖(默认不包含)\n if (options.includeCoverage && !deps['@vitest/coverage-v8'])\n {\n deps['@vitest/coverage-v8'] = '^3.2.4';\n }\n\n return deps;\n}\n","/**\n * 项目模板文件内容\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\n/**\n * 模板目录路径\n */\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = path.resolve(__dirname, '../templates');\n\n/**\n * 获取 .gitignore 模板内容\n */\nexport function getGitignoreTemplate(): string\n{\n // 模板文件命名为 gitignore(不带点),避免对 templates 目录生效\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'gitignore'), 'utf-8');\n}\n\n/**\n * 获取 .cursorrules 模板内容\n */\nexport function getCursorrrulesTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.cursorrules'), 'utf-8');\n}\n\n/**\n * 获取 tsconfig.json 模板内容(对象形式)\n */\nexport function getTsconfigTemplate(): object\n{\n return fs.readJsonSync(path.join(TEMPLATES_DIR, 'tsconfig.json'));\n}\n\n/**\n * 获取 tsconfig.json 模板内容(字符串形式)\n */\nexport function getTsconfigTemplateString(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'tsconfig.json'), 'utf-8');\n}\n\n/**\n * 获取 vite.config.js 模板内容\n */\nexport function getViteConfigTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'vite.config.js'), 'utf-8');\n}\n\n/**\n * 获取 eslint.config.js 模板内容\n */\nexport function getEslintConfigTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'eslint.config.js'), 'utf-8');\n}\n\n/**\n * 获取 typedoc.json 模板内容(返回对象)\n */\nexport function getTypedocConfig(options: {\n repoName: string;\n}): object\n{\n return JSON.parse(getTypedocConfigTemplate(options));\n}\n\n/**\n * 获取 typedoc.json 模板内容(返回字符串)\n */\nexport function getTypedocConfigTemplate(options: {\n repoName: string;\n}): string\n{\n const templateContent = fs.readFileSync(path.join(TEMPLATES_DIR, 'typedoc.json'), 'utf-8');\n\n return templateContent.replace(/\\{\\{repoName\\}\\}/g, options.repoName);\n}\n\n/**\n * 获取 test/_.test.ts 模板内容(空文件占位)\n */\nexport function getTestIndexTemplate(_options: { name: string }): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'test/_.test.ts'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions publish workflow 模板内容\n */\nexport function getPublishWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/publish.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions pages workflow 模板内容\n */\nexport function getPagesWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/pages.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions pull-request workflow 模板内容\n */\nexport function getPullRequestWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/pull-request.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions upload-oss workflow 模板内容\n */\nexport function getUploadOssWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/upload-oss.yml'), 'utf-8');\n}\n\n/**\n * 获取 .husky/pre-commit 模板内容\n */\nexport function getHuskyPreCommitTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.husky/pre-commit'), 'utf-8');\n}\n\n/**\n * 获取 LICENSE 模板内容\n */\nexport function getLicenseTemplate(ctx: { year?: number } = {}): string\n{\n const year = ctx.year || new Date().getFullYear();\n const template = fs.readFileSync(path.join(TEMPLATES_DIR, 'LICENSE'), 'utf-8');\n\n return template.replace('{{year}}', String(year));\n}\n\n/**\n * 获取 .vscode/settings.json 模板内容\n */\nexport function getVscodeSettingsTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.vscode/settings.json'), 'utf-8');\n}\n\n/**\n * 获取 scripts/prepublish.js 模板内容\n */\nexport function getPrepublishScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/prepublish.js'), 'utf-8');\n}\n\n/**\n * 获取 scripts/postpublish.js 模板内容\n */\nexport function getPostpublishScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/postpublish.js'), 'utf-8');\n}\n\n/**\n * 获取 scripts/postdocs.js 模板内容\n */\nexport function getPostdocsScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/postdocs.js'), 'utf-8');\n}\n\n/**\n * 获取 src/index.ts 模板内容\n */\nexport function getSrcIndexTemplate(options: { name: string }): string\n{\n const template = fs.readFileSync(path.join(TEMPLATES_DIR, 'src/index.ts'), 'utf-8');\n\n return template.replace(/\\{\\{name\\}\\}/g, options.name);\n}\n\n/**\n * 获取 vitest.config.ts 模板内容\n */\nexport function getVitestConfigTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'vitest.config.ts'), 'utf-8');\n}\n\n","/**\n * 更新项目规范命令\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport { getDevDependencies, VERSIONS } from '../versions.js';\nimport {\n getGitignoreTemplate,\n getCursorrrulesTemplate,\n getEslintConfigTemplate,\n getPublishWorkflowTemplate,\n getPagesWorkflowTemplate,\n getPullRequestWorkflowTemplate,\n getUploadOssWorkflowTemplate,\n getTypedocConfigTemplate,\n getTestIndexTemplate,\n getHuskyPreCommitTemplate,\n getLicenseTemplate,\n getVscodeSettingsTemplate,\n getTsconfigTemplateString,\n getViteConfigTemplate,\n getVitestConfigTemplate,\n getPrepublishScriptTemplate,\n getPostpublishScriptTemplate,\n getPostdocsScriptTemplate,\n getSrcIndexTemplate,\n} from '../templates.js';\n\n/**\n * 模板上下文\n */\ninterface TemplateContext {\n name: string;\n repoName: string;\n}\n\n/**\n * 更新项目的规范配置\n * @param directory 项目目录路径\n */\nexport async function updateProject(directory: string = '.'): Promise<void>\n{\n const projectDir = path.resolve(directory);\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 如果 package.json 不存在,创建基础 package.json\n if (!await fs.pathExists(packageJsonPath))\n {\n await fs.ensureDir(projectDir);\n const dirName = path.basename(projectDir);\n const initialPackageJson = {\n name: `@feng3d/${dirName}`,\n version: '0.0.1',\n description: '',\n };\n\n await fs.writeJson(packageJsonPath, initialPackageJson, { spaces: 4 });\n console.log(chalk.gray(' 创建: package.json'));\n\n // 创建 src/index.ts\n const srcDir = path.join(projectDir, 'src');\n\n await fs.ensureDir(srcDir);\n await fs.writeFile(path.join(srcDir, 'index.ts'), getSrcIndexTemplate({ name: `@feng3d/${dirName}` }));\n console.log(chalk.gray(' 创建: src/index.ts'));\n }\n\n // 获取项目信息用于模板\n const packageJson = await fs.readJson(packageJsonPath);\n const name = packageJson.name || path.basename(projectDir);\n const repoName = name.replace(/^@[^/]+\\//, ''); // 移除 scope 前缀\n const templateContext: TemplateContext = { name, repoName };\n\n // feng3d-cli 项目:不更新 tsconfig.json 和 vite.config.js(有自定义配置)\n const isFeng3dCli = name === 'feng3d-cli';\n\n // 更新 .gitignore(强制覆盖)\n await fs.writeFile(path.join(projectDir, '.gitignore'), getGitignoreTemplate());\n console.log(chalk.gray(' 更新: .gitignore'));\n\n // 更新 .cursorrules\n await fs.writeFile(path.join(projectDir, '.cursorrules'), getCursorrrulesTemplate());\n console.log(chalk.gray(' 更新: .cursorrules'));\n\n // 更新 eslint.config.js\n await createEslintConfigFile(projectDir);\n console.log(chalk.gray(' 更新: eslint.config.js'));\n\n // 更新 .github/workflows/publish.yml\n await fs.ensureDir(path.join(projectDir, '.github/workflows'));\n await fs.writeFile(path.join(projectDir, '.github/workflows/publish.yml'), getPublishWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/publish.yml'));\n\n // 更新 .github/workflows/pages.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/pages.yml'), getPagesWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/pages.yml'));\n\n // 更新 .github/workflows/pull-request.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/pull-request.yml'), getPullRequestWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/pull-request.yml'));\n\n // 更新 .github/workflows/upload-oss.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/upload-oss.yml'), getUploadOssWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/upload-oss.yml'));\n\n // 更新 typedoc.json\n const typedocContent = getTypedocConfigTemplate({ repoName });\n\n await fs.writeFile(path.join(projectDir, 'typedoc.json'), typedocContent);\n console.log(chalk.gray(' 更新: typedoc.json'));\n\n // 更新 test/_.test.ts(强制覆盖)\n const testDir = path.join(projectDir, 'test');\n\n await fs.ensureDir(testDir);\n const testContent = getTestIndexTemplate({ name });\n\n await fs.writeFile(path.join(testDir, '_.test.ts'), testContent);\n console.log(chalk.gray(' 更新: test/_.test.ts'));\n\n // 更新依赖版本\n await updateDependencies(projectDir);\n console.log(chalk.gray(' 更新: package.json devDependencies'));\n\n // 更新 husky pre-commit hook\n await fs.ensureDir(path.join(projectDir, '.husky'));\n await fs.writeFile(path.join(projectDir, '.husky/pre-commit'), getHuskyPreCommitTemplate());\n console.log(chalk.gray(' 更新: .husky/pre-commit'));\n await updateHuskyConfig(projectDir);\n\n // 更新 LICENSE 文件(强制覆盖)\n await fs.writeFile(path.join(projectDir, 'LICENSE'), getLicenseTemplate());\n console.log(chalk.gray(' 更新: LICENSE'));\n\n // 更新 .vscode/settings.json\n await fs.ensureDir(path.join(projectDir, '.vscode'));\n await fs.writeFile(path.join(projectDir, '.vscode/settings.json'), getVscodeSettingsTemplate());\n console.log(chalk.gray(' 更新: .vscode/settings.json'));\n\n // 更新 tsconfig.json(强制覆盖,feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n await fs.writeFile(path.join(projectDir, 'tsconfig.json'), getTsconfigTemplateString());\n console.log(chalk.gray(' 更新: tsconfig.json'));\n }\n\n // 更新 vite.config.js(强制覆盖,feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n await fs.writeFile(path.join(projectDir, 'vite.config.js'), getViteConfigTemplate());\n console.log(chalk.gray(' 更新: vite.config.js'));\n }\n\n // 更新 vitest.config.ts(强制覆盖,feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n await fs.writeFile(path.join(projectDir, 'vitest.config.ts'), getVitestConfigTemplate());\n console.log(chalk.gray(' 更新: vitest.config.ts'));\n }\n\n // 更新发布脚本(强制覆盖)\n const scriptsDir = path.join(projectDir, 'scripts');\n\n await fs.ensureDir(scriptsDir);\n await fs.writeFile(path.join(scriptsDir, 'prepublish.js'), getPrepublishScriptTemplate());\n console.log(chalk.gray(' 更新: scripts/prepublish.js'));\n\n await fs.writeFile(path.join(scriptsDir, 'postpublish.js'), getPostpublishScriptTemplate());\n console.log(chalk.gray(' 更新: scripts/postpublish.js'));\n\n // 如果存在 examples 目录,更新 postdocs.js 脚本(强制覆盖)\n const examplesDir = path.join(projectDir, 'examples');\n\n if (await fs.pathExists(examplesDir))\n {\n await fs.writeFile(path.join(scriptsDir, 'postdocs.js'), getPostdocsScriptTemplate());\n console.log(chalk.gray(' 更新: scripts/postdocs.js'));\n }\n}\n\n/**\n * 创建 ESLint 配置文件\n */\nexport async function createEslintConfigFile(projectDir: string): Promise<void>\n{\n await fs.writeFile(path.join(projectDir, 'eslint.config.js'), getEslintConfigTemplate());\n}\n\n/**\n * 检测 JSON 文件的缩进风格\n */\nfunction detectIndent(content: string): string\n{\n const match = content.match(/^[ \\t]+/m);\n\n return match ? match[0] : ' ';\n}\n\n/**\n * package.json 字段的标准顺序\n */\nconst PACKAGE_JSON_FIELD_ORDER = [\n 'name',\n 'version',\n 'description',\n 'homepage',\n 'author',\n 'license',\n 'type',\n 'main',\n 'types',\n 'module',\n 'exports',\n 'bin',\n 'scripts',\n 'repository',\n 'publishConfig',\n 'files',\n 'devDependencies',\n 'dependencies',\n 'peerDependencies',\n 'lint-staged',\n];\n\n/**\n * scripts 字段的标准顺序\n */\nconst SCRIPTS_ORDER = [\n 'examples:dev',\n 'test_web',\n 'postdocs',\n 'clean',\n 'build',\n 'watch',\n 'test',\n 'lint',\n 'lintfix',\n 'docs',\n 'prepublishOnly',\n 'release',\n 'postpublish',\n 'prepare',\n];\n\n/**\n * 按标准顺序重新排列对象字段\n */\nfunction reorderObject(obj: Record<string, unknown>, order: string[]): Record<string, unknown>\n{\n const ordered: Record<string, unknown> = {};\n\n // 先按标准顺序添加已存在的字段\n for (const key of order)\n {\n if (key in obj)\n {\n ordered[key] = obj[key];\n }\n }\n\n // 再添加其他未在标准顺序中的字段\n for (const key of Object.keys(obj))\n {\n if (!(key in ordered))\n {\n ordered[key] = obj[key];\n }\n }\n\n return ordered;\n}\n\n/**\n * 按标准顺序重新排列 package.json 字段\n */\nfunction reorderPackageJson(packageJson: Record<string, unknown>): Record<string, unknown>\n{\n const ordered = reorderObject(packageJson, PACKAGE_JSON_FIELD_ORDER);\n\n // 重新排列 scripts\n if (ordered.scripts && typeof ordered.scripts === 'object')\n {\n ordered.scripts = reorderObject(ordered.scripts as Record<string, unknown>, SCRIPTS_ORDER);\n }\n\n return ordered;\n}\n\n/**\n * 更新 package.json 中的 devDependencies 版本\n */\nasync function updateDependencies(projectDir: string): Promise<void>\n{\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 读取原始内容以检测缩进风格\n const originalContent = await fs.readFile(packageJsonPath, 'utf-8');\n const indent = detectIndent(originalContent);\n const hasTrailingNewline = originalContent.endsWith('\\n');\n\n const packageJson = JSON.parse(originalContent);\n\n const standardDeps = getDevDependencies({\n includeVitest: true,\n includeTypedoc: true,\n });\n\n // 添加或更新 devDependencies\n let updated = false;\n\n if (!packageJson.devDependencies)\n {\n packageJson.devDependencies = {};\n }\n\n for (const [key, value] of Object.entries(standardDeps))\n {\n if (!(key in packageJson.devDependencies))\n {\n packageJson.devDependencies[key] = value;\n updated = true;\n console.log(chalk.gray(` 添加: devDependencies.${key} = \"${value}\"`));\n }\n else if (packageJson.devDependencies[key] !== value)\n {\n packageJson.devDependencies[key] = value;\n updated = true;\n console.log(chalk.gray(` 更新: devDependencies.${key} = \"${value}\"`));\n }\n }\n\n // 添加标准 scripts\n if (!packageJson.scripts)\n {\n packageJson.scripts = {};\n }\n\n const standardScripts: Record<string, string> = {\n clean: 'rimraf lib dist public',\n build: 'vite build && tsc',\n watch: 'concurrently \"vite build --watch\" \"tsc -w\" \"vitest\"',\n test: 'vitest run',\n lint: 'eslint . --ext .js,.ts --max-warnings 0',\n lintfix: 'npm run lint -- --fix',\n docs: 'typedoc',\n prepublishOnly: 'node scripts/prepublish.js',\n release: 'npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish',\n postpublish: 'node scripts/postpublish.js',\n };\n\n // 检查是否存在 examples 目录,添加相关脚本\n const examplesDir = path.join(projectDir, 'examples');\n\n if (await fs.pathExists(examplesDir))\n {\n standardScripts['examples:dev'] = 'cd examples && npm run dev';\n standardScripts.postdocs = 'node scripts/postdocs.js && cd examples && vite build --outDir ../public';\n }\n\n // 强制覆盖标准 scripts\n for (const [key, value] of Object.entries(standardScripts))\n {\n if (packageJson.scripts[key] !== value)\n {\n packageJson.scripts[key] = value;\n updated = true;\n console.log(chalk.gray(` 更新: scripts.${key}`));\n }\n }\n\n // 设置标准入口点配置(强制覆盖)\n if (packageJson.type !== 'module')\n {\n packageJson.type = 'module';\n updated = true;\n console.log(chalk.gray(' 更新: type = \"module\"'));\n }\n\n const entryPoints = {\n main: './src/index.ts',\n types: './src/index.ts',\n module: './src/index.ts',\n };\n\n for (const [key, value] of Object.entries(entryPoints))\n {\n if (packageJson[key] !== value)\n {\n packageJson[key] = value;\n updated = true;\n console.log(chalk.gray(` 更新: ${key} = \"${value}\"`));\n }\n }\n\n // 设置 exports 配置(强制覆盖)\n const standardExports = {\n '.': {\n types: './src/index.ts',\n import: './src/index.ts',\n require: './src/index.ts',\n },\n };\n\n if (JSON.stringify(packageJson.exports) !== JSON.stringify(standardExports))\n {\n packageJson.exports = standardExports;\n updated = true;\n console.log(chalk.gray(' 更新: exports'));\n }\n\n // 只有在有更新时才写入文件\n if (updated)\n {\n const orderedPackageJson = reorderPackageJson(packageJson);\n let newContent = JSON.stringify(orderedPackageJson, null, indent);\n\n if (hasTrailingNewline)\n {\n newContent += '\\n';\n }\n await fs.writeFile(packageJsonPath, newContent);\n }\n}\n\n/**\n * 更新 package.json 添加 husky 配置\n */\nasync function updateHuskyConfig(projectDir: string): Promise<void>\n{\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 读取原始内容以检测缩进风格\n const originalContent = await fs.readFile(packageJsonPath, 'utf-8');\n const indent = detectIndent(originalContent);\n const hasTrailingNewline = originalContent.endsWith('\\n');\n\n const packageJson = JSON.parse(originalContent);\n let updated = false;\n\n // 强制覆盖 husky 和 lint-staged 依赖\n if (!packageJson.devDependencies)\n {\n packageJson.devDependencies = {};\n }\n if (packageJson.devDependencies.husky !== VERSIONS.husky)\n {\n packageJson.devDependencies.husky = VERSIONS.husky;\n updated = true;\n console.log(chalk.gray(` 更新: devDependencies.husky = \"${VERSIONS.husky}\"`));\n }\n if (packageJson.devDependencies['lint-staged'] !== VERSIONS['lint-staged'])\n {\n packageJson.devDependencies['lint-staged'] = VERSIONS['lint-staged'];\n updated = true;\n console.log(chalk.gray(` 更新: devDependencies.lint-staged = \"${VERSIONS['lint-staged']}\"`));\n }\n\n // 强制覆盖 prepare 脚本\n if (!packageJson.scripts)\n {\n packageJson.scripts = {};\n }\n if (packageJson.scripts.prepare !== 'husky')\n {\n packageJson.scripts.prepare = 'husky';\n updated = true;\n console.log(chalk.gray(' 更新: scripts.prepare = \"husky\"'));\n }\n\n // 强制覆盖 lint-staged 配置\n const standardLintStaged = {\n '*.{js,ts}': ['eslint --fix --max-warnings 0'],\n };\n\n if (JSON.stringify(packageJson['lint-staged']) !== JSON.stringify(standardLintStaged))\n {\n packageJson['lint-staged'] = standardLintStaged;\n updated = true;\n console.log(chalk.gray(' 更新: lint-staged 配置'));\n }\n\n // 只有在有更新时才写入文件\n if (updated)\n {\n const orderedPackageJson = reorderPackageJson(packageJson);\n let newContent = JSON.stringify(orderedPackageJson, null, indent);\n\n if (hasTrailingNewline)\n {\n newContent += '\\n';\n }\n await fs.writeFile(packageJsonPath, newContent);\n }\n}\n","/**\n * 创建新项目命令\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport { getDevDependencies } from '../versions.js';\nimport {\n getGitignoreTemplate,\n getCursorrrulesTemplate,\n getTsconfigTemplate,\n getTypedocConfig,\n getPublishWorkflowTemplate,\n getPrepublishScriptTemplate,\n getPostpublishScriptTemplate,\n getPostdocsScriptTemplate,\n getSrcIndexTemplate,\n} from '../templates.js';\nimport { createEslintConfigFile } from './update.js';\n\nexport interface CreateOptions {\n directory: string;\n examples?: boolean;\n vitest?: boolean;\n}\n\n/**\n * 创建符合 feng3d 规范的新项目\n */\nexport async function createProject(name: string, options: CreateOptions): Promise<void>\n{\n const projectDir = path.join(options.directory, name);\n\n // 检查目录是否已存在\n if (await fs.pathExists(projectDir))\n {\n throw new Error(`目录 ${projectDir} 已存在`);\n }\n\n // 创建项目目录\n await fs.ensureDir(projectDir);\n await fs.ensureDir(path.join(projectDir, 'src'));\n\n console.log(chalk.gray(` 创建目录: ${projectDir}`));\n\n // 创建 package.json\n const packageJson = createPackageJson(name, options);\n\n await fs.writeJson(path.join(projectDir, 'package.json'), packageJson, { spaces: 4 });\n console.log(chalk.gray(' 创建: package.json'));\n\n // 创建 tsconfig.json\n await fs.writeJson(path.join(projectDir, 'tsconfig.json'), getTsconfigTemplate(), { spaces: 4 });\n console.log(chalk.gray(' 创建: tsconfig.json'));\n\n // 创建 .gitignore\n await fs.writeFile(path.join(projectDir, '.gitignore'), getGitignoreTemplate());\n console.log(chalk.gray(' 创建: .gitignore'));\n\n // 创建 .cursorrules\n await fs.writeFile(path.join(projectDir, '.cursorrules'), getCursorrrulesTemplate());\n console.log(chalk.gray(' 创建: .cursorrules'));\n\n // 创建 eslint.config.js\n await createEslintConfigFile(projectDir);\n console.log(chalk.gray(' 创建: eslint.config.js'));\n\n // 创建 typedoc.json\n const typedocConfig = getTypedocConfig({ repoName: name });\n\n await fs.writeJson(path.join(projectDir, 'typedoc.json'), typedocConfig, { spaces: 4 });\n console.log(chalk.gray(' 创建: typedoc.json'));\n\n // 创建 src/index.ts\n await fs.writeFile(path.join(projectDir, 'src/index.ts'), getSrcIndexTemplate({ name: `@feng3d/${name}` }));\n console.log(chalk.gray(' 创建: src/index.ts'));\n\n // 创建 README.md\n await fs.writeFile(path.join(projectDir, 'README.md'), `# @feng3d/${name}\\n`);\n console.log(chalk.gray(' 创建: README.md'));\n\n // 创建示例目录\n if (options.examples !== false)\n {\n await fs.ensureDir(path.join(projectDir, 'examples'));\n console.log(chalk.gray(' 创建: examples/'));\n }\n\n // 创建测试目录\n if (options.vitest !== false)\n {\n await fs.ensureDir(path.join(projectDir, 'test'));\n console.log(chalk.gray(' 创建: test/'));\n }\n\n // 创建 .github/workflows 目录和 publish.yml\n await fs.ensureDir(path.join(projectDir, '.github/workflows'));\n await fs.writeFile(path.join(projectDir, '.github/workflows/publish.yml'), getPublishWorkflowTemplate());\n console.log(chalk.gray(' 创建: .github/workflows/publish.yml'));\n\n // 创建 scripts 目录和发布脚本\n await fs.ensureDir(path.join(projectDir, 'scripts'));\n await fs.writeFile(path.join(projectDir, 'scripts/prepublish.js'), getPrepublishScriptTemplate());\n await fs.writeFile(path.join(projectDir, 'scripts/postpublish.js'), getPostpublishScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/prepublish.js'));\n console.log(chalk.gray(' 创建: scripts/postpublish.js'));\n\n // 如果创建了 examples 目录,添加 postdocs.js 脚本\n if (options.examples !== false)\n {\n await fs.writeFile(path.join(projectDir, 'scripts/postdocs.js'), getPostdocsScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/postdocs.js'));\n }\n}\n\n/**\n * 创建 package.json 内容\n */\nfunction createPackageJson(name: string, options: CreateOptions): object\n{\n const scripts: Record<string, string> = {\n clean: 'rimraf lib dist public',\n build: 'vite build && tsc',\n types: 'tsc',\n watch: 'tsc -w',\n lint: 'eslint . --ext .js,.ts --max-warnings 0',\n lintfix: 'npm run lint -- --fix',\n docs: 'typedoc',\n release: 'npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish',\n prepublishOnly: 'node scripts/prepublish.js',\n postpublish: 'node scripts/postpublish.js',\n };\n\n // 如果包含 examples 目录,添加相关脚本\n if (options.examples !== false)\n {\n scripts['examples:dev'] = 'cd examples && npm run dev';\n scripts.postdocs = 'node scripts/postdocs.js && cd examples && vite build --outDir ../public';\n }\n\n if (options.vitest !== false)\n {\n scripts.test = 'vitest run';\n scripts['test:watch'] = 'vitest';\n }\n\n return {\n name: `@feng3d/${name}`,\n version: '0.0.1',\n description: '',\n homepage: `https://feng3d.com/${name}/`,\n author: 'feng',\n type: 'module',\n main: './src/index.ts',\n types: './src/index.ts',\n module: './src/index.ts',\n exports: {\n '.': {\n types: './src/index.ts',\n import: './src/index.ts',\n require: './src/index.ts',\n },\n },\n scripts,\n repository: {\n type: 'git',\n url: `https://github.com/feng3d-labs/${name}.git`,\n },\n publishConfig: {\n access: 'public',\n },\n files: ['src', 'dist', 'lib'],\n devDependencies: getDevDependencies({\n includeVitest: options.vitest !== false,\n includeTypedoc: true,\n }),\n };\n}\n\n"],"names":["__dirname","TEMPLATES_DIR"],"mappings":"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"}
@@ -90,6 +90,9 @@
90
90
  const template = fs.readFileSync(path.join(TEMPLATES_DIR, "src/index.ts"), "utf-8");
91
91
  return template.replace(/\{\{name\}\}/g, options.name);
92
92
  }
93
+ function getVitestConfigTemplate() {
94
+ return fs.readFileSync(path.join(TEMPLATES_DIR, "vitest.config.ts"), "utf-8");
95
+ }
93
96
  async function updateProject(directory = ".") {
94
97
  const projectDir = path.resolve(directory);
95
98
  const packageJsonPath = path.join(projectDir, "package.json");
@@ -112,13 +115,8 @@
112
115
  const name = packageJson.name || path.basename(projectDir);
113
116
  const repoName = name.replace(/^@[^/]+\//, "");
114
117
  const isFeng3dCli = name === "feng3d-cli";
115
- const gitignorePath = path.join(projectDir, ".gitignore");
116
- if (!await fs.pathExists(gitignorePath)) {
117
- await fs.writeFile(gitignorePath, getGitignoreTemplate());
118
- console.log(chalk.gray(" 创建: .gitignore"));
119
- } else {
120
- console.log(chalk.gray(" 跳过: .gitignore(已存在)"));
121
- }
118
+ await fs.writeFile(path.join(projectDir, ".gitignore"), getGitignoreTemplate());
119
+ console.log(chalk.gray(" 更新: .gitignore"));
122
120
  await fs.writeFile(path.join(projectDir, ".cursorrules"), getCursorrrulesTemplate());
123
121
  console.log(chalk.gray(" 更新: .cursorrules"));
124
122
  await createEslintConfigFile(projectDir);
@@ -136,75 +134,43 @@
136
134
  await fs.writeFile(path.join(projectDir, "typedoc.json"), typedocContent);
137
135
  console.log(chalk.gray(" 更新: typedoc.json"));
138
136
  const testDir = path.join(projectDir, "test");
139
- const testFilePath = path.join(testDir, "_.test.ts");
140
- let hasOtherFiles = false;
141
- if (await fs.pathExists(testDir)) {
142
- const files = await fs.readdir(testDir);
143
- hasOtherFiles = files.some((file) => file !== "_.test.ts");
144
- }
145
- if (!hasOtherFiles) {
146
- await fs.ensureDir(testDir);
147
- const testContent = getTestIndexTemplate();
148
- await fs.writeFile(testFilePath, testContent);
149
- console.log(chalk.gray(" 更新: test/_.test.ts"));
150
- } else {
151
- console.log(chalk.gray(" 跳过: test/_.test.ts(测试目录已有其他文件)"));
152
- }
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"));
153
141
  await updateDependencies(projectDir);
154
142
  console.log(chalk.gray(" 更新: package.json devDependencies"));
155
143
  await fs.ensureDir(path.join(projectDir, ".husky"));
156
144
  await fs.writeFile(path.join(projectDir, ".husky/pre-commit"), getHuskyPreCommitTemplate());
157
145
  console.log(chalk.gray(" 更新: .husky/pre-commit"));
158
146
  await updateHuskyConfig(projectDir);
159
- const licensePath = path.join(projectDir, "LICENSE");
160
- if (!await fs.pathExists(licensePath)) {
161
- await fs.writeFile(licensePath, getLicenseTemplate());
162
- console.log(chalk.gray(" 创建: LICENSE"));
163
- } else {
164
- console.log(chalk.gray(" 跳过: LICENSE(已存在)"));
165
- }
147
+ await fs.writeFile(path.join(projectDir, "LICENSE"), getLicenseTemplate());
148
+ console.log(chalk.gray(" 更新: LICENSE"));
166
149
  await fs.ensureDir(path.join(projectDir, ".vscode"));
167
150
  await fs.writeFile(path.join(projectDir, ".vscode/settings.json"), getVscodeSettingsTemplate());
168
151
  console.log(chalk.gray(" 更新: .vscode/settings.json"));
169
152
  if (!isFeng3dCli) {
170
- const tsconfigPath = path.join(projectDir, "tsconfig.json");
171
- if (!await fs.pathExists(tsconfigPath)) {
172
- await fs.writeFile(tsconfigPath, getTsconfigTemplateString());
173
- console.log(chalk.gray(" 创建: tsconfig.json"));
174
- } else {
175
- console.log(chalk.gray(" 跳过: tsconfig.json(已存在)"));
176
- }
153
+ await fs.writeFile(path.join(projectDir, "tsconfig.json"), getTsconfigTemplateString());
154
+ console.log(chalk.gray(" 更新: tsconfig.json"));
177
155
  }
178
156
  if (!isFeng3dCli) {
179
- const viteConfigPath = path.join(projectDir, "vite.config.js");
180
- if (!await fs.pathExists(viteConfigPath)) {
181
- await fs.writeFile(viteConfigPath, getViteConfigTemplate());
182
- console.log(chalk.gray(" 创建: vite.config.js"));
183
- } else {
184
- console.log(chalk.gray(" 跳过: vite.config.js(已存在)"));
185
- }
157
+ await fs.writeFile(path.join(projectDir, "vite.config.js"), getViteConfigTemplate());
158
+ console.log(chalk.gray(" 更新: vite.config.js"));
186
159
  }
187
- const scriptsDir = path.join(projectDir, "scripts");
188
- const prepublishPath = path.join(scriptsDir, "prepublish.js");
189
- const postpublishPath = path.join(scriptsDir, "postpublish.js");
190
- if (!await fs.pathExists(prepublishPath)) {
191
- await fs.ensureDir(scriptsDir);
192
- await fs.writeFile(prepublishPath, getPrepublishScriptTemplate());
193
- console.log(chalk.gray(" 创建: scripts/prepublish.js"));
194
- }
195
- if (!await fs.pathExists(postpublishPath)) {
196
- await fs.ensureDir(scriptsDir);
197
- await fs.writeFile(postpublishPath, getPostpublishScriptTemplate());
198
- console.log(chalk.gray(" 创建: scripts/postpublish.js"));
160
+ if (!isFeng3dCli) {
161
+ await fs.writeFile(path.join(projectDir, "vitest.config.ts"), getVitestConfigTemplate());
162
+ console.log(chalk.gray(" 更新: vitest.config.ts"));
199
163
  }
164
+ const scriptsDir = path.join(projectDir, "scripts");
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"));
200
170
  const examplesDir = path.join(projectDir, "examples");
201
- const postdocsPath = path.join(scriptsDir, "postdocs.js");
202
171
  if (await fs.pathExists(examplesDir)) {
203
- if (!await fs.pathExists(postdocsPath)) {
204
- await fs.ensureDir(scriptsDir);
205
- await fs.writeFile(postdocsPath, getPostdocsScriptTemplate());
206
- console.log(chalk.gray(" 创建: scripts/postdocs.js"));
207
- }
172
+ await fs.writeFile(path.join(scriptsDir, "postdocs.js"), getPostdocsScriptTemplate());
173
+ console.log(chalk.gray(" 更新: scripts/postdocs.js"));
208
174
  }
209
175
  }
210
176
  async function createEslintConfigFile(projectDir) {
@@ -319,16 +285,16 @@
319
285
  standardScripts.postdocs = "node scripts/postdocs.js && cd examples && vite build --outDir ../public";
320
286
  }
321
287
  for (const [key, value] of Object.entries(standardScripts)) {
322
- if (!(key in packageJson.scripts)) {
288
+ if (packageJson.scripts[key] !== value) {
323
289
  packageJson.scripts[key] = value;
324
290
  updated = true;
325
- console.log(chalk.gray(` 添加: scripts.${key}`));
291
+ console.log(chalk.gray(` 更新: scripts.${key}`));
326
292
  }
327
293
  }
328
- if (!packageJson.type) {
294
+ if (packageJson.type !== "module") {
329
295
  packageJson.type = "module";
330
296
  updated = true;
331
- console.log(chalk.gray(' 添加: type = "module"'));
297
+ console.log(chalk.gray(' 更新: type = "module"'));
332
298
  }
333
299
  const entryPoints = {
334
300
  main: "./src/index.ts",
@@ -336,22 +302,23 @@
336
302
  module: "./src/index.ts"
337
303
  };
338
304
  for (const [key, value] of Object.entries(entryPoints)) {
339
- if (!(key in packageJson)) {
305
+ if (packageJson[key] !== value) {
340
306
  packageJson[key] = value;
341
307
  updated = true;
342
- console.log(chalk.gray(` 添加: ${key} = "${value}"`));
308
+ console.log(chalk.gray(` 更新: ${key} = "${value}"`));
343
309
  }
344
310
  }
345
- if (!packageJson.exports) {
346
- packageJson.exports = {
347
- ".": {
348
- types: "./src/index.ts",
349
- import: "./src/index.ts",
350
- require: "./src/index.ts"
351
- }
352
- };
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;
353
320
  updated = true;
354
- console.log(chalk.gray(" 添加: exports"));
321
+ console.log(chalk.gray(" 更新: exports"));
355
322
  }
356
323
  if (updated) {
357
324
  const orderedPackageJson = reorderPackageJson(packageJson);
@@ -372,15 +339,15 @@
372
339
  if (!packageJson.devDependencies) {
373
340
  packageJson.devDependencies = {};
374
341
  }
375
- if (!packageJson.devDependencies.husky) {
342
+ if (packageJson.devDependencies.husky !== VERSIONS.husky) {
376
343
  packageJson.devDependencies.husky = VERSIONS.husky;
377
344
  updated = true;
378
- console.log(chalk.gray(` 添加: devDependencies.husky = "${VERSIONS.husky}"`));
345
+ console.log(chalk.gray(` 更新: devDependencies.husky = "${VERSIONS.husky}"`));
379
346
  }
380
- if (!packageJson.devDependencies["lint-staged"]) {
347
+ if (packageJson.devDependencies["lint-staged"] !== VERSIONS["lint-staged"]) {
381
348
  packageJson.devDependencies["lint-staged"] = VERSIONS["lint-staged"];
382
349
  updated = true;
383
- console.log(chalk.gray(` 添加: devDependencies.lint-staged = "${VERSIONS["lint-staged"]}"`));
350
+ console.log(chalk.gray(` 更新: devDependencies.lint-staged = "${VERSIONS["lint-staged"]}"`));
384
351
  }
385
352
  if (!packageJson.scripts) {
386
353
  packageJson.scripts = {};
@@ -388,14 +355,15 @@
388
355
  if (packageJson.scripts.prepare !== "husky") {
389
356
  packageJson.scripts.prepare = "husky";
390
357
  updated = true;
391
- console.log(chalk.gray(' 添加: scripts.prepare = "husky"'));
358
+ console.log(chalk.gray(' 更新: scripts.prepare = "husky"'));
392
359
  }
393
- if (!packageJson["lint-staged"]) {
394
- packageJson["lint-staged"] = {
395
- "*.{js,ts}": ["eslint --fix --max-warnings 0"]
396
- };
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;
397
365
  updated = true;
398
- console.log(chalk.gray(" 添加: lint-staged 配置"));
366
+ console.log(chalk.gray(" 更新: lint-staged 配置"));
399
367
  }
400
368
  if (updated) {
401
369
  const orderedPackageJson = reorderPackageJson(packageJson);
@@ -529,6 +497,7 @@
529
497
  exports2.getTypedocConfigTemplate = getTypedocConfigTemplate;
530
498
  exports2.getUploadOssWorkflowTemplate = getUploadOssWorkflowTemplate;
531
499
  exports2.getViteConfigTemplate = getViteConfigTemplate;
500
+ exports2.getVitestConfigTemplate = getVitestConfigTemplate;
532
501
  exports2.getVscodeSettingsTemplate = getVscodeSettingsTemplate;
533
502
  exports2.updateProject = updateProject;
534
503
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.cjs","sources":["../src/versions.ts","../src/templates.ts","../src/commands/update.ts","../src/commands/create.ts"],"sourcesContent":["/**\n * feng3d 项目统一依赖版本\n * 从 templates/package.json 中读取\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\n/**\n * 模板目录路径\n */\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = path.resolve(__dirname, '../templates');\n\n/**\n * 从模板 package.json 中读取 devDependencies\n */\nfunction loadVersionsFromTemplate(): Record<string, string>\n{\n const packageJsonPath = path.join(TEMPLATES_DIR, 'package.json');\n const packageJson = fs.readJsonSync(packageJsonPath);\n\n return packageJson.devDependencies || {};\n}\n\n/**\n * 统一依赖版本(从 templates/package.json 读取)\n */\nexport const VERSIONS = loadVersionsFromTemplate();\n\n/**\n * 获取 devDependencies 配置\n */\nexport function getDevDependencies(options: {\n includeVitest?: boolean;\n includeTypedoc?: boolean;\n includeCoverage?: boolean;\n} = {}): Record<string, string>\n{\n // 从 VERSIONS 中复制所有依赖\n const deps: Record<string, string> = { ...VERSIONS };\n\n // 根据选项移除可选依赖\n if (options.includeVitest === false)\n {\n delete deps.vitest;\n }\n\n if (options.includeTypedoc === false)\n {\n delete deps.typedoc;\n }\n\n // 可选添加覆盖率依赖(默认不包含)\n if (options.includeCoverage && !deps['@vitest/coverage-v8'])\n {\n deps['@vitest/coverage-v8'] = '^3.2.4';\n }\n\n return deps;\n}\n","/**\n * 项目模板文件内容\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\n/**\n * 模板目录路径\n */\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = path.resolve(__dirname, '../templates');\n\n/**\n * 获取 .gitignore 模板内容\n */\nexport function getGitignoreTemplate(): string\n{\n // 模板文件命名为 gitignore(不带点),避免对 templates 目录生效\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'gitignore'), 'utf-8');\n}\n\n/**\n * 获取 .cursorrules 模板内容\n */\nexport function getCursorrrulesTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.cursorrules'), 'utf-8');\n}\n\n/**\n * 获取 tsconfig.json 模板内容(对象形式)\n */\nexport function getTsconfigTemplate(): object\n{\n return fs.readJsonSync(path.join(TEMPLATES_DIR, 'tsconfig.json'));\n}\n\n/**\n * 获取 tsconfig.json 模板内容(字符串形式)\n */\nexport function getTsconfigTemplateString(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'tsconfig.json'), 'utf-8');\n}\n\n/**\n * 获取 vite.config.js 模板内容\n */\nexport function getViteConfigTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'vite.config.js'), 'utf-8');\n}\n\n/**\n * 获取 eslint.config.js 模板内容\n */\nexport function getEslintConfigTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'eslint.config.js'), 'utf-8');\n}\n\n/**\n * 获取 typedoc.json 模板内容(返回对象)\n */\nexport function getTypedocConfig(options: {\n repoName: string;\n}): object\n{\n return JSON.parse(getTypedocConfigTemplate(options));\n}\n\n/**\n * 获取 typedoc.json 模板内容(返回字符串)\n */\nexport function getTypedocConfigTemplate(options: {\n repoName: string;\n}): string\n{\n const templateContent = fs.readFileSync(path.join(TEMPLATES_DIR, 'typedoc.json'), 'utf-8');\n\n return templateContent.replace(/\\{\\{repoName\\}\\}/g, options.repoName);\n}\n\n/**\n * 获取 test/_.test.ts 模板内容(空文件占位)\n */\nexport function getTestIndexTemplate(_options: { name: string }): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'test/_.test.ts'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions publish workflow 模板内容\n */\nexport function getPublishWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/publish.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions pages workflow 模板内容\n */\nexport function getPagesWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/pages.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions pull-request workflow 模板内容\n */\nexport function getPullRequestWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/pull-request.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions upload-oss workflow 模板内容\n */\nexport function getUploadOssWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/upload-oss.yml'), 'utf-8');\n}\n\n/**\n * 获取 .husky/pre-commit 模板内容\n */\nexport function getHuskyPreCommitTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.husky/pre-commit'), 'utf-8');\n}\n\n/**\n * 获取 LICENSE 模板内容\n */\nexport function getLicenseTemplate(ctx: { year?: number } = {}): string\n{\n const year = ctx.year || new Date().getFullYear();\n const template = fs.readFileSync(path.join(TEMPLATES_DIR, 'LICENSE'), 'utf-8');\n\n return template.replace('{{year}}', String(year));\n}\n\n/**\n * 获取 .vscode/settings.json 模板内容\n */\nexport function getVscodeSettingsTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.vscode/settings.json'), 'utf-8');\n}\n\n/**\n * 获取 scripts/prepublish.js 模板内容\n */\nexport function getPrepublishScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/prepublish.js'), 'utf-8');\n}\n\n/**\n * 获取 scripts/postpublish.js 模板内容\n */\nexport function getPostpublishScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/postpublish.js'), 'utf-8');\n}\n\n/**\n * 获取 scripts/postdocs.js 模板内容\n */\nexport function getPostdocsScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/postdocs.js'), 'utf-8');\n}\n\n/**\n * 获取 src/index.ts 模板内容\n */\nexport function getSrcIndexTemplate(options: { name: string }): string\n{\n const template = fs.readFileSync(path.join(TEMPLATES_DIR, 'src/index.ts'), 'utf-8');\n\n return template.replace(/\\{\\{name\\}\\}/g, options.name);\n}\n\n","/**\n * 更新项目规范命令\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport { getDevDependencies, VERSIONS } from '../versions.js';\nimport {\n getGitignoreTemplate,\n getCursorrrulesTemplate,\n getEslintConfigTemplate,\n getPublishWorkflowTemplate,\n getPagesWorkflowTemplate,\n getPullRequestWorkflowTemplate,\n getUploadOssWorkflowTemplate,\n getTypedocConfigTemplate,\n getTestIndexTemplate,\n getHuskyPreCommitTemplate,\n getLicenseTemplate,\n getVscodeSettingsTemplate,\n getTsconfigTemplateString,\n getViteConfigTemplate,\n getPrepublishScriptTemplate,\n getPostpublishScriptTemplate,\n getPostdocsScriptTemplate,\n getSrcIndexTemplate,\n} from '../templates.js';\n\n/**\n * 模板上下文\n */\ninterface TemplateContext {\n name: string;\n repoName: string;\n}\n\n/**\n * 更新项目的规范配置\n * @param directory 项目目录路径\n */\nexport async function updateProject(directory: string = '.'): Promise<void>\n{\n const projectDir = path.resolve(directory);\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 如果 package.json 不存在,创建基础 package.json\n if (!await fs.pathExists(packageJsonPath))\n {\n await fs.ensureDir(projectDir);\n const dirName = path.basename(projectDir);\n const initialPackageJson = {\n name: `@feng3d/${dirName}`,\n version: '0.0.1',\n description: '',\n };\n\n await fs.writeJson(packageJsonPath, initialPackageJson, { spaces: 4 });\n console.log(chalk.gray(' 创建: package.json'));\n\n // 创建 src/index.ts\n const srcDir = path.join(projectDir, 'src');\n\n await fs.ensureDir(srcDir);\n await fs.writeFile(path.join(srcDir, 'index.ts'), getSrcIndexTemplate({ name: `@feng3d/${dirName}` }));\n console.log(chalk.gray(' 创建: src/index.ts'));\n }\n\n // 获取项目信息用于模板\n const packageJson = await fs.readJson(packageJsonPath);\n const name = packageJson.name || path.basename(projectDir);\n const repoName = name.replace(/^@[^/]+\\//, ''); // 移除 scope 前缀\n const templateContext: TemplateContext = { name, repoName };\n\n // feng3d-cli 项目:不更新 tsconfig.json 和 vite.config.js(有自定义配置)\n const isFeng3dCli = name === 'feng3d-cli';\n\n // 更新 .gitignore(仅在文件不存在时创建)\n const gitignorePath = path.join(projectDir, '.gitignore');\n\n if (!await fs.pathExists(gitignorePath))\n {\n await fs.writeFile(gitignorePath, getGitignoreTemplate());\n console.log(chalk.gray(' 创建: .gitignore'));\n }\n else\n {\n console.log(chalk.gray(' 跳过: .gitignore(已存在)'));\n }\n\n // 更新 .cursorrules\n await fs.writeFile(path.join(projectDir, '.cursorrules'), getCursorrrulesTemplate());\n console.log(chalk.gray(' 更新: .cursorrules'));\n\n // 更新 eslint.config.js\n await createEslintConfigFile(projectDir);\n console.log(chalk.gray(' 更新: eslint.config.js'));\n\n // 更新 .github/workflows/publish.yml\n await fs.ensureDir(path.join(projectDir, '.github/workflows'));\n await fs.writeFile(path.join(projectDir, '.github/workflows/publish.yml'), getPublishWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/publish.yml'));\n\n // 更新 .github/workflows/pages.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/pages.yml'), getPagesWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/pages.yml'));\n\n // 更新 .github/workflows/pull-request.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/pull-request.yml'), getPullRequestWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/pull-request.yml'));\n\n // 更新 .github/workflows/upload-oss.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/upload-oss.yml'), getUploadOssWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/upload-oss.yml'));\n\n // 更新 typedoc.json\n const typedocContent = getTypedocConfigTemplate({ repoName });\n\n await fs.writeFile(path.join(projectDir, 'typedoc.json'), typedocContent);\n console.log(chalk.gray(' 更新: typedoc.json'));\n\n // 更新 test/_.test.ts\n const testDir = path.join(projectDir, 'test');\n const testFilePath = path.join(testDir, '_.test.ts');\n\n // 检查测试目录是否有其他文件\n let hasOtherFiles = false;\n\n if (await fs.pathExists(testDir))\n {\n const files = await fs.readdir(testDir);\n\n hasOtherFiles = files.some(file => file !== '_.test.ts');\n }\n\n if (!hasOtherFiles)\n {\n await fs.ensureDir(testDir);\n const testContent = getTestIndexTemplate({ name });\n\n await fs.writeFile(testFilePath, testContent);\n console.log(chalk.gray(' 更新: test/_.test.ts'));\n }\n else\n {\n console.log(chalk.gray(' 跳过: test/_.test.ts(测试目录已有其他文件)'));\n }\n\n // 更新依赖版本\n await updateDependencies(projectDir);\n console.log(chalk.gray(' 更新: package.json devDependencies'));\n\n // 更新 husky pre-commit hook\n await fs.ensureDir(path.join(projectDir, '.husky'));\n await fs.writeFile(path.join(projectDir, '.husky/pre-commit'), getHuskyPreCommitTemplate());\n console.log(chalk.gray(' 更新: .husky/pre-commit'));\n await updateHuskyConfig(projectDir);\n\n // 更新 LICENSE 文件(仅在不存在时创建)\n const licensePath = path.join(projectDir, 'LICENSE');\n\n if (!await fs.pathExists(licensePath))\n {\n await fs.writeFile(licensePath, getLicenseTemplate());\n console.log(chalk.gray(' 创建: LICENSE'));\n }\n else\n {\n console.log(chalk.gray(' 跳过: LICENSE(已存在)'));\n }\n\n // 更新 .vscode/settings.json\n await fs.ensureDir(path.join(projectDir, '.vscode'));\n await fs.writeFile(path.join(projectDir, '.vscode/settings.json'), getVscodeSettingsTemplate());\n console.log(chalk.gray(' 更新: .vscode/settings.json'));\n\n // 更新 tsconfig.json(仅在不存在时创建,feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n const tsconfigPath = path.join(projectDir, 'tsconfig.json');\n\n if (!await fs.pathExists(tsconfigPath))\n {\n await fs.writeFile(tsconfigPath, getTsconfigTemplateString());\n console.log(chalk.gray(' 创建: tsconfig.json'));\n }\n else\n {\n console.log(chalk.gray(' 跳过: tsconfig.json(已存在)'));\n }\n }\n\n // 更新 vite.config.js(仅在不存在时创建,feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n const viteConfigPath = path.join(projectDir, 'vite.config.js');\n\n if (!await fs.pathExists(viteConfigPath))\n {\n await fs.writeFile(viteConfigPath, getViteConfigTemplate());\n console.log(chalk.gray(' 创建: vite.config.js'));\n }\n else\n {\n console.log(chalk.gray(' 跳过: vite.config.js(已存在)'));\n }\n }\n\n // 更新发布脚本(仅在不存在时创建)\n const scriptsDir = path.join(projectDir, 'scripts');\n const prepublishPath = path.join(scriptsDir, 'prepublish.js');\n const postpublishPath = path.join(scriptsDir, 'postpublish.js');\n\n if (!await fs.pathExists(prepublishPath))\n {\n await fs.ensureDir(scriptsDir);\n await fs.writeFile(prepublishPath, getPrepublishScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/prepublish.js'));\n }\n\n if (!await fs.pathExists(postpublishPath))\n {\n await fs.ensureDir(scriptsDir);\n await fs.writeFile(postpublishPath, getPostpublishScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/postpublish.js'));\n }\n\n // 如果存在 examples 目录,创建 postdocs.js 脚本\n const examplesDir = path.join(projectDir, 'examples');\n const postdocsPath = path.join(scriptsDir, 'postdocs.js');\n\n if (await fs.pathExists(examplesDir))\n {\n if (!await fs.pathExists(postdocsPath))\n {\n await fs.ensureDir(scriptsDir);\n await fs.writeFile(postdocsPath, getPostdocsScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/postdocs.js'));\n }\n }\n}\n\n/**\n * 创建 ESLint 配置文件\n */\nexport async function createEslintConfigFile(projectDir: string): Promise<void>\n{\n await fs.writeFile(path.join(projectDir, 'eslint.config.js'), getEslintConfigTemplate());\n}\n\n/**\n * 检测 JSON 文件的缩进风格\n */\nfunction detectIndent(content: string): string\n{\n const match = content.match(/^[ \\t]+/m);\n\n return match ? match[0] : ' ';\n}\n\n/**\n * package.json 字段的标准顺序\n */\nconst PACKAGE_JSON_FIELD_ORDER = [\n 'name',\n 'version',\n 'description',\n 'homepage',\n 'author',\n 'license',\n 'type',\n 'main',\n 'types',\n 'module',\n 'exports',\n 'bin',\n 'scripts',\n 'repository',\n 'publishConfig',\n 'files',\n 'devDependencies',\n 'dependencies',\n 'peerDependencies',\n 'lint-staged',\n];\n\n/**\n * scripts 字段的标准顺序\n */\nconst SCRIPTS_ORDER = [\n 'examples:dev',\n 'test_web',\n 'postdocs',\n 'clean',\n 'build',\n 'watch',\n 'test',\n 'lint',\n 'lintfix',\n 'docs',\n 'prepublishOnly',\n 'release',\n 'postpublish',\n 'prepare',\n];\n\n/**\n * 按标准顺序重新排列对象字段\n */\nfunction reorderObject(obj: Record<string, unknown>, order: string[]): Record<string, unknown>\n{\n const ordered: Record<string, unknown> = {};\n\n // 先按标准顺序添加已存在的字段\n for (const key of order)\n {\n if (key in obj)\n {\n ordered[key] = obj[key];\n }\n }\n\n // 再添加其他未在标准顺序中的字段\n for (const key of Object.keys(obj))\n {\n if (!(key in ordered))\n {\n ordered[key] = obj[key];\n }\n }\n\n return ordered;\n}\n\n/**\n * 按标准顺序重新排列 package.json 字段\n */\nfunction reorderPackageJson(packageJson: Record<string, unknown>): Record<string, unknown>\n{\n const ordered = reorderObject(packageJson, PACKAGE_JSON_FIELD_ORDER);\n\n // 重新排列 scripts\n if (ordered.scripts && typeof ordered.scripts === 'object')\n {\n ordered.scripts = reorderObject(ordered.scripts as Record<string, unknown>, SCRIPTS_ORDER);\n }\n\n return ordered;\n}\n\n/**\n * 更新 package.json 中的 devDependencies 版本\n */\nasync function updateDependencies(projectDir: string): Promise<void>\n{\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 读取原始内容以检测缩进风格\n const originalContent = await fs.readFile(packageJsonPath, 'utf-8');\n const indent = detectIndent(originalContent);\n const hasTrailingNewline = originalContent.endsWith('\\n');\n\n const packageJson = JSON.parse(originalContent);\n\n const standardDeps = getDevDependencies({\n includeVitest: true,\n includeTypedoc: true,\n });\n\n // 添加或更新 devDependencies\n let updated = false;\n\n if (!packageJson.devDependencies)\n {\n packageJson.devDependencies = {};\n }\n\n for (const [key, value] of Object.entries(standardDeps))\n {\n if (!(key in packageJson.devDependencies))\n {\n packageJson.devDependencies[key] = value;\n updated = true;\n console.log(chalk.gray(` 添加: devDependencies.${key} = \"${value}\"`));\n }\n else if (packageJson.devDependencies[key] !== value)\n {\n packageJson.devDependencies[key] = value;\n updated = true;\n console.log(chalk.gray(` 更新: devDependencies.${key} = \"${value}\"`));\n }\n }\n\n // 添加标准 scripts\n if (!packageJson.scripts)\n {\n packageJson.scripts = {};\n }\n\n const standardScripts: Record<string, string> = {\n clean: 'rimraf lib dist public',\n build: 'vite build && tsc',\n watch: 'concurrently \"vite build --watch\" \"tsc -w\" \"vitest\"',\n test: 'vitest run',\n lint: 'eslint . --ext .js,.ts --max-warnings 0',\n lintfix: 'npm run lint -- --fix',\n docs: 'typedoc',\n prepublishOnly: 'node scripts/prepublish.js',\n release: 'npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish',\n postpublish: 'node scripts/postpublish.js',\n };\n\n // 检查是否存在 examples 目录,添加相关脚本\n const examplesDir = path.join(projectDir, 'examples');\n\n if (await fs.pathExists(examplesDir))\n {\n standardScripts['examples:dev'] = 'cd examples && npm run dev';\n standardScripts.postdocs = 'node scripts/postdocs.js && cd examples && vite build --outDir ../public';\n }\n\n for (const [key, value] of Object.entries(standardScripts))\n {\n if (!(key in packageJson.scripts))\n {\n packageJson.scripts[key] = value;\n updated = true;\n console.log(chalk.gray(` 添加: scripts.${key}`));\n }\n }\n\n // 设置标准入口点配置(配合 prepublish/postpublish 脚本使用,仅在不存在时添加)\n if (!packageJson.type)\n {\n packageJson.type = 'module';\n updated = true;\n console.log(chalk.gray(' 添加: type = \"module\"'));\n }\n\n const entryPoints = {\n main: './src/index.ts',\n types: './src/index.ts',\n module: './src/index.ts',\n };\n\n for (const [key, value] of Object.entries(entryPoints))\n {\n if (!(key in packageJson))\n {\n packageJson[key] = value;\n updated = true;\n console.log(chalk.gray(` 添加: ${key} = \"${value}\"`));\n }\n }\n\n // 设置 exports 配置(仅在不存在时添加)\n if (!packageJson.exports)\n {\n packageJson.exports = {\n '.': {\n types: './src/index.ts',\n import: './src/index.ts',\n require: './src/index.ts',\n },\n };\n updated = true;\n console.log(chalk.gray(' 添加: exports'));\n }\n\n // 只有在有更新时才写入文件\n if (updated)\n {\n const orderedPackageJson = reorderPackageJson(packageJson);\n let newContent = JSON.stringify(orderedPackageJson, null, indent);\n\n if (hasTrailingNewline)\n {\n newContent += '\\n';\n }\n await fs.writeFile(packageJsonPath, newContent);\n }\n}\n\n/**\n * 更新 package.json 添加 husky 配置\n */\nasync function updateHuskyConfig(projectDir: string): Promise<void>\n{\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 读取原始内容以检测缩进风格\n const originalContent = await fs.readFile(packageJsonPath, 'utf-8');\n const indent = detectIndent(originalContent);\n const hasTrailingNewline = originalContent.endsWith('\\n');\n\n const packageJson = JSON.parse(originalContent);\n let updated = false;\n\n // 添加 husky 和 lint-staged 依赖\n if (!packageJson.devDependencies)\n {\n packageJson.devDependencies = {};\n }\n if (!packageJson.devDependencies.husky)\n {\n packageJson.devDependencies.husky = VERSIONS.husky;\n updated = true;\n console.log(chalk.gray(` 添加: devDependencies.husky = \"${VERSIONS.husky}\"`));\n }\n if (!packageJson.devDependencies['lint-staged'])\n {\n packageJson.devDependencies['lint-staged'] = VERSIONS['lint-staged'];\n updated = true;\n console.log(chalk.gray(` 添加: devDependencies.lint-staged = \"${VERSIONS['lint-staged']}\"`));\n }\n\n // 添加 prepare 脚本\n if (!packageJson.scripts)\n {\n packageJson.scripts = {};\n }\n if (packageJson.scripts.prepare !== 'husky')\n {\n packageJson.scripts.prepare = 'husky';\n updated = true;\n console.log(chalk.gray(' 添加: scripts.prepare = \"husky\"'));\n }\n\n // 添加 lint-staged 配置\n if (!packageJson['lint-staged'])\n {\n packageJson['lint-staged'] = {\n '*.{js,ts}': ['eslint --fix --max-warnings 0'],\n };\n updated = true;\n console.log(chalk.gray(' 添加: lint-staged 配置'));\n }\n\n // 只有在有更新时才写入文件\n if (updated)\n {\n const orderedPackageJson = reorderPackageJson(packageJson);\n let newContent = JSON.stringify(orderedPackageJson, null, indent);\n\n if (hasTrailingNewline)\n {\n newContent += '\\n';\n }\n await fs.writeFile(packageJsonPath, newContent);\n }\n}\n","/**\n * 创建新项目命令\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport { getDevDependencies } from '../versions.js';\nimport {\n getGitignoreTemplate,\n getCursorrrulesTemplate,\n getTsconfigTemplate,\n getTypedocConfig,\n getPublishWorkflowTemplate,\n getPrepublishScriptTemplate,\n getPostpublishScriptTemplate,\n getPostdocsScriptTemplate,\n getSrcIndexTemplate,\n} from '../templates.js';\nimport { createEslintConfigFile } from './update.js';\n\nexport interface CreateOptions {\n directory: string;\n examples?: boolean;\n vitest?: boolean;\n}\n\n/**\n * 创建符合 feng3d 规范的新项目\n */\nexport async function createProject(name: string, options: CreateOptions): Promise<void>\n{\n const projectDir = path.join(options.directory, name);\n\n // 检查目录是否已存在\n if (await fs.pathExists(projectDir))\n {\n throw new Error(`目录 ${projectDir} 已存在`);\n }\n\n // 创建项目目录\n await fs.ensureDir(projectDir);\n await fs.ensureDir(path.join(projectDir, 'src'));\n\n console.log(chalk.gray(` 创建目录: ${projectDir}`));\n\n // 创建 package.json\n const packageJson = createPackageJson(name, options);\n\n await fs.writeJson(path.join(projectDir, 'package.json'), packageJson, { spaces: 4 });\n console.log(chalk.gray(' 创建: package.json'));\n\n // 创建 tsconfig.json\n await fs.writeJson(path.join(projectDir, 'tsconfig.json'), getTsconfigTemplate(), { spaces: 4 });\n console.log(chalk.gray(' 创建: tsconfig.json'));\n\n // 创建 .gitignore\n await fs.writeFile(path.join(projectDir, '.gitignore'), getGitignoreTemplate());\n console.log(chalk.gray(' 创建: .gitignore'));\n\n // 创建 .cursorrules\n await fs.writeFile(path.join(projectDir, '.cursorrules'), getCursorrrulesTemplate());\n console.log(chalk.gray(' 创建: .cursorrules'));\n\n // 创建 eslint.config.js\n await createEslintConfigFile(projectDir);\n console.log(chalk.gray(' 创建: eslint.config.js'));\n\n // 创建 typedoc.json\n const typedocConfig = getTypedocConfig({ repoName: name });\n\n await fs.writeJson(path.join(projectDir, 'typedoc.json'), typedocConfig, { spaces: 4 });\n console.log(chalk.gray(' 创建: typedoc.json'));\n\n // 创建 src/index.ts\n await fs.writeFile(path.join(projectDir, 'src/index.ts'), getSrcIndexTemplate({ name: `@feng3d/${name}` }));\n console.log(chalk.gray(' 创建: src/index.ts'));\n\n // 创建 README.md\n await fs.writeFile(path.join(projectDir, 'README.md'), `# @feng3d/${name}\\n`);\n console.log(chalk.gray(' 创建: README.md'));\n\n // 创建示例目录\n if (options.examples !== false)\n {\n await fs.ensureDir(path.join(projectDir, 'examples'));\n console.log(chalk.gray(' 创建: examples/'));\n }\n\n // 创建测试目录\n if (options.vitest !== false)\n {\n await fs.ensureDir(path.join(projectDir, 'test'));\n console.log(chalk.gray(' 创建: test/'));\n }\n\n // 创建 .github/workflows 目录和 publish.yml\n await fs.ensureDir(path.join(projectDir, '.github/workflows'));\n await fs.writeFile(path.join(projectDir, '.github/workflows/publish.yml'), getPublishWorkflowTemplate());\n console.log(chalk.gray(' 创建: .github/workflows/publish.yml'));\n\n // 创建 scripts 目录和发布脚本\n await fs.ensureDir(path.join(projectDir, 'scripts'));\n await fs.writeFile(path.join(projectDir, 'scripts/prepublish.js'), getPrepublishScriptTemplate());\n await fs.writeFile(path.join(projectDir, 'scripts/postpublish.js'), getPostpublishScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/prepublish.js'));\n console.log(chalk.gray(' 创建: scripts/postpublish.js'));\n\n // 如果创建了 examples 目录,添加 postdocs.js 脚本\n if (options.examples !== false)\n {\n await fs.writeFile(path.join(projectDir, 'scripts/postdocs.js'), getPostdocsScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/postdocs.js'));\n }\n}\n\n/**\n * 创建 package.json 内容\n */\nfunction createPackageJson(name: string, options: CreateOptions): object\n{\n const scripts: Record<string, string> = {\n clean: 'rimraf lib dist public',\n build: 'vite build && tsc',\n types: 'tsc',\n watch: 'tsc -w',\n lint: 'eslint . --ext .js,.ts --max-warnings 0',\n lintfix: 'npm run lint -- --fix',\n docs: 'typedoc',\n release: 'npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish',\n prepublishOnly: 'node scripts/prepublish.js',\n postpublish: 'node scripts/postpublish.js',\n };\n\n // 如果包含 examples 目录,添加相关脚本\n if (options.examples !== false)\n {\n scripts['examples:dev'] = 'cd examples && npm run dev';\n scripts.postdocs = 'node scripts/postdocs.js && cd examples && vite build --outDir ../public';\n }\n\n if (options.vitest !== false)\n {\n scripts.test = 'vitest run';\n scripts['test:watch'] = 'vitest';\n }\n\n return {\n name: `@feng3d/${name}`,\n version: '0.0.1',\n description: '',\n homepage: `https://feng3d.com/${name}/`,\n author: 'feng',\n type: 'module',\n main: './src/index.ts',\n types: './src/index.ts',\n module: './src/index.ts',\n exports: {\n '.': {\n types: './src/index.ts',\n import: './src/index.ts',\n require: './src/index.ts',\n },\n },\n scripts,\n repository: {\n type: 'git',\n url: `https://github.com/feng3d-labs/${name}.git`,\n },\n publishConfig: {\n access: 'public',\n },\n files: ['src', 'dist', 'lib'],\n devDependencies: getDevDependencies({\n includeVitest: options.vitest !== false,\n includeTypedoc: true,\n }),\n };\n}\n\n"],"names":["__dirname","fileURLToPath","TEMPLATES_DIR"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.cjs","sources":["../src/versions.ts","../src/templates.ts","../src/commands/update.ts","../src/commands/create.ts"],"sourcesContent":["/**\n * feng3d 项目统一依赖版本\n * 从 templates/package.json 中读取\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\n/**\n * 模板目录路径\n */\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = path.resolve(__dirname, '../templates');\n\n/**\n * 从模板 package.json 中读取 devDependencies\n */\nfunction loadVersionsFromTemplate(): Record<string, string>\n{\n const packageJsonPath = path.join(TEMPLATES_DIR, 'package.json');\n const packageJson = fs.readJsonSync(packageJsonPath);\n\n return packageJson.devDependencies || {};\n}\n\n/**\n * 统一依赖版本(从 templates/package.json 读取)\n */\nexport const VERSIONS = loadVersionsFromTemplate();\n\n/**\n * 获取 devDependencies 配置\n */\nexport function getDevDependencies(options: {\n includeVitest?: boolean;\n includeTypedoc?: boolean;\n includeCoverage?: boolean;\n} = {}): Record<string, string>\n{\n // 从 VERSIONS 中复制所有依赖\n const deps: Record<string, string> = { ...VERSIONS };\n\n // 根据选项移除可选依赖\n if (options.includeVitest === false)\n {\n delete deps.vitest;\n }\n\n if (options.includeTypedoc === false)\n {\n delete deps.typedoc;\n }\n\n // 可选添加覆盖率依赖(默认不包含)\n if (options.includeCoverage && !deps['@vitest/coverage-v8'])\n {\n deps['@vitest/coverage-v8'] = '^3.2.4';\n }\n\n return deps;\n}\n","/**\n * 项目模板文件内容\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\n/**\n * 模板目录路径\n */\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = path.resolve(__dirname, '../templates');\n\n/**\n * 获取 .gitignore 模板内容\n */\nexport function getGitignoreTemplate(): string\n{\n // 模板文件命名为 gitignore(不带点),避免对 templates 目录生效\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'gitignore'), 'utf-8');\n}\n\n/**\n * 获取 .cursorrules 模板内容\n */\nexport function getCursorrrulesTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.cursorrules'), 'utf-8');\n}\n\n/**\n * 获取 tsconfig.json 模板内容(对象形式)\n */\nexport function getTsconfigTemplate(): object\n{\n return fs.readJsonSync(path.join(TEMPLATES_DIR, 'tsconfig.json'));\n}\n\n/**\n * 获取 tsconfig.json 模板内容(字符串形式)\n */\nexport function getTsconfigTemplateString(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'tsconfig.json'), 'utf-8');\n}\n\n/**\n * 获取 vite.config.js 模板内容\n */\nexport function getViteConfigTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'vite.config.js'), 'utf-8');\n}\n\n/**\n * 获取 eslint.config.js 模板内容\n */\nexport function getEslintConfigTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'eslint.config.js'), 'utf-8');\n}\n\n/**\n * 获取 typedoc.json 模板内容(返回对象)\n */\nexport function getTypedocConfig(options: {\n repoName: string;\n}): object\n{\n return JSON.parse(getTypedocConfigTemplate(options));\n}\n\n/**\n * 获取 typedoc.json 模板内容(返回字符串)\n */\nexport function getTypedocConfigTemplate(options: {\n repoName: string;\n}): string\n{\n const templateContent = fs.readFileSync(path.join(TEMPLATES_DIR, 'typedoc.json'), 'utf-8');\n\n return templateContent.replace(/\\{\\{repoName\\}\\}/g, options.repoName);\n}\n\n/**\n * 获取 test/_.test.ts 模板内容(空文件占位)\n */\nexport function getTestIndexTemplate(_options: { name: string }): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'test/_.test.ts'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions publish workflow 模板内容\n */\nexport function getPublishWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/publish.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions pages workflow 模板内容\n */\nexport function getPagesWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/pages.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions pull-request workflow 模板内容\n */\nexport function getPullRequestWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/pull-request.yml'), 'utf-8');\n}\n\n/**\n * 获取 GitHub Actions upload-oss workflow 模板内容\n */\nexport function getUploadOssWorkflowTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.github/workflows/upload-oss.yml'), 'utf-8');\n}\n\n/**\n * 获取 .husky/pre-commit 模板内容\n */\nexport function getHuskyPreCommitTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.husky/pre-commit'), 'utf-8');\n}\n\n/**\n * 获取 LICENSE 模板内容\n */\nexport function getLicenseTemplate(ctx: { year?: number } = {}): string\n{\n const year = ctx.year || new Date().getFullYear();\n const template = fs.readFileSync(path.join(TEMPLATES_DIR, 'LICENSE'), 'utf-8');\n\n return template.replace('{{year}}', String(year));\n}\n\n/**\n * 获取 .vscode/settings.json 模板内容\n */\nexport function getVscodeSettingsTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, '.vscode/settings.json'), 'utf-8');\n}\n\n/**\n * 获取 scripts/prepublish.js 模板内容\n */\nexport function getPrepublishScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/prepublish.js'), 'utf-8');\n}\n\n/**\n * 获取 scripts/postpublish.js 模板内容\n */\nexport function getPostpublishScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/postpublish.js'), 'utf-8');\n}\n\n/**\n * 获取 scripts/postdocs.js 模板内容\n */\nexport function getPostdocsScriptTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'scripts/postdocs.js'), 'utf-8');\n}\n\n/**\n * 获取 src/index.ts 模板内容\n */\nexport function getSrcIndexTemplate(options: { name: string }): string\n{\n const template = fs.readFileSync(path.join(TEMPLATES_DIR, 'src/index.ts'), 'utf-8');\n\n return template.replace(/\\{\\{name\\}\\}/g, options.name);\n}\n\n/**\n * 获取 vitest.config.ts 模板内容\n */\nexport function getVitestConfigTemplate(): string\n{\n return fs.readFileSync(path.join(TEMPLATES_DIR, 'vitest.config.ts'), 'utf-8');\n}\n\n","/**\n * 更新项目规范命令\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport { getDevDependencies, VERSIONS } from '../versions.js';\nimport {\n getGitignoreTemplate,\n getCursorrrulesTemplate,\n getEslintConfigTemplate,\n getPublishWorkflowTemplate,\n getPagesWorkflowTemplate,\n getPullRequestWorkflowTemplate,\n getUploadOssWorkflowTemplate,\n getTypedocConfigTemplate,\n getTestIndexTemplate,\n getHuskyPreCommitTemplate,\n getLicenseTemplate,\n getVscodeSettingsTemplate,\n getTsconfigTemplateString,\n getViteConfigTemplate,\n getVitestConfigTemplate,\n getPrepublishScriptTemplate,\n getPostpublishScriptTemplate,\n getPostdocsScriptTemplate,\n getSrcIndexTemplate,\n} from '../templates.js';\n\n/**\n * 模板上下文\n */\ninterface TemplateContext {\n name: string;\n repoName: string;\n}\n\n/**\n * 更新项目的规范配置\n * @param directory 项目目录路径\n */\nexport async function updateProject(directory: string = '.'): Promise<void>\n{\n const projectDir = path.resolve(directory);\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 如果 package.json 不存在,创建基础 package.json\n if (!await fs.pathExists(packageJsonPath))\n {\n await fs.ensureDir(projectDir);\n const dirName = path.basename(projectDir);\n const initialPackageJson = {\n name: `@feng3d/${dirName}`,\n version: '0.0.1',\n description: '',\n };\n\n await fs.writeJson(packageJsonPath, initialPackageJson, { spaces: 4 });\n console.log(chalk.gray(' 创建: package.json'));\n\n // 创建 src/index.ts\n const srcDir = path.join(projectDir, 'src');\n\n await fs.ensureDir(srcDir);\n await fs.writeFile(path.join(srcDir, 'index.ts'), getSrcIndexTemplate({ name: `@feng3d/${dirName}` }));\n console.log(chalk.gray(' 创建: src/index.ts'));\n }\n\n // 获取项目信息用于模板\n const packageJson = await fs.readJson(packageJsonPath);\n const name = packageJson.name || path.basename(projectDir);\n const repoName = name.replace(/^@[^/]+\\//, ''); // 移除 scope 前缀\n const templateContext: TemplateContext = { name, repoName };\n\n // feng3d-cli 项目:不更新 tsconfig.json 和 vite.config.js(有自定义配置)\n const isFeng3dCli = name === 'feng3d-cli';\n\n // 更新 .gitignore(强制覆盖)\n await fs.writeFile(path.join(projectDir, '.gitignore'), getGitignoreTemplate());\n console.log(chalk.gray(' 更新: .gitignore'));\n\n // 更新 .cursorrules\n await fs.writeFile(path.join(projectDir, '.cursorrules'), getCursorrrulesTemplate());\n console.log(chalk.gray(' 更新: .cursorrules'));\n\n // 更新 eslint.config.js\n await createEslintConfigFile(projectDir);\n console.log(chalk.gray(' 更新: eslint.config.js'));\n\n // 更新 .github/workflows/publish.yml\n await fs.ensureDir(path.join(projectDir, '.github/workflows'));\n await fs.writeFile(path.join(projectDir, '.github/workflows/publish.yml'), getPublishWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/publish.yml'));\n\n // 更新 .github/workflows/pages.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/pages.yml'), getPagesWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/pages.yml'));\n\n // 更新 .github/workflows/pull-request.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/pull-request.yml'), getPullRequestWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/pull-request.yml'));\n\n // 更新 .github/workflows/upload-oss.yml\n await fs.writeFile(path.join(projectDir, '.github/workflows/upload-oss.yml'), getUploadOssWorkflowTemplate());\n console.log(chalk.gray(' 更新: .github/workflows/upload-oss.yml'));\n\n // 更新 typedoc.json\n const typedocContent = getTypedocConfigTemplate({ repoName });\n\n await fs.writeFile(path.join(projectDir, 'typedoc.json'), typedocContent);\n console.log(chalk.gray(' 更新: typedoc.json'));\n\n // 更新 test/_.test.ts(强制覆盖)\n const testDir = path.join(projectDir, 'test');\n\n await fs.ensureDir(testDir);\n const testContent = getTestIndexTemplate({ name });\n\n await fs.writeFile(path.join(testDir, '_.test.ts'), testContent);\n console.log(chalk.gray(' 更新: test/_.test.ts'));\n\n // 更新依赖版本\n await updateDependencies(projectDir);\n console.log(chalk.gray(' 更新: package.json devDependencies'));\n\n // 更新 husky pre-commit hook\n await fs.ensureDir(path.join(projectDir, '.husky'));\n await fs.writeFile(path.join(projectDir, '.husky/pre-commit'), getHuskyPreCommitTemplate());\n console.log(chalk.gray(' 更新: .husky/pre-commit'));\n await updateHuskyConfig(projectDir);\n\n // 更新 LICENSE 文件(强制覆盖)\n await fs.writeFile(path.join(projectDir, 'LICENSE'), getLicenseTemplate());\n console.log(chalk.gray(' 更新: LICENSE'));\n\n // 更新 .vscode/settings.json\n await fs.ensureDir(path.join(projectDir, '.vscode'));\n await fs.writeFile(path.join(projectDir, '.vscode/settings.json'), getVscodeSettingsTemplate());\n console.log(chalk.gray(' 更新: .vscode/settings.json'));\n\n // 更新 tsconfig.json(强制覆盖,feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n await fs.writeFile(path.join(projectDir, 'tsconfig.json'), getTsconfigTemplateString());\n console.log(chalk.gray(' 更新: tsconfig.json'));\n }\n\n // 更新 vite.config.js(强制覆盖,feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n await fs.writeFile(path.join(projectDir, 'vite.config.js'), getViteConfigTemplate());\n console.log(chalk.gray(' 更新: vite.config.js'));\n }\n\n // 更新 vitest.config.ts(强制覆盖,feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n await fs.writeFile(path.join(projectDir, 'vitest.config.ts'), getVitestConfigTemplate());\n console.log(chalk.gray(' 更新: vitest.config.ts'));\n }\n\n // 更新发布脚本(强制覆盖)\n const scriptsDir = path.join(projectDir, 'scripts');\n\n await fs.ensureDir(scriptsDir);\n await fs.writeFile(path.join(scriptsDir, 'prepublish.js'), getPrepublishScriptTemplate());\n console.log(chalk.gray(' 更新: scripts/prepublish.js'));\n\n await fs.writeFile(path.join(scriptsDir, 'postpublish.js'), getPostpublishScriptTemplate());\n console.log(chalk.gray(' 更新: scripts/postpublish.js'));\n\n // 如果存在 examples 目录,更新 postdocs.js 脚本(强制覆盖)\n const examplesDir = path.join(projectDir, 'examples');\n\n if (await fs.pathExists(examplesDir))\n {\n await fs.writeFile(path.join(scriptsDir, 'postdocs.js'), getPostdocsScriptTemplate());\n console.log(chalk.gray(' 更新: scripts/postdocs.js'));\n }\n}\n\n/**\n * 创建 ESLint 配置文件\n */\nexport async function createEslintConfigFile(projectDir: string): Promise<void>\n{\n await fs.writeFile(path.join(projectDir, 'eslint.config.js'), getEslintConfigTemplate());\n}\n\n/**\n * 检测 JSON 文件的缩进风格\n */\nfunction detectIndent(content: string): string\n{\n const match = content.match(/^[ \\t]+/m);\n\n return match ? match[0] : ' ';\n}\n\n/**\n * package.json 字段的标准顺序\n */\nconst PACKAGE_JSON_FIELD_ORDER = [\n 'name',\n 'version',\n 'description',\n 'homepage',\n 'author',\n 'license',\n 'type',\n 'main',\n 'types',\n 'module',\n 'exports',\n 'bin',\n 'scripts',\n 'repository',\n 'publishConfig',\n 'files',\n 'devDependencies',\n 'dependencies',\n 'peerDependencies',\n 'lint-staged',\n];\n\n/**\n * scripts 字段的标准顺序\n */\nconst SCRIPTS_ORDER = [\n 'examples:dev',\n 'test_web',\n 'postdocs',\n 'clean',\n 'build',\n 'watch',\n 'test',\n 'lint',\n 'lintfix',\n 'docs',\n 'prepublishOnly',\n 'release',\n 'postpublish',\n 'prepare',\n];\n\n/**\n * 按标准顺序重新排列对象字段\n */\nfunction reorderObject(obj: Record<string, unknown>, order: string[]): Record<string, unknown>\n{\n const ordered: Record<string, unknown> = {};\n\n // 先按标准顺序添加已存在的字段\n for (const key of order)\n {\n if (key in obj)\n {\n ordered[key] = obj[key];\n }\n }\n\n // 再添加其他未在标准顺序中的字段\n for (const key of Object.keys(obj))\n {\n if (!(key in ordered))\n {\n ordered[key] = obj[key];\n }\n }\n\n return ordered;\n}\n\n/**\n * 按标准顺序重新排列 package.json 字段\n */\nfunction reorderPackageJson(packageJson: Record<string, unknown>): Record<string, unknown>\n{\n const ordered = reorderObject(packageJson, PACKAGE_JSON_FIELD_ORDER);\n\n // 重新排列 scripts\n if (ordered.scripts && typeof ordered.scripts === 'object')\n {\n ordered.scripts = reorderObject(ordered.scripts as Record<string, unknown>, SCRIPTS_ORDER);\n }\n\n return ordered;\n}\n\n/**\n * 更新 package.json 中的 devDependencies 版本\n */\nasync function updateDependencies(projectDir: string): Promise<void>\n{\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 读取原始内容以检测缩进风格\n const originalContent = await fs.readFile(packageJsonPath, 'utf-8');\n const indent = detectIndent(originalContent);\n const hasTrailingNewline = originalContent.endsWith('\\n');\n\n const packageJson = JSON.parse(originalContent);\n\n const standardDeps = getDevDependencies({\n includeVitest: true,\n includeTypedoc: true,\n });\n\n // 添加或更新 devDependencies\n let updated = false;\n\n if (!packageJson.devDependencies)\n {\n packageJson.devDependencies = {};\n }\n\n for (const [key, value] of Object.entries(standardDeps))\n {\n if (!(key in packageJson.devDependencies))\n {\n packageJson.devDependencies[key] = value;\n updated = true;\n console.log(chalk.gray(` 添加: devDependencies.${key} = \"${value}\"`));\n }\n else if (packageJson.devDependencies[key] !== value)\n {\n packageJson.devDependencies[key] = value;\n updated = true;\n console.log(chalk.gray(` 更新: devDependencies.${key} = \"${value}\"`));\n }\n }\n\n // 添加标准 scripts\n if (!packageJson.scripts)\n {\n packageJson.scripts = {};\n }\n\n const standardScripts: Record<string, string> = {\n clean: 'rimraf lib dist public',\n build: 'vite build && tsc',\n watch: 'concurrently \"vite build --watch\" \"tsc -w\" \"vitest\"',\n test: 'vitest run',\n lint: 'eslint . --ext .js,.ts --max-warnings 0',\n lintfix: 'npm run lint -- --fix',\n docs: 'typedoc',\n prepublishOnly: 'node scripts/prepublish.js',\n release: 'npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish',\n postpublish: 'node scripts/postpublish.js',\n };\n\n // 检查是否存在 examples 目录,添加相关脚本\n const examplesDir = path.join(projectDir, 'examples');\n\n if (await fs.pathExists(examplesDir))\n {\n standardScripts['examples:dev'] = 'cd examples && npm run dev';\n standardScripts.postdocs = 'node scripts/postdocs.js && cd examples && vite build --outDir ../public';\n }\n\n // 强制覆盖标准 scripts\n for (const [key, value] of Object.entries(standardScripts))\n {\n if (packageJson.scripts[key] !== value)\n {\n packageJson.scripts[key] = value;\n updated = true;\n console.log(chalk.gray(` 更新: scripts.${key}`));\n }\n }\n\n // 设置标准入口点配置(强制覆盖)\n if (packageJson.type !== 'module')\n {\n packageJson.type = 'module';\n updated = true;\n console.log(chalk.gray(' 更新: type = \"module\"'));\n }\n\n const entryPoints = {\n main: './src/index.ts',\n types: './src/index.ts',\n module: './src/index.ts',\n };\n\n for (const [key, value] of Object.entries(entryPoints))\n {\n if (packageJson[key] !== value)\n {\n packageJson[key] = value;\n updated = true;\n console.log(chalk.gray(` 更新: ${key} = \"${value}\"`));\n }\n }\n\n // 设置 exports 配置(强制覆盖)\n const standardExports = {\n '.': {\n types: './src/index.ts',\n import: './src/index.ts',\n require: './src/index.ts',\n },\n };\n\n if (JSON.stringify(packageJson.exports) !== JSON.stringify(standardExports))\n {\n packageJson.exports = standardExports;\n updated = true;\n console.log(chalk.gray(' 更新: exports'));\n }\n\n // 只有在有更新时才写入文件\n if (updated)\n {\n const orderedPackageJson = reorderPackageJson(packageJson);\n let newContent = JSON.stringify(orderedPackageJson, null, indent);\n\n if (hasTrailingNewline)\n {\n newContent += '\\n';\n }\n await fs.writeFile(packageJsonPath, newContent);\n }\n}\n\n/**\n * 更新 package.json 添加 husky 配置\n */\nasync function updateHuskyConfig(projectDir: string): Promise<void>\n{\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 读取原始内容以检测缩进风格\n const originalContent = await fs.readFile(packageJsonPath, 'utf-8');\n const indent = detectIndent(originalContent);\n const hasTrailingNewline = originalContent.endsWith('\\n');\n\n const packageJson = JSON.parse(originalContent);\n let updated = false;\n\n // 强制覆盖 husky 和 lint-staged 依赖\n if (!packageJson.devDependencies)\n {\n packageJson.devDependencies = {};\n }\n if (packageJson.devDependencies.husky !== VERSIONS.husky)\n {\n packageJson.devDependencies.husky = VERSIONS.husky;\n updated = true;\n console.log(chalk.gray(` 更新: devDependencies.husky = \"${VERSIONS.husky}\"`));\n }\n if (packageJson.devDependencies['lint-staged'] !== VERSIONS['lint-staged'])\n {\n packageJson.devDependencies['lint-staged'] = VERSIONS['lint-staged'];\n updated = true;\n console.log(chalk.gray(` 更新: devDependencies.lint-staged = \"${VERSIONS['lint-staged']}\"`));\n }\n\n // 强制覆盖 prepare 脚本\n if (!packageJson.scripts)\n {\n packageJson.scripts = {};\n }\n if (packageJson.scripts.prepare !== 'husky')\n {\n packageJson.scripts.prepare = 'husky';\n updated = true;\n console.log(chalk.gray(' 更新: scripts.prepare = \"husky\"'));\n }\n\n // 强制覆盖 lint-staged 配置\n const standardLintStaged = {\n '*.{js,ts}': ['eslint --fix --max-warnings 0'],\n };\n\n if (JSON.stringify(packageJson['lint-staged']) !== JSON.stringify(standardLintStaged))\n {\n packageJson['lint-staged'] = standardLintStaged;\n updated = true;\n console.log(chalk.gray(' 更新: lint-staged 配置'));\n }\n\n // 只有在有更新时才写入文件\n if (updated)\n {\n const orderedPackageJson = reorderPackageJson(packageJson);\n let newContent = JSON.stringify(orderedPackageJson, null, indent);\n\n if (hasTrailingNewline)\n {\n newContent += '\\n';\n }\n await fs.writeFile(packageJsonPath, newContent);\n }\n}\n","/**\n * 创建新项目命令\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport { getDevDependencies } from '../versions.js';\nimport {\n getGitignoreTemplate,\n getCursorrrulesTemplate,\n getTsconfigTemplate,\n getTypedocConfig,\n getPublishWorkflowTemplate,\n getPrepublishScriptTemplate,\n getPostpublishScriptTemplate,\n getPostdocsScriptTemplate,\n getSrcIndexTemplate,\n} from '../templates.js';\nimport { createEslintConfigFile } from './update.js';\n\nexport interface CreateOptions {\n directory: string;\n examples?: boolean;\n vitest?: boolean;\n}\n\n/**\n * 创建符合 feng3d 规范的新项目\n */\nexport async function createProject(name: string, options: CreateOptions): Promise<void>\n{\n const projectDir = path.join(options.directory, name);\n\n // 检查目录是否已存在\n if (await fs.pathExists(projectDir))\n {\n throw new Error(`目录 ${projectDir} 已存在`);\n }\n\n // 创建项目目录\n await fs.ensureDir(projectDir);\n await fs.ensureDir(path.join(projectDir, 'src'));\n\n console.log(chalk.gray(` 创建目录: ${projectDir}`));\n\n // 创建 package.json\n const packageJson = createPackageJson(name, options);\n\n await fs.writeJson(path.join(projectDir, 'package.json'), packageJson, { spaces: 4 });\n console.log(chalk.gray(' 创建: package.json'));\n\n // 创建 tsconfig.json\n await fs.writeJson(path.join(projectDir, 'tsconfig.json'), getTsconfigTemplate(), { spaces: 4 });\n console.log(chalk.gray(' 创建: tsconfig.json'));\n\n // 创建 .gitignore\n await fs.writeFile(path.join(projectDir, '.gitignore'), getGitignoreTemplate());\n console.log(chalk.gray(' 创建: .gitignore'));\n\n // 创建 .cursorrules\n await fs.writeFile(path.join(projectDir, '.cursorrules'), getCursorrrulesTemplate());\n console.log(chalk.gray(' 创建: .cursorrules'));\n\n // 创建 eslint.config.js\n await createEslintConfigFile(projectDir);\n console.log(chalk.gray(' 创建: eslint.config.js'));\n\n // 创建 typedoc.json\n const typedocConfig = getTypedocConfig({ repoName: name });\n\n await fs.writeJson(path.join(projectDir, 'typedoc.json'), typedocConfig, { spaces: 4 });\n console.log(chalk.gray(' 创建: typedoc.json'));\n\n // 创建 src/index.ts\n await fs.writeFile(path.join(projectDir, 'src/index.ts'), getSrcIndexTemplate({ name: `@feng3d/${name}` }));\n console.log(chalk.gray(' 创建: src/index.ts'));\n\n // 创建 README.md\n await fs.writeFile(path.join(projectDir, 'README.md'), `# @feng3d/${name}\\n`);\n console.log(chalk.gray(' 创建: README.md'));\n\n // 创建示例目录\n if (options.examples !== false)\n {\n await fs.ensureDir(path.join(projectDir, 'examples'));\n console.log(chalk.gray(' 创建: examples/'));\n }\n\n // 创建测试目录\n if (options.vitest !== false)\n {\n await fs.ensureDir(path.join(projectDir, 'test'));\n console.log(chalk.gray(' 创建: test/'));\n }\n\n // 创建 .github/workflows 目录和 publish.yml\n await fs.ensureDir(path.join(projectDir, '.github/workflows'));\n await fs.writeFile(path.join(projectDir, '.github/workflows/publish.yml'), getPublishWorkflowTemplate());\n console.log(chalk.gray(' 创建: .github/workflows/publish.yml'));\n\n // 创建 scripts 目录和发布脚本\n await fs.ensureDir(path.join(projectDir, 'scripts'));\n await fs.writeFile(path.join(projectDir, 'scripts/prepublish.js'), getPrepublishScriptTemplate());\n await fs.writeFile(path.join(projectDir, 'scripts/postpublish.js'), getPostpublishScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/prepublish.js'));\n console.log(chalk.gray(' 创建: scripts/postpublish.js'));\n\n // 如果创建了 examples 目录,添加 postdocs.js 脚本\n if (options.examples !== false)\n {\n await fs.writeFile(path.join(projectDir, 'scripts/postdocs.js'), getPostdocsScriptTemplate());\n console.log(chalk.gray(' 创建: scripts/postdocs.js'));\n }\n}\n\n/**\n * 创建 package.json 内容\n */\nfunction createPackageJson(name: string, options: CreateOptions): object\n{\n const scripts: Record<string, string> = {\n clean: 'rimraf lib dist public',\n build: 'vite build && tsc',\n types: 'tsc',\n watch: 'tsc -w',\n lint: 'eslint . --ext .js,.ts --max-warnings 0',\n lintfix: 'npm run lint -- --fix',\n docs: 'typedoc',\n release: 'npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish',\n prepublishOnly: 'node scripts/prepublish.js',\n postpublish: 'node scripts/postpublish.js',\n };\n\n // 如果包含 examples 目录,添加相关脚本\n if (options.examples !== false)\n {\n scripts['examples:dev'] = 'cd examples && npm run dev';\n scripts.postdocs = 'node scripts/postdocs.js && cd examples && vite build --outDir ../public';\n }\n\n if (options.vitest !== false)\n {\n scripts.test = 'vitest run';\n scripts['test:watch'] = 'vitest';\n }\n\n return {\n name: `@feng3d/${name}`,\n version: '0.0.1',\n description: '',\n homepage: `https://feng3d.com/${name}/`,\n author: 'feng',\n type: 'module',\n main: './src/index.ts',\n types: './src/index.ts',\n module: './src/index.ts',\n exports: {\n '.': {\n types: './src/index.ts',\n import: './src/index.ts',\n require: './src/index.ts',\n },\n },\n scripts,\n repository: {\n type: 'git',\n url: `https://github.com/feng3d-labs/${name}.git`,\n },\n publishConfig: {\n access: 'public',\n },\n files: ['src', 'dist', 'lib'],\n devDependencies: getDevDependencies({\n includeVitest: options.vitest !== false,\n includeTypedoc: true,\n }),\n };\n}\n\n"],"names":["__dirname","fileURLToPath","TEMPLATES_DIR"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmCH;;;GAGG;AACH,wBAAsB,aAAa,CAAC,SAAS,GAAE,MAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAuM1E;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoCH;;;GAGG;AACH,wBAAsB,aAAa,CAAC,SAAS,GAAE,MAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA0I1E;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E"}
@@ -91,4 +91,8 @@ export declare function getPostdocsScriptTemplate(): string;
91
91
  export declare function getSrcIndexTemplate(options: {
92
92
  name: string;
93
93
  }): string;
94
+ /**
95
+ * 获取 vitest.config.ts 模板内容
96
+ */
97
+ export declare function getVitestConfigTemplate(): string;
94
98
  //# sourceMappingURL=templates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAI7C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAGhD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAG5C;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAG9C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAGhD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACtC,QAAQ,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAGT;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IAC9C,QAAQ,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAKT;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAGvE;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAGnD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAGjD;AAED;;GAEG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,CAGvD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CAMtE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,CAGpD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAKrE"}
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAI7C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAGhD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAG5C;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAG9C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAGhD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACtC,QAAQ,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAGT;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IAC9C,QAAQ,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAKT;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAGvE;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAGnD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAGjD;AAED;;GAEG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,CAGvD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CAMtE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,CAGpD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAKrE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAGhD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "feng3d-cli",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "feng3d 项目通用标准,包含代码规范、配置模板和 CLI 工具",
5
5
  "homepage": "https://feng3d.com/feng3d-cli/",
6
6
  "author": "feng",
@@ -0,0 +1,14 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ // 配置Vitest以适配项目
4
+ export default defineConfig({
5
+ define: {
6
+ __DEV__: true,
7
+ },
8
+ // 设置测试环境
9
+ test: {
10
+ globals: true,
11
+ include: ['test/**/*.spec.ts'],
12
+ },
13
+ });
14
+