{"version":3,"file":"core-discovery-DoUt3gJ3.cjs","sources":["../src/core/Discovery.ts"],"sourcesContent":["import { join, dirname } from 'path'\nimport { FileOperations } from './FileOperations.ts'\nimport type { ConfigFileInfo } from '../services/ConfigService.ts'\nimport type { ArchitectureType, ProjectType, UpdateConfigOptions } from '../types.ts'\n\ninterface DirInfo {\n  dir: string\n  targetDir: string\n  priority: number\n}\n\n/**\n * 配置发现服务类\n * 负责发现和扫描项目中的配置文件\n */\nexport class Discovery {\n  /**\n   * 获取可用的配置文件列表\n   */\n  static async getAvailableConfigFiles(\n    templatesDir: string,\n    projectRoot: string,\n    options?: UpdateConfigOptions\n  ): Promise<ConfigFileInfo[]> {\n    const configs: ConfigFileInfo[] = []\n\n    await Discovery.scanTemplateDirectories(templatesDir, projectRoot, configs, options)\n\n    return configs\n  }\n\n  /**\n   * 应用过滤选项\n   */\n  static applyFilters(dirInfos: DirInfo[], options?: UpdateConfigOptions): DirInfo[] {\n    const { includeOnly = [], excludeGitHooks, excludeStaticFiles, excludeScripts } = options ?? {}\n    const include = includeOnly.length > 0\n    if (include || excludeGitHooks || excludeStaticFiles || excludeScripts) {\n      return dirInfos.filter(({ dir }) => {\n        const [, configType] = dir.split('/') // 获取配置类型，如 'build-tools', 'env' 等\n        if (include) {\n          return includeOnly.includes(configType as string)\n        }\n        if (excludeGitHooks && configType === 'git-hooks') {\n          return false\n        }\n        if (excludeStaticFiles && configType === 'static-files') {\n          return false\n        }\n        if (excludeScripts && configType === 'scripts') {\n          return false\n        }\n        return true\n      })\n    } else {\n      return dirInfos\n    }\n  }\n\n  /**\n   * 扫描模板目录\n   */\n  static async scanTemplateDirectories(\n    templatesDir: string,\n    projectRoot: string,\n    configs: ConfigFileInfo[],\n    options?: UpdateConfigOptions\n  ): Promise<void> {\n    const templateDirs = [\n      { dir: 'configs/rules', targetDir: 'rules', priority: 11 },\n      { dir: 'configs/env', targetDir: 'env', priority: 10 },\n      { dir: 'configs/static-files', targetDir: '', priority: 9 },\n      { dir: 'configs/types', targetDir: 'types', priority: 8 },\n      { dir: 'configs/develop-tools', targetDir: '', priority: 7 },\n      { dir: `configs/build-tools`, targetDir: '', priority: 6 },\n      { dir: `configs/scripts`, targetDir: 'scripts', priority: 5 },\n      { dir: 'configs/npm', targetDir: '', priority: 4 },\n      { dir: 'configs/git-hooks', targetDir: '.husky', priority: 3 },\n      { dir: 'configs/git-config', targetDir: '', priority: 2 },\n      { dir: 'configs/docs', targetDir: '', priority: 1 },\n    ]\n\n    // 过滤模板目录\n    const filteredTemplateDirs = Discovery.applyFilters(templateDirs, options)\n\n    for (const { dir, targetDir, priority } of filteredTemplateDirs) {\n      const templateSubDir = join(templatesDir, dir)\n\n      try {\n        const files = await FileOperations.readDir(templateSubDir)\n        await Discovery.processTemplateFiles(\n          files,\n          templateSubDir,\n          targetDir,\n          priority,\n          dir,\n          projectRoot,\n          configs,\n          options\n        )\n      } catch {\n        // 目录不存在，跳过\n        continue\n      }\n    }\n  }\n\n  /**\n   * 处理模板文件\n   */\n  static async processTemplateFiles(\n    files: string[],\n    templateSubDir: string,\n    targetDir: string,\n    priority: number,\n    dir: string,\n    projectRoot: string,\n    configs: ConfigFileInfo[],\n    options?: UpdateConfigOptions\n  ): Promise<void> {\n    for (const file of files) {\n      // 跳过特定文件\n      if (Discovery.shouldSkipFile(file, options)) {\n        continue\n      }\n      const templatePath = join(templateSubDir, file)\n      // 特殊处理路径和文件名\n      const { finalTargetPath, displayName } = Discovery.resolveFilePaths(\n        file,\n        targetDir,\n        projectRoot\n      )\n\n      // 检查是否已经在配置列表中\n      const exists = configs.some(config => config.name === displayName)\n\n      if (!exists) {\n        const group = Discovery.determineFileGroup(dir)\n        const [commentPrefix, commentSuffix] = Discovery.getCommentFix(displayName)\n        const configInfo: ConfigFileInfo = {\n          name: displayName,\n          path: finalTargetPath,\n          templatePath,\n          description: Discovery.getFileDescription(displayName),\n          commentPrefix,\n          commentSuffix,\n          group,\n          priority,\n        }\n\n        configs.push(configInfo)\n      }\n    }\n  }\n\n  /**\n   * 判断是否应该跳过文件\n   */\n  static shouldSkipFile(file: string, options?: UpdateConfigOptions): boolean {\n    // 跳过VS Code配置目录本身\n    if (file === '.vscode') {\n      return true\n    }\n    if (options?.excludeNpmrc && file === 'npmrc') {\n      return true\n    }\n\n    // 跳过系统文件和临时文件\n    const skipPatterns = [\n      /^\\.DS_Store$/,\n      /^Thumbs\\.db$/,\n      /^node_modules$/,\n      /^dist$/,\n      /^build$/,\n      /^\\.cache/,\n      /^\\.temp/,\n      /^\\.tmp/,\n      /~$/,\n      /\\.bak$/,\n      /\\.swp$/,\n      /\\.swo$/,\n    ]\n    if (skipPatterns.some(pattern => pattern.test(file))) return true\n\n    // 定义特殊处理文件\n    const specialFiles = ['apps', 'libs', 'single', 'monorepo']\n    return specialFiles.includes(file)\n  }\n\n  /**\n   * 解析文件路径\n   */\n  static resolveFilePaths(\n    file: string,\n    targetDir: string,\n    projectRoot: string\n  ): {\n    finalTargetPath: string\n    displayName: string\n  } {\n    let finalTargetPath: string\n    let displayName: string\n\n    const needAddDot = [\n      'browserslistrc',\n      'editorconfig',\n      'lintstagedrc',\n      'prettierignore',\n      'gitattributes',\n      'gitconfig',\n      'gitignore',\n      'npmrc',\n      'pnpmrc',\n    ]\n\n    if (file === 'vite.svg') {\n      finalTargetPath = join(projectRoot, 'public', file)\n      displayName = file\n    } else if (needAddDot.includes(file)) {\n      finalTargetPath = join(projectRoot, `.${file}`)\n      displayName = `.${file}`\n    } else {\n      finalTargetPath = targetDir ? join(projectRoot, targetDir, file) : join(projectRoot, file)\n      displayName = file\n    }\n\n    return { finalTargetPath, displayName }\n  }\n\n  /**\n   * 确定文件分组\n   */\n  static determineFileGroup(dir: string): string {\n    if (dir === 'configs/types') return 'types'\n    if (dir === 'configs/rules') return 'rules'\n    if (dir === 'configs/env') return 'env'\n    if (dir === 'configs/git-hooks') return 'git-hooks'\n    if (dir === 'configs/npm') return 'npm'\n    if (dir === 'configs/develop-tools') return 'develop-tools'\n    if (dir === 'configs/git-config') return 'git-config'\n    if (dir.includes('configs/build-tools')) return 'build-tools'\n    if (dir.includes('configs/docs')) return 'docs'\n    if (dir === 'configs/static-files') return 'static-files'\n    if (dir === 'configs/scripts') return 'scripts'\n    return 'other'\n  }\n\n  /**\n   * 获取文件描述\n   */\n  static getFileDescription(fileName: string): string {\n    const descriptions: Record<string, string> = {\n      eslint: 'ESLint 代码质量检查配置',\n      prettier: 'Prettier 代码格式化配置',\n      '.editorconfig': 'EditorConfig 编辑器配置',\n      '.gitignore': 'Git 忽略文件配置',\n      '.gitattributes': 'Git 属性配置',\n      'package.json': 'Node.js 项目配置文件',\n      'tsconfig.json': 'TypeScript 编译配置',\n      'vite.config': 'Vite 构建工具配置',\n      '.npmrc': 'npm 包管理器配置',\n      '.pnpmrc': 'pnpm 包管理器配置',\n      '.env': '环境变量配置文件',\n      'base.d.ts': 'TypeScript 环境变量类型定义',\n      'pre-commit': 'Git 提交前钩子',\n      'commit-msg': 'Git 提交信息钩子',\n      'vite.svg': 'Vite 项目图标',\n      'babel.config': 'Babel编译配置（预设、插件）',\n      '.browserslistrc': '浏览器兼容性配置文件',\n      'commitlint.config': 'CommitLint 规范提交信息',\n      lintstage: 'LintStaged 提交前代码检查',\n    }\n\n    for (const key in descriptions) {\n      if (fileName.includes(key)) {\n        return descriptions[key] as string\n      }\n    }\n\n    return `${fileName} 配置文件`\n  }\n\n  /**\n   * 获取注释前缀\n   */\n  static getCommentFix(fileName: string): [string, string] {\n    // JavaScript/TypeScript 文件\n    if (\n      fileName.endsWith('.js') ||\n      fileName.endsWith('.ts') ||\n      fileName.endsWith('.jsx') ||\n      fileName.endsWith('.tsx')\n    ) {\n      return ['//', '']\n    }\n\n    // CSS 相关文件\n    if (\n      fileName.endsWith('.css') ||\n      fileName.endsWith('.scss') ||\n      fileName.endsWith('.sass') ||\n      fileName.endsWith('.less')\n    ) {\n      return ['/*', '*/']\n    }\n\n    // HTML/XML/SVG 文件\n    if (\n      fileName.endsWith('.html') ||\n      fileName.endsWith('.xml') ||\n      fileName.endsWith('.svg') ||\n      fileName.endsWith('.vue')\n    ) {\n      return ['<!--', '-->']\n    }\n\n    // Shell 脚本\n    if (fileName.endsWith('.sh') || fileName.endsWith('.bash') || fileName.endsWith('.zsh')) {\n      return ['#', '']\n    }\n\n    // Python, Ruby, PHP\n    if (fileName.endsWith('.py') || fileName.endsWith('.rb') || fileName.endsWith('.php')) {\n      return ['#', '']\n    }\n\n    // YAML 文件\n    if (fileName.endsWith('.yaml') || fileName.endsWith('.yml')) {\n      return ['#', '']\n    }\n\n    const commentSupportedFiles = [\n      '.browserslistrc',\n      '.editorconfig',\n      '.gitattributes',\n      '.gitconfig',\n      '.gitignore',\n      '.lintstagedrc',\n      '.npmrc',\n      '.pnpmrc',\n      '.prettierignore',\n    ]\n    // 环境变量和配置文件\n    if (fileName.startsWith('.env') || commentSupportedFiles.includes(fileName)) {\n      return ['#', '']\n    }\n\n    return ['//', '']\n  }\n\n  /**\n   * 检查是否为 monorepo 根目录\n   */\n  static async isMonorepoRoot(projectRoot: string): Promise<boolean> {\n    try {\n      // 检查是否存在 monorepo 标识文件\n      const workspaceFiles = ['pnpm-workspace.yaml', 'lerna.json', 'rush.json']\n      for (const file of workspaceFiles) {\n        if (await FileOperations.exists(join(projectRoot, file))) {\n          return true\n        }\n      }\n\n      // 检查 package.json 中的 workspaces 字段\n      const packageJsonPath = join(projectRoot, 'package.json')\n      const packageJsonContent = await FileOperations.readFile(packageJsonPath)\n      const packageJson = JSON.parse(packageJsonContent)\n\n      if (packageJson.workspaces) {\n        return true\n      }\n\n      return false\n    } catch {\n      return false\n    }\n  }\n\n  /**\n   * 查找项目根目录信息对象\n   * 返回包含项目根目录和顶层根目录的对象\n   * - projectRoot: 根据项目类型返回适当的根目录\n   *   - 如果项目是monorepo架构的子项目，返回子项目的根目录\n   *   - 如果项目是monorepo项目非子项目，返回monorepo项目根目录\n   *   - 如果是single架构的项目，返回项目根目录\n   * - rootPath: 总是返回最顶层的项目根目录\n   *   - 如果项目是monorepo架构的子项目，返回monorepo项目的根目录\n   *   - 如果项目是monorepo项目非子项目，返回monorepo项目根目录\n   *   - 如果是single架构的项目，返回项目根目录\n   */\n  static async findProjectRoot(startDir = process.cwd()): Promise<{\n    projectPath: string | null\n    rootPath: string | null\n  }> {\n    let currentDir = startDir\n    let projectPath: string | null = null\n    let rootPath: string | null = null\n\n    // 向上查找，直到文件系统根目录\n    while (currentDir !== dirname(currentDir)) {\n      const packageJsonPath = join(currentDir, 'package.json')\n\n      if (await FileOperations.exists(packageJsonPath)) {\n        // 记录第一个找到的 package.json 目录（最可能的项目根目录）\n        projectPath ??= currentDir\n        rootPath = currentDir\n\n        // 检查是否为 monorepo 根目录\n        const isMonorepoRoot = await Discovery.isMonorepoRoot(currentDir)\n        if (isMonorepoRoot) {\n          // 如果当前目录是monorepo 根目录，直接返回\n          return {\n            projectPath,\n            rootPath: currentDir,\n          }\n        }\n      }\n      // 继续向上查找\n      currentDir = dirname(currentDir)\n    }\n\n    // 如果是 monorepo 子项目，返回子项目根目录和 monorepo 根目录\n    // 如果是 monorepo 根目录或 single 项目，返回找到的第一个 package.json 目录\n    return {\n      projectPath,\n      rootPath,\n    }\n  }\n\n  /**\n   * 查找指定目录下的所有package.json文件\n   */\n  static async findPackageJsonFiles(dir: string): Promise<string[]> {\n    const packageJsonFiles: string[] = []\n\n    const searchDirectory = async (currentDir: string): Promise<void> => {\n      const entries = await FileOperations.readDirWithFileTypes(currentDir)\n\n      for (const entry of entries) {\n        const fullPath = join(currentDir, entry.name)\n\n        if (entry.name === 'package.json' && entry.isFile()) {\n          packageJsonFiles.push(fullPath)\n        } else if (\n          entry.isDirectory() &&\n          !entry.name.startsWith('.') &&\n          entry.name !== 'node_modules'\n        ) {\n          await searchDirectory(fullPath)\n        }\n      }\n    }\n\n    await searchDirectory(dir)\n    return packageJsonFiles\n  }\n\n  /**\n   * 检测项目架构类型\n   */\n  static async detectArchitectureType(root: string): Promise<ArchitectureType> {\n    return (await Discovery.isMonorepoRoot(root)) ? 'monorepo' : 'single'\n  }\n\n  /**\n   * 检测项目类型(应用项目或库项目)\n   * 基于npm库项目的典型特征进行判断\n   */\n  static async detectProjectType(projectRoot: string): Promise<ProjectType> {\n    try {\n      const packageJsonPath = join(projectRoot, 'package.json')\n\n      // 检查 package.json 是否存在\n      if (!(await FileOperations.exists(packageJsonPath))) {\n        return 'app' // 默认返回应用项目\n      }\n\n      // 检测项目架构类型\n      const architectureType = await Discovery.detectArchitectureType(projectRoot)\n\n      // 如果是 monorepo 架构根目录，则直接返回 'root'\n      if (architectureType === 'monorepo') {\n        // 再次确认当前目录是否为 monorepo 的根目录\n        const isMonorepoRoot = await Discovery.isMonorepoRoot(projectRoot)\n        if (isMonorepoRoot) {\n          return 'root'\n        }\n      }\n\n      const packageJsonContent = await FileOperations.readFile(packageJsonPath)\n      const packageJson = JSON.parse(packageJsonContent)\n\n      // 库项目特征计分\n      let libScore = 0\n\n      // 1. 检查是否有导出相关的字段 (exports, main, module, types/typings, files)\n      const hasExports = !!packageJson.exports\n      const hasMain = !!packageJson.main\n      const hasModule = !!packageJson.module\n      const hasTypes = !!(packageJson.types ?? packageJson.typings)\n      const hasFiles = !!packageJson.files\n\n      if (hasExports) libScore += 3 // exports是现代库的标准\n      if (hasMain) libScore += 2\n      if (hasModule) libScore += 2\n      if (hasTypes) libScore += 2 // TypeScript库的典型特征\n      if (hasFiles) libScore += 1 // 明确定义要发布的文件是库的特征\n\n      // 2. 检查是否有库相关的关键词\n      const keywords = packageJson.keywords ?? []\n      const libKeywords = [\n        'library',\n        'component',\n        'util',\n        'tool',\n        'helper',\n        'sdk',\n        'api',\n        'framework',\n        'module',\n        'package',\n        'plugin',\n        'extension',\n        'widget',\n        'ui',\n        'esm',\n        'cjs',\n      ]\n      const hasLibKeywords = keywords.some((keyword: string) =>\n        libKeywords.includes(keyword.toLowerCase())\n      )\n\n      if (hasLibKeywords) libScore += 2\n\n      // 3. 检查构建和开发相关的依赖\n      const devDependencies = packageJson.devDependencies ?? {}\n      const libDevDependencies = ['jest', 'vitest', 'mocha', 'karma', 'vite-plugin-dts']\n\n      const hasLibDevDeps = Object.keys(devDependencies).some(dep =>\n        libDevDependencies.some(libDep => dep.includes(libDep))\n      )\n\n      if (hasLibDevDeps) libScore += 2\n\n      // 4. 检查是否有发布配置\n      const hasPublishConfig = !!packageJson.publishConfig\n      if (hasPublishConfig) libScore += 1\n\n      // 如果库特征分数大于等于5，认为是库项目\n      // 这个阈值考虑了库项目通常具有多个特征的情况\n      if (libScore >= 5) {\n        return 'lib'\n      }\n\n      // 默认认为是应用项目\n      return 'app'\n    } catch (error) {\n      // 出现错误时默认返回应用项目\n      console.warn('⚠️ 项目类型检测失败，使用默认类型:', error)\n      return 'app'\n    }\n  }\n\n  /**\n   * 更新package.json脚本\n   */\n  static async updatePackageJsonScripts(projectRoot: string): Promise<void> {\n    const packageJsonPath = join(projectRoot, 'package.json')\n\n    try {\n      const packageJson = JSON.parse(await FileOperations.readFile(packageJsonPath))\n\n      // 添加或更新基础脚本\n      const defaultScripts = {\n        build: 'vue-tsc --noEmit && vite build',\n        preview: 'vite preview',\n      }\n\n      // 根据环境变量文件生成构建脚本\n      const envBuildScripts = await Discovery.generateEnvBuildScripts(projectRoot)\n\n      packageJson.scripts = {\n        ...defaultScripts,\n        ...packageJson.scripts,\n        ...envBuildScripts,\n      }\n\n      await FileOperations.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2))\n      // package.json脚本已更新\n    } catch (error) {\n      console.warn('⚠️ package.json脚本更新失败:', error)\n    }\n  }\n\n  /**\n   * 根据环境变量文件生成构建脚本\n   */\n  static async generateEnvBuildScripts(projectRoot: string): Promise<Record<string, string>> {\n    const envBuildScripts: Record<string, string> = {}\n\n    try {\n      const envDir = join(projectRoot, 'env')\n\n      // 检查env目录是否存在\n      // 扫描env目录/项目根目录 中的环境变量文件\n      const envFiles = await Discovery.scanEnvFilesInDirectory(\n        (await FileOperations.exists(envDir)) ? envDir : projectRoot\n      )\n\n      for (const envFile of envFiles) {\n        const mode = Discovery.extractModeFromEnvFile(envFile)\n        if (mode) {\n          envBuildScripts[`build:${mode}`] = `vite build --mode ${mode}`\n        }\n      }\n    } catch (error) {\n      console.warn('⚠️ 生成环境构建脚本失败:', error)\n    }\n\n    return envBuildScripts\n  }\n\n  /**\n   * 扫描指定目录中的环境变量文件\n   */\n  static async scanEnvFilesInDirectory(directory: string): Promise<string[]> {\n    try {\n      const files = await FileOperations.readDir(directory)\n      return files.filter(\n        file => file.startsWith('.env.') && !file.endsWith('.example') && !file.endsWith('.local')\n      )\n    } catch {\n      return []\n    }\n  }\n\n  /**\n   * 从环境变量文件名中提取模式名称\n   */\n  static extractModeFromEnvFile(envFile: string): string | null {\n    // 移除.env.前缀\n    const mode = envFile.replace(/^\\.env\\./, '')\n\n    // 验证模式名称是否有效（只包含字母、数字、点和连字符）\n    if (/^[a-zA-Z0-9.-]+$/.test(mode) && mode.length > 0) {\n      return mode\n    }\n\n    return null\n  }\n}\n"],"names":["Discovery","getAvailableConfigFiles","templatesDir","projectRoot","options","configs","scanTemplateDirectories","applyFilters","dirInfos","includeOnly","excludeGitHooks","excludeStaticFiles","excludeScripts","include","length","filter","dir","configType","split","includes","templateDirs","targetDir","priority","filteredTemplateDirs","templateSubDir","join","files","FileOperations","readDir","processTemplateFiles","file","shouldSkipFile","templatePath","finalTargetPath","displayName","resolveFilePaths","some","config","name","group","determineFileGroup","commentPrefix","commentSuffix","getCommentFix","configInfo","path","description","getFileDescription","push","excludeNpmrc","pattern","test","fileName","descriptions","eslint","prettier","lintstage","key","endsWith","startsWith","isMonorepoRoot","workspaceFiles","exists","packageJsonPath","packageJsonContent","readFile","JSON","parse","workspaces","findProjectRoot","startDir","process","cwd","currentDir","projectPath","rootPath","dirname","findPackageJsonFiles","packageJsonFiles","searchDirectory","async","entries","readDirWithFileTypes","entry","fullPath","isFile","isDirectory","detectArchitectureType","root","detectProjectType","packageJson","libScore","hasExports","exports","hasMain","main","hasModule","module","hasTypes","types","typings","hasFiles","keywords","libKeywords","keyword","toLowerCase","devDependencies","libDevDependencies","Object","keys","dep","libDep","publishConfig","error","console","warn","updatePackageJsonScripts","defaultScripts","build","preview","envBuildScripts","generateEnvBuildScripts","scripts","writeFile","stringify","envDir","envFiles","scanEnvFilesInDirectory","envFile","mode","extractModeFromEnvFile","directory","replace"],"mappings":"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"}