UNPKG

@tianyio/quality-helper

Version:

A comprehensive quality helper tool for project scaffolding and management

1 lines 52.2 kB
{"version":3,"file":"utils-CuBC1baf.cjs","sources":["../src/utils/install.ts","../src/utils/npm-version.ts","../src/utils/dependency.ts","../src/utils/validation-rules.ts","../src/utils/dependency-validator.ts","../src/utils/array-utils.ts","../src/utils/format.ts","../src/utils/git.ts"],"sourcesContent":["'use strict'\nimport { execSync } from 'child_process'\nimport fs from 'fs/promises'\nimport { join } from 'path'\n\n/**\n * 检测可用的包管理器\n */\nexport async function detectPackageManager(projectPath: string): Promise<string> {\n const lockFiles = {\n 'pnpm-lock.yaml': 'pnpm',\n 'yarn.lock': 'yarn',\n 'package-lock.json': 'npm',\n }\n\n // 检查锁文件\n for (const [lockFile, manager] of Object.entries(lockFiles)) {\n try {\n const lockPath = join(projectPath, lockFile)\n await fs.access(lockPath)\n return manager\n } catch {\n continue\n }\n }\n\n // 检查全局安装的包管理器\n const managers = ['pnpm', 'yarn', 'npm']\n for (const manager of managers) {\n try {\n execSync(`${manager} --version`, { stdio: 'ignore' })\n return manager\n } catch {\n continue\n }\n }\n\n return 'npm' // 默认使用npm\n}\n\n/**\n * 安装项目依赖\n */\nexport async function installProjectDependencies(projectPath: string): Promise<void> {\n const packageManager = await detectPackageManager(projectPath)\n\n // 安装项目依赖\n\n try {\n const installCommand = getInstallCommand(packageManager)\n\n // 对于 pnpm,先尝试捕获输出以检测锁文件问题\n if (packageManager === 'pnpm') {\n try {\n // 使用 --no-frozen-lockfile 参数避免锁文件问题,并使用 inherit stdio 处理交互\n execSync(`${installCommand} --no-frozen-lockfile`, {\n cwd: projectPath,\n stdio: 'inherit',\n })\n } catch (retryError: any) {\n console.error('❌ 重新安装失败:')\n console.log('\\n💡 请手动执行以下命令解决:')\n console.log('1. rm -rf node_modules pnpm-lock.yaml')\n console.log('2. pnpm install --no-frozen-lockfile')\n throw retryError\n }\n } else {\n // 非 pnpm 包管理器直接执行\n execSync(installCommand, {\n cwd: projectPath,\n stdio: 'inherit',\n })\n }\n\n // 依赖安装成功\n } catch (error: any) {\n console.warn('依赖安装失败:', error)\n throw error\n }\n}\n\n/**\n * 获取安装命令\n */\nfunction getInstallCommand(packageManager: string): string {\n switch (packageManager) {\n case 'pnpm':\n return 'pnpm install'\n case 'yarn':\n return 'yarn install'\n case 'npm':\n default:\n return 'npm install'\n }\n}\n\n/**\n * 安装指定依赖\n */\nexport async function installDependencies(\n projectPath: string,\n dependencies: string[],\n isDev = false\n): Promise<void> {\n if (dependencies.length === 0) {\n // 没有需要安装的依赖\n return\n }\n\n const packageManager = await detectPackageManager(projectPath)\n const installCommand = getInstallDependenciesCommand(packageManager, dependencies, isDev)\n\n // 正在安装依赖\n\n try {\n execSync(installCommand, {\n cwd: projectPath,\n stdio: 'inherit',\n })\n // 依赖安装成功\n } catch (error: any) {\n console.warn('依赖安装失败:', error.message)\n throw error\n }\n}\n\n/**\n * 获取安装依赖命令\n */\nfunction getInstallDependenciesCommand(\n packageManager: string,\n dependencies: string[],\n isDev: boolean\n): string {\n // 处理 @tianyio/ 依赖,为其添加 @latest 后缀\n const processedDeps = dependencies.map(dep => {\n if (dep.startsWith('@tianyio/')) {\n return `${dep}@latest`\n }\n return dep\n })\n\n const deps = processedDeps.join(' ')\n\n switch (packageManager) {\n case 'pnpm':\n return `pnpm add ${isDev ? '-D' : ''} ${deps}`\n case 'yarn':\n return `yarn add ${isDev ? '--dev' : ''} ${deps}`\n case 'npm':\n default:\n return `npm install ${isDev ? '--save-dev' : '--save'} ${deps}`\n }\n}\n\n/**\n * 更新依赖到最新版本\n */\nexport async function updateDependenciesToLatest(projectPath: string): Promise<void> {\n const packageManager = await detectPackageManager(projectPath)\n\n // 使用包管理器更新依赖\n\n try {\n const updateCommand = getUpdateCommand(packageManager)\n execSync(updateCommand, {\n cwd: projectPath,\n stdio: 'inherit',\n })\n\n // 依赖更新成功\n } catch (error: any) {\n // 如果是 pnpm 的依赖冲突错误,尝试清理后重新安装\n if (\n packageManager === 'pnpm' &&\n (error.message.includes('ERR_PNPM_INCLUDED_DEPS_CONFLICT') ||\n error.stderr?.includes('ERR_PNPM_INCLUDED_DEPS_CONFLICT'))\n ) {\n console.warn('\\n⚠️ 检测到 pnpm 依赖冲突,正在清理并重新安装...')\n try {\n // 清理依赖\n await cleanDependencies(projectPath)\n console.log('✅ 依赖清理完成,正在重新安装...')\n\n // 重新安装\n execSync('pnpm install', {\n cwd: projectPath,\n stdio: 'inherit',\n })\n console.log('✅ 依赖重新安装成功')\n return\n } catch (cleanError: any) {\n console.error('❌ 清理重装失败:', cleanError.message)\n // 提供手动解决方案\n console.log('\\n💡 请手动执行以下命令解决:')\n console.log('1. rm -rf node_modules pnpm-lock.yaml')\n console.log('2. pnpm install')\n throw cleanError\n }\n }\n throw error\n }\n}\n\n/**\n * 获取更新命令\n */\nfunction getUpdateCommand(packageManager: string): string {\n switch (packageManager) {\n case 'pnpm':\n return 'pnpm update --latest'\n case 'yarn':\n return 'yarn upgrade --latest'\n case 'npm':\n default:\n return 'npm update'\n }\n}\n\n/**\n * 清理依赖\n */\nexport async function cleanDependencies(projectPath: string): Promise<void> {\n const nodeModulesPath = join(projectPath, 'node_modules')\n const lockFiles = ['pnpm-lock.yaml', 'yarn.lock', 'package-lock.json']\n const pnpmFiles = ['.pnpm-store', '.pnpm-debug.log']\n\n try {\n // 删除node_modules\n await fs.rm(nodeModulesPath, { recursive: true, force: true })\n // node_modules 已删除\n\n // 删除锁文件\n for (const lockFile of lockFiles) {\n try {\n await fs.unlink(join(projectPath, lockFile))\n // 锁文件已删除\n } catch {\n // 文件不存在,忽略错误\n }\n }\n\n // 删除 pnpm 相关文件\n for (const pnpmFile of pnpmFiles) {\n try {\n const pnpmPath = join(projectPath, pnpmFile)\n await fs.rm(pnpmPath, { recursive: true, force: true })\n } catch {\n // 文件不存在,忽略错误\n }\n }\n\n // 清理 pnpm 缓存(如果是 pnpm 项目)\n try {\n const packageManager = await detectPackageManager(projectPath)\n if (packageManager === 'pnpm') {\n execSync('pnpm store prune', { cwd: projectPath, stdio: 'ignore' })\n }\n } catch {\n // 忽略缓存清理错误\n }\n\n // 依赖清理完成\n } catch (error: any) {\n console.warn('依赖清理失败:', error.message)\n throw error\n }\n}\n\n/**\n * 检查依赖是否已安装\n */\nexport async function checkDependencyInstalled(\n projectPath: string,\n dependency: string\n): Promise<boolean> {\n try {\n const packageJsonPath = join(projectPath, 'package.json')\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'))\n\n return !!(packageJson.dependencies?.[dependency] ?? packageJson.devDependencies?.[dependency])\n } catch {\n return false\n }\n}\n\n/**\n * 获取已安装依赖的版本\n */\nexport async function getInstalledVersion(\n projectPath: string,\n dependency: string\n): Promise<string | null> {\n try {\n const packageJsonPath = join(projectPath, 'node_modules', dependency, 'package.json')\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'))\n return packageJson.version\n } catch {\n return null\n }\n}\n","import { execSync } from 'child_process'\n\n/**\n * 从npm获取包的最新版本\n * @param packageName 包名\n * @returns 最新版本号\n */\nexport async function getLatestVersion(packageName: string): Promise<string> {\n try {\n const command = `npm view ${packageName} version --json`\n const result = execSync(command, {\n encoding: 'utf8',\n timeout: 30000, // 增加超时时间到30秒\n stdio: ['pipe', 'pipe', 'pipe'], // 明确指定stdio\n })\n\n // 过滤掉 npm 警告信息,只保留 JSON 部分\n const lines = result.split('\\n')\n const jsonLines = lines.filter(\n line => !line.startsWith('npm warn') && !line.startsWith('npm notice') && line.trim() !== ''\n )\n const jsonString = jsonLines.join('\\n').trim()\n\n if (!jsonString) {\n console.warn(`No valid JSON response for ${packageName}`)\n return 'latest'\n }\n\n const version = JSON.parse(jsonString)\n return typeof version === 'string' ? version : version[version.length - 1]\n } catch (error: any) {\n // 对于超时或网络错误,返回 latest 而不是抛出错误\n if (error.code === 'ETIMEDOUT' || error.errno === -4039) {\n console.warn(`Timeout getting version for ${packageName}, using 'latest'`)\n } else {\n console.warn(`Failed to get latest version for ${packageName}:`, error.message)\n }\n return 'latest'\n }\n}\n\n/**\n * 批量获取多个包的最新版本\n * @param packageNames 包名数组\n * @returns 包名到版本号的映射\n */\nexport async function getLatestVersions(packageNames: string[]): Promise<Record<string, string>> {\n const versions: Record<string, string> = {}\n\n // 并发获取版本信息以提高性能\n const promises = packageNames.map(async packageName => {\n const version = await getLatestVersion(packageName)\n versions[packageName] = version\n })\n\n await Promise.all(promises)\n return versions\n}\n\n/**\n * 获取@tianyio/开头的包的最新版本\n */\nexport async function getTianyioLatestVersions(): Promise<Record<string, string>> {\n const tianyioPackages = ['@tianyio/fast-util-lib', '@tianyio/quality-helper']\n return await getLatestVersions(tianyioPackages)\n}\n\n/**\n * 解析依赖对象,将'latest'版本或未提供版本号的依赖替换为最新稳定版本\n * @param dependencies 依赖对象\n * @returns 解析后的依赖对象\n */\nexport async function resolveDependencyVersions(\n dependencies: Record<string, string>\n): Promise<Record<string, string>> {\n const resolved: Record<string, string> = { ...dependencies }\n const packagesToResolve: string[] = []\n\n // 找出需要解析版本的包\n for (const [name, version] of Object.entries(dependencies)) {\n if (!version || version === 'latest') {\n packagesToResolve.push(name)\n }\n }\n\n if (packagesToResolve.length > 0) {\n const latestVersions = await getLatestVersions(packagesToResolve)\n\n // 更新版本\n for (const packageName of packagesToResolve) {\n if (latestVersions[packageName]) {\n resolved[packageName] = latestVersions[packageName]\n }\n }\n }\n\n return resolved\n}\n\n/**\n * 检查包是否需要版本解析\n * @param version 版本字符串\n * @returns 是否需要解析\n */\nexport function needsVersionResolution(version: string): boolean {\n return !version || version === 'latest'\n}\n","'use strict'\nimport { join } from 'path'\nimport chalk from 'chalk'\nimport type { DependencyAnalysis, DependencyUpdateStrategy } from '../types.ts'\nimport { FileOperations } from '../core/FileOperations.ts'\nimport { resolveDependencyVersions } from './npm-version.ts'\n\n/**\n * Vue 项目依赖配置\n * 固定版本,分离运行时和开发时依赖\n */\n\n// 运行时依赖配置\nexport const RUNTIME_DEPENDENCIES = {\n // Vue 核心\n vue: '3.5.18',\n // 路由管理\n 'vue-router': '4.5.1',\n // 状态管理\n pinia: '3.0.3',\n // VueUse 工具库\n '@vueuse/core': '13.9.0',\n // 工具库\n 'lodash-es': '4.17.21',\n axios: '1.12.2',\n // 自研工具包\n '@tianyio/fast-util-lib': 'latest', // @tianyio/ 依赖使用 latest 版本\n} as const\n\n// 开发时依赖配置\nexport const DEV_DEPENDENCIES = {\n // 脚手架工具\n '@tianyio/quality-helper': 'latest', // @tianyio/ 依赖使用 latest 版本\n\n // 构建工具\n vite: '7.1.5',\n '@vitejs/plugin-vue': '6.0.1',\n '@vitejs/plugin-legacy': '7.2.1',\n 'vite-plugin-vue-devtools': '8.0.0',\n 'vite-plugin-dts': '4.5.4',\n '@originjs/vite-plugin-federation': '1.4.1',\n 'vite-bundle-analyzer': '1.2.3',\n 'vue-tsc': '3.1.1',\n\n // TypeScript\n typescript: '5.9.2',\n '@types/node': '24.3.0',\n '@vue/tsconfig': '0.8.1',\n\n // 代码规范\n eslint: '9.33.0',\n '@eslint/js': '9.38.0',\n 'eslint-config-prettier': '10.1.8',\n 'eslint-plugin-prettier': '5.5.4',\n 'eslint-plugin-promise': '7.2.1',\n 'eslint-plugin-vue': '10.4.0',\n '@typescript-eslint/eslint-plugin': '8.40.0',\n '@typescript-eslint/parser': '8.40.0',\n 'eslint-plugin-complexity': '^1.0.0',\n 'vue-eslint-parser': '10.2.0',\n prettier: '3.6.2',\n\n // Git 工具\n husky: '9.1.7',\n 'lint-staged': '16.1.5',\n '@commitlint/cli': '19.8.1',\n '@commitlint/config-conventional': '19.8.1',\n\n // 自动导入\n 'unplugin-auto-import': '20.0.0',\n 'unplugin-vue-components': '29.0.0',\n 'unplugin-icons': '22.3.0',\n\n // Babel 浏览器兼容\n '@babel/core': '7.28.3',\n '@babel/preset-env': '7.28.3',\n '@babel/preset-typescript': '7.27.1',\n '@babel/plugin-proposal-decorators': '7.28.0',\n '@babel/plugin-syntax-dynamic-import': '7.8.3',\n '@rollup/plugin-babel': '6.0.4',\n '@vue/babel-plugin-jsx': '1.5.0',\n 'react-refresh': '0.17.0',\n} as const\n\n// 依赖类型定义\nexport type RuntimeDependency = keyof typeof RUNTIME_DEPENDENCIES\nexport type DevDependency = keyof typeof DEV_DEPENDENCIES\n\n// 获取运行时依赖\nexport function getRuntimeDependencies(): Record<string, string> {\n return { ...RUNTIME_DEPENDENCIES }\n}\n\n// 获取开发依赖\nexport function getDevDependencies(): Record<string, string> {\n return { ...DEV_DEPENDENCIES }\n}\n\n// 获取所有依赖\nexport function getAllDependencies(): {\n dependencies: Record<string, string>\n devDependencies: Record<string, string>\n} {\n return {\n dependencies: getRuntimeDependencies(),\n devDependencies: getDevDependencies(),\n }\n}\n\n// 检查依赖是否存在\nexport function isDependencySupported(name: string): boolean {\n return name in RUNTIME_DEPENDENCIES || name in DEV_DEPENDENCIES\n}\n\n// 获取依赖版本\nexport function getDependencyVersion(name: string): string | undefined {\n if (name in RUNTIME_DEPENDENCIES) {\n return RUNTIME_DEPENDENCIES[name as RuntimeDependency]\n }\n if (name in DEV_DEPENDENCIES) {\n return DEV_DEPENDENCIES[name as DevDependency]\n }\n return undefined\n}\n\n// 依赖更新策略配置\nexport const DEPENDENCY_UPDATE_STRATEGY = {\n // 模板依赖优先级:模板版本覆盖项目版本\n templatePriority: true,\n // 保留用户新增的依赖\n preserveUserDependencies: true,\n // 同步新增的模板依赖到项目\n syncNewTemplateDependencies: true,\n} as const\n\n// 自定义依赖配置接口\nexport interface CustomDependencyConfig {\n customDependencies?: Record<string, string>\n customDevDependencies?: Record<string, string>\n}\n\n/**\n * 获取运行时依赖(支持动态版本解析)\n * @param resolveVersions 是否解析'latest'版本为具体版本号\n * @returns 运行时依赖对象\n */\nexport async function getRuntimeDependenciesWithVersionResolution(\n resolveVersions: boolean = true\n): Promise<Record<string, string>> {\n const dependencies = getRuntimeDependencies()\n\n if (resolveVersions) {\n return await resolveDependencyVersions(dependencies)\n }\n\n return dependencies\n}\n\n/**\n * 获取开发依赖(支持动态版本解析)\n * @param resolveVersions 是否解析'latest'版本为具体版本号\n * @returns 开发依赖对象\n */\nexport async function getDevDependenciesWithVersionResolution(\n resolveVersions: boolean = true\n): Promise<Record<string, string>> {\n const dependencies = getDevDependencies()\n\n if (resolveVersions) {\n return await resolveDependencyVersions(dependencies)\n }\n\n return dependencies\n}\n\n/**\n * 获取所有依赖(支持动态版本解析)\n * @param resolveVersions 是否解析'latest'版本为具体版本号\n * @returns 所有依赖对象\n */\nexport async function getAllDependenciesWithVersionResolution(\n resolveVersions: boolean = true\n): Promise<{\n dependencies: Record<string, string>\n devDependencies: Record<string, string>\n}> {\n const [dependencies, devDependencies] = await Promise.all([\n getRuntimeDependenciesWithVersionResolution(resolveVersions),\n getDevDependenciesWithVersionResolution(resolveVersions),\n ])\n\n return {\n dependencies,\n devDependencies,\n }\n}\n\n/**\n * 依赖管理器\n */\nexport class DependencyManager {\n private strategy: DependencyUpdateStrategy\n private customDependencies?: Record<string, string>\n private customDevDependencies?: Record<string, string>\n\n constructor(\n strategy: DependencyUpdateStrategy = DEPENDENCY_UPDATE_STRATEGY,\n customConfig?: CustomDependencyConfig\n ) {\n this.strategy = strategy\n if (customConfig?.customDependencies) {\n this.customDependencies = customConfig.customDependencies\n }\n if (customConfig?.customDevDependencies) {\n this.customDevDependencies = customConfig.customDevDependencies\n }\n }\n\n /**\n * 直接更新项目依赖到推荐版本\n * @returns 是否有更新\n */\n async updateToRecommendedVersions(projectRoot: string): Promise<boolean> {\n const packageJsonPath = join(projectRoot, 'package.json')\n const packageJson = JSON.parse(await FileOperations.readFile(packageJsonPath))\n\n // 获取推荐的依赖版本(优先使用自定义依赖)\n const templateRuntimeDeps =\n this.customDependencies ?? (await getRuntimeDependenciesWithVersionResolution())\n const templateDevDeps =\n this.customDevDependencies ?? (await getDevDependenciesWithVersionResolution())\n\n // 确保依赖对象存在\n packageJson.dependencies ??= {}\n packageJson.devDependencies ??= {}\n\n let hasChanges = false\n const preservedUserDeps: string[] = []\n const updatedDeps: string[] = []\n const addedDeps: string[] = []\n\n // 处理运行时依赖\n hasChanges =\n this.updateDependencyGroup(\n packageJson.dependencies,\n templateRuntimeDeps,\n preservedUserDeps,\n updatedDeps,\n addedDeps\n ) || hasChanges\n\n // 处理开发依赖\n hasChanges =\n this.updateDependencyGroup(\n packageJson.devDependencies,\n templateDevDeps,\n preservedUserDeps,\n updatedDeps,\n addedDeps\n ) || hasChanges\n\n // 写入更新后的 package.json\n if (hasChanges) {\n await FileOperations.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2))\n }\n\n return hasChanges\n }\n\n /**\n * 更新依赖组\n */\n private updateDependencyGroup(\n projectDeps: Record<string, string>,\n templateDeps: Record<string, string>,\n preservedUserDeps: string[],\n updatedDeps: string[],\n addedDeps: string[]\n ): boolean {\n let hasChanges = false\n\n // 添加或更新推荐依赖\n for (const [name, templateVersion] of Object.entries(templateDeps)) {\n const currentVersion = projectDeps[name]\n\n if (!currentVersion) {\n // 添加新依赖\n projectDeps[name] = templateVersion\n addedDeps.push(name)\n hasChanges = true\n } else if (currentVersion !== templateVersion) {\n // 更新到推荐版本\n projectDeps[name] = templateVersion\n updatedDeps.push(name)\n hasChanges = true\n }\n }\n\n // 保留用户独有依赖\n if (this.strategy.preserveUserDependencies) {\n for (const [name] of Object.entries(projectDeps)) {\n if (!isDependencySupported(name) && !templateDeps[name]) {\n preservedUserDeps.push(name)\n // 用户依赖保持不变,不删除\n }\n }\n }\n\n return hasChanges\n }\n\n /**\n * 分析项目依赖状态\n */\n async analyzeDependencies(projectRoot: string): Promise<DependencyAnalysis> {\n const packageJsonPath = join(projectRoot, 'package.json')\n const packageJson = JSON.parse(await FileOperations.readFile(packageJsonPath))\n\n const templateRuntimeDeps =\n this.customDependencies ?? (await getRuntimeDependenciesWithVersionResolution())\n const templateDevDeps =\n this.customDevDependencies ?? (await getDevDependenciesWithVersionResolution())\n const projectDeps = packageJson.dependencies ?? {}\n const projectDevDeps = packageJson.devDependencies ?? {}\n\n const analysis: DependencyAnalysis = {\n toUpdate: {},\n toAdd: {},\n userAdded: {},\n synced: {},\n }\n\n // 分析运行时依赖\n this.analyzeDepGroup(projectDeps, templateRuntimeDeps, analysis)\n\n // 分析开发依赖\n this.analyzeDepGroup(projectDevDeps, templateDevDeps, analysis)\n\n return analysis\n }\n\n /**\n * 分析依赖组\n */\n private analyzeDepGroup(\n projectDeps: Record<string, string>,\n templateDeps: Record<string, string>,\n analysis: DependencyAnalysis\n ): void {\n // 检查模板依赖\n for (const [name, templateVersion] of Object.entries(templateDeps)) {\n const projectVersion = projectDeps[name]\n\n if (!projectVersion) {\n // 项目中不存在,需要添加\n analysis.toAdd[name] = templateVersion\n } else if (projectVersion !== templateVersion) {\n // 版本不一致,需要更新\n analysis.toUpdate[name] = {\n current: projectVersion,\n template: templateVersion,\n }\n } else {\n // 版本一致,已同步\n analysis.synced[name] = templateVersion\n }\n }\n\n // 检查用户新增的依赖\n if (this.strategy.preserveUserDependencies) {\n for (const [name, version] of Object.entries(projectDeps)) {\n if (!isDependencySupported(name)) {\n analysis.userAdded[name] = version\n }\n }\n }\n }\n\n /**\n * 生成依赖报告\n */\n generateReport(analysis: DependencyAnalysis): void {\n const { toUpdate, toAdd, userAdded, synced } = analysis\n const totalDeps =\n Object.keys(synced).length +\n Object.keys(toUpdate).length +\n Object.keys(toAdd).length +\n Object.keys(userAdded).length\n\n console.log(chalk.blue('\\n📊 依赖分析结果:'))\n\n if (Object.keys(synced).length > 0) {\n console.log(chalk.green(`✅ 已同步: ${Object.keys(synced).length} 个依赖`))\n }\n\n if (Object.keys(toUpdate).length > 0) {\n console.log(chalk.yellow(`🔄 需要更新: ${Object.keys(toUpdate).length} 个依赖`))\n Object.entries(toUpdate)\n .slice(0, 3)\n .forEach(([name, { current, template }]) => {\n console.log(chalk.gray(` ${name}: ${current} → ${template}`))\n })\n if (Object.keys(toUpdate).length > 3) {\n console.log(chalk.gray(` ... 还有 ${Object.keys(toUpdate).length - 3} 个`))\n }\n }\n\n if (Object.keys(toAdd).length > 0) {\n console.log(chalk.cyan(`➕ 需要添加: ${Object.keys(toAdd).length} 个依赖`))\n }\n\n if (Object.keys(userAdded).length > 0) {\n console.log(chalk.magenta(`👤 用户自定义: ${Object.keys(userAdded).length} 个依赖`))\n }\n\n console.log(chalk.gray(`总计: ${totalDeps} 个依赖`))\n }\n\n /**\n * 检查依赖兼容性\n */\n checkCompatibility(analysis: DependencyAnalysis): boolean {\n // 检查是否有冲突的依赖版本\n const conflicts: string[] = []\n\n for (const [name, { current, template }] of Object.entries(analysis.toUpdate)) {\n // 简单的版本冲突检查(可以扩展更复杂的逻辑)\n const currentMajor = this.extractMajorVersion(current)\n const templateMajor = this.extractMajorVersion(template)\n\n if (currentMajor !== templateMajor) {\n conflicts.push(`${name}: ${current} → ${template} (主版本变更)`)\n }\n }\n\n if (conflicts.length > 0) {\n console.log(chalk.red('⚠️ 发现潜在的版本冲突:'))\n conflicts.forEach(conflict => {\n console.log(chalk.red(` ${conflict}`))\n })\n return false\n }\n\n return true\n }\n\n /**\n * 提取主版本号\n */\n private extractMajorVersion(version: string): string {\n const match = version.match(/\\d+/)\n return match ? match[0] : '0'\n }\n}\n\n/**\n * 创建默认依赖管理器实例\n */\nexport function createDependencyManager(\n strategy?: Partial<DependencyUpdateStrategy> | CustomDependencyConfig\n): DependencyManager {\n // 检查是否是自定义依赖配置\n if (strategy && 'customDependencies' in strategy) {\n const customConfig = strategy\n return new DependencyManager(DEPENDENCY_UPDATE_STRATEGY, customConfig)\n }\n\n // 否则是策略配置\n const fullStrategy = {\n ...DEPENDENCY_UPDATE_STRATEGY,\n ...(strategy as Partial<DependencyUpdateStrategy>),\n }\n return new DependencyManager(fullStrategy)\n}\n","/**\n * 验证规则接口\n */\nexport interface ValidationRule<T> {\n validate(value: T): ValidationResult\n}\n\n/**\n * 验证结果\n */\nexport interface ValidationResult {\n isValid: boolean\n errors: string[]\n warnings: string[]\n}\n\n/**\n * 包名验证规则\n */\nexport class PackageNameValidationRule implements ValidationRule<string> {\n validate(name: string): ValidationResult {\n const result: ValidationResult = {\n isValid: true,\n errors: [],\n warnings: [],\n }\n\n if (!name || typeof name !== 'string') {\n result.isValid = false\n result.errors.push('包名不能为空')\n return result\n }\n\n if (name.trim().length === 0) {\n result.isValid = false\n result.errors.push('包名不能为空')\n return result\n }\n\n if (name.startsWith('.') || name.startsWith('_')) {\n result.isValid = false\n result.errors.push('包名不能以点或下划线开头')\n return result\n }\n\n if (name.includes('@')) {\n // 作用域包验证\n const parts = name.split('/')\n if (parts.length !== 2) {\n result.isValid = false\n result.errors.push('作用域包格式无效')\n return result\n }\n\n const scope = parts[0]?.substring(1)\n const [, packageName] = parts\n\n if (!scope || !packageName) {\n result.isValid = false\n result.errors.push('作用域包格式无效')\n return result\n }\n\n // 作用域包名允许小写字母、数字、连字符和下划线\n if (!/^[a-z0-9_-]+$/.test(scope) || !/^[a-z0-9_-]+$/.test(packageName)) {\n result.isValid = false\n result.errors.push('作用域包名格式无效')\n return result\n }\n } else {\n // 普通包名验证,允许小写字母、数字、连字符和下划线\n if (!/^[a-z0-9_-]+$/.test(name)) {\n result.isValid = false\n result.errors.push('包名格式无效')\n return result\n }\n }\n\n return result\n }\n}\n\n/**\n * 版本验证规则\n */\nexport class VersionValidationRule implements ValidationRule<string> {\n private readonly versionPatterns = [\n /^\\d+\\.\\d+\\.\\d+$/, // 1.2.3\n /^\\d+\\.\\d+\\.\\d+-\\w+$/, // 1.2.3-beta\n /^\\d+\\.\\d+\\.\\d+\\+\\w+$/, // 1.2.3+build\n /^\\^\\d+\\.\\d+\\.\\d+$/, // ^1.2.3\n /^~\\d+\\.\\d+\\.\\d+$/, // ~1.2.3\n /^>=?\\d+\\.\\d+\\.\\d+$/, // >=1.2.3\n /^<=?\\d+\\.\\d+\\.\\d+$/, // <=1.2.3\n /^latest$/, // latest\n /^next$/, // next\n /^beta$/, // beta\n /^alpha$/, // alpha\n /^rc$/, // rc\n /^\\*$/, // *\n /^x$/, // x\n /^\\d+\\.\\d+\\.\\d+ - \\d+\\.\\d+\\.\\d+$/, // 1.2.3 - 2.3.4\n ]\n\n validate(version: string): ValidationResult {\n const result: ValidationResult = {\n isValid: true,\n errors: [],\n warnings: [],\n }\n\n if (!version || typeof version !== 'string') {\n result.isValid = false\n result.errors.push('版本号不能为空')\n return result\n }\n\n if (!this.versionPatterns.some(pattern => pattern.test(version))) {\n result.warnings.push(`版本格式可能无效: ${version}`)\n }\n\n return result\n }\n}\n\n/**\n * 验证规则工厂\n */\nexport class ValidationRuleFactory {\n static createPackageNameRule(): PackageNameValidationRule {\n return new PackageNameValidationRule()\n }\n\n static createVersionRule(): VersionValidationRule {\n return new VersionValidationRule()\n }\n}\n","'use strict'\nimport { readFile } from 'fs/promises'\nimport chalk from 'chalk'\nimport { ValidationRuleFactory } from './validation-rules.ts'\n\n/**\n * 依赖列表文件结构接口\n */\nexport interface DependencyListFile {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n [key: string]: any\n}\n\n/**\n * 依赖列表验证结果\n */\nexport interface DependencyValidationResult {\n isValid: boolean\n errors: string[]\n warnings: string[]\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n}\n\n/**\n * 依赖列表文件验证器\n */\nexport class DependencyValidator {\n private packageNameRule = ValidationRuleFactory.createPackageNameRule()\n private versionRule = ValidationRuleFactory.createVersionRule()\n /**\n * 验证依赖列表文件\n * @param filePath 文件路径\n * @returns 验证结果\n */\n async validateDependencyFile(filePath: string): Promise<DependencyValidationResult> {\n const result: DependencyValidationResult = {\n isValid: false,\n errors: [],\n warnings: [],\n }\n\n try {\n // 读取文件内容\n const fileContent = await readFile(filePath, 'utf-8')\n\n // 解析 JSON\n let parsedContent: DependencyListFile\n try {\n parsedContent = JSON.parse(fileContent)\n } catch (parseError) {\n result.errors.push('文件不是有效的 JSON 格式')\n return result\n }\n\n // 验证基本结构\n this.validateBasicStructure(parsedContent, result)\n\n // 如果基本结构有效,提取依赖信息\n if (result.isValid) {\n result.dependencies = parsedContent.dependencies ?? {}\n result.devDependencies = parsedContent.devDependencies ?? {}\n\n // 验证依赖格式\n this.validateDependencyFormat(result.dependencies, 'dependencies', result)\n this.validateDependencyFormat(result.devDependencies, 'devDependencies', result)\n }\n\n return result\n } catch (error: any) {\n result.errors.push(`读取文件失败: ${error.message}`)\n return result\n }\n }\n\n /**\n * 验证基本结构\n * @param content 解析后的内容\n * @param result 验证结果\n */\n private validateBasicStructure(\n content: DependencyListFile,\n result: DependencyValidationResult\n ): void {\n // 检查是否包含依赖字段\n const hasDependencies = 'dependencies' in content\n const hasDevDependencies = 'devDependencies' in content\n\n if (!hasDependencies && !hasDevDependencies) {\n result.errors.push('文件必须包含 dependencies 或 devDependencies 字段')\n return\n }\n\n // 检查字段类型\n if (hasDependencies && typeof content.dependencies !== 'object') {\n result.errors.push('dependencies 字段必须是对象类型')\n return\n }\n\n if (hasDevDependencies && typeof content.devDependencies !== 'object') {\n result.errors.push('devDependencies 字段必须是对象类型')\n return\n }\n\n // 检查是否为空对象\n if (hasDependencies && Object.keys(content.dependencies ?? {}).length === 0) {\n result.warnings.push('dependencies 字段为空')\n }\n\n if (hasDevDependencies && Object.keys(content.devDependencies ?? {}).length === 0) {\n result.warnings.push('devDependencies 字段为空')\n }\n\n result.isValid = true\n }\n\n /**\n * 验证依赖格式\n * @param dependencies 依赖对象\n * @param fieldName 字段名称\n * @param result 验证结果\n */\n private validateDependencyFormat(\n dependencies: Record<string, string>,\n fieldName: string,\n result: DependencyValidationResult\n ): void {\n for (const [name, version] of Object.entries(dependencies)) {\n // 检查包名格式\n if (!this.isValidPackageName(name)) {\n result.errors.push(`${fieldName}.${name}: 包名格式无效`)\n continue\n }\n\n // 检查版本格式\n if (!this.isValidVersion(version)) {\n result.warnings.push(`${fieldName}.${name}: 版本格式可能无效 (${version})`)\n }\n }\n }\n\n /**\n * 验证包名格式\n * @param name 包名\n * @returns 是否有效\n */\n private isValidPackageName(name: string): boolean {\n const result = this.packageNameRule.validate(name)\n return result.isValid\n }\n\n /**\n * 验证版本格式\n * @param version 版本号\n * @returns 是否有效\n */\n private isValidVersion(version: string): boolean {\n const result = this.versionRule.validate(version)\n return result.isValid\n }\n\n /**\n * 打印验证结果\n * @param result 验证结果\n * @param filePath 文件路径\n */\n printValidationResult(result: DependencyValidationResult, filePath: string): void {\n console.log(chalk.blue(`\\n📋 依赖列表文件验证结果: ${filePath}`))\n\n if (result.isValid) {\n console.log(chalk.green('✅ 文件结构有效'))\n\n if (result.dependencies && Object.keys(result.dependencies).length > 0) {\n console.log(chalk.cyan(`📦 运行时依赖: ${Object.keys(result.dependencies).length} 个`))\n }\n\n if (result.devDependencies && Object.keys(result.devDependencies).length > 0) {\n console.log(chalk.cyan(`🔧 开发依赖: ${Object.keys(result.devDependencies).length} 个`))\n }\n } else {\n console.log(chalk.red('❌ 文件结构无效'))\n }\n\n // 显示错误\n if (result.errors.length > 0) {\n console.log(chalk.red('\\n❌ 错误:'))\n result.errors.forEach(error => {\n console.log(chalk.red(` • ${error}`))\n })\n }\n\n // 显示警告\n if (result.warnings.length > 0) {\n console.log(chalk.yellow('\\n⚠️ 警告:'))\n result.warnings.forEach(warning => {\n console.log(chalk.yellow(` • ${warning}`))\n })\n }\n }\n}\n\n/**\n * 创建依赖验证器实例\n */\nexport function createDependencyValidator(): DependencyValidator {\n return new DependencyValidator()\n}\n","/**\n * 数组工具函数\n */\nexport class ArrayUtils {\n /**\n * 按指定键对数组进行分组\n * @param array 要分组的数组\n * @param keySelector 键选择器函数\n * @returns 分组后的 Map\n */\n static groupBy<T, K extends string | number | symbol>(\n array: T[],\n keySelector: (item: T) => K\n ): Map<K, T[]> {\n const groups = new Map<K, T[]>()\n\n for (const item of array) {\n const key = keySelector(item)\n if (!groups.has(key)) {\n groups.set(key, [])\n }\n groups.get(key)!.push(item)\n }\n\n return groups\n }\n\n /**\n * 安全地获取数组元素\n * @param array 数组\n * @param index 索引\n * @returns 元素或 undefined\n */\n static safeGet<T>(array: T[], index: number): T | undefined {\n return array[index]\n }\n}\n","import { execSync } from 'child_process'\nimport chalk from 'chalk'\nimport ora from 'ora'\nimport { existsSync } from 'fs'\nimport { join } from 'path'\n\n/**\n * 格式化项目代码\n * @param projectPath 项目路径\n * @param silent 是否静默执行\n */\nexport async function formatProject(projectPath: string, silent: boolean = false): Promise<void> {\n // 格式化项目代码\n\n const spinner = !silent ? ora('格式化代码中...').start() : null\n\n try {\n // 检查项目路径是否存在\n if (!existsSync(projectPath)) {\n throw new Error(`项目路径不存在: ${projectPath}`)\n }\n\n // 检查是否存在package.json\n const packageJsonPath = join(projectPath, 'package.json')\n if (!existsSync(packageJsonPath)) {\n throw new Error('项目中未找到package.json文件')\n }\n\n // 尝试运行格式化命令\n\n let formatSuccess = false\n\n try {\n execSync('eslint . --fix', {\n cwd: projectPath,\n stdio: silent ? 'ignore' : 'pipe',\n timeout: 60000, // 60秒超时\n })\n formatSuccess = true\n } catch {}\n\n if (!formatSuccess) {\n if (spinner) {\n spinner.warn(chalk.yellow('代码格式化失败,请手动运行格式化命令'))\n } else if (!silent) {\n console.log(chalk.yellow('⚠️ 代码格式化失败,请手动运行格式化命令'))\n }\n } else {\n if (spinner) {\n spinner.succeed(chalk.green('代码格式化成功'))\n }\n }\n } catch (error) {\n if (spinner) {\n spinner.fail(chalk.red('代码格式化失败'))\n } else if (!silent) {\n console.warn('代码格式化失败:', error)\n }\n\n if (!silent) {\n console.log(chalk.yellow('提示: 可以稍后手动运行 npm run format 进行代码格式化'))\n }\n }\n}\n","'use strict'\nimport { execSync } from 'child_process'\n\n/**\n * 初始化Git仓库\n */\nexport async function initializeGit(projectPath: string): Promise<void> {\n try {\n execSync('git init', { cwd: projectPath, stdio: 'ignore' })\n } catch (error) {\n console.warn('Git仓库初始化失败,请手动初始化')\n throw error\n }\n}\n\n/**\n * 初始化Husky钩子\n */\nexport async function initializeHusky(projectPath: string): Promise<void> {\n try {\n execSync('npx husky init', { cwd: projectPath, stdio: 'ignore' })\n } catch (error) {\n console.warn('Husky初始化失败,请手动初始化')\n throw error\n }\n}\n"],"names":["async","detectPackageManager","projectPath","lockFiles","lockFile","manager","Object","entries","lockPath","join","fs","access","managers","execSync","stdio","getLatestVersions","packageNames","versions","promises","map","packageName","version","command","jsonString","encoding","timeout","split","filter","line","startsWith","trim","console","warn","JSON","parse","length","error","code","errno","message","getLatestVersion","Promise","all","resolveDependencyVersions","dependencies","resolved","packagesToResolve","name","push","latestVersions","RUNTIME_DEPENDENCIES","vue","pinia","axios","DEV_DEPENDENCIES","vite","typescript","eslint","prettier","husky","isDependencySupported","DEPENDENCY_UPDATE_STRATEGY","templatePriority","preserveUserDependencies","syncNewTemplateDependencies","getRuntimeDependenciesWithVersionResolution","resolveVersions","getDevDependenciesWithVersionResolution","DependencyManager","strategy","customDependencies","customDevDependencies","constructor","customConfig","this","updateToRecommendedVersions","projectRoot","packageJsonPath","packageJson","FileOperations","readFile","templateRuntimeDeps","templateDevDeps","devDependencies","hasChanges","preservedUserDeps","updatedDeps","addedDeps","updateDependencyGroup","writeFile","stringify","projectDeps","templateDeps","templateVersion","currentVersion","analyzeDependencies","projectDevDeps","analysis","toUpdate","toAdd","userAdded","synced","analyzeDepGroup","projectVersion","current","template","generateReport","totalDeps","keys","log","chalk","blue","green","yellow","slice","forEach","gray","cyan","magenta","checkCompatibility","conflicts","extractMajorVersion","red","conflict","match","PackageNameValidationRule","validate","result","isValid","errors","warnings","includes","parts","scope","substring","test","VersionValidationRule","versionPatterns","some","pattern","ValidationRuleFactory","createPackageNameRule","createVersionRule","DependencyValidator","packageNameRule","versionRule","validateDependencyFile","filePath","fileContent","parsedContent","parseError","validateBasicStructure","validateDependencyFormat","content","hasDependencies","hasDevDependencies","fieldName","isValidPackageName","isValidVersion","printValidationResult","warning","groupBy","array","keySelector","groups","Map","item","key","has","set","get","safeGet","index","nodeModulesPath","pnpmFiles","rm","recursive","force","unlink","pnpmFile","pnpmPath","cwd","fullStrategy","silent","spinner","ora","start","existsSync","Error","formatSuccess","succeed","fail","packageManager","installCommand","getInstallCommand","retryError"],"mappings":"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"}