feng3d-cli 0.1.2 → 0.1.3
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/.claude-skill/skill.json +1 -1
- package/bin/cli.js +5 -1
- package/dist/__vite-browser-external-2Ng8QIWW.js +5 -0
- package/dist/__vite-browser-external-2Ng8QIWW.js.map +1 -0
- package/dist/index.js +435 -163
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +440 -163
- package/dist/index.umd.cjs.map +1 -1
- package/lib/commands/update.d.ts +3 -6
- package/lib/commands/update.d.ts.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/types.d.ts +75 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/utils/merge.d.ts +52 -0
- package/lib/utils/merge.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.umd.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.cjs","sources":["../src/versions.ts","../src/templates.ts","../src/commands/update.ts","../src/commands/create.ts","../src/commands/install-skill.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(仅当 test 目录为空时)\n const testDir = path.join(projectDir, 'test');\n\n await fs.ensureDir(testDir);\n const testFiles = await fs.readdir(testDir);\n\n if (testFiles.length === 0)\n {\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 // 更新依赖版本\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 'workspaces',\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 (!(key in packageJson.scripts))\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 // 如果 workspaces 不存在则添加\n if (!packageJson.workspaces)\n {\n packageJson.workspaces = [\n '.',\n './examples',\n './test_web',\n 'packages/*',\n 'packages/*/examples',\n ];\n updated = true;\n console.log(chalk.gray(' 添加: workspaces'));\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","import fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport os from 'os';\nimport chalk from 'chalk';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * 安装 Claude Code Skill\n */\nexport async function installSkill()\n{\n try\n {\n // 获取用户主目录\n const homeDir = os.homedir();\n const claudeSkillsDir = path.join(homeDir, '.claude', 'skills', 'feng3d');\n\n // 获取 .claude-skill 源目录\n // 尝试多个可能的路径\n const possiblePaths = [\n // 从当前文件位置向上查找(开发环境)\n path.resolve(__dirname, '../../.claude-skill'),\n path.resolve(__dirname, '../../../.claude-skill'),\n path.resolve(__dirname, '../.claude-skill'),\n // 从 package.json 所在目录查找\n path.resolve(process.cwd(), '.claude-skill'),\n // 从 node_modules 查找(全局安装)\n path.resolve(__dirname, '../../../../feng3d-cli/.claude-skill'),\n ];\n\n let sourceDir = '';\n\n for (const tryPath of possiblePaths)\n {\n if (fs.existsSync(path.join(tryPath, 'skill.json')))\n {\n sourceDir = tryPath;\n break;\n }\n }\n\n if (!sourceDir)\n {\n console.error(chalk.red('❌ 错误:找不到 .claude-skill 目录'));\n console.log(chalk.yellow('尝试的路径:'));\n possiblePaths.forEach((p) => console.log(` - ${p}`));\n console.log(chalk.yellow('\\n请确保 feng3d-cli 已正确安装'));\n process.exit(1);\n }\n\n // 检查 skill.json 是否存在\n if (!fs.existsSync(path.join(sourceDir, 'skill.json')))\n {\n console.error(chalk.red('❌ 错误:.claude-skill/skill.json 不存在'));\n process.exit(1);\n }\n\n // 创建目标目录\n console.log(chalk.blue('\\n📦 开始安装 feng3d Claude Code Skill...\\n'));\n\n // 检查是否已安装\n if (fs.existsSync(claudeSkillsDir))\n {\n console.log(chalk.yellow('⚠️ 检测到已安装的 skill,将进行覆盖更新...'));\n await fs.remove(claudeSkillsDir);\n }\n\n // 确保父目录存在\n await fs.ensureDir(path.dirname(claudeSkillsDir));\n\n // 复制 skill 文件\n console.log(chalk.blue('📂 复制 skill 文件...'));\n await fs.copy(sourceDir, claudeSkillsDir, {\n overwrite: true,\n errorOnExist: false,\n });\n\n // 验证安装\n if (fs.existsSync(path.join(claudeSkillsDir, 'skill.json')))\n {\n console.log(chalk.green('\\n✅ feng3d Skill 安装成功!\\n'));\n console.log(chalk.cyan(`安装位置: ${claudeSkillsDir}\\n`));\n console.log(chalk.yellow('使用方法:'));\n console.log(' /feng3d create my-project');\n console.log(' /feng3d update\\n');\n console.log(chalk.yellow('或直接对话: \"用 feng3d 创建一个新项目\"\\n'));\n console.log(chalk.cyan('💡 提示: 可能需要重启 Claude Code 使 skill 生效\\n'));\n }\n else\n {\n console.error(chalk.red('\\n❌ 安装失败:无法验证安装结果\\n'));\n process.exit(1);\n }\n }\n catch (error)\n {\n console.error(chalk.red(`\\n❌ 安装失败: ${error}\\n`));\n process.exit(1);\n }\n}\n"],"names":["__dirname","fileURLToPath","TEMPLATES_DIR","__filename"],"mappings":";;;;;AAYA,QAAMA,cAAY,KAAK,QAAQC,IAAAA,cAAc,OAAA,aAAA,eAAA,OAAA,aAAA,cAAA,QAAA,KAAA,EAAA,cAAA,UAAA,EAAA,OAAA,OAAA,aAAA,cAAA,SAAA,OAAA,0BAAA,uBAAA,QAAA,YAAA,MAAA,YAAA,uBAAA,OAAA,IAAA,IAAA,iBAAA,SAAA,OAAA,EAAA,IAAe,CAAC;AAC7D,QAAMC,kBAAgB,KAAK,QAAQF,aAAW,cAAc;AAK5D,WAAS,2BACT;AACI,UAAM,kBAAkB,KAAK,KAAKE,iBAAe,cAAc;AAC/D,UAAM,cAAc,GAAG,aAAa,eAAe;AAEnD,WAAO,YAAY,mBAAmB,CAAA;AAAA,EAC1C;AAKO,QAAM,WAAW,yBAAA;AAKjB,WAAS,mBAAmB,UAI/B,IACJ;AAEI,UAAM,OAA+B,EAAE,GAAG,SAAA;AAG1C,QAAI,QAAQ,kBAAkB,OAC9B;AACI,aAAO,KAAK;AAAA,IAChB;AAEA,QAAI,QAAQ,mBAAmB,OAC/B;AACI,aAAO,KAAK;AAAA,IAChB;AAGA,QAAI,QAAQ,mBAAmB,CAAC,KAAK,qBAAqB,GAC1D;AACI,WAAK,qBAAqB,IAAI;AAAA,IAClC;AAEA,WAAO;AAAA,EACX;AClDA,QAAMF,cAAY,KAAK,QAAQC,IAAAA,cAAc,OAAA,aAAA,eAAA,OAAA,aAAA,cAAA,QAAA,KAAA,EAAA,cAAA,UAAA,EAAA,OAAA,OAAA,aAAA,cAAA,SAAA,OAAA,0BAAA,uBAAA,QAAA,YAAA,MAAA,YAAA,uBAAA,OAAA,IAAA,IAAA,iBAAA,SAAA,OAAA,EAAA,IAAe,CAAC;AAC7D,QAAM,gBAAgB,KAAK,QAAQD,aAAW,cAAc;AAKrD,WAAS,uBAChB;AAEI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,WAAW,GAAG,OAAO;AAAA,EACzE;AAKO,WAAS,0BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,cAAc,GAAG,OAAO;AAAA,EAC5E;AAKO,WAAS,sBAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,eAAe,CAAC;AAAA,EACpE;AAKO,WAAS,4BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,eAAe,GAAG,OAAO;AAAA,EAC7E;AAKO,WAAS,wBAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,gBAAgB,GAAG,OAAO;AAAA,EAC9E;AAKO,WAAS,0BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,kBAAkB,GAAG,OAAO;AAAA,EAChF;AAKO,WAAS,iBAAiB,SAGjC;AACI,WAAO,KAAK,MAAM,yBAAyB,OAAO,CAAC;AAAA,EACvD;AAKO,WAAS,yBAAyB,SAGzC;AACI,UAAM,kBAAkB,GAAG,aAAa,KAAK,KAAK,eAAe,cAAc,GAAG,OAAO;AAEzF,WAAO,gBAAgB,QAAQ,qBAAqB,QAAQ,QAAQ;AAAA,EACxE;AAKO,WAAS,qBAAqB,UACrC;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,gBAAgB,GAAG,OAAO;AAAA,EAC9E;AAKO,WAAS,6BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,+BAA+B,GAAG,OAAO;AAAA,EAC7F;AAKO,WAAS,2BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,6BAA6B,GAAG,OAAO;AAAA,EAC3F;AAKO,WAAS,iCAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,oCAAoC,GAAG,OAAO;AAAA,EAClG;AAKO,WAAS,+BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,kCAAkC,GAAG,OAAO;AAAA,EAChG;AAKO,WAAS,4BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,mBAAmB,GAAG,OAAO;AAAA,EACjF;AAKO,WAAS,mBAAmB,MAAyB,IAC5D;AACI,UAAM,OAAO,IAAI,SAAQ,oBAAI,KAAA,GAAO,YAAA;AACpC,UAAM,WAAW,GAAG,aAAa,KAAK,KAAK,eAAe,SAAS,GAAG,OAAO;AAE7E,WAAO,SAAS,QAAQ,YAAY,OAAO,IAAI,CAAC;AAAA,EACpD;AAKO,WAAS,4BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,uBAAuB,GAAG,OAAO;AAAA,EACrF;AAKO,WAAS,8BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,uBAAuB,GAAG,OAAO;AAAA,EACrF;AAKO,WAAS,+BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,wBAAwB,GAAG,OAAO;AAAA,EACtF;AAKO,WAAS,4BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,qBAAqB,GAAG,OAAO;AAAA,EACnF;AAKO,WAAS,oBAAoB,SACpC;AACI,UAAM,WAAW,GAAG,aAAa,KAAK,KAAK,eAAe,cAAc,GAAG,OAAO;AAElF,WAAO,SAAS,QAAQ,iBAAiB,QAAQ,IAAI;AAAA,EACzD;AAKO,WAAS,0BAChB;AACI,WAAO,GAAG,aAAa,KAAK,KAAK,eAAe,kBAAkB,GAAG,OAAO;AAAA,EAChF;ACtJA,iBAAsB,cAAc,YAAoB,KACxD;AACI,UAAM,aAAa,KAAK,QAAQ,SAAS;AACzC,UAAM,kBAAkB,KAAK,KAAK,YAAY,cAAc;AAG5D,QAAI,CAAC,MAAM,GAAG,WAAW,eAAe,GACxC;AACI,YAAM,GAAG,UAAU,UAAU;AAC7B,YAAM,UAAU,KAAK,SAAS,UAAU;AACxC,YAAM,qBAAqB;AAAA,QACvB,MAAM,WAAW,OAAO;AAAA,QACxB,SAAS;AAAA,QACT,aAAa;AAAA,MAAA;AAGjB,YAAM,GAAG,UAAU,iBAAiB,oBAAoB,EAAE,QAAQ,GAAG;AACrE,cAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,YAAM,SAAS,KAAK,KAAK,YAAY,KAAK;AAE1C,YAAM,GAAG,UAAU,MAAM;AACzB,YAAM,GAAG,UAAU,KAAK,KAAK,QAAQ,UAAU,GAAG,oBAAoB,EAAE,MAAM,WAAW,OAAO,GAAA,CAAI,CAAC;AACrG,cAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAAA,IAChD;AAGA,UAAM,cAAc,MAAM,GAAG,SAAS,eAAe;AACrD,UAAM,OAAO,YAAY,QAAQ,KAAK,SAAS,UAAU;AACzD,UAAM,WAAW,KAAK,QAAQ,aAAa,EAAE;AAI7C,UAAM,cAAc,SAAS;AAG7B,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,YAAY,GAAG,sBAAsB;AAC9E,YAAQ,IAAI,MAAM,KAAK,kBAAkB,CAAC;AAG1C,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,yBAAyB;AACnF,YAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,UAAM,uBAAuB,UAAU;AACvC,YAAQ,IAAI,MAAM,KAAK,wBAAwB,CAAC;AAGhD,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,mBAAmB,CAAC;AAC7D,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,+BAA+B,GAAG,4BAA4B;AACvG,YAAQ,IAAI,MAAM,KAAK,qCAAqC,CAAC;AAG7D,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,6BAA6B,GAAG,0BAA0B;AACnG,YAAQ,IAAI,MAAM,KAAK,mCAAmC,CAAC;AAG3D,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,oCAAoC,GAAG,gCAAgC;AAChH,YAAQ,IAAI,MAAM,KAAK,0CAA0C,CAAC;AAGlE,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,kCAAkC,GAAG,8BAA8B;AAC5G,YAAQ,IAAI,MAAM,KAAK,wCAAwC,CAAC;AAGhE,UAAM,iBAAiB,yBAAyB,EAAE,UAAU;AAE5D,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,cAAc;AACxE,YAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,UAAM,UAAU,KAAK,KAAK,YAAY,MAAM;AAE5C,UAAM,GAAG,UAAU,OAAO;AAC1B,UAAM,YAAY,MAAM,GAAG,QAAQ,OAAO;AAE1C,QAAI,UAAU,WAAW,GACzB;AACI,YAAM,cAAc,qBAA6B;AAEjD,YAAM,GAAG,UAAU,KAAK,KAAK,SAAS,WAAW,GAAG,WAAW;AAC/D,cAAQ,IAAI,MAAM,KAAK,sBAAsB,CAAC;AAAA,IAClD;AAGA,UAAM,mBAAmB,UAAU;AACnC,YAAQ,IAAI,MAAM,KAAK,oCAAoC,CAAC;AAG5D,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,QAAQ,CAAC;AAClD,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,mBAAmB,GAAG,2BAA2B;AAC1F,YAAQ,IAAI,MAAM,KAAK,yBAAyB,CAAC;AACjD,UAAM,kBAAkB,UAAU;AAGlC,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,SAAS,GAAG,oBAAoB;AACzE,YAAQ,IAAI,MAAM,KAAK,eAAe,CAAC;AAGvC,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,SAAS,CAAC;AACnD,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,uBAAuB,GAAG,2BAA2B;AAC9F,YAAQ,IAAI,MAAM,KAAK,6BAA6B,CAAC;AAGrD,QAAI,CAAC,aACL;AACI,YAAM,GAAG,UAAU,KAAK,KAAK,YAAY,eAAe,GAAG,2BAA2B;AACtF,cAAQ,IAAI,MAAM,KAAK,qBAAqB,CAAC;AAAA,IACjD;AAGA,QAAI,CAAC,aACL;AACI,YAAM,GAAG,UAAU,KAAK,KAAK,YAAY,gBAAgB,GAAG,uBAAuB;AACnF,cAAQ,IAAI,MAAM,KAAK,sBAAsB,CAAC;AAAA,IAClD;AAGA,QAAI,CAAC,aACL;AACI,YAAM,GAAG,UAAU,KAAK,KAAK,YAAY,kBAAkB,GAAG,yBAAyB;AACvF,cAAQ,IAAI,MAAM,KAAK,wBAAwB,CAAC;AAAA,IACpD;AAGA,UAAM,aAAa,KAAK,KAAK,YAAY,SAAS;AAElD,UAAM,GAAG,UAAU,UAAU;AAC7B,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,eAAe,GAAG,6BAA6B;AACxF,YAAQ,IAAI,MAAM,KAAK,6BAA6B,CAAC;AAErD,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,gBAAgB,GAAG,8BAA8B;AAC1F,YAAQ,IAAI,MAAM,KAAK,8BAA8B,CAAC;AAGtD,UAAM,cAAc,KAAK,KAAK,YAAY,UAAU;AAEpD,QAAI,MAAM,GAAG,WAAW,WAAW,GACnC;AACI,YAAM,GAAG,UAAU,KAAK,KAAK,YAAY,aAAa,GAAG,2BAA2B;AACpF,cAAQ,IAAI,MAAM,KAAK,2BAA2B,CAAC;AAAA,IACvD;AAAA,EACJ;AAKA,iBAAsB,uBAAuB,YAC7C;AACI,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,kBAAkB,GAAG,yBAAyB;AAAA,EAC3F;AAKA,WAAS,aAAa,SACtB;AACI,UAAM,QAAQ,QAAQ,MAAM,UAAU;AAEtC,WAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,EAC9B;AAKA,QAAM,2BAA2B;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ;AAKA,QAAM,gBAAgB;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ;AAKA,WAAS,cAAc,KAA8B,OACrD;AACI,UAAM,UAAmC,CAAA;AAGzC,eAAW,OAAO,OAClB;AACI,UAAI,OAAO,KACX;AACI,gBAAQ,GAAG,IAAI,IAAI,GAAG;AAAA,MAC1B;AAAA,IACJ;AAGA,eAAW,OAAO,OAAO,KAAK,GAAG,GACjC;AACI,UAAI,EAAE,OAAO,UACb;AACI,gBAAQ,GAAG,IAAI,IAAI,GAAG;AAAA,MAC1B;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAKA,WAAS,mBAAmB,aAC5B;AACI,UAAM,UAAU,cAAc,aAAa,wBAAwB;AAGnE,QAAI,QAAQ,WAAW,OAAO,QAAQ,YAAY,UAClD;AACI,cAAQ,UAAU,cAAc,QAAQ,SAAoC,aAAa;AAAA,IAC7F;AAEA,WAAO;AAAA,EACX;AAKA,iBAAe,mBAAmB,YAClC;AACI,UAAM,kBAAkB,KAAK,KAAK,YAAY,cAAc;AAG5D,UAAM,kBAAkB,MAAM,GAAG,SAAS,iBAAiB,OAAO;AAClE,UAAM,SAAS,aAAa,eAAe;AAC3C,UAAM,qBAAqB,gBAAgB,SAAS,IAAI;AAExD,UAAM,cAAc,KAAK,MAAM,eAAe;AAE9C,UAAM,eAAe,mBAAmB;AAAA,MACpC,eAAe;AAAA,MACf,gBAAgB;AAAA,IAAA,CACnB;AAGD,QAAI,UAAU;AAEd,QAAI,CAAC,YAAY,iBACjB;AACI,kBAAY,kBAAkB,CAAA;AAAA,IAClC;AAEA,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAY,GACtD;AACI,UAAI,EAAE,OAAO,YAAY,kBACzB;AACI,oBAAY,gBAAgB,GAAG,IAAI;AACnC,kBAAU;AACV,gBAAQ,IAAI,MAAM,KAAK,yBAAyB,GAAG,OAAO,KAAK,GAAG,CAAC;AAAA,MACvE,WACS,YAAY,gBAAgB,GAAG,MAAM,OAC9C;AACI,oBAAY,gBAAgB,GAAG,IAAI;AACnC,kBAAU;AACV,gBAAQ,IAAI,MAAM,KAAK,yBAAyB,GAAG,OAAO,KAAK,GAAG,CAAC;AAAA,MACvE;AAAA,IACJ;AAGA,QAAI,CAAC,YAAY,SACjB;AACI,kBAAY,UAAU,CAAA;AAAA,IAC1B;AAEA,UAAM,kBAA0C;AAAA,MAC5C,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,IAAA;AAIjB,UAAM,cAAc,KAAK,KAAK,YAAY,UAAU;AAEpD,QAAI,MAAM,GAAG,WAAW,WAAW,GACnC;AACI,sBAAgB,cAAc,IAAI;AAClC,sBAAgB,WAAW;AAAA,IAC/B;AAGA,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,eAAe,GACzD;AACI,UAAI,EAAE,OAAO,YAAY,UACzB;AACI,oBAAY,QAAQ,GAAG,IAAI;AAC3B,kBAAU;AACV,gBAAQ,IAAI,MAAM,KAAK,iBAAiB,GAAG,EAAE,CAAC;AAAA,MAClD;AAAA,IACJ;AAGA,QAAI,YAAY,SAAS,UACzB;AACI,kBAAY,OAAO;AACnB,gBAAU;AACV,cAAQ,IAAI,MAAM,KAAK,uBAAuB,CAAC;AAAA,IACnD;AAEA,UAAM,cAAc;AAAA,MAChB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,IAAA;AAGZ,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,WAAW,GACrD;AACI,UAAI,YAAY,GAAG,MAAM,OACzB;AACI,oBAAY,GAAG,IAAI;AACnB,kBAAU;AACV,gBAAQ,IAAI,MAAM,KAAK,SAAS,GAAG,OAAO,KAAK,GAAG,CAAC;AAAA,MACvD;AAAA,IACJ;AAGA,UAAM,kBAAkB;AAAA,MACpB,KAAK;AAAA,QACD,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,MAAA;AAAA,IACb;AAGJ,QAAI,KAAK,UAAU,YAAY,OAAO,MAAM,KAAK,UAAU,eAAe,GAC1E;AACI,kBAAY,UAAU;AACtB,gBAAU;AACV,cAAQ,IAAI,MAAM,KAAK,eAAe,CAAC;AAAA,IAC3C;AAGA,QAAI,CAAC,YAAY,YACjB;AACI,kBAAY,aAAa;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAEJ,gBAAU;AACV,cAAQ,IAAI,MAAM,KAAK,kBAAkB,CAAC;AAAA,IAC9C;AAGA,QAAI,SACJ;AACI,YAAM,qBAAqB,mBAAmB,WAAW;AACzD,UAAI,aAAa,KAAK,UAAU,oBAAoB,MAAM,MAAM;AAEhE,UAAI,oBACJ;AACI,sBAAc;AAAA,MAClB;AACA,YAAM,GAAG,UAAU,iBAAiB,UAAU;AAAA,IAClD;AAAA,EACJ;AAKA,iBAAe,kBAAkB,YACjC;AACI,UAAM,kBAAkB,KAAK,KAAK,YAAY,cAAc;AAG5D,UAAM,kBAAkB,MAAM,GAAG,SAAS,iBAAiB,OAAO;AAClE,UAAM,SAAS,aAAa,eAAe;AAC3C,UAAM,qBAAqB,gBAAgB,SAAS,IAAI;AAExD,UAAM,cAAc,KAAK,MAAM,eAAe;AAC9C,QAAI,UAAU;AAGd,QAAI,CAAC,YAAY,iBACjB;AACI,kBAAY,kBAAkB,CAAA;AAAA,IAClC;AACA,QAAI,YAAY,gBAAgB,UAAU,SAAS,OACnD;AACI,kBAAY,gBAAgB,QAAQ,SAAS;AAC7C,gBAAU;AACV,cAAQ,IAAI,MAAM,KAAK,kCAAkC,SAAS,KAAK,GAAG,CAAC;AAAA,IAC/E;AACA,QAAI,YAAY,gBAAgB,aAAa,MAAM,SAAS,aAAa,GACzE;AACI,kBAAY,gBAAgB,aAAa,IAAI,SAAS,aAAa;AACnE,gBAAU;AACV,cAAQ,IAAI,MAAM,KAAK,wCAAwC,SAAS,aAAa,CAAC,GAAG,CAAC;AAAA,IAC9F;AAGA,QAAI,CAAC,YAAY,SACjB;AACI,kBAAY,UAAU,CAAA;AAAA,IAC1B;AACA,QAAI,YAAY,QAAQ,YAAY,SACpC;AACI,kBAAY,QAAQ,UAAU;AAC9B,gBAAU;AACV,cAAQ,IAAI,MAAM,KAAK,iCAAiC,CAAC;AAAA,IAC7D;AAGA,UAAM,qBAAqB;AAAA,MACvB,aAAa,CAAC,+BAA+B;AAAA,IAAA;AAGjD,QAAI,KAAK,UAAU,YAAY,aAAa,CAAC,MAAM,KAAK,UAAU,kBAAkB,GACpF;AACI,kBAAY,aAAa,IAAI;AAC7B,gBAAU;AACV,cAAQ,IAAI,MAAM,KAAK,sBAAsB,CAAC;AAAA,IAClD;AAGA,QAAI,SACJ;AACI,YAAM,qBAAqB,mBAAmB,WAAW;AACzD,UAAI,aAAa,KAAK,UAAU,oBAAoB,MAAM,MAAM;AAEhE,UAAI,oBACJ;AACI,sBAAc;AAAA,MAClB;AACA,YAAM,GAAG,UAAU,iBAAiB,UAAU;AAAA,IAClD;AAAA,EACJ;ACreA,iBAAsB,cAAc,MAAc,SAClD;AACI,UAAM,aAAa,KAAK,KAAK,QAAQ,WAAW,IAAI;AAGpD,QAAI,MAAM,GAAG,WAAW,UAAU,GAClC;AACI,YAAM,IAAI,MAAM,MAAM,UAAU,MAAM;AAAA,IAC1C;AAGA,UAAM,GAAG,UAAU,UAAU;AAC7B,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,KAAK,CAAC;AAE/C,YAAQ,IAAI,MAAM,KAAK,WAAW,UAAU,EAAE,CAAC;AAG/C,UAAM,cAAc,kBAAkB,MAAM,OAAO;AAEnD,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,aAAa,EAAE,QAAQ,EAAA,CAAG;AACpF,YAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,eAAe,GAAG,oBAAA,GAAuB,EAAE,QAAQ,EAAA,CAAG;AAC/F,YAAQ,IAAI,MAAM,KAAK,qBAAqB,CAAC;AAG7C,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,YAAY,GAAG,sBAAsB;AAC9E,YAAQ,IAAI,MAAM,KAAK,kBAAkB,CAAC;AAG1C,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,yBAAyB;AACnF,YAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,UAAM,uBAAuB,UAAU;AACvC,YAAQ,IAAI,MAAM,KAAK,wBAAwB,CAAC;AAGhD,UAAM,gBAAgB,iBAAiB,EAAE,UAAU,MAAM;AAEzD,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,eAAe,EAAE,QAAQ,EAAA,CAAG;AACtF,YAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,cAAc,GAAG,oBAAoB,EAAE,MAAM,WAAW,IAAI,GAAA,CAAI,CAAC;AAC1G,YAAQ,IAAI,MAAM,KAAK,oBAAoB,CAAC;AAG5C,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,WAAW,GAAG,aAAa,IAAI;AAAA,CAAI;AAC5E,YAAQ,IAAI,MAAM,KAAK,iBAAiB,CAAC;AAGzC,QAAI,QAAQ,aAAa,OACzB;AACI,YAAM,GAAG,UAAU,KAAK,KAAK,YAAY,UAAU,CAAC;AACpD,cAAQ,IAAI,MAAM,KAAK,iBAAiB,CAAC;AAAA,IAC7C;AAGA,QAAI,QAAQ,WAAW,OACvB;AACI,YAAM,GAAG,UAAU,KAAK,KAAK,YAAY,MAAM,CAAC;AAChD,cAAQ,IAAI,MAAM,KAAK,aAAa,CAAC;AAAA,IACzC;AAGA,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,mBAAmB,CAAC;AAC7D,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,+BAA+B,GAAG,4BAA4B;AACvG,YAAQ,IAAI,MAAM,KAAK,qCAAqC,CAAC;AAG7D,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,SAAS,CAAC;AACnD,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,uBAAuB,GAAG,6BAA6B;AAChG,UAAM,GAAG,UAAU,KAAK,KAAK,YAAY,wBAAwB,GAAG,8BAA8B;AAClG,YAAQ,IAAI,MAAM,KAAK,6BAA6B,CAAC;AACrD,YAAQ,IAAI,MAAM,KAAK,8BAA8B,CAAC;AAGtD,QAAI,QAAQ,aAAa,OACzB;AACI,YAAM,GAAG,UAAU,KAAK,KAAK,YAAY,qBAAqB,GAAG,2BAA2B;AAC5F,cAAQ,IAAI,MAAM,KAAK,2BAA2B,CAAC;AAAA,IACvD;AAAA,EACJ;AAKA,WAAS,kBAAkB,MAAc,SACzC;AACI,UAAM,UAAkC;AAAA,MACpC,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB,aAAa;AAAA,IAAA;AAIjB,QAAI,QAAQ,aAAa,OACzB;AACI,cAAQ,cAAc,IAAI;AAC1B,cAAQ,WAAW;AAAA,IACvB;AAEA,QAAI,QAAQ,WAAW,OACvB;AACI,cAAQ,OAAO;AACf,cAAQ,YAAY,IAAI;AAAA,IAC5B;AAEA,WAAO;AAAA,MACH,MAAM,WAAW,IAAI;AAAA,MACrB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,sBAAsB,IAAI;AAAA,MACpC,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,KAAK;AAAA,UACD,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,SAAS;AAAA,QAAA;AAAA,MACb;AAAA,MAEJ;AAAA,MACA,YAAY;AAAA,QACR,MAAM;AAAA,QACN,KAAK,kCAAkC,IAAI;AAAA,MAAA;AAAA,MAE/C,eAAe;AAAA,QACX,QAAQ;AAAA,MAAA;AAAA,MAEZ,OAAO,CAAC,OAAO,QAAQ,KAAK;AAAA,MAC5B,iBAAiB,mBAAmB;AAAA,QAChC,eAAe,QAAQ,WAAW;AAAA,QAClC,gBAAgB;AAAA,MAAA,CACnB;AAAA,IAAA;AAAA,EAET;AC5KA,QAAMG,eAAaF,IAAAA,yVAA6B;AAChD,QAAMD,cAAY,KAAK,QAAQG,YAAU;AAKzC,iBAAsB,eACtB;AACI,QACA;AAEI,YAAM,UAAU,GAAG,QAAA;AACnB,YAAM,kBAAkB,KAAK,KAAK,SAAS,WAAW,UAAU,QAAQ;AAIxE,YAAM,gBAAgB;AAAA;AAAA,QAElB,KAAK,QAAQH,aAAW,qBAAqB;AAAA,QAC7C,KAAK,QAAQA,aAAW,wBAAwB;AAAA,QAChD,KAAK,QAAQA,aAAW,kBAAkB;AAAA;AAAA,QAE1C,KAAK,QAAQ,QAAQ,IAAA,GAAO,eAAe;AAAA;AAAA,QAE3C,KAAK,QAAQA,aAAW,sCAAsC;AAAA,MAAA;AAGlE,UAAI,YAAY;AAEhB,iBAAW,WAAW,eACtB;AACI,YAAI,GAAG,WAAW,KAAK,KAAK,SAAS,YAAY,CAAC,GAClD;AACI,sBAAY;AACZ;AAAA,QACJ;AAAA,MACJ;AAEA,UAAI,CAAC,WACL;AACI,gBAAQ,MAAM,MAAM,IAAI,2BAA2B,CAAC;AACpD,gBAAQ,IAAI,MAAM,OAAO,QAAQ,CAAC;AAClC,sBAAc,QAAQ,CAAC,MAAM,QAAQ,IAAI,OAAO,CAAC,EAAE,CAAC;AACpD,gBAAQ,IAAI,MAAM,OAAO,wBAAwB,CAAC;AAClD,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAGA,UAAI,CAAC,GAAG,WAAW,KAAK,KAAK,WAAW,YAAY,CAAC,GACrD;AACI,gBAAQ,MAAM,MAAM,IAAI,mCAAmC,CAAC;AAC5D,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAGA,cAAQ,IAAI,MAAM,KAAK,yCAAyC,CAAC;AAGjE,UAAI,GAAG,WAAW,eAAe,GACjC;AACI,gBAAQ,IAAI,MAAM,OAAO,8BAA8B,CAAC;AACxD,cAAM,GAAG,OAAO,eAAe;AAAA,MACnC;AAGA,YAAM,GAAG,UAAU,KAAK,QAAQ,eAAe,CAAC;AAGhD,cAAQ,IAAI,MAAM,KAAK,mBAAmB,CAAC;AAC3C,YAAM,GAAG,KAAK,WAAW,iBAAiB;AAAA,QACtC,WAAW;AAAA,QACX,cAAc;AAAA,MAAA,CACjB;AAGD,UAAI,GAAG,WAAW,KAAK,KAAK,iBAAiB,YAAY,CAAC,GAC1D;AACI,gBAAQ,IAAI,MAAM,MAAM,0BAA0B,CAAC;AACnD,gBAAQ,IAAI,MAAM,KAAK,SAAS,eAAe;AAAA,CAAI,CAAC;AACpD,gBAAQ,IAAI,MAAM,OAAO,OAAO,CAAC;AACjC,gBAAQ,IAAI,6BAA6B;AACzC,gBAAQ,IAAI,oBAAoB;AAChC,gBAAQ,IAAI,MAAM,OAAO,6BAA6B,CAAC;AACvD,gBAAQ,IAAI,MAAM,KAAK,wCAAwC,CAAC;AAAA,MACpE,OAEA;AACI,gBAAQ,MAAM,MAAM,IAAI,qBAAqB,CAAC;AAC9C,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAAA,IACJ,SACO,OACP;AACI,cAAQ,MAAM,MAAM,IAAI;AAAA,UAAa,KAAK;AAAA,CAAI,CAAC;AAC/C,cAAQ,KAAK,CAAC;AAAA,IAClB;AAAA,EACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.umd.cjs","sources":["../src/versions.ts","../src/templates.ts","../src/commands/create.ts","../src/utils/merge.ts","../src/commands/update.ts","../src/commands/install-skill.ts","../__vite-browser-external"],"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 } from '../versions.js';\nimport {\n getGitignoreTemplate,\n getCursorrrulesTemplate,\n getEslintConfigTemplate,\n getTsconfigTemplate,\n getTypedocConfig,\n getPublishWorkflowTemplate,\n getPrepublishScriptTemplate,\n getPostpublishScriptTemplate,\n getPostdocsScriptTemplate,\n getSrcIndexTemplate,\n} from '../templates.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 fs.writeFile(path.join(projectDir, 'eslint.config.js'), getEslintConfigTemplate());\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","/**\n * 配置文件智能合并工具\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport type { FileAction, MergeStrategy } from '../types.js';\n\n/**\n * 深度合并两个对象\n * @param target 目标对象(用户配置)\n * @param source 源对象(标准配置)\n * @returns 合并后的对象\n */\nexport function deepMerge<T extends Record<string, any>>(target: T, source: T): T\n{\n const result = { ...target };\n\n for (const key in source)\n {\n if (Object.prototype.hasOwnProperty.call(source, key))\n {\n const sourceValue = source[key];\n const targetValue = result[key];\n\n // 如果源值是对象且目标值也是对象,递归合并\n if (\n sourceValue\n && typeof sourceValue === 'object'\n && !Array.isArray(sourceValue)\n && targetValue\n && typeof targetValue === 'object'\n && !Array.isArray(targetValue)\n )\n {\n result[key] = deepMerge(targetValue, sourceValue);\n }\n // 如果目标中不存在该键,添加源值\n else if (!(key in result))\n {\n result[key] = sourceValue;\n }\n // 否则保留目标值(用户配置优先)\n }\n }\n\n return result;\n}\n\n/**\n * 合并 JSON 配置文件\n * @param existingPath 现有文件路径\n * @param standardContent 标准配置内容(字符串)\n * @returns 合并后的内容\n */\nexport async function mergeJsonConfig(existingPath: string, standardContent: string): Promise<string>\n{\n // 读取现有文件\n const existingContent = await fs.readFile(existingPath, 'utf-8');\n const existingJson = JSON.parse(existingContent);\n const standardJson = JSON.parse(standardContent);\n\n // 检测缩进\n const indent = detectIndent(existingContent);\n const hasTrailingNewline = existingContent.endsWith('\\n');\n\n // 深度合并\n const merged = deepMerge(existingJson, standardJson);\n\n // 生成 JSON 字符串\n let result = JSON.stringify(merged, null, indent);\n\n if (hasTrailingNewline)\n {\n result += '\\n';\n }\n\n return result;\n}\n\n/**\n * 检测 JSON 文件的缩进风格\n */\nexport function detectIndent(content: string): string\n{\n const match = content.match(/^[ \\t]+/m);\n\n return match ? match[0] : ' ';\n}\n\n/**\n * 根据合并策略决定文件处理方式\n * @param filePath 文件路径\n * @param mergeStrategy 合并策略\n * @returns 文件处理方式\n */\nexport async function determineFileAction(\n filePath: string,\n mergeStrategy: MergeStrategy,\n): Promise<FileAction>\n{\n const exists = await fs.pathExists(filePath);\n\n if (!exists)\n {\n return 'overwrite'; // 文件不存在,直接创建\n }\n\n switch (mergeStrategy)\n {\n case 'overwrite':\n return 'overwrite';\n case 'skip-existing':\n return 'skip';\n case 'merge':\n default:\n {\n // 对于可合并的文件(JSON),返回 merge\n // 对于其他文件,返回 overwrite\n const ext = path.extname(filePath);\n\n if (ext === '.json')\n {\n return 'merge';\n }\n\n return 'overwrite';\n }\n }\n}\n\n/**\n * 交互式询问用户如何处理文件\n * @param filePath 文件路径(相对路径,用于显示)\n * @returns 用户选择的处理方式\n */\nexport async function askFileAction(filePath: string): Promise<FileAction>\n{\n const readline = await import('readline');\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) =>\n {\n console.log(chalk.yellow(`\\n文件已存在: ${filePath}`));\n console.log('请选择处理方式:');\n console.log(' 1. 覆盖 (overwrite) - 完全使用标准配置');\n console.log(' 2. 合并 (merge) - 保留用户配置,添加缺失项');\n console.log(' 3. 跳过 (skip) - 不修改该文件');\n\n rl.question('请输入选项 (1/2/3,默认 2): ', (answer) =>\n {\n rl.close();\n\n switch (answer.trim())\n {\n case '1':\n resolve('overwrite');\n break;\n case '3':\n resolve('skip');\n break;\n case '2':\n case '':\n default:\n resolve('merge');\n break;\n }\n });\n });\n}\n\n/**\n * 写入文件内容(支持 dry-run)\n * @param filePath 文件路径\n * @param content 内容\n * @param dryRun 是否为预览模式\n */\nexport async function writeFileContent(\n filePath: string,\n content: string,\n dryRun: boolean = false,\n): Promise<void>\n{\n if (dryRun)\n {\n console.log(chalk.gray(` [预览] 将写入: ${filePath}`));\n\n return;\n }\n\n await fs.ensureDir(path.dirname(filePath));\n await fs.writeFile(filePath, content);\n}\n\n/**\n * 处理文件更新\n * @param filePath 文件完整路径\n * @param standardContent 标准配置内容\n * @param action 处理方式\n * @param dryRun 是否为预览模式\n * @returns 是否执行了操作\n */\nexport async function handleFileUpdate(\n filePath: string,\n standardContent: string,\n action: FileAction,\n dryRun: boolean = false,\n): Promise<boolean>\n{\n const exists = await fs.pathExists(filePath);\n const relativePath = path.relative(process.cwd(), filePath);\n\n switch (action)\n {\n case 'skip':\n console.log(chalk.yellow(` 跳过: ${relativePath}`));\n\n return false;\n\n case 'merge':\n if (!exists)\n {\n // 文件不存在,直接创建\n await writeFileContent(filePath, standardContent, dryRun);\n console.log(chalk.gray(` 创建: ${relativePath}`));\n\n return true;\n }\n\n // 尝试合并(目前仅支持 JSON)\n try\n {\n const ext = path.extname(filePath);\n\n if (ext === '.json')\n {\n const merged = await mergeJsonConfig(filePath, standardContent);\n\n await writeFileContent(filePath, merged, dryRun);\n console.log(chalk.blue(` 合并: ${relativePath}`));\n\n return true;\n }\n // 非 JSON 文件,回退到覆盖\n await writeFileContent(filePath, standardContent, dryRun);\n console.log(chalk.gray(` 更新: ${relativePath}`));\n\n return true;\n }\n catch (error)\n {\n console.log(chalk.red(` 合并失败,跳过: ${relativePath}`));\n console.log(chalk.red(` 错误: ${error}`));\n\n return false;\n }\n\n case 'overwrite':\n default:\n await writeFileContent(filePath, standardContent, dryRun);\n if (exists)\n {\n console.log(chalk.gray(` 更新: ${relativePath}`));\n }\n else\n {\n console.log(chalk.gray(` 创建: ${relativePath}`));\n }\n\n return true;\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 type { UpdateOptions, MergeStrategy, FileAction } from '../types.js';\nimport {\n determineFileAction,\n askFileAction,\n handleFileUpdate,\n} from '../utils/merge.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 * @param options 更新选项\n */\nexport async function updateProject(options: UpdateOptions = {}): Promise<void>\n{\n // 解析选项\n const directory = options.directory || '.';\n const projectDir = path.resolve(directory);\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n // 确定合并策略\n let mergeStrategy: MergeStrategy = options.mergeStrategy || 'merge';\n\n if (options.force)\n {\n mergeStrategy = 'overwrite';\n }\n\n const interactive = options.interactive || false;\n const dryRun = options.dryRun || false;\n\n if (dryRun)\n {\n console.log(chalk.yellow(' [预览模式] 不会实际修改文件\\n'));\n }\n if (interactive)\n {\n console.log(chalk.cyan(' [交互模式] 将逐个询问文件处理方式\\n'));\n }\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\n // 检测是否是 monorepo 根目录\n const isMonorepoRoot = Boolean(packageJson.workspaces);\n\n // feng3d-cli 项目:不更新 tsconfig.json 和 vite.config.js(有自定义配置)\n const isFeng3dCli = name === 'feng3d-cli';\n\n // 更新 .gitignore(强制覆盖)\n await updateSingleFile(\n path.join(projectDir, '.gitignore'),\n getGitignoreTemplate(),\n 'overwrite', // .gitignore 总是覆盖\n false,\n dryRun,\n );\n\n // 更新 .cursorrules\n await updateSingleFile(\n path.join(projectDir, '.cursorrules'),\n getCursorrrulesTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n\n // 更新 eslint.config.js\n await updateSingleFile(\n path.join(projectDir, 'eslint.config.js'),\n getEslintConfigTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n\n // 确保 .github/workflows 目录存在\n if (!dryRun)\n {\n await fs.ensureDir(path.join(projectDir, '.github/workflows'));\n }\n\n // 更新 .github/workflows/publish.yml\n await updateSingleFile(\n path.join(projectDir, '.github/workflows/publish.yml'),\n getPublishWorkflowTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n\n // 更新 .github/workflows/pages.yml\n await updateSingleFile(\n path.join(projectDir, '.github/workflows/pages.yml'),\n getPagesWorkflowTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n\n // 更新 .github/workflows/pull-request.yml\n await updateSingleFile(\n path.join(projectDir, '.github/workflows/pull-request.yml'),\n getPullRequestWorkflowTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n\n // 更新 .github/workflows/upload-oss.yml\n await updateSingleFile(\n path.join(projectDir, '.github/workflows/upload-oss.yml'),\n getUploadOssWorkflowTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n\n // 更新 typedoc.json(monorepo 根目录跳过)\n if (!isMonorepoRoot)\n {\n await updateSingleFile(\n path.join(projectDir, 'typedoc.json'),\n getTypedocConfigTemplate({ repoName }),\n mergeStrategy,\n interactive,\n dryRun,\n );\n }\n\n // 创建 test/_.test.ts(monorepo 根目录跳过,仅当 test 目录为空时)\n if (!isMonorepoRoot)\n {\n const testDir = path.join(projectDir, 'test');\n\n if (!dryRun)\n {\n await fs.ensureDir(testDir);\n }\n const testFiles = dryRun ? [] : await fs.readdir(testDir);\n\n if (testFiles.length === 0)\n {\n await updateSingleFile(\n path.join(testDir, '_.test.ts'),\n getTestIndexTemplate({ name }),\n 'overwrite', // 新文件,直接创建\n false,\n dryRun,\n );\n }\n }\n\n // 更新依赖版本\n if (!dryRun)\n {\n await updateDependencies(projectDir, isMonorepoRoot);\n console.log(chalk.gray(' 更新: package.json devDependencies'));\n }\n\n // 确保 .husky 目录存在\n if (!dryRun)\n {\n await fs.ensureDir(path.join(projectDir, '.husky'));\n }\n\n // 更新 husky pre-commit hook\n await updateSingleFile(\n path.join(projectDir, '.husky/pre-commit'),\n getHuskyPreCommitTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n\n // 更新 Husky 配置(dry-run 模式跳过)\n if (!dryRun)\n {\n await updateHuskyConfig(projectDir);\n }\n\n // 更新 LICENSE 文件(强制覆盖)\n await updateSingleFile(\n path.join(projectDir, 'LICENSE'),\n getLicenseTemplate(),\n 'overwrite', // LICENSE 总是覆盖\n false,\n dryRun,\n );\n\n // 确保 .vscode 目录存在\n if (!dryRun)\n {\n await fs.ensureDir(path.join(projectDir, '.vscode'));\n }\n\n // 更新 .vscode/settings.json(强制覆盖,因为可能包含注释)\n await updateSingleFile(\n path.join(projectDir, '.vscode/settings.json'),\n getVscodeSettingsTemplate(),\n 'overwrite', // VS Code 设置文件总是覆盖\n false,\n dryRun,\n );\n\n // 更新 tsconfig.json(强制覆盖,因为可能包含注释,feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n await updateSingleFile(\n path.join(projectDir, 'tsconfig.json'),\n getTsconfigTemplateString(),\n 'overwrite', // tsconfig.json 总是覆盖\n false,\n dryRun,\n );\n }\n\n // 更新 vite.config.js(feng3d-cli 跳过)\n if (!isFeng3dCli)\n {\n await updateSingleFile(\n path.join(projectDir, 'vite.config.js'),\n getViteConfigTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n }\n\n // 更新 vitest.config.ts(monorepo 根目录和 feng3d-cli 跳过)\n if (!isFeng3dCli && !isMonorepoRoot)\n {\n await updateSingleFile(\n path.join(projectDir, 'vitest.config.ts'),\n getVitestConfigTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n }\n\n // 确保 scripts 目录存在\n const scriptsDir = path.join(projectDir, 'scripts');\n\n if (!dryRun)\n {\n await fs.ensureDir(scriptsDir);\n }\n\n // 更新发布脚本\n await updateSingleFile(\n path.join(scriptsDir, 'prepublish.js'),\n getPrepublishScriptTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n\n await updateSingleFile(\n path.join(scriptsDir, 'postpublish.js'),\n getPostpublishScriptTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n\n // 如果存在 examples 目录,更新 postdocs.js 脚本\n const examplesDir = path.join(projectDir, 'examples');\n const hasExamples = dryRun ? false : await fs.pathExists(examplesDir);\n\n if (hasExamples)\n {\n await updateSingleFile(\n path.join(scriptsDir, 'postdocs.js'),\n getPostdocsScriptTemplate(),\n mergeStrategy,\n interactive,\n dryRun,\n );\n }\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 'workspaces',\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 * @param projectDir 项目目录\n * @param isMonorepoRoot 是否是 monorepo 根目录\n */\nasync function updateDependencies(projectDir: string, isMonorepoRoot: boolean = false): 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 // monorepo 根目录不包含 vitest 和 typedoc\n const standardDeps = getDevDependencies({\n includeVitest: !isMonorepoRoot,\n includeTypedoc: !isMonorepoRoot,\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 lint: 'eslint . --ext .js,.ts --max-warnings 0',\n lintfix: 'npm run lint -- --fix',\n prepublishOnly: 'node scripts/prepublish.js',\n postpublish: 'node scripts/postpublish.js',\n };\n\n // monorepo 根目录不添加 test、docs、watch 相关脚本\n if (!isMonorepoRoot)\n {\n standardScripts.watch = 'concurrently \"vite build --watch\" \"tsc -w\" \"vitest\"';\n standardScripts.test = 'vitest run';\n standardScripts.docs = 'typedoc';\n standardScripts.release = 'npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish';\n }\n else\n {\n // monorepo 根目录的 release 脚本\n standardScripts.release = 'npm run clean && npm run lint && npm run build && npm publish';\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 (!(key in packageJson.scripts))\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 // 如果 workspaces 不存在则添加\n if (!packageJson.workspaces)\n {\n packageJson.workspaces = [\n '.',\n './examples',\n './test_web',\n 'packages/*',\n 'packages/*/examples',\n ];\n updated = true;\n console.log(chalk.gray(' 添加: workspaces'));\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['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 * @param filePath 文件路径\n * @param content 文件内容\n * @param mergeStrategy 合并策略\n * @param interactive 是否交互式\n * @param dryRun 是否预览模式\n */\nasync function updateSingleFile(\n filePath: string,\n content: string,\n mergeStrategy: MergeStrategy,\n interactive: boolean,\n dryRun: boolean,\n): Promise<void>\n{\n let action: FileAction;\n\n if (interactive)\n {\n const exists = await fs.pathExists(filePath);\n\n if (exists)\n {\n action = await askFileAction(path.relative(process.cwd(), filePath));\n }\n else\n {\n action = 'overwrite'; // 文件不存在,直接创建\n }\n }\n else\n {\n action = await determineFileAction(filePath, mergeStrategy);\n }\n\n await handleFileUpdate(filePath, content, action, dryRun);\n}\n","import fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport os from 'os';\nimport chalk from 'chalk';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * 安装 Claude Code Skill\n */\nexport async function installSkill()\n{\n try\n {\n // 获取用户主目录\n const homeDir = os.homedir();\n const claudeSkillsDir = path.join(homeDir, '.claude', 'skills', 'feng3d');\n\n // 获取 .claude-skill 源目录\n // 尝试多个可能的路径\n const possiblePaths = [\n // 从当前文件位置向上查找(开发环境)\n path.resolve(__dirname, '../../.claude-skill'),\n path.resolve(__dirname, '../../../.claude-skill'),\n path.resolve(__dirname, '../.claude-skill'),\n // 从 package.json 所在目录查找\n path.resolve(process.cwd(), '.claude-skill'),\n // 从 node_modules 查找(全局安装)\n path.resolve(__dirname, '../../../../feng3d-cli/.claude-skill'),\n ];\n\n let sourceDir = '';\n\n for (const tryPath of possiblePaths)\n {\n if (fs.existsSync(path.join(tryPath, 'skill.json')))\n {\n sourceDir = tryPath;\n break;\n }\n }\n\n if (!sourceDir)\n {\n console.error(chalk.red('❌ 错误:找不到 .claude-skill 目录'));\n console.log(chalk.yellow('尝试的路径:'));\n possiblePaths.forEach((p) => console.log(` - ${p}`));\n console.log(chalk.yellow('\\n请确保 feng3d-cli 已正确安装'));\n process.exit(1);\n }\n\n // 检查 skill.json 是否存在\n if (!fs.existsSync(path.join(sourceDir, 'skill.json')))\n {\n console.error(chalk.red('❌ 错误:.claude-skill/skill.json 不存在'));\n process.exit(1);\n }\n\n // 创建目标目录\n console.log(chalk.blue('\\n📦 开始安装 feng3d Claude Code Skill...\\n'));\n\n // 检查是否已安装\n if (fs.existsSync(claudeSkillsDir))\n {\n console.log(chalk.yellow('⚠️ 检测到已安装的 skill,将进行覆盖更新...'));\n await fs.remove(claudeSkillsDir);\n }\n\n // 确保父目录存在\n await fs.ensureDir(path.dirname(claudeSkillsDir));\n\n // 复制 skill 文件\n console.log(chalk.blue('📂 复制 skill 文件...'));\n await fs.copy(sourceDir, claudeSkillsDir, {\n overwrite: true,\n errorOnExist: false,\n });\n\n // 验证安装\n if (fs.existsSync(path.join(claudeSkillsDir, 'skill.json')))\n {\n console.log(chalk.green('\\n✅ feng3d Skill 安装成功!\\n'));\n console.log(chalk.cyan(`安装位置: ${claudeSkillsDir}\\n`));\n console.log(chalk.yellow('使用方法:'));\n console.log(' /feng3d create my-project');\n console.log(' /feng3d update\\n');\n console.log(chalk.yellow('或直接对话: \"用 feng3d 创建一个新项目\"\\n'));\n console.log(chalk.cyan('💡 提示: 可能需要重启 Claude Code 使 skill 生效\\n'));\n }\n else\n {\n console.error(chalk.red('\\n❌ 安装失败:无法验证安装结果\\n'));\n process.exit(1);\n }\n }\n catch (error)\n {\n console.error(chalk.red(`\\n❌ 安装失败: ${error}\\n`));\n process.exit(1);\n }\n}\n","export default {}"],"names":["__dirname","fileURLToPath","TEMPLATES_DIR","detectIndent","__filename"],"mappings":"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"}
|
package/lib/commands/update.d.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 更新项目规范命令
|
|
3
3
|
*/
|
|
4
|
+
import type { UpdateOptions } from '../types.js';
|
|
4
5
|
/**
|
|
5
6
|
* 更新项目的规范配置
|
|
6
|
-
* @param
|
|
7
|
+
* @param options 更新选项
|
|
7
8
|
*/
|
|
8
|
-
export declare function updateProject(
|
|
9
|
-
/**
|
|
10
|
-
* 创建 ESLint 配置文件
|
|
11
|
-
*/
|
|
12
|
-
export declare function createEslintConfigFile(projectDir: string): Promise<void>;
|
|
9
|
+
export declare function updateProject(options?: UpdateOptions): Promise<void>;
|
|
13
10
|
//# sourceMappingURL=update.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,aAAa,EAA6B,MAAM,aAAa,CAAC;AA4B5E;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmS9E"}
|
package/lib/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { VERSIONS, getDevDependencies } from './versions.js';
|
|
6
6
|
export * from './templates.js';
|
|
7
|
+
export * from './types.js';
|
|
7
8
|
export { createProject } from './commands/create.js';
|
|
8
9
|
export { updateProject } from './commands/update.js';
|
|
9
10
|
export { installSkill } from './commands/install-skill.js';
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC7D,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC7D,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC"}
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 合并策略枚举
|
|
3
|
+
*/
|
|
4
|
+
export type MergeStrategy = 'overwrite' | 'merge' | 'skip-existing';
|
|
5
|
+
/**
|
|
6
|
+
* 文件处理方式
|
|
7
|
+
*/
|
|
8
|
+
export type FileAction = 'overwrite' | 'merge' | 'skip';
|
|
9
|
+
/**
|
|
10
|
+
* 更新项目选项
|
|
11
|
+
*/
|
|
12
|
+
export interface UpdateOptions {
|
|
13
|
+
/**
|
|
14
|
+
* 项目目录(默认当前目录)
|
|
15
|
+
*/
|
|
16
|
+
directory?: string;
|
|
17
|
+
/**
|
|
18
|
+
* 合并策略
|
|
19
|
+
* - overwrite: 覆盖所有文件
|
|
20
|
+
* - merge: 智能合并(默认)
|
|
21
|
+
* - skip-existing: 跳过已存在的文件
|
|
22
|
+
*/
|
|
23
|
+
mergeStrategy?: MergeStrategy;
|
|
24
|
+
/**
|
|
25
|
+
* 交互式模式,让用户选择要更新的部分
|
|
26
|
+
*/
|
|
27
|
+
interactive?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* 预览更改而不实际修改文件
|
|
30
|
+
*/
|
|
31
|
+
dryRun?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* 强制覆盖已存在的配置文件
|
|
34
|
+
*/
|
|
35
|
+
force?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 文件更新结果
|
|
39
|
+
*/
|
|
40
|
+
export interface FileUpdateResult {
|
|
41
|
+
/**
|
|
42
|
+
* 文件路径(相对于项目根目录)
|
|
43
|
+
*/
|
|
44
|
+
filePath: string;
|
|
45
|
+
/**
|
|
46
|
+
* 执行的操作
|
|
47
|
+
*/
|
|
48
|
+
action: 'created' | 'updated' | 'merged' | 'skipped';
|
|
49
|
+
/**
|
|
50
|
+
* 操作说明
|
|
51
|
+
*/
|
|
52
|
+
message?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 更新报告
|
|
56
|
+
*/
|
|
57
|
+
export interface UpdateReport {
|
|
58
|
+
/**
|
|
59
|
+
* 已更新的文件
|
|
60
|
+
*/
|
|
61
|
+
updated: FileUpdateResult[];
|
|
62
|
+
/**
|
|
63
|
+
* 已创建的文件
|
|
64
|
+
*/
|
|
65
|
+
created: FileUpdateResult[];
|
|
66
|
+
/**
|
|
67
|
+
* 已跳过的文件
|
|
68
|
+
*/
|
|
69
|
+
skipped: FileUpdateResult[];
|
|
70
|
+
/**
|
|
71
|
+
* 需要手动处理的项目
|
|
72
|
+
*/
|
|
73
|
+
manualActions: string[];
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,OAAO,GAAG,eAAe,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,aAAa;IAE1B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAE9B;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAE7B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IAErD;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAEzB;;OAEG;IACH,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAE5B;;OAEG;IACH,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAE5B;;OAEG;IACH,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAE5B;;OAEG;IACH,aAAa,EAAE,MAAM,EAAE,CAAC;CAC3B"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 配置文件智能合并工具
|
|
3
|
+
*/
|
|
4
|
+
import type { FileAction, MergeStrategy } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* 深度合并两个对象
|
|
7
|
+
* @param target 目标对象(用户配置)
|
|
8
|
+
* @param source 源对象(标准配置)
|
|
9
|
+
* @returns 合并后的对象
|
|
10
|
+
*/
|
|
11
|
+
export declare function deepMerge<T extends Record<string, any>>(target: T, source: T): T;
|
|
12
|
+
/**
|
|
13
|
+
* 合并 JSON 配置文件
|
|
14
|
+
* @param existingPath 现有文件路径
|
|
15
|
+
* @param standardContent 标准配置内容(字符串)
|
|
16
|
+
* @returns 合并后的内容
|
|
17
|
+
*/
|
|
18
|
+
export declare function mergeJsonConfig(existingPath: string, standardContent: string): Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* 检测 JSON 文件的缩进风格
|
|
21
|
+
*/
|
|
22
|
+
export declare function detectIndent(content: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* 根据合并策略决定文件处理方式
|
|
25
|
+
* @param filePath 文件路径
|
|
26
|
+
* @param mergeStrategy 合并策略
|
|
27
|
+
* @returns 文件处理方式
|
|
28
|
+
*/
|
|
29
|
+
export declare function determineFileAction(filePath: string, mergeStrategy: MergeStrategy): Promise<FileAction>;
|
|
30
|
+
/**
|
|
31
|
+
* 交互式询问用户如何处理文件
|
|
32
|
+
* @param filePath 文件路径(相对路径,用于显示)
|
|
33
|
+
* @returns 用户选择的处理方式
|
|
34
|
+
*/
|
|
35
|
+
export declare function askFileAction(filePath: string): Promise<FileAction>;
|
|
36
|
+
/**
|
|
37
|
+
* 写入文件内容(支持 dry-run)
|
|
38
|
+
* @param filePath 文件路径
|
|
39
|
+
* @param content 内容
|
|
40
|
+
* @param dryRun 是否为预览模式
|
|
41
|
+
*/
|
|
42
|
+
export declare function writeFileContent(filePath: string, content: string, dryRun?: boolean): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* 处理文件更新
|
|
45
|
+
* @param filePath 文件完整路径
|
|
46
|
+
* @param standardContent 标准配置内容
|
|
47
|
+
* @param action 处理方式
|
|
48
|
+
* @param dryRun 是否为预览模式
|
|
49
|
+
* @returns 是否执行了操作
|
|
50
|
+
*/
|
|
51
|
+
export declare function handleFileUpdate(filePath: string, standardContent: string, action: FileAction, dryRun?: boolean): Promise<boolean>;
|
|
52
|
+
//# sourceMappingURL=merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/utils/merge.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7D;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAiChF;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBpG;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACrC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,aAAa,GAC7B,OAAO,CAAC,UAAU,CAAC,CA8BrB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAoCzE;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAClC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,OAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAClC,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,UAAU,EAClB,MAAM,GAAE,OAAe,GACxB,OAAO,CAAC,OAAO,CAAC,CAgElB"}
|