feng3d-cli 0.0.4 → 0.0.6

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.
Files changed (62) hide show
  1. package/README.md +54 -65
  2. package/bin/cli.js +58 -0
  3. package/dist/index.js +535 -10
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.umd.cjs +536 -0
  6. package/dist/index.umd.cjs.map +1 -0
  7. package/{dist → lib}/commands/create.d.ts.map +1 -1
  8. package/lib/commands/update.d.ts +13 -0
  9. package/lib/commands/update.d.ts.map +1 -0
  10. package/lib/index.d.ts +9 -0
  11. package/lib/index.d.ts.map +1 -0
  12. package/{dist → lib}/templates.d.ts +19 -19
  13. package/{dist → lib}/templates.d.ts.map +1 -1
  14. package/lib/versions.d.ts +17 -0
  15. package/lib/versions.d.ts.map +1 -0
  16. package/package.json +21 -27
  17. package/templates/.github/workflows/pages.yml +11 -41
  18. package/templates/.github/workflows/publish.yml +2 -8
  19. package/templates/.github/workflows/pull-request.yml +3 -3
  20. package/templates/.github/workflows/upload-oss.yml +100 -0
  21. package/templates/.husky/pre-commit +32 -1
  22. package/templates/gitignore +0 -10
  23. package/templates/package.json +71 -0
  24. package/templates/scripts/postdocs.js +46 -0
  25. package/templates/scripts/postpublish.js +19 -0
  26. package/templates/scripts/prepublish.js +19 -0
  27. package/templates/src/index.ts +6 -0
  28. package/templates/vite.config.js +50 -0
  29. package/dist/cli.d.ts +0 -7
  30. package/dist/cli.d.ts.map +0 -1
  31. package/dist/cli.js +0 -108
  32. package/dist/cli.js.map +0 -1
  33. package/dist/commands/create.js +0 -125
  34. package/dist/commands/create.js.map +0 -1
  35. package/dist/commands/oss.d.ts +0 -11
  36. package/dist/commands/oss.d.ts.map +0 -1
  37. package/dist/commands/oss.js +0 -132
  38. package/dist/commands/oss.js.map +0 -1
  39. package/dist/commands/update.d.ts +0 -30
  40. package/dist/commands/update.d.ts.map +0 -1
  41. package/dist/commands/update.js +0 -482
  42. package/dist/commands/update.js.map +0 -1
  43. package/dist/eslint.d.ts +0 -236
  44. package/dist/eslint.d.ts.map +0 -1
  45. package/dist/eslint.js +0 -119
  46. package/dist/eslint.js.map +0 -1
  47. package/dist/index.d.ts +0 -10
  48. package/dist/index.d.ts.map +0 -1
  49. package/dist/templates.js +0 -151
  50. package/dist/templates.js.map +0 -1
  51. package/dist/types/config.d.ts +0 -111
  52. package/dist/types/config.d.ts.map +0 -1
  53. package/dist/types/config.js +0 -50
  54. package/dist/types/config.js.map +0 -1
  55. package/dist/versions.d.ts +0 -31
  56. package/dist/versions.d.ts.map +0 -1
  57. package/dist/versions.js +0 -60
  58. package/dist/versions.js.map +0 -1
  59. package/schemas/feng3d.schema.json +0 -191
  60. package/templates/feng3d.json +0 -42
  61. package/templates/vitest.config.ts +0 -8
  62. /package/{dist → lib}/commands/create.d.ts +0 -0
package/dist/index.js CHANGED
@@ -1,10 +1,535 @@
1
- /**
2
- * feng3d-cli
3
- * feng3d 命令行工具
4
- */
5
- export { eslintConfig, createEslintConfig } from './eslint.js';
6
- export { VERSIONS, getDevDependencies } from './versions.js';
7
- export * from './templates.js';
8
- export * from './types/config.js';
9
- export { ossUploadDir } from './commands/oss.js';
10
- //# sourceMappingURL=index.js.map
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+ import chalk from "chalk";
5
+ const __dirname$2 = path.dirname(fileURLToPath(import.meta.url));
6
+ const TEMPLATES_DIR$1 = path.resolve(__dirname$2, "../templates");
7
+ function loadVersionsFromTemplate() {
8
+ const packageJsonPath = path.join(TEMPLATES_DIR$1, "package.json");
9
+ const packageJson = fs.readJsonSync(packageJsonPath);
10
+ return packageJson.devDependencies || {};
11
+ }
12
+ const VERSIONS = loadVersionsFromTemplate();
13
+ function getDevDependencies(options = {}) {
14
+ const deps = { ...VERSIONS };
15
+ if (options.includeVitest === false) {
16
+ delete deps.vitest;
17
+ }
18
+ if (options.includeTypedoc === false) {
19
+ delete deps.typedoc;
20
+ }
21
+ if (options.includeCoverage && !deps["@vitest/coverage-v8"]) {
22
+ deps["@vitest/coverage-v8"] = "^3.2.4";
23
+ }
24
+ return deps;
25
+ }
26
+ const __dirname$1 = path.dirname(fileURLToPath(import.meta.url));
27
+ const TEMPLATES_DIR = path.resolve(__dirname$1, "../templates");
28
+ function getGitignoreTemplate() {
29
+ return fs.readFileSync(path.join(TEMPLATES_DIR, "gitignore"), "utf-8");
30
+ }
31
+ function getCursorrrulesTemplate() {
32
+ return fs.readFileSync(path.join(TEMPLATES_DIR, ".cursorrules"), "utf-8");
33
+ }
34
+ function getTsconfigTemplate() {
35
+ return fs.readJsonSync(path.join(TEMPLATES_DIR, "tsconfig.json"));
36
+ }
37
+ function getTsconfigTemplateString() {
38
+ return fs.readFileSync(path.join(TEMPLATES_DIR, "tsconfig.json"), "utf-8");
39
+ }
40
+ function getViteConfigTemplate() {
41
+ return fs.readFileSync(path.join(TEMPLATES_DIR, "vite.config.js"), "utf-8");
42
+ }
43
+ function getEslintConfigTemplate() {
44
+ return fs.readFileSync(path.join(TEMPLATES_DIR, "eslint.config.js"), "utf-8");
45
+ }
46
+ function getTypedocConfig(options) {
47
+ return JSON.parse(getTypedocConfigTemplate(options));
48
+ }
49
+ function getTypedocConfigTemplate(options) {
50
+ const templateContent = fs.readFileSync(path.join(TEMPLATES_DIR, "typedoc.json"), "utf-8");
51
+ return templateContent.replace(/\{\{repoName\}\}/g, options.repoName);
52
+ }
53
+ function getTestIndexTemplate(_options) {
54
+ return fs.readFileSync(path.join(TEMPLATES_DIR, "test/_.test.ts"), "utf-8");
55
+ }
56
+ function getPublishWorkflowTemplate() {
57
+ return fs.readFileSync(path.join(TEMPLATES_DIR, ".github/workflows/publish.yml"), "utf-8");
58
+ }
59
+ function getPagesWorkflowTemplate() {
60
+ return fs.readFileSync(path.join(TEMPLATES_DIR, ".github/workflows/pages.yml"), "utf-8");
61
+ }
62
+ function getPullRequestWorkflowTemplate() {
63
+ return fs.readFileSync(path.join(TEMPLATES_DIR, ".github/workflows/pull-request.yml"), "utf-8");
64
+ }
65
+ function getUploadOssWorkflowTemplate() {
66
+ return fs.readFileSync(path.join(TEMPLATES_DIR, ".github/workflows/upload-oss.yml"), "utf-8");
67
+ }
68
+ function getHuskyPreCommitTemplate() {
69
+ return fs.readFileSync(path.join(TEMPLATES_DIR, ".husky/pre-commit"), "utf-8");
70
+ }
71
+ function getLicenseTemplate(ctx = {}) {
72
+ const year = ctx.year || (/* @__PURE__ */ new Date()).getFullYear();
73
+ const template = fs.readFileSync(path.join(TEMPLATES_DIR, "LICENSE"), "utf-8");
74
+ return template.replace("{{year}}", String(year));
75
+ }
76
+ function getVscodeSettingsTemplate() {
77
+ return fs.readFileSync(path.join(TEMPLATES_DIR, ".vscode/settings.json"), "utf-8");
78
+ }
79
+ function getPrepublishScriptTemplate() {
80
+ return fs.readFileSync(path.join(TEMPLATES_DIR, "scripts/prepublish.js"), "utf-8");
81
+ }
82
+ function getPostpublishScriptTemplate() {
83
+ return fs.readFileSync(path.join(TEMPLATES_DIR, "scripts/postpublish.js"), "utf-8");
84
+ }
85
+ function getPostdocsScriptTemplate() {
86
+ return fs.readFileSync(path.join(TEMPLATES_DIR, "scripts/postdocs.js"), "utf-8");
87
+ }
88
+ function getSrcIndexTemplate(options) {
89
+ const template = fs.readFileSync(path.join(TEMPLATES_DIR, "src/index.ts"), "utf-8");
90
+ return template.replace(/\{\{name\}\}/g, options.name);
91
+ }
92
+ async function updateProject(directory = ".") {
93
+ const projectDir = path.resolve(directory);
94
+ const packageJsonPath = path.join(projectDir, "package.json");
95
+ if (!await fs.pathExists(packageJsonPath)) {
96
+ await fs.ensureDir(projectDir);
97
+ const dirName = path.basename(projectDir);
98
+ const initialPackageJson = {
99
+ name: `@feng3d/${dirName}`,
100
+ version: "0.0.1",
101
+ description: ""
102
+ };
103
+ await fs.writeJson(packageJsonPath, initialPackageJson, { spaces: 4 });
104
+ console.log(chalk.gray(" 创建: package.json"));
105
+ const srcDir = path.join(projectDir, "src");
106
+ await fs.ensureDir(srcDir);
107
+ await fs.writeFile(path.join(srcDir, "index.ts"), getSrcIndexTemplate({ name: `@feng3d/${dirName}` }));
108
+ console.log(chalk.gray(" 创建: src/index.ts"));
109
+ }
110
+ const packageJson = await fs.readJson(packageJsonPath);
111
+ const name = packageJson.name || path.basename(projectDir);
112
+ const repoName = name.replace(/^@[^/]+\//, "");
113
+ 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
+ }
121
+ await fs.writeFile(path.join(projectDir, ".cursorrules"), getCursorrrulesTemplate());
122
+ console.log(chalk.gray(" 更新: .cursorrules"));
123
+ await createEslintConfigFile(projectDir);
124
+ console.log(chalk.gray(" 更新: eslint.config.js"));
125
+ await fs.ensureDir(path.join(projectDir, ".github/workflows"));
126
+ await fs.writeFile(path.join(projectDir, ".github/workflows/publish.yml"), getPublishWorkflowTemplate());
127
+ console.log(chalk.gray(" 更新: .github/workflows/publish.yml"));
128
+ await fs.writeFile(path.join(projectDir, ".github/workflows/pages.yml"), getPagesWorkflowTemplate());
129
+ console.log(chalk.gray(" 更新: .github/workflows/pages.yml"));
130
+ await fs.writeFile(path.join(projectDir, ".github/workflows/pull-request.yml"), getPullRequestWorkflowTemplate());
131
+ console.log(chalk.gray(" 更新: .github/workflows/pull-request.yml"));
132
+ await fs.writeFile(path.join(projectDir, ".github/workflows/upload-oss.yml"), getUploadOssWorkflowTemplate());
133
+ console.log(chalk.gray(" 更新: .github/workflows/upload-oss.yml"));
134
+ const typedocContent = getTypedocConfigTemplate({ repoName });
135
+ await fs.writeFile(path.join(projectDir, "typedoc.json"), typedocContent);
136
+ console.log(chalk.gray(" 更新: typedoc.json"));
137
+ 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
+ }
152
+ await updateDependencies(projectDir);
153
+ console.log(chalk.gray(" 更新: package.json devDependencies"));
154
+ await fs.ensureDir(path.join(projectDir, ".husky"));
155
+ await fs.writeFile(path.join(projectDir, ".husky/pre-commit"), getHuskyPreCommitTemplate());
156
+ console.log(chalk.gray(" 更新: .husky/pre-commit"));
157
+ 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
+ }
165
+ await fs.ensureDir(path.join(projectDir, ".vscode"));
166
+ await fs.writeFile(path.join(projectDir, ".vscode/settings.json"), getVscodeSettingsTemplate());
167
+ console.log(chalk.gray(" 更新: .vscode/settings.json"));
168
+ 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
+ }
176
+ }
177
+ 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
+ }
185
+ }
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"));
198
+ }
199
+ const examplesDir = path.join(projectDir, "examples");
200
+ const postdocsPath = path.join(scriptsDir, "postdocs.js");
201
+ 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
+ }
207
+ }
208
+ }
209
+ async function createEslintConfigFile(projectDir) {
210
+ await fs.writeFile(path.join(projectDir, "eslint.config.js"), getEslintConfigTemplate());
211
+ }
212
+ function detectIndent(content) {
213
+ const match = content.match(/^[ \t]+/m);
214
+ return match ? match[0] : " ";
215
+ }
216
+ const PACKAGE_JSON_FIELD_ORDER = [
217
+ "name",
218
+ "version",
219
+ "description",
220
+ "homepage",
221
+ "author",
222
+ "license",
223
+ "type",
224
+ "main",
225
+ "types",
226
+ "module",
227
+ "exports",
228
+ "bin",
229
+ "scripts",
230
+ "repository",
231
+ "publishConfig",
232
+ "files",
233
+ "devDependencies",
234
+ "dependencies",
235
+ "peerDependencies",
236
+ "lint-staged"
237
+ ];
238
+ const SCRIPTS_ORDER = [
239
+ "examples:dev",
240
+ "test_web",
241
+ "postdocs",
242
+ "clean",
243
+ "build",
244
+ "watch",
245
+ "test",
246
+ "lint",
247
+ "lintfix",
248
+ "docs",
249
+ "prepublishOnly",
250
+ "release",
251
+ "postpublish",
252
+ "prepare"
253
+ ];
254
+ function reorderObject(obj, order) {
255
+ const ordered = {};
256
+ for (const key of order) {
257
+ if (key in obj) {
258
+ ordered[key] = obj[key];
259
+ }
260
+ }
261
+ for (const key of Object.keys(obj)) {
262
+ if (!(key in ordered)) {
263
+ ordered[key] = obj[key];
264
+ }
265
+ }
266
+ return ordered;
267
+ }
268
+ function reorderPackageJson(packageJson) {
269
+ const ordered = reorderObject(packageJson, PACKAGE_JSON_FIELD_ORDER);
270
+ if (ordered.scripts && typeof ordered.scripts === "object") {
271
+ ordered.scripts = reorderObject(ordered.scripts, SCRIPTS_ORDER);
272
+ }
273
+ return ordered;
274
+ }
275
+ async function updateDependencies(projectDir) {
276
+ const packageJsonPath = path.join(projectDir, "package.json");
277
+ const originalContent = await fs.readFile(packageJsonPath, "utf-8");
278
+ const indent = detectIndent(originalContent);
279
+ const hasTrailingNewline = originalContent.endsWith("\n");
280
+ const packageJson = JSON.parse(originalContent);
281
+ const standardDeps = getDevDependencies({
282
+ includeVitest: true,
283
+ includeTypedoc: true
284
+ });
285
+ let updated = false;
286
+ if (!packageJson.devDependencies) {
287
+ packageJson.devDependencies = {};
288
+ }
289
+ for (const [key, value] of Object.entries(standardDeps)) {
290
+ if (!(key in packageJson.devDependencies)) {
291
+ packageJson.devDependencies[key] = value;
292
+ updated = true;
293
+ console.log(chalk.gray(` 添加: devDependencies.${key} = "${value}"`));
294
+ } else if (packageJson.devDependencies[key] !== value) {
295
+ packageJson.devDependencies[key] = value;
296
+ updated = true;
297
+ console.log(chalk.gray(` 更新: devDependencies.${key} = "${value}"`));
298
+ }
299
+ }
300
+ if (!packageJson.scripts) {
301
+ packageJson.scripts = {};
302
+ }
303
+ const standardScripts = {
304
+ clean: "rimraf lib dist public",
305
+ build: "vite build && tsc",
306
+ watch: 'concurrently "vite build --watch" "tsc -w" "vitest"',
307
+ test: "vitest run",
308
+ lint: "eslint . --ext .js,.ts --max-warnings 0",
309
+ lintfix: "npm run lint -- --fix",
310
+ docs: "typedoc",
311
+ prepublishOnly: "node scripts/prepublish.js",
312
+ release: "npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish",
313
+ postpublish: "node scripts/postpublish.js"
314
+ };
315
+ const examplesDir = path.join(projectDir, "examples");
316
+ if (await fs.pathExists(examplesDir)) {
317
+ standardScripts["examples:dev"] = "cd examples && npm run dev";
318
+ standardScripts.postdocs = "node scripts/postdocs.js && cd examples && vite build --outDir ../public";
319
+ }
320
+ for (const [key, value] of Object.entries(standardScripts)) {
321
+ if (!(key in packageJson.scripts)) {
322
+ packageJson.scripts[key] = value;
323
+ updated = true;
324
+ console.log(chalk.gray(` 添加: scripts.${key}`));
325
+ }
326
+ }
327
+ if (!packageJson.type) {
328
+ packageJson.type = "module";
329
+ updated = true;
330
+ console.log(chalk.gray(' 添加: type = "module"'));
331
+ }
332
+ const entryPoints = {
333
+ main: "./src/index.ts",
334
+ types: "./src/index.ts",
335
+ module: "./src/index.ts"
336
+ };
337
+ for (const [key, value] of Object.entries(entryPoints)) {
338
+ if (!(key in packageJson)) {
339
+ packageJson[key] = value;
340
+ updated = true;
341
+ console.log(chalk.gray(` 添加: ${key} = "${value}"`));
342
+ }
343
+ }
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
+ };
352
+ updated = true;
353
+ console.log(chalk.gray(" 添加: exports"));
354
+ }
355
+ if (updated) {
356
+ const orderedPackageJson = reorderPackageJson(packageJson);
357
+ let newContent = JSON.stringify(orderedPackageJson, null, indent);
358
+ if (hasTrailingNewline) {
359
+ newContent += "\n";
360
+ }
361
+ await fs.writeFile(packageJsonPath, newContent);
362
+ }
363
+ }
364
+ async function updateHuskyConfig(projectDir) {
365
+ const packageJsonPath = path.join(projectDir, "package.json");
366
+ const originalContent = await fs.readFile(packageJsonPath, "utf-8");
367
+ const indent = detectIndent(originalContent);
368
+ const hasTrailingNewline = originalContent.endsWith("\n");
369
+ const packageJson = JSON.parse(originalContent);
370
+ let updated = false;
371
+ if (!packageJson.devDependencies) {
372
+ packageJson.devDependencies = {};
373
+ }
374
+ if (!packageJson.devDependencies.husky) {
375
+ packageJson.devDependencies.husky = VERSIONS.husky;
376
+ updated = true;
377
+ console.log(chalk.gray(` 添加: devDependencies.husky = "${VERSIONS.husky}"`));
378
+ }
379
+ if (!packageJson.devDependencies["lint-staged"]) {
380
+ packageJson.devDependencies["lint-staged"] = VERSIONS["lint-staged"];
381
+ updated = true;
382
+ console.log(chalk.gray(` 添加: devDependencies.lint-staged = "${VERSIONS["lint-staged"]}"`));
383
+ }
384
+ if (!packageJson.scripts) {
385
+ packageJson.scripts = {};
386
+ }
387
+ if (packageJson.scripts.prepare !== "husky") {
388
+ packageJson.scripts.prepare = "husky";
389
+ updated = true;
390
+ console.log(chalk.gray(' 添加: scripts.prepare = "husky"'));
391
+ }
392
+ if (!packageJson["lint-staged"]) {
393
+ packageJson["lint-staged"] = {
394
+ "*.{js,ts}": ["eslint --fix --max-warnings 0"]
395
+ };
396
+ updated = true;
397
+ console.log(chalk.gray(" 添加: lint-staged 配置"));
398
+ }
399
+ if (updated) {
400
+ const orderedPackageJson = reorderPackageJson(packageJson);
401
+ let newContent = JSON.stringify(orderedPackageJson, null, indent);
402
+ if (hasTrailingNewline) {
403
+ newContent += "\n";
404
+ }
405
+ await fs.writeFile(packageJsonPath, newContent);
406
+ }
407
+ }
408
+ async function createProject(name, options) {
409
+ const projectDir = path.join(options.directory, name);
410
+ if (await fs.pathExists(projectDir)) {
411
+ throw new Error(`目录 ${projectDir} 已存在`);
412
+ }
413
+ await fs.ensureDir(projectDir);
414
+ await fs.ensureDir(path.join(projectDir, "src"));
415
+ console.log(chalk.gray(` 创建目录: ${projectDir}`));
416
+ const packageJson = createPackageJson(name, options);
417
+ await fs.writeJson(path.join(projectDir, "package.json"), packageJson, { spaces: 4 });
418
+ console.log(chalk.gray(" 创建: package.json"));
419
+ await fs.writeJson(path.join(projectDir, "tsconfig.json"), getTsconfigTemplate(), { spaces: 4 });
420
+ console.log(chalk.gray(" 创建: tsconfig.json"));
421
+ await fs.writeFile(path.join(projectDir, ".gitignore"), getGitignoreTemplate());
422
+ console.log(chalk.gray(" 创建: .gitignore"));
423
+ await fs.writeFile(path.join(projectDir, ".cursorrules"), getCursorrrulesTemplate());
424
+ console.log(chalk.gray(" 创建: .cursorrules"));
425
+ await createEslintConfigFile(projectDir);
426
+ console.log(chalk.gray(" 创建: eslint.config.js"));
427
+ const typedocConfig = getTypedocConfig({ repoName: name });
428
+ await fs.writeJson(path.join(projectDir, "typedoc.json"), typedocConfig, { spaces: 4 });
429
+ console.log(chalk.gray(" 创建: typedoc.json"));
430
+ await fs.writeFile(path.join(projectDir, "src/index.ts"), getSrcIndexTemplate({ name: `@feng3d/${name}` }));
431
+ console.log(chalk.gray(" 创建: src/index.ts"));
432
+ await fs.writeFile(path.join(projectDir, "README.md"), `# @feng3d/${name}
433
+ `);
434
+ console.log(chalk.gray(" 创建: README.md"));
435
+ if (options.examples !== false) {
436
+ await fs.ensureDir(path.join(projectDir, "examples"));
437
+ console.log(chalk.gray(" 创建: examples/"));
438
+ }
439
+ if (options.vitest !== false) {
440
+ await fs.ensureDir(path.join(projectDir, "test"));
441
+ console.log(chalk.gray(" 创建: test/"));
442
+ }
443
+ await fs.ensureDir(path.join(projectDir, ".github/workflows"));
444
+ await fs.writeFile(path.join(projectDir, ".github/workflows/publish.yml"), getPublishWorkflowTemplate());
445
+ console.log(chalk.gray(" 创建: .github/workflows/publish.yml"));
446
+ await fs.ensureDir(path.join(projectDir, "scripts"));
447
+ await fs.writeFile(path.join(projectDir, "scripts/prepublish.js"), getPrepublishScriptTemplate());
448
+ await fs.writeFile(path.join(projectDir, "scripts/postpublish.js"), getPostpublishScriptTemplate());
449
+ console.log(chalk.gray(" 创建: scripts/prepublish.js"));
450
+ console.log(chalk.gray(" 创建: scripts/postpublish.js"));
451
+ if (options.examples !== false) {
452
+ await fs.writeFile(path.join(projectDir, "scripts/postdocs.js"), getPostdocsScriptTemplate());
453
+ console.log(chalk.gray(" 创建: scripts/postdocs.js"));
454
+ }
455
+ }
456
+ function createPackageJson(name, options) {
457
+ const scripts = {
458
+ clean: "rimraf lib dist public",
459
+ build: "vite build && tsc",
460
+ types: "tsc",
461
+ watch: "tsc -w",
462
+ lint: "eslint . --ext .js,.ts --max-warnings 0",
463
+ lintfix: "npm run lint -- --fix",
464
+ docs: "typedoc",
465
+ release: "npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish",
466
+ prepublishOnly: "node scripts/prepublish.js",
467
+ postpublish: "node scripts/postpublish.js"
468
+ };
469
+ if (options.examples !== false) {
470
+ scripts["examples:dev"] = "cd examples && npm run dev";
471
+ scripts.postdocs = "node scripts/postdocs.js && cd examples && vite build --outDir ../public";
472
+ }
473
+ if (options.vitest !== false) {
474
+ scripts.test = "vitest run";
475
+ scripts["test:watch"] = "vitest";
476
+ }
477
+ return {
478
+ name: `@feng3d/${name}`,
479
+ version: "0.0.1",
480
+ description: "",
481
+ homepage: `https://feng3d.com/${name}/`,
482
+ author: "feng",
483
+ type: "module",
484
+ main: "./src/index.ts",
485
+ types: "./src/index.ts",
486
+ module: "./src/index.ts",
487
+ exports: {
488
+ ".": {
489
+ types: "./src/index.ts",
490
+ import: "./src/index.ts",
491
+ require: "./src/index.ts"
492
+ }
493
+ },
494
+ scripts,
495
+ repository: {
496
+ type: "git",
497
+ url: `https://github.com/feng3d-labs/${name}.git`
498
+ },
499
+ publishConfig: {
500
+ access: "public"
501
+ },
502
+ files: ["src", "dist", "lib"],
503
+ devDependencies: getDevDependencies({
504
+ includeVitest: options.vitest !== false,
505
+ includeTypedoc: true
506
+ })
507
+ };
508
+ }
509
+ export {
510
+ VERSIONS,
511
+ createProject,
512
+ getCursorrrulesTemplate,
513
+ getDevDependencies,
514
+ getEslintConfigTemplate,
515
+ getGitignoreTemplate,
516
+ getHuskyPreCommitTemplate,
517
+ getLicenseTemplate,
518
+ getPagesWorkflowTemplate,
519
+ getPostdocsScriptTemplate,
520
+ getPostpublishScriptTemplate,
521
+ getPrepublishScriptTemplate,
522
+ getPublishWorkflowTemplate,
523
+ getPullRequestWorkflowTemplate,
524
+ getSrcIndexTemplate,
525
+ getTestIndexTemplate,
526
+ getTsconfigTemplate,
527
+ getTsconfigTemplateString,
528
+ getTypedocConfig,
529
+ getTypedocConfigTemplate,
530
+ getUploadOssWorkflowTemplate,
531
+ getViteConfigTemplate,
532
+ getVscodeSettingsTemplate,
533
+ updateProject
534
+ };
535
+ //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC7D,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
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":";;;;AAYA,MAAMA,cAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAC7D,MAAMC,kBAAgB,KAAK,QAAQD,aAAW,cAAc;AAK5D,SAAS,2BACT;AACI,QAAM,kBAAkB,KAAK,KAAKC,iBAAe,cAAc;AAC/D,QAAM,cAAc,GAAG,aAAa,eAAe;AAEnD,SAAO,YAAY,mBAAmB,CAAA;AAC1C;AAKO,MAAM,WAAW,yBAAA;AAKjB,SAAS,mBAAmB,UAI/B,IACJ;AAEI,QAAM,OAA+B,EAAE,GAAG,SAAA;AAG1C,MAAI,QAAQ,kBAAkB,OAC9B;AACI,WAAO,KAAK;AAAA,EAChB;AAEA,MAAI,QAAQ,mBAAmB,OAC/B;AACI,WAAO,KAAK;AAAA,EAChB;AAGA,MAAI,QAAQ,mBAAmB,CAAC,KAAK,qBAAqB,GAC1D;AACI,SAAK,qBAAqB,IAAI;AAAA,EAClC;AAEA,SAAO;AACX;AClDA,MAAMD,cAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAC7D,MAAM,gBAAgB,KAAK,QAAQA,aAAW,cAAc;AAKrD,SAAS,uBAChB;AAEI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,WAAW,GAAG,OAAO;AACzE;AAKO,SAAS,0BAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,cAAc,GAAG,OAAO;AAC5E;AAKO,SAAS,sBAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,eAAe,CAAC;AACpE;AAKO,SAAS,4BAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,eAAe,GAAG,OAAO;AAC7E;AAKO,SAAS,wBAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,gBAAgB,GAAG,OAAO;AAC9E;AAKO,SAAS,0BAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,kBAAkB,GAAG,OAAO;AAChF;AAKO,SAAS,iBAAiB,SAGjC;AACI,SAAO,KAAK,MAAM,yBAAyB,OAAO,CAAC;AACvD;AAKO,SAAS,yBAAyB,SAGzC;AACI,QAAM,kBAAkB,GAAG,aAAa,KAAK,KAAK,eAAe,cAAc,GAAG,OAAO;AAEzF,SAAO,gBAAgB,QAAQ,qBAAqB,QAAQ,QAAQ;AACxE;AAKO,SAAS,qBAAqB,UACrC;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,gBAAgB,GAAG,OAAO;AAC9E;AAKO,SAAS,6BAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,+BAA+B,GAAG,OAAO;AAC7F;AAKO,SAAS,2BAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,6BAA6B,GAAG,OAAO;AAC3F;AAKO,SAAS,iCAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,oCAAoC,GAAG,OAAO;AAClG;AAKO,SAAS,+BAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,kCAAkC,GAAG,OAAO;AAChG;AAKO,SAAS,4BAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,mBAAmB,GAAG,OAAO;AACjF;AAKO,SAAS,mBAAmB,MAAyB,IAC5D;AACI,QAAM,OAAO,IAAI,SAAQ,oBAAI,KAAA,GAAO,YAAA;AACpC,QAAM,WAAW,GAAG,aAAa,KAAK,KAAK,eAAe,SAAS,GAAG,OAAO;AAE7E,SAAO,SAAS,QAAQ,YAAY,OAAO,IAAI,CAAC;AACpD;AAKO,SAAS,4BAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,uBAAuB,GAAG,OAAO;AACrF;AAKO,SAAS,8BAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,uBAAuB,GAAG,OAAO;AACrF;AAKO,SAAS,+BAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,wBAAwB,GAAG,OAAO;AACtF;AAKO,SAAS,4BAChB;AACI,SAAO,GAAG,aAAa,KAAK,KAAK,eAAe,qBAAqB,GAAG,OAAO;AACnF;AAKO,SAAS,oBAAoB,SACpC;AACI,QAAM,WAAW,GAAG,aAAa,KAAK,KAAK,eAAe,cAAc,GAAG,OAAO;AAElF,SAAO,SAAS,QAAQ,iBAAiB,QAAQ,IAAI;AACzD;AC/IA,eAAsB,cAAc,YAAoB,KACxD;AACI,QAAM,aAAa,KAAK,QAAQ,SAAS;AACzC,QAAM,kBAAkB,KAAK,KAAK,YAAY,cAAc;AAG5D,MAAI,CAAC,MAAM,GAAG,WAAW,eAAe,GACxC;AACI,UAAM,GAAG,UAAU,UAAU;AAC7B,UAAM,UAAU,KAAK,SAAS,UAAU;AACxC,UAAM,qBAAqB;AAAA,MACvB,MAAM,WAAW,OAAO;AAAA,MACxB,SAAS;AAAA,MACT,aAAa;AAAA,IAAA;AAGjB,UAAM,GAAG,UAAU,iBAAiB,oBAAoB,EAAE,QAAQ,GAAG;AACrE,YAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,UAAM,SAAS,KAAK,KAAK,YAAY,KAAK;AAE1C,UAAM,GAAG,UAAU,MAAM;AACzB,UAAM,GAAG,UAAU,KAAK,KAAK,QAAQ,UAAU,GAAG,oBAAoB,EAAE,MAAM,WAAW,OAAO,GAAA,CAAI,CAAC;AACrG,YAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAAA,EAChD;AAGA,QAAM,cAAc,MAAM,GAAG,SAAS,eAAe;AACrD,QAAM,OAAO,YAAY,QAAQ,KAAK,SAAS,UAAU;AACzD,QAAM,WAAW,KAAK,QAAQ,aAAa,EAAE;AAI7C,QAAM,cAAc,SAAS;AAG7B,QAAM,gBAAgB,KAAK,KAAK,YAAY,YAAY;AAExD,MAAI,CAAC,MAAM,GAAG,WAAW,aAAa,GACtC;AACI,UAAM,GAAG,UAAU,eAAe,qBAAA,CAAsB;AACxD,YAAQ,IAAI,MAAM,KAAK,kBAAkB,CAAC;AAAA,EAC9C,OAEA;AACI,YAAQ,IAAI,MAAM,KAAK,uBAAuB,CAAC;AAAA,EACnD;AAGA,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,yBAAyB;AACnF,UAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,QAAM,uBAAuB,UAAU;AACvC,UAAQ,IAAI,MAAM,KAAK,wBAAwB,CAAC;AAGhD,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,mBAAmB,CAAC;AAC7D,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,+BAA+B,GAAG,4BAA4B;AACvG,UAAQ,IAAI,MAAM,KAAK,qCAAqC,CAAC;AAG7D,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,6BAA6B,GAAG,0BAA0B;AACnG,UAAQ,IAAI,MAAM,KAAK,mCAAmC,CAAC;AAG3D,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,oCAAoC,GAAG,gCAAgC;AAChH,UAAQ,IAAI,MAAM,KAAK,0CAA0C,CAAC;AAGlE,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,kCAAkC,GAAG,8BAA8B;AAC5G,UAAQ,IAAI,MAAM,KAAK,wCAAwC,CAAC;AAGhE,QAAM,iBAAiB,yBAAyB,EAAE,UAAU;AAE5D,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,cAAc;AACxE,UAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,QAAM,UAAU,KAAK,KAAK,YAAY,MAAM;AAC5C,QAAM,eAAe,KAAK,KAAK,SAAS,WAAW;AAGnD,MAAI,gBAAgB;AAEpB,MAAI,MAAM,GAAG,WAAW,OAAO,GAC/B;AACI,UAAM,QAAQ,MAAM,GAAG,QAAQ,OAAO;AAEtC,oBAAgB,MAAM,KAAK,CAAA,SAAQ,SAAS,WAAW;AAAA,EAC3D;AAEA,MAAI,CAAC,eACL;AACI,UAAM,GAAG,UAAU,OAAO;AAC1B,UAAM,cAAc,qBAA6B;AAEjD,UAAM,GAAG,UAAU,cAAc,WAAW;AAC5C,YAAQ,IAAI,MAAM,KAAK,sBAAsB,CAAC;AAAA,EAClD,OAEA;AACI,YAAQ,IAAI,MAAM,KAAK,kCAAkC,CAAC;AAAA,EAC9D;AAGA,QAAM,mBAAmB,UAAU;AACnC,UAAQ,IAAI,MAAM,KAAK,oCAAoC,CAAC;AAG5D,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,QAAQ,CAAC;AAClD,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,mBAAmB,GAAG,2BAA2B;AAC1F,UAAQ,IAAI,MAAM,KAAK,yBAAyB,CAAC;AACjD,QAAM,kBAAkB,UAAU;AAGlC,QAAM,cAAc,KAAK,KAAK,YAAY,SAAS;AAEnD,MAAI,CAAC,MAAM,GAAG,WAAW,WAAW,GACpC;AACI,UAAM,GAAG,UAAU,aAAa,mBAAA,CAAoB;AACpD,YAAQ,IAAI,MAAM,KAAK,eAAe,CAAC;AAAA,EAC3C,OAEA;AACI,YAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAAA,EAChD;AAGA,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,SAAS,CAAC;AACnD,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,uBAAuB,GAAG,2BAA2B;AAC9F,UAAQ,IAAI,MAAM,KAAK,6BAA6B,CAAC;AAGrD,MAAI,CAAC,aACL;AACI,UAAM,eAAe,KAAK,KAAK,YAAY,eAAe;AAE1D,QAAI,CAAC,MAAM,GAAG,WAAW,YAAY,GACrC;AACI,YAAM,GAAG,UAAU,cAAc,0BAAA,CAA2B;AAC5D,cAAQ,IAAI,MAAM,KAAK,qBAAqB,CAAC;AAAA,IACjD,OAEA;AACI,cAAQ,IAAI,MAAM,KAAK,0BAA0B,CAAC;AAAA,IACtD;AAAA,EACJ;AAGA,MAAI,CAAC,aACL;AACI,UAAM,iBAAiB,KAAK,KAAK,YAAY,gBAAgB;AAE7D,QAAI,CAAC,MAAM,GAAG,WAAW,cAAc,GACvC;AACI,YAAM,GAAG,UAAU,gBAAgB,sBAAA,CAAuB;AAC1D,cAAQ,IAAI,MAAM,KAAK,sBAAsB,CAAC;AAAA,IAClD,OAEA;AACI,cAAQ,IAAI,MAAM,KAAK,2BAA2B,CAAC;AAAA,IACvD;AAAA,EACJ;AAGA,QAAM,aAAa,KAAK,KAAK,YAAY,SAAS;AAClD,QAAM,iBAAiB,KAAK,KAAK,YAAY,eAAe;AAC5D,QAAM,kBAAkB,KAAK,KAAK,YAAY,gBAAgB;AAE9D,MAAI,CAAC,MAAM,GAAG,WAAW,cAAc,GACvC;AACI,UAAM,GAAG,UAAU,UAAU;AAC7B,UAAM,GAAG,UAAU,gBAAgB,4BAAA,CAA6B;AAChE,YAAQ,IAAI,MAAM,KAAK,6BAA6B,CAAC;AAAA,EACzD;AAEA,MAAI,CAAC,MAAM,GAAG,WAAW,eAAe,GACxC;AACI,UAAM,GAAG,UAAU,UAAU;AAC7B,UAAM,GAAG,UAAU,iBAAiB,6BAAA,CAA8B;AAClE,YAAQ,IAAI,MAAM,KAAK,8BAA8B,CAAC;AAAA,EAC1D;AAGA,QAAM,cAAc,KAAK,KAAK,YAAY,UAAU;AACpD,QAAM,eAAe,KAAK,KAAK,YAAY,aAAa;AAExD,MAAI,MAAM,GAAG,WAAW,WAAW,GACnC;AACI,QAAI,CAAC,MAAM,GAAG,WAAW,YAAY,GACrC;AACI,YAAM,GAAG,UAAU,UAAU;AAC7B,YAAM,GAAG,UAAU,cAAc,0BAAA,CAA2B;AAC5D,cAAQ,IAAI,MAAM,KAAK,2BAA2B,CAAC;AAAA,IACvD;AAAA,EACJ;AACJ;AAKA,eAAsB,uBAAuB,YAC7C;AACI,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,kBAAkB,GAAG,yBAAyB;AAC3F;AAKA,SAAS,aAAa,SACtB;AACI,QAAM,QAAQ,QAAQ,MAAM,UAAU;AAEtC,SAAO,QAAQ,MAAM,CAAC,IAAI;AAC9B;AAKA,MAAM,2BAA2B;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAKA,MAAM,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAKA,SAAS,cAAc,KAA8B,OACrD;AACI,QAAM,UAAmC,CAAA;AAGzC,aAAW,OAAO,OAClB;AACI,QAAI,OAAO,KACX;AACI,cAAQ,GAAG,IAAI,IAAI,GAAG;AAAA,IAC1B;AAAA,EACJ;AAGA,aAAW,OAAO,OAAO,KAAK,GAAG,GACjC;AACI,QAAI,EAAE,OAAO,UACb;AACI,cAAQ,GAAG,IAAI,IAAI,GAAG;AAAA,IAC1B;AAAA,EACJ;AAEA,SAAO;AACX;AAKA,SAAS,mBAAmB,aAC5B;AACI,QAAM,UAAU,cAAc,aAAa,wBAAwB;AAGnE,MAAI,QAAQ,WAAW,OAAO,QAAQ,YAAY,UAClD;AACI,YAAQ,UAAU,cAAc,QAAQ,SAAoC,aAAa;AAAA,EAC7F;AAEA,SAAO;AACX;AAKA,eAAe,mBAAmB,YAClC;AACI,QAAM,kBAAkB,KAAK,KAAK,YAAY,cAAc;AAG5D,QAAM,kBAAkB,MAAM,GAAG,SAAS,iBAAiB,OAAO;AAClE,QAAM,SAAS,aAAa,eAAe;AAC3C,QAAM,qBAAqB,gBAAgB,SAAS,IAAI;AAExD,QAAM,cAAc,KAAK,MAAM,eAAe;AAE9C,QAAM,eAAe,mBAAmB;AAAA,IACpC,eAAe;AAAA,IACf,gBAAgB;AAAA,EAAA,CACnB;AAGD,MAAI,UAAU;AAEd,MAAI,CAAC,YAAY,iBACjB;AACI,gBAAY,kBAAkB,CAAA;AAAA,EAClC;AAEA,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAY,GACtD;AACI,QAAI,EAAE,OAAO,YAAY,kBACzB;AACI,kBAAY,gBAAgB,GAAG,IAAI;AACnC,gBAAU;AACV,cAAQ,IAAI,MAAM,KAAK,yBAAyB,GAAG,OAAO,KAAK,GAAG,CAAC;AAAA,IACvE,WACS,YAAY,gBAAgB,GAAG,MAAM,OAC9C;AACI,kBAAY,gBAAgB,GAAG,IAAI;AACnC,gBAAU;AACV,cAAQ,IAAI,MAAM,KAAK,yBAAyB,GAAG,OAAO,KAAK,GAAG,CAAC;AAAA,IACvE;AAAA,EACJ;AAGA,MAAI,CAAC,YAAY,SACjB;AACI,gBAAY,UAAU,CAAA;AAAA,EAC1B;AAEA,QAAM,kBAA0C;AAAA,IAC5C,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,aAAa;AAAA,EAAA;AAIjB,QAAM,cAAc,KAAK,KAAK,YAAY,UAAU;AAEpD,MAAI,MAAM,GAAG,WAAW,WAAW,GACnC;AACI,oBAAgB,cAAc,IAAI;AAClC,oBAAgB,WAAW;AAAA,EAC/B;AAEA,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,eAAe,GACzD;AACI,QAAI,EAAE,OAAO,YAAY,UACzB;AACI,kBAAY,QAAQ,GAAG,IAAI;AAC3B,gBAAU;AACV,cAAQ,IAAI,MAAM,KAAK,iBAAiB,GAAG,EAAE,CAAC;AAAA,IAClD;AAAA,EACJ;AAGA,MAAI,CAAC,YAAY,MACjB;AACI,gBAAY,OAAO;AACnB,cAAU;AACV,YAAQ,IAAI,MAAM,KAAK,uBAAuB,CAAC;AAAA,EACnD;AAEA,QAAM,cAAc;AAAA,IAChB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,EAAA;AAGZ,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,WAAW,GACrD;AACI,QAAI,EAAE,OAAO,cACb;AACI,kBAAY,GAAG,IAAI;AACnB,gBAAU;AACV,cAAQ,IAAI,MAAM,KAAK,SAAS,GAAG,OAAO,KAAK,GAAG,CAAC;AAAA,IACvD;AAAA,EACJ;AAGA,MAAI,CAAC,YAAY,SACjB;AACI,gBAAY,UAAU;AAAA,MAClB,KAAK;AAAA,QACD,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,MAAA;AAAA,IACb;AAEJ,cAAU;AACV,YAAQ,IAAI,MAAM,KAAK,eAAe,CAAC;AAAA,EAC3C;AAGA,MAAI,SACJ;AACI,UAAM,qBAAqB,mBAAmB,WAAW;AACzD,QAAI,aAAa,KAAK,UAAU,oBAAoB,MAAM,MAAM;AAEhE,QAAI,oBACJ;AACI,oBAAc;AAAA,IAClB;AACA,UAAM,GAAG,UAAU,iBAAiB,UAAU;AAAA,EAClD;AACJ;AAKA,eAAe,kBAAkB,YACjC;AACI,QAAM,kBAAkB,KAAK,KAAK,YAAY,cAAc;AAG5D,QAAM,kBAAkB,MAAM,GAAG,SAAS,iBAAiB,OAAO;AAClE,QAAM,SAAS,aAAa,eAAe;AAC3C,QAAM,qBAAqB,gBAAgB,SAAS,IAAI;AAExD,QAAM,cAAc,KAAK,MAAM,eAAe;AAC9C,MAAI,UAAU;AAGd,MAAI,CAAC,YAAY,iBACjB;AACI,gBAAY,kBAAkB,CAAA;AAAA,EAClC;AACA,MAAI,CAAC,YAAY,gBAAgB,OACjC;AACI,gBAAY,gBAAgB,QAAQ,SAAS;AAC7C,cAAU;AACV,YAAQ,IAAI,MAAM,KAAK,kCAAkC,SAAS,KAAK,GAAG,CAAC;AAAA,EAC/E;AACA,MAAI,CAAC,YAAY,gBAAgB,aAAa,GAC9C;AACI,gBAAY,gBAAgB,aAAa,IAAI,SAAS,aAAa;AACnE,cAAU;AACV,YAAQ,IAAI,MAAM,KAAK,wCAAwC,SAAS,aAAa,CAAC,GAAG,CAAC;AAAA,EAC9F;AAGA,MAAI,CAAC,YAAY,SACjB;AACI,gBAAY,UAAU,CAAA;AAAA,EAC1B;AACA,MAAI,YAAY,QAAQ,YAAY,SACpC;AACI,gBAAY,QAAQ,UAAU;AAC9B,cAAU;AACV,YAAQ,IAAI,MAAM,KAAK,iCAAiC,CAAC;AAAA,EAC7D;AAGA,MAAI,CAAC,YAAY,aAAa,GAC9B;AACI,gBAAY,aAAa,IAAI;AAAA,MACzB,aAAa,CAAC,+BAA+B;AAAA,IAAA;AAEjD,cAAU;AACV,YAAQ,IAAI,MAAM,KAAK,sBAAsB,CAAC;AAAA,EAClD;AAGA,MAAI,SACJ;AACI,UAAM,qBAAqB,mBAAmB,WAAW;AACzD,QAAI,aAAa,KAAK,UAAU,oBAAoB,MAAM,MAAM;AAEhE,QAAI,oBACJ;AACI,oBAAc;AAAA,IAClB;AACA,UAAM,GAAG,UAAU,iBAAiB,UAAU;AAAA,EAClD;AACJ;ACxgBA,eAAsB,cAAc,MAAc,SAClD;AACI,QAAM,aAAa,KAAK,KAAK,QAAQ,WAAW,IAAI;AAGpD,MAAI,MAAM,GAAG,WAAW,UAAU,GAClC;AACI,UAAM,IAAI,MAAM,MAAM,UAAU,MAAM;AAAA,EAC1C;AAGA,QAAM,GAAG,UAAU,UAAU;AAC7B,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,KAAK,CAAC;AAE/C,UAAQ,IAAI,MAAM,KAAK,WAAW,UAAU,EAAE,CAAC;AAG/C,QAAM,cAAc,kBAAkB,MAAM,OAAO;AAEnD,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,aAAa,EAAE,QAAQ,EAAA,CAAG;AACpF,UAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,eAAe,GAAG,oBAAA,GAAuB,EAAE,QAAQ,EAAA,CAAG;AAC/F,UAAQ,IAAI,MAAM,KAAK,qBAAqB,CAAC;AAG7C,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,YAAY,GAAG,sBAAsB;AAC9E,UAAQ,IAAI,MAAM,KAAK,kBAAkB,CAAC;AAG1C,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,yBAAyB;AACnF,UAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,QAAM,uBAAuB,UAAU;AACvC,UAAQ,IAAI,MAAM,KAAK,wBAAwB,CAAC;AAGhD,QAAM,gBAAgB,iBAAiB,EAAE,UAAU,MAAM;AAEzD,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,eAAe,EAAE,QAAQ,EAAA,CAAG;AACtF,UAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,oBAAoB,EAAE,MAAM,WAAW,IAAI,GAAA,CAAI,CAAC;AAC1G,UAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,WAAW,GAAG,aAAa,IAAI;AAAA,CAAI;AAC5E,UAAQ,IAAI,MAAM,KAAK,iBAAiB,CAAC;AAGzC,MAAI,QAAQ,aAAa,OACzB;AACI,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,UAAU,CAAC;AACpD,YAAQ,IAAI,MAAM,KAAK,iBAAiB,CAAC;AAAA,EAC7C;AAGA,MAAI,QAAQ,WAAW,OACvB;AACI,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,MAAM,CAAC;AAChD,YAAQ,IAAI,MAAM,KAAK,aAAa,CAAC;AAAA,EACzC;AAGA,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,mBAAmB,CAAC;AAC7D,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,+BAA+B,GAAG,4BAA4B;AACvG,UAAQ,IAAI,MAAM,KAAK,qCAAqC,CAAC;AAG7D,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,SAAS,CAAC;AACnD,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,uBAAuB,GAAG,6BAA6B;AAChG,QAAM,GAAG,UAAU,KAAK,KAAK,YAAY,wBAAwB,GAAG,8BAA8B;AAClG,UAAQ,IAAI,MAAM,KAAK,6BAA6B,CAAC;AACrD,UAAQ,IAAI,MAAM,KAAK,8BAA8B,CAAC;AAGtD,MAAI,QAAQ,aAAa,OACzB;AACI,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,qBAAqB,GAAG,2BAA2B;AAC5F,YAAQ,IAAI,MAAM,KAAK,2BAA2B,CAAC;AAAA,EACvD;AACJ;AAKA,SAAS,kBAAkB,MAAc,SACzC;AACI,QAAM,UAAkC;AAAA,IACpC,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,aAAa;AAAA,EAAA;AAIjB,MAAI,QAAQ,aAAa,OACzB;AACI,YAAQ,cAAc,IAAI;AAC1B,YAAQ,WAAW;AAAA,EACvB;AAEA,MAAI,QAAQ,WAAW,OACvB;AACI,YAAQ,OAAO;AACf,YAAQ,YAAY,IAAI;AAAA,EAC5B;AAEA,SAAO;AAAA,IACH,MAAM,WAAW,IAAI;AAAA,IACrB,SAAS;AAAA,IACT,aAAa;AAAA,IACb,UAAU,sBAAsB,IAAI;AAAA,IACpC,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,KAAK;AAAA,QACD,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,MAAA;AAAA,IACb;AAAA,IAEJ;AAAA,IACA,YAAY;AAAA,MACR,MAAM;AAAA,MACN,KAAK,kCAAkC,IAAI;AAAA,IAAA;AAAA,IAE/C,eAAe;AAAA,MACX,QAAQ;AAAA,IAAA;AAAA,IAEZ,OAAO,CAAC,OAAO,QAAQ,KAAK;AAAA,IAC5B,iBAAiB,mBAAmB;AAAA,MAChC,eAAe,QAAQ,WAAW;AAAA,MAClC,gBAAgB;AAAA,IAAA,CACnB;AAAA,EAAA;AAET;"}